etnaviv: gallium driver for Vivante GPUs

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>
This commit is contained in:
The etnaviv authors 2016-12-23 20:58:23 +01:00 committed by Emil Velikov
parent 848b49b288
commit c9e8b49b88
71 changed files with 14962 additions and 1 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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 */

View File

@ -0,0 +1 @@
etnaviv_compiler

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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.

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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, &copy_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, &copy_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;
}

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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_ */

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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_ */

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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_ */

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
}