This driver supports a wide range of Vivante IP cores like GC880, GC1000, GC2000 and GC3000. Changes from V1 -> V2: - added missing files to actually integrate the driver into build system. - adapted driver to new renderonly API Signed-off-by: Christian Gmeiner <christian.gmeiner@gmail.com> Signed-off-by: Lucas Stach <l.stach@pengutronix.de> Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de> Signed-off-by: Rob Herring <robh@kernel.org> Signed-off-by: Russell King <rmk@arm.linux.org.uk> Signed-off-by: Wladimir J. van der Laan <laanwj@gmail.com> Acked-by: Emil Velikov <emil.velikov@collabora.com>tags/17.0-branchpoint
@@ -76,6 +76,7 @@ LIBDRM_NVVIEUX_REQUIRED=2.4.66 | |||
LIBDRM_NOUVEAU_REQUIRED=2.4.66 | |||
LIBDRM_FREEDRENO_REQUIRED=2.4.74 | |||
LIBDRM_VC4_REQUIRED=2.4.69 | |||
LIBDRM_ETNAVIV_REQUIRED=2.4.74 | |||
DRI2PROTO_REQUIRED=2.6 | |||
DRI3PROTO_REQUIRED=1.0 | |||
PRESENTPROTO_REQUIRED=1.0 | |||
@@ -1233,7 +1234,7 @@ GALLIUM_DRIVERS_DEFAULT="r300,r600,svga,swrast" | |||
AC_ARG_WITH([gallium-drivers], | |||
[AS_HELP_STRING([--with-gallium-drivers@<:@=DIRS...@:>@], | |||
[comma delimited Gallium drivers list, e.g. | |||
"i915,ilo,nouveau,r300,r600,radeonsi,freedreno,svga,swrast,vc4,virgl" | |||
"i915,ilo,nouveau,r300,r600,radeonsi,freedreno,svga,swrast,vc4,virgl,etnaviv" | |||
@<:@default=r300,r600,svga,swrast@:>@])], | |||
[with_gallium_drivers="$withval"], | |||
[with_gallium_drivers="$GALLIUM_DRIVERS_DEFAULT"]) | |||
@@ -2506,6 +2507,11 @@ if test -n "$with_gallium_drivers"; then | |||
PKG_CHECK_MODULES([FREEDRENO], [libdrm_freedreno >= $LIBDRM_FREEDRENO_REQUIRED]) | |||
require_libdrm "freedreno" | |||
;; | |||
xetnaviv) | |||
HAVE_GALLIUM_ETNAVIV=yes | |||
PKG_CHECK_MODULES([ETNAVIV], [libdrm_etnaviv >= $LIBDRM_ETNAVIV_REQUIRED]) | |||
require_libdrm "etnaviv" | |||
;; | |||
xswrast) | |||
HAVE_GALLIUM_SOFTPIPE=yes | |||
if test "x$MESA_LLVM" = x1 && test "x$enable_gallium_llvm" == "xyes"; then | |||
@@ -2624,6 +2630,7 @@ AM_CONDITIONAL(HAVE_GALLIUM_RADEON_COMMON, test "x$HAVE_GALLIUM_R600" = xyes -o | |||
"x$HAVE_GALLIUM_RADEONSI" = xyes) | |||
AM_CONDITIONAL(HAVE_GALLIUM_NOUVEAU, test "x$HAVE_GALLIUM_NOUVEAU" = xyes) | |||
AM_CONDITIONAL(HAVE_GALLIUM_FREEDRENO, test "x$HAVE_GALLIUM_FREEDRENO" = xyes) | |||
AM_CONDITIONAL(HAVE_GALLIUM_ETNAVIV, test "x$HAVE_GALLIUM_ETNAVIV" = xyes) | |||
AM_CONDITIONAL(HAVE_GALLIUM_SOFTPIPE, test "x$HAVE_GALLIUM_SOFTPIPE" = xyes) | |||
AM_CONDITIONAL(HAVE_GALLIUM_LLVMPIPE, test "x$HAVE_GALLIUM_LLVMPIPE" = xyes) | |||
AM_CONDITIONAL(HAVE_GALLIUM_SWR, test "x$HAVE_GALLIUM_SWR" = xyes) | |||
@@ -2777,6 +2784,7 @@ AC_CONFIG_FILES([Makefile | |||
src/gallium/drivers/svga/Makefile | |||
src/gallium/drivers/swr/Makefile | |||
src/gallium/drivers/trace/Makefile | |||
src/gallium/drivers/etnaviv/Makefile | |||
src/gallium/drivers/vc4/Makefile | |||
src/gallium/drivers/virgl/Makefile | |||
src/gallium/state_trackers/clover/Makefile | |||
@@ -2806,6 +2814,7 @@ AC_CONFIG_FILES([Makefile | |||
src/gallium/targets/xvmc/Makefile | |||
src/gallium/tests/trivial/Makefile | |||
src/gallium/tests/unit/Makefile | |||
src/gallium/winsys/etnaviv/drm/Makefile | |||
src/gallium/winsys/freedreno/drm/Makefile | |||
src/gallium/winsys/i915/drm/Makefile | |||
src/gallium/winsys/intel/drm/Makefile |
@@ -68,6 +68,10 @@ if NEED_RADEON_DRM_WINSYS | |||
SUBDIRS += winsys/radeon/drm | |||
endif | |||
if HAVE_GALLIUM_ETNAVIV | |||
SUBDIRS += drivers/etnaviv winsys/etnaviv/drm | |||
endif | |||
## swrast/softpipe | |||
if HAVE_GALLIUM_SOFTPIPE | |||
SUBDIRS += drivers/softpipe |
@@ -154,6 +154,11 @@ static const struct drm_driver_descriptor driver_descriptors[] = { | |||
.create_screen = pipe_vc4_create_screen, | |||
.configuration = configuration_query, | |||
}, | |||
{ | |||
.driver_name = "etnaviv", | |||
.create_screen = pipe_etna_create_screen, | |||
.configuration = configuration_query, | |||
} | |||
}; | |||
#endif | |||
@@ -266,5 +266,27 @@ pipe_vc4_create_screen(int fd) | |||
#endif | |||
#ifdef GALLIUM_ETNAVIV | |||
#include "etnaviv/drm/etnaviv_drm_public.h" | |||
struct pipe_screen * | |||
pipe_etna_create_screen(int fd) | |||
{ | |||
struct pipe_screen *screen; | |||
screen = etna_drm_screen_create(fd); | |||
return screen ? debug_screen_wrap(screen) : NULL; | |||
} | |||
#else | |||
struct pipe_screen * | |||
pipe_etna_create_screen(int fd) | |||
{ | |||
fprintf(stderr, "etnaviv: driver missing\n"); | |||
return NULL; | |||
} | |||
#endif | |||
#endif /* DRM_HELPER_H */ |
@@ -34,4 +34,7 @@ pipe_virgl_create_screen(int fd); | |||
struct pipe_screen * | |||
pipe_vc4_create_screen(int fd); | |||
struct pipe_screen * | |||
pipe_etna_create_screen(int fd); | |||
#endif /* _DRM_HELPER_PUBLIC_H */ |
@@ -0,0 +1 @@ | |||
etnaviv_compiler |
@@ -0,0 +1,11 @@ | |||
if HAVE_GALLIUM_ETNAVIV | |||
TARGET_DRIVERS += etnaviv | |||
TARGET_CPPFLAGS += -DGALLIUM_ETNAVIV | |||
TARGET_LIB_DEPS += \ | |||
$(top_builddir)/src/gallium/winsys/etnaviv/drm/libetnavivdrm.la \ | |||
$(top_builddir)/src/gallium/drivers/etnaviv/libetnaviv.la \ | |||
$(ETNAVIV_LIBS) \ | |||
$(LIBDRM_LIBS) | |||
endif |
@@ -0,0 +1,44 @@ | |||
# Copyright © 2013 W.J. van der Laan | |||
# | |||
# Permission is hereby granted, free of charge, to any person obtaining a | |||
# copy of this software and associated documentation files (the "Software"), | |||
# to deal in the Software without restriction, including without limitation | |||
# the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||
# and/or sell copies of the Software, and to permit persons to whom the | |||
# Software is furnished to do so, subject to the following conditions: | |||
# | |||
# The above copyright notice and this permission notice (including the next | |||
# paragraph) shall be included in all copies or substantial portions of the | |||
# Software. | |||
# | |||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | |||
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |||
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
# DEALINGS IN THE SOFTWARE. | |||
include Makefile.sources | |||
include $(top_srcdir)/src/gallium/Automake.inc | |||
noinst_LTLIBRARIES = libetnaviv.la | |||
AM_CPPFLAGS = \ | |||
$(GALLIUM_DRIVER_CFLAGS) \ | |||
$(ETNAVIV_CFLAGS) | |||
libetnaviv_la_SOURCES = $(C_SOURCES) | |||
noinst_PROGRAMS = etnaviv_compiler | |||
etnaviv_compiler_SOURCES = \ | |||
etnaviv_compiler_cmdline.c | |||
etnaviv_compiler_LDADD = \ | |||
libetnaviv.la \ | |||
$(top_builddir)/src/gallium/auxiliary/libgallium.la \ | |||
$(top_builddir)/src/util/libmesautil.la \ | |||
$(GALLIUM_COMMON_LIB_DEPS) \ | |||
$(ETNAVIV_LIBS) |
@@ -0,0 +1,49 @@ | |||
C_SOURCES := \ | |||
etnaviv_asm.c \ | |||
etnaviv_asm.h \ | |||
etnaviv_blend.c \ | |||
etnaviv_blend.h \ | |||
etnaviv_clear_blit.c \ | |||
etnaviv_clear_blit.h \ | |||
etnaviv_compiler.c \ | |||
etnaviv_compiler.h \ | |||
etnaviv_context.c \ | |||
etnaviv_context.h \ | |||
etnaviv_debug.h \ | |||
etnaviv_disasm.c \ | |||
etnaviv_disasm.h \ | |||
etnaviv_emit.c \ | |||
etnaviv_emit.h \ | |||
etnaviv_fence.c \ | |||
etnaviv_fence.h \ | |||
etnaviv_format.c \ | |||
etnaviv_format.h \ | |||
etnaviv_query.c \ | |||
etnaviv_query.h \ | |||
etnaviv_query_sw.c \ | |||
etnaviv_query_sw.h \ | |||
etnaviv_rasterizer.c \ | |||
etnaviv_rasterizer.h \ | |||
etnaviv_resource.c \ | |||
etnaviv_resource.h \ | |||
etnaviv_rs.c \ | |||
etnaviv_rs.h \ | |||
etnaviv_screen.c \ | |||
etnaviv_screen.h \ | |||
etnaviv_shader.c \ | |||
etnaviv_shader.h \ | |||
etnaviv_state.c \ | |||
etnaviv_state.h \ | |||
etnaviv_surface.c \ | |||
etnaviv_surface.h \ | |||
etnaviv_texture.c \ | |||
etnaviv_texture.h \ | |||
etnaviv_tiling.c \ | |||
etnaviv_tiling.h \ | |||
etnaviv_transfer.c \ | |||
etnaviv_transfer.h \ | |||
etnaviv_uniforms.c \ | |||
etnaviv_uniforms.h \ | |||
etnaviv_utils.h \ | |||
etnaviv_zsa.c \ | |||
etnaviv_zsa.h |
@@ -0,0 +1,13 @@ | |||
Notes for the etnaviv gallium driver | |||
------------------------------------ | |||
There are two ways how this driver might get used: | |||
- application opens kms device (kmscube, weston, ..) | |||
- X via xf86-video-armada | |||
For the kms device case we provide a renderonly based driver like | |||
imx where all the magic for buffer import and export between kms | |||
and renderonly GPU is handled automaticly. | |||
For X/xf86-video-armada we need to provide etnaviv_dri.so. |
@@ -0,0 +1,107 @@ | |||
/* | |||
* Copyright (c) 2012-2015 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Wladimir J. van der Laan <laanwj@gmail.com> | |||
*/ | |||
#include "etnaviv_asm.h" | |||
#include "etnaviv_debug.h" | |||
#include "etnaviv_util.h" | |||
/* An instruction can only read from one distinct uniform. | |||
* This function verifies this property and returns true if the instruction | |||
* is deemed correct and false otherwise. | |||
*/ | |||
static bool | |||
check_uniforms(const struct etna_inst *inst) | |||
{ | |||
unsigned uni_rgroup = -1; | |||
unsigned uni_reg = -1; | |||
bool conflict = false; | |||
for (unsigned i = 0; i < ETNA_NUM_SRC; i++) { | |||
const struct etna_inst_src *src = &inst->src[i]; | |||
if (!etna_rgroup_is_uniform(src->rgroup)) | |||
continue; | |||
if (uni_reg == -1) { /* first uniform used */ | |||
uni_rgroup = src->rgroup; | |||
uni_reg = src->reg; | |||
} else { /* second or later; check that it is a re-use */ | |||
if (uni_rgroup != src->rgroup || uni_reg != src->reg) { | |||
conflict = true; | |||
} | |||
} | |||
} | |||
return !conflict; | |||
} | |||
int | |||
etna_assemble(uint32_t *out, const struct etna_inst *inst) | |||
{ | |||
/* cannot have both src2 and imm */ | |||
if (inst->imm && inst->src[2].use) | |||
return 1; | |||
if (!check_uniforms(inst)) | |||
BUG("error: generating instruction that accesses two different uniforms"); | |||
out[0] = VIV_ISA_WORD_0_OPCODE(inst->opcode) | | |||
VIV_ISA_WORD_0_COND(inst->cond) | | |||
COND(inst->sat, VIV_ISA_WORD_0_SAT) | | |||
COND(inst->dst.use, VIV_ISA_WORD_0_DST_USE) | | |||
VIV_ISA_WORD_0_DST_AMODE(inst->dst.amode) | | |||
VIV_ISA_WORD_0_DST_REG(inst->dst.reg) | | |||
VIV_ISA_WORD_0_DST_COMPS(inst->dst.comps) | | |||
VIV_ISA_WORD_0_TEX_ID(inst->tex.id); | |||
out[1] = VIV_ISA_WORD_1_TEX_AMODE(inst->tex.amode) | | |||
VIV_ISA_WORD_1_TEX_SWIZ(inst->tex.swiz) | | |||
COND(inst->src[0].use, VIV_ISA_WORD_1_SRC0_USE) | | |||
VIV_ISA_WORD_1_SRC0_REG(inst->src[0].reg) | | |||
COND(inst->type & 0x4, VIV_ISA_WORD_1_TYPE_BIT2) | | |||
VIV_ISA_WORD_1_SRC0_SWIZ(inst->src[0].swiz) | | |||
COND(inst->src[0].neg, VIV_ISA_WORD_1_SRC0_NEG) | | |||
COND(inst->src[0].abs, VIV_ISA_WORD_1_SRC0_ABS); | |||
out[2] = VIV_ISA_WORD_2_SRC0_AMODE(inst->src[0].amode) | | |||
VIV_ISA_WORD_2_SRC0_RGROUP(inst->src[0].rgroup) | | |||
COND(inst->src[1].use, VIV_ISA_WORD_2_SRC1_USE) | | |||
VIV_ISA_WORD_2_SRC1_REG(inst->src[1].reg) | | |||
VIV_ISA_WORD_2_SRC1_SWIZ(inst->src[1].swiz) | | |||
COND(inst->src[1].neg, VIV_ISA_WORD_2_SRC1_NEG) | | |||
COND(inst->src[1].abs, VIV_ISA_WORD_2_SRC1_ABS) | | |||
VIV_ISA_WORD_2_SRC1_AMODE(inst->src[1].amode) | | |||
VIV_ISA_WORD_2_TYPE_BIT01(inst->type & 0x3); | |||
out[3] = VIV_ISA_WORD_3_SRC1_RGROUP(inst->src[1].rgroup) | | |||
COND(inst->src[2].use, VIV_ISA_WORD_3_SRC2_USE) | | |||
VIV_ISA_WORD_3_SRC2_REG(inst->src[2].reg) | | |||
VIV_ISA_WORD_3_SRC2_SWIZ(inst->src[2].swiz) | | |||
COND(inst->src[2].neg, VIV_ISA_WORD_3_SRC2_NEG) | | |||
COND(inst->src[2].abs, VIV_ISA_WORD_3_SRC2_ABS) | | |||
VIV_ISA_WORD_3_SRC2_AMODE(inst->src[2].amode) | | |||
VIV_ISA_WORD_3_SRC2_RGROUP(inst->src[2].rgroup); | |||
out[3] |= VIV_ISA_WORD_3_SRC2_IMM(inst->imm); | |||
return 0; | |||
} |
@@ -0,0 +1,133 @@ | |||
/* | |||
* Copyright (c) 2012-2015 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Wladimir J. van der Laan <laanwj@gmail.com> | |||
*/ | |||
#ifndef H_ETNAVIV_ASM | |||
#define H_ETNAVIV_ASM | |||
#include <stdint.h> | |||
#include "hw/isa.xml.h" | |||
/* Size of an instruction in 32-bit words */ | |||
#define ETNA_INST_SIZE (4) | |||
/* Number of source operands per instruction */ | |||
#define ETNA_NUM_SRC (3) | |||
/* Broadcast swizzle to all four components */ | |||
#define INST_SWIZ_BROADCAST(x) \ | |||
(INST_SWIZ_X(x) | INST_SWIZ_Y(x) | INST_SWIZ_Z(x) | INST_SWIZ_W(x)) | |||
/* Identity (NOP) swizzle */ | |||
#define INST_SWIZ_IDENTITY \ | |||
(INST_SWIZ_X(0) | INST_SWIZ_Y(1) | INST_SWIZ_Z(2) | INST_SWIZ_W(3)) | |||
/* Fully specified swizzle */ | |||
#define INST_SWIZ(x,y,z,w) \ | |||
(INST_SWIZ_X(x) | INST_SWIZ_Y(y) | INST_SWIZ_Z(z) | INST_SWIZ_W(w)) | |||
#define SWIZZLE(c0,c1,c2,c3) \ | |||
INST_SWIZ(INST_SWIZ_COMP_##c0, \ | |||
INST_SWIZ_COMP_##c1, \ | |||
INST_SWIZ_COMP_##c2, \ | |||
INST_SWIZ_COMP_##c3) | |||
/*** operands ***/ | |||
/* destination operand */ | |||
struct etna_inst_dst { | |||
unsigned use:1; /* 0: not in use, 1: in use */ | |||
unsigned amode:3; /* INST_AMODE_* */ | |||
unsigned reg:7; /* register number 0..127 */ | |||
unsigned comps:4; /* INST_COMPS_* */ | |||
}; | |||
/* texture operand */ | |||
struct etna_inst_tex { | |||
unsigned id:5; /* sampler id */ | |||
unsigned amode:3; /* INST_AMODE_* */ | |||
unsigned swiz:8; /* INST_SWIZ */ | |||
}; | |||
/* source operand */ | |||
struct etna_inst_src { | |||
unsigned use:1; /* 0: not in use, 1: in use */ | |||
unsigned reg:9; /* register or uniform number 0..511 */ | |||
unsigned swiz:8; /* INST_SWIZ */ | |||
unsigned neg:1; /* negate (flip sign) if set */ | |||
unsigned abs:1; /* absolute (remove sign) if set */ | |||
unsigned amode:3; /* INST_AMODE_* */ | |||
unsigned rgroup:3; /* INST_RGROUP_* */ | |||
}; | |||
/*** instruction ***/ | |||
struct etna_inst { | |||
uint8_t opcode; /* INST_OPCODE_* */ | |||
uint8_t type; /* INST_TYPE_* */ | |||
unsigned cond:5; /* INST_CONDITION_* */ | |||
unsigned sat:1; /* saturate result between 0..1 */ | |||
struct etna_inst_dst dst; /* destination operand */ | |||
struct etna_inst_tex tex; /* texture operand */ | |||
struct etna_inst_src src[ETNA_NUM_SRC]; /* source operand */ | |||
unsigned imm; /* takes place of src[2] for BRANCH/CALL */ | |||
}; | |||
/* Compose two swizzles (computes swz1.swz2) */ | |||
static inline uint32_t inst_swiz_compose(uint32_t swz1, uint32_t swz2) | |||
{ | |||
return INST_SWIZ_X((swz1 >> (((swz2 >> 0)&3)*2))&3) | | |||
INST_SWIZ_Y((swz1 >> (((swz2 >> 2)&3)*2))&3) | | |||
INST_SWIZ_Z((swz1 >> (((swz2 >> 4)&3)*2))&3) | | |||
INST_SWIZ_W((swz1 >> (((swz2 >> 6)&3)*2))&3); | |||
}; | |||
/* Return whether the rgroup is one of the uniforms */ | |||
static inline int | |||
etna_rgroup_is_uniform(unsigned rgroup) | |||
{ | |||
return rgroup == INST_RGROUP_UNIFORM_0 || | |||
rgroup == INST_RGROUP_UNIFORM_1; | |||
} | |||
/** | |||
* Build vivante instruction from structure with | |||
* opcode, cond, sat, dst_use, dst_amode, | |||
* dst_reg, dst_comps, tex_id, tex_amode, tex_swiz, | |||
* src[0-2]_reg, use, swiz, neg, abs, amode, rgroup, | |||
* imm | |||
* | |||
* Return 0 if successful, and a non-zero | |||
* value otherwise. | |||
*/ | |||
int | |||
etna_assemble(uint32_t *out, const struct etna_inst *inst); | |||
/** | |||
* Set field imm of already-assembled instruction. | |||
* This is used for filling in jump destinations in a separate pass. | |||
*/ | |||
static inline void | |||
etna_assemble_set_imm(uint32_t *out, uint32_t imm) | |||
{ | |||
out[3] |= VIV_ISA_WORD_3_SRC2_IMM(imm); | |||
} | |||
#endif |
@@ -0,0 +1,109 @@ | |||
/* | |||
* Copyright (c) 2012-2015 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Wladimir J. van der Laan <laanwj@gmail.com> | |||
*/ | |||
#include "etnaviv_blend.h" | |||
#include "etnaviv_context.h" | |||
#include "etnaviv_translate.h" | |||
#include "pipe/p_defines.h" | |||
#include "util/u_memory.h" | |||
void * | |||
etna_blend_state_create(struct pipe_context *pctx, | |||
const struct pipe_blend_state *so) | |||
{ | |||
const struct pipe_rt_blend_state *rt0 = &so->rt[0]; | |||
struct etna_blend_state *co = CALLOC_STRUCT(etna_blend_state); | |||
if (!co) | |||
return NULL; | |||
co->base = *so; | |||
/* Enable blending if | |||
* - blend enabled in blend state | |||
* - NOT source factor is ONE and destination factor ZERO for both rgb and | |||
* alpha (which would mean that blending is effectively disabled) | |||
*/ | |||
bool enable = rt0->blend_enable && | |||
!(rt0->rgb_src_factor == PIPE_BLENDFACTOR_ONE && | |||
rt0->rgb_dst_factor == PIPE_BLENDFACTOR_ZERO && | |||
rt0->alpha_src_factor == PIPE_BLENDFACTOR_ONE && | |||
rt0->alpha_dst_factor == PIPE_BLENDFACTOR_ZERO); | |||
/* Enable separate alpha if | |||
* - Blending enabled (see above) | |||
* - NOT source factor is equal to destination factor for both rgb abd | |||
* alpha (which would effectively that mean alpha is not separate) | |||
*/ | |||
bool separate_alpha = enable && | |||
!(rt0->rgb_src_factor == rt0->alpha_src_factor && | |||
rt0->rgb_dst_factor == rt0->alpha_dst_factor); | |||
/* If the complete render target is written, set full_overwrite: | |||
* - The color mask is 1111 | |||
* - No blending is used | |||
*/ | |||
bool full_overwrite = (rt0->colormask == 15) && !enable; | |||
if (enable) { | |||
co->PE_ALPHA_CONFIG = | |||
VIVS_PE_ALPHA_CONFIG_BLEND_ENABLE_COLOR | | |||
COND(separate_alpha, VIVS_PE_ALPHA_CONFIG_BLEND_SEPARATE_ALPHA) | | |||
VIVS_PE_ALPHA_CONFIG_SRC_FUNC_COLOR(translate_blend_factor(rt0->rgb_src_factor)) | | |||
VIVS_PE_ALPHA_CONFIG_SRC_FUNC_ALPHA(translate_blend_factor(rt0->alpha_src_factor)) | | |||
VIVS_PE_ALPHA_CONFIG_DST_FUNC_COLOR(translate_blend_factor(rt0->rgb_dst_factor)) | | |||
VIVS_PE_ALPHA_CONFIG_DST_FUNC_ALPHA(translate_blend_factor(rt0->alpha_dst_factor)) | | |||
VIVS_PE_ALPHA_CONFIG_EQ_COLOR(translate_blend(rt0->rgb_func)) | | |||
VIVS_PE_ALPHA_CONFIG_EQ_ALPHA(translate_blend(rt0->alpha_func)); | |||
} else { | |||
co->PE_ALPHA_CONFIG = 0; | |||
} | |||
co->PE_COLOR_FORMAT = | |||
VIVS_PE_COLOR_FORMAT_COMPONENTS(rt0->colormask) | | |||
COND(full_overwrite, VIVS_PE_COLOR_FORMAT_OVERWRITE); | |||
co->PE_LOGIC_OP = | |||
VIVS_PE_LOGIC_OP_OP(so->logicop_enable ? so->logicop_func : LOGIC_OP_COPY) | | |||
0x000E4000 /* ??? */; | |||
/* independent_blend_enable not needed: only one rt supported */ | |||
/* XXX alpha_to_coverage / alpha_to_one? */ | |||
/* Set dither registers based on dither status. These registers set the | |||
* dither pattern, | |||
* for now, set the same values as the blob. | |||
*/ | |||
if (so->dither) { | |||
co->PE_DITHER[0] = 0x6e4ca280; | |||
co->PE_DITHER[1] = 0x5d7f91b3; | |||
} else { | |||
co->PE_DITHER[0] = 0xffffffff; | |||
co->PE_DITHER[1] = 0xffffffff; | |||
} | |||
return co; | |||
} |
@@ -0,0 +1,52 @@ | |||
/* | |||
* Copyright (c) 2012-2015 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Wladimir J. van der Laan <laanwj@gmail.com> | |||
*/ | |||
#ifndef H_ETNAVIV_BLEND | |||
#define H_ETNAVIV_BLEND | |||
#include "pipe/p_context.h" | |||
#include "pipe/p_state.h" | |||
struct etna_blend_state { | |||
struct pipe_blend_state base; | |||
uint32_t PE_ALPHA_CONFIG; | |||
uint32_t PE_COLOR_FORMAT; | |||
uint32_t PE_LOGIC_OP; | |||
uint32_t PE_DITHER[2]; | |||
}; | |||
static inline struct etna_blend_state * | |||
etna_blend_state(struct pipe_blend_state *blend) | |||
{ | |||
return (struct etna_blend_state *)blend; | |||
} | |||
void * | |||
etna_blend_state_create(struct pipe_context *pctx, | |||
const struct pipe_blend_state *so); | |||
#endif |
@@ -0,0 +1,640 @@ | |||
/* | |||
* Copyright (c) 2012-2015 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Wladimir J. van der Laan <laanwj@gmail.com> | |||
*/ | |||
#include "etnaviv_clear_blit.h" | |||
#include "hw/common.xml.h" | |||
#include "etnaviv_context.h" | |||
#include "etnaviv_emit.h" | |||
#include "etnaviv_emit.h" | |||
#include "etnaviv_format.h" | |||
#include "etnaviv_resource.h" | |||
#include "etnaviv_surface.h" | |||
#include "etnaviv_translate.h" | |||
#include "pipe/p_defines.h" | |||
#include "pipe/p_state.h" | |||
#include "util/u_blitter.h" | |||
#include "util/u_inlines.h" | |||
#include "util/u_memory.h" | |||
#include "util/u_surface.h" | |||
/* Save current state for blitter operation */ | |||
static void | |||
etna_blit_save_state(struct etna_context *ctx) | |||
{ | |||
util_blitter_save_vertex_buffer_slot(ctx->blitter, ctx->vertex_buffer.vb); | |||
util_blitter_save_vertex_elements(ctx->blitter, ctx->vertex_elements); | |||
util_blitter_save_vertex_shader(ctx->blitter, ctx->vs); | |||
util_blitter_save_rasterizer(ctx->blitter, ctx->rasterizer); | |||
util_blitter_save_viewport(ctx->blitter, &ctx->viewport_s); | |||
util_blitter_save_scissor(ctx->blitter, &ctx->scissor_s); | |||
util_blitter_save_fragment_shader(ctx->blitter, ctx->fs); | |||
util_blitter_save_blend(ctx->blitter, ctx->blend); | |||
util_blitter_save_depth_stencil_alpha(ctx->blitter, ctx->zsa); | |||
util_blitter_save_stencil_ref(ctx->blitter, &ctx->stencil_ref_s); | |||
util_blitter_save_sample_mask(ctx->blitter, ctx->sample_mask); | |||
util_blitter_save_framebuffer(ctx->blitter, &ctx->framebuffer_s); | |||
util_blitter_save_fragment_sampler_states(ctx->blitter, | |||
ctx->num_fragment_samplers, (void **)ctx->sampler); | |||
util_blitter_save_fragment_sampler_views(ctx->blitter, | |||
ctx->num_fragment_sampler_views, ctx->sampler_view); | |||
} | |||
/* Generate clear command for a surface (non-fast clear case) */ | |||
void | |||
etna_rs_gen_clear_surface(struct etna_context *ctx, struct etna_surface *surf, | |||
uint32_t clear_value) | |||
{ | |||
struct etna_resource *dst = etna_resource(surf->base.texture); | |||
uint32_t format = translate_rs_format(surf->base.format); | |||
if (format == ETNA_NO_MATCH) { | |||
BUG("etna_rs_gen_clear_surface: Unhandled clear fmt %s", util_format_name(surf->base.format)); | |||
format = RS_FORMAT_A8R8G8B8; | |||
assert(0); | |||
} | |||
/* use tiled clear if width is multiple of 16 */ | |||
bool tiled_clear = (surf->surf.padded_width & ETNA_RS_WIDTH_MASK) == 0 && | |||
(surf->surf.padded_height & ETNA_RS_HEIGHT_MASK) == 0; | |||
etna_compile_rs_state( ctx, &surf->clear_command, &(struct rs_state) { | |||
.source_format = format, | |||
.dest_format = format, | |||
.dest = dst->bo, | |||
.dest_offset = surf->surf.offset, | |||
.dest_stride = surf->surf.stride, | |||
.dest_padded_height = surf->surf.padded_height, | |||
.dest_tiling = tiled_clear ? dst->layout : ETNA_LAYOUT_LINEAR, | |||
.dither = {0xffffffff, 0xffffffff}, | |||
.width = surf->surf.padded_width, /* These must be padded to 16x4 if !LINEAR, otherwise RS will hang */ | |||
.height = surf->surf.padded_height, | |||
.clear_value = {clear_value}, | |||
.clear_mode = VIVS_RS_CLEAR_CONTROL_MODE_ENABLED1, | |||
.clear_bits = 0xffff | |||
}); | |||
} | |||
static void | |||
etna_blit_clear_color(struct pipe_context *pctx, struct pipe_surface *dst, | |||
const union pipe_color_union *color) | |||
{ | |||
struct etna_context *ctx = etna_context(pctx); | |||
struct etna_surface *surf = etna_surface(dst); | |||
uint32_t new_clear_value = translate_clear_color(surf->base.format, color); | |||
if (surf->surf.ts_size) { /* TS: use precompiled clear command */ | |||
ctx->framebuffer.TS_COLOR_CLEAR_VALUE = new_clear_value; | |||
if (!DBG_ENABLED(ETNA_DBG_NO_AUTODISABLE) && | |||
VIV_FEATURE(ctx->screen, chipMinorFeatures1, AUTO_DISABLE)) { | |||
/* Set number of color tiles to be filled */ | |||
etna_set_state(ctx->stream, VIVS_TS_COLOR_AUTO_DISABLE_COUNT, | |||
surf->surf.padded_width * surf->surf.padded_height / 16); | |||
ctx->framebuffer.TS_MEM_CONFIG |= VIVS_TS_MEM_CONFIG_COLOR_AUTO_DISABLE; | |||
} | |||
ctx->dirty |= ETNA_DIRTY_TS; | |||
} else if (unlikely(new_clear_value != surf->level->clear_value)) { /* Queue normal RS clear for non-TS surfaces */ | |||
/* If clear color changed, re-generate stored command */ | |||
etna_rs_gen_clear_surface(ctx, surf, new_clear_value); | |||
} | |||
etna_submit_rs_state(ctx, &surf->clear_command); | |||
surf->level->clear_value = new_clear_value; | |||
resource_written(ctx, surf->base.texture); | |||
etna_resource(surf->base.texture)->seqno++; | |||
} | |||
static void | |||
etna_blit_clear_zs(struct pipe_context *pctx, struct pipe_surface *dst, | |||
unsigned buffers, double depth, unsigned stencil) | |||
{ | |||
struct etna_context *ctx = etna_context(pctx); | |||
struct etna_surface *surf = etna_surface(dst); | |||
uint32_t new_clear_value = translate_clear_depth_stencil(surf->base.format, depth, stencil); | |||
uint32_t new_clear_bits = 0, clear_bits_depth, clear_bits_stencil; | |||
/* Get the channels to clear */ | |||
switch (surf->base.format) { | |||
case PIPE_FORMAT_Z16_UNORM: | |||
clear_bits_depth = 0xffff; | |||
clear_bits_stencil = 0; | |||
break; | |||
case PIPE_FORMAT_X8Z24_UNORM: | |||
case PIPE_FORMAT_S8_UINT_Z24_UNORM: | |||
clear_bits_depth = 0xeeee; | |||
clear_bits_stencil = 0x1111; | |||
break; | |||
default: | |||
clear_bits_depth = clear_bits_stencil = 0xffff; | |||
break; | |||
} | |||
if (buffers & PIPE_CLEAR_DEPTH) | |||
new_clear_bits |= clear_bits_depth; | |||
if (buffers & PIPE_CLEAR_STENCIL) | |||
new_clear_bits |= clear_bits_stencil; | |||
/* FIXME: when tile status is enabled, this becomes more complex as | |||
* we may separately clear the depth from the stencil. In this case, | |||
* we want to resolve the surface, and avoid using the tile status. | |||
* We may be better off recording the pending clear operation, | |||
* delaying the actual clear to the first use. This way, we can merge | |||
* consecutive clears together. */ | |||
if (surf->surf.ts_size) { /* TS: use precompiled clear command */ | |||
/* Set new clear depth value */ | |||
ctx->framebuffer.TS_DEPTH_CLEAR_VALUE = new_clear_value; | |||
if (!DBG_ENABLED(ETNA_DBG_NO_AUTODISABLE) && | |||
VIV_FEATURE(ctx->screen, chipMinorFeatures1, AUTO_DISABLE)) { | |||
/* Set number of depth tiles to be filled */ | |||
etna_set_state(ctx->stream, VIVS_TS_DEPTH_AUTO_DISABLE_COUNT, | |||
surf->surf.padded_width * surf->surf.padded_height / 16); | |||
ctx->framebuffer.TS_MEM_CONFIG |= VIVS_TS_MEM_CONFIG_DEPTH_AUTO_DISABLE; | |||
} | |||
ctx->dirty |= ETNA_DIRTY_TS; | |||
} else { | |||
if (unlikely(new_clear_value != surf->level->clear_value)) { /* Queue normal RS clear for non-TS surfaces */ | |||
/* If clear depth value changed, re-generate stored command */ | |||
etna_rs_gen_clear_surface(ctx, surf, new_clear_value); | |||
} | |||
/* Update the channels to be cleared */ | |||
etna_modify_rs_clearbits(&surf->clear_command, new_clear_bits); | |||
} | |||
etna_submit_rs_state(ctx, &surf->clear_command); | |||
surf->level->clear_value = new_clear_value; | |||
resource_written(ctx, surf->base.texture); | |||
etna_resource(surf->base.texture)->seqno++; | |||
} | |||
static void | |||
etna_clear(struct pipe_context *pctx, unsigned buffers, | |||
const union pipe_color_union *color, double depth, unsigned stencil) | |||
{ | |||
struct etna_context *ctx = etna_context(pctx); | |||
/* Flush color and depth cache before clearing anything. | |||
* This is especially important when coming from another surface, as | |||
* otherwise it may clear part of the old surface instead. */ | |||
etna_set_state(ctx->stream, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH); | |||
etna_stall(ctx->stream, SYNC_RECIPIENT_RA, SYNC_RECIPIENT_PE); | |||
/* Preparation: Flush the TS if needed. This must be done after flushing | |||
* color and depth, otherwise it can result in crashes */ | |||
bool need_ts_flush = false; | |||
if ((buffers & PIPE_CLEAR_COLOR) && ctx->framebuffer_s.nr_cbufs) { | |||
struct etna_surface *surf = etna_surface(ctx->framebuffer_s.cbufs[0]); | |||
if (surf->surf.ts_size) | |||
need_ts_flush = true; | |||
} | |||
if ((buffers & PIPE_CLEAR_DEPTHSTENCIL) && ctx->framebuffer_s.zsbuf != NULL) { | |||
struct etna_surface *surf = etna_surface(ctx->framebuffer_s.zsbuf); | |||
if (surf->surf.ts_size) | |||
need_ts_flush = true; | |||
} | |||
if (need_ts_flush) | |||
etna_set_state(ctx->stream, VIVS_TS_FLUSH_CACHE, VIVS_TS_FLUSH_CACHE_FLUSH); | |||
/* No need to set up the TS here as RS clear operations (in contrast to | |||
* resolve and copy) do not require the TS state. | |||
*/ | |||
if (buffers & PIPE_CLEAR_COLOR) { | |||
for (int idx = 0; idx < ctx->framebuffer_s.nr_cbufs; ++idx) { | |||
etna_blit_clear_color(pctx, ctx->framebuffer_s.cbufs[idx], | |||
&color[idx]); | |||
} | |||
} | |||
/* Flush the color and depth caches before each RS clear operation | |||
* This fixes a hang on GC600. */ | |||
if (buffers & PIPE_CLEAR_DEPTHSTENCIL && buffers & PIPE_CLEAR_COLOR) | |||
etna_set_state(ctx->stream, VIVS_GL_FLUSH_CACHE, | |||
VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH); | |||
if ((buffers & PIPE_CLEAR_DEPTHSTENCIL) && ctx->framebuffer_s.zsbuf != NULL) | |||
etna_blit_clear_zs(pctx, ctx->framebuffer_s.zsbuf, buffers, depth, stencil); | |||
etna_stall(ctx->stream, SYNC_RECIPIENT_RA, SYNC_RECIPIENT_PE); | |||
} | |||
static void | |||
etna_clear_render_target(struct pipe_context *pctx, struct pipe_surface *dst, | |||
const union pipe_color_union *color, unsigned dstx, | |||
unsigned dsty, unsigned width, unsigned height, | |||
bool render_condition_enabled) | |||
{ | |||
struct etna_context *ctx = etna_context(pctx); | |||
/* XXX could fall back to RS when target area is full screen / resolveable | |||
* and no TS. */ | |||
etna_blit_save_state(ctx); | |||
util_blitter_clear_render_target(ctx->blitter, dst, color, dstx, dsty, width, height); | |||
} | |||
static void | |||
etna_clear_depth_stencil(struct pipe_context *pctx, struct pipe_surface *dst, | |||
unsigned clear_flags, double depth, unsigned stencil, | |||
unsigned dstx, unsigned dsty, unsigned width, | |||
unsigned height, bool render_condition_enabled) | |||
{ | |||
struct etna_context *ctx = etna_context(pctx); | |||
/* XXX could fall back to RS when target area is full screen / resolveable | |||
* and no TS. */ | |||
etna_blit_save_state(ctx); | |||
util_blitter_clear_depth_stencil(ctx->blitter, dst, clear_flags, depth, | |||
stencil, dstx, dsty, width, height); | |||
} | |||
static void | |||
etna_resource_copy_region(struct pipe_context *pctx, struct pipe_resource *dst, | |||
unsigned dst_level, unsigned dstx, unsigned dsty, | |||
unsigned dstz, struct pipe_resource *src, | |||
unsigned src_level, const struct pipe_box *src_box) | |||
{ | |||
struct etna_context *ctx = etna_context(pctx); | |||
/* The resource must be of the same format. */ | |||
assert(src->format == dst->format); | |||
/* Resources with nr_samples > 1 are not allowed. */ | |||
assert(src->nr_samples <= 1 && dst->nr_samples <= 1); | |||
/* XXX we can use the RS as a literal copy engine here | |||
* the only complexity is tiling; the size of the boxes needs to be aligned | |||
* to the tile size | |||
* how to handle the case where a resource is copied from/to a non-aligned | |||
* position? | |||
* from non-aligned: can fall back to rendering-based copy? | |||
* to non-aligned: can fall back to rendering-based copy? | |||
* XXX this goes wrong when source surface is supertiled. | |||
*/ | |||
if (util_blitter_is_copy_supported(ctx->blitter, dst, src)) { | |||
etna_blit_save_state(ctx); | |||
util_blitter_copy_texture(ctx->blitter, dst, dst_level, dstx, dsty, dstz, | |||
src, src_level, src_box); | |||
} else { | |||
util_resource_copy_region(pctx, dst, dst_level, dstx, dsty, dstz, src, | |||
src_level, src_box); | |||
} | |||
} | |||
static bool | |||
etna_manual_blit(struct etna_resource *dst, struct etna_resource_level *dst_lev, | |||
unsigned int dst_offset, struct etna_resource *src, | |||
struct etna_resource_level *src_lev, unsigned int src_offset, | |||
const struct pipe_blit_info *blit_info) | |||
{ | |||
void *smap, *srow, *dmap, *drow; | |||
size_t tile_size; | |||
assert(src->layout == ETNA_LAYOUT_TILED); | |||
assert(dst->layout == ETNA_LAYOUT_TILED); | |||
assert(src->base.nr_samples == 0); | |||
assert(dst->base.nr_samples == 0); | |||
tile_size = util_format_get_blocksize(blit_info->src.format) * 4 * 4; | |||
smap = etna_bo_map(src->bo); | |||
if (!smap) | |||
return false; | |||
dmap = etna_bo_map(dst->bo); | |||
if (!dmap) | |||
return false; | |||
srow = smap + src_offset; | |||
drow = dmap + dst_offset; | |||
etna_bo_cpu_prep(src->bo, DRM_ETNA_PREP_READ); | |||
etna_bo_cpu_prep(dst->bo, DRM_ETNA_PREP_WRITE); | |||
for (int y = 0; y < blit_info->src.box.height; y += 4) { | |||
memcpy(drow, srow, tile_size * blit_info->src.box.width); | |||
srow += src_lev->stride * 4; | |||
drow += dst_lev->stride * 4; | |||
} | |||
etna_bo_cpu_fini(dst->bo); | |||
etna_bo_cpu_fini(src->bo); | |||
return true; | |||
} | |||
static bool | |||
etna_try_rs_blit(struct pipe_context *pctx, | |||
const struct pipe_blit_info *blit_info) | |||
{ | |||
struct etna_context *ctx = etna_context(pctx); | |||
struct etna_resource *src = etna_resource(blit_info->src.resource); | |||
struct etna_resource *dst = etna_resource(blit_info->dst.resource); | |||
struct compiled_rs_state copy_to_screen; | |||
uint32_t ts_mem_config = 0; | |||
int msaa_xscale = 1, msaa_yscale = 1; | |||
/* Ensure that the level is valid */ | |||
assert(blit_info->src.level <= src->base.last_level); | |||
assert(blit_info->dst.level <= dst->base.last_level); | |||
if (!translate_samples_to_xyscale(src->base.nr_samples, &msaa_xscale, &msaa_yscale, NULL)) | |||
return FALSE; | |||
/* The width/height are in pixels; they do not change as a result of | |||
* multi-sampling. So, when blitting from a 4x multisampled surface | |||
* to a non-multisampled surface, the width and height will be | |||
* identical. As we do not support scaling, reject different sizes. */ | |||
if (blit_info->dst.box.width != blit_info->src.box.width || | |||
blit_info->dst.box.height != blit_info->src.box.height) { | |||
DBG("scaling requested: source %dx%d destination %dx%d", | |||
blit_info->src.box.width, blit_info->src.box.height, | |||
blit_info->dst.box.width, blit_info->dst.box.height); | |||
return FALSE; | |||
} | |||
/* No masks - RS can't copy specific channels */ | |||
unsigned mask = util_format_get_mask(blit_info->dst.format); | |||
if ((blit_info->mask & mask) != mask) { | |||
DBG("sub-mask requested: 0x%02x vs format mask 0x%02x", blit_info->mask, mask); | |||
return FALSE; | |||
} | |||
unsigned src_format = etna_compatible_rs_format(blit_info->src.format); | |||
unsigned dst_format = etna_compatible_rs_format(blit_info->src.format); | |||
if (translate_rs_format(src_format) == ETNA_NO_MATCH || | |||
translate_rs_format(dst_format) == ETNA_NO_MATCH || | |||
blit_info->scissor_enable || blit_info->src.box.x != 0 || | |||
blit_info->src.box.y != 0 || blit_info->dst.box.x != 0 || | |||
blit_info->dst.box.y != 0 || | |||
blit_info->dst.box.depth != blit_info->src.box.depth || | |||
blit_info->dst.box.depth != 1) { | |||
return FALSE; | |||
} | |||
/* Ensure that the Z coordinate is sane */ | |||
if (dst->base.target != PIPE_TEXTURE_CUBE) | |||
assert(blit_info->dst.box.z == 0); | |||
if (src->base.target != PIPE_TEXTURE_CUBE) | |||
assert(blit_info->src.box.z == 0); | |||
assert(blit_info->src.box.z < src->base.array_size); | |||
assert(blit_info->dst.box.z < dst->base.array_size); | |||
struct etna_resource_level *src_lev = &src->levels[blit_info->src.level]; | |||
struct etna_resource_level *dst_lev = &dst->levels[blit_info->dst.level]; | |||
/* we may be given coordinates up to the padded width to avoid | |||
* any alignment issues with different tiling formats */ | |||
assert((blit_info->src.box.x + blit_info->src.box.width) * msaa_xscale <= src_lev->padded_width); | |||
assert((blit_info->src.box.y + blit_info->src.box.height) * msaa_yscale <= src_lev->padded_height); | |||
assert(blit_info->dst.box.x + blit_info->dst.box.width <= dst_lev->padded_width); | |||
assert(blit_info->dst.box.y + blit_info->dst.box.height <= dst_lev->padded_height); | |||
unsigned src_offset = | |||
src_lev->offset + blit_info->src.box.z * src_lev->layer_stride; | |||
unsigned dst_offset = | |||
dst_lev->offset + blit_info->dst.box.z * dst_lev->layer_stride; | |||
if (src_lev->padded_width <= ETNA_RS_WIDTH_MASK || | |||
dst_lev->padded_width <= ETNA_RS_WIDTH_MASK || | |||
src_lev->padded_height <= ETNA_RS_HEIGHT_MASK || | |||
dst_lev->padded_height <= ETNA_RS_HEIGHT_MASK) | |||
goto manual; | |||
/* If the width is not aligned to the RS width, but is within our | |||
* padding, adjust the width to suite the RS width restriction. | |||
* Note: the RS width/height are converted to source samples here. */ | |||
unsigned int width = blit_info->src.box.width * msaa_xscale; | |||
unsigned int height = blit_info->src.box.height * msaa_yscale; | |||
unsigned int w_align = ETNA_RS_WIDTH_MASK + 1; | |||
unsigned int h_align = (ETNA_RS_HEIGHT_MASK + 1) * ctx->specs.pixel_pipes; | |||
if (width & (w_align - 1) && width >= src_lev->width * msaa_xscale && width >= dst_lev->width) | |||
width = align(width, w_align); | |||
if (height & (h_align - 1) && height >= src_lev->height * msaa_yscale && height >= dst_lev->height) | |||
height = align(height, h_align); | |||
/* The padded dimensions are in samples */ | |||
if (width > src_lev->padded_width || | |||
width > dst_lev->padded_width * msaa_xscale || | |||
height > src_lev->padded_height || | |||
height > dst_lev->padded_height * msaa_yscale) | |||
goto manual; | |||
if (src->base.nr_samples > 1) { | |||
uint32_t msaa_format = translate_msaa_format(src_format); | |||
assert(msaa_format != ETNA_NO_MATCH); | |||
ts_mem_config |= VIVS_TS_MEM_CONFIG_MSAA | msaa_format; | |||
} | |||
uint32_t to_flush = 0; | |||
if (src->base.bind & PIPE_BIND_RENDER_TARGET) | |||
to_flush |= VIVS_GL_FLUSH_CACHE_COLOR; | |||
if (src->base.bind & PIPE_BIND_DEPTH_STENCIL) | |||
to_flush |= VIVS_GL_FLUSH_CACHE_DEPTH; | |||
if (to_flush) { | |||
etna_set_state(ctx->stream, VIVS_GL_FLUSH_CACHE, to_flush); | |||
etna_stall(ctx->stream, SYNC_RECIPIENT_RA, SYNC_RECIPIENT_PE); | |||
} | |||
/* Set up color TS to source surface before blit, if needed */ | |||
if (src->levels[blit_info->src.level].ts_size) { | |||
struct etna_reloc reloc; | |||
unsigned ts_offset = | |||
src_lev->ts_offset + blit_info->src.box.z * src_lev->ts_layer_stride; | |||
etna_set_state(ctx->stream, VIVS_TS_MEM_CONFIG, | |||
VIVS_TS_MEM_CONFIG_COLOR_FAST_CLEAR | ts_mem_config); | |||
memset(&reloc, 0, sizeof(struct etna_reloc)); | |||
reloc.bo = src->ts_bo; | |||
reloc.offset = ts_offset; | |||
reloc.flags = ETNA_RELOC_READ; | |||
etna_set_state_reloc(ctx->stream, VIVS_TS_COLOR_STATUS_BASE, &reloc); | |||
memset(&reloc, 0, sizeof(struct etna_reloc)); | |||
reloc.bo = src->bo; | |||
reloc.offset = src_offset; | |||
reloc.flags = ETNA_RELOC_READ; | |||
etna_set_state_reloc(ctx->stream, VIVS_TS_COLOR_SURFACE_BASE, &reloc); | |||
etna_set_state(ctx->stream, VIVS_TS_COLOR_CLEAR_VALUE, | |||
src->levels[blit_info->src.level].clear_value); | |||
} else { | |||
etna_set_state(ctx->stream, VIVS_TS_MEM_CONFIG, ts_mem_config); | |||
} | |||
ctx->dirty |= ETNA_DIRTY_TS; | |||
/* Kick off RS here */ | |||
etna_compile_rs_state(ctx, ©_to_screen, &(struct rs_state) { | |||
.source_format = translate_rs_format(src_format), | |||
.source_tiling = src->layout, | |||
.source = src->bo, | |||
.source_offset = src_offset, | |||
.source_stride = src_lev->stride, | |||
.source_padded_height = src_lev->padded_height, | |||
.dest_format = translate_rs_format(dst_format), | |||
.dest_tiling = dst->layout, | |||
.dest = dst->bo, | |||
.dest_offset = dst_offset, | |||
.dest_stride = dst_lev->stride, | |||
.dest_padded_height = dst_lev->padded_height, | |||
.downsample_x = msaa_xscale > 1, | |||
.downsample_y = msaa_yscale > 1, | |||
.swap_rb = translate_rb_src_dst_swap(src->base.format, dst->base.format), | |||
.dither = {0xffffffff, 0xffffffff}, // XXX dither when going from 24 to 16 bit? | |||
.clear_mode = VIVS_RS_CLEAR_CONTROL_MODE_DISABLED, | |||
.width = width, | |||
.height = height | |||
}); | |||
etna_submit_rs_state(ctx, ©_to_screen); | |||
resource_written(ctx, &dst->base); | |||
dst->seqno++; | |||
return TRUE; | |||
manual: | |||
if (src->layout == ETNA_LAYOUT_TILED && dst->layout == ETNA_LAYOUT_TILED) { | |||
etna_resource_wait(pctx, dst); | |||
etna_resource_wait(pctx, src); | |||
return etna_manual_blit(dst, dst_lev, dst_offset, src, src_lev, src_offset, blit_info); | |||
} | |||
return FALSE; | |||
} | |||
static void | |||
etna_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info) | |||
{ | |||
/* This is a more extended version of resource_copy_region */ | |||
/* TODO Some cases can be handled by RS; if not, fall back to rendering or | |||
* even CPU copy block of pixels from info->src to info->dst | |||
* (resource, level, box, format); | |||
* function is used for scaling, flipping in x and y direction (negative | |||
* width/height), format conversion, mask and filter and even a scissor rectangle | |||
* | |||
* What can the RS do for us: | |||
* convert between tiling formats (layouts) | |||
* downsample 2x in x and y | |||
* convert between a limited number of pixel formats | |||
* | |||
* For the rest, fall back to util_blitter | |||
* XXX this goes wrong when source surface is supertiled. */ | |||
struct etna_context *ctx = etna_context(pctx); | |||
struct pipe_blit_info info = *blit_info; | |||
if (info.src.resource->nr_samples > 1 && | |||
info.dst.resource->nr_samples <= 1 && | |||
!util_format_is_depth_or_stencil(info.src.resource->format) && | |||
!util_format_is_pure_integer(info.src.resource->format)) { | |||
DBG("color resolve unimplemented"); | |||
return; | |||
} | |||
if (etna_try_rs_blit(pctx, blit_info)) | |||
return; | |||
if (util_try_blit_via_copy_region(pctx, blit_info)) | |||
return; | |||
if (info.mask & PIPE_MASK_S) { | |||
DBG("cannot blit stencil, skipping"); | |||
info.mask &= ~PIPE_MASK_S; | |||
} | |||
if (!util_blitter_is_blit_supported(ctx->blitter, &info)) { | |||
DBG("blit unsupported %s -> %s", | |||
util_format_short_name(info.src.resource->format), | |||
util_format_short_name(info.dst.resource->format)); | |||
return; | |||
} | |||
etna_blit_save_state(ctx); | |||
util_blitter_blit(ctx->blitter, &info); | |||
} | |||
static void | |||
etna_flush_resource(struct pipe_context *pctx, struct pipe_resource *prsc) | |||
{ | |||
struct etna_resource *rsc = etna_resource(prsc); | |||
if (rsc->scanout) | |||
etna_copy_resource(pctx, rsc->scanout->prime, prsc, 0, 0); | |||
} | |||
void | |||
etna_copy_resource(struct pipe_context *pctx, struct pipe_resource *dst, | |||
struct pipe_resource *src, int first_level, int last_level) | |||
{ | |||
struct etna_resource *src_priv = etna_resource(src); | |||
struct etna_resource *dst_priv = etna_resource(dst); | |||
assert(src->format == dst->format); | |||
assert(src->array_size == dst->array_size); | |||
assert(last_level <= dst->last_level && last_level <= src->last_level); | |||
struct pipe_blit_info blit = {}; | |||
blit.mask = util_format_get_mask(dst->format); | |||
blit.filter = PIPE_TEX_FILTER_NEAREST; | |||
blit.src.resource = src; | |||
blit.src.format = src->format; | |||
blit.dst.resource = dst; | |||
blit.dst.format = dst->format; | |||
blit.dst.box.depth = blit.src.box.depth = 1; | |||
/* Copy each level and each layer */ | |||
for (int level = first_level; level <= last_level; level++) { | |||
blit.src.level = blit.dst.level = level; | |||
blit.src.box.width = blit.dst.box.width = | |||
MIN2(src_priv->levels[level].width, dst_priv->levels[level].width); | |||
blit.src.box.height = blit.dst.box.height = | |||
MIN2(src_priv->levels[level].height, dst_priv->levels[level].height); | |||
for (int layer = 0; layer < dst->array_size; layer++) { | |||
blit.src.box.z = blit.dst.box.z = layer; | |||
pctx->blit(pctx, &blit); | |||
} | |||
} | |||
} | |||
void | |||
etna_clear_blit_init(struct pipe_context *pctx) | |||
{ | |||
pctx->clear = etna_clear; | |||
pctx->clear_render_target = etna_clear_render_target; | |||
pctx->clear_depth_stencil = etna_clear_depth_stencil; | |||
pctx->resource_copy_region = etna_resource_copy_region; | |||
pctx->blit = etna_blit; | |||
pctx->flush_resource = etna_flush_resource; | |||
} |
@@ -0,0 +1,48 @@ | |||
/* | |||
* Copyright (c) 2012-2013 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Wladimir J. van der Laan <laanwj@gmail.com> | |||
*/ | |||
#ifndef H_ETNAVIV_CLEAR_BLIT | |||
#define H_ETNAVIV_CLEAR_BLIT | |||
#include <stdint.h> | |||
struct etna_context; | |||
struct etna_surface; | |||
#include "pipe/p_context.h" | |||
void | |||
etna_rs_gen_clear_surface(struct etna_context *ctx, struct etna_surface *surf, | |||
uint32_t clear_value); | |||
void | |||
etna_copy_resource(struct pipe_context *pctx, struct pipe_resource *dst, | |||
struct pipe_resource *src, int first_level, int last_level); | |||
void | |||
etna_clear_blit_init(struct pipe_context *pctx); | |||
#endif |
@@ -0,0 +1,120 @@ | |||
/* | |||
* Copyright (c) 2012-2015 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Wladimir J. van der Laan <laanwj@gmail.com> | |||
*/ | |||
#ifndef H_ETNAVIV_COMPILER | |||
#define H_ETNAVIV_COMPILER | |||
#include "etnaviv_context.h" | |||
#include "etnaviv_internal.h" | |||
#include "pipe/p_compiler.h" | |||
#include "pipe/p_shader_tokens.h" | |||
/* XXX some of these are pretty arbitrary limits, may be better to switch | |||
* to dynamic allocation at some point. | |||
*/ | |||
#define ETNA_MAX_TEMPS (64) /* max temp register count of all Vivante hw */ | |||
#define ETNA_MAX_TOKENS (2048) | |||
#define ETNA_MAX_IMM (1024) /* max const+imm in 32-bit words */ | |||
#define ETNA_MAX_DECL (2048) /* max declarations */ | |||
#define ETNA_MAX_DEPTH (32) | |||
#define ETNA_MAX_INSTRUCTIONS (2048) | |||
/* compiler output per input/output */ | |||
struct etna_shader_inout { | |||
int reg; /* native register */ | |||
struct tgsi_declaration_semantic semantic; /* tgsi semantic name and index */ | |||
int num_components; | |||
}; | |||
struct etna_shader_io_file { | |||
size_t num_reg; | |||
struct etna_shader_inout reg[ETNA_NUM_INPUTS]; | |||
}; | |||
/* shader object, for linking */ | |||
struct etna_shader { | |||
uint processor; /* TGSI_PROCESSOR_... */ | |||
uint32_t code_size; /* code size in uint32 words */ | |||
uint32_t *code; | |||
unsigned num_temps; | |||
struct etna_shader_uniform_info uniforms; | |||
/* ETNA_DIRTY_* flags that, when set in context dirty, mean that the | |||
* uniforms have to get (partial) reloaded. */ | |||
uint32_t uniforms_dirty_bits; | |||
/* inputs (for linking) for fs, the inputs must be in register 1..N */ | |||
struct etna_shader_io_file infile; | |||
/* outputs (for linking) */ | |||
struct etna_shader_io_file outfile; | |||
/* index into outputs (for linking) */ | |||
int output_count_per_semantic[TGSI_SEMANTIC_COUNT]; | |||
struct etna_shader_inout * *output_per_semantic_list; /* list of pointers to outputs */ | |||
struct etna_shader_inout **output_per_semantic[TGSI_SEMANTIC_COUNT]; | |||
/* special outputs (vs only) */ | |||
int vs_pos_out_reg; /* VS position output */ | |||
int vs_pointsize_out_reg; /* VS point size output */ | |||
uint32_t vs_load_balancing; | |||
/* special outputs (ps only) */ | |||
int ps_color_out_reg; /* color output register */ | |||
int ps_depth_out_reg; /* depth output register */ | |||
/* unknown input property (XX_INPUT_COUNT, field UNK8) */ | |||
uint32_t input_count_unk8; | |||
}; | |||
struct etna_varying { | |||
uint32_t pa_attributes; | |||
uint8_t num_components; | |||
uint8_t use[4]; | |||
uint8_t reg; | |||
}; | |||
struct etna_shader_link_info { | |||
/* each PS input is annotated with the VS output reg */ | |||
unsigned num_varyings; | |||
struct etna_varying varyings[ETNA_NUM_INPUTS]; | |||
}; | |||
struct etna_shader * | |||
etna_compile_shader(const struct etna_specs *specs, const struct tgsi_token *tokens); | |||
void | |||
etna_dump_shader(const struct etna_shader *shader); | |||
bool | |||
etna_link_shader(struct etna_shader_link_info *info, | |||
const struct etna_shader *vs, const struct etna_shader *fs); | |||
void | |||
etna_destroy_shader(struct etna_shader *shader); | |||
#endif |
@@ -0,0 +1,146 @@ | |||
/* | |||
* Copyright (c) 2015 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Rob Clark <robclark@freedesktop.org> | |||
* Christian Gmeiner <christian.gmeiner@gmail.com> | |||
*/ | |||
#include <err.h> | |||
#include <fcntl.h> | |||
#include <sys/mman.h> | |||
#include <sys/stat.h> | |||
#include <unistd.h> | |||
#include "tgsi/tgsi_dump.h" | |||
#include "tgsi/tgsi_parse.h" | |||
#include "tgsi/tgsi_text.h" | |||
#include "etnaviv_compiler.h" | |||
#include "etnaviv_debug.h" | |||
#include "etnaviv_internal.h" | |||
static const struct etna_specs specs_gc2000 = { | |||
.vs_need_z_div = 0, | |||
.has_sin_cos_sqrt = 1, | |||
.has_sign_floor_ceil = 1, | |||
.vertex_sampler_offset = 8, | |||
.vertex_output_buffer_size = 512, | |||
.vertex_cache_size = 16, | |||
.shader_core_count = 4, | |||
.max_instructions = 512, | |||
.max_varyings = 12, | |||
.max_registers = 64, | |||
.max_vs_uniforms = 168, | |||
.max_ps_uniforms = 128, | |||
.num_constants = 168, | |||
}; | |||
static int | |||
read_file(const char *filename, void **ptr, size_t *size) | |||
{ | |||
int fd, ret; | |||
struct stat st; | |||
*ptr = MAP_FAILED; | |||
fd = open(filename, O_RDONLY); | |||
if (fd == -1) { | |||
warnx("couldn't open `%s'", filename); | |||
return 1; | |||
} | |||
ret = fstat(fd, &st); | |||
if (ret) | |||
errx(1, "couldn't stat `%s'", filename); | |||
*size = st.st_size; | |||
*ptr = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0); | |||
if (*ptr == MAP_FAILED) | |||
errx(1, "couldn't map `%s'", filename); | |||
close(fd); | |||
return 0; | |||
} | |||
static void | |||
print_usage(void) | |||
{ | |||
printf("Usage: etnaviv_compiler [OPTIONS]... FILE\n"); | |||
printf(" --verbose - verbose compiler/debug messages\n"); | |||
printf(" --help - show this message\n"); | |||
} | |||
int | |||
main(int argc, char **argv) | |||
{ | |||
int ret = 0, n = 1; | |||
const char *filename; | |||
struct tgsi_token toks[65536]; | |||
struct tgsi_parse_context parse; | |||
struct etna_shader *shader_obj; | |||
void *ptr; | |||
size_t size; | |||
etna_mesa_debug = ETNA_DBG_MSGS; | |||
while (n < argc) { | |||
if (!strcmp(argv[n], "--verbose")) { | |||
etna_mesa_debug |= ETNA_DBG_COMPILER_MSGS; | |||
n++; | |||
continue; | |||
} | |||
if (!strcmp(argv[n], "--help")) { | |||
print_usage(); | |||
return 0; | |||
} | |||
break; | |||
} | |||
filename = argv[n]; | |||
ret = read_file(filename, &ptr, &size); | |||
if (ret) { | |||
print_usage(); | |||
return ret; | |||
} | |||
debug_printf("%s\n", (char *)ptr); | |||
if (!tgsi_text_translate(ptr, toks, ARRAY_SIZE(toks))) | |||
errx(1, "could not parse `%s'", filename); | |||
tgsi_parse_init(&parse, toks); | |||
shader_obj = etna_compile_shader(&specs_gc2000, toks); | |||
if (shader_obj == NULL) { | |||
fprintf(stderr, "compiler failed!\n"); | |||
return 1; | |||
} | |||
etna_dump_shader(shader_obj); | |||
etna_destroy_shader(shader_obj); | |||
} |
@@ -0,0 +1,323 @@ | |||
/* | |||
* Copyright (c) 2012-2015 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Wladimir J. van der Laan <laanwj@gmail.com> | |||
* Christian Gmeiner <christian.gmeiner@gmail.com> | |||
*/ | |||
#include "etnaviv_context.h" | |||
#include "etnaviv_blend.h" | |||
#include "etnaviv_clear_blit.h" | |||
#include "etnaviv_compiler.h" | |||
#include "etnaviv_debug.h" | |||
#include "etnaviv_emit.h" | |||
#include "etnaviv_fence.h" | |||
#include "etnaviv_query.h" | |||
#include "etnaviv_rasterizer.h" | |||
#include "etnaviv_screen.h" | |||
#include "etnaviv_shader.h" | |||
#include "etnaviv_state.h" | |||
#include "etnaviv_surface.h" | |||
#include "etnaviv_texture.h" | |||
#include "etnaviv_transfer.h" | |||
#include "etnaviv_translate.h" | |||
#include "etnaviv_zsa.h" | |||
#include "pipe/p_context.h" | |||
#include "pipe/p_state.h" | |||
#include "util/u_blitter.h" | |||
#include "util/u_memory.h" | |||
#include "util/u_prim.h" | |||
#include "hw/common.xml.h" | |||
static void | |||
etna_context_destroy(struct pipe_context *pctx) | |||
{ | |||
struct etna_context *ctx = etna_context(pctx); | |||
if (ctx->primconvert) | |||
util_primconvert_destroy(ctx->primconvert); | |||
if (ctx->blitter) | |||
util_blitter_destroy(ctx->blitter); | |||
if (ctx->stream) | |||
etna_cmd_stream_del(ctx->stream); | |||
slab_destroy_child(&ctx->transfer_pool); | |||
FREE(pctx); | |||
} | |||
/* Update render state where needed based on draw operation */ | |||
static void | |||
etna_update_state_for_draw(struct etna_context *ctx, const struct pipe_draw_info *info) | |||
{ | |||
/* Handle primitive restart: | |||
* - If not an indexed draw, we don't care about the state of the primitive restart bit. | |||
* - Otherwise, set the bit in INDEX_STREAM_CONTROL in the index buffer state | |||
* accordingly | |||
* - If the value of the INDEX_STREAM_CONTROL register changed due to this, or | |||
* primitive restart is enabled and the restart index changed, mark the index | |||
* buffer state as dirty | |||
*/ | |||
if (info->indexed) { | |||
uint32_t new_control = ctx->index_buffer.FE_INDEX_STREAM_CONTROL; | |||
if (info->primitive_restart) | |||
new_control |= VIVS_FE_INDEX_STREAM_CONTROL_PRIMITIVE_RESTART; | |||
else | |||
new_control &= ~VIVS_FE_INDEX_STREAM_CONTROL_PRIMITIVE_RESTART; | |||
if (ctx->index_buffer.FE_INDEX_STREAM_CONTROL != new_control || | |||
(info->primitive_restart && ctx->index_buffer.FE_PRIMITIVE_RESTART_INDEX != info->restart_index)) { | |||
ctx->index_buffer.FE_INDEX_STREAM_CONTROL = new_control; | |||
ctx->index_buffer.FE_PRIMITIVE_RESTART_INDEX = info->restart_index; | |||
ctx->dirty |= ETNA_DIRTY_INDEX_BUFFER; | |||
} | |||
} | |||
} | |||
static void | |||
etna_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info) | |||
{ | |||
struct etna_context *ctx = etna_context(pctx); | |||
struct pipe_framebuffer_state *pfb = &ctx->framebuffer_s; | |||
uint32_t draw_mode; | |||
unsigned i; | |||
if (ctx->vertex_elements == NULL || ctx->vertex_elements->num_elements == 0) | |||
return; /* Nothing to do */ | |||
if (!(ctx->prim_hwsupport & (1 << info->mode))) { | |||
struct primconvert_context *primconvert = ctx->primconvert; | |||
util_primconvert_save_index_buffer(primconvert, &ctx->index_buffer.ib); | |||
util_primconvert_save_rasterizer_state(primconvert, ctx->rasterizer); | |||
util_primconvert_draw_vbo(primconvert, info); | |||
return; | |||
} | |||
int prims = u_decomposed_prims_for_vertices(info->mode, info->count); | |||
if (unlikely(prims <= 0)) { | |||
DBG("Invalid draw primitive mode=%i or no primitives to be drawn", info->mode); | |||
return; | |||
} | |||
draw_mode = translate_draw_mode(info->mode); | |||
if (draw_mode == ETNA_NO_MATCH) { | |||
BUG("Unsupported draw mode"); | |||
return; | |||
} | |||
if (info->indexed && !ctx->index_buffer.FE_INDEX_STREAM_BASE_ADDR.bo) { | |||
BUG("Unsupported or no index buffer"); | |||
return; | |||
} | |||
/* Update any derived state */ | |||
if (!etna_state_update(ctx)) | |||
return; | |||
/* | |||
* Figure out the buffers/features we need: | |||
*/ | |||
if (etna_depth_enabled(ctx)) | |||
resource_written(ctx, pfb->zsbuf->texture); | |||
if (etna_stencil_enabled(ctx)) | |||
resource_written(ctx, pfb->zsbuf->texture); | |||
for (i = 0; i < pfb->nr_cbufs; i++) { | |||
struct pipe_resource *surf; | |||
if (!pfb->cbufs[i]) | |||
continue; | |||
surf = pfb->cbufs[i]->texture; | |||
resource_written(ctx, surf); | |||
} | |||
/* Mark constant buffers as being read */ | |||
resource_read(ctx, ctx->constant_buffer[PIPE_SHADER_VERTEX].buffer); | |||
resource_read(ctx, ctx->constant_buffer[PIPE_SHADER_FRAGMENT].buffer); | |||
/* Mark VBOs as being read */ | |||
for (i = 0; i < ctx->vertex_buffer.count; i++) { | |||
assert(!ctx->vertex_buffer.vb[i].user_buffer); | |||
resource_read(ctx, ctx->vertex_buffer.vb[i].buffer); | |||
} | |||
/* Mark index buffer as being read */ | |||
resource_read(ctx, ctx->index_buffer.ib.buffer); | |||
/* Mark textures as being read */ | |||
for (i = 0; i < PIPE_MAX_SAMPLERS; i++) | |||
if (ctx->sampler_view[i]) | |||
resource_read(ctx, ctx->sampler_view[i]->texture); | |||
ctx->stats.prims_emitted += u_reduced_prims_for_vertices(info->mode, info->count); | |||
ctx->stats.draw_calls++; | |||
/* Update state for this draw operation */ | |||
etna_update_state_for_draw(ctx, info); | |||
/* First, sync state, then emit DRAW_PRIMITIVES or DRAW_INDEXED_PRIMITIVES */ | |||
etna_emit_state(ctx); | |||
if (info->indexed) | |||
etna_draw_indexed_primitives(ctx->stream, draw_mode, info->start, prims, info->index_bias); | |||
else | |||
etna_draw_primitives(ctx->stream, draw_mode, info->start, prims); | |||
if (DBG_ENABLED(ETNA_DBG_DRAW_STALL)) { | |||
/* Stall the FE after every draw operation. This allows better | |||
* debug of GPU hang conditions, as the FE will indicate which | |||
* draw op has caused the hang. */ | |||
etna_stall(ctx->stream, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE); | |||
} | |||
if (DBG_ENABLED(ETNA_DBG_FLUSH_ALL)) | |||
pctx->flush(pctx, NULL, 0); | |||
if (ctx->framebuffer.cbuf) | |||
etna_resource(ctx->framebuffer.cbuf->texture)->seqno++; | |||
if (ctx->framebuffer.zsbuf) | |||
etna_resource(ctx->framebuffer.zsbuf->texture)->seqno++; | |||
} | |||
static void | |||
etna_flush(struct pipe_context *pctx, struct pipe_fence_handle **fence, | |||
enum pipe_flush_flags flags) | |||
{ | |||
struct etna_context *ctx = etna_context(pctx); | |||
etna_cmd_stream_flush(ctx->stream); | |||
if (fence) | |||
*fence = etna_fence_create(pctx); | |||
} | |||
static void | |||
etna_cmd_stream_reset_notify(struct etna_cmd_stream *stream, void *priv) | |||
{ | |||
struct etna_context *ctx = priv; | |||
struct etna_resource *rsc, *rsc_tmp; | |||
etna_set_state(stream, VIVS_GL_API_MODE, VIVS_GL_API_MODE_OPENGL); | |||
etna_set_state(stream, VIVS_GL_VERTEX_ELEMENT_CONFIG, 0x00000001); | |||
etna_set_state(stream, VIVS_RA_EARLY_DEPTH, 0x00000031); | |||
etna_set_state(stream, VIVS_PA_W_CLIP_LIMIT, 0x34000001); | |||
ctx->dirty = ~0L; | |||
/* go through all the used resources and clear their status flag */ | |||
LIST_FOR_EACH_ENTRY_SAFE(rsc, rsc_tmp, &ctx->used_resources, list) | |||
{ | |||
debug_assert(rsc->status != 0); | |||
rsc->status = 0; | |||
rsc->pending_ctx = NULL; | |||
list_delinit(&rsc->list); | |||
} | |||
assert(LIST_IS_EMPTY(&ctx->used_resources)); | |||
} | |||
struct pipe_context * | |||
etna_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags) | |||
{ | |||
struct etna_context *ctx = CALLOC_STRUCT(etna_context); | |||
struct etna_screen *screen; | |||
struct pipe_context *pctx = NULL; | |||
if (ctx == NULL) | |||
return NULL; | |||
screen = etna_screen(pscreen); | |||
ctx->stream = etna_cmd_stream_new(screen->pipe, 0x2000, &etna_cmd_stream_reset_notify, ctx); | |||
if (ctx->stream == NULL) | |||
goto fail; | |||
pctx = &ctx->base; | |||
pctx->priv = ctx; | |||
pctx->screen = pscreen; | |||
/* context ctxate setup */ | |||
ctx->specs = screen->specs; | |||
ctx->screen = screen; | |||
/* need some sane default in case state tracker doesn't set some state: */ | |||
ctx->sample_mask = 0xffff; | |||
list_inithead(&ctx->used_resources); | |||
/* Set sensible defaults for state */ | |||
etna_cmd_stream_reset_notify(ctx->stream, ctx); | |||
pctx->destroy = etna_context_destroy; | |||
pctx->draw_vbo = etna_draw_vbo; | |||
pctx->flush = etna_flush; | |||
/* creation of compile states */ | |||
pctx->create_blend_state = etna_blend_state_create; | |||
pctx->create_rasterizer_state = etna_rasterizer_state_create; | |||
pctx->create_depth_stencil_alpha_state = etna_zsa_state_create; | |||
etna_clear_blit_init(pctx); | |||
etna_query_context_init(pctx); | |||
etna_state_init(pctx); | |||
etna_surface_init(pctx); | |||
etna_shader_init(pctx); | |||
etna_texture_init(pctx); | |||
etna_transfer_init(pctx); | |||
ctx->blitter = util_blitter_create(pctx); | |||
if (!ctx->blitter) | |||
goto fail; | |||
/* Generate the bitmask of supported draw primitives. */ | |||
ctx->prim_hwsupport = 1 << PIPE_PRIM_POINTS | | |||
1 << PIPE_PRIM_LINES | | |||
1 << PIPE_PRIM_LINE_STRIP | | |||
1 << PIPE_PRIM_TRIANGLES | | |||
1 << PIPE_PRIM_TRIANGLE_STRIP | | |||
1 << PIPE_PRIM_TRIANGLE_FAN; | |||
if (VIV_FEATURE(ctx->screen, chipMinorFeatures2, LINE_LOOP)) | |||
ctx->prim_hwsupport |= 1 << PIPE_PRIM_LINE_LOOP; | |||
ctx->primconvert = util_primconvert_create(pctx, ctx->prim_hwsupport); | |||
if (!ctx->primconvert) | |||
goto fail; | |||
slab_create_child(&ctx->transfer_pool, &screen->transfer_pool); | |||
return pctx; | |||
fail: | |||
pctx->destroy(pctx); | |||
return NULL; | |||
} |
@@ -0,0 +1,194 @@ | |||
/* | |||
* Copyright (c) 2012-2015 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Wladimir J. van der Laan <laanwj@gmail.com> | |||
* Christian Gmeiner <christian.gmeiner@gmail.com> | |||
*/ | |||
#ifndef H_ETNAVIV_CONTEXT | |||
#define H_ETNAVIV_CONTEXT | |||
#include <stdint.h> | |||
#include "etnaviv_resource.h" | |||
#include "etnaviv_tiling.h" | |||
#include "indices/u_primconvert.h" | |||
#include "pipe/p_context.h" | |||
#include "pipe/p_defines.h" | |||
#include "pipe/p_format.h" | |||
#include "pipe/p_shader_tokens.h" | |||
#include "pipe/p_state.h" | |||
#include "util/slab.h" | |||
struct pipe_screen; | |||
struct etna_shader; | |||
struct etna_index_buffer { | |||
struct pipe_index_buffer ib; | |||
struct etna_reloc FE_INDEX_STREAM_BASE_ADDR; | |||
uint32_t FE_INDEX_STREAM_CONTROL; | |||
uint32_t FE_PRIMITIVE_RESTART_INDEX; | |||
}; | |||
struct etna_shader_input { | |||
int vs_reg; /* VS input register */ | |||
}; | |||
enum etna_varying_special { | |||
ETNA_VARYING_VSOUT = 0, /* from VS */ | |||
ETNA_VARYING_POINTCOORD, /* point texture coord */ | |||
}; | |||
struct etna_shader_varying { | |||
int num_components; | |||
enum etna_varying_special special; | |||
int pa_attributes; | |||
int vs_reg; /* VS output register */ | |||
}; | |||
struct etna_transfer { | |||
struct pipe_transfer base; | |||
struct pipe_resource *rsc; | |||
void *staging; | |||
}; | |||
struct etna_vertexbuf_state { | |||
struct pipe_vertex_buffer vb[PIPE_MAX_ATTRIBS]; | |||
struct compiled_set_vertex_buffer cvb[PIPE_MAX_ATTRIBS]; | |||
unsigned count; | |||
uint32_t enabled_mask; | |||
}; | |||
enum etna_immediate_contents { | |||
ETNA_IMMEDIATE_UNUSED = 0, | |||
ETNA_IMMEDIATE_CONSTANT, | |||
ETNA_IMMEDIATE_TEXRECT_SCALE_X, | |||
ETNA_IMMEDIATE_TEXRECT_SCALE_Y, | |||
}; | |||
struct etna_shader_uniform_info { | |||
enum etna_immediate_contents *imm_contents; | |||
uint32_t *imm_data; | |||
uint32_t imm_count; | |||
uint32_t const_count; | |||
}; | |||
struct etna_context { | |||
struct pipe_context base; | |||
struct etna_specs specs; | |||
struct etna_screen *screen; | |||
struct etna_cmd_stream *stream; | |||
/* which state objects need to be re-emit'd: */ | |||
enum { | |||
ETNA_DIRTY_BLEND = (1 << 0), | |||
ETNA_DIRTY_SAMPLERS = (1 << 1), | |||
ETNA_DIRTY_RASTERIZER = (1 << 2), | |||
ETNA_DIRTY_ZSA = (1 << 3), | |||
ETNA_DIRTY_VERTEX_ELEMENTS = (1 << 4), | |||
ETNA_DIRTY_BLEND_COLOR = (1 << 6), | |||
ETNA_DIRTY_STENCIL_REF = (1 << 7), | |||
ETNA_DIRTY_SAMPLE_MASK = (1 << 8), | |||
ETNA_DIRTY_VIEWPORT = (1 << 9), | |||
ETNA_DIRTY_FRAMEBUFFER = (1 << 10), | |||
ETNA_DIRTY_SCISSOR = (1 << 11), | |||
ETNA_DIRTY_SAMPLER_VIEWS = (1 << 12), | |||
ETNA_DIRTY_CONSTBUF = (1 << 13), | |||
ETNA_DIRTY_VERTEX_BUFFERS = (1 << 14), | |||
ETNA_DIRTY_INDEX_BUFFER = (1 << 15), | |||
ETNA_DIRTY_SHADER = (1 << 16), | |||
ETNA_DIRTY_TS = (1 << 17), | |||
ETNA_DIRTY_TEXTURE_CACHES = (1 << 18), | |||
} dirty; | |||
uint32_t prim_hwsupport; | |||
struct primconvert_context *primconvert; | |||
/* list of resources used by currently-unsubmitted renders */ | |||
struct list_head used_resources; | |||
struct slab_child_pool transfer_pool; | |||
struct blitter_context *blitter; | |||
/* compiled bindable state */ | |||
unsigned sample_mask; | |||
struct pipe_blend_state *blend; | |||
unsigned num_fragment_samplers; | |||
uint32_t active_samplers; | |||
struct pipe_sampler_state *sampler[PIPE_MAX_SAMPLERS]; | |||
struct pipe_rasterizer_state *rasterizer; | |||
struct pipe_depth_stencil_alpha_state *zsa; | |||
struct compiled_vertex_elements_state *vertex_elements; | |||
struct compiled_shader_state shader_state; | |||
/* to simplify the emit process we store pre compiled state objects, | |||
* which got 'compiled' during state change. */ | |||
struct compiled_blend_color blend_color; | |||
struct compiled_stencil_ref stencil_ref; | |||
struct compiled_framebuffer_state framebuffer; | |||
struct compiled_scissor_state scissor; | |||
struct compiled_viewport_state viewport; | |||
unsigned num_fragment_sampler_views; | |||
uint32_t active_sampler_views; | |||
struct pipe_sampler_view *sampler_view[PIPE_MAX_SAMPLERS]; | |||
struct pipe_constant_buffer constant_buffer[PIPE_SHADER_TYPES]; | |||
struct etna_vertexbuf_state vertex_buffer; | |||
struct etna_index_buffer index_buffer; | |||
/* pointers to the bound state. these are mainly kept around for the blitter */ | |||
struct etna_shader *vs; | |||
struct etna_shader *fs; | |||
/* saved parameter-like state. these are mainly kept around for the blitter */ | |||
struct pipe_framebuffer_state framebuffer_s; | |||
struct pipe_stencil_ref stencil_ref_s; | |||
struct pipe_viewport_state viewport_s; | |||
struct pipe_scissor_state scissor_s; | |||
/* cached state of entire GPU */ | |||
struct etna_3d_state gpu3d; | |||
/* stats/counters */ | |||
struct { | |||
uint64_t prims_emitted; | |||
uint64_t draw_calls; | |||
} stats; | |||
}; | |||
static inline struct etna_context * | |||
etna_context(struct pipe_context *pctx) | |||
{ | |||
return (struct etna_context *)pctx; | |||
} | |||
static inline struct etna_transfer * | |||
etna_transfer(struct pipe_transfer *p) | |||
{ | |||
return (struct etna_transfer *)p; | |||
} | |||
struct pipe_context * | |||
etna_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags); | |||
#endif |
@@ -0,0 +1,79 @@ | |||
/* | |||
* Copyright (c) 2012-2013 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
*/ | |||
/* Common debug stuffl */ | |||
#ifndef H_ETNA_DEBUG | |||
#define H_ETNA_DEBUG | |||
#include "util/u_debug.h" | |||
#include <stdint.h> | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
/* Logging */ | |||
#define ETNA_DBG_MSGS 0x1 /* Warnings and non-fatal errors */ | |||
#define ETNA_DBG_FRAME_MSGS 0x2 | |||
#define ETNA_DBG_RESOURCE_MSGS 0x4 | |||
#define ETNA_DBG_COMPILER_MSGS 0x8 | |||
#define ETNA_DBG_LINKER_MSGS 0x10 | |||
#define ETNA_DBG_DUMP_SHADERS 0x20 | |||
/* Bypasses */ | |||
#define ETNA_DBG_NO_TS 0x1000 /* Disable TS */ | |||
#define ETNA_DBG_NO_AUTODISABLE 0x2000 /* Disable autodisable */ | |||
#define ETNA_DBG_NO_SUPERTILE 0x4000 /* Disable supertile */ | |||
#define ETNA_DBG_NO_EARLY_Z 0x8000 /* Disable early z */ | |||
#define ETNA_DBG_CFLUSH_ALL 0x10000 /* Flush before every state update + draw call */ | |||
#define ETNA_DBG_MSAA_2X 0x20000 /* Force 2X MSAA for screen */ | |||
#define ETNA_DBG_MSAA_4X 0x40000 /* Force 4X MSAA for screen */ | |||
#define ETNA_DBG_FINISH_ALL 0x80000 /* Finish on every flush */ | |||
#define ETNA_DBG_FLUSH_ALL 0x100000 /* Flush after every rendered primitive */ | |||
#define ETNA_DBG_ZERO 0x200000 /* Zero all resources after allocation */ | |||
#define ETNA_DBG_DRAW_STALL 0x400000 /* Stall FE/PE after every draw op */ | |||
extern int etna_mesa_debug; /* set in etna_screen.c from ETNA_DEBUG */ | |||
#define DBG_ENABLED(flag) unlikely(etna_mesa_debug & (flag)) | |||
#define DBG_F(flag, fmt, ...) \ | |||
do { \ | |||
if (etna_mesa_debug & (flag)) \ | |||
debug_printf("%s:%d: " fmt "\n", __FUNCTION__, __LINE__, \ | |||
##__VA_ARGS__); \ | |||
} while (0) | |||
#define DBG(fmt, ...) \ | |||
do { \ | |||
if (etna_mesa_debug & ETNA_DBG_MSGS) \ | |||
debug_printf("%s:%d: " fmt "\n", __FUNCTION__, __LINE__, \ | |||
##__VA_ARGS__); \ | |||
} while (0) | |||
/* A serious bug, show this even in non-debug mode */ | |||
#define BUG(fmt, ...) \ | |||
do { \ | |||
printf("%s:%d: " fmt "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__); \ | |||
} while (0) | |||
#endif |
@@ -0,0 +1,612 @@ | |||
/* | |||
* Copyright (c) 2016 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Christian Gmeiner <christian.gmeiner@gmail.com> | |||
*/ | |||
#include "etnaviv_disasm.h" | |||
#include <assert.h> | |||
#include <stdbool.h> | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include "hw/isa.xml.h" | |||
struct instr { | |||
/* dword0: */ | |||
uint32_t opc : 6; | |||
uint32_t cond : 5; | |||
uint32_t sat : 1; | |||
uint32_t dst_use : 1; | |||
uint32_t dst_amode : 3; | |||
uint32_t dst_reg : 7; | |||
uint32_t dst_comps : 4; | |||
uint32_t tex_id : 5; | |||
/* dword1: */ | |||
uint32_t tex_amode : 3; | |||
uint32_t tex_swiz : 8; | |||
uint32_t src0_use : 1; | |||
uint32_t src0_reg : 9; | |||
uint32_t type_bit2 : 1; | |||
uint32_t src0_swiz : 8; | |||
uint32_t src0_neg : 1; | |||
uint32_t src0_abs : 1; | |||
/* dword2: */ | |||
uint32_t src0_amode : 3; | |||
uint32_t src0_rgroup : 3; | |||
uint32_t src1_use : 1; | |||
uint32_t src1_reg : 9; | |||
uint32_t opcode_bit6 : 1; | |||
uint32_t src1_swiz : 8; | |||
uint32_t src1_neg : 1; | |||
uint32_t src1_abs : 1; | |||
uint32_t src1_amode : 3; | |||
uint32_t type_bit01 : 2; | |||
/* dword3: */ | |||
union { | |||
struct { | |||
uint32_t src1_rgroup : 3; | |||
uint32_t src2_use : 1; | |||
uint32_t src2_reg : 9; | |||
uint32_t unk3_13 : 1; | |||
uint32_t src2_swiz : 8; | |||
uint32_t src2_neg : 1; | |||
uint32_t src2_abs : 1; | |||
uint32_t unk3_24 : 1; | |||
uint32_t src2_amode : 3; | |||
uint32_t src2_rgroup : 3; | |||
uint32_t unk3_31 : 1; | |||
}; | |||
uint32_t dword3; | |||
}; | |||
}; | |||
struct dst_operand { | |||
bool use; | |||
uint8_t amode; | |||
uint16_t reg; | |||
uint8_t comps; | |||
}; | |||
struct src_operand { | |||
bool use; | |||
bool neg; | |||
bool abs; | |||
uint8_t rgroup; | |||
uint16_t reg; | |||
uint8_t swiz; | |||
uint8_t amode; | |||
}; | |||
struct tex_operand { | |||
uint8_t id; | |||
uint8_t amode; | |||
uint8_t swiz; | |||
}; | |||
struct opc_operands { | |||
struct dst_operand *dst; | |||
struct tex_operand *tex; | |||
struct src_operand *src0; | |||
struct src_operand *src1; | |||
struct src_operand *src2; | |||
int imm; | |||
}; | |||
static void | |||
printf_type(uint8_t type) | |||
{ | |||
switch(type) { | |||
case INST_TYPE_F32: | |||
/* as f32 is the default print nothing */ | |||
break; | |||
case INST_TYPE_S32: | |||
printf(".s32"); | |||
break; | |||
case INST_TYPE_S8: | |||
printf(".s8"); | |||
break; | |||
case INST_TYPE_U16: | |||
printf(".u16"); | |||
break; | |||
case INST_TYPE_F16: | |||
printf(".f16"); | |||
break; | |||
case INST_TYPE_S16: | |||
printf(".s16"); | |||
break; | |||
case INST_TYPE_U32: | |||
printf(".u32"); | |||
break; | |||
case INST_TYPE_U8: | |||
printf(".u8"); | |||
break; | |||
default: | |||
abort(); | |||
break; | |||
} | |||
} | |||
static void | |||
print_condition(uint8_t condition) | |||
{ | |||
switch (condition) { | |||
case INST_CONDITION_TRUE: | |||
break; | |||
case INST_CONDITION_GT: | |||
printf(".GT"); | |||
break; | |||
case INST_CONDITION_LT: | |||
printf(".LT"); | |||
break; | |||
case INST_CONDITION_GE: | |||
printf(".GE"); | |||
break; | |||
case INST_CONDITION_LE: | |||
printf(".LE"); | |||
break; | |||
case INST_CONDITION_EQ: | |||
printf(".EQ"); | |||
break; | |||
case INST_CONDITION_NE: | |||
printf(".NE"); | |||
break; | |||
case INST_CONDITION_AND: | |||
printf(".AND"); | |||
break; | |||
case INST_CONDITION_OR: | |||
printf(".OR"); | |||
break; | |||
case INST_CONDITION_XOR: | |||
printf(".XOR"); | |||
break; | |||
case INST_CONDITION_NOT: | |||
printf(".NOT"); | |||
break; | |||
case INST_CONDITION_NZ: | |||
printf(".NZ"); | |||
break; | |||
case INST_CONDITION_GEZ: | |||
printf(".GEZ"); | |||
break; | |||
case INST_CONDITION_GZ: | |||
printf(".GZ"); | |||
break; | |||
case INST_CONDITION_LEZ: | |||
printf(".LEZ"); | |||
break; | |||
case INST_CONDITION_LZ: | |||
printf(".LZ"); | |||
break; | |||
default: | |||
abort(); | |||
break; | |||
} | |||
} | |||
static void | |||
print_rgroup(uint8_t rgoup) | |||
{ | |||
switch (rgoup) { | |||
case INST_RGROUP_TEMP: | |||
printf("t"); | |||
break; | |||
case INST_RGROUP_INTERNAL: | |||
printf("i"); | |||
break; | |||
case INST_RGROUP_UNIFORM_0: | |||
case INST_RGROUP_UNIFORM_1: | |||
printf("u"); | |||
break; | |||
} | |||
} | |||
static void | |||
print_components(uint8_t components) | |||
{ | |||
if (components == 15) | |||
return; | |||
printf("."); | |||
if (components & INST_COMPS_X) | |||
printf("x"); | |||
else | |||
printf("_"); | |||
if (components & INST_COMPS_Y) | |||
printf("y"); | |||
else | |||
printf("_"); | |||
if (components & INST_COMPS_Z) | |||
printf("z"); | |||
else | |||
printf("_"); | |||
if (components & INST_COMPS_W) | |||
printf("w"); | |||
else | |||
printf("_"); | |||
} | |||
static inline void | |||
print_swiz_comp(uint8_t swiz_comp) | |||
{ | |||
switch (swiz_comp) { | |||
case INST_SWIZ_COMP_X: | |||
printf("x"); | |||
break; | |||
case INST_SWIZ_COMP_Y: | |||
printf("y"); | |||
break; | |||
case INST_SWIZ_COMP_Z: | |||
printf("z"); | |||
break; | |||
case INST_SWIZ_COMP_W: | |||
printf("w"); | |||
break; | |||
default: | |||
abort(); | |||
break; | |||
} | |||
} | |||
static void | |||
print_swiz(uint8_t swiz) | |||
{ | |||
// if a null swizzle | |||
if (swiz == 0xe4) | |||
return; | |||
const unsigned x = swiz & 0x3; | |||
const unsigned y = (swiz & 0x0C) >> 2; | |||
const unsigned z = (swiz & 0x30) >> 4; | |||
const unsigned w = (swiz & 0xc0) >> 6; | |||
printf("."); | |||
print_swiz_comp(x); | |||
print_swiz_comp(y); | |||
print_swiz_comp(z); | |||
print_swiz_comp(w); | |||
} | |||
static void | |||
print_amode(uint8_t amode) | |||
{ | |||
switch (amode) { | |||
case INST_AMODE_DIRECT: | |||
/* nothing to output */ | |||
break; | |||
case INST_AMODE_ADD_A_X: | |||
printf("[a.x]"); | |||
break; | |||
case INST_AMODE_ADD_A_Y: | |||
printf("[a.y]"); | |||
break; | |||
case INST_AMODE_ADD_A_Z: | |||
printf("[a.z]"); | |||
break; | |||
case INST_AMODE_ADD_A_W: | |||
printf("[a.w]"); | |||
break; | |||
default: | |||
abort(); | |||
break; | |||
} | |||
} | |||
static void | |||
print_dst(struct dst_operand *dst, bool sep) | |||
{ | |||
if (dst->use) { | |||
printf("t%u", dst->reg); | |||
print_amode(dst->amode); | |||
print_components(dst->comps); | |||
} else { | |||
printf("void"); | |||
} | |||
if (sep) | |||
printf(", "); | |||
} | |||
static void | |||
print_tex(struct tex_operand *tex, bool sep) | |||
{ | |||
printf("tex%u", tex->id); | |||
print_amode(tex->amode); | |||
print_swiz(tex->swiz); | |||
if (sep) | |||
printf(", "); | |||
} | |||
static void | |||
print_src(struct src_operand *src, bool sep) | |||
{ | |||
if (src->use) { | |||
if (src->neg) | |||
printf("-"); | |||
if (src->abs) | |||
printf("|"); | |||
if (src->rgroup == INST_RGROUP_UNIFORM_1) | |||
src->reg += 128; | |||
print_rgroup(src->rgroup); | |||
printf("%u", src->reg); | |||
print_amode(src->amode); | |||
print_swiz(src->swiz); | |||
if (src->abs) | |||
printf("|"); | |||
} else { | |||
printf("void"); | |||
} | |||
if (sep) | |||
printf(", "); | |||
} | |||
static void | |||
print_opc_default(struct opc_operands *operands) | |||
{ | |||
print_dst(operands->dst, true); | |||
print_src(operands->src0, true); | |||
print_src(operands->src1, true); | |||
print_src(operands->src2, false); | |||
} | |||
static void | |||
print_opc_mov(struct opc_operands *operands) | |||
{ | |||
// dst (areg) | |||
printf("a%u", operands->dst->reg); | |||
print_components(operands->dst->comps); | |||
printf(", "); | |||
print_src(operands->src0, true); | |||
print_src(operands->src1, true); | |||
print_src(operands->src2, false); | |||
} | |||
static void | |||
print_opc_tex(struct opc_operands *operands) | |||
{ | |||
print_dst(operands->dst, true); | |||
print_tex(operands->tex, true); | |||
print_src(operands->src0, true); | |||
print_src(operands->src1, true); | |||
print_src(operands->src2, false); | |||
} | |||
static void | |||
print_opc_imm(struct opc_operands *operands) | |||
{ | |||
print_dst(operands->dst, true); | |||
print_src(operands->src0, true); | |||
print_src(operands->src1, true); | |||
printf("label_%04d", operands->imm); | |||
} | |||
#define OPC_BITS 7 | |||
static const struct opc_info { | |||
const char *name; | |||
void (*print)(struct opc_operands *operands); | |||
} opcs[1 << OPC_BITS] = { | |||
#define OPC(opc) [INST_OPCODE_##opc] = {#opc, print_opc_default} | |||
#define OPC_MOV(opc) [INST_OPCODE_##opc] = {#opc, print_opc_mov} | |||
#define OPC_TEX(opc) [INST_OPCODE_##opc] = {#opc, print_opc_tex} | |||
#define OPC_IMM(opc) [INST_OPCODE_##opc] = {#opc, print_opc_imm} | |||
OPC(NOP), | |||
OPC(ADD), | |||
OPC(MAD), | |||
OPC(MUL), | |||
OPC(DST), | |||
OPC(DP3), | |||
OPC(DP4), | |||
OPC(DSX), | |||
OPC(DSY), | |||
OPC(MOV), | |||
OPC_MOV(MOVAR), | |||
OPC_MOV(MOVAF), | |||
OPC(RCP), | |||
OPC(RSQ), | |||
OPC(LITP), | |||
OPC(SELECT), | |||
OPC(SET), | |||
OPC(EXP), | |||
OPC(LOG), | |||
OPC(FRC), | |||
OPC_IMM(CALL), | |||
OPC(RET), | |||
OPC_IMM(BRANCH), | |||
OPC_TEX(TEXKILL), | |||
OPC_TEX(TEXLD), | |||
OPC_TEX(TEXLDB), | |||
OPC_TEX(TEXLDD), | |||
OPC_TEX(TEXLDL), | |||
OPC_TEX(TEXLDPCF), | |||
OPC(REP), | |||
OPC(ENDREP), | |||
OPC(LOOP), | |||
OPC(ENDLOOP), | |||
OPC(SQRT), | |||
OPC(SIN), | |||
OPC(COS), | |||
OPC(FLOOR), | |||
OPC(CEIL), | |||
OPC(SIGN), | |||
OPC(I2F), | |||
OPC(CMP), | |||
OPC(LOAD), | |||
OPC(STORE), | |||
OPC(IMULLO0), | |||
OPC(IMULHI0), | |||
OPC(LEADZERO), | |||
OPC(LSHIFT), | |||
OPC(RSHIFT), | |||
OPC(ROTATE), | |||
OPC(OR), | |||
OPC(AND), | |||
OPC(XOR), | |||
OPC(NOT), | |||
}; | |||
static void | |||
print_instr(uint32_t *dwords, int n, enum debug_t debug) | |||
{ | |||
struct instr *instr = (struct instr *)dwords; | |||
const unsigned opc = instr->opc | (instr->opcode_bit6 << 6); | |||
const char *name = opcs[opc].name; | |||
printf("%04d: ", n); | |||
if (debug & PRINT_RAW) | |||
printf("%08x %08x %08x %08x ", dwords[0], dwords[1], dwords[2], | |||
dwords[3]); | |||
if (name) { | |||
struct dst_operand dst = { | |||
.use = instr->dst_use, | |||
.amode = instr->dst_amode, | |||
.reg = instr->dst_reg, | |||
.comps = instr->dst_comps | |||
}; | |||
struct tex_operand tex = { | |||
.id = instr->tex_id, | |||
.amode = instr->tex_amode, | |||
.swiz = instr->tex_swiz, | |||
}; | |||
struct src_operand src0 = { | |||
.use = instr->src0_use, | |||
.neg = instr->src0_neg, | |||
.abs = instr->src0_abs, | |||
.rgroup = instr->src0_rgroup, | |||
.reg = instr->src0_reg, | |||
.swiz = instr->src0_swiz, | |||
.amode = instr->src0_amode, | |||
}; | |||
struct src_operand src1 = { | |||
.use = instr->src1_use, | |||
.neg = instr->src1_neg, | |||
.abs = instr->src1_abs, | |||
.rgroup = instr->src1_rgroup, | |||
.reg = instr->src1_reg, | |||
.swiz = instr->src1_swiz, | |||
.amode = instr->src1_amode, | |||
}; | |||
struct src_operand src2 = { | |||
.use = instr->src2_use, | |||
.neg = instr->src2_neg, | |||
.abs = instr->src2_abs, | |||
.rgroup = instr->src2_rgroup, | |||
.reg = instr->src2_reg, | |||
.swiz = instr->src2_swiz, | |||
.amode = instr->src2_amode, | |||
}; | |||
int imm = (instr->dword3 & VIV_ISA_WORD_3_SRC2_IMM__MASK) | |||
>> VIV_ISA_WORD_3_SRC2_IMM__SHIFT; | |||
struct opc_operands operands = { | |||
.dst = &dst, | |||
.tex = &tex, | |||
.src0 = &src0, | |||
.src1 = &src1, | |||
.src2 = &src2, | |||
.imm = imm, | |||
}; | |||
uint8_t type = instr->type_bit01 | (instr->type_bit2 << 2); | |||
printf("%s", name); | |||
printf_type(type); | |||
if (instr->sat) | |||
printf(".SAT"); | |||
print_condition(instr->cond); | |||
printf(" "); | |||
opcs[opc].print(&operands); | |||
} else { | |||
printf("unknown (%d)", instr->opc); | |||
} | |||
printf("\n"); | |||
} | |||
void | |||
etna_disasm(uint32_t *dwords, int sizedwords, enum debug_t debug) | |||
{ | |||
unsigned i; | |||
assert((sizedwords % 2) == 0); | |||
for (i = 0; i < sizedwords; i += 4) | |||
print_instr(&dwords[i], i / 4, debug); | |||
} |
@@ -0,0 +1,40 @@ | |||
/* | |||
* Copyright (c) 2016 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Christian Gmeiner <christian.gmeiner@gmail.com> | |||
*/ | |||
#ifndef H_ETNAVIV_DISASM | |||
#define H_ETNAVIV_DISASM | |||
#include <stdint.h> | |||
/* bitmask of print flags */ | |||
enum debug_t { | |||
PRINT_RAW = 0x1, /* dump raw hexdump */ | |||
}; | |||
void | |||
etna_disasm(uint32_t *dwords, int sizedwords, enum debug_t debug); | |||
#endif |
@@ -0,0 +1,770 @@ | |||
/* | |||
* Copyright (c) 2014-2015 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Wladimir J. van der Laan <laanwj@gmail.com> | |||
*/ | |||
#include "etnaviv_emit.h" | |||
#include "etnaviv_blend.h" | |||
#include "etnaviv_compiler.h" | |||
#include "etnaviv_context.h" | |||
#include "etnaviv_rasterizer.h" | |||
#include "etnaviv_resource.h" | |||
#include "etnaviv_rs.h" | |||
#include "etnaviv_screen.h" | |||
#include "etnaviv_shader.h" | |||
#include "etnaviv_texture.h" | |||
#include "etnaviv_translate.h" | |||
#include "etnaviv_uniforms.h" | |||
#include "etnaviv_util.h" | |||
#include "etnaviv_zsa.h" | |||
#include "hw/common.xml.h" | |||
#include "hw/state.xml.h" | |||
#include "util/u_math.h" | |||
struct etna_coalesce { | |||
uint32_t start; | |||
uint32_t last_reg; | |||
uint32_t last_fixp; | |||
}; | |||
/* Queue a STALL command (queues 2 words) */ | |||
static inline void | |||
CMD_STALL(struct etna_cmd_stream *stream, uint32_t from, uint32_t to) | |||
{ | |||
etna_cmd_stream_emit(stream, VIV_FE_STALL_HEADER_OP_STALL); | |||
etna_cmd_stream_emit(stream, VIV_FE_STALL_TOKEN_FROM(from) | VIV_FE_STALL_TOKEN_TO(to)); | |||
} | |||
void | |||
etna_stall(struct etna_cmd_stream *stream, uint32_t from, uint32_t to) | |||
{ | |||
etna_cmd_stream_reserve(stream, 4); | |||
etna_emit_load_state(stream, VIVS_GL_SEMAPHORE_TOKEN >> 2, 1, 0); | |||
etna_cmd_stream_emit(stream, VIVS_GL_SEMAPHORE_TOKEN_FROM(from) | VIVS_GL_SEMAPHORE_TOKEN_TO(to)); | |||
if (from == SYNC_RECIPIENT_FE) { | |||
/* if the frontend is to be stalled, queue a STALL frontend command */ | |||
CMD_STALL(stream, from, to); | |||
} else { | |||
/* otherwise, load the STALL token state */ | |||
etna_emit_load_state(stream, VIVS_GL_STALL_TOKEN >> 2, 1, 0); | |||
etna_cmd_stream_emit(stream, VIVS_GL_STALL_TOKEN_FROM(from) | VIVS_GL_STALL_TOKEN_TO(to)); | |||
} | |||
} | |||
static void | |||
etna_coalesce_start(struct etna_cmd_stream *stream, | |||
struct etna_coalesce *coalesce) | |||
{ | |||
coalesce->start = etna_cmd_stream_offset(stream); | |||
coalesce->last_reg = 0; | |||
coalesce->last_fixp = 0; | |||
} | |||
static void | |||
etna_coalesce_end(struct etna_cmd_stream *stream, | |||
struct etna_coalesce *coalesce) | |||
{ | |||
uint32_t end = etna_cmd_stream_offset(stream); | |||
uint32_t size = end - coalesce->start; | |||
if (size) { | |||
uint32_t offset = coalesce->start - 1; | |||
uint32_t value = etna_cmd_stream_get(stream, offset); | |||
value |= VIV_FE_LOAD_STATE_HEADER_COUNT(size); | |||
etna_cmd_stream_set(stream, offset, value); | |||
} | |||
/* append needed padding */ | |||
if (end % 2 == 1) | |||
etna_cmd_stream_emit(stream, 0xdeadbeef); | |||
} | |||
static void | |||
check_coalsence(struct etna_cmd_stream *stream, struct etna_coalesce *coalesce, | |||
uint32_t reg, uint32_t fixp) | |||
{ | |||
if (coalesce->last_reg != 0) { | |||
if (((coalesce->last_reg + 4) != reg) || (coalesce->last_fixp != fixp)) { | |||
etna_coalesce_end(stream, coalesce); | |||
etna_emit_load_state(stream, reg >> 2, 0, fixp); | |||
coalesce->start = etna_cmd_stream_offset(stream); | |||
} | |||
} else { | |||
etna_emit_load_state(stream, reg >> 2, 0, fixp); | |||
coalesce->start = etna_cmd_stream_offset(stream); | |||
} | |||
coalesce->last_reg = reg; | |||
coalesce->last_fixp = fixp; | |||
} | |||
static inline void | |||
etna_coalsence_emit(struct etna_cmd_stream *stream, | |||
struct etna_coalesce *coalesce, uint32_t reg, | |||
uint32_t value) | |||
{ | |||
check_coalsence(stream, coalesce, reg, 0); | |||
etna_cmd_stream_emit(stream, value); | |||
} | |||
static inline void | |||
etna_coalsence_emit_fixp(struct etna_cmd_stream *stream, | |||
struct etna_coalesce *coalesce, uint32_t reg, | |||
uint32_t value) | |||
{ | |||
check_coalsence(stream, coalesce, reg, 1); | |||
etna_cmd_stream_emit(stream, value); | |||
} | |||
static inline void | |||
etna_coalsence_emit_reloc(struct etna_cmd_stream *stream, | |||
struct etna_coalesce *coalesce, uint32_t reg, | |||
const struct etna_reloc *r) | |||
{ | |||
if (r->bo) { | |||
check_coalsence(stream, coalesce, reg, 0); | |||
etna_cmd_stream_reloc(stream, r); | |||
} | |||
} | |||
#define EMIT_STATE(state_name, src_value) \ | |||
etna_coalsence_emit(stream, &coalesce, VIVS_##state_name, src_value) | |||
#define EMIT_STATE_FIXP(state_name, src_value) \ | |||
etna_coalsence_emit_fixp(stream, &coalesce, VIVS_##state_name, src_value) | |||
#define EMIT_STATE_RELOC(state_name, src_value) \ | |||
etna_coalsence_emit_reloc(stream, &coalesce, VIVS_##state_name, src_value) | |||
/* submit RS state, without any processing and no dependence on context | |||
* except TS if this is a source-to-destination blit. */ | |||
void | |||
etna_submit_rs_state(struct etna_context *ctx, | |||
const struct compiled_rs_state *cs) | |||
{ | |||
struct etna_screen *screen = etna_screen(ctx->base.screen); | |||
struct etna_cmd_stream *stream = ctx->stream; | |||
struct etna_coalesce coalesce; | |||
if (screen->specs.pixel_pipes == 1) { | |||
etna_cmd_stream_reserve(stream, 22); | |||
etna_coalesce_start(stream, &coalesce); | |||
/* 0/1 */ EMIT_STATE(RS_CONFIG, cs->RS_CONFIG); | |||
/* 2 */ EMIT_STATE_RELOC(RS_SOURCE_ADDR, &cs->source[0]); | |||
/* 3 */ EMIT_STATE(RS_SOURCE_STRIDE, cs->RS_SOURCE_STRIDE); | |||
/* 4 */ EMIT_STATE_RELOC(RS_DEST_ADDR, &cs->dest[0]); | |||
/* 5 */ EMIT_STATE(RS_DEST_STRIDE, cs->RS_DEST_STRIDE); | |||
/* 6/7 */ EMIT_STATE(RS_WINDOW_SIZE, cs->RS_WINDOW_SIZE); | |||
/* 8/9 */ EMIT_STATE(RS_DITHER(0), cs->RS_DITHER[0]); | |||
/*10 */ EMIT_STATE(RS_DITHER(1), cs->RS_DITHER[1]); | |||
/*11 - pad */ | |||
/*12/13*/ EMIT_STATE(RS_CLEAR_CONTROL, cs->RS_CLEAR_CONTROL); | |||
/*14 */ EMIT_STATE(RS_FILL_VALUE(0), cs->RS_FILL_VALUE[0]); | |||
/*15 */ EMIT_STATE(RS_FILL_VALUE(1), cs->RS_FILL_VALUE[1]); | |||
/*16 */ EMIT_STATE(RS_FILL_VALUE(2), cs->RS_FILL_VALUE[2]); | |||
/*17 */ EMIT_STATE(RS_FILL_VALUE(3), cs->RS_FILL_VALUE[3]); | |||
/*18/19*/ EMIT_STATE(RS_EXTRA_CONFIG, cs->RS_EXTRA_CONFIG); | |||
/*20/21*/ EMIT_STATE(RS_KICKER, 0xbeebbeeb); | |||
etna_coalesce_end(stream, &coalesce); | |||
} else if (screen->specs.pixel_pipes == 2) { | |||
etna_cmd_stream_reserve(stream, 34); /* worst case - both pipes multi=1 */ | |||
etna_coalesce_start(stream, &coalesce); | |||
/* 0/1 */ EMIT_STATE(RS_CONFIG, cs->RS_CONFIG); | |||
/* 2/3 */ EMIT_STATE(RS_SOURCE_STRIDE, cs->RS_SOURCE_STRIDE); | |||
/* 4/5 */ EMIT_STATE(RS_DEST_STRIDE, cs->RS_DEST_STRIDE); | |||
/* 6/7 */ EMIT_STATE_RELOC(RS_PIPE_SOURCE_ADDR(0), &cs->source[0]); | |||
if (cs->RS_SOURCE_STRIDE & VIVS_RS_SOURCE_STRIDE_MULTI) { | |||
/*8 */ EMIT_STATE_RELOC(RS_PIPE_SOURCE_ADDR(1), &cs->source[1]); | |||
/*9 - pad */ | |||
} | |||
/*10/11*/ EMIT_STATE_RELOC(RS_PIPE_DEST_ADDR(0), &cs->dest[0]); | |||
if (cs->RS_DEST_STRIDE & VIVS_RS_DEST_STRIDE_MULTI) { | |||
/*12*/ EMIT_STATE_RELOC(RS_PIPE_DEST_ADDR(1), &cs->dest[1]); | |||
/*13 - pad */ | |||
} | |||
/*14/15*/ EMIT_STATE(RS_PIPE_OFFSET(0), cs->RS_PIPE_OFFSET[0]); | |||
/*16 */ EMIT_STATE(RS_PIPE_OFFSET(1), cs->RS_PIPE_OFFSET[1]); | |||
/*17 - pad */ | |||
/*18/19*/ EMIT_STATE(RS_WINDOW_SIZE, cs->RS_WINDOW_SIZE); | |||
/*20/21*/ EMIT_STATE(RS_DITHER(0), cs->RS_DITHER[0]); | |||
/*22 */ EMIT_STATE(RS_DITHER(1), cs->RS_DITHER[1]); | |||
/*23 - pad */ | |||
/*24/25*/ EMIT_STATE(RS_CLEAR_CONTROL, cs->RS_CLEAR_CONTROL); | |||
/*26 */ EMIT_STATE(RS_FILL_VALUE(0), cs->RS_FILL_VALUE[0]); | |||
/*27 */ EMIT_STATE(RS_FILL_VALUE(1), cs->RS_FILL_VALUE[1]); | |||
/*28 */ EMIT_STATE(RS_FILL_VALUE(2), cs->RS_FILL_VALUE[2]); | |||
/*29 */ EMIT_STATE(RS_FILL_VALUE(3), cs->RS_FILL_VALUE[3]); | |||
/*30/31*/ EMIT_STATE(RS_EXTRA_CONFIG, cs->RS_EXTRA_CONFIG); | |||
/*32/33*/ EMIT_STATE(RS_KICKER, 0xbeebbeeb); | |||
etna_coalesce_end(stream, &coalesce); | |||
} else { | |||
abort(); | |||
} | |||
} | |||
/* Create bit field that specifies which samplers are active and thus need to be | |||
* programmed | |||
* 32 bits is enough for 32 samplers. As far as I know this is the upper bound | |||
* supported on any Vivante hw | |||
* up to GC4000. | |||
*/ | |||
static uint32_t | |||
active_samplers_bits(struct etna_context *ctx) | |||
{ | |||
return ctx->active_sampler_views & ctx->active_samplers; | |||
} | |||
#define ETNA_3D_CONTEXT_SIZE (400) /* keep this number above "Total state updates (fixed)" from gen_weave_state tool */ | |||
static unsigned | |||
required_stream_size(struct etna_context *ctx) | |||
{ | |||
unsigned size = ETNA_3D_CONTEXT_SIZE; | |||
/* stall + flush */ | |||
size += 2 + 4; | |||
/* vertex elements */ | |||
size += ctx->vertex_elements->num_elements + 1; | |||
/* uniforms - worst case (2 words per uniform load) */ | |||
size += ctx->vs->uniforms.const_count * 2; | |||
size += ctx->fs->uniforms.const_count * 2; | |||
/* shader */ | |||
size += ctx->shader_state.vs_inst_mem_size + 1; | |||
size += ctx->shader_state.ps_inst_mem_size + 1; | |||
/* DRAW_INDEXED_PRIMITIVES command */ | |||
size += 6; | |||
/* reserve for alignment etc. */ | |||
size += 64; | |||
return size; | |||
} | |||
/* Weave state before draw operation. This function merges all the compiled | |||
* state blocks under the context into one device register state. Parts of | |||
* this state that are changed since last call (dirty) will be uploaded as | |||
* state changes in the command buffer. */ | |||
void | |||
etna_emit_state(struct etna_context *ctx) | |||
{ | |||
struct etna_cmd_stream *stream = ctx->stream; | |||
uint32_t active_samplers = active_samplers_bits(ctx); | |||
/* Pre-reserve the command buffer space which we are likely to need. | |||
* This must cover all the state emitted below, and the following | |||
* draw command. */ | |||
etna_cmd_stream_reserve(stream, required_stream_size(ctx)); | |||
uint32_t dirty = ctx->dirty; | |||
/* Pre-processing: see what caches we need to flush before making state changes. */ | |||
uint32_t to_flush = 0; | |||
if (unlikely(dirty & (ETNA_DIRTY_BLEND))) { | |||
/* Need flush COLOR when changing PE.COLOR_FORMAT.OVERWRITE. */ | |||
#if 0 | |||
/* TODO*/ | |||
if ((ctx->gpu3d.PE_COLOR_FORMAT & VIVS_PE_COLOR_FORMAT_OVERWRITE) != | |||
(etna_blend_state(ctx->blend)->PE_COLOR_FORMAT & VIVS_PE_COLOR_FORMAT_OVERWRITE)) | |||
#endif | |||
to_flush |= VIVS_GL_FLUSH_CACHE_COLOR; | |||
} | |||
if (unlikely(dirty & (ETNA_DIRTY_TEXTURE_CACHES))) | |||
to_flush |= VIVS_GL_FLUSH_CACHE_TEXTURE; | |||
if (unlikely(dirty & (ETNA_DIRTY_FRAMEBUFFER))) /* Framebuffer config changed? */ | |||
to_flush |= VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH; | |||
if (DBG_ENABLED(ETNA_DBG_CFLUSH_ALL)) | |||
to_flush |= VIVS_GL_FLUSH_CACHE_TEXTURE | VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH; | |||
if (to_flush) { | |||
etna_set_state(stream, VIVS_GL_FLUSH_CACHE, to_flush); | |||
etna_stall(stream, SYNC_RECIPIENT_RA, SYNC_RECIPIENT_PE); | |||
} | |||
/* If MULTI_SAMPLE_CONFIG.MSAA_SAMPLES changed, clobber affected shader | |||
* state to make sure it is always rewritten. */ | |||
if (unlikely(dirty & (ETNA_DIRTY_FRAMEBUFFER))) { | |||
if ((ctx->gpu3d.GL_MULTI_SAMPLE_CONFIG & VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES__MASK) != | |||
(ctx->framebuffer.GL_MULTI_SAMPLE_CONFIG & VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES__MASK)) { | |||
/* XXX what does the GPU set these states to on MSAA samples change? | |||
* Does it do the right thing? | |||
* (increase/decrease as necessary) or something else? Just set some | |||
* invalid value until we know for | |||
* sure. */ | |||
ctx->gpu3d.PS_INPUT_COUNT = 0xffffffff; | |||
ctx->gpu3d.PS_TEMP_REGISTER_CONTROL = 0xffffffff; | |||
} | |||
} | |||
/* Update vertex elements. This is different from any of the other states, in that | |||
* a) the number of vertex elements written matters: so write only active ones | |||
* b) the vertex element states must all be written: do not skip entries that stay the same */ | |||
if (dirty & (ETNA_DIRTY_VERTEX_ELEMENTS)) { | |||
/* Special case: vertex elements must always be sent in full if changed */ | |||
/*00600*/ etna_set_state_multi(stream, VIVS_FE_VERTEX_ELEMENT_CONFIG(0), | |||
ctx->vertex_elements->num_elements, | |||
ctx->vertex_elements->FE_VERTEX_ELEMENT_CONFIG); | |||
} | |||
/* The following code is originally generated by gen_merge_state.py, to | |||
* emit state in increasing order of address (this makes it possible to merge | |||
* consecutive register updates into one SET_STATE command) | |||
* | |||
* There have been some manual changes, where the weaving operation is not | |||
* simply bitwise or: | |||
* - scissor fixp | |||
* - num vertex elements | |||
* - scissor handling | |||
* - num samplers | |||
* - texture lod | |||
* - ETNA_DIRTY_TS | |||
* - removed ETNA_DIRTY_BASE_SETUP statements -- these are guaranteed to not | |||
* change anyway | |||
* - PS / framebuffer interaction for MSAA | |||
* - move update of GL_MULTI_SAMPLE_CONFIG first | |||
* - add unlikely()/likely() | |||
*/ | |||
struct etna_coalesce coalesce; | |||
etna_coalesce_start(stream, &coalesce); | |||
/* begin only EMIT_STATE -- make sure no new etna_reserve calls are done here | |||
* directly | |||
* or indirectly */ | |||
/* multi sample config is set first, and outside of the normal sorting | |||
* order, as changing the multisample state clobbers PS.INPUT_COUNT (and | |||
* possibly PS.TEMP_REGISTER_CONTROL). | |||
*/ | |||
if (unlikely(dirty & (ETNA_DIRTY_FRAMEBUFFER | ETNA_DIRTY_SAMPLE_MASK))) { | |||
uint32_t val = VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_ENABLES(ctx->sample_mask); | |||
val |= ctx->framebuffer.GL_MULTI_SAMPLE_CONFIG; | |||
/*03818*/ EMIT_STATE(GL_MULTI_SAMPLE_CONFIG, val); | |||
} | |||
if (likely(dirty & (ETNA_DIRTY_INDEX_BUFFER)) && | |||
ctx->index_buffer.ib.buffer) { | |||
/*00644*/ EMIT_STATE_RELOC(FE_INDEX_STREAM_BASE_ADDR, &ctx->index_buffer.FE_INDEX_STREAM_BASE_ADDR); | |||
/*00648*/ EMIT_STATE(FE_INDEX_STREAM_CONTROL, ctx->index_buffer.FE_INDEX_STREAM_CONTROL); | |||
} | |||
if (likely(dirty & (ETNA_DIRTY_VERTEX_BUFFERS))) { | |||
/*0064C*/ EMIT_STATE_RELOC(FE_VERTEX_STREAM_BASE_ADDR, &ctx->vertex_buffer.cvb[0].FE_VERTEX_STREAM_BASE_ADDR); | |||
/*00650*/ EMIT_STATE(FE_VERTEX_STREAM_CONTROL, ctx->vertex_buffer.cvb[0].FE_VERTEX_STREAM_CONTROL); | |||
} | |||
if (likely(dirty & (ETNA_DIRTY_INDEX_BUFFER))) { | |||
/*00674*/ EMIT_STATE(FE_PRIMITIVE_RESTART_INDEX, ctx->index_buffer.FE_PRIMITIVE_RESTART_INDEX); | |||
} | |||
if (likely(dirty & (ETNA_DIRTY_VERTEX_BUFFERS))) { | |||
for (int x = 1; x < ctx->vertex_buffer.count; ++x) { | |||
/*00680*/ EMIT_STATE_RELOC(FE_VERTEX_STREAMS_BASE_ADDR(x), &ctx->vertex_buffer.cvb[x].FE_VERTEX_STREAM_BASE_ADDR); | |||
} | |||
for (int x = 1; x < ctx->vertex_buffer.count; ++x) { | |||
if (ctx->vertex_buffer.cvb[x].FE_VERTEX_STREAM_BASE_ADDR.bo) { | |||
/*006A0*/ EMIT_STATE(FE_VERTEX_STREAMS_CONTROL(x), ctx->vertex_buffer.cvb[x].FE_VERTEX_STREAM_CONTROL); | |||
} | |||
} | |||
} | |||
if (unlikely(dirty & (ETNA_DIRTY_SHADER))) { | |||
/*00800*/ EMIT_STATE(VS_END_PC, ctx->shader_state.VS_END_PC); | |||
} | |||
if (unlikely(dirty & (ETNA_DIRTY_SHADER | ETNA_DIRTY_RASTERIZER))) { | |||
bool point_size_per_vertex = | |||
etna_rasterizer_state(ctx->rasterizer)->point_size_per_vertex; | |||
/*00804*/ EMIT_STATE(VS_OUTPUT_COUNT, | |||
point_size_per_vertex | |||
? ctx->shader_state.VS_OUTPUT_COUNT_PSIZE | |||
: ctx->shader_state.VS_OUTPUT_COUNT); | |||
} | |||
if (unlikely(dirty & (ETNA_DIRTY_VERTEX_ELEMENTS | ETNA_DIRTY_SHADER))) { | |||
/*00808*/ EMIT_STATE(VS_INPUT_COUNT, ctx->shader_state.VS_INPUT_COUNT); | |||
/*0080C*/ EMIT_STATE(VS_TEMP_REGISTER_CONTROL, ctx->shader_state.VS_TEMP_REGISTER_CONTROL); | |||
} | |||
if (unlikely(dirty & (ETNA_DIRTY_SHADER))) { | |||
for (int x = 0; x < 4; ++x) { | |||
/*00810*/ EMIT_STATE(VS_OUTPUT(x), ctx->shader_state.VS_OUTPUT[x]); | |||
} | |||
} | |||
if (unlikely(dirty & (ETNA_DIRTY_VERTEX_ELEMENTS | ETNA_DIRTY_SHADER))) { | |||
for (int x = 0; x < 4; ++x) { | |||
/*00820*/ EMIT_STATE(VS_INPUT(x), ctx->shader_state.VS_INPUT[x]); | |||
} | |||
} | |||
if (unlikely(dirty & (ETNA_DIRTY_SHADER))) { | |||
/*00830*/ EMIT_STATE(VS_LOAD_BALANCING, ctx->shader_state.VS_LOAD_BALANCING); | |||
/*00838*/ EMIT_STATE(VS_START_PC, ctx->shader_state.VS_START_PC); | |||
if (ctx->specs.has_shader_range_registers) { | |||
/*0085C*/ EMIT_STATE(VS_RANGE, (ctx->shader_state.vs_inst_mem_size / 4 - 1) << 16); | |||
} | |||
} | |||
if (unlikely(dirty & (ETNA_DIRTY_VIEWPORT))) { | |||
/*00A00*/ EMIT_STATE_FIXP(PA_VIEWPORT_SCALE_X, ctx->viewport.PA_VIEWPORT_SCALE_X); | |||
/*00A04*/ EMIT_STATE_FIXP(PA_VIEWPORT_SCALE_Y, ctx->viewport.PA_VIEWPORT_SCALE_Y); | |||
/*00A08*/ EMIT_STATE(PA_VIEWPORT_SCALE_Z, ctx->viewport.PA_VIEWPORT_SCALE_Z); | |||
/*00A0C*/ EMIT_STATE_FIXP(PA_VIEWPORT_OFFSET_X, ctx->viewport.PA_VIEWPORT_OFFSET_X); | |||
/*00A10*/ EMIT_STATE_FIXP(PA_VIEWPORT_OFFSET_Y, ctx->viewport.PA_VIEWPORT_OFFSET_Y); | |||
/*00A14*/ EMIT_STATE(PA_VIEWPORT_OFFSET_Z, ctx->viewport.PA_VIEWPORT_OFFSET_Z); | |||
} | |||
if (unlikely(dirty & (ETNA_DIRTY_RASTERIZER))) { | |||
struct etna_rasterizer_state *rasterizer = etna_rasterizer_state(ctx->rasterizer); | |||
/*00A18*/ EMIT_STATE(PA_LINE_WIDTH, rasterizer->PA_LINE_WIDTH); | |||
/*00A1C*/ EMIT_STATE(PA_POINT_SIZE, rasterizer->PA_POINT_SIZE); | |||
/*00A28*/ EMIT_STATE(PA_SYSTEM_MODE, rasterizer->PA_SYSTEM_MODE); | |||
} | |||
if (unlikely(dirty & (ETNA_DIRTY_SHADER))) { | |||
/*00A30*/ EMIT_STATE(PA_ATTRIBUTE_ELEMENT_COUNT, ctx->shader_state.PA_ATTRIBUTE_ELEMENT_COUNT); | |||
} | |||
if (unlikely(dirty & (ETNA_DIRTY_RASTERIZER | ETNA_DIRTY_SHADER))) { | |||
uint32_t val = etna_rasterizer_state(ctx->rasterizer)->PA_CONFIG; | |||
/*00A34*/ EMIT_STATE(PA_CONFIG, val & ctx->shader_state.PA_CONFIG); | |||
} | |||
if (unlikely(dirty & (ETNA_DIRTY_RASTERIZER))) { | |||
struct etna_rasterizer_state *rasterizer = etna_rasterizer_state(ctx->rasterizer); | |||
/*00A38*/ EMIT_STATE(PA_WIDE_LINE_WIDTH0, rasterizer->PA_LINE_WIDTH); | |||
/*00A3C*/ EMIT_STATE(PA_WIDE_LINE_WIDTH1, rasterizer->PA_LINE_WIDTH); | |||
} | |||
if (unlikely(dirty & (ETNA_DIRTY_SHADER))) { | |||
for (int x = 0; x < 10; ++x) { | |||
/*00A40*/ EMIT_STATE(PA_SHADER_ATTRIBUTES(x), ctx->shader_state.PA_SHADER_ATTRIBUTES[x]); | |||
} | |||
} | |||
if (unlikely(dirty & (ETNA_DIRTY_SCISSOR | ETNA_DIRTY_FRAMEBUFFER | | |||
ETNA_DIRTY_RASTERIZER | ETNA_DIRTY_VIEWPORT))) { | |||
/* this is a bit of a mess: rasterizer.scissor determines whether to use | |||
* only the framebuffer scissor, or specific scissor state, and the | |||
* viewport clips too so the logic spans four CSOs */ | |||
struct etna_rasterizer_state *rasterizer = etna_rasterizer_state(ctx->rasterizer); | |||
uint32_t scissor_left = | |||
MAX2(ctx->framebuffer.SE_SCISSOR_LEFT, ctx->viewport.SE_SCISSOR_LEFT); | |||
uint32_t scissor_top = | |||
MAX2(ctx->framebuffer.SE_SCISSOR_TOP, ctx->viewport.SE_SCISSOR_TOP); | |||
uint32_t scissor_right = | |||
MIN2(ctx->framebuffer.SE_SCISSOR_RIGHT, ctx->viewport.SE_SCISSOR_RIGHT); | |||
uint32_t scissor_bottom = | |||
MIN2(ctx->framebuffer.SE_SCISSOR_BOTTOM, ctx->viewport.SE_SCISSOR_BOTTOM); | |||
if (rasterizer->scissor) { | |||
scissor_left = MAX2(ctx->scissor.SE_SCISSOR_LEFT, scissor_left); | |||
scissor_top = MAX2(ctx->scissor.SE_SCISSOR_TOP, scissor_top); | |||
scissor_right = MIN2(ctx->scissor.SE_SCISSOR_RIGHT, scissor_right); | |||
scissor_bottom = MIN2(ctx->scissor.SE_SCISSOR_BOTTOM, scissor_bottom); | |||
} | |||
/*00C00*/ EMIT_STATE_FIXP(SE_SCISSOR_LEFT, scissor_left); | |||
/*00C04*/ EMIT_STATE_FIXP(SE_SCISSOR_TOP, scissor_top); | |||
/*00C08*/ EMIT_STATE_FIXP(SE_SCISSOR_RIGHT, scissor_right); | |||
/*00C0C*/ EMIT_STATE_FIXP(SE_SCISSOR_BOTTOM, scissor_bottom); | |||
} | |||
if (unlikely(dirty & (ETNA_DIRTY_RASTERIZER))) { | |||
struct etna_rasterizer_state *rasterizer = etna_rasterizer_state(ctx->rasterizer); | |||
/*00C10*/ EMIT_STATE(SE_DEPTH_SCALE, rasterizer->SE_DEPTH_SCALE); | |||
/*00C14*/ EMIT_STATE(SE_DEPTH_BIAS, rasterizer->SE_DEPTH_BIAS); | |||
/*00C18*/ EMIT_STATE(SE_CONFIG, rasterizer->SE_CONFIG); | |||
} | |||
if (unlikely(dirty & (ETNA_DIRTY_SHADER))) { | |||
/*00E00*/ EMIT_STATE(RA_CONTROL, ctx->shader_state.RA_CONTROL); | |||
} | |||
if (unlikely(dirty & (ETNA_DIRTY_FRAMEBUFFER))) { | |||
/*00E04*/ EMIT_STATE(RA_MULTISAMPLE_UNK00E04, ctx->framebuffer.RA_MULTISAMPLE_UNK00E04); | |||
for (int x = 0; x < 4; ++x) { | |||
/*00E10*/ EMIT_STATE(RA_MULTISAMPLE_UNK00E10(x), ctx->framebuffer.RA_MULTISAMPLE_UNK00E10[x]); | |||
} | |||
for (int x = 0; x < 16; ++x) { | |||
/*00E40*/ EMIT_STATE(RA_CENTROID_TABLE(x), ctx->framebuffer.RA_CENTROID_TABLE[x]); | |||
} | |||
} | |||
if (unlikely(dirty & (ETNA_DIRTY_SHADER | ETNA_DIRTY_FRAMEBUFFER))) { | |||
/*01000*/ EMIT_STATE(PS_END_PC, ctx->shader_state.PS_END_PC); | |||
/*01004*/ EMIT_STATE(PS_OUTPUT_REG, ctx->shader_state.PS_OUTPUT_REG); | |||
/*01008*/ EMIT_STATE(PS_INPUT_COUNT, | |||
ctx->framebuffer.msaa_mode | |||
? ctx->shader_state.PS_INPUT_COUNT_MSAA | |||
: ctx->shader_state.PS_INPUT_COUNT); | |||
/*0100C*/ EMIT_STATE(PS_TEMP_REGISTER_CONTROL, | |||
ctx->framebuffer.msaa_mode | |||
? ctx->shader_state.PS_TEMP_REGISTER_CONTROL_MSAA | |||
: ctx->shader_state.PS_TEMP_REGISTER_CONTROL); | |||
/*01010*/ EMIT_STATE(PS_CONTROL, ctx->shader_state.PS_CONTROL); | |||
/*01018*/ EMIT_STATE(PS_START_PC, ctx->shader_state.PS_START_PC); | |||
if (ctx->specs.has_shader_range_registers) { | |||
/*0101C*/ EMIT_STATE(PS_RANGE, ((ctx->shader_state.ps_inst_mem_size / 4 - 1 + 0x100) << 16) | | |||
0x100); | |||
} | |||
} | |||
if (unlikely(dirty & (ETNA_DIRTY_ZSA | ETNA_DIRTY_FRAMEBUFFER))) { | |||
uint32_t val = etna_zsa_state(ctx->zsa)->PE_DEPTH_CONFIG; | |||
/*01400*/ EMIT_STATE(PE_DEPTH_CONFIG, val | ctx->framebuffer.PE_DEPTH_CONFIG); | |||
} | |||
if (unlikely(dirty & (ETNA_DIRTY_VIEWPORT))) { | |||
/*01404*/ EMIT_STATE(PE_DEPTH_NEAR, ctx->viewport.PE_DEPTH_NEAR); | |||
/*01408*/ EMIT_STATE(PE_DEPTH_FAR, ctx->viewport.PE_DEPTH_FAR); | |||
} | |||
if (unlikely(dirty & (ETNA_DIRTY_FRAMEBUFFER))) { | |||
/*0140C*/ EMIT_STATE(PE_DEPTH_NORMALIZE, ctx->framebuffer.PE_DEPTH_NORMALIZE); | |||
if (ctx->specs.pixel_pipes == 1) { | |||
/*01410*/ EMIT_STATE_RELOC(PE_DEPTH_ADDR, &ctx->framebuffer.PE_DEPTH_ADDR); | |||
} | |||
/*01414*/ EMIT_STATE(PE_DEPTH_STRIDE, ctx->framebuffer.PE_DEPTH_STRIDE); | |||
} | |||
if (unlikely(dirty & (ETNA_DIRTY_ZSA))) { | |||
uint32_t val = etna_zsa_state(ctx->zsa)->PE_STENCIL_OP; | |||
/*01418*/ EMIT_STATE(PE_STENCIL_OP, val); | |||
} | |||
if (unlikely(dirty & (ETNA_DIRTY_ZSA | ETNA_DIRTY_STENCIL_REF))) { | |||
uint32_t val = etna_zsa_state(ctx->zsa)->PE_STENCIL_CONFIG; | |||
/*0141C*/ EMIT_STATE(PE_STENCIL_CONFIG, val | ctx->stencil_ref.PE_STENCIL_CONFIG); | |||
} | |||
if (unlikely(dirty & (ETNA_DIRTY_ZSA))) { | |||
uint32_t val = etna_zsa_state(ctx->zsa)->PE_ALPHA_OP; | |||
/*01420*/ EMIT_STATE(PE_ALPHA_OP, val); | |||
} | |||
if (unlikely(dirty & (ETNA_DIRTY_BLEND_COLOR))) { | |||
/*01424*/ EMIT_STATE(PE_ALPHA_BLEND_COLOR, ctx->blend_color.PE_ALPHA_BLEND_COLOR); | |||
} | |||
if (unlikely(dirty & (ETNA_DIRTY_BLEND))) { | |||
uint32_t val = etna_blend_state(ctx->blend)->PE_ALPHA_CONFIG; | |||
/*01428*/ EMIT_STATE(PE_ALPHA_CONFIG, val); | |||
} | |||
if (unlikely(dirty & (ETNA_DIRTY_BLEND | ETNA_DIRTY_FRAMEBUFFER))) { | |||
uint32_t val; | |||
/* Use the components and overwrite bits in framebuffer.PE_COLOR_FORMAT | |||
* as a mask to enable the bits from blend PE_COLOR_FORMAT */ | |||
val = ~(VIVS_PE_COLOR_FORMAT_COMPONENTS__MASK | | |||
VIVS_PE_COLOR_FORMAT_OVERWRITE); | |||
val |= etna_blend_state(ctx->blend)->PE_COLOR_FORMAT; | |||
val &= ctx->framebuffer.PE_COLOR_FORMAT; | |||
/*0142C*/ EMIT_STATE(PE_COLOR_FORMAT, val); | |||
} | |||
if (unlikely(dirty & (ETNA_DIRTY_FRAMEBUFFER))) { | |||
if (ctx->specs.pixel_pipes == 1) { | |||
/*01430*/ EMIT_STATE_RELOC(PE_COLOR_ADDR, &ctx->framebuffer.PE_COLOR_ADDR); | |||
/*01434*/ EMIT_STATE(PE_COLOR_STRIDE, ctx->framebuffer.PE_COLOR_STRIDE); | |||
/*01454*/ EMIT_STATE(PE_HDEPTH_CONTROL, ctx->framebuffer.PE_HDEPTH_CONTROL); | |||
} else if (ctx->specs.pixel_pipes == 2) { | |||
/*01434*/ EMIT_STATE(PE_COLOR_STRIDE, ctx->framebuffer.PE_COLOR_STRIDE); | |||
/*01454*/ EMIT_STATE(PE_HDEPTH_CONTROL, ctx->framebuffer.PE_HDEPTH_CONTROL); | |||
/*01460*/ EMIT_STATE_RELOC(PE_PIPE_COLOR_ADDR(0), &ctx->framebuffer.PE_PIPE_COLOR_ADDR[0]); | |||
/*01464*/ EMIT_STATE_RELOC(PE_PIPE_COLOR_ADDR(1), &ctx->framebuffer.PE_PIPE_COLOR_ADDR[1]); | |||
/*01480*/ EMIT_STATE_RELOC(PE_PIPE_DEPTH_ADDR(0), &ctx->framebuffer.PE_PIPE_DEPTH_ADDR[0]); | |||
/*01484*/ EMIT_STATE_RELOC(PE_PIPE_DEPTH_ADDR(1), &ctx->framebuffer.PE_PIPE_DEPTH_ADDR[1]); | |||
} else { | |||
abort(); | |||
} | |||
} | |||
if (unlikely(dirty & (ETNA_DIRTY_STENCIL_REF))) { | |||
/*014A0*/ EMIT_STATE(PE_STENCIL_CONFIG_EXT, ctx->stencil_ref.PE_STENCIL_CONFIG_EXT); | |||
} | |||
if (unlikely(dirty & (ETNA_DIRTY_BLEND))) { | |||
struct etna_blend_state *blend = etna_blend_state(ctx->blend); | |||
/*014A4*/ EMIT_STATE(PE_LOGIC_OP, blend->PE_LOGIC_OP); | |||
for (int x = 0; x < 2; ++x) { | |||
/*014A8*/ EMIT_STATE(PE_DITHER(x), blend->PE_DITHER[x]); | |||
} | |||
} | |||
if (unlikely(dirty & (ETNA_DIRTY_FRAMEBUFFER | ETNA_DIRTY_TS))) { | |||
/*01654*/ EMIT_STATE(TS_MEM_CONFIG, ctx->framebuffer.TS_MEM_CONFIG); | |||
/*01658*/ EMIT_STATE_RELOC(TS_COLOR_STATUS_BASE, &ctx->framebuffer.TS_COLOR_STATUS_BASE); | |||
/*0165C*/ EMIT_STATE_RELOC(TS_COLOR_SURFACE_BASE, &ctx->framebuffer.TS_COLOR_SURFACE_BASE); | |||
/*01660*/ EMIT_STATE(TS_COLOR_CLEAR_VALUE, ctx->framebuffer.TS_COLOR_CLEAR_VALUE); | |||
/*01664*/ EMIT_STATE_RELOC(TS_DEPTH_STATUS_BASE, &ctx->framebuffer.TS_DEPTH_STATUS_BASE); | |||
/*01668*/ EMIT_STATE_RELOC(TS_DEPTH_SURFACE_BASE, &ctx->framebuffer.TS_DEPTH_SURFACE_BASE); | |||
/*0166C*/ EMIT_STATE(TS_DEPTH_CLEAR_VALUE, ctx->framebuffer.TS_DEPTH_CLEAR_VALUE); | |||
} | |||
if (unlikely(dirty & (ETNA_DIRTY_SAMPLER_VIEWS | ETNA_DIRTY_SAMPLERS))) { | |||
for (int x = 0; x < VIVS_TE_SAMPLER__LEN; ++x) { | |||
uint32_t val = 0; /* 0 == sampler inactive */ | |||
/* set active samplers to their configuration value (determined by both | |||
* the sampler state and sampler view) */ | |||
if ((1 << x) & active_samplers) { | |||
struct etna_sampler_state *ss = etna_sampler_state(ctx->sampler[x]); | |||
struct etna_sampler_view *sv = etna_sampler_view(ctx->sampler_view[x]); | |||
val = (ss->TE_SAMPLER_CONFIG0 & sv->TE_SAMPLER_CONFIG0_MASK) | | |||
sv->TE_SAMPLER_CONFIG0; | |||
} | |||
/*02000*/ EMIT_STATE(TE_SAMPLER_CONFIG0(x), val); | |||
} | |||
} | |||
if (unlikely(dirty & (ETNA_DIRTY_SAMPLER_VIEWS))) { | |||
struct etna_sampler_view *sv; | |||
for (int x = 0; x < VIVS_TE_SAMPLER__LEN; ++x) { | |||
if ((1 << x) & active_samplers) { | |||
sv = etna_sampler_view(ctx->sampler_view[x]); | |||
/*02040*/ EMIT_STATE(TE_SAMPLER_SIZE(x), sv->TE_SAMPLER_SIZE); | |||
} | |||
} | |||
for (int x = 0; x < VIVS_TE_SAMPLER__LEN; ++x) { | |||
if ((1 << x) & active_samplers) { | |||
sv = etna_sampler_view(ctx->sampler_view[x]); | |||
/*02080*/ EMIT_STATE(TE_SAMPLER_LOG_SIZE(x), sv->TE_SAMPLER_LOG_SIZE); | |||
} | |||
} | |||
} | |||
if (unlikely(dirty & (ETNA_DIRTY_SAMPLER_VIEWS | ETNA_DIRTY_SAMPLERS))) { | |||
struct etna_sampler_state *ss; | |||
struct etna_sampler_view *sv; | |||
for (int x = 0; x < VIVS_TE_SAMPLER__LEN; ++x) { | |||
if ((1 << x) & active_samplers) { | |||
ss = etna_sampler_state(ctx->sampler[x]); | |||
sv = etna_sampler_view(ctx->sampler_view[x]); | |||
/* min and max lod is determined both by the sampler and the view */ | |||
/*020C0*/ EMIT_STATE(TE_SAMPLER_LOD_CONFIG(x), | |||
ss->TE_SAMPLER_LOD_CONFIG | | |||
VIVS_TE_SAMPLER_LOD_CONFIG_MAX(MIN2(ss->max_lod, sv->max_lod)) | | |||
VIVS_TE_SAMPLER_LOD_CONFIG_MIN(MAX2(ss->min_lod, sv->min_lod))); | |||
} | |||
} | |||
for (int x = 0; x < VIVS_TE_SAMPLER__LEN; ++x) { | |||
if ((1 << x) & active_samplers) { | |||
ss = etna_sampler_state(ctx->sampler[x]); | |||
sv = etna_sampler_view(ctx->sampler_view[x]); | |||
/*021C0*/ EMIT_STATE(TE_SAMPLER_CONFIG1(x), ss->TE_SAMPLER_CONFIG1 | | |||
sv->TE_SAMPLER_CONFIG1); | |||
} | |||
} | |||
} | |||
if (unlikely(dirty & (ETNA_DIRTY_SAMPLER_VIEWS))) { | |||
for (int y = 0; y < VIVS_TE_SAMPLER_LOD_ADDR__LEN; ++y) { | |||
for (int x = 0; x < VIVS_TE_SAMPLER__LEN; ++x) { | |||
if ((1 << x) & active_samplers) { | |||
struct etna_sampler_view *sv = etna_sampler_view(ctx->sampler_view[x]); | |||
/*02400*/ EMIT_STATE_RELOC(TE_SAMPLER_LOD_ADDR(x, y),&sv->TE_SAMPLER_LOD_ADDR[y]); | |||
} | |||
} | |||
} | |||
} | |||
if (unlikely(dirty & (ETNA_DIRTY_SHADER))) { | |||
/*0381C*/ EMIT_STATE(GL_VARYING_TOTAL_COMPONENTS, ctx->shader_state.GL_VARYING_TOTAL_COMPONENTS); | |||
/*03820*/ EMIT_STATE(GL_VARYING_NUM_COMPONENTS, ctx->shader_state.GL_VARYING_NUM_COMPONENTS); | |||
for (int x = 0; x < 2; ++x) { | |||
/*03828*/ EMIT_STATE(GL_VARYING_COMPONENT_USE(x), ctx->shader_state.GL_VARYING_COMPONENT_USE[x]); | |||
} | |||
} | |||
etna_coalesce_end(stream, &coalesce); | |||
/* end only EMIT_STATE */ | |||
/* Insert a FE/PE stall as changing the shader instructions (and maybe | |||
* the uniforms) can corrupt the previous in-progress draw operation. | |||
* Observed with amoeba on GC2000 during the right-to-left rendering | |||
* of PI, and can cause GPU hangs immediately after. | |||
* I summise that this is because the "new" locations at 0xc000 are not | |||
* properly protected against updates as other states seem to be. Hence, | |||
* we detect the "new" vertex shader instruction offset to apply this. */ | |||
if (ctx->dirty & (ETNA_DIRTY_SHADER | ETNA_DIRTY_CONSTBUF) && ctx->specs.vs_offset > 0x4000) | |||
etna_stall(ctx->stream, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE); | |||
/* We need to update the uniform cache only if one of the following bits are | |||
* set in ctx->dirty: | |||
* - ETNA_DIRTY_SHADER | |||
* - ETNA_DIRTY_CONSTBUF | |||
* - uniforms_dirty_bits | |||
* | |||
* In case of ETNA_DIRTY_SHADER we need load all uniforms from the cache. In | |||
* all | |||
* other cases we can load on the changed uniforms. | |||
*/ | |||
static const uint32_t uniform_dirty_bits = | |||
ETNA_DIRTY_SHADER | ETNA_DIRTY_CONSTBUF; | |||
if (dirty & (uniform_dirty_bits | ctx->fs->uniforms_dirty_bits)) | |||
etna_uniforms_write( | |||
ctx, ctx->vs, &ctx->constant_buffer[PIPE_SHADER_VERTEX], | |||
ctx->shader_state.VS_UNIFORMS, &ctx->shader_state.vs_uniforms_size); | |||
if (dirty & (uniform_dirty_bits | ctx->vs->uniforms_dirty_bits)) | |||
etna_uniforms_write( | |||
ctx, ctx->fs, &ctx->constant_buffer[PIPE_SHADER_FRAGMENT], | |||
ctx->shader_state.PS_UNIFORMS, &ctx->shader_state.ps_uniforms_size); | |||
/**** Large dynamically-sized state ****/ | |||
if (dirty & (ETNA_DIRTY_SHADER)) { | |||
/* Special case: a new shader was loaded; simply re-load all uniforms and | |||
* shader code at once */ | |||
/*04000 or 0C000*/ | |||
etna_set_state_multi(stream, ctx->specs.vs_offset, | |||
ctx->shader_state.vs_inst_mem_size, | |||
ctx->shader_state.VS_INST_MEM); | |||
/*06000 or 0D000*/ | |||
etna_set_state_multi(stream, ctx->specs.ps_offset, | |||
ctx->shader_state.ps_inst_mem_size, | |||
ctx->shader_state.PS_INST_MEM); | |||
/*05000*/ etna_set_state_multi(stream, VIVS_VS_UNIFORMS(0), | |||
ctx->shader_state.vs_uniforms_size, | |||
ctx->shader_state.VS_UNIFORMS); | |||
/*07000*/ etna_set_state_multi(stream, VIVS_PS_UNIFORMS(0), | |||
ctx->shader_state.ps_uniforms_size, | |||
ctx->shader_state.PS_UNIFORMS); | |||
/* Copy uniforms to gpu3d, so that incremental updates to uniforms are | |||
* possible as long as the | |||
* same shader remains bound */ | |||
ctx->gpu3d.vs_uniforms_size = ctx->shader_state.vs_uniforms_size; | |||
ctx->gpu3d.ps_uniforms_size = ctx->shader_state.ps_uniforms_size; | |||
memcpy(ctx->gpu3d.VS_UNIFORMS, ctx->shader_state.VS_UNIFORMS, | |||
ctx->shader_state.vs_uniforms_size * 4); | |||
memcpy(ctx->gpu3d.PS_UNIFORMS, ctx->shader_state.PS_UNIFORMS, | |||
ctx->shader_state.ps_uniforms_size * 4); | |||
} else { | |||
etna_coalesce_start(stream, &coalesce); | |||
for (int x = 0; x < ctx->vs->uniforms.const_count; ++x) { | |||
if (ctx->gpu3d.VS_UNIFORMS[x] != ctx->shader_state.VS_UNIFORMS[x]) { | |||
/*05000*/ EMIT_STATE(VS_UNIFORMS(x), ctx->shader_state.VS_UNIFORMS[x]); | |||
ctx->gpu3d.VS_UNIFORMS[x] = ctx->shader_state.VS_UNIFORMS[x]; | |||
} | |||
} | |||
etna_coalesce_end(stream, &coalesce); | |||
etna_coalesce_start(stream, &coalesce); | |||
for (int x = 0; x < ctx->fs->uniforms.const_count; ++x) { | |||
if (ctx->gpu3d.PS_UNIFORMS[x] != ctx->shader_state.PS_UNIFORMS[x]) { | |||
/*07000*/ EMIT_STATE(PS_UNIFORMS(x), ctx->shader_state.PS_UNIFORMS[x]); | |||
ctx->gpu3d.PS_UNIFORMS[x] = ctx->shader_state.PS_UNIFORMS[x]; | |||
} | |||
} | |||
etna_coalesce_end(stream, &coalesce); | |||
} | |||
/**** End of state update ****/ | |||
#undef EMIT_STATE | |||
#undef EMIT_STATE_FIXP | |||
#undef EMIT_STATE_RELOC | |||
ctx->dirty = 0; | |||
} |
@@ -0,0 +1,123 @@ | |||
/* | |||
* Copyright (c) 2012-2015 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Wladimir J. van der Laan <laanwj@gmail.com> | |||
*/ | |||
#ifndef H_ETNA_EMIT | |||
#define H_ETNA_EMIT | |||
#include "etnaviv_screen.h" | |||
#include "etnaviv_util.h" | |||
#include "hw/cmdstream.xml.h" | |||
struct etna_context; | |||
struct compiled_rs_state; | |||
static inline void | |||
etna_emit_load_state(struct etna_cmd_stream *stream, const uint16_t offset, | |||
const uint16_t count, const int fixp) | |||
{ | |||
uint32_t v; | |||
v = VIV_FE_LOAD_STATE_HEADER_OP_LOAD_STATE | | |||
COND(fixp, VIV_FE_LOAD_STATE_HEADER_FIXP) | | |||
VIV_FE_LOAD_STATE_HEADER_OFFSET(offset) | | |||
(VIV_FE_LOAD_STATE_HEADER_COUNT(count) & | |||
VIV_FE_LOAD_STATE_HEADER_COUNT__MASK); | |||
etna_cmd_stream_emit(stream, v); | |||
} | |||
static inline void | |||
etna_set_state(struct etna_cmd_stream *stream, uint32_t address, uint32_t value) | |||
{ | |||
etna_cmd_stream_reserve(stream, 2); | |||
etna_emit_load_state(stream, address >> 2, 1, 0); | |||
etna_cmd_stream_emit(stream, value); | |||
} | |||
static inline void | |||
etna_set_state_reloc(struct etna_cmd_stream *stream, uint32_t address, | |||
struct etna_reloc *reloc) | |||
{ | |||
etna_cmd_stream_reserve(stream, 2); | |||
etna_emit_load_state(stream, address >> 2, 1, 0); | |||
etna_cmd_stream_reloc(stream, reloc); | |||
} | |||
static inline void | |||
etna_set_state_multi(struct etna_cmd_stream *stream, uint32_t base, | |||
uint32_t num, const uint32_t *values) | |||
{ | |||
if (num == 0) | |||
return; | |||
etna_cmd_stream_reserve(stream, 1 + num + 1); /* 1 extra for potential alignment */ | |||
etna_emit_load_state(stream, base >> 2, num, 0); | |||
for (uint32_t i = 0; i < num; i++) | |||
etna_cmd_stream_emit(stream, values[i]); | |||
/* add potential padding */ | |||
if ((num % 2) == 0) | |||
etna_cmd_stream_emit(stream, 0); | |||
} | |||
void | |||
etna_stall(struct etna_cmd_stream *stream, uint32_t from, uint32_t to); | |||
void | |||
etna_submit_rs_state(struct etna_context *ctx, const struct compiled_rs_state *cs); | |||
static inline void | |||
etna_draw_primitives(struct etna_cmd_stream *stream, uint32_t primitive_type, | |||
uint32_t start, uint32_t count) | |||
{ | |||
etna_cmd_stream_reserve(stream, 4); | |||
etna_cmd_stream_emit(stream, VIV_FE_DRAW_PRIMITIVES_HEADER_OP_DRAW_PRIMITIVES); | |||
etna_cmd_stream_emit(stream, primitive_type); | |||
etna_cmd_stream_emit(stream, start); | |||
etna_cmd_stream_emit(stream, count); | |||
} | |||
static inline void | |||
etna_draw_indexed_primitives(struct etna_cmd_stream *stream, | |||
uint32_t primitive_type, uint32_t start, | |||
uint32_t count, uint32_t offset) | |||
{ | |||
etna_cmd_stream_reserve(stream, 5 + 1); | |||
etna_cmd_stream_emit(stream, VIV_FE_DRAW_INDEXED_PRIMITIVES_HEADER_OP_DRAW_INDEXED_PRIMITIVES); | |||
etna_cmd_stream_emit(stream, primitive_type); | |||
etna_cmd_stream_emit(stream, start); | |||
etna_cmd_stream_emit(stream, count); | |||
etna_cmd_stream_emit(stream, offset); | |||
etna_cmd_stream_emit(stream, 0); | |||
} | |||
void | |||
etna_emit_state(struct etna_context *ctx); | |||
#endif |
@@ -0,0 +1,87 @@ | |||
/* | |||
* Copyright (c) 2012-2015 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Wladimir J. van der Laan <laanwj@gmail.com> | |||
* Rob Clark <robclark@freedesktop.org> | |||
*/ | |||
#include "etnaviv_fence.h" | |||
#include "etnaviv_context.h" | |||
#include "etnaviv_screen.h" | |||
#include "util/u_inlines.h" | |||
#include "util/u_memory.h" | |||
struct pipe_fence_handle { | |||
struct pipe_reference reference; | |||
struct etna_context *ctx; | |||
struct etna_screen *screen; | |||
uint32_t timestamp; | |||
}; | |||
static void | |||
etna_screen_fence_reference(struct pipe_screen *pscreen, | |||
struct pipe_fence_handle **ptr, | |||
struct pipe_fence_handle *fence) | |||
{ | |||
if (pipe_reference(&(*ptr)->reference, &fence->reference)) | |||
FREE(*ptr); | |||
*ptr = fence; | |||
} | |||
static boolean | |||
etna_screen_fence_finish(struct pipe_screen *pscreen, struct pipe_context *ctx, | |||
struct pipe_fence_handle *fence, uint64_t timeout) | |||
{ | |||
if (etna_pipe_wait_ns(fence->screen->pipe, fence->timestamp, timeout)) | |||
return false; | |||
return true; | |||
} | |||
struct pipe_fence_handle * | |||
etna_fence_create(struct pipe_context *pctx) | |||
{ | |||
struct pipe_fence_handle *fence; | |||
struct etna_context *ctx = etna_context(pctx); | |||
fence = CALLOC_STRUCT(pipe_fence_handle); | |||
if (!fence) | |||
return NULL; | |||
pipe_reference_init(&fence->reference, 1); | |||
fence->ctx = ctx; | |||
fence->screen = ctx->screen; | |||
fence->timestamp = etna_cmd_stream_timestamp(ctx->stream); | |||
return fence; | |||
} | |||
void | |||
etna_fence_screen_init(struct pipe_screen *pscreen) | |||
{ | |||
pscreen->fence_reference = etna_screen_fence_reference; | |||
pscreen->fence_finish = etna_screen_fence_finish; | |||
} |
@@ -0,0 +1,39 @@ | |||
/* | |||
* Copyright (c) 2012-2015 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Wladimir J. van der Laan <laanwj@gmail.com> | |||
* Rob Clark <robclark@freedesktop.org> | |||
*/ | |||
#ifndef ETNAVIV_FENCE_H_ | |||
#define ETNAVIV_FENCE_H_ | |||
#include "pipe/p_context.h" | |||
struct pipe_fence_handle * | |||
etna_fence_create(struct pipe_context *pctx); | |||
void | |||
etna_fence_screen_init(struct pipe_screen *pscreen); | |||
#endif |
@@ -0,0 +1,268 @@ | |||
/* | |||
* Copyright (c) 2016 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Christian Gmeiner <christian.gmeiner@gmail.com> | |||
*/ | |||
#include "etnaviv_format.h" | |||
#include "hw/state.xml.h" | |||
#include "hw/state_3d.xml.h" | |||
#include "pipe/p_defines.h" | |||
/* Specifies the table of all the formats and their features. Also supplies | |||
* the helpers that look up various data in those tables. | |||
*/ | |||
struct etna_format { | |||
unsigned vtx; | |||
unsigned tex; | |||
unsigned rs; | |||
boolean present; | |||
}; | |||
#define RS_FORMAT_NONE ~0 | |||
#define RS_FORMAT_MASK 0xf | |||
#define RS_FORMAT(x) ((x) & RS_FORMAT_MASK) | |||
#define RS_FORMAT_RB_SWAP 0x10 | |||
#define RS_FORMAT_X8B8G8R8 (RS_FORMAT_X8R8G8B8 | RS_FORMAT_RB_SWAP) | |||
#define RS_FORMAT_A8B8G8R8 (RS_FORMAT_A8R8G8B8 | RS_FORMAT_RB_SWAP) | |||
/* vertex + texture */ | |||
#define VT(pipe, vtxfmt, texfmt, rsfmt) \ | |||
[PIPE_FORMAT_##pipe] = { \ | |||
.vtx = VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_##vtxfmt, \ | |||
.tex = TEXTURE_FORMAT_##texfmt, \ | |||
.rs = RS_FORMAT_##rsfmt, \ | |||
.present = 1, \ | |||
} | |||
/* texture-only */ | |||
#define _T(pipe, fmt, rsfmt) \ | |||
[PIPE_FORMAT_##pipe] = { \ | |||
.vtx = ETNA_NO_MATCH, \ | |||
.tex = TEXTURE_FORMAT_##fmt, \ | |||
.rs = RS_FORMAT_##rsfmt, \ | |||
.present = 1, \ | |||
} | |||
/* vertex-only */ | |||
#define V_(pipe, fmt, rsfmt) \ | |||
[PIPE_FORMAT_##pipe] = { \ | |||
.vtx = VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_##fmt, \ | |||
.tex = ETNA_NO_MATCH, \ | |||
.rs = RS_FORMAT_##rsfmt, \ | |||
.present = 1, \ | |||
} | |||
static struct etna_format formats[PIPE_FORMAT_COUNT] = { | |||
/* 8-bit */ | |||
V_(R8_UNORM, UNSIGNED_BYTE, NONE), | |||
V_(R8_SNORM, BYTE, NONE), | |||
V_(R8_UINT, UNSIGNED_BYTE, NONE), | |||
V_(R8_SINT, BYTE, NONE), | |||
V_(R8_USCALED, UNSIGNED_BYTE, NONE), | |||
V_(R8_SSCALED, BYTE, NONE), | |||
_T(A8_UNORM, A8, NONE), | |||
_T(L8_UNORM, L8, NONE), | |||
_T(I8_UNORM, I8, NONE), | |||
/* 16-bit */ | |||
V_(R16_UNORM, UNSIGNED_SHORT, NONE), | |||
V_(R16_SNORM, SHORT, NONE), | |||
V_(R16_UINT, UNSIGNED_SHORT, NONE), | |||
V_(R16_SINT, SHORT, NONE), | |||
V_(R16_USCALED, UNSIGNED_SHORT, NONE), | |||
V_(R16_SSCALED, SHORT, NONE), | |||
V_(R16_FLOAT, HALF_FLOAT, NONE), | |||
_T(B4G4R4A4_UNORM, A4R4G4B4, A4R4G4B4), | |||
_T(B4G4R4X4_UNORM, X4R4G4B4, X4R4G4B4), | |||
_T(Z16_UNORM, D16, A4R4G4B4), | |||
_T(B5G6R5_UNORM, R5G6B5, R5G6B5), | |||
_T(B5G5R5A1_UNORM, A1R5G5B5, A1R5G5B5), | |||
_T(B5G5R5X1_UNORM, X1R5G5B5, X1R5G5B5), | |||
V_(R8G8_UNORM, UNSIGNED_BYTE, NONE), | |||
V_(R8G8_SNORM, BYTE, NONE), | |||
V_(R8G8_UINT, UNSIGNED_BYTE, NONE), | |||
V_(R8G8_SINT, BYTE, NONE), | |||
V_(R8G8_USCALED, UNSIGNED_BYTE, NONE), | |||
V_(R8G8_SSCALED, BYTE, NONE), | |||
/* 24-bit */ | |||
V_(R8G8B8_UNORM, UNSIGNED_BYTE, NONE), | |||
V_(R8G8B8_SNORM, BYTE, NONE), | |||
V_(R8G8B8_UINT, UNSIGNED_BYTE, NONE), | |||
V_(R8G8B8_SINT, BYTE, NONE), | |||
V_(R8G8B8_USCALED, UNSIGNED_BYTE, NONE), | |||
V_(R8G8B8_SSCALED, BYTE, NONE), | |||
/* 32-bit */ | |||
V_(R32_UNORM, UNSIGNED_INT, NONE), | |||
V_(R32_SNORM, INT, NONE), | |||
V_(R32_SINT, INT, NONE), | |||
V_(R32_UINT, UNSIGNED_INT, NONE), | |||
V_(R32_USCALED, UNSIGNED_INT, NONE), | |||
V_(R32_SSCALED, INT, NONE), | |||
V_(R32_FLOAT, FLOAT, NONE), | |||
V_(R32_FIXED, FIXED, NONE), | |||
V_(R16G16_UNORM, UNSIGNED_SHORT, NONE), | |||
V_(R16G16_SNORM, SHORT, NONE), | |||
V_(R16G16_UINT, UNSIGNED_SHORT, NONE), | |||
V_(R16G16_SINT, SHORT, NONE), | |||
V_(R16G16_USCALED, UNSIGNED_SHORT, NONE), | |||
V_(R16G16_SSCALED, SHORT, NONE), | |||
V_(R16G16_FLOAT, HALF_FLOAT, NONE), | |||
V_(A8B8G8R8_UNORM, UNSIGNED_BYTE, NONE), | |||
V_(R8G8B8A8_UNORM, UNSIGNED_BYTE, A8B8G8R8), | |||
V_(R8G8B8A8_SNORM, BYTE, A8B8G8R8), | |||
_T(R8G8B8X8_UNORM, X8B8G8R8, X8B8G8R8), | |||
V_(R8G8B8A8_UINT, UNSIGNED_BYTE, A8B8G8R8), | |||
V_(R8G8B8A8_SINT, BYTE, A8B8G8R8), | |||
V_(R8G8B8A8_USCALED, UNSIGNED_BYTE, A8B8G8R8), | |||
V_(R8G8B8A8_SSCALED, BYTE, A8B8G8R8), | |||
_T(R8G8B8A8_UNORM, A8B8G8R8, A8B8G8R8), | |||
_T(R8G8B8X8_UNORM, X8B8G8R8, X8B8G8R8), | |||
_T(B8G8R8A8_UNORM, A8R8G8B8, A8R8G8B8), | |||
_T(B8G8R8X8_UNORM, X8R8G8B8, X8R8G8B8), | |||
V_(R10G10B10A2_UNORM, UNSIGNED_INT_10_10_10_2, NONE), | |||
V_(R10G10B10A2_SNORM, INT_10_10_10_2, NONE), | |||
V_(R10G10B10A2_USCALED, UNSIGNED_INT_10_10_10_2, NONE), | |||
V_(R10G10B10A2_SSCALED, INT_10_10_10_2, NONE), | |||
_T(X8Z24_UNORM, D24S8, A8R8G8B8), | |||
_T(S8_UINT_Z24_UNORM, D24S8, A8R8G8B8), | |||
/* 48-bit */ | |||
V_(R16G16B16_UNORM, UNSIGNED_SHORT, NONE), | |||
V_(R16G16B16_SNORM, SHORT, NONE), | |||
V_(R16G16B16_UINT, UNSIGNED_SHORT, NONE), | |||
V_(R16G16B16_SINT, SHORT, NONE), | |||
V_(R16G16B16_USCALED, UNSIGNED_SHORT, NONE), | |||
V_(R16G16B16_SSCALED, SHORT, NONE), | |||
V_(R16G16B16_FLOAT, HALF_FLOAT, NONE), | |||
/* 64-bit */ | |||
V_(R16G16B16A16_UNORM, UNSIGNED_SHORT, NONE), | |||
V_(R16G16B16A16_SNORM, SHORT, NONE), | |||
V_(R16G16B16A16_UINT, UNSIGNED_SHORT, NONE), | |||
V_(R16G16B16A16_SINT, SHORT, NONE), | |||
V_(R16G16B16A16_USCALED, UNSIGNED_SHORT, NONE), | |||
V_(R16G16B16A16_SSCALED, SHORT, NONE), | |||
V_(R16G16B16A16_FLOAT, HALF_FLOAT, NONE), | |||
V_(R32G32_UNORM, UNSIGNED_INT, NONE), | |||
V_(R32G32_SNORM, INT, NONE), | |||
V_(R32G32_UINT, UNSIGNED_INT, NONE), | |||
V_(R32G32_SINT, INT, NONE), | |||
V_(R32G32_USCALED, UNSIGNED_INT, NONE), | |||
V_(R32G32_SSCALED, INT, NONE), | |||
V_(R32G32_FLOAT, FLOAT, NONE), | |||
V_(R32G32_FIXED, FIXED, NONE), | |||
/* 96-bit */ | |||
V_(R32G32B32_UNORM, UNSIGNED_INT, NONE), | |||
V_(R32G32B32_SNORM, INT, NONE), | |||
V_(R32G32B32_UINT, UNSIGNED_INT, NONE), | |||
V_(R32G32B32_SINT, INT, NONE), | |||
V_(R32G32B32_USCALED, UNSIGNED_INT, NONE), | |||
V_(R32G32B32_SSCALED, INT, NONE), | |||
V_(R32G32B32_FLOAT, FLOAT, NONE), | |||
V_(R32G32B32_FIXED, FIXED, NONE), | |||
/* 128-bit */ | |||
V_(R32G32B32A32_UNORM, UNSIGNED_INT, NONE), | |||
V_(R32G32B32A32_SNORM, INT, NONE), | |||
V_(R32G32B32A32_UINT, UNSIGNED_INT, NONE), | |||
V_(R32G32B32A32_SINT, INT, NONE), | |||
V_(R32G32B32A32_USCALED, UNSIGNED_INT, NONE), | |||
V_(R32G32B32A32_SSCALED, INT, NONE), | |||
V_(R32G32B32A32_FLOAT, FLOAT, NONE), | |||
V_(R32G32B32A32_FIXED, FIXED, NONE), | |||
/* compressed */ | |||
_T(ETC1_RGB8, ETC1, NONE), | |||
_T(DXT1_RGB, DXT1, NONE), | |||
_T(DXT1_RGBA, DXT1, NONE), | |||
_T(DXT3_RGBA, DXT2_DXT3, NONE), | |||
_T(DXT3_RGBA, DXT2_DXT3, NONE), | |||
_T(DXT5_RGBA, DXT4_DXT5, NONE), | |||
/* YUV */ | |||
_T(YUYV, YUY2, YUY2), | |||
_T(UYVY, UYVY, NONE), | |||
}; | |||
uint32_t | |||
translate_texture_format(enum pipe_format fmt) | |||
{ | |||
/* XXX with TEXTURE_FORMAT_EXT and swizzle on newer chips we can | |||
* support much more */ | |||
if (!formats[fmt].present) | |||
return ETNA_NO_MATCH; | |||
return formats[fmt].tex; | |||
} | |||
uint32_t | |||
translate_rs_format(enum pipe_format fmt) | |||
{ | |||
if (!formats[fmt].present) | |||
return ETNA_NO_MATCH; | |||
if (formats[fmt].rs == ETNA_NO_MATCH) | |||
return ETNA_NO_MATCH; | |||
return RS_FORMAT(formats[fmt].rs); | |||
} | |||
int | |||
translate_rs_format_rb_swap(enum pipe_format fmt) | |||
{ | |||
assert(formats[fmt].present); | |||
return formats[fmt].rs & RS_FORMAT_RB_SWAP; | |||
} | |||
/* Return type flags for vertex element format */ | |||
uint32_t | |||
translate_vertex_format_type(enum pipe_format fmt) | |||
{ | |||
if (!formats[fmt].present) | |||
return ETNA_NO_MATCH; | |||
return formats[fmt].vtx; | |||
} |
@@ -0,0 +1,47 @@ | |||
/* | |||
* Copyright (c) 2016 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Christian Gmeiner <christian.gmeiner@gmail.com> | |||
*/ | |||
#ifndef ETNAVIV_FORMAT_H_ | |||
#define ETNAVIV_FORMAT_H_ | |||
#include "util/u_format.h" | |||
#include <stdint.h> | |||
#define ETNA_NO_MATCH (~0) | |||
uint32_t | |||
translate_texture_format(enum pipe_format fmt); | |||
uint32_t | |||
translate_rs_format(enum pipe_format fmt); | |||
int | |||
translate_rs_format_rb_swap(enum pipe_format fmt); | |||
uint32_t | |||
translate_vertex_format_type(enum pipe_format fmt); | |||
#endif /* ETNAVIV_FORMAT_H_ */ |
@@ -0,0 +1,259 @@ | |||
/* | |||
* Copyright (c) 2012-2015 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
*/ | |||
#ifndef H_ETNA_INTERNAL | |||
#define H_ETNA_INTERNAL | |||
#include <assert.h> | |||
#include <stdbool.h> | |||
#include <stdint.h> | |||
#include "hw/state.xml.h" | |||
#include "hw/state_3d.xml.h" | |||
#include <etnaviv_drmif.h> | |||
#define ETNA_NUM_INPUTS (16) | |||
#define ETNA_NUM_VARYINGS 8 | |||
#define ETNA_NUM_LOD (14) | |||
#define ETNA_NUM_LAYERS (6) | |||
#define ETNA_MAX_UNIFORMS (256) | |||
#define ETNA_MAX_PIXELPIPES 2 | |||
/* All RS operations must have width%16 = 0 */ | |||
#define ETNA_RS_WIDTH_MASK (16 - 1) | |||
/* RS tiled operations must have height%4 = 0 */ | |||
#define ETNA_RS_HEIGHT_MASK (3) | |||
/* PE render targets must be aligned to 64 bytes */ | |||
#define ETNA_PE_ALIGNMENT (64) | |||
/* GPU chip 3D specs */ | |||
struct etna_specs { | |||
/* supports SUPERTILE (64x64) tiling? */ | |||
unsigned can_supertile : 1; | |||
/* needs z=(z+w)/2, for older GCxxx */ | |||
unsigned vs_need_z_div : 1; | |||
/* supports trigonometric instructions */ | |||
unsigned has_sin_cos_sqrt : 1; | |||
/* has SIGN/FLOOR/CEIL instructions */ | |||
unsigned has_sign_floor_ceil : 1; | |||
/* can use VS_RANGE, PS_RANGE registers*/ | |||
unsigned has_shader_range_registers : 1; | |||
/* can use any kind of wrapping mode on npot textures */ | |||
unsigned npot_tex_any_wrap; | |||
/* number of bits per TS tile */ | |||
unsigned bits_per_tile; | |||
/* clear value for TS (dependent on bits_per_tile) */ | |||
uint32_t ts_clear_value; | |||
/* base of vertex texture units */ | |||
unsigned vertex_sampler_offset; | |||
/* number of fragment sampler units */ | |||
unsigned fragment_sampler_count; | |||
/* number of vertex sampler units */ | |||
unsigned vertex_sampler_count; | |||
/* size of vertex shader output buffer */ | |||
unsigned vertex_output_buffer_size; | |||
/* maximum number of vertex element configurations */ | |||
unsigned vertex_max_elements; | |||
/* size of a cached vertex (?) */ | |||
unsigned vertex_cache_size; | |||
/* number of shader cores */ | |||
unsigned shader_core_count; | |||
/* number of vertex streams */ | |||
unsigned stream_count; | |||
/* vertex shader memory address*/ | |||
uint32_t vs_offset; | |||
/* pixel shader memory address*/ | |||
uint32_t ps_offset; | |||
/* vertex/fragment shader max instructions */ | |||
uint32_t max_instructions; | |||
/* maximum number of varyings */ | |||
unsigned max_varyings; | |||
/* maximum number of registers */ | |||
unsigned max_registers; | |||
/* maximum vertex uniforms */ | |||
unsigned max_vs_uniforms; | |||
/* maximum pixel uniforms */ | |||
unsigned max_ps_uniforms; | |||
/* maximum texture size */ | |||
unsigned max_texture_size; | |||
/* maximum texture size */ | |||
unsigned max_rendertarget_size; | |||
/* available pixel pipes */ | |||
unsigned pixel_pipes; | |||
/* number of constants */ | |||
unsigned num_constants; | |||
}; | |||
/* Compiled Gallium state. All the different compiled state atoms are woven | |||
* together and uploaded only when it is necessary to synchronize the state, | |||
* for example before rendering. */ | |||
/* Compiled pipe_blend_color */ | |||
struct compiled_blend_color { | |||
uint32_t PE_ALPHA_BLEND_COLOR; | |||
}; | |||
/* Compiled pipe_stencil_ref */ | |||
struct compiled_stencil_ref { | |||
uint32_t PE_STENCIL_CONFIG; | |||
uint32_t PE_STENCIL_CONFIG_EXT; | |||
}; | |||
/* Compiled pipe_scissor_state */ | |||
struct compiled_scissor_state { | |||
uint32_t SE_SCISSOR_LEFT; | |||
uint32_t SE_SCISSOR_TOP; | |||
uint32_t SE_SCISSOR_RIGHT; | |||
uint32_t SE_SCISSOR_BOTTOM; | |||
}; | |||
/* Compiled pipe_viewport_state */ | |||
struct compiled_viewport_state { | |||
uint32_t PA_VIEWPORT_SCALE_X; | |||
uint32_t PA_VIEWPORT_SCALE_Y; | |||
uint32_t PA_VIEWPORT_SCALE_Z; | |||
uint32_t PA_VIEWPORT_OFFSET_X; | |||
uint32_t PA_VIEWPORT_OFFSET_Y; | |||
uint32_t PA_VIEWPORT_OFFSET_Z; | |||
uint32_t SE_SCISSOR_LEFT; | |||
uint32_t SE_SCISSOR_TOP; | |||
uint32_t SE_SCISSOR_RIGHT; | |||
uint32_t SE_SCISSOR_BOTTOM; | |||
uint32_t PE_DEPTH_NEAR; | |||
uint32_t PE_DEPTH_FAR; | |||
}; | |||
/* Compiled pipe_framebuffer_state */ | |||
struct compiled_framebuffer_state { | |||
struct pipe_surface *cbuf, *zsbuf; /* keep reference to surfaces */ | |||
uint32_t GL_MULTI_SAMPLE_CONFIG; | |||
uint32_t PE_COLOR_FORMAT; | |||
uint32_t PE_DEPTH_CONFIG; | |||
struct etna_reloc PE_DEPTH_ADDR; | |||
struct etna_reloc PE_PIPE_DEPTH_ADDR[ETNA_MAX_PIXELPIPES]; | |||
uint32_t PE_DEPTH_STRIDE; | |||
uint32_t PE_HDEPTH_CONTROL; | |||
uint32_t PE_DEPTH_NORMALIZE; | |||
struct etna_reloc PE_COLOR_ADDR; | |||
struct etna_reloc PE_PIPE_COLOR_ADDR[ETNA_MAX_PIXELPIPES]; | |||
uint32_t PE_COLOR_STRIDE; | |||
uint32_t SE_SCISSOR_LEFT; | |||
uint32_t SE_SCISSOR_TOP; | |||
uint32_t SE_SCISSOR_RIGHT; | |||
uint32_t SE_SCISSOR_BOTTOM; | |||
uint32_t RA_MULTISAMPLE_UNK00E04; | |||
uint32_t RA_MULTISAMPLE_UNK00E10[VIVS_RA_MULTISAMPLE_UNK00E10__LEN]; | |||
uint32_t RA_CENTROID_TABLE[VIVS_RA_CENTROID_TABLE__LEN]; | |||
uint32_t TS_MEM_CONFIG; | |||
uint32_t TS_DEPTH_CLEAR_VALUE; | |||
struct etna_reloc TS_DEPTH_STATUS_BASE; | |||
struct etna_reloc TS_DEPTH_SURFACE_BASE; | |||
uint32_t TS_COLOR_CLEAR_VALUE; | |||
struct etna_reloc TS_COLOR_STATUS_BASE; | |||
struct etna_reloc TS_COLOR_SURFACE_BASE; | |||
bool msaa_mode; /* adds input (and possible temp) to PS */ | |||
}; | |||
/* Compiled context->create_vertex_elements_state */ | |||
struct compiled_vertex_elements_state { | |||
unsigned num_elements; | |||
uint32_t FE_VERTEX_ELEMENT_CONFIG[VIVS_FE_VERTEX_ELEMENT_CONFIG__LEN]; | |||
}; | |||
/* Compiled context->set_vertex_buffer result */ | |||
struct compiled_set_vertex_buffer { | |||
uint32_t FE_VERTEX_STREAM_CONTROL; | |||
struct etna_reloc FE_VERTEX_STREAM_BASE_ADDR; | |||
}; | |||
/* Compiled linked VS+PS shader state */ | |||
struct compiled_shader_state { | |||
uint32_t RA_CONTROL; | |||
uint32_t PA_ATTRIBUTE_ELEMENT_COUNT; | |||
uint32_t PA_CONFIG; | |||
uint32_t PA_SHADER_ATTRIBUTES[VIVS_PA_SHADER_ATTRIBUTES__LEN]; | |||
uint32_t VS_END_PC; | |||
uint32_t VS_OUTPUT_COUNT; /* number of outputs if point size per vertex disabled */ | |||
uint32_t VS_OUTPUT_COUNT_PSIZE; /* number of outputs of point size per vertex enabled */ | |||
uint32_t VS_INPUT_COUNT; | |||
uint32_t VS_TEMP_REGISTER_CONTROL; | |||
uint32_t VS_OUTPUT[4]; | |||
uint32_t VS_INPUT[4]; | |||
uint32_t VS_LOAD_BALANCING; | |||
uint32_t VS_START_PC; | |||
uint32_t PS_END_PC; | |||
uint32_t PS_OUTPUT_REG; | |||
uint32_t PS_INPUT_COUNT; | |||
uint32_t PS_INPUT_COUNT_MSAA; /* Adds an input */ | |||
uint32_t PS_TEMP_REGISTER_CONTROL; | |||
uint32_t PS_TEMP_REGISTER_CONTROL_MSAA; /* Adds a temporary if needed to make space for extra input */ | |||
uint32_t PS_CONTROL; | |||
uint32_t PS_START_PC; | |||
uint32_t GL_VARYING_TOTAL_COMPONENTS; | |||
uint32_t GL_VARYING_NUM_COMPONENTS; | |||
uint32_t GL_VARYING_COMPONENT_USE[2]; | |||
unsigned vs_inst_mem_size; | |||
unsigned vs_uniforms_size; | |||
unsigned ps_inst_mem_size; | |||
unsigned ps_uniforms_size; | |||
uint32_t *VS_INST_MEM; | |||
uint32_t VS_UNIFORMS[ETNA_MAX_UNIFORMS * 4]; | |||
uint32_t *PS_INST_MEM; | |||
uint32_t PS_UNIFORMS[ETNA_MAX_UNIFORMS * 4]; | |||
}; | |||
/* state of some 3d and common registers relevant to etna driver */ | |||
struct etna_3d_state { | |||
unsigned vs_uniforms_size; | |||
unsigned ps_uniforms_size; | |||
uint32_t /*01008*/ PS_INPUT_COUNT; | |||
uint32_t /*0100C*/ PS_TEMP_REGISTER_CONTROL; | |||
uint32_t /*03818*/ GL_MULTI_SAMPLE_CONFIG; | |||
uint32_t /*05000*/ VS_UNIFORMS[VIVS_VS_UNIFORMS__LEN]; | |||
uint32_t /*07000*/ PS_UNIFORMS[VIVS_PS_UNIFORMS__LEN]; | |||
}; | |||
/* Helpers to assist creating and setting bitarrays (eg, for varyings). | |||
* field_size must be a power of two, and <= 32. */ | |||
#define DEFINE_ETNA_BITARRAY(name, num, field_size) \ | |||
uint32_t name[(num) * (field_size) / 32] | |||
static inline void | |||
etna_bitarray_set(uint32_t *array, size_t array_size, size_t field_size, | |||
size_t index, uint32_t value) | |||
{ | |||
size_t shift = (index * field_size) % 32; | |||
size_t offset = (index * field_size) / 32; | |||
assert(index < array_size * 32 / field_size); | |||
assert(value < 1 << field_size); | |||
array[offset] |= value << shift; | |||
} | |||
#define etna_bitarray_set(array, field_size, index, value) \ | |||
etna_bitarray_set((array), ARRAY_SIZE(array), field_size, index, value) | |||
#endif |
@@ -0,0 +1,120 @@ | |||
/* | |||
* Copyright (c) 2016 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Rob Clark <robclark@freedesktop.org> | |||
* Christian Gmeiner <christian.gmeiner@gmail.com> | |||
*/ | |||
#include "pipe/p_screen.h" | |||
#include "etnaviv_context.h" | |||
#include "etnaviv_query.h" | |||
#include "etnaviv_query_sw.h" | |||
static struct pipe_query * | |||
etna_create_query(struct pipe_context *pctx, unsigned query_type, | |||
unsigned index) | |||
{ | |||
struct etna_context *ctx = etna_context(pctx); | |||
struct etna_query *q; | |||
q = etna_sw_create_query(ctx, query_type); | |||
return (struct pipe_query *)q; | |||
} | |||
static void | |||
etna_destroy_query(struct pipe_context *pctx, struct pipe_query *pq) | |||
{ | |||
struct etna_query *q = etna_query(pq); | |||
q->funcs->destroy_query(etna_context(pctx), q); | |||
} | |||
static boolean | |||
etna_begin_query(struct pipe_context *pctx, struct pipe_query *pq) | |||
{ | |||
struct etna_query *q = etna_query(pq); | |||
return q->funcs->begin_query(etna_context(pctx), q); | |||
} | |||
static bool | |||
etna_end_query(struct pipe_context *pctx, struct pipe_query *pq) | |||
{ | |||
struct etna_query *q = etna_query(pq); | |||
q->funcs->end_query(etna_context(pctx), q); | |||
return true; | |||
} | |||
static boolean | |||
etna_get_query_result(struct pipe_context *pctx, struct pipe_query *pq, | |||
boolean wait, union pipe_query_result *result) | |||
{ | |||
struct etna_query *q = etna_query(pq); | |||
return q->funcs->get_query_result(etna_context(pctx), q, wait, result); | |||
} | |||
static int | |||
etna_get_driver_query_info(struct pipe_screen *pscreen, unsigned index, | |||
struct pipe_driver_query_info *info) | |||
{ | |||
struct pipe_driver_query_info list[] = { | |||
{"prims-emitted", PIPE_QUERY_PRIMITIVES_EMITTED, { 0 }}, | |||
{"draw-calls", ETNA_QUERY_DRAW_CALLS, { 0 }}, | |||
}; | |||
if (!info) | |||
return ARRAY_SIZE(list); | |||
if (index >= ARRAY_SIZE(list)) | |||
return 0; | |||
*info = list[index]; | |||
return 1; | |||
} | |||
static void | |||
etna_set_active_query_state(struct pipe_context *pipe, boolean enable) | |||
{ | |||
} | |||
void | |||
etna_query_screen_init(struct pipe_screen *pscreen) | |||
{ | |||
pscreen->get_driver_query_info = etna_get_driver_query_info; | |||
} | |||
void | |||
etna_query_context_init(struct pipe_context *pctx) | |||
{ | |||
pctx->create_query = etna_create_query; | |||
pctx->destroy_query = etna_destroy_query; | |||
pctx->begin_query = etna_begin_query; | |||
pctx->end_query = etna_end_query; | |||
pctx->get_query_result = etna_get_query_result; | |||
pctx->set_active_query_state = etna_set_active_query_state; | |||
} |
@@ -0,0 +1,64 @@ | |||
/* | |||
* Copyright (c) 2016 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Rob Clark <robclark@freedesktop.org> | |||
* Christian Gmeiner <christian.gmeiner@gmail.com> | |||
*/ | |||
#ifndef H_ETNAVIV_QUERY | |||
#define H_ETNAVIV_QUERY | |||
#include "pipe/p_context.h" | |||
struct etna_context; | |||
struct etna_query; | |||
struct etna_query_funcs { | |||
void (*destroy_query)(struct etna_context *ctx, struct etna_query *q); | |||
boolean (*begin_query)(struct etna_context *ctx, struct etna_query *q); | |||
void (*end_query)(struct etna_context *ctx, struct etna_query *q); | |||
boolean (*get_query_result)(struct etna_context *ctx, struct etna_query *q, | |||
boolean wait, union pipe_query_result *result); | |||
}; | |||
struct etna_query { | |||
const struct etna_query_funcs *funcs; | |||
bool active; | |||
int type; | |||
}; | |||
static inline struct etna_query * | |||
etna_query(struct pipe_query *pq) | |||
{ | |||
return (struct etna_query *)pq; | |||
} | |||
#define ETNA_QUERY_DRAW_CALLS (PIPE_QUERY_DRIVER_SPECIFIC + 0) | |||
void | |||
etna_query_screen_init(struct pipe_screen *pscreen); | |||
void | |||
etna_query_context_init(struct pipe_context *pctx); | |||
#endif |
@@ -0,0 +1,123 @@ | |||
/* | |||
* Copyright (c) 2016 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Rob Clark <robclark@freedesktop.org> | |||
* Christian Gmeiner <christian.gmeiner@gmail.com> | |||
*/ | |||
#include "os/os_time.h" | |||
#include "pipe/p_state.h" | |||
#include "util/u_inlines.h" | |||
#include "util/u_memory.h" | |||
#include "util/u_string.h" | |||
#include "etnaviv_context.h" | |||
#include "etnaviv_query_sw.h" | |||
static void | |||
etna_sw_destroy_query(struct etna_context *ctx, struct etna_query *q) | |||
{ | |||
struct etna_sw_query *sq = etna_sw_query(q); | |||
FREE(sq); | |||
} | |||
static uint64_t | |||
read_counter(struct etna_context *ctx, int type) | |||
{ | |||
switch (type) { | |||
case PIPE_QUERY_PRIMITIVES_EMITTED: | |||
return ctx->stats.prims_emitted; | |||
case ETNA_QUERY_DRAW_CALLS: | |||
return ctx->stats.draw_calls; | |||
} | |||
return 0; | |||
} | |||
static boolean | |||
etna_sw_begin_query(struct etna_context *ctx, struct etna_query *q) | |||
{ | |||
struct etna_sw_query *sq = etna_sw_query(q); | |||
q->active = true; | |||
sq->begin_value = read_counter(ctx, q->type); | |||
return true; | |||
} | |||
static void | |||
etna_sw_end_query(struct etna_context *ctx, struct etna_query *q) | |||
{ | |||
struct etna_sw_query *sq = etna_sw_query(q); | |||
q->active = false; | |||
sq->end_value = read_counter(ctx, q->type); | |||
} | |||
static boolean | |||
etna_sw_get_query_result(struct etna_context *ctx, struct etna_query *q, | |||
boolean wait, union pipe_query_result *result) | |||
{ | |||
struct etna_sw_query *sq = etna_sw_query(q); | |||
if (q->active) | |||
return false; | |||
util_query_clear_result(result, q->type); | |||
result->u64 = sq->end_value - sq->begin_value; | |||
return true; | |||
} | |||
static const struct etna_query_funcs sw_query_funcs = { | |||
.destroy_query = etna_sw_destroy_query, | |||
.begin_query = etna_sw_begin_query, | |||
.end_query = etna_sw_end_query, | |||
.get_query_result = etna_sw_get_query_result, | |||
}; | |||
struct etna_query * | |||
etna_sw_create_query(struct etna_context *ctx, unsigned query_type) | |||
{ | |||
struct etna_sw_query *sq; | |||
struct etna_query *q; | |||
switch (query_type) { | |||
case PIPE_QUERY_PRIMITIVES_EMITTED: | |||
case ETNA_QUERY_DRAW_CALLS: | |||
break; | |||
default: | |||
return NULL; | |||
} | |||
sq = CALLOC_STRUCT(etna_sw_query); | |||
if (!sq) | |||
return NULL; | |||
q = &sq->base; | |||
q->funcs = &sw_query_funcs; | |||
q->type = query_type; | |||
return q; | |||
} |
@@ -0,0 +1,47 @@ | |||
/* | |||
* Copyright (c) 2016 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Rob Clark <robclark@freedesktop.org> | |||
* Christian Gmeiner <christian.gmeiner@gmail.com> | |||
*/ | |||
#ifndef H_ETNAVIV_QUERY_SW | |||
#define H_ETNAVIV_QUERY_SW | |||
#include "etnaviv_query.h" | |||
struct etna_sw_query { | |||
struct etna_query base; | |||
uint64_t begin_value, end_value; | |||
}; | |||
static inline struct etna_sw_query * | |||
etna_sw_query(struct etna_query *q) | |||
{ | |||
return (struct etna_sw_query *)q; | |||
} | |||
struct etna_query * | |||
etna_sw_create_query(struct etna_context *ctx, unsigned query_type); | |||
#endif |
@@ -0,0 +1,81 @@ | |||
/* | |||
* Copyright (c) 2012-2015 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
*/ | |||
#include "etnaviv_rasterizer.h" | |||
#include "etnaviv_context.h" | |||
#include "etnaviv_screen.h" | |||
#include "hw/common.xml.h" | |||
#include "etnaviv_translate.h" | |||
#include "util/u_math.h" | |||
#include "util/u_memory.h" | |||
void * | |||
etna_rasterizer_state_create(struct pipe_context *pctx, | |||
const struct pipe_rasterizer_state *so) | |||
{ | |||
struct etna_rasterizer_state *cs; | |||
struct etna_context *ctx = etna_context(pctx); | |||
/* Disregard flatshading on GC880+, as a HW bug there seem to disable all | |||
* varying interpolation if it's enabled */ | |||
bool flatshade = ctx->screen->model < 880 ? so->flatshade : false; | |||
if (so->fill_front != so->fill_back) | |||
DBG("Different front and back fill mode not supported"); | |||
cs = CALLOC_STRUCT(etna_rasterizer_state); | |||
if (!cs) | |||
return NULL; | |||
cs->base = *so; | |||
cs->PA_CONFIG = (flatshade ? VIVS_PA_CONFIG_SHADE_MODEL_FLAT : VIVS_PA_CONFIG_SHADE_MODEL_SMOOTH) | | |||
translate_cull_face(so->cull_face, so->front_ccw) | | |||
translate_polygon_mode(so->fill_front) | | |||
COND(so->point_quad_rasterization, VIVS_PA_CONFIG_POINT_SPRITE_ENABLE) | | |||
COND(so->point_size_per_vertex, VIVS_PA_CONFIG_POINT_SIZE_ENABLE) | | |||
COND(VIV_FEATURE(ctx->screen, chipMinorFeatures1, WIDE_LINE), VIVS_PA_CONFIG_WIDE_LINE); | |||
cs->PA_LINE_WIDTH = fui(so->line_width / 2.0f); | |||
cs->PA_POINT_SIZE = fui(so->point_size / 2.0f); | |||
cs->SE_DEPTH_SCALE = fui(so->offset_scale); | |||
cs->SE_DEPTH_BIAS = fui(so->offset_units) / 65535.0f; | |||
cs->SE_CONFIG = COND(so->line_last_pixel, VIVS_SE_CONFIG_LAST_PIXEL_ENABLE); | |||
/* XXX anything else? */ | |||
/* XXX bottom_edge_rule */ | |||
cs->PA_SYSTEM_MODE = | |||
COND(so->half_pixel_center, VIVS_PA_SYSTEM_MODE_UNK0 | VIVS_PA_SYSTEM_MODE_UNK4); | |||
/* so->scissor overrides the scissor, defaulting to the whole framebuffer, | |||
* with the scissor state */ | |||
cs->scissor = so->scissor; | |||
/* point size per vertex adds a vertex shader output */ | |||
cs->point_size_per_vertex = so->point_size_per_vertex; | |||
assert(!so->clip_halfz); /* could be supported with shader magic, actually | |||
D3D z is default on older gc */ | |||
return cs; | |||
} |
@@ -0,0 +1,57 @@ | |||
/* | |||
* Copyright (c) 2012-2015 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Wladimir J. van der Laan <laanwj@gmail.com> | |||
*/ | |||
#ifndef H_ETNAVIV_RASTERIZER | |||
#define H_ETNAVIV_RASTERIZER | |||
#include "pipe/p_context.h" | |||
#include "pipe/p_state.h" | |||
struct etna_rasterizer_state { | |||
struct pipe_rasterizer_state base; | |||
uint32_t PA_CONFIG; | |||
uint32_t PA_LINE_WIDTH; | |||
uint32_t PA_POINT_SIZE; | |||
uint32_t PA_SYSTEM_MODE; | |||
uint32_t SE_DEPTH_SCALE; | |||
uint32_t SE_DEPTH_BIAS; | |||
uint32_t SE_CONFIG; | |||
bool point_size_per_vertex; | |||
bool scissor; | |||
}; | |||
static inline struct etna_rasterizer_state * | |||
etna_rasterizer_state(struct pipe_rasterizer_state *rast) | |||
{ | |||
return (struct etna_rasterizer_state *)rast; | |||
} | |||
void * | |||
etna_rasterizer_state_create(struct pipe_context *pctx, | |||
const struct pipe_rasterizer_state *so); | |||
#endif |
@@ -0,0 +1,438 @@ | |||
/* | |||
* Copyright (c) 2012-2015 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Wladimir J. van der Laan <laanwj@gmail.com> | |||
*/ | |||
#include "etnaviv_resource.h" | |||
#include "hw/common.xml.h" | |||
#include "etnaviv_context.h" | |||
#include "etnaviv_debug.h" | |||
#include "etnaviv_screen.h" | |||
#include "etnaviv_translate.h" | |||
#include "util/u_inlines.h" | |||
#include "util/u_memory.h" | |||
/* A tile is 4x4 pixels, having 'screen->specs.bits_per_tile' of tile status. | |||
* So, in a buffer of N pixels, there are N / (4 * 4) tiles. | |||
* We need N * screen->specs.bits_per_tile / (4 * 4) bits of tile status, or | |||
* N * screen->specs.bits_per_tile / (4 * 4 * 8) bytes. | |||
*/ | |||
bool | |||
etna_screen_resource_alloc_ts(struct pipe_screen *pscreen, | |||
struct etna_resource *rsc) | |||
{ | |||
struct etna_screen *screen = etna_screen(pscreen); | |||
size_t rt_ts_size, ts_layer_stride, pixels; | |||
assert(!rsc->ts_bo); | |||
/* TS only for level 0 -- XXX is this formula correct? */ | |||
pixels = rsc->levels[0].layer_stride / util_format_get_blocksize(rsc->base.format); | |||
ts_layer_stride = align(pixels * screen->specs.bits_per_tile / 0x80, 0x100); | |||
rt_ts_size = ts_layer_stride * rsc->base.array_size; | |||
if (rt_ts_size == 0) | |||
return true; | |||
DBG_F(ETNA_DBG_RESOURCE_MSGS, "%p: Allocating tile status of size %zu", | |||
rsc, rt_ts_size); | |||
struct etna_bo *rt_ts; | |||
rt_ts = etna_bo_new(screen->dev, rt_ts_size, DRM_ETNA_GEM_CACHE_WC); | |||
if (unlikely(!rt_ts)) { | |||
BUG("Problem allocating tile status for resource"); | |||
return false; | |||
} | |||
rsc->ts_bo = rt_ts; | |||
rsc->levels[0].ts_offset = 0; | |||
rsc->levels[0].ts_layer_stride = ts_layer_stride; | |||
rsc->levels[0].ts_size = rt_ts_size; | |||
/* It is important to initialize the TS, as random pattern | |||
* can result in crashes. Do this on the CPU as this only happens once | |||
* per surface anyway and it's a small area, so it may not be worth | |||
* queuing this to the GPU. */ | |||
void *ts_map = etna_bo_map(rt_ts); | |||
memset(ts_map, screen->specs.ts_clear_value, rt_ts_size); | |||
return true; | |||
} | |||
static boolean | |||
etna_screen_can_create_resource(struct pipe_screen *pscreen, | |||
const struct pipe_resource *templat) | |||
{ | |||
struct etna_screen *screen = etna_screen(pscreen); | |||
if (!translate_samples_to_xyscale(templat->nr_samples, NULL, NULL, NULL)) | |||
return false; | |||
/* templat->bind is not set here, so we must use the minimum sizes */ | |||
uint max_size = | |||
MIN2(screen->specs.max_rendertarget_size, screen->specs.max_texture_size); | |||
if (templat->width0 > max_size || templat->height0 > max_size) | |||
return false; | |||
return true; | |||
} | |||
static unsigned | |||
setup_miptree(struct etna_resource *rsc, unsigned paddingX, unsigned paddingY, | |||
unsigned msaa_xscale, unsigned msaa_yscale) | |||
{ | |||
struct pipe_resource *prsc = &rsc->base; | |||
unsigned level, size = 0; | |||
unsigned width = prsc->width0; | |||
unsigned height = prsc->height0; | |||
unsigned depth = prsc->depth0; | |||
for (level = 0; level <= prsc->last_level; level++) { | |||
struct etna_resource_level *mip = &rsc->levels[level]; | |||
mip->width = width; | |||
mip->height = height; | |||
mip->padded_width = align(width * msaa_xscale, paddingX); | |||
mip->padded_height = align(height * msaa_yscale, paddingY); | |||
mip->stride = util_format_get_stride(prsc->format, mip->padded_width); | |||
mip->offset = size; | |||
mip->layer_stride = mip->stride * util_format_get_nblocksy(prsc->format, mip->padded_height); | |||
mip->size = prsc->array_size * mip->layer_stride; | |||
/* align levels to 64 bytes to be able to render to them */ | |||
size += align(mip->size, ETNA_PE_ALIGNMENT) * depth; | |||
width = u_minify(width, 1); | |||
height = u_minify(height, 1); | |||
depth = u_minify(depth, 1); | |||
} | |||
return size; | |||
} | |||
/* Create a new resource object, using the given template info */ | |||
struct pipe_resource * | |||
etna_resource_alloc(struct pipe_screen *pscreen, unsigned layout, | |||
const struct pipe_resource *templat) | |||
{ | |||
struct etna_screen *screen = etna_screen(pscreen); | |||
unsigned size; | |||
DBG_F(ETNA_DBG_RESOURCE_MSGS, | |||
"target=%d, format=%s, %ux%ux%u, array_size=%u, " | |||
"last_level=%u, nr_samples=%u, usage=%u, bind=%x, flags=%x", | |||
templat->target, util_format_name(templat->format), templat->width0, | |||
templat->height0, templat->depth0, templat->array_size, | |||
templat->last_level, templat->nr_samples, templat->usage, | |||
templat->bind, templat->flags); | |||
/* Determine scaling for antialiasing, allow override using debug flag */ | |||
int nr_samples = templat->nr_samples; | |||
if ((templat->bind & (PIPE_BIND_RENDER_TARGET | PIPE_BIND_DEPTH_STENCIL)) && | |||
!(templat->bind & PIPE_BIND_SAMPLER_VIEW)) { | |||
if (DBG_ENABLED(ETNA_DBG_MSAA_2X)) | |||
nr_samples = 2; | |||
if (DBG_ENABLED(ETNA_DBG_MSAA_4X)) | |||
nr_samples = 4; | |||
} | |||
int msaa_xscale = 1, msaa_yscale = 1; | |||
if (!translate_samples_to_xyscale(nr_samples, &msaa_xscale, &msaa_yscale, NULL)) { | |||
/* Number of samples not supported */ | |||
return NULL; | |||
} | |||
/* If we have the TEXTURE_HALIGN feature, we can always align to the | |||
* resolve engine's width. If not, we must not align resources used | |||
* only for textures. */ | |||
bool rs_align = VIV_FEATURE(screen, chipMinorFeatures1, TEXTURE_HALIGN) || | |||
!etna_resource_sampler_only(templat); | |||
/* Determine needed padding (alignment of height/width) */ | |||
unsigned paddingX = 0, paddingY = 0; | |||
unsigned halign = TEXTURE_HALIGN_FOUR; | |||
etna_layout_multiple(layout, screen->specs.pixel_pipes, rs_align, &paddingX, | |||
&paddingY, &halign); | |||
assert(paddingX && paddingY); | |||
if (templat->bind != PIPE_BUFFER) { | |||
unsigned min_paddingY = 4 * screen->specs.pixel_pipes; | |||
if (paddingY < min_paddingY) | |||
paddingY = min_paddingY; | |||
} | |||
struct etna_resource *rsc = CALLOC_STRUCT(etna_resource); | |||
if (!rsc) | |||
return NULL; | |||
rsc->base = *templat; | |||
rsc->base.screen = pscreen; | |||
rsc->base.nr_samples = nr_samples; | |||
rsc->layout = layout; | |||
rsc->halign = halign; | |||
pipe_reference_init(&rsc->base.reference, 1); | |||
list_inithead(&rsc->list); | |||
size = setup_miptree(rsc, paddingX, paddingY, msaa_xscale, msaa_yscale); | |||
struct etna_bo *bo = etna_bo_new(screen->dev, size, DRM_ETNA_GEM_CACHE_WC); | |||
if (unlikely(bo == NULL)) { | |||
BUG("Problem allocating video memory for resource"); | |||
return NULL; | |||
} | |||
rsc->bo = bo; | |||
rsc->ts_bo = 0; /* TS is only created when first bound to surface */ | |||
if (templat->bind & PIPE_BIND_SCANOUT) | |||
rsc->scanout = renderonly_scanout_for_resource(&rsc->base, screen->ro); | |||
if (DBG_ENABLED(ETNA_DBG_ZERO)) { | |||
void *map = etna_bo_map(bo); | |||
memset(map, 0, size); | |||
} | |||
return &rsc->base; | |||
} | |||
static struct pipe_resource * | |||
etna_resource_create(struct pipe_screen *pscreen, | |||
const struct pipe_resource *templat) | |||
{ | |||
struct etna_screen *screen = etna_screen(pscreen); | |||
/* Figure out what tiling to use -- for now, assume that textures cannot be | |||
* supertiled, and cannot be linear. | |||
* There is a feature flag SUPERTILED_TEXTURE (not supported on any known hw) | |||
* that may allow this, as well | |||
* as LINEAR_TEXTURE_SUPPORT (supported on gc880 and gc2000 at least), but | |||
* not sure how it works. | |||
* Buffers always have LINEAR layout. | |||
*/ | |||
unsigned layout = ETNA_LAYOUT_LINEAR; | |||
if (etna_resource_sampler_only(templat)) { | |||
/* The buffer is only used for texturing, so create something | |||
* directly compatible with the sampler. Such a buffer can | |||
* never be rendered to. */ | |||
layout = ETNA_LAYOUT_TILED; | |||
if (util_format_is_compressed(templat->format)) | |||
layout = ETNA_LAYOUT_LINEAR; | |||
} else if (templat->target != PIPE_BUFFER) { | |||
bool want_multitiled = screen->specs.pixel_pipes > 1; | |||
bool want_supertiled = screen->specs.can_supertile && !DBG_ENABLED(ETNA_DBG_NO_SUPERTILE); | |||
/* Keep single byte blocksized resources as tiled, since we | |||
* are unable to use the RS blit to de-tile them. However, | |||
* if they're used as a render target or depth/stencil, they | |||
* must be multi-tiled for GPUs with multiple pixel pipes. | |||
* Ignore depth/stencil here, but it is an error for a render | |||
* target. | |||
*/ | |||
if (util_format_get_blocksize(templat->format) == 1 && | |||
!(templat->bind & PIPE_BIND_DEPTH_STENCIL)) { | |||
assert(!(templat->bind & PIPE_BIND_RENDER_TARGET && want_multitiled)); | |||
want_multitiled = want_supertiled = false; | |||
} | |||
layout = ETNA_LAYOUT_BIT_TILE; | |||
if (want_multitiled) | |||
layout |= ETNA_LAYOUT_BIT_MULTI; | |||
if (want_supertiled) | |||
layout |= ETNA_LAYOUT_BIT_SUPER; | |||
} | |||
if (templat->target == PIPE_TEXTURE_3D) | |||
layout = ETNA_LAYOUT_LINEAR; | |||
return etna_resource_alloc(pscreen, layout, templat); | |||
} | |||
static void | |||
etna_resource_destroy(struct pipe_screen *pscreen, struct pipe_resource *prsc) | |||
{ | |||
struct etna_resource *rsc = etna_resource(prsc); | |||
if (rsc->bo) | |||
etna_bo_del(rsc->bo); | |||
if (rsc->ts_bo) | |||
etna_bo_del(rsc->ts_bo); | |||
if (rsc->scanout) | |||
renderonly_scanout_destroy(rsc->scanout); | |||
list_delinit(&rsc->list); | |||
pipe_resource_reference(&rsc->texture, NULL); | |||
FREE(rsc); | |||
} | |||
static struct pipe_resource * | |||
etna_resource_from_handle(struct pipe_screen *pscreen, | |||
const struct pipe_resource *tmpl, | |||
struct winsys_handle *handle, unsigned usage) | |||
{ | |||
struct etna_screen *screen = etna_screen(pscreen); | |||
struct etna_resource *rsc = CALLOC_STRUCT(etna_resource); | |||
struct etna_resource_level *level = &rsc->levels[0]; | |||
struct pipe_resource *prsc = &rsc->base; | |||
struct pipe_resource *ptiled = NULL; | |||
DBG("target=%d, format=%s, %ux%ux%u, array_size=%u, last_level=%u, " | |||
"nr_samples=%u, usage=%u, bind=%x, flags=%x", | |||
tmpl->target, util_format_name(tmpl->format), tmpl->width0, | |||
tmpl->height0, tmpl->depth0, tmpl->array_size, tmpl->last_level, | |||
tmpl->nr_samples, tmpl->usage, tmpl->bind, tmpl->flags); | |||
if (!rsc) | |||
return NULL; | |||
*prsc = *tmpl; | |||
pipe_reference_init(&prsc->reference, 1); | |||
list_inithead(&rsc->list); | |||
prsc->screen = pscreen; | |||
rsc->bo = etna_screen_bo_from_handle(pscreen, handle, &level->stride); | |||
if (!rsc->bo) | |||
goto fail; | |||
level->width = tmpl->width0; | |||
level->height = tmpl->height0; | |||
/* We will be using the RS to copy with this resource, so we must | |||
* ensure that it is appropriately aligned for the RS requirements. */ | |||
unsigned paddingX = ETNA_RS_WIDTH_MASK + 1; | |||
unsigned paddingY = (ETNA_RS_HEIGHT_MASK + 1) * screen->specs.pixel_pipes; | |||
level->padded_width = align(level->width, paddingX); | |||
level->padded_height = align(level->height, paddingY); | |||
/* The DDX must give us a BO which conforms to our padding size. | |||
* The stride of the BO must be greater or equal to our padded | |||
* stride. The size of the BO must accomodate the padded height. */ | |||
if (level->stride < util_format_get_stride(tmpl->format, level->padded_width)) { | |||
BUG("BO stride is too small for RS engine width padding"); | |||
goto fail; | |||
} | |||
if (etna_bo_size(rsc->bo) < level->stride * level->padded_height) { | |||
BUG("BO size is too small for RS engine height padding"); | |||
goto fail; | |||
} | |||
if (handle->type == DRM_API_HANDLE_TYPE_SHARED && tmpl->bind & PIPE_BIND_RENDER_TARGET) { | |||
/* Render targets are linear in Xorg but must be tiled | |||
* here. It would be nice if dri_drawable_get_format() | |||
* set scanout for these buffers too. */ | |||
struct etna_resource *tiled; | |||
ptiled = etna_resource_create(pscreen, tmpl); | |||
if (!ptiled) | |||
goto fail; | |||
tiled = etna_resource(ptiled); | |||
tiled->scanout = renderonly_scanout_for_prime(prsc, screen->ro); | |||
if (!tiled->scanout) | |||
goto fail; | |||
return ptiled; | |||
} | |||
return prsc; | |||
fail: | |||
etna_resource_destroy(pscreen, prsc); | |||
if (ptiled) | |||
etna_resource_destroy(pscreen, ptiled); | |||
return NULL; | |||
} | |||
static boolean | |||
etna_resource_get_handle(struct pipe_screen *pscreen, | |||
struct pipe_context *pctx, | |||
struct pipe_resource *prsc, | |||
struct winsys_handle *handle, unsigned usage) | |||
{ | |||
struct etna_resource *rsc = etna_resource(prsc); | |||
if (renderonly_get_handle(rsc->scanout, handle)) | |||
return TRUE; | |||
return etna_screen_bo_get_handle(pscreen, rsc->bo, rsc->levels[0].stride, | |||
handle); | |||
} | |||
void | |||
etna_resource_used(struct etna_context *ctx, struct pipe_resource *prsc, | |||
enum etna_resource_status status) | |||
{ | |||
struct etna_resource *rsc; | |||
if (!prsc) | |||
return; | |||
rsc = etna_resource(prsc); | |||
rsc->status |= status; | |||
/* TODO resources can actually be shared across contexts, | |||
* so I'm not sure a single list-head will do the trick? */ | |||
debug_assert((rsc->pending_ctx == ctx) || !rsc->pending_ctx); | |||
list_delinit(&rsc->list); | |||
list_addtail(&rsc->list, &ctx->used_resources); | |||
rsc->pending_ctx = ctx; | |||
} | |||
void | |||
etna_resource_wait(struct pipe_context *pctx, struct etna_resource *rsc) | |||
{ | |||
if (rsc->status & ETNA_PENDING_WRITE) { | |||
struct pipe_fence_handle *fence; | |||
struct pipe_screen *pscreen = pctx->screen; | |||
pctx->flush(pctx, &fence, 0); | |||
if (!pscreen->fence_finish(pscreen, pctx, fence, 5000000000ULL)) | |||
BUG("fence timed out (hung GPU?)"); | |||
pscreen->fence_reference(pscreen, &fence, NULL); | |||
} | |||
} | |||
void | |||
etna_resource_screen_init(struct pipe_screen *pscreen) | |||
{ | |||
pscreen->can_create_resource = etna_screen_can_create_resource; | |||
pscreen->resource_create = etna_resource_create; | |||
pscreen->resource_from_handle = etna_resource_from_handle; | |||
pscreen->resource_get_handle = etna_resource_get_handle; | |||
pscreen->resource_destroy = etna_resource_destroy; | |||
} |
@@ -0,0 +1,148 @@ | |||
/* | |||
* Copyright (c) 2012-2015 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Wladimir J. van der Laan <laanwj@gmail.com> | |||
*/ | |||
#ifndef H_ETNAVIV_RESOURCE | |||
#define H_ETNAVIV_RESOURCE | |||
#include "etnaviv_internal.h" | |||
#include "etnaviv_tiling.h" | |||
#include "pipe/p_state.h" | |||
#include "util/list.h" | |||
struct pipe_screen; | |||
struct etna_resource_level { | |||
unsigned width, padded_width; /* in pixels */ | |||
unsigned height, padded_height; /* in samples */ | |||
unsigned offset; /* offset into memory area */ | |||
uint32_t stride; /* row stride */ | |||
uint32_t layer_stride; /* layer stride */ | |||
unsigned size; /* total size of memory area */ | |||
uint32_t ts_offset; | |||
uint32_t ts_layer_stride; | |||
uint32_t ts_size; | |||
uint32_t clear_value; /* clear value of resource level (mainly for TS) */ | |||
}; | |||
/* status of queued up but not flushed reads and write operations. | |||
* In _transfer_map() we need to know if queued up rendering needs | |||
* to be flushed to preserve the order of cpu and gpu access. */ | |||
enum etna_resource_status { | |||
ETNA_PENDING_WRITE = 0x01, | |||
ETNA_PENDING_READ = 0x02, | |||
}; | |||
struct etna_resource { | |||
struct pipe_resource base; | |||
struct renderonly_scanout *scanout; | |||
uint32_t seqno; | |||
/* only lod 0 used for non-texture buffers */ | |||
/* Layout for surface (tiled, multitiled, split tiled, ...) */ | |||
enum etna_surface_layout layout; | |||
/* Horizontal alignment for texture unit (TEXTURE_HALIGN_*) */ | |||
unsigned halign; | |||
struct etna_bo *bo; /* Surface video memory */ | |||
struct etna_bo *ts_bo; /* Tile status video memory */ | |||
struct etna_resource_level levels[ETNA_NUM_LOD]; | |||
/* When we are rendering to a texture, we need a differently tiled resource */ | |||
struct pipe_resource *texture; | |||
enum etna_resource_status status; | |||
/* resources accessed by queued but not flushed draws are tracked | |||
* in the used_resources list. */ | |||
struct list_head list; | |||
struct etna_context *pending_ctx; | |||
}; | |||
/* returns TRUE if a is newer than b */ | |||
static inline bool | |||
etna_resource_newer(struct etna_resource *a, struct etna_resource *b) | |||
{ | |||
return (int)(a->seqno - b->seqno) > 0; | |||
} | |||
/* returns TRUE if a is older than b */ | |||
static inline bool | |||
etna_resource_older(struct etna_resource *a, struct etna_resource *b) | |||
{ | |||
return (int)(a->seqno - b->seqno) < 0; | |||
} | |||
/* is the resource only used on the sampler? */ | |||
static inline bool | |||
etna_resource_sampler_only(const struct pipe_resource *pres) | |||
{ | |||
return (pres->bind & (PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET | | |||
PIPE_BIND_DEPTH_STENCIL | PIPE_BIND_BLENDABLE)) == | |||
PIPE_BIND_SAMPLER_VIEW; | |||
} | |||
static inline struct etna_resource * | |||
etna_resource(struct pipe_resource *p) | |||
{ | |||
return (struct etna_resource *)p; | |||
} | |||
void | |||
etna_resource_used(struct etna_context *ctx, struct pipe_resource *prsc, | |||
enum etna_resource_status status); | |||
void | |||
etna_resource_wait(struct pipe_context *ctx, struct etna_resource *rsc); | |||
static inline void | |||
resource_read(struct etna_context *ctx, struct pipe_resource *prsc) | |||
{ | |||
etna_resource_used(ctx, prsc, ETNA_PENDING_READ); | |||
} | |||
static inline void | |||
resource_written(struct etna_context *ctx, struct pipe_resource *prsc) | |||
{ | |||
etna_resource_used(ctx, prsc, ETNA_PENDING_WRITE); | |||
} | |||
/* Allocate Tile Status for an etna resource. | |||
* Tile status is a cache of the clear status per tile. This means a smaller | |||
* surface has to be cleared which is faster. | |||
* This is also called "fast clear". */ | |||
bool | |||
etna_screen_resource_alloc_ts(struct pipe_screen *pscreen, | |||
struct etna_resource *prsc); | |||
struct pipe_resource * | |||
etna_resource_alloc(struct pipe_screen *pscreen, unsigned layout, | |||
const struct pipe_resource *templat); | |||
void | |||
etna_resource_screen_init(struct pipe_screen *pscreen); | |||
#endif |
@@ -0,0 +1,127 @@ | |||
/* | |||
* Copyright (c) 2012-2015 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Wladimir J. van der Laan <laanwj@gmail.com> | |||
*/ | |||
#include "etnaviv_rs.h" | |||
#include "etnaviv_screen.h" | |||
#include "etnaviv_tiling.h" | |||
#include "etnaviv_util.h" | |||
#include "hw/common.xml.h" | |||
#include "hw/state.xml.h" | |||
#include "hw/state_3d.xml.h" | |||
#include <assert.h> | |||
void | |||
etna_compile_rs_state(struct etna_context *ctx, struct compiled_rs_state *cs, | |||
const struct rs_state *rs) | |||
{ | |||
memset(cs, 0, sizeof(*cs)); | |||
/* TILED and SUPERTILED layout have their strides multiplied with 4 in RS */ | |||
unsigned source_stride_shift = COND(rs->source_tiling != ETNA_LAYOUT_LINEAR, 2); | |||
unsigned dest_stride_shift = COND(rs->dest_tiling != ETNA_LAYOUT_LINEAR, 2); | |||
/* tiling == ETNA_LAYOUT_MULTI_TILED or ETNA_LAYOUT_MULTI_SUPERTILED? */ | |||
int source_multi = COND(rs->source_tiling & ETNA_LAYOUT_BIT_MULTI, 1); | |||
int dest_multi = COND(rs->dest_tiling & ETNA_LAYOUT_BIT_MULTI, 1); | |||
/* Vivante RS needs widths to be a multiple of 16 or bad things | |||
* happen, such as scribbing over memory, or the GPU hanging, | |||
* even for non-tiled formats. As this is serious, use abort(). | |||
*/ | |||
if (rs->width & ETNA_RS_WIDTH_MASK) | |||
abort(); | |||
/* TODO could just pre-generate command buffer, would simply submit to one memcpy */ | |||
cs->RS_CONFIG = VIVS_RS_CONFIG_SOURCE_FORMAT(rs->source_format) | | |||
COND(rs->downsample_x, VIVS_RS_CONFIG_DOWNSAMPLE_X) | | |||
COND(rs->downsample_y, VIVS_RS_CONFIG_DOWNSAMPLE_Y) | | |||
COND(rs->source_tiling & 1, VIVS_RS_CONFIG_SOURCE_TILED) | | |||
VIVS_RS_CONFIG_DEST_FORMAT(rs->dest_format) | | |||
COND(rs->dest_tiling & 1, VIVS_RS_CONFIG_DEST_TILED) | | |||
COND(rs->swap_rb, VIVS_RS_CONFIG_SWAP_RB) | | |||
COND(rs->flip, VIVS_RS_CONFIG_FLIP); | |||
cs->RS_SOURCE_STRIDE = (rs->source_stride << source_stride_shift) | | |||
COND(rs->source_tiling & 2, VIVS_RS_SOURCE_STRIDE_TILING) | | |||
COND(source_multi, VIVS_RS_SOURCE_STRIDE_MULTI); | |||
cs->source[0].bo = rs->source; | |||
cs->source[0].offset = rs->source_offset; | |||
cs->source[0].flags = ETNA_RELOC_READ; | |||
cs->dest[0].bo = rs->dest; | |||
cs->dest[0].offset = rs->dest_offset; | |||
cs->dest[0].flags = ETNA_RELOC_WRITE; | |||
cs->RS_DEST_STRIDE = (rs->dest_stride << dest_stride_shift) | | |||
COND(rs->dest_tiling & 2, VIVS_RS_DEST_STRIDE_TILING) | | |||
COND(dest_multi, VIVS_RS_DEST_STRIDE_MULTI); | |||
if (ctx->specs.pixel_pipes == 1) { | |||
cs->RS_WINDOW_SIZE = VIVS_RS_WINDOW_SIZE_WIDTH(rs->width) | | |||
VIVS_RS_WINDOW_SIZE_HEIGHT(rs->height); | |||
} else if (ctx->specs.pixel_pipes == 2) { | |||
assert((rs->height & 7) == 0); /* GPU hangs happen if height not 8-aligned */ | |||
if (source_multi) { | |||
cs->source[1].bo = rs->source; | |||
cs->source[1].offset = rs->source_offset + rs->source_stride * rs->source_padded_height / 2; | |||
cs->source[1].flags = ETNA_RELOC_READ; | |||
} | |||
if (dest_multi) { | |||
cs->dest[1].bo = rs->dest; | |||
cs->dest[1].offset = rs->dest_offset + rs->dest_stride * rs->dest_padded_height / 2; | |||
cs->dest[1].flags = ETNA_RELOC_WRITE; | |||
} | |||
cs->RS_WINDOW_SIZE = VIVS_RS_WINDOW_SIZE_WIDTH(rs->width) | | |||
VIVS_RS_WINDOW_SIZE_HEIGHT(rs->height / 2); | |||
} else { | |||
abort(); | |||
} | |||
cs->RS_PIPE_OFFSET[0] = VIVS_RS_PIPE_OFFSET_X(0) | VIVS_RS_PIPE_OFFSET_Y(0); | |||
cs->RS_PIPE_OFFSET[1] = VIVS_RS_PIPE_OFFSET_X(0) | VIVS_RS_PIPE_OFFSET_Y(rs->height / 2); | |||
cs->RS_DITHER[0] = rs->dither[0]; | |||
cs->RS_DITHER[1] = rs->dither[1]; | |||
cs->RS_CLEAR_CONTROL = VIVS_RS_CLEAR_CONTROL_BITS(rs->clear_bits) | rs->clear_mode; | |||
cs->RS_FILL_VALUE[0] = rs->clear_value[0]; | |||
cs->RS_FILL_VALUE[1] = rs->clear_value[1]; | |||
cs->RS_FILL_VALUE[2] = rs->clear_value[2]; | |||
cs->RS_FILL_VALUE[3] = rs->clear_value[3]; | |||
cs->RS_EXTRA_CONFIG = VIVS_RS_EXTRA_CONFIG_AA(rs->aa) | | |||
VIVS_RS_EXTRA_CONFIG_ENDIAN(rs->endian_mode); | |||
} | |||
void | |||
etna_modify_rs_clearbits(struct compiled_rs_state *cs, uint32_t clear_bits) | |||
{ | |||
cs->RS_CLEAR_CONTROL &= ~VIVS_RS_CLEAR_CONTROL_BITS__MASK; | |||
cs->RS_CLEAR_CONTROL |= VIVS_RS_CLEAR_CONTROL_BITS(clear_bits); | |||
} |
@@ -0,0 +1,86 @@ | |||
/* | |||
* Copyright (c) 2012-2013 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Wladimir J. van der Laan <laanwj@gmail.com> | |||
*/ | |||
#ifndef H_ETNAVIV_RS | |||
#define H_ETNAVIV_RS | |||
#include "etnaviv_context.h" | |||
#include <stdint.h> | |||
struct rs_state { | |||
uint8_t downsample_x : 1; /* Downsample in x direction */ | |||
uint8_t downsample_y : 1; /* Downsample in y direction */ | |||
uint8_t source_format; /* RS_FORMAT_XXX */ | |||
uint8_t source_tiling; /* ETNA_LAYOUT_XXX */ | |||
uint8_t dest_tiling; /* ETNA_LAYOUT_XXX */ | |||
uint8_t dest_format; /* RS_FORMAT_XXX */ | |||
uint8_t swap_rb; | |||
uint8_t flip; | |||
struct etna_bo *source; | |||
uint32_t source_offset; | |||
uint32_t source_stride; | |||
uint32_t source_padded_height; /* total padded height */ | |||
struct etna_bo *dest; | |||
uint32_t dest_offset; | |||
uint32_t dest_stride; | |||
uint32_t dest_padded_height; /* total padded height */ | |||
uint16_t width; /* source width */ | |||
uint16_t height; /* source height */ | |||
uint32_t dither[2]; | |||
uint32_t clear_bits; | |||
uint32_t clear_mode; /* VIVS_RS_CLEAR_CONTROL_MODE_XXX */ | |||
uint32_t clear_value[4]; | |||
uint8_t aa; | |||
uint8_t endian_mode; /* ENDIAN_MODE_XXX */ | |||
}; | |||
/* treat this as opaque structure */ | |||
struct compiled_rs_state { | |||
uint32_t RS_CONFIG; | |||
uint32_t RS_SOURCE_STRIDE; | |||
uint32_t RS_DEST_STRIDE; | |||
uint32_t RS_WINDOW_SIZE; | |||
uint32_t RS_DITHER[2]; | |||
uint32_t RS_CLEAR_CONTROL; | |||
uint32_t RS_FILL_VALUE[4]; | |||
uint32_t RS_EXTRA_CONFIG; | |||
uint32_t RS_PIPE_OFFSET[2]; | |||
struct etna_reloc source[2]; | |||
struct etna_reloc dest[2]; | |||
}; | |||
/* compile RS state struct */ | |||
void | |||
etna_compile_rs_state(struct etna_context *ctx, struct compiled_rs_state *cs, | |||
const struct rs_state *rs); | |||
/* modify the clear bits value in the compiled RS state */ | |||
void | |||
etna_modify_rs_clearbits(struct compiled_rs_state *cs, uint32_t clear_bits); | |||
#endif |
@@ -0,0 +1,813 @@ | |||
/* | |||
* Copyright (c) 2012-2015 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Wladimir J. van der Laan <laanwj@gmail.com> | |||
* Christian Gmeiner <christian.gmeiner@gmail.com> | |||
*/ | |||
#include "etnaviv_screen.h" | |||
#include "hw/common.xml.h" | |||
#include "etnaviv_compiler.h" | |||
#include "etnaviv_context.h" | |||
#include "etnaviv_debug.h" | |||
#include "etnaviv_fence.h" | |||
#include "etnaviv_format.h" | |||
#include "etnaviv_query.h" | |||
#include "etnaviv_resource.h" | |||
#include "etnaviv_translate.h" | |||
#include "os/os_time.h" | |||
#include "util/u_math.h" | |||
#include "util/u_memory.h" | |||
#include "util/u_string.h" | |||
#include "state_tracker/drm_driver.h" | |||
static const struct debug_named_value debug_options[] = { | |||
{"dbg_msgs", ETNA_DBG_MSGS, "Print debug messages"}, | |||
{"frame_msgs", ETNA_DBG_FRAME_MSGS, "Print frame messages"}, | |||
{"resource_msgs", ETNA_DBG_RESOURCE_MSGS, "Print resource messages"}, | |||
{"compiler_msgs", ETNA_DBG_COMPILER_MSGS, "Print compiler messages"}, | |||
{"linker_msgs", ETNA_DBG_LINKER_MSGS, "Print linker messages"}, | |||
{"dump_shaders", ETNA_DBG_DUMP_SHADERS, "Dump shaders"}, | |||
{"no_ts", ETNA_DBG_NO_TS, "Disable TS"}, | |||
{"no_autodisable", ETNA_DBG_NO_AUTODISABLE, "Disable autodisable"}, | |||
{"no_supertile", ETNA_DBG_NO_SUPERTILE, "Disable supertiles"}, | |||
{"no_early_z", ETNA_DBG_NO_EARLY_Z, "Disable early z"}, | |||
{"cflush_all", ETNA_DBG_CFLUSH_ALL, "Flush every cash before state update"}, | |||
{"msaa2x", ETNA_DBG_MSAA_2X, "Force 2x msaa"}, | |||
{"msaa4x", ETNA_DBG_MSAA_4X, "Force 4x msaa"}, | |||
{"flush_all", ETNA_DBG_FLUSH_ALL, "Flush after every rendered primitive"}, | |||
{"zero", ETNA_DBG_ZERO, "Zero all resources after allocation"}, | |||
{"draw_stall", ETNA_DBG_DRAW_STALL, "Stall FE/PE after each rendered primitive"}, | |||
DEBUG_NAMED_VALUE_END | |||
}; | |||
DEBUG_GET_ONCE_FLAGS_OPTION(etna_mesa_debug, "ETNA_MESA_DEBUG", debug_options, 0) | |||
int etna_mesa_debug = 0; | |||
static void | |||
etna_screen_destroy(struct pipe_screen *pscreen) | |||
{ | |||
struct etna_screen *screen = etna_screen(pscreen); | |||
if (screen->pipe) | |||
etna_pipe_del(screen->pipe); | |||
if (screen->gpu) | |||
etna_gpu_del(screen->gpu); | |||
if (screen->ro) | |||
FREE(screen->ro); | |||
if (screen->dev) | |||
etna_device_del(screen->dev); | |||
FREE(screen); | |||
} | |||
static const char * | |||
etna_screen_get_name(struct pipe_screen *pscreen) | |||
{ | |||
struct etna_screen *priv = etna_screen(pscreen); | |||
static char buffer[128]; | |||
util_snprintf(buffer, sizeof(buffer), "Vivante GC%x rev %04x", priv->model, | |||
priv->revision); | |||
return buffer; | |||
} | |||
static const char * | |||
etna_screen_get_vendor(struct pipe_screen *pscreen) | |||
{ | |||
return "etnaviv"; | |||
} | |||
static const char * | |||
etna_screen_get_device_vendor(struct pipe_screen *pscreen) | |||
{ | |||
return "Vivante"; | |||
} | |||
static int | |||
etna_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) | |||
{ | |||
struct etna_screen *screen = etna_screen(pscreen); | |||
switch (param) { | |||
/* Supported features (boolean caps). */ | |||
case PIPE_CAP_TWO_SIDED_STENCIL: | |||
case PIPE_CAP_ANISOTROPIC_FILTER: | |||
case PIPE_CAP_POINT_SPRITE: | |||
case PIPE_CAP_TEXTURE_SHADOW_MAP: | |||
case PIPE_CAP_BLEND_EQUATION_SEPARATE: | |||
case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: | |||
case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: | |||
case PIPE_CAP_SM3: | |||
case PIPE_CAP_TEXTURE_BARRIER: | |||
case PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION: | |||
case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY: | |||
case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY: | |||
case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY: | |||
case PIPE_CAP_USER_CONSTANT_BUFFERS: | |||
case PIPE_CAP_TGSI_TEXCOORD: | |||
case PIPE_CAP_VERTEX_COLOR_UNCLAMPED: | |||
return 1; | |||
/* Memory */ | |||
case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT: | |||
return 256; | |||
case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT: | |||
return 4; /* XXX could easily be supported */ | |||
case PIPE_CAP_GLSL_FEATURE_LEVEL: | |||
return 120; | |||
case PIPE_CAP_NPOT_TEXTURES: | |||
return true; /* VIV_FEATURE(priv->dev, chipMinorFeatures1, | |||
NON_POWER_OF_TWO); */ | |||
case PIPE_CAP_PRIMITIVE_RESTART: | |||
return VIV_FEATURE(screen, chipMinorFeatures1, HALTI0); | |||
case PIPE_CAP_ENDIANNESS: | |||
return PIPE_ENDIAN_LITTLE; /* on most Viv hw this is configurable (feature | |||
ENDIANNESS_CONFIG) */ | |||
/* Unsupported features. */ | |||
case PIPE_CAP_SEAMLESS_CUBE_MAP: | |||
case PIPE_CAP_TEXTURE_SWIZZLE: /* XXX supported on gc2000 */ | |||
case PIPE_CAP_COMPUTE: /* XXX supported on gc2000 */ | |||
case PIPE_CAP_MIXED_COLORBUFFER_FORMATS: /* only one colorbuffer supported, so mixing makes no sense */ | |||
case PIPE_CAP_CONDITIONAL_RENDER: /* no occlusion queries */ | |||
case PIPE_CAP_TGSI_INSTANCEID: /* no idea, really */ | |||
case PIPE_CAP_START_INSTANCE: /* instancing not supported AFAIK */ | |||
case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR: /* instancing not supported AFAIK */ | |||
case PIPE_CAP_SHADER_STENCIL_EXPORT: /* Fragment shader cannot export stencil value */ | |||
case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS: /* no dual-source supported */ | |||
case PIPE_CAP_TEXTURE_MULTISAMPLE: /* no texture multisample */ | |||
case PIPE_CAP_TEXTURE_MIRROR_CLAMP: /* only mirrored repeat */ | |||
case PIPE_CAP_INDEP_BLEND_ENABLE: | |||
case PIPE_CAP_INDEP_BLEND_FUNC: | |||
case PIPE_CAP_DEPTH_CLIP_DISABLE: | |||
case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE: | |||
case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: | |||
case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: | |||
case PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS: /* Don't skip strict max uniform limit check */ | |||
case PIPE_CAP_FRAGMENT_COLOR_CLAMPED: | |||
case PIPE_CAP_VERTEX_COLOR_CLAMPED: | |||
case PIPE_CAP_USER_VERTEX_BUFFERS: | |||
case PIPE_CAP_USER_INDEX_BUFFERS: | |||
case PIPE_CAP_TEXTURE_BUFFER_OBJECTS: | |||
case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT: | |||
case PIPE_CAP_BUFFER_SAMPLER_VIEW_RGBA_ONLY: | |||
case PIPE_CAP_MIXED_FRAMEBUFFER_SIZES: /* TODO: test me out with piglit */ | |||
case PIPE_CAP_TGSI_VS_LAYER_VIEWPORT: | |||
case PIPE_CAP_MAX_TEXTURE_GATHER_COMPONENTS: | |||
case PIPE_CAP_TEXTURE_GATHER_SM5: | |||
case PIPE_CAP_BUFFER_MAP_PERSISTENT_COHERENT: | |||
case PIPE_CAP_FAKE_SW_MSAA: | |||
case PIPE_CAP_TEXTURE_QUERY_LOD: | |||
case PIPE_CAP_SAMPLE_SHADING: | |||
case PIPE_CAP_TEXTURE_GATHER_OFFSETS: | |||
case PIPE_CAP_TGSI_VS_WINDOW_SPACE_POSITION: | |||
case PIPE_CAP_DRAW_INDIRECT: | |||
case PIPE_CAP_TGSI_FS_FINE_DERIVATIVE: | |||
case PIPE_CAP_CONDITIONAL_RENDER_INVERTED: | |||
case PIPE_CAP_SAMPLER_VIEW_TARGET: | |||
case PIPE_CAP_CLIP_HALFZ: | |||
case PIPE_CAP_VERTEXID_NOBASE: | |||
case PIPE_CAP_POLYGON_OFFSET_CLAMP: | |||
case PIPE_CAP_MULTISAMPLE_Z_RESOLVE: | |||
case PIPE_CAP_RESOURCE_FROM_USER_MEMORY: | |||
case PIPE_CAP_DEVICE_RESET_STATUS_QUERY: | |||
case PIPE_CAP_MAX_SHADER_PATCH_VARYINGS: | |||
case PIPE_CAP_TEXTURE_FLOAT_LINEAR: | |||
case PIPE_CAP_TEXTURE_HALF_FLOAT_LINEAR: | |||
case PIPE_CAP_DEPTH_BOUNDS_TEST: | |||
case PIPE_CAP_TGSI_TXQS: | |||
case PIPE_CAP_FORCE_PERSAMPLE_INTERP: | |||
case PIPE_CAP_SHAREABLE_SHADERS: | |||
case PIPE_CAP_COPY_BETWEEN_COMPRESSED_AND_PLAIN_FORMATS: | |||
case PIPE_CAP_CLEAR_TEXTURE: | |||
case PIPE_CAP_DRAW_PARAMETERS: | |||
case PIPE_CAP_TGSI_PACK_HALF_FLOAT: | |||
case PIPE_CAP_MULTI_DRAW_INDIRECT: | |||
case PIPE_CAP_MULTI_DRAW_INDIRECT_PARAMS: | |||
case PIPE_CAP_TGSI_FS_POSITION_IS_SYSVAL: | |||
case PIPE_CAP_TGSI_FS_FACE_IS_INTEGER_SYSVAL: | |||
case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT: | |||
case PIPE_CAP_INVALIDATE_BUFFER: | |||
case PIPE_CAP_GENERATE_MIPMAP: | |||
case PIPE_CAP_STRING_MARKER: | |||
case PIPE_CAP_SURFACE_REINTERPRET_BLOCKS: | |||
case PIPE_CAP_QUERY_BUFFER_OBJECT: | |||
case PIPE_CAP_QUERY_MEMORY_INFO: | |||
case PIPE_CAP_FRAMEBUFFER_NO_ATTACHMENT: | |||
case PIPE_CAP_ROBUST_BUFFER_ACCESS_BEHAVIOR: | |||
case PIPE_CAP_CULL_DISTANCE: | |||
case PIPE_CAP_PRIMITIVE_RESTART_FOR_PATCHES: | |||
case PIPE_CAP_TGSI_VOTE: | |||
case PIPE_CAP_MAX_WINDOW_RECTANGLES: | |||
case PIPE_CAP_POLYGON_OFFSET_UNITS_UNSCALED: | |||
case PIPE_CAP_VIEWPORT_SUBPIXEL_BITS: | |||
case PIPE_CAP_MIXED_COLOR_DEPTH_BITS: | |||
case PIPE_CAP_TGSI_ARRAY_COMPONENTS: | |||
case PIPE_CAP_STREAM_OUTPUT_INTERLEAVE_BUFFERS: | |||
case PIPE_CAP_TGSI_CAN_READ_OUTPUTS: | |||
case PIPE_CAP_NATIVE_FENCE_FD: | |||
case PIPE_CAP_GLSL_OPTIMIZE_CONSERVATIVELY: | |||
return 0; | |||
/* Stream output. */ | |||
case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS: | |||
case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME: | |||
case PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS: | |||
case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS: | |||
return 0; | |||
/* Geometry shader output, unsupported. */ | |||
case PIPE_CAP_MAX_GEOMETRY_OUTPUT_VERTICES: | |||
case PIPE_CAP_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS: | |||
case PIPE_CAP_MAX_VERTEX_STREAMS: | |||
return 0; | |||
case PIPE_CAP_MAX_VERTEX_ATTRIB_STRIDE: | |||
return 128; | |||
/* Texturing. */ | |||
case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: | |||
case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: | |||
{ | |||
int log2_max_tex_size = util_last_bit(screen->specs.max_texture_size); | |||
assert(log2_max_tex_size > 0); | |||
return log2_max_tex_size; | |||
} | |||
case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: /* 3D textures not supported - fake it */ | |||
return 5; | |||
case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS: | |||
return 0; | |||
case PIPE_CAP_CUBE_MAP_ARRAY: | |||
return 0; | |||
case PIPE_CAP_MIN_TEXTURE_GATHER_OFFSET: | |||
case PIPE_CAP_MIN_TEXEL_OFFSET: | |||
return -8; | |||
case PIPE_CAP_MAX_TEXTURE_GATHER_OFFSET: | |||
case PIPE_CAP_MAX_TEXEL_OFFSET: | |||
return 7; | |||
case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK: | |||
return 0; | |||
case PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE: | |||
return 65536; | |||
/* Render targets. */ | |||
case PIPE_CAP_MAX_RENDER_TARGETS: | |||
return 1; | |||
/* Viewports and scissors. */ | |||
case PIPE_CAP_MAX_VIEWPORTS: | |||
return 1; | |||
/* Timer queries. */ | |||
case PIPE_CAP_QUERY_TIME_ELAPSED: | |||
case PIPE_CAP_OCCLUSION_QUERY: | |||
return 0; | |||
case PIPE_CAP_QUERY_TIMESTAMP: | |||
return 1; | |||
case PIPE_CAP_QUERY_PIPELINE_STATISTICS: | |||
return 0; | |||
/* Preferences */ | |||
case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER: | |||
return 0; | |||
case PIPE_CAP_PCI_GROUP: | |||
case PIPE_CAP_PCI_BUS: | |||
case PIPE_CAP_PCI_DEVICE: | |||
case PIPE_CAP_PCI_FUNCTION: | |||
return 0; | |||
case PIPE_CAP_VENDOR_ID: | |||
case PIPE_CAP_DEVICE_ID: | |||
return 0xFFFFFFFF; | |||
case PIPE_CAP_ACCELERATED: | |||
return 1; | |||
case PIPE_CAP_VIDEO_MEMORY: | |||
return 0; | |||
case PIPE_CAP_UMA: | |||
return 1; | |||
} | |||
debug_printf("unknown param %d", param); | |||
return 0; | |||
} | |||
static float | |||
etna_screen_get_paramf(struct pipe_screen *pscreen, enum pipe_capf param) | |||
{ | |||
switch (param) { | |||
case PIPE_CAPF_MAX_LINE_WIDTH: | |||
case PIPE_CAPF_MAX_LINE_WIDTH_AA: | |||
case PIPE_CAPF_MAX_POINT_WIDTH: | |||
case PIPE_CAPF_MAX_POINT_WIDTH_AA: | |||
return 8192.0f; | |||
case PIPE_CAPF_MAX_TEXTURE_ANISOTROPY: | |||
return 16.0f; | |||
case PIPE_CAPF_MAX_TEXTURE_LOD_BIAS: | |||
return 16.0f; | |||
case PIPE_CAPF_GUARD_BAND_LEFT: | |||
case PIPE_CAPF_GUARD_BAND_TOP: | |||
case PIPE_CAPF_GUARD_BAND_RIGHT: | |||
case PIPE_CAPF_GUARD_BAND_BOTTOM: | |||
return 0.0f; | |||
} | |||
debug_printf("unknown paramf %d", param); | |||
return 0; | |||
} | |||
static int | |||
etna_screen_get_shader_param(struct pipe_screen *pscreen, unsigned shader, | |||
enum pipe_shader_cap param) | |||
{ | |||
struct etna_screen *screen = etna_screen(pscreen); | |||
switch (shader) { | |||
case PIPE_SHADER_FRAGMENT: | |||
case PIPE_SHADER_VERTEX: | |||
break; | |||
case PIPE_SHADER_COMPUTE: | |||
case PIPE_SHADER_GEOMETRY: | |||
case PIPE_SHADER_TESS_CTRL: | |||
case PIPE_SHADER_TESS_EVAL: | |||
return 0; | |||
default: | |||
DBG("unknown shader type %d", shader); | |||
return 0; | |||
} | |||
switch (param) { | |||
case PIPE_SHADER_CAP_MAX_INSTRUCTIONS: | |||
case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS: | |||
case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS: | |||
case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS: | |||
return ETNA_MAX_TOKENS; | |||
case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH: | |||
return ETNA_MAX_DEPTH; /* XXX */ | |||
case PIPE_SHADER_CAP_MAX_INPUTS: | |||
/* Maximum number of inputs for the vertex shader is the number | |||
* of vertex elements - each element defines one vertex shader | |||
* input register. For the fragment shader, this is the number | |||
* of varyings. */ | |||
return shader == PIPE_SHADER_FRAGMENT ? screen->specs.max_varyings | |||
: screen->specs.vertex_max_elements; | |||
case PIPE_SHADER_CAP_MAX_OUTPUTS: | |||
return 16; /* see VIVS_VS_OUTPUT */ | |||
case PIPE_SHADER_CAP_MAX_TEMPS: | |||
return 64; /* Max native temporaries. */ | |||
case PIPE_SHADER_CAP_MAX_CONST_BUFFERS: | |||
return 1; | |||
case PIPE_SHADER_CAP_MAX_PREDS: | |||
return 0; /* nothing uses this */ | |||
case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED: | |||
return 1; | |||
case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR: | |||
case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR: | |||
case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR: | |||
case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR: | |||
return 1; | |||
case PIPE_SHADER_CAP_SUBROUTINES: | |||
return 0; | |||
case PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED: | |||
return VIV_FEATURE(screen, chipMinorFeatures0, HAS_SQRT_TRIG); | |||
case PIPE_SHADER_CAP_INTEGERS: | |||
return 0; | |||
case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS: | |||
case PIPE_SHADER_CAP_MAX_SAMPLER_VIEWS: | |||
return shader == PIPE_SHADER_FRAGMENT | |||
? screen->specs.fragment_sampler_count | |||
: screen->specs.vertex_sampler_count; | |||
case PIPE_SHADER_CAP_PREFERRED_IR: | |||
return PIPE_SHADER_IR_TGSI; | |||
case PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE: | |||
return 4096; | |||
case PIPE_SHADER_CAP_DOUBLES: | |||
case PIPE_SHADER_CAP_TGSI_DROUND_SUPPORTED: | |||
case PIPE_SHADER_CAP_TGSI_DFRACEXP_DLDEXP_SUPPORTED: | |||
case PIPE_SHADER_CAP_TGSI_FMA_SUPPORTED: | |||
case PIPE_SHADER_CAP_TGSI_ANY_INOUT_DECL_RANGE: | |||
return false; | |||
case PIPE_SHADER_CAP_SUPPORTED_IRS: | |||
return 0; | |||
case PIPE_SHADER_CAP_MAX_UNROLL_ITERATIONS_HINT: | |||
return 32; | |||
case PIPE_SHADER_CAP_MAX_SHADER_BUFFERS: | |||
case PIPE_SHADER_CAP_MAX_SHADER_IMAGES: | |||
case PIPE_SHADER_CAP_LOWER_IF_THRESHOLD: | |||
return 0; | |||
} | |||
debug_printf("unknown shader param %d", param); | |||
return 0; | |||
} | |||
static uint64_t | |||
etna_screen_get_timestamp(struct pipe_screen *pscreen) | |||
{ | |||
return os_time_get_nano(); | |||
} | |||
static bool | |||
gpu_supports_texure_format(struct etna_screen *screen, uint32_t fmt) | |||
{ | |||
if (fmt == TEXTURE_FORMAT_ETC1) | |||
return VIV_FEATURE(screen, chipFeatures, ETC1_TEXTURE_COMPRESSION); | |||
if (fmt >= TEXTURE_FORMAT_DXT1 && fmt <= TEXTURE_FORMAT_DXT4_DXT5) | |||
return VIV_FEATURE(screen, chipFeatures, DXT_TEXTURE_COMPRESSION); | |||
return true; | |||
} | |||
static boolean | |||
etna_screen_is_format_supported(struct pipe_screen *pscreen, | |||
enum pipe_format format, | |||
enum pipe_texture_target target, | |||
unsigned sample_count, unsigned usage) | |||
{ | |||
struct etna_screen *screen = etna_screen(pscreen); | |||
unsigned allowed = 0; | |||
if (target != PIPE_BUFFER && | |||
target != PIPE_TEXTURE_1D && | |||
target != PIPE_TEXTURE_2D && | |||
target != PIPE_TEXTURE_3D && | |||
target != PIPE_TEXTURE_CUBE && | |||
target != PIPE_TEXTURE_RECT) | |||
return FALSE; | |||
if (usage & PIPE_BIND_RENDER_TARGET) { | |||
/* if render target, must be RS-supported format */ | |||
if (translate_rs_format(format) != ETNA_NO_MATCH) { | |||
/* Validate MSAA; number of samples must be allowed, and render target | |||
* must have MSAA'able format. */ | |||
if (sample_count > 1) { | |||
if (translate_samples_to_xyscale(sample_count, NULL, NULL, NULL) && | |||
translate_msaa_format(format) != ETNA_NO_MATCH) { | |||
allowed |= PIPE_BIND_RENDER_TARGET; | |||
} | |||
} else { | |||
allowed |= PIPE_BIND_RENDER_TARGET; | |||
} | |||
} | |||
} | |||
if (usage & PIPE_BIND_DEPTH_STENCIL) { | |||
if (translate_depth_format(format) != ETNA_NO_MATCH) | |||
allowed |= PIPE_BIND_DEPTH_STENCIL; | |||
} | |||
if (usage & PIPE_BIND_SAMPLER_VIEW) { | |||
uint32_t fmt = translate_texture_format(format); | |||
if (!gpu_supports_texure_format(screen, fmt)) | |||
fmt = ETNA_NO_MATCH; | |||
if (sample_count < 2 && fmt != ETNA_NO_MATCH) | |||
allowed |= PIPE_BIND_SAMPLER_VIEW; | |||
} | |||
if (usage & PIPE_BIND_VERTEX_BUFFER) { | |||
if (translate_vertex_format_type(format) != ETNA_NO_MATCH) | |||
allowed |= PIPE_BIND_VERTEX_BUFFER; | |||
} | |||
if (usage & PIPE_BIND_INDEX_BUFFER) { | |||
/* must be supported index format */ | |||
if (format == PIPE_FORMAT_I8_UINT || format == PIPE_FORMAT_I16_UINT || | |||
(format == PIPE_FORMAT_I32_UINT && | |||
VIV_FEATURE(screen, chipFeatures, 32_BIT_INDICES))) { | |||
allowed |= PIPE_BIND_INDEX_BUFFER; | |||
} | |||
} | |||
/* Always allowed */ | |||
allowed |= | |||
usage & (PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_SCANOUT | PIPE_BIND_SHARED); | |||
if (usage != allowed) { | |||
DBG("not supported: format=%s, target=%d, sample_count=%d, " | |||
"usage=%x, allowed=%x", | |||
util_format_name(format), target, sample_count, usage, allowed); | |||
} | |||
return usage == allowed; | |||
} | |||
static boolean | |||
etna_get_specs(struct etna_screen *screen) | |||
{ | |||
uint64_t val; | |||
uint32_t instruction_count; | |||
if (etna_gpu_get_param(screen->gpu, ETNA_GPU_INSTRUCTION_COUNT, &val)) { | |||
DBG("could not get ETNA_GPU_INSTRUCTION_COUNT"); | |||
goto fail; | |||
} | |||
instruction_count = val; | |||
if (etna_gpu_get_param(screen->gpu, ETNA_GPU_VERTEX_OUTPUT_BUFFER_SIZE, | |||
&val)) { | |||
DBG("could not get ETNA_GPU_VERTEX_OUTPUT_BUFFER_SIZE"); | |||
goto fail; | |||
} | |||
screen->specs.vertex_output_buffer_size = val; | |||
if (etna_gpu_get_param(screen->gpu, ETNA_GPU_VERTEX_CACHE_SIZE, &val)) { | |||
DBG("could not get ETNA_GPU_VERTEX_CACHE_SIZE"); | |||
goto fail; | |||
} | |||
screen->specs.vertex_cache_size = val; | |||
if (etna_gpu_get_param(screen->gpu, ETNA_GPU_SHADER_CORE_COUNT, &val)) { | |||
DBG("could not get ETNA_GPU_SHADER_CORE_COUNT"); | |||
goto fail; | |||
} | |||
screen->specs.shader_core_count = val; | |||
if (etna_gpu_get_param(screen->gpu, ETNA_GPU_STREAM_COUNT, &val)) { | |||
DBG("could not get ETNA_GPU_STREAM_COUNT"); | |||
goto fail; | |||
} | |||
screen->specs.stream_count = val; | |||
if (etna_gpu_get_param(screen->gpu, ETNA_GPU_REGISTER_MAX, &val)) { | |||
DBG("could not get ETNA_GPU_REGISTER_MAX"); | |||
goto fail; | |||
} | |||
screen->specs.max_registers = val; | |||
if (etna_gpu_get_param(screen->gpu, ETNA_GPU_PIXEL_PIPES, &val)) { | |||
DBG("could not get ETNA_GPU_PIXEL_PIPES"); | |||
goto fail; | |||
} | |||
if (val < 1 && val > ETNA_MAX_PIXELPIPES) { | |||
if (val == 0) { | |||
fprintf(stderr, "Warning: zero pixel pipes (update kernel?)\n"); | |||
val = 1; | |||
} else { | |||
fprintf(stderr, "Error: bad pixel pipes value %u\n", | |||
(unsigned int)val); | |||
goto fail; | |||
} | |||
} | |||
screen->specs.pixel_pipes = val; | |||
if (etna_gpu_get_param(screen->gpu, ETNA_GPU_NUM_CONSTANTS, &val)) { | |||
DBG("could not get %s", "ETNA_GPU_NUM_CONSTANTS"); | |||
goto fail; | |||
} | |||
if (val == 0) { | |||
fprintf(stderr, "Warning: zero num constants (update kernel?)\n"); | |||
val = 168; | |||
} | |||
screen->specs.num_constants = val; | |||
screen->specs.can_supertile = | |||
VIV_FEATURE(screen, chipMinorFeatures0, SUPER_TILED); | |||
screen->specs.bits_per_tile = | |||
VIV_FEATURE(screen, chipMinorFeatures0, 2BITPERTILE) ? 2 : 4; | |||
screen->specs.ts_clear_value = | |||
VIV_FEATURE(screen, chipMinorFeatures0, 2BITPERTILE) ? 0x55555555 | |||
: 0x11111111; | |||
/* vertex and fragment samplers live in one address space */ | |||
screen->specs.vertex_sampler_offset = 8; | |||
screen->specs.fragment_sampler_count = 8; | |||
screen->specs.vertex_sampler_count = 4; | |||
screen->specs.vs_need_z_div = | |||
screen->model < 0x1000 && screen->model != 0x880; | |||
screen->specs.has_sin_cos_sqrt = | |||
VIV_FEATURE(screen, chipMinorFeatures0, HAS_SQRT_TRIG); | |||
screen->specs.has_sign_floor_ceil = | |||
VIV_FEATURE(screen, chipMinorFeatures0, HAS_SIGN_FLOOR_CEIL); | |||
screen->specs.has_shader_range_registers = | |||
screen->model >= 0x1000 || screen->model == 0x880; | |||
screen->specs.npot_tex_any_wrap = | |||
VIV_FEATURE(screen, chipMinorFeatures1, NON_POWER_OF_TWO); | |||
if (instruction_count > 256) { /* unified instruction memory? */ | |||
screen->specs.vs_offset = 0xC000; | |||
screen->specs.ps_offset = 0xD000; /* like vivante driver */ | |||
screen->specs.max_instructions = 256; | |||
} else { | |||
screen->specs.vs_offset = 0x4000; | |||
screen->specs.ps_offset = 0x6000; | |||
screen->specs.max_instructions = instruction_count / 2; | |||
} | |||
if (VIV_FEATURE(screen, chipMinorFeatures1, HALTI0)) { | |||
screen->specs.max_varyings = 12; | |||
screen->specs.vertex_max_elements = 16; | |||
} else { | |||
screen->specs.max_varyings = 8; | |||
/* Etna_viv documentation seems confused over the correct value | |||
* here so choose the lower to be safe: HALTI0 says 16 i.s.o. | |||
* 10, but VERTEX_ELEMENT_CONFIG register says 16 i.s.o. 12. */ | |||
screen->specs.vertex_max_elements = 10; | |||
} | |||
/* Etna_viv documentation does not indicate where varyings above 8 are | |||
* stored. Moreover, if we are passed more than 8 varyings, we will | |||
* walk off the end of some arrays. Limit the maximum number of varyings. */ | |||
if (screen->specs.max_varyings > ETNA_NUM_VARYINGS) | |||
screen->specs.max_varyings = ETNA_NUM_VARYINGS; | |||
/* from QueryShaderCaps in kernel driver */ | |||
if (screen->model < chipModel_GC4000) { | |||
screen->specs.max_vs_uniforms = 168; | |||
screen->specs.max_ps_uniforms = 64; | |||
} else { | |||
screen->specs.max_vs_uniforms = 256; | |||
screen->specs.max_ps_uniforms = 256; | |||
} | |||
screen->specs.max_texture_size = | |||
VIV_FEATURE(screen, chipMinorFeatures0, TEXTURE_8K) ? 8192 : 2048; | |||
screen->specs.max_rendertarget_size = | |||
VIV_FEATURE(screen, chipMinorFeatures0, RENDERTARGET_8K) ? 8192 : 2048; | |||
return true; | |||
fail: | |||
return false; | |||
} | |||
boolean | |||
etna_screen_bo_get_handle(struct pipe_screen *pscreen, struct etna_bo *bo, | |||
unsigned stride, struct winsys_handle *whandle) | |||
{ | |||
whandle->stride = stride; | |||
if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) { | |||
return etna_bo_get_name(bo, &whandle->handle) == 0; | |||
} else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) { | |||
whandle->handle = etna_bo_handle(bo); | |||
return TRUE; | |||
} else if (whandle->type == DRM_API_HANDLE_TYPE_FD) { | |||
whandle->handle = etna_bo_dmabuf(bo); | |||
return TRUE; | |||
} else { | |||
return FALSE; | |||
} | |||
} | |||
struct etna_bo * | |||
etna_screen_bo_from_handle(struct pipe_screen *pscreen, | |||
struct winsys_handle *whandle, unsigned *out_stride) | |||
{ | |||
struct etna_screen *screen = etna_screen(pscreen); | |||
struct etna_bo *bo; | |||
if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) { | |||
bo = etna_bo_from_name(screen->dev, whandle->handle); | |||
} else if (whandle->type == DRM_API_HANDLE_TYPE_FD) { | |||
bo = etna_bo_from_dmabuf(screen->dev, whandle->handle); | |||
} else { | |||
DBG("Attempt to import unsupported handle type %d", whandle->type); | |||
return NULL; | |||
} | |||
if (!bo) { | |||
DBG("ref name 0x%08x failed", whandle->handle); | |||
return NULL; | |||
} | |||
*out_stride = whandle->stride; | |||
return bo; | |||
} | |||
struct pipe_screen * | |||
etna_screen_create(struct etna_device *dev, struct etna_gpu *gpu, | |||
struct renderonly *ro) | |||
{ | |||
struct etna_screen *screen = CALLOC_STRUCT(etna_screen); | |||
struct pipe_screen *pscreen; | |||
uint64_t val; | |||
if (!screen) | |||
return NULL; | |||
pscreen = &screen->base; | |||
screen->dev = dev; | |||
screen->gpu = gpu; | |||
screen->ro = renderonly_dup(ro); | |||
if (!screen->ro) { | |||
DBG("could not create renderonly object"); | |||
goto fail; | |||
} | |||
etna_mesa_debug = debug_get_option_etna_mesa_debug(); | |||
/* FIXME: Disable tile status for stability at the moment */ | |||
etna_mesa_debug |= ETNA_DBG_NO_TS; | |||
screen->pipe = etna_pipe_new(gpu, ETNA_PIPE_3D); | |||
if (!screen->pipe) { | |||
DBG("could not create 3d pipe"); | |||
goto fail; | |||
} | |||
if (etna_gpu_get_param(screen->gpu, ETNA_GPU_MODEL, &val)) { | |||
DBG("could not get ETNA_GPU_MODEL"); | |||
goto fail; | |||
} | |||
screen->model = val; | |||
if (etna_gpu_get_param(screen->gpu, ETNA_GPU_REVISION, &val)) { | |||
DBG("could not get ETNA_GPU_REVISION"); | |||
goto fail; | |||
} | |||
screen->revision = val; | |||
if (etna_gpu_get_param(screen->gpu, ETNA_GPU_FEATURES_0, &val)) { | |||
DBG("could not get ETNA_GPU_FEATURES_0"); | |||
goto fail; | |||
} | |||
screen->features[0] = val; | |||
if (etna_gpu_get_param(screen->gpu, ETNA_GPU_FEATURES_1, &val)) { | |||
DBG("could not get ETNA_GPU_FEATURES_1"); | |||
goto fail; | |||
} | |||
screen->features[1] = val; | |||
if (etna_gpu_get_param(screen->gpu, ETNA_GPU_FEATURES_2, &val)) { | |||
DBG("could not get ETNA_GPU_FEATURES_2"); | |||
goto fail; | |||
} | |||
screen->features[2] = val; | |||
if (etna_gpu_get_param(screen->gpu, ETNA_GPU_FEATURES_3, &val)) { | |||
DBG("could not get ETNA_GPU_FEATURES_3"); | |||
goto fail; | |||
} | |||
screen->features[3] = val; | |||
if (etna_gpu_get_param(screen->gpu, ETNA_GPU_FEATURES_4, &val)) { | |||
DBG("could not get ETNA_GPU_FEATURES_4"); | |||
goto fail; | |||
} | |||
screen->features[4] = val; | |||
if (!etna_get_specs(screen)) | |||
goto fail; | |||
pscreen->destroy = etna_screen_destroy; | |||
pscreen->get_param = etna_screen_get_param; | |||
pscreen->get_paramf = etna_screen_get_paramf; | |||
pscreen->get_shader_param = etna_screen_get_shader_param; | |||
pscreen->get_name = etna_screen_get_name; | |||
pscreen->get_vendor = etna_screen_get_vendor; | |||
pscreen->get_device_vendor = etna_screen_get_device_vendor; | |||
pscreen->get_timestamp = etna_screen_get_timestamp; | |||
pscreen->context_create = etna_context_create; | |||
pscreen->is_format_supported = etna_screen_is_format_supported; | |||
etna_fence_screen_init(pscreen); | |||
etna_query_screen_init(pscreen); | |||
etna_resource_screen_init(pscreen); | |||
slab_create_parent(&screen->transfer_pool, sizeof(struct etna_transfer), 16); | |||
return pscreen; | |||
fail: | |||
etna_screen_destroy(pscreen); | |||
return NULL; | |||
} |
@@ -0,0 +1,95 @@ | |||
/* | |||
* Copyright (c) 2012-2015 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Wladimir J. van der Laan <laanwj@gmail.com> | |||
* Christian Gmeiner <christian.gmeiner@gmail.com> | |||
*/ | |||
#ifndef H_ETNAVIV_SCREEN | |||
#define H_ETNAVIV_SCREEN | |||
#include "etnaviv_internal.h" | |||
#include "os/os_thread.h" | |||
#include "pipe/p_screen.h" | |||
#include "renderonly/renderonly.h" | |||
#include "util/slab.h" | |||
struct etna_bo; | |||
/* Enum with indices for each of the feature words */ | |||
enum viv_features_word { | |||
viv_chipFeatures = 0, | |||
viv_chipMinorFeatures0 = 1, | |||
viv_chipMinorFeatures1 = 2, | |||
viv_chipMinorFeatures2 = 3, | |||
viv_chipMinorFeatures3 = 4, | |||
VIV_FEATURES_WORD_COUNT /* Must be last */ | |||
}; | |||
/** Convenience macro to probe features from state.xml.h: | |||
* VIV_FEATURE(chipFeatures, FAST_CLEAR) | |||
* VIV_FEATURE(chipMinorFeatures1, AUTO_DISABLE) | |||
*/ | |||
#define VIV_FEATURE(screen, word, feature) \ | |||
((screen->features[viv_ ## word] & (word ## _ ## feature)) != 0) | |||
struct etna_screen { | |||
struct pipe_screen base; | |||
int refcnt; | |||
void *winsys_priv; | |||
struct etna_device *dev; | |||
struct etna_gpu *gpu; | |||
struct etna_pipe *pipe; | |||
struct renderonly *ro; | |||
struct slab_parent_pool transfer_pool; | |||
uint32_t model; | |||
uint32_t revision; | |||
uint32_t features[5]; | |||
struct etna_specs specs; | |||
}; | |||
static inline struct etna_screen * | |||
etna_screen(struct pipe_screen *pscreen) | |||
{ | |||
return (struct etna_screen *)pscreen; | |||
} | |||
boolean | |||
etna_screen_bo_get_handle(struct pipe_screen *pscreen, struct etna_bo *bo, | |||
unsigned stride, struct winsys_handle *whandle); | |||
struct etna_bo * | |||
etna_screen_bo_from_handle(struct pipe_screen *pscreen, | |||
struct winsys_handle *whandle, unsigned *out_stride); | |||
struct pipe_screen * | |||
etna_screen_create(struct etna_device *dev, struct etna_gpu *gpu, | |||
struct renderonly *ro); | |||
#endif |
@@ -0,0 +1,285 @@ | |||
/* | |||
* Copyright (c) 2012-2015 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Wladimir J. van der Laan <laanwj@gmail.com> | |||
*/ | |||
#include "etnaviv_shader.h" | |||
#include "etnaviv_compiler.h" | |||
#include "etnaviv_context.h" | |||
#include "etnaviv_debug.h" | |||
#include "etnaviv_util.h" | |||
#include "util/u_math.h" | |||
#include "util/u_memory.h" | |||
/* Link vs and fs together: fill in shader_state from vs and fs | |||
* as this function is called every time a new fs or vs is bound, the goal is to | |||
* do little processing as possible here, and to precompute as much as possible in | |||
* the vs/fs shader_object. | |||
* | |||
* XXX we could cache the link result for a certain set of VS/PS; usually a pair | |||
* of VS and PS will be used together anyway. | |||
*/ | |||
static bool | |||
etna_link_shaders(struct etna_context *ctx, struct compiled_shader_state *cs, | |||
const struct etna_shader *vs, const struct etna_shader *fs) | |||
{ | |||
struct etna_shader_link_info link = { }; | |||
assert(vs->processor == PIPE_SHADER_VERTEX); | |||
assert(fs->processor == PIPE_SHADER_FRAGMENT); | |||
#ifdef DEBUG | |||
if (DBG_ENABLED(ETNA_DBG_DUMP_SHADERS)) { | |||
etna_dump_shader(vs); | |||
etna_dump_shader(fs); | |||
} | |||
#endif | |||
if (etna_link_shader(&link, vs, fs)) { | |||
/* linking failed: some fs inputs do not have corresponding | |||
* vs outputs */ | |||
assert(0); | |||
return false; | |||
} | |||
if (DBG_ENABLED(ETNA_DBG_LINKER_MSGS)) { | |||
debug_printf("link result:\n"); | |||
debug_printf(" vs -> fs comps use pa_attr\n"); | |||
for (int idx = 0; idx < link.num_varyings; ++idx) | |||
debug_printf(" t%-2u -> t%-2u %-5.*s %u,%u,%u,%u 0x%08x\n", | |||
link.varyings[idx].reg, idx + 1, | |||
link.varyings[idx].num_components, "xyzw", | |||
link.varyings[idx].use[0], link.varyings[idx].use[1], | |||
link.varyings[idx].use[2], link.varyings[idx].use[3], | |||
link.varyings[idx].pa_attributes); | |||
} | |||
/* set last_varying_2x flag if the last varying has 1 or 2 components */ | |||
bool last_varying_2x = false; | |||
if (link.num_varyings > 0 && link.varyings[link.num_varyings - 1].num_components <= 2) | |||
last_varying_2x = true; | |||
cs->RA_CONTROL = VIVS_RA_CONTROL_UNK0 | | |||
COND(last_varying_2x, VIVS_RA_CONTROL_LAST_VARYING_2X); | |||
cs->PA_ATTRIBUTE_ELEMENT_COUNT = VIVS_PA_ATTRIBUTE_ELEMENT_COUNT_COUNT(link.num_varyings); | |||
for (int idx = 0; idx < link.num_varyings; ++idx) | |||
cs->PA_SHADER_ATTRIBUTES[idx] = link.varyings[idx].pa_attributes; | |||
cs->VS_END_PC = vs->code_size / 4; | |||
cs->VS_OUTPUT_COUNT = 1 + link.num_varyings; /* position + varyings */ | |||
/* vs outputs (varyings) */ | |||
DEFINE_ETNA_BITARRAY(vs_output, 16, 8) = {0}; | |||
int varid = 0; | |||
etna_bitarray_set(vs_output, 8, varid++, vs->vs_pos_out_reg); | |||
for (int idx = 0; idx < link.num_varyings; ++idx) | |||
etna_bitarray_set(vs_output, 8, varid++, link.varyings[idx].reg); | |||
if (vs->vs_pointsize_out_reg >= 0) | |||
etna_bitarray_set(vs_output, 8, varid++, vs->vs_pointsize_out_reg); /* pointsize is last */ | |||
for (int idx = 0; idx < ARRAY_SIZE(cs->VS_OUTPUT); ++idx) | |||
cs->VS_OUTPUT[idx] = vs_output[idx]; | |||
if (vs->vs_pointsize_out_reg != -1) { | |||
/* vertex shader outputs point coordinate, provide extra output and make | |||
* sure PA config is | |||
* not masked */ | |||
cs->PA_CONFIG = ~0; | |||
cs->VS_OUTPUT_COUNT_PSIZE = cs->VS_OUTPUT_COUNT + 1; | |||
} else { | |||
/* vertex shader does not output point coordinate, make sure thate | |||
* POINT_SIZE_ENABLE is masked | |||
* and no extra output is given */ | |||
cs->PA_CONFIG = ~VIVS_PA_CONFIG_POINT_SIZE_ENABLE; | |||
cs->VS_OUTPUT_COUNT_PSIZE = cs->VS_OUTPUT_COUNT; | |||
} | |||
cs->VS_LOAD_BALANCING = vs->vs_load_balancing; | |||
cs->VS_START_PC = 0; | |||
cs->PS_END_PC = fs->code_size / 4; | |||
cs->PS_OUTPUT_REG = fs->ps_color_out_reg; | |||
cs->PS_INPUT_COUNT = | |||
VIVS_PS_INPUT_COUNT_COUNT(link.num_varyings + 1) | /* Number of inputs plus position */ | |||
VIVS_PS_INPUT_COUNT_UNK8(fs->input_count_unk8); | |||
cs->PS_TEMP_REGISTER_CONTROL = | |||
VIVS_PS_TEMP_REGISTER_CONTROL_NUM_TEMPS(MAX2(fs->num_temps, link.num_varyings + 1)); | |||
cs->PS_CONTROL = VIVS_PS_CONTROL_UNK1; /* XXX when can we set BYPASS? */ | |||
cs->PS_START_PC = 0; | |||
/* Precompute PS_INPUT_COUNT and TEMP_REGISTER_CONTROL in the case of MSAA | |||
* mode, avoids some fumbling in sync_context. */ | |||
cs->PS_INPUT_COUNT_MSAA = | |||
VIVS_PS_INPUT_COUNT_COUNT(link.num_varyings + 2) | /* MSAA adds another input */ | |||
VIVS_PS_INPUT_COUNT_UNK8(fs->input_count_unk8); | |||
cs->PS_TEMP_REGISTER_CONTROL_MSAA = | |||
VIVS_PS_TEMP_REGISTER_CONTROL_NUM_TEMPS(MAX2(fs->num_temps, link.num_varyings + 2)); | |||
uint32_t total_components = 0; | |||
DEFINE_ETNA_BITARRAY(num_components, ETNA_NUM_VARYINGS, 4) = {0}; | |||
DEFINE_ETNA_BITARRAY(component_use, 4 * ETNA_NUM_VARYINGS, 2) = {0}; | |||
for (int idx = 0; idx < link.num_varyings; ++idx) { | |||
const struct etna_varying *varying = &link.varyings[idx]; | |||
etna_bitarray_set(num_components, 4, idx, varying->num_components); | |||
for (int comp = 0; comp < varying->num_components; ++comp) { | |||
etna_bitarray_set(component_use, 2, total_components, varying->use[comp]); | |||
total_components += 1; | |||
} | |||
} | |||
cs->GL_VARYING_TOTAL_COMPONENTS = | |||
VIVS_GL_VARYING_TOTAL_COMPONENTS_NUM(align(total_components, 2)); | |||
cs->GL_VARYING_NUM_COMPONENTS = num_components[0]; | |||
cs->GL_VARYING_COMPONENT_USE[0] = component_use[0]; | |||
cs->GL_VARYING_COMPONENT_USE[1] = component_use[1]; | |||
/* reference instruction memory */ | |||
cs->vs_inst_mem_size = vs->code_size; | |||
cs->VS_INST_MEM = vs->code; | |||
cs->ps_inst_mem_size = fs->code_size; | |||
cs->PS_INST_MEM = fs->code; | |||
return true; | |||
} | |||
bool | |||
etna_shader_link(struct etna_context *ctx) | |||
{ | |||
if (!ctx->vs || !ctx->fs) | |||
return false; | |||
/* re-link vs and fs if needed */ | |||
return etna_link_shaders(ctx, &ctx->shader_state, ctx->vs, ctx->fs); | |||
} | |||
static bool | |||
etna_shader_update_vs_inputs(struct etna_context *ctx, | |||
struct compiled_shader_state *cs, | |||
const struct etna_shader *vs, | |||
const struct compiled_vertex_elements_state *ves) | |||
{ | |||
unsigned num_temps, cur_temp, num_vs_inputs; | |||
if (!vs) | |||
return false; | |||
/* Number of vertex elements determines number of VS inputs. Otherwise, | |||
* the GPU crashes. Allocate any unused vertex elements to VS temporary | |||
* registers. */ | |||
num_vs_inputs = MAX2(ves->num_elements, vs->infile.num_reg); | |||
if (num_vs_inputs != ves->num_elements) { | |||
BUG("Number of elements %u does not match the number of VS inputs %zu", | |||
ctx->vertex_elements->num_elements, ctx->vs->infile.num_reg); | |||
return false; | |||
} | |||
cur_temp = vs->num_temps; | |||
num_temps = num_vs_inputs - vs->infile.num_reg + cur_temp; | |||
cs->VS_INPUT_COUNT = VIVS_VS_INPUT_COUNT_COUNT(num_vs_inputs) | | |||
VIVS_VS_INPUT_COUNT_UNK8(vs->input_count_unk8); | |||
cs->VS_TEMP_REGISTER_CONTROL = | |||
VIVS_VS_TEMP_REGISTER_CONTROL_NUM_TEMPS(num_temps); | |||
/* vs inputs (attributes) */ | |||
DEFINE_ETNA_BITARRAY(vs_input, 16, 8) = {0}; | |||
for (int idx = 0; idx < num_vs_inputs; ++idx) { | |||
if (idx < vs->infile.num_reg) | |||
etna_bitarray_set(vs_input, 8, idx, vs->infile.reg[idx].reg); | |||
else | |||
etna_bitarray_set(vs_input, 8, idx, cur_temp++); | |||
} | |||
for (int idx = 0; idx < ARRAY_SIZE(cs->VS_INPUT); ++idx) | |||
cs->VS_INPUT[idx] = vs_input[idx]; | |||
return true; | |||
} | |||
bool | |||
etna_shader_update_vertex(struct etna_context *ctx) | |||
{ | |||
return etna_shader_update_vs_inputs(ctx, &ctx->shader_state, ctx->vs, | |||
ctx->vertex_elements); | |||
} | |||
static void * | |||
etna_create_shader_state(struct pipe_context *pctx, | |||
const struct pipe_shader_state *pss) | |||
{ | |||
struct etna_context *ctx = etna_context(pctx); | |||
return etna_compile_shader(&ctx->specs, pss->tokens); | |||
} | |||
static void | |||
etna_delete_shader_state(struct pipe_context *pctx, void *ss) | |||
{ | |||
etna_destroy_shader(ss); | |||
} | |||
static void | |||
etna_bind_fs_state(struct pipe_context *pctx, void *fss_) | |||
{ | |||
struct etna_context *ctx = etna_context(pctx); | |||
struct etna_shader *fss = fss_; | |||
if (ctx->fs == fss) /* skip if already bound */ | |||
return; | |||
assert(fss == NULL || fss->processor == PIPE_SHADER_FRAGMENT); | |||
ctx->fs = fss; | |||
ctx->dirty |= ETNA_DIRTY_SHADER; | |||
} | |||
static void | |||
etna_bind_vs_state(struct pipe_context *pctx, void *vss_) | |||
{ | |||
struct etna_context *ctx = etna_context(pctx); | |||
struct etna_shader *vss = vss_; | |||
if (ctx->vs == vss) /* skip if already bound */ | |||
return; | |||
assert(vss == NULL || vss->processor == PIPE_SHADER_VERTEX); | |||
ctx->vs = vss; | |||
ctx->dirty |= ETNA_DIRTY_SHADER; | |||
} | |||
void | |||
etna_shader_init(struct pipe_context *pctx) | |||
{ | |||
pctx->create_fs_state = etna_create_shader_state; | |||
pctx->bind_fs_state = etna_bind_fs_state; | |||
pctx->delete_fs_state = etna_delete_shader_state; | |||
pctx->create_vs_state = etna_create_shader_state; | |||
pctx->bind_vs_state = etna_bind_vs_state; | |||
pctx->delete_vs_state = etna_delete_shader_state; | |||
} |
@@ -0,0 +1,45 @@ | |||
/* | |||
* Copyright (c) 2012-2015 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Wladimir J. van der Laan <laanwj@gmail.com> | |||
*/ | |||
#ifndef H_ETNAVIV_SHADER | |||
#define H_ETNAVIV_SHADER | |||
#include "pipe/p_state.h" | |||
struct etna_context; | |||
struct etna_shader; | |||
struct compiled_shader_state; | |||
bool | |||
etna_shader_link(struct etna_context *ctx); | |||
bool | |||
etna_shader_update_vertex(struct etna_context *ctx); | |||
void | |||
etna_shader_init(struct pipe_context *pctx); | |||
#endif |
@@ -0,0 +1,664 @@ | |||
/* | |||
* Copyright (c) 2012-2015 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Wladimir J. van der Laan <laanwj@gmail.com> | |||
* Christian Gmeiner <christian.gmeiner@gmail.com> | |||
*/ | |||
#include "etnaviv_state.h" | |||
#include "hw/common.xml.h" | |||
#include "etnaviv_clear_blit.h" | |||
#include "etnaviv_context.h" | |||
#include "etnaviv_format.h" | |||
#include "etnaviv_shader.h" | |||
#include "etnaviv_surface.h" | |||
#include "etnaviv_translate.h" | |||
#include "etnaviv_util.h" | |||
#include "util/u_helpers.h" | |||
#include "util/u_inlines.h" | |||
#include "util/u_math.h" | |||
#include "util/u_memory.h" | |||
static void | |||
etna_set_blend_color(struct pipe_context *pctx, const struct pipe_blend_color *bc) | |||
{ | |||
struct etna_context *ctx = etna_context(pctx); | |||
struct compiled_blend_color *cs = &ctx->blend_color; | |||
cs->PE_ALPHA_BLEND_COLOR = | |||
VIVS_PE_ALPHA_BLEND_COLOR_R(etna_cfloat_to_uint8(bc->color[0])) | | |||
VIVS_PE_ALPHA_BLEND_COLOR_G(etna_cfloat_to_uint8(bc->color[1])) | | |||
VIVS_PE_ALPHA_BLEND_COLOR_B(etna_cfloat_to_uint8(bc->color[2])) | | |||
VIVS_PE_ALPHA_BLEND_COLOR_A(etna_cfloat_to_uint8(bc->color[3])); | |||
ctx->dirty |= ETNA_DIRTY_BLEND_COLOR; | |||
} | |||
static void | |||
etna_set_stencil_ref(struct pipe_context *pctx, const struct pipe_stencil_ref *sr) | |||
{ | |||
struct etna_context *ctx = etna_context(pctx); | |||
struct compiled_stencil_ref *cs = &ctx->stencil_ref; | |||
ctx->stencil_ref_s = *sr; | |||
cs->PE_STENCIL_CONFIG = VIVS_PE_STENCIL_CONFIG_REF_FRONT(sr->ref_value[0]); | |||
/* rest of bits weaved in from depth_stencil_alpha */ | |||
cs->PE_STENCIL_CONFIG_EXT = | |||
VIVS_PE_STENCIL_CONFIG_EXT_REF_BACK(sr->ref_value[0]); | |||
ctx->dirty |= ETNA_DIRTY_STENCIL_REF; | |||
} | |||
static void | |||
etna_set_clip_state(struct pipe_context *pctx, const struct pipe_clip_state *pcs) | |||
{ | |||
/* NOOP */ | |||
} | |||
static void | |||
etna_set_sample_mask(struct pipe_context *pctx, unsigned sample_mask) | |||
{ | |||
struct etna_context *ctx = etna_context(pctx); | |||
ctx->sample_mask = sample_mask; | |||
ctx->dirty |= ETNA_DIRTY_SAMPLE_MASK; | |||
} | |||
static void | |||
etna_set_constant_buffer(struct pipe_context *pctx, uint shader, uint index, | |||
const struct pipe_constant_buffer *cb) | |||
{ | |||
struct etna_context *ctx = etna_context(pctx); | |||
if (unlikely(index > 0)) { | |||
DBG("Unhandled buffer index %i", index); | |||
return; | |||
} | |||
util_copy_constant_buffer(&ctx->constant_buffer[shader], cb); | |||
/* Note that the state tracker can unbind constant buffers by | |||
* passing NULL here. */ | |||
if (unlikely(!cb)) | |||
return; | |||
/* there is no support for ARB_uniform_buffer_object */ | |||
assert(cb->buffer == NULL && cb->user_buffer != NULL); | |||
ctx->dirty |= ETNA_DIRTY_CONSTBUF; | |||
} | |||
static void | |||
etna_update_render_resource(struct pipe_context *pctx, struct pipe_resource *pres) | |||
{ | |||
struct etna_resource *res = etna_resource(pres); | |||
if (res->texture && etna_resource_older(res, etna_resource(res->texture))) { | |||
/* The render buffer is older than the texture buffer. Copy it over. */ | |||
etna_copy_resource(pctx, pres, res->texture, 0, pres->last_level); | |||
res->seqno = etna_resource(res->texture)->seqno; | |||
} | |||
} | |||
static void | |||
etna_set_framebuffer_state(struct pipe_context *pctx, | |||
const struct pipe_framebuffer_state *sv) | |||
{ | |||
struct etna_context *ctx = etna_context(pctx); | |||
struct compiled_framebuffer_state *cs = &ctx->framebuffer; | |||
int nr_samples_color = -1; | |||
int nr_samples_depth = -1; | |||
/* Set up TS as well. Warning: this state is used by both the RS and PE */ | |||
uint32_t ts_mem_config = 0; | |||
if (sv->nr_cbufs > 0) { /* at least one color buffer? */ | |||
struct etna_surface *cbuf = etna_surface(sv->cbufs[0]); | |||
struct etna_resource *res = etna_resource(cbuf->base.texture); | |||
bool color_supertiled = (res->layout & ETNA_LAYOUT_BIT_SUPER) != 0; | |||
assert(res->layout & ETNA_LAYOUT_BIT_TILE); /* Cannot render to linear surfaces */ | |||
etna_update_render_resource(pctx, cbuf->base.texture); | |||
pipe_surface_reference(&cs->cbuf, &cbuf->base); | |||
cs->PE_COLOR_FORMAT = | |||
VIVS_PE_COLOR_FORMAT_FORMAT(translate_rs_format(cbuf->base.format)) | | |||
VIVS_PE_COLOR_FORMAT_COMPONENTS__MASK | | |||
VIVS_PE_COLOR_FORMAT_OVERWRITE | | |||
COND(color_supertiled, VIVS_PE_COLOR_FORMAT_SUPER_TILED); | |||
/* VIVS_PE_COLOR_FORMAT_COMPONENTS() and | |||
* VIVS_PE_COLOR_FORMAT_OVERWRITE comes from blend_state | |||
* but only if we set the bits above. */ | |||
/* merged with depth_stencil_alpha */ | |||
if ((cbuf->surf.offset & 63) || | |||
(((cbuf->surf.stride * 4) & 63) && cbuf->surf.height > 4)) { | |||
/* XXX Must make temporary surface here. | |||
* Need the same mechanism on gc2000 when we want to do mipmap | |||
* generation by | |||
* rendering to levels > 1 due to multitiled / tiled conversion. */ | |||
BUG("Alignment error, trying to render to offset %08x with tile " | |||
"stride %i", | |||
cbuf->surf.offset, cbuf->surf.stride * 4); | |||
} | |||
if (ctx->specs.pixel_pipes == 1) { | |||
cs->PE_COLOR_ADDR = cbuf->reloc[0]; | |||
cs->PE_COLOR_ADDR.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE; | |||
} else { | |||
/* Rendered textures must always be multi-tiled */ | |||
assert(res->layout & ETNA_LAYOUT_BIT_MULTI); | |||
for (int i = 0; i < ctx->specs.pixel_pipes; i++) { | |||
cs->PE_PIPE_COLOR_ADDR[i] = cbuf->reloc[i]; | |||
cs->PE_PIPE_COLOR_ADDR[i].flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE; | |||
} | |||
} | |||
cs->PE_COLOR_STRIDE = cbuf->surf.stride; | |||
if (cbuf->surf.ts_size) { | |||
ts_mem_config |= VIVS_TS_MEM_CONFIG_COLOR_FAST_CLEAR; | |||
cs->TS_COLOR_CLEAR_VALUE = cbuf->level->clear_value; | |||
cs->TS_COLOR_STATUS_BASE = cbuf->ts_reloc; | |||
cs->TS_COLOR_STATUS_BASE.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE; | |||
cs->TS_COLOR_SURFACE_BASE = cbuf->reloc[0]; | |||
cs->TS_COLOR_SURFACE_BASE.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE; | |||
} | |||
/* MSAA */ | |||
if (cbuf->base.texture->nr_samples > 1) | |||
ts_mem_config |= | |||
VIVS_TS_MEM_CONFIG_MSAA | translate_msaa_format(cbuf->base.format); | |||
nr_samples_color = cbuf->base.texture->nr_samples; | |||
} else { | |||
pipe_surface_reference(&cs->cbuf, NULL); | |||
/* Clearing VIVS_PE_COLOR_FORMAT_COMPONENTS__MASK and | |||
* VIVS_PE_COLOR_FORMAT_OVERWRITE prevents us from overwriting the | |||
* color target */ | |||
cs->PE_COLOR_FORMAT = 0; | |||
cs->PE_COLOR_STRIDE = 0; | |||
cs->TS_COLOR_STATUS_BASE.bo = NULL; | |||
cs->TS_COLOR_SURFACE_BASE.bo = NULL; | |||
for (int i = 0; i < ETNA_MAX_PIXELPIPES; i++) | |||
cs->PE_PIPE_COLOR_ADDR[i].bo = NULL; | |||
} | |||
if (sv->zsbuf != NULL) { | |||
struct etna_surface *zsbuf = etna_surface(sv->zsbuf); | |||
struct etna_resource *res = etna_resource(zsbuf->base.texture); | |||
etna_update_render_resource(pctx, zsbuf->base.texture); | |||
pipe_surface_reference(&cs->zsbuf, &zsbuf->base); | |||
assert(res->layout &ETNA_LAYOUT_BIT_TILE); /* Cannot render to linear surfaces */ | |||
uint32_t depth_format = translate_depth_format(zsbuf->base.format); | |||
unsigned depth_bits = | |||
depth_format == VIVS_PE_DEPTH_CONFIG_DEPTH_FORMAT_D16 ? 16 : 24; | |||
bool depth_supertiled = (res->layout & ETNA_LAYOUT_BIT_SUPER) != 0; | |||
cs->PE_DEPTH_CONFIG = | |||
depth_format | | |||
COND(depth_supertiled, VIVS_PE_DEPTH_CONFIG_SUPER_TILED) | | |||
VIVS_PE_DEPTH_CONFIG_DEPTH_MODE_Z; | |||
/* VIVS_PE_DEPTH_CONFIG_ONLY_DEPTH */ | |||
/* merged with depth_stencil_alpha */ | |||
if (ctx->specs.pixel_pipes == 1) { | |||
cs->PE_DEPTH_ADDR = zsbuf->reloc[0]; | |||
cs->PE_DEPTH_ADDR.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE; | |||
} else { | |||
for (int i = 0; i < ctx->specs.pixel_pipes; i++) { | |||
cs->PE_PIPE_DEPTH_ADDR[i] = zsbuf->reloc[i]; | |||
cs->PE_PIPE_DEPTH_ADDR[i].flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE; | |||
} | |||
} | |||
cs->PE_DEPTH_STRIDE = zsbuf->surf.stride; | |||
cs->PE_HDEPTH_CONTROL = VIVS_PE_HDEPTH_CONTROL_FORMAT_DISABLED; | |||
cs->PE_DEPTH_NORMALIZE = fui(exp2f(depth_bits) - 1.0f); | |||
if (zsbuf->surf.ts_size) { | |||
ts_mem_config |= VIVS_TS_MEM_CONFIG_DEPTH_FAST_CLEAR; | |||
cs->TS_DEPTH_CLEAR_VALUE = zsbuf->level->clear_value; | |||
cs->TS_DEPTH_STATUS_BASE = zsbuf->ts_reloc; | |||
cs->TS_DEPTH_STATUS_BASE.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE; | |||
cs->TS_DEPTH_SURFACE_BASE = zsbuf->reloc[0]; | |||
cs->TS_DEPTH_SURFACE_BASE.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE; | |||
} | |||
ts_mem_config |= COND(depth_bits == 16, VIVS_TS_MEM_CONFIG_DEPTH_16BPP); | |||
/* MSAA */ | |||
if (zsbuf->base.texture->nr_samples > 1) | |||
/* XXX VIVS_TS_MEM_CONFIG_DEPTH_COMPRESSION; | |||
* Disable without MSAA for now, as it causes corruption in glquake. */ | |||
ts_mem_config |= VIVS_TS_MEM_CONFIG_DEPTH_COMPRESSION; | |||
nr_samples_depth = zsbuf->base.texture->nr_samples; | |||
} else { | |||
pipe_surface_reference(&cs->zsbuf, NULL); | |||
cs->PE_DEPTH_CONFIG = VIVS_PE_DEPTH_CONFIG_DEPTH_MODE_NONE; | |||
cs->PE_DEPTH_ADDR.bo = NULL; | |||
cs->PE_DEPTH_STRIDE = 0; | |||
cs->TS_DEPTH_STATUS_BASE.bo = NULL; | |||
cs->TS_DEPTH_SURFACE_BASE.bo = NULL; | |||
for (int i = 0; i < ETNA_MAX_PIXELPIPES; i++) | |||
cs->PE_PIPE_DEPTH_ADDR[i].bo = NULL; | |||
} | |||
/* MSAA setup */ | |||
if (nr_samples_depth != -1 && nr_samples_color != -1 && | |||
nr_samples_depth != nr_samples_color) { | |||
BUG("Number of samples in color and depth texture must match (%i and %i respectively)", | |||
nr_samples_color, nr_samples_depth); | |||
} | |||
switch (MAX2(nr_samples_depth, nr_samples_color)) { | |||
case 0: | |||
case 1: /* Are 0 and 1 samples allowed? */ | |||
cs->GL_MULTI_SAMPLE_CONFIG = | |||
VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_NONE; | |||
cs->msaa_mode = false; | |||
break; | |||
case 2: | |||
cs->GL_MULTI_SAMPLE_CONFIG = VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_2X; | |||
cs->msaa_mode = true; /* Add input to PS */ | |||
cs->RA_MULTISAMPLE_UNK00E04 = 0x0; | |||
cs->RA_MULTISAMPLE_UNK00E10[0] = 0x0000aa22; | |||
cs->RA_CENTROID_TABLE[0] = 0x66aa2288; | |||
cs->RA_CENTROID_TABLE[1] = 0x88558800; | |||
cs->RA_CENTROID_TABLE[2] = 0x88881100; | |||
cs->RA_CENTROID_TABLE[3] = 0x33888800; | |||
break; | |||
case 4: | |||
cs->GL_MULTI_SAMPLE_CONFIG = VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_4X; | |||
cs->msaa_mode = true; /* Add input to PS */ | |||
cs->RA_MULTISAMPLE_UNK00E04 = 0x0; | |||
cs->RA_MULTISAMPLE_UNK00E10[0] = 0xeaa26e26; | |||
cs->RA_MULTISAMPLE_UNK00E10[1] = 0xe6ae622a; | |||
cs->RA_MULTISAMPLE_UNK00E10[2] = 0xaaa22a22; | |||
cs->RA_CENTROID_TABLE[0] = 0x4a6e2688; | |||
cs->RA_CENTROID_TABLE[1] = 0x888888a2; | |||
cs->RA_CENTROID_TABLE[2] = 0x888888ea; | |||
cs->RA_CENTROID_TABLE[3] = 0x888888c6; | |||
cs->RA_CENTROID_TABLE[4] = 0x46622a88; | |||
cs->RA_CENTROID_TABLE[5] = 0x888888ae; | |||
cs->RA_CENTROID_TABLE[6] = 0x888888e6; | |||
cs->RA_CENTROID_TABLE[7] = 0x888888ca; | |||
cs->RA_CENTROID_TABLE[8] = 0x262a2288; | |||
cs->RA_CENTROID_TABLE[9] = 0x886688a2; | |||
cs->RA_CENTROID_TABLE[10] = 0x888866aa; | |||
cs->RA_CENTROID_TABLE[11] = 0x668888a6; | |||
break; | |||
} | |||
/* Scissor setup */ | |||
cs->SE_SCISSOR_LEFT = 0; /* affected by rasterizer and scissor state as well */ | |||
cs->SE_SCISSOR_TOP = 0; | |||
cs->SE_SCISSOR_RIGHT = (sv->width << 16) - 1; | |||
cs->SE_SCISSOR_BOTTOM = (sv->height << 16) - 1; | |||
cs->TS_MEM_CONFIG = ts_mem_config; | |||
ctx->framebuffer_s = *sv; /* keep copy of original structure */ | |||
ctx->dirty |= ETNA_DIRTY_FRAMEBUFFER; | |||
} | |||
static void | |||
etna_set_polygon_stipple(struct pipe_context *pctx, | |||
const struct pipe_poly_stipple *stipple) | |||
{ | |||
/* NOP */ | |||
} | |||
static void | |||
etna_set_scissor_states(struct pipe_context *pctx, unsigned start_slot, | |||
unsigned num_scissors, const struct pipe_scissor_state *ss) | |||
{ | |||
struct etna_context *ctx = etna_context(pctx); | |||
struct compiled_scissor_state *cs = &ctx->scissor; | |||
/* note that this state is only used when rasterizer_state->scissor is on */ | |||
ctx->scissor_s = *ss; | |||
cs->SE_SCISSOR_LEFT = (ss->minx << 16); | |||
cs->SE_SCISSOR_TOP = (ss->miny << 16); | |||
cs->SE_SCISSOR_RIGHT = (ss->maxx << 16) - 1; | |||
cs->SE_SCISSOR_BOTTOM = (ss->maxy << 16) - 1; | |||
ctx->dirty |= ETNA_DIRTY_SCISSOR; | |||
} | |||
static void | |||
etna_set_viewport_states(struct pipe_context *pctx, unsigned start_slot, | |||
unsigned num_scissors, const struct pipe_viewport_state *vs) | |||
{ | |||
struct etna_context *ctx = etna_context(pctx); | |||
struct compiled_viewport_state *cs = &ctx->viewport; | |||
ctx->viewport_s = *vs; | |||
/** | |||
* For Vivante GPU, viewport z transformation is 0..1 to 0..1 instead of | |||
* -1..1 to 0..1. | |||
* scaling and translation to 0..1 already happened, so remove that | |||
* | |||
* z' = (z * 2 - 1) * scale + translate | |||
* = z * (2 * scale) + (translate - scale) | |||
* | |||
* scale' = 2 * scale | |||
* translate' = translate - scale | |||
*/ | |||
/* must be fixp as v4 state deltas assume it is */ | |||
cs->PA_VIEWPORT_SCALE_X = etna_f32_to_fixp16(vs->scale[0]); | |||
cs->PA_VIEWPORT_SCALE_Y = etna_f32_to_fixp16(vs->scale[1]); | |||
cs->PA_VIEWPORT_SCALE_Z = fui(vs->scale[2] * 2.0f); | |||
cs->PA_VIEWPORT_OFFSET_X = etna_f32_to_fixp16(vs->translate[0]); | |||
cs->PA_VIEWPORT_OFFSET_Y = etna_f32_to_fixp16(vs->translate[1]); | |||
cs->PA_VIEWPORT_OFFSET_Z = fui(vs->translate[2] - vs->scale[2]); | |||
/* Compute scissor rectangle (fixp) from viewport. | |||
* Make sure left is always < right and top always < bottom. | |||
*/ | |||
cs->SE_SCISSOR_LEFT = etna_f32_to_fixp16(MAX2(vs->translate[0] - vs->scale[0], 0.0f)); | |||
cs->SE_SCISSOR_TOP = etna_f32_to_fixp16(MAX2(vs->translate[1] - vs->scale[1], 0.0f)); | |||
cs->SE_SCISSOR_RIGHT = etna_f32_to_fixp16(MAX2(vs->translate[0] + vs->scale[0], 0.0f)); | |||
cs->SE_SCISSOR_BOTTOM = etna_f32_to_fixp16(MAX2(vs->translate[1] + vs->scale[1], 0.0f)); | |||
if (cs->SE_SCISSOR_LEFT > cs->SE_SCISSOR_RIGHT) { | |||
uint32_t tmp = cs->SE_SCISSOR_RIGHT; | |||
cs->SE_SCISSOR_RIGHT = cs->SE_SCISSOR_LEFT; | |||
cs->SE_SCISSOR_LEFT = tmp; | |||
} | |||
if (cs->SE_SCISSOR_TOP > cs->SE_SCISSOR_BOTTOM) { | |||
uint32_t tmp = cs->SE_SCISSOR_BOTTOM; | |||
cs->SE_SCISSOR_BOTTOM = cs->SE_SCISSOR_TOP; | |||
cs->SE_SCISSOR_TOP = tmp; | |||
} | |||
cs->PE_DEPTH_NEAR = fui(0.0); /* not affected if depth mode is Z (as in GL) */ | |||
cs->PE_DEPTH_FAR = fui(1.0); | |||
ctx->dirty |= ETNA_DIRTY_VIEWPORT; | |||
} | |||
static void | |||
etna_set_vertex_buffers(struct pipe_context *pctx, unsigned start_slot, | |||
unsigned num_buffers, const struct pipe_vertex_buffer *vb) | |||
{ | |||
struct etna_context *ctx = etna_context(pctx); | |||
struct etna_vertexbuf_state *so = &ctx->vertex_buffer; | |||
util_set_vertex_buffers_mask(so->vb, &so->enabled_mask, vb, start_slot, num_buffers); | |||
so->count = util_last_bit(so->enabled_mask); | |||
for (unsigned idx = start_slot; idx < start_slot + num_buffers; ++idx) { | |||
struct compiled_set_vertex_buffer *cs = &so->cvb[idx]; | |||
struct pipe_vertex_buffer *vbi = &so->vb[idx]; | |||
assert(!vbi->user_buffer); /* XXX support user_buffer using | |||
etna_usermem_map */ | |||
if (vbi->buffer) { /* GPU buffer */ | |||
cs->FE_VERTEX_STREAM_BASE_ADDR.bo = etna_resource(vbi->buffer)->bo; | |||
cs->FE_VERTEX_STREAM_BASE_ADDR.offset = vbi->buffer_offset; | |||
cs->FE_VERTEX_STREAM_BASE_ADDR.flags = ETNA_RELOC_READ; | |||
cs->FE_VERTEX_STREAM_CONTROL = | |||
FE_VERTEX_STREAM_CONTROL_VERTEX_STRIDE(vbi->stride); | |||
} else { | |||
cs->FE_VERTEX_STREAM_BASE_ADDR.bo = NULL; | |||
cs->FE_VERTEX_STREAM_CONTROL = 0; | |||
} | |||
} | |||
ctx->dirty |= ETNA_DIRTY_VERTEX_BUFFERS; | |||
} | |||
static void | |||
etna_set_index_buffer(struct pipe_context *pctx, const struct pipe_index_buffer *ib) | |||
{ | |||
struct etna_context *ctx = etna_context(pctx); | |||
uint32_t ctrl; | |||
if (ib) { | |||
pipe_resource_reference(&ctx->index_buffer.ib.buffer, ib->buffer); | |||
memcpy(&ctx->index_buffer.ib, ib, sizeof(ctx->index_buffer.ib)); | |||
ctrl = translate_index_size(ctx->index_buffer.ib.index_size); | |||
} else { | |||
pipe_resource_reference(&ctx->index_buffer.ib.buffer, NULL); | |||
ctrl = 0; | |||
} | |||
if (ctx->index_buffer.ib.buffer && ctrl != ETNA_NO_MATCH) { | |||
ctx->index_buffer.FE_INDEX_STREAM_BASE_ADDR.bo = etna_resource(ctx->index_buffer.ib.buffer)->bo; | |||
ctx->index_buffer.FE_INDEX_STREAM_BASE_ADDR.offset = ctx->index_buffer.ib.offset; | |||
ctx->index_buffer.FE_INDEX_STREAM_BASE_ADDR.flags = ETNA_RELOC_READ; | |||
ctx->index_buffer.FE_INDEX_STREAM_CONTROL = ctrl; | |||
} else { | |||
ctx->index_buffer.FE_INDEX_STREAM_BASE_ADDR.bo = NULL; | |||
ctx->index_buffer.FE_INDEX_STREAM_CONTROL = 0; | |||
} | |||
ctx->dirty |= ETNA_DIRTY_INDEX_BUFFER; | |||
} | |||
static void | |||
etna_blend_state_bind(struct pipe_context *pctx, void *bs) | |||
{ | |||
struct etna_context *ctx = etna_context(pctx); | |||
ctx->blend = bs; | |||
ctx->dirty |= ETNA_DIRTY_BLEND; | |||
} | |||
static void | |||
etna_blend_state_delete(struct pipe_context *pctx, void *bs) | |||
{ | |||
FREE(bs); | |||
} | |||
static void | |||
etna_rasterizer_state_bind(struct pipe_context *pctx, void *rs) | |||
{ | |||
struct etna_context *ctx = etna_context(pctx); | |||
ctx->rasterizer = rs; | |||
ctx->dirty |= ETNA_DIRTY_RASTERIZER; | |||
} | |||
static void | |||
etna_rasterizer_state_delete(struct pipe_context *pctx, void *rs) | |||
{ | |||
FREE(rs); | |||
} | |||
static void | |||
etna_zsa_state_bind(struct pipe_context *pctx, void *zs) | |||
{ | |||
struct etna_context *ctx = etna_context(pctx); | |||
ctx->zsa = zs; | |||
ctx->dirty |= ETNA_DIRTY_ZSA; | |||
} | |||
static void | |||
etna_zsa_state_delete(struct pipe_context *pctx, void *zs) | |||
{ | |||
FREE(zs); | |||
} | |||
/** Create vertex element states, which define a layout for fetching | |||
* vertices for rendering. | |||
*/ | |||
static void * | |||
etna_vertex_elements_state_create(struct pipe_context *pctx, | |||
unsigned num_elements, const struct pipe_vertex_element *elements) | |||
{ | |||
struct etna_context *ctx = etna_context(pctx); | |||
struct compiled_vertex_elements_state *cs = CALLOC_STRUCT(compiled_vertex_elements_state); | |||
if (!cs) | |||
return NULL; | |||
if (num_elements > ctx->specs.vertex_max_elements) { | |||
BUG("number of elements (%u) exceeds chip maximum (%u)", num_elements, | |||
ctx->specs.vertex_max_elements); | |||
return NULL; | |||
} | |||
/* XXX could minimize number of consecutive stretches here by sorting, and | |||
* permuting the inputs in shader or does Mesa do this already? */ | |||
/* Check that vertex element binding is compatible with hardware; thus | |||
* elements[idx].vertex_buffer_index are < stream_count. If not, the binding | |||
* uses more streams than is supported, and u_vbuf should have done some | |||
* reorganization for compatibility. */ | |||
/* TODO: does mesa this for us? */ | |||
bool incompatible = false; | |||
for (unsigned idx = 0; idx < num_elements; ++idx) { | |||
if (elements[idx].vertex_buffer_index >= ctx->specs.stream_count || elements[idx].instance_divisor > 0) | |||
incompatible = true; | |||
} | |||
cs->num_elements = num_elements; | |||
if (incompatible || num_elements == 0) { | |||
DBG("Error: zero vertex elements, or more vertex buffers used than supported"); | |||
FREE(cs); | |||
return NULL; | |||
} | |||
unsigned start_offset = 0; /* start of current consecutive stretch */ | |||
bool nonconsecutive = true; /* previous value of nonconsecutive */ | |||
for (unsigned idx = 0; idx < num_elements; ++idx) { | |||
unsigned element_size = util_format_get_blocksize(elements[idx].src_format); | |||
unsigned end_offset = elements[idx].src_offset + element_size; | |||
uint32_t format_type, normalize; | |||
if (nonconsecutive) | |||
start_offset = elements[idx].src_offset; | |||
/* maximum vertex size is 256 bytes */ | |||
assert(element_size != 0 && end_offset <= 256); | |||
/* check whether next element is consecutive to this one */ | |||
nonconsecutive = (idx == (num_elements - 1)) || | |||
elements[idx + 1].vertex_buffer_index != elements[idx].vertex_buffer_index || | |||
end_offset != elements[idx + 1].src_offset; | |||
format_type = translate_vertex_format_type(elements[idx].src_format); | |||
normalize = translate_vertex_format_normalize(elements[idx].src_format); | |||
assert(format_type != ETNA_NO_MATCH); | |||
assert(normalize != ETNA_NO_MATCH); | |||
cs->FE_VERTEX_ELEMENT_CONFIG[idx] = | |||
COND(nonconsecutive, VIVS_FE_VERTEX_ELEMENT_CONFIG_NONCONSECUTIVE) | | |||
format_type | | |||
VIVS_FE_VERTEX_ELEMENT_CONFIG_NUM(util_format_get_nr_components(elements[idx].src_format)) | | |||
normalize | VIVS_FE_VERTEX_ELEMENT_CONFIG_ENDIAN(ENDIAN_MODE_NO_SWAP) | | |||
VIVS_FE_VERTEX_ELEMENT_CONFIG_STREAM(elements[idx].vertex_buffer_index) | | |||
VIVS_FE_VERTEX_ELEMENT_CONFIG_START(elements[idx].src_offset) | | |||
VIVS_FE_VERTEX_ELEMENT_CONFIG_END(end_offset - start_offset); | |||
} | |||
return cs; | |||
} | |||
static void | |||
etna_vertex_elements_state_delete(struct pipe_context *pctx, void *ve) | |||
{ | |||
FREE(ve); | |||
} | |||
static void | |||
etna_vertex_elements_state_bind(struct pipe_context *pctx, void *ve) | |||
{ | |||
struct etna_context *ctx = etna_context(pctx); | |||
ctx->vertex_elements = ve; | |||
ctx->dirty |= ETNA_DIRTY_VERTEX_ELEMENTS; | |||
} | |||
struct etna_state_updater { | |||
bool (*update)(struct etna_context *ctx); | |||
uint32_t dirty; | |||
}; | |||
static const struct etna_state_updater etna_state_updates[] = { | |||
{ | |||
etna_shader_update_vertex, ETNA_DIRTY_SHADER | ETNA_DIRTY_VERTEX_ELEMENTS, | |||
}, | |||
{ | |||
etna_shader_link, ETNA_DIRTY_SHADER, | |||
} | |||
}; | |||
bool | |||
etna_state_update(struct etna_context *ctx) | |||
{ | |||
for (unsigned int i = 0; i < ARRAY_SIZE(etna_state_updates); i++) | |||
if (ctx->dirty & etna_state_updates[i].dirty) | |||
if (!etna_state_updates[i].update(ctx)) | |||
return false; | |||
return true; | |||
} | |||
void | |||
etna_state_init(struct pipe_context *pctx) | |||
{ | |||
pctx->set_blend_color = etna_set_blend_color; | |||
pctx->set_stencil_ref = etna_set_stencil_ref; | |||
pctx->set_clip_state = etna_set_clip_state; | |||
pctx->set_sample_mask = etna_set_sample_mask; | |||
pctx->set_constant_buffer = etna_set_constant_buffer; | |||
pctx->set_framebuffer_state = etna_set_framebuffer_state; | |||
pctx->set_polygon_stipple = etna_set_polygon_stipple; | |||
pctx->set_scissor_states = etna_set_scissor_states; | |||
pctx->set_viewport_states = etna_set_viewport_states; | |||
pctx->set_vertex_buffers = etna_set_vertex_buffers; | |||
pctx->set_index_buffer = etna_set_index_buffer; | |||
pctx->bind_blend_state = etna_blend_state_bind; | |||
pctx->delete_blend_state = etna_blend_state_delete; | |||
pctx->bind_rasterizer_state = etna_rasterizer_state_bind; | |||
pctx->delete_rasterizer_state = etna_rasterizer_state_delete; | |||
pctx->bind_depth_stencil_alpha_state = etna_zsa_state_bind; | |||
pctx->delete_depth_stencil_alpha_state = etna_zsa_state_delete; | |||
pctx->create_vertex_elements_state = etna_vertex_elements_state_create; | |||
pctx->delete_vertex_elements_state = etna_vertex_elements_state_delete; | |||
pctx->bind_vertex_elements_state = etna_vertex_elements_state_bind; | |||
} |
@@ -0,0 +1,52 @@ | |||
/* | |||
* Copyright (c) 2012-2015 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Wladimir J. van der Laan <laanwj@gmail.com> | |||
* Christian Gmeiner <christian.gmeiner@gmail.com> | |||
*/ | |||
#ifndef ETNAVIV_STATE_H_ | |||
#define ETNAVIV_STATE_H_ | |||
#include "etnaviv_context.h" | |||
#include "pipe/p_context.h" | |||
static inline bool | |||
etna_depth_enabled(struct etna_context *ctx) | |||
{ | |||
return ctx->zsa && ctx->zsa->depth.enabled; | |||
} | |||
static inline bool | |||
etna_stencil_enabled(struct etna_context *ctx) | |||
{ | |||
return ctx->zsa && ctx->zsa->stencil[0].enabled; | |||
} | |||
bool | |||
etna_state_update(struct etna_context *ctx); | |||
void | |||
etna_state_init(struct pipe_context *pctx); | |||
#endif /* ETNAVIV_STATE_H_ */ |
@@ -0,0 +1,152 @@ | |||
/* | |||
* Copyright (c) 2012-2013 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Wladimir J. van der Laan <laanwj@gmail.com> | |||
*/ | |||
#include "etnaviv_surface.h" | |||
#include "etnaviv_screen.h" | |||
#include "etnaviv_clear_blit.h" | |||
#include "etnaviv_context.h" | |||
#include "etnaviv_translate.h" | |||
#include "pipe/p_defines.h" | |||
#include "pipe/p_state.h" | |||
#include "util/u_inlines.h" | |||
#include "util/u_memory.h" | |||
#include "hw/common.xml.h" | |||
static struct pipe_surface * | |||
etna_create_surface(struct pipe_context *pctx, struct pipe_resource *prsc, | |||
const struct pipe_surface *templat) | |||
{ | |||
struct etna_context *ctx = etna_context(pctx); | |||
struct etna_resource *rsc = etna_resource(prsc); | |||
struct etna_surface *surf = CALLOC_STRUCT(etna_surface); | |||
if (!surf) | |||
return NULL; | |||
assert(templat->u.tex.first_layer == templat->u.tex.last_layer); | |||
unsigned layer = templat->u.tex.first_layer; | |||
unsigned level = templat->u.tex.level; | |||
assert(layer < rsc->base.array_size); | |||
surf->base.context = pctx; | |||
pipe_reference_init(&surf->base.reference, 1); | |||
pipe_resource_reference(&surf->base.texture, &rsc->base); | |||
/* Allocate a TS for the resource if there isn't one yet, | |||
* and it is allowed by the hw (width is a multiple of 16). | |||
* Avoid doing this for GPUs with MC1.0, as kernel sources | |||
* indicate the tile status module bypasses the memory | |||
* offset and MMU. */ | |||
/* XXX for now, don't do TS for render textures as this path | |||
* is not stable. */ | |||
if (VIV_FEATURE(ctx->screen, chipFeatures, FAST_CLEAR) && | |||
VIV_FEATURE(ctx->screen, chipMinorFeatures0, MC20) && | |||
!DBG_ENABLED(ETNA_DBG_NO_TS) && !rsc->ts_bo && | |||
!(rsc->base.bind & (PIPE_BIND_SAMPLER_VIEW)) && | |||
(rsc->levels[level].padded_width & ETNA_RS_WIDTH_MASK) == 0 && | |||
(rsc->levels[level].padded_height & ETNA_RS_HEIGHT_MASK) == 0) { | |||
etna_screen_resource_alloc_ts(pctx->screen, rsc); | |||
} | |||
surf->base.texture = &rsc->base; | |||
surf->base.format = rsc->base.format; | |||
surf->base.width = rsc->levels[level].width; | |||
surf->base.height = rsc->levels[level].height; | |||
surf->base.writable = templat->writable; /* what is this for anyway */ | |||
surf->base.u = templat->u; | |||
surf->level = &rsc->levels[level]; /* Keep pointer to actual level to set | |||
* clear color on underlying resource | |||
* instead of surface */ | |||
surf->surf = rsc->levels [level]; /* Make copy of level to narrow down | |||
* address to layer */ | |||
/* XXX we don't really need a copy but it's convenient */ | |||
surf->surf.offset += layer * surf->surf.layer_stride; | |||
struct etna_resource_level *lev = &rsc->levels[level]; | |||
/* Setup template relocations for this surface */ | |||
surf->reloc[0].bo = rsc->bo; | |||
surf->reloc[0].offset = surf->surf.offset; | |||
surf->reloc[0].flags = 0; | |||
surf->reloc[1].bo = rsc->bo; | |||
surf->reloc[1].offset = surf->surf.offset + lev->stride * lev->padded_height / 2; | |||
surf->reloc[1].flags = 0; | |||
if (surf->surf.ts_size) { | |||
unsigned int layer_offset = layer * surf->surf.ts_layer_stride; | |||
assert(layer_offset < surf->surf.ts_size); | |||
surf->surf.ts_offset += layer_offset; | |||
surf->surf.ts_size -= layer_offset; | |||
surf->ts_reloc.bo = rsc->ts_bo; | |||
surf->ts_reloc.offset = surf->surf.ts_offset; | |||
surf->ts_reloc.flags = 0; | |||
/* This (ab)uses the RS as a plain buffer memset(). | |||
* Currently uses a fixed row size of 64 bytes. Some benchmarking with | |||
* different sizes may be in order. */ | |||
struct etna_bo *ts_bo = etna_resource(surf->base.texture)->ts_bo; | |||
etna_compile_rs_state(ctx, &surf->clear_command, &(struct rs_state) { | |||
.source_format = RS_FORMAT_A8R8G8B8, | |||
.dest_format = RS_FORMAT_A8R8G8B8, | |||
.dest = ts_bo, | |||
.dest_offset = surf->surf.ts_offset, | |||
.dest_stride = 0x40, | |||
.dest_tiling = ETNA_LAYOUT_TILED, | |||
.dither = {0xffffffff, 0xffffffff}, | |||
.width = 16, | |||
.height = etna_align_up(surf->surf.ts_size / 0x40, 4), | |||
.clear_value = {ctx->specs.ts_clear_value}, | |||
.clear_mode = VIVS_RS_CLEAR_CONTROL_MODE_ENABLED1, | |||
.clear_bits = 0xffff | |||
}); | |||
} else { | |||
etna_rs_gen_clear_surface(ctx, surf, surf->level->clear_value); | |||
} | |||
return &surf->base; | |||
} | |||
static void | |||
etna_surface_destroy(struct pipe_context *pctx, struct pipe_surface *psurf) | |||
{ | |||
pipe_resource_reference(&psurf->texture, NULL); | |||
FREE(psurf); | |||
} | |||
void | |||
etna_surface_init(struct pipe_context *pctx) | |||
{ | |||
pctx->create_surface = etna_create_surface; | |||
pctx->surface_destroy = etna_surface_destroy; | |||
} |
@@ -0,0 +1,55 @@ | |||
/* | |||
* Copyright (c) 2012-2015 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Wladimir J. van der Laan <laanwj@gmail.com> | |||
*/ | |||
#ifndef H_ETNAVIV_SURFACE | |||
#define H_ETNAVIV_SURFACE | |||
#include "etnaviv_resource.h" | |||
#include "etnaviv_rs.h" | |||
#include "etnaviv_tiling.h" | |||
#include "pipe/p_state.h" | |||
struct etna_surface { | |||
struct pipe_surface base; | |||
struct etna_resource_level surf; | |||
struct compiled_rs_state clear_command; | |||
/* Keep pointer to resource level, for fast clear */ | |||
struct etna_resource_level *level; | |||
struct etna_reloc reloc[ETNA_MAX_PIXELPIPES]; | |||
struct etna_reloc ts_reloc; | |||
}; | |||
static inline struct etna_surface * | |||
etna_surface(struct pipe_surface *p) | |||
{ | |||
return (struct etna_surface *)p; | |||
} | |||
void | |||
etna_surface_init(struct pipe_context *pctx); | |||
#endif |
@@ -0,0 +1,338 @@ | |||
/* | |||
* Copyright (c) 2012-2015 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Wladimir J. van der Laan <laanwj@gmail.com> | |||
*/ | |||
#include "etnaviv_texture.h" | |||
#include "hw/common.xml.h" | |||
#include "etnaviv_clear_blit.h" | |||
#include "etnaviv_context.h" | |||
#include "etnaviv_emit.h" | |||
#include "etnaviv_format.h" | |||
#include "etnaviv_translate.h" | |||
#include "util/u_inlines.h" | |||
#include "util/u_memory.h" | |||
static void * | |||
etna_create_sampler_state(struct pipe_context *pipe, | |||
const struct pipe_sampler_state *ss) | |||
{ | |||
struct etna_sampler_state *cs = CALLOC_STRUCT(etna_sampler_state); | |||
if (!cs) | |||
return NULL; | |||
cs->TE_SAMPLER_CONFIG0 = | |||
VIVS_TE_SAMPLER_CONFIG0_UWRAP(translate_texture_wrapmode(ss->wrap_s)) | | |||
VIVS_TE_SAMPLER_CONFIG0_VWRAP(translate_texture_wrapmode(ss->wrap_t)) | | |||
VIVS_TE_SAMPLER_CONFIG0_MIN(translate_texture_filter(ss->min_img_filter)) | | |||
VIVS_TE_SAMPLER_CONFIG0_MIP(translate_texture_mipfilter(ss->min_mip_filter)) | | |||
VIVS_TE_SAMPLER_CONFIG0_MAG(translate_texture_filter(ss->mag_img_filter)) | | |||
COND(ss->normalized_coords, VIVS_TE_SAMPLER_CONFIG0_ROUND_UV); | |||
cs->TE_SAMPLER_CONFIG1 = 0; /* VIVS_TE_SAMPLER_CONFIG1 (swizzle, extended | |||
format) fully determined by sampler view */ | |||
cs->TE_SAMPLER_LOD_CONFIG = | |||
COND(ss->lod_bias != 0.0, VIVS_TE_SAMPLER_LOD_CONFIG_BIAS_ENABLE) | | |||
VIVS_TE_SAMPLER_LOD_CONFIG_BIAS(etna_float_to_fixp55(ss->lod_bias)); | |||
if (ss->min_mip_filter != PIPE_TEX_MIPFILTER_NONE) { | |||
cs->min_lod = etna_float_to_fixp55(ss->min_lod); | |||
cs->max_lod = etna_float_to_fixp55(ss->max_lod); | |||
} else { | |||
/* when not mipmapping, we need to set max/min lod so that always | |||
* lowest LOD is selected */ | |||
cs->min_lod = cs->max_lod = etna_float_to_fixp55(ss->min_lod); | |||
} | |||
return cs; | |||
} | |||
static void | |||
etna_bind_sampler_states(struct pipe_context *pctx, unsigned shader, | |||
unsigned start_slot, unsigned num_samplers, | |||
void **samplers) | |||
{ | |||
/* bind fragment sampler */ | |||
struct etna_context *ctx = etna_context(pctx); | |||
int offset; | |||
switch (shader) { | |||
case PIPE_SHADER_FRAGMENT: | |||
offset = 0; | |||
ctx->num_fragment_samplers = num_samplers; | |||
break; | |||
case PIPE_SHADER_VERTEX: | |||
offset = ctx->specs.vertex_sampler_offset; | |||
break; | |||
default: | |||
assert(!"Invalid shader"); | |||
return; | |||
} | |||
uint32_t mask = 1 << offset; | |||
for (int idx = 0; idx < num_samplers; ++idx, mask <<= 1) { | |||
ctx->sampler[offset + idx] = samplers[idx]; | |||
if (samplers[idx]) | |||
ctx->active_samplers |= mask; | |||
else | |||
ctx->active_samplers &= ~mask; | |||
} | |||
ctx->dirty |= ETNA_DIRTY_SAMPLERS; | |||
} | |||
static void | |||
etna_delete_sampler_state(struct pipe_context *pctx, void *ss) | |||
{ | |||
FREE(ss); | |||
} | |||
static void | |||
etna_update_sampler_source(struct pipe_sampler_view *view) | |||
{ | |||
struct etna_resource *res = etna_resource(view->texture); | |||
if (res->texture && etna_resource_older(etna_resource(res->texture), res)) { | |||
/* Texture is older than render buffer, copy the texture using RS */ | |||
etna_copy_resource(view->context, res->texture, view->texture, 0, | |||
view->texture->last_level); | |||
etna_resource(res->texture)->seqno = res->seqno; | |||
} | |||
} | |||
static bool | |||
etna_resource_sampler_compatible(struct etna_resource *res) | |||
{ | |||
if (util_format_is_compressed(res->base.format)) | |||
return true; | |||
/* The sampler (as we currently know it) only accepts tiled layouts */ | |||
if (res->layout != ETNA_LAYOUT_TILED) | |||
return false; | |||
/* If we have HALIGN support, we can allow for the RS padding */ | |||
struct etna_screen *screen = etna_screen(res->base.screen); | |||
if (VIV_FEATURE(screen, chipMinorFeatures1, TEXTURE_HALIGN)) | |||
return true; | |||
/* Non-HALIGN GPUs only accept 4x4 tile-aligned textures */ | |||
if (res->halign != TEXTURE_HALIGN_FOUR) | |||
return false; | |||
return true; | |||
} | |||
static struct pipe_sampler_view * | |||
etna_create_sampler_view(struct pipe_context *pctx, struct pipe_resource *prsc, | |||
const struct pipe_sampler_view *so) | |||
{ | |||
struct etna_sampler_view *sv = CALLOC_STRUCT(etna_sampler_view); | |||
struct etna_resource *res = etna_resource(prsc); | |||
struct etna_context *ctx = etna_context(pctx); | |||
if (!sv) | |||
return NULL; | |||
if (!etna_resource_sampler_compatible(res)) { | |||
/* The original resource is not compatible with the sampler. | |||
* Allocate an appropriately tiled texture. */ | |||
if (!res->texture) { | |||
struct pipe_resource templat = *prsc; | |||
templat.bind &= ~(PIPE_BIND_DEPTH_STENCIL | PIPE_BIND_RENDER_TARGET | | |||
PIPE_BIND_BLENDABLE); | |||
res->texture = | |||
etna_resource_alloc(pctx->screen, ETNA_LAYOUT_TILED, &templat); | |||
} | |||
if (!res->texture) { | |||
free(sv); | |||
return NULL; | |||
} | |||
res = etna_resource(res->texture); | |||
} | |||
sv->base = *so; | |||
pipe_reference(NULL, &prsc->reference); | |||
sv->base.texture = prsc; | |||
sv->base.reference.count = 1; | |||
sv->base.context = pctx; | |||
/* merged with sampler state */ | |||
sv->TE_SAMPLER_CONFIG0 = | |||
VIVS_TE_SAMPLER_CONFIG0_FORMAT(translate_texture_format(sv->base.format)); | |||
sv->TE_SAMPLER_CONFIG0_MASK = 0xffffffff; | |||
switch (sv->base.target) { | |||
case PIPE_TEXTURE_1D: | |||
/* For 1D textures, we will have a height of 1, so we can use 2D | |||
* but set T wrap to repeat */ | |||
sv->TE_SAMPLER_CONFIG0_MASK = ~VIVS_TE_SAMPLER_CONFIG0_VWRAP__MASK; | |||
sv->TE_SAMPLER_CONFIG0 |= VIVS_TE_SAMPLER_CONFIG0_VWRAP(TEXTURE_WRAPMODE_REPEAT); | |||
case PIPE_TEXTURE_2D: | |||
case PIPE_TEXTURE_RECT: | |||
sv->TE_SAMPLER_CONFIG0 |= VIVS_TE_SAMPLER_CONFIG0_TYPE(TEXTURE_TYPE_2D); | |||
break; | |||
case PIPE_TEXTURE_CUBE: | |||
sv->TE_SAMPLER_CONFIG0 |= VIVS_TE_SAMPLER_CONFIG0_TYPE(TEXTURE_TYPE_CUBE_MAP); | |||
break; | |||
default: | |||
BUG("Unhandled texture target"); | |||
free(sv); | |||
return NULL; | |||
} | |||
sv->TE_SAMPLER_CONFIG1 = VIVS_TE_SAMPLER_CONFIG1_SWIZZLE_R(so->swizzle_r) | | |||
VIVS_TE_SAMPLER_CONFIG1_SWIZZLE_G(so->swizzle_g) | | |||
VIVS_TE_SAMPLER_CONFIG1_SWIZZLE_B(so->swizzle_b) | | |||
VIVS_TE_SAMPLER_CONFIG1_SWIZZLE_A(so->swizzle_a) | | |||
VIVS_TE_SAMPLER_CONFIG1_HALIGN(res->halign); | |||
sv->TE_SAMPLER_SIZE = VIVS_TE_SAMPLER_SIZE_WIDTH(res->base.width0) | | |||
VIVS_TE_SAMPLER_SIZE_HEIGHT(res->base.height0); | |||
sv->TE_SAMPLER_LOG_SIZE = | |||
VIVS_TE_SAMPLER_LOG_SIZE_WIDTH(etna_log2_fixp55(res->base.width0)) | | |||
VIVS_TE_SAMPLER_LOG_SIZE_HEIGHT(etna_log2_fixp55(res->base.height0)); | |||
/* Set up levels-of-detail */ | |||
for (int lod = 0; lod <= res->base.last_level; ++lod) { | |||
sv->TE_SAMPLER_LOD_ADDR[lod].bo = res->bo; | |||
sv->TE_SAMPLER_LOD_ADDR[lod].offset = res->levels[lod].offset; | |||
sv->TE_SAMPLER_LOD_ADDR[lod].flags = ETNA_RELOC_READ; | |||
} | |||
sv->min_lod = sv->base.u.tex.first_level << 5; | |||
sv->max_lod = MIN2(sv->base.u.tex.last_level, res->base.last_level) << 5; | |||
/* Workaround for npot textures -- it appears that only CLAMP_TO_EDGE is | |||
* supported when the appropriate capability is not set. */ | |||
if (!ctx->specs.npot_tex_any_wrap && | |||
(!util_is_power_of_two(res->base.width0) || !util_is_power_of_two(res->base.height0))) { | |||
sv->TE_SAMPLER_CONFIG0_MASK = ~(VIVS_TE_SAMPLER_CONFIG0_UWRAP__MASK | | |||
VIVS_TE_SAMPLER_CONFIG0_VWRAP__MASK); | |||
sv->TE_SAMPLER_CONFIG0 |= | |||
VIVS_TE_SAMPLER_CONFIG0_UWRAP(TEXTURE_WRAPMODE_CLAMP_TO_EDGE) | | |||
VIVS_TE_SAMPLER_CONFIG0_VWRAP(TEXTURE_WRAPMODE_CLAMP_TO_EDGE); | |||
} | |||
return &sv->base; | |||
} | |||
static void | |||
etna_sampler_view_destroy(struct pipe_context *pctx, | |||
struct pipe_sampler_view *view) | |||
{ | |||
pipe_resource_reference(&view->texture, NULL); | |||
FREE(view); | |||
} | |||
static void | |||
set_sampler_views(struct etna_context *ctx, unsigned start, unsigned end, | |||
unsigned nr, struct pipe_sampler_view **views) | |||
{ | |||
unsigned i, j; | |||
uint32_t mask = 1 << start; | |||
for (i = start, j = 0; j < nr; i++, j++, mask <<= 1) { | |||
pipe_sampler_view_reference(&ctx->sampler_view[i], views[j]); | |||
if (views[j]) | |||
ctx->active_sampler_views |= mask; | |||
else | |||
ctx->active_sampler_views &= ~mask; | |||
} | |||
for (; i < end; i++, mask <<= 1) { | |||
pipe_sampler_view_reference(&ctx->sampler_view[i], NULL); | |||
ctx->active_sampler_views &= ~mask; | |||
} | |||
} | |||
static inline void | |||
etna_fragtex_set_sampler_views(struct etna_context *ctx, unsigned nr, | |||
struct pipe_sampler_view **views) | |||
{ | |||
unsigned start = 0; | |||
unsigned end = start + ctx->specs.fragment_sampler_count; | |||
set_sampler_views(ctx, start, end, nr, views); | |||
ctx->num_fragment_sampler_views = nr; | |||
} | |||
static inline void | |||
etna_vertex_set_sampler_views(struct etna_context *ctx, unsigned nr, | |||
struct pipe_sampler_view **views) | |||
{ | |||
unsigned start = ctx->specs.vertex_sampler_offset; | |||
unsigned end = start + ctx->specs.vertex_sampler_count; | |||
set_sampler_views(ctx, start, end, nr, views); | |||
} | |||
static void | |||
etna_set_sampler_views(struct pipe_context *pctx, unsigned shader, | |||
unsigned start_slot, unsigned num_views, | |||
struct pipe_sampler_view **views) | |||
{ | |||
struct etna_context *ctx = etna_context(pctx); | |||
assert(start_slot == 0); | |||
ctx->dirty |= ETNA_DIRTY_SAMPLER_VIEWS | ETNA_DIRTY_TEXTURE_CACHES; | |||
for (unsigned idx = 0; idx < num_views; ++idx) { | |||
if (views[idx]) | |||
etna_update_sampler_source(views[idx]); | |||
} | |||
switch (shader) { | |||
case PIPE_SHADER_FRAGMENT: | |||
etna_fragtex_set_sampler_views(ctx, num_views, views); | |||
break; | |||
case PIPE_SHADER_VERTEX: | |||
etna_vertex_set_sampler_views(ctx, num_views, views); | |||
break; | |||
default:; | |||
} | |||
} | |||
static void | |||
etna_texture_barrier(struct pipe_context *pctx) | |||
{ | |||
struct etna_context *ctx = etna_context(pctx); | |||
/* clear color and texture cache to make sure that texture unit reads | |||
* what has been written */ | |||
etna_set_state(ctx->stream, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_TEXTURE); | |||
} | |||
void | |||
etna_texture_init(struct pipe_context *pctx) | |||
{ | |||
pctx->create_sampler_state = etna_create_sampler_state; | |||
pctx->bind_sampler_states = etna_bind_sampler_states; | |||
pctx->delete_sampler_state = etna_delete_sampler_state; | |||
pctx->set_sampler_views = etna_set_sampler_views; | |||
pctx->create_sampler_view = etna_create_sampler_view; | |||
pctx->sampler_view_destroy = etna_sampler_view_destroy; | |||
pctx->texture_barrier = etna_texture_barrier; | |||
} |
@@ -0,0 +1,75 @@ | |||
/* | |||
* Copyright (c) 2012-2015 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Wladimir J. van der Laan <laanwj@gmail.com> | |||
*/ | |||
#ifndef H_ETNAVIV_TEXTURE | |||
#define H_ETNAVIV_TEXTURE | |||
#include <etnaviv_drmif.h> | |||
#include "pipe/p_context.h" | |||
#include "pipe/p_state.h" | |||
#include "hw/state_3d.xml.h" | |||
struct etna_sampler_state { | |||
struct pipe_sampler_state base; | |||
/* sampler offset +4*sampler, interleave when committing state */ | |||
uint32_t TE_SAMPLER_CONFIG0; | |||
uint32_t TE_SAMPLER_CONFIG1; | |||
uint32_t TE_SAMPLER_LOD_CONFIG; | |||
unsigned min_lod, max_lod; | |||
}; | |||
static inline struct etna_sampler_state * | |||
etna_sampler_state(struct pipe_sampler_state *samp) | |||
{ | |||
return (struct etna_sampler_state *)samp; | |||
} | |||
struct etna_sampler_view { | |||
struct pipe_sampler_view base; | |||
/* sampler offset +4*sampler, interleave when committing state */ | |||
uint32_t TE_SAMPLER_CONFIG0; | |||
uint32_t TE_SAMPLER_CONFIG0_MASK; | |||
uint32_t TE_SAMPLER_CONFIG1; | |||
uint32_t TE_SAMPLER_SIZE; | |||
uint32_t TE_SAMPLER_LOG_SIZE; | |||
struct etna_reloc TE_SAMPLER_LOD_ADDR[VIVS_TE_SAMPLER_LOD_ADDR__LEN]; | |||
unsigned min_lod, max_lod; /* 5.5 fixp */ | |||
}; | |||
static inline struct etna_sampler_view * | |||
etna_sampler_view(struct pipe_sampler_view *view) | |||
{ | |||
return (struct etna_sampler_view *)view; | |||
} | |||
void | |||
etna_texture_init(struct pipe_context *pctx); | |||
#endif |
@@ -0,0 +1,96 @@ | |||
/* | |||
* Copyright (c) 2012-2015 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Wladimir J. van der Laan <laanwj@gmail.com> | |||
*/ | |||
#include "etnaviv_tiling.h" | |||
#include <stdint.h> | |||
#include <stdio.h> | |||
#define TEX_TILE_WIDTH (4) | |||
#define TEX_TILE_HEIGHT (4) | |||
#define TEX_TILE_WORDS (TEX_TILE_WIDTH * TEX_TILE_HEIGHT) | |||
#define DO_TILE(type) \ | |||
src_stride /= sizeof(type); \ | |||
dst_stride = (dst_stride * TEX_TILE_HEIGHT) / sizeof(type); \ | |||
for (unsigned srcy = 0; srcy < height; ++srcy) { \ | |||
unsigned dsty = basey + srcy; \ | |||
unsigned ty = (dsty / TEX_TILE_HEIGHT) * dst_stride + \ | |||
(dsty % TEX_TILE_HEIGHT) * TEX_TILE_WIDTH; \ | |||
for (unsigned srcx = 0; srcx < width; ++srcx) { \ | |||
unsigned dstx = basex + srcx; \ | |||
((type *)dest)[ty + (dstx / TEX_TILE_WIDTH) * TEX_TILE_WORDS + \ | |||
(dstx % TEX_TILE_WIDTH)] = \ | |||
((type *)src)[srcy * src_stride + srcx]; \ | |||
} \ | |||
} | |||
#define DO_UNTILE(type) \ | |||
src_stride = (src_stride * TEX_TILE_HEIGHT) / sizeof(type); \ | |||
dst_stride /= sizeof(type); \ | |||
for (unsigned dsty = 0; dsty < height; ++dsty) { \ | |||
unsigned srcy = basey + dsty; \ | |||
unsigned sy = (srcy / TEX_TILE_HEIGHT) * src_stride + \ | |||
(srcy % TEX_TILE_HEIGHT) * TEX_TILE_WIDTH; \ | |||
for (unsigned dstx = 0; dstx < width; ++dstx) { \ | |||
unsigned srcx = basex + dstx; \ | |||
((type *)dest)[dsty * dst_stride + dstx] = \ | |||
((type *)src)[sy + (srcx / TEX_TILE_WIDTH) * TEX_TILE_WORDS + \ | |||
(srcx % TEX_TILE_WIDTH)]; \ | |||
} \ | |||
} | |||
void | |||
etna_texture_tile(void *dest, void *src, unsigned basex, unsigned basey, | |||
unsigned dst_stride, unsigned width, unsigned height, | |||
unsigned src_stride, unsigned elmtsize) | |||
{ | |||
if (elmtsize == 4) { | |||
DO_TILE(uint32_t) | |||
} else if (elmtsize == 2) { | |||
DO_TILE(uint16_t) | |||
} else if (elmtsize == 1) { | |||
DO_TILE(uint8_t) | |||
} else { | |||
printf("etna_texture_tile: unhandled element size %i\n", elmtsize); | |||
} | |||
} | |||
void | |||
etna_texture_untile(void *dest, void *src, unsigned basex, unsigned basey, | |||
unsigned src_stride, unsigned width, unsigned height, | |||
unsigned dst_stride, unsigned elmtsize) | |||
{ | |||
if (elmtsize == 4) { | |||
DO_UNTILE(uint32_t); | |||
} else if (elmtsize == 2) { | |||
DO_UNTILE(uint16_t); | |||
} else if (elmtsize == 1) { | |||
DO_UNTILE(uint8_t); | |||
} else { | |||
printf("etna_texture_tile: unhandled element size %i\n", elmtsize); | |||
} | |||
} |
@@ -0,0 +1,56 @@ | |||
/* | |||
* Copyright (c) 2012-2015 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Wladimir J. van der Laan <laanwj@gmail.com> | |||
*/ | |||
#ifndef H_ETNAVIV_TILING | |||
#define H_ETNAVIV_TILING | |||
#include <stdint.h> | |||
/* texture or surface layout */ | |||
enum etna_surface_layout { | |||
ETNA_LAYOUT_BIT_TILE = (1 << 0), | |||
ETNA_LAYOUT_BIT_SUPER = (1 << 1), | |||
ETNA_LAYOUT_BIT_MULTI = (1 << 2), | |||
ETNA_LAYOUT_LINEAR = 0, | |||
ETNA_LAYOUT_TILED = ETNA_LAYOUT_BIT_TILE, | |||
ETNA_LAYOUT_SUPER_TILED = ETNA_LAYOUT_BIT_TILE | ETNA_LAYOUT_BIT_SUPER, | |||
ETNA_LAYOUT_MULTI_TILED = ETNA_LAYOUT_BIT_TILE | ETNA_LAYOUT_BIT_MULTI, | |||
ETNA_LAYOUT_MULTI_SUPERTILED = ETNA_LAYOUT_BIT_TILE | ETNA_LAYOUT_BIT_SUPER | ETNA_LAYOUT_BIT_MULTI, | |||
}; | |||
void | |||
etna_texture_tile(void *dest, void *src, unsigned basex, unsigned basey, | |||
unsigned dst_stride, unsigned width, unsigned height, | |||
unsigned src_stride, unsigned elmtsize); | |||
void | |||
etna_texture_untile(void *dest, void *src, unsigned basex, unsigned basey, | |||
unsigned src_stride, unsigned width, unsigned height, | |||
unsigned dst_stride, unsigned elmtsize); | |||
/* XXX from/to supertiling (can have different layouts, may be better | |||
* to leave to RS) */ | |||
#endif |
@@ -0,0 +1,355 @@ | |||
/* | |||
* Copyright (c) 2012-2015 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Wladimir J. van der Laan <laanwj@gmail.com> | |||
*/ | |||
#include "etnaviv_transfer.h" | |||
#include "etnaviv_clear_blit.h" | |||
#include "etnaviv_context.h" | |||
#include "etnaviv_debug.h" | |||
#include "pipe/p_defines.h" | |||
#include "pipe/p_format.h" | |||
#include "pipe/p_screen.h" | |||
#include "pipe/p_state.h" | |||
#include "util/u_format.h" | |||
#include "util/u_inlines.h" | |||
#include "util/u_memory.h" | |||
#include "util/u_surface.h" | |||
#include "util/u_transfer.h" | |||
/* Compute offset into a 1D/2D/3D buffer of a certain box. | |||
* This box must be aligned to the block width and height of the | |||
* underlying format. */ | |||
static inline size_t | |||
etna_compute_offset(enum pipe_format format, const struct pipe_box *box, | |||
size_t stride, size_t layer_stride) | |||
{ | |||
return box->z * layer_stride + | |||
box->y / util_format_get_blockheight(format) * stride + | |||
box->x / util_format_get_blockwidth(format) * | |||
util_format_get_blocksize(format); | |||
} | |||
static void | |||
etna_transfer_unmap(struct pipe_context *pctx, struct pipe_transfer *ptrans) | |||
{ | |||
struct etna_context *ctx = etna_context(pctx); | |||
struct etna_transfer *trans = etna_transfer(ptrans); | |||
struct etna_resource *rsc = etna_resource(ptrans->resource); | |||
/* XXX | |||
* When writing to a resource that is already in use, replace the resource | |||
* with a completely new buffer | |||
* and free the old one using a fenced free. | |||
* The most tricky case to implement will be: tiled or supertiled surface, | |||
* partial write, target not aligned to 4/64. */ | |||
assert(ptrans->level <= rsc->base.last_level); | |||
if (rsc->texture && !etna_resource_newer(rsc, etna_resource(rsc->texture))) | |||
rsc = etna_resource(rsc->texture); /* switch to using the texture resource */ | |||
if (ptrans->usage & PIPE_TRANSFER_WRITE) { | |||
if (trans->rsc) { | |||
/* We have a temporary resource due to either tile status or | |||
* tiling format. Write back the updated buffer contents. | |||
* FIXME: we need to invalidate the tile status. */ | |||
etna_copy_resource(pctx, ptrans->resource, trans->rsc, ptrans->level, | |||
trans->rsc->last_level); | |||
} else if (trans->staging) { | |||
/* map buffer object */ | |||
struct etna_resource_level *res_level = &rsc->levels[ptrans->level]; | |||
void *mapped = etna_bo_map(rsc->bo) + res_level->offset; | |||
if (rsc->layout == ETNA_LAYOUT_LINEAR || rsc->layout == ETNA_LAYOUT_TILED) { | |||
if (rsc->layout == ETNA_LAYOUT_TILED && !util_format_is_compressed(rsc->base.format)) { | |||
etna_texture_tile( | |||
mapped + ptrans->box.z * res_level->layer_stride, | |||
trans->staging, ptrans->box.x, ptrans->box.y, | |||
res_level->stride, ptrans->box.width, ptrans->box.height, | |||
ptrans->stride, util_format_get_blocksize(rsc->base.format)); | |||
} else { /* non-tiled or compressed format */ | |||
util_copy_box(mapped, rsc->base.format, res_level->stride, | |||
res_level->layer_stride, ptrans->box.x, | |||
ptrans->box.y, ptrans->box.z, ptrans->box.width, | |||
ptrans->box.height, ptrans->box.depth, | |||
trans->staging, ptrans->stride, | |||
ptrans->layer_stride, 0, 0, 0 /* src x,y,z */); | |||
} | |||
} else { | |||
BUG("unsupported tiling %i", rsc->layout); | |||
} | |||
FREE(trans->staging); | |||
} | |||
rsc->seqno++; | |||
etna_bo_cpu_fini(rsc->bo); | |||
if (rsc->base.bind & PIPE_BIND_SAMPLER_VIEW) { | |||
/* XXX do we need to flush the CPU cache too or start a write barrier | |||
* to make sure the GPU sees it? */ | |||
ctx->dirty |= ETNA_DIRTY_TEXTURE_CACHES; | |||
} | |||
} | |||
pipe_resource_reference(&trans->rsc, NULL); | |||
pipe_resource_reference(&ptrans->resource, NULL); | |||
slab_free(&ctx->transfer_pool, trans); | |||
} | |||
static void * | |||
etna_transfer_map(struct pipe_context *pctx, struct pipe_resource *prsc, | |||
unsigned level, | |||
unsigned usage, | |||
const struct pipe_box *box, | |||
struct pipe_transfer **out_transfer) | |||
{ | |||
struct etna_context *ctx = etna_context(pctx); | |||
struct etna_resource *rsc = etna_resource(prsc); | |||
struct etna_transfer *trans; | |||
struct pipe_transfer *ptrans; | |||
enum pipe_format format = prsc->format; | |||
trans = slab_alloc(&ctx->transfer_pool); | |||
if (!trans) | |||
return NULL; | |||
/* slab_alloc() doesn't zero */ | |||
memset(trans, 0, sizeof(*trans)); | |||
ptrans = &trans->base; | |||
pipe_resource_reference(&ptrans->resource, prsc); | |||
ptrans->level = level; | |||
ptrans->usage = usage; | |||
ptrans->box = *box; | |||
assert(level <= prsc->last_level); | |||
if (rsc->texture && !etna_resource_newer(rsc, etna_resource(rsc->texture))) { | |||
/* We have a texture resource which is the same age or newer than the | |||
* render resource. Use the texture resource, which avoids bouncing | |||
* pixels between the two resources, and we can de-tile it in s/w. */ | |||
rsc = etna_resource(rsc->texture); | |||
} else if (rsc->ts_bo || | |||
(rsc->layout != ETNA_LAYOUT_LINEAR && | |||
util_format_get_blocksize(format) > 1 && | |||
/* HALIGN 4 resources are incompatible with the resolve engine, | |||
* so fall back to using software to detile this resource. */ | |||
rsc->halign != TEXTURE_HALIGN_FOUR)) { | |||
/* If the surface has tile status, we need to resolve it first. | |||
* The strategy we implement here is to use the RS to copy the | |||
* depth buffer, filling in the "holes" where the tile status | |||
* indicates that it's clear. We also do this for tiled | |||
* resources, but only if the RS can blit them. */ | |||
if (usage & PIPE_TRANSFER_MAP_DIRECTLY) { | |||
slab_free(&ctx->transfer_pool, trans); | |||
BUG("unsupported transfer flags %#x with tile status/tiled layout", usage); | |||
return NULL; | |||
} | |||
if (prsc->depth0 > 1) { | |||
slab_free(&ctx->transfer_pool, trans); | |||
BUG("resource has depth >1 with tile status"); | |||
return NULL; | |||
} | |||
struct pipe_resource templ = *prsc; | |||
templ.nr_samples = 0; | |||
templ.bind = PIPE_BIND_RENDER_TARGET; | |||
trans->rsc = etna_resource_alloc(pctx->screen, ETNA_LAYOUT_LINEAR, &templ); | |||
if (!trans->rsc) { | |||
slab_free(&ctx->transfer_pool, trans); | |||
return NULL; | |||
} | |||
etna_copy_resource(pctx, trans->rsc, prsc, level, trans->rsc->last_level); | |||
/* Switch to using the temporary resource instead */ | |||
rsc = etna_resource(trans->rsc); | |||
} | |||
struct etna_resource_level *res_level = &rsc->levels[level]; | |||
/* Always sync if we have the temporary resource. The PIPE_TRANSFER_READ | |||
* case could be optimised if we knew whether the resource has outstanding | |||
* rendering. */ | |||
if (usage & PIPE_TRANSFER_READ || trans->rsc) | |||
etna_resource_wait(pctx, rsc); | |||
/* XXX we don't handle PIPE_TRANSFER_FLUSH_EXPLICIT; this flag can be ignored | |||
* when mapping in-place, | |||
* but when not in place we need to fire off the copy operation in | |||
* transfer_flush_region (currently | |||
* a no-op) instead of unmap. Need to handle this to support | |||
* ARB_map_buffer_range extension at least. | |||
*/ | |||
/* XXX we don't take care of current operations on the resource; which can | |||
be, at some point in the pipeline | |||
which is not yet executed: | |||
- bound as surface | |||
- bound through vertex buffer | |||
- bound through index buffer | |||
- bound in sampler view | |||
- used in clear_render_target / clear_depth_stencil operation | |||
- used in blit | |||
- used in resource_copy_region | |||
How do other drivers record this information over course of the rendering | |||
pipeline? | |||
Is it necessary at all? Only in case we want to provide a fast path and | |||
map the resource directly | |||
(and for PIPE_TRANSFER_MAP_DIRECTLY) and we don't want to force a sync. | |||
We also need to know whether the resource is in use to determine if a sync | |||
is needed (or just do it | |||
always, but that comes at the expense of performance). | |||
A conservative approximation without too much overhead would be to mark | |||
all resources that have | |||
been bound at some point as busy. A drawback would be that accessing | |||
resources that have | |||
been bound but are no longer in use for a while still carry a performance | |||
penalty. On the other hand, | |||
the program could be using PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE or | |||
PIPE_TRANSFER_UNSYNCHRONIZED to | |||
avoid this in the first place... | |||
A) We use an in-pipe copy engine, and queue the copy operation after unmap | |||
so that the copy | |||
will be performed when all current commands have been executed. | |||
Using the RS is possible, not sure if always efficient. This can also | |||
do any kind of tiling for us. | |||
Only possible when PIPE_TRANSFER_DISCARD_RANGE is set. | |||
B) We discard the entire resource (or at least, the mipmap level) and | |||
allocate new memory for it. | |||
Only possible when mapping the entire resource or | |||
PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE is set. | |||
*/ | |||
/* No need to allocate a buffer for copying if the resource is not in use, | |||
* and no tiling is needed, can just return a direct pointer. | |||
*/ | |||
bool in_place = rsc->layout == ETNA_LAYOUT_LINEAR || | |||
(rsc->layout == ETNA_LAYOUT_TILED && | |||
util_format_is_compressed(prsc->format)); | |||
/* Ignore PIPE_TRANSFER_UNSYNCHRONIZED and PIPE_TRANSFER_DONTBLOCK here. | |||
* It appears that Gallium operates the index/vertex buffers in a | |||
* circular fashion, and the CPU can catch up with the GPU and starts | |||
* overwriting yet-to-be-processed entries, causing rendering corruption. */ | |||
uint32_t prep_flags = 0; | |||
if (usage & PIPE_TRANSFER_READ) | |||
prep_flags |= DRM_ETNA_PREP_READ; | |||
if (usage & PIPE_TRANSFER_WRITE) | |||
prep_flags |= DRM_ETNA_PREP_WRITE; | |||
if (etna_bo_cpu_prep(rsc->bo, prep_flags)) | |||
goto fail_prep; | |||
/* map buffer object */ | |||
void *mapped = etna_bo_map(rsc->bo); | |||
if (!mapped) | |||
goto fail; | |||
*out_transfer = ptrans; | |||
if (in_place) { | |||
ptrans->stride = res_level->stride; | |||
ptrans->layer_stride = res_level->layer_stride; | |||
return mapped + res_level->offset + | |||
etna_compute_offset(prsc->format, box, res_level->stride, | |||
res_level->layer_stride); | |||
} else { | |||
unsigned divSizeX = util_format_get_blockwidth(format); | |||
unsigned divSizeY = util_format_get_blockheight(format); | |||
/* No direct mappings of tiled, since we need to manually | |||
* tile/untile. | |||
*/ | |||
if (usage & PIPE_TRANSFER_MAP_DIRECTLY) | |||
goto fail; | |||
mapped += res_level->offset; | |||
ptrans->stride = align(box->width, divSizeX) * util_format_get_blocksize(format); /* row stride in bytes */ | |||
ptrans->layer_stride = align(box->height, divSizeY) * ptrans->stride; | |||
size_t size = ptrans->layer_stride * box->depth; | |||
trans->staging = MALLOC(size); | |||
if (!trans->staging) | |||
goto fail; | |||
if (usage & PIPE_TRANSFER_READ) { | |||
/* untile or copy resource for reading */ | |||
if (rsc->layout == ETNA_LAYOUT_LINEAR || rsc->layout == ETNA_LAYOUT_TILED) { | |||
if (rsc->layout == ETNA_LAYOUT_TILED && !util_format_is_compressed(rsc->base.format)) { | |||
etna_texture_untile(trans->staging, | |||
mapped + ptrans->box.z * res_level->layer_stride, | |||
ptrans->box.x, ptrans->box.y, res_level->stride, | |||
ptrans->box.width, ptrans->box.height, ptrans->stride, | |||
util_format_get_blocksize(rsc->base.format)); | |||
} else { /* non-tiled or compressed format */ | |||
util_copy_box(trans->staging, rsc->base.format, ptrans->stride, | |||
ptrans->layer_stride, 0, 0, 0, /* dst x,y,z */ | |||
ptrans->box.width, ptrans->box.height, | |||
ptrans->box.depth, mapped, res_level->stride, | |||
res_level->layer_stride, ptrans->box.x, | |||
ptrans->box.y, ptrans->box.z); | |||
} | |||
} else /* TODO supertiling */ | |||
{ | |||
BUG("unsupported tiling %i for reading", rsc->layout); | |||
} | |||
} | |||
return trans->staging; | |||
} | |||
fail: | |||
etna_bo_cpu_fini(rsc->bo); | |||
fail_prep: | |||
etna_transfer_unmap(pctx, ptrans); | |||
return NULL; | |||
} | |||
static void | |||
etna_transfer_flush_region(struct pipe_context *pctx, | |||
struct pipe_transfer *transfer, | |||
const struct pipe_box *box) | |||
{ | |||
/* NOOP for now */ | |||
} | |||
void | |||
etna_transfer_init(struct pipe_context *pctx) | |||
{ | |||
pctx->transfer_map = etna_transfer_map; | |||
pctx->transfer_flush_region = etna_transfer_flush_region; | |||
pctx->transfer_unmap = etna_transfer_unmap; | |||
pctx->buffer_subdata = u_default_buffer_subdata; | |||
pctx->texture_subdata = u_default_texture_subdata; | |||
} |
@@ -0,0 +1,35 @@ | |||
/* | |||
* Copyright (c) 2012-2015 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Wladimir J. van der Laan <laanwj@gmail.com> | |||
*/ | |||
#ifndef H_ETNAVIV_TRANSFER | |||
#define H_ETNAVIV_TRANSFER | |||
#include "pipe/p_state.h" | |||
void | |||
etna_transfer_init(struct pipe_context *pctx); | |||
#endif |
@@ -0,0 +1,516 @@ | |||
/* | |||
* Copyright (c) 2012-2013 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
*/ | |||
/* inlined translation functions between gallium and vivante */ | |||
#ifndef H_TRANSLATE | |||
#define H_TRANSLATE | |||
#include "pipe/p_defines.h" | |||
#include "pipe/p_format.h" | |||
#include "pipe/p_state.h" | |||
#include "etnaviv_debug.h" | |||
#include "etnaviv_format.h" | |||
#include "etnaviv_tiling.h" | |||
#include "etnaviv_util.h" | |||
#include "hw/cmdstream.xml.h" | |||
#include "hw/state.xml.h" | |||
#include "hw/state_3d.xml.h" | |||
#include "util/u_format.h" | |||
#include <stdio.h> | |||
/* Returned when there is no match of pipe value to etna value */ | |||
#define ETNA_NO_MATCH (~0) | |||
static inline uint32_t | |||
translate_cull_face(unsigned cull_face, unsigned front_ccw) | |||
{ | |||
switch (cull_face) { | |||
case PIPE_FACE_NONE: | |||
return VIVS_PA_CONFIG_CULL_FACE_MODE_OFF; | |||
case PIPE_FACE_BACK: | |||
return front_ccw ? VIVS_PA_CONFIG_CULL_FACE_MODE_CW | |||
: VIVS_PA_CONFIG_CULL_FACE_MODE_CCW; | |||
case PIPE_FACE_FRONT: | |||
return front_ccw ? VIVS_PA_CONFIG_CULL_FACE_MODE_CCW | |||
: VIVS_PA_CONFIG_CULL_FACE_MODE_CW; | |||
default: | |||
DBG("Unhandled cull face mode %i", cull_face); | |||
return ETNA_NO_MATCH; | |||
} | |||
} | |||
static inline uint32_t | |||
translate_polygon_mode(unsigned polygon_mode) | |||
{ | |||
switch (polygon_mode) { | |||
case PIPE_POLYGON_MODE_FILL: | |||
return VIVS_PA_CONFIG_FILL_MODE_SOLID; | |||
case PIPE_POLYGON_MODE_LINE: | |||
return VIVS_PA_CONFIG_FILL_MODE_WIREFRAME; | |||
case PIPE_POLYGON_MODE_POINT: | |||
return VIVS_PA_CONFIG_FILL_MODE_POINT; | |||
default: | |||
DBG("Unhandled polygon mode %i", polygon_mode); | |||
return ETNA_NO_MATCH; | |||
} | |||
} | |||
static inline uint32_t | |||
translate_stencil_mode(bool enable_0, bool enable_1) | |||
{ | |||
if (enable_0) { | |||
return enable_1 ? VIVS_PE_STENCIL_CONFIG_MODE_TWO_SIDED | |||
: VIVS_PE_STENCIL_CONFIG_MODE_ONE_SIDED; | |||
} else { | |||
return VIVS_PE_STENCIL_CONFIG_MODE_DISABLED; | |||
} | |||
} | |||
static inline uint32_t | |||
translate_stencil_op(unsigned stencil_op) | |||
{ | |||
switch (stencil_op) { | |||
case PIPE_STENCIL_OP_KEEP: | |||
return STENCIL_OP_KEEP; | |||
case PIPE_STENCIL_OP_ZERO: | |||
return STENCIL_OP_ZERO; | |||
case PIPE_STENCIL_OP_REPLACE: | |||
return STENCIL_OP_REPLACE; | |||
case PIPE_STENCIL_OP_INCR: | |||
return STENCIL_OP_INCR; | |||
case PIPE_STENCIL_OP_DECR: | |||
return STENCIL_OP_DECR; | |||
case PIPE_STENCIL_OP_INCR_WRAP: | |||
return STENCIL_OP_INCR_WRAP; | |||
case PIPE_STENCIL_OP_DECR_WRAP: | |||
return STENCIL_OP_DECR_WRAP; | |||
case PIPE_STENCIL_OP_INVERT: | |||
return STENCIL_OP_INVERT; | |||
default: | |||
DBG("Unhandled stencil op: %i", stencil_op); | |||
return ETNA_NO_MATCH; | |||
} | |||
} | |||
static inline uint32_t | |||
translate_blend(unsigned blend) | |||
{ | |||
switch (blend) { | |||
case PIPE_BLEND_ADD: | |||
return BLEND_EQ_ADD; | |||
case PIPE_BLEND_SUBTRACT: | |||
return BLEND_EQ_SUBTRACT; | |||
case PIPE_BLEND_REVERSE_SUBTRACT: | |||
return BLEND_EQ_REVERSE_SUBTRACT; | |||
case PIPE_BLEND_MIN: | |||
return BLEND_EQ_MIN; | |||
case PIPE_BLEND_MAX: | |||
return BLEND_EQ_MAX; | |||
default: | |||
DBG("Unhandled blend: %i", blend); | |||
return ETNA_NO_MATCH; | |||
} | |||
} | |||
static inline uint32_t | |||
translate_blend_factor(unsigned blend_factor) | |||
{ | |||
switch (blend_factor) { | |||
case PIPE_BLENDFACTOR_ONE: | |||
return BLEND_FUNC_ONE; | |||
case PIPE_BLENDFACTOR_SRC_COLOR: | |||
return BLEND_FUNC_SRC_COLOR; | |||
case PIPE_BLENDFACTOR_SRC_ALPHA: | |||
return BLEND_FUNC_SRC_ALPHA; | |||
case PIPE_BLENDFACTOR_DST_ALPHA: | |||
return BLEND_FUNC_DST_ALPHA; | |||
case PIPE_BLENDFACTOR_DST_COLOR: | |||
return BLEND_FUNC_DST_COLOR; | |||
case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: | |||
return BLEND_FUNC_SRC_ALPHA_SATURATE; | |||
case PIPE_BLENDFACTOR_CONST_COLOR: | |||
return BLEND_FUNC_CONSTANT_COLOR; | |||
case PIPE_BLENDFACTOR_CONST_ALPHA: | |||
return BLEND_FUNC_CONSTANT_ALPHA; | |||
case PIPE_BLENDFACTOR_ZERO: | |||
return BLEND_FUNC_ZERO; | |||
case PIPE_BLENDFACTOR_INV_SRC_COLOR: | |||
return BLEND_FUNC_ONE_MINUS_SRC_COLOR; | |||
case PIPE_BLENDFACTOR_INV_SRC_ALPHA: | |||
return BLEND_FUNC_ONE_MINUS_SRC_ALPHA; | |||
case PIPE_BLENDFACTOR_INV_DST_ALPHA: | |||
return BLEND_FUNC_ONE_MINUS_DST_ALPHA; | |||
case PIPE_BLENDFACTOR_INV_DST_COLOR: | |||
return BLEND_FUNC_ONE_MINUS_DST_COLOR; | |||
case PIPE_BLENDFACTOR_INV_CONST_COLOR: | |||
return BLEND_FUNC_ONE_MINUS_CONSTANT_COLOR; | |||
case PIPE_BLENDFACTOR_INV_CONST_ALPHA: | |||
return BLEND_FUNC_ONE_MINUS_CONSTANT_ALPHA; | |||
case PIPE_BLENDFACTOR_SRC1_COLOR: | |||
case PIPE_BLENDFACTOR_SRC1_ALPHA: | |||
case PIPE_BLENDFACTOR_INV_SRC1_COLOR: | |||
case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: | |||
default: | |||
DBG("Unhandled blend factor: %i", blend_factor); | |||
return ETNA_NO_MATCH; | |||
} | |||
} | |||
static inline uint32_t | |||
translate_texture_wrapmode(unsigned wrap) | |||
{ | |||
switch (wrap) { | |||
case PIPE_TEX_WRAP_REPEAT: | |||
return TEXTURE_WRAPMODE_REPEAT; | |||
case PIPE_TEX_WRAP_CLAMP: | |||
return TEXTURE_WRAPMODE_CLAMP_TO_EDGE; | |||
case PIPE_TEX_WRAP_CLAMP_TO_EDGE: | |||
return TEXTURE_WRAPMODE_CLAMP_TO_EDGE; | |||
case PIPE_TEX_WRAP_CLAMP_TO_BORDER: | |||
return TEXTURE_WRAPMODE_CLAMP_TO_EDGE; /* XXX */ | |||
case PIPE_TEX_WRAP_MIRROR_REPEAT: | |||
return TEXTURE_WRAPMODE_MIRRORED_REPEAT; | |||
case PIPE_TEX_WRAP_MIRROR_CLAMP: | |||
return TEXTURE_WRAPMODE_MIRRORED_REPEAT; /* XXX */ | |||
case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: | |||
return TEXTURE_WRAPMODE_MIRRORED_REPEAT; /* XXX */ | |||
case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: | |||
return TEXTURE_WRAPMODE_MIRRORED_REPEAT; /* XXX */ | |||
default: | |||
DBG("Unhandled texture wrapmode: %i", wrap); | |||
return ETNA_NO_MATCH; | |||
} | |||
} | |||
static inline uint32_t | |||
translate_texture_mipfilter(unsigned filter) | |||
{ | |||
switch (filter) { | |||
case PIPE_TEX_MIPFILTER_NEAREST: | |||
return TEXTURE_FILTER_NEAREST; | |||
case PIPE_TEX_MIPFILTER_LINEAR: | |||
return TEXTURE_FILTER_LINEAR; | |||
case PIPE_TEX_MIPFILTER_NONE: | |||
return TEXTURE_FILTER_NONE; | |||
default: | |||
DBG("Unhandled texture mipfilter: %i", filter); | |||
return ETNA_NO_MATCH; | |||
} | |||
} | |||
static inline uint32_t | |||
translate_texture_filter(unsigned filter) | |||
{ | |||
switch (filter) { | |||
case PIPE_TEX_FILTER_NEAREST: | |||
return TEXTURE_FILTER_NEAREST; | |||
case PIPE_TEX_FILTER_LINEAR: | |||
return TEXTURE_FILTER_LINEAR; | |||
/* What about anisotropic? */ | |||
default: | |||
DBG("Unhandled texture filter: %i", filter); | |||
return ETNA_NO_MATCH; | |||
} | |||
} | |||
/* return a RS "compatible" format for use when copying */ | |||
static inline enum pipe_format | |||
etna_compatible_rs_format(enum pipe_format fmt) | |||
{ | |||
/* YUYV and UYVY are blocksize 4, but 2 bytes per pixel */ | |||
if (fmt == PIPE_FORMAT_YUYV || fmt == PIPE_FORMAT_UYVY) | |||
return PIPE_FORMAT_B4G4R4A4_UNORM; | |||
switch (util_format_get_blocksize(fmt)) { | |||
case 2: | |||
return PIPE_FORMAT_B4G4R4A4_UNORM; | |||
case 4: | |||
return PIPE_FORMAT_B8G8R8A8_UNORM; | |||
default: | |||
return fmt; | |||
} | |||
} | |||
static inline int | |||
translate_rb_src_dst_swap(enum pipe_format src, enum pipe_format dst) | |||
{ | |||
return translate_rs_format_rb_swap(src) ^ translate_rs_format_rb_swap(dst); | |||
} | |||
static inline uint32_t | |||
translate_depth_format(enum pipe_format fmt) | |||
{ | |||
/* Note: Pipe format convention is LSB to MSB, VIVS is MSB to LSB */ | |||
switch (fmt) { | |||
case PIPE_FORMAT_Z16_UNORM: | |||
return VIVS_PE_DEPTH_CONFIG_DEPTH_FORMAT_D16; | |||
case PIPE_FORMAT_X8Z24_UNORM: | |||
return VIVS_PE_DEPTH_CONFIG_DEPTH_FORMAT_D24S8; | |||
case PIPE_FORMAT_S8_UINT_Z24_UNORM: | |||
return VIVS_PE_DEPTH_CONFIG_DEPTH_FORMAT_D24S8; | |||
default: | |||
return ETNA_NO_MATCH; | |||
} | |||
} | |||
/* render target format for MSAA */ | |||
static inline uint32_t | |||
translate_msaa_format(enum pipe_format fmt) | |||
{ | |||
/* Note: Pipe format convention is LSB to MSB, VIVS is MSB to LSB */ | |||
switch (fmt) { | |||
case PIPE_FORMAT_B4G4R4X4_UNORM: | |||
return VIVS_TS_MEM_CONFIG_MSAA_FORMAT_A4R4G4B4; | |||
case PIPE_FORMAT_B4G4R4A4_UNORM: | |||
return VIVS_TS_MEM_CONFIG_MSAA_FORMAT_A4R4G4B4; | |||
case PIPE_FORMAT_B5G5R5X1_UNORM: | |||
return VIVS_TS_MEM_CONFIG_MSAA_FORMAT_A1R5G5B5; | |||
case PIPE_FORMAT_B5G5R5A1_UNORM: | |||
return VIVS_TS_MEM_CONFIG_MSAA_FORMAT_A1R5G5B5; | |||
case PIPE_FORMAT_B5G6R5_UNORM: | |||
return VIVS_TS_MEM_CONFIG_MSAA_FORMAT_R5G6B5; | |||
case PIPE_FORMAT_B8G8R8X8_UNORM: | |||
return VIVS_TS_MEM_CONFIG_MSAA_FORMAT_X8R8G8B8; | |||
case PIPE_FORMAT_B8G8R8A8_UNORM: | |||
return VIVS_TS_MEM_CONFIG_MSAA_FORMAT_A8R8G8B8; | |||
/* MSAA with YUYV not supported */ | |||
default: | |||
return ETNA_NO_MATCH; | |||
} | |||
} | |||
/* Return normalization flag for vertex element format */ | |||
static inline uint32_t | |||
translate_vertex_format_normalize(enum pipe_format fmt) | |||
{ | |||
const struct util_format_description *desc = util_format_description(fmt); | |||
if (!desc) | |||
return VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE_OFF; | |||
/* assumes that normalization of channel 0 holds for all channels; | |||
* this holds for all vertex formats that we support */ | |||
return desc->channel[0].normalized | |||
? VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE_ON | |||
: VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE_OFF; | |||
} | |||
static inline uint32_t | |||
translate_index_size(unsigned index_size) | |||
{ | |||
switch (index_size) { | |||
case 1: | |||
return VIVS_FE_INDEX_STREAM_CONTROL_TYPE_UNSIGNED_CHAR; | |||
case 2: | |||
return VIVS_FE_INDEX_STREAM_CONTROL_TYPE_UNSIGNED_SHORT; | |||
case 4: | |||
return VIVS_FE_INDEX_STREAM_CONTROL_TYPE_UNSIGNED_INT; | |||
default: | |||
DBG("Unhandled index size %i", index_size); | |||
return ETNA_NO_MATCH; | |||
} | |||
} | |||
static inline uint32_t | |||
translate_draw_mode(unsigned mode) | |||
{ | |||
switch (mode) { | |||
case PIPE_PRIM_POINTS: | |||
return PRIMITIVE_TYPE_POINTS; | |||
case PIPE_PRIM_LINES: | |||
return PRIMITIVE_TYPE_LINES; | |||
case PIPE_PRIM_LINE_LOOP: | |||
return PRIMITIVE_TYPE_LINE_LOOP; | |||
case PIPE_PRIM_LINE_STRIP: | |||
return PRIMITIVE_TYPE_LINE_STRIP; | |||
case PIPE_PRIM_TRIANGLES: | |||
return PRIMITIVE_TYPE_TRIANGLES; | |||
case PIPE_PRIM_TRIANGLE_STRIP: | |||
return PRIMITIVE_TYPE_TRIANGLE_STRIP; | |||
case PIPE_PRIM_TRIANGLE_FAN: | |||
return PRIMITIVE_TYPE_TRIANGLE_FAN; | |||
case PIPE_PRIM_QUADS: | |||
return PRIMITIVE_TYPE_QUADS; | |||
default: | |||
DBG("Unhandled draw mode primitive %i", mode); | |||
return ETNA_NO_MATCH; | |||
} | |||
} | |||
/* Get size multiple for size of texture/rendertarget with a certain layout | |||
* This is affected by many different parameters: | |||
* - A horizontal multiple of 16 is used when possible as resolve can be used | |||
* at the cost of only a little bit extra memory usage. | |||
* - If the surface is to be used with the resolve engine, set rs_align true. | |||
* If set, a horizontal multiple of 16 will be used for tiled and linear, | |||
* otherwise one of 16. However, such a surface will be incompatible | |||
* with the samplers if the GPU does hot support the HALIGN feature. | |||
* - If the surface is supertiled, horizontal and vertical multiple is always 64 | |||
* - If the surface is multi tiled or supertiled, make sure that the vertical size | |||
* is a multiple of the number of pixel pipes as well. | |||
* */ | |||
static inline void | |||
etna_layout_multiple(unsigned layout, unsigned pixel_pipes, bool rs_align, | |||
unsigned *paddingX, unsigned *paddingY, unsigned *halign) | |||
{ | |||
switch (layout) { | |||
case ETNA_LAYOUT_LINEAR: | |||
*paddingX = rs_align ? 16 : 4; | |||
*paddingY = 1; | |||
*halign = rs_align ? TEXTURE_HALIGN_SIXTEEN : TEXTURE_HALIGN_FOUR; | |||
break; | |||
case ETNA_LAYOUT_TILED: | |||
*paddingX = rs_align ? 16 : 4; | |||
*paddingY = 4; | |||
*halign = rs_align ? TEXTURE_HALIGN_SIXTEEN : TEXTURE_HALIGN_FOUR; | |||
break; | |||
case ETNA_LAYOUT_SUPER_TILED: | |||
*paddingX = 64; | |||
*paddingY = 64; | |||
*halign = TEXTURE_HALIGN_SUPER_TILED; | |||
break; | |||
case ETNA_LAYOUT_MULTI_TILED: | |||
*paddingX = 16; | |||
*paddingY = 4 * pixel_pipes; | |||
*halign = TEXTURE_HALIGN_SPLIT_TILED; | |||
break; | |||
case ETNA_LAYOUT_MULTI_SUPERTILED: | |||
*paddingX = 64; | |||
*paddingY = 64 * pixel_pipes; | |||
*halign = TEXTURE_HALIGN_SPLIT_SUPER_TILED; | |||
break; | |||
default: | |||
DBG("Unhandled layout %i", layout); | |||
} | |||
} | |||
/* return 32-bit clear pattern for color */ | |||
static inline uint32_t | |||
translate_clear_color(enum pipe_format format, | |||
const union pipe_color_union *color) | |||
{ | |||
uint32_t clear_value = 0; | |||
// XXX util_pack_color | |||
switch (format) { | |||
case PIPE_FORMAT_B8G8R8A8_UNORM: | |||
case PIPE_FORMAT_B8G8R8X8_UNORM: | |||
clear_value = etna_cfloat_to_uintN(color->f[2], 8) | | |||
(etna_cfloat_to_uintN(color->f[1], 8) << 8) | | |||
(etna_cfloat_to_uintN(color->f[0], 8) << 16) | | |||
(etna_cfloat_to_uintN(color->f[3], 8) << 24); | |||
break; | |||
case PIPE_FORMAT_B4G4R4X4_UNORM: | |||
case PIPE_FORMAT_B4G4R4A4_UNORM: | |||
clear_value = etna_cfloat_to_uintN(color->f[2], 4) | | |||
(etna_cfloat_to_uintN(color->f[1], 4) << 4) | | |||
(etna_cfloat_to_uintN(color->f[0], 4) << 8) | | |||
(etna_cfloat_to_uintN(color->f[3], 4) << 12); | |||
clear_value |= clear_value << 16; | |||
break; | |||
case PIPE_FORMAT_B5G5R5X1_UNORM: | |||
case PIPE_FORMAT_B5G5R5A1_UNORM: | |||
clear_value = etna_cfloat_to_uintN(color->f[2], 5) | | |||
(etna_cfloat_to_uintN(color->f[1], 5) << 5) | | |||
(etna_cfloat_to_uintN(color->f[0], 5) << 10) | | |||
(etna_cfloat_to_uintN(color->f[3], 1) << 15); | |||
clear_value |= clear_value << 16; | |||
break; | |||
case PIPE_FORMAT_B5G6R5_UNORM: | |||
clear_value = etna_cfloat_to_uintN(color->f[2], 5) | | |||
(etna_cfloat_to_uintN(color->f[1], 6) << 5) | | |||
(etna_cfloat_to_uintN(color->f[0], 5) << 11); | |||
clear_value |= clear_value << 16; | |||
break; | |||
default: | |||
DBG("Unhandled pipe format for color clear: %i", format); | |||
} | |||
return clear_value; | |||
} | |||
static inline uint32_t | |||
translate_clear_depth_stencil(enum pipe_format format, float depth, | |||
unsigned stencil) | |||
{ | |||
uint32_t clear_value = 0; | |||
// XXX util_pack_color | |||
switch (format) { | |||
case PIPE_FORMAT_Z16_UNORM: | |||
clear_value = etna_cfloat_to_uintN(depth, 16); | |||
clear_value |= clear_value << 16; | |||
break; | |||
case PIPE_FORMAT_X8Z24_UNORM: | |||
case PIPE_FORMAT_S8_UINT_Z24_UNORM: | |||
clear_value = (etna_cfloat_to_uintN(depth, 24) << 8) | (stencil & 0xFF); | |||
break; | |||
default: | |||
DBG("Unhandled pipe format for depth stencil clear: %i", format); | |||
} | |||
return clear_value; | |||
} | |||
/* Convert MSAA number of samples to x and y scaling factor and | |||
* VIVS_GL_MULTI_SAMPLE_CONFIG value. | |||
* Return true if supported and false otherwise. */ | |||
static inline bool | |||
translate_samples_to_xyscale(int num_samples, int *xscale_out, int *yscale_out, | |||
uint32_t *config_out) | |||
{ | |||
int xscale, yscale; | |||
uint32_t config; | |||
switch (num_samples) { | |||
case 0: | |||
case 1: | |||
xscale = 1; | |||
yscale = 1; | |||
config = VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_NONE; | |||
break; | |||
case 2: | |||
xscale = 2; | |||
yscale = 1; | |||
config = VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_2X; | |||
break; | |||
case 4: | |||
xscale = 2; | |||
yscale = 2; | |||
config = VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_4X; | |||
break; | |||
default: | |||
return false; | |||
} | |||
if (xscale_out) | |||
*xscale_out = xscale; | |||
if (yscale_out) | |||
*yscale_out = yscale; | |||
if (config_out) | |||
*config_out = config; | |||
return true; | |||
} | |||
#endif |
@@ -0,0 +1,118 @@ | |||
/* | |||
* Copyright (c) 2016 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Christian Gmeiner <christian.gmeiner@gmail.com> | |||
*/ | |||
#include "etnaviv_uniforms.h" | |||
#include "etnaviv_compiler.h" | |||
#include "etnaviv_context.h" | |||
#include "etnaviv_util.h" | |||
#include "pipe/p_defines.h" | |||
#include "util/u_math.h" | |||
static unsigned | |||
get_const_idx(const struct etna_context *ctx, bool frag, unsigned samp_id) | |||
{ | |||
if (frag) | |||
return samp_id; | |||
return samp_id + ctx->specs.vertex_sampler_offset; | |||
} | |||
static uint32_t | |||
get_texrect_scale(const struct etna_context *ctx, bool frag, | |||
enum etna_immediate_contents contents, uint32_t data) | |||
{ | |||
unsigned index = get_const_idx(ctx, frag, data); | |||
struct pipe_sampler_view *texture = ctx->sampler_view[index]; | |||
uint32_t dim; | |||
if (contents == ETNA_IMMEDIATE_TEXRECT_SCALE_X) | |||
dim = texture->texture->width0; | |||
else | |||
dim = texture->texture->height0; | |||
return fui(1.0f / dim); | |||
} | |||
void | |||
etna_uniforms_write(const struct etna_context *ctx, | |||
const struct etna_shader *sobj, | |||
struct pipe_constant_buffer *cb, uint32_t *uniforms, | |||
unsigned *size) | |||
{ | |||
const struct etna_shader_uniform_info *uinfo = &sobj->uniforms; | |||
bool frag = false; | |||
if (cb->user_buffer) { | |||
unsigned size = MIN2(cb->buffer_size, uinfo->const_count * 4); | |||
memcpy(uniforms, cb->user_buffer, size); | |||
} | |||
if (sobj == ctx->fs) | |||
frag = true; | |||
for (uint32_t i = 0; i < uinfo->imm_count; i++) { | |||
switch (uinfo->imm_contents[i]) { | |||
case ETNA_IMMEDIATE_CONSTANT: | |||
uniforms[i + uinfo->const_count] = uinfo->imm_data[i]; | |||
break; | |||
case ETNA_IMMEDIATE_TEXRECT_SCALE_X: | |||
case ETNA_IMMEDIATE_TEXRECT_SCALE_Y: | |||
uniforms[i + uinfo->const_count] = | |||
get_texrect_scale(ctx, frag, uinfo->imm_contents[i], uinfo->imm_data[i]); | |||
break; | |||
case ETNA_IMMEDIATE_UNUSED: | |||
/* nothing to do */ | |||
break; | |||
} | |||
} | |||
*size = uinfo->const_count + uinfo->imm_count; | |||
} | |||
void | |||
etna_set_shader_uniforms_dirty_flags(struct etna_shader *sobj) | |||
{ | |||
uint32_t dirty = 0; | |||
for (uint32_t i = 0; i < sobj->uniforms.imm_count; i++) { | |||
switch (sobj->uniforms.imm_contents[i]) { | |||
case ETNA_IMMEDIATE_UNUSED: | |||
case ETNA_IMMEDIATE_CONSTANT: | |||
break; | |||
case ETNA_IMMEDIATE_TEXRECT_SCALE_X: | |||
case ETNA_IMMEDIATE_TEXRECT_SCALE_Y: | |||
dirty |= ETNA_DIRTY_SAMPLER_VIEWS; | |||
break; | |||
} | |||
} | |||
sobj->uniforms_dirty_bits = dirty; | |||
} |
@@ -0,0 +1,45 @@ | |||
/* | |||
* Copyright (c) 2016 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Christian Gmeiner <christian.gmeiner@gmail.com> | |||
*/ | |||
#ifndef ETNAVIV_UNIFORMS_H_ | |||
#define ETNAVIV_UNIFORMS_H_ | |||
#include <stdint.h> | |||
struct etna_context; | |||
struct etna_shader; | |||
struct pipe_constant_buffer; | |||
void | |||
etna_uniforms_write(const struct etna_context *ctx, | |||
const struct etna_shader *sobj, | |||
struct pipe_constant_buffer *cb, uint32_t *uniforms, | |||
unsigned *size); | |||
void | |||
etna_set_shader_uniforms_dirty_flags(struct etna_shader *sobj); | |||
#endif /* ETNAVIV_UNIFORMS_H_ */ |
@@ -0,0 +1,108 @@ | |||
/* | |||
* Copyright (c) 2012-2015 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
*/ | |||
/* Misc util */ | |||
#ifndef H_ETNA_UTIL | |||
#define H_ETNA_UTIL | |||
#include <math.h> | |||
/* for conditionally setting boolean flag(s): */ | |||
#define COND(bool, val) ((bool) ? (val) : 0) | |||
/* align to a value divisable by granularity >= value, works only for powers of two */ | |||
static inline uint32_t | |||
etna_align_up(uint32_t value, uint32_t granularity) | |||
{ | |||
return (value + (granularity - 1)) & (~(granularity - 1)); | |||
} | |||
static inline uint32_t | |||
etna_bits_ones(unsigned num) | |||
{ | |||
return (1 << num) - 1; | |||
} | |||
/* clamped float [0.0 .. 1.0] -> [0 .. 255] */ | |||
static inline uint8_t | |||
etna_cfloat_to_uint8(float f) | |||
{ | |||
if (f <= 0.0f) | |||
return 0; | |||
if (f >= (1.0f - 1.0f / 256.0f)) | |||
return 255; | |||
return f * 256.0f; | |||
} | |||
/* clamped float [0.0 .. 1.0] -> [0 .. (1<<bits)-1] */ | |||
static inline uint32_t | |||
etna_cfloat_to_uintN(float f, int bits) | |||
{ | |||
if (f <= 0.0f) | |||
return 0; | |||
if (f >= (1.0f - 1.0f / (1 << bits))) | |||
return (1 << bits) - 1; | |||
return f * (1 << bits); | |||
} | |||
/* 1/log10(2) */ | |||
#define RCPLOG2 (1.4426950408889634f) | |||
/* float to fixp 5.5 */ | |||
static inline uint32_t | |||
etna_float_to_fixp55(float f) | |||
{ | |||
if (f >= 15.953125f) | |||
return 511; | |||
if (f < -16.0f) | |||
return 512; | |||
return (int32_t)(f * 32.0f + 0.5f); | |||
} | |||
/* texture size to log2 in fixp 5.5 format */ | |||
static inline uint32_t | |||
etna_log2_fixp55(unsigned width) | |||
{ | |||
return etna_float_to_fixp55(logf((float)width) * RCPLOG2); | |||
} | |||
/* float to fixp 16.16 */ | |||
static inline uint32_t | |||
etna_f32_to_fixp16(float f) | |||
{ | |||
if (f >= (32768.0f - 1.0f / 65536.0f)) | |||
return 0x7fffffff; | |||
if (f < -32768.0f) | |||
return 0x80000000; | |||
return (int32_t)(f * 65536.0f + 0.5f); | |||
} | |||
#endif |
@@ -0,0 +1,123 @@ | |||
/* | |||
* Copyright (c) 2012-2015 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Wladimir J. van der Laan <laanwj@gmail.com> | |||
*/ | |||
#include "etnaviv_zsa.h" | |||
#include "etnaviv_context.h" | |||
#include "etnaviv_translate.h" | |||
#include "util/u_memory.h" | |||
void * | |||
etna_zsa_state_create(struct pipe_context *pctx, | |||
const struct pipe_depth_stencil_alpha_state *so) | |||
{ | |||
struct etna_zsa_state *cs = CALLOC_STRUCT(etna_zsa_state); | |||
if (!cs) | |||
return NULL; | |||
cs->base = *so; | |||
/* XXX does stencil[0] / stencil[1] order depend on rs->front_ccw? */ | |||
bool early_z = true; | |||
bool disable_zs = | |||
(!so->depth.enabled || so->depth.func == PIPE_FUNC_ALWAYS) && | |||
!so->depth.writemask; | |||
/* Set operations to KEEP if write mask is 0. | |||
* When we don't do this, the depth buffer is written for the entire primitive | |||
* instead of just where the stencil condition holds (GC600 rev 0x0019, without | |||
* feature CORRECT_STENCIL). | |||
* Not sure if this is a hardware bug or just a strange edge case. */ | |||
#if 0 /* TODO: It looks like a hardware bug */ | |||
for(int i=0; i<2; ++i) | |||
{ | |||
if(so->stencil[i].writemask == 0) | |||
{ | |||
so->stencil[i].fail_op = so->stencil[i].zfail_op = so->stencil[i].zpass_op = PIPE_STENCIL_OP_KEEP; | |||
} | |||
} | |||
#endif | |||
/* Determine whether to enable early z reject. Don't enable it when any of | |||
* the stencil-modifying functions is used. */ | |||
if (so->stencil[0].enabled) { | |||
if (so->stencil[0].func != PIPE_FUNC_ALWAYS || | |||
(so->stencil[1].enabled && so->stencil[1].func != PIPE_FUNC_ALWAYS)) | |||
disable_zs = false; | |||
if (so->stencil[0].fail_op != PIPE_STENCIL_OP_KEEP || | |||
so->stencil[0].zfail_op != PIPE_STENCIL_OP_KEEP || | |||
so->stencil[0].zpass_op != PIPE_STENCIL_OP_KEEP) { | |||
disable_zs = early_z = false; | |||
} else if (so->stencil[1].enabled) { | |||
if (so->stencil[1].fail_op != PIPE_STENCIL_OP_KEEP || | |||
so->stencil[1].zfail_op != PIPE_STENCIL_OP_KEEP || | |||
so->stencil[1].zpass_op != PIPE_STENCIL_OP_KEEP) { | |||
disable_zs = early_z = false; | |||
} | |||
} | |||
} | |||
/* Disable early z reject when no depth test is enabled. | |||
* This avoids having to sample depth even though we know it's going to | |||
* succeed. */ | |||
if (so->depth.enabled == false || so->depth.func == PIPE_FUNC_ALWAYS) | |||
early_z = false; | |||
if (DBG_ENABLED(ETNA_DBG_NO_EARLY_Z)) | |||
early_z = false; | |||
/* compare funcs have 1 to 1 mapping */ | |||
cs->PE_DEPTH_CONFIG = | |||
VIVS_PE_DEPTH_CONFIG_DEPTH_FUNC(so->depth.enabled ? so->depth.func | |||
: PIPE_FUNC_ALWAYS) | | |||
COND(so->depth.writemask, VIVS_PE_DEPTH_CONFIG_WRITE_ENABLE) | | |||
COND(early_z, VIVS_PE_DEPTH_CONFIG_EARLY_Z) | | |||
COND(disable_zs, VIVS_PE_DEPTH_CONFIG_DISABLE_ZS); | |||
cs->PE_ALPHA_OP = | |||
COND(so->alpha.enabled, VIVS_PE_ALPHA_OP_ALPHA_TEST) | | |||
VIVS_PE_ALPHA_OP_ALPHA_FUNC(so->alpha.func) | | |||
VIVS_PE_ALPHA_OP_ALPHA_REF(etna_cfloat_to_uint8(so->alpha.ref_value)); | |||
cs->PE_STENCIL_OP = | |||
VIVS_PE_STENCIL_OP_FUNC_FRONT(so->stencil[0].func) | | |||
VIVS_PE_STENCIL_OP_FUNC_BACK(so->stencil[1].func) | | |||
VIVS_PE_STENCIL_OP_FAIL_FRONT(translate_stencil_op(so->stencil[0].fail_op)) | | |||
VIVS_PE_STENCIL_OP_FAIL_BACK(translate_stencil_op(so->stencil[1].fail_op)) | | |||
VIVS_PE_STENCIL_OP_DEPTH_FAIL_FRONT(translate_stencil_op(so->stencil[0].zfail_op)) | | |||
VIVS_PE_STENCIL_OP_DEPTH_FAIL_BACK(translate_stencil_op(so->stencil[1].zfail_op)) | | |||
VIVS_PE_STENCIL_OP_PASS_FRONT(translate_stencil_op(so->stencil[0].zpass_op)) | | |||
VIVS_PE_STENCIL_OP_PASS_BACK(translate_stencil_op(so->stencil[1].zpass_op)); | |||
cs->PE_STENCIL_CONFIG = | |||
translate_stencil_mode(so->stencil[0].enabled, so->stencil[1].enabled) | | |||
VIVS_PE_STENCIL_CONFIG_MASK_FRONT(so->stencil[0].valuemask) | | |||
VIVS_PE_STENCIL_CONFIG_WRITE_MASK_FRONT(so->stencil[0].writemask); | |||
/* XXX back masks in VIVS_PE_DEPTH_CONFIG_EXT? */ | |||
/* XXX VIVS_PE_STENCIL_CONFIG_REF_FRONT comes from pipe_stencil_ref */ | |||
/* XXX does alpha/stencil test affect PE_COLOR_FORMAT_OVERWRITE? */ | |||
return cs; | |||
} |
@@ -0,0 +1,52 @@ | |||
/* | |||
* Copyright (c) 2012-2015 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Wladimir J. van der Laan <laanwj@gmail.com> | |||
*/ | |||
#ifndef H_ETNAVIV_ZSA | |||
#define H_ETNAVIV_ZSA | |||
#include "pipe/p_context.h" | |||
#include "pipe/p_state.h" | |||
struct etna_zsa_state { | |||
struct pipe_depth_stencil_alpha_state base; | |||
uint32_t PE_DEPTH_CONFIG; | |||
uint32_t PE_ALPHA_OP; | |||
uint32_t PE_STENCIL_OP; | |||
uint32_t PE_STENCIL_CONFIG; | |||
}; | |||
static inline struct etna_zsa_state * | |||
etna_zsa_state(struct pipe_depth_stencil_alpha_state *zsa) | |||
{ | |||
return (struct etna_zsa_state *)zsa; | |||
} | |||
void * | |||
etna_zsa_state_create(struct pipe_context *pctx, | |||
const struct pipe_depth_stencil_alpha_state *so); | |||
#endif |
@@ -0,0 +1,270 @@ | |||
#ifndef CMDSTREAM_XML | |||
#define CMDSTREAM_XML | |||
/* Autogenerated file, DO NOT EDIT manually! | |||
This file was generated by the rules-ng-ng headergen tool in this git repository: | |||
http://0x04.net/cgit/index.cgi/rules-ng-ng | |||
git clone git://0x04.net/rules-ng-ng | |||
The rules-ng-ng source files this header was generated from are: | |||
- cmdstream.xml ( 14094 bytes, from 2016-11-16 18:54:37) | |||
- copyright.xml ( 1597 bytes, from 2016-10-02 14:26:13) | |||
- common.xml ( 23422 bytes, from 2016-11-16 18:54:37) | |||
Copyright (C) 2012-2016 by the following authors: | |||
- Wladimir J. van der Laan <laanwj@gmail.com> | |||
- Christian Gmeiner <christian.gmeiner@gmail.com> | |||
- Lucas Stach <l.stach@pengutronix.de> | |||
- Russell King <rmk@arm.linux.org.uk> | |||
Permission is hereby granted, free of charge, to any person obtaining a | |||
copy of this software and associated documentation files (the "Software"), | |||
to deal in the Software without restriction, including without limitation | |||
the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
and/or sell copies of the Software, and to permit persons to whom the | |||
Software is furnished to do so, subject to the following conditions: | |||
The above copyright notice and this permission notice (including the | |||
next paragraph) shall be included in all copies or substantial portions | |||
of the Software. | |||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
DEALINGS IN THE SOFTWARE. | |||
*/ | |||
#define FE_OPCODE_LOAD_STATE 0x00000001 | |||
#define FE_OPCODE_END 0x00000002 | |||
#define FE_OPCODE_NOP 0x00000003 | |||
#define FE_OPCODE_DRAW_2D 0x00000004 | |||
#define FE_OPCODE_DRAW_PRIMITIVES 0x00000005 | |||
#define FE_OPCODE_DRAW_INDEXED_PRIMITIVES 0x00000006 | |||
#define FE_OPCODE_WAIT 0x00000007 | |||
#define FE_OPCODE_LINK 0x00000008 | |||
#define FE_OPCODE_STALL 0x00000009 | |||
#define FE_OPCODE_CALL 0x0000000a | |||
#define FE_OPCODE_RETURN 0x0000000b | |||
#define FE_OPCODE_DRAW_INSTANCED 0x0000000c | |||
#define FE_OPCODE_CHIP_SELECT 0x0000000d | |||
#define PRIMITIVE_TYPE_POINTS 0x00000001 | |||
#define PRIMITIVE_TYPE_LINES 0x00000002 | |||
#define PRIMITIVE_TYPE_LINE_STRIP 0x00000003 | |||
#define PRIMITIVE_TYPE_TRIANGLES 0x00000004 | |||
#define PRIMITIVE_TYPE_TRIANGLE_STRIP 0x00000005 | |||
#define PRIMITIVE_TYPE_TRIANGLE_FAN 0x00000006 | |||
#define PRIMITIVE_TYPE_LINE_LOOP 0x00000007 | |||
#define PRIMITIVE_TYPE_QUADS 0x00000008 | |||
#define VIV_FE_LOAD_STATE 0x00000000 | |||
#define VIV_FE_LOAD_STATE_HEADER 0x00000000 | |||
#define VIV_FE_LOAD_STATE_HEADER_OP__MASK 0xf8000000 | |||
#define VIV_FE_LOAD_STATE_HEADER_OP__SHIFT 27 | |||
#define VIV_FE_LOAD_STATE_HEADER_OP_LOAD_STATE 0x08000000 | |||
#define VIV_FE_LOAD_STATE_HEADER_FIXP 0x04000000 | |||
#define VIV_FE_LOAD_STATE_HEADER_COUNT__MASK 0x03ff0000 | |||
#define VIV_FE_LOAD_STATE_HEADER_COUNT__SHIFT 16 | |||
#define VIV_FE_LOAD_STATE_HEADER_COUNT(x) (((x) << VIV_FE_LOAD_STATE_HEADER_COUNT__SHIFT) & VIV_FE_LOAD_STATE_HEADER_COUNT__MASK) | |||
#define VIV_FE_LOAD_STATE_HEADER_OFFSET__MASK 0x0000ffff | |||
#define VIV_FE_LOAD_STATE_HEADER_OFFSET__SHIFT 0 | |||
#define VIV_FE_LOAD_STATE_HEADER_OFFSET(x) (((x) << VIV_FE_LOAD_STATE_HEADER_OFFSET__SHIFT) & VIV_FE_LOAD_STATE_HEADER_OFFSET__MASK) | |||
#define VIV_FE_LOAD_STATE_HEADER_OFFSET__SHR 2 | |||
#define VIV_FE_END 0x00000000 | |||
#define VIV_FE_END_HEADER 0x00000000 | |||
#define VIV_FE_END_HEADER_EVENT_ID__MASK 0x0000001f | |||
#define VIV_FE_END_HEADER_EVENT_ID__SHIFT 0 | |||
#define VIV_FE_END_HEADER_EVENT_ID(x) (((x) << VIV_FE_END_HEADER_EVENT_ID__SHIFT) & VIV_FE_END_HEADER_EVENT_ID__MASK) | |||
#define VIV_FE_END_HEADER_EVENT_ENABLE 0x00000100 | |||
#define VIV_FE_END_HEADER_OP__MASK 0xf8000000 | |||
#define VIV_FE_END_HEADER_OP__SHIFT 27 | |||
#define VIV_FE_END_HEADER_OP_END 0x10000000 | |||
#define VIV_FE_NOP 0x00000000 | |||
#define VIV_FE_NOP_HEADER 0x00000000 | |||
#define VIV_FE_NOP_HEADER_OP__MASK 0xf8000000 | |||
#define VIV_FE_NOP_HEADER_OP__SHIFT 27 | |||
#define VIV_FE_NOP_HEADER_OP_NOP 0x18000000 | |||
#define VIV_FE_DRAW_2D 0x00000000 | |||
#define VIV_FE_DRAW_2D_HEADER 0x00000000 | |||
#define VIV_FE_DRAW_2D_HEADER_COUNT__MASK 0x0000ff00 | |||
#define VIV_FE_DRAW_2D_HEADER_COUNT__SHIFT 8 | |||
#define VIV_FE_DRAW_2D_HEADER_COUNT(x) (((x) << VIV_FE_DRAW_2D_HEADER_COUNT__SHIFT) & VIV_FE_DRAW_2D_HEADER_COUNT__MASK) | |||
#define VIV_FE_DRAW_2D_HEADER_DATA_COUNT__MASK 0x07ff0000 | |||
#define VIV_FE_DRAW_2D_HEADER_DATA_COUNT__SHIFT 16 | |||
#define VIV_FE_DRAW_2D_HEADER_DATA_COUNT(x) (((x) << VIV_FE_DRAW_2D_HEADER_DATA_COUNT__SHIFT) & VIV_FE_DRAW_2D_HEADER_DATA_COUNT__MASK) | |||
#define VIV_FE_DRAW_2D_HEADER_OP__MASK 0xf8000000 | |||
#define VIV_FE_DRAW_2D_HEADER_OP__SHIFT 27 | |||
#define VIV_FE_DRAW_2D_HEADER_OP_DRAW_2D 0x20000000 | |||
#define VIV_FE_DRAW_2D_TOP_LEFT 0x00000008 | |||
#define VIV_FE_DRAW_2D_TOP_LEFT_X__MASK 0x0000ffff | |||
#define VIV_FE_DRAW_2D_TOP_LEFT_X__SHIFT 0 | |||
#define VIV_FE_DRAW_2D_TOP_LEFT_X(x) (((x) << VIV_FE_DRAW_2D_TOP_LEFT_X__SHIFT) & VIV_FE_DRAW_2D_TOP_LEFT_X__MASK) | |||
#define VIV_FE_DRAW_2D_TOP_LEFT_Y__MASK 0xffff0000 | |||
#define VIV_FE_DRAW_2D_TOP_LEFT_Y__SHIFT 16 | |||
#define VIV_FE_DRAW_2D_TOP_LEFT_Y(x) (((x) << VIV_FE_DRAW_2D_TOP_LEFT_Y__SHIFT) & VIV_FE_DRAW_2D_TOP_LEFT_Y__MASK) | |||
#define VIV_FE_DRAW_2D_BOTTOM_RIGHT 0x0000000c | |||
#define VIV_FE_DRAW_2D_BOTTOM_RIGHT_X__MASK 0x0000ffff | |||
#define VIV_FE_DRAW_2D_BOTTOM_RIGHT_X__SHIFT 0 | |||
#define VIV_FE_DRAW_2D_BOTTOM_RIGHT_X(x) (((x) << VIV_FE_DRAW_2D_BOTTOM_RIGHT_X__SHIFT) & VIV_FE_DRAW_2D_BOTTOM_RIGHT_X__MASK) | |||
#define VIV_FE_DRAW_2D_BOTTOM_RIGHT_Y__MASK 0xffff0000 | |||
#define VIV_FE_DRAW_2D_BOTTOM_RIGHT_Y__SHIFT 16 | |||
#define VIV_FE_DRAW_2D_BOTTOM_RIGHT_Y(x) (((x) << VIV_FE_DRAW_2D_BOTTOM_RIGHT_Y__SHIFT) & VIV_FE_DRAW_2D_BOTTOM_RIGHT_Y__MASK) | |||
#define VIV_FE_DRAW_PRIMITIVES 0x00000000 | |||
#define VIV_FE_DRAW_PRIMITIVES_HEADER 0x00000000 | |||
#define VIV_FE_DRAW_PRIMITIVES_HEADER_OP__MASK 0xf8000000 | |||
#define VIV_FE_DRAW_PRIMITIVES_HEADER_OP__SHIFT 27 | |||
#define VIV_FE_DRAW_PRIMITIVES_HEADER_OP_DRAW_PRIMITIVES 0x28000000 | |||
#define VIV_FE_DRAW_PRIMITIVES_COMMAND 0x00000004 | |||
#define VIV_FE_DRAW_PRIMITIVES_COMMAND_TYPE__MASK 0x000000ff | |||
#define VIV_FE_DRAW_PRIMITIVES_COMMAND_TYPE__SHIFT 0 | |||
#define VIV_FE_DRAW_PRIMITIVES_COMMAND_TYPE(x) (((x) << VIV_FE_DRAW_PRIMITIVES_COMMAND_TYPE__SHIFT) & VIV_FE_DRAW_PRIMITIVES_COMMAND_TYPE__MASK) | |||
#define VIV_FE_DRAW_PRIMITIVES_START 0x00000008 | |||
#define VIV_FE_DRAW_PRIMITIVES_COUNT 0x0000000c | |||
#define VIV_FE_DRAW_INDEXED_PRIMITIVES 0x00000000 | |||
#define VIV_FE_DRAW_INDEXED_PRIMITIVES_HEADER 0x00000000 | |||
#define VIV_FE_DRAW_INDEXED_PRIMITIVES_HEADER_OP__MASK 0xf8000000 | |||
#define VIV_FE_DRAW_INDEXED_PRIMITIVES_HEADER_OP__SHIFT 27 | |||
#define VIV_FE_DRAW_INDEXED_PRIMITIVES_HEADER_OP_DRAW_INDEXED_PRIMITIVES 0x30000000 | |||
#define VIV_FE_DRAW_INDEXED_PRIMITIVES_COMMAND 0x00000004 | |||
#define VIV_FE_DRAW_INDEXED_PRIMITIVES_COMMAND_TYPE__MASK 0x000000ff | |||
#define VIV_FE_DRAW_INDEXED_PRIMITIVES_COMMAND_TYPE__SHIFT 0 | |||
#define VIV_FE_DRAW_INDEXED_PRIMITIVES_COMMAND_TYPE(x) (((x) << VIV_FE_DRAW_INDEXED_PRIMITIVES_COMMAND_TYPE__SHIFT) & VIV_FE_DRAW_INDEXED_PRIMITIVES_COMMAND_TYPE__MASK) | |||
#define VIV_FE_DRAW_INDEXED_PRIMITIVES_START 0x00000008 | |||
#define VIV_FE_DRAW_INDEXED_PRIMITIVES_COUNT 0x0000000c | |||
#define VIV_FE_DRAW_INDEXED_PRIMITIVES_OFFSET 0x00000010 | |||
#define VIV_FE_WAIT 0x00000000 | |||
#define VIV_FE_WAIT_HEADER 0x00000000 | |||
#define VIV_FE_WAIT_HEADER_DELAY__MASK 0x0000ffff | |||
#define VIV_FE_WAIT_HEADER_DELAY__SHIFT 0 | |||
#define VIV_FE_WAIT_HEADER_DELAY(x) (((x) << VIV_FE_WAIT_HEADER_DELAY__SHIFT) & VIV_FE_WAIT_HEADER_DELAY__MASK) | |||
#define VIV_FE_WAIT_HEADER_OP__MASK 0xf8000000 | |||
#define VIV_FE_WAIT_HEADER_OP__SHIFT 27 | |||
#define VIV_FE_WAIT_HEADER_OP_WAIT 0x38000000 | |||
#define VIV_FE_LINK 0x00000000 | |||
#define VIV_FE_LINK_HEADER 0x00000000 | |||
#define VIV_FE_LINK_HEADER_PREFETCH__MASK 0x0000ffff | |||
#define VIV_FE_LINK_HEADER_PREFETCH__SHIFT 0 | |||
#define VIV_FE_LINK_HEADER_PREFETCH(x) (((x) << VIV_FE_LINK_HEADER_PREFETCH__SHIFT) & VIV_FE_LINK_HEADER_PREFETCH__MASK) | |||
#define VIV_FE_LINK_HEADER_OP__MASK 0xf8000000 | |||
#define VIV_FE_LINK_HEADER_OP__SHIFT 27 | |||
#define VIV_FE_LINK_HEADER_OP_LINK 0x40000000 | |||
#define VIV_FE_LINK_ADDRESS 0x00000004 | |||
#define VIV_FE_STALL 0x00000000 | |||
#define VIV_FE_STALL_HEADER 0x00000000 | |||
#define VIV_FE_STALL_HEADER_OP__MASK 0xf8000000 | |||
#define VIV_FE_STALL_HEADER_OP__SHIFT 27 | |||
#define VIV_FE_STALL_HEADER_OP_STALL 0x48000000 | |||
#define VIV_FE_STALL_TOKEN 0x00000004 | |||
#define VIV_FE_STALL_TOKEN_FROM__MASK 0x0000001f | |||
#define VIV_FE_STALL_TOKEN_FROM__SHIFT 0 | |||
#define VIV_FE_STALL_TOKEN_FROM(x) (((x) << VIV_FE_STALL_TOKEN_FROM__SHIFT) & VIV_FE_STALL_TOKEN_FROM__MASK) | |||
#define VIV_FE_STALL_TOKEN_TO__MASK 0x00001f00 | |||
#define VIV_FE_STALL_TOKEN_TO__SHIFT 8 | |||
#define VIV_FE_STALL_TOKEN_TO(x) (((x) << VIV_FE_STALL_TOKEN_TO__SHIFT) & VIV_FE_STALL_TOKEN_TO__MASK) | |||
#define VIV_FE_CALL 0x00000000 | |||
#define VIV_FE_CALL_HEADER 0x00000000 | |||
#define VIV_FE_CALL_HEADER_PREFETCH__MASK 0x0000ffff | |||
#define VIV_FE_CALL_HEADER_PREFETCH__SHIFT 0 | |||
#define VIV_FE_CALL_HEADER_PREFETCH(x) (((x) << VIV_FE_CALL_HEADER_PREFETCH__SHIFT) & VIV_FE_CALL_HEADER_PREFETCH__MASK) | |||
#define VIV_FE_CALL_HEADER_OP__MASK 0xf8000000 | |||
#define VIV_FE_CALL_HEADER_OP__SHIFT 27 | |||
#define VIV_FE_CALL_HEADER_OP_CALL 0x50000000 | |||
#define VIV_FE_CALL_ADDRESS 0x00000004 | |||
#define VIV_FE_CALL_RETURN_PREFETCH 0x00000008 | |||
#define VIV_FE_CALL_RETURN_ADDRESS 0x0000000c | |||
#define VIV_FE_RETURN 0x00000000 | |||
#define VIV_FE_RETURN_HEADER 0x00000000 | |||
#define VIV_FE_RETURN_HEADER_OP__MASK 0xf8000000 | |||
#define VIV_FE_RETURN_HEADER_OP__SHIFT 27 | |||
#define VIV_FE_RETURN_HEADER_OP_RETURN 0x58000000 | |||
#define VIV_FE_CHIP_SELECT 0x00000000 | |||
#define VIV_FE_CHIP_SELECT_HEADER 0x00000000 | |||
#define VIV_FE_CHIP_SELECT_HEADER_OP__MASK 0xf8000000 | |||
#define VIV_FE_CHIP_SELECT_HEADER_OP__SHIFT 27 | |||
#define VIV_FE_CHIP_SELECT_HEADER_OP_CHIP_SELECT 0x68000000 | |||
#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP15 0x00008000 | |||
#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP14 0x00004000 | |||
#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP13 0x00002000 | |||
#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP12 0x00001000 | |||
#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP11 0x00000800 | |||
#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP10 0x00000400 | |||
#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP9 0x00000200 | |||
#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP8 0x00000100 | |||
#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP7 0x00000080 | |||
#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP6 0x00000040 | |||
#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP5 0x00000020 | |||
#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP4 0x00000010 | |||
#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP3 0x00000008 | |||
#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP2 0x00000004 | |||
#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP1 0x00000002 | |||
#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP0 0x00000001 | |||
#define VIV_FE_DRAW_INSTANCED 0x00000000 | |||
#define VIV_FE_DRAW_INSTANCED_HEADER 0x00000000 | |||
#define VIV_FE_DRAW_INSTANCED_HEADER_OP__MASK 0xf8000000 | |||
#define VIV_FE_DRAW_INSTANCED_HEADER_OP__SHIFT 27 | |||
#define VIV_FE_DRAW_INSTANCED_HEADER_OP_DRAW_INSTANCED 0x60000000 | |||
#define VIV_FE_DRAW_INSTANCED_HEADER_INDEXED 0x00100000 | |||
#define VIV_FE_DRAW_INSTANCED_HEADER_TYPE__MASK 0x000f0000 | |||
#define VIV_FE_DRAW_INSTANCED_HEADER_TYPE__SHIFT 16 | |||
#define VIV_FE_DRAW_INSTANCED_HEADER_TYPE(x) (((x) << VIV_FE_DRAW_INSTANCED_HEADER_TYPE__SHIFT) & VIV_FE_DRAW_INSTANCED_HEADER_TYPE__MASK) | |||
#define VIV_FE_DRAW_INSTANCED_HEADER_INSTANCE_COUNT_LO__MASK 0x0000ffff | |||
#define VIV_FE_DRAW_INSTANCED_HEADER_INSTANCE_COUNT_LO__SHIFT 0 | |||
#define VIV_FE_DRAW_INSTANCED_HEADER_INSTANCE_COUNT_LO(x) (((x) << VIV_FE_DRAW_INSTANCED_HEADER_INSTANCE_COUNT_LO__SHIFT) & VIV_FE_DRAW_INSTANCED_HEADER_INSTANCE_COUNT_LO__MASK) | |||
#define VIV_FE_DRAW_INSTANCED_COUNT 0x00000004 | |||
#define VIV_FE_DRAW_INSTANCED_COUNT_INSTANCE_COUNT_HI__MASK 0xff000000 | |||
#define VIV_FE_DRAW_INSTANCED_COUNT_INSTANCE_COUNT_HI__SHIFT 24 | |||
#define VIV_FE_DRAW_INSTANCED_COUNT_INSTANCE_COUNT_HI(x) (((x) << VIV_FE_DRAW_INSTANCED_COUNT_INSTANCE_COUNT_HI__SHIFT) & VIV_FE_DRAW_INSTANCED_COUNT_INSTANCE_COUNT_HI__MASK) | |||
#define VIV_FE_DRAW_INSTANCED_COUNT_VERTEX_COUNT__MASK 0x00ffffff | |||
#define VIV_FE_DRAW_INSTANCED_COUNT_VERTEX_COUNT__SHIFT 0 | |||
#define VIV_FE_DRAW_INSTANCED_COUNT_VERTEX_COUNT(x) (((x) << VIV_FE_DRAW_INSTANCED_COUNT_VERTEX_COUNT__SHIFT) & VIV_FE_DRAW_INSTANCED_COUNT_VERTEX_COUNT__MASK) | |||
#define VIV_FE_DRAW_INSTANCED_START 0x00000008 | |||
#define VIV_FE_DRAW_INSTANCED_START_INDEX__MASK 0xffffffff | |||
#define VIV_FE_DRAW_INSTANCED_START_INDEX__SHIFT 0 | |||
#define VIV_FE_DRAW_INSTANCED_START_INDEX(x) (((x) << VIV_FE_DRAW_INSTANCED_START_INDEX__SHIFT) & VIV_FE_DRAW_INSTANCED_START_INDEX__MASK) | |||
#endif /* CMDSTREAM_XML */ |
@@ -0,0 +1,320 @@ | |||
#ifndef COMMON_XML | |||
#define COMMON_XML | |||
/* Autogenerated file, DO NOT EDIT manually! | |||
This file was generated by the rules-ng-ng headergen tool in this git repository: | |||
http://0x04.net/cgit/index.cgi/rules-ng-ng | |||
git clone git://0x04.net/rules-ng-ng | |||
The rules-ng-ng source files this header was generated from are: | |||
- state.xml ( 19792 bytes, from 2016-11-16 18:54:37) | |||
- common.xml ( 23422 bytes, from 2016-11-16 18:54:37) | |||
- state_hi.xml ( 25653 bytes, from 2016-10-02 14:26:13) | |||
- copyright.xml ( 1597 bytes, from 2016-10-02 14:26:13) | |||
- state_2d.xml ( 51552 bytes, from 2016-10-02 14:26:13) | |||
- state_3d.xml ( 57579 bytes, from 2016-11-16 18:54:37) | |||
- state_vg.xml ( 5975 bytes, from 2016-10-02 14:26:13) | |||
Copyright (C) 2012-2016 by the following authors: | |||
- Wladimir J. van der Laan <laanwj@gmail.com> | |||
- Christian Gmeiner <christian.gmeiner@gmail.com> | |||
- Lucas Stach <l.stach@pengutronix.de> | |||
- Russell King <rmk@arm.linux.org.uk> | |||
Permission is hereby granted, free of charge, to any person obtaining a | |||
copy of this software and associated documentation files (the "Software"), | |||
to deal in the Software without restriction, including without limitation | |||
the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
and/or sell copies of the Software, and to permit persons to whom the | |||
Software is furnished to do so, subject to the following conditions: | |||
The above copyright notice and this permission notice (including the | |||
next paragraph) shall be included in all copies or substantial portions | |||
of the Software. | |||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
DEALINGS IN THE SOFTWARE. | |||
*/ | |||
#define PIPE_ID_PIPE_3D 0x00000000 | |||
#define PIPE_ID_PIPE_2D 0x00000001 | |||
#define SYNC_RECIPIENT_FE 0x00000001 | |||
#define SYNC_RECIPIENT_RA 0x00000005 | |||
#define SYNC_RECIPIENT_PE 0x00000007 | |||
#define SYNC_RECIPIENT_DE 0x0000000b | |||
#define SYNC_RECIPIENT_VG 0x0000000f | |||
#define SYNC_RECIPIENT_TESSELATOR 0x00000010 | |||
#define SYNC_RECIPIENT_VG2 0x00000011 | |||
#define SYNC_RECIPIENT_TESSELATOR2 0x00000012 | |||
#define SYNC_RECIPIENT_VG3 0x00000013 | |||
#define SYNC_RECIPIENT_TESSELATOR3 0x00000014 | |||
#define ENDIAN_MODE_NO_SWAP 0x00000000 | |||
#define ENDIAN_MODE_SWAP_16 0x00000001 | |||
#define ENDIAN_MODE_SWAP_32 0x00000002 | |||
#define chipModel_GC200 0x00000200 | |||
#define chipModel_GC300 0x00000300 | |||
#define chipModel_GC320 0x00000320 | |||
#define chipModel_GC328 0x00000328 | |||
#define chipModel_GC350 0x00000350 | |||
#define chipModel_GC355 0x00000355 | |||
#define chipModel_GC400 0x00000400 | |||
#define chipModel_GC410 0x00000410 | |||
#define chipModel_GC420 0x00000420 | |||
#define chipModel_GC428 0x00000428 | |||
#define chipModel_GC450 0x00000450 | |||
#define chipModel_GC500 0x00000500 | |||
#define chipModel_GC520 0x00000520 | |||
#define chipModel_GC530 0x00000530 | |||
#define chipModel_GC600 0x00000600 | |||
#define chipModel_GC700 0x00000700 | |||
#define chipModel_GC800 0x00000800 | |||
#define chipModel_GC860 0x00000860 | |||
#define chipModel_GC880 0x00000880 | |||
#define chipModel_GC1000 0x00001000 | |||
#define chipModel_GC1500 0x00001500 | |||
#define chipModel_GC2000 0x00002000 | |||
#define chipModel_GC2100 0x00002100 | |||
#define chipModel_GC2200 0x00002200 | |||
#define chipModel_GC2500 0x00002500 | |||
#define chipModel_GC3000 0x00003000 | |||
#define chipModel_GC4000 0x00004000 | |||
#define chipModel_GC5000 0x00005000 | |||
#define chipModel_GC5200 0x00005200 | |||
#define chipModel_GC6400 0x00006400 | |||
#define RGBA_BITS_R 0x00000001 | |||
#define RGBA_BITS_G 0x00000002 | |||
#define RGBA_BITS_B 0x00000004 | |||
#define RGBA_BITS_A 0x00000008 | |||
#define chipFeatures_FAST_CLEAR 0x00000001 | |||
#define chipFeatures_SPECIAL_ANTI_ALIASING 0x00000002 | |||
#define chipFeatures_PIPE_3D 0x00000004 | |||
#define chipFeatures_DXT_TEXTURE_COMPRESSION 0x00000008 | |||
#define chipFeatures_DEBUG_MODE 0x00000010 | |||
#define chipFeatures_Z_COMPRESSION 0x00000020 | |||
#define chipFeatures_YUV420_SCALER 0x00000040 | |||
#define chipFeatures_MSAA 0x00000080 | |||
#define chipFeatures_DC 0x00000100 | |||
#define chipFeatures_PIPE_2D 0x00000200 | |||
#define chipFeatures_ETC1_TEXTURE_COMPRESSION 0x00000400 | |||
#define chipFeatures_FAST_SCALER 0x00000800 | |||
#define chipFeatures_HIGH_DYNAMIC_RANGE 0x00001000 | |||
#define chipFeatures_YUV420_TILER 0x00002000 | |||
#define chipFeatures_MODULE_CG 0x00004000 | |||
#define chipFeatures_MIN_AREA 0x00008000 | |||
#define chipFeatures_NO_EARLY_Z 0x00010000 | |||
#define chipFeatures_NO_422_TEXTURE 0x00020000 | |||
#define chipFeatures_BUFFER_INTERLEAVING 0x00040000 | |||
#define chipFeatures_BYTE_WRITE_2D 0x00080000 | |||
#define chipFeatures_NO_SCALER 0x00100000 | |||
#define chipFeatures_YUY2_AVERAGING 0x00200000 | |||
#define chipFeatures_HALF_PE_CACHE 0x00400000 | |||
#define chipFeatures_HALF_TX_CACHE 0x00800000 | |||
#define chipFeatures_YUY2_RENDER_TARGET 0x01000000 | |||
#define chipFeatures_MEM32 0x02000000 | |||
#define chipFeatures_PIPE_VG 0x04000000 | |||
#define chipFeatures_VGTS 0x08000000 | |||
#define chipFeatures_FE20 0x10000000 | |||
#define chipFeatures_BYTE_WRITE_3D 0x20000000 | |||
#define chipFeatures_RS_YUV_TARGET 0x40000000 | |||
#define chipFeatures_32_BIT_INDICES 0x80000000 | |||
#define chipMinorFeatures0_FLIP_Y 0x00000001 | |||
#define chipMinorFeatures0_DUAL_RETURN_BUS 0x00000002 | |||
#define chipMinorFeatures0_ENDIANNESS_CONFIG 0x00000004 | |||
#define chipMinorFeatures0_TEXTURE_8K 0x00000008 | |||
#define chipMinorFeatures0_CORRECT_TEXTURE_CONVERTER 0x00000010 | |||
#define chipMinorFeatures0_SPECIAL_MSAA_LOD 0x00000020 | |||
#define chipMinorFeatures0_FAST_CLEAR_FLUSH 0x00000040 | |||
#define chipMinorFeatures0_2DPE20 0x00000080 | |||
#define chipMinorFeatures0_CORRECT_AUTO_DISABLE 0x00000100 | |||
#define chipMinorFeatures0_RENDERTARGET_8K 0x00000200 | |||
#define chipMinorFeatures0_2BITPERTILE 0x00000400 | |||
#define chipMinorFeatures0_SEPARATE_TILE_STATUS_WHEN_INTERLEAVED 0x00000800 | |||
#define chipMinorFeatures0_SUPER_TILED 0x00001000 | |||
#define chipMinorFeatures0_VG_20 0x00002000 | |||
#define chipMinorFeatures0_TS_EXTENDED_COMMANDS 0x00004000 | |||
#define chipMinorFeatures0_COMPRESSION_FIFO_FIXED 0x00008000 | |||
#define chipMinorFeatures0_HAS_SIGN_FLOOR_CEIL 0x00010000 | |||
#define chipMinorFeatures0_VG_FILTER 0x00020000 | |||
#define chipMinorFeatures0_VG_21 0x00040000 | |||
#define chipMinorFeatures0_SHADER_HAS_W 0x00080000 | |||
#define chipMinorFeatures0_HAS_SQRT_TRIG 0x00100000 | |||
#define chipMinorFeatures0_MORE_MINOR_FEATURES 0x00200000 | |||
#define chipMinorFeatures0_MC20 0x00400000 | |||
#define chipMinorFeatures0_MSAA_SIDEBAND 0x00800000 | |||
#define chipMinorFeatures0_BUG_FIXES0 0x01000000 | |||
#define chipMinorFeatures0_VAA 0x02000000 | |||
#define chipMinorFeatures0_BYPASS_IN_MSAA 0x04000000 | |||
#define chipMinorFeatures0_HZ 0x08000000 | |||
#define chipMinorFeatures0_NEW_TEXTURE 0x10000000 | |||
#define chipMinorFeatures0_2D_A8_TARGET 0x20000000 | |||
#define chipMinorFeatures0_CORRECT_STENCIL 0x40000000 | |||
#define chipMinorFeatures0_ENHANCE_VR 0x80000000 | |||
#define chipMinorFeatures1_RSUV_SWIZZLE 0x00000001 | |||
#define chipMinorFeatures1_V2_COMPRESSION 0x00000002 | |||
#define chipMinorFeatures1_VG_DOUBLE_BUFFER 0x00000004 | |||
#define chipMinorFeatures1_EXTRA_EVENT_STATES 0x00000008 | |||
#define chipMinorFeatures1_NO_STRIPING_NEEDED 0x00000010 | |||
#define chipMinorFeatures1_TEXTURE_STRIDE 0x00000020 | |||
#define chipMinorFeatures1_BUG_FIXES3 0x00000040 | |||
#define chipMinorFeatures1_AUTO_DISABLE 0x00000080 | |||
#define chipMinorFeatures1_AUTO_RESTART_TS 0x00000100 | |||
#define chipMinorFeatures1_DISABLE_PE_GATING 0x00000200 | |||
#define chipMinorFeatures1_L2_WINDOWING 0x00000400 | |||
#define chipMinorFeatures1_HALF_FLOAT 0x00000800 | |||
#define chipMinorFeatures1_PIXEL_DITHER 0x00001000 | |||
#define chipMinorFeatures1_TWO_STENCIL_REFERENCE 0x00002000 | |||
#define chipMinorFeatures1_EXTENDED_PIXEL_FORMAT 0x00004000 | |||
#define chipMinorFeatures1_CORRECT_MIN_MAX_DEPTH 0x00008000 | |||
#define chipMinorFeatures1_2D_DITHER 0x00010000 | |||
#define chipMinorFeatures1_BUG_FIXES5 0x00020000 | |||
#define chipMinorFeatures1_NEW_2D 0x00040000 | |||
#define chipMinorFeatures1_NEW_FP 0x00080000 | |||
#define chipMinorFeatures1_TEXTURE_HALIGN 0x00100000 | |||
#define chipMinorFeatures1_NON_POWER_OF_TWO 0x00200000 | |||
#define chipMinorFeatures1_LINEAR_TEXTURE_SUPPORT 0x00400000 | |||
#define chipMinorFeatures1_HALTI0 0x00800000 | |||
#define chipMinorFeatures1_CORRECT_OVERFLOW_VG 0x01000000 | |||
#define chipMinorFeatures1_NEGATIVE_LOG_FIX 0x02000000 | |||
#define chipMinorFeatures1_RESOLVE_OFFSET 0x04000000 | |||
#define chipMinorFeatures1_OK_TO_GATE_AXI_CLOCK 0x08000000 | |||
#define chipMinorFeatures1_MMU_VERSION 0x10000000 | |||
#define chipMinorFeatures1_WIDE_LINE 0x20000000 | |||
#define chipMinorFeatures1_BUG_FIXES6 0x40000000 | |||
#define chipMinorFeatures1_FC_FLUSH_STALL 0x80000000 | |||
#define chipMinorFeatures2_LINE_LOOP 0x00000001 | |||
#define chipMinorFeatures2_LOGIC_OP 0x00000002 | |||
#define chipMinorFeatures2_SEAMLESS_CUBE_MAP 0x00000004 | |||
#define chipMinorFeatures2_SUPERTILED_TEXTURE 0x00000008 | |||
#define chipMinorFeatures2_LINEAR_PE 0x00000010 | |||
#define chipMinorFeatures2_RECT_PRIMITIVE 0x00000020 | |||
#define chipMinorFeatures2_COMPOSITION 0x00000040 | |||
#define chipMinorFeatures2_CORRECT_AUTO_DISABLE_COUNT 0x00000080 | |||
#define chipMinorFeatures2_PE_SWIZZLE 0x00000100 | |||
#define chipMinorFeatures2_END_EVENT 0x00000200 | |||
#define chipMinorFeatures2_S1S8 0x00000400 | |||
#define chipMinorFeatures2_HALTI1 0x00000800 | |||
#define chipMinorFeatures2_RGB888 0x00001000 | |||
#define chipMinorFeatures2_TX__YUV_ASSEMBLER 0x00002000 | |||
#define chipMinorFeatures2_DYNAMIC_FREQUENCY_SCALING 0x00004000 | |||
#define chipMinorFeatures2_EXTRA_TEXTURE_STATE 0x00008000 | |||
#define chipMinorFeatures2_FULL_DIRECTFB 0x00010000 | |||
#define chipMinorFeatures2_2D_TILING 0x00020000 | |||
#define chipMinorFeatures2_THREAD_WALKER_IN_PS 0x00040000 | |||
#define chipMinorFeatures2_TILE_FILLER 0x00080000 | |||
#define chipMinorFeatures2_YUV_STANDARD 0x00100000 | |||
#define chipMinorFeatures2_2D_MULTI_SOURCE_BLIT 0x00200000 | |||
#define chipMinorFeatures2_YUV_CONVERSION 0x00400000 | |||
#define chipMinorFeatures2_FLUSH_FIXED_2D 0x00800000 | |||
#define chipMinorFeatures2_INTERLEAVER 0x01000000 | |||
#define chipMinorFeatures2_MIXED_STREAMS 0x02000000 | |||
#define chipMinorFeatures2_2D_420_L2CACHE 0x04000000 | |||
#define chipMinorFeatures2_BUG_FIXES7 0x08000000 | |||
#define chipMinorFeatures2_2D_NO_INDEX8_BRUSH 0x10000000 | |||
#define chipMinorFeatures2_TEXTURE_TILED_READ 0x20000000 | |||
#define chipMinorFeatures2_DECOMPRESS_Z16 0x40000000 | |||
#define chipMinorFeatures2_BUG_FIXES8 0x80000000 | |||
#define chipMinorFeatures3_ROTATION_STALL_FIX 0x00000001 | |||
#define chipMinorFeatures3_OCL_ONLY 0x00000002 | |||
#define chipMinorFeatures3_2D_MULTI_SOURCE_BLT_EX 0x00000004 | |||
#define chipMinorFeatures3_INSTRUCTION_CACHE 0x00000008 | |||
#define chipMinorFeatures3_GEOMETRY_SHADER 0x00000010 | |||
#define chipMinorFeatures3_TEX_COMPRESSION_SUPERTILED 0x00000020 | |||
#define chipMinorFeatures3_GENERICS 0x00000040 | |||
#define chipMinorFeatures3_BUG_FIXES9 0x00000080 | |||
#define chipMinorFeatures3_FAST_MSAA 0x00000100 | |||
#define chipMinorFeatures3_WCLIP 0x00000200 | |||
#define chipMinorFeatures3_BUG_FIXES10 0x00000400 | |||
#define chipMinorFeatures3_UNIFIED_SAMPLERS 0x00000800 | |||
#define chipMinorFeatures3_BUG_FIXES11 0x00001000 | |||
#define chipMinorFeatures3_PERFORMANCE_COUNTERS 0x00002000 | |||
#define chipMinorFeatures3_HAS_FAST_TRANSCENDENTALS 0x00004000 | |||
#define chipMinorFeatures3_BUG_FIXES12 0x00008000 | |||
#define chipMinorFeatures3_BUG_FIXES13 0x00010000 | |||
#define chipMinorFeatures3_DE_ENHANCEMENTS1 0x00020000 | |||
#define chipMinorFeatures3_ACE 0x00040000 | |||
#define chipMinorFeatures3_TX_ENHANCEMENTS1 0x00080000 | |||
#define chipMinorFeatures3_SH_ENHANCEMENTS1 0x00100000 | |||
#define chipMinorFeatures3_SH_ENHANCEMENTS2 0x00200000 | |||
#define chipMinorFeatures3_UNK22 0x00400000 | |||
#define chipMinorFeatures3_2D_FC_SOURCE 0x00800000 | |||
#define chipMinorFeatures3_UNK24 0x01000000 | |||
#define chipMinorFeatures3_UNK25 0x02000000 | |||
#define chipMinorFeatures3_NEW_HZ 0x04000000 | |||
#define chipMinorFeatures3_UNK27 0x08000000 | |||
#define chipMinorFeatures3_UNK28 0x10000000 | |||
#define chipMinorFeatures3_SH_ENHANCEMENTS3 0x20000000 | |||
#define chipMinorFeatures3_UNK30 0x40000000 | |||
#define chipMinorFeatures3_UNK31 0x80000000 | |||
#define chipMinorFeatures4_UNK0 0x00000001 | |||
#define chipMinorFeatures4_PE_ENHANCEMENTS2 0x00000002 | |||
#define chipMinorFeatures4_FRUSTUM_CLIP_FIX 0x00000004 | |||
#define chipMinorFeatures4_UNK3 0x00000008 | |||
#define chipMinorFeatures4_UNK4 0x00000010 | |||
#define chipMinorFeatures4_2D_GAMMA 0x00000020 | |||
#define chipMinorFeatures4_SINGLE_BUFFER 0x00000040 | |||
#define chipMinorFeatures4_UNK7 0x00000080 | |||
#define chipMinorFeatures4_UNK8 0x00000100 | |||
#define chipMinorFeatures4_UNK9 0x00000200 | |||
#define chipMinorFeatures4_UNK10 0x00000400 | |||
#define chipMinorFeatures4_TX_LERP_PRECISION_FIX 0x00000800 | |||
#define chipMinorFeatures4_2D_COLOR_SPACE_CONVERSION 0x00001000 | |||
#define chipMinorFeatures4_TEXTURE_ASTC 0x00002000 | |||
#define chipMinorFeatures4_UNK14 0x00004000 | |||
#define chipMinorFeatures4_UNK15 0x00008000 | |||
#define chipMinorFeatures4_HALTI2 0x00010000 | |||
#define chipMinorFeatures4_UNK17 0x00020000 | |||
#define chipMinorFeatures4_SMALL_MSAA 0x00040000 | |||
#define chipMinorFeatures4_UNK19 0x00080000 | |||
#define chipMinorFeatures4_NEW_RA 0x00100000 | |||
#define chipMinorFeatures4_2D_OPF_YUV_OUTPUT 0x00200000 | |||
#define chipMinorFeatures4_2D_MULTI_SOURCE_BLT_EX2 0x00400000 | |||
#define chipMinorFeatures4_NO_USER_CSC 0x00800000 | |||
#define chipMinorFeatures4_ZFIXES 0x01000000 | |||
#define chipMinorFeatures4_BUG_FIXES18 0x02000000 | |||
#define chipMinorFeatures4_2D_COMPRESSION 0x04000000 | |||
#define chipMinorFeatures4_PROBE 0x08000000 | |||
#define chipMinorFeatures4_UNK28 0x10000000 | |||
#define chipMinorFeatures4_2D_SUPER_TILE_VERSION 0x20000000 | |||
#define chipMinorFeatures4_UNK30 0x40000000 | |||
#define chipMinorFeatures4_UNK31 0x80000000 | |||
#define chipMinorFeatures5_UNK0 0x00000001 | |||
#define chipMinorFeatures5_UNK1 0x00000002 | |||
#define chipMinorFeatures5_UNK2 0x00000004 | |||
#define chipMinorFeatures5_UNK3 0x00000008 | |||
#define chipMinorFeatures5_EEZ 0x00000010 | |||
#define chipMinorFeatures5_UNK5 0x00000020 | |||
#define chipMinorFeatures5_UNK6 0x00000040 | |||
#define chipMinorFeatures5_UNK7 0x00000080 | |||
#define chipMinorFeatures5_UNK8 0x00000100 | |||
#define chipMinorFeatures5_HALTI3 0x00000200 | |||
#define chipMinorFeatures5_UNK10 0x00000400 | |||
#define chipMinorFeatures5_2D_ONE_PASS_FILTER_TAP 0x00000800 | |||
#define chipMinorFeatures5_UNK12 0x00001000 | |||
#define chipMinorFeatures5_SEPARATE_SRC_DST 0x00002000 | |||
#define chipMinorFeatures5_HALTI4 0x00004000 | |||
#define chipMinorFeatures5_UNK15 0x00008000 | |||
#define chipMinorFeatures5_ANDROID_ONLY 0x00010000 | |||
#define chipMinorFeatures5_HAS_PRODUCTID 0x00020000 | |||
#define chipMinorFeatures5_UNK18 0x00040000 | |||
#define chipMinorFeatures5_UNK19 0x00080000 | |||
#define chipMinorFeatures5_PE_DITHER_FIX2 0x00100000 | |||
#define chipMinorFeatures5_UNK21 0x00200000 | |||
#define chipMinorFeatures5_UNK22 0x00400000 | |||
#define chipMinorFeatures5_UNK23 0x00800000 | |||
#define chipMinorFeatures5_UNK24 0x01000000 | |||
#define chipMinorFeatures5_UNK25 0x02000000 | |||
#define chipMinorFeatures5_UNK26 0x04000000 | |||
#define chipMinorFeatures5_RS_DEPTHSTENCIL_NATIVE_SUPPORT 0x08000000 | |||
#define chipMinorFeatures5_V2_MSAA_COMP_FIX 0x10000000 | |||
#define chipMinorFeatures5_UNK29 0x20000000 | |||
#define chipMinorFeatures5_UNK30 0x40000000 | |||
#define chipMinorFeatures5_UNK31 0x80000000 | |||
#endif /* COMMON_XML */ |
@@ -0,0 +1,239 @@ | |||
#ifndef ISA_XML | |||
#define ISA_XML | |||
/* Autogenerated file, DO NOT EDIT manually! | |||
This file was generated by the rules-ng-ng headergen tool in this git repository: | |||
http://0x04.net/cgit/index.cgi/rules-ng-ng | |||
git clone git://0x04.net/rules-ng-ng | |||
The rules-ng-ng source files this header was generated from are: | |||
- isa.xml ( 24392 bytes, from 2016-11-16 18:54:37) | |||
- copyright.xml ( 1597 bytes, from 2016-10-02 14:26:13) | |||
Copyright (C) 2012-2016 by the following authors: | |||
- Wladimir J. van der Laan <laanwj@gmail.com> | |||
- Christian Gmeiner <christian.gmeiner@gmail.com> | |||
- Lucas Stach <l.stach@pengutronix.de> | |||
- Russell King <rmk@arm.linux.org.uk> | |||
Permission is hereby granted, free of charge, to any person obtaining a | |||
copy of this software and associated documentation files (the "Software"), | |||
to deal in the Software without restriction, including without limitation | |||
the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
and/or sell copies of the Software, and to permit persons to whom the | |||
Software is furnished to do so, subject to the following conditions: | |||
The above copyright notice and this permission notice (including the | |||
next paragraph) shall be included in all copies or substantial portions | |||
of the Software. | |||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
DEALINGS IN THE SOFTWARE. | |||
*/ | |||
#define INST_OPCODE_NOP 0x00000000 | |||
#define INST_OPCODE_ADD 0x00000001 | |||
#define INST_OPCODE_MAD 0x00000002 | |||
#define INST_OPCODE_MUL 0x00000003 | |||
#define INST_OPCODE_DST 0x00000004 | |||
#define INST_OPCODE_DP3 0x00000005 | |||
#define INST_OPCODE_DP4 0x00000006 | |||
#define INST_OPCODE_DSX 0x00000007 | |||
#define INST_OPCODE_DSY 0x00000008 | |||
#define INST_OPCODE_MOV 0x00000009 | |||
#define INST_OPCODE_MOVAR 0x0000000a | |||
#define INST_OPCODE_MOVAF 0x0000000b | |||
#define INST_OPCODE_RCP 0x0000000c | |||
#define INST_OPCODE_RSQ 0x0000000d | |||
#define INST_OPCODE_LITP 0x0000000e | |||
#define INST_OPCODE_SELECT 0x0000000f | |||
#define INST_OPCODE_SET 0x00000010 | |||
#define INST_OPCODE_EXP 0x00000011 | |||
#define INST_OPCODE_LOG 0x00000012 | |||
#define INST_OPCODE_FRC 0x00000013 | |||
#define INST_OPCODE_CALL 0x00000014 | |||
#define INST_OPCODE_RET 0x00000015 | |||
#define INST_OPCODE_BRANCH 0x00000016 | |||
#define INST_OPCODE_TEXKILL 0x00000017 | |||
#define INST_OPCODE_TEXLD 0x00000018 | |||
#define INST_OPCODE_TEXLDB 0x00000019 | |||
#define INST_OPCODE_TEXLDD 0x0000001a | |||
#define INST_OPCODE_TEXLDL 0x0000001b | |||
#define INST_OPCODE_TEXLDPCF 0x0000001c | |||
#define INST_OPCODE_REP 0x0000001d | |||
#define INST_OPCODE_ENDREP 0x0000001e | |||
#define INST_OPCODE_LOOP 0x0000001f | |||
#define INST_OPCODE_ENDLOOP 0x00000020 | |||
#define INST_OPCODE_SQRT 0x00000021 | |||
#define INST_OPCODE_SIN 0x00000022 | |||
#define INST_OPCODE_COS 0x00000023 | |||
#define INST_OPCODE_FLOOR 0x00000025 | |||
#define INST_OPCODE_CEIL 0x00000026 | |||
#define INST_OPCODE_SIGN 0x00000027 | |||
#define INST_OPCODE_I2F 0x0000002d | |||
#define INST_OPCODE_CMP 0x00000031 | |||
#define INST_OPCODE_LOAD 0x00000032 | |||
#define INST_OPCODE_STORE 0x00000033 | |||
#define INST_OPCODE_IMULLO0 0x0000003c | |||
#define INST_OPCODE_IMULHI0 0x00000040 | |||
#define INST_OPCODE_IMADLO0 0x0000004c | |||
#define INST_OPCODE_LEADZERO 0x00000058 | |||
#define INST_OPCODE_LSHIFT 0x00000059 | |||
#define INST_OPCODE_RSHIFT 0x0000005a | |||
#define INST_OPCODE_ROTATE 0x0000005b | |||
#define INST_OPCODE_OR 0x0000005c | |||
#define INST_OPCODE_AND 0x0000005d | |||
#define INST_OPCODE_XOR 0x0000005e | |||
#define INST_OPCODE_NOT 0x0000005f | |||
#define INST_CONDITION_TRUE 0x00000000 | |||
#define INST_CONDITION_GT 0x00000001 | |||
#define INST_CONDITION_LT 0x00000002 | |||
#define INST_CONDITION_GE 0x00000003 | |||
#define INST_CONDITION_LE 0x00000004 | |||
#define INST_CONDITION_EQ 0x00000005 | |||
#define INST_CONDITION_NE 0x00000006 | |||
#define INST_CONDITION_AND 0x00000007 | |||
#define INST_CONDITION_OR 0x00000008 | |||
#define INST_CONDITION_XOR 0x00000009 | |||
#define INST_CONDITION_NOT 0x0000000a | |||
#define INST_CONDITION_NZ 0x0000000b | |||
#define INST_CONDITION_GEZ 0x0000000c | |||
#define INST_CONDITION_GZ 0x0000000d | |||
#define INST_CONDITION_LEZ 0x0000000e | |||
#define INST_CONDITION_LZ 0x0000000f | |||
#define INST_RGROUP_TEMP 0x00000000 | |||
#define INST_RGROUP_INTERNAL 0x00000001 | |||
#define INST_RGROUP_UNIFORM_0 0x00000002 | |||
#define INST_RGROUP_UNIFORM_1 0x00000003 | |||
#define INST_AMODE_DIRECT 0x00000000 | |||
#define INST_AMODE_ADD_A_X 0x00000001 | |||
#define INST_AMODE_ADD_A_Y 0x00000002 | |||
#define INST_AMODE_ADD_A_Z 0x00000003 | |||
#define INST_AMODE_ADD_A_W 0x00000004 | |||
#define INST_SWIZ_COMP_X 0x00000000 | |||
#define INST_SWIZ_COMP_Y 0x00000001 | |||
#define INST_SWIZ_COMP_Z 0x00000002 | |||
#define INST_SWIZ_COMP_W 0x00000003 | |||
#define INST_TYPE_F32 0x00000000 | |||
#define INST_TYPE_S32 0x00000001 | |||
#define INST_TYPE_S8 0x00000002 | |||
#define INST_TYPE_U16 0x00000003 | |||
#define INST_TYPE_F16 0x00000004 | |||
#define INST_TYPE_S16 0x00000005 | |||
#define INST_TYPE_U32 0x00000006 | |||
#define INST_TYPE_U8 0x00000007 | |||
#define INST_COMPS_X 0x00000001 | |||
#define INST_COMPS_Y 0x00000002 | |||
#define INST_COMPS_Z 0x00000004 | |||
#define INST_COMPS_W 0x00000008 | |||
#define INST_SWIZ_X__MASK 0x00000003 | |||
#define INST_SWIZ_X__SHIFT 0 | |||
#define INST_SWIZ_X(x) (((x) << INST_SWIZ_X__SHIFT) & INST_SWIZ_X__MASK) | |||
#define INST_SWIZ_Y__MASK 0x0000000c | |||
#define INST_SWIZ_Y__SHIFT 2 | |||
#define INST_SWIZ_Y(x) (((x) << INST_SWIZ_Y__SHIFT) & INST_SWIZ_Y__MASK) | |||
#define INST_SWIZ_Z__MASK 0x00000030 | |||
#define INST_SWIZ_Z__SHIFT 4 | |||
#define INST_SWIZ_Z(x) (((x) << INST_SWIZ_Z__SHIFT) & INST_SWIZ_Z__MASK) | |||
#define INST_SWIZ_W__MASK 0x000000c0 | |||
#define INST_SWIZ_W__SHIFT 6 | |||
#define INST_SWIZ_W(x) (((x) << INST_SWIZ_W__SHIFT) & INST_SWIZ_W__MASK) | |||
#define VIV_ISA_WORD_0 0x00000000 | |||
#define VIV_ISA_WORD_0_OPCODE__MASK 0x0000003f | |||
#define VIV_ISA_WORD_0_OPCODE__SHIFT 0 | |||
#define VIV_ISA_WORD_0_OPCODE(x) (((x) << VIV_ISA_WORD_0_OPCODE__SHIFT) & VIV_ISA_WORD_0_OPCODE__MASK) | |||
#define VIV_ISA_WORD_0_COND__MASK 0x000007c0 | |||
#define VIV_ISA_WORD_0_COND__SHIFT 6 | |||
#define VIV_ISA_WORD_0_COND(x) (((x) << VIV_ISA_WORD_0_COND__SHIFT) & VIV_ISA_WORD_0_COND__MASK) | |||
#define VIV_ISA_WORD_0_SAT 0x00000800 | |||
#define VIV_ISA_WORD_0_DST_USE 0x00001000 | |||
#define VIV_ISA_WORD_0_DST_AMODE__MASK 0x0000e000 | |||
#define VIV_ISA_WORD_0_DST_AMODE__SHIFT 13 | |||
#define VIV_ISA_WORD_0_DST_AMODE(x) (((x) << VIV_ISA_WORD_0_DST_AMODE__SHIFT) & VIV_ISA_WORD_0_DST_AMODE__MASK) | |||
#define VIV_ISA_WORD_0_DST_REG__MASK 0x007f0000 | |||
#define VIV_ISA_WORD_0_DST_REG__SHIFT 16 | |||
#define VIV_ISA_WORD_0_DST_REG(x) (((x) << VIV_ISA_WORD_0_DST_REG__SHIFT) & VIV_ISA_WORD_0_DST_REG__MASK) | |||
#define VIV_ISA_WORD_0_DST_COMPS__MASK 0x07800000 | |||
#define VIV_ISA_WORD_0_DST_COMPS__SHIFT 23 | |||
#define VIV_ISA_WORD_0_DST_COMPS(x) (((x) << VIV_ISA_WORD_0_DST_COMPS__SHIFT) & VIV_ISA_WORD_0_DST_COMPS__MASK) | |||
#define VIV_ISA_WORD_0_TEX_ID__MASK 0xf8000000 | |||
#define VIV_ISA_WORD_0_TEX_ID__SHIFT 27 | |||
#define VIV_ISA_WORD_0_TEX_ID(x) (((x) << VIV_ISA_WORD_0_TEX_ID__SHIFT) & VIV_ISA_WORD_0_TEX_ID__MASK) | |||
#define VIV_ISA_WORD_1 0x00000004 | |||
#define VIV_ISA_WORD_1_TEX_AMODE__MASK 0x00000007 | |||
#define VIV_ISA_WORD_1_TEX_AMODE__SHIFT 0 | |||
#define VIV_ISA_WORD_1_TEX_AMODE(x) (((x) << VIV_ISA_WORD_1_TEX_AMODE__SHIFT) & VIV_ISA_WORD_1_TEX_AMODE__MASK) | |||
#define VIV_ISA_WORD_1_TEX_SWIZ__MASK 0x000007f8 | |||
#define VIV_ISA_WORD_1_TEX_SWIZ__SHIFT 3 | |||
#define VIV_ISA_WORD_1_TEX_SWIZ(x) (((x) << VIV_ISA_WORD_1_TEX_SWIZ__SHIFT) & VIV_ISA_WORD_1_TEX_SWIZ__MASK) | |||
#define VIV_ISA_WORD_1_SRC0_USE 0x00000800 | |||
#define VIV_ISA_WORD_1_SRC0_REG__MASK 0x001ff000 | |||
#define VIV_ISA_WORD_1_SRC0_REG__SHIFT 12 | |||
#define VIV_ISA_WORD_1_SRC0_REG(x) (((x) << VIV_ISA_WORD_1_SRC0_REG__SHIFT) & VIV_ISA_WORD_1_SRC0_REG__MASK) | |||
#define VIV_ISA_WORD_1_TYPE_BIT2 0x00200000 | |||
#define VIV_ISA_WORD_1_SRC0_SWIZ__MASK 0x3fc00000 | |||
#define VIV_ISA_WORD_1_SRC0_SWIZ__SHIFT 22 | |||
#define VIV_ISA_WORD_1_SRC0_SWIZ(x) (((x) << VIV_ISA_WORD_1_SRC0_SWIZ__SHIFT) & VIV_ISA_WORD_1_SRC0_SWIZ__MASK) | |||
#define VIV_ISA_WORD_1_SRC0_NEG 0x40000000 | |||
#define VIV_ISA_WORD_1_SRC0_ABS 0x80000000 | |||
#define VIV_ISA_WORD_2 0x00000008 | |||
#define VIV_ISA_WORD_2_SRC0_AMODE__MASK 0x00000007 | |||
#define VIV_ISA_WORD_2_SRC0_AMODE__SHIFT 0 | |||
#define VIV_ISA_WORD_2_SRC0_AMODE(x) (((x) << VIV_ISA_WORD_2_SRC0_AMODE__SHIFT) & VIV_ISA_WORD_2_SRC0_AMODE__MASK) | |||
#define VIV_ISA_WORD_2_SRC0_RGROUP__MASK 0x00000038 | |||
#define VIV_ISA_WORD_2_SRC0_RGROUP__SHIFT 3 | |||
#define VIV_ISA_WORD_2_SRC0_RGROUP(x) (((x) << VIV_ISA_WORD_2_SRC0_RGROUP__SHIFT) & VIV_ISA_WORD_2_SRC0_RGROUP__MASK) | |||
#define VIV_ISA_WORD_2_SRC1_USE 0x00000040 | |||
#define VIV_ISA_WORD_2_SRC1_REG__MASK 0x0000ff80 | |||
#define VIV_ISA_WORD_2_SRC1_REG__SHIFT 7 | |||
#define VIV_ISA_WORD_2_SRC1_REG(x) (((x) << VIV_ISA_WORD_2_SRC1_REG__SHIFT) & VIV_ISA_WORD_2_SRC1_REG__MASK) | |||
#define VIV_ISA_WORD_2_OPCODE_BIT6 0x00010000 | |||
#define VIV_ISA_WORD_2_SRC1_SWIZ__MASK 0x01fe0000 | |||
#define VIV_ISA_WORD_2_SRC1_SWIZ__SHIFT 17 | |||
#define VIV_ISA_WORD_2_SRC1_SWIZ(x) (((x) << VIV_ISA_WORD_2_SRC1_SWIZ__SHIFT) & VIV_ISA_WORD_2_SRC1_SWIZ__MASK) | |||
#define VIV_ISA_WORD_2_SRC1_NEG 0x02000000 | |||
#define VIV_ISA_WORD_2_SRC1_ABS 0x04000000 | |||
#define VIV_ISA_WORD_2_SRC1_AMODE__MASK 0x38000000 | |||
#define VIV_ISA_WORD_2_SRC1_AMODE__SHIFT 27 | |||
#define VIV_ISA_WORD_2_SRC1_AMODE(x) (((x) << VIV_ISA_WORD_2_SRC1_AMODE__SHIFT) & VIV_ISA_WORD_2_SRC1_AMODE__MASK) | |||
#define VIV_ISA_WORD_2_TYPE_BIT01__MASK 0xc0000000 | |||
#define VIV_ISA_WORD_2_TYPE_BIT01__SHIFT 30 | |||
#define VIV_ISA_WORD_2_TYPE_BIT01(x) (((x) << VIV_ISA_WORD_2_TYPE_BIT01__SHIFT) & VIV_ISA_WORD_2_TYPE_BIT01__MASK) | |||
#define VIV_ISA_WORD_3 0x0000000c | |||
#define VIV_ISA_WORD_3_SRC1_RGROUP__MASK 0x00000007 | |||
#define VIV_ISA_WORD_3_SRC1_RGROUP__SHIFT 0 | |||
#define VIV_ISA_WORD_3_SRC1_RGROUP(x) (((x) << VIV_ISA_WORD_3_SRC1_RGROUP__SHIFT) & VIV_ISA_WORD_3_SRC1_RGROUP__MASK) | |||
#define VIV_ISA_WORD_3_SRC2_IMM__MASK 0x003fff80 | |||
#define VIV_ISA_WORD_3_SRC2_IMM__SHIFT 7 | |||
#define VIV_ISA_WORD_3_SRC2_IMM(x) (((x) << VIV_ISA_WORD_3_SRC2_IMM__SHIFT) & VIV_ISA_WORD_3_SRC2_IMM__MASK) | |||
#define VIV_ISA_WORD_3_SRC2_USE 0x00000008 | |||
#define VIV_ISA_WORD_3_SRC2_REG__MASK 0x00001ff0 | |||
#define VIV_ISA_WORD_3_SRC2_REG__SHIFT 4 | |||
#define VIV_ISA_WORD_3_SRC2_REG(x) (((x) << VIV_ISA_WORD_3_SRC2_REG__SHIFT) & VIV_ISA_WORD_3_SRC2_REG__MASK) | |||
#define VIV_ISA_WORD_3_UNK3_13 0x00002000 | |||
#define VIV_ISA_WORD_3_SRC2_SWIZ__MASK 0x003fc000 | |||
#define VIV_ISA_WORD_3_SRC2_SWIZ__SHIFT 14 | |||
#define VIV_ISA_WORD_3_SRC2_SWIZ(x) (((x) << VIV_ISA_WORD_3_SRC2_SWIZ__SHIFT) & VIV_ISA_WORD_3_SRC2_SWIZ__MASK) | |||
#define VIV_ISA_WORD_3_SRC2_NEG 0x00400000 | |||
#define VIV_ISA_WORD_3_SRC2_ABS 0x00800000 | |||
#define VIV_ISA_WORD_3_UNK3_24 0x01000000 | |||
#define VIV_ISA_WORD_3_SRC2_AMODE__MASK 0x0e000000 | |||
#define VIV_ISA_WORD_3_SRC2_AMODE__SHIFT 25 | |||
#define VIV_ISA_WORD_3_SRC2_AMODE(x) (((x) << VIV_ISA_WORD_3_SRC2_AMODE__SHIFT) & VIV_ISA_WORD_3_SRC2_AMODE__MASK) | |||
#define VIV_ISA_WORD_3_SRC2_RGROUP__MASK 0x70000000 | |||
#define VIV_ISA_WORD_3_SRC2_RGROUP__SHIFT 28 | |||
#define VIV_ISA_WORD_3_SRC2_RGROUP(x) (((x) << VIV_ISA_WORD_3_SRC2_RGROUP__SHIFT) & VIV_ISA_WORD_3_SRC2_RGROUP__MASK) | |||
#define VIV_ISA_WORD_3_UNK3_31 0x80000000 | |||
#endif /* ISA_XML */ |
@@ -0,0 +1,397 @@ | |||
#ifndef STATE_XML | |||
#define STATE_XML | |||
/* Autogenerated file, DO NOT EDIT manually! | |||
This file was generated by the rules-ng-ng headergen tool in this git repository: | |||
http://0x04.net/cgit/index.cgi/rules-ng-ng | |||
git clone git://0x04.net/rules-ng-ng | |||
The rules-ng-ng source files this header was generated from are: | |||
- state.xml ( 19792 bytes, from 2016-11-16 18:54:37) | |||
- common.xml ( 23422 bytes, from 2016-11-16 18:54:37) | |||
- state_hi.xml ( 25653 bytes, from 2016-10-02 14:26:13) | |||
- copyright.xml ( 1597 bytes, from 2016-10-02 14:26:13) | |||
- state_2d.xml ( 51552 bytes, from 2016-10-02 14:26:13) | |||
- state_3d.xml ( 57579 bytes, from 2016-11-16 18:54:37) | |||
- state_vg.xml ( 5975 bytes, from 2016-10-02 14:26:13) | |||
Copyright (C) 2012-2016 by the following authors: | |||
- Wladimir J. van der Laan <laanwj@gmail.com> | |||
- Christian Gmeiner <christian.gmeiner@gmail.com> | |||
- Lucas Stach <l.stach@pengutronix.de> | |||
- Russell King <rmk@arm.linux.org.uk> | |||
Permission is hereby granted, free of charge, to any person obtaining a | |||
copy of this software and associated documentation files (the "Software"), | |||
to deal in the Software without restriction, including without limitation | |||
the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
and/or sell copies of the Software, and to permit persons to whom the | |||
Software is furnished to do so, subject to the following conditions: | |||
The above copyright notice and this permission notice (including the | |||
next paragraph) shall be included in all copies or substantial portions | |||
of the Software. | |||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
DEALINGS IN THE SOFTWARE. | |||
*/ | |||
#define VARYING_COMPONENT_USE_UNUSED 0x00000000 | |||
#define VARYING_COMPONENT_USE_USED 0x00000001 | |||
#define VARYING_COMPONENT_USE_POINTCOORD_X 0x00000002 | |||
#define VARYING_COMPONENT_USE_POINTCOORD_Y 0x00000003 | |||
#define FE_VERTEX_STREAM_CONTROL_VERTEX_STRIDE__MASK 0x000000ff | |||
#define FE_VERTEX_STREAM_CONTROL_VERTEX_STRIDE__SHIFT 0 | |||
#define FE_VERTEX_STREAM_CONTROL_VERTEX_STRIDE(x) (((x) << FE_VERTEX_STREAM_CONTROL_VERTEX_STRIDE__SHIFT) & FE_VERTEX_STREAM_CONTROL_VERTEX_STRIDE__MASK) | |||
#define FE_VERTEX_STREAM_CONTROL_VERTEX_DIVISOR__MASK 0x00ff0000 | |||
#define FE_VERTEX_STREAM_CONTROL_VERTEX_DIVISOR__SHIFT 16 | |||
#define FE_VERTEX_STREAM_CONTROL_VERTEX_DIVISOR(x) (((x) << FE_VERTEX_STREAM_CONTROL_VERTEX_DIVISOR__SHIFT) & FE_VERTEX_STREAM_CONTROL_VERTEX_DIVISOR__MASK) | |||
#define VIVS_FE 0x00000000 | |||
#define VIVS_FE_VERTEX_ELEMENT_CONFIG(i0) (0x00000600 + 0x4*(i0)) | |||
#define VIVS_FE_VERTEX_ELEMENT_CONFIG__ESIZE 0x00000004 | |||
#define VIVS_FE_VERTEX_ELEMENT_CONFIG__LEN 0x00000010 | |||
#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE__MASK 0x0000000f | |||
#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE__SHIFT 0 | |||
#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_BYTE 0x00000000 | |||
#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_UNSIGNED_BYTE 0x00000001 | |||
#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_SHORT 0x00000002 | |||
#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_UNSIGNED_SHORT 0x00000003 | |||
#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_INT 0x00000004 | |||
#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_UNSIGNED_INT 0x00000005 | |||
#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_FLOAT 0x00000008 | |||
#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_HALF_FLOAT 0x00000009 | |||
#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_FIXED 0x0000000b | |||
#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_INT_10_10_10_2 0x0000000c | |||
#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_UNSIGNED_INT_10_10_10_2 0x0000000d | |||
#define VIVS_FE_VERTEX_ELEMENT_CONFIG_ENDIAN__MASK 0x00000030 | |||
#define VIVS_FE_VERTEX_ELEMENT_CONFIG_ENDIAN__SHIFT 4 | |||
#define VIVS_FE_VERTEX_ELEMENT_CONFIG_ENDIAN(x) (((x) << VIVS_FE_VERTEX_ELEMENT_CONFIG_ENDIAN__SHIFT) & VIVS_FE_VERTEX_ELEMENT_CONFIG_ENDIAN__MASK) | |||
#define VIVS_FE_VERTEX_ELEMENT_CONFIG_NONCONSECUTIVE 0x00000080 | |||
#define VIVS_FE_VERTEX_ELEMENT_CONFIG_STREAM__MASK 0x00000700 | |||
#define VIVS_FE_VERTEX_ELEMENT_CONFIG_STREAM__SHIFT 8 | |||
#define VIVS_FE_VERTEX_ELEMENT_CONFIG_STREAM(x) (((x) << VIVS_FE_VERTEX_ELEMENT_CONFIG_STREAM__SHIFT) & VIVS_FE_VERTEX_ELEMENT_CONFIG_STREAM__MASK) | |||
#define VIVS_FE_VERTEX_ELEMENT_CONFIG_NUM__MASK 0x00003000 | |||
#define VIVS_FE_VERTEX_ELEMENT_CONFIG_NUM__SHIFT 12 | |||
#define VIVS_FE_VERTEX_ELEMENT_CONFIG_NUM(x) (((x) << VIVS_FE_VERTEX_ELEMENT_CONFIG_NUM__SHIFT) & VIVS_FE_VERTEX_ELEMENT_CONFIG_NUM__MASK) | |||
#define VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE__MASK 0x0000c000 | |||
#define VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE__SHIFT 14 | |||
#define VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE_OFF 0x00000000 | |||
#define VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE_ON 0x00008000 | |||
#define VIVS_FE_VERTEX_ELEMENT_CONFIG_START__MASK 0x00ff0000 | |||
#define VIVS_FE_VERTEX_ELEMENT_CONFIG_START__SHIFT 16 | |||
#define VIVS_FE_VERTEX_ELEMENT_CONFIG_START(x) (((x) << VIVS_FE_VERTEX_ELEMENT_CONFIG_START__SHIFT) & VIVS_FE_VERTEX_ELEMENT_CONFIG_START__MASK) | |||
#define VIVS_FE_VERTEX_ELEMENT_CONFIG_END__MASK 0xff000000 | |||
#define VIVS_FE_VERTEX_ELEMENT_CONFIG_END__SHIFT 24 | |||
#define VIVS_FE_VERTEX_ELEMENT_CONFIG_END(x) (((x) << VIVS_FE_VERTEX_ELEMENT_CONFIG_END__SHIFT) & VIVS_FE_VERTEX_ELEMENT_CONFIG_END__MASK) | |||
#define VIVS_FE_CMD_STREAM_BASE_ADDR 0x00000640 | |||
#define VIVS_FE_INDEX_STREAM_BASE_ADDR 0x00000644 | |||
#define VIVS_FE_INDEX_STREAM_CONTROL 0x00000648 | |||
#define VIVS_FE_INDEX_STREAM_CONTROL_TYPE__MASK 0x00000003 | |||
#define VIVS_FE_INDEX_STREAM_CONTROL_TYPE__SHIFT 0 | |||
#define VIVS_FE_INDEX_STREAM_CONTROL_TYPE_UNSIGNED_CHAR 0x00000000 | |||
#define VIVS_FE_INDEX_STREAM_CONTROL_TYPE_UNSIGNED_SHORT 0x00000001 | |||
#define VIVS_FE_INDEX_STREAM_CONTROL_TYPE_UNSIGNED_INT 0x00000002 | |||
#define VIVS_FE_INDEX_STREAM_CONTROL_PRIMITIVE_RESTART 0x00000100 | |||
#define VIVS_FE_VERTEX_STREAM_BASE_ADDR 0x0000064c | |||
#define VIVS_FE_VERTEX_STREAM_CONTROL 0x00000650 | |||
#define VIVS_FE_COMMAND_ADDRESS 0x00000654 | |||
#define VIVS_FE_COMMAND_CONTROL 0x00000658 | |||
#define VIVS_FE_COMMAND_CONTROL_PREFETCH__MASK 0x0000ffff | |||
#define VIVS_FE_COMMAND_CONTROL_PREFETCH__SHIFT 0 | |||
#define VIVS_FE_COMMAND_CONTROL_PREFETCH(x) (((x) << VIVS_FE_COMMAND_CONTROL_PREFETCH__SHIFT) & VIVS_FE_COMMAND_CONTROL_PREFETCH__MASK) | |||
#define VIVS_FE_COMMAND_CONTROL_ENABLE 0x00010000 | |||
#define VIVS_FE_DMA_STATUS 0x0000065c | |||
#define VIVS_FE_DMA_DEBUG_STATE 0x00000660 | |||
#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE__MASK 0x0000001f | |||
#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE__SHIFT 0 | |||
#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_IDLE 0x00000000 | |||
#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_DEC 0x00000001 | |||
#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_ADR0 0x00000002 | |||
#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_LOAD0 0x00000003 | |||
#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_ADR1 0x00000004 | |||
#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_LOAD1 0x00000005 | |||
#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_3DADR 0x00000006 | |||
#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_3DCMD 0x00000007 | |||
#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_3DCNTL 0x00000008 | |||
#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_3DIDXCNTL 0x00000009 | |||
#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_INITREQDMA 0x0000000a | |||
#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_DRAWIDX 0x0000000b | |||
#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_DRAW 0x0000000c | |||
#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_2DRECT0 0x0000000d | |||
#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_2DRECT1 0x0000000e | |||
#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_2DDATA0 0x0000000f | |||
#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_2DDATA1 0x00000010 | |||
#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_WAITFIFO 0x00000011 | |||
#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_WAIT 0x00000012 | |||
#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_LINK 0x00000013 | |||
#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_END 0x00000014 | |||
#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_STALL 0x00000015 | |||
#define VIVS_FE_DMA_DEBUG_STATE_CMD_DMA_STATE__MASK 0x00000300 | |||
#define VIVS_FE_DMA_DEBUG_STATE_CMD_DMA_STATE__SHIFT 8 | |||
#define VIVS_FE_DMA_DEBUG_STATE_CMD_DMA_STATE_IDLE 0x00000000 | |||
#define VIVS_FE_DMA_DEBUG_STATE_CMD_DMA_STATE_START 0x00000100 | |||
#define VIVS_FE_DMA_DEBUG_STATE_CMD_DMA_STATE_REQ 0x00000200 | |||
#define VIVS_FE_DMA_DEBUG_STATE_CMD_DMA_STATE_END 0x00000300 | |||
#define VIVS_FE_DMA_DEBUG_STATE_CMD_FETCH_STATE__MASK 0x00000c00 | |||
#define VIVS_FE_DMA_DEBUG_STATE_CMD_FETCH_STATE__SHIFT 10 | |||
#define VIVS_FE_DMA_DEBUG_STATE_CMD_FETCH_STATE_IDLE 0x00000000 | |||
#define VIVS_FE_DMA_DEBUG_STATE_CMD_FETCH_STATE_RAMVALID 0x00000400 | |||
#define VIVS_FE_DMA_DEBUG_STATE_CMD_FETCH_STATE_VALID 0x00000800 | |||
#define VIVS_FE_DMA_DEBUG_STATE_REQ_DMA_STATE__MASK 0x00003000 | |||
#define VIVS_FE_DMA_DEBUG_STATE_REQ_DMA_STATE__SHIFT 12 | |||
#define VIVS_FE_DMA_DEBUG_STATE_REQ_DMA_STATE_IDLE 0x00000000 | |||
#define VIVS_FE_DMA_DEBUG_STATE_REQ_DMA_STATE_WAITIDX 0x00001000 | |||
#define VIVS_FE_DMA_DEBUG_STATE_REQ_DMA_STATE_CAL 0x00002000 | |||
#define VIVS_FE_DMA_DEBUG_STATE_CAL_STATE__MASK 0x0000c000 | |||
#define VIVS_FE_DMA_DEBUG_STATE_CAL_STATE__SHIFT 14 | |||
#define VIVS_FE_DMA_DEBUG_STATE_CAL_STATE_IDLE 0x00000000 | |||
#define VIVS_FE_DMA_DEBUG_STATE_CAL_STATE_LDADR 0x00004000 | |||
#define VIVS_FE_DMA_DEBUG_STATE_CAL_STATE_IDXCALC 0x00008000 | |||
#define VIVS_FE_DMA_DEBUG_STATE_VE_REQ_STATE__MASK 0x00030000 | |||
#define VIVS_FE_DMA_DEBUG_STATE_VE_REQ_STATE__SHIFT 16 | |||
#define VIVS_FE_DMA_DEBUG_STATE_VE_REQ_STATE_IDLE 0x00000000 | |||
#define VIVS_FE_DMA_DEBUG_STATE_VE_REQ_STATE_CKCACHE 0x00010000 | |||
#define VIVS_FE_DMA_DEBUG_STATE_VE_REQ_STATE_MISS 0x00020000 | |||
#define VIVS_FE_DMA_ADDRESS 0x00000664 | |||
#define VIVS_FE_DMA_LOW 0x00000668 | |||
#define VIVS_FE_DMA_HIGH 0x0000066c | |||
#define VIVS_FE_AUTO_FLUSH 0x00000670 | |||
#define VIVS_FE_PRIMITIVE_RESTART_INDEX 0x00000674 | |||
#define VIVS_FE_UNK00678 0x00000678 | |||
#define VIVS_FE_UNK0067C 0x0000067c | |||
#define VIVS_FE_VERTEX_STREAMS(i0) (0x00000000 + 0x4*(i0)) | |||
#define VIVS_FE_VERTEX_STREAMS__ESIZE 0x00000004 | |||
#define VIVS_FE_VERTEX_STREAMS__LEN 0x00000008 | |||
#define VIVS_FE_VERTEX_STREAMS_BASE_ADDR(i0) (0x00000680 + 0x4*(i0)) | |||
#define VIVS_FE_VERTEX_STREAMS_CONTROL(i0) (0x000006a0 + 0x4*(i0)) | |||
#define VIVS_FE_UNK00700(i0) (0x00000700 + 0x4*(i0)) | |||
#define VIVS_FE_UNK00700__ESIZE 0x00000004 | |||
#define VIVS_FE_UNK00700__LEN 0x00000010 | |||
#define VIVS_FE_UNK00740(i0) (0x00000740 + 0x4*(i0)) | |||
#define VIVS_FE_UNK00740__ESIZE 0x00000004 | |||
#define VIVS_FE_UNK00740__LEN 0x00000010 | |||
#define VIVS_FE_UNK00780(i0) (0x00000780 + 0x4*(i0)) | |||
#define VIVS_FE_UNK00780__ESIZE 0x00000004 | |||
#define VIVS_FE_UNK00780__LEN 0x00000010 | |||
#define VIVS_GL 0x00000000 | |||
#define VIVS_GL_PIPE_SELECT 0x00003800 | |||
#define VIVS_GL_PIPE_SELECT_PIPE__MASK 0x00000001 | |||
#define VIVS_GL_PIPE_SELECT_PIPE__SHIFT 0 | |||
#define VIVS_GL_PIPE_SELECT_PIPE(x) (((x) << VIVS_GL_PIPE_SELECT_PIPE__SHIFT) & VIVS_GL_PIPE_SELECT_PIPE__MASK) | |||
#define VIVS_GL_EVENT 0x00003804 | |||
#define VIVS_GL_EVENT_EVENT_ID__MASK 0x0000001f | |||
#define VIVS_GL_EVENT_EVENT_ID__SHIFT 0 | |||
#define VIVS_GL_EVENT_EVENT_ID(x) (((x) << VIVS_GL_EVENT_EVENT_ID__SHIFT) & VIVS_GL_EVENT_EVENT_ID__MASK) | |||
#define VIVS_GL_EVENT_FROM_FE 0x00000020 | |||
#define VIVS_GL_EVENT_FROM_PE 0x00000040 | |||
#define VIVS_GL_EVENT_SOURCE__MASK 0x00001f00 | |||
#define VIVS_GL_EVENT_SOURCE__SHIFT 8 | |||
#define VIVS_GL_EVENT_SOURCE(x) (((x) << VIVS_GL_EVENT_SOURCE__SHIFT) & VIVS_GL_EVENT_SOURCE__MASK) | |||
#define VIVS_GL_SEMAPHORE_TOKEN 0x00003808 | |||
#define VIVS_GL_SEMAPHORE_TOKEN_FROM__MASK 0x0000001f | |||
#define VIVS_GL_SEMAPHORE_TOKEN_FROM__SHIFT 0 | |||
#define VIVS_GL_SEMAPHORE_TOKEN_FROM(x) (((x) << VIVS_GL_SEMAPHORE_TOKEN_FROM__SHIFT) & VIVS_GL_SEMAPHORE_TOKEN_FROM__MASK) | |||
#define VIVS_GL_SEMAPHORE_TOKEN_TO__MASK 0x00001f00 | |||
#define VIVS_GL_SEMAPHORE_TOKEN_TO__SHIFT 8 | |||
#define VIVS_GL_SEMAPHORE_TOKEN_TO(x) (((x) << VIVS_GL_SEMAPHORE_TOKEN_TO__SHIFT) & VIVS_GL_SEMAPHORE_TOKEN_TO__MASK) | |||
#define VIVS_GL_FLUSH_CACHE 0x0000380c | |||
#define VIVS_GL_FLUSH_CACHE_DEPTH 0x00000001 | |||
#define VIVS_GL_FLUSH_CACHE_COLOR 0x00000002 | |||
#define VIVS_GL_FLUSH_CACHE_TEXTURE 0x00000004 | |||
#define VIVS_GL_FLUSH_CACHE_PE2D 0x00000008 | |||
#define VIVS_GL_FLUSH_CACHE_TEXTUREVS 0x00000010 | |||
#define VIVS_GL_FLUSH_CACHE_SHADER_L1 0x00000020 | |||
#define VIVS_GL_FLUSH_CACHE_SHADER_L2 0x00000040 | |||
#define VIVS_GL_FLUSH_MMU 0x00003810 | |||
#define VIVS_GL_FLUSH_MMU_FLUSH_FEMMU 0x00000001 | |||
#define VIVS_GL_FLUSH_MMU_FLUSH_UNK1 0x00000002 | |||
#define VIVS_GL_FLUSH_MMU_FLUSH_UNK2 0x00000004 | |||
#define VIVS_GL_FLUSH_MMU_FLUSH_PEMMU 0x00000008 | |||
#define VIVS_GL_FLUSH_MMU_FLUSH_UNK4 0x00000010 | |||
#define VIVS_GL_VERTEX_ELEMENT_CONFIG 0x00003814 | |||
#define VIVS_GL_MULTI_SAMPLE_CONFIG 0x00003818 | |||
#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES__MASK 0x00000003 | |||
#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES__SHIFT 0 | |||
#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_NONE 0x00000000 | |||
#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_2X 0x00000001 | |||
#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_4X 0x00000002 | |||
#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_MASK 0x00000008 | |||
#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_ENABLES__MASK 0x000000f0 | |||
#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_ENABLES__SHIFT 4 | |||
#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_ENABLES(x) (((x) << VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_ENABLES__SHIFT) & VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_ENABLES__MASK) | |||
#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_ENABLES_MASK 0x00000100 | |||
#define VIVS_GL_MULTI_SAMPLE_CONFIG_UNK12__MASK 0x00007000 | |||
#define VIVS_GL_MULTI_SAMPLE_CONFIG_UNK12__SHIFT 12 | |||
#define VIVS_GL_MULTI_SAMPLE_CONFIG_UNK12(x) (((x) << VIVS_GL_MULTI_SAMPLE_CONFIG_UNK12__SHIFT) & VIVS_GL_MULTI_SAMPLE_CONFIG_UNK12__MASK) | |||
#define VIVS_GL_MULTI_SAMPLE_CONFIG_UNK12_MASK 0x00008000 | |||
#define VIVS_GL_MULTI_SAMPLE_CONFIG_UNK16__MASK 0x00030000 | |||
#define VIVS_GL_MULTI_SAMPLE_CONFIG_UNK16__SHIFT 16 | |||
#define VIVS_GL_MULTI_SAMPLE_CONFIG_UNK16(x) (((x) << VIVS_GL_MULTI_SAMPLE_CONFIG_UNK16__SHIFT) & VIVS_GL_MULTI_SAMPLE_CONFIG_UNK16__MASK) | |||
#define VIVS_GL_MULTI_SAMPLE_CONFIG_UNK16_MASK 0x00080000 | |||
#define VIVS_GL_VARYING_TOTAL_COMPONENTS 0x0000381c | |||
#define VIVS_GL_VARYING_TOTAL_COMPONENTS_NUM__MASK 0x000000ff | |||
#define VIVS_GL_VARYING_TOTAL_COMPONENTS_NUM__SHIFT 0 | |||
#define VIVS_GL_VARYING_TOTAL_COMPONENTS_NUM(x) (((x) << VIVS_GL_VARYING_TOTAL_COMPONENTS_NUM__SHIFT) & VIVS_GL_VARYING_TOTAL_COMPONENTS_NUM__MASK) | |||
#define VIVS_GL_VARYING_NUM_COMPONENTS 0x00003820 | |||
#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR0__MASK 0x00000007 | |||
#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR0__SHIFT 0 | |||
#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR0(x) (((x) << VIVS_GL_VARYING_NUM_COMPONENTS_VAR0__SHIFT) & VIVS_GL_VARYING_NUM_COMPONENTS_VAR0__MASK) | |||
#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR1__MASK 0x00000070 | |||
#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR1__SHIFT 4 | |||
#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR1(x) (((x) << VIVS_GL_VARYING_NUM_COMPONENTS_VAR1__SHIFT) & VIVS_GL_VARYING_NUM_COMPONENTS_VAR1__MASK) | |||
#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR2__MASK 0x00000700 | |||
#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR2__SHIFT 8 | |||
#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR2(x) (((x) << VIVS_GL_VARYING_NUM_COMPONENTS_VAR2__SHIFT) & VIVS_GL_VARYING_NUM_COMPONENTS_VAR2__MASK) | |||
#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR3__MASK 0x00007000 | |||
#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR3__SHIFT 12 | |||
#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR3(x) (((x) << VIVS_GL_VARYING_NUM_COMPONENTS_VAR3__SHIFT) & VIVS_GL_VARYING_NUM_COMPONENTS_VAR3__MASK) | |||
#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR4__MASK 0x00070000 | |||
#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR4__SHIFT 16 | |||
#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR4(x) (((x) << VIVS_GL_VARYING_NUM_COMPONENTS_VAR4__SHIFT) & VIVS_GL_VARYING_NUM_COMPONENTS_VAR4__MASK) | |||
#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR5__MASK 0x00700000 | |||
#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR5__SHIFT 20 | |||
#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR5(x) (((x) << VIVS_GL_VARYING_NUM_COMPONENTS_VAR5__SHIFT) & VIVS_GL_VARYING_NUM_COMPONENTS_VAR5__MASK) | |||
#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR6__MASK 0x07000000 | |||
#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR6__SHIFT 24 | |||
#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR6(x) (((x) << VIVS_GL_VARYING_NUM_COMPONENTS_VAR6__SHIFT) & VIVS_GL_VARYING_NUM_COMPONENTS_VAR6__MASK) | |||
#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR7__MASK 0x70000000 | |||
#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR7__SHIFT 28 | |||
#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR7(x) (((x) << VIVS_GL_VARYING_NUM_COMPONENTS_VAR7__SHIFT) & VIVS_GL_VARYING_NUM_COMPONENTS_VAR7__MASK) | |||
#define VIVS_GL_VARYING_COMPONENT_USE(i0) (0x00003828 + 0x4*(i0)) | |||
#define VIVS_GL_VARYING_COMPONENT_USE__ESIZE 0x00000004 | |||
#define VIVS_GL_VARYING_COMPONENT_USE__LEN 0x00000002 | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP0__MASK 0x00000003 | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP0__SHIFT 0 | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP0(x) (((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP0__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP0__MASK) | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP1__MASK 0x0000000c | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP1__SHIFT 2 | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP1(x) (((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP1__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP1__MASK) | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP2__MASK 0x00000030 | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP2__SHIFT 4 | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP2(x) (((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP2__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP2__MASK) | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP3__MASK 0x000000c0 | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP3__SHIFT 6 | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP3(x) (((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP3__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP3__MASK) | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP4__MASK 0x00000300 | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP4__SHIFT 8 | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP4(x) (((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP4__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP4__MASK) | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP5__MASK 0x00000c00 | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP5__SHIFT 10 | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP5(x) (((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP5__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP5__MASK) | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP6__MASK 0x00003000 | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP6__SHIFT 12 | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP6(x) (((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP6__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP6__MASK) | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP7__MASK 0x0000c000 | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP7__SHIFT 14 | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP7(x) (((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP7__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP7__MASK) | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP8__MASK 0x00030000 | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP8__SHIFT 16 | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP8(x) (((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP8__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP8__MASK) | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP9__MASK 0x000c0000 | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP9__SHIFT 18 | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP9(x) (((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP9__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP9__MASK) | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP10__MASK 0x00300000 | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP10__SHIFT 20 | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP10(x) (((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP10__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP10__MASK) | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP11__MASK 0x00c00000 | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP11__SHIFT 22 | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP11(x) (((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP11__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP11__MASK) | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP12__MASK 0x03000000 | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP12__SHIFT 24 | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP12(x) (((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP12__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP12__MASK) | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP13__MASK 0x0c000000 | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP13__SHIFT 26 | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP13(x) (((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP13__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP13__MASK) | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP14__MASK 0x30000000 | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP14__SHIFT 28 | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP14(x) (((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP14__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP14__MASK) | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP15__MASK 0xc0000000 | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP15__SHIFT 30 | |||
#define VIVS_GL_VARYING_COMPONENT_USE_COMP15(x) (((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP15__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP15__MASK) | |||
#define VIVS_GL_UNK03834 0x00003834 | |||
#define VIVS_GL_UNK03838 0x00003838 | |||
#define VIVS_GL_API_MODE 0x0000384c | |||
#define VIVS_GL_API_MODE_OPENGL 0x00000000 | |||
#define VIVS_GL_API_MODE_OPENVG 0x00000001 | |||
#define VIVS_GL_API_MODE_OPENCL 0x00000002 | |||
#define VIVS_GL_CONTEXT_POINTER 0x00003850 | |||
#define VIVS_GL_UNK03854 0x00003854 | |||
#define VIVS_GL_UNK03A00 0x00003a00 | |||
#define VIVS_GL_STALL_TOKEN 0x00003c00 | |||
#define VIVS_GL_STALL_TOKEN_FROM__MASK 0x0000001f | |||
#define VIVS_GL_STALL_TOKEN_FROM__SHIFT 0 | |||
#define VIVS_GL_STALL_TOKEN_FROM(x) (((x) << VIVS_GL_STALL_TOKEN_FROM__SHIFT) & VIVS_GL_STALL_TOKEN_FROM__MASK) | |||
#define VIVS_GL_STALL_TOKEN_TO__MASK 0x00001f00 | |||
#define VIVS_GL_STALL_TOKEN_TO__SHIFT 8 | |||
#define VIVS_GL_STALL_TOKEN_TO(x) (((x) << VIVS_GL_STALL_TOKEN_TO__SHIFT) & VIVS_GL_STALL_TOKEN_TO__MASK) | |||
#define VIVS_GL_STALL_TOKEN_FLIP0 0x40000000 | |||
#define VIVS_GL_STALL_TOKEN_FLIP1 0x80000000 | |||
#define VIVS_NFE 0x00000000 | |||
#define VIVS_NFE_UNK14600(i0) (0x00014600 + 0x4*(i0)) | |||
#define VIVS_NFE_UNK14600__ESIZE 0x00000004 | |||
#define VIVS_NFE_UNK14600__LEN 0x00000010 | |||
#define VIVS_NFE_UNK14640(i0) (0x00014640 + 0x4*(i0)) | |||
#define VIVS_NFE_UNK14640__ESIZE 0x00000004 | |||
#define VIVS_NFE_UNK14640__LEN 0x00000010 | |||
#define VIVS_NFE_UNK14680(i0) (0x00014680 + 0x4*(i0)) | |||
#define VIVS_NFE_UNK14680__ESIZE 0x00000004 | |||
#define VIVS_NFE_UNK14680__LEN 0x00000010 | |||
#define VIVS_DUMMY 0x00000000 | |||
#define VIVS_DUMMY_DUMMY 0x0003fffc | |||
#endif /* STATE_XML */ |
@@ -91,6 +91,8 @@ include $(top_srcdir)/src/gallium/drivers/vc4/Automake.inc | |||
include $(top_srcdir)/src/gallium/drivers/virgl/Automake.inc | |||
include $(top_srcdir)/src/gallium/drivers/etnaviv/Automake.inc | |||
include $(top_srcdir)/src/gallium/drivers/softpipe/Automake.inc | |||
include $(top_srcdir)/src/gallium/drivers/llvmpipe/Automake.inc | |||
include $(top_srcdir)/src/gallium/drivers/swr/Automake.inc |
@@ -162,3 +162,14 @@ PUBLIC const __DRIextension **__driDriverGetExtensions_i965(void) | |||
} | |||
#endif | |||
#endif | |||
#if defined(GALLIUM_ETNAVIV) | |||
const __DRIextension **__driDriverGetExtensions_etnaviv(void); | |||
PUBLIC const __DRIextension **__driDriverGetExtensions_etnaviv(void) | |||
{ | |||
globalDriverAPI = &galliumdrm_driver_api; | |||
return galliumdrm_driver_extensions; | |||
} | |||
#endif |
@@ -0,0 +1,32 @@ | |||
# Copyright © 2012 Intel Corporation | |||
# | |||
# Permission is hereby granted, free of charge, to any person obtaining a | |||
# copy of this software and associated documentation files (the "Software"), | |||
# to deal in the Software without restriction, including without limitation | |||
# the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||
# and/or sell copies of the Software, and to permit persons to whom the | |||
# Software is furnished to do so, subject to the following conditions: | |||
# | |||
# The above copyright notice and this permission notice (including the next | |||
# paragraph) shall be included in all copies or substantial portions of the | |||
# Software. | |||
# | |||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | |||
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |||
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
# DEALINGS IN THE SOFTWARE. | |||
include $(top_srcdir)/src/gallium/Automake.inc | |||
AM_CFLAGS = \ | |||
-I$(top_srcdir)/src/gallium/drivers \ | |||
$(GALLIUM_CFLAGS) \ | |||
$(ETNAVIV_CFLAGS) | |||
noinst_LTLIBRARIES = libetnavivdrm.la | |||
libetnavivdrm_la_SOURCES = etnaviv_drm_winsys.c |
@@ -0,0 +1,39 @@ | |||
/* | |||
* Copyright (c) 2015 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Christian Gmeiner <christian.gmeiner@gmail.com> | |||
*/ | |||
#ifndef __ETNA_DRM_PUBLIC_H__ | |||
#define __ETNA_DRM_PUBLIC_H__ | |||
struct pipe_screen; | |||
struct renderonly; | |||
struct pipe_screen * | |||
etna_drm_screen_create_renderonly(struct renderonly *ro); | |||
struct pipe_screen * | |||
etna_drm_screen_create(int fd); | |||
#endif |
@@ -0,0 +1,162 @@ | |||
/* | |||
* Copyright (c) 2015 Etnaviv Project | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
* to deal in the Software without restriction, including without limitation | |||
* the rights to use, copy, modify, merge, publish, distribute, sub license, | |||
* and/or sell copies of the Software, and to permit persons to whom the | |||
* Software is furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | |||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
* DEALINGS IN THE SOFTWARE. | |||
* | |||
* Authors: | |||
* Christian Gmeiner <christian.gmeiner@gmail.com> | |||
*/ | |||
#include <sys/stat.h> | |||
#include "util/u_hash_table.h" | |||
#include "util/u_memory.h" | |||
#include "etnaviv/etnaviv_screen.h" | |||
#include "etnaviv/hw/common.xml.h" | |||
#include "etnaviv_drm_public.h" | |||
#include <stdio.h> | |||
static struct pipe_screen * | |||
screen_create(struct renderonly *ro) | |||
{ | |||
struct etna_device *dev; | |||
struct etna_gpu *gpu; | |||
uint64_t val; | |||
int i; | |||
dev = etna_device_new_dup(ro->gpu_fd); | |||
if (!dev) { | |||
fprintf(stderr, "Error creating device\n"); | |||
return NULL; | |||
} | |||
for (i = 0;; i++) { | |||
gpu = etna_gpu_new(dev, i); | |||
if (!gpu) { | |||
fprintf(stderr, "Error creating gpu\n"); | |||
return NULL; | |||
} | |||
/* Look for a 3D capable GPU */ | |||
int ret = etna_gpu_get_param(gpu, ETNA_GPU_FEATURES_0, &val); | |||
if (ret == 0 && (val & chipFeatures_PIPE_3D)) | |||
break; | |||
etna_gpu_del(gpu); | |||
} | |||
return etna_screen_create(dev, gpu, ro); | |||
} | |||
static struct util_hash_table *etna_tab = NULL; | |||
pipe_static_mutex(etna_screen_mutex); | |||
static void | |||
etna_drm_screen_destroy(struct pipe_screen *pscreen) | |||
{ | |||
struct etna_screen *screen = etna_screen(pscreen); | |||
boolean destroy; | |||
pipe_mutex_lock(etna_screen_mutex); | |||
destroy = --screen->refcnt == 0; | |||
if (destroy) { | |||
int fd = etna_device_fd(screen->dev); | |||
util_hash_table_remove(etna_tab, intptr_to_pointer(fd)); | |||
} | |||
pipe_mutex_unlock(etna_screen_mutex); | |||
if (destroy) { | |||
pscreen->destroy = screen->winsys_priv; | |||
pscreen->destroy(pscreen); | |||
} | |||
} | |||
static unsigned hash_fd(void *key) | |||
{ | |||
int fd = pointer_to_intptr(key); | |||
struct stat stat; | |||
fstat(fd, &stat); | |||
return stat.st_dev ^ stat.st_ino ^ stat.st_rdev; | |||
} | |||
static int compare_fd(void *key1, void *key2) | |||
{ | |||
int fd1 = pointer_to_intptr(key1); | |||
int fd2 = pointer_to_intptr(key2); | |||
struct stat stat1, stat2; | |||
fstat(fd1, &stat1); | |||
fstat(fd2, &stat2); | |||
return stat1.st_dev != stat2.st_dev || | |||
stat1.st_ino != stat2.st_ino || | |||
stat1.st_rdev != stat2.st_rdev; | |||
} | |||
struct pipe_screen * | |||
etna_drm_screen_create_renderonly(struct renderonly *ro) | |||
{ | |||
struct pipe_screen *pscreen = NULL; | |||
pipe_mutex_lock(etna_screen_mutex); | |||
if (!etna_tab) { | |||
etna_tab = util_hash_table_create(hash_fd, compare_fd); | |||
if (!etna_tab) | |||
goto unlock; | |||
} | |||
pscreen = util_hash_table_get(etna_tab, intptr_to_pointer(ro->gpu_fd)); | |||
if (pscreen) { | |||
etna_screen(pscreen)->refcnt++; | |||
} else { | |||
pscreen = screen_create(ro); | |||
if (pscreen) { | |||
int fd = etna_device_fd(etna_screen(pscreen)->dev); | |||
util_hash_table_set(etna_tab, intptr_to_pointer(fd), pscreen); | |||
/* Bit of a hack, to avoid circular linkage dependency, | |||
* ie. pipe driver having to call in to winsys, we | |||
* override the pipe drivers screen->destroy() */ | |||
etna_screen(pscreen)->winsys_priv = pscreen->destroy; | |||
pscreen->destroy = etna_drm_screen_destroy; | |||
} | |||
} | |||
unlock: | |||
pipe_mutex_unlock(etna_screen_mutex); | |||
return pscreen; | |||
} | |||
struct pipe_screen * | |||
etna_drm_screen_create(int fd) | |||
{ | |||
struct renderonly ro = { | |||
.create_for_resource = renderonly_create_gpu_import_for_resource, | |||
.kms_fd = -1, | |||
.gpu_fd = fd | |||
}; | |||
return etna_drm_screen_create_renderonly(&ro); | |||
} |