diff options
author | Jonathan Gray <jsg@cvs.openbsd.org> | 2018-10-23 06:36:00 +0000 |
---|---|---|
committer | Jonathan Gray <jsg@cvs.openbsd.org> | 2018-10-23 06:36:00 +0000 |
commit | b65fcab046d3a1b6b6ac315720df220925c5322e (patch) | |
tree | ff73dcc383ac0799c655ff6194cda9dacb75dde9 /lib/mesa/src/gallium/drivers/etnaviv | |
parent | 18d6381c51e253e4c41c62619f80d9ce745b95c8 (diff) |
Merge Mesa 17.3.9
Mesa 18.x needs an ld with build-id for at least the intel code
Mesa 18.2 assumes linux only memfd syscalls in intel code
Tested by matthieu@, kettenis@ and myself on a variety of hardware and
architectures. ok kettenis@
Diffstat (limited to 'lib/mesa/src/gallium/drivers/etnaviv')
61 files changed, 17696 insertions, 0 deletions
diff --git a/lib/mesa/src/gallium/drivers/etnaviv/Automake.inc b/lib/mesa/src/gallium/drivers/etnaviv/Automake.inc new file mode 100644 index 000000000..f9b39567e --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/Automake.inc @@ -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 diff --git a/lib/mesa/src/gallium/drivers/etnaviv/Makefile.am b/lib/mesa/src/gallium/drivers/etnaviv/Makefile.am new file mode 100644 index 000000000..654671133 --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/Makefile.am @@ -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) diff --git a/lib/mesa/src/gallium/drivers/etnaviv/Makefile.in b/lib/mesa/src/gallium/drivers/etnaviv/Makefile.in new file mode 100644 index 000000000..71921a07b --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/Makefile.in @@ -0,0 +1,961 @@ +# Makefile.in generated by automake 1.12.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# 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. + + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(srcdir)/Makefile.sources $(top_srcdir)/bin/depcomp \ + $(top_srcdir)/src/gallium/Automake.inc +@HAVE_LIBDRM_TRUE@am__append_1 = \ +@HAVE_LIBDRM_TRUE@ $(LIBDRM_LIBS) + +@HAVE_DRISW_TRUE@am__append_2 = \ +@HAVE_DRISW_TRUE@ $(top_builddir)/src/gallium/winsys/sw/dri/libswdri.la + +@HAVE_DRISW_KMS_TRUE@am__append_3 = \ +@HAVE_DRISW_KMS_TRUE@ $(top_builddir)/src/gallium/winsys/sw/kms-dri/libswkmsdri.la \ +@HAVE_DRISW_KMS_TRUE@ $(LIBDRM_LIBS) + +noinst_PROGRAMS = etnaviv_compiler$(EXEEXT) +subdir = src/gallium/drivers/etnaviv +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \ + $(top_srcdir)/m4/ax_check_gnu_make.m4 \ + $(top_srcdir)/m4/ax_check_python_mako_module.m4 \ + $(top_srcdir)/m4/ax_gcc_builtin.m4 \ + $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \ + $(top_srcdir)/m4/ax_prog_bison.m4 \ + $(top_srcdir)/m4/ax_prog_flex.m4 \ + $(top_srcdir)/m4/ax_pthread.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/VERSION $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libetnaviv_la_LIBADD = +am__objects_1 = etnaviv_asm.lo etnaviv_blend.lo etnaviv_clear_blit.lo \ + etnaviv_compiler.lo etnaviv_context.lo etnaviv_disasm.lo \ + etnaviv_emit.lo etnaviv_fence.lo etnaviv_format.lo \ + etnaviv_query.lo etnaviv_query_hw.lo etnaviv_query_sw.lo \ + etnaviv_rasterizer.lo etnaviv_resource.lo etnaviv_rs.lo \ + etnaviv_screen.lo etnaviv_shader.lo etnaviv_state.lo \ + etnaviv_surface.lo etnaviv_texture.lo etnaviv_tiling.lo \ + etnaviv_transfer.lo etnaviv_uniforms.lo etnaviv_zsa.lo +am_libetnaviv_la_OBJECTS = $(am__objects_1) +libetnaviv_la_OBJECTS = $(am_libetnaviv_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +PROGRAMS = $(noinst_PROGRAMS) +am_etnaviv_compiler_OBJECTS = etnaviv_compiler_cmdline.$(OBJEXT) +etnaviv_compiler_OBJECTS = $(am_etnaviv_compiler_OBJECTS) +am__DEPENDENCIES_1 = +@HAVE_LIBDRM_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) +am__DEPENDENCIES_3 = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) +etnaviv_compiler_DEPENDENCIES = libetnaviv.la \ + $(top_builddir)/src/gallium/auxiliary/libgallium.la \ + $(top_builddir)/src/util/libmesautil.la $(am__DEPENDENCIES_3) \ + $(am__DEPENDENCIES_1) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/bin/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libetnaviv_la_SOURCES) $(etnaviv_compiler_SOURCES) +DIST_SOURCES = $(libetnaviv_la_SOURCES) $(etnaviv_compiler_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDGPU_CFLAGS = @AMDGPU_CFLAGS@ +AMDGPU_LIBS = @AMDGPU_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +ANDROID_CFLAGS = @ANDROID_CFLAGS@ +ANDROID_LIBS = @ANDROID_LIBS@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BSYMBOLIC = @BSYMBOLIC@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CLANG_RESOURCE_DIR = @CLANG_RESOURCE_DIR@ +CLOCK_LIB = @CLOCK_LIB@ +CLOVER_STD_OVERRIDE = @CLOVER_STD_OVERRIDE@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +D3D_DRIVER_INSTALL_DIR = @D3D_DRIVER_INSTALL_DIR@ +DEFINES = @DEFINES@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DLOPEN_LIBS = @DLOPEN_LIBS@ +DRI2PROTO_CFLAGS = @DRI2PROTO_CFLAGS@ +DRI2PROTO_LIBS = @DRI2PROTO_LIBS@ +DRIGL_CFLAGS = @DRIGL_CFLAGS@ +DRIGL_LIBS = @DRIGL_LIBS@ +DRI_DRIVER_INSTALL_DIR = @DRI_DRIVER_INSTALL_DIR@ +DRI_DRIVER_SEARCH_DIR = @DRI_DRIVER_SEARCH_DIR@ +DRI_LIB_DEPS = @DRI_LIB_DEPS@ +DRI_PC_REQ_PRIV = @DRI_PC_REQ_PRIV@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGL_CFLAGS = @EGL_CFLAGS@ +EGL_LIB_DEPS = @EGL_LIB_DEPS@ +EGL_NATIVE_PLATFORM = @EGL_NATIVE_PLATFORM@ +EGREP = @EGREP@ +ETNAVIV_CFLAGS = @ETNAVIV_CFLAGS@ +ETNAVIV_LIBS = @ETNAVIV_LIBS@ +EXEEXT = @EXEEXT@ +EXPAT_CFLAGS = @EXPAT_CFLAGS@ +EXPAT_LIBS = @EXPAT_LIBS@ +FGREP = @FGREP@ +FREEDRENO_CFLAGS = @FREEDRENO_CFLAGS@ +FREEDRENO_LIBS = @FREEDRENO_LIBS@ +GALLIUM_PIPE_LOADER_DEFINES = @GALLIUM_PIPE_LOADER_DEFINES@ +GBM_PC_LIB_PRIV = @GBM_PC_LIB_PRIV@ +GBM_PC_REQ_PRIV = @GBM_PC_REQ_PRIV@ +GC_SECTIONS = @GC_SECTIONS@ +GLESv1_CM_LIB_DEPS = @GLESv1_CM_LIB_DEPS@ +GLESv1_CM_PC_LIB_PRIV = @GLESv1_CM_PC_LIB_PRIV@ +GLESv2_LIB_DEPS = @GLESv2_LIB_DEPS@ +GLESv2_PC_LIB_PRIV = @GLESv2_PC_LIB_PRIV@ +GLPROTO_CFLAGS = @GLPROTO_CFLAGS@ +GLPROTO_LIBS = @GLPROTO_LIBS@ +GLVND_CFLAGS = @GLVND_CFLAGS@ +GLVND_LIBS = @GLVND_LIBS@ +GLX_TLS = @GLX_TLS@ +GL_LIB = @GL_LIB@ +GL_LIB_DEPS = @GL_LIB_DEPS@ +GL_PC_CFLAGS = @GL_PC_CFLAGS@ +GL_PC_LIB_PRIV = @GL_PC_LIB_PRIV@ +GL_PC_REQ_PRIV = @GL_PC_REQ_PRIV@ +GREP = @GREP@ +HAVE_XF86VIDMODE = @HAVE_XF86VIDMODE@ +I915_CFLAGS = @I915_CFLAGS@ +I915_LIBS = @I915_LIBS@ +INDENT = @INDENT@ +INDENT_FLAGS = @INDENT_FLAGS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LD_NO_UNDEFINED = @LD_NO_UNDEFINED@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBATOMIC_LIBS = @LIBATOMIC_LIBS@ +LIBCLC_INCLUDEDIR = @LIBCLC_INCLUDEDIR@ +LIBCLC_LIBEXECDIR = @LIBCLC_LIBEXECDIR@ +LIBDRM_CFLAGS = @LIBDRM_CFLAGS@ +LIBDRM_LIBS = @LIBDRM_LIBS@ +LIBELF_CFLAGS = @LIBELF_CFLAGS@ +LIBELF_LIBS = @LIBELF_LIBS@ +LIBGLVND_DATADIR = @LIBGLVND_DATADIR@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSENSORS_LIBS = @LIBSENSORS_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUNWIND_CFLAGS = @LIBUNWIND_CFLAGS@ +LIBUNWIND_LIBS = @LIBUNWIND_LIBS@ +LIB_DIR = @LIB_DIR@ +LIB_EXT = @LIB_EXT@ +LIPO = @LIPO@ +LLVM_CFLAGS = @LLVM_CFLAGS@ +LLVM_CONFIG = @LLVM_CONFIG@ +LLVM_CXXFLAGS = @LLVM_CXXFLAGS@ +LLVM_INCLUDEDIR = @LLVM_INCLUDEDIR@ +LLVM_LDFLAGS = @LLVM_LDFLAGS@ +LLVM_LIBS = @LLVM_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSVC2013_COMPAT_CFLAGS = @MSVC2013_COMPAT_CFLAGS@ +MSVC2013_COMPAT_CXXFLAGS = @MSVC2013_COMPAT_CXXFLAGS@ +NINE_MAJOR = @NINE_MAJOR@ +NINE_MINOR = @NINE_MINOR@ +NINE_TINY = @NINE_TINY@ +NINE_VERSION = @NINE_VERSION@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NOUVEAU_CFLAGS = @NOUVEAU_CFLAGS@ +NOUVEAU_LIBS = @NOUVEAU_LIBS@ +NVVIEUX_CFLAGS = @NVVIEUX_CFLAGS@ +NVVIEUX_LIBS = @NVVIEUX_LIBS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OMX_BELLAGIO_CFLAGS = @OMX_BELLAGIO_CFLAGS@ +OMX_BELLAGIO_LIBS = @OMX_BELLAGIO_LIBS@ +OMX_BELLAGIO_LIB_INSTALL_DIR = @OMX_BELLAGIO_LIB_INSTALL_DIR@ +OPENCL_LIBNAME = @OPENCL_LIBNAME@ +OPENCL_VERSION = @OPENCL_VERSION@ +OSMESA_LIB = @OSMESA_LIB@ +OSMESA_LIB_DEPS = @OSMESA_LIB_DEPS@ +OSMESA_PC_LIB_PRIV = @OSMESA_PC_LIB_PRIV@ +OSMESA_PC_REQ = @OSMESA_PC_REQ@ +OSMESA_VERSION = @OSMESA_VERSION@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POSIX_SHELL = @POSIX_SHELL@ +PTHREADSTUBS_CFLAGS = @PTHREADSTUBS_CFLAGS@ +PTHREADSTUBS_LIBS = @PTHREADSTUBS_LIBS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PWR8_CFLAGS = @PWR8_CFLAGS@ +PYTHON2 = @PYTHON2@ +RADEON_CFLAGS = @RADEON_CFLAGS@ +RADEON_LIBS = @RADEON_LIBS@ +RANLIB = @RANLIB@ +RM = @RM@ +SED = @SED@ +SELINUX_CFLAGS = @SELINUX_CFLAGS@ +SELINUX_LIBS = @SELINUX_LIBS@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SIMPENROSE_CFLAGS = @SIMPENROSE_CFLAGS@ +SIMPENROSE_LIBS = @SIMPENROSE_LIBS@ +SSE41_CFLAGS = @SSE41_CFLAGS@ +STRIP = @STRIP@ +SWR_AVX2_CXXFLAGS = @SWR_AVX2_CXXFLAGS@ +SWR_AVX_CXXFLAGS = @SWR_AVX_CXXFLAGS@ +SWR_CXX11_CXXFLAGS = @SWR_CXX11_CXXFLAGS@ +SWR_KNL_CXXFLAGS = @SWR_KNL_CXXFLAGS@ +SWR_SKX_CXXFLAGS = @SWR_SKX_CXXFLAGS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VA_CFLAGS = @VA_CFLAGS@ +VA_LIBS = @VA_LIBS@ +VA_LIB_INSTALL_DIR = @VA_LIB_INSTALL_DIR@ +VA_MAJOR = @VA_MAJOR@ +VA_MINOR = @VA_MINOR@ +VC5_SIMULATOR_CFLAGS = @VC5_SIMULATOR_CFLAGS@ +VC5_SIMULATOR_LIBS = @VC5_SIMULATOR_LIBS@ +VDPAU_CFLAGS = @VDPAU_CFLAGS@ +VDPAU_LIBS = @VDPAU_LIBS@ +VDPAU_LIB_INSTALL_DIR = @VDPAU_LIB_INSTALL_DIR@ +VDPAU_MAJOR = @VDPAU_MAJOR@ +VDPAU_MINOR = @VDPAU_MINOR@ +VERSION = @VERSION@ +VISIBILITY_CFLAGS = @VISIBILITY_CFLAGS@ +VISIBILITY_CXXFLAGS = @VISIBILITY_CXXFLAGS@ +VL_CFLAGS = @VL_CFLAGS@ +VL_LIBS = @VL_LIBS@ +VULKAN_ICD_INSTALL_DIR = @VULKAN_ICD_INSTALL_DIR@ +WAYLAND_CLIENT_CFLAGS = @WAYLAND_CLIENT_CFLAGS@ +WAYLAND_CLIENT_LIBS = @WAYLAND_CLIENT_LIBS@ +WAYLAND_PROTOCOLS_DATADIR = @WAYLAND_PROTOCOLS_DATADIR@ +WAYLAND_SCANNER = @WAYLAND_SCANNER@ +WAYLAND_SCANNER_CFLAGS = @WAYLAND_SCANNER_CFLAGS@ +WAYLAND_SCANNER_LIBS = @WAYLAND_SCANNER_LIBS@ +WAYLAND_SERVER_CFLAGS = @WAYLAND_SERVER_CFLAGS@ +WAYLAND_SERVER_LIBS = @WAYLAND_SERVER_LIBS@ +WNO_OVERRIDE_INIT = @WNO_OVERRIDE_INIT@ +X11_INCLUDES = @X11_INCLUDES@ +XA_MAJOR = @XA_MAJOR@ +XA_MINOR = @XA_MINOR@ +XA_TINY = @XA_TINY@ +XA_VERSION = @XA_VERSION@ +XCB_DRI2_CFLAGS = @XCB_DRI2_CFLAGS@ +XCB_DRI2_LIBS = @XCB_DRI2_LIBS@ +XCB_DRI3_CFLAGS = @XCB_DRI3_CFLAGS@ +XCB_DRI3_LIBS = @XCB_DRI3_LIBS@ +XF86VIDMODE_CFLAGS = @XF86VIDMODE_CFLAGS@ +XF86VIDMODE_LIBS = @XF86VIDMODE_LIBS@ +XLIBGL_CFLAGS = @XLIBGL_CFLAGS@ +XLIBGL_LIBS = @XLIBGL_LIBS@ +XVMC_CFLAGS = @XVMC_CFLAGS@ +XVMC_LIBS = @XVMC_LIBS@ +XVMC_LIB_INSTALL_DIR = @XVMC_LIB_INSTALL_DIR@ +XVMC_MAJOR = @XVMC_MAJOR@ +XVMC_MINOR = @XVMC_MINOR@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +acv_mako_found = @acv_mako_found@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +ifGNUmake = @ifGNUmake@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +C_SOURCES := \ + hw/cmdstream.xml.h \ + hw/common.xml.h \ + hw/isa.xml.h \ + hw/state_3d.xml.h \ + hw/state.xml.h \ + \ + 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_internal.h \ + etnaviv_query.c \ + etnaviv_query.h \ + etnaviv_query_hw.c \ + etnaviv_query_hw.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_translate.h \ + etnaviv_uniforms.c \ + etnaviv_uniforms.h \ + etnaviv_util.h \ + etnaviv_zsa.c \ + etnaviv_zsa.h + +GALLIUM_CFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/gallium/include \ + -I$(top_srcdir)/src/gallium/auxiliary \ + $(DEFINES) + + +# src/gallium/auxiliary must appear before src/gallium/drivers +# because there are stupidly two rbug_context.h files in +# different directories, and which one is included by the +# preprocessor is determined by the ordering of the -I flags. +GALLIUM_DRIVER_CFLAGS = \ + -I$(srcdir)/include \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/src/gallium/include \ + -I$(top_srcdir)/src/gallium/auxiliary \ + -I$(top_srcdir)/src/gallium/drivers \ + -I$(top_srcdir)/src/gallium/winsys \ + $(DEFINES) \ + $(VISIBILITY_CFLAGS) + +GALLIUM_DRIVER_CXXFLAGS = \ + -I$(srcdir)/include \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/src/gallium/include \ + -I$(top_srcdir)/src/gallium/auxiliary \ + -I$(top_srcdir)/src/gallium/drivers \ + -I$(top_srcdir)/src/gallium/winsys \ + $(DEFINES) \ + $(VISIBILITY_CXXFLAGS) + +GALLIUM_TARGET_CFLAGS = \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/src/loader \ + -I$(top_srcdir)/src/gallium/include \ + -I$(top_srcdir)/src/gallium/auxiliary \ + -I$(top_srcdir)/src/gallium/drivers \ + -I$(top_srcdir)/src/gallium/winsys \ + -I$(top_builddir)/src/util/ \ + -I$(top_builddir)/src/gallium/drivers/ \ + $(DEFINES) \ + $(PTHREAD_CFLAGS) \ + $(LIBDRM_CFLAGS) \ + $(VISIBILITY_CFLAGS) + +GALLIUM_COMMON_LIB_DEPS = -lm $(LIBUNWIND_LIBS) $(LIBSENSORS_LIBS) \ + $(CLOCK_LIB) $(PTHREAD_LIBS) $(DLOPEN_LIBS) $(am__append_1) +GALLIUM_WINSYS_CFLAGS = \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/src/gallium/include \ + -I$(top_srcdir)/src/gallium/auxiliary \ + $(DEFINES) \ + $(VISIBILITY_CFLAGS) + +GALLIUM_PIPE_LOADER_WINSYS_LIBS = \ + $(top_builddir)/src/gallium/winsys/sw/null/libws_null.la \ + $(top_builddir)/src/gallium/winsys/sw/wrapper/libwsw.la \ + $(am__append_2) $(am__append_3) +noinst_LTLIBRARIES = libetnaviv.la +AM_CPPFLAGS = \ + $(GALLIUM_DRIVER_CFLAGS) \ + $(ETNAVIV_CFLAGS) + +libetnaviv_la_SOURCES = $(C_SOURCES) +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) + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/Makefile.sources $(top_srcdir)/src/gallium/Automake.inc $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/gallium/drivers/etnaviv/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/gallium/drivers/etnaviv/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; +$(srcdir)/Makefile.sources $(top_srcdir)/src/gallium/Automake.inc: + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +libetnaviv.la: $(libetnaviv_la_OBJECTS) $(libetnaviv_la_DEPENDENCIES) $(EXTRA_libetnaviv_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libetnaviv_la_OBJECTS) $(libetnaviv_la_LIBADD) $(LIBS) + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +etnaviv_compiler$(EXEEXT): $(etnaviv_compiler_OBJECTS) $(etnaviv_compiler_DEPENDENCIES) $(EXTRA_etnaviv_compiler_DEPENDENCIES) + @rm -f etnaviv_compiler$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(etnaviv_compiler_OBJECTS) $(etnaviv_compiler_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etnaviv_asm.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etnaviv_blend.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etnaviv_clear_blit.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etnaviv_compiler.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etnaviv_compiler_cmdline.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etnaviv_context.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etnaviv_disasm.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etnaviv_emit.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etnaviv_fence.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etnaviv_format.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etnaviv_query.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etnaviv_query_hw.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etnaviv_query_sw.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etnaviv_rasterizer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etnaviv_resource.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etnaviv_rs.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etnaviv_screen.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etnaviv_shader.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etnaviv_state.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etnaviv_surface.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etnaviv_texture.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etnaviv_tiling.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etnaviv_transfer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etnaviv_uniforms.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etnaviv_zsa.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + clean-noinstPROGRAMS mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES clean-noinstPROGRAMS \ + cscopelist ctags distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/lib/mesa/src/gallium/drivers/etnaviv/Makefile.sources b/lib/mesa/src/gallium/drivers/etnaviv/Makefile.sources new file mode 100644 index 000000000..ea8df807f --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/Makefile.sources @@ -0,0 +1,59 @@ +C_SOURCES := \ + hw/cmdstream.xml.h \ + hw/common.xml.h \ + hw/isa.xml.h \ + hw/state_3d.xml.h \ + hw/state.xml.h \ + \ + 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_internal.h \ + etnaviv_query.c \ + etnaviv_query.h \ + etnaviv_query_hw.c \ + etnaviv_query_hw.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_translate.h \ + etnaviv_uniforms.c \ + etnaviv_uniforms.h \ + etnaviv_util.h \ + etnaviv_zsa.c \ + etnaviv_zsa.h diff --git a/lib/mesa/src/gallium/drivers/etnaviv/README b/lib/mesa/src/gallium/drivers/etnaviv/README new file mode 100644 index 000000000..58034b56e --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/README @@ -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. diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_asm.c b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_asm.c new file mode 100644 index 000000000..8ef4dc9f7 --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_asm.c @@ -0,0 +1,110 @@ +/* + * 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"); + + assert(!(inst->opcode&~0x7f)); + + out[0] = VIV_ISA_WORD_0_OPCODE(inst->opcode & 0x3f) | + 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) | + COND(inst->opcode & 0x40, VIV_ISA_WORD_2_OPCODE_BIT6) | + 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; +} diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_asm.h b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_asm.h new file mode 100644 index 000000000..2fe23df8d --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_asm.h @@ -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 diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_blend.c b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_blend.c new file mode 100644 index 000000000..1b432bd68 --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_blend.c @@ -0,0 +1,176 @@ +/* + * 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_screen.h" +#include "etnaviv_translate.h" +#include "hw/common.xml.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) +{ + struct etna_context *ctx = etna_context(pctx); + const struct pipe_rt_blend_state *rt0 = &so->rt[0]; + struct etna_blend_state *co = CALLOC_STRUCT(etna_blend_state); + bool alpha_enable, logicop_enable; + + 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) + */ + alpha_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 = alpha_enable && + !(rt0->rgb_src_factor == rt0->alpha_src_factor && + rt0->rgb_dst_factor == rt0->alpha_dst_factor); + + if (alpha_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; + } + + logicop_enable = so->logicop_enable && + VIV_FEATURE(ctx->screen, chipMinorFeatures2, LOGIC_OP); + + co->PE_LOGIC_OP = + VIVS_PE_LOGIC_OP_OP(logicop_enable ? so->logicop_func : LOGIC_OP_COPY) | + 0x000E4000 /* ??? */; + + co->fo_allowed = !alpha_enable && !logicop_enable; + + /* 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; +} + +bool +etna_update_blend(struct etna_context *ctx) +{ + struct pipe_framebuffer_state *pfb = &ctx->framebuffer_s; + struct pipe_blend_state *pblend = ctx->blend; + struct etna_blend_state *blend = etna_blend_state(pblend); + const struct pipe_rt_blend_state *rt0 = &pblend->rt[0]; + uint32_t colormask; + + if (pfb->cbufs[0] && + translate_rs_format_rb_swap(pfb->cbufs[0]->texture->format)) { + colormask = rt0->colormask & (PIPE_MASK_A | PIPE_MASK_G); + if (rt0->colormask & PIPE_MASK_R) + colormask |= PIPE_MASK_B; + if (rt0->colormask & PIPE_MASK_B) + colormask |= PIPE_MASK_R; + } else { + colormask = rt0->colormask; + } + + /* If the complete render target is written, set full_overwrite: + * - The color mask is 1111 + * - No blending is used + */ + bool full_overwrite = (rt0->colormask == 0xf) && + blend->fo_allowed; + blend->PE_COLOR_FORMAT = + VIVS_PE_COLOR_FORMAT_COMPONENTS(colormask) | + COND(full_overwrite, VIVS_PE_COLOR_FORMAT_OVERWRITE); + + return true; +} + +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; + + memcpy(cs->color, bc->color, sizeof(float) * 4); + + ctx->dirty |= ETNA_DIRTY_BLEND_COLOR; +} + +bool +etna_update_blend_color(struct etna_context *ctx) +{ + struct pipe_framebuffer_state *pfb = &ctx->framebuffer_s; + struct compiled_blend_color *cs = &ctx->blend_color; + + if (pfb->cbufs[0] && + translate_rs_format_rb_swap(pfb->cbufs[0]->texture->format)) { + cs->PE_ALPHA_BLEND_COLOR = + VIVS_PE_ALPHA_BLEND_COLOR_R(etna_cfloat_to_uint8(cs->color[2])) | + VIVS_PE_ALPHA_BLEND_COLOR_G(etna_cfloat_to_uint8(cs->color[1])) | + VIVS_PE_ALPHA_BLEND_COLOR_B(etna_cfloat_to_uint8(cs->color[0])) | + VIVS_PE_ALPHA_BLEND_COLOR_A(etna_cfloat_to_uint8(cs->color[3])); + } else { + cs->PE_ALPHA_BLEND_COLOR = + VIVS_PE_ALPHA_BLEND_COLOR_R(etna_cfloat_to_uint8(cs->color[0])) | + VIVS_PE_ALPHA_BLEND_COLOR_G(etna_cfloat_to_uint8(cs->color[1])) | + VIVS_PE_ALPHA_BLEND_COLOR_B(etna_cfloat_to_uint8(cs->color[2])) | + VIVS_PE_ALPHA_BLEND_COLOR_A(etna_cfloat_to_uint8(cs->color[3])); + } + + return true; +} diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_blend.h b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_blend.h new file mode 100644 index 000000000..de04a9d5e --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_blend.h @@ -0,0 +1,65 @@ +/* + * 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_context; + +struct etna_blend_state { + struct pipe_blend_state base; + + bool fo_allowed; + + 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); + +bool +etna_update_blend(struct etna_context *ctx); + +void +etna_set_blend_color(struct pipe_context *pctx, const struct pipe_blend_color *bc); + +bool +etna_update_blend_color(struct etna_context *ctx); + +#endif diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c new file mode 100644 index 000000000..21f50b7c2 --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c @@ -0,0 +1,771 @@ +/* + * 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->shader.bind_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->shader.bind_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 inline uint32_t +pack_rgba(enum pipe_format format, const float *rgba) +{ + union util_color uc; + util_pack_color(rgba, format, &uc); + if (util_format_get_blocksize(format) == 2) + return uc.ui[0] << 16 | (uc.ui[0] & 0xffff); + else + return uc.ui[0]; +} + +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 = pack_rgba(surf->base.format, color->f); + + if (surf->surf.ts_size) { /* TS: use precompiled clear command */ + ctx->framebuffer.TS_COLOR_CLEAR_VALUE = new_clear_value; + + if (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; + } + + surf->level->ts_valid = true; + ctx->dirty |= ETNA_DIRTY_TS | ETNA_DIRTY_DERIVE_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 (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; + } + + surf->level->ts_valid = true; + ctx->dirty |= ETNA_DIRTY_TS | ETNA_DIRTY_DERIVE_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); + + /* 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 inline size_t +etna_compute_tileoffset(const struct pipe_box *box, enum pipe_format format, + size_t stride, enum etna_surface_layout layout) +{ + size_t offset; + unsigned int x = box->x, y = box->y; + unsigned int blocksize = util_format_get_blocksize(format); + + switch (layout) { + case ETNA_LAYOUT_LINEAR: + offset = y * stride + x * blocksize; + break; + case ETNA_LAYOUT_MULTI_TILED: + y >>= 1; + /* fall-through */ + case ETNA_LAYOUT_TILED: + assert(!(x & 0x03) && !(y & 0x03)); + offset = (y & ~0x03) * stride + blocksize * ((x & ~0x03) << 2); + break; + case ETNA_LAYOUT_MULTI_SUPERTILED: + y >>= 1; + /* fall-through */ + case ETNA_LAYOUT_SUPER_TILED: + assert(!(x & 0x3f) && !(y & 0x3f)); + offset = (y & ~0x3f) * stride + blocksize * ((x & ~0x3f) << 6); + break; + default: + unreachable("invalid resource layout"); + } + + return offset; +} + +static inline void +etna_get_rs_alignment_mask(const struct etna_context *ctx, + const enum etna_surface_layout layout, + unsigned int *width_mask, unsigned int *height_mask) +{ + unsigned int h_align, w_align; + + if (layout & ETNA_LAYOUT_BIT_SUPER) { + w_align = h_align = 64; + } else { + w_align = ETNA_RS_WIDTH_MASK + 1; + h_align = ETNA_RS_HEIGHT_MASK + 1; + } + + h_align *= ctx->screen->specs.pixel_pipes; + + *width_mask = w_align - 1; + *height_mask = h_align -1; +} + +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->dst.format); + if (translate_rs_format(src_format) == ETNA_NO_MATCH || + translate_rs_format(dst_format) == ETNA_NO_MATCH || + blit_info->scissor_enable || + blit_info->dst.box.depth != blit_info->src.box.depth || + blit_info->dst.box.depth != 1) { + return FALSE; + } + + unsigned w_mask, h_mask; + + etna_get_rs_alignment_mask(ctx, src->layout, &w_mask, &h_mask); + if ((blit_info->src.box.x & w_mask) || (blit_info->src.box.y & h_mask)) + return FALSE; + + etna_get_rs_alignment_mask(ctx, dst->layout, &w_mask, &h_mask); + if ((blit_info->dst.box.x & w_mask) || (blit_info->dst.box.y & h_mask)) + 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 + + etna_compute_tileoffset(&blit_info->src.box, + blit_info->src.format, + src_lev->stride, + src->layout); + unsigned dst_offset = dst_lev->offset + + blit_info->dst.box.z * dst_lev->layer_stride + + etna_compute_tileoffset(&blit_info->dst.box, + blit_info->dst.format, + dst_lev->stride, + dst->layout); + + 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 || + width & (w_align - 1) || height & (h_align - 1)) + 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; + } + + /* Always flush color and depth cache together before resolving. This works + * around artifacts that appear in some cases when scanning out a texture + * directly after it has been rendered to, such as rendering an animated web + * page in a QtWebEngine based WebView on GC2000. The artifacts look like + * the texture sampler samples zeroes instead of texture data in a small, + * irregular triangle in the lower right of each browser tile quad. Other + * attempts to avoid these artifacts, including a pipeline stall before the + * color flush or a TS cache flush afterwards, or flushing multiple times, + * with stalls before and after each flush, have shown no effect. */ + if (src->base.bind & PIPE_BIND_RENDER_TARGET || + src->base.bind & PIPE_BIND_DEPTH_STENCIL) { + 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); + + if (src->levels[blit_info->src.level].ts_size && + src->levels[blit_info->src.level].ts_valid) + etna_set_state(ctx->stream, VIVS_TS_FLUSH_CACHE, VIVS_TS_FLUSH_CACHE_FLUSH); + } + + /* Set up color TS to source surface before blit, if needed */ + bool source_ts_valid = false; + if (src->levels[blit_info->src.level].ts_size && + src->levels[blit_info->src.level].ts_valid) { + 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_lev->offset + + blit_info->src.box.z * src_lev->layer_stride; + 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); + + source_ts_valid = true; + } else { + etna_set_state(ctx->stream, VIVS_TS_MEM_CONFIG, ts_mem_config); + } + ctx->dirty |= ETNA_DIRTY_TS; + + /* Kick off RS here */ + etna_compile_rs_state(ctx, ©_to_screen, &(struct rs_state) { + .source_format = translate_rs_format(src_format), + .source_tiling = src->layout, + .source = src->bo, + .source_offset = src_offset, + .source_stride = src_lev->stride, + .source_padded_width = src_lev->padded_width, + .source_padded_height = src_lev->padded_height, + .source_ts_valid = source_ts_valid, + .dest_format = translate_rs_format(dst_format), + .dest_tiling = dst->layout, + .dest = dst->bo, + .dest_offset = dst_offset, + .dest_stride = dst_lev->stride, + .dest_padded_height = dst_lev->padded_height, + .downsample_x = msaa_xscale > 1, + .downsample_y = msaa_yscale > 1, + .swap_rb = translate_rb_src_dst_swap(src->base.format, dst->base.format), + .dither = {0xffffffff, 0xffffffff}, // XXX dither when going from 24 to 16 bit? + .clear_mode = VIVS_RS_CLEAR_CONTROL_MODE_DISABLED, + .width = width, + .height = height + }); + + etna_submit_rs_state(ctx, ©_to_screen); + resource_written(ctx, &dst->base); + dst->seqno++; + dst->levels[blit_info->dst.level].ts_valid = false; + ctx->dirty |= ETNA_DIRTY_DERIVE_TS; + + return TRUE; + +manual: + if (src->layout == ETNA_LAYOUT_TILED && dst->layout == ETNA_LAYOUT_TILED) { + if ((src->status & ETNA_PENDING_WRITE) || + (dst->status & ETNA_PENDING_WRITE)) + pctx->flush(pctx, NULL, 0); + 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->external) { + if (etna_resource_older(etna_resource(rsc->external), rsc)) { + etna_copy_resource(pctx, rsc->external, prsc, 0, 0); + etna_resource(rsc->external)->seqno = rsc->seqno; + } + } else if (etna_resource_needs_flush(rsc)) { + etna_copy_resource(pctx, prsc, prsc, 0, 0); + rsc->flush_seqno = rsc->seqno; + } +} + +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].padded_width, dst_priv->levels[level].padded_width); + blit.src.box.height = blit.dst.box.height = + MIN2(src_priv->levels[level].padded_height, dst_priv->levels[level].padded_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_copy_resource_box(struct pipe_context *pctx, struct pipe_resource *dst, + struct pipe_resource *src, int level, + struct pipe_box *box) +{ + assert(src->format == dst->format); + assert(src->array_size == dst->array_size); + + 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.src.box = *box; + blit.dst.resource = dst; + blit.dst.format = dst->format; + blit.dst.box = *box; + + blit.dst.box.depth = blit.src.box.depth = 1; + blit.src.level = blit.dst.level = level; + + 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; +} diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_clear_blit.h b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_clear_blit.h new file mode 100644 index 000000000..9bba6236b --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_clear_blit.h @@ -0,0 +1,53 @@ +/* + * 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_copy_resource_box(struct pipe_context *pctx, struct pipe_resource *dst, + struct pipe_resource *src, int level, + struct pipe_box *box); + +void +etna_clear_blit_init(struct pipe_context *pctx); + +#endif diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_compiler.c b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_compiler.c new file mode 100644 index 000000000..41ab4031f --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_compiler.c @@ -0,0 +1,2598 @@ +/* + * 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> + */ + +/* TGSI->Vivante shader ISA conversion */ + +/* What does the compiler return (see etna_shader_object)? + * 1) instruction data + * 2) input-to-temporary mapping (fixed for ps) + * *) in case of ps, semantic -> varying id mapping + * *) for each varying: number of components used (r, rg, rgb, rgba) + * 3) temporary-to-output mapping (in case of vs, fixed for ps) + * 4) for each input/output: possible semantic (position, color, glpointcoord, ...) + * 5) immediates base offset, immediates data + * 6) used texture units (and possibly the TGSI_TEXTURE_* type); not needed to + * configure the hw, but useful for error checking + * 7) enough information to add the z=(z+w)/2.0 necessary for older chips + * (output reg id is enough) + * + * Empty shaders are not allowed, should always at least generate a NOP. Also + * if there is a label at the end of the shader, an extra NOP should be + * generated as jump target. + * + * TODO + * * Use an instruction scheduler + * * Indirect access to uniforms / temporaries using amode + */ + +#include "etnaviv_compiler.h" + +#include "etnaviv_asm.h" +#include "etnaviv_context.h" +#include "etnaviv_debug.h" +#include "etnaviv_disasm.h" +#include "etnaviv_uniforms.h" +#include "etnaviv_util.h" + +#include "pipe/p_shader_tokens.h" +#include "tgsi/tgsi_info.h" +#include "tgsi/tgsi_iterate.h" +#include "tgsi/tgsi_lowering.h" +#include "tgsi/tgsi_strings.h" +#include "tgsi/tgsi_util.h" +#include "util/u_math.h" +#include "util/u_memory.h" + +#include <fcntl.h> +#include <stdio.h> +#include <sys/stat.h> +#include <sys/types.h> + +#define ETNA_MAX_INNER_TEMPS 2 + +static const float sincos_const[2][4] = { + { + 2., -1., 4., -4., + }, + { + 1. / (2. * M_PI), 0.75, 0.5, 0.0, + }, +}; + +/* Native register description structure */ +struct etna_native_reg { + unsigned valid : 1; + unsigned is_tex : 1; /* is texture unit, overrides rgroup */ + unsigned rgroup : 3; + unsigned id : 9; +}; + +/* Register description */ +struct etna_reg_desc { + enum tgsi_file_type file; /* IN, OUT, TEMP, ... */ + int idx; /* index into file */ + bool active; /* used in program */ + int first_use; /* instruction id of first use (scope begin) */ + int last_use; /* instruction id of last use (scope end, inclusive) */ + + struct etna_native_reg native; /* native register to map to */ + unsigned usage_mask : 4; /* usage, per channel */ + bool has_semantic; /* register has associated TGSI semantic */ + struct tgsi_declaration_semantic semantic; /* TGSI semantic */ + struct tgsi_declaration_interp interp; /* Interpolation type */ +}; + +/* Label information structure */ +struct etna_compile_label { + int inst_idx; /* Instruction id that label points to */ +}; + +enum etna_compile_frame_type { + ETNA_COMPILE_FRAME_IF, /* IF/ELSE/ENDIF */ + ETNA_COMPILE_FRAME_LOOP, +}; + +/* nesting scope frame (LOOP, IF, ...) during compilation + */ +struct etna_compile_frame { + enum etna_compile_frame_type type; + int lbl_else_idx; + int lbl_endif_idx; + int lbl_loop_bgn_idx; + int lbl_loop_end_idx; +}; + +struct etna_compile_file { + /* Number of registers in each TGSI file (max register+1) */ + size_t reg_size; + /* Register descriptions, per register index */ + struct etna_reg_desc *reg; +}; + +#define array_insert(arr, val) \ + do { \ + if (arr##_count == arr##_sz) { \ + arr##_sz = MAX2(2 * arr##_sz, 16); \ + arr = realloc(arr, arr##_sz * sizeof(arr[0])); \ + } \ + arr[arr##_count++] = val; \ + } while (0) + + +/* scratch area for compiling shader, freed after compilation finishes */ +struct etna_compile { + const struct tgsi_token *tokens; + bool free_tokens; + + struct tgsi_shader_info info; + + /* Register descriptions, per TGSI file, per register index */ + struct etna_compile_file file[TGSI_FILE_COUNT]; + + /* Keep track of TGSI register declarations */ + struct etna_reg_desc decl[ETNA_MAX_DECL]; + uint total_decls; + + /* Bitmap of dead instructions which are removed in a separate pass */ + bool dead_inst[ETNA_MAX_TOKENS]; + + /* Immediate data */ + enum etna_immediate_contents imm_contents[ETNA_MAX_IMM]; + uint32_t imm_data[ETNA_MAX_IMM]; + uint32_t imm_base; /* base of immediates (in 32 bit units) */ + uint32_t imm_size; /* size of immediates (in 32 bit units) */ + + /* Next free native register, for register allocation */ + uint32_t next_free_native; + + /* Temporary register for use within translated TGSI instruction, + * only allocated when needed. + */ + int inner_temps; /* number of inner temps used; only up to one available at + this point */ + struct etna_native_reg inner_temp[ETNA_MAX_INNER_TEMPS]; + + /* Fields for handling nested conditionals */ + struct etna_compile_frame frame_stack[ETNA_MAX_DEPTH]; + int frame_sp; + int lbl_usage[ETNA_MAX_INSTRUCTIONS]; + + unsigned labels_count, labels_sz; + struct etna_compile_label *labels; + + unsigned num_loops; + + /* Code generation */ + int inst_ptr; /* current instruction pointer */ + uint32_t code[ETNA_MAX_INSTRUCTIONS * ETNA_INST_SIZE]; + + /* I/O */ + + /* Number of varyings (PS only) */ + int num_varyings; + + /* GPU hardware specs */ + const struct etna_specs *specs; + + const struct etna_shader_key *key; +}; + +static struct etna_reg_desc * +etna_get_dst_reg(struct etna_compile *c, struct tgsi_dst_register dst) +{ + return &c->file[dst.File].reg[dst.Index]; +} + +static struct etna_reg_desc * +etna_get_src_reg(struct etna_compile *c, struct tgsi_src_register src) +{ + return &c->file[src.File].reg[src.Index]; +} + +static struct etna_native_reg +etna_native_temp(unsigned reg) +{ + return (struct etna_native_reg) { + .valid = 1, + .rgroup = INST_RGROUP_TEMP, + .id = reg + }; +} + +/** Register allocation **/ +enum reg_sort_order { + FIRST_USE_ASC, + FIRST_USE_DESC, + LAST_USE_ASC, + LAST_USE_DESC +}; + +/* Augmented register description for sorting */ +struct sort_rec { + struct etna_reg_desc *ptr; + int key; +}; + +static int +sort_rec_compar(const struct sort_rec *a, const struct sort_rec *b) +{ + if (a->key < b->key) + return -1; + + if (a->key > b->key) + return 1; + + return 0; +} + +/* create an index on a register set based on certain criteria. */ +static int +sort_registers(struct sort_rec *sorted, struct etna_compile_file *file, + enum reg_sort_order so) +{ + struct etna_reg_desc *regs = file->reg; + int ptr = 0; + + /* pre-populate keys from active registers */ + for (int idx = 0; idx < file->reg_size; ++idx) { + /* only interested in active registers now; will only assign inactive ones + * if no space in active ones */ + if (regs[idx].active) { + sorted[ptr].ptr = ®s[idx]; + + switch (so) { + case FIRST_USE_ASC: + sorted[ptr].key = regs[idx].first_use; + break; + case LAST_USE_ASC: + sorted[ptr].key = regs[idx].last_use; + break; + case FIRST_USE_DESC: + sorted[ptr].key = -regs[idx].first_use; + break; + case LAST_USE_DESC: + sorted[ptr].key = -regs[idx].last_use; + break; + } + ptr++; + } + } + + /* sort index by key */ + qsort(sorted, ptr, sizeof(struct sort_rec), + (int (*)(const void *, const void *))sort_rec_compar); + + return ptr; +} + +/* Allocate a new, unused, native temp register */ +static struct etna_native_reg +alloc_new_native_reg(struct etna_compile *c) +{ + assert(c->next_free_native < ETNA_MAX_TEMPS); + return etna_native_temp(c->next_free_native++); +} + +/* assign TEMPs to native registers */ +static void +assign_temporaries_to_native(struct etna_compile *c, + struct etna_compile_file *file) +{ + struct etna_reg_desc *temps = file->reg; + + for (int idx = 0; idx < file->reg_size; ++idx) + temps[idx].native = alloc_new_native_reg(c); +} + +/* assign inputs and outputs to temporaries + * Gallium assumes that the hardware has separate registers for taking input and + * output, however Vivante GPUs use temporaries both for passing in inputs and + * passing back outputs. + * Try to re-use temporary registers where possible. */ +static void +assign_inouts_to_temporaries(struct etna_compile *c, uint file) +{ + bool mode_inputs = (file == TGSI_FILE_INPUT); + int inout_ptr = 0, num_inouts; + int temp_ptr = 0, num_temps; + struct sort_rec inout_order[ETNA_MAX_TEMPS]; + struct sort_rec temps_order[ETNA_MAX_TEMPS]; + num_inouts = sort_registers(inout_order, &c->file[file], + mode_inputs ? LAST_USE_ASC : FIRST_USE_ASC); + num_temps = sort_registers(temps_order, &c->file[TGSI_FILE_TEMPORARY], + mode_inputs ? FIRST_USE_ASC : LAST_USE_ASC); + + while (inout_ptr < num_inouts && temp_ptr < num_temps) { + struct etna_reg_desc *inout = inout_order[inout_ptr].ptr; + struct etna_reg_desc *temp = temps_order[temp_ptr].ptr; + + if (!inout->active || inout->native.valid) { /* Skip if already a native register assigned */ + inout_ptr++; + continue; + } + + /* last usage of this input is before or in same instruction of first use + * of temporary? */ + if (mode_inputs ? (inout->last_use <= temp->first_use) + : (inout->first_use >= temp->last_use)) { + /* assign it and advance to next input */ + inout->native = temp->native; + inout_ptr++; + } + + temp_ptr++; + } + + /* if we couldn't reuse current ones, allocate new temporaries */ + for (inout_ptr = 0; inout_ptr < num_inouts; ++inout_ptr) { + struct etna_reg_desc *inout = inout_order[inout_ptr].ptr; + + if (inout->active && !inout->native.valid) + inout->native = alloc_new_native_reg(c); + } +} + +/* Allocate an immediate with a certain value and return the index. If + * there is already an immediate with that value, return that. + */ +static struct etna_inst_src +alloc_imm(struct etna_compile *c, enum etna_immediate_contents contents, + uint32_t value) +{ + int idx; + + /* Could use a hash table to speed this up */ + for (idx = 0; idx < c->imm_size; ++idx) { + if (c->imm_contents[idx] == contents && c->imm_data[idx] == value) + break; + } + + /* look if there is an unused slot */ + if (idx == c->imm_size) { + for (idx = 0; idx < c->imm_size; ++idx) { + if (c->imm_contents[idx] == ETNA_IMMEDIATE_UNUSED) + break; + } + } + + /* allocate new immediate */ + if (idx == c->imm_size) { + assert(c->imm_size < ETNA_MAX_IMM); + idx = c->imm_size++; + c->imm_data[idx] = value; + c->imm_contents[idx] = contents; + } + + /* swizzle so that component with value is returned in all components */ + idx += c->imm_base; + struct etna_inst_src imm_src = { + .use = 1, + .rgroup = INST_RGROUP_UNIFORM_0, + .reg = idx / 4, + .swiz = INST_SWIZ_BROADCAST(idx & 3) + }; + + return imm_src; +} + +static struct etna_inst_src +alloc_imm_u32(struct etna_compile *c, uint32_t value) +{ + return alloc_imm(c, ETNA_IMMEDIATE_CONSTANT, value); +} + +static struct etna_inst_src +alloc_imm_vec4u(struct etna_compile *c, enum etna_immediate_contents contents, + const uint32_t *values) +{ + struct etna_inst_src imm_src = { }; + int idx, i; + + for (idx = 0; idx + 3 < c->imm_size; idx += 4) { + /* What if we can use a uniform with a different swizzle? */ + for (i = 0; i < 4; i++) + if (c->imm_contents[idx + i] != contents || c->imm_data[idx + i] != values[i]) + break; + if (i == 4) + break; + } + + if (idx + 3 >= c->imm_size) { + idx = align(c->imm_size, 4); + assert(idx + 4 <= ETNA_MAX_IMM); + + for (i = 0; i < 4; i++) { + c->imm_data[idx + i] = values[i]; + c->imm_contents[idx + i] = contents; + } + + c->imm_size = idx + 4; + } + + assert((c->imm_base & 3) == 0); + idx += c->imm_base; + imm_src.use = 1; + imm_src.rgroup = INST_RGROUP_UNIFORM_0; + imm_src.reg = idx / 4; + imm_src.swiz = INST_SWIZ_IDENTITY; + + return imm_src; +} + +static uint32_t +get_imm_u32(struct etna_compile *c, const struct etna_inst_src *imm, + unsigned swiz_idx) +{ + assert(imm->use == 1 && imm->rgroup == INST_RGROUP_UNIFORM_0); + unsigned int idx = imm->reg * 4 + ((imm->swiz >> (swiz_idx * 2)) & 3); + + return c->imm_data[idx]; +} + +/* Allocate immediate with a certain float value. If there is already an + * immediate with that value, return that. + */ +static struct etna_inst_src +alloc_imm_f32(struct etna_compile *c, float value) +{ + return alloc_imm_u32(c, fui(value)); +} + +static struct etna_inst_src +etna_imm_vec4f(struct etna_compile *c, const float *vec4) +{ + uint32_t val[4]; + + for (int i = 0; i < 4; i++) + val[i] = fui(vec4[i]); + + return alloc_imm_vec4u(c, ETNA_IMMEDIATE_CONSTANT, val); +} + +/* Pass -- check register file declarations and immediates */ +static void +etna_compile_parse_declarations(struct etna_compile *c) +{ + struct tgsi_parse_context ctx = { }; + unsigned status = TGSI_PARSE_OK; + status = tgsi_parse_init(&ctx, c->tokens); + assert(status == TGSI_PARSE_OK); + + while (!tgsi_parse_end_of_tokens(&ctx)) { + tgsi_parse_token(&ctx); + + switch (ctx.FullToken.Token.Type) { + case TGSI_TOKEN_TYPE_IMMEDIATE: { + /* immediates are handled differently from other files; they are + * not declared explicitly, and always add four components */ + const struct tgsi_full_immediate *imm = &ctx.FullToken.FullImmediate; + assert(c->imm_size <= (ETNA_MAX_IMM - 4)); + + for (int i = 0; i < 4; ++i) { + unsigned idx = c->imm_size++; + + c->imm_data[idx] = imm->u[i].Uint; + c->imm_contents[idx] = ETNA_IMMEDIATE_CONSTANT; + } + } + break; + } + } + + tgsi_parse_free(&ctx); +} + +/* Allocate register declarations for the registers in all register files */ +static void +etna_allocate_decls(struct etna_compile *c) +{ + uint idx = 0; + + for (int x = 0; x < TGSI_FILE_COUNT; ++x) { + c->file[x].reg = &c->decl[idx]; + c->file[x].reg_size = c->info.file_max[x] + 1; + + for (int sub = 0; sub < c->file[x].reg_size; ++sub) { + c->decl[idx].file = x; + c->decl[idx].idx = sub; + idx++; + } + } + + c->total_decls = idx; +} + +/* Pass -- check and record usage of temporaries, inputs, outputs */ +static void +etna_compile_pass_check_usage(struct etna_compile *c) +{ + struct tgsi_parse_context ctx = { }; + unsigned status = TGSI_PARSE_OK; + status = tgsi_parse_init(&ctx, c->tokens); + assert(status == TGSI_PARSE_OK); + + for (int idx = 0; idx < c->total_decls; ++idx) { + c->decl[idx].active = false; + c->decl[idx].first_use = c->decl[idx].last_use = -1; + } + + int inst_idx = 0; + while (!tgsi_parse_end_of_tokens(&ctx)) { + tgsi_parse_token(&ctx); + /* find out max register #s used + * For every register mark first and last instruction index where it's + * used this allows finding ranges where the temporary can be borrowed + * as input and/or output register + * + * XXX in the case of loops this needs special care, or even be completely + * disabled, as + * the last usage of a register inside a loop means it can still be used + * on next loop + * iteration (execution is no longer * chronological). The register can + * only be + * declared "free" after the loop finishes. + * + * Same for inputs: the first usage of a register inside a loop doesn't + * mean that the register + * won't have been overwritten in previous iteration. The register can + * only be declared free before the loop + * starts. + * The proper way would be to do full dominator / post-dominator analysis + * (especially with more complicated + * control flow such as direct branch instructions) but not for now... + */ + switch (ctx.FullToken.Token.Type) { + case TGSI_TOKEN_TYPE_DECLARATION: { + /* Declaration: fill in file details */ + const struct tgsi_full_declaration *decl = &ctx.FullToken.FullDeclaration; + struct etna_compile_file *file = &c->file[decl->Declaration.File]; + + for (int idx = decl->Range.First; idx <= decl->Range.Last; ++idx) { + file->reg[idx].usage_mask = 0; // we'll compute this ourselves + file->reg[idx].has_semantic = decl->Declaration.Semantic; + file->reg[idx].semantic = decl->Semantic; + file->reg[idx].interp = decl->Interp; + } + } break; + case TGSI_TOKEN_TYPE_INSTRUCTION: { + /* Instruction: iterate over operands of instruction */ + const struct tgsi_full_instruction *inst = &ctx.FullToken.FullInstruction; + + /* iterate over destination registers */ + for (int idx = 0; idx < inst->Instruction.NumDstRegs; ++idx) { + struct etna_reg_desc *reg_desc = &c->file[inst->Dst[idx].Register.File].reg[inst->Dst[idx].Register.Index]; + + if (reg_desc->first_use == -1) + reg_desc->first_use = inst_idx; + + reg_desc->last_use = inst_idx; + reg_desc->active = true; + } + + /* iterate over source registers */ + for (int idx = 0; idx < inst->Instruction.NumSrcRegs; ++idx) { + struct etna_reg_desc *reg_desc = &c->file[inst->Src[idx].Register.File].reg[inst->Src[idx].Register.Index]; + + if (reg_desc->first_use == -1) + reg_desc->first_use = inst_idx; + + reg_desc->last_use = inst_idx; + reg_desc->active = true; + /* accumulate usage mask for register, this is used to determine how + * many slots for varyings + * should be allocated */ + reg_desc->usage_mask |= tgsi_util_get_inst_usage_mask(inst, idx); + } + inst_idx += 1; + } break; + default: + break; + } + } + + tgsi_parse_free(&ctx); +} + +/* assign inputs that need to be assigned to specific registers */ +static void +assign_special_inputs(struct etna_compile *c) +{ + if (c->info.processor == PIPE_SHADER_FRAGMENT) { + /* never assign t0 as it is the position output, start assigning at t1 */ + c->next_free_native = 1; + + /* hardwire TGSI_SEMANTIC_POSITION (input and output) to t0 */ + for (int idx = 0; idx < c->total_decls; ++idx) { + struct etna_reg_desc *reg = &c->decl[idx]; + + if (reg->active && reg->semantic.Name == TGSI_SEMANTIC_POSITION) + reg->native = etna_native_temp(0); + } + } +} + +/* Check that a move instruction does not swizzle any of the components + * that it writes. + */ +static bool +etna_mov_check_no_swizzle(const struct tgsi_dst_register dst, + const struct tgsi_src_register src) +{ + return (!(dst.WriteMask & TGSI_WRITEMASK_X) || src.SwizzleX == TGSI_SWIZZLE_X) && + (!(dst.WriteMask & TGSI_WRITEMASK_Y) || src.SwizzleY == TGSI_SWIZZLE_Y) && + (!(dst.WriteMask & TGSI_WRITEMASK_Z) || src.SwizzleZ == TGSI_SWIZZLE_Z) && + (!(dst.WriteMask & TGSI_WRITEMASK_W) || src.SwizzleW == TGSI_SWIZZLE_W); +} + +/* Pass -- optimize outputs + * Mesa tends to generate code like this at the end if their shaders + * MOV OUT[1], TEMP[2] + * MOV OUT[0], TEMP[0] + * MOV OUT[2], TEMP[1] + * Recognize if + * a) there is only a single assignment to an output register and + * b) the temporary is not used after that + * Also recognize direct assignment of IN to OUT (passthrough) + **/ +static void +etna_compile_pass_optimize_outputs(struct etna_compile *c) +{ + struct tgsi_parse_context ctx = { }; + int inst_idx = 0; + unsigned status = TGSI_PARSE_OK; + status = tgsi_parse_init(&ctx, c->tokens); + assert(status == TGSI_PARSE_OK); + + while (!tgsi_parse_end_of_tokens(&ctx)) { + tgsi_parse_token(&ctx); + + switch (ctx.FullToken.Token.Type) { + case TGSI_TOKEN_TYPE_INSTRUCTION: { + const struct tgsi_full_instruction *inst = &ctx.FullToken.FullInstruction; + + /* iterate over operands */ + switch (inst->Instruction.Opcode) { + case TGSI_OPCODE_MOV: { + /* We are only interested in eliminating MOVs which write to + * the shader outputs. Test for this early. */ + if (inst->Dst[0].Register.File != TGSI_FILE_OUTPUT) + break; + /* Elimination of a MOV must have no visible effect on the + * resulting shader: this means the MOV must not swizzle or + * saturate, and its source must not have the negate or + * absolute modifiers. */ + if (!etna_mov_check_no_swizzle(inst->Dst[0].Register, inst->Src[0].Register) || + inst->Instruction.Saturate || inst->Src[0].Register.Negate || + inst->Src[0].Register.Absolute) + break; + + uint out_idx = inst->Dst[0].Register.Index; + uint in_idx = inst->Src[0].Register.Index; + /* assignment of temporary to output -- + * and the output doesn't yet have a native register assigned + * and the last use of the temporary is this instruction + * and the MOV does not do a swizzle + */ + if (inst->Src[0].Register.File == TGSI_FILE_TEMPORARY && + !c->file[TGSI_FILE_OUTPUT].reg[out_idx].native.valid && + c->file[TGSI_FILE_TEMPORARY].reg[in_idx].last_use == inst_idx) { + c->file[TGSI_FILE_OUTPUT].reg[out_idx].native = + c->file[TGSI_FILE_TEMPORARY].reg[in_idx].native; + /* prevent temp from being re-used for the rest of the shader */ + c->file[TGSI_FILE_TEMPORARY].reg[in_idx].last_use = ETNA_MAX_TOKENS; + /* mark this MOV instruction as a no-op */ + c->dead_inst[inst_idx] = true; + } + /* direct assignment of input to output -- + * and the input or output doesn't yet have a native register + * assigned + * and the output is only used in this instruction, + * allocate a new register, and associate both input and output to + * it + * and the MOV does not do a swizzle + */ + if (inst->Src[0].Register.File == TGSI_FILE_INPUT && + !c->file[TGSI_FILE_INPUT].reg[in_idx].native.valid && + !c->file[TGSI_FILE_OUTPUT].reg[out_idx].native.valid && + c->file[TGSI_FILE_OUTPUT].reg[out_idx].last_use == inst_idx && + c->file[TGSI_FILE_OUTPUT].reg[out_idx].first_use == inst_idx) { + c->file[TGSI_FILE_OUTPUT].reg[out_idx].native = + c->file[TGSI_FILE_INPUT].reg[in_idx].native = + alloc_new_native_reg(c); + /* mark this MOV instruction as a no-op */ + c->dead_inst[inst_idx] = true; + } + } break; + default:; + } + inst_idx += 1; + } break; + } + } + + tgsi_parse_free(&ctx); +} + +/* Get a temporary to be used within one TGSI instruction. + * The first time that this function is called the temporary will be allocated. + * Each call to this function will return the same temporary. + */ +static struct etna_native_reg +etna_compile_get_inner_temp(struct etna_compile *c) +{ + int inner_temp = c->inner_temps; + + if (inner_temp < ETNA_MAX_INNER_TEMPS) { + if (!c->inner_temp[inner_temp].valid) + c->inner_temp[inner_temp] = alloc_new_native_reg(c); + + /* alloc_new_native_reg() handles lack of registers */ + c->inner_temps += 1; + } else { + BUG("Too many inner temporaries (%i) requested in one instruction", + inner_temp + 1); + } + + return c->inner_temp[inner_temp]; +} + +static struct etna_inst_dst +etna_native_to_dst(struct etna_native_reg native, unsigned comps) +{ + /* Can only assign to temporaries */ + assert(native.valid && !native.is_tex && native.rgroup == INST_RGROUP_TEMP); + + struct etna_inst_dst rv = { + .comps = comps, + .use = 1, + .reg = native.id, + }; + + return rv; +} + +static struct etna_inst_src +etna_native_to_src(struct etna_native_reg native, uint32_t swizzle) +{ + assert(native.valid && !native.is_tex); + + struct etna_inst_src rv = { + .use = 1, + .swiz = swizzle, + .rgroup = native.rgroup, + .reg = native.id, + .amode = INST_AMODE_DIRECT, + }; + + return rv; +} + +static inline struct etna_inst_src +negate(struct etna_inst_src src) +{ + src.neg = !src.neg; + + return src; +} + +static inline struct etna_inst_src +absolute(struct etna_inst_src src) +{ + src.abs = 1; + + return src; +} + +static inline struct etna_inst_src +swizzle(struct etna_inst_src src, unsigned swizzle) +{ + src.swiz = inst_swiz_compose(src.swiz, swizzle); + + return src; +} + +/* Emit instruction and append it to program */ +static void +emit_inst(struct etna_compile *c, struct etna_inst *inst) +{ + assert(c->inst_ptr <= ETNA_MAX_INSTRUCTIONS); + + /* Check for uniform conflicts (each instruction can only access one + * uniform), + * if detected, use an intermediate temporary */ + unsigned uni_rgroup = -1; + unsigned uni_reg = -1; + + for (int src = 0; src < ETNA_NUM_SRC; ++src) { + if (etna_rgroup_is_uniform(inst->src[src].rgroup)) { + if (uni_reg == -1) { /* first unique uniform used */ + uni_rgroup = inst->src[src].rgroup; + uni_reg = inst->src[src].reg; + } else { /* second or later; check that it is a re-use */ + if (uni_rgroup != inst->src[src].rgroup || + uni_reg != inst->src[src].reg) { + DBG_F(ETNA_DBG_COMPILER_MSGS, "perf warning: instruction that " + "accesses different uniforms, " + "need to generate extra MOV"); + struct etna_native_reg inner_temp = etna_compile_get_inner_temp(c); + + /* Generate move instruction to temporary */ + etna_assemble(&c->code[c->inst_ptr * 4], &(struct etna_inst) { + .opcode = INST_OPCODE_MOV, + .dst = etna_native_to_dst(inner_temp, INST_COMPS_X | INST_COMPS_Y | + INST_COMPS_Z | INST_COMPS_W), + .src[2] = inst->src[src] + }); + + c->inst_ptr++; + + /* Modify instruction to use temp register instead of uniform */ + inst->src[src].use = 1; + inst->src[src].rgroup = INST_RGROUP_TEMP; + inst->src[src].reg = inner_temp.id; + inst->src[src].swiz = INST_SWIZ_IDENTITY; /* swizzling happens on MOV */ + inst->src[src].neg = 0; /* negation happens on MOV */ + inst->src[src].abs = 0; /* abs happens on MOV */ + inst->src[src].amode = 0; /* amode effects happen on MOV */ + } + } + } + } + + /* Finally assemble the actual instruction */ + etna_assemble(&c->code[c->inst_ptr * 4], inst); + c->inst_ptr++; +} + +static unsigned int +etna_amode(struct tgsi_ind_register indirect) +{ + assert(indirect.File == TGSI_FILE_ADDRESS); + assert(indirect.Index == 0); + + switch (indirect.Swizzle) { + case TGSI_SWIZZLE_X: + return INST_AMODE_ADD_A_X; + case TGSI_SWIZZLE_Y: + return INST_AMODE_ADD_A_Y; + case TGSI_SWIZZLE_Z: + return INST_AMODE_ADD_A_Z; + case TGSI_SWIZZLE_W: + return INST_AMODE_ADD_A_W; + default: + assert(!"Invalid swizzle"); + } + + unreachable("bad swizzle"); +} + +/* convert destination operand */ +static struct etna_inst_dst +convert_dst(struct etna_compile *c, const struct tgsi_full_dst_register *in) +{ + struct etna_inst_dst rv = { + /// XXX .amode + .comps = in->Register.WriteMask, + }; + + if (in->Register.File == TGSI_FILE_ADDRESS) { + assert(in->Register.Index == 0); + rv.reg = in->Register.Index; + rv.use = 0; + } else { + rv = etna_native_to_dst(etna_get_dst_reg(c, in->Register)->native, + in->Register.WriteMask); + } + + if (in->Register.Indirect) + rv.amode = etna_amode(in->Indirect); + + return rv; +} + +/* convert texture operand */ +static struct etna_inst_tex +convert_tex(struct etna_compile *c, const struct tgsi_full_src_register *in, + const struct tgsi_instruction_texture *tex) +{ + struct etna_native_reg native_reg = etna_get_src_reg(c, in->Register)->native; + struct etna_inst_tex rv = { + // XXX .amode (to allow for an array of samplers?) + .swiz = INST_SWIZ_IDENTITY + }; + + assert(native_reg.is_tex && native_reg.valid); + rv.id = native_reg.id; + + return rv; +} + +/* convert source operand */ +static struct etna_inst_src +etna_create_src(const struct tgsi_full_src_register *tgsi, + const struct etna_native_reg *native) +{ + const struct tgsi_src_register *reg = &tgsi->Register; + struct etna_inst_src rv = { + .use = 1, + .swiz = INST_SWIZ(reg->SwizzleX, reg->SwizzleY, reg->SwizzleZ, reg->SwizzleW), + .neg = reg->Negate, + .abs = reg->Absolute, + .rgroup = native->rgroup, + .reg = native->id, + .amode = INST_AMODE_DIRECT, + }; + + assert(native->valid && !native->is_tex); + + if (reg->Indirect) + rv.amode = etna_amode(tgsi->Indirect); + + return rv; +} + +static struct etna_inst_src +etna_mov_src_to_temp(struct etna_compile *c, struct etna_inst_src src, + struct etna_native_reg temp) +{ + struct etna_inst mov = { }; + + mov.opcode = INST_OPCODE_MOV; + mov.sat = 0; + mov.dst = etna_native_to_dst(temp, INST_COMPS_X | INST_COMPS_Y | + INST_COMPS_Z | INST_COMPS_W); + mov.src[2] = src; + emit_inst(c, &mov); + + src.swiz = INST_SWIZ_IDENTITY; + src.neg = src.abs = 0; + src.rgroup = temp.rgroup; + src.reg = temp.id; + + return src; +} + +static struct etna_inst_src +etna_mov_src(struct etna_compile *c, struct etna_inst_src src) +{ + struct etna_native_reg temp = etna_compile_get_inner_temp(c); + + return etna_mov_src_to_temp(c, src, temp); +} + +static bool +etna_src_uniforms_conflict(struct etna_inst_src a, struct etna_inst_src b) +{ + return etna_rgroup_is_uniform(a.rgroup) && + etna_rgroup_is_uniform(b.rgroup) && + (a.rgroup != b.rgroup || a.reg != b.reg); +} + +/* create a new label */ +static unsigned int +alloc_new_label(struct etna_compile *c) +{ + struct etna_compile_label label = { + .inst_idx = -1, /* start by point to no specific instruction */ + }; + + array_insert(c->labels, label); + + return c->labels_count - 1; +} + +/* place label at current instruction pointer */ +static void +label_place(struct etna_compile *c, struct etna_compile_label *label) +{ + label->inst_idx = c->inst_ptr; +} + +/* mark label use at current instruction. + * target of the label will be filled in in the marked instruction's src2.imm + * slot as soon + * as the value becomes known. + */ +static void +label_mark_use(struct etna_compile *c, int lbl_idx) +{ + assert(c->inst_ptr < ETNA_MAX_INSTRUCTIONS); + c->lbl_usage[c->inst_ptr] = lbl_idx; +} + +/* walk the frame stack and return first frame with matching type */ +static struct etna_compile_frame * +find_frame(struct etna_compile *c, enum etna_compile_frame_type type) +{ + for (int sp = c->frame_sp; sp >= 0; sp--) + if (c->frame_stack[sp].type == type) + return &c->frame_stack[sp]; + + assert(0); + return NULL; +} + +struct instr_translater { + void (*fxn)(const struct instr_translater *t, struct etna_compile *c, + const struct tgsi_full_instruction *inst, + struct etna_inst_src *src); + unsigned tgsi_opc; + uint8_t opc; + + /* tgsi src -> etna src swizzle */ + int src[3]; + + unsigned cond; +}; + +static void +trans_instr(const struct instr_translater *t, struct etna_compile *c, + const struct tgsi_full_instruction *inst, struct etna_inst_src *src) +{ + const struct tgsi_opcode_info *info = tgsi_get_opcode_info(inst->Instruction.Opcode); + struct etna_inst instr = { }; + + instr.opcode = t->opc; + instr.cond = t->cond; + instr.sat = inst->Instruction.Saturate; + + assert(info->num_dst <= 1); + if (info->num_dst) + instr.dst = convert_dst(c, &inst->Dst[0]); + + assert(info->num_src <= ETNA_NUM_SRC); + + for (unsigned i = 0; i < info->num_src; i++) { + int swizzle = t->src[i]; + + assert(swizzle != -1); + instr.src[swizzle] = src[i]; + } + + emit_inst(c, &instr); +} + +static void +trans_min_max(const struct instr_translater *t, struct etna_compile *c, + const struct tgsi_full_instruction *inst, + struct etna_inst_src *src) +{ + emit_inst(c, &(struct etna_inst) { + .opcode = INST_OPCODE_SELECT, + .cond = t->cond, + .sat = inst->Instruction.Saturate, + .dst = convert_dst(c, &inst->Dst[0]), + .src[0] = src[0], + .src[1] = src[1], + .src[2] = src[0], + }); +} + +static void +trans_if(const struct instr_translater *t, struct etna_compile *c, + const struct tgsi_full_instruction *inst, struct etna_inst_src *src) +{ + struct etna_compile_frame *f = &c->frame_stack[c->frame_sp++]; + struct etna_inst_src imm_0 = alloc_imm_f32(c, 0.0f); + + /* push IF to stack */ + f->type = ETNA_COMPILE_FRAME_IF; + /* create "else" label */ + f->lbl_else_idx = alloc_new_label(c); + f->lbl_endif_idx = -1; + + /* We need to avoid the emit_inst() below becoming two instructions */ + if (etna_src_uniforms_conflict(src[0], imm_0)) + src[0] = etna_mov_src(c, src[0]); + + /* mark position in instruction stream of label reference so that it can be + * filled in in next pass */ + label_mark_use(c, f->lbl_else_idx); + + /* create conditional branch to label if src0 EQ 0 */ + emit_inst(c, &(struct etna_inst){ + .opcode = INST_OPCODE_BRANCH, + .cond = INST_CONDITION_EQ, + .src[0] = src[0], + .src[1] = imm_0, + /* imm is filled in later */ + }); +} + +static void +trans_else(const struct instr_translater *t, struct etna_compile *c, + const struct tgsi_full_instruction *inst, struct etna_inst_src *src) +{ + assert(c->frame_sp > 0); + struct etna_compile_frame *f = &c->frame_stack[c->frame_sp - 1]; + assert(f->type == ETNA_COMPILE_FRAME_IF); + + /* create "endif" label, and branch to endif label */ + f->lbl_endif_idx = alloc_new_label(c); + label_mark_use(c, f->lbl_endif_idx); + emit_inst(c, &(struct etna_inst) { + .opcode = INST_OPCODE_BRANCH, + .cond = INST_CONDITION_TRUE, + /* imm is filled in later */ + }); + + /* mark "else" label at this position in instruction stream */ + label_place(c, &c->labels[f->lbl_else_idx]); +} + +static void +trans_endif(const struct instr_translater *t, struct etna_compile *c, + const struct tgsi_full_instruction *inst, struct etna_inst_src *src) +{ + assert(c->frame_sp > 0); + struct etna_compile_frame *f = &c->frame_stack[--c->frame_sp]; + assert(f->type == ETNA_COMPILE_FRAME_IF); + + /* assign "endif" or "else" (if no ELSE) label to current position in + * instruction stream, pop IF */ + if (f->lbl_endif_idx != -1) + label_place(c, &c->labels[f->lbl_endif_idx]); + else + label_place(c, &c->labels[f->lbl_else_idx]); +} + +static void +trans_loop_bgn(const struct instr_translater *t, struct etna_compile *c, + const struct tgsi_full_instruction *inst, + struct etna_inst_src *src) +{ + struct etna_compile_frame *f = &c->frame_stack[c->frame_sp++]; + + /* push LOOP to stack */ + f->type = ETNA_COMPILE_FRAME_LOOP; + f->lbl_loop_bgn_idx = alloc_new_label(c); + f->lbl_loop_end_idx = alloc_new_label(c); + + label_place(c, &c->labels[f->lbl_loop_bgn_idx]); + + c->num_loops++; +} + +static void +trans_loop_end(const struct instr_translater *t, struct etna_compile *c, + const struct tgsi_full_instruction *inst, + struct etna_inst_src *src) +{ + assert(c->frame_sp > 0); + struct etna_compile_frame *f = &c->frame_stack[--c->frame_sp]; + assert(f->type == ETNA_COMPILE_FRAME_LOOP); + + /* mark position in instruction stream of label reference so that it can be + * filled in in next pass */ + label_mark_use(c, f->lbl_loop_bgn_idx); + + /* create branch to loop_bgn label */ + emit_inst(c, &(struct etna_inst) { + .opcode = INST_OPCODE_BRANCH, + .cond = INST_CONDITION_TRUE, + .src[0] = src[0], + /* imm is filled in later */ + }); + + label_place(c, &c->labels[f->lbl_loop_end_idx]); +} + +static void +trans_brk(const struct instr_translater *t, struct etna_compile *c, + const struct tgsi_full_instruction *inst, struct etna_inst_src *src) +{ + assert(c->frame_sp > 0); + struct etna_compile_frame *f = find_frame(c, ETNA_COMPILE_FRAME_LOOP); + + /* mark position in instruction stream of label reference so that it can be + * filled in in next pass */ + label_mark_use(c, f->lbl_loop_end_idx); + + /* create branch to loop_end label */ + emit_inst(c, &(struct etna_inst) { + .opcode = INST_OPCODE_BRANCH, + .cond = INST_CONDITION_TRUE, + .src[0] = src[0], + /* imm is filled in later */ + }); +} + +static void +trans_cont(const struct instr_translater *t, struct etna_compile *c, + const struct tgsi_full_instruction *inst, struct etna_inst_src *src) +{ + assert(c->frame_sp > 0); + struct etna_compile_frame *f = find_frame(c, ETNA_COMPILE_FRAME_LOOP); + + /* mark position in instruction stream of label reference so that it can be + * filled in in next pass */ + label_mark_use(c, f->lbl_loop_bgn_idx); + + /* create branch to loop_end label */ + emit_inst(c, &(struct etna_inst) { + .opcode = INST_OPCODE_BRANCH, + .cond = INST_CONDITION_TRUE, + .src[0] = src[0], + /* imm is filled in later */ + }); +} + +static void +trans_deriv(const struct instr_translater *t, struct etna_compile *c, + const struct tgsi_full_instruction *inst, struct etna_inst_src *src) +{ + emit_inst(c, &(struct etna_inst) { + .opcode = t->opc, + .sat = inst->Instruction.Saturate, + .dst = convert_dst(c, &inst->Dst[0]), + .src[0] = src[0], + .src[2] = src[0], + }); +} + +static void +trans_arl(const struct instr_translater *t, struct etna_compile *c, + const struct tgsi_full_instruction *inst, struct etna_inst_src *src) +{ + struct etna_native_reg temp = etna_compile_get_inner_temp(c); + struct etna_inst arl = { }; + struct etna_inst_dst dst; + + dst = etna_native_to_dst(temp, INST_COMPS_X | INST_COMPS_Y | INST_COMPS_Z | + INST_COMPS_W); + + if (c->specs->has_sign_floor_ceil) { + struct etna_inst floor = { }; + + floor.opcode = INST_OPCODE_FLOOR; + floor.src[2] = src[0]; + floor.dst = dst; + + emit_inst(c, &floor); + } else { + struct etna_inst floor[2] = { }; + + floor[0].opcode = INST_OPCODE_FRC; + floor[0].sat = inst->Instruction.Saturate; + floor[0].dst = dst; + floor[0].src[2] = src[0]; + + floor[1].opcode = INST_OPCODE_ADD; + floor[1].sat = inst->Instruction.Saturate; + floor[1].dst = dst; + floor[1].src[0] = src[0]; + floor[1].src[2].use = 1; + floor[1].src[2].swiz = INST_SWIZ_IDENTITY; + floor[1].src[2].neg = 1; + floor[1].src[2].rgroup = temp.rgroup; + floor[1].src[2].reg = temp.id; + + emit_inst(c, &floor[0]); + emit_inst(c, &floor[1]); + } + + arl.opcode = INST_OPCODE_MOVAR; + arl.sat = inst->Instruction.Saturate; + arl.dst = convert_dst(c, &inst->Dst[0]); + arl.src[2] = etna_native_to_src(temp, INST_SWIZ_IDENTITY); + + emit_inst(c, &arl); +} + +static void +trans_lrp(const struct instr_translater *t, struct etna_compile *c, + const struct tgsi_full_instruction *inst, struct etna_inst_src *src) +{ + /* dst = src0 * src1 + (1 - src0) * src2 + * => src0 * src1 - (src0 - 1) * src2 + * => src0 * src1 - (src0 * src2 - src2) + * MAD tTEMP.xyzw, tSRC0.xyzw, tSRC2.xyzw, -tSRC2.xyzw + * MAD tDST.xyzw, tSRC0.xyzw, tSRC1.xyzw, -tTEMP.xyzw + */ + struct etna_native_reg temp = etna_compile_get_inner_temp(c); + if (etna_src_uniforms_conflict(src[0], src[1]) || + etna_src_uniforms_conflict(src[0], src[2])) { + src[0] = etna_mov_src(c, src[0]); + } + + struct etna_inst mad[2] = { }; + mad[0].opcode = INST_OPCODE_MAD; + mad[0].sat = 0; + mad[0].dst = etna_native_to_dst(temp, INST_COMPS_X | INST_COMPS_Y | + INST_COMPS_Z | INST_COMPS_W); + mad[0].src[0] = src[0]; + mad[0].src[1] = src[2]; + mad[0].src[2] = negate(src[2]); + mad[1].opcode = INST_OPCODE_MAD; + mad[1].sat = inst->Instruction.Saturate; + mad[1].dst = convert_dst(c, &inst->Dst[0]), mad[1].src[0] = src[0]; + mad[1].src[1] = src[1]; + mad[1].src[2] = negate(etna_native_to_src(temp, INST_SWIZ_IDENTITY)); + + emit_inst(c, &mad[0]); + emit_inst(c, &mad[1]); +} + +static void +trans_lit(const struct instr_translater *t, struct etna_compile *c, + const struct tgsi_full_instruction *inst, struct etna_inst_src *src) +{ + /* SELECT.LT tmp._y__, 0, src.yyyy, 0 + * - can be eliminated if src.y is a uniform and >= 0 + * SELECT.GT tmp.___w, 128, src.wwww, 128 + * SELECT.LT tmp.___w, -128, tmp.wwww, -128 + * - can be eliminated if src.w is a uniform and fits clamp + * LOG tmp.x, void, void, tmp.yyyy + * MUL tmp.x, tmp.xxxx, tmp.wwww, void + * LITP dst, undef, src.xxxx, tmp.xxxx + */ + struct etna_native_reg inner_temp = etna_compile_get_inner_temp(c); + struct etna_inst_src src_y = { }; + + if (!etna_rgroup_is_uniform(src[0].rgroup)) { + src_y = etna_native_to_src(inner_temp, SWIZZLE(Y, Y, Y, Y)); + + struct etna_inst ins = { }; + ins.opcode = INST_OPCODE_SELECT; + ins.cond = INST_CONDITION_LT; + ins.dst = etna_native_to_dst(inner_temp, INST_COMPS_Y); + ins.src[0] = ins.src[2] = alloc_imm_f32(c, 0.0); + ins.src[1] = swizzle(src[0], SWIZZLE(Y, Y, Y, Y)); + emit_inst(c, &ins); + } else if (uif(get_imm_u32(c, &src[0], 1)) < 0) + src_y = alloc_imm_f32(c, 0.0); + else + src_y = swizzle(src[0], SWIZZLE(Y, Y, Y, Y)); + + struct etna_inst_src src_w = { }; + + if (!etna_rgroup_is_uniform(src[0].rgroup)) { + src_w = etna_native_to_src(inner_temp, SWIZZLE(W, W, W, W)); + + struct etna_inst ins = { }; + ins.opcode = INST_OPCODE_SELECT; + ins.cond = INST_CONDITION_GT; + ins.dst = etna_native_to_dst(inner_temp, INST_COMPS_W); + ins.src[0] = ins.src[2] = alloc_imm_f32(c, 128.); + ins.src[1] = swizzle(src[0], SWIZZLE(W, W, W, W)); + emit_inst(c, &ins); + ins.cond = INST_CONDITION_LT; + ins.src[0].neg = !ins.src[0].neg; + ins.src[2].neg = !ins.src[2].neg; + ins.src[1] = src_w; + emit_inst(c, &ins); + } else if (uif(get_imm_u32(c, &src[0], 3)) < -128.) + src_w = alloc_imm_f32(c, -128.); + else if (uif(get_imm_u32(c, &src[0], 3)) > 128.) + src_w = alloc_imm_f32(c, 128.); + else + src_w = swizzle(src[0], SWIZZLE(W, W, W, W)); + + if (c->specs->has_new_transcendentals) { /* Alternative LOG sequence */ + emit_inst(c, &(struct etna_inst) { + .opcode = INST_OPCODE_LOG, + .dst = etna_native_to_dst(inner_temp, INST_COMPS_X | INST_COMPS_Y), + .src[2] = src_y, + .tex = { .amode=1 }, /* Unknown bit needs to be set */ + }); + emit_inst(c, &(struct etna_inst) { + .opcode = INST_OPCODE_MUL, + .dst = etna_native_to_dst(inner_temp, INST_COMPS_X), + .src[0] = etna_native_to_src(inner_temp, SWIZZLE(X, X, X, X)), + .src[1] = etna_native_to_src(inner_temp, SWIZZLE(Y, Y, Y, Y)), + }); + } else { + struct etna_inst ins[3] = { }; + ins[0].opcode = INST_OPCODE_LOG; + ins[0].dst = etna_native_to_dst(inner_temp, INST_COMPS_X); + ins[0].src[2] = src_y; + + emit_inst(c, &ins[0]); + } + emit_inst(c, &(struct etna_inst) { + .opcode = INST_OPCODE_MUL, + .sat = 0, + .dst = etna_native_to_dst(inner_temp, INST_COMPS_X), + .src[0] = etna_native_to_src(inner_temp, SWIZZLE(X, X, X, X)), + .src[1] = src_w, + }); + emit_inst(c, &(struct etna_inst) { + .opcode = INST_OPCODE_LITP, + .sat = 0, + .dst = convert_dst(c, &inst->Dst[0]), + .src[0] = swizzle(src[0], SWIZZLE(X, X, X, X)), + .src[1] = swizzle(src[0], SWIZZLE(X, X, X, X)), + .src[2] = etna_native_to_src(inner_temp, SWIZZLE(X, X, X, X)), + }); +} + +static void +trans_ssg(const struct instr_translater *t, struct etna_compile *c, + const struct tgsi_full_instruction *inst, struct etna_inst_src *src) +{ + if (c->specs->has_sign_floor_ceil) { + emit_inst(c, &(struct etna_inst){ + .opcode = INST_OPCODE_SIGN, + .sat = inst->Instruction.Saturate, + .dst = convert_dst(c, &inst->Dst[0]), + .src[2] = src[0], + }); + } else { + struct etna_native_reg temp = etna_compile_get_inner_temp(c); + struct etna_inst ins[2] = { }; + + ins[0].opcode = INST_OPCODE_SET; + ins[0].cond = INST_CONDITION_NZ; + ins[0].dst = etna_native_to_dst(temp, INST_COMPS_X | INST_COMPS_Y | + INST_COMPS_Z | INST_COMPS_W); + ins[0].src[0] = src[0]; + + ins[1].opcode = INST_OPCODE_SELECT; + ins[1].cond = INST_CONDITION_LZ; + ins[1].sat = inst->Instruction.Saturate; + ins[1].dst = convert_dst(c, &inst->Dst[0]); + ins[1].src[0] = src[0]; + ins[1].src[2] = etna_native_to_src(temp, INST_SWIZ_IDENTITY); + ins[1].src[1] = negate(ins[1].src[2]); + + emit_inst(c, &ins[0]); + emit_inst(c, &ins[1]); + } +} + +static void +trans_trig(const struct instr_translater *t, struct etna_compile *c, + const struct tgsi_full_instruction *inst, struct etna_inst_src *src) +{ + if (c->specs->has_new_transcendentals) { /* Alternative SIN/COS */ + /* On newer chips alternative SIN/COS instructions are implemented, + * which: + * - Need their input scaled by 1/pi instead of 2/pi + * - Output an x and y component, which need to be multiplied to + * get the result + */ + struct etna_native_reg temp = etna_compile_get_inner_temp(c); /* only using .xyz */ + emit_inst(c, &(struct etna_inst) { + .opcode = INST_OPCODE_MUL, + .sat = 0, + .dst = etna_native_to_dst(temp, INST_COMPS_Z), + .src[0] = src[0], /* any swizzling happens here */ + .src[1] = alloc_imm_f32(c, 1.0f / M_PI), + }); + emit_inst(c, &(struct etna_inst) { + .opcode = inst->Instruction.Opcode == TGSI_OPCODE_COS + ? INST_OPCODE_COS + : INST_OPCODE_SIN, + .sat = 0, + .dst = etna_native_to_dst(temp, INST_COMPS_X | INST_COMPS_Y), + .src[2] = etna_native_to_src(temp, SWIZZLE(Z, Z, Z, Z)), + .tex = { .amode=1 }, /* Unknown bit needs to be set */ + }); + emit_inst(c, &(struct etna_inst) { + .opcode = INST_OPCODE_MUL, + .sat = inst->Instruction.Saturate, + .dst = convert_dst(c, &inst->Dst[0]), + .src[0] = etna_native_to_src(temp, SWIZZLE(X, X, X, X)), + .src[1] = etna_native_to_src(temp, SWIZZLE(Y, Y, Y, Y)), + }); + + } else if (c->specs->has_sin_cos_sqrt) { + struct etna_native_reg temp = etna_compile_get_inner_temp(c); + /* add divide by PI/2, using a temp register. GC2000 + * fails with src==dst for the trig instruction. */ + emit_inst(c, &(struct etna_inst) { + .opcode = INST_OPCODE_MUL, + .sat = 0, + .dst = etna_native_to_dst(temp, INST_COMPS_X | INST_COMPS_Y | + INST_COMPS_Z | INST_COMPS_W), + .src[0] = src[0], /* any swizzling happens here */ + .src[1] = alloc_imm_f32(c, 2.0f / M_PI), + }); + emit_inst(c, &(struct etna_inst) { + .opcode = inst->Instruction.Opcode == TGSI_OPCODE_COS + ? INST_OPCODE_COS + : INST_OPCODE_SIN, + .sat = inst->Instruction.Saturate, + .dst = convert_dst(c, &inst->Dst[0]), + .src[2] = etna_native_to_src(temp, INST_SWIZ_IDENTITY), + }); + } else { + /* Implement Nick's fast sine/cosine. Taken from: + * http://forum.devmaster.net/t/fast-and-accurate-sine-cosine/9648 + * A=(1/2*PI 0 1/2*PI 0) B=(0.75 0 0.5 0) C=(-4 4 X X) + * MAD t.x_zw, src.xxxx, A, B + * FRC t.x_z_, void, void, t.xwzw + * MAD t.x_z_, t.xwzw, 2, -1 + * MUL t._y__, t.wzww, |t.wzww|, void (for sin/scs) + * DP3 t.x_z_, t.zyww, C, void (for sin) + * DP3 t.__z_, t.zyww, C, void (for scs) + * MUL t._y__, t.wxww, |t.wxww|, void (for cos/scs) + * DP3 t.x_z_, t.xyww, C, void (for cos) + * DP3 t.x___, t.xyww, C, void (for scs) + * MAD t._y_w, t,xxzz, |t.xxzz|, -t.xxzz + * MAD dst, t.ywyw, .2225, t.xzxz + */ + struct etna_inst *p, ins[9] = { }; + struct etna_native_reg t0 = etna_compile_get_inner_temp(c); + struct etna_inst_src t0s = etna_native_to_src(t0, INST_SWIZ_IDENTITY); + struct etna_inst_src sincos[3], in = src[0]; + sincos[0] = etna_imm_vec4f(c, sincos_const[0]); + sincos[1] = etna_imm_vec4f(c, sincos_const[1]); + + /* A uniform source will cause the inner temp limit to + * be exceeded. Explicitly deal with that scenario. + */ + if (etna_rgroup_is_uniform(src[0].rgroup)) { + struct etna_inst ins = { }; + ins.opcode = INST_OPCODE_MOV; + ins.dst = etna_native_to_dst(t0, INST_COMPS_X); + ins.src[2] = in; + emit_inst(c, &ins); + in = t0s; + } + + ins[0].opcode = INST_OPCODE_MAD; + ins[0].dst = etna_native_to_dst(t0, INST_COMPS_X | INST_COMPS_Z | INST_COMPS_W); + ins[0].src[0] = swizzle(in, SWIZZLE(X, X, X, X)); + ins[0].src[1] = swizzle(sincos[1], SWIZZLE(X, W, X, W)); /* 1/2*PI */ + ins[0].src[2] = swizzle(sincos[1], SWIZZLE(Y, W, Z, W)); /* 0.75, 0, 0.5, 0 */ + + ins[1].opcode = INST_OPCODE_FRC; + ins[1].dst = etna_native_to_dst(t0, INST_COMPS_X | INST_COMPS_Z); + ins[1].src[2] = swizzle(t0s, SWIZZLE(X, W, Z, W)); + + ins[2].opcode = INST_OPCODE_MAD; + ins[2].dst = etna_native_to_dst(t0, INST_COMPS_X | INST_COMPS_Z); + ins[2].src[0] = swizzle(t0s, SWIZZLE(X, W, Z, W)); + ins[2].src[1] = swizzle(sincos[0], SWIZZLE(X, X, X, X)); /* 2 */ + ins[2].src[2] = swizzle(sincos[0], SWIZZLE(Y, Y, Y, Y)); /* -1 */ + + unsigned mul_swiz, dp3_swiz; + if (inst->Instruction.Opcode == TGSI_OPCODE_SIN) { + mul_swiz = SWIZZLE(W, Z, W, W); + dp3_swiz = SWIZZLE(Z, Y, W, W); + } else { + mul_swiz = SWIZZLE(W, X, W, W); + dp3_swiz = SWIZZLE(X, Y, W, W); + } + + ins[3].opcode = INST_OPCODE_MUL; + ins[3].dst = etna_native_to_dst(t0, INST_COMPS_Y); + ins[3].src[0] = swizzle(t0s, mul_swiz); + ins[3].src[1] = absolute(ins[3].src[0]); + + ins[4].opcode = INST_OPCODE_DP3; + ins[4].dst = etna_native_to_dst(t0, INST_COMPS_X | INST_COMPS_Z); + ins[4].src[0] = swizzle(t0s, dp3_swiz); + ins[4].src[1] = swizzle(sincos[0], SWIZZLE(Z, W, W, W)); + + p = &ins[5]; + p->opcode = INST_OPCODE_MAD; + p->dst = etna_native_to_dst(t0, INST_COMPS_Y | INST_COMPS_W); + p->src[0] = swizzle(t0s, SWIZZLE(X, X, Z, Z)); + p->src[1] = absolute(p->src[0]); + p->src[2] = negate(p->src[0]); + + p++; + p->opcode = INST_OPCODE_MAD; + p->sat = inst->Instruction.Saturate; + p->dst = convert_dst(c, &inst->Dst[0]), + p->src[0] = swizzle(t0s, SWIZZLE(Y, W, Y, W)); + p->src[1] = alloc_imm_f32(c, 0.2225); + p->src[2] = swizzle(t0s, SWIZZLE(X, Z, X, Z)); + + for (int i = 0; &ins[i] <= p; i++) + emit_inst(c, &ins[i]); + } +} + +static void +trans_lg2(const struct instr_translater *t, struct etna_compile *c, + const struct tgsi_full_instruction *inst, struct etna_inst_src *src) +{ + if (c->specs->has_new_transcendentals) { + /* On newer chips alternative LOG instruction is implemented, + * which outputs an x and y component, which need to be multiplied to + * get the result. + */ + struct etna_native_reg temp = etna_compile_get_inner_temp(c); /* only using .xy */ + emit_inst(c, &(struct etna_inst) { + .opcode = INST_OPCODE_LOG, + .sat = 0, + .dst = etna_native_to_dst(temp, INST_COMPS_X | INST_COMPS_Y), + .src[2] = src[0], + .tex = { .amode=1 }, /* Unknown bit needs to be set */ + }); + emit_inst(c, &(struct etna_inst) { + .opcode = INST_OPCODE_MUL, + .sat = inst->Instruction.Saturate, + .dst = convert_dst(c, &inst->Dst[0]), + .src[0] = etna_native_to_src(temp, SWIZZLE(X, X, X, X)), + .src[1] = etna_native_to_src(temp, SWIZZLE(Y, Y, Y, Y)), + }); + } else { + emit_inst(c, &(struct etna_inst) { + .opcode = INST_OPCODE_LOG, + .sat = inst->Instruction.Saturate, + .dst = convert_dst(c, &inst->Dst[0]), + .src[2] = src[0], + }); + } +} + +static void +trans_sampler(const struct instr_translater *t, struct etna_compile *c, + const struct tgsi_full_instruction *inst, + struct etna_inst_src *src) +{ + /* There is no native support for GL texture rectangle coordinates, so + * we have to rescale from ([0, width], [0, height]) to ([0, 1], [0, 1]). */ + if (inst->Texture.Texture == TGSI_TEXTURE_RECT) { + uint32_t unit = inst->Src[1].Register.Index; + struct etna_inst ins[2] = { }; + struct etna_native_reg temp = etna_compile_get_inner_temp(c); + + ins[0].opcode = INST_OPCODE_MUL; + ins[0].dst = etna_native_to_dst(temp, INST_COMPS_X); + ins[0].src[0] = src[0]; + ins[0].src[1] = alloc_imm(c, ETNA_IMMEDIATE_TEXRECT_SCALE_X, unit); + + ins[1].opcode = INST_OPCODE_MUL; + ins[1].dst = etna_native_to_dst(temp, INST_COMPS_Y); + ins[1].src[0] = src[0]; + ins[1].src[1] = alloc_imm(c, ETNA_IMMEDIATE_TEXRECT_SCALE_Y, unit); + + emit_inst(c, &ins[0]); + emit_inst(c, &ins[1]); + + src[0] = etna_native_to_src(temp, INST_SWIZ_IDENTITY); /* temp.xyzw */ + } + + switch (inst->Instruction.Opcode) { + case TGSI_OPCODE_TEX: + emit_inst(c, &(struct etna_inst) { + .opcode = INST_OPCODE_TEXLD, + .sat = 0, + .dst = convert_dst(c, &inst->Dst[0]), + .tex = convert_tex(c, &inst->Src[1], &inst->Texture), + .src[0] = src[0], + }); + break; + + case TGSI_OPCODE_TXB: + emit_inst(c, &(struct etna_inst) { + .opcode = INST_OPCODE_TEXLDB, + .sat = 0, + .dst = convert_dst(c, &inst->Dst[0]), + .tex = convert_tex(c, &inst->Src[1], &inst->Texture), + .src[0] = src[0], + }); + break; + + case TGSI_OPCODE_TXL: + emit_inst(c, &(struct etna_inst) { + .opcode = INST_OPCODE_TEXLDL, + .sat = 0, + .dst = convert_dst(c, &inst->Dst[0]), + .tex = convert_tex(c, &inst->Src[1], &inst->Texture), + .src[0] = src[0], + }); + break; + + case TGSI_OPCODE_TXP: { /* divide src.xyz by src.w */ + struct etna_native_reg temp = etna_compile_get_inner_temp(c); + + emit_inst(c, &(struct etna_inst) { + .opcode = INST_OPCODE_RCP, + .sat = 0, + .dst = etna_native_to_dst(temp, INST_COMPS_W), /* tmp.w */ + .src[2] = swizzle(src[0], SWIZZLE(W, W, W, W)), + }); + emit_inst(c, &(struct etna_inst) { + .opcode = INST_OPCODE_MUL, + .sat = 0, + .dst = etna_native_to_dst(temp, INST_COMPS_X | INST_COMPS_Y | + INST_COMPS_Z), /* tmp.xyz */ + .src[0] = etna_native_to_src(temp, SWIZZLE(W, W, W, W)), + .src[1] = src[0], /* src.xyzw */ + }); + emit_inst(c, &(struct etna_inst) { + .opcode = INST_OPCODE_TEXLD, + .sat = 0, + .dst = convert_dst(c, &inst->Dst[0]), + .tex = convert_tex(c, &inst->Src[1], &inst->Texture), + .src[0] = etna_native_to_src(temp, INST_SWIZ_IDENTITY), /* tmp.xyzw */ + }); + } break; + + default: + BUG("Unhandled instruction %s", + tgsi_get_opcode_name(inst->Instruction.Opcode)); + assert(0); + break; + } +} + +static void +trans_dummy(const struct instr_translater *t, struct etna_compile *c, + const struct tgsi_full_instruction *inst, struct etna_inst_src *src) +{ + /* nothing to do */ +} + +static const struct instr_translater translaters[TGSI_OPCODE_LAST] = { +#define INSTR(n, f, ...) \ + [TGSI_OPCODE_##n] = {.fxn = (f), .tgsi_opc = TGSI_OPCODE_##n, ##__VA_ARGS__} + + INSTR(MOV, trans_instr, .opc = INST_OPCODE_MOV, .src = {2, -1, -1}), + INSTR(RCP, trans_instr, .opc = INST_OPCODE_RCP, .src = {2, -1, -1}), + INSTR(RSQ, trans_instr, .opc = INST_OPCODE_RSQ, .src = {2, -1, -1}), + INSTR(MUL, trans_instr, .opc = INST_OPCODE_MUL, .src = {0, 1, -1}), + INSTR(ADD, trans_instr, .opc = INST_OPCODE_ADD, .src = {0, 2, -1}), + INSTR(DP2, trans_instr, .opc = INST_OPCODE_DP2, .src = {0, 1, -1}), + INSTR(DP3, trans_instr, .opc = INST_OPCODE_DP3, .src = {0, 1, -1}), + INSTR(DP4, trans_instr, .opc = INST_OPCODE_DP4, .src = {0, 1, -1}), + INSTR(DST, trans_instr, .opc = INST_OPCODE_DST, .src = {0, 1, -1}), + INSTR(MAD, trans_instr, .opc = INST_OPCODE_MAD, .src = {0, 1, 2}), + INSTR(EX2, trans_instr, .opc = INST_OPCODE_EXP, .src = {2, -1, -1}), + INSTR(LG2, trans_lg2), + INSTR(SQRT, trans_instr, .opc = INST_OPCODE_SQRT, .src = {2, -1, -1}), + INSTR(FRC, trans_instr, .opc = INST_OPCODE_FRC, .src = {2, -1, -1}), + INSTR(CEIL, trans_instr, .opc = INST_OPCODE_CEIL, .src = {2, -1, -1}), + INSTR(FLR, trans_instr, .opc = INST_OPCODE_FLOOR, .src = {2, -1, -1}), + INSTR(CMP, trans_instr, .opc = INST_OPCODE_SELECT, .src = {0, 1, 2}, .cond = INST_CONDITION_LZ), + + INSTR(KILL, trans_instr, .opc = INST_OPCODE_TEXKILL), + INSTR(KILL_IF, trans_instr, .opc = INST_OPCODE_TEXKILL, .src = {0, -1, -1}, .cond = INST_CONDITION_LZ), + + INSTR(DDX, trans_deriv, .opc = INST_OPCODE_DSX), + INSTR(DDY, trans_deriv, .opc = INST_OPCODE_DSY), + + INSTR(IF, trans_if), + INSTR(ELSE, trans_else), + INSTR(ENDIF, trans_endif), + + INSTR(BGNLOOP, trans_loop_bgn), + INSTR(ENDLOOP, trans_loop_end), + INSTR(BRK, trans_brk), + INSTR(CONT, trans_cont), + + INSTR(MIN, trans_min_max, .opc = INST_OPCODE_SELECT, .cond = INST_CONDITION_GT), + INSTR(MAX, trans_min_max, .opc = INST_OPCODE_SELECT, .cond = INST_CONDITION_LT), + + INSTR(ARL, trans_arl), + INSTR(LRP, trans_lrp), + INSTR(LIT, trans_lit), + INSTR(SSG, trans_ssg), + + INSTR(SIN, trans_trig), + INSTR(COS, trans_trig), + + INSTR(SLT, trans_instr, .opc = INST_OPCODE_SET, .src = {0, 1, -1}, .cond = INST_CONDITION_LT), + INSTR(SGE, trans_instr, .opc = INST_OPCODE_SET, .src = {0, 1, -1}, .cond = INST_CONDITION_GE), + INSTR(SEQ, trans_instr, .opc = INST_OPCODE_SET, .src = {0, 1, -1}, .cond = INST_CONDITION_EQ), + INSTR(SGT, trans_instr, .opc = INST_OPCODE_SET, .src = {0, 1, -1}, .cond = INST_CONDITION_GT), + INSTR(SLE, trans_instr, .opc = INST_OPCODE_SET, .src = {0, 1, -1}, .cond = INST_CONDITION_LE), + INSTR(SNE, trans_instr, .opc = INST_OPCODE_SET, .src = {0, 1, -1}, .cond = INST_CONDITION_NE), + + INSTR(TEX, trans_sampler), + INSTR(TXB, trans_sampler), + INSTR(TXL, trans_sampler), + INSTR(TXP, trans_sampler), + + INSTR(NOP, trans_dummy), + INSTR(END, trans_dummy), +}; + +/* Pass -- compile instructions */ +static void +etna_compile_pass_generate_code(struct etna_compile *c) +{ + struct tgsi_parse_context ctx = { }; + unsigned status = tgsi_parse_init(&ctx, c->tokens); + assert(status == TGSI_PARSE_OK); + + int inst_idx = 0; + while (!tgsi_parse_end_of_tokens(&ctx)) { + const struct tgsi_full_instruction *inst = 0; + + /* No inner temps used yet for this instruction, clear counter */ + c->inner_temps = 0; + + tgsi_parse_token(&ctx); + + switch (ctx.FullToken.Token.Type) { + case TGSI_TOKEN_TYPE_INSTRUCTION: + /* iterate over operands */ + inst = &ctx.FullToken.FullInstruction; + if (c->dead_inst[inst_idx]) { /* skip dead instructions */ + inst_idx++; + continue; + } + + /* Lookup the TGSI information and generate the source arguments */ + struct etna_inst_src src[ETNA_NUM_SRC]; + memset(src, 0, sizeof(src)); + + const struct tgsi_opcode_info *tgsi = tgsi_get_opcode_info(inst->Instruction.Opcode); + + for (int i = 0; i < tgsi->num_src && i < ETNA_NUM_SRC; i++) { + const struct tgsi_full_src_register *reg = &inst->Src[i]; + const struct etna_native_reg *n = &etna_get_src_reg(c, reg->Register)->native; + + if (!n->valid || n->is_tex) + continue; + + src[i] = etna_create_src(reg, n); + } + + const unsigned opc = inst->Instruction.Opcode; + const struct instr_translater *t = &translaters[opc]; + + if (t->fxn) { + t->fxn(t, c, inst, src); + + inst_idx += 1; + } else { + BUG("Unhandled instruction %s", tgsi_get_opcode_name(opc)); + assert(0); + } + break; + } + } + tgsi_parse_free(&ctx); +} + +/* Look up register by semantic */ +static struct etna_reg_desc * +find_decl_by_semantic(struct etna_compile *c, uint file, uint name, uint index) +{ + for (int idx = 0; idx < c->file[file].reg_size; ++idx) { + struct etna_reg_desc *reg = &c->file[file].reg[idx]; + + if (reg->semantic.Name == name && reg->semantic.Index == index) + return reg; + } + + return NULL; /* not found */ +} + +/** Add ADD and MUL instruction to bring Z/W to 0..1 if -1..1 if needed: + * - this is a vertex shader + * - and this is an older GPU + */ +static void +etna_compile_add_z_div_if_needed(struct etna_compile *c) +{ + if (c->info.processor == PIPE_SHADER_VERTEX && c->specs->vs_need_z_div) { + /* find position out */ + struct etna_reg_desc *pos_reg = + find_decl_by_semantic(c, TGSI_FILE_OUTPUT, TGSI_SEMANTIC_POSITION, 0); + + if (pos_reg != NULL) { + /* + * ADD tX.__z_, tX.zzzz, void, tX.wwww + * MUL tX.__z_, tX.zzzz, 0.5, void + */ + emit_inst(c, &(struct etna_inst) { + .opcode = INST_OPCODE_ADD, + .dst = etna_native_to_dst(pos_reg->native, INST_COMPS_Z), + .src[0] = etna_native_to_src(pos_reg->native, SWIZZLE(Z, Z, Z, Z)), + .src[2] = etna_native_to_src(pos_reg->native, SWIZZLE(W, W, W, W)), + }); + emit_inst(c, &(struct etna_inst) { + .opcode = INST_OPCODE_MUL, + .dst = etna_native_to_dst(pos_reg->native, INST_COMPS_Z), + .src[0] = etna_native_to_src(pos_reg->native, SWIZZLE(Z, Z, Z, Z)), + .src[1] = alloc_imm_f32(c, 0.5f), + }); + } + } +} + +static void +etna_compile_frag_rb_swap(struct etna_compile *c) +{ + if (c->info.processor == PIPE_SHADER_FRAGMENT && c->key->frag_rb_swap) { + /* find color out */ + struct etna_reg_desc *color_reg = + find_decl_by_semantic(c, TGSI_FILE_OUTPUT, TGSI_SEMANTIC_COLOR, 0); + + emit_inst(c, &(struct etna_inst) { + .opcode = INST_OPCODE_MOV, + .dst = etna_native_to_dst(color_reg->native, INST_COMPS_X | INST_COMPS_Y | INST_COMPS_Z | INST_COMPS_W), + .src[2] = etna_native_to_src(color_reg->native, SWIZZLE(Z, Y, X, W)), + }); + } +} + +/** add a NOP to the shader if + * a) the shader is empty + * or + * b) there is a label at the end of the shader + */ +static void +etna_compile_add_nop_if_needed(struct etna_compile *c) +{ + bool label_at_last_inst = false; + + for (int idx = 0; idx < c->labels_count; ++idx) { + if (c->labels[idx].inst_idx == c->inst_ptr) + label_at_last_inst = true; + + } + + if (c->inst_ptr == 0 || label_at_last_inst) + emit_inst(c, &(struct etna_inst){.opcode = INST_OPCODE_NOP}); +} + +static void +assign_uniforms(struct etna_compile_file *file, unsigned base) +{ + for (int idx = 0; idx < file->reg_size; ++idx) { + file->reg[idx].native.valid = 1; + file->reg[idx].native.rgroup = INST_RGROUP_UNIFORM_0; + file->reg[idx].native.id = base + idx; + } +} + +/* Allocate CONST and IMM to native ETNA_RGROUP_UNIFORM(x). + * CONST must be consecutive as const buffers are supposed to be consecutive, + * and before IMM, as this is + * more convenient because is possible for the compilation process itself to + * generate extra + * immediates for constants such as pi, one, zero. + */ +static void +assign_constants_and_immediates(struct etna_compile *c) +{ + assign_uniforms(&c->file[TGSI_FILE_CONSTANT], 0); + /* immediates start after the constants */ + c->imm_base = c->file[TGSI_FILE_CONSTANT].reg_size * 4; + assign_uniforms(&c->file[TGSI_FILE_IMMEDIATE], c->imm_base / 4); + DBG_F(ETNA_DBG_COMPILER_MSGS, "imm base: %i size: %i", c->imm_base, + c->imm_size); +} + +/* Assign declared samplers to native texture units */ +static void +assign_texture_units(struct etna_compile *c) +{ + uint tex_base = 0; + + if (c->info.processor == PIPE_SHADER_VERTEX) + tex_base = c->specs->vertex_sampler_offset; + + for (int idx = 0; idx < c->file[TGSI_FILE_SAMPLER].reg_size; ++idx) { + c->file[TGSI_FILE_SAMPLER].reg[idx].native.valid = 1; + c->file[TGSI_FILE_SAMPLER].reg[idx].native.is_tex = 1; // overrides rgroup + c->file[TGSI_FILE_SAMPLER].reg[idx].native.id = tex_base + idx; + } +} + +/* Additional pass to fill in branch targets. This pass should be last + * as no instruction reordering or removing/addition can be done anymore + * once the branch targets are computed. + */ +static void +etna_compile_fill_in_labels(struct etna_compile *c) +{ + for (int idx = 0; idx < c->inst_ptr; ++idx) { + if (c->lbl_usage[idx] != -1) + etna_assemble_set_imm(&c->code[idx * 4], + c->labels[c->lbl_usage[idx]].inst_idx); + } +} + +/* compare two etna_native_reg structures, return true if equal */ +static bool +cmp_etna_native_reg(const struct etna_native_reg to, + const struct etna_native_reg from) +{ + return to.valid == from.valid && to.is_tex == from.is_tex && + to.rgroup == from.rgroup && to.id == from.id; +} + +/* go through all declarations and swap native registers *to* and *from* */ +static void +swap_native_registers(struct etna_compile *c, const struct etna_native_reg to, + const struct etna_native_reg from) +{ + if (cmp_etna_native_reg(from, to)) + return; /* Nothing to do */ + + for (int idx = 0; idx < c->total_decls; ++idx) { + if (cmp_etna_native_reg(c->decl[idx].native, from)) { + c->decl[idx].native = to; + } else if (cmp_etna_native_reg(c->decl[idx].native, to)) { + c->decl[idx].native = from; + } + } +} + +/* For PS we need to permute so that inputs are always in temporary 0..N-1. + * Semantic POS is always t0. If that semantic is not used, avoid t0. + */ +static void +permute_ps_inputs(struct etna_compile *c) +{ + /* Special inputs: + * gl_FragCoord VARYING_SLOT_POS TGSI_SEMANTIC_POSITION + * gl_PointCoord VARYING_SLOT_PNTC TGSI_SEMANTIC_PCOORD + */ + uint native_idx = 1; + + for (int idx = 0; idx < c->file[TGSI_FILE_INPUT].reg_size; ++idx) { + struct etna_reg_desc *reg = &c->file[TGSI_FILE_INPUT].reg[idx]; + uint input_id; + assert(reg->has_semantic); + + if (!reg->active || reg->semantic.Name == TGSI_SEMANTIC_POSITION) + continue; + + input_id = native_idx++; + swap_native_registers(c, etna_native_temp(input_id), + c->file[TGSI_FILE_INPUT].reg[idx].native); + } + + c->num_varyings = native_idx - 1; + + if (native_idx > c->next_free_native) + c->next_free_native = native_idx; +} + +/* fill in ps inputs into shader object */ +static void +fill_in_ps_inputs(struct etna_shader_variant *sobj, struct etna_compile *c) +{ + struct etna_shader_io_file *sf = &sobj->infile; + + sf->num_reg = 0; + + for (int idx = 0; idx < c->file[TGSI_FILE_INPUT].reg_size; ++idx) { + struct etna_reg_desc *reg = &c->file[TGSI_FILE_INPUT].reg[idx]; + + if (reg->native.id > 0) { + assert(sf->num_reg < ETNA_NUM_INPUTS); + sf->reg[sf->num_reg].reg = reg->native.id; + sf->reg[sf->num_reg].semantic = reg->semantic; + /* convert usage mask to number of components (*=wildcard) + * .r (0..1) -> 1 component + * .*g (2..3) -> 2 component + * .**b (4..7) -> 3 components + * .***a (8..15) -> 4 components + */ + sf->reg[sf->num_reg].num_components = util_last_bit(reg->usage_mask); + sf->num_reg++; + } + } + + assert(sf->num_reg == c->num_varyings); + sobj->input_count_unk8 = 31; /* XXX what is this */ +} + +/* fill in output mapping for ps into shader object */ +static void +fill_in_ps_outputs(struct etna_shader_variant *sobj, struct etna_compile *c) +{ + sobj->outfile.num_reg = 0; + + for (int idx = 0; idx < c->file[TGSI_FILE_OUTPUT].reg_size; ++idx) { + struct etna_reg_desc *reg = &c->file[TGSI_FILE_OUTPUT].reg[idx]; + + switch (reg->semantic.Name) { + case TGSI_SEMANTIC_COLOR: /* FRAG_RESULT_COLOR */ + sobj->ps_color_out_reg = reg->native.id; + break; + case TGSI_SEMANTIC_POSITION: /* FRAG_RESULT_DEPTH */ + sobj->ps_depth_out_reg = reg->native.id; /* =always native reg 0, only z component should be assigned */ + break; + default: + assert(0); /* only outputs supported are COLOR and POSITION at the moment */ + } + } +} + +/* fill in inputs for vs into shader object */ +static void +fill_in_vs_inputs(struct etna_shader_variant *sobj, struct etna_compile *c) +{ + struct etna_shader_io_file *sf = &sobj->infile; + + sf->num_reg = 0; + for (int idx = 0; idx < c->file[TGSI_FILE_INPUT].reg_size; ++idx) { + struct etna_reg_desc *reg = &c->file[TGSI_FILE_INPUT].reg[idx]; + assert(sf->num_reg < ETNA_NUM_INPUTS); + + if (!reg->native.valid) + continue; + + /* XXX exclude inputs with special semantics such as gl_frontFacing */ + sf->reg[sf->num_reg].reg = reg->native.id; + sf->reg[sf->num_reg].semantic = reg->semantic; + sf->reg[sf->num_reg].num_components = util_last_bit(reg->usage_mask); + sf->num_reg++; + } + + sobj->input_count_unk8 = (sf->num_reg + 19) / 16; /* XXX what is this */ +} + +/* build two-level output index [Semantic][Index] for fast linking */ +static void +build_output_index(struct etna_shader_variant *sobj) +{ + int total = 0; + int offset = 0; + + for (int name = 0; name < TGSI_SEMANTIC_COUNT; ++name) + total += sobj->output_count_per_semantic[name]; + + sobj->output_per_semantic_list = CALLOC(total, sizeof(struct etna_shader_inout *)); + + for (int name = 0; name < TGSI_SEMANTIC_COUNT; ++name) { + sobj->output_per_semantic[name] = &sobj->output_per_semantic_list[offset]; + offset += sobj->output_count_per_semantic[name]; + } + + for (int idx = 0; idx < sobj->outfile.num_reg; ++idx) { + sobj->output_per_semantic[sobj->outfile.reg[idx].semantic.Name] + [sobj->outfile.reg[idx].semantic.Index] = + &sobj->outfile.reg[idx]; + } +} + +/* fill in outputs for vs into shader object */ +static void +fill_in_vs_outputs(struct etna_shader_variant *sobj, struct etna_compile *c) +{ + struct etna_shader_io_file *sf = &sobj->outfile; + + sf->num_reg = 0; + for (int idx = 0; idx < c->file[TGSI_FILE_OUTPUT].reg_size; ++idx) { + struct etna_reg_desc *reg = &c->file[TGSI_FILE_OUTPUT].reg[idx]; + assert(sf->num_reg < ETNA_NUM_INPUTS); + + switch (reg->semantic.Name) { + case TGSI_SEMANTIC_POSITION: + sobj->vs_pos_out_reg = reg->native.id; + break; + case TGSI_SEMANTIC_PSIZE: + sobj->vs_pointsize_out_reg = reg->native.id; + break; + default: + sf->reg[sf->num_reg].reg = reg->native.id; + sf->reg[sf->num_reg].semantic = reg->semantic; + sf->reg[sf->num_reg].num_components = 4; // XXX reg->num_components; + sf->num_reg++; + sobj->output_count_per_semantic[reg->semantic.Name] = + MAX2(reg->semantic.Index + 1, + sobj->output_count_per_semantic[reg->semantic.Name]); + } + } + + /* build two-level index for linking */ + build_output_index(sobj); + + /* fill in "mystery meat" load balancing value. This value determines how + * work is scheduled between VS and PS + * in the unified shader architecture. More precisely, it is determined from + * the number of VS outputs, as well as chip-specific + * vertex output buffer size, vertex cache size, and the number of shader + * cores. + * + * XXX this is a conservative estimate, the "optimal" value is only known for + * sure at link time because some + * outputs may be unused and thus unmapped. Then again, in the general use + * case with GLSL the vertex and fragment + * shaders are linked already before submitting to Gallium, thus all outputs + * are used. + */ + int half_out = (c->file[TGSI_FILE_OUTPUT].reg_size + 1) / 2; + assert(half_out); + + uint32_t b = ((20480 / (c->specs->vertex_output_buffer_size - + 2 * half_out * c->specs->vertex_cache_size)) + + 9) / + 10; + uint32_t a = (b + 256 / (c->specs->shader_core_count * half_out)) / 2; + sobj->vs_load_balancing = VIVS_VS_LOAD_BALANCING_A(MIN2(a, 255)) | + VIVS_VS_LOAD_BALANCING_B(MIN2(b, 255)) | + VIVS_VS_LOAD_BALANCING_C(0x3f) | + VIVS_VS_LOAD_BALANCING_D(0x0f); +} + +static bool +etna_compile_check_limits(struct etna_compile *c) +{ + int max_uniforms = (c->info.processor == PIPE_SHADER_VERTEX) + ? c->specs->max_vs_uniforms + : c->specs->max_ps_uniforms; + /* round up number of uniforms, including immediates, in units of four */ + int num_uniforms = c->imm_base / 4 + (c->imm_size + 3) / 4; + + if (!c->specs->has_icache && c->inst_ptr > c->specs->max_instructions) { + DBG("Number of instructions (%d) exceeds maximum %d", c->inst_ptr, + c->specs->max_instructions); + return false; + } + + if (c->next_free_native > c->specs->max_registers) { + DBG("Number of registers (%d) exceeds maximum %d", c->next_free_native, + c->specs->max_registers); + return false; + } + + if (num_uniforms > max_uniforms) { + DBG("Number of uniforms (%d) exceeds maximum %d", num_uniforms, + max_uniforms); + return false; + } + + if (c->num_varyings > c->specs->max_varyings) { + DBG("Number of varyings (%d) exceeds maximum %d", c->num_varyings, + c->specs->max_varyings); + return false; + } + + if (c->imm_base > c->specs->num_constants) { + DBG("Number of constants (%d) exceeds maximum %d", c->imm_base, + c->specs->num_constants); + } + + return true; +} + +static void +copy_uniform_state_to_shader(struct etna_compile *c, struct etna_shader_variant *sobj) +{ + uint32_t count = c->imm_size; + struct etna_shader_uniform_info *uinfo = &sobj->uniforms; + + uinfo->const_count = c->imm_base; + uinfo->imm_count = count; + uinfo->imm_data = mem_dup(c->imm_data, count * sizeof(*c->imm_data)); + uinfo->imm_contents = mem_dup(c->imm_contents, count * sizeof(*c->imm_contents)); + + etna_set_shader_uniforms_dirty_flags(sobj); +} + +bool +etna_compile_shader(struct etna_shader_variant *v) +{ + /* Create scratch space that may be too large to fit on stack + */ + bool ret; + struct etna_compile *c; + + if (unlikely(!v)) + return false; + + const struct etna_specs *specs = v->shader->specs; + + struct tgsi_lowering_config lconfig = { + .lower_FLR = !specs->has_sign_floor_ceil, + .lower_CEIL = !specs->has_sign_floor_ceil, + .lower_POW = true, + .lower_EXP = true, + .lower_LOG = true, + .lower_DP2 = !specs->has_halti2_instructions, + .lower_TRUNC = true, + }; + + c = CALLOC_STRUCT(etna_compile); + if (!c) + return false; + + memset(&c->lbl_usage, -1, sizeof(c->lbl_usage)); + + const struct tgsi_token *tokens = v->shader->tokens; + + c->specs = specs; + c->key = &v->key; + c->tokens = tgsi_transform_lowering(&lconfig, tokens, &c->info); + c->free_tokens = !!c->tokens; + if (!c->tokens) { + /* no lowering */ + c->tokens = tokens; + } + + /* Build a map from gallium register to native registers for files + * CONST, SAMP, IMM, OUT, IN, TEMP. + * SAMP will map as-is for fragment shaders, there will be a +8 offset for + * vertex shaders. + */ + /* Pass one -- check register file declarations and immediates */ + etna_compile_parse_declarations(c); + + etna_allocate_decls(c); + + /* Pass two -- check usage of temporaries, inputs, outputs */ + etna_compile_pass_check_usage(c); + + assign_special_inputs(c); + + /* Assign native temp register to TEMPs */ + assign_temporaries_to_native(c, &c->file[TGSI_FILE_TEMPORARY]); + + /* optimize outputs */ + etna_compile_pass_optimize_outputs(c); + + /* XXX assign special inputs: gl_FrontFacing (VARYING_SLOT_FACE) + * this is part of RGROUP_INTERNAL + */ + + /* assign inputs: last usage of input should be <= first usage of temp */ + /* potential optimization case: + * if single MOV TEMP[y], IN[x] before which temp y is not used, and + * after which IN[x] + * is not read, temp[y] can be used as input register as-is + */ + /* sort temporaries by first use + * sort inputs by last usage + * iterate over inputs, temporaries + * if last usage of input <= first usage of temp: + * assign input to temp + * advance input, temporary pointer + * else + * advance temporary pointer + * + * potential problem: instruction with multiple inputs of which one is the + * temp and the other is the input; + * however, as the temp is not used before this, how would this make + * sense? uninitialized temporaries have an undefined + * value, so this would be ok + */ + assign_inouts_to_temporaries(c, TGSI_FILE_INPUT); + + /* assign outputs: first usage of output should be >= last usage of temp */ + /* potential optimization case: + * if single MOV OUT[x], TEMP[y] (with full write mask, or at least + * writing all components that are used in + * the shader) after which temp y is no longer used temp[y] can be + * used as output register as-is + * + * potential problem: instruction with multiple outputs of which one is the + * temp and the other is the output; + * however, as the temp is not used after this, how would this make + * sense? could just discard the output value + */ + /* sort temporaries by last use + * sort outputs by first usage + * iterate over outputs, temporaries + * if first usage of output >= last usage of temp: + * assign output to temp + * advance output, temporary pointer + * else + * advance temporary pointer + */ + assign_inouts_to_temporaries(c, TGSI_FILE_OUTPUT); + + assign_constants_and_immediates(c); + assign_texture_units(c); + + /* list declarations */ + for (int x = 0; x < c->total_decls; ++x) { + DBG_F(ETNA_DBG_COMPILER_MSGS, "%i: %s,%d active=%i first_use=%i " + "last_use=%i native=%i usage_mask=%x " + "has_semantic=%i", + x, tgsi_file_name(c->decl[x].file), c->decl[x].idx, + c->decl[x].active, c->decl[x].first_use, c->decl[x].last_use, + c->decl[x].native.valid ? c->decl[x].native.id : -1, + c->decl[x].usage_mask, c->decl[x].has_semantic); + if (c->decl[x].has_semantic) + DBG_F(ETNA_DBG_COMPILER_MSGS, " semantic_name=%s semantic_idx=%i", + tgsi_semantic_names[c->decl[x].semantic.Name], + c->decl[x].semantic.Index); + } + /* XXX for PS we need to permute so that inputs are always in temporary + * 0..N-1. + * There is no "switchboard" for varyings (AFAIK!). The output color, + * however, can be routed + * from an arbitrary temporary. + */ + if (c->info.processor == PIPE_SHADER_FRAGMENT) + permute_ps_inputs(c); + + + /* list declarations */ + for (int x = 0; x < c->total_decls; ++x) { + DBG_F(ETNA_DBG_COMPILER_MSGS, "%i: %s,%d active=%i first_use=%i " + "last_use=%i native=%i usage_mask=%x " + "has_semantic=%i", + x, tgsi_file_name(c->decl[x].file), c->decl[x].idx, + c->decl[x].active, c->decl[x].first_use, c->decl[x].last_use, + c->decl[x].native.valid ? c->decl[x].native.id : -1, + c->decl[x].usage_mask, c->decl[x].has_semantic); + if (c->decl[x].has_semantic) + DBG_F(ETNA_DBG_COMPILER_MSGS, " semantic_name=%s semantic_idx=%i", + tgsi_semantic_names[c->decl[x].semantic.Name], + c->decl[x].semantic.Index); + } + + /* pass 3: generate instructions */ + etna_compile_pass_generate_code(c); + etna_compile_add_z_div_if_needed(c); + etna_compile_frag_rb_swap(c); + etna_compile_add_nop_if_needed(c); + + ret = etna_compile_check_limits(c); + if (!ret) + goto out; + + etna_compile_fill_in_labels(c); + + /* fill in output structure */ + v->processor = c->info.processor; + v->code_size = c->inst_ptr * 4; + v->code = mem_dup(c->code, c->inst_ptr * 16); + v->num_loops = c->num_loops; + v->num_temps = c->next_free_native; + v->vs_pos_out_reg = -1; + v->vs_pointsize_out_reg = -1; + v->ps_color_out_reg = -1; + v->ps_depth_out_reg = -1; + v->needs_icache = c->inst_ptr > c->specs->max_instructions; + copy_uniform_state_to_shader(c, v); + + if (c->info.processor == PIPE_SHADER_VERTEX) { + fill_in_vs_inputs(v, c); + fill_in_vs_outputs(v, c); + } else if (c->info.processor == PIPE_SHADER_FRAGMENT) { + fill_in_ps_inputs(v, c); + fill_in_ps_outputs(v, c); + } + +out: + if (c->free_tokens) + FREE((void *)c->tokens); + + FREE(c->labels); + FREE(c); + + return ret; +} + +extern const char *tgsi_swizzle_names[]; +void +etna_dump_shader(const struct etna_shader_variant *shader) +{ + if (shader->processor == PIPE_SHADER_VERTEX) + printf("VERT\n"); + else + printf("FRAG\n"); + + + etna_disasm(shader->code, shader->code_size, PRINT_RAW); + + printf("num loops: %i\n", shader->num_loops); + printf("num temps: %i\n", shader->num_temps); + printf("num const: %i\n", shader->uniforms.const_count); + printf("immediates:\n"); + for (int idx = 0; idx < shader->uniforms.imm_count; ++idx) { + printf(" [%i].%s = %f (0x%08x)\n", + (idx + shader->uniforms.const_count) / 4, + tgsi_swizzle_names[idx % 4], + *((float *)&shader->uniforms.imm_data[idx]), + shader->uniforms.imm_data[idx]); + } + printf("inputs:\n"); + for (int idx = 0; idx < shader->infile.num_reg; ++idx) { + printf(" [%i] name=%s index=%i comps=%i\n", shader->infile.reg[idx].reg, + tgsi_semantic_names[shader->infile.reg[idx].semantic.Name], + shader->infile.reg[idx].semantic.Index, + shader->infile.reg[idx].num_components); + } + printf("outputs:\n"); + for (int idx = 0; idx < shader->outfile.num_reg; ++idx) { + printf(" [%i] name=%s index=%i comps=%i\n", shader->outfile.reg[idx].reg, + tgsi_semantic_names[shader->outfile.reg[idx].semantic.Name], + shader->outfile.reg[idx].semantic.Index, + shader->outfile.reg[idx].num_components); + } + printf("special:\n"); + if (shader->processor == PIPE_SHADER_VERTEX) { + printf(" vs_pos_out_reg=%i\n", shader->vs_pos_out_reg); + printf(" vs_pointsize_out_reg=%i\n", shader->vs_pointsize_out_reg); + printf(" vs_load_balancing=0x%08x\n", shader->vs_load_balancing); + } else { + printf(" ps_color_out_reg=%i\n", shader->ps_color_out_reg); + printf(" ps_depth_out_reg=%i\n", shader->ps_depth_out_reg); + } + printf(" input_count_unk8=0x%08x\n", shader->input_count_unk8); +} + +void +etna_destroy_shader(struct etna_shader_variant *shader) +{ + assert(shader); + + FREE(shader->code); + FREE(shader->uniforms.imm_data); + FREE(shader->uniforms.imm_contents); + FREE(shader->output_per_semantic_list); + FREE(shader); +} + +static const struct etna_shader_inout * +etna_shader_vs_lookup(const struct etna_shader_variant *sobj, + const struct etna_shader_inout *in) +{ + if (in->semantic.Index < sobj->output_count_per_semantic[in->semantic.Name]) + return sobj->output_per_semantic[in->semantic.Name][in->semantic.Index]; + + return NULL; +} + +bool +etna_link_shader(struct etna_shader_link_info *info, + const struct etna_shader_variant *vs, const struct etna_shader_variant *fs) +{ + /* For each fragment input we need to find the associated vertex shader + * output, which can be found by matching on semantic name and index. A + * binary search could be used because the vs outputs are sorted by their + * semantic index and grouped by semantic type by fill_in_vs_outputs. + */ + assert(fs->infile.num_reg < ETNA_NUM_INPUTS); + + for (int idx = 0; idx < fs->infile.num_reg; ++idx) { + const struct etna_shader_inout *fsio = &fs->infile.reg[idx]; + const struct etna_shader_inout *vsio = etna_shader_vs_lookup(vs, fsio); + struct etna_varying *varying; + bool interpolate_always = fsio->semantic.Name != TGSI_SEMANTIC_COLOR; + + assert(fsio->reg > 0 && fsio->reg <= ARRAY_SIZE(info->varyings)); + + if (fsio->reg > info->num_varyings) + info->num_varyings = fsio->reg; + + varying = &info->varyings[fsio->reg - 1]; + varying->num_components = fsio->num_components; + + if (!interpolate_always) /* colors affected by flat shading */ + varying->pa_attributes = 0x200; + else /* texture coord or other bypasses flat shading */ + varying->pa_attributes = 0x2f1; + + varying->use[0] = interpolate_always ? VARYING_COMPONENT_USE_POINTCOORD_X : VARYING_COMPONENT_USE_USED; + varying->use[1] = interpolate_always ? VARYING_COMPONENT_USE_POINTCOORD_Y : VARYING_COMPONENT_USE_USED; + varying->use[2] = VARYING_COMPONENT_USE_USED; + varying->use[3] = VARYING_COMPONENT_USE_USED; + + + /* point coord is position output from VS, so has no dedicated reg */ + if (fsio->semantic.Name == TGSI_SEMANTIC_PCOORD) + continue; + + if (vsio == NULL) + return true; /* not found -- link error */ + + varying->reg = vsio->reg; + } + + assert(info->num_varyings == fs->infile.num_reg); + + return false; +} diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_compiler.h b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_compiler.h new file mode 100644 index 000000000..f5c16890a --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_compiler.h @@ -0,0 +1,136 @@ +/* + * 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 "etnaviv_shader.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_variant { + uint32_t id; /* for debug */ + + uint processor; /* TGSI_PROCESSOR_... */ + uint32_t code_size; /* code size in uint32 words */ + uint32_t *code; + unsigned num_loops; + 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; + + /* shader is larger than GPU instruction limit, thus needs icache */ + bool needs_icache; + + /* shader variants form a linked list */ + struct etna_shader_variant *next; + + /* replicated here to avoid passing extra ptrs everywhere */ + struct etna_shader *shader; + struct etna_shader_key key; + + struct etna_bo *bo; /* cached code memory bo handle (for icache) */ +}; + +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]; +}; + +bool +etna_compile_shader(struct etna_shader_variant *shader); + +void +etna_dump_shader(const struct etna_shader_variant *shader); + +bool +etna_link_shader(struct etna_shader_link_info *info, + const struct etna_shader_variant *vs, const struct etna_shader_variant *fs); + +void +etna_destroy_shader(struct etna_shader_variant *shader); + +#endif diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_compiler_cmdline.c b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_compiler_cmdline.c new file mode 100644 index 000000000..bdaa78efe --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_compiler_cmdline.c @@ -0,0 +1,168 @@ +/* + * 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" +#include "etnaviv_shader.h" + +#include "util/u_memory.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(" --frag-rb-swap - swap rb in color output (FRAG)\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 s = {}; + struct etna_shader_key key = {}; + void *ptr; + size_t size; + + struct etna_shader_variant *v = CALLOC_STRUCT(etna_shader_variant); + if (!v) { + fprintf(stderr, "malloc failed!\n"); + return 1; + } + + 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], "--frag-rb-swap")) { + debug_printf(" %s", argv[n]); + key.frag_rb_swap = true; + 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); + + s.specs = &specs_gc2000; + s.tokens = toks; + + v->shader = &s; + v->key = key; + + if (!etna_compile_shader(v)) { + fprintf(stderr, "compiler failed!\n"); + return 1; + } + + etna_dump_shader(v); + etna_destroy_shader(v); +} diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_context.c b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_context.c new file mode 100644 index 000000000..65c20d2f8 --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_context.c @@ -0,0 +1,457 @@ +/* + * 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_query_hw.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_helpers.h" +#include "util/u_memory.h" +#include "util/u_prim.h" +#include "util/u_upload_mgr.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 (pctx->stream_uploader) + u_upload_destroy(pctx->stream_uploader); + + if (ctx->stream) + etna_cmd_stream_del(ctx->stream); + + slab_destroy_child(&ctx->transfer_pool); + + if (ctx->in_fence_fd != -1) + close(ctx->in_fence_fd); + + 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->index_size) { + 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 bool +etna_get_vs(struct etna_context *ctx, struct etna_shader_key key) +{ + const struct etna_shader_variant *old = ctx->shader.vs; + + ctx->shader.vs = etna_shader_variant(ctx->shader.bind_vs, key, &ctx->debug); + + if (!ctx->shader.vs) + return false; + + if (old != ctx->shader.vs) + ctx->dirty |= ETNA_DIRTY_SHADER; + + return true; +} + +static bool +etna_get_fs(struct etna_context *ctx, struct etna_shader_key key) +{ + const struct etna_shader_variant *old = ctx->shader.fs; + + ctx->shader.fs = etna_shader_variant(ctx->shader.bind_fs, key, &ctx->debug); + + if (!ctx->shader.fs) + return false; + + if (old != ctx->shader.fs) + ctx->dirty |= ETNA_DIRTY_SHADER; + + return true; +} + +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 (!info->count_from_stream_output && !info->indirect && + !info->primitive_restart && + !u_trim_pipe_prim(info->mode, (unsigned*)&info->count)) + return; + + 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_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; + } + + /* Upload a user index buffer. */ + unsigned index_offset = 0; + struct pipe_resource *indexbuf = NULL; + + if (info->index_size) { + indexbuf = info->has_user_indices ? NULL : info->index.resource; + if (info->has_user_indices && + !util_upload_index_buffer(pctx, info, &indexbuf, &index_offset)) { + BUG("Index buffer upload failed."); + return; + } + + ctx->index_buffer.FE_INDEX_STREAM_BASE_ADDR.bo = etna_resource(indexbuf)->bo; + ctx->index_buffer.FE_INDEX_STREAM_BASE_ADDR.offset = index_offset; + ctx->index_buffer.FE_INDEX_STREAM_BASE_ADDR.flags = ETNA_RELOC_READ; + ctx->index_buffer.FE_INDEX_STREAM_CONTROL = translate_index_size(info->index_size); + + if (!ctx->index_buffer.FE_INDEX_STREAM_BASE_ADDR.bo) { + BUG("Unsupported or no index buffer"); + return; + } + } else { + ctx->index_buffer.FE_INDEX_STREAM_BASE_ADDR.bo = 0; + ctx->index_buffer.FE_INDEX_STREAM_BASE_ADDR.offset = 0; + ctx->index_buffer.FE_INDEX_STREAM_BASE_ADDR.flags = 0; + ctx->index_buffer.FE_INDEX_STREAM_CONTROL = 0; + } + ctx->dirty |= ETNA_DIRTY_INDEX_BUFFER; + + struct etna_shader_key key = {}; + struct etna_surface *cbuf = etna_surface(pfb->cbufs[0]); + + if (cbuf) { + struct etna_resource *res = etna_resource(cbuf->base.texture); + + key.frag_rb_swap = !!translate_rs_format_rb_swap(res->base.format); + } + + if (!etna_get_vs(ctx, key) || !etna_get_fs(ctx, key)) { + BUG("compiled shaders are not okay"); + 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].is_user_buffer); + resource_read(ctx, ctx->vertex_buffer.vb[i].buffer.resource); + } + + /* Mark index buffer as being read */ + resource_read(ctx, indexbuf); + + /* 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); + + list_for_each_entry(struct etna_hw_query, hq, &ctx->active_hw_queries, node) + resource_written(ctx, hq->prsc); + + 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->index_size) + 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++; + if (info->index_size && indexbuf != info->index.resource) + pipe_resource_reference(&indexbuf, NULL); +} + +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); + int out_fence_fd = -1; + + list_for_each_entry(struct etna_hw_query, hq, &ctx->active_hw_queries, node) + etna_hw_query_suspend(hq, ctx); + + etna_cmd_stream_flush2(ctx->stream, ctx->in_fence_fd, + (flags & PIPE_FLUSH_FENCE_FD) ? &out_fence_fd : + NULL); + + list_for_each_entry(struct etna_hw_query, hq, &ctx->active_hw_queries, node) + etna_hw_query_resume(hq, ctx); + + if (fence) + *fence = etna_fence_create(pctx, out_fence_fd); +} + +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); + etna_set_state(stream, VIVS_PA_FLAGS, 0x00000000); /* blob sets ZCONVERT_BYPASS on GC3000, this messes up z for us */ + etna_set_state(stream, VIVS_RA_UNK00E0C, 0x00000000); + etna_set_state(stream, VIVS_PA_VIEWPORT_UNK00A80, 0x38a01404); + etna_set_state(stream, VIVS_PA_VIEWPORT_UNK00A84, fui(8192.0)); + etna_set_state(stream, VIVS_PA_ZFARCLIPPING, 0x00000000); + etna_set_state(stream, VIVS_PE_ALPHA_COLOR_EXT0, 0x00000000); + etna_set_state(stream, VIVS_PE_ALPHA_COLOR_EXT1, 0x00000000); + etna_set_state(stream, VIVS_RA_HDEPTH_CONTROL, 0x00007000); + etna_set_state(stream, VIVS_PE_STENCIL_CONFIG_EXT2, 0x00000000); + etna_set_state(stream, VIVS_GL_UNK03834, 0x00000000); + etna_set_state(stream, VIVS_GL_UNK03838, 0x00000000); + etna_set_state(stream, VIVS_GL_UNK03854, 0x00000000); + etna_set_state(stream, VIVS_PS_CONTROL_EXT, 0x00000000); + + /* Enable SINGLE_BUFFER for resolve, if supported */ + etna_set_state(stream, VIVS_RS_SINGLE_BUFFER, COND(ctx->specs.single_buffer, VIVS_RS_SINGLE_BUFFER_ENABLE)); + + 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)); +} + +static void +etna_set_debug_callback(struct pipe_context *pctx, + const struct pipe_debug_callback *cb) +{ + struct etna_context *ctx = etna_context(pctx); + + if (cb) + ctx->debug = *cb; + else + memset(&ctx->debug, 0, sizeof(ctx->debug)); +} + +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; + + if (ctx == NULL) + return NULL; + + pctx = &ctx->base; + pctx->priv = ctx; + pctx->screen = pscreen; + pctx->stream_uploader = u_upload_create_default(pctx); + if (!pctx->stream_uploader) + goto fail; + pctx->const_uploader = pctx->stream_uploader; + + 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; + + /* 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); + + ctx->in_fence_fd = -1; + + pctx->destroy = etna_context_destroy; + pctx->draw_vbo = etna_draw_vbo; + pctx->flush = etna_flush; + pctx->set_debug_callback = etna_set_debug_callback; + pctx->create_fence_fd = etna_create_fence_fd; + pctx->fence_server_sync = etna_fence_server_sync; + + /* 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); + list_inithead(&ctx->active_hw_queries); + + return pctx; + +fail: + pctx->destroy(pctx); + + return NULL; +} diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_context.h b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_context.h new file mode 100644 index 000000000..2903e0963 --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_context.h @@ -0,0 +1,203 @@ +/* + * 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_variant; + +struct etna_index_buffer { + 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; +}; + +struct etna_shader_state { + void *bind_vs, *bind_fs; + struct etna_shader_variant *vs, *fs; +}; + +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), + ETNA_DIRTY_DERIVE_TS = (1 << 19), + } 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; + struct etna_shader_state shader; + + /* 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; + uint64_t rs_operations; + } stats; + + struct pipe_debug_callback debug; + int in_fence_fd; + + /* list of active hardware queries */ + struct list_head active_hw_queries; +}; + +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 diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_debug.h b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_debug.h new file mode 100644 index 000000000..f47dffe59 --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_debug.h @@ -0,0 +1,80 @@ +/* + * 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 */ +#define ETNA_DBG_SHADERDB 0x800000 /* dump program compile information */ + +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 diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_disasm.c b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_disasm.c new file mode 100644 index 000000000..9ae99daf6 --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_disasm.c @@ -0,0 +1,613 @@ +/* + * 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), + OPC(DP2), +}; + +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); +} diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_disasm.h b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_disasm.h new file mode 100644 index 000000000..15df612bb --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_disasm.h @@ -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 diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_emit.c b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_emit.c new file mode 100644 index 000000000..5397aa33c --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_emit.c @@ -0,0 +1,834 @@ +/* + * 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 (cs->RS_KICKER_INPLACE && !cs->source_ts_valid) + /* Inplace resolve is no-op if TS is not configured */ + return; + + ctx->stats.rs_operations++; + + if (cs->RS_KICKER_INPLACE) { + etna_cmd_stream_reserve(stream, 6); + etna_coalesce_start(stream, &coalesce); + /* 0/1 */ EMIT_STATE(RS_EXTRA_CONFIG, cs->RS_EXTRA_CONFIG); + /* 2/3 */ EMIT_STATE(RS_SOURCE_STRIDE, cs->RS_SOURCE_STRIDE); + /* 4/5 */ EMIT_STATE(RS_KICKER_INPLACE, cs->RS_KICKER_INPLACE); + etna_coalesce_end(stream, &coalesce); + } else 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->shader.vs->uniforms.const_count * 2; + size += ctx->shader.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))) { + /*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 (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_SCISSOR | ETNA_DIRTY_FRAMEBUFFER | + ETNA_DIRTY_RASTERIZER | ETNA_DIRTY_VIEWPORT))) { + struct etna_rasterizer_state *rasterizer = etna_rasterizer_state(ctx->rasterizer); + + uint32_t clip_right = + MIN2(ctx->framebuffer.SE_CLIP_RIGHT, ctx->viewport.SE_CLIP_RIGHT); + uint32_t clip_bottom = + MIN2(ctx->framebuffer.SE_CLIP_BOTTOM, ctx->viewport.SE_CLIP_BOTTOM); + + if (rasterizer->scissor) { + clip_right = MIN2(ctx->scissor.SE_CLIP_RIGHT, clip_right); + clip_bottom = MIN2(ctx->scissor.SE_CLIP_BOTTOM, clip_bottom); + } + + /*00C20*/ EMIT_STATE_FIXP(SE_CLIP_RIGHT, clip_right); + /*00C24*/ EMIT_STATE_FIXP(SE_CLIP_BOTTOM, clip_bottom); + } + 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 (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 | ETNA_DIRTY_FRAMEBUFFER))) { + struct etna_blend_state *blend = etna_blend_state(ctx->blend); + /*014A4*/ EMIT_STATE(PE_LOGIC_OP, blend->PE_LOGIC_OP | ctx->framebuffer.PE_LOGIC_OP); + } + if (unlikely(dirty & (ETNA_DIRTY_BLEND))) { + struct etna_blend_state *blend = etna_blend_state(ctx->blend); + 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->shader.fs->uniforms_dirty_bits)) + etna_uniforms_write( + ctx, ctx->shader.vs, &ctx->constant_buffer[PIPE_SHADER_VERTEX], + ctx->shader_state.VS_UNIFORMS, &ctx->shader_state.vs_uniforms_size); + + if (dirty & (uniform_dirty_bits | ctx->shader.vs->uniforms_dirty_bits)) + etna_uniforms_write( + ctx, ctx->shader.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 */ + if (ctx->shader_state.VS_INST_ADDR.bo || ctx->shader_state.PS_INST_ADDR.bo) { + assert(ctx->specs.has_icache && ctx->specs.has_shader_range_registers); + /* Set icache (VS) */ + etna_set_state(stream, VIVS_VS_RANGE, (ctx->shader_state.vs_inst_mem_size / 4 - 1) << 16); + etna_set_state(stream, VIVS_VS_ICACHE_CONTROL, + VIVS_VS_ICACHE_CONTROL_ENABLE | + VIVS_VS_ICACHE_CONTROL_FLUSH_VS); + assert(ctx->shader_state.VS_INST_ADDR.bo); + etna_set_state_reloc(stream, VIVS_VS_INST_ADDR, &ctx->shader_state.VS_INST_ADDR); + + /* Set icache (PS) */ + etna_set_state(stream, VIVS_PS_RANGE, (ctx->shader_state.ps_inst_mem_size / 4 - 1) << 16); + etna_set_state(stream, VIVS_VS_ICACHE_CONTROL, + VIVS_VS_ICACHE_CONTROL_ENABLE | + VIVS_VS_ICACHE_CONTROL_FLUSH_PS); + assert(ctx->shader_state.PS_INST_ADDR.bo); + etna_set_state_reloc(stream, VIVS_PS_INST_ADDR, &ctx->shader_state.PS_INST_ADDR); + } else { + /* Upload shader directly, first flushing and disabling icache if + * supported on this hw */ + if (ctx->specs.has_icache) { + etna_set_state(stream, VIVS_VS_ICACHE_CONTROL, + VIVS_VS_ICACHE_CONTROL_FLUSH_PS | + VIVS_VS_ICACHE_CONTROL_FLUSH_VS); + } + if (ctx->specs.has_shader_range_registers) { + etna_set_state(stream, VIVS_VS_RANGE, (ctx->shader_state.vs_inst_mem_size / 4 - 1) << 16); + etna_set_state(stream, VIVS_PS_RANGE, ((ctx->shader_state.ps_inst_mem_size / 4 - 1 + 0x100) << 16) | + 0x100); + } + etna_set_state_multi(stream, ctx->specs.vs_offset, + ctx->shader_state.vs_inst_mem_size, + ctx->shader_state.VS_INST_MEM); + etna_set_state_multi(stream, ctx->specs.ps_offset, + ctx->shader_state.ps_inst_mem_size, + ctx->shader_state.PS_INST_MEM); + } + + if (ctx->specs.has_unified_uniforms) { + etna_set_state(stream, VIVS_VS_UNIFORM_BASE, 0); + etna_set_state(stream, VIVS_PS_UNIFORM_BASE, ctx->specs.max_vs_uniforms); + } + etna_set_state(stream, VIVS_VS_UNIFORM_CACHE, VIVS_VS_UNIFORM_CACHE_FLUSH); + etna_set_state_multi(stream, ctx->specs.vs_uniforms_offset, + ctx->shader_state.vs_uniforms_size, + ctx->shader_state.VS_UNIFORMS); + etna_set_state(stream, VIVS_VS_UNIFORM_CACHE, VIVS_VS_UNIFORM_CACHE_FLUSH | VIVS_VS_UNIFORM_CACHE_PS); + etna_set_state_multi(stream, ctx->specs.ps_uniforms_offset, + 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 { + /* ideally this cache would only be flushed if there are VS uniform changes */ + etna_set_state(stream, VIVS_VS_UNIFORM_CACHE, VIVS_VS_UNIFORM_CACHE_FLUSH); + etna_coalesce_start(stream, &coalesce); + for (int x = 0; x < ctx->shader.vs->uniforms.const_count; ++x) { + if (ctx->gpu3d.VS_UNIFORMS[x] != ctx->shader_state.VS_UNIFORMS[x]) { + etna_coalsence_emit(stream, &coalesce, ctx->specs.vs_uniforms_offset + x*4, ctx->shader_state.VS_UNIFORMS[x]); + ctx->gpu3d.VS_UNIFORMS[x] = ctx->shader_state.VS_UNIFORMS[x]; + } + } + etna_coalesce_end(stream, &coalesce); + + /* ideally this cache would only be flushed if there are PS uniform changes */ + etna_set_state(stream, VIVS_VS_UNIFORM_CACHE, VIVS_VS_UNIFORM_CACHE_FLUSH | VIVS_VS_UNIFORM_CACHE_PS); + etna_coalesce_start(stream, &coalesce); + for (int x = 0; x < ctx->shader.fs->uniforms.const_count; ++x) { + if (ctx->gpu3d.PS_UNIFORMS[x] != ctx->shader_state.PS_UNIFORMS[x]) { + etna_coalsence_emit(stream, &coalesce, ctx->specs.ps_uniforms_offset + x*4, 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; +} diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_emit.h b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_emit.h new file mode 100644 index 000000000..6a3c77286 --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_emit.h @@ -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 diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_fence.c b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_fence.c new file mode 100644 index 000000000..d82708eac --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_fence.c @@ -0,0 +1,126 @@ +/* + * 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 <libsync.h> + +#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; + int fence_fd; + uint32_t timestamp; +}; + +static void +etna_fence_destroy(struct pipe_fence_handle *fence) +{ + if (fence->fence_fd != -1) + close(fence->fence_fd); + FREE(fence); +} + +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)) + etna_fence_destroy(*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 (fence->fence_fd != -1) + return !sync_wait(fence->fence_fd, timeout / 1000000); + + if (etna_pipe_wait_ns(fence->screen->pipe, fence->timestamp, timeout)) + return false; + + return true; +} + +void +etna_create_fence_fd(struct pipe_context *pctx, + struct pipe_fence_handle **pfence, int fd) +{ + *pfence = etna_fence_create(pctx, dup(fd)); +} + +void +etna_fence_server_sync(struct pipe_context *pctx, + struct pipe_fence_handle *pfence) +{ + struct etna_context *ctx = etna_context(pctx); + + sync_accumulate("etnaviv", &ctx->in_fence_fd, pfence->fence_fd); +} + +static int +etna_screen_fence_get_fd(struct pipe_screen *pscreen, + struct pipe_fence_handle *pfence) +{ + return dup(pfence->fence_fd); +} + +struct pipe_fence_handle * +etna_fence_create(struct pipe_context *pctx, int fence_fd) +{ + 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); + fence->fence_fd = fence_fd; + + 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; + pscreen->fence_get_fd = etna_screen_fence_get_fd; +} diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_fence.h b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_fence.h new file mode 100644 index 000000000..cd68a428d --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_fence.h @@ -0,0 +1,51 @@ +/* + * 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" + +void +etna_create_fence_fd(struct pipe_context *pctx, + struct pipe_fence_handle **pfence, int fd); + +void +etna_fence_server_sync(struct pipe_context *pctx, + struct pipe_fence_handle *fence); + +int +etna_fence_get_fd(struct pipe_screen *pscreen, + struct pipe_fence_handle *pfence); + +struct pipe_fence_handle * +etna_fence_create(struct pipe_context *pctx, int fence_fd); + +void +etna_fence_screen_init(struct pipe_screen *pscreen); + +#endif diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_format.c b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_format.c new file mode 100644 index 000000000..a2e215b43 --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_format.c @@ -0,0 +1,322 @@ +/* + * 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; + const unsigned char tex_swiz[4]; +}; + +#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) + +#define SWIZ(x,y,z,w) { \ + PIPE_SWIZZLE_##x, \ + PIPE_SWIZZLE_##y, \ + PIPE_SWIZZLE_##z, \ + PIPE_SWIZZLE_##w \ +} + +/* vertex + texture */ +#define VT(pipe, vtxfmt, texfmt, texswiz, rsfmt) \ + [PIPE_FORMAT_##pipe] = { \ + .vtx = VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_##vtxfmt, \ + .tex = TEXTURE_FORMAT_##texfmt, \ + .rs = RS_FORMAT_##rsfmt, \ + .present = 1, \ + .tex_swiz = texswiz, \ + } + +/* texture-only */ +#define _T(pipe, fmt, swiz, rsfmt) \ + [PIPE_FORMAT_##pipe] = { \ + .vtx = ETNA_NO_MATCH, \ + .tex = TEXTURE_FORMAT_##fmt, \ + .rs = RS_FORMAT_##rsfmt, \ + .present = 1, \ + .tex_swiz = swiz, \ + } + +/* 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 */ + VT(R8_UNORM, UNSIGNED_BYTE, L8, SWIZ(X, 0, 0, 1), 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, SWIZ(X, Y, Z, W), NONE), + _T(L8_UNORM, L8, SWIZ(X, Y, Z, W), NONE), + _T(I8_UNORM, I8, SWIZ(X, Y, Z, W), 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, SWIZ(X, Y, Z, W), A4R4G4B4), + _T(B4G4R4X4_UNORM, X4R4G4B4, SWIZ(X, Y, Z, W), X4R4G4B4), + + _T(L8A8_UNORM, A8L8, SWIZ(X, Y, Z, W), NONE), + + _T(Z16_UNORM, D16, SWIZ(X, Y, Z, W), A4R4G4B4), + _T(B5G6R5_UNORM, R5G6B5, SWIZ(X, Y, Z, W), R5G6B5), + _T(B5G5R5A1_UNORM, A1R5G5B5, SWIZ(X, Y, Z, W), A1R5G5B5), + _T(B5G5R5X1_UNORM, X1R5G5B5, SWIZ(X, Y, Z, W), X1R5G5B5), + + VT(R8G8_UNORM, UNSIGNED_BYTE, EXT_G8R8 | EXT_FORMAT, SWIZ(X, Y, 0, 1), 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), + + VT(R8G8B8A8_UNORM, UNSIGNED_BYTE, A8B8G8R8, SWIZ(X, Y, Z, W), A8B8G8R8), + V_(R8G8B8A8_SNORM, BYTE, A8B8G8R8), + _T(R8G8B8X8_UNORM, X8B8G8R8, SWIZ(X, Y, Z, W), X8B8G8R8), + V_(R8G8B8A8_UINT, UNSIGNED_BYTE, A8B8G8R8), + V_(R8G8B8A8_SINT, BYTE, A8B8G8R8), + V_(R8G8B8A8_USCALED, UNSIGNED_BYTE, A8B8G8R8), + V_(R8G8B8A8_SSCALED, BYTE, A8B8G8R8), + + _T(B8G8R8A8_UNORM, A8R8G8B8, SWIZ(X, Y, Z, W), A8R8G8B8), + _T(B8G8R8X8_UNORM, X8R8G8B8, SWIZ(X, Y, Z, W), 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, SWIZ(X, Y, Z, W), A8R8G8B8), + _T(S8_UINT_Z24_UNORM, D24S8, SWIZ(X, Y, Z, W), 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, SWIZ(X, Y, Z, W), NONE), + + _T(DXT1_RGB, DXT1, SWIZ(X, Y, Z, W), NONE), + _T(DXT1_RGBA, DXT1, SWIZ(X, Y, Z, W), NONE), + _T(DXT3_RGBA, DXT2_DXT3, SWIZ(X, Y, Z, W), NONE), + _T(DXT5_RGBA, DXT4_DXT5, SWIZ(X, Y, Z, W), NONE), + + _T(ETC2_RGB8, EXT_NONE | EXT_FORMAT, SWIZ(X, Y, Z, W), NONE), /* Extd. format NONE doubles as ETC2_RGB8 */ + _T(ETC2_SRGB8, EXT_NONE | EXT_FORMAT, SWIZ(X, Y, Z, W), NONE), + _T(ETC2_RGB8A1, EXT_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 | EXT_FORMAT, SWIZ(X, Y, Z, W), NONE), + _T(ETC2_SRGB8A1, EXT_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 | EXT_FORMAT, SWIZ(X, Y, Z, W), NONE), + _T(ETC2_RGBA8, EXT_RGBA8_ETC2_EAC | EXT_FORMAT, SWIZ(X, Y, Z, W), NONE), + _T(ETC2_SRGBA8, EXT_RGBA8_ETC2_EAC | EXT_FORMAT, SWIZ(X, Y, Z, W), NONE), + _T(ETC2_R11_UNORM, EXT_R11_EAC | EXT_FORMAT, SWIZ(X, Y, Z, W), NONE), + _T(ETC2_R11_SNORM, EXT_SIGNED_R11_EAC | EXT_FORMAT, SWIZ(X, Y, Z, W), NONE), + _T(ETC2_RG11_UNORM, EXT_RG11_EAC | EXT_FORMAT, SWIZ(X, Y, Z, W), NONE), + _T(ETC2_RG11_SNORM, EXT_SIGNED_RG11_EAC | EXT_FORMAT, SWIZ(X, Y, Z, W), NONE), + + /* YUV */ + _T(YUYV, YUY2, SWIZ(X, Y, Z, W), YUY2), + _T(UYVY, UYVY, SWIZ(X, Y, Z, W), NONE), +}; + +uint32_t +translate_texture_format(enum pipe_format fmt) +{ + if (!formats[fmt].present) + return ETNA_NO_MATCH; + + return formats[fmt].tex; +} + +bool +texture_format_needs_swiz(enum pipe_format fmt) +{ + static const unsigned char def[4] = SWIZ(X, Y, Z, W); + bool swiz = false; + + if (formats[fmt].present) + swiz = !memcmp(def, formats[fmt].tex_swiz, sizeof(formats[fmt].tex_swiz)); + + return swiz; +} + +uint32_t +get_texture_swiz(enum pipe_format fmt, unsigned swizzle_r, + unsigned swizzle_g, unsigned swizzle_b, unsigned swizzle_a) +{ + unsigned char swiz[4] = { + swizzle_r, swizzle_g, swizzle_b, swizzle_a, + }, rswiz[4]; + + assert(formats[fmt].present); + util_format_compose_swizzles(formats[fmt].tex_swiz, swiz, rswiz); + + /* PIPE_SWIZZLE_ maps 1:1 to TEXTURE_SWIZZLE_ */ + STATIC_ASSERT(PIPE_SWIZZLE_X == TEXTURE_SWIZZLE_RED); + STATIC_ASSERT(PIPE_SWIZZLE_Y == TEXTURE_SWIZZLE_GREEN); + STATIC_ASSERT(PIPE_SWIZZLE_Z == TEXTURE_SWIZZLE_BLUE); + STATIC_ASSERT(PIPE_SWIZZLE_W == TEXTURE_SWIZZLE_ALPHA); + STATIC_ASSERT(PIPE_SWIZZLE_0 == TEXTURE_SWIZZLE_ZERO); + STATIC_ASSERT(PIPE_SWIZZLE_1 == TEXTURE_SWIZZLE_ONE); + + return VIVS_TE_SAMPLER_CONFIG1_SWIZZLE_R(rswiz[0]) | + VIVS_TE_SAMPLER_CONFIG1_SWIZZLE_G(rswiz[1]) | + VIVS_TE_SAMPLER_CONFIG1_SWIZZLE_B(rswiz[2]) | + VIVS_TE_SAMPLER_CONFIG1_SWIZZLE_A(rswiz[3]); +} + +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; +} diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_format.h b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_format.h new file mode 100644 index 000000000..543e30965 --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_format.h @@ -0,0 +1,55 @@ +/* + * 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) +#define EXT_FORMAT (1 << 31) + +uint32_t +translate_texture_format(enum pipe_format fmt); + +bool +texture_format_needs_swiz(enum pipe_format fmt); + +uint32_t +get_texture_swiz(enum pipe_format fmt, unsigned swizzle_r, + unsigned swizzle_g, unsigned swizzle_b, unsigned swizzle_a); + +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_ */ diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_internal.h b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_internal.h new file mode 100644 index 000000000..896bbf565 --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_internal.h @@ -0,0 +1,294 @@ +/* + * 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) + +/* These demarcate the margin (fixp16) between the computed sizes and the + value sent to the chip. These have been set to the numbers used by the + Vivante driver on gc2000. They used to be -1 for scissor right and bottom. I + am not sure whether older hardware was relying on these or they were just a + guess. But if so, these need to be moved to the _specs structure. +*/ +#define ETNA_SE_SCISSOR_MARGIN_RIGHT (0x1119) +#define ETNA_SE_SCISSOR_MARGIN_BOTTOM (0x1111) +#define ETNA_SE_CLIP_MARGIN_RIGHT (0xffff) +#define ETNA_SE_CLIP_MARGIN_BOTTOM (0xffff) + +/* 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; + /* has the new sin/cos/log functions */ + unsigned has_new_transcendentals : 1; + /* has the new dp2/dpX_norm instructions, among others */ + unsigned has_halti2_instructions : 1; + /* supports single-buffer rendering with multiple pixel pipes */ + unsigned single_buffer : 1; + /* has unified uniforms memory */ + unsigned has_unified_uniforms : 1; + /* can load shader instructions from memory */ + unsigned has_icache : 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 shader uniforms address*/ + uint32_t vs_uniforms_offset; + /* pixel shader uniforms address*/ + uint32_t ps_uniforms_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 { + float color[4]; + 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; + uint32_t SE_CLIP_RIGHT; + uint32_t SE_CLIP_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 SE_CLIP_RIGHT; + uint32_t SE_CLIP_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 SE_CLIP_RIGHT; + uint32_t SE_CLIP_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; + uint32_t PE_LOGIC_OP; + 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]; + struct etna_reloc PS_INST_ADDR; + struct etna_reloc VS_INST_ADDR; +}; + +/* 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 diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_query.c b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_query.c new file mode 100644 index 000000000..9e897cd75 --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_query.c @@ -0,0 +1,133 @@ +/* + * 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 "util/u_inlines.h" + +#include "etnaviv_context.h" +#include "etnaviv_query.h" +#include "etnaviv_query_hw.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); + if (!q) + q = etna_hw_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); + boolean ret; + + if (q->active) + return false; + + ret = q->funcs->begin_query(etna_context(pctx), q); + q->active = ret; + + return ret; +} + +static bool +etna_end_query(struct pipe_context *pctx, struct pipe_query *pq) +{ + struct etna_query *q = etna_query(pq); + + if (!q->active) + return false; + + q->funcs->end_query(etna_context(pctx), q); + q->active = false; + + 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); + + if (q->active) + return false; + + util_query_clear_result(result, q->type); + + 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) +{ + int nr_sw_queries = etna_sw_get_driver_query_info(pscreen, 0, NULL); + + if (!info) + return nr_sw_queries; + + return etna_sw_get_driver_query_info(pscreen, index, info); +} + +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; +} diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_query.h b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_query.h new file mode 100644 index 000000000..892726605 --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_query.h @@ -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; + unsigned type; +}; + +static inline struct etna_query * +etna_query(struct pipe_query *pq) +{ + return (struct etna_query *)pq; +} + +#define ETNA_SW_QUERY_BASE (PIPE_QUERY_DRIVER_SPECIFIC + 0) + +void +etna_query_screen_init(struct pipe_screen *pscreen); + +void +etna_query_context_init(struct pipe_context *pctx); + +#endif diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_query_sw.c b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_query_sw.c new file mode 100644 index 000000000..dd9bac385 --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_query_sw.c @@ -0,0 +1,140 @@ +/* + * 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_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, unsigned type) +{ + switch (type) { + case PIPE_QUERY_PRIMITIVES_EMITTED: + return ctx->stats.prims_emitted; + case ETNA_QUERY_DRAW_CALLS: + return ctx->stats.draw_calls; + case ETNA_QUERY_RS_OPERATIONS: + return ctx->stats.rs_operations; + } + + 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); + + 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); + + 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); + + 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: + case ETNA_QUERY_RS_OPERATIONS: + 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; +} + +int +etna_sw_get_driver_query_info(struct pipe_screen *pscreen, unsigned index, + struct pipe_driver_query_info *info) +{ + static const struct pipe_driver_query_info list[] = { + {"prims-emitted", PIPE_QUERY_PRIMITIVES_EMITTED, { 0 }}, + {"draw-calls", ETNA_QUERY_DRAW_CALLS, { 0 }}, + {"rs-operations", ETNA_QUERY_RS_OPERATIONS, { 0 }}, + }; + + if (!info) + return ARRAY_SIZE(list); + + if (index >= ARRAY_SIZE(list)) + return 0; + + *info = list[index]; + + return 1; +} diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_query_sw.h b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_query_sw.h new file mode 100644 index 000000000..932114709 --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_query_sw.h @@ -0,0 +1,54 @@ +/* + * 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" + +#define ETNA_QUERY_DRAW_CALLS (ETNA_SW_QUERY_BASE + 0) +#define ETNA_QUERY_RS_OPERATIONS (ETNA_SW_QUERY_BASE + 1) + +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); + +int +etna_sw_get_driver_query_info(struct pipe_screen *pscreen, unsigned index, + struct pipe_driver_query_info *info); + +#endif diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_rasterizer.c b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_rasterizer.c new file mode 100644 index 000000000..c8627b1a9 --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_rasterizer.c @@ -0,0 +1,78 @@ +/* + * 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); + + 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 = (so->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->flatshade_first, VIVS_PA_SYSTEM_MODE_PROVOKING_VERTEX_LAST) | + COND(so->half_pixel_center, VIVS_PA_SYSTEM_MODE_HALF_PIXEL_CENTER); + + /* 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; +} diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_rasterizer.h b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_rasterizer.h new file mode 100644 index 000000000..d715dd08d --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_rasterizer.h @@ -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 diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_resource.c b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_resource.c new file mode 100644 index 000000000..d6cccd2db --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_resource.c @@ -0,0 +1,636 @@ +/* + * 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" + +#include <drm_fourcc.h> + +#ifndef DRM_FORMAT_MOD_INVALID +#define DRM_FORMAT_MOD_INVALID ((1ULL<<56) - 1) +#endif + +static enum etna_surface_layout modifier_to_layout(uint64_t modifier) +{ + switch (modifier) { + case DRM_FORMAT_MOD_VIVANTE_TILED: + return ETNA_LAYOUT_TILED; + case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED: + return ETNA_LAYOUT_SUPER_TILED; + case DRM_FORMAT_MOD_VIVANTE_SPLIT_TILED: + return ETNA_LAYOUT_MULTI_TILED; + case DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED: + return ETNA_LAYOUT_MULTI_SUPERTILED; + case DRM_FORMAT_MOD_LINEAR: + default: + return ETNA_LAYOUT_LINEAR; + } +} + +static uint64_t layout_to_modifier(enum etna_surface_layout layout) +{ + switch (layout) { + case ETNA_LAYOUT_TILED: + return DRM_FORMAT_MOD_VIVANTE_TILED; + case ETNA_LAYOUT_SUPER_TILED: + return DRM_FORMAT_MOD_VIVANTE_SUPER_TILED; + case ETNA_LAYOUT_MULTI_TILED: + return DRM_FORMAT_MOD_VIVANTE_SPLIT_TILED; + case ETNA_LAYOUT_MULTI_SUPERTILED: + return DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED; + case ETNA_LAYOUT_LINEAR: + return DRM_FORMAT_MOD_LINEAR; + default: + return DRM_FORMAT_MOD_INVALID; + } +} + +/* 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 * screen->specs.pixel_pipes); + 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, + uint64_t modifier, const struct pipe_resource *templat) +{ + struct etna_screen *screen = etna_screen(pscreen); + struct etna_resource *rsc; + 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->target != PIPE_BUFFER) + etna_adjust_rs_align(screen->specs.pixel_pipes, NULL, &paddingY); + + if (templat->bind & PIPE_BIND_SCANOUT) { + struct pipe_resource scanout_templat = *templat; + struct renderonly_scanout *scanout; + struct winsys_handle handle; + + /* pad scanout buffer size to be compatible with the RS */ + if (modifier == DRM_FORMAT_MOD_LINEAR) + etna_adjust_rs_align(screen->specs.pixel_pipes, &paddingX, &paddingY); + + scanout_templat.width0 = align(scanout_templat.width0, paddingX); + scanout_templat.height0 = align(scanout_templat.height0, paddingY); + + scanout = renderonly_scanout_for_resource(&scanout_templat, + screen->ro, &handle); + if (!scanout) + return NULL; + + assert(handle.type == DRM_API_HANDLE_TYPE_FD); + handle.modifier = modifier; + rsc = etna_resource(pscreen->resource_from_handle(pscreen, templat, + &handle, + PIPE_HANDLE_USAGE_WRITE)); + close(handle.handle); + if (!rsc) + return NULL; + + rsc->scanout = scanout; + + return &rsc->base; + } + + 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); + + uint32_t flags = DRM_ETNA_GEM_CACHE_WC; + if (templat->bind & PIPE_BIND_VERTEX_BUFFER) + flags |= DRM_ETNA_GEM_FORCE_MMU; + struct etna_bo *bo = etna_bo_new(screen->dev, size, flags); + if (unlikely(bo == NULL)) { + BUG("Problem allocating video memory for resource"); + goto free_rsc; + } + + rsc->bo = bo; + rsc->ts_bo = 0; /* TS is only created when first bound to surface */ + + if (DBG_ENABLED(ETNA_DBG_ZERO)) { + void *map = etna_bo_map(bo); + memset(map, 0, size); + } + + return &rsc->base; + +free_rsc: + FREE(rsc); + return NULL; +} + +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 texture cannot be linear. + * there is a capability 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 = false; + bool want_supertiled = screen->specs.can_supertile; + + /* When this GPU supports single-buffer rendering, don't ever enable + * multi-tiling. This replicates the blob behavior on GC3000. + */ + if (!screen->specs.single_buffer) + want_multitiled = screen->specs.pixel_pipes > 1; + + /* 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; + + /* modifier is only used for scanout surfaces, so safe to use LINEAR here */ + return etna_resource_alloc(pscreen, layout, DRM_FORMAT_MOD_LINEAR, templat); +} + +enum modifier_priority { + MODIFIER_PRIORITY_INVALID = 0, + MODIFIER_PRIORITY_LINEAR, + MODIFIER_PRIORITY_SPLIT_TILED, + MODIFIER_PRIORITY_SPLIT_SUPER_TILED, + MODIFIER_PRIORITY_TILED, + MODIFIER_PRIORITY_SUPER_TILED, +}; + +const uint64_t priority_to_modifier[] = { + [MODIFIER_PRIORITY_INVALID] = DRM_FORMAT_MOD_INVALID, + [MODIFIER_PRIORITY_LINEAR] = DRM_FORMAT_MOD_LINEAR, + [MODIFIER_PRIORITY_SPLIT_TILED] = DRM_FORMAT_MOD_VIVANTE_SPLIT_TILED, + [MODIFIER_PRIORITY_SPLIT_SUPER_TILED] = DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED, + [MODIFIER_PRIORITY_TILED] = DRM_FORMAT_MOD_VIVANTE_TILED, + [MODIFIER_PRIORITY_SUPER_TILED] = DRM_FORMAT_MOD_VIVANTE_SUPER_TILED, +}; + +static uint64_t +select_best_modifier(const struct etna_screen * screen, + const uint64_t *modifiers, const unsigned count) +{ + enum modifier_priority prio = MODIFIER_PRIORITY_INVALID; + + for (int i = 0; i < count; i++) { + switch (modifiers[i]) { + case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED: + if ((screen->specs.pixel_pipes > 1 && !screen->specs.single_buffer) || + !screen->specs.can_supertile) + break; + prio = MAX2(prio, MODIFIER_PRIORITY_SUPER_TILED); + break; + case DRM_FORMAT_MOD_VIVANTE_TILED: + if (screen->specs.pixel_pipes > 1 && !screen->specs.single_buffer) + break; + prio = MAX2(prio, MODIFIER_PRIORITY_TILED); + break; + case DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED: + if ((screen->specs.pixel_pipes < 2) || !screen->specs.can_supertile) + break; + prio = MAX2(prio, MODIFIER_PRIORITY_SPLIT_SUPER_TILED); + break; + case DRM_FORMAT_MOD_VIVANTE_SPLIT_TILED: + if (screen->specs.pixel_pipes < 2) + break; + prio = MAX2(prio, MODIFIER_PRIORITY_SPLIT_TILED); + break; + case DRM_FORMAT_MOD_LINEAR: + prio = MAX2(prio, MODIFIER_PRIORITY_LINEAR); + break; + case DRM_FORMAT_MOD_INVALID: + default: + break; + } + } + + return priority_to_modifier[prio]; +} + +static struct pipe_resource * +etna_resource_create_modifiers(struct pipe_screen *pscreen, + const struct pipe_resource *templat, + const uint64_t *modifiers, int count) +{ + struct etna_screen *screen = etna_screen(pscreen); + struct pipe_resource tmpl = *templat; + uint64_t modifier = select_best_modifier(screen, modifiers, count); + + if (modifier == DRM_FORMAT_MOD_INVALID) + return NULL; + + /* + * We currently assume that all buffers allocated through this interface + * should be scanout enabled. + */ + tmpl.bind |= PIPE_BIND_SCANOUT; + + return etna_resource_alloc(pscreen, modifier_to_layout(modifier), + modifier, &tmpl); +} + +static void +etna_resource_changed(struct pipe_screen *pscreen, struct pipe_resource *prsc) +{ + struct etna_resource *res = etna_resource(prsc); + + if (res->external) + etna_resource(res->external)->seqno++; + else + res->seqno++; +} + +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, etna_screen(pscreen)->ro); + + list_delinit(&rsc->list); + + pipe_resource_reference(&rsc->texture, NULL); + pipe_resource_reference(&rsc->external, 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; + struct etna_resource_level *level; + struct pipe_resource *prsc; + 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); + + rsc = CALLOC_STRUCT(etna_resource); + if (!rsc) + return NULL; + + level = &rsc->levels[0]; + prsc = &rsc->base; + + *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; + + rsc->seqno = 1; + rsc->layout = modifier_to_layout(handle->modifier); + rsc->halign = TEXTURE_HALIGN_FOUR; + + + level->width = tmpl->width0; + level->height = tmpl->height0; + + /* Determine padding of the imported resource. */ + unsigned paddingX = 0, paddingY = 0; + etna_layout_multiple(rsc->layout, screen->specs.pixel_pipes, + VIV_FEATURE(screen, chipMinorFeatures1, TEXTURE_HALIGN), + &paddingX, &paddingY, &rsc->halign); + + etna_adjust_rs_align(screen->specs.pixel_pipes, NULL, &paddingY); + level->padded_width = align(level->width, paddingX); + level->padded_height = align(level->height, paddingY); + + level->layer_stride = level->stride * util_format_get_nblocksy(prsc->format, + level->padded_height); + + /* 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 (rsc->layout == ETNA_LAYOUT_LINEAR) { + /* + * Both sampler and pixel pipes can't handle linear, create a compatible + * base resource, where we can attach the imported buffer as an external + * resource. + */ + struct pipe_resource tiled_templat = *tmpl; + + /* + * Remove BIND_SCANOUT to avoid recursion, as etna_resource_create uses + * this function to import the scanout buffer and get a tiled resource. + */ + tiled_templat.bind &= ~PIPE_BIND_SCANOUT; + + ptiled = etna_resource_create(pscreen, &tiled_templat); + if (!ptiled) + goto fail; + + etna_resource(ptiled)->external = prsc; + + 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); + /* Scanout is always attached to the base resource */ + struct renderonly_scanout *scanout = rsc->scanout; + + /* + * External resources are preferred, so a import->export chain of + * render/sampler incompatible buffers yield the same handle. + */ + if (rsc->external) + rsc = etna_resource(rsc->external); + + handle->stride = rsc->levels[0].stride; + handle->modifier = layout_to_modifier(rsc->layout); + + if (handle->type == DRM_API_HANDLE_TYPE_SHARED) { + return etna_bo_get_name(rsc->bo, &handle->handle) == 0; + } else if (handle->type == DRM_API_HANDLE_TYPE_KMS) { + if (renderonly_get_handle(scanout, handle)) { + return TRUE; + } else { + handle->handle = etna_bo_handle(rsc->bo); + return TRUE; + } + } else if (handle->type == DRM_API_HANDLE_TYPE_FD) { + handle->handle = etna_bo_dmabuf(rsc->bo); + return TRUE; + } else { + return FALSE; + } +} + +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_screen_init(struct pipe_screen *pscreen) +{ + pscreen->can_create_resource = etna_screen_can_create_resource; + pscreen->resource_create = etna_resource_create; + pscreen->resource_create_with_modifiers = etna_resource_create_modifiers; + pscreen->resource_from_handle = etna_resource_from_handle; + pscreen->resource_get_handle = etna_resource_get_handle; + pscreen->resource_changed = etna_resource_changed; + pscreen->resource_destroy = etna_resource_destroy; +} diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_resource.h b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_resource.h new file mode 100644 index 000000000..0b135e237 --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_resource.h @@ -0,0 +1,159 @@ +/* + * 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) */ + bool ts_valid; +}; + +/* 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; + uint32_t flush_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; + /* + * If imported resources have an render/sampler incompatible tiling, we keep + * them as an external resource, which is blitted as needed. + */ + struct pipe_resource *external; + + 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; +} + +/* returns TRUE if the resource needs a resolve to itself */ +static inline bool +etna_resource_needs_flush(struct etna_resource *res) +{ + return res->ts_bo && ((int)(res->seqno - res->flush_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); + +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, + uint64_t modifier, const struct pipe_resource *templat); + +void +etna_resource_screen_init(struct pipe_screen *pscreen); + +#endif diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_rs.c b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_rs.c new file mode 100644 index 000000000..2c9b267f7 --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_rs.c @@ -0,0 +1,145 @@ +/* + * 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); + + /* Initially all pipes are set to the base address of the source and + * destination buffer respectively. This will be overridden below as + * necessary for the multi-pipe, multi-tiled case. + */ + for (unsigned pipe = 0; pipe < ctx->specs.pixel_pipes; ++pipe) { + cs->source[pipe].bo = rs->source; + cs->source[pipe].offset = rs->source_offset; + cs->source[pipe].flags = ETNA_RELOC_READ; + + cs->dest[pipe].bo = rs->dest; + cs->dest[pipe].offset = rs->dest_offset; + cs->dest[pipe].flags = ETNA_RELOC_WRITE; + + cs->RS_PIPE_OFFSET[pipe] = VIVS_RS_PIPE_OFFSET_X(0) | VIVS_RS_PIPE_OFFSET_Y(0); + } + + 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 || ctx->specs.single_buffer) { + 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].offset = rs->source_offset + rs->source_stride * rs->source_padded_height / 2; + + if (dest_multi) + cs->dest[1].offset = rs->dest_offset + rs->dest_stride * rs->dest_padded_height / 2; + + cs->RS_WINDOW_SIZE = VIVS_RS_WINDOW_SIZE_WIDTH(rs->width) | + VIVS_RS_WINDOW_SIZE_HEIGHT(rs->height / 2); + cs->RS_PIPE_OFFSET[1] = VIVS_RS_PIPE_OFFSET_X(0) | VIVS_RS_PIPE_OFFSET_Y(rs->height / 2); + } else { + abort(); + } + + 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); + + /* If source the same as destination, and the hardware supports this, + * do an in-place resolve to fill in unrendered tiles. + */ + if (ctx->specs.single_buffer && rs->source == rs->dest && + rs->source_offset == rs->dest_offset && + rs->source_format == rs->dest_format && + rs->source_tiling == rs->dest_tiling && + (rs->source_tiling & ETNA_LAYOUT_BIT_SUPER) && + rs->source_stride == rs->dest_stride && + !rs->downsample_x && !rs->downsample_y && + !rs->swap_rb && !rs->flip && + !rs->clear_mode && rs->source_padded_width) { + /* Total number of tiles (same as for autodisable) */ + cs->RS_KICKER_INPLACE = rs->source_padded_width * rs->source_padded_height / 16; + } + cs->source_ts_valid = rs->source_ts_valid; +} + +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); +} diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_rs.h b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_rs.h new file mode 100644 index 000000000..41a596055 --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_rs.h @@ -0,0 +1,90 @@ +/* + * 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_ts_valid : 1; + + 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_width; /* total padded width (only needed for source) */ + 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 { + uint8_t source_ts_valid : 1; + 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]; + uint32_t RS_KICKER_INPLACE; /* Set if source is destination */ + + 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 diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_screen.c b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_screen.c new file mode 100644 index 000000000..009bc73c1 --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_screen.c @@ -0,0 +1,950 @@ +/* + * 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" + +#include <drm_fourcc.h> + +#define ETNA_DRM_VERSION(major, minor) ((major) << 16 | (minor)) +#define ETNA_DRM_VERSION_FENCE_FD ETNA_DRM_VERSION(1, 1) + +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"}, + {"shaderdb", ETNA_DBG_SHADERDB, "Enable shaderdb output"}, + 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; + case PIPE_CAP_NATIVE_FENCE_FD: + return screen->drm_version >= ETNA_DRM_VERSION_FENCE_FD; + + /* 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_TEXTURE_SWIZZLE: + 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_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_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_GLSL_OPTIMIZE_CONSERVATIVELY: + case PIPE_CAP_TGSI_FS_FBFETCH: + case PIPE_CAP_TGSI_MUL_ZERO_WINS: + case PIPE_CAP_DOUBLES: + case PIPE_CAP_INT64: + case PIPE_CAP_INT64_DIVMOD: + case PIPE_CAP_TGSI_TEX_TXF_LZ: + case PIPE_CAP_TGSI_CLOCK: + case PIPE_CAP_POLYGON_MODE_FILL_RECTANGLE: + case PIPE_CAP_SPARSE_BUFFER_PAGE_SIZE: + case PIPE_CAP_TGSI_BALLOT: + case PIPE_CAP_TGSI_TES_LAYER_VIEWPORT: + case PIPE_CAP_CAN_BIND_CONST_BUFFER_AS_VERTEX: + case PIPE_CAP_ALLOW_MAPPED_BUFFERS_DURING_EXECUTION: + case PIPE_CAP_POST_DEPTH_COVERAGE: + case PIPE_CAP_BINDLESS_TEXTURE: + case PIPE_CAP_NIR_SAMPLERS_AS_DEREF: + case PIPE_CAP_QUERY_SO_OVERFLOW: + case PIPE_CAP_MEMOBJ: + case PIPE_CAP_LOAD_CONSTBUF: + case PIPE_CAP_TGSI_ANY_REG_AS_ADDRESS: + case PIPE_CAP_TILE_RASTER_ORDER: + 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: + return 0; + case PIPE_CAP_OCCLUSION_QUERY: + return VIV_FEATURE(screen, chipMinorFeatures1, HALTI0); + 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) +{ + struct etna_screen *screen = etna_screen(pscreen); + + 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 util_last_bit(screen->specs.max_texture_size); + 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, + enum pipe_shader_type 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_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: + case PIPE_SHADER_CAP_INT64_ATOMICS: + case PIPE_SHADER_CAP_FP16: + 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_TGSI_DROUND_SUPPORTED: + case PIPE_SHADER_CAP_TGSI_DFRACEXP_DLDEXP_SUPPORTED: + case PIPE_SHADER_CAP_TGSI_LDEXP_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: + case PIPE_SHADER_CAP_TGSI_SKIP_MERGE_REGISTERS: + 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, + enum pipe_format format) +{ + bool supported = true; + + if (fmt == TEXTURE_FORMAT_ETC1) + supported = VIV_FEATURE(screen, chipFeatures, ETC1_TEXTURE_COMPRESSION); + + if (fmt >= TEXTURE_FORMAT_DXT1 && fmt <= TEXTURE_FORMAT_DXT4_DXT5) + supported = VIV_FEATURE(screen, chipFeatures, DXT_TEXTURE_COMPRESSION); + + if (fmt & EXT_FORMAT) { + supported = VIV_FEATURE(screen, chipMinorFeatures1, HALTI0); + + /* ETC1 is checked above, as it has its own feature bit. ETC2 is + * supported with HALTI0, however that implementation is buggy in hardware. + * The blob driver does per-block patching to work around this. As this + * is currently not implemented by etnaviv, enable it for HALTI1 (GC3000) + * only. + */ + if (util_format_is_etc(format)) + supported = VIV_FEATURE(screen, chipMinorFeatures2, HALTI1); + } + + if (!supported) + return false; + + if (texture_format_needs_swiz(format)) + return VIV_FEATURE(screen, chipMinorFeatures1, HALTI0); + + 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, format)) + 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; +} + +const uint64_t supported_modifiers[] = { + DRM_FORMAT_MOD_LINEAR, + DRM_FORMAT_MOD_VIVANTE_TILED, + DRM_FORMAT_MOD_VIVANTE_SUPER_TILED, + DRM_FORMAT_MOD_VIVANTE_SPLIT_TILED, + DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED, +}; + +static void +etna_screen_query_dmabuf_modifiers(struct pipe_screen *pscreen, + enum pipe_format format, int max, + uint64_t *modifiers, + unsigned int *external_only, int *count) +{ + struct etna_screen *screen = etna_screen(pscreen); + int i, num_modifiers = 0; + + if (max > ARRAY_SIZE(supported_modifiers)) + max = ARRAY_SIZE(supported_modifiers); + + if (!max) { + modifiers = NULL; + max = ARRAY_SIZE(supported_modifiers); + } + + for (i = 0; num_modifiers < max; i++) { + /* don't advertise split tiled formats on single pipe/buffer GPUs */ + if ((screen->specs.pixel_pipes == 1 || screen->specs.single_buffer) && + i >= 3) + break; + + if (modifiers) + modifiers[num_modifiers] = supported_modifiers[i]; + if (external_only) + external_only[num_modifiers] = 0; + num_modifiers++; + } + + *count = num_modifiers; +} + +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; + } + 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); + screen->specs.has_new_transcendentals = + VIV_FEATURE(screen, chipMinorFeatures3, HAS_FAST_TRANSCENDENTALS); + screen->specs.has_halti2_instructions = + VIV_FEATURE(screen, chipMinorFeatures4, HALTI2); + + if (VIV_FEATURE(screen, chipMinorFeatures3, INSTRUCTION_CACHE)) { + /* GC3000 - this core is capable of loading shaders from + * memory. It can also run shaders from registers, as a fallback, but + * "max_instructions" does not have the correct value. It has place for + * 2*256 instructions just like GC2000, but the offsets are slightly + * different. + */ + screen->specs.vs_offset = 0xC000; + /* State 08000-0C000 mirrors 0C000-0E000, and the Vivante driver uses + * this mirror for writing PS instructions, probably safest to do the + * same. + */ + screen->specs.ps_offset = 0x8000 + 0x1000; + screen->specs.max_instructions = 256; /* maximum number instructions for non-icache use */ + screen->specs.has_icache = true; + } else { + 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; + } + screen->specs.has_icache = false; + } + + 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; + } + /* unified uniform memory on GC3000 - HALTI1 feature bit is just a guess + */ + if (VIV_FEATURE(screen, chipMinorFeatures2, HALTI1)) { + screen->specs.has_unified_uniforms = true; + screen->specs.vs_uniforms_offset = VIVS_SH_UNIFORMS(0); + /* hardcode PS uniforms to start after end of VS uniforms - + * for more flexibility this offset could be variable based on the + * shader. + */ + screen->specs.ps_uniforms_offset = VIVS_SH_UNIFORMS(screen->specs.max_vs_uniforms*4); + } else { + screen->specs.has_unified_uniforms = false; + screen->specs.vs_uniforms_offset = VIVS_VS_UNIFORMS(0); + screen->specs.ps_uniforms_offset = VIVS_PS_UNIFORMS(0); + } + + 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; + + screen->specs.single_buffer = VIV_FEATURE(screen, chipMinorFeatures4, SINGLE_BUFFER); + if (screen->specs.single_buffer) + DBG("etnaviv: Single buffer mode enabled with %d pixel pipes\n", screen->specs.pixel_pipes); + + return true; + +fail: + 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; + drmVersionPtr version; + uint64_t val; + + if (!screen) + return NULL; + + pscreen = &screen->base; + screen->dev = dev; + screen->gpu = gpu; + screen->ro = renderonly_dup(ro); + screen->refcnt = 1; + + if (!screen->ro) { + DBG("could not create renderonly object"); + goto fail; + } + + version = drmGetVersion(screen->ro->gpu_fd); + screen->drm_version = ETNA_DRM_VERSION(version->version_major, + version->version_minor); + drmFreeVersion(version); + + etna_mesa_debug = debug_get_option_etna_mesa_debug(); + + /* Disable autodisable for correct rendering with TS */ + etna_mesa_debug |= ETNA_DBG_NO_AUTODISABLE; + + 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_gpu_get_param(screen->gpu, ETNA_GPU_FEATURES_5, &val)) { + DBG("could not get ETNA_GPU_FEATURES_5"); + goto fail; + } + screen->features[5] = val; + + if (etna_gpu_get_param(screen->gpu, ETNA_GPU_FEATURES_6, &val)) { + DBG("could not get ETNA_GPU_FEATURES_6"); + goto fail; + } + screen->features[6] = val; + + if (!etna_get_specs(screen)) + goto fail; + + /* apply debug options that disable individual features */ + if (DBG_ENABLED(ETNA_DBG_NO_EARLY_Z)) + screen->features[viv_chipFeatures] |= chipFeatures_NO_EARLY_Z; + if (DBG_ENABLED(ETNA_DBG_NO_TS)) + screen->features[viv_chipFeatures] &= ~chipFeatures_FAST_CLEAR; + if (DBG_ENABLED(ETNA_DBG_NO_AUTODISABLE)) + screen->features[viv_chipMinorFeatures1] &= ~chipMinorFeatures1_AUTO_DISABLE; + if (DBG_ENABLED(ETNA_DBG_NO_SUPERTILE)) + screen->specs.can_supertile = 0; + + 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; + pscreen->query_dmabuf_modifiers = etna_screen_query_dmabuf_modifiers; + + 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; +} diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_screen.h b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_screen.h new file mode 100644 index 000000000..dc57a38db --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_screen.h @@ -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_chipMinorFeatures4 = 5, + viv_chipMinorFeatures5 = 6, + 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[VIV_FEATURES_WORD_COUNT]; + + struct etna_specs specs; + + uint32_t drm_version; +}; + +static inline struct etna_screen * +etna_screen(struct pipe_screen *pscreen) +{ + return (struct etna_screen *)pscreen; +} + +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 diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_shader.c b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_shader.c new file mode 100644 index 000000000..601268062 --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_shader.c @@ -0,0 +1,432 @@ +/* + * 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_screen.h" +#include "etnaviv_util.h" + +#include "tgsi/tgsi_parse.h" +#include "util/u_math.h" +#include "util/u_memory.h" + +/* Upload shader code to bo, if not already done */ +static bool etna_icache_upload_shader(struct etna_context *ctx, struct etna_shader_variant *v) +{ + if (v->bo) + return true; + v->bo = etna_bo_new(ctx->screen->dev, v->code_size*4, DRM_ETNA_GEM_CACHE_UNCACHED); + if (!v->bo) + return false; + + void *buf = etna_bo_map(v->bo); + etna_bo_cpu_prep(v->bo, DRM_ETNA_PREP_WRITE); + memcpy(buf, v->code, v->code_size*4); + etna_bo_cpu_fini(v->bo); + DBG("Uploaded %s of %u words to bo %p", v->processor == PIPE_SHADER_FRAGMENT ? "fs":"vs", v->code_size, v->bo); + return true; +} + +/* 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, + struct etna_shader_variant *vs, struct etna_shader_variant *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; + + if (vs->needs_icache | fs->needs_icache) { + /* If either of the shaders needs ICACHE, we use it for both. It is + * either switched on or off for the entire shader processor. + */ + if (!etna_icache_upload_shader(ctx, vs) || + !etna_icache_upload_shader(ctx, fs)) { + assert(0); + return false; + } + + cs->VS_INST_ADDR.bo = vs->bo; + cs->VS_INST_ADDR.offset = 0; + cs->VS_INST_ADDR.flags = ETNA_RELOC_READ; + cs->PS_INST_ADDR.bo = fs->bo; + cs->PS_INST_ADDR.offset = 0; + cs->PS_INST_ADDR.flags = ETNA_RELOC_READ; + } else { + /* clear relocs */ + memset(&cs->VS_INST_ADDR, 0, sizeof(cs->VS_INST_ADDR)); + memset(&cs->PS_INST_ADDR, 0, sizeof(cs->PS_INST_ADDR)); + } + + return true; +} + +bool +etna_shader_link(struct etna_context *ctx) +{ + if (!ctx->shader.vs || !ctx->shader.fs) + return false; + + /* re-link vs and fs if needed */ + return etna_link_shaders(ctx, &ctx->shader_state, ctx->shader.vs, ctx->shader.fs); +} + +static bool +etna_shader_update_vs_inputs(struct etna_context *ctx, + struct compiled_shader_state *cs, + const struct etna_shader_variant *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->shader.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; +} + +static inline const char * +etna_shader_stage(struct etna_shader_variant *shader) +{ + switch (shader->processor) { + case PIPE_SHADER_VERTEX: return "VERT"; + case PIPE_SHADER_FRAGMENT: return "FRAG"; + case PIPE_SHADER_COMPUTE: return "CL"; + default: + unreachable("invalid type"); + return NULL; + } +} + +static void +dump_shader_info(struct etna_shader_variant *v, struct pipe_debug_callback *debug) +{ + if (!unlikely(etna_mesa_debug & ETNA_DBG_SHADERDB)) + return; + + pipe_debug_message(debug, SHADER_INFO, "\n" + "SHADER-DB: %s prog %d/%d: %u instructions %u temps\n" + "SHADER-DB: %s prog %d/%d: %u immediates %u consts\n" + "SHADER-DB: %s prog %d/%d: %u loops\n", + etna_shader_stage(v), + v->shader->id, v->id, + v->code_size, + v->num_temps, + etna_shader_stage(v), + v->shader->id, v->id, + v->uniforms.imm_count, + v->uniforms.const_count, + etna_shader_stage(v), + v->shader->id, v->id, + v->num_loops); +} + +bool +etna_shader_update_vertex(struct etna_context *ctx) +{ + return etna_shader_update_vs_inputs(ctx, &ctx->shader_state, ctx->shader.vs, + ctx->vertex_elements); +} + +static struct etna_shader_variant * +create_variant(struct etna_shader *shader, struct etna_shader_key key) +{ + struct etna_shader_variant *v = CALLOC_STRUCT(etna_shader_variant); + int ret; + + if (!v) + return NULL; + + v->shader = shader; + v->key = key; + + ret = etna_compile_shader(v); + if (!ret) { + debug_error("compile failed!"); + goto fail; + } + + v->id = ++shader->variant_count; + + return v; + +fail: + FREE(v); + return NULL; +} + +struct etna_shader_variant * +etna_shader_variant(struct etna_shader *shader, struct etna_shader_key key, + struct pipe_debug_callback *debug) +{ + struct etna_shader_variant *v; + + for (v = shader->variants; v; v = v->next) + if (etna_shader_key_equal(&key, &v->key)) + return v; + + /* compile new variant if it doesn't exist already */ + v = create_variant(shader, key); + if (v) { + v->next = shader->variants; + shader->variants = v; + dump_shader_info(v, debug); + } + + return v; +} + +static void * +etna_create_shader_state(struct pipe_context *pctx, + const struct pipe_shader_state *pss) +{ + struct etna_context *ctx = etna_context(pctx); + struct etna_shader *shader = CALLOC_STRUCT(etna_shader); + + if (!shader) + return NULL; + + static uint32_t id; + shader->id = id++; + shader->specs = &ctx->specs; + shader->tokens = tgsi_dup_tokens(pss->tokens); + + if (etna_mesa_debug & ETNA_DBG_SHADERDB) { + /* if shader-db run, create a standard variant immediately + * (as otherwise nothing will trigger the shader to be + * actually compiled). + */ + struct etna_shader_key key = {}; + etna_shader_variant(shader, key, &ctx->debug); + } + + return shader; +} + +static void +etna_delete_shader_state(struct pipe_context *pctx, void *ss) +{ + struct etna_shader *shader = ss; + struct etna_shader_variant *v, *t; + + v = shader->variants; + while (v) { + t = v; + v = v->next; + if (t->bo) + etna_bo_del(t->bo); + etna_destroy_shader(t); + } + + FREE(shader->tokens); + FREE(shader); +} + +static void +etna_bind_fs_state(struct pipe_context *pctx, void *hwcso) +{ + struct etna_context *ctx = etna_context(pctx); + + ctx->shader.bind_fs = hwcso; + ctx->dirty |= ETNA_DIRTY_SHADER; +} + +static void +etna_bind_vs_state(struct pipe_context *pctx, void *hwcso) +{ + struct etna_context *ctx = etna_context(pctx); + + ctx->shader.bind_vs = hwcso; + 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; +} diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_shader.h b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_shader.h new file mode 100644 index 000000000..121d5815b --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_shader.h @@ -0,0 +1,82 @@ +/* + * 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_variant; + +struct etna_shader_key +{ + union { + struct { + /* + * Combined Vertex/Fragment shader parameters: + */ + + /* do we need to swap rb in frag color? */ + unsigned frag_rb_swap : 1; + }; + uint32_t global; + }; +}; + +static inline bool +etna_shader_key_equal(struct etna_shader_key *a, struct etna_shader_key *b) +{ + STATIC_ASSERT(sizeof(struct etna_shader_key) <= sizeof(a->global)); + + return a->global == b->global; +} + +struct etna_shader { + /* shader id (for debug): */ + uint32_t id; + uint32_t variant_count; + + struct tgsi_token *tokens; + const struct etna_specs *specs; + + struct etna_shader_variant *variants; +}; + +bool +etna_shader_link(struct etna_context *ctx); + +bool +etna_shader_update_vertex(struct etna_context *ctx); + +struct etna_shader_variant * +etna_shader_variant(struct etna_shader *shader, struct etna_shader_key key, + struct pipe_debug_callback *debug); + +void +etna_shader_init(struct pipe_context *pctx); + +#endif diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_state.c b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_state.c new file mode 100644 index 000000000..bf06892fd --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_state.c @@ -0,0 +1,670 @@ +/* + * 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_blend.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_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, + enum pipe_shader_type 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, or single-buffer mode must be supported */ + assert((res->layout & ETNA_LAYOUT_BIT_MULTI) || ctx->specs.single_buffer); + 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) { + 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) { + 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) + ETNA_SE_SCISSOR_MARGIN_RIGHT; + cs->SE_SCISSOR_BOTTOM = (sv->height << 16) + ETNA_SE_SCISSOR_MARGIN_BOTTOM; + cs->SE_CLIP_RIGHT = (sv->width << 16) + ETNA_SE_CLIP_MARGIN_RIGHT; + cs->SE_CLIP_BOTTOM = (sv->height << 16) + ETNA_SE_CLIP_MARGIN_BOTTOM; + + cs->TS_MEM_CONFIG = ts_mem_config; + + /* Single buffer setup. There is only one switch for this, not a separate + * one per color buffer / depth buffer. To keep the logic simple always use + * single buffer when this feature is available. + */ + cs->PE_LOGIC_OP = VIVS_PE_LOGIC_OP_SINGLE_BUFFER(ctx->specs.single_buffer ? 2 : 0); + + ctx->framebuffer_s = *sv; /* keep copy of original structure */ + ctx->dirty |= ETNA_DIRTY_FRAMEBUFFER | ETNA_DIRTY_DERIVE_TS; +} + +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; + assert(ss->minx <= ss->maxx); + assert(ss->miny <= ss->maxy); + + /* 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) + ETNA_SE_SCISSOR_MARGIN_RIGHT; + cs->SE_SCISSOR_BOTTOM = (ss->maxy << 16) + ETNA_SE_SCISSOR_MARGIN_BOTTOM; + cs->SE_CLIP_RIGHT = (ss->maxx << 16) + ETNA_SE_CLIP_MARGIN_RIGHT; + cs->SE_CLIP_BOTTOM = (ss->maxy << 16) + ETNA_SE_CLIP_MARGIN_BOTTOM; + + 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] - fabsf(vs->scale[0]), 0.0f)); + cs->SE_SCISSOR_TOP = etna_f32_to_fixp16(MAX2(vs->translate[1] - fabsf(vs->scale[1]), 0.0f)); + uint32_t right_fixp = etna_f32_to_fixp16(MAX2(vs->translate[0] + fabsf(vs->scale[0]), 0.0f)); + uint32_t bottom_fixp = etna_f32_to_fixp16(MAX2(vs->translate[1] + fabsf(vs->scale[1]), 0.0f)); + cs->SE_SCISSOR_RIGHT = right_fixp + ETNA_SE_SCISSOR_MARGIN_RIGHT; + cs->SE_SCISSOR_BOTTOM = bottom_fixp + ETNA_SE_SCISSOR_MARGIN_BOTTOM; + cs->SE_CLIP_RIGHT = right_fixp + ETNA_SE_CLIP_MARGIN_RIGHT; + cs->SE_CLIP_BOTTOM = bottom_fixp + ETNA_SE_CLIP_MARGIN_BOTTOM; + + 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->is_user_buffer); /* XXX support user_buffer using + etna_usermem_map */ + + if (vbi->buffer.resource) { /* GPU buffer */ + cs->FE_VERTEX_STREAM_BASE_ADDR.bo = etna_resource(vbi->buffer.resource)->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_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; +} + +static bool +etna_update_ts_config(struct etna_context *ctx) +{ + uint32_t new_ts_config = ctx->framebuffer.TS_MEM_CONFIG; + + if (ctx->framebuffer_s.nr_cbufs > 0) { + struct etna_surface *c_surf = etna_surface(ctx->framebuffer_s.cbufs[0]); + + if(c_surf->level->ts_size && c_surf->level->ts_valid) { + new_ts_config |= VIVS_TS_MEM_CONFIG_COLOR_FAST_CLEAR; + } else { + new_ts_config &= ~VIVS_TS_MEM_CONFIG_COLOR_FAST_CLEAR; + } + } + + if (ctx->framebuffer_s.zsbuf) { + struct etna_surface *zs_surf = etna_surface(ctx->framebuffer_s.zsbuf); + + if(zs_surf->level->ts_size && zs_surf->level->ts_valid) { + new_ts_config |= VIVS_TS_MEM_CONFIG_DEPTH_FAST_CLEAR; + } else { + new_ts_config &= ~VIVS_TS_MEM_CONFIG_DEPTH_FAST_CLEAR; + } + } + + if (new_ts_config != ctx->framebuffer.TS_MEM_CONFIG || + (ctx->dirty & ETNA_DIRTY_FRAMEBUFFER)) { + ctx->framebuffer.TS_MEM_CONFIG = new_ts_config; + ctx->dirty |= ETNA_DIRTY_TS; + } + + ctx->dirty &= ~ETNA_DIRTY_DERIVE_TS; + + return true; +} + +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, + }, + { + etna_update_blend, ETNA_DIRTY_BLEND | ETNA_DIRTY_FRAMEBUFFER + }, + { + etna_update_blend_color, ETNA_DIRTY_BLEND_COLOR | ETNA_DIRTY_FRAMEBUFFER, + }, + { + etna_update_ts_config, ETNA_DIRTY_DERIVE_TS, + } +}; + +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->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; +} diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_state.h b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_state.h new file mode 100644 index 000000000..a1db9f789 --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_state.h @@ -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_ */ diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_surface.c b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_surface.c new file mode 100644 index 000000000..4b95f6575 --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_surface.c @@ -0,0 +1,156 @@ +/* + * 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. */ + + if (VIV_FEATURE(ctx->screen, chipFeatures, FAST_CLEAR) && + VIV_FEATURE(ctx->screen, chipMinorFeatures0, MC20) && + !rsc->ts_bo && + (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 */ + for (unsigned pipe = 0; pipe < ctx->specs.pixel_pipes; ++pipe) { + surf->reloc[pipe].bo = rsc->bo; + surf->reloc[pipe].offset = surf->surf.offset; + surf->reloc[pipe].flags = 0; + } + + /* In single buffer mode, both pixel pipes must point to the same address, + * for multi-tiled surfaces on the other hand the second pipe is expected to + * point halfway the image vertically. + */ + if (rsc->layout & ETNA_LAYOUT_BIT_MULTI) + surf->reloc[1].offset = surf->surf.offset + lev->stride * lev->padded_height / 2; + + 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->surf.ts_valid = false; + + 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; +} diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_surface.h b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_surface.h new file mode 100644 index 000000000..e8cfd209a --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_surface.h @@ -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 diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_texture.c b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_texture.c new file mode 100644 index 000000000..b8ebab608 --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_texture.c @@ -0,0 +1,360 @@ +/* + * 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" + +#include <drm_fourcc.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, enum pipe_shader_type 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 *base = etna_resource(view->texture); + struct etna_resource *to = base, *from = base; + + if (base->external && etna_resource_newer(etna_resource(base->external), base)) + from = etna_resource(base->external); + + if (base->texture) + to = etna_resource(base->texture); + + if ((to != from) && etna_resource_older(to, from)) { + etna_copy_resource(view->context, &to->base, &from->base, 0, + view->texture->last_level); + to->seqno = from->seqno; + } else if ((to == from) && etna_resource_needs_flush(to)) { + /* Resolve TS if needed, remove when adding sampler TS */ + etna_copy_resource(view->context, &to->base, &from->base, 0, + view->texture->last_level); + to->flush_seqno = from->seqno; + } +} + +static bool +etna_resource_sampler_compatible(struct etna_resource *res) +{ + if (util_format_is_compressed(res->base.format)) + return true; + + struct etna_screen *screen = etna_screen(res->base.screen); + /* This GPU supports texturing from supertiled textures? */ + if (res->layout == ETNA_LAYOUT_SUPER_TILED && VIV_FEATURE(screen, chipMinorFeatures2, SUPERTILED_TEXTURE)) + return true; + + /* TODO: LINEAR_TEXTURE_SUPPORT */ + + /* Otherwise, only support tiled layouts */ + if (res->layout != ETNA_LAYOUT_TILED) + return false; + + /* If we have HALIGN support, we can allow for the RS padding */ + 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); + const uint32_t format = translate_texture_format(so->format); + const bool ext = !!(format & EXT_FORMAT); + const uint32_t swiz = get_texture_swiz(so->format, so->swizzle_r, + so->swizzle_g, so->swizzle_b, + so->swizzle_a); + + 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, + DRM_FORMAT_MOD_LINEAR, &templat); + } + + if (!res->texture) { + free(sv); + return NULL; + } + res = etna_resource(res->texture); + } + + sv->base = *so; + pipe_reference_init(&sv->base.reference, 1); + sv->base.texture = NULL; + pipe_resource_reference(&sv->base.texture, prsc); + sv->base.context = pctx; + + /* merged with sampler state */ + sv->TE_SAMPLER_CONFIG0 = COND(!ext, VIVS_TE_SAMPLER_CONFIG0_FORMAT(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); + /* fallthrough */ + 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 = COND(ext, VIVS_TE_SAMPLER_CONFIG1_FORMAT_EXT(format)) | + VIVS_TE_SAMPLER_CONFIG1_HALIGN(res->halign) | swiz; + 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, enum pipe_shader_type 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, unsigned flags) +{ + 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; +} diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_texture.h b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_texture.h new file mode 100644 index 000000000..a7a67fc24 --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_texture.h @@ -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 diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_tiling.c b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_tiling.c new file mode 100644 index 000000000..f4f85c1d6 --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_tiling.c @@ -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); + } +} diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_tiling.h b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_tiling.h new file mode 100644 index 000000000..3c69e2246 --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_tiling.h @@ -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 diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_transfer.c b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_transfer.c new file mode 100644 index 000000000..08ec1987d --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_transfer.c @@ -0,0 +1,403 @@ +/* + * 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 "etnaviv_screen.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" + +#include <drm_fourcc.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 */ + + /* + * Temporary resources are always pulled into the CPU domain, must push them + * back into GPU domain before the RS execs the blit to the base resource. + */ + if (trans->rsc) + etna_bo_cpu_fini(etna_resource(trans->rsc)->bo); + + 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_box(pctx, ptrans->resource, trans->rsc, ptrans->level, &ptrans->box); + } 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_TILED) { + 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 if (rsc->layout == ETNA_LAYOUT_LINEAR) { + 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++; + + if (rsc->base.bind & PIPE_BIND_SAMPLER_VIEW) { + ctx->dirty |= ETNA_DIRTY_TEXTURE_CACHES; + } + } + + /* + * Transfers without a temporary are only pulled into the CPU domain if they + * are not mapped unsynchronized. If they are, must push them back into GPU + * domain after CPU access is finished. + */ + if (!trans->rsc && !(ptrans->usage & PIPE_TRANSFER_UNSYNCHRONIZED)) + etna_bo_cpu_fini(rsc->bo); + + 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); + + /* Upgrade DISCARD_RANGE to WHOLE_RESOURCE if the whole resource is + * being mapped. If we add buffer reallocation to avoid CPU/GPU sync this + * check needs to be extended to coherent mappings and shared resources. + */ + if ((usage & PIPE_TRANSFER_DISCARD_RANGE) && + !(usage & PIPE_TRANSFER_UNSYNCHRONIZED) && + prsc->last_level == 0 && + prsc->width0 == box->width && + prsc->height0 == box->height && + prsc->depth0 == box->depth && + prsc->array_size == 1) { + usage |= PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE; + } + + 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, + DRM_FORMAT_MOD_LINEAR, &templ); + if (!trans->rsc) { + slab_free(&ctx->transfer_pool, trans); + return NULL; + } + + /* Need to align the transfer region to satisfy RS restrictions, as we + * really want to hit the RS blit path here. + */ + unsigned w_align, h_align; + + if (rsc->layout & ETNA_LAYOUT_BIT_SUPER) { + w_align = h_align = 64; + } else { + w_align = ETNA_RS_WIDTH_MASK + 1; + h_align = ETNA_RS_HEIGHT_MASK + 1; + } + h_align *= ctx->screen->specs.pixel_pipes; + + ptrans->box.width += ptrans->box.x & (w_align - 1); + ptrans->box.x = ptrans->box.x & ~(w_align - 1); + ptrans->box.width = align(ptrans->box.width, (ETNA_RS_WIDTH_MASK + 1)); + ptrans->box.height += ptrans->box.y & (h_align - 1); + ptrans->box.y = ptrans->box.y & ~(h_align - 1); + ptrans->box.height = align(ptrans->box.height, + (ETNA_RS_HEIGHT_MASK + 1) * + ctx->screen->specs.pixel_pipes); + + if (!(usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE)) + etna_copy_resource_box(pctx, trans->rsc, prsc, level, &ptrans->box); + + /* Switch to using the temporary resource instead */ + rsc = etna_resource(trans->rsc); + } + + struct etna_resource_level *res_level = &rsc->levels[level]; + + /* + * Always flush if we have the temporary resource and have a copy to this + * outstanding. Otherwise infer flush requirement from resource access and + * current GPU usage (reads must wait for GPU writes, writes must have + * exclusive access to the buffer). + */ + if ((trans->rsc && (etna_resource(trans->rsc)->status & ETNA_PENDING_WRITE)) || + (!trans->rsc && + (((usage & PIPE_TRANSFER_READ) && (rsc->status & ETNA_PENDING_WRITE)) || + ((usage & PIPE_TRANSFER_WRITE) && rsc->status)))) + pctx->flush(pctx, NULL, 0); + + /* 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. + */ + + /* + * Pull resources into the CPU domain. Only skipped for unsynchronized + * transfers without a temporary resource. + */ + if (trans->rsc || !(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) { + 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 (rsc->layout == ETNA_LAYOUT_LINEAR) { + 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) { + if (rsc->layout == ETNA_LAYOUT_TILED) { + 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 if (rsc->layout == ETNA_LAYOUT_LINEAR) { + 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; +} diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_transfer.h b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_transfer.h new file mode 100644 index 000000000..ca156a476 --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_transfer.h @@ -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 diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_translate.h b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_translate.h new file mode 100644 index 000000000..0761251a3 --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_translate.h @@ -0,0 +1,484 @@ +/* + * 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 "util/u_math.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); + } +} + +static inline void etna_adjust_rs_align(unsigned num_pixelpipes, + unsigned *paddingX, unsigned *paddingY) +{ + unsigned alignX = ETNA_RS_WIDTH_MASK + 1; + unsigned alignY = (ETNA_RS_HEIGHT_MASK + 1) * num_pixelpipes; + + if (paddingX) + *paddingX = align(*paddingX, alignX); + if (paddingY) + *paddingY = align(*paddingY, alignY); +} + +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 diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_uniforms.c b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_uniforms.c new file mode 100644 index 000000000..a8d970d18 --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_uniforms.c @@ -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_variant *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->shader.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_variant *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; +} diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_uniforms.h b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_uniforms.h new file mode 100644 index 000000000..1dacd2a85 --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_uniforms.h @@ -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_variant; +struct pipe_constant_buffer; + +void +etna_uniforms_write(const struct etna_context *ctx, + const struct etna_shader_variant *sobj, + struct pipe_constant_buffer *cb, uint32_t *uniforms, + unsigned *size); + +void +etna_set_shader_uniforms_dirty_flags(struct etna_shader_variant *sobj); + +#endif /* ETNAVIV_UNIFORMS_H_ */ diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_util.h b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_util.h new file mode 100644 index 000000000..62f62548d --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_util.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2012-2015 Etnaviv Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/* Misc util */ +#ifndef H_ETNA_UTIL +#define H_ETNA_UTIL + +#include <math.h> + +/* for conditionally setting boolean flag(s): */ +#define COND(bool, val) ((bool) ? (val) : 0) + +/* align to a value divisable by granularity >= value, works only for powers of two */ +static inline uint32_t +etna_align_up(uint32_t value, uint32_t granularity) +{ + return (value + (granularity - 1)) & (~(granularity - 1)); +} + +static inline uint32_t +etna_bits_ones(unsigned num) +{ + return (1 << num) - 1; +} + +/* clamped float [0.0 .. 1.0] -> [0 .. 255] */ +static inline uint8_t +etna_cfloat_to_uint8(float f) +{ + if (f <= 0.0f) + return 0; + + if (f >= (1.0f - 1.0f / 256.0f)) + return 255; + + return f * 256.0f; +} + +/* clamped float [0.0 .. 1.0] -> [0 .. (1<<bits)-1] */ +static inline uint32_t +etna_cfloat_to_uintN(float f, int bits) +{ + if (f <= 0.0f) + return 0; + + if (f >= (1.0f - 1.0f / (1 << bits))) + return (1 << bits) - 1; + + return f * (1 << bits); +} + +/* 1/log10(2) */ +#define RCPLOG2 (1.4426950408889634f) + +/* float to fixp 5.5 */ +static inline uint32_t +etna_float_to_fixp55(float f) +{ + if (f >= 15.953125f) + return 511; + + if (f < -16.0f) + return 512; + + return (int32_t)(f * 32.0f + 0.5f); +} + +/* texture size to log2 in fixp 5.5 format */ +static inline uint32_t +etna_log2_fixp55(unsigned width) +{ + return etna_float_to_fixp55(logf((float)width) * RCPLOG2); +} + +/* float to fixp 16.16 */ +static inline uint32_t +etna_f32_to_fixp16(float f) +{ + if (f >= (32768.0f - 1.0f / 65536.0f)) + return 0x7fffffff; + + if (f < -32768.0f) + return 0x80000000; + + return (int32_t)(f * 65536.0f + 0.5f); +} + +#endif diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_zsa.c b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_zsa.c new file mode 100644 index 000000000..22c2020fe --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_zsa.c @@ -0,0 +1,124 @@ +/* + * 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_screen.h" +#include "etnaviv_translate.h" +#include "util/u_memory.h" + +#include "hw/common.xml.h" + +void * +etna_zsa_state_create(struct pipe_context *pctx, + const struct pipe_depth_stencil_alpha_state *so) +{ + struct etna_context *ctx = etna_context(pctx); + 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 = !VIV_FEATURE(ctx->screen, chipFeatures, NO_EARLY_Z); + 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; + + /* 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; +} diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_zsa.h b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_zsa.h new file mode 100644 index 000000000..953a6a78b --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_zsa.h @@ -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 diff --git a/lib/mesa/src/gallium/drivers/etnaviv/hw/cmdstream.xml.h b/lib/mesa/src/gallium/drivers/etnaviv/hw/cmdstream.xml.h new file mode 100644 index 000000000..e12188ea5 --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/hw/cmdstream.xml.h @@ -0,0 +1,300 @@ +#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 ( 16595 bytes, from 2017-10-05 21:20:32) +- copyright.xml ( 1597 bytes, from 2016-11-13 13:46:17) +- common.xml ( 26135 bytes, from 2017-10-05 21:20:32) + +Copyright (C) 2012-2017 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 FE_OPCODE_WAIT_FENCE 0x0000000f +#define FE_OPCODE_SNAP_PAGES 0x00000013 +#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_STALL_TOKEN_UNK28__MASK 0x30000000 +#define VIV_FE_STALL_TOKEN_UNK28__SHIFT 28 +#define VIV_FE_STALL_TOKEN_UNK28(x) (((x) << VIV_FE_STALL_TOKEN_UNK28__SHIFT) & VIV_FE_STALL_TOKEN_UNK28__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) + +#define VIV_FE_WAIT_FENCE 0x00000000 + +#define VIV_FE_WAIT_FENCE_HEADER 0x00000000 +#define VIV_FE_WAIT_FENCE_HEADER_OP__MASK 0xf8000000 +#define VIV_FE_WAIT_FENCE_HEADER_OP__SHIFT 27 +#define VIV_FE_WAIT_FENCE_HEADER_OP_WAIT_FENCE 0x78000000 +#define VIV_FE_WAIT_FENCE_HEADER_UNK16__MASK 0x00030000 +#define VIV_FE_WAIT_FENCE_HEADER_UNK16__SHIFT 16 +#define VIV_FE_WAIT_FENCE_HEADER_UNK16(x) (((x) << VIV_FE_WAIT_FENCE_HEADER_UNK16__SHIFT) & VIV_FE_WAIT_FENCE_HEADER_UNK16__MASK) +#define VIV_FE_WAIT_FENCE_HEADER_WAITCOUNT__MASK 0x0000ffff +#define VIV_FE_WAIT_FENCE_HEADER_WAITCOUNT__SHIFT 0 +#define VIV_FE_WAIT_FENCE_HEADER_WAITCOUNT(x) (((x) << VIV_FE_WAIT_FENCE_HEADER_WAITCOUNT__SHIFT) & VIV_FE_WAIT_FENCE_HEADER_WAITCOUNT__MASK) + +#define VIV_FE_WAIT_FENCE_ADDRESS 0x00000004 + +#define VIV_FE_SNAP_PAGES 0x00000000 + +#define VIV_FE_SNAP_PAGES_HEADER 0x00000000 +#define VIV_FE_SNAP_PAGES_HEADER_OP__MASK 0xf8000000 +#define VIV_FE_SNAP_PAGES_HEADER_OP__SHIFT 27 +#define VIV_FE_SNAP_PAGES_HEADER_OP_SNAP_PAGES 0x98000000 +#define VIV_FE_SNAP_PAGES_HEADER_UNK0__MASK 0x0000001f +#define VIV_FE_SNAP_PAGES_HEADER_UNK0__SHIFT 0 +#define VIV_FE_SNAP_PAGES_HEADER_UNK0(x) (((x) << VIV_FE_SNAP_PAGES_HEADER_UNK0__SHIFT) & VIV_FE_SNAP_PAGES_HEADER_UNK0__MASK) + + +#endif /* CMDSTREAM_XML */ diff --git a/lib/mesa/src/gallium/drivers/etnaviv/hw/common.xml.h b/lib/mesa/src/gallium/drivers/etnaviv/hw/common.xml.h new file mode 100644 index 000000000..57369d741 --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/hw/common.xml.h @@ -0,0 +1,327 @@ +#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 ( 26245 bytes, from 2017-10-05 21:32:06) +- common.xml ( 26135 bytes, from 2017-10-05 21:20:32) +- state_hi.xml ( 27733 bytes, from 2017-10-05 21:20:32) +- copyright.xml ( 1597 bytes, from 2016-11-13 13:46:17) +- state_2d.xml ( 51552 bytes, from 2016-11-13 13:46:17) +- state_3d.xml ( 80819 bytes, from 2017-10-05 21:20:32) +- state_vg.xml ( 5975 bytes, from 2016-11-13 13:46:17) + +Copyright (C) 2012-2017 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_BLT 0x00000010 +#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_GC900 0x00000900 +#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 chipModel_GC7000 0x00007000 +#define chipModel_GC7400 0x00007400 +#define chipModel_GC8000 0x00008000 +#define chipModel_GC8100 0x00008100 +#define chipModel_GC8200 0x00008200 +#define chipModel_GC8400 0x00008400 +#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_TX_FILTER 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_PE_ENHANCEMENTS1 0x00400000 +#define chipMinorFeatures3_2D_FC_SOURCE 0x00800000 +#define chipMinorFeatures3_BUG_FIXES_14 0x01000000 +#define chipMinorFeatures3_POWER_OPTIMIZATIONS_0 0x02000000 +#define chipMinorFeatures3_NEW_HZ 0x04000000 +#define chipMinorFeatures3_PE_DITHER_FIX 0x08000000 +#define chipMinorFeatures3_DE_ENHANCEMENTS3 0x10000000 +#define chipMinorFeatures3_SH_ENHANCEMENTS3 0x20000000 +#define chipMinorFeatures3_SH_ENHANCEMENTS4 0x40000000 +#define chipMinorFeatures3_TX_ENHANCEMENTS2 0x80000000 +#define chipMinorFeatures4_FE_ENHANCEMENTS1 0x00000001 +#define chipMinorFeatures4_PE_ENHANCEMENTS2 0x00000002 +#define chipMinorFeatures4_FRUSTUM_CLIP_FIX 0x00000004 +#define chipMinorFeatures4_DE_NO_GAMMA 0x00000008 +#define chipMinorFeatures4_PA_ENHANCEMENTS_2 0x00000010 +#define chipMinorFeatures4_2D_GAMMA 0x00000020 +#define chipMinorFeatures4_SINGLE_BUFFER 0x00000040 +#define chipMinorFeatures4_HI_ENHANCEMENTS_1 0x00000080 +#define chipMinorFeatures4_TX_ENHANCEMENTS_3 0x00000100 +#define chipMinorFeatures4_SH_ENHANCEMENTS_5 0x00000200 +#define chipMinorFeatures4_FE_ENHANCEMENTS_2 0x00000400 +#define chipMinorFeatures4_TX_LERP_PRECISION_FIX 0x00000800 +#define chipMinorFeatures4_2D_COLOR_SPACE_CONVERSION 0x00001000 +#define chipMinorFeatures4_TEXTURE_ASTC 0x00002000 +#define chipMinorFeatures4_PE_ENHANCEMENTS_4 0x00004000 +#define chipMinorFeatures4_MC_ENHANCEMENTS_1 0x00008000 +#define chipMinorFeatures4_HALTI2 0x00010000 +#define chipMinorFeatures4_2D_MIRROR_EXTENSION 0x00020000 +#define chipMinorFeatures4_SMALL_MSAA 0x00040000 +#define chipMinorFeatures4_BUG_FIXES_17 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_MEDIUM_PRECISION 0x10000000 +#define chipMinorFeatures4_2D_SUPER_TILE_VERSION 0x20000000 +#define chipMinorFeatures4_BUG_FIXES19 0x40000000 +#define chipMinorFeatures4_SH_ENHANCEMENTS6 0x80000000 +#define chipMinorFeatures5_SH_ENHANCEMENTS7 0x00000001 +#define chipMinorFeatures5_BUG_FIXES20 0x00000002 +#define chipMinorFeatures5_DE_ADDRESS_40 0x00000004 +#define chipMinorFeatures5_MINI_MMU_FIX 0x00000008 +#define chipMinorFeatures5_EEZ 0x00000010 +#define chipMinorFeatures5_BUG_FIXES21 0x00000020 +#define chipMinorFeatures5_EXTRA_VG_CAPS 0x00000040 +#define chipMinorFeatures5_MULTI_SRC_V15 0x00000080 +#define chipMinorFeatures5_BUG_FIXES22 0x00000100 +#define chipMinorFeatures5_HALTI3 0x00000200 +#define chipMinorFeatures5_TESSELATION_SHADERS 0x00000400 +#define chipMinorFeatures5_2D_ONE_PASS_FILTER_TAP 0x00000800 +#define chipMinorFeatures5_MULTI_SRC_V2_STR_QUAD 0x00001000 +#define chipMinorFeatures5_SEPARATE_SRC_DST 0x00002000 +#define chipMinorFeatures5_HALTI4 0x00004000 +#define chipMinorFeatures5_RA_WRITE_DEPTH 0x00008000 +#define chipMinorFeatures5_ANDROID_ONLY 0x00010000 +#define chipMinorFeatures5_HAS_PRODUCTID 0x00020000 +#define chipMinorFeatures5_TX_SUPPORT_DEC 0x00040000 +#define chipMinorFeatures5_S8_MSAA_COMPRESSION 0x00080000 +#define chipMinorFeatures5_PE_DITHER_FIX2 0x00100000 +#define chipMinorFeatures5_L2_CACHE_REMOVE 0x00200000 +#define chipMinorFeatures5_FE_ALLOW_RND_VTX_CNT 0x00400000 +#define chipMinorFeatures5_CUBE_MAP_FL28 0x00800000 +#define chipMinorFeatures5_TX_6BIT_FRAC 0x01000000 +#define chipMinorFeatures5_FE_ALLOW_STALL_PREFETCH_ENG 0x02000000 +#define chipMinorFeatures5_THIRD_PARTY_COMPRESSION 0x04000000 +#define chipMinorFeatures5_RS_DEPTHSTENCIL_NATIVE_SUPPORT 0x08000000 +#define chipMinorFeatures5_V2_MSAA_COMP_FIX 0x10000000 +#define chipMinorFeatures5_HALTI5 0x20000000 +#define chipMinorFeatures5_EVIS 0x40000000 +#define chipMinorFeatures5_BLT_ENGINE 0x80000000 +#define chipMinorFeatures6_BUG_FIXES_23 0x00000001 +#define chipMinorFeatures6_BUG_FIXES_24 0x00000002 +#define chipMinorFeatures6_DEC 0x00000004 +#define chipMinorFeatures6_VS_TILE_NV12 0x00000008 +#define chipMinorFeatures6_VS_TILE_NV12_10BIT 0x00000010 + +#endif /* COMMON_XML */ diff --git a/lib/mesa/src/gallium/drivers/etnaviv/hw/isa.xml.h b/lib/mesa/src/gallium/drivers/etnaviv/hw/isa.xml.h new file mode 100644 index 000000000..f89ab0a0a --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/hw/isa.xml.h @@ -0,0 +1,312 @@ +#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 ( 35432 bytes, from 2017-10-05 21:20:32) +- copyright.xml ( 1597 bytes, from 2016-11-13 13:46:17) + +Copyright (C) 2012-2017 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_ADDLO 0x00000028 +#define INST_OPCODE_MULLO 0x00000029 +#define INST_OPCODE_BARRIER 0x0000002a +#define INST_OPCODE_SWIZZLE 0x0000002b +#define INST_OPCODE_I2I 0x0000002c +#define INST_OPCODE_I2F 0x0000002d +#define INST_OPCODE_F2I 0x0000002e +#define INST_OPCODE_F2IRND 0x0000002f +#define INST_OPCODE_F2I7 0x00000030 +#define INST_OPCODE_CMP 0x00000031 +#define INST_OPCODE_LOAD 0x00000032 +#define INST_OPCODE_STORE 0x00000033 +#define INST_OPCODE_COPYSIGN 0x00000034 +#define INST_OPCODE_GETEXP 0x00000035 +#define INST_OPCODE_GETMANT 0x00000036 +#define INST_OPCODE_NAN 0x00000037 +#define INST_OPCODE_NEXTAFTER 0x00000038 +#define INST_OPCODE_ROUNDEVEN 0x00000039 +#define INST_OPCODE_ROUNDAWAY 0x0000003a +#define INST_OPCODE_IADDSAT 0x0000003b +#define INST_OPCODE_IMULLO0 0x0000003c +#define INST_OPCODE_IMULLO1 0x0000003d +#define INST_OPCODE_IMULLOSAT0 0x0000003e +#define INST_OPCODE_IMULLOSAT1 0x0000003f +#define INST_OPCODE_IMULHI0 0x00000040 +#define INST_OPCODE_IMULHI1 0x00000041 +#define INST_OPCODE_IMUL0 0x00000042 +#define INST_OPCODE_IMUL1 0x00000043 +#define INST_OPCODE_IDIV0 0x00000044 +#define INST_OPCODE_IDIV1 0x00000045 +#define INST_OPCODE_IDIV2 0x00000046 +#define INST_OPCODE_IDIV3 0x00000047 +#define INST_OPCODE_IMOD0 0x00000048 +#define INST_OPCODE_IMOD1 0x00000049 +#define INST_OPCODE_IMOD2 0x0000004a +#define INST_OPCODE_IMOD3 0x0000004b +#define INST_OPCODE_IMADLO0 0x0000004c +#define INST_OPCODE_IMADLO1 0x0000004d +#define INST_OPCODE_IMADLOSAT0 0x0000004e +#define INST_OPCODE_IMADLOSAT1 0x0000004f +#define INST_OPCODE_IMADHI0 0x00000050 +#define INST_OPCODE_IMADHI1 0x00000051 +#define INST_OPCODE_IMADHISAT0 0x00000052 +#define INST_OPCODE_IMADHISAT1 0x00000053 +#define INST_OPCODE_HALFADD 0x00000054 +#define INST_OPCODE_HALFADDINC 0x00000055 +#define INST_OPCODE_MOVAI 0x00000056 +#define INST_OPCODE_IABS 0x00000057 +#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_OPCODE_BITSELECT 0x00000060 +#define INST_OPCODE_POPCOUNT 0x00000061 +#define INST_OPCODE_STOREB 0x00000062 +#define INST_OPCODE_RGB2YUV 0x00000063 +#define INST_OPCODE_DIV 0x00000064 +#define INST_OPCODE_ATOM_ADD 0x00000065 +#define INST_OPCODE_ATOM_XCHG 0x00000066 +#define INST_OPCODE_ATOM_CMP_XCHG 0x00000067 +#define INST_OPCODE_ATOM_MIN 0x00000068 +#define INST_OPCODE_ATOM_MAX 0x00000069 +#define INST_OPCODE_ATOM_OR 0x0000006a +#define INST_OPCODE_ATOM_AND 0x0000006b +#define INST_OPCODE_ATOM_XOR 0x0000006c +#define INST_OPCODE_BIT_REV 0x0000006d +#define INST_OPCODE_BYTE_REV 0x0000006e +#define INST_OPCODE_TEXLDLPCF 0x0000006f +#define INST_OPCODE_TEXLDGPCF 0x00000070 +#define INST_OPCODE_PACK 0x00000071 +#define INST_OPCODE_CONV 0x00000072 +#define INST_OPCODE_DP2 0x00000073 +#define INST_OPCODE_NORM_DP2 0x00000074 +#define INST_OPCODE_NORM_DP3 0x00000075 +#define INST_OPCODE_NORM_DP4 0x00000076 +#define INST_OPCODE_NORM_MUL 0x00000077 +#define INST_OPCODE_STORE_ATTR 0x00000078 +#define INST_OPCODE_LOAD_ATTR 0x00000079 +#define INST_OPCODE_EMIT 0x0000007a +#define INST_OPCODE_RESTART 0x0000007b +#define INST_OPCODE_NOP7C 0x0000007c +#define INST_OPCODE_NOP7D 0x0000007d +#define INST_OPCODE_NOP7E 0x0000007e +#define INST_OPCODE_NOP7F 0x0000007f +#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 */ diff --git a/lib/mesa/src/gallium/drivers/etnaviv/hw/state.xml.h b/lib/mesa/src/gallium/drivers/etnaviv/hw/state.xml.h new file mode 100644 index 000000000..729d0ee08 --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/hw/state.xml.h @@ -0,0 +1,560 @@ +#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 ( 26245 bytes, from 2017-10-05 21:32:06) +- common.xml ( 26135 bytes, from 2017-10-05 21:20:32) +- state_hi.xml ( 27733 bytes, from 2017-10-05 21:20:32) +- copyright.xml ( 1597 bytes, from 2016-11-13 13:46:17) +- state_2d.xml ( 51552 bytes, from 2016-11-13 13:46:17) +- state_3d.xml ( 80819 bytes, from 2017-10-05 21:20:32) +- state_vg.xml ( 5975 bytes, from 2016-11-13 13:46:17) + +Copyright (C) 2012-2017 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_GENERIC_ATTRIB(i0) (0x00000000 + 0x4*(i0)) +#define VIVS_FE_GENERIC_ATTRIB__ESIZE 0x00000004 +#define VIVS_FE_GENERIC_ATTRIB__LEN 0x00000010 + +#define VIVS_FE_GENERIC_ATTRIB_UNK006C0(i0) (0x000006c0 + 0x4*(i0)) + +#define VIVS_FE_GENERIC_ATTRIB_UNK00700(i0) (0x00000700 + 0x4*(i0)) + +#define VIVS_FE_GENERIC_ATTRIB_UNK00740(i0) (0x00000740 + 0x4*(i0)) + +#define VIVS_FE_GENERIC_ATTRIB_UNK00780(i0) (0x00000780 + 0x4*(i0)) + +#define VIVS_FE_HALTI5_UNK007C4 0x000007c4 + +#define VIVS_FE_HALTI5_UNK007D0(i0) (0x000007d0 + 0x4*(i0)) +#define VIVS_FE_HALTI5_UNK007D0__ESIZE 0x00000004 +#define VIVS_FE_HALTI5_UNK007D0__LEN 0x00000002 + +#define VIVS_FE_HALTI5_UNK007D8 0x000007d8 + +#define VIVS_FE_DESC_START 0x000007dc + +#define VIVS_FE_DESC_END 0x000007e0 + +#define VIVS_FE_DESC_AVAIL 0x000007e4 +#define VIVS_FE_DESC_AVAIL_COUNT__MASK 0x0000007f +#define VIVS_FE_DESC_AVAIL_COUNT__SHIFT 0 +#define VIVS_FE_DESC_AVAIL_COUNT(x) (((x) << VIVS_FE_DESC_AVAIL_COUNT__SHIFT) & VIVS_FE_DESC_AVAIL_COUNT__MASK) + +#define VIVS_FE_FENCE_WAIT_DATA_LOW 0x000007e8 + +#define VIVS_FE_FENCE_WAIT_DATA_HIGH 0x000007f4 + +#define VIVS_FE_ROBUSTNESS_UNK007F8 0x000007f8 + +#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_SEMAPHORE_TOKEN_UNK28__MASK 0x30000000 +#define VIVS_GL_SEMAPHORE_TOKEN_UNK28__SHIFT 28 +#define VIVS_GL_SEMAPHORE_TOKEN_UNK28(x) (((x) << VIVS_GL_SEMAPHORE_TOKEN_UNK28__SHIFT) & VIVS_GL_SEMAPHORE_TOKEN_UNK28__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_CACHE_UNK10 0x00000400 +#define VIVS_GL_FLUSH_CACHE_UNK11 0x00000800 +#define VIVS_GL_FLUSH_CACHE_DESCRIPTOR_UNK12 0x00001000 +#define VIVS_GL_FLUSH_CACHE_DESCRIPTOR_UNK13 0x00002000 + +#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_OCCLUSION_QUERY_ADDR 0x00003824 + +#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_UNK0382C 0x0000382c + +#define VIVS_GL_OCCLUSION_QUERY_CONTROL 0x00003830 + +#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_BUG_FIXES 0x00003860 + +#define VIVS_GL_FENCE_OUT_ADDRESS 0x00003868 + +#define VIVS_GL_FENCE_OUT_DATA_LOW 0x0000386c + +#define VIVS_GL_HALTI5_UNK03884 0x00003884 + +#define VIVS_GL_HALTI5_UNK03888 0x00003888 + +#define VIVS_GL_GS_UNK0388C 0x0000388c + +#define VIVS_GL_FENCE_OUT_DATA_HIGH 0x00003898 + +#define VIVS_GL_SHADER_INDEX 0x0000389c + +#define VIVS_GL_GS_UNK038A0(i0) (0x000038a0 + 0x4*(i0)) +#define VIVS_GL_GS_UNK038A0__ESIZE 0x00000004 +#define VIVS_GL_GS_UNK038A0__LEN 0x00000008 + +#define VIVS_GL_HALTI5_UNK038C0(i0) (0x000038c0 + 0x4*(i0)) +#define VIVS_GL_HALTI5_UNK038C0__ESIZE 0x00000004 +#define VIVS_GL_HALTI5_UNK038C0__LEN 0x00000010 + +#define VIVS_GL_SECURITY_UNK3900 0x00003900 + +#define VIVS_GL_SECURITY_UNK3904 0x00003904 + +#define VIVS_GL_UNK03A00 0x00003a00 + +#define VIVS_GL_UNK03A04 0x00003a04 + +#define VIVS_GL_UNK03A08 0x00003a08 + +#define VIVS_GL_UNK03A0C 0x00003a0c + +#define VIVS_GL_UNK03A10 0x00003a10 + +#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_VERTEX_STREAMS(i0) (0x00000000 + 0x4*(i0)) +#define VIVS_NFE_VERTEX_STREAMS__ESIZE 0x00000004 +#define VIVS_NFE_VERTEX_STREAMS__LEN 0x00000010 + +#define VIVS_NFE_VERTEX_STREAMS_BASE_ADDR(i0) (0x00014600 + 0x4*(i0)) + +#define VIVS_NFE_VERTEX_STREAMS_CONTROL(i0) (0x00014640 + 0x4*(i0)) + +#define VIVS_NFE_VERTEX_STREAMS_UNK14680(i0) (0x00014680 + 0x4*(i0)) + +#define VIVS_NFE_VERTEX_STREAMS_ROBUSTNESS_UNK146C0(i0) (0x000146c0 + 0x4*(i0)) + +#define VIVS_NFE_HALTI5_UNK17800(i0) (0x00017800 + 0x4*(i0)) +#define VIVS_NFE_HALTI5_UNK17800__ESIZE 0x00000004 +#define VIVS_NFE_HALTI5_UNK17800__LEN 0x00000020 + +#define VIVS_NFE_HALTI5_UNK17880(i0) (0x00017880 + 0x4*(i0)) +#define VIVS_NFE_HALTI5_UNK17880__ESIZE 0x00000004 +#define VIVS_NFE_HALTI5_UNK17880__LEN 0x00000020 + +#define VIVS_NFE_HALTI5_UNK17900(i0) (0x00017900 + 0x4*(i0)) +#define VIVS_NFE_HALTI5_UNK17900__ESIZE 0x00000004 +#define VIVS_NFE_HALTI5_UNK17900__LEN 0x00000020 + +#define VIVS_NFE_HALTI5_UNK17980(i0) (0x00017980 + 0x4*(i0)) +#define VIVS_NFE_HALTI5_UNK17980__ESIZE 0x00000004 +#define VIVS_NFE_HALTI5_UNK17980__LEN 0x00000020 + +#define VIVS_NFE_HALTI5_UNK17A00(i0) (0x00017a00 + 0x4*(i0)) +#define VIVS_NFE_HALTI5_UNK17A00__ESIZE 0x00000004 +#define VIVS_NFE_HALTI5_UNK17A00__LEN 0x00000020 + +#define VIVS_NFE_HALTI5_UNK17A80(i0) (0x00017a80 + 0x4*(i0)) +#define VIVS_NFE_HALTI5_UNK17A80__ESIZE 0x00000004 +#define VIVS_NFE_HALTI5_UNK17A80__LEN 0x00000020 + +#define VIVS_BLT 0x00000000 + +#define VIVS_BLT_UNK14000 0x00014000 + +#define VIVS_BLT_UNK14008 0x00014008 + +#define VIVS_BLT_UNK1400C 0x0001400c + +#define VIVS_BLT_UNK14010 0x00014010 + +#define VIVS_BLT_UNK14014 0x00014014 + +#define VIVS_BLT_UNK14018 0x00014018 + +#define VIVS_BLT_UNK14020 0x00014020 + +#define VIVS_BLT_UNK14024 0x00014024 + +#define VIVS_BLT_UNK14028 0x00014028 + +#define VIVS_BLT_UNK1402C 0x0001402c + +#define VIVS_BLT_UNK14030 0x00014030 + +#define VIVS_BLT_UNK14034 0x00014034 + +#define VIVS_BLT_UNK14038 0x00014038 + +#define VIVS_BLT_UNK1403C 0x0001403c + +#define VIVS_BLT_UNK14040 0x00014040 + +#define VIVS_BLT_UNK14044 0x00014044 + +#define VIVS_BLT_UNK14048 0x00014048 + +#define VIVS_BLT_UNK1404C 0x0001404c + +#define VIVS_BLT_UNK14050 0x00014050 + +#define VIVS_BLT_UNK14054 0x00014054 + +#define VIVS_BLT_UNK14058 0x00014058 + +#define VIVS_BLT_UNK1405C 0x0001405c + +#define VIVS_BLT_UNK14060 0x00014060 + +#define VIVS_BLT_UNK14064 0x00014064 + +#define VIVS_BLT_UNK1409C 0x0001409c + +#define VIVS_BLT_UNK140A0 0x000140a0 + +#define VIVS_BLT_FENCE_OUT_ADDRESS 0x000140a4 + +#define VIVS_BLT_FENCE_OUT_DATA_LOW 0x000140a8 + +#define VIVS_BLT_UNK140AC 0x000140ac + +#define VIVS_BLT_FENCE_OUT_DATA_HIGH 0x000140b4 + +#define VIVS_BLT_ENABLE 0x000140b8 +#define VIVS_BLT_ENABLE_ENABLE 0x00000001 + +#define VIVS_BLT_UNK140BC 0x000140bc + +#define VIVS_DUMMY 0x00000000 + +#define VIVS_DUMMY_DUMMY 0x0003fffc + + +#endif /* STATE_XML */ diff --git a/lib/mesa/src/gallium/drivers/etnaviv/hw/state_3d.xml.h b/lib/mesa/src/gallium/drivers/etnaviv/hw/state_3d.xml.h new file mode 100644 index 000000000..9084e643d --- /dev/null +++ b/lib/mesa/src/gallium/drivers/etnaviv/hw/state_3d.xml.h @@ -0,0 +1,1697 @@ +#ifndef STATE_3D_XML +#define STATE_3D_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 ( 26245 bytes, from 2017-10-05 21:32:06) +- common.xml ( 26135 bytes, from 2017-10-05 21:20:32) +- state_hi.xml ( 27733 bytes, from 2017-10-05 21:20:32) +- copyright.xml ( 1597 bytes, from 2016-11-13 13:46:17) +- state_2d.xml ( 51552 bytes, from 2016-11-13 13:46:17) +- state_3d.xml ( 80819 bytes, from 2017-10-05 21:20:32) +- state_vg.xml ( 5975 bytes, from 2016-11-13 13:46:17) + +Copyright (C) 2012-2017 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 COMPARE_FUNC_NEVER 0x00000000 +#define COMPARE_FUNC_LESS 0x00000001 +#define COMPARE_FUNC_EQUAL 0x00000002 +#define COMPARE_FUNC_LEQUAL 0x00000003 +#define COMPARE_FUNC_GREATER 0x00000004 +#define COMPARE_FUNC_NOTEQUAL 0x00000005 +#define COMPARE_FUNC_GEQUAL 0x00000006 +#define COMPARE_FUNC_ALWAYS 0x00000007 +#define STENCIL_OP_KEEP 0x00000000 +#define STENCIL_OP_ZERO 0x00000001 +#define STENCIL_OP_REPLACE 0x00000002 +#define STENCIL_OP_INCR 0x00000003 +#define STENCIL_OP_DECR 0x00000004 +#define STENCIL_OP_INVERT 0x00000005 +#define STENCIL_OP_INCR_WRAP 0x00000006 +#define STENCIL_OP_DECR_WRAP 0x00000007 +#define BLEND_EQ_ADD 0x00000000 +#define BLEND_EQ_SUBTRACT 0x00000001 +#define BLEND_EQ_REVERSE_SUBTRACT 0x00000002 +#define BLEND_EQ_MIN 0x00000003 +#define BLEND_EQ_MAX 0x00000004 +#define BLEND_FUNC_ZERO 0x00000000 +#define BLEND_FUNC_ONE 0x00000001 +#define BLEND_FUNC_SRC_COLOR 0x00000002 +#define BLEND_FUNC_ONE_MINUS_SRC_COLOR 0x00000003 +#define BLEND_FUNC_SRC_ALPHA 0x00000004 +#define BLEND_FUNC_ONE_MINUS_SRC_ALPHA 0x00000005 +#define BLEND_FUNC_DST_ALPHA 0x00000006 +#define BLEND_FUNC_ONE_MINUS_DST_ALPHA 0x00000007 +#define BLEND_FUNC_DST_COLOR 0x00000008 +#define BLEND_FUNC_ONE_MINUS_DST_COLOR 0x00000009 +#define BLEND_FUNC_SRC_ALPHA_SATURATE 0x0000000a +#define BLEND_FUNC_CONSTANT_ALPHA 0x0000000b +#define BLEND_FUNC_ONE_MINUS_CONSTANT_ALPHA 0x0000000c +#define BLEND_FUNC_CONSTANT_COLOR 0x0000000d +#define BLEND_FUNC_ONE_MINUS_CONSTANT_COLOR 0x0000000e +#define RS_FORMAT_X4R4G4B4 0x00000000 +#define RS_FORMAT_A4R4G4B4 0x00000001 +#define RS_FORMAT_X1R5G5B5 0x00000002 +#define RS_FORMAT_A1R5G5B5 0x00000003 +#define RS_FORMAT_R5G6B5 0x00000004 +#define RS_FORMAT_X8R8G8B8 0x00000005 +#define RS_FORMAT_A8R8G8B8 0x00000006 +#define RS_FORMAT_YUY2 0x00000007 +#define RS_FORMAT_R16F 0x00000011 +#define RS_FORMAT_G16R16F 0x00000012 +#define RS_FORMAT_A16B16G16R16F 0x00000013 +#define RS_FORMAT_R32F 0x00000014 +#define RS_FORMAT_G32R32F 0x00000015 +#define RS_FORMAT_A2B10G10R10 0x00000016 +#define RS_FORMAT_R8I 0x00000017 +#define RS_FORMAT_G8R8I 0x00000018 +#define RS_FORMAT_A8B8G8R8I 0x00000019 +#define RS_FORMAT_R16I 0x0000001a +#define RS_FORMAT_G16R16I 0x0000001b +#define RS_FORMAT_A16B16G16R16I 0x0000001c +#define RS_FORMAT_B10G11R11F 0x0000001d +#define RS_FORMAT_A2B10G10R10UI 0x0000001e +#define RS_FORMAT_G8R8 0x0000001f +#define RS_FORMAT_R8 0x00000023 +#define TEXTURE_FORMAT_NONE 0x00000000 +#define TEXTURE_FORMAT_A8 0x00000001 +#define TEXTURE_FORMAT_L8 0x00000002 +#define TEXTURE_FORMAT_I8 0x00000003 +#define TEXTURE_FORMAT_A8L8 0x00000004 +#define TEXTURE_FORMAT_A4R4G4B4 0x00000005 +#define TEXTURE_FORMAT_X4R4G4B4 0x00000006 +#define TEXTURE_FORMAT_A8R8G8B8 0x00000007 +#define TEXTURE_FORMAT_X8R8G8B8 0x00000008 +#define TEXTURE_FORMAT_A8B8G8R8 0x00000009 +#define TEXTURE_FORMAT_X8B8G8R8 0x0000000a +#define TEXTURE_FORMAT_R5G6B5 0x0000000b +#define TEXTURE_FORMAT_A1R5G5B5 0x0000000c +#define TEXTURE_FORMAT_X1R5G5B5 0x0000000d +#define TEXTURE_FORMAT_YUY2 0x0000000e +#define TEXTURE_FORMAT_UYVY 0x0000000f +#define TEXTURE_FORMAT_D16 0x00000010 +#define TEXTURE_FORMAT_D24S8 0x00000011 +#define TEXTURE_FORMAT_DXT1 0x00000013 +#define TEXTURE_FORMAT_DXT2_DXT3 0x00000014 +#define TEXTURE_FORMAT_DXT4_DXT5 0x00000015 +#define TEXTURE_FORMAT_E5B9G9R9 0x0000001d +#define TEXTURE_FORMAT_ETC1 0x0000001e +#define TEXTURE_FORMAT_EXT_NONE 0x00000000 +#define TEXTURE_FORMAT_EXT_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x00000001 +#define TEXTURE_FORMAT_EXT_RGBA8_ETC2_EAC 0x00000002 +#define TEXTURE_FORMAT_EXT_R11_EAC 0x00000003 +#define TEXTURE_FORMAT_EXT_RG11_EAC 0x00000004 +#define TEXTURE_FORMAT_EXT_SIGNED_RG11_EAC 0x00000005 +#define TEXTURE_FORMAT_EXT_G8R8 0x00000006 +#define TEXTURE_FORMAT_EXT_R16F 0x00000007 +#define TEXTURE_FORMAT_EXT_G16R16F 0x00000008 +#define TEXTURE_FORMAT_EXT_A16B16G16R16F 0x00000009 +#define TEXTURE_FORMAT_EXT_R32F 0x0000000a +#define TEXTURE_FORMAT_EXT_G32R32F 0x0000000b +#define TEXTURE_FORMAT_EXT_A2B10G10R10 0x0000000c +#define TEXTURE_FORMAT_EXT_SIGNED_R11_EAC 0x0000000d +#define TEXTURE_FORMAT_EXT_R8_SNORM 0x0000000e +#define TEXTURE_FORMAT_EXT_G8R8_SNORM 0x0000000f +#define TEXTURE_FORMAT_EXT_X8B8G8R8_SNORM 0x00000010 +#define TEXTURE_FORMAT_EXT_A8B8G8R8_SNORM 0x00000011 +#define TEXTURE_FORMAT_EXT_ASTC 0x00000014 +#define TEXTURE_FORMAT_EXT_R8I 0x00000015 +#define TEXTURE_FORMAT_EXT_G8R8I 0x00000016 +#define TEXTURE_FORMAT_EXT_A8B8G8R8I 0x00000017 +#define TEXTURE_FORMAT_EXT_R16I 0x00000018 +#define TEXTURE_FORMAT_EXT_G16R16I 0x00000019 +#define TEXTURE_FORMAT_EXT_A16B16G16R16I 0x0000001a +#define TEXTURE_FORMAT_EXT_B10G11R11F 0x0000001b +#define TEXTURE_FORMAT_EXT_A2B10G10R10UI 0x0000001c +#define TEXTURE_FILTER_NONE 0x00000000 +#define TEXTURE_FILTER_NEAREST 0x00000001 +#define TEXTURE_FILTER_LINEAR 0x00000002 +#define TEXTURE_FILTER_ANISOTROPIC 0x00000003 +#define TEXTURE_TYPE_NONE 0x00000000 +#define TEXTURE_TYPE_1D 0x00000001 +#define TEXTURE_TYPE_2D 0x00000002 +#define TEXTURE_TYPE_3D 0x00000003 +#define TEXTURE_TYPE_CUBE_MAP 0x00000005 +#define TEXTURE_WRAPMODE_REPEAT 0x00000000 +#define TEXTURE_WRAPMODE_MIRRORED_REPEAT 0x00000001 +#define TEXTURE_WRAPMODE_CLAMP_TO_EDGE 0x00000002 +#define TEXTURE_FACE_POS_X 0x00000000 +#define TEXTURE_FACE_NEG_X 0x00000001 +#define TEXTURE_FACE_POS_Y 0x00000002 +#define TEXTURE_FACE_NEG_Y 0x00000003 +#define TEXTURE_FACE_POS_Z 0x00000004 +#define TEXTURE_FACE_NEG_Z 0x00000005 +#define TEXTURE_SWIZZLE_RED 0x00000000 +#define TEXTURE_SWIZZLE_GREEN 0x00000001 +#define TEXTURE_SWIZZLE_BLUE 0x00000002 +#define TEXTURE_SWIZZLE_ALPHA 0x00000003 +#define TEXTURE_SWIZZLE_ZERO 0x00000004 +#define TEXTURE_SWIZZLE_ONE 0x00000005 +#define TEXTURE_HALIGN_FOUR 0x00000000 +#define TEXTURE_HALIGN_SIXTEEN 0x00000001 +#define TEXTURE_HALIGN_SUPER_TILED 0x00000002 +#define TEXTURE_HALIGN_SPLIT_TILED 0x00000003 +#define TEXTURE_HALIGN_SPLIT_SUPER_TILED 0x00000004 +#define LOGIC_OP_CLEAR 0x00000000 +#define LOGIC_OP_NOR 0x00000001 +#define LOGIC_OP_AND_INVERTED 0x00000002 +#define LOGIC_OP_COPY_INVERTED 0x00000003 +#define LOGIC_OP_AND_REVERSE 0x00000004 +#define LOGIC_OP_INVERT 0x00000005 +#define LOGIC_OP_XOR 0x00000006 +#define LOGIC_OP_NAND 0x00000007 +#define LOGIC_OP_AND 0x00000008 +#define LOGIC_OP_EQUIV 0x00000009 +#define LOGIC_OP_NOOP 0x0000000a +#define LOGIC_OP_OR_INVERTED 0x0000000b +#define LOGIC_OP_COPY 0x0000000c +#define LOGIC_OP_OR_REVERSE 0x0000000d +#define LOGIC_OP_OR 0x0000000e +#define LOGIC_OP_SET 0x0000000f +#define VIVS_VS 0x00000000 + +#define VIVS_VS_END_PC 0x00000800 + +#define VIVS_VS_OUTPUT_COUNT 0x00000804 + +#define VIVS_VS_INPUT_COUNT 0x00000808 +#define VIVS_VS_INPUT_COUNT_COUNT__MASK 0x0000000f +#define VIVS_VS_INPUT_COUNT_COUNT__SHIFT 0 +#define VIVS_VS_INPUT_COUNT_COUNT(x) (((x) << VIVS_VS_INPUT_COUNT_COUNT__SHIFT) & VIVS_VS_INPUT_COUNT_COUNT__MASK) +#define VIVS_VS_INPUT_COUNT_UNK8__MASK 0x00001f00 +#define VIVS_VS_INPUT_COUNT_UNK8__SHIFT 8 +#define VIVS_VS_INPUT_COUNT_UNK8(x) (((x) << VIVS_VS_INPUT_COUNT_UNK8__SHIFT) & VIVS_VS_INPUT_COUNT_UNK8__MASK) + +#define VIVS_VS_TEMP_REGISTER_CONTROL 0x0000080c +#define VIVS_VS_TEMP_REGISTER_CONTROL_NUM_TEMPS__MASK 0x0000003f +#define VIVS_VS_TEMP_REGISTER_CONTROL_NUM_TEMPS__SHIFT 0 +#define VIVS_VS_TEMP_REGISTER_CONTROL_NUM_TEMPS(x) (((x) << VIVS_VS_TEMP_REGISTER_CONTROL_NUM_TEMPS__SHIFT) & VIVS_VS_TEMP_REGISTER_CONTROL_NUM_TEMPS__MASK) + +#define VIVS_VS_OUTPUT(i0) (0x00000810 + 0x4*(i0)) +#define VIVS_VS_OUTPUT__ESIZE 0x00000004 +#define VIVS_VS_OUTPUT__LEN 0x00000004 +#define VIVS_VS_OUTPUT_O0__MASK 0x000000ff +#define VIVS_VS_OUTPUT_O0__SHIFT 0 +#define VIVS_VS_OUTPUT_O0(x) (((x) << VIVS_VS_OUTPUT_O0__SHIFT) & VIVS_VS_OUTPUT_O0__MASK) +#define VIVS_VS_OUTPUT_O1__MASK 0x0000ff00 +#define VIVS_VS_OUTPUT_O1__SHIFT 8 +#define VIVS_VS_OUTPUT_O1(x) (((x) << VIVS_VS_OUTPUT_O1__SHIFT) & VIVS_VS_OUTPUT_O1__MASK) +#define VIVS_VS_OUTPUT_O2__MASK 0x00ff0000 +#define VIVS_VS_OUTPUT_O2__SHIFT 16 +#define VIVS_VS_OUTPUT_O2(x) (((x) << VIVS_VS_OUTPUT_O2__SHIFT) & VIVS_VS_OUTPUT_O2__MASK) +#define VIVS_VS_OUTPUT_O3__MASK 0xff000000 +#define VIVS_VS_OUTPUT_O3__SHIFT 24 +#define VIVS_VS_OUTPUT_O3(x) (((x) << VIVS_VS_OUTPUT_O3__SHIFT) & VIVS_VS_OUTPUT_O3__MASK) + +#define VIVS_VS_INPUT(i0) (0x00000820 + 0x4*(i0)) +#define VIVS_VS_INPUT__ESIZE 0x00000004 +#define VIVS_VS_INPUT__LEN 0x00000004 +#define VIVS_VS_INPUT_I0__MASK 0x000000ff +#define VIVS_VS_INPUT_I0__SHIFT 0 +#define VIVS_VS_INPUT_I0(x) (((x) << VIVS_VS_INPUT_I0__SHIFT) & VIVS_VS_INPUT_I0__MASK) +#define VIVS_VS_INPUT_I1__MASK 0x0000ff00 +#define VIVS_VS_INPUT_I1__SHIFT 8 +#define VIVS_VS_INPUT_I1(x) (((x) << VIVS_VS_INPUT_I1__SHIFT) & VIVS_VS_INPUT_I1__MASK) +#define VIVS_VS_INPUT_I2__MASK 0x00ff0000 +#define VIVS_VS_INPUT_I2__SHIFT 16 +#define VIVS_VS_INPUT_I2(x) (((x) << VIVS_VS_INPUT_I2__SHIFT) & VIVS_VS_INPUT_I2__MASK) +#define VIVS_VS_INPUT_I3__MASK 0xff000000 +#define VIVS_VS_INPUT_I3__SHIFT 24 +#define VIVS_VS_INPUT_I3(x) (((x) << VIVS_VS_INPUT_I3__SHIFT) & VIVS_VS_INPUT_I3__MASK) + +#define VIVS_VS_LOAD_BALANCING 0x00000830 +#define VIVS_VS_LOAD_BALANCING_A__MASK 0x000000ff +#define VIVS_VS_LOAD_BALANCING_A__SHIFT 0 +#define VIVS_VS_LOAD_BALANCING_A(x) (((x) << VIVS_VS_LOAD_BALANCING_A__SHIFT) & VIVS_VS_LOAD_BALANCING_A__MASK) +#define VIVS_VS_LOAD_BALANCING_B__MASK 0x0000ff00 +#define VIVS_VS_LOAD_BALANCING_B__SHIFT 8 +#define VIVS_VS_LOAD_BALANCING_B(x) (((x) << VIVS_VS_LOAD_BALANCING_B__SHIFT) & VIVS_VS_LOAD_BALANCING_B__MASK) +#define VIVS_VS_LOAD_BALANCING_C__MASK 0x00ff0000 +#define VIVS_VS_LOAD_BALANCING_C__SHIFT 16 +#define VIVS_VS_LOAD_BALANCING_C(x) (((x) << VIVS_VS_LOAD_BALANCING_C__SHIFT) & VIVS_VS_LOAD_BALANCING_C__MASK) +#define VIVS_VS_LOAD_BALANCING_D__MASK 0xff000000 +#define VIVS_VS_LOAD_BALANCING_D__SHIFT 24 +#define VIVS_VS_LOAD_BALANCING_D(x) (((x) << VIVS_VS_LOAD_BALANCING_D__SHIFT) & VIVS_VS_LOAD_BALANCING_D__MASK) + +#define VIVS_VS_PERF_COUNTER 0x00000834 + +#define VIVS_VS_START_PC 0x00000838 + +#define VIVS_VS_UNK00850 0x00000850 + +#define VIVS_VS_UNK00854 0x00000854 + +#define VIVS_VS_UNK00858 0x00000858 + +#define VIVS_VS_RANGE 0x0000085c +#define VIVS_VS_RANGE_LOW__MASK 0x0000ffff +#define VIVS_VS_RANGE_LOW__SHIFT 0 +#define VIVS_VS_RANGE_LOW(x) (((x) << VIVS_VS_RANGE_LOW__SHIFT) & VIVS_VS_RANGE_LOW__MASK) +#define VIVS_VS_RANGE_HIGH__MASK 0xffff0000 +#define VIVS_VS_RANGE_HIGH__SHIFT 16 +#define VIVS_VS_RANGE_HIGH(x) (((x) << VIVS_VS_RANGE_HIGH__SHIFT) & VIVS_VS_RANGE_HIGH__MASK) + +#define VIVS_VS_UNIFORM_CACHE 0x00000860 +#define VIVS_VS_UNIFORM_CACHE_FLUSH 0x00000001 +#define VIVS_VS_UNIFORM_CACHE_PS 0x00000010 +#define VIVS_VS_UNIFORM_CACHE_UNK12 0x00001000 + +#define VIVS_VS_UNIFORM_BASE 0x00000864 + +#define VIVS_VS_ICACHE_CONTROL 0x00000868 +#define VIVS_VS_ICACHE_CONTROL_ENABLE 0x00000001 +#define VIVS_VS_ICACHE_CONTROL_FLUSH_VS 0x00000010 +#define VIVS_VS_ICACHE_CONTROL_FLUSH_PS 0x00000020 + +#define VIVS_VS_INST_ADDR 0x0000086c + +#define VIVS_VS_HALTI5_UNK00870 0x00000870 + +#define VIVS_VS_HALTI5_UNK00874 0x00000874 + +#define VIVS_VS_HALTI5_UNK00878 0x00000878 + +#define VIVS_VS_HALTI5_UNK0087C 0x0000087c + +#define VIVS_VS_HALTI5_UNK00880 0x00000880 + +#define VIVS_VS_HALTI1_UNK00884 0x00000884 + +#define VIVS_VS_UNK0088C 0x0000088c + +#define VIVS_VS_ICACHE_UNK00890 0x00000890 + +#define VIVS_VS_HALTI5_UNK00898(i0) (0x00000898 + 0x4*(i0)) +#define VIVS_VS_HALTI5_UNK00898__ESIZE 0x00000004 +#define VIVS_VS_HALTI5_UNK00898__LEN 0x00000002 + +#define VIVS_VS_HALTI5_UNK008A0 0x000008a0 + +#define VIVS_VS_HALTI5_UNK008A8 0x000008a8 + +#define VIVS_VS_ICACHE_INVALIDATE 0x000008b0 +#define VIVS_VS_ICACHE_INVALIDATE_UNK0 0x00000001 +#define VIVS_VS_ICACHE_INVALIDATE_UNK1 0x00000002 +#define VIVS_VS_ICACHE_INVALIDATE_UNK2 0x00000004 +#define VIVS_VS_ICACHE_INVALIDATE_UNK3 0x00000008 +#define VIVS_VS_ICACHE_INVALIDATE_UNK4 0x00000010 + +#define VIVS_VS_HALTI5_UNK008B8 0x000008b8 + +#define VIVS_VS_HALTI5_UNK008BC 0x000008bc + +#define VIVS_VS_HALTI5_UNK008C0(i0) (0x000008c0 + 0x4*(i0)) +#define VIVS_VS_HALTI5_UNK008C0__ESIZE 0x00000004 +#define VIVS_VS_HALTI5_UNK008C0__LEN 0x00000008 + +#define VIVS_VS_HALTI5_UNK008E0(i0) (0x000008e0 + 0x4*(i0)) +#define VIVS_VS_HALTI5_UNK008E0__ESIZE 0x00000004 +#define VIVS_VS_HALTI5_UNK008E0__LEN 0x00000008 + +#define VIVS_VS_INST_MEM(i0) (0x00004000 + 0x4*(i0)) +#define VIVS_VS_INST_MEM__ESIZE 0x00000004 +#define VIVS_VS_INST_MEM__LEN 0x00000400 + +#define VIVS_VS_UNIFORMS(i0) (0x00005000 + 0x4*(i0)) +#define VIVS_VS_UNIFORMS__ESIZE 0x00000004 +#define VIVS_VS_UNIFORMS__LEN 0x00000400 + +#define VIVS_VS_HALTI5_UNK15600 0x00015600 + +#define VIVS_VS_HALTI5_UNK15604 0x00015604 + +#define VIVS_CL 0x00000000 + +#define VIVS_CL_CONFIG 0x00000900 +#define VIVS_CL_CONFIG_DIMENSIONS__MASK 0x00000003 +#define VIVS_CL_CONFIG_DIMENSIONS__SHIFT 0 +#define VIVS_CL_CONFIG_DIMENSIONS(x) (((x) << VIVS_CL_CONFIG_DIMENSIONS__SHIFT) & VIVS_CL_CONFIG_DIMENSIONS__MASK) +#define VIVS_CL_CONFIG_TRAVERSE_ORDER__MASK 0x00000070 +#define VIVS_CL_CONFIG_TRAVERSE_ORDER__SHIFT 4 +#define VIVS_CL_CONFIG_TRAVERSE_ORDER(x) (((x) << VIVS_CL_CONFIG_TRAVERSE_ORDER__SHIFT) & VIVS_CL_CONFIG_TRAVERSE_ORDER__MASK) +#define VIVS_CL_CONFIG_ENABLE_SWATH_X 0x00000100 +#define VIVS_CL_CONFIG_ENABLE_SWATH_Y 0x00000200 +#define VIVS_CL_CONFIG_ENABLE_SWATH_Z 0x00000400 +#define VIVS_CL_CONFIG_SWATH_SIZE_X__MASK 0x0000f000 +#define VIVS_CL_CONFIG_SWATH_SIZE_X__SHIFT 12 +#define VIVS_CL_CONFIG_SWATH_SIZE_X(x) (((x) << VIVS_CL_CONFIG_SWATH_SIZE_X__SHIFT) & VIVS_CL_CONFIG_SWATH_SIZE_X__MASK) +#define VIVS_CL_CONFIG_SWATH_SIZE_Y__MASK 0x000f0000 +#define VIVS_CL_CONFIG_SWATH_SIZE_Y__SHIFT 16 +#define VIVS_CL_CONFIG_SWATH_SIZE_Y(x) (((x) << VIVS_CL_CONFIG_SWATH_SIZE_Y__SHIFT) & VIVS_CL_CONFIG_SWATH_SIZE_Y__MASK) +#define VIVS_CL_CONFIG_SWATH_SIZE_Z__MASK 0x00f00000 +#define VIVS_CL_CONFIG_SWATH_SIZE_Z__SHIFT 20 +#define VIVS_CL_CONFIG_SWATH_SIZE_Z(x) (((x) << VIVS_CL_CONFIG_SWATH_SIZE_Z__SHIFT) & VIVS_CL_CONFIG_SWATH_SIZE_Z__MASK) +#define VIVS_CL_CONFIG_VALUE_ORDER__MASK 0x07000000 +#define VIVS_CL_CONFIG_VALUE_ORDER__SHIFT 24 +#define VIVS_CL_CONFIG_VALUE_ORDER(x) (((x) << VIVS_CL_CONFIG_VALUE_ORDER__SHIFT) & VIVS_CL_CONFIG_VALUE_ORDER__MASK) + +#define VIVS_CL_GLOBAL_X 0x00000904 +#define VIVS_CL_GLOBAL_X_SIZE__MASK 0x0000ffff +#define VIVS_CL_GLOBAL_X_SIZE__SHIFT 0 +#define VIVS_CL_GLOBAL_X_SIZE(x) (((x) << VIVS_CL_GLOBAL_X_SIZE__SHIFT) & VIVS_CL_GLOBAL_X_SIZE__MASK) +#define VIVS_CL_GLOBAL_X_OFFSET__MASK 0xffff0000 +#define VIVS_CL_GLOBAL_X_OFFSET__SHIFT 16 +#define VIVS_CL_GLOBAL_X_OFFSET(x) (((x) << VIVS_CL_GLOBAL_X_OFFSET__SHIFT) & VIVS_CL_GLOBAL_X_OFFSET__MASK) + +#define VIVS_CL_GLOBAL_Y 0x00000908 +#define VIVS_CL_GLOBAL_Y_SIZE__MASK 0x0000ffff +#define VIVS_CL_GLOBAL_Y_SIZE__SHIFT 0 +#define VIVS_CL_GLOBAL_Y_SIZE(x) (((x) << VIVS_CL_GLOBAL_Y_SIZE__SHIFT) & VIVS_CL_GLOBAL_Y_SIZE__MASK) +#define VIVS_CL_GLOBAL_Y_OFFSET__MASK 0xffff0000 +#define VIVS_CL_GLOBAL_Y_OFFSET__SHIFT 16 +#define VIVS_CL_GLOBAL_Y_OFFSET(x) (((x) << VIVS_CL_GLOBAL_Y_OFFSET__SHIFT) & VIVS_CL_GLOBAL_Y_OFFSET__MASK) + +#define VIVS_CL_GLOBAL_Z 0x0000090c +#define VIVS_CL_GLOBAL_Z_SIZE__MASK 0x0000ffff +#define VIVS_CL_GLOBAL_Z_SIZE__SHIFT 0 +#define VIVS_CL_GLOBAL_Z_SIZE(x) (((x) << VIVS_CL_GLOBAL_Z_SIZE__SHIFT) & VIVS_CL_GLOBAL_Z_SIZE__MASK) +#define VIVS_CL_GLOBAL_Z_OFFSET__MASK 0xffff0000 +#define VIVS_CL_GLOBAL_Z_OFFSET__SHIFT 16 +#define VIVS_CL_GLOBAL_Z_OFFSET(x) (((x) << VIVS_CL_GLOBAL_Z_OFFSET__SHIFT) & VIVS_CL_GLOBAL_Z_OFFSET__MASK) + +#define VIVS_CL_WORKGROUP_X 0x00000910 +#define VIVS_CL_WORKGROUP_X_SIZE__MASK 0x000003ff +#define VIVS_CL_WORKGROUP_X_SIZE__SHIFT 0 +#define VIVS_CL_WORKGROUP_X_SIZE(x) (((x) << VIVS_CL_WORKGROUP_X_SIZE__SHIFT) & VIVS_CL_WORKGROUP_X_SIZE__MASK) +#define VIVS_CL_WORKGROUP_X_COUNT__MASK 0xffff0000 +#define VIVS_CL_WORKGROUP_X_COUNT__SHIFT 16 +#define VIVS_CL_WORKGROUP_X_COUNT(x) (((x) << VIVS_CL_WORKGROUP_X_COUNT__SHIFT) & VIVS_CL_WORKGROUP_X_COUNT__MASK) + +#define VIVS_CL_WORKGROUP_Y 0x00000914 +#define VIVS_CL_WORKGROUP_Y_SIZE__MASK 0x000003ff +#define VIVS_CL_WORKGROUP_Y_SIZE__SHIFT 0 +#define VIVS_CL_WORKGROUP_Y_SIZE(x) (((x) << VIVS_CL_WORKGROUP_Y_SIZE__SHIFT) & VIVS_CL_WORKGROUP_Y_SIZE__MASK) +#define VIVS_CL_WORKGROUP_Y_COUNT__MASK 0xffff0000 +#define VIVS_CL_WORKGROUP_Y_COUNT__SHIFT 16 +#define VIVS_CL_WORKGROUP_Y_COUNT(x) (((x) << VIVS_CL_WORKGROUP_Y_COUNT__SHIFT) & VIVS_CL_WORKGROUP_Y_COUNT__MASK) + +#define VIVS_CL_WORKGROUP_Z 0x00000918 +#define VIVS_CL_WORKGROUP_Z_SIZE__MASK 0x000003ff +#define VIVS_CL_WORKGROUP_Z_SIZE__SHIFT 0 +#define VIVS_CL_WORKGROUP_Z_SIZE(x) (((x) << VIVS_CL_WORKGROUP_Z_SIZE__SHIFT) & VIVS_CL_WORKGROUP_Z_SIZE__MASK) +#define VIVS_CL_WORKGROUP_Z_COUNT__MASK 0xffff0000 +#define VIVS_CL_WORKGROUP_Z_COUNT__SHIFT 16 +#define VIVS_CL_WORKGROUP_Z_COUNT(x) (((x) << VIVS_CL_WORKGROUP_Z_COUNT__SHIFT) & VIVS_CL_WORKGROUP_Z_COUNT__MASK) + +#define VIVS_CL_THREAD_ALLOCATION 0x0000091c + +#define VIVS_CL_KICKER 0x00000920 + +#define VIVS_CL_UNK00924 0x00000924 + +#define VIVS_CL_UNK00940 0x00000940 + +#define VIVS_CL_UNK00944 0x00000944 + +#define VIVS_CL_UNK00948 0x00000948 + +#define VIVS_CL_UNK0094C 0x0000094c + +#define VIVS_CL_UNK00950 0x00000950 + +#define VIVS_CL_UNK00954 0x00000954 + +#define VIVS_CL_HALTI5_UNK00958 0x00000958 + +#define VIVS_CL_HALTI5_UNK0095C 0x0000095c + +#define VIVS_CL_HALTI5_UNK00960 0x00000960 + +#define VIVS_PA 0x00000000 + +#define VIVS_PA_VIEWPORT_SCALE_X 0x00000a00 + +#define VIVS_PA_VIEWPORT_SCALE_Y 0x00000a04 + +#define VIVS_PA_VIEWPORT_SCALE_Z 0x00000a08 + +#define VIVS_PA_VIEWPORT_OFFSET_X 0x00000a0c + +#define VIVS_PA_VIEWPORT_OFFSET_Y 0x00000a10 + +#define VIVS_PA_VIEWPORT_OFFSET_Z 0x00000a14 + +#define VIVS_PA_LINE_WIDTH 0x00000a18 + +#define VIVS_PA_POINT_SIZE 0x00000a1c + +#define VIVS_PA_UNK00A24 0x00000a24 + +#define VIVS_PA_SYSTEM_MODE 0x00000a28 +#define VIVS_PA_SYSTEM_MODE_PROVOKING_VERTEX_LAST 0x00000001 +#define VIVS_PA_SYSTEM_MODE_HALF_PIXEL_CENTER 0x00000010 + +#define VIVS_PA_W_CLIP_LIMIT 0x00000a2c + +#define VIVS_PA_ATTRIBUTE_ELEMENT_COUNT 0x00000a30 +#define VIVS_PA_ATTRIBUTE_ELEMENT_COUNT_UNK0__MASK 0x000000ff +#define VIVS_PA_ATTRIBUTE_ELEMENT_COUNT_UNK0__SHIFT 0 +#define VIVS_PA_ATTRIBUTE_ELEMENT_COUNT_UNK0(x) (((x) << VIVS_PA_ATTRIBUTE_ELEMENT_COUNT_UNK0__SHIFT) & VIVS_PA_ATTRIBUTE_ELEMENT_COUNT_UNK0__MASK) +#define VIVS_PA_ATTRIBUTE_ELEMENT_COUNT_COUNT__MASK 0x0000ff00 +#define VIVS_PA_ATTRIBUTE_ELEMENT_COUNT_COUNT__SHIFT 8 +#define VIVS_PA_ATTRIBUTE_ELEMENT_COUNT_COUNT(x) (((x) << VIVS_PA_ATTRIBUTE_ELEMENT_COUNT_COUNT__SHIFT) & VIVS_PA_ATTRIBUTE_ELEMENT_COUNT_COUNT__MASK) + +#define VIVS_PA_CONFIG 0x00000a34 +#define VIVS_PA_CONFIG_POINT_SIZE_ENABLE 0x00000004 +#define VIVS_PA_CONFIG_POINT_SIZE_ENABLE_MASK 0x00000008 +#define VIVS_PA_CONFIG_POINT_SPRITE_ENABLE 0x00000010 +#define VIVS_PA_CONFIG_POINT_SPRITE_ENABLE_MASK 0x00000020 +#define VIVS_PA_CONFIG_CULL_FACE_MODE__MASK 0x00000300 +#define VIVS_PA_CONFIG_CULL_FACE_MODE__SHIFT 8 +#define VIVS_PA_CONFIG_CULL_FACE_MODE_OFF 0x00000000 +#define VIVS_PA_CONFIG_CULL_FACE_MODE_CW 0x00000100 +#define VIVS_PA_CONFIG_CULL_FACE_MODE_CCW 0x00000200 +#define VIVS_PA_CONFIG_CULL_FACE_MODE_MASK 0x00000400 +#define VIVS_PA_CONFIG_FILL_MODE__MASK 0x00003000 +#define VIVS_PA_CONFIG_FILL_MODE__SHIFT 12 +#define VIVS_PA_CONFIG_FILL_MODE_POINT 0x00000000 +#define VIVS_PA_CONFIG_FILL_MODE_WIREFRAME 0x00001000 +#define VIVS_PA_CONFIG_FILL_MODE_SOLID 0x00002000 +#define VIVS_PA_CONFIG_FILL_MODE_MASK 0x00004000 +#define VIVS_PA_CONFIG_SHADE_MODEL__MASK 0x00030000 +#define VIVS_PA_CONFIG_SHADE_MODEL__SHIFT 16 +#define VIVS_PA_CONFIG_SHADE_MODEL_FLAT 0x00000000 +#define VIVS_PA_CONFIG_SHADE_MODEL_SMOOTH 0x00010000 +#define VIVS_PA_CONFIG_SHADE_MODEL_MASK 0x00040000 +#define VIVS_PA_CONFIG_WIDE_LINE 0x00400000 +#define VIVS_PA_CONFIG_WIDE_LINE_MASK 0x00800000 + +#define VIVS_PA_WIDE_LINE_WIDTH0 0x00000a38 + +#define VIVS_PA_WIDE_LINE_WIDTH1 0x00000a3c + +#define VIVS_PA_SHADER_ATTRIBUTES(i0) (0x00000a40 + 0x4*(i0)) +#define VIVS_PA_SHADER_ATTRIBUTES__ESIZE 0x00000004 +#define VIVS_PA_SHADER_ATTRIBUTES__LEN 0x0000000a +#define VIVS_PA_SHADER_ATTRIBUTES_BYPASS_FLAT 0x00000001 +#define VIVS_PA_SHADER_ATTRIBUTES_UNK4__MASK 0x000000f0 +#define VIVS_PA_SHADER_ATTRIBUTES_UNK4__SHIFT 4 +#define VIVS_PA_SHADER_ATTRIBUTES_UNK4(x) (((x) << VIVS_PA_SHADER_ATTRIBUTES_UNK4__SHIFT) & VIVS_PA_SHADER_ATTRIBUTES_UNK4__MASK) +#define VIVS_PA_SHADER_ATTRIBUTES_UNK8__MASK 0x00000f00 +#define VIVS_PA_SHADER_ATTRIBUTES_UNK8__SHIFT 8 +#define VIVS_PA_SHADER_ATTRIBUTES_UNK8(x) (((x) << VIVS_PA_SHADER_ATTRIBUTES_UNK8__SHIFT) & VIVS_PA_SHADER_ATTRIBUTES_UNK8__MASK) + +#define VIVS_PA_VIEWPORT_UNK00A80 0x00000a80 + +#define VIVS_PA_VIEWPORT_UNK00A84 0x00000a84 + +#define VIVS_PA_FLAGS 0x00000a88 +#define VIVS_PA_FLAGS_UNK24 0x01000000 +#define VIVS_PA_FLAGS_ZCONVERT_BYPASS 0x40000000 + +#define VIVS_PA_ZFARCLIPPING 0x00000a8c + +#define VIVS_PA_HALTI5_UNK00A90(i0) (0x00000a90 + 0x4*(i0)) +#define VIVS_PA_HALTI5_UNK00A90__ESIZE 0x00000004 +#define VIVS_PA_HALTI5_UNK00A90__LEN 0x00000004 + +#define VIVS_PA_HALTI5_UNK00AA8 0x00000aa8 + +#define VIVS_SE 0x00000000 + +#define VIVS_SE_SCISSOR_LEFT 0x00000c00 + +#define VIVS_SE_SCISSOR_TOP 0x00000c04 + +#define VIVS_SE_SCISSOR_RIGHT 0x00000c08 + +#define VIVS_SE_SCISSOR_BOTTOM 0x00000c0c + +#define VIVS_SE_DEPTH_SCALE 0x00000c10 + +#define VIVS_SE_DEPTH_BIAS 0x00000c14 + +#define VIVS_SE_CONFIG 0x00000c18 +#define VIVS_SE_CONFIG_LAST_PIXEL_ENABLE 0x00000001 + +#define VIVS_SE_UNK00C1C 0x00000c1c + +#define VIVS_SE_CLIP_RIGHT 0x00000c20 + +#define VIVS_SE_CLIP_BOTTOM 0x00000c24 + +#define VIVS_RA 0x00000000 + +#define VIVS_RA_CONTROL 0x00000e00 +#define VIVS_RA_CONTROL_UNK0 0x00000001 +#define VIVS_RA_CONTROL_LAST_VARYING_2X 0x00000002 + +#define VIVS_RA_MULTISAMPLE_UNK00E04 0x00000e04 + +#define VIVS_RA_EARLY_DEPTH 0x00000e08 + +#define VIVS_RA_UNK00E0C 0x00000e0c + +#define VIVS_RA_MULTISAMPLE_UNK00E10(i0) (0x00000e10 + 0x4*(i0)) +#define VIVS_RA_MULTISAMPLE_UNK00E10__ESIZE 0x00000004 +#define VIVS_RA_MULTISAMPLE_UNK00E10__LEN 0x00000004 + +#define VIVS_RA_HDEPTH_CONTROL 0x00000e20 +#define VIVS_RA_HDEPTH_CONTROL_UNK0 0x00000001 +#define VIVS_RA_HDEPTH_CONTROL_COMPARE__MASK 0x00007000 +#define VIVS_RA_HDEPTH_CONTROL_COMPARE__SHIFT 12 +#define VIVS_RA_HDEPTH_CONTROL_COMPARE(x) (((x) << VIVS_RA_HDEPTH_CONTROL_COMPARE__SHIFT) & VIVS_RA_HDEPTH_CONTROL_COMPARE__MASK) + +#define VIVS_RA_UNK00E24 0x00000e24 + +#define VIVS_RA_HALTI5_UNK00E34 0x00000e34 + +#define VIVS_RA_CENTROID_TABLE(i0) (0x00000e40 + 0x4*(i0)) +#define VIVS_RA_CENTROID_TABLE__ESIZE 0x00000004 +#define VIVS_RA_CENTROID_TABLE__LEN 0x00000010 + +#define VIVS_PS 0x00000000 + +#define VIVS_PS_END_PC 0x00001000 + +#define VIVS_PS_OUTPUT_REG 0x00001004 + +#define VIVS_PS_INPUT_COUNT 0x00001008 +#define VIVS_PS_INPUT_COUNT_COUNT__MASK 0x0000000f +#define VIVS_PS_INPUT_COUNT_COUNT__SHIFT 0 +#define VIVS_PS_INPUT_COUNT_COUNT(x) (((x) << VIVS_PS_INPUT_COUNT_COUNT__SHIFT) & VIVS_PS_INPUT_COUNT_COUNT__MASK) +#define VIVS_PS_INPUT_COUNT_UNK8__MASK 0x00001f00 +#define VIVS_PS_INPUT_COUNT_UNK8__SHIFT 8 +#define VIVS_PS_INPUT_COUNT_UNK8(x) (((x) << VIVS_PS_INPUT_COUNT_UNK8__SHIFT) & VIVS_PS_INPUT_COUNT_UNK8__MASK) + +#define VIVS_PS_TEMP_REGISTER_CONTROL 0x0000100c +#define VIVS_PS_TEMP_REGISTER_CONTROL_NUM_TEMPS__MASK 0x0000003f +#define VIVS_PS_TEMP_REGISTER_CONTROL_NUM_TEMPS__SHIFT 0 +#define VIVS_PS_TEMP_REGISTER_CONTROL_NUM_TEMPS(x) (((x) << VIVS_PS_TEMP_REGISTER_CONTROL_NUM_TEMPS__SHIFT) & VIVS_PS_TEMP_REGISTER_CONTROL_NUM_TEMPS__MASK) + +#define VIVS_PS_CONTROL 0x00001010 +#define VIVS_PS_CONTROL_BYPASS 0x00000001 +#define VIVS_PS_CONTROL_UNK1 0x00000002 + +#define VIVS_PS_PERF_COUNTER 0x00001014 + +#define VIVS_PS_START_PC 0x00001018 + +#define VIVS_PS_RANGE 0x0000101c +#define VIVS_PS_RANGE_LOW__MASK 0x0000ffff +#define VIVS_PS_RANGE_LOW__SHIFT 0 +#define VIVS_PS_RANGE_LOW(x) (((x) << VIVS_PS_RANGE_LOW__SHIFT) & VIVS_PS_RANGE_LOW__MASK) +#define VIVS_PS_RANGE_HIGH__MASK 0xffff0000 +#define VIVS_PS_RANGE_HIGH__SHIFT 16 +#define VIVS_PS_RANGE_HIGH(x) (((x) << VIVS_PS_RANGE_HIGH__SHIFT) & VIVS_PS_RANGE_HIGH__MASK) + +#define VIVS_PS_UNIFORM_BASE 0x00001024 + +#define VIVS_PS_INST_ADDR 0x00001028 + +#define VIVS_PS_UNK0102C 0x0000102c + +#define VIVS_PS_CONTROL_EXT 0x00001030 +#define VIVS_PS_CONTROL_EXT_COLOR_OUTPUT_COUNT__MASK 0x00000003 +#define VIVS_PS_CONTROL_EXT_COLOR_OUTPUT_COUNT__SHIFT 0 +#define VIVS_PS_CONTROL_EXT_COLOR_OUTPUT_COUNT(x) (((x) << VIVS_PS_CONTROL_EXT_COLOR_OUTPUT_COUNT__SHIFT) & VIVS_PS_CONTROL_EXT_COLOR_OUTPUT_COUNT__MASK) + +#define VIVS_PS_UNK01034 0x00001034 + +#define VIVS_PS_UNK01038 0x00001038 + +#define VIVS_PS_HALTI3_UNK0103C 0x0000103c + +#define VIVS_PS_UNK01040(i0) (0x00001040 + 0x4*(i0)) +#define VIVS_PS_UNK01040__ESIZE 0x00000004 +#define VIVS_PS_UNK01040__LEN 0x00000002 + +#define VIVS_PS_UNK01048 0x00001048 + +#define VIVS_PS_ICACHE_UNK0104C 0x0000104c + +#define VIVS_PS_HALTI4_UNK01054 0x00001054 + +#define VIVS_PS_HALTI5_UNK01058 0x00001058 + +#define VIVS_PS_HALTI5_UNK01080(i0) (0x00001080 + 0x4*(i0)) +#define VIVS_PS_HALTI5_UNK01080__ESIZE 0x00000004 +#define VIVS_PS_HALTI5_UNK01080__LEN 0x00000004 + +#define VIVS_PS_HALTI5_UNK01090 0x00001090 + +#define VIVS_PS_HALTI5_UNK01094 0x00001094 + +#define VIVS_PS_HALTI5_UNK01098 0x00001098 + +#define VIVS_PS_INST_MEM(i0) (0x00006000 + 0x4*(i0)) +#define VIVS_PS_INST_MEM__ESIZE 0x00000004 +#define VIVS_PS_INST_MEM__LEN 0x00000400 + +#define VIVS_PS_UNIFORMS(i0) (0x00007000 + 0x4*(i0)) +#define VIVS_PS_UNIFORMS__ESIZE 0x00000004 +#define VIVS_PS_UNIFORMS__LEN 0x00000400 + +#define VIVS_GS 0x00000000 + +#define VIVS_GS_UNK01100 0x00001100 + +#define VIVS_GS_UNK01104 0x00001104 + +#define VIVS_GS_UNK01108 0x00001108 + +#define VIVS_GS_UNK0110C 0x0000110c + +#define VIVS_GS_UNK01110 0x00001110 + +#define VIVS_GS_UNK01114 0x00001114 + +#define VIVS_GS_UNK0111C 0x0000111c + +#define VIVS_GS_UNK01120(i0) (0x00001120 + 0x4*(i0)) +#define VIVS_GS_UNK01120__ESIZE 0x00000004 +#define VIVS_GS_UNK01120__LEN 0x00000008 + +#define VIVS_GS_UNK01140 0x00001140 + +#define VIVS_GS_UNK01144 0x00001144 + +#define VIVS_GS_UNK01148 0x00001148 + +#define VIVS_GS_UNK0114C 0x0000114c + +#define VIVS_GS_UNK01154 0x00001154 + +#define VIVS_TCS 0x00000000 + +#define VIVS_TCS_UNK007C0 0x000007c0 + +#define VIVS_TCS_UNK14A00 0x00014a00 + +#define VIVS_TCS_UNK14A04 0x00014a04 + +#define VIVS_TCS_UNK14A08 0x00014a08 + +#define VIVS_TCS_UNK14A10 0x00014a10 + +#define VIVS_TCS_UNK14A14 0x00014a14 + +#define VIVS_TCS_UNK14A18 0x00014a18 + +#define VIVS_TCS_UNK14A1C 0x00014a1c + +#define VIVS_TCS_UNK14A20(i0) (0x00014a20 + 0x4*(i0)) +#define VIVS_TCS_UNK14A20__ESIZE 0x00000004 +#define VIVS_TCS_UNK14A20__LEN 0x00000008 + +#define VIVS_TCS_UNK14A40 0x00014a40 + +#define VIVS_TCS_UNK14A44 0x00014a44 + +#define VIVS_TCS_UNK14A4C 0x00014a4c + +#define VIVS_TES 0x00000000 + +#define VIVS_TES_UNK14B00 0x00014b00 + +#define VIVS_TES_UNK14B04 0x00014b04 + +#define VIVS_TES_UNK14B08 0x00014b08 + +#define VIVS_TES_UNK14B0C 0x00014b0c + +#define VIVS_TES_UNK14B14 0x00014b14 + +#define VIVS_TES_UNK14B18 0x00014b18 + +#define VIVS_TES_UNK14B1C 0x00014b1c + +#define VIVS_TES_UNK14B20 0x00014b20 + +#define VIVS_TES_UNK14B24 0x00014b24 + +#define VIVS_TES_UNK14B2C 0x00014b2c + +#define VIVS_TES_UNK14B34 0x00014b34 + +#define VIVS_TES_UNK14B40(i0) (0x00014b40 + 0x4*(i0)) +#define VIVS_TES_UNK14B40__ESIZE 0x00000004 +#define VIVS_TES_UNK14B40__LEN 0x00000008 + +#define VIVS_TFB 0x00000000 + +#define VIVS_TFB_UNK1C000 0x0001c000 + +#define VIVS_TFB_UNK1C008 0x0001c008 + +#define VIVS_TFB_FLUSH 0x0001c00c + +#define VIVS_TFB_UNK1C014 0x0001c014 + +#define VIVS_TFB_UNK1C040(i0) (0x0001c040 + 0x4*(i0)) +#define VIVS_TFB_UNK1C040__ESIZE 0x00000004 +#define VIVS_TFB_UNK1C040__LEN 0x00000004 + +#define VIVS_TFB_UNK1C080(i0) (0x0001c080 + 0x4*(i0)) +#define VIVS_TFB_UNK1C080__ESIZE 0x00000004 +#define VIVS_TFB_UNK1C080__LEN 0x00000004 + +#define VIVS_TFB_UNK1C0C0(i0) (0x0001c0c0 + 0x4*(i0)) +#define VIVS_TFB_UNK1C0C0__ESIZE 0x00000004 +#define VIVS_TFB_UNK1C0C0__LEN 0x00000004 + +#define VIVS_TFB_UNK1C100(i0) (0x0001c100 + 0x4*(i0)) +#define VIVS_TFB_UNK1C100__ESIZE 0x00000004 +#define VIVS_TFB_UNK1C100__LEN 0x00000004 + +#define VIVS_TFB_UNK1C800(i0) (0x0001c800 + 0x4*(i0)) +#define VIVS_TFB_UNK1C800__ESIZE 0x00000004 +#define VIVS_TFB_UNK1C800__LEN 0x00000200 + +#define VIVS_PE 0x00000000 + +#define VIVS_PE_DEPTH_CONFIG 0x00001400 +#define VIVS_PE_DEPTH_CONFIG_DEPTH_MODE__MASK 0x00000003 +#define VIVS_PE_DEPTH_CONFIG_DEPTH_MODE__SHIFT 0 +#define VIVS_PE_DEPTH_CONFIG_DEPTH_MODE_NONE 0x00000000 +#define VIVS_PE_DEPTH_CONFIG_DEPTH_MODE_Z 0x00000001 +#define VIVS_PE_DEPTH_CONFIG_DEPTH_MODE_W 0x00000002 +#define VIVS_PE_DEPTH_CONFIG_DEPTH_MODE_MASK 0x00000008 +#define VIVS_PE_DEPTH_CONFIG_DEPTH_FORMAT__MASK 0x00000010 +#define VIVS_PE_DEPTH_CONFIG_DEPTH_FORMAT__SHIFT 4 +#define VIVS_PE_DEPTH_CONFIG_DEPTH_FORMAT_D16 0x00000000 +#define VIVS_PE_DEPTH_CONFIG_DEPTH_FORMAT_D24S8 0x00000010 +#define VIVS_PE_DEPTH_CONFIG_DEPTH_FORMAT_MASK 0x00000020 +#define VIVS_PE_DEPTH_CONFIG_DEPTH_FUNC__MASK 0x00000700 +#define VIVS_PE_DEPTH_CONFIG_DEPTH_FUNC__SHIFT 8 +#define VIVS_PE_DEPTH_CONFIG_DEPTH_FUNC(x) (((x) << VIVS_PE_DEPTH_CONFIG_DEPTH_FUNC__SHIFT) & VIVS_PE_DEPTH_CONFIG_DEPTH_FUNC__MASK) +#define VIVS_PE_DEPTH_CONFIG_DEPTH_FUNC_MASK 0x00000800 +#define VIVS_PE_DEPTH_CONFIG_WRITE_ENABLE 0x00001000 +#define VIVS_PE_DEPTH_CONFIG_WRITE_ENABLE_MASK 0x00002000 +#define VIVS_PE_DEPTH_CONFIG_EARLY_Z 0x00010000 +#define VIVS_PE_DEPTH_CONFIG_EARLY_Z_MASK 0x00020000 +#define VIVS_PE_DEPTH_CONFIG_UNK18 0x00040000 +#define VIVS_PE_DEPTH_CONFIG_UNK18_MASK 0x00080000 +#define VIVS_PE_DEPTH_CONFIG_ONLY_DEPTH 0x00100000 +#define VIVS_PE_DEPTH_CONFIG_ONLY_DEPTH_MASK 0x00200000 +#define VIVS_PE_DEPTH_CONFIG_DISABLE_ZS 0x01000000 +#define VIVS_PE_DEPTH_CONFIG_DISABLE_ZS_MASK 0x02000000 +#define VIVS_PE_DEPTH_CONFIG_SUPER_TILED 0x04000000 +#define VIVS_PE_DEPTH_CONFIG_SUPER_TILED_MASK 0x08000000 + +#define VIVS_PE_DEPTH_NEAR 0x00001404 + +#define VIVS_PE_DEPTH_FAR 0x00001408 + +#define VIVS_PE_DEPTH_NORMALIZE 0x0000140c + +#define VIVS_PE_DEPTH_ADDR 0x00001410 + +#define VIVS_PE_DEPTH_STRIDE 0x00001414 + +#define VIVS_PE_STENCIL_OP 0x00001418 +#define VIVS_PE_STENCIL_OP_FUNC_FRONT__MASK 0x00000007 +#define VIVS_PE_STENCIL_OP_FUNC_FRONT__SHIFT 0 +#define VIVS_PE_STENCIL_OP_FUNC_FRONT(x) (((x) << VIVS_PE_STENCIL_OP_FUNC_FRONT__SHIFT) & VIVS_PE_STENCIL_OP_FUNC_FRONT__MASK) +#define VIVS_PE_STENCIL_OP_FUNC_FRONT_MASK 0x00000008 +#define VIVS_PE_STENCIL_OP_PASS_FRONT__MASK 0x00000070 +#define VIVS_PE_STENCIL_OP_PASS_FRONT__SHIFT 4 +#define VIVS_PE_STENCIL_OP_PASS_FRONT(x) (((x) << VIVS_PE_STENCIL_OP_PASS_FRONT__SHIFT) & VIVS_PE_STENCIL_OP_PASS_FRONT__MASK) +#define VIVS_PE_STENCIL_OP_PASS_FRONT_MASK 0x00000080 +#define VIVS_PE_STENCIL_OP_FAIL_FRONT__MASK 0x00000700 +#define VIVS_PE_STENCIL_OP_FAIL_FRONT__SHIFT 8 +#define VIVS_PE_STENCIL_OP_FAIL_FRONT(x) (((x) << VIVS_PE_STENCIL_OP_FAIL_FRONT__SHIFT) & VIVS_PE_STENCIL_OP_FAIL_FRONT__MASK) +#define VIVS_PE_STENCIL_OP_FAIL_FRONT_MASK 0x00000800 +#define VIVS_PE_STENCIL_OP_DEPTH_FAIL_FRONT__MASK 0x00007000 +#define VIVS_PE_STENCIL_OP_DEPTH_FAIL_FRONT__SHIFT 12 +#define VIVS_PE_STENCIL_OP_DEPTH_FAIL_FRONT(x) (((x) << VIVS_PE_STENCIL_OP_DEPTH_FAIL_FRONT__SHIFT) & VIVS_PE_STENCIL_OP_DEPTH_FAIL_FRONT__MASK) +#define VIVS_PE_STENCIL_OP_DEPTH_FAIL_FRONT_MASK 0x00008000 +#define VIVS_PE_STENCIL_OP_FUNC_BACK__MASK 0x00070000 +#define VIVS_PE_STENCIL_OP_FUNC_BACK__SHIFT 16 +#define VIVS_PE_STENCIL_OP_FUNC_BACK(x) (((x) << VIVS_PE_STENCIL_OP_FUNC_BACK__SHIFT) & VIVS_PE_STENCIL_OP_FUNC_BACK__MASK) +#define VIVS_PE_STENCIL_OP_FUNC_BACK_MASK 0x00080000 +#define VIVS_PE_STENCIL_OP_PASS_BACK__MASK 0x00700000 +#define VIVS_PE_STENCIL_OP_PASS_BACK__SHIFT 20 +#define VIVS_PE_STENCIL_OP_PASS_BACK(x) (((x) << VIVS_PE_STENCIL_OP_PASS_BACK__SHIFT) & VIVS_PE_STENCIL_OP_PASS_BACK__MASK) +#define VIVS_PE_STENCIL_OP_PASS_BACK_MASK 0x00800000 +#define VIVS_PE_STENCIL_OP_FAIL_BACK__MASK 0x07000000 +#define VIVS_PE_STENCIL_OP_FAIL_BACK__SHIFT 24 +#define VIVS_PE_STENCIL_OP_FAIL_BACK(x) (((x) << VIVS_PE_STENCIL_OP_FAIL_BACK__SHIFT) & VIVS_PE_STENCIL_OP_FAIL_BACK__MASK) +#define VIVS_PE_STENCIL_OP_FAIL_BACK_MASK 0x08000000 +#define VIVS_PE_STENCIL_OP_DEPTH_FAIL_BACK__MASK 0x70000000 +#define VIVS_PE_STENCIL_OP_DEPTH_FAIL_BACK__SHIFT 28 +#define VIVS_PE_STENCIL_OP_DEPTH_FAIL_BACK(x) (((x) << VIVS_PE_STENCIL_OP_DEPTH_FAIL_BACK__SHIFT) & VIVS_PE_STENCIL_OP_DEPTH_FAIL_BACK__MASK) +#define VIVS_PE_STENCIL_OP_DEPTH_FAIL_BACK_MASK 0x80000000 + +#define VIVS_PE_STENCIL_CONFIG 0x0000141c +#define VIVS_PE_STENCIL_CONFIG_MODE__MASK 0x00000003 +#define VIVS_PE_STENCIL_CONFIG_MODE__SHIFT 0 +#define VIVS_PE_STENCIL_CONFIG_MODE_DISABLED 0x00000000 +#define VIVS_PE_STENCIL_CONFIG_MODE_ONE_SIDED 0x00000001 +#define VIVS_PE_STENCIL_CONFIG_MODE_TWO_SIDED 0x00000002 +#define VIVS_PE_STENCIL_CONFIG_MODE_MASK 0x00000010 +#define VIVS_PE_STENCIL_CONFIG_REF_FRONT_MASK 0x00000020 +#define VIVS_PE_STENCIL_CONFIG_MASK_FRONT_MASK 0x00000040 +#define VIVS_PE_STENCIL_CONFIG_WRITE_MASK_MASK 0x00000080 +#define VIVS_PE_STENCIL_CONFIG_REF_FRONT__MASK 0x0000ff00 +#define VIVS_PE_STENCIL_CONFIG_REF_FRONT__SHIFT 8 +#define VIVS_PE_STENCIL_CONFIG_REF_FRONT(x) (((x) << VIVS_PE_STENCIL_CONFIG_REF_FRONT__SHIFT) & VIVS_PE_STENCIL_CONFIG_REF_FRONT__MASK) +#define VIVS_PE_STENCIL_CONFIG_MASK_FRONT__MASK 0x00ff0000 +#define VIVS_PE_STENCIL_CONFIG_MASK_FRONT__SHIFT 16 +#define VIVS_PE_STENCIL_CONFIG_MASK_FRONT(x) (((x) << VIVS_PE_STENCIL_CONFIG_MASK_FRONT__SHIFT) & VIVS_PE_STENCIL_CONFIG_MASK_FRONT__MASK) +#define VIVS_PE_STENCIL_CONFIG_WRITE_MASK_FRONT__MASK 0xff000000 +#define VIVS_PE_STENCIL_CONFIG_WRITE_MASK_FRONT__SHIFT 24 +#define VIVS_PE_STENCIL_CONFIG_WRITE_MASK_FRONT(x) (((x) << VIVS_PE_STENCIL_CONFIG_WRITE_MASK_FRONT__SHIFT) & VIVS_PE_STENCIL_CONFIG_WRITE_MASK_FRONT__MASK) + +#define VIVS_PE_ALPHA_OP 0x00001420 +#define VIVS_PE_ALPHA_OP_ALPHA_TEST 0x00000001 +#define VIVS_PE_ALPHA_OP_ALPHA_TEST_MASK 0x00000002 +#define VIVS_PE_ALPHA_OP_ALPHA_FUNC__MASK 0x00000070 +#define VIVS_PE_ALPHA_OP_ALPHA_FUNC__SHIFT 4 +#define VIVS_PE_ALPHA_OP_ALPHA_FUNC(x) (((x) << VIVS_PE_ALPHA_OP_ALPHA_FUNC__SHIFT) & VIVS_PE_ALPHA_OP_ALPHA_FUNC__MASK) +#define VIVS_PE_ALPHA_OP_ALPHA_FUNC_MASK 0x00000080 +#define VIVS_PE_ALPHA_OP_ALPHA_REF__MASK 0x0000ff00 +#define VIVS_PE_ALPHA_OP_ALPHA_REF__SHIFT 8 +#define VIVS_PE_ALPHA_OP_ALPHA_REF(x) (((x) << VIVS_PE_ALPHA_OP_ALPHA_REF__SHIFT) & VIVS_PE_ALPHA_OP_ALPHA_REF__MASK) +#define VIVS_PE_ALPHA_OP_ALPHA_REF_MASKFUNC_MASK 0x00010000 + +#define VIVS_PE_ALPHA_BLEND_COLOR 0x00001424 +#define VIVS_PE_ALPHA_BLEND_COLOR_B__MASK 0x000000ff +#define VIVS_PE_ALPHA_BLEND_COLOR_B__SHIFT 0 +#define VIVS_PE_ALPHA_BLEND_COLOR_B(x) (((x) << VIVS_PE_ALPHA_BLEND_COLOR_B__SHIFT) & VIVS_PE_ALPHA_BLEND_COLOR_B__MASK) +#define VIVS_PE_ALPHA_BLEND_COLOR_G__MASK 0x0000ff00 +#define VIVS_PE_ALPHA_BLEND_COLOR_G__SHIFT 8 +#define VIVS_PE_ALPHA_BLEND_COLOR_G(x) (((x) << VIVS_PE_ALPHA_BLEND_COLOR_G__SHIFT) & VIVS_PE_ALPHA_BLEND_COLOR_G__MASK) +#define VIVS_PE_ALPHA_BLEND_COLOR_R__MASK 0x00ff0000 +#define VIVS_PE_ALPHA_BLEND_COLOR_R__SHIFT 16 +#define VIVS_PE_ALPHA_BLEND_COLOR_R(x) (((x) << VIVS_PE_ALPHA_BLEND_COLOR_R__SHIFT) & VIVS_PE_ALPHA_BLEND_COLOR_R__MASK) +#define VIVS_PE_ALPHA_BLEND_COLOR_A__MASK 0xff000000 +#define VIVS_PE_ALPHA_BLEND_COLOR_A__SHIFT 24 +#define VIVS_PE_ALPHA_BLEND_COLOR_A(x) (((x) << VIVS_PE_ALPHA_BLEND_COLOR_A__SHIFT) & VIVS_PE_ALPHA_BLEND_COLOR_A__MASK) + +#define VIVS_PE_ALPHA_CONFIG 0x00001428 +#define VIVS_PE_ALPHA_CONFIG_BLEND_ENABLE_COLOR 0x00000001 +#define VIVS_PE_ALPHA_CONFIG_BLEND_ENABLE_COLOR_MASK 0x00000002 +#define VIVS_PE_ALPHA_CONFIG_SRC_FUNC_COLOR_MASK 0x00000004 +#define VIVS_PE_ALPHA_CONFIG_DST_FUNC_COLOR_MASK 0x00000008 +#define VIVS_PE_ALPHA_CONFIG_SRC_FUNC_COLOR__MASK 0x000000f0 +#define VIVS_PE_ALPHA_CONFIG_SRC_FUNC_COLOR__SHIFT 4 +#define VIVS_PE_ALPHA_CONFIG_SRC_FUNC_COLOR(x) (((x) << VIVS_PE_ALPHA_CONFIG_SRC_FUNC_COLOR__SHIFT) & VIVS_PE_ALPHA_CONFIG_SRC_FUNC_COLOR__MASK) +#define VIVS_PE_ALPHA_CONFIG_DST_FUNC_COLOR__MASK 0x00000f00 +#define VIVS_PE_ALPHA_CONFIG_DST_FUNC_COLOR__SHIFT 8 +#define VIVS_PE_ALPHA_CONFIG_DST_FUNC_COLOR(x) (((x) << VIVS_PE_ALPHA_CONFIG_DST_FUNC_COLOR__SHIFT) & VIVS_PE_ALPHA_CONFIG_DST_FUNC_COLOR__MASK) +#define VIVS_PE_ALPHA_CONFIG_EQ_COLOR__MASK 0x00007000 +#define VIVS_PE_ALPHA_CONFIG_EQ_COLOR__SHIFT 12 +#define VIVS_PE_ALPHA_CONFIG_EQ_COLOR(x) (((x) << VIVS_PE_ALPHA_CONFIG_EQ_COLOR__SHIFT) & VIVS_PE_ALPHA_CONFIG_EQ_COLOR__MASK) +#define VIVS_PE_ALPHA_CONFIG_EQ_COLOR_MASK 0x00008000 +#define VIVS_PE_ALPHA_CONFIG_BLEND_SEPARATE_ALPHA 0x00010000 +#define VIVS_PE_ALPHA_CONFIG_BLEND_SEPARATE_ALPHA_MASK 0x00020000 +#define VIVS_PE_ALPHA_CONFIG_SRC_FUNC_ALPHA_MASK 0x00040000 +#define VIVS_PE_ALPHA_CONFIG_DST_FUNC_ALPHA_MASK 0x00080000 +#define VIVS_PE_ALPHA_CONFIG_SRC_FUNC_ALPHA__MASK 0x00f00000 +#define VIVS_PE_ALPHA_CONFIG_SRC_FUNC_ALPHA__SHIFT 20 +#define VIVS_PE_ALPHA_CONFIG_SRC_FUNC_ALPHA(x) (((x) << VIVS_PE_ALPHA_CONFIG_SRC_FUNC_ALPHA__SHIFT) & VIVS_PE_ALPHA_CONFIG_SRC_FUNC_ALPHA__MASK) +#define VIVS_PE_ALPHA_CONFIG_DST_FUNC_ALPHA__MASK 0x0f000000 +#define VIVS_PE_ALPHA_CONFIG_DST_FUNC_ALPHA__SHIFT 24 +#define VIVS_PE_ALPHA_CONFIG_DST_FUNC_ALPHA(x) (((x) << VIVS_PE_ALPHA_CONFIG_DST_FUNC_ALPHA__SHIFT) & VIVS_PE_ALPHA_CONFIG_DST_FUNC_ALPHA__MASK) +#define VIVS_PE_ALPHA_CONFIG_EQ_ALPHA__MASK 0x70000000 +#define VIVS_PE_ALPHA_CONFIG_EQ_ALPHA__SHIFT 28 +#define VIVS_PE_ALPHA_CONFIG_EQ_ALPHA(x) (((x) << VIVS_PE_ALPHA_CONFIG_EQ_ALPHA__SHIFT) & VIVS_PE_ALPHA_CONFIG_EQ_ALPHA__MASK) +#define VIVS_PE_ALPHA_CONFIG_EQ_ALPHA_MASK 0x80000000 + +#define VIVS_PE_COLOR_FORMAT 0x0000142c +#define VIVS_PE_COLOR_FORMAT_FORMAT__MASK 0x0000000f +#define VIVS_PE_COLOR_FORMAT_FORMAT__SHIFT 0 +#define VIVS_PE_COLOR_FORMAT_FORMAT(x) (((x) << VIVS_PE_COLOR_FORMAT_FORMAT__SHIFT) & VIVS_PE_COLOR_FORMAT_FORMAT__MASK) +#define VIVS_PE_COLOR_FORMAT_FORMAT_MASK 0x00000010 +#define VIVS_PE_COLOR_FORMAT_COMPONENTS__MASK 0x00000f00 +#define VIVS_PE_COLOR_FORMAT_COMPONENTS__SHIFT 8 +#define VIVS_PE_COLOR_FORMAT_COMPONENTS(x) (((x) << VIVS_PE_COLOR_FORMAT_COMPONENTS__SHIFT) & VIVS_PE_COLOR_FORMAT_COMPONENTS__MASK) +#define VIVS_PE_COLOR_FORMAT_COMPONENTS_MASK 0x00001000 +#define VIVS_PE_COLOR_FORMAT_OVERWRITE 0x00010000 +#define VIVS_PE_COLOR_FORMAT_OVERWRITE_MASK 0x00020000 +#define VIVS_PE_COLOR_FORMAT_SUPER_TILED 0x00100000 +#define VIVS_PE_COLOR_FORMAT_SUPER_TILED_MASK 0x00200000 +#define VIVS_PE_COLOR_FORMAT_FORMAT_EXT__MASK 0x7f000000 +#define VIVS_PE_COLOR_FORMAT_FORMAT_EXT__SHIFT 24 +#define VIVS_PE_COLOR_FORMAT_FORMAT_EXT(x) (((x) << VIVS_PE_COLOR_FORMAT_FORMAT_EXT__SHIFT) & VIVS_PE_COLOR_FORMAT_FORMAT_EXT__MASK) +#define VIVS_PE_COLOR_FORMAT_FORMAT_EXT_MASK 0x80000000 + +#define VIVS_PE_COLOR_ADDR 0x00001430 + +#define VIVS_PE_COLOR_STRIDE 0x00001434 + +#define VIVS_PE_HDEPTH_CONTROL 0x00001454 +#define VIVS_PE_HDEPTH_CONTROL_FORMAT__MASK 0x0000000f +#define VIVS_PE_HDEPTH_CONTROL_FORMAT__SHIFT 0 +#define VIVS_PE_HDEPTH_CONTROL_FORMAT_DISABLED 0x00000000 +#define VIVS_PE_HDEPTH_CONTROL_FORMAT_D16 0x00000005 +#define VIVS_PE_HDEPTH_CONTROL_FORMAT_D24S8 0x00000008 + +#define VIVS_PE_HDEPTH_ADDR 0x00001458 + +#define VIVS_PE_UNK0145C 0x0000145c + +#define VIVS_PE_PIPE(i0) (0x00000000 + 0x4*(i0)) +#define VIVS_PE_PIPE__ESIZE 0x00000004 +#define VIVS_PE_PIPE__LEN 0x00000008 + +#define VIVS_PE_PIPE_COLOR_ADDR(i0) (0x00001460 + 0x4*(i0)) + +#define VIVS_PE_PIPE_DEPTH_ADDR(i0) (0x00001480 + 0x4*(i0)) + +#define VIVS_PE_PIPE_ADDR_UNK01500(i0) (0x00001500 + 0x4*(i0)) + +#define VIVS_PE_PIPE_ADDR_UNK01520(i0) (0x00001520 + 0x4*(i0)) + +#define VIVS_PE_PIPE_ADDR_UNK01540(i0) (0x00001540 + 0x4*(i0)) + +#define VIVS_PE_STENCIL_CONFIG_EXT 0x000014a0 +#define VIVS_PE_STENCIL_CONFIG_EXT_REF_BACK__MASK 0x000000ff +#define VIVS_PE_STENCIL_CONFIG_EXT_REF_BACK__SHIFT 0 +#define VIVS_PE_STENCIL_CONFIG_EXT_REF_BACK(x) (((x) << VIVS_PE_STENCIL_CONFIG_EXT_REF_BACK__SHIFT) & VIVS_PE_STENCIL_CONFIG_EXT_REF_BACK__MASK) +#define VIVS_PE_STENCIL_CONFIG_EXT_REF_BACK_MASK 0x00000100 +#define VIVS_PE_STENCIL_CONFIG_EXT_UNK16_MASK 0x00000200 +#define VIVS_PE_STENCIL_CONFIG_EXT_UNK16__MASK 0xffff0000 +#define VIVS_PE_STENCIL_CONFIG_EXT_UNK16__SHIFT 16 +#define VIVS_PE_STENCIL_CONFIG_EXT_UNK16(x) (((x) << VIVS_PE_STENCIL_CONFIG_EXT_UNK16__SHIFT) & VIVS_PE_STENCIL_CONFIG_EXT_UNK16__MASK) + +#define VIVS_PE_LOGIC_OP 0x000014a4 +#define VIVS_PE_LOGIC_OP_OP__MASK 0x0000000f +#define VIVS_PE_LOGIC_OP_OP__SHIFT 0 +#define VIVS_PE_LOGIC_OP_OP(x) (((x) << VIVS_PE_LOGIC_OP_OP__SHIFT) & VIVS_PE_LOGIC_OP_OP__MASK) +#define VIVS_PE_LOGIC_OP_OP_MASK 0x00000010 +#define VIVS_PE_LOGIC_OP_SINGLE_BUFFER_MASK 0x00000080 +#define VIVS_PE_LOGIC_OP_SINGLE_BUFFER__MASK 0x00000300 +#define VIVS_PE_LOGIC_OP_SINGLE_BUFFER__SHIFT 8 +#define VIVS_PE_LOGIC_OP_SINGLE_BUFFER(x) (((x) << VIVS_PE_LOGIC_OP_SINGLE_BUFFER__SHIFT) & VIVS_PE_LOGIC_OP_SINGLE_BUFFER__MASK) +#define VIVS_PE_LOGIC_OP_UNK11_MASK 0x00000400 +#define VIVS_PE_LOGIC_OP_UNK11 0x00000800 +#define VIVS_PE_LOGIC_OP_UNK20__MASK 0x00300000 +#define VIVS_PE_LOGIC_OP_UNK20__SHIFT 20 +#define VIVS_PE_LOGIC_OP_UNK20(x) (((x) << VIVS_PE_LOGIC_OP_UNK20__SHIFT) & VIVS_PE_LOGIC_OP_UNK20__MASK) +#define VIVS_PE_LOGIC_OP_UNK20_MASK 0x00800000 +#define VIVS_PE_LOGIC_OP_UNK24__MASK 0x07000000 +#define VIVS_PE_LOGIC_OP_UNK24__SHIFT 24 +#define VIVS_PE_LOGIC_OP_UNK24(x) (((x) << VIVS_PE_LOGIC_OP_UNK24__SHIFT) & VIVS_PE_LOGIC_OP_UNK24__MASK) +#define VIVS_PE_LOGIC_OP_UNK24_MASK 0x08000000 +#define VIVS_PE_LOGIC_OP_UNK31_MASK 0x40000000 +#define VIVS_PE_LOGIC_OP_UNK31 0x80000000 + +#define VIVS_PE_DITHER(i0) (0x000014a8 + 0x4*(i0)) +#define VIVS_PE_DITHER__ESIZE 0x00000004 +#define VIVS_PE_DITHER__LEN 0x00000002 + +#define VIVS_PE_ALPHA_COLOR_EXT0 0x000014b0 +#define VIVS_PE_ALPHA_COLOR_EXT0_B__MASK 0x0000ffff +#define VIVS_PE_ALPHA_COLOR_EXT0_B__SHIFT 0 +#define VIVS_PE_ALPHA_COLOR_EXT0_B(x) (((x) << VIVS_PE_ALPHA_COLOR_EXT0_B__SHIFT) & VIVS_PE_ALPHA_COLOR_EXT0_B__MASK) +#define VIVS_PE_ALPHA_COLOR_EXT0_G__MASK 0xffff0000 +#define VIVS_PE_ALPHA_COLOR_EXT0_G__SHIFT 16 +#define VIVS_PE_ALPHA_COLOR_EXT0_G(x) (((x) << VIVS_PE_ALPHA_COLOR_EXT0_G__SHIFT) & VIVS_PE_ALPHA_COLOR_EXT0_G__MASK) + +#define VIVS_PE_ALPHA_COLOR_EXT1 0x000014b4 +#define VIVS_PE_ALPHA_COLOR_EXT1_R__MASK 0x0000ffff +#define VIVS_PE_ALPHA_COLOR_EXT1_R__SHIFT 0 +#define VIVS_PE_ALPHA_COLOR_EXT1_R(x) (((x) << VIVS_PE_ALPHA_COLOR_EXT1_R__SHIFT) & VIVS_PE_ALPHA_COLOR_EXT1_R__MASK) +#define VIVS_PE_ALPHA_COLOR_EXT1_A__MASK 0xffff0000 +#define VIVS_PE_ALPHA_COLOR_EXT1_A__SHIFT 16 +#define VIVS_PE_ALPHA_COLOR_EXT1_A(x) (((x) << VIVS_PE_ALPHA_COLOR_EXT1_A__SHIFT) & VIVS_PE_ALPHA_COLOR_EXT1_A__MASK) + +#define VIVS_PE_STENCIL_CONFIG_EXT2 0x000014b8 +#define VIVS_PE_STENCIL_CONFIG_EXT2_MASK_BACK__MASK 0x000000ff +#define VIVS_PE_STENCIL_CONFIG_EXT2_MASK_BACK__SHIFT 0 +#define VIVS_PE_STENCIL_CONFIG_EXT2_MASK_BACK(x) (((x) << VIVS_PE_STENCIL_CONFIG_EXT2_MASK_BACK__SHIFT) & VIVS_PE_STENCIL_CONFIG_EXT2_MASK_BACK__MASK) +#define VIVS_PE_STENCIL_CONFIG_EXT2_WRITE_MASK_BACK__MASK 0x0000ff00 +#define VIVS_PE_STENCIL_CONFIG_EXT2_WRITE_MASK_BACK__SHIFT 8 +#define VIVS_PE_STENCIL_CONFIG_EXT2_WRITE_MASK_BACK(x) (((x) << VIVS_PE_STENCIL_CONFIG_EXT2_WRITE_MASK_BACK__SHIFT) & VIVS_PE_STENCIL_CONFIG_EXT2_WRITE_MASK_BACK__MASK) + +#define VIVS_PE_HALTI3_UNK014BC 0x000014bc + +#define VIVS_PE_HALTI4_UNK014C0 0x000014c0 + +#define VIVS_PE_ROBUSTNESS_UNK014C4 0x000014c4 + +#define VIVS_PE_UNK01580(i0) (0x00001580 + 0x4*(i0)) +#define VIVS_PE_UNK01580__ESIZE 0x00000004 +#define VIVS_PE_UNK01580__LEN 0x00000003 + +#define VIVS_PE_RT_ADDR(i0) (0x00000000 + 0x20*(i0)) +#define VIVS_PE_RT_ADDR__ESIZE 0x00000020 +#define VIVS_PE_RT_ADDR__LEN 0x00000008 + +#define VIVS_PE_RT_ADDR_PIPE(i0, i1) (0x00014800 + 0x20*(i0) + 0x4*(i1)) +#define VIVS_PE_RT_ADDR_PIPE__ESIZE 0x00000004 +#define VIVS_PE_RT_ADDR_PIPE__LEN 0x00000008 + +#define VIVS_PE_RT_CONFIG(i0) (0x00014900 + 0x4*(i0)) +#define VIVS_PE_RT_CONFIG__ESIZE 0x00000004 +#define VIVS_PE_RT_CONFIG__LEN 0x00000008 +#define VIVS_PE_RT_CONFIG_STRIDE__MASK 0x0000ffff +#define VIVS_PE_RT_CONFIG_STRIDE__SHIFT 0 +#define VIVS_PE_RT_CONFIG_STRIDE(x) (((x) << VIVS_PE_RT_CONFIG_STRIDE__SHIFT) & VIVS_PE_RT_CONFIG_STRIDE__MASK) +#define VIVS_PE_RT_CONFIG_UNK16__MASK 0xffff0000 +#define VIVS_PE_RT_CONFIG_UNK16__SHIFT 16 +#define VIVS_PE_RT_CONFIG_UNK16(x) (((x) << VIVS_PE_RT_CONFIG_UNK16__SHIFT) & VIVS_PE_RT_CONFIG_UNK16__MASK) + +#define VIVS_PE_HALTI5_UNK14920(i0) (0x00014920 + 0x4*(i0)) +#define VIVS_PE_HALTI5_UNK14920__ESIZE 0x00000004 +#define VIVS_PE_HALTI5_UNK14920__LEN 0x00000007 + +#define VIVS_PE_HALTI5_UNK14940(i0) (0x00014940 + 0x4*(i0)) +#define VIVS_PE_HALTI5_UNK14940__ESIZE 0x00000004 +#define VIVS_PE_HALTI5_UNK14940__LEN 0x00000007 + +#define VIVS_PE_HALTI5_UNK14960(i0) (0x00014960 + 0x4*(i0)) +#define VIVS_PE_HALTI5_UNK14960__ESIZE 0x00000004 +#define VIVS_PE_HALTI5_UNK14960__LEN 0x00000007 + +#define VIVS_PE_HALTI5_UNK14980(i0) (0x00014980 + 0x4*(i0)) +#define VIVS_PE_HALTI5_UNK14980__ESIZE 0x00000004 +#define VIVS_PE_HALTI5_UNK14980__LEN 0x00000007 + +#define VIVS_PE_HALTI5_UNK149A0(i0) (0x000149a0 + 0x4*(i0)) +#define VIVS_PE_HALTI5_UNK149A0__ESIZE 0x00000004 +#define VIVS_PE_HALTI5_UNK149A0__LEN 0x00000007 + +#define VIVS_PE_ROBUSTNESS_UNK149C0(i0) (0x000149c0 + 0x4*(i0)) +#define VIVS_PE_ROBUSTNESS_UNK149C0__ESIZE 0x00000004 +#define VIVS_PE_ROBUSTNESS_UNK149C0__LEN 0x00000008 + +#define VIVS_CO 0x00000000 + +#define VIVS_CO_UNK03008 0x00003008 + +#define VIVS_CO_KICKER 0x0000300c + +#define VIVS_CO_UNK03010 0x00003010 + +#define VIVS_CO_UNK03014 0x00003014 + +#define VIVS_CO_UNK03018 0x00003018 + +#define VIVS_CO_UNK0301C 0x0000301c + +#define VIVS_CO_UNK03020 0x00003020 + +#define VIVS_CO_UNK03024 0x00003024 + +#define VIVS_CO_UNK03040 0x00003040 + +#define VIVS_CO_UNK03044 0x00003044 + +#define VIVS_CO_UNK03048 0x00003048 + +#define VIVS_CO_ICACHE_UNK0304C 0x0000304c + +#define VIVS_CO_SAMPLER(i0) (0x00000000 + 0x4*(i0)) +#define VIVS_CO_SAMPLER__ESIZE 0x00000004 +#define VIVS_CO_SAMPLER__LEN 0x00000008 + +#define VIVS_CO_SAMPLER_UNK03060(i0) (0x00003060 + 0x4*(i0)) + +#define VIVS_CO_SAMPLER_UNK03080(i0) (0x00003080 + 0x4*(i0)) + +#define VIVS_CO_SAMPLER_UNK030A0(i0) (0x000030a0 + 0x4*(i0)) + +#define VIVS_CO_SAMPLER_UNK030C0(i0) (0x000030c0 + 0x4*(i0)) + +#define VIVS_CO_SAMPLER_UNK030E0(i0) (0x000030e0 + 0x4*(i0)) + +#define VIVS_CO_SAMPLER_UNK03100(i0) (0x00003100 + 0x4*(i0)) + +#define VIVS_CO_SAMPLER_UNK03120(i0) (0x00003120 + 0x4*(i0)) + +#define VIVS_CO_SAMPLER_UNK03140(i0) (0x00003140 + 0x4*(i0)) + +#define VIVS_CO_SAMPLER_UNK03160(i0) (0x00003160 + 0x4*(i0)) + +#define VIVS_CO_SAMPLER_UNK03180(i0) (0x00003180 + 0x4*(i0)) + +#define VIVS_CO_SAMPLER_UNK031A0(i0) (0x000031a0 + 0x4*(i0)) + +#define VIVS_CO_SAMPLER_UNK031C0(i0) (0x000031c0 + 0x4*(i0)) + +#define VIVS_CO_SAMPLER_UNK031E0(i0) (0x000031e0 + 0x4*(i0)) + +#define VIVS_CO_ADDR_UNK03200(i0) (0x00003200 + 0x20*(i0)) +#define VIVS_CO_ADDR_UNK03200__ESIZE 0x00000020 +#define VIVS_CO_ADDR_UNK03200__LEN 0x00000008 + +#define VIVS_CO_ADDR_UNK03200_PPIPE(i0, i1) (0x00003200 + 0x20*(i0) + 0x4*(i1)) +#define VIVS_CO_ADDR_UNK03200_PPIPE__ESIZE 0x00000004 +#define VIVS_CO_ADDR_UNK03200_PPIPE__LEN 0x00000008 + +#define VIVS_RS 0x00000000 + +#define VIVS_RS_KICKER 0x00001600 + +#define VIVS_RS_CONFIG 0x00001604 +#define VIVS_RS_CONFIG_SOURCE_FORMAT__MASK 0x0000001f +#define VIVS_RS_CONFIG_SOURCE_FORMAT__SHIFT 0 +#define VIVS_RS_CONFIG_SOURCE_FORMAT(x) (((x) << VIVS_RS_CONFIG_SOURCE_FORMAT__SHIFT) & VIVS_RS_CONFIG_SOURCE_FORMAT__MASK) +#define VIVS_RS_CONFIG_DOWNSAMPLE_X 0x00000020 +#define VIVS_RS_CONFIG_DOWNSAMPLE_Y 0x00000040 +#define VIVS_RS_CONFIG_SOURCE_TILED 0x00000080 +#define VIVS_RS_CONFIG_DEST_FORMAT__MASK 0x00001f00 +#define VIVS_RS_CONFIG_DEST_FORMAT__SHIFT 8 +#define VIVS_RS_CONFIG_DEST_FORMAT(x) (((x) << VIVS_RS_CONFIG_DEST_FORMAT__SHIFT) & VIVS_RS_CONFIG_DEST_FORMAT__MASK) +#define VIVS_RS_CONFIG_DEST_TILED 0x00004000 +#define VIVS_RS_CONFIG_SWAP_RB 0x20000000 +#define VIVS_RS_CONFIG_FLIP 0x40000000 + +#define VIVS_RS_SOURCE_ADDR 0x00001608 + +#define VIVS_RS_SOURCE_STRIDE 0x0000160c +#define VIVS_RS_SOURCE_STRIDE_STRIDE__MASK 0x0003ffff +#define VIVS_RS_SOURCE_STRIDE_STRIDE__SHIFT 0 +#define VIVS_RS_SOURCE_STRIDE_STRIDE(x) (((x) << VIVS_RS_SOURCE_STRIDE_STRIDE__SHIFT) & VIVS_RS_SOURCE_STRIDE_STRIDE__MASK) +#define VIVS_RS_SOURCE_STRIDE_MULTI 0x40000000 +#define VIVS_RS_SOURCE_STRIDE_TILING 0x80000000 + +#define VIVS_RS_DEST_ADDR 0x00001610 + +#define VIVS_RS_DEST_STRIDE 0x00001614 +#define VIVS_RS_DEST_STRIDE_STRIDE__MASK 0x0003ffff +#define VIVS_RS_DEST_STRIDE_STRIDE__SHIFT 0 +#define VIVS_RS_DEST_STRIDE_STRIDE(x) (((x) << VIVS_RS_DEST_STRIDE_STRIDE__SHIFT) & VIVS_RS_DEST_STRIDE_STRIDE__MASK) +#define VIVS_RS_DEST_STRIDE_MULTI 0x40000000 +#define VIVS_RS_DEST_STRIDE_TILING 0x80000000 + +#define VIVS_RS_WINDOW_SIZE 0x00001620 +#define VIVS_RS_WINDOW_SIZE_HEIGHT__MASK 0xffff0000 +#define VIVS_RS_WINDOW_SIZE_HEIGHT__SHIFT 16 +#define VIVS_RS_WINDOW_SIZE_HEIGHT(x) (((x) << VIVS_RS_WINDOW_SIZE_HEIGHT__SHIFT) & VIVS_RS_WINDOW_SIZE_HEIGHT__MASK) +#define VIVS_RS_WINDOW_SIZE_WIDTH__MASK 0x0000ffff +#define VIVS_RS_WINDOW_SIZE_WIDTH__SHIFT 0 +#define VIVS_RS_WINDOW_SIZE_WIDTH(x) (((x) << VIVS_RS_WINDOW_SIZE_WIDTH__SHIFT) & VIVS_RS_WINDOW_SIZE_WIDTH__MASK) + +#define VIVS_RS_DITHER(i0) (0x00001630 + 0x4*(i0)) +#define VIVS_RS_DITHER__ESIZE 0x00000004 +#define VIVS_RS_DITHER__LEN 0x00000002 + +#define VIVS_RS_CLEAR_CONTROL 0x0000163c +#define VIVS_RS_CLEAR_CONTROL_BITS__MASK 0x0000ffff +#define VIVS_RS_CLEAR_CONTROL_BITS__SHIFT 0 +#define VIVS_RS_CLEAR_CONTROL_BITS(x) (((x) << VIVS_RS_CLEAR_CONTROL_BITS__SHIFT) & VIVS_RS_CLEAR_CONTROL_BITS__MASK) +#define VIVS_RS_CLEAR_CONTROL_MODE__MASK 0x00030000 +#define VIVS_RS_CLEAR_CONTROL_MODE__SHIFT 16 +#define VIVS_RS_CLEAR_CONTROL_MODE_DISABLED 0x00000000 +#define VIVS_RS_CLEAR_CONTROL_MODE_ENABLED1 0x00010000 +#define VIVS_RS_CLEAR_CONTROL_MODE_ENABLED4 0x00020000 +#define VIVS_RS_CLEAR_CONTROL_MODE_ENABLED4_2 0x00030000 + +#define VIVS_RS_FILL_VALUE(i0) (0x00001640 + 0x4*(i0)) +#define VIVS_RS_FILL_VALUE__ESIZE 0x00000004 +#define VIVS_RS_FILL_VALUE__LEN 0x00000004 + +#define VIVS_RS_EXTRA_CONFIG 0x000016a0 +#define VIVS_RS_EXTRA_CONFIG_AA__MASK 0x00000003 +#define VIVS_RS_EXTRA_CONFIG_AA__SHIFT 0 +#define VIVS_RS_EXTRA_CONFIG_AA(x) (((x) << VIVS_RS_EXTRA_CONFIG_AA__SHIFT) & VIVS_RS_EXTRA_CONFIG_AA__MASK) +#define VIVS_RS_EXTRA_CONFIG_ENDIAN__MASK 0x00000300 +#define VIVS_RS_EXTRA_CONFIG_ENDIAN__SHIFT 8 +#define VIVS_RS_EXTRA_CONFIG_ENDIAN(x) (((x) << VIVS_RS_EXTRA_CONFIG_ENDIAN__SHIFT) & VIVS_RS_EXTRA_CONFIG_ENDIAN__MASK) +#define VIVS_RS_EXTRA_CONFIG_UNK20 0x00100000 +#define VIVS_RS_EXTRA_CONFIG_UNK28 0x10000000 + +#define VIVS_RS_KICKER_INPLACE 0x000016b0 + +#define VIVS_RS_UNK016B4 0x000016b4 + +#define VIVS_RS_SINGLE_BUFFER 0x000016b8 +#define VIVS_RS_SINGLE_BUFFER_ENABLE 0x00000001 + +#define VIVS_RS_PIPE(i0) (0x00000000 + 0x4*(i0)) +#define VIVS_RS_PIPE__ESIZE 0x00000004 +#define VIVS_RS_PIPE__LEN 0x00000008 + +#define VIVS_RS_PIPE_SOURCE_ADDR(i0) (0x000016c0 + 0x4*(i0)) + +#define VIVS_RS_PIPE_DEST_ADDR(i0) (0x000016e0 + 0x4*(i0)) + +#define VIVS_RS_PIPE_OFFSET(i0) (0x00001700 + 0x4*(i0)) +#define VIVS_RS_PIPE_OFFSET_X__MASK 0x0000ffff +#define VIVS_RS_PIPE_OFFSET_X__SHIFT 0 +#define VIVS_RS_PIPE_OFFSET_X(x) (((x) << VIVS_RS_PIPE_OFFSET_X__SHIFT) & VIVS_RS_PIPE_OFFSET_X__MASK) +#define VIVS_RS_PIPE_OFFSET_Y__MASK 0xffff0000 +#define VIVS_RS_PIPE_OFFSET_Y__SHIFT 16 +#define VIVS_RS_PIPE_OFFSET_Y(x) (((x) << VIVS_RS_PIPE_OFFSET_Y__SHIFT) & VIVS_RS_PIPE_OFFSET_Y__MASK) + +#define VIVS_TS 0x00000000 + +#define VIVS_TS_FLUSH_CACHE 0x00001650 +#define VIVS_TS_FLUSH_CACHE_FLUSH 0x00000001 + +#define VIVS_TS_MEM_CONFIG 0x00001654 +#define VIVS_TS_MEM_CONFIG_DEPTH_FAST_CLEAR 0x00000001 +#define VIVS_TS_MEM_CONFIG_COLOR_FAST_CLEAR 0x00000002 +#define VIVS_TS_MEM_CONFIG_DEPTH_16BPP 0x00000008 +#define VIVS_TS_MEM_CONFIG_DEPTH_AUTO_DISABLE 0x00000010 +#define VIVS_TS_MEM_CONFIG_COLOR_AUTO_DISABLE 0x00000020 +#define VIVS_TS_MEM_CONFIG_DEPTH_COMPRESSION 0x00000040 +#define VIVS_TS_MEM_CONFIG_MSAA 0x00000080 +#define VIVS_TS_MEM_CONFIG_MSAA_FORMAT__MASK 0x00000f00 +#define VIVS_TS_MEM_CONFIG_MSAA_FORMAT__SHIFT 8 +#define VIVS_TS_MEM_CONFIG_MSAA_FORMAT_A4R4G4B4 0x00000000 +#define VIVS_TS_MEM_CONFIG_MSAA_FORMAT_A1R5G5B5 0x00000100 +#define VIVS_TS_MEM_CONFIG_MSAA_FORMAT_R5G6B5 0x00000200 +#define VIVS_TS_MEM_CONFIG_MSAA_FORMAT_A8R8G8B8 0x00000300 +#define VIVS_TS_MEM_CONFIG_MSAA_FORMAT_X8R8G8B8 0x00000400 +#define VIVS_TS_MEM_CONFIG_UNK12 0x00001000 +#define VIVS_TS_MEM_CONFIG_HDEPTH_AUTO_DISABLE 0x00002000 +#define VIVS_TS_MEM_CONFIG_UNK14 0x00004000 +#define VIVS_TS_MEM_CONFIG_UNK21 0x00200000 + +#define VIVS_TS_COLOR_STATUS_BASE 0x00001658 + +#define VIVS_TS_COLOR_SURFACE_BASE 0x0000165c + +#define VIVS_TS_COLOR_CLEAR_VALUE 0x00001660 + +#define VIVS_TS_DEPTH_STATUS_BASE 0x00001664 + +#define VIVS_TS_DEPTH_SURFACE_BASE 0x00001668 + +#define VIVS_TS_DEPTH_CLEAR_VALUE 0x0000166c + +#define VIVS_TS_DEPTH_AUTO_DISABLE_COUNT 0x00001670 + +#define VIVS_TS_COLOR_AUTO_DISABLE_COUNT 0x00001674 + +#define VIVS_TS_HDEPTH_STATUS_BASE 0x000016a4 + +#define VIVS_TS_HDEPTH_CLEAR_VALUE 0x000016a8 + +#define VIVS_TS_HDEPTH_SIZE 0x000016ac + +#define VIVS_TS_COLOR_CLEAR_VALUE_EXT 0x000016bc + +#define VIVS_TS_SAMPLER(i0) (0x00000000 + 0x4*(i0)) +#define VIVS_TS_SAMPLER__ESIZE 0x00000004 +#define VIVS_TS_SAMPLER__LEN 0x00000008 + +#define VIVS_TS_SAMPLER_CONFIG(i0) (0x00001720 + 0x4*(i0)) +#define VIVS_TS_SAMPLER_CONFIG_ENABLE__MASK 0x00000003 +#define VIVS_TS_SAMPLER_CONFIG_ENABLE__SHIFT 0 +#define VIVS_TS_SAMPLER_CONFIG_ENABLE(x) (((x) << VIVS_TS_SAMPLER_CONFIG_ENABLE__SHIFT) & VIVS_TS_SAMPLER_CONFIG_ENABLE__MASK) +#define VIVS_TS_SAMPLER_CONFIG_FORMAT__MASK 0x000000f0 +#define VIVS_TS_SAMPLER_CONFIG_FORMAT__SHIFT 4 +#define VIVS_TS_SAMPLER_CONFIG_FORMAT(x) (((x) << VIVS_TS_SAMPLER_CONFIG_FORMAT__SHIFT) & VIVS_TS_SAMPLER_CONFIG_FORMAT__MASK) +#define VIVS_TS_SAMPLER_CONFIG_UNK11__MASK 0x00003800 +#define VIVS_TS_SAMPLER_CONFIG_UNK11__SHIFT 11 +#define VIVS_TS_SAMPLER_CONFIG_UNK11(x) (((x) << VIVS_TS_SAMPLER_CONFIG_UNK11__SHIFT) & VIVS_TS_SAMPLER_CONFIG_UNK11__MASK) + +#define VIVS_TS_SAMPLER_STATUS_BASE(i0) (0x00001740 + 0x4*(i0)) + +#define VIVS_TS_SAMPLER_CLEAR_VALUE(i0) (0x00001760 + 0x4*(i0)) + +#define VIVS_TS_SAMPLER_CLEAR_VALUE2(i0) (0x00001780 + 0x4*(i0)) + +#define VIVS_TS_SAMPLER_SURFACE_BASE(i0) (0x00001a80 + 0x4*(i0)) + +#define VIVS_TS_RT(i0) (0x00000000 + 0x4*(i0)) +#define VIVS_TS_RT__ESIZE 0x00000004 +#define VIVS_TS_RT__LEN 0x00000008 + +#define VIVS_TS_RT_UNK017A0(i0) (0x000017a0 + 0x4*(i0)) + +#define VIVS_TS_RT_STATUS_BASE(i0) (0x000017c0 + 0x4*(i0)) + +#define VIVS_TS_RT_SURFACE_BASE(i0) (0x000017e0 + 0x4*(i0)) + +#define VIVS_TS_RT_CLEAR_VALUE(i0) (0x00001a00 + 0x4*(i0)) + +#define VIVS_TS_RT_CLEAR_VALUE2(i0) (0x00001a20 + 0x4*(i0)) + +#define VIVS_TS_RT_UNK01A40(i0) (0x00001a40 + 0x4*(i0)) + +#define VIVS_YUV 0x00000000 + +#define VIVS_YUV_UNK01678 0x00001678 + +#define VIVS_YUV_UNK0167C 0x0000167c + +#define VIVS_YUV_UNK01680 0x00001680 + +#define VIVS_YUV_UNK01684 0x00001684 + +#define VIVS_YUV_UNK01688 0x00001688 + +#define VIVS_YUV_UNK0168C 0x0000168c + +#define VIVS_YUV_UNK01690 0x00001690 + +#define VIVS_YUV_UNK01694 0x00001694 + +#define VIVS_YUV_UNK01698 0x00001698 + +#define VIVS_YUV_UNK0169C 0x0000169c + +#define VIVS_TE 0x00000000 + +#define VIVS_TE_SAMPLER(i0) (0x00000000 + 0x4*(i0)) +#define VIVS_TE_SAMPLER__ESIZE 0x00000004 +#define VIVS_TE_SAMPLER__LEN 0x0000000c + +#define VIVS_TE_SAMPLER_CONFIG0(i0) (0x00002000 + 0x4*(i0)) +#define VIVS_TE_SAMPLER_CONFIG0_TYPE__MASK 0x00000007 +#define VIVS_TE_SAMPLER_CONFIG0_TYPE__SHIFT 0 +#define VIVS_TE_SAMPLER_CONFIG0_TYPE(x) (((x) << VIVS_TE_SAMPLER_CONFIG0_TYPE__SHIFT) & VIVS_TE_SAMPLER_CONFIG0_TYPE__MASK) +#define VIVS_TE_SAMPLER_CONFIG0_UWRAP__MASK 0x00000018 +#define VIVS_TE_SAMPLER_CONFIG0_UWRAP__SHIFT 3 +#define VIVS_TE_SAMPLER_CONFIG0_UWRAP(x) (((x) << VIVS_TE_SAMPLER_CONFIG0_UWRAP__SHIFT) & VIVS_TE_SAMPLER_CONFIG0_UWRAP__MASK) +#define VIVS_TE_SAMPLER_CONFIG0_VWRAP__MASK 0x00000060 +#define VIVS_TE_SAMPLER_CONFIG0_VWRAP__SHIFT 5 +#define VIVS_TE_SAMPLER_CONFIG0_VWRAP(x) (((x) << VIVS_TE_SAMPLER_CONFIG0_VWRAP__SHIFT) & VIVS_TE_SAMPLER_CONFIG0_VWRAP__MASK) +#define VIVS_TE_SAMPLER_CONFIG0_MIN__MASK 0x00000180 +#define VIVS_TE_SAMPLER_CONFIG0_MIN__SHIFT 7 +#define VIVS_TE_SAMPLER_CONFIG0_MIN(x) (((x) << VIVS_TE_SAMPLER_CONFIG0_MIN__SHIFT) & VIVS_TE_SAMPLER_CONFIG0_MIN__MASK) +#define VIVS_TE_SAMPLER_CONFIG0_MIP__MASK 0x00000600 +#define VIVS_TE_SAMPLER_CONFIG0_MIP__SHIFT 9 +#define VIVS_TE_SAMPLER_CONFIG0_MIP(x) (((x) << VIVS_TE_SAMPLER_CONFIG0_MIP__SHIFT) & VIVS_TE_SAMPLER_CONFIG0_MIP__MASK) +#define VIVS_TE_SAMPLER_CONFIG0_MAG__MASK 0x00001800 +#define VIVS_TE_SAMPLER_CONFIG0_MAG__SHIFT 11 +#define VIVS_TE_SAMPLER_CONFIG0_MAG(x) (((x) << VIVS_TE_SAMPLER_CONFIG0_MAG__SHIFT) & VIVS_TE_SAMPLER_CONFIG0_MAG__MASK) +#define VIVS_TE_SAMPLER_CONFIG0_FORMAT__MASK 0x0003e000 +#define VIVS_TE_SAMPLER_CONFIG0_FORMAT__SHIFT 13 +#define VIVS_TE_SAMPLER_CONFIG0_FORMAT(x) (((x) << VIVS_TE_SAMPLER_CONFIG0_FORMAT__SHIFT) & VIVS_TE_SAMPLER_CONFIG0_FORMAT__MASK) +#define VIVS_TE_SAMPLER_CONFIG0_ROUND_UV 0x00080000 +#define VIVS_TE_SAMPLER_CONFIG0_ENDIAN__MASK 0x00c00000 +#define VIVS_TE_SAMPLER_CONFIG0_ENDIAN__SHIFT 22 +#define VIVS_TE_SAMPLER_CONFIG0_ENDIAN(x) (((x) << VIVS_TE_SAMPLER_CONFIG0_ENDIAN__SHIFT) & VIVS_TE_SAMPLER_CONFIG0_ENDIAN__MASK) +#define VIVS_TE_SAMPLER_CONFIG0_ANISOTROPY__MASK 0xff000000 +#define VIVS_TE_SAMPLER_CONFIG0_ANISOTROPY__SHIFT 24 +#define VIVS_TE_SAMPLER_CONFIG0_ANISOTROPY(x) (((x) << VIVS_TE_SAMPLER_CONFIG0_ANISOTROPY__SHIFT) & VIVS_TE_SAMPLER_CONFIG0_ANISOTROPY__MASK) + +#define VIVS_TE_SAMPLER_SIZE(i0) (0x00002040 + 0x4*(i0)) +#define VIVS_TE_SAMPLER_SIZE_WIDTH__MASK 0x0000ffff +#define VIVS_TE_SAMPLER_SIZE_WIDTH__SHIFT 0 +#define VIVS_TE_SAMPLER_SIZE_WIDTH(x) (((x) << VIVS_TE_SAMPLER_SIZE_WIDTH__SHIFT) & VIVS_TE_SAMPLER_SIZE_WIDTH__MASK) +#define VIVS_TE_SAMPLER_SIZE_HEIGHT__MASK 0xffff0000 +#define VIVS_TE_SAMPLER_SIZE_HEIGHT__SHIFT 16 +#define VIVS_TE_SAMPLER_SIZE_HEIGHT(x) (((x) << VIVS_TE_SAMPLER_SIZE_HEIGHT__SHIFT) & VIVS_TE_SAMPLER_SIZE_HEIGHT__MASK) + +#define VIVS_TE_SAMPLER_LOG_SIZE(i0) (0x00002080 + 0x4*(i0)) +#define VIVS_TE_SAMPLER_LOG_SIZE_WIDTH__MASK 0x000003ff +#define VIVS_TE_SAMPLER_LOG_SIZE_WIDTH__SHIFT 0 +#define VIVS_TE_SAMPLER_LOG_SIZE_WIDTH(x) (((x) << VIVS_TE_SAMPLER_LOG_SIZE_WIDTH__SHIFT) & VIVS_TE_SAMPLER_LOG_SIZE_WIDTH__MASK) +#define VIVS_TE_SAMPLER_LOG_SIZE_HEIGHT__MASK 0x000ffc00 +#define VIVS_TE_SAMPLER_LOG_SIZE_HEIGHT__SHIFT 10 +#define VIVS_TE_SAMPLER_LOG_SIZE_HEIGHT(x) (((x) << VIVS_TE_SAMPLER_LOG_SIZE_HEIGHT__SHIFT) & VIVS_TE_SAMPLER_LOG_SIZE_HEIGHT__MASK) +#define VIVS_TE_SAMPLER_LOG_SIZE_RGB 0x20000000 +#define VIVS_TE_SAMPLER_LOG_SIZE_SRGB 0x80000000 + +#define VIVS_TE_SAMPLER_LOD_CONFIG(i0) (0x000020c0 + 0x4*(i0)) +#define VIVS_TE_SAMPLER_LOD_CONFIG_BIAS_ENABLE 0x00000001 +#define VIVS_TE_SAMPLER_LOD_CONFIG_MAX__MASK 0x000007fe +#define VIVS_TE_SAMPLER_LOD_CONFIG_MAX__SHIFT 1 +#define VIVS_TE_SAMPLER_LOD_CONFIG_MAX(x) (((x) << VIVS_TE_SAMPLER_LOD_CONFIG_MAX__SHIFT) & VIVS_TE_SAMPLER_LOD_CONFIG_MAX__MASK) +#define VIVS_TE_SAMPLER_LOD_CONFIG_MIN__MASK 0x001ff800 +#define VIVS_TE_SAMPLER_LOD_CONFIG_MIN__SHIFT 11 +#define VIVS_TE_SAMPLER_LOD_CONFIG_MIN(x) (((x) << VIVS_TE_SAMPLER_LOD_CONFIG_MIN__SHIFT) & VIVS_TE_SAMPLER_LOD_CONFIG_MIN__MASK) +#define VIVS_TE_SAMPLER_LOD_CONFIG_BIAS__MASK 0x7fe00000 +#define VIVS_TE_SAMPLER_LOD_CONFIG_BIAS__SHIFT 21 +#define VIVS_TE_SAMPLER_LOD_CONFIG_BIAS(x) (((x) << VIVS_TE_SAMPLER_LOD_CONFIG_BIAS__SHIFT) & VIVS_TE_SAMPLER_LOD_CONFIG_BIAS__MASK) + +#define VIVS_TE_SAMPLER_UNK02100(i0) (0x00002100 + 0x4*(i0)) + +#define VIVS_TE_SAMPLER_UNK02140(i0) (0x00002140 + 0x4*(i0)) + +#define VIVS_TE_SAMPLER_3D_CONFIG(i0) (0x00002180 + 0x4*(i0)) +#define VIVS_TE_SAMPLER_3D_CONFIG_DEPTH__MASK 0x00003fff +#define VIVS_TE_SAMPLER_3D_CONFIG_DEPTH__SHIFT 0 +#define VIVS_TE_SAMPLER_3D_CONFIG_DEPTH(x) (((x) << VIVS_TE_SAMPLER_3D_CONFIG_DEPTH__SHIFT) & VIVS_TE_SAMPLER_3D_CONFIG_DEPTH__MASK) +#define VIVS_TE_SAMPLER_3D_CONFIG_LOG_DEPTH__MASK 0x03ff0000 +#define VIVS_TE_SAMPLER_3D_CONFIG_LOG_DEPTH__SHIFT 16 +#define VIVS_TE_SAMPLER_3D_CONFIG_LOG_DEPTH(x) (((x) << VIVS_TE_SAMPLER_3D_CONFIG_LOG_DEPTH__SHIFT) & VIVS_TE_SAMPLER_3D_CONFIG_LOG_DEPTH__MASK) +#define VIVS_TE_SAMPLER_3D_CONFIG_WRAP__MASK 0x30000000 +#define VIVS_TE_SAMPLER_3D_CONFIG_WRAP__SHIFT 28 +#define VIVS_TE_SAMPLER_3D_CONFIG_WRAP(x) (((x) << VIVS_TE_SAMPLER_3D_CONFIG_WRAP__SHIFT) & VIVS_TE_SAMPLER_3D_CONFIG_WRAP__MASK) + +#define VIVS_TE_SAMPLER_CONFIG1(i0) (0x000021c0 + 0x4*(i0)) +#define VIVS_TE_SAMPLER_CONFIG1_FORMAT_EXT__MASK 0x0000001f +#define VIVS_TE_SAMPLER_CONFIG1_FORMAT_EXT__SHIFT 0 +#define VIVS_TE_SAMPLER_CONFIG1_FORMAT_EXT(x) (((x) << VIVS_TE_SAMPLER_CONFIG1_FORMAT_EXT__SHIFT) & VIVS_TE_SAMPLER_CONFIG1_FORMAT_EXT__MASK) +#define VIVS_TE_SAMPLER_CONFIG1_SWIZZLE_R__MASK 0x00000700 +#define VIVS_TE_SAMPLER_CONFIG1_SWIZZLE_R__SHIFT 8 +#define VIVS_TE_SAMPLER_CONFIG1_SWIZZLE_R(x) (((x) << VIVS_TE_SAMPLER_CONFIG1_SWIZZLE_R__SHIFT) & VIVS_TE_SAMPLER_CONFIG1_SWIZZLE_R__MASK) +#define VIVS_TE_SAMPLER_CONFIG1_SWIZZLE_G__MASK 0x00007000 +#define VIVS_TE_SAMPLER_CONFIG1_SWIZZLE_G__SHIFT 12 +#define VIVS_TE_SAMPLER_CONFIG1_SWIZZLE_G(x) (((x) << VIVS_TE_SAMPLER_CONFIG1_SWIZZLE_G__SHIFT) & VIVS_TE_SAMPLER_CONFIG1_SWIZZLE_G__MASK) +#define VIVS_TE_SAMPLER_CONFIG1_SWIZZLE_B__MASK 0x00070000 +#define VIVS_TE_SAMPLER_CONFIG1_SWIZZLE_B__SHIFT 16 +#define VIVS_TE_SAMPLER_CONFIG1_SWIZZLE_B(x) (((x) << VIVS_TE_SAMPLER_CONFIG1_SWIZZLE_B__SHIFT) & VIVS_TE_SAMPLER_CONFIG1_SWIZZLE_B__MASK) +#define VIVS_TE_SAMPLER_CONFIG1_SWIZZLE_A__MASK 0x00700000 +#define VIVS_TE_SAMPLER_CONFIG1_SWIZZLE_A__SHIFT 20 +#define VIVS_TE_SAMPLER_CONFIG1_SWIZZLE_A(x) (((x) << VIVS_TE_SAMPLER_CONFIG1_SWIZZLE_A__SHIFT) & VIVS_TE_SAMPLER_CONFIG1_SWIZZLE_A__MASK) +#define VIVS_TE_SAMPLER_CONFIG1_TEXTURE_ARRAY 0x01000000 +#define VIVS_TE_SAMPLER_CONFIG1_UNK25 0x02000000 +#define VIVS_TE_SAMPLER_CONFIG1_HALIGN__MASK 0x1c000000 +#define VIVS_TE_SAMPLER_CONFIG1_HALIGN__SHIFT 26 +#define VIVS_TE_SAMPLER_CONFIG1_HALIGN(x) (((x) << VIVS_TE_SAMPLER_CONFIG1_HALIGN__SHIFT) & VIVS_TE_SAMPLER_CONFIG1_HALIGN__MASK) + +#define VIVS_TE_SAMPLER_UNK02200(i0) (0x00002200 + 0x4*(i0)) + +#define VIVS_TE_SAMPLER_UNK02240(i0) (0x00002240 + 0x4*(i0)) + +#define VIVS_TE_SAMPLER_LOD_ADDR(i0, i1) (0x00002400 + 0x4*(i0) + 0x40*(i1)) +#define VIVS_TE_SAMPLER_LOD_ADDR__ESIZE 0x00000040 +#define VIVS_TE_SAMPLER_LOD_ADDR__LEN 0x0000000e + +#define VIVS_TE_SAMPLER_LINEAR_STRIDE(i0, i1) (0x00002c00 + 0x4*(i0) + 0x40*(i1)) +#define VIVS_TE_SAMPLER_LINEAR_STRIDE__ESIZE 0x00000040 +#define VIVS_TE_SAMPLER_LINEAR_STRIDE__LEN 0x0000000e + +#define VIVS_NTE 0x00000000 + +#define VIVS_NTE_SAMPLER(i0) (0x00000000 + 0x4*(i0)) +#define VIVS_NTE_SAMPLER__ESIZE 0x00000004 +#define VIVS_NTE_SAMPLER__LEN 0x00000020 + +#define VIVS_NTE_SAMPLER_CONFIG0(i0) (0x00010000 + 0x4*(i0)) +#define VIVS_NTE_SAMPLER_CONFIG0_TYPE__MASK 0x00000007 +#define VIVS_NTE_SAMPLER_CONFIG0_TYPE__SHIFT 0 +#define VIVS_NTE_SAMPLER_CONFIG0_TYPE(x) (((x) << VIVS_NTE_SAMPLER_CONFIG0_TYPE__SHIFT) & VIVS_NTE_SAMPLER_CONFIG0_TYPE__MASK) +#define VIVS_NTE_SAMPLER_CONFIG0_UWRAP__MASK 0x00000018 +#define VIVS_NTE_SAMPLER_CONFIG0_UWRAP__SHIFT 3 +#define VIVS_NTE_SAMPLER_CONFIG0_UWRAP(x) (((x) << VIVS_NTE_SAMPLER_CONFIG0_UWRAP__SHIFT) & VIVS_NTE_SAMPLER_CONFIG0_UWRAP__MASK) +#define VIVS_NTE_SAMPLER_CONFIG0_VWRAP__MASK 0x00000060 +#define VIVS_NTE_SAMPLER_CONFIG0_VWRAP__SHIFT 5 +#define VIVS_NTE_SAMPLER_CONFIG0_VWRAP(x) (((x) << VIVS_NTE_SAMPLER_CONFIG0_VWRAP__SHIFT) & VIVS_NTE_SAMPLER_CONFIG0_VWRAP__MASK) +#define VIVS_NTE_SAMPLER_CONFIG0_MIN__MASK 0x00000180 +#define VIVS_NTE_SAMPLER_CONFIG0_MIN__SHIFT 7 +#define VIVS_NTE_SAMPLER_CONFIG0_MIN(x) (((x) << VIVS_NTE_SAMPLER_CONFIG0_MIN__SHIFT) & VIVS_NTE_SAMPLER_CONFIG0_MIN__MASK) +#define VIVS_NTE_SAMPLER_CONFIG0_MIP__MASK 0x00000600 +#define VIVS_NTE_SAMPLER_CONFIG0_MIP__SHIFT 9 +#define VIVS_NTE_SAMPLER_CONFIG0_MIP(x) (((x) << VIVS_NTE_SAMPLER_CONFIG0_MIP__SHIFT) & VIVS_NTE_SAMPLER_CONFIG0_MIP__MASK) +#define VIVS_NTE_SAMPLER_CONFIG0_MAG__MASK 0x00001800 +#define VIVS_NTE_SAMPLER_CONFIG0_MAG__SHIFT 11 +#define VIVS_NTE_SAMPLER_CONFIG0_MAG(x) (((x) << VIVS_NTE_SAMPLER_CONFIG0_MAG__SHIFT) & VIVS_NTE_SAMPLER_CONFIG0_MAG__MASK) +#define VIVS_NTE_SAMPLER_CONFIG0_FORMAT__MASK 0x0003e000 +#define VIVS_NTE_SAMPLER_CONFIG0_FORMAT__SHIFT 13 +#define VIVS_NTE_SAMPLER_CONFIG0_FORMAT(x) (((x) << VIVS_NTE_SAMPLER_CONFIG0_FORMAT__SHIFT) & VIVS_NTE_SAMPLER_CONFIG0_FORMAT__MASK) +#define VIVS_NTE_SAMPLER_CONFIG0_ROUND_UV 0x00080000 +#define VIVS_NTE_SAMPLER_CONFIG0_ENDIAN__MASK 0x00c00000 +#define VIVS_NTE_SAMPLER_CONFIG0_ENDIAN__SHIFT 22 +#define VIVS_NTE_SAMPLER_CONFIG0_ENDIAN(x) (((x) << VIVS_NTE_SAMPLER_CONFIG0_ENDIAN__SHIFT) & VIVS_NTE_SAMPLER_CONFIG0_ENDIAN__MASK) +#define VIVS_NTE_SAMPLER_CONFIG0_ANISOTROPY__MASK 0xff000000 +#define VIVS_NTE_SAMPLER_CONFIG0_ANISOTROPY__SHIFT 24 +#define VIVS_NTE_SAMPLER_CONFIG0_ANISOTROPY(x) (((x) << VIVS_NTE_SAMPLER_CONFIG0_ANISOTROPY__SHIFT) & VIVS_NTE_SAMPLER_CONFIG0_ANISOTROPY__MASK) + +#define VIVS_NTE_SAMPLER_SIZE(i0) (0x00010080 + 0x4*(i0)) +#define VIVS_NTE_SAMPLER_SIZE_WIDTH__MASK 0x0000ffff +#define VIVS_NTE_SAMPLER_SIZE_WIDTH__SHIFT 0 +#define VIVS_NTE_SAMPLER_SIZE_WIDTH(x) (((x) << VIVS_NTE_SAMPLER_SIZE_WIDTH__SHIFT) & VIVS_NTE_SAMPLER_SIZE_WIDTH__MASK) +#define VIVS_NTE_SAMPLER_SIZE_HEIGHT__MASK 0xffff0000 +#define VIVS_NTE_SAMPLER_SIZE_HEIGHT__SHIFT 16 +#define VIVS_NTE_SAMPLER_SIZE_HEIGHT(x) (((x) << VIVS_NTE_SAMPLER_SIZE_HEIGHT__SHIFT) & VIVS_NTE_SAMPLER_SIZE_HEIGHT__MASK) + +#define VIVS_NTE_SAMPLER_LOG_SIZE(i0) (0x00010100 + 0x4*(i0)) +#define VIVS_NTE_SAMPLER_LOG_SIZE_WIDTH__MASK 0x000003ff +#define VIVS_NTE_SAMPLER_LOG_SIZE_WIDTH__SHIFT 0 +#define VIVS_NTE_SAMPLER_LOG_SIZE_WIDTH(x) (((x) << VIVS_NTE_SAMPLER_LOG_SIZE_WIDTH__SHIFT) & VIVS_NTE_SAMPLER_LOG_SIZE_WIDTH__MASK) +#define VIVS_NTE_SAMPLER_LOG_SIZE_HEIGHT__MASK 0x000ffc00 +#define VIVS_NTE_SAMPLER_LOG_SIZE_HEIGHT__SHIFT 10 +#define VIVS_NTE_SAMPLER_LOG_SIZE_HEIGHT(x) (((x) << VIVS_NTE_SAMPLER_LOG_SIZE_HEIGHT__SHIFT) & VIVS_NTE_SAMPLER_LOG_SIZE_HEIGHT__MASK) +#define VIVS_NTE_SAMPLER_LOG_SIZE_RGB 0x20000000 +#define VIVS_NTE_SAMPLER_LOG_SIZE_SRGB 0x80000000 + +#define VIVS_NTE_SAMPLER_LOD_CONFIG(i0) (0x00010180 + 0x4*(i0)) +#define VIVS_NTE_SAMPLER_LOD_CONFIG_BIAS_ENABLE 0x00000001 +#define VIVS_NTE_SAMPLER_LOD_CONFIG_MAX__MASK 0x000007fe +#define VIVS_NTE_SAMPLER_LOD_CONFIG_MAX__SHIFT 1 +#define VIVS_NTE_SAMPLER_LOD_CONFIG_MAX(x) (((x) << VIVS_NTE_SAMPLER_LOD_CONFIG_MAX__SHIFT) & VIVS_NTE_SAMPLER_LOD_CONFIG_MAX__MASK) +#define VIVS_NTE_SAMPLER_LOD_CONFIG_MIN__MASK 0x001ff800 +#define VIVS_NTE_SAMPLER_LOD_CONFIG_MIN__SHIFT 11 +#define VIVS_NTE_SAMPLER_LOD_CONFIG_MIN(x) (((x) << VIVS_NTE_SAMPLER_LOD_CONFIG_MIN__SHIFT) & VIVS_NTE_SAMPLER_LOD_CONFIG_MIN__MASK) +#define VIVS_NTE_SAMPLER_LOD_CONFIG_BIAS__MASK 0x7fe00000 +#define VIVS_NTE_SAMPLER_LOD_CONFIG_BIAS__SHIFT 21 +#define VIVS_NTE_SAMPLER_LOD_CONFIG_BIAS(x) (((x) << VIVS_NTE_SAMPLER_LOD_CONFIG_BIAS__SHIFT) & VIVS_NTE_SAMPLER_LOD_CONFIG_BIAS__MASK) + +#define VIVS_NTE_SAMPLER_UNK10200(i0) (0x00010200 + 0x4*(i0)) + +#define VIVS_NTE_SAMPLER_UNK10280(i0) (0x00010280 + 0x4*(i0)) + +#define VIVS_NTE_SAMPLER_UNK10300(i0) (0x00010300 + 0x4*(i0)) + +#define VIVS_NTE_SAMPLER_CONFIG1(i0) (0x00010380 + 0x4*(i0)) +#define VIVS_NTE_SAMPLER_CONFIG1_FORMAT_EXT__MASK 0x0000001f +#define VIVS_NTE_SAMPLER_CONFIG1_FORMAT_EXT__SHIFT 0 +#define VIVS_NTE_SAMPLER_CONFIG1_FORMAT_EXT(x) (((x) << VIVS_NTE_SAMPLER_CONFIG1_FORMAT_EXT__SHIFT) & VIVS_NTE_SAMPLER_CONFIG1_FORMAT_EXT__MASK) +#define VIVS_NTE_SAMPLER_CONFIG1_SWIZZLE_R__MASK 0x00000700 +#define VIVS_NTE_SAMPLER_CONFIG1_SWIZZLE_R__SHIFT 8 +#define VIVS_NTE_SAMPLER_CONFIG1_SWIZZLE_R(x) (((x) << VIVS_NTE_SAMPLER_CONFIG1_SWIZZLE_R__SHIFT) & VIVS_NTE_SAMPLER_CONFIG1_SWIZZLE_R__MASK) +#define VIVS_NTE_SAMPLER_CONFIG1_SWIZZLE_G__MASK 0x00007000 +#define VIVS_NTE_SAMPLER_CONFIG1_SWIZZLE_G__SHIFT 12 +#define VIVS_NTE_SAMPLER_CONFIG1_SWIZZLE_G(x) (((x) << VIVS_NTE_SAMPLER_CONFIG1_SWIZZLE_G__SHIFT) & VIVS_NTE_SAMPLER_CONFIG1_SWIZZLE_G__MASK) +#define VIVS_NTE_SAMPLER_CONFIG1_SWIZZLE_B__MASK 0x00070000 +#define VIVS_NTE_SAMPLER_CONFIG1_SWIZZLE_B__SHIFT 16 +#define VIVS_NTE_SAMPLER_CONFIG1_SWIZZLE_B(x) (((x) << VIVS_NTE_SAMPLER_CONFIG1_SWIZZLE_B__SHIFT) & VIVS_NTE_SAMPLER_CONFIG1_SWIZZLE_B__MASK) +#define VIVS_NTE_SAMPLER_CONFIG1_SWIZZLE_A__MASK 0x00700000 +#define VIVS_NTE_SAMPLER_CONFIG1_SWIZZLE_A__SHIFT 20 +#define VIVS_NTE_SAMPLER_CONFIG1_SWIZZLE_A(x) (((x) << VIVS_NTE_SAMPLER_CONFIG1_SWIZZLE_A__SHIFT) & VIVS_NTE_SAMPLER_CONFIG1_SWIZZLE_A__MASK) +#define VIVS_NTE_SAMPLER_CONFIG1_TEXTURE_ARRAY 0x01000000 +#define VIVS_NTE_SAMPLER_CONFIG1_UNK25 0x02000000 +#define VIVS_NTE_SAMPLER_CONFIG1_HALIGN__MASK 0x1c000000 +#define VIVS_NTE_SAMPLER_CONFIG1_HALIGN__SHIFT 26 +#define VIVS_NTE_SAMPLER_CONFIG1_HALIGN(x) (((x) << VIVS_NTE_SAMPLER_CONFIG1_HALIGN__SHIFT) & VIVS_NTE_SAMPLER_CONFIG1_HALIGN__MASK) + +#define VIVS_NTE_SAMPLER_UNK10400(i0) (0x00010400 + 0x4*(i0)) + +#define VIVS_NTE_SAMPLER_UNK10480(i0) (0x00010480 + 0x4*(i0)) + +#define VIVS_NTE_SAMPLER_ASTC_UNK10500(i0) (0x00010500 + 0x4*(i0)) + +#define VIVS_NTE_SAMPLER_ASTC_UNK10580(i0) (0x00010580 + 0x4*(i0)) + +#define VIVS_NTE_SAMPLER_ASTC_UNK10600(i0) (0x00010600 + 0x4*(i0)) + +#define VIVS_NTE_SAMPLER_ASTC_UNK10680(i0) (0x00010600 + 0x4*(i0)) + +#define VIVS_NTE_SAMPLER_BASELOD(i0) (0x00010700 + 0x4*(i0)) + +#define VIVS_NTE_SAMPLER_UNK10780(i0) (0x00010780 + 0x4*(i0)) + +#define VIVS_NTE_SAMPLER_FRAC_UNK11000(i0) (0x00011000 + 0x4*(i0)) + +#define VIVS_NTE_SAMPLER_FRAC_UNK11080(i0) (0x00011080 + 0x4*(i0)) + +#define VIVS_NTE_SAMPLER_FRAC_UNK11100(i0) (0x00011100 + 0x4*(i0)) + +#define VIVS_NTE_SAMPLER_FRAC_UNK11180(i0) (0x00011180 + 0x4*(i0)) + +#define VIVS_NTE_SAMPLER_HALTI4_UNK11200(i0) (0x00011200 + 0x4*(i0)) + +#define VIVS_NTE_SAMPLER_HALTI4_UNK11280(i0) (0x00011280 + 0x4*(i0)) + +#define VIVS_NTE_SAMPLER_FRAC_UNK11300(i0) (0x00011300 + 0x4*(i0)) + +#define VIVS_NTE_SAMPLER_ADDR(i0) (0x00010800 + 0x40*(i0)) +#define VIVS_NTE_SAMPLER_ADDR__ESIZE 0x00000040 +#define VIVS_NTE_SAMPLER_ADDR__LEN 0x00000020 + +#define VIVS_NTE_SAMPLER_ADDR_LOD(i0, i1) (0x00010800 + 0x40*(i0) + 0x4*(i1)) +#define VIVS_NTE_SAMPLER_ADDR_LOD__ESIZE 0x00000004 +#define VIVS_NTE_SAMPLER_ADDR_LOD__LEN 0x0000000e + +#define VIVS_NTE_UNK12000(i0) (0x00012000 + 0x4*(i0)) +#define VIVS_NTE_UNK12000__ESIZE 0x00000004 +#define VIVS_NTE_UNK12000__LEN 0x00000100 + +#define VIVS_NTE_UNK12400(i0) (0x00012400 + 0x4*(i0)) +#define VIVS_NTE_UNK12400__ESIZE 0x00000004 +#define VIVS_NTE_UNK12400__LEN 0x00000100 + +#define VIVS_NTE_HALTI3_UNK14C00(i0) (0x00014c00 + 0x4*(i0)) +#define VIVS_NTE_HALTI3_UNK14C00__ESIZE 0x00000004 +#define VIVS_NTE_HALTI3_UNK14C00__LEN 0x00000010 + +#define VIVS_NTE_DESCRIPTOR_UNK14C40 0x00014c40 + +#define VIVS_NTE_DESCRIPTOR_INVALIDATE 0x00014c48 +#define VIVS_NTE_DESCRIPTOR_INVALIDATE_IDX__MASK 0x000001ff +#define VIVS_NTE_DESCRIPTOR_INVALIDATE_IDX__SHIFT 0 +#define VIVS_NTE_DESCRIPTOR_INVALIDATE_IDX(x) (((x) << VIVS_NTE_DESCRIPTOR_INVALIDATE_IDX__SHIFT) & VIVS_NTE_DESCRIPTOR_INVALIDATE_IDX__MASK) +#define VIVS_NTE_DESCRIPTOR_INVALIDATE_UNK29 0x20000000 + +#define VIVS_NTE_DESCRIPTOR(i0) (0x00000000 + 0x4*(i0)) +#define VIVS_NTE_DESCRIPTOR__ESIZE 0x00000004 +#define VIVS_NTE_DESCRIPTOR__LEN 0x00000080 + +#define VIVS_NTE_DESCRIPTOR_MIRROR_UNK15C00(i0) (0x00015800 + 0x4*(i0)) + +#define VIVS_NTE_DESCRIPTOR_MIRROR_UNK15E00(i0) (0x00015a00 + 0x4*(i0)) + +#define VIVS_NTE_DESCRIPTOR_UNK15C00(i0) (0x00015c00 + 0x4*(i0)) + +#define VIVS_NTE_DESCRIPTOR_UNK15E00(i0) (0x00015e00 + 0x4*(i0)) + +#define VIVS_NTE_DESCRIPTOR_MIRROR_UNK16C00(i0) (0x00016000 + 0x4*(i0)) + +#define VIVS_NTE_DESCRIPTOR_MIRROR_UNK16E00(i0) (0x00016200 + 0x4*(i0)) + +#define VIVS_NTE_DESCRIPTOR_MIRROR_UNK17000(i0) (0x00016400 + 0x4*(i0)) + +#define VIVS_NTE_DESCRIPTOR_MIRROR_UNK17200(i0) (0x00016600 + 0x4*(i0)) + +#define VIVS_NTE_DESCRIPTOR_MIRROR_UNK17400(i0) (0x00016800 + 0x4*(i0)) + +#define VIVS_NTE_DESCRIPTOR_UNK16C00(i0) (0x00016c00 + 0x4*(i0)) + +#define VIVS_NTE_DESCRIPTOR_UNK16E00(i0) (0x00016e00 + 0x4*(i0)) + +#define VIVS_NTE_DESCRIPTOR_UNK17000(i0) (0x00017000 + 0x4*(i0)) + +#define VIVS_NTE_DESCRIPTOR_UNK17200(i0) (0x00017200 + 0x4*(i0)) + +#define VIVS_NTE_DESCRIPTOR_UNK17400(i0) (0x00017400 + 0x4*(i0)) + +#define VIVS_SH 0x00000000 + +#define VIVS_SH_UNK20000(i0) (0x00020000 + 0x4*(i0)) +#define VIVS_SH_UNK20000__ESIZE 0x00000004 +#define VIVS_SH_UNK20000__LEN 0x00002000 + +#define VIVS_SH_INST_MEM(i0) (0x0000c000 + 0x4*(i0)) +#define VIVS_SH_INST_MEM__ESIZE 0x00000004 +#define VIVS_SH_INST_MEM__LEN 0x00001000 + +#define VIVS_SH_INST_MEM_MIRROR(i0) (0x00008000 + 0x4*(i0)) +#define VIVS_SH_INST_MEM_MIRROR__ESIZE 0x00000004 +#define VIVS_SH_INST_MEM_MIRROR__LEN 0x00001000 + +#define VIVS_SH_UNIFORMS(i0) (0x00030000 + 0x4*(i0)) +#define VIVS_SH_UNIFORMS__ESIZE 0x00000004 +#define VIVS_SH_UNIFORMS__LEN 0x00000800 + +#define VIVS_SH_HALTI5_UNIFORMS_MIRROR(i0) (0x00034000 + 0x4*(i0)) +#define VIVS_SH_HALTI5_UNIFORMS_MIRROR__ESIZE 0x00000004 +#define VIVS_SH_HALTI5_UNIFORMS_MIRROR__LEN 0x00000800 + +#define VIVS_SH_HALTI5_UNIFORMS(i0) (0x00036000 + 0x4*(i0)) +#define VIVS_SH_HALTI5_UNIFORMS__ESIZE 0x00000004 +#define VIVS_SH_HALTI5_UNIFORMS__LEN 0x00000800 + + +#endif /* STATE_3D_XML */ |