Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 5563 → Rev 5564

/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/Automake.inc
0,0 → 1,11
if HAVE_GALLIUM_FREEDRENO
 
TARGET_DRIVERS += msm kgsl
TARGET_CPPFLAGS += -DGALLIUM_FREEDRENO
TARGET_LIB_DEPS += \
$(top_builddir)/src/gallium/winsys/freedreno/drm/libfreedrenodrm.la \
$(top_builddir)/src/gallium/drivers/freedreno/libfreedreno.la \
$(FREEDRENO_LIBS) \
$(LIBDRM_LIBS)
 
endif
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/Makefile.am
0,0 → 1,35
AUTOMAKE_OPTIONS = subdir-objects
 
include Makefile.sources
include $(top_srcdir)/src/gallium/Automake.inc
 
AM_CFLAGS = \
-Wno-packed-bitfield-compat \
-I$(top_srcdir)/src/gallium/drivers/freedreno/ir3 \
-I$(top_builddir)/src/glsl/nir \
$(GALLIUM_DRIVER_CFLAGS) \
$(FREEDRENO_CFLAGS)
 
noinst_LTLIBRARIES = libfreedreno.la
 
libfreedreno_la_SOURCES = \
$(C_SOURCES) \
$(a2xx_SOURCES) \
$(a3xx_SOURCES) \
$(a4xx_SOURCES) \
$(ir3_SOURCES)
 
noinst_PROGRAMS = ir3_compiler
 
ir3_compiler_SOURCES = \
ir3/ir3_cmdline.c
 
ir3_compiler_LDADD = \
libfreedreno.la \
../../auxiliary/libgallium.la \
$(top_builddir)/src/glsl/libnir.la \
$(top_builddir)/src/libglsl_util.la \
-lstdc++ \
$(top_builddir)/src/util/libmesautil.la \
$(GALLIUM_COMMON_LIB_DEPS) \
$(FREEDRENO_LIBS)
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/Makefile.in
0,0 → 1,1237
# Makefile.in generated by automake 1.15 from Makefile.am.
# @configure_input@
 
# Copyright (C) 1994-2014 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@
 
 
VPATH = @srcdir@
am__is_gnu_make = { \
if test -z '$(MAKELEVEL)'; then \
false; \
elif test -n '$(MAKE_HOST)'; then \
true; \
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
true; \
else \
false; \
fi; \
}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
*) echo "am__make_running_with_option: internal error: invalid" \
"target option '$${target_option-}' specified" >&2; \
exit 1;; \
esac; \
has_opt=no; \
sane_makeflags=$$MAKEFLAGS; \
if $(am__is_gnu_make); then \
sane_makeflags=$$MFLAGS; \
else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
bs=\\; \
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
fi; \
skip_next=no; \
strip_trailopt () \
{ \
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
}; \
for flg in $$sane_makeflags; do \
test $$skip_next = yes && { skip_next=no; continue; }; \
case $$flg in \
*=*|--*) continue;; \
-*I) strip_trailopt 'I'; skip_next=yes;; \
-*I?*) strip_trailopt 'I';; \
-*O) strip_trailopt 'O'; skip_next=yes;; \
-*O?*) strip_trailopt 'O';; \
-*l) strip_trailopt 'l'; skip_next=yes;; \
-*l?*) strip_trailopt 'l';; \
-[dEDm]) skip_next=yes;; \
-[JT]) skip_next=yes;; \
esac; \
case $$flg in \
*$$target_option*) has_opt=yes; break;; \
esac; \
done; \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
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@
@HAVE_DRISW_TRUE@am__append_1 = \
@HAVE_DRISW_TRUE@ $(top_builddir)/src/gallium/winsys/sw/dri/libswdri.la
 
@NEED_WINSYS_XLIB_TRUE@am__append_2 = \
@NEED_WINSYS_XLIB_TRUE@ $(top_builddir)/src/gallium/winsys/sw/xlib/libws_xlib.la \
@NEED_WINSYS_XLIB_TRUE@ -lX11 -lXext -lXfixes \
@NEED_WINSYS_XLIB_TRUE@ $(LIBDRM_LIBS)
 
noinst_PROGRAMS = ir3_compiler$(EXEEXT)
subdir = src/gallium/drivers/freedreno
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(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)
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
LTLIBRARIES = $(noinst_LTLIBRARIES)
libfreedreno_la_LIBADD =
am__objects_1 = freedreno_context.lo freedreno_draw.lo \
freedreno_fence.lo freedreno_gmem.lo freedreno_program.lo \
freedreno_query.lo freedreno_query_hw.lo freedreno_query_sw.lo \
freedreno_resource.lo freedreno_screen.lo freedreno_state.lo \
freedreno_surface.lo freedreno_texture.lo freedreno_util.lo
am__dirstamp = $(am__leading_dot)dirstamp
am__objects_2 = a2xx/disasm-a2xx.lo a2xx/fd2_blend.lo \
a2xx/fd2_compiler.lo a2xx/fd2_context.lo a2xx/fd2_draw.lo \
a2xx/fd2_emit.lo a2xx/fd2_gmem.lo a2xx/fd2_program.lo \
a2xx/fd2_rasterizer.lo a2xx/fd2_screen.lo a2xx/fd2_texture.lo \
a2xx/fd2_util.lo a2xx/fd2_zsa.lo a2xx/ir-a2xx.lo
am__objects_3 = a3xx/fd3_blend.lo a3xx/fd3_context.lo a3xx/fd3_draw.lo \
a3xx/fd3_emit.lo a3xx/fd3_format.lo a3xx/fd3_gmem.lo \
a3xx/fd3_program.lo a3xx/fd3_query.lo a3xx/fd3_rasterizer.lo \
a3xx/fd3_screen.lo a3xx/fd3_texture.lo a3xx/fd3_zsa.lo
am__objects_4 = a4xx/fd4_blend.lo a4xx/fd4_context.lo a4xx/fd4_draw.lo \
a4xx/fd4_emit.lo a4xx/fd4_format.lo a4xx/fd4_gmem.lo \
a4xx/fd4_program.lo a4xx/fd4_query.lo a4xx/fd4_rasterizer.lo \
a4xx/fd4_screen.lo a4xx/fd4_texture.lo a4xx/fd4_zsa.lo
am__objects_5 = ir3/disasm-a3xx.lo ir3/ir3.lo ir3/ir3_compiler.lo \
ir3/ir3_compiler_nir.lo ir3/ir3_cp.lo ir3/ir3_depth.lo \
ir3/ir3_dump.lo ir3/ir3_flatten.lo ir3/ir3_group.lo \
ir3/ir3_legalize.lo ir3/ir3_nir_lower_if_else.lo ir3/ir3_ra.lo \
ir3/ir3_sched.lo ir3/ir3_shader.lo
am_libfreedreno_la_OBJECTS = $(am__objects_1) $(am__objects_2) \
$(am__objects_3) $(am__objects_4) $(am__objects_5)
libfreedreno_la_OBJECTS = $(am_libfreedreno_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_ir3_compiler_OBJECTS = ir3/ir3_cmdline.$(OBJEXT)
ir3_compiler_OBJECTS = $(am_ir3_compiler_OBJECTS)
am__DEPENDENCIES_1 =
am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1)
ir3_compiler_DEPENDENCIES = libfreedreno.la \
../../auxiliary/libgallium.la \
$(top_builddir)/src/glsl/libnir.la \
$(top_builddir)/src/libglsl_util.la \
$(top_builddir)/src/util/libmesautil.la $(am__DEPENDENCIES_2) \
$(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 = $(libfreedreno_la_SOURCES) $(ir3_compiler_SOURCES)
DIST_SOURCES = $(libfreedreno_la_SOURCES) $(ir3_compiler_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
# *not* preserved.
am__uniquify_input = $(AWK) '\
BEGIN { nonempty = 0; } \
{ items[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in items) print i; }; } \
'
# Make sure the list of sources is unique. This is necessary because,
# e.g., the same source file might be shared among _SOURCES variables
# for different programs/libraries.
am__define_uniq_tagged_files = \
list='$(am__tagged_files)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.sources \
$(top_srcdir)/bin/depcomp \
$(top_srcdir)/src/gallium/Automake.inc
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
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@
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@
DRI3PROTO_CFLAGS = @DRI3PROTO_CFLAGS@
DRI3PROTO_LIBS = @DRI3PROTO_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_CLIENT_APIS = @EGL_CLIENT_APIS@
EGL_LIB_DEPS = @EGL_LIB_DEPS@
EGL_NATIVE_PLATFORM = @EGL_NATIVE_PLATFORM@
EGREP = @EGREP@
ELF_LIB = @ELF_LIB@
EXEEXT = @EXEEXT@
EXPAT_CFLAGS = @EXPAT_CFLAGS@
EXPAT_LIBS = @EXPAT_LIBS@
FGREP = @FGREP@
FREEDRENO_CFLAGS = @FREEDRENO_CFLAGS@
FREEDRENO_LIBS = @FREEDRENO_LIBS@
GALLIUM_PIPE_LOADER_CLIENT_DEFINES = @GALLIUM_PIPE_LOADER_CLIENT_DEFINES@
GALLIUM_PIPE_LOADER_CLIENT_LIBS = @GALLIUM_PIPE_LOADER_CLIENT_LIBS@
GALLIUM_PIPE_LOADER_DEFINES = @GALLIUM_PIPE_LOADER_DEFINES@
GALLIUM_PIPE_LOADER_LIBS = @GALLIUM_PIPE_LOADER_LIBS@
GALLIUM_PIPE_LOADER_XCB_CFLAGS = @GALLIUM_PIPE_LOADER_XCB_CFLAGS@
GALLIUM_PIPE_LOADER_XCB_LIBS = @GALLIUM_PIPE_LOADER_XCB_LIBS@
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@
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@
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@
INTEL_CFLAGS = @INTEL_CFLAGS@
INTEL_LIBS = @INTEL_LIBS@
LD = @LD@
LDFLAGS = @LDFLAGS@
LD_NO_UNDEFINED = @LD_NO_UNDEFINED@
LEX = @LEX@
LEXLIB = @LEXLIB@
LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
LIBCLC_INCLUDEDIR = @LIBCLC_INCLUDEDIR@
LIBCLC_LIBEXECDIR = @LIBCLC_LIBEXECDIR@
LIBDRM_CFLAGS = @LIBDRM_CFLAGS@
LIBDRM_LIBS = @LIBDRM_LIBS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBSHA1_CFLAGS = @LIBSHA1_CFLAGS@
LIBSHA1_LIBS = @LIBSHA1_LIBS@
LIBTOOL = @LIBTOOL@
LIBUDEV_CFLAGS = @LIBUDEV_CFLAGS@
LIBUDEV_LIBS = @LIBUDEV_LIBS@
LIB_DIR = @LIB_DIR@
LIB_EXT = @LIB_EXT@
LIPO = @LIPO@
LLVM_BINDIR = @LLVM_BINDIR@
LLVM_CFLAGS = @LLVM_CFLAGS@
LLVM_CONFIG = @LLVM_CONFIG@
LLVM_CPPFLAGS = @LLVM_CPPFLAGS@
LLVM_CXXFLAGS = @LLVM_CXXFLAGS@
LLVM_INCLUDEDIR = @LLVM_INCLUDEDIR@
LLVM_LDFLAGS = @LLVM_LDFLAGS@
LLVM_LIBDIR = @LLVM_LIBDIR@
LLVM_LIBS = @LLVM_LIBS@
LLVM_VERSION = @LLVM_VERSION@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MESA_LLVM = @MESA_LLVM@
MKDIR_P = @MKDIR_P@
MSVC2008_COMPAT_CFLAGS = @MSVC2008_COMPAT_CFLAGS@
MSVC2008_COMPAT_CXXFLAGS = @MSVC2008_COMPAT_CXXFLAGS@
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@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OMX_CFLAGS = @OMX_CFLAGS@
OMX_LIBS = @OMX_LIBS@
OMX_LIB_INSTALL_DIR = @OMX_LIB_INSTALL_DIR@
OPENCL_LIBNAME = @OPENCL_LIBNAME@
OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
OPENSSL_LIBS = @OPENSSL_LIBS@
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@
PRESENTPROTO_CFLAGS = @PRESENTPROTO_CFLAGS@
PRESENTPROTO_LIBS = @PRESENTPROTO_LIBS@
PTHREAD_CC = @PTHREAD_CC@
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
PTHREAD_LIBS = @PTHREAD_LIBS@
PYTHON2 = @PYTHON2@
RADEON_CFLAGS = @RADEON_CFLAGS@
RADEON_LIBS = @RADEON_LIBS@
RANLIB = @RANLIB@
SED = @SED@
SELINUX_CFLAGS = @SELINUX_CFLAGS@
SELINUX_LIBS = @SELINUX_LIBS@
SET_MAKE = @SET_MAKE@
SHA1_CFLAGS = @SHA1_CFLAGS@
SHA1_LIBS = @SHA1_LIBS@
SHELL = @SHELL@
SSE41_CFLAGS = @SSE41_CFLAGS@
STRIP = @STRIP@
VA_CFLAGS = @VA_CFLAGS@
VA_LIBS = @VA_LIBS@
VA_LIB_INSTALL_DIR = @VA_LIB_INSTALL_DIR@
VA_MAJOR = @VA_MAJOR@
VA_MINOR = @VA_MINOR@
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@
VG_LIB_DEPS = @VG_LIB_DEPS@
VISIBILITY_CFLAGS = @VISIBILITY_CFLAGS@
VISIBILITY_CXXFLAGS = @VISIBILITY_CXXFLAGS@
VL_CFLAGS = @VL_CFLAGS@
VL_LIBS = @VL_LIBS@
WAYLAND_CFLAGS = @WAYLAND_CFLAGS@
WAYLAND_LIBS = @WAYLAND_LIBS@
WAYLAND_SCANNER = @WAYLAND_SCANNER@
WAYLAND_SCANNER_CFLAGS = @WAYLAND_SCANNER_CFLAGS@
WAYLAND_SCANNER_LIBS = @WAYLAND_SCANNER_LIBS@
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@
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@
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@
AUTOMAKE_OPTIONS = subdir-objects
C_SOURCES := \
adreno_common.xml.h \
adreno_pm4.xml.h \
disasm.h \
freedreno_context.c \
freedreno_context.h \
freedreno_draw.c \
freedreno_draw.h \
freedreno_fence.c \
freedreno_fence.h \
freedreno_gmem.c \
freedreno_gmem.h \
freedreno_program.c \
freedreno_program.h \
freedreno_query.c \
freedreno_query.h \
freedreno_query_hw.c \
freedreno_query_hw.h \
freedreno_query_sw.c \
freedreno_query_sw.h \
freedreno_resource.c \
freedreno_resource.h \
freedreno_screen.c \
freedreno_screen.h \
freedreno_state.c \
freedreno_state.h \
freedreno_surface.c \
freedreno_surface.h \
freedreno_texture.c \
freedreno_texture.h \
freedreno_util.c \
freedreno_util.h
 
a2xx_SOURCES := \
a2xx/a2xx.xml.h \
a2xx/disasm-a2xx.c \
a2xx/fd2_blend.c \
a2xx/fd2_blend.h \
a2xx/fd2_compiler.c \
a2xx/fd2_compiler.h \
a2xx/fd2_context.c \
a2xx/fd2_context.h \
a2xx/fd2_draw.c \
a2xx/fd2_draw.h \
a2xx/fd2_emit.c \
a2xx/fd2_emit.h \
a2xx/fd2_gmem.c \
a2xx/fd2_gmem.h \
a2xx/fd2_program.c \
a2xx/fd2_program.h \
a2xx/fd2_rasterizer.c \
a2xx/fd2_rasterizer.h \
a2xx/fd2_screen.c \
a2xx/fd2_screen.h \
a2xx/fd2_texture.c \
a2xx/fd2_texture.h \
a2xx/fd2_util.c \
a2xx/fd2_util.h \
a2xx/fd2_zsa.c \
a2xx/fd2_zsa.h \
a2xx/instr-a2xx.h \
a2xx/ir-a2xx.c \
a2xx/ir-a2xx.h
 
a3xx_SOURCES := \
a3xx/a3xx.xml.h \
a3xx/fd3_blend.c \
a3xx/fd3_blend.h \
a3xx/fd3_context.c \
a3xx/fd3_context.h \
a3xx/fd3_draw.c \
a3xx/fd3_draw.h \
a3xx/fd3_emit.c \
a3xx/fd3_emit.h \
a3xx/fd3_format.c \
a3xx/fd3_format.h \
a3xx/fd3_gmem.c \
a3xx/fd3_gmem.h \
a3xx/fd3_program.c \
a3xx/fd3_program.h \
a3xx/fd3_query.c \
a3xx/fd3_query.h \
a3xx/fd3_rasterizer.c \
a3xx/fd3_rasterizer.h \
a3xx/fd3_screen.c \
a3xx/fd3_screen.h \
a3xx/fd3_texture.c \
a3xx/fd3_texture.h \
a3xx/fd3_zsa.c \
a3xx/fd3_zsa.h
 
a4xx_SOURCES := \
a4xx/a4xx.xml.h \
a4xx/fd4_blend.c \
a4xx/fd4_blend.h \
a4xx/fd4_context.c \
a4xx/fd4_context.h \
a4xx/fd4_draw.c \
a4xx/fd4_draw.h \
a4xx/fd4_emit.c \
a4xx/fd4_emit.h \
a4xx/fd4_format.c \
a4xx/fd4_format.h \
a4xx/fd4_gmem.c \
a4xx/fd4_gmem.h \
a4xx/fd4_program.c \
a4xx/fd4_program.h \
a4xx/fd4_query.c \
a4xx/fd4_query.h \
a4xx/fd4_rasterizer.c \
a4xx/fd4_rasterizer.h \
a4xx/fd4_screen.c \
a4xx/fd4_screen.h \
a4xx/fd4_texture.c \
a4xx/fd4_texture.h \
a4xx/fd4_zsa.c \
a4xx/fd4_zsa.h
 
ir3_SOURCES := \
ir3/disasm-a3xx.c \
ir3/instr-a3xx.h \
ir3/ir3.c \
ir3/ir3_compiler.c \
ir3/ir3_compiler_nir.c \
ir3/ir3_compiler.h \
ir3/ir3_cp.c \
ir3/ir3_depth.c \
ir3/ir3_dump.c \
ir3/ir3_flatten.c \
ir3/ir3_group.c \
ir3/ir3.h \
ir3/ir3_legalize.c \
ir3/ir3_nir.h \
ir3/ir3_nir_lower_if_else.c \
ir3/ir3_ra.c \
ir3/ir3_sched.c \
ir3/ir3_shader.c \
ir3/ir3_shader.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 \
$(DEFINES) \
$(PTHREAD_CFLAGS) \
$(LIBDRM_CFLAGS) \
$(VISIBILITY_CFLAGS)
 
GALLIUM_COMMON_LIB_DEPS = \
-lm \
$(CLOCK_LIB) \
$(PTHREAD_LIBS) \
$(DLOPEN_LIBS)
 
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_1) $(am__append_2)
AM_CFLAGS = \
-Wno-packed-bitfield-compat \
-I$(top_srcdir)/src/gallium/drivers/freedreno/ir3 \
-I$(top_builddir)/src/glsl/nir \
$(GALLIUM_DRIVER_CFLAGS) \
$(FREEDRENO_CFLAGS)
 
noinst_LTLIBRARIES = libfreedreno.la
libfreedreno_la_SOURCES = \
$(C_SOURCES) \
$(a2xx_SOURCES) \
$(a3xx_SOURCES) \
$(a4xx_SOURCES) \
$(ir3_SOURCES)
 
ir3_compiler_SOURCES = \
ir3/ir3_cmdline.c
 
ir3_compiler_LDADD = \
libfreedreno.la \
../../auxiliary/libgallium.la \
$(top_builddir)/src/glsl/libnir.la \
$(top_builddir)/src/libglsl_util.la \
-lstdc++ \
$(top_builddir)/src/util/libmesautil.la \
$(GALLIUM_COMMON_LIB_DEPS) \
$(FREEDRENO_LIBS)
 
all: all-am
 
.SUFFIXES:
.SUFFIXES: .c .lo .o .obj
$(srcdir)/Makefile.in: $(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/freedreno/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --foreign src/gallium/drivers/freedreno/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 $(am__empty):
 
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
 
$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(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}; \
}
a2xx/$(am__dirstamp):
@$(MKDIR_P) a2xx
@: > a2xx/$(am__dirstamp)
a2xx/$(DEPDIR)/$(am__dirstamp):
@$(MKDIR_P) a2xx/$(DEPDIR)
@: > a2xx/$(DEPDIR)/$(am__dirstamp)
a2xx/disasm-a2xx.lo: a2xx/$(am__dirstamp) \
a2xx/$(DEPDIR)/$(am__dirstamp)
a2xx/fd2_blend.lo: a2xx/$(am__dirstamp) a2xx/$(DEPDIR)/$(am__dirstamp)
a2xx/fd2_compiler.lo: a2xx/$(am__dirstamp) \
a2xx/$(DEPDIR)/$(am__dirstamp)
a2xx/fd2_context.lo: a2xx/$(am__dirstamp) \
a2xx/$(DEPDIR)/$(am__dirstamp)
a2xx/fd2_draw.lo: a2xx/$(am__dirstamp) a2xx/$(DEPDIR)/$(am__dirstamp)
a2xx/fd2_emit.lo: a2xx/$(am__dirstamp) a2xx/$(DEPDIR)/$(am__dirstamp)
a2xx/fd2_gmem.lo: a2xx/$(am__dirstamp) a2xx/$(DEPDIR)/$(am__dirstamp)
a2xx/fd2_program.lo: a2xx/$(am__dirstamp) \
a2xx/$(DEPDIR)/$(am__dirstamp)
a2xx/fd2_rasterizer.lo: a2xx/$(am__dirstamp) \
a2xx/$(DEPDIR)/$(am__dirstamp)
a2xx/fd2_screen.lo: a2xx/$(am__dirstamp) \
a2xx/$(DEPDIR)/$(am__dirstamp)
a2xx/fd2_texture.lo: a2xx/$(am__dirstamp) \
a2xx/$(DEPDIR)/$(am__dirstamp)
a2xx/fd2_util.lo: a2xx/$(am__dirstamp) a2xx/$(DEPDIR)/$(am__dirstamp)
a2xx/fd2_zsa.lo: a2xx/$(am__dirstamp) a2xx/$(DEPDIR)/$(am__dirstamp)
a2xx/ir-a2xx.lo: a2xx/$(am__dirstamp) a2xx/$(DEPDIR)/$(am__dirstamp)
a3xx/$(am__dirstamp):
@$(MKDIR_P) a3xx
@: > a3xx/$(am__dirstamp)
a3xx/$(DEPDIR)/$(am__dirstamp):
@$(MKDIR_P) a3xx/$(DEPDIR)
@: > a3xx/$(DEPDIR)/$(am__dirstamp)
a3xx/fd3_blend.lo: a3xx/$(am__dirstamp) a3xx/$(DEPDIR)/$(am__dirstamp)
a3xx/fd3_context.lo: a3xx/$(am__dirstamp) \
a3xx/$(DEPDIR)/$(am__dirstamp)
a3xx/fd3_draw.lo: a3xx/$(am__dirstamp) a3xx/$(DEPDIR)/$(am__dirstamp)
a3xx/fd3_emit.lo: a3xx/$(am__dirstamp) a3xx/$(DEPDIR)/$(am__dirstamp)
a3xx/fd3_format.lo: a3xx/$(am__dirstamp) \
a3xx/$(DEPDIR)/$(am__dirstamp)
a3xx/fd3_gmem.lo: a3xx/$(am__dirstamp) a3xx/$(DEPDIR)/$(am__dirstamp)
a3xx/fd3_program.lo: a3xx/$(am__dirstamp) \
a3xx/$(DEPDIR)/$(am__dirstamp)
a3xx/fd3_query.lo: a3xx/$(am__dirstamp) a3xx/$(DEPDIR)/$(am__dirstamp)
a3xx/fd3_rasterizer.lo: a3xx/$(am__dirstamp) \
a3xx/$(DEPDIR)/$(am__dirstamp)
a3xx/fd3_screen.lo: a3xx/$(am__dirstamp) \
a3xx/$(DEPDIR)/$(am__dirstamp)
a3xx/fd3_texture.lo: a3xx/$(am__dirstamp) \
a3xx/$(DEPDIR)/$(am__dirstamp)
a3xx/fd3_zsa.lo: a3xx/$(am__dirstamp) a3xx/$(DEPDIR)/$(am__dirstamp)
a4xx/$(am__dirstamp):
@$(MKDIR_P) a4xx
@: > a4xx/$(am__dirstamp)
a4xx/$(DEPDIR)/$(am__dirstamp):
@$(MKDIR_P) a4xx/$(DEPDIR)
@: > a4xx/$(DEPDIR)/$(am__dirstamp)
a4xx/fd4_blend.lo: a4xx/$(am__dirstamp) a4xx/$(DEPDIR)/$(am__dirstamp)
a4xx/fd4_context.lo: a4xx/$(am__dirstamp) \
a4xx/$(DEPDIR)/$(am__dirstamp)
a4xx/fd4_draw.lo: a4xx/$(am__dirstamp) a4xx/$(DEPDIR)/$(am__dirstamp)
a4xx/fd4_emit.lo: a4xx/$(am__dirstamp) a4xx/$(DEPDIR)/$(am__dirstamp)
a4xx/fd4_format.lo: a4xx/$(am__dirstamp) \
a4xx/$(DEPDIR)/$(am__dirstamp)
a4xx/fd4_gmem.lo: a4xx/$(am__dirstamp) a4xx/$(DEPDIR)/$(am__dirstamp)
a4xx/fd4_program.lo: a4xx/$(am__dirstamp) \
a4xx/$(DEPDIR)/$(am__dirstamp)
a4xx/fd4_query.lo: a4xx/$(am__dirstamp) a4xx/$(DEPDIR)/$(am__dirstamp)
a4xx/fd4_rasterizer.lo: a4xx/$(am__dirstamp) \
a4xx/$(DEPDIR)/$(am__dirstamp)
a4xx/fd4_screen.lo: a4xx/$(am__dirstamp) \
a4xx/$(DEPDIR)/$(am__dirstamp)
a4xx/fd4_texture.lo: a4xx/$(am__dirstamp) \
a4xx/$(DEPDIR)/$(am__dirstamp)
a4xx/fd4_zsa.lo: a4xx/$(am__dirstamp) a4xx/$(DEPDIR)/$(am__dirstamp)
ir3/$(am__dirstamp):
@$(MKDIR_P) ir3
@: > ir3/$(am__dirstamp)
ir3/$(DEPDIR)/$(am__dirstamp):
@$(MKDIR_P) ir3/$(DEPDIR)
@: > ir3/$(DEPDIR)/$(am__dirstamp)
ir3/disasm-a3xx.lo: ir3/$(am__dirstamp) ir3/$(DEPDIR)/$(am__dirstamp)
ir3/ir3.lo: ir3/$(am__dirstamp) ir3/$(DEPDIR)/$(am__dirstamp)
ir3/ir3_compiler.lo: ir3/$(am__dirstamp) ir3/$(DEPDIR)/$(am__dirstamp)
ir3/ir3_compiler_nir.lo: ir3/$(am__dirstamp) \
ir3/$(DEPDIR)/$(am__dirstamp)
ir3/ir3_cp.lo: ir3/$(am__dirstamp) ir3/$(DEPDIR)/$(am__dirstamp)
ir3/ir3_depth.lo: ir3/$(am__dirstamp) ir3/$(DEPDIR)/$(am__dirstamp)
ir3/ir3_dump.lo: ir3/$(am__dirstamp) ir3/$(DEPDIR)/$(am__dirstamp)
ir3/ir3_flatten.lo: ir3/$(am__dirstamp) ir3/$(DEPDIR)/$(am__dirstamp)
ir3/ir3_group.lo: ir3/$(am__dirstamp) ir3/$(DEPDIR)/$(am__dirstamp)
ir3/ir3_legalize.lo: ir3/$(am__dirstamp) ir3/$(DEPDIR)/$(am__dirstamp)
ir3/ir3_nir_lower_if_else.lo: ir3/$(am__dirstamp) \
ir3/$(DEPDIR)/$(am__dirstamp)
ir3/ir3_ra.lo: ir3/$(am__dirstamp) ir3/$(DEPDIR)/$(am__dirstamp)
ir3/ir3_sched.lo: ir3/$(am__dirstamp) ir3/$(DEPDIR)/$(am__dirstamp)
ir3/ir3_shader.lo: ir3/$(am__dirstamp) ir3/$(DEPDIR)/$(am__dirstamp)
 
libfreedreno.la: $(libfreedreno_la_OBJECTS) $(libfreedreno_la_DEPENDENCIES) $(EXTRA_libfreedreno_la_DEPENDENCIES)
$(AM_V_CCLD)$(LINK) $(libfreedreno_la_OBJECTS) $(libfreedreno_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
ir3/ir3_cmdline.$(OBJEXT): ir3/$(am__dirstamp) \
ir3/$(DEPDIR)/$(am__dirstamp)
 
ir3_compiler$(EXEEXT): $(ir3_compiler_OBJECTS) $(ir3_compiler_DEPENDENCIES) $(EXTRA_ir3_compiler_DEPENDENCIES)
@rm -f ir3_compiler$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(ir3_compiler_OBJECTS) $(ir3_compiler_LDADD) $(LIBS)
 
mostlyclean-compile:
-rm -f *.$(OBJEXT)
-rm -f a2xx/*.$(OBJEXT)
-rm -f a2xx/*.lo
-rm -f a3xx/*.$(OBJEXT)
-rm -f a3xx/*.lo
-rm -f a4xx/*.$(OBJEXT)
-rm -f a4xx/*.lo
-rm -f ir3/*.$(OBJEXT)
-rm -f ir3/*.lo
 
distclean-compile:
-rm -f *.tab.c
 
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/freedreno_context.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/freedreno_draw.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/freedreno_fence.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/freedreno_gmem.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/freedreno_program.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/freedreno_query.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/freedreno_query_hw.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/freedreno_query_sw.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/freedreno_resource.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/freedreno_screen.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/freedreno_state.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/freedreno_surface.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/freedreno_texture.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/freedreno_util.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@a2xx/$(DEPDIR)/disasm-a2xx.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@a2xx/$(DEPDIR)/fd2_blend.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@a2xx/$(DEPDIR)/fd2_compiler.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@a2xx/$(DEPDIR)/fd2_context.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@a2xx/$(DEPDIR)/fd2_draw.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@a2xx/$(DEPDIR)/fd2_emit.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@a2xx/$(DEPDIR)/fd2_gmem.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@a2xx/$(DEPDIR)/fd2_program.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@a2xx/$(DEPDIR)/fd2_rasterizer.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@a2xx/$(DEPDIR)/fd2_screen.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@a2xx/$(DEPDIR)/fd2_texture.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@a2xx/$(DEPDIR)/fd2_util.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@a2xx/$(DEPDIR)/fd2_zsa.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@a2xx/$(DEPDIR)/ir-a2xx.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@a3xx/$(DEPDIR)/fd3_blend.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@a3xx/$(DEPDIR)/fd3_context.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@a3xx/$(DEPDIR)/fd3_draw.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@a3xx/$(DEPDIR)/fd3_emit.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@a3xx/$(DEPDIR)/fd3_format.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@a3xx/$(DEPDIR)/fd3_gmem.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@a3xx/$(DEPDIR)/fd3_program.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@a3xx/$(DEPDIR)/fd3_query.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@a3xx/$(DEPDIR)/fd3_rasterizer.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@a3xx/$(DEPDIR)/fd3_screen.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@a3xx/$(DEPDIR)/fd3_texture.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@a3xx/$(DEPDIR)/fd3_zsa.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@a4xx/$(DEPDIR)/fd4_blend.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@a4xx/$(DEPDIR)/fd4_context.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@a4xx/$(DEPDIR)/fd4_draw.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@a4xx/$(DEPDIR)/fd4_emit.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@a4xx/$(DEPDIR)/fd4_format.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@a4xx/$(DEPDIR)/fd4_gmem.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@a4xx/$(DEPDIR)/fd4_program.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@a4xx/$(DEPDIR)/fd4_query.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@a4xx/$(DEPDIR)/fd4_rasterizer.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@a4xx/$(DEPDIR)/fd4_screen.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@a4xx/$(DEPDIR)/fd4_texture.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@a4xx/$(DEPDIR)/fd4_zsa.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ir3/$(DEPDIR)/disasm-a3xx.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ir3/$(DEPDIR)/ir3.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ir3/$(DEPDIR)/ir3_cmdline.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ir3/$(DEPDIR)/ir3_compiler.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ir3/$(DEPDIR)/ir3_compiler_nir.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ir3/$(DEPDIR)/ir3_cp.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ir3/$(DEPDIR)/ir3_depth.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ir3/$(DEPDIR)/ir3_dump.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ir3/$(DEPDIR)/ir3_flatten.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ir3/$(DEPDIR)/ir3_group.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ir3/$(DEPDIR)/ir3_legalize.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ir3/$(DEPDIR)/ir3_nir_lower_if_else.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ir3/$(DEPDIR)/ir3_ra.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ir3/$(DEPDIR)/ir3_sched.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ir3/$(DEPDIR)/ir3_shader.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
-rm -rf a2xx/.libs a2xx/_libs
-rm -rf a3xx/.libs a3xx/_libs
-rm -rf a4xx/.libs a4xx/_libs
-rm -rf ir3/.libs ir3/_libs
 
ID: $(am__tagged_files)
$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-am
TAGS: tags
 
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
set x; \
here=`pwd`; \
$(am__define_uniq_tagged_files); \
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-am
 
CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
$(am__define_uniq_tagged_files); \
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: cscopelist-am
 
cscopelist-am: $(am__tagged_files)
list='$(am__tagged_files)'; \
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)
-rm -f a2xx/$(DEPDIR)/$(am__dirstamp)
-rm -f a2xx/$(am__dirstamp)
-rm -f a3xx/$(DEPDIR)/$(am__dirstamp)
-rm -f a3xx/$(am__dirstamp)
-rm -f a4xx/$(DEPDIR)/$(am__dirstamp)
-rm -f a4xx/$(am__dirstamp)
-rm -f ir3/$(DEPDIR)/$(am__dirstamp)
-rm -f ir3/$(am__dirstamp)
 
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) a2xx/$(DEPDIR) a3xx/$(DEPDIR) a4xx/$(DEPDIR) ir3/$(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) a2xx/$(DEPDIR) a3xx/$(DEPDIR) a4xx/$(DEPDIR) ir3/$(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 TAGS all all-am check check-am clean clean-generic \
clean-libtool clean-noinstLTLIBRARIES clean-noinstPROGRAMS \
cscopelist-am ctags ctags-am 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 tags-am uninstall uninstall-am
 
.PRECIOUS: Makefile
 
 
# 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:
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/Makefile.sources
0,0 → 1,138
C_SOURCES := \
adreno_common.xml.h \
adreno_pm4.xml.h \
disasm.h \
freedreno_context.c \
freedreno_context.h \
freedreno_draw.c \
freedreno_draw.h \
freedreno_fence.c \
freedreno_fence.h \
freedreno_gmem.c \
freedreno_gmem.h \
freedreno_program.c \
freedreno_program.h \
freedreno_query.c \
freedreno_query.h \
freedreno_query_hw.c \
freedreno_query_hw.h \
freedreno_query_sw.c \
freedreno_query_sw.h \
freedreno_resource.c \
freedreno_resource.h \
freedreno_screen.c \
freedreno_screen.h \
freedreno_state.c \
freedreno_state.h \
freedreno_surface.c \
freedreno_surface.h \
freedreno_texture.c \
freedreno_texture.h \
freedreno_util.c \
freedreno_util.h
 
a2xx_SOURCES := \
a2xx/a2xx.xml.h \
a2xx/disasm-a2xx.c \
a2xx/fd2_blend.c \
a2xx/fd2_blend.h \
a2xx/fd2_compiler.c \
a2xx/fd2_compiler.h \
a2xx/fd2_context.c \
a2xx/fd2_context.h \
a2xx/fd2_draw.c \
a2xx/fd2_draw.h \
a2xx/fd2_emit.c \
a2xx/fd2_emit.h \
a2xx/fd2_gmem.c \
a2xx/fd2_gmem.h \
a2xx/fd2_program.c \
a2xx/fd2_program.h \
a2xx/fd2_rasterizer.c \
a2xx/fd2_rasterizer.h \
a2xx/fd2_screen.c \
a2xx/fd2_screen.h \
a2xx/fd2_texture.c \
a2xx/fd2_texture.h \
a2xx/fd2_util.c \
a2xx/fd2_util.h \
a2xx/fd2_zsa.c \
a2xx/fd2_zsa.h \
a2xx/instr-a2xx.h \
a2xx/ir-a2xx.c \
a2xx/ir-a2xx.h
 
a3xx_SOURCES := \
a3xx/a3xx.xml.h \
a3xx/fd3_blend.c \
a3xx/fd3_blend.h \
a3xx/fd3_context.c \
a3xx/fd3_context.h \
a3xx/fd3_draw.c \
a3xx/fd3_draw.h \
a3xx/fd3_emit.c \
a3xx/fd3_emit.h \
a3xx/fd3_format.c \
a3xx/fd3_format.h \
a3xx/fd3_gmem.c \
a3xx/fd3_gmem.h \
a3xx/fd3_program.c \
a3xx/fd3_program.h \
a3xx/fd3_query.c \
a3xx/fd3_query.h \
a3xx/fd3_rasterizer.c \
a3xx/fd3_rasterizer.h \
a3xx/fd3_screen.c \
a3xx/fd3_screen.h \
a3xx/fd3_texture.c \
a3xx/fd3_texture.h \
a3xx/fd3_zsa.c \
a3xx/fd3_zsa.h
 
a4xx_SOURCES := \
a4xx/a4xx.xml.h \
a4xx/fd4_blend.c \
a4xx/fd4_blend.h \
a4xx/fd4_context.c \
a4xx/fd4_context.h \
a4xx/fd4_draw.c \
a4xx/fd4_draw.h \
a4xx/fd4_emit.c \
a4xx/fd4_emit.h \
a4xx/fd4_format.c \
a4xx/fd4_format.h \
a4xx/fd4_gmem.c \
a4xx/fd4_gmem.h \
a4xx/fd4_program.c \
a4xx/fd4_program.h \
a4xx/fd4_query.c \
a4xx/fd4_query.h \
a4xx/fd4_rasterizer.c \
a4xx/fd4_rasterizer.h \
a4xx/fd4_screen.c \
a4xx/fd4_screen.h \
a4xx/fd4_texture.c \
a4xx/fd4_texture.h \
a4xx/fd4_zsa.c \
a4xx/fd4_zsa.h
 
ir3_SOURCES := \
ir3/disasm-a3xx.c \
ir3/instr-a3xx.h \
ir3/ir3.c \
ir3/ir3_compiler.c \
ir3/ir3_compiler_nir.c \
ir3/ir3_compiler.h \
ir3/ir3_cp.c \
ir3/ir3_depth.c \
ir3/ir3_dump.c \
ir3/ir3_flatten.c \
ir3/ir3_group.c \
ir3/ir3.h \
ir3/ir3_legalize.c \
ir3/ir3_nir.h \
ir3/ir3_nir_lower_if_else.c \
ir3/ir3_ra.c \
ir3/ir3_sched.c \
ir3/ir3_shader.c \
ir3/ir3_shader.h
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a2xx/a2xx.xml.h
0,0 → 1,1597
#ifndef A2XX_XML
#define A2XX_XML
 
/* Autogenerated file, DO NOT EDIT manually!
 
This file was generated by the rules-ng-ng headergen tool in this git repository:
http://github.com/freedreno/envytools/
git clone https://github.com/freedreno/envytools.git
 
The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml ( 364 bytes, from 2013-11-30 14:47:15)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32901 bytes, from 2014-06-02 15:21:30)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10551 bytes, from 2014-11-13 22:44:30)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 14895 bytes, from 2015-04-19 15:23:28)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 66709 bytes, from 2015-04-12 18:16:35)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 59314 bytes, from 2015-04-19 16:21:40)
 
Copyright (C) 2013-2014 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
 
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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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.
*/
 
 
enum a2xx_rb_dither_type {
DITHER_PIXEL = 0,
DITHER_SUBPIXEL = 1,
};
 
enum a2xx_colorformatx {
COLORX_4_4_4_4 = 0,
COLORX_1_5_5_5 = 1,
COLORX_5_6_5 = 2,
COLORX_8 = 3,
COLORX_8_8 = 4,
COLORX_8_8_8_8 = 5,
COLORX_S8_8_8_8 = 6,
COLORX_16_FLOAT = 7,
COLORX_16_16_FLOAT = 8,
COLORX_16_16_16_16_FLOAT = 9,
COLORX_32_FLOAT = 10,
COLORX_32_32_FLOAT = 11,
COLORX_32_32_32_32_FLOAT = 12,
COLORX_2_3_3 = 13,
COLORX_8_8_8 = 14,
};
 
enum a2xx_sq_surfaceformat {
FMT_1_REVERSE = 0,
FMT_1 = 1,
FMT_8 = 2,
FMT_1_5_5_5 = 3,
FMT_5_6_5 = 4,
FMT_6_5_5 = 5,
FMT_8_8_8_8 = 6,
FMT_2_10_10_10 = 7,
FMT_8_A = 8,
FMT_8_B = 9,
FMT_8_8 = 10,
FMT_Cr_Y1_Cb_Y0 = 11,
FMT_Y1_Cr_Y0_Cb = 12,
FMT_5_5_5_1 = 13,
FMT_8_8_8_8_A = 14,
FMT_4_4_4_4 = 15,
FMT_10_11_11 = 16,
FMT_11_11_10 = 17,
FMT_DXT1 = 18,
FMT_DXT2_3 = 19,
FMT_DXT4_5 = 20,
FMT_24_8 = 22,
FMT_24_8_FLOAT = 23,
FMT_16 = 24,
FMT_16_16 = 25,
FMT_16_16_16_16 = 26,
FMT_16_EXPAND = 27,
FMT_16_16_EXPAND = 28,
FMT_16_16_16_16_EXPAND = 29,
FMT_16_FLOAT = 30,
FMT_16_16_FLOAT = 31,
FMT_16_16_16_16_FLOAT = 32,
FMT_32 = 33,
FMT_32_32 = 34,
FMT_32_32_32_32 = 35,
FMT_32_FLOAT = 36,
FMT_32_32_FLOAT = 37,
FMT_32_32_32_32_FLOAT = 38,
FMT_32_AS_8 = 39,
FMT_32_AS_8_8 = 40,
FMT_16_MPEG = 41,
FMT_16_16_MPEG = 42,
FMT_8_INTERLACED = 43,
FMT_32_AS_8_INTERLACED = 44,
FMT_32_AS_8_8_INTERLACED = 45,
FMT_16_INTERLACED = 46,
FMT_16_MPEG_INTERLACED = 47,
FMT_16_16_MPEG_INTERLACED = 48,
FMT_DXN = 49,
FMT_8_8_8_8_AS_16_16_16_16 = 50,
FMT_DXT1_AS_16_16_16_16 = 51,
FMT_DXT2_3_AS_16_16_16_16 = 52,
FMT_DXT4_5_AS_16_16_16_16 = 53,
FMT_2_10_10_10_AS_16_16_16_16 = 54,
FMT_10_11_11_AS_16_16_16_16 = 55,
FMT_11_11_10_AS_16_16_16_16 = 56,
FMT_32_32_32_FLOAT = 57,
FMT_DXT3A = 58,
FMT_DXT5A = 59,
FMT_CTX1 = 60,
FMT_DXT3A_AS_1_1_1_1 = 61,
};
 
enum a2xx_sq_ps_vtx_mode {
POSITION_1_VECTOR = 0,
POSITION_2_VECTORS_UNUSED = 1,
POSITION_2_VECTORS_SPRITE = 2,
POSITION_2_VECTORS_EDGE = 3,
POSITION_2_VECTORS_KILL = 4,
POSITION_2_VECTORS_SPRITE_KILL = 5,
POSITION_2_VECTORS_EDGE_KILL = 6,
MULTIPASS = 7,
};
 
enum a2xx_sq_sample_cntl {
CENTROIDS_ONLY = 0,
CENTERS_ONLY = 1,
CENTROIDS_AND_CENTERS = 2,
};
 
enum a2xx_dx_clip_space {
DXCLIP_OPENGL = 0,
DXCLIP_DIRECTX = 1,
};
 
enum a2xx_pa_su_sc_polymode {
POLY_DISABLED = 0,
POLY_DUALMODE = 1,
};
 
enum a2xx_rb_edram_mode {
EDRAM_NOP = 0,
COLOR_DEPTH = 4,
DEPTH_ONLY = 5,
EDRAM_COPY = 6,
};
 
enum a2xx_pa_sc_pattern_bit_order {
LITTLE = 0,
BIG = 1,
};
 
enum a2xx_pa_sc_auto_reset_cntl {
NEVER = 0,
EACH_PRIMITIVE = 1,
EACH_PACKET = 2,
};
 
enum a2xx_pa_pixcenter {
PIXCENTER_D3D = 0,
PIXCENTER_OGL = 1,
};
 
enum a2xx_pa_roundmode {
TRUNCATE = 0,
ROUND = 1,
ROUNDTOEVEN = 2,
ROUNDTOODD = 3,
};
 
enum a2xx_pa_quantmode {
ONE_SIXTEENTH = 0,
ONE_EIGTH = 1,
ONE_QUARTER = 2,
ONE_HALF = 3,
ONE = 4,
};
 
enum a2xx_rb_copy_sample_select {
SAMPLE_0 = 0,
SAMPLE_1 = 1,
SAMPLE_2 = 2,
SAMPLE_3 = 3,
SAMPLE_01 = 4,
SAMPLE_23 = 5,
SAMPLE_0123 = 6,
};
 
enum a2xx_rb_blend_opcode {
BLEND_DST_PLUS_SRC = 0,
BLEND_SRC_MINUS_DST = 1,
BLEND_MIN_DST_SRC = 2,
BLEND_MAX_DST_SRC = 3,
BLEND_DST_MINUS_SRC = 4,
BLEND_DST_PLUS_SRC_BIAS = 5,
};
 
enum adreno_mmu_clnt_beh {
BEH_NEVR = 0,
BEH_TRAN_RNG = 1,
BEH_TRAN_FLT = 2,
};
 
enum sq_tex_clamp {
SQ_TEX_WRAP = 0,
SQ_TEX_MIRROR = 1,
SQ_TEX_CLAMP_LAST_TEXEL = 2,
SQ_TEX_MIRROR_ONCE_LAST_TEXEL = 3,
SQ_TEX_CLAMP_HALF_BORDER = 4,
SQ_TEX_MIRROR_ONCE_HALF_BORDER = 5,
SQ_TEX_CLAMP_BORDER = 6,
SQ_TEX_MIRROR_ONCE_BORDER = 7,
};
 
enum sq_tex_swiz {
SQ_TEX_X = 0,
SQ_TEX_Y = 1,
SQ_TEX_Z = 2,
SQ_TEX_W = 3,
SQ_TEX_ZERO = 4,
SQ_TEX_ONE = 5,
};
 
enum sq_tex_filter {
SQ_TEX_FILTER_POINT = 0,
SQ_TEX_FILTER_BILINEAR = 1,
SQ_TEX_FILTER_BICUBIC = 2,
};
 
#define REG_A2XX_RBBM_PATCH_RELEASE 0x00000001
 
#define REG_A2XX_RBBM_CNTL 0x0000003b
 
#define REG_A2XX_RBBM_SOFT_RESET 0x0000003c
 
#define REG_A2XX_CP_PFP_UCODE_ADDR 0x000000c0
 
#define REG_A2XX_CP_PFP_UCODE_DATA 0x000000c1
 
#define REG_A2XX_MH_MMU_CONFIG 0x00000040
#define A2XX_MH_MMU_CONFIG_MMU_ENABLE 0x00000001
#define A2XX_MH_MMU_CONFIG_SPLIT_MODE_ENABLE 0x00000002
#define A2XX_MH_MMU_CONFIG_RB_W_CLNT_BEHAVIOR__MASK 0x00000030
#define A2XX_MH_MMU_CONFIG_RB_W_CLNT_BEHAVIOR__SHIFT 4
static inline uint32_t A2XX_MH_MMU_CONFIG_RB_W_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
{
return ((val) << A2XX_MH_MMU_CONFIG_RB_W_CLNT_BEHAVIOR__SHIFT) & A2XX_MH_MMU_CONFIG_RB_W_CLNT_BEHAVIOR__MASK;
}
#define A2XX_MH_MMU_CONFIG_CP_W_CLNT_BEHAVIOR__MASK 0x000000c0
#define A2XX_MH_MMU_CONFIG_CP_W_CLNT_BEHAVIOR__SHIFT 6
static inline uint32_t A2XX_MH_MMU_CONFIG_CP_W_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
{
return ((val) << A2XX_MH_MMU_CONFIG_CP_W_CLNT_BEHAVIOR__SHIFT) & A2XX_MH_MMU_CONFIG_CP_W_CLNT_BEHAVIOR__MASK;
}
#define A2XX_MH_MMU_CONFIG_CP_R0_CLNT_BEHAVIOR__MASK 0x00000300
#define A2XX_MH_MMU_CONFIG_CP_R0_CLNT_BEHAVIOR__SHIFT 8
static inline uint32_t A2XX_MH_MMU_CONFIG_CP_R0_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
{
return ((val) << A2XX_MH_MMU_CONFIG_CP_R0_CLNT_BEHAVIOR__SHIFT) & A2XX_MH_MMU_CONFIG_CP_R0_CLNT_BEHAVIOR__MASK;
}
#define A2XX_MH_MMU_CONFIG_CP_R1_CLNT_BEHAVIOR__MASK 0x00000c00
#define A2XX_MH_MMU_CONFIG_CP_R1_CLNT_BEHAVIOR__SHIFT 10
static inline uint32_t A2XX_MH_MMU_CONFIG_CP_R1_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
{
return ((val) << A2XX_MH_MMU_CONFIG_CP_R1_CLNT_BEHAVIOR__SHIFT) & A2XX_MH_MMU_CONFIG_CP_R1_CLNT_BEHAVIOR__MASK;
}
#define A2XX_MH_MMU_CONFIG_CP_R2_CLNT_BEHAVIOR__MASK 0x00003000
#define A2XX_MH_MMU_CONFIG_CP_R2_CLNT_BEHAVIOR__SHIFT 12
static inline uint32_t A2XX_MH_MMU_CONFIG_CP_R2_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
{
return ((val) << A2XX_MH_MMU_CONFIG_CP_R2_CLNT_BEHAVIOR__SHIFT) & A2XX_MH_MMU_CONFIG_CP_R2_CLNT_BEHAVIOR__MASK;
}
#define A2XX_MH_MMU_CONFIG_CP_R3_CLNT_BEHAVIOR__MASK 0x0000c000
#define A2XX_MH_MMU_CONFIG_CP_R3_CLNT_BEHAVIOR__SHIFT 14
static inline uint32_t A2XX_MH_MMU_CONFIG_CP_R3_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
{
return ((val) << A2XX_MH_MMU_CONFIG_CP_R3_CLNT_BEHAVIOR__SHIFT) & A2XX_MH_MMU_CONFIG_CP_R3_CLNT_BEHAVIOR__MASK;
}
#define A2XX_MH_MMU_CONFIG_CP_R4_CLNT_BEHAVIOR__MASK 0x00030000
#define A2XX_MH_MMU_CONFIG_CP_R4_CLNT_BEHAVIOR__SHIFT 16
static inline uint32_t A2XX_MH_MMU_CONFIG_CP_R4_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
{
return ((val) << A2XX_MH_MMU_CONFIG_CP_R4_CLNT_BEHAVIOR__SHIFT) & A2XX_MH_MMU_CONFIG_CP_R4_CLNT_BEHAVIOR__MASK;
}
#define A2XX_MH_MMU_CONFIG_VGT_R0_CLNT_BEHAVIOR__MASK 0x000c0000
#define A2XX_MH_MMU_CONFIG_VGT_R0_CLNT_BEHAVIOR__SHIFT 18
static inline uint32_t A2XX_MH_MMU_CONFIG_VGT_R0_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
{
return ((val) << A2XX_MH_MMU_CONFIG_VGT_R0_CLNT_BEHAVIOR__SHIFT) & A2XX_MH_MMU_CONFIG_VGT_R0_CLNT_BEHAVIOR__MASK;
}
#define A2XX_MH_MMU_CONFIG_VGT_R1_CLNT_BEHAVIOR__MASK 0x00300000
#define A2XX_MH_MMU_CONFIG_VGT_R1_CLNT_BEHAVIOR__SHIFT 20
static inline uint32_t A2XX_MH_MMU_CONFIG_VGT_R1_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
{
return ((val) << A2XX_MH_MMU_CONFIG_VGT_R1_CLNT_BEHAVIOR__SHIFT) & A2XX_MH_MMU_CONFIG_VGT_R1_CLNT_BEHAVIOR__MASK;
}
#define A2XX_MH_MMU_CONFIG_TC_R_CLNT_BEHAVIOR__MASK 0x00c00000
#define A2XX_MH_MMU_CONFIG_TC_R_CLNT_BEHAVIOR__SHIFT 22
static inline uint32_t A2XX_MH_MMU_CONFIG_TC_R_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
{
return ((val) << A2XX_MH_MMU_CONFIG_TC_R_CLNT_BEHAVIOR__SHIFT) & A2XX_MH_MMU_CONFIG_TC_R_CLNT_BEHAVIOR__MASK;
}
#define A2XX_MH_MMU_CONFIG_PA_W_CLNT_BEHAVIOR__MASK 0x03000000
#define A2XX_MH_MMU_CONFIG_PA_W_CLNT_BEHAVIOR__SHIFT 24
static inline uint32_t A2XX_MH_MMU_CONFIG_PA_W_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
{
return ((val) << A2XX_MH_MMU_CONFIG_PA_W_CLNT_BEHAVIOR__SHIFT) & A2XX_MH_MMU_CONFIG_PA_W_CLNT_BEHAVIOR__MASK;
}
 
#define REG_A2XX_MH_MMU_VA_RANGE 0x00000041
 
#define REG_A2XX_MH_MMU_PT_BASE 0x00000042
 
#define REG_A2XX_MH_MMU_PAGE_FAULT 0x00000043
 
#define REG_A2XX_MH_MMU_TRAN_ERROR 0x00000044
 
#define REG_A2XX_MH_MMU_INVALIDATE 0x00000045
 
#define REG_A2XX_MH_MMU_MPU_BASE 0x00000046
 
#define REG_A2XX_MH_MMU_MPU_END 0x00000047
 
#define REG_A2XX_NQWAIT_UNTIL 0x00000394
 
#define REG_A2XX_RBBM_PERFCOUNTER1_SELECT 0x00000395
 
#define REG_A2XX_RBBM_PERFCOUNTER1_LO 0x00000397
 
#define REG_A2XX_RBBM_PERFCOUNTER1_HI 0x00000398
 
#define REG_A2XX_RBBM_DEBUG 0x0000039b
 
#define REG_A2XX_RBBM_PM_OVERRIDE1 0x0000039c
 
#define REG_A2XX_RBBM_PM_OVERRIDE2 0x0000039d
 
#define REG_A2XX_RBBM_DEBUG_OUT 0x000003a0
 
#define REG_A2XX_RBBM_DEBUG_CNTL 0x000003a1
 
#define REG_A2XX_RBBM_READ_ERROR 0x000003b3
 
#define REG_A2XX_RBBM_INT_CNTL 0x000003b4
 
#define REG_A2XX_RBBM_INT_STATUS 0x000003b5
 
#define REG_A2XX_RBBM_INT_ACK 0x000003b6
 
#define REG_A2XX_MASTER_INT_SIGNAL 0x000003b7
 
#define REG_A2XX_RBBM_PERIPHID1 0x000003f9
 
#define REG_A2XX_RBBM_PERIPHID2 0x000003fa
 
#define REG_A2XX_CP_PERFMON_CNTL 0x00000444
 
#define REG_A2XX_CP_PERFCOUNTER_SELECT 0x00000445
 
#define REG_A2XX_CP_PERFCOUNTER_LO 0x00000446
 
#define REG_A2XX_CP_PERFCOUNTER_HI 0x00000447
 
#define REG_A2XX_RBBM_STATUS 0x000005d0
#define A2XX_RBBM_STATUS_CMDFIFO_AVAIL__MASK 0x0000001f
#define A2XX_RBBM_STATUS_CMDFIFO_AVAIL__SHIFT 0
static inline uint32_t A2XX_RBBM_STATUS_CMDFIFO_AVAIL(uint32_t val)
{
return ((val) << A2XX_RBBM_STATUS_CMDFIFO_AVAIL__SHIFT) & A2XX_RBBM_STATUS_CMDFIFO_AVAIL__MASK;
}
#define A2XX_RBBM_STATUS_TC_BUSY 0x00000020
#define A2XX_RBBM_STATUS_HIRQ_PENDING 0x00000100
#define A2XX_RBBM_STATUS_CPRQ_PENDING 0x00000200
#define A2XX_RBBM_STATUS_CFRQ_PENDING 0x00000400
#define A2XX_RBBM_STATUS_PFRQ_PENDING 0x00000800
#define A2XX_RBBM_STATUS_VGT_BUSY_NO_DMA 0x00001000
#define A2XX_RBBM_STATUS_RBBM_WU_BUSY 0x00004000
#define A2XX_RBBM_STATUS_CP_NRT_BUSY 0x00010000
#define A2XX_RBBM_STATUS_MH_BUSY 0x00040000
#define A2XX_RBBM_STATUS_MH_COHERENCY_BUSY 0x00080000
#define A2XX_RBBM_STATUS_SX_BUSY 0x00200000
#define A2XX_RBBM_STATUS_TPC_BUSY 0x00400000
#define A2XX_RBBM_STATUS_SC_CNTX_BUSY 0x01000000
#define A2XX_RBBM_STATUS_PA_BUSY 0x02000000
#define A2XX_RBBM_STATUS_VGT_BUSY 0x04000000
#define A2XX_RBBM_STATUS_SQ_CNTX17_BUSY 0x08000000
#define A2XX_RBBM_STATUS_SQ_CNTX0_BUSY 0x10000000
#define A2XX_RBBM_STATUS_RB_CNTX_BUSY 0x40000000
#define A2XX_RBBM_STATUS_GUI_ACTIVE 0x80000000
 
#define REG_A2XX_MH_ARBITER_CONFIG 0x00000a40
#define A2XX_MH_ARBITER_CONFIG_SAME_PAGE_LIMIT__MASK 0x0000003f
#define A2XX_MH_ARBITER_CONFIG_SAME_PAGE_LIMIT__SHIFT 0
static inline uint32_t A2XX_MH_ARBITER_CONFIG_SAME_PAGE_LIMIT(uint32_t val)
{
return ((val) << A2XX_MH_ARBITER_CONFIG_SAME_PAGE_LIMIT__SHIFT) & A2XX_MH_ARBITER_CONFIG_SAME_PAGE_LIMIT__MASK;
}
#define A2XX_MH_ARBITER_CONFIG_SAME_PAGE_GRANULARITY 0x00000040
#define A2XX_MH_ARBITER_CONFIG_L1_ARB_ENABLE 0x00000080
#define A2XX_MH_ARBITER_CONFIG_L1_ARB_HOLD_ENABLE 0x00000100
#define A2XX_MH_ARBITER_CONFIG_L2_ARB_CONTROL 0x00000200
#define A2XX_MH_ARBITER_CONFIG_PAGE_SIZE__MASK 0x00001c00
#define A2XX_MH_ARBITER_CONFIG_PAGE_SIZE__SHIFT 10
static inline uint32_t A2XX_MH_ARBITER_CONFIG_PAGE_SIZE(uint32_t val)
{
return ((val) << A2XX_MH_ARBITER_CONFIG_PAGE_SIZE__SHIFT) & A2XX_MH_ARBITER_CONFIG_PAGE_SIZE__MASK;
}
#define A2XX_MH_ARBITER_CONFIG_TC_REORDER_ENABLE 0x00002000
#define A2XX_MH_ARBITER_CONFIG_TC_ARB_HOLD_ENABLE 0x00004000
#define A2XX_MH_ARBITER_CONFIG_IN_FLIGHT_LIMIT_ENABLE 0x00008000
#define A2XX_MH_ARBITER_CONFIG_IN_FLIGHT_LIMIT__MASK 0x003f0000
#define A2XX_MH_ARBITER_CONFIG_IN_FLIGHT_LIMIT__SHIFT 16
static inline uint32_t A2XX_MH_ARBITER_CONFIG_IN_FLIGHT_LIMIT(uint32_t val)
{
return ((val) << A2XX_MH_ARBITER_CONFIG_IN_FLIGHT_LIMIT__SHIFT) & A2XX_MH_ARBITER_CONFIG_IN_FLIGHT_LIMIT__MASK;
}
#define A2XX_MH_ARBITER_CONFIG_CP_CLNT_ENABLE 0x00400000
#define A2XX_MH_ARBITER_CONFIG_VGT_CLNT_ENABLE 0x00800000
#define A2XX_MH_ARBITER_CONFIG_TC_CLNT_ENABLE 0x01000000
#define A2XX_MH_ARBITER_CONFIG_RB_CLNT_ENABLE 0x02000000
#define A2XX_MH_ARBITER_CONFIG_PA_CLNT_ENABLE 0x04000000
 
#define REG_A2XX_A220_VSC_BIN_SIZE 0x00000c01
#define A2XX_A220_VSC_BIN_SIZE_WIDTH__MASK 0x0000001f
#define A2XX_A220_VSC_BIN_SIZE_WIDTH__SHIFT 0
static inline uint32_t A2XX_A220_VSC_BIN_SIZE_WIDTH(uint32_t val)
{
return ((val >> 5) << A2XX_A220_VSC_BIN_SIZE_WIDTH__SHIFT) & A2XX_A220_VSC_BIN_SIZE_WIDTH__MASK;
}
#define A2XX_A220_VSC_BIN_SIZE_HEIGHT__MASK 0x000003e0
#define A2XX_A220_VSC_BIN_SIZE_HEIGHT__SHIFT 5
static inline uint32_t A2XX_A220_VSC_BIN_SIZE_HEIGHT(uint32_t val)
{
return ((val >> 5) << A2XX_A220_VSC_BIN_SIZE_HEIGHT__SHIFT) & A2XX_A220_VSC_BIN_SIZE_HEIGHT__MASK;
}
 
static inline uint32_t REG_A2XX_VSC_PIPE(uint32_t i0) { return 0x00000c06 + 0x3*i0; }
 
static inline uint32_t REG_A2XX_VSC_PIPE_CONFIG(uint32_t i0) { return 0x00000c06 + 0x3*i0; }
 
static inline uint32_t REG_A2XX_VSC_PIPE_DATA_ADDRESS(uint32_t i0) { return 0x00000c07 + 0x3*i0; }
 
static inline uint32_t REG_A2XX_VSC_PIPE_DATA_LENGTH(uint32_t i0) { return 0x00000c08 + 0x3*i0; }
 
#define REG_A2XX_PC_DEBUG_CNTL 0x00000c38
 
#define REG_A2XX_PC_DEBUG_DATA 0x00000c39
 
#define REG_A2XX_PA_SC_VIZ_QUERY_STATUS 0x00000c44
 
#define REG_A2XX_GRAS_DEBUG_CNTL 0x00000c80
 
#define REG_A2XX_PA_SU_DEBUG_CNTL 0x00000c80
 
#define REG_A2XX_GRAS_DEBUG_DATA 0x00000c81
 
#define REG_A2XX_PA_SU_DEBUG_DATA 0x00000c81
 
#define REG_A2XX_PA_SU_FACE_DATA 0x00000c86
 
#define REG_A2XX_SQ_GPR_MANAGEMENT 0x00000d00
 
#define REG_A2XX_SQ_FLOW_CONTROL 0x00000d01
 
#define REG_A2XX_SQ_INST_STORE_MANAGMENT 0x00000d02
 
#define REG_A2XX_SQ_DEBUG_MISC 0x00000d05
 
#define REG_A2XX_SQ_INT_CNTL 0x00000d34
 
#define REG_A2XX_SQ_INT_STATUS 0x00000d35
 
#define REG_A2XX_SQ_INT_ACK 0x00000d36
 
#define REG_A2XX_SQ_DEBUG_INPUT_FSM 0x00000dae
 
#define REG_A2XX_SQ_DEBUG_CONST_MGR_FSM 0x00000daf
 
#define REG_A2XX_SQ_DEBUG_TP_FSM 0x00000db0
 
#define REG_A2XX_SQ_DEBUG_FSM_ALU_0 0x00000db1
 
#define REG_A2XX_SQ_DEBUG_FSM_ALU_1 0x00000db2
 
#define REG_A2XX_SQ_DEBUG_EXP_ALLOC 0x00000db3
 
#define REG_A2XX_SQ_DEBUG_PTR_BUFF 0x00000db4
 
#define REG_A2XX_SQ_DEBUG_GPR_VTX 0x00000db5
 
#define REG_A2XX_SQ_DEBUG_GPR_PIX 0x00000db6
 
#define REG_A2XX_SQ_DEBUG_TB_STATUS_SEL 0x00000db7
 
#define REG_A2XX_SQ_DEBUG_VTX_TB_0 0x00000db8
 
#define REG_A2XX_SQ_DEBUG_VTX_TB_1 0x00000db9
 
#define REG_A2XX_SQ_DEBUG_VTX_TB_STATUS_REG 0x00000dba
 
#define REG_A2XX_SQ_DEBUG_VTX_TB_STATE_MEM 0x00000dbb
 
#define REG_A2XX_SQ_DEBUG_PIX_TB_0 0x00000dbc
 
#define REG_A2XX_SQ_DEBUG_PIX_TB_STATUS_REG_0 0x00000dbd
 
#define REG_A2XX_SQ_DEBUG_PIX_TB_STATUS_REG_1 0x00000dbe
 
#define REG_A2XX_SQ_DEBUG_PIX_TB_STATUS_REG_2 0x00000dbf
 
#define REG_A2XX_SQ_DEBUG_PIX_TB_STATUS_REG_3 0x00000dc0
 
#define REG_A2XX_SQ_DEBUG_PIX_TB_STATE_MEM 0x00000dc1
 
#define REG_A2XX_TC_CNTL_STATUS 0x00000e00
#define A2XX_TC_CNTL_STATUS_L2_INVALIDATE 0x00000001
 
#define REG_A2XX_TP0_CHICKEN 0x00000e1e
 
#define REG_A2XX_RB_BC_CONTROL 0x00000f01
#define A2XX_RB_BC_CONTROL_ACCUM_LINEAR_MODE_ENABLE 0x00000001
#define A2XX_RB_BC_CONTROL_ACCUM_TIMEOUT_SELECT__MASK 0x00000006
#define A2XX_RB_BC_CONTROL_ACCUM_TIMEOUT_SELECT__SHIFT 1
static inline uint32_t A2XX_RB_BC_CONTROL_ACCUM_TIMEOUT_SELECT(uint32_t val)
{
return ((val) << A2XX_RB_BC_CONTROL_ACCUM_TIMEOUT_SELECT__SHIFT) & A2XX_RB_BC_CONTROL_ACCUM_TIMEOUT_SELECT__MASK;
}
#define A2XX_RB_BC_CONTROL_DISABLE_EDRAM_CAM 0x00000008
#define A2XX_RB_BC_CONTROL_DISABLE_EZ_FAST_CONTEXT_SWITCH 0x00000010
#define A2XX_RB_BC_CONTROL_DISABLE_EZ_NULL_ZCMD_DROP 0x00000020
#define A2XX_RB_BC_CONTROL_DISABLE_LZ_NULL_ZCMD_DROP 0x00000040
#define A2XX_RB_BC_CONTROL_ENABLE_AZ_THROTTLE 0x00000080
#define A2XX_RB_BC_CONTROL_AZ_THROTTLE_COUNT__MASK 0x00001f00
#define A2XX_RB_BC_CONTROL_AZ_THROTTLE_COUNT__SHIFT 8
static inline uint32_t A2XX_RB_BC_CONTROL_AZ_THROTTLE_COUNT(uint32_t val)
{
return ((val) << A2XX_RB_BC_CONTROL_AZ_THROTTLE_COUNT__SHIFT) & A2XX_RB_BC_CONTROL_AZ_THROTTLE_COUNT__MASK;
}
#define A2XX_RB_BC_CONTROL_ENABLE_CRC_UPDATE 0x00004000
#define A2XX_RB_BC_CONTROL_CRC_MODE 0x00008000
#define A2XX_RB_BC_CONTROL_DISABLE_SAMPLE_COUNTERS 0x00010000
#define A2XX_RB_BC_CONTROL_DISABLE_ACCUM 0x00020000
#define A2XX_RB_BC_CONTROL_ACCUM_ALLOC_MASK__MASK 0x003c0000
#define A2XX_RB_BC_CONTROL_ACCUM_ALLOC_MASK__SHIFT 18
static inline uint32_t A2XX_RB_BC_CONTROL_ACCUM_ALLOC_MASK(uint32_t val)
{
return ((val) << A2XX_RB_BC_CONTROL_ACCUM_ALLOC_MASK__SHIFT) & A2XX_RB_BC_CONTROL_ACCUM_ALLOC_MASK__MASK;
}
#define A2XX_RB_BC_CONTROL_LINEAR_PERFORMANCE_ENABLE 0x00400000
#define A2XX_RB_BC_CONTROL_ACCUM_DATA_FIFO_LIMIT__MASK 0x07800000
#define A2XX_RB_BC_CONTROL_ACCUM_DATA_FIFO_LIMIT__SHIFT 23
static inline uint32_t A2XX_RB_BC_CONTROL_ACCUM_DATA_FIFO_LIMIT(uint32_t val)
{
return ((val) << A2XX_RB_BC_CONTROL_ACCUM_DATA_FIFO_LIMIT__SHIFT) & A2XX_RB_BC_CONTROL_ACCUM_DATA_FIFO_LIMIT__MASK;
}
#define A2XX_RB_BC_CONTROL_MEM_EXPORT_TIMEOUT_SELECT__MASK 0x18000000
#define A2XX_RB_BC_CONTROL_MEM_EXPORT_TIMEOUT_SELECT__SHIFT 27
static inline uint32_t A2XX_RB_BC_CONTROL_MEM_EXPORT_TIMEOUT_SELECT(uint32_t val)
{
return ((val) << A2XX_RB_BC_CONTROL_MEM_EXPORT_TIMEOUT_SELECT__SHIFT) & A2XX_RB_BC_CONTROL_MEM_EXPORT_TIMEOUT_SELECT__MASK;
}
#define A2XX_RB_BC_CONTROL_MEM_EXPORT_LINEAR_MODE_ENABLE 0x20000000
#define A2XX_RB_BC_CONTROL_CRC_SYSTEM 0x40000000
#define A2XX_RB_BC_CONTROL_RESERVED6 0x80000000
 
#define REG_A2XX_RB_EDRAM_INFO 0x00000f02
 
#define REG_A2XX_RB_DEBUG_CNTL 0x00000f26
 
#define REG_A2XX_RB_DEBUG_DATA 0x00000f27
 
#define REG_A2XX_RB_SURFACE_INFO 0x00002000
 
#define REG_A2XX_RB_COLOR_INFO 0x00002001
#define A2XX_RB_COLOR_INFO_FORMAT__MASK 0x0000000f
#define A2XX_RB_COLOR_INFO_FORMAT__SHIFT 0
static inline uint32_t A2XX_RB_COLOR_INFO_FORMAT(enum a2xx_colorformatx val)
{
return ((val) << A2XX_RB_COLOR_INFO_FORMAT__SHIFT) & A2XX_RB_COLOR_INFO_FORMAT__MASK;
}
#define A2XX_RB_COLOR_INFO_ROUND_MODE__MASK 0x00000030
#define A2XX_RB_COLOR_INFO_ROUND_MODE__SHIFT 4
static inline uint32_t A2XX_RB_COLOR_INFO_ROUND_MODE(uint32_t val)
{
return ((val) << A2XX_RB_COLOR_INFO_ROUND_MODE__SHIFT) & A2XX_RB_COLOR_INFO_ROUND_MODE__MASK;
}
#define A2XX_RB_COLOR_INFO_LINEAR 0x00000040
#define A2XX_RB_COLOR_INFO_ENDIAN__MASK 0x00000180
#define A2XX_RB_COLOR_INFO_ENDIAN__SHIFT 7
static inline uint32_t A2XX_RB_COLOR_INFO_ENDIAN(uint32_t val)
{
return ((val) << A2XX_RB_COLOR_INFO_ENDIAN__SHIFT) & A2XX_RB_COLOR_INFO_ENDIAN__MASK;
}
#define A2XX_RB_COLOR_INFO_SWAP__MASK 0x00000600
#define A2XX_RB_COLOR_INFO_SWAP__SHIFT 9
static inline uint32_t A2XX_RB_COLOR_INFO_SWAP(uint32_t val)
{
return ((val) << A2XX_RB_COLOR_INFO_SWAP__SHIFT) & A2XX_RB_COLOR_INFO_SWAP__MASK;
}
#define A2XX_RB_COLOR_INFO_BASE__MASK 0xfffff000
#define A2XX_RB_COLOR_INFO_BASE__SHIFT 12
static inline uint32_t A2XX_RB_COLOR_INFO_BASE(uint32_t val)
{
return ((val >> 10) << A2XX_RB_COLOR_INFO_BASE__SHIFT) & A2XX_RB_COLOR_INFO_BASE__MASK;
}
 
#define REG_A2XX_RB_DEPTH_INFO 0x00002002
#define A2XX_RB_DEPTH_INFO_DEPTH_FORMAT__MASK 0x00000001
#define A2XX_RB_DEPTH_INFO_DEPTH_FORMAT__SHIFT 0
static inline uint32_t A2XX_RB_DEPTH_INFO_DEPTH_FORMAT(enum adreno_rb_depth_format val)
{
return ((val) << A2XX_RB_DEPTH_INFO_DEPTH_FORMAT__SHIFT) & A2XX_RB_DEPTH_INFO_DEPTH_FORMAT__MASK;
}
#define A2XX_RB_DEPTH_INFO_DEPTH_BASE__MASK 0xfffff000
#define A2XX_RB_DEPTH_INFO_DEPTH_BASE__SHIFT 12
static inline uint32_t A2XX_RB_DEPTH_INFO_DEPTH_BASE(uint32_t val)
{
return ((val >> 10) << A2XX_RB_DEPTH_INFO_DEPTH_BASE__SHIFT) & A2XX_RB_DEPTH_INFO_DEPTH_BASE__MASK;
}
 
#define REG_A2XX_A225_RB_COLOR_INFO3 0x00002005
 
#define REG_A2XX_COHER_DEST_BASE_0 0x00002006
 
#define REG_A2XX_PA_SC_SCREEN_SCISSOR_TL 0x0000200e
#define A2XX_PA_SC_SCREEN_SCISSOR_TL_WINDOW_OFFSET_DISABLE 0x80000000
#define A2XX_PA_SC_SCREEN_SCISSOR_TL_X__MASK 0x00007fff
#define A2XX_PA_SC_SCREEN_SCISSOR_TL_X__SHIFT 0
static inline uint32_t A2XX_PA_SC_SCREEN_SCISSOR_TL_X(uint32_t val)
{
return ((val) << A2XX_PA_SC_SCREEN_SCISSOR_TL_X__SHIFT) & A2XX_PA_SC_SCREEN_SCISSOR_TL_X__MASK;
}
#define A2XX_PA_SC_SCREEN_SCISSOR_TL_Y__MASK 0x7fff0000
#define A2XX_PA_SC_SCREEN_SCISSOR_TL_Y__SHIFT 16
static inline uint32_t A2XX_PA_SC_SCREEN_SCISSOR_TL_Y(uint32_t val)
{
return ((val) << A2XX_PA_SC_SCREEN_SCISSOR_TL_Y__SHIFT) & A2XX_PA_SC_SCREEN_SCISSOR_TL_Y__MASK;
}
 
#define REG_A2XX_PA_SC_SCREEN_SCISSOR_BR 0x0000200f
#define A2XX_PA_SC_SCREEN_SCISSOR_BR_WINDOW_OFFSET_DISABLE 0x80000000
#define A2XX_PA_SC_SCREEN_SCISSOR_BR_X__MASK 0x00007fff
#define A2XX_PA_SC_SCREEN_SCISSOR_BR_X__SHIFT 0
static inline uint32_t A2XX_PA_SC_SCREEN_SCISSOR_BR_X(uint32_t val)
{
return ((val) << A2XX_PA_SC_SCREEN_SCISSOR_BR_X__SHIFT) & A2XX_PA_SC_SCREEN_SCISSOR_BR_X__MASK;
}
#define A2XX_PA_SC_SCREEN_SCISSOR_BR_Y__MASK 0x7fff0000
#define A2XX_PA_SC_SCREEN_SCISSOR_BR_Y__SHIFT 16
static inline uint32_t A2XX_PA_SC_SCREEN_SCISSOR_BR_Y(uint32_t val)
{
return ((val) << A2XX_PA_SC_SCREEN_SCISSOR_BR_Y__SHIFT) & A2XX_PA_SC_SCREEN_SCISSOR_BR_Y__MASK;
}
 
#define REG_A2XX_PA_SC_WINDOW_OFFSET 0x00002080
#define A2XX_PA_SC_WINDOW_OFFSET_X__MASK 0x00007fff
#define A2XX_PA_SC_WINDOW_OFFSET_X__SHIFT 0
static inline uint32_t A2XX_PA_SC_WINDOW_OFFSET_X(int32_t val)
{
return ((val) << A2XX_PA_SC_WINDOW_OFFSET_X__SHIFT) & A2XX_PA_SC_WINDOW_OFFSET_X__MASK;
}
#define A2XX_PA_SC_WINDOW_OFFSET_Y__MASK 0x7fff0000
#define A2XX_PA_SC_WINDOW_OFFSET_Y__SHIFT 16
static inline uint32_t A2XX_PA_SC_WINDOW_OFFSET_Y(int32_t val)
{
return ((val) << A2XX_PA_SC_WINDOW_OFFSET_Y__SHIFT) & A2XX_PA_SC_WINDOW_OFFSET_Y__MASK;
}
#define A2XX_PA_SC_WINDOW_OFFSET_DISABLE 0x80000000
 
#define REG_A2XX_PA_SC_WINDOW_SCISSOR_TL 0x00002081
#define A2XX_PA_SC_WINDOW_SCISSOR_TL_WINDOW_OFFSET_DISABLE 0x80000000
#define A2XX_PA_SC_WINDOW_SCISSOR_TL_X__MASK 0x00007fff
#define A2XX_PA_SC_WINDOW_SCISSOR_TL_X__SHIFT 0
static inline uint32_t A2XX_PA_SC_WINDOW_SCISSOR_TL_X(uint32_t val)
{
return ((val) << A2XX_PA_SC_WINDOW_SCISSOR_TL_X__SHIFT) & A2XX_PA_SC_WINDOW_SCISSOR_TL_X__MASK;
}
#define A2XX_PA_SC_WINDOW_SCISSOR_TL_Y__MASK 0x7fff0000
#define A2XX_PA_SC_WINDOW_SCISSOR_TL_Y__SHIFT 16
static inline uint32_t A2XX_PA_SC_WINDOW_SCISSOR_TL_Y(uint32_t val)
{
return ((val) << A2XX_PA_SC_WINDOW_SCISSOR_TL_Y__SHIFT) & A2XX_PA_SC_WINDOW_SCISSOR_TL_Y__MASK;
}
 
#define REG_A2XX_PA_SC_WINDOW_SCISSOR_BR 0x00002082
#define A2XX_PA_SC_WINDOW_SCISSOR_BR_WINDOW_OFFSET_DISABLE 0x80000000
#define A2XX_PA_SC_WINDOW_SCISSOR_BR_X__MASK 0x00007fff
#define A2XX_PA_SC_WINDOW_SCISSOR_BR_X__SHIFT 0
static inline uint32_t A2XX_PA_SC_WINDOW_SCISSOR_BR_X(uint32_t val)
{
return ((val) << A2XX_PA_SC_WINDOW_SCISSOR_BR_X__SHIFT) & A2XX_PA_SC_WINDOW_SCISSOR_BR_X__MASK;
}
#define A2XX_PA_SC_WINDOW_SCISSOR_BR_Y__MASK 0x7fff0000
#define A2XX_PA_SC_WINDOW_SCISSOR_BR_Y__SHIFT 16
static inline uint32_t A2XX_PA_SC_WINDOW_SCISSOR_BR_Y(uint32_t val)
{
return ((val) << A2XX_PA_SC_WINDOW_SCISSOR_BR_Y__SHIFT) & A2XX_PA_SC_WINDOW_SCISSOR_BR_Y__MASK;
}
 
#define REG_A2XX_UNKNOWN_2010 0x00002010
 
#define REG_A2XX_VGT_MAX_VTX_INDX 0x00002100
 
#define REG_A2XX_VGT_MIN_VTX_INDX 0x00002101
 
#define REG_A2XX_VGT_INDX_OFFSET 0x00002102
 
#define REG_A2XX_A225_PC_MULTI_PRIM_IB_RESET_INDX 0x00002103
 
#define REG_A2XX_RB_COLOR_MASK 0x00002104
#define A2XX_RB_COLOR_MASK_WRITE_RED 0x00000001
#define A2XX_RB_COLOR_MASK_WRITE_GREEN 0x00000002
#define A2XX_RB_COLOR_MASK_WRITE_BLUE 0x00000004
#define A2XX_RB_COLOR_MASK_WRITE_ALPHA 0x00000008
 
#define REG_A2XX_RB_BLEND_RED 0x00002105
 
#define REG_A2XX_RB_BLEND_GREEN 0x00002106
 
#define REG_A2XX_RB_BLEND_BLUE 0x00002107
 
#define REG_A2XX_RB_BLEND_ALPHA 0x00002108
 
#define REG_A2XX_RB_FOG_COLOR 0x00002109
 
#define REG_A2XX_RB_STENCILREFMASK_BF 0x0000210c
#define A2XX_RB_STENCILREFMASK_BF_STENCILREF__MASK 0x000000ff
#define A2XX_RB_STENCILREFMASK_BF_STENCILREF__SHIFT 0
static inline uint32_t A2XX_RB_STENCILREFMASK_BF_STENCILREF(uint32_t val)
{
return ((val) << A2XX_RB_STENCILREFMASK_BF_STENCILREF__SHIFT) & A2XX_RB_STENCILREFMASK_BF_STENCILREF__MASK;
}
#define A2XX_RB_STENCILREFMASK_BF_STENCILMASK__MASK 0x0000ff00
#define A2XX_RB_STENCILREFMASK_BF_STENCILMASK__SHIFT 8
static inline uint32_t A2XX_RB_STENCILREFMASK_BF_STENCILMASK(uint32_t val)
{
return ((val) << A2XX_RB_STENCILREFMASK_BF_STENCILMASK__SHIFT) & A2XX_RB_STENCILREFMASK_BF_STENCILMASK__MASK;
}
#define A2XX_RB_STENCILREFMASK_BF_STENCILWRITEMASK__MASK 0x00ff0000
#define A2XX_RB_STENCILREFMASK_BF_STENCILWRITEMASK__SHIFT 16
static inline uint32_t A2XX_RB_STENCILREFMASK_BF_STENCILWRITEMASK(uint32_t val)
{
return ((val) << A2XX_RB_STENCILREFMASK_BF_STENCILWRITEMASK__SHIFT) & A2XX_RB_STENCILREFMASK_BF_STENCILWRITEMASK__MASK;
}
 
#define REG_A2XX_RB_STENCILREFMASK 0x0000210d
#define A2XX_RB_STENCILREFMASK_STENCILREF__MASK 0x000000ff
#define A2XX_RB_STENCILREFMASK_STENCILREF__SHIFT 0
static inline uint32_t A2XX_RB_STENCILREFMASK_STENCILREF(uint32_t val)
{
return ((val) << A2XX_RB_STENCILREFMASK_STENCILREF__SHIFT) & A2XX_RB_STENCILREFMASK_STENCILREF__MASK;
}
#define A2XX_RB_STENCILREFMASK_STENCILMASK__MASK 0x0000ff00
#define A2XX_RB_STENCILREFMASK_STENCILMASK__SHIFT 8
static inline uint32_t A2XX_RB_STENCILREFMASK_STENCILMASK(uint32_t val)
{
return ((val) << A2XX_RB_STENCILREFMASK_STENCILMASK__SHIFT) & A2XX_RB_STENCILREFMASK_STENCILMASK__MASK;
}
#define A2XX_RB_STENCILREFMASK_STENCILWRITEMASK__MASK 0x00ff0000
#define A2XX_RB_STENCILREFMASK_STENCILWRITEMASK__SHIFT 16
static inline uint32_t A2XX_RB_STENCILREFMASK_STENCILWRITEMASK(uint32_t val)
{
return ((val) << A2XX_RB_STENCILREFMASK_STENCILWRITEMASK__SHIFT) & A2XX_RB_STENCILREFMASK_STENCILWRITEMASK__MASK;
}
 
#define REG_A2XX_RB_ALPHA_REF 0x0000210e
 
#define REG_A2XX_PA_CL_VPORT_XSCALE 0x0000210f
#define A2XX_PA_CL_VPORT_XSCALE__MASK 0xffffffff
#define A2XX_PA_CL_VPORT_XSCALE__SHIFT 0
static inline uint32_t A2XX_PA_CL_VPORT_XSCALE(float val)
{
return ((fui(val)) << A2XX_PA_CL_VPORT_XSCALE__SHIFT) & A2XX_PA_CL_VPORT_XSCALE__MASK;
}
 
#define REG_A2XX_PA_CL_VPORT_XOFFSET 0x00002110
#define A2XX_PA_CL_VPORT_XOFFSET__MASK 0xffffffff
#define A2XX_PA_CL_VPORT_XOFFSET__SHIFT 0
static inline uint32_t A2XX_PA_CL_VPORT_XOFFSET(float val)
{
return ((fui(val)) << A2XX_PA_CL_VPORT_XOFFSET__SHIFT) & A2XX_PA_CL_VPORT_XOFFSET__MASK;
}
 
#define REG_A2XX_PA_CL_VPORT_YSCALE 0x00002111
#define A2XX_PA_CL_VPORT_YSCALE__MASK 0xffffffff
#define A2XX_PA_CL_VPORT_YSCALE__SHIFT 0
static inline uint32_t A2XX_PA_CL_VPORT_YSCALE(float val)
{
return ((fui(val)) << A2XX_PA_CL_VPORT_YSCALE__SHIFT) & A2XX_PA_CL_VPORT_YSCALE__MASK;
}
 
#define REG_A2XX_PA_CL_VPORT_YOFFSET 0x00002112
#define A2XX_PA_CL_VPORT_YOFFSET__MASK 0xffffffff
#define A2XX_PA_CL_VPORT_YOFFSET__SHIFT 0
static inline uint32_t A2XX_PA_CL_VPORT_YOFFSET(float val)
{
return ((fui(val)) << A2XX_PA_CL_VPORT_YOFFSET__SHIFT) & A2XX_PA_CL_VPORT_YOFFSET__MASK;
}
 
#define REG_A2XX_PA_CL_VPORT_ZSCALE 0x00002113
#define A2XX_PA_CL_VPORT_ZSCALE__MASK 0xffffffff
#define A2XX_PA_CL_VPORT_ZSCALE__SHIFT 0
static inline uint32_t A2XX_PA_CL_VPORT_ZSCALE(float val)
{
return ((fui(val)) << A2XX_PA_CL_VPORT_ZSCALE__SHIFT) & A2XX_PA_CL_VPORT_ZSCALE__MASK;
}
 
#define REG_A2XX_PA_CL_VPORT_ZOFFSET 0x00002114
#define A2XX_PA_CL_VPORT_ZOFFSET__MASK 0xffffffff
#define A2XX_PA_CL_VPORT_ZOFFSET__SHIFT 0
static inline uint32_t A2XX_PA_CL_VPORT_ZOFFSET(float val)
{
return ((fui(val)) << A2XX_PA_CL_VPORT_ZOFFSET__SHIFT) & A2XX_PA_CL_VPORT_ZOFFSET__MASK;
}
 
#define REG_A2XX_SQ_PROGRAM_CNTL 0x00002180
#define A2XX_SQ_PROGRAM_CNTL_VS_REGS__MASK 0x000000ff
#define A2XX_SQ_PROGRAM_CNTL_VS_REGS__SHIFT 0
static inline uint32_t A2XX_SQ_PROGRAM_CNTL_VS_REGS(uint32_t val)
{
return ((val) << A2XX_SQ_PROGRAM_CNTL_VS_REGS__SHIFT) & A2XX_SQ_PROGRAM_CNTL_VS_REGS__MASK;
}
#define A2XX_SQ_PROGRAM_CNTL_PS_REGS__MASK 0x0000ff00
#define A2XX_SQ_PROGRAM_CNTL_PS_REGS__SHIFT 8
static inline uint32_t A2XX_SQ_PROGRAM_CNTL_PS_REGS(uint32_t val)
{
return ((val) << A2XX_SQ_PROGRAM_CNTL_PS_REGS__SHIFT) & A2XX_SQ_PROGRAM_CNTL_PS_REGS__MASK;
}
#define A2XX_SQ_PROGRAM_CNTL_VS_RESOURCE 0x00010000
#define A2XX_SQ_PROGRAM_CNTL_PS_RESOURCE 0x00020000
#define A2XX_SQ_PROGRAM_CNTL_PARAM_GEN 0x00040000
#define A2XX_SQ_PROGRAM_CNTL_GEN_INDEX_PIX 0x00080000
#define A2XX_SQ_PROGRAM_CNTL_VS_EXPORT_COUNT__MASK 0x00f00000
#define A2XX_SQ_PROGRAM_CNTL_VS_EXPORT_COUNT__SHIFT 20
static inline uint32_t A2XX_SQ_PROGRAM_CNTL_VS_EXPORT_COUNT(uint32_t val)
{
return ((val) << A2XX_SQ_PROGRAM_CNTL_VS_EXPORT_COUNT__SHIFT) & A2XX_SQ_PROGRAM_CNTL_VS_EXPORT_COUNT__MASK;
}
#define A2XX_SQ_PROGRAM_CNTL_VS_EXPORT_MODE__MASK 0x07000000
#define A2XX_SQ_PROGRAM_CNTL_VS_EXPORT_MODE__SHIFT 24
static inline uint32_t A2XX_SQ_PROGRAM_CNTL_VS_EXPORT_MODE(enum a2xx_sq_ps_vtx_mode val)
{
return ((val) << A2XX_SQ_PROGRAM_CNTL_VS_EXPORT_MODE__SHIFT) & A2XX_SQ_PROGRAM_CNTL_VS_EXPORT_MODE__MASK;
}
#define A2XX_SQ_PROGRAM_CNTL_PS_EXPORT_MODE__MASK 0x78000000
#define A2XX_SQ_PROGRAM_CNTL_PS_EXPORT_MODE__SHIFT 27
static inline uint32_t A2XX_SQ_PROGRAM_CNTL_PS_EXPORT_MODE(uint32_t val)
{
return ((val) << A2XX_SQ_PROGRAM_CNTL_PS_EXPORT_MODE__SHIFT) & A2XX_SQ_PROGRAM_CNTL_PS_EXPORT_MODE__MASK;
}
#define A2XX_SQ_PROGRAM_CNTL_GEN_INDEX_VTX 0x80000000
 
#define REG_A2XX_SQ_CONTEXT_MISC 0x00002181
#define A2XX_SQ_CONTEXT_MISC_INST_PRED_OPTIMIZE 0x00000001
#define A2XX_SQ_CONTEXT_MISC_SC_OUTPUT_SCREEN_XY 0x00000002
#define A2XX_SQ_CONTEXT_MISC_SC_SAMPLE_CNTL__MASK 0x0000000c
#define A2XX_SQ_CONTEXT_MISC_SC_SAMPLE_CNTL__SHIFT 2
static inline uint32_t A2XX_SQ_CONTEXT_MISC_SC_SAMPLE_CNTL(enum a2xx_sq_sample_cntl val)
{
return ((val) << A2XX_SQ_CONTEXT_MISC_SC_SAMPLE_CNTL__SHIFT) & A2XX_SQ_CONTEXT_MISC_SC_SAMPLE_CNTL__MASK;
}
#define A2XX_SQ_CONTEXT_MISC_PARAM_GEN_POS__MASK 0x0000ff00
#define A2XX_SQ_CONTEXT_MISC_PARAM_GEN_POS__SHIFT 8
static inline uint32_t A2XX_SQ_CONTEXT_MISC_PARAM_GEN_POS(uint32_t val)
{
return ((val) << A2XX_SQ_CONTEXT_MISC_PARAM_GEN_POS__SHIFT) & A2XX_SQ_CONTEXT_MISC_PARAM_GEN_POS__MASK;
}
#define A2XX_SQ_CONTEXT_MISC_PERFCOUNTER_REF 0x00010000
#define A2XX_SQ_CONTEXT_MISC_YEILD_OPTIMIZE 0x00020000
#define A2XX_SQ_CONTEXT_MISC_TX_CACHE_SEL 0x00040000
 
#define REG_A2XX_SQ_INTERPOLATOR_CNTL 0x00002182
 
#define REG_A2XX_SQ_WRAPPING_0 0x00002183
 
#define REG_A2XX_SQ_WRAPPING_1 0x00002184
 
#define REG_A2XX_SQ_PS_PROGRAM 0x000021f6
 
#define REG_A2XX_SQ_VS_PROGRAM 0x000021f7
 
#define REG_A2XX_VGT_EVENT_INITIATOR 0x000021f9
 
#define REG_A2XX_VGT_DRAW_INITIATOR 0x000021fc
#define A2XX_VGT_DRAW_INITIATOR_PRIM_TYPE__MASK 0x0000003f
#define A2XX_VGT_DRAW_INITIATOR_PRIM_TYPE__SHIFT 0
static inline uint32_t A2XX_VGT_DRAW_INITIATOR_PRIM_TYPE(enum pc_di_primtype val)
{
return ((val) << A2XX_VGT_DRAW_INITIATOR_PRIM_TYPE__SHIFT) & A2XX_VGT_DRAW_INITIATOR_PRIM_TYPE__MASK;
}
#define A2XX_VGT_DRAW_INITIATOR_SOURCE_SELECT__MASK 0x000000c0
#define A2XX_VGT_DRAW_INITIATOR_SOURCE_SELECT__SHIFT 6
static inline uint32_t A2XX_VGT_DRAW_INITIATOR_SOURCE_SELECT(enum pc_di_src_sel val)
{
return ((val) << A2XX_VGT_DRAW_INITIATOR_SOURCE_SELECT__SHIFT) & A2XX_VGT_DRAW_INITIATOR_SOURCE_SELECT__MASK;
}
#define A2XX_VGT_DRAW_INITIATOR_VIS_CULL__MASK 0x00000600
#define A2XX_VGT_DRAW_INITIATOR_VIS_CULL__SHIFT 9
static inline uint32_t A2XX_VGT_DRAW_INITIATOR_VIS_CULL(enum pc_di_vis_cull_mode val)
{
return ((val) << A2XX_VGT_DRAW_INITIATOR_VIS_CULL__SHIFT) & A2XX_VGT_DRAW_INITIATOR_VIS_CULL__MASK;
}
#define A2XX_VGT_DRAW_INITIATOR_INDEX_SIZE__MASK 0x00000800
#define A2XX_VGT_DRAW_INITIATOR_INDEX_SIZE__SHIFT 11
static inline uint32_t A2XX_VGT_DRAW_INITIATOR_INDEX_SIZE(enum pc_di_index_size val)
{
return ((val) << A2XX_VGT_DRAW_INITIATOR_INDEX_SIZE__SHIFT) & A2XX_VGT_DRAW_INITIATOR_INDEX_SIZE__MASK;
}
#define A2XX_VGT_DRAW_INITIATOR_NOT_EOP 0x00001000
#define A2XX_VGT_DRAW_INITIATOR_SMALL_INDEX 0x00002000
#define A2XX_VGT_DRAW_INITIATOR_PRE_DRAW_INITIATOR_ENABLE 0x00004000
#define A2XX_VGT_DRAW_INITIATOR_NUM_INSTANCES__MASK 0xff000000
#define A2XX_VGT_DRAW_INITIATOR_NUM_INSTANCES__SHIFT 24
static inline uint32_t A2XX_VGT_DRAW_INITIATOR_NUM_INSTANCES(uint32_t val)
{
return ((val) << A2XX_VGT_DRAW_INITIATOR_NUM_INSTANCES__SHIFT) & A2XX_VGT_DRAW_INITIATOR_NUM_INSTANCES__MASK;
}
 
#define REG_A2XX_VGT_IMMED_DATA 0x000021fd
 
#define REG_A2XX_RB_DEPTHCONTROL 0x00002200
#define A2XX_RB_DEPTHCONTROL_STENCIL_ENABLE 0x00000001
#define A2XX_RB_DEPTHCONTROL_Z_ENABLE 0x00000002
#define A2XX_RB_DEPTHCONTROL_Z_WRITE_ENABLE 0x00000004
#define A2XX_RB_DEPTHCONTROL_EARLY_Z_ENABLE 0x00000008
#define A2XX_RB_DEPTHCONTROL_ZFUNC__MASK 0x00000070
#define A2XX_RB_DEPTHCONTROL_ZFUNC__SHIFT 4
static inline uint32_t A2XX_RB_DEPTHCONTROL_ZFUNC(enum adreno_compare_func val)
{
return ((val) << A2XX_RB_DEPTHCONTROL_ZFUNC__SHIFT) & A2XX_RB_DEPTHCONTROL_ZFUNC__MASK;
}
#define A2XX_RB_DEPTHCONTROL_BACKFACE_ENABLE 0x00000080
#define A2XX_RB_DEPTHCONTROL_STENCILFUNC__MASK 0x00000700
#define A2XX_RB_DEPTHCONTROL_STENCILFUNC__SHIFT 8
static inline uint32_t A2XX_RB_DEPTHCONTROL_STENCILFUNC(enum adreno_compare_func val)
{
return ((val) << A2XX_RB_DEPTHCONTROL_STENCILFUNC__SHIFT) & A2XX_RB_DEPTHCONTROL_STENCILFUNC__MASK;
}
#define A2XX_RB_DEPTHCONTROL_STENCILFAIL__MASK 0x00003800
#define A2XX_RB_DEPTHCONTROL_STENCILFAIL__SHIFT 11
static inline uint32_t A2XX_RB_DEPTHCONTROL_STENCILFAIL(enum adreno_stencil_op val)
{
return ((val) << A2XX_RB_DEPTHCONTROL_STENCILFAIL__SHIFT) & A2XX_RB_DEPTHCONTROL_STENCILFAIL__MASK;
}
#define A2XX_RB_DEPTHCONTROL_STENCILZPASS__MASK 0x0001c000
#define A2XX_RB_DEPTHCONTROL_STENCILZPASS__SHIFT 14
static inline uint32_t A2XX_RB_DEPTHCONTROL_STENCILZPASS(enum adreno_stencil_op val)
{
return ((val) << A2XX_RB_DEPTHCONTROL_STENCILZPASS__SHIFT) & A2XX_RB_DEPTHCONTROL_STENCILZPASS__MASK;
}
#define A2XX_RB_DEPTHCONTROL_STENCILZFAIL__MASK 0x000e0000
#define A2XX_RB_DEPTHCONTROL_STENCILZFAIL__SHIFT 17
static inline uint32_t A2XX_RB_DEPTHCONTROL_STENCILZFAIL(enum adreno_stencil_op val)
{
return ((val) << A2XX_RB_DEPTHCONTROL_STENCILZFAIL__SHIFT) & A2XX_RB_DEPTHCONTROL_STENCILZFAIL__MASK;
}
#define A2XX_RB_DEPTHCONTROL_STENCILFUNC_BF__MASK 0x00700000
#define A2XX_RB_DEPTHCONTROL_STENCILFUNC_BF__SHIFT 20
static inline uint32_t A2XX_RB_DEPTHCONTROL_STENCILFUNC_BF(enum adreno_compare_func val)
{
return ((val) << A2XX_RB_DEPTHCONTROL_STENCILFUNC_BF__SHIFT) & A2XX_RB_DEPTHCONTROL_STENCILFUNC_BF__MASK;
}
#define A2XX_RB_DEPTHCONTROL_STENCILFAIL_BF__MASK 0x03800000
#define A2XX_RB_DEPTHCONTROL_STENCILFAIL_BF__SHIFT 23
static inline uint32_t A2XX_RB_DEPTHCONTROL_STENCILFAIL_BF(enum adreno_stencil_op val)
{
return ((val) << A2XX_RB_DEPTHCONTROL_STENCILFAIL_BF__SHIFT) & A2XX_RB_DEPTHCONTROL_STENCILFAIL_BF__MASK;
}
#define A2XX_RB_DEPTHCONTROL_STENCILZPASS_BF__MASK 0x1c000000
#define A2XX_RB_DEPTHCONTROL_STENCILZPASS_BF__SHIFT 26
static inline uint32_t A2XX_RB_DEPTHCONTROL_STENCILZPASS_BF(enum adreno_stencil_op val)
{
return ((val) << A2XX_RB_DEPTHCONTROL_STENCILZPASS_BF__SHIFT) & A2XX_RB_DEPTHCONTROL_STENCILZPASS_BF__MASK;
}
#define A2XX_RB_DEPTHCONTROL_STENCILZFAIL_BF__MASK 0xe0000000
#define A2XX_RB_DEPTHCONTROL_STENCILZFAIL_BF__SHIFT 29
static inline uint32_t A2XX_RB_DEPTHCONTROL_STENCILZFAIL_BF(enum adreno_stencil_op val)
{
return ((val) << A2XX_RB_DEPTHCONTROL_STENCILZFAIL_BF__SHIFT) & A2XX_RB_DEPTHCONTROL_STENCILZFAIL_BF__MASK;
}
 
#define REG_A2XX_RB_BLEND_CONTROL 0x00002201
#define A2XX_RB_BLEND_CONTROL_COLOR_SRCBLEND__MASK 0x0000001f
#define A2XX_RB_BLEND_CONTROL_COLOR_SRCBLEND__SHIFT 0
static inline uint32_t A2XX_RB_BLEND_CONTROL_COLOR_SRCBLEND(enum adreno_rb_blend_factor val)
{
return ((val) << A2XX_RB_BLEND_CONTROL_COLOR_SRCBLEND__SHIFT) & A2XX_RB_BLEND_CONTROL_COLOR_SRCBLEND__MASK;
}
#define A2XX_RB_BLEND_CONTROL_COLOR_COMB_FCN__MASK 0x000000e0
#define A2XX_RB_BLEND_CONTROL_COLOR_COMB_FCN__SHIFT 5
static inline uint32_t A2XX_RB_BLEND_CONTROL_COLOR_COMB_FCN(enum a2xx_rb_blend_opcode val)
{
return ((val) << A2XX_RB_BLEND_CONTROL_COLOR_COMB_FCN__SHIFT) & A2XX_RB_BLEND_CONTROL_COLOR_COMB_FCN__MASK;
}
#define A2XX_RB_BLEND_CONTROL_COLOR_DESTBLEND__MASK 0x00001f00
#define A2XX_RB_BLEND_CONTROL_COLOR_DESTBLEND__SHIFT 8
static inline uint32_t A2XX_RB_BLEND_CONTROL_COLOR_DESTBLEND(enum adreno_rb_blend_factor val)
{
return ((val) << A2XX_RB_BLEND_CONTROL_COLOR_DESTBLEND__SHIFT) & A2XX_RB_BLEND_CONTROL_COLOR_DESTBLEND__MASK;
}
#define A2XX_RB_BLEND_CONTROL_ALPHA_SRCBLEND__MASK 0x001f0000
#define A2XX_RB_BLEND_CONTROL_ALPHA_SRCBLEND__SHIFT 16
static inline uint32_t A2XX_RB_BLEND_CONTROL_ALPHA_SRCBLEND(enum adreno_rb_blend_factor val)
{
return ((val) << A2XX_RB_BLEND_CONTROL_ALPHA_SRCBLEND__SHIFT) & A2XX_RB_BLEND_CONTROL_ALPHA_SRCBLEND__MASK;
}
#define A2XX_RB_BLEND_CONTROL_ALPHA_COMB_FCN__MASK 0x00e00000
#define A2XX_RB_BLEND_CONTROL_ALPHA_COMB_FCN__SHIFT 21
static inline uint32_t A2XX_RB_BLEND_CONTROL_ALPHA_COMB_FCN(enum a2xx_rb_blend_opcode val)
{
return ((val) << A2XX_RB_BLEND_CONTROL_ALPHA_COMB_FCN__SHIFT) & A2XX_RB_BLEND_CONTROL_ALPHA_COMB_FCN__MASK;
}
#define A2XX_RB_BLEND_CONTROL_ALPHA_DESTBLEND__MASK 0x1f000000
#define A2XX_RB_BLEND_CONTROL_ALPHA_DESTBLEND__SHIFT 24
static inline uint32_t A2XX_RB_BLEND_CONTROL_ALPHA_DESTBLEND(enum adreno_rb_blend_factor val)
{
return ((val) << A2XX_RB_BLEND_CONTROL_ALPHA_DESTBLEND__SHIFT) & A2XX_RB_BLEND_CONTROL_ALPHA_DESTBLEND__MASK;
}
#define A2XX_RB_BLEND_CONTROL_BLEND_FORCE_ENABLE 0x20000000
#define A2XX_RB_BLEND_CONTROL_BLEND_FORCE 0x40000000
 
#define REG_A2XX_RB_COLORCONTROL 0x00002202
#define A2XX_RB_COLORCONTROL_ALPHA_FUNC__MASK 0x00000007
#define A2XX_RB_COLORCONTROL_ALPHA_FUNC__SHIFT 0
static inline uint32_t A2XX_RB_COLORCONTROL_ALPHA_FUNC(enum adreno_compare_func val)
{
return ((val) << A2XX_RB_COLORCONTROL_ALPHA_FUNC__SHIFT) & A2XX_RB_COLORCONTROL_ALPHA_FUNC__MASK;
}
#define A2XX_RB_COLORCONTROL_ALPHA_TEST_ENABLE 0x00000008
#define A2XX_RB_COLORCONTROL_ALPHA_TO_MASK_ENABLE 0x00000010
#define A2XX_RB_COLORCONTROL_BLEND_DISABLE 0x00000020
#define A2XX_RB_COLORCONTROL_VOB_ENABLE 0x00000040
#define A2XX_RB_COLORCONTROL_VS_EXPORTS_FOG 0x00000080
#define A2XX_RB_COLORCONTROL_ROP_CODE__MASK 0x00000f00
#define A2XX_RB_COLORCONTROL_ROP_CODE__SHIFT 8
static inline uint32_t A2XX_RB_COLORCONTROL_ROP_CODE(uint32_t val)
{
return ((val) << A2XX_RB_COLORCONTROL_ROP_CODE__SHIFT) & A2XX_RB_COLORCONTROL_ROP_CODE__MASK;
}
#define A2XX_RB_COLORCONTROL_DITHER_MODE__MASK 0x00003000
#define A2XX_RB_COLORCONTROL_DITHER_MODE__SHIFT 12
static inline uint32_t A2XX_RB_COLORCONTROL_DITHER_MODE(enum adreno_rb_dither_mode val)
{
return ((val) << A2XX_RB_COLORCONTROL_DITHER_MODE__SHIFT) & A2XX_RB_COLORCONTROL_DITHER_MODE__MASK;
}
#define A2XX_RB_COLORCONTROL_DITHER_TYPE__MASK 0x0000c000
#define A2XX_RB_COLORCONTROL_DITHER_TYPE__SHIFT 14
static inline uint32_t A2XX_RB_COLORCONTROL_DITHER_TYPE(enum a2xx_rb_dither_type val)
{
return ((val) << A2XX_RB_COLORCONTROL_DITHER_TYPE__SHIFT) & A2XX_RB_COLORCONTROL_DITHER_TYPE__MASK;
}
#define A2XX_RB_COLORCONTROL_PIXEL_FOG 0x00010000
#define A2XX_RB_COLORCONTROL_ALPHA_TO_MASK_OFFSET0__MASK 0x03000000
#define A2XX_RB_COLORCONTROL_ALPHA_TO_MASK_OFFSET0__SHIFT 24
static inline uint32_t A2XX_RB_COLORCONTROL_ALPHA_TO_MASK_OFFSET0(uint32_t val)
{
return ((val) << A2XX_RB_COLORCONTROL_ALPHA_TO_MASK_OFFSET0__SHIFT) & A2XX_RB_COLORCONTROL_ALPHA_TO_MASK_OFFSET0__MASK;
}
#define A2XX_RB_COLORCONTROL_ALPHA_TO_MASK_OFFSET1__MASK 0x0c000000
#define A2XX_RB_COLORCONTROL_ALPHA_TO_MASK_OFFSET1__SHIFT 26
static inline uint32_t A2XX_RB_COLORCONTROL_ALPHA_TO_MASK_OFFSET1(uint32_t val)
{
return ((val) << A2XX_RB_COLORCONTROL_ALPHA_TO_MASK_OFFSET1__SHIFT) & A2XX_RB_COLORCONTROL_ALPHA_TO_MASK_OFFSET1__MASK;
}
#define A2XX_RB_COLORCONTROL_ALPHA_TO_MASK_OFFSET2__MASK 0x30000000
#define A2XX_RB_COLORCONTROL_ALPHA_TO_MASK_OFFSET2__SHIFT 28
static inline uint32_t A2XX_RB_COLORCONTROL_ALPHA_TO_MASK_OFFSET2(uint32_t val)
{
return ((val) << A2XX_RB_COLORCONTROL_ALPHA_TO_MASK_OFFSET2__SHIFT) & A2XX_RB_COLORCONTROL_ALPHA_TO_MASK_OFFSET2__MASK;
}
#define A2XX_RB_COLORCONTROL_ALPHA_TO_MASK_OFFSET3__MASK 0xc0000000
#define A2XX_RB_COLORCONTROL_ALPHA_TO_MASK_OFFSET3__SHIFT 30
static inline uint32_t A2XX_RB_COLORCONTROL_ALPHA_TO_MASK_OFFSET3(uint32_t val)
{
return ((val) << A2XX_RB_COLORCONTROL_ALPHA_TO_MASK_OFFSET3__SHIFT) & A2XX_RB_COLORCONTROL_ALPHA_TO_MASK_OFFSET3__MASK;
}
 
#define REG_A2XX_VGT_CURRENT_BIN_ID_MAX 0x00002203
#define A2XX_VGT_CURRENT_BIN_ID_MAX_COLUMN__MASK 0x00000007
#define A2XX_VGT_CURRENT_BIN_ID_MAX_COLUMN__SHIFT 0
static inline uint32_t A2XX_VGT_CURRENT_BIN_ID_MAX_COLUMN(uint32_t val)
{
return ((val) << A2XX_VGT_CURRENT_BIN_ID_MAX_COLUMN__SHIFT) & A2XX_VGT_CURRENT_BIN_ID_MAX_COLUMN__MASK;
}
#define A2XX_VGT_CURRENT_BIN_ID_MAX_ROW__MASK 0x00000038
#define A2XX_VGT_CURRENT_BIN_ID_MAX_ROW__SHIFT 3
static inline uint32_t A2XX_VGT_CURRENT_BIN_ID_MAX_ROW(uint32_t val)
{
return ((val) << A2XX_VGT_CURRENT_BIN_ID_MAX_ROW__SHIFT) & A2XX_VGT_CURRENT_BIN_ID_MAX_ROW__MASK;
}
#define A2XX_VGT_CURRENT_BIN_ID_MAX_GUARD_BAND_MASK__MASK 0x000001c0
#define A2XX_VGT_CURRENT_BIN_ID_MAX_GUARD_BAND_MASK__SHIFT 6
static inline uint32_t A2XX_VGT_CURRENT_BIN_ID_MAX_GUARD_BAND_MASK(uint32_t val)
{
return ((val) << A2XX_VGT_CURRENT_BIN_ID_MAX_GUARD_BAND_MASK__SHIFT) & A2XX_VGT_CURRENT_BIN_ID_MAX_GUARD_BAND_MASK__MASK;
}
 
#define REG_A2XX_PA_CL_CLIP_CNTL 0x00002204
#define A2XX_PA_CL_CLIP_CNTL_CLIP_DISABLE 0x00010000
#define A2XX_PA_CL_CLIP_CNTL_BOUNDARY_EDGE_FLAG_ENA 0x00040000
#define A2XX_PA_CL_CLIP_CNTL_DX_CLIP_SPACE_DEF__MASK 0x00080000
#define A2XX_PA_CL_CLIP_CNTL_DX_CLIP_SPACE_DEF__SHIFT 19
static inline uint32_t A2XX_PA_CL_CLIP_CNTL_DX_CLIP_SPACE_DEF(enum a2xx_dx_clip_space val)
{
return ((val) << A2XX_PA_CL_CLIP_CNTL_DX_CLIP_SPACE_DEF__SHIFT) & A2XX_PA_CL_CLIP_CNTL_DX_CLIP_SPACE_DEF__MASK;
}
#define A2XX_PA_CL_CLIP_CNTL_DIS_CLIP_ERR_DETECT 0x00100000
#define A2XX_PA_CL_CLIP_CNTL_VTX_KILL_OR 0x00200000
#define A2XX_PA_CL_CLIP_CNTL_XY_NAN_RETAIN 0x00400000
#define A2XX_PA_CL_CLIP_CNTL_Z_NAN_RETAIN 0x00800000
#define A2XX_PA_CL_CLIP_CNTL_W_NAN_RETAIN 0x01000000
 
#define REG_A2XX_PA_SU_SC_MODE_CNTL 0x00002205
#define A2XX_PA_SU_SC_MODE_CNTL_CULL_FRONT 0x00000001
#define A2XX_PA_SU_SC_MODE_CNTL_CULL_BACK 0x00000002
#define A2XX_PA_SU_SC_MODE_CNTL_FACE 0x00000004
#define A2XX_PA_SU_SC_MODE_CNTL_POLYMODE__MASK 0x00000018
#define A2XX_PA_SU_SC_MODE_CNTL_POLYMODE__SHIFT 3
static inline uint32_t A2XX_PA_SU_SC_MODE_CNTL_POLYMODE(enum a2xx_pa_su_sc_polymode val)
{
return ((val) << A2XX_PA_SU_SC_MODE_CNTL_POLYMODE__SHIFT) & A2XX_PA_SU_SC_MODE_CNTL_POLYMODE__MASK;
}
#define A2XX_PA_SU_SC_MODE_CNTL_FRONT_PTYPE__MASK 0x000000e0
#define A2XX_PA_SU_SC_MODE_CNTL_FRONT_PTYPE__SHIFT 5
static inline uint32_t A2XX_PA_SU_SC_MODE_CNTL_FRONT_PTYPE(enum adreno_pa_su_sc_draw val)
{
return ((val) << A2XX_PA_SU_SC_MODE_CNTL_FRONT_PTYPE__SHIFT) & A2XX_PA_SU_SC_MODE_CNTL_FRONT_PTYPE__MASK;
}
#define A2XX_PA_SU_SC_MODE_CNTL_BACK_PTYPE__MASK 0x00000700
#define A2XX_PA_SU_SC_MODE_CNTL_BACK_PTYPE__SHIFT 8
static inline uint32_t A2XX_PA_SU_SC_MODE_CNTL_BACK_PTYPE(enum adreno_pa_su_sc_draw val)
{
return ((val) << A2XX_PA_SU_SC_MODE_CNTL_BACK_PTYPE__SHIFT) & A2XX_PA_SU_SC_MODE_CNTL_BACK_PTYPE__MASK;
}
#define A2XX_PA_SU_SC_MODE_CNTL_POLY_OFFSET_FRONT_ENABLE 0x00000800
#define A2XX_PA_SU_SC_MODE_CNTL_POLY_OFFSET_BACK_ENABLE 0x00001000
#define A2XX_PA_SU_SC_MODE_CNTL_POLY_OFFSET_PARA_ENABLE 0x00002000
#define A2XX_PA_SU_SC_MODE_CNTL_MSAA_ENABLE 0x00008000
#define A2XX_PA_SU_SC_MODE_CNTL_VTX_WINDOW_OFFSET_ENABLE 0x00010000
#define A2XX_PA_SU_SC_MODE_CNTL_LINE_STIPPLE_ENABLE 0x00040000
#define A2XX_PA_SU_SC_MODE_CNTL_PROVOKING_VTX_LAST 0x00080000
#define A2XX_PA_SU_SC_MODE_CNTL_PERSP_CORR_DIS 0x00100000
#define A2XX_PA_SU_SC_MODE_CNTL_MULTI_PRIM_IB_ENA 0x00200000
#define A2XX_PA_SU_SC_MODE_CNTL_QUAD_ORDER_ENABLE 0x00800000
#define A2XX_PA_SU_SC_MODE_CNTL_WAIT_RB_IDLE_ALL_TRI 0x02000000
#define A2XX_PA_SU_SC_MODE_CNTL_WAIT_RB_IDLE_FIRST_TRI_NEW_STATE 0x04000000
#define A2XX_PA_SU_SC_MODE_CNTL_CLAMPED_FACENESS 0x10000000
#define A2XX_PA_SU_SC_MODE_CNTL_ZERO_AREA_FACENESS 0x20000000
#define A2XX_PA_SU_SC_MODE_CNTL_FACE_KILL_ENABLE 0x40000000
#define A2XX_PA_SU_SC_MODE_CNTL_FACE_WRITE_ENABLE 0x80000000
 
#define REG_A2XX_PA_CL_VTE_CNTL 0x00002206
#define A2XX_PA_CL_VTE_CNTL_VPORT_X_SCALE_ENA 0x00000001
#define A2XX_PA_CL_VTE_CNTL_VPORT_X_OFFSET_ENA 0x00000002
#define A2XX_PA_CL_VTE_CNTL_VPORT_Y_SCALE_ENA 0x00000004
#define A2XX_PA_CL_VTE_CNTL_VPORT_Y_OFFSET_ENA 0x00000008
#define A2XX_PA_CL_VTE_CNTL_VPORT_Z_SCALE_ENA 0x00000010
#define A2XX_PA_CL_VTE_CNTL_VPORT_Z_OFFSET_ENA 0x00000020
#define A2XX_PA_CL_VTE_CNTL_VTX_XY_FMT 0x00000100
#define A2XX_PA_CL_VTE_CNTL_VTX_Z_FMT 0x00000200
#define A2XX_PA_CL_VTE_CNTL_VTX_W0_FMT 0x00000400
#define A2XX_PA_CL_VTE_CNTL_PERFCOUNTER_REF 0x00000800
 
#define REG_A2XX_VGT_CURRENT_BIN_ID_MIN 0x00002207
#define A2XX_VGT_CURRENT_BIN_ID_MIN_COLUMN__MASK 0x00000007
#define A2XX_VGT_CURRENT_BIN_ID_MIN_COLUMN__SHIFT 0
static inline uint32_t A2XX_VGT_CURRENT_BIN_ID_MIN_COLUMN(uint32_t val)
{
return ((val) << A2XX_VGT_CURRENT_BIN_ID_MIN_COLUMN__SHIFT) & A2XX_VGT_CURRENT_BIN_ID_MIN_COLUMN__MASK;
}
#define A2XX_VGT_CURRENT_BIN_ID_MIN_ROW__MASK 0x00000038
#define A2XX_VGT_CURRENT_BIN_ID_MIN_ROW__SHIFT 3
static inline uint32_t A2XX_VGT_CURRENT_BIN_ID_MIN_ROW(uint32_t val)
{
return ((val) << A2XX_VGT_CURRENT_BIN_ID_MIN_ROW__SHIFT) & A2XX_VGT_CURRENT_BIN_ID_MIN_ROW__MASK;
}
#define A2XX_VGT_CURRENT_BIN_ID_MIN_GUARD_BAND_MASK__MASK 0x000001c0
#define A2XX_VGT_CURRENT_BIN_ID_MIN_GUARD_BAND_MASK__SHIFT 6
static inline uint32_t A2XX_VGT_CURRENT_BIN_ID_MIN_GUARD_BAND_MASK(uint32_t val)
{
return ((val) << A2XX_VGT_CURRENT_BIN_ID_MIN_GUARD_BAND_MASK__SHIFT) & A2XX_VGT_CURRENT_BIN_ID_MIN_GUARD_BAND_MASK__MASK;
}
 
#define REG_A2XX_RB_MODECONTROL 0x00002208
#define A2XX_RB_MODECONTROL_EDRAM_MODE__MASK 0x00000007
#define A2XX_RB_MODECONTROL_EDRAM_MODE__SHIFT 0
static inline uint32_t A2XX_RB_MODECONTROL_EDRAM_MODE(enum a2xx_rb_edram_mode val)
{
return ((val) << A2XX_RB_MODECONTROL_EDRAM_MODE__SHIFT) & A2XX_RB_MODECONTROL_EDRAM_MODE__MASK;
}
 
#define REG_A2XX_A220_RB_LRZ_VSC_CONTROL 0x00002209
 
#define REG_A2XX_RB_SAMPLE_POS 0x0000220a
 
#define REG_A2XX_CLEAR_COLOR 0x0000220b
#define A2XX_CLEAR_COLOR_RED__MASK 0x000000ff
#define A2XX_CLEAR_COLOR_RED__SHIFT 0
static inline uint32_t A2XX_CLEAR_COLOR_RED(uint32_t val)
{
return ((val) << A2XX_CLEAR_COLOR_RED__SHIFT) & A2XX_CLEAR_COLOR_RED__MASK;
}
#define A2XX_CLEAR_COLOR_GREEN__MASK 0x0000ff00
#define A2XX_CLEAR_COLOR_GREEN__SHIFT 8
static inline uint32_t A2XX_CLEAR_COLOR_GREEN(uint32_t val)
{
return ((val) << A2XX_CLEAR_COLOR_GREEN__SHIFT) & A2XX_CLEAR_COLOR_GREEN__MASK;
}
#define A2XX_CLEAR_COLOR_BLUE__MASK 0x00ff0000
#define A2XX_CLEAR_COLOR_BLUE__SHIFT 16
static inline uint32_t A2XX_CLEAR_COLOR_BLUE(uint32_t val)
{
return ((val) << A2XX_CLEAR_COLOR_BLUE__SHIFT) & A2XX_CLEAR_COLOR_BLUE__MASK;
}
#define A2XX_CLEAR_COLOR_ALPHA__MASK 0xff000000
#define A2XX_CLEAR_COLOR_ALPHA__SHIFT 24
static inline uint32_t A2XX_CLEAR_COLOR_ALPHA(uint32_t val)
{
return ((val) << A2XX_CLEAR_COLOR_ALPHA__SHIFT) & A2XX_CLEAR_COLOR_ALPHA__MASK;
}
 
#define REG_A2XX_A220_GRAS_CONTROL 0x00002210
 
#define REG_A2XX_PA_SU_POINT_SIZE 0x00002280
#define A2XX_PA_SU_POINT_SIZE_HEIGHT__MASK 0x0000ffff
#define A2XX_PA_SU_POINT_SIZE_HEIGHT__SHIFT 0
static inline uint32_t A2XX_PA_SU_POINT_SIZE_HEIGHT(float val)
{
return ((((uint32_t)(val * 16.0))) << A2XX_PA_SU_POINT_SIZE_HEIGHT__SHIFT) & A2XX_PA_SU_POINT_SIZE_HEIGHT__MASK;
}
#define A2XX_PA_SU_POINT_SIZE_WIDTH__MASK 0xffff0000
#define A2XX_PA_SU_POINT_SIZE_WIDTH__SHIFT 16
static inline uint32_t A2XX_PA_SU_POINT_SIZE_WIDTH(float val)
{
return ((((uint32_t)(val * 16.0))) << A2XX_PA_SU_POINT_SIZE_WIDTH__SHIFT) & A2XX_PA_SU_POINT_SIZE_WIDTH__MASK;
}
 
#define REG_A2XX_PA_SU_POINT_MINMAX 0x00002281
#define A2XX_PA_SU_POINT_MINMAX_MIN__MASK 0x0000ffff
#define A2XX_PA_SU_POINT_MINMAX_MIN__SHIFT 0
static inline uint32_t A2XX_PA_SU_POINT_MINMAX_MIN(float val)
{
return ((((uint32_t)(val * 16.0))) << A2XX_PA_SU_POINT_MINMAX_MIN__SHIFT) & A2XX_PA_SU_POINT_MINMAX_MIN__MASK;
}
#define A2XX_PA_SU_POINT_MINMAX_MAX__MASK 0xffff0000
#define A2XX_PA_SU_POINT_MINMAX_MAX__SHIFT 16
static inline uint32_t A2XX_PA_SU_POINT_MINMAX_MAX(float val)
{
return ((((uint32_t)(val * 16.0))) << A2XX_PA_SU_POINT_MINMAX_MAX__SHIFT) & A2XX_PA_SU_POINT_MINMAX_MAX__MASK;
}
 
#define REG_A2XX_PA_SU_LINE_CNTL 0x00002282
#define A2XX_PA_SU_LINE_CNTL_WIDTH__MASK 0x0000ffff
#define A2XX_PA_SU_LINE_CNTL_WIDTH__SHIFT 0
static inline uint32_t A2XX_PA_SU_LINE_CNTL_WIDTH(float val)
{
return ((((uint32_t)(val * 16.0))) << A2XX_PA_SU_LINE_CNTL_WIDTH__SHIFT) & A2XX_PA_SU_LINE_CNTL_WIDTH__MASK;
}
 
#define REG_A2XX_PA_SC_LINE_STIPPLE 0x00002283
#define A2XX_PA_SC_LINE_STIPPLE_LINE_PATTERN__MASK 0x0000ffff
#define A2XX_PA_SC_LINE_STIPPLE_LINE_PATTERN__SHIFT 0
static inline uint32_t A2XX_PA_SC_LINE_STIPPLE_LINE_PATTERN(uint32_t val)
{
return ((val) << A2XX_PA_SC_LINE_STIPPLE_LINE_PATTERN__SHIFT) & A2XX_PA_SC_LINE_STIPPLE_LINE_PATTERN__MASK;
}
#define A2XX_PA_SC_LINE_STIPPLE_REPEAT_COUNT__MASK 0x00ff0000
#define A2XX_PA_SC_LINE_STIPPLE_REPEAT_COUNT__SHIFT 16
static inline uint32_t A2XX_PA_SC_LINE_STIPPLE_REPEAT_COUNT(uint32_t val)
{
return ((val) << A2XX_PA_SC_LINE_STIPPLE_REPEAT_COUNT__SHIFT) & A2XX_PA_SC_LINE_STIPPLE_REPEAT_COUNT__MASK;
}
#define A2XX_PA_SC_LINE_STIPPLE_PATTERN_BIT_ORDER__MASK 0x10000000
#define A2XX_PA_SC_LINE_STIPPLE_PATTERN_BIT_ORDER__SHIFT 28
static inline uint32_t A2XX_PA_SC_LINE_STIPPLE_PATTERN_BIT_ORDER(enum a2xx_pa_sc_pattern_bit_order val)
{
return ((val) << A2XX_PA_SC_LINE_STIPPLE_PATTERN_BIT_ORDER__SHIFT) & A2XX_PA_SC_LINE_STIPPLE_PATTERN_BIT_ORDER__MASK;
}
#define A2XX_PA_SC_LINE_STIPPLE_AUTO_RESET_CNTL__MASK 0x60000000
#define A2XX_PA_SC_LINE_STIPPLE_AUTO_RESET_CNTL__SHIFT 29
static inline uint32_t A2XX_PA_SC_LINE_STIPPLE_AUTO_RESET_CNTL(enum a2xx_pa_sc_auto_reset_cntl val)
{
return ((val) << A2XX_PA_SC_LINE_STIPPLE_AUTO_RESET_CNTL__SHIFT) & A2XX_PA_SC_LINE_STIPPLE_AUTO_RESET_CNTL__MASK;
}
 
#define REG_A2XX_PA_SC_VIZ_QUERY 0x00002293
 
#define REG_A2XX_VGT_ENHANCE 0x00002294
 
#define REG_A2XX_PA_SC_LINE_CNTL 0x00002300
#define A2XX_PA_SC_LINE_CNTL_BRES_CNTL__MASK 0x0000ffff
#define A2XX_PA_SC_LINE_CNTL_BRES_CNTL__SHIFT 0
static inline uint32_t A2XX_PA_SC_LINE_CNTL_BRES_CNTL(uint32_t val)
{
return ((val) << A2XX_PA_SC_LINE_CNTL_BRES_CNTL__SHIFT) & A2XX_PA_SC_LINE_CNTL_BRES_CNTL__MASK;
}
#define A2XX_PA_SC_LINE_CNTL_USE_BRES_CNTL 0x00000100
#define A2XX_PA_SC_LINE_CNTL_EXPAND_LINE_WIDTH 0x00000200
#define A2XX_PA_SC_LINE_CNTL_LAST_PIXEL 0x00000400
 
#define REG_A2XX_PA_SC_AA_CONFIG 0x00002301
 
#define REG_A2XX_PA_SU_VTX_CNTL 0x00002302
#define A2XX_PA_SU_VTX_CNTL_PIX_CENTER__MASK 0x00000001
#define A2XX_PA_SU_VTX_CNTL_PIX_CENTER__SHIFT 0
static inline uint32_t A2XX_PA_SU_VTX_CNTL_PIX_CENTER(enum a2xx_pa_pixcenter val)
{
return ((val) << A2XX_PA_SU_VTX_CNTL_PIX_CENTER__SHIFT) & A2XX_PA_SU_VTX_CNTL_PIX_CENTER__MASK;
}
#define A2XX_PA_SU_VTX_CNTL_ROUND_MODE__MASK 0x00000006
#define A2XX_PA_SU_VTX_CNTL_ROUND_MODE__SHIFT 1
static inline uint32_t A2XX_PA_SU_VTX_CNTL_ROUND_MODE(enum a2xx_pa_roundmode val)
{
return ((val) << A2XX_PA_SU_VTX_CNTL_ROUND_MODE__SHIFT) & A2XX_PA_SU_VTX_CNTL_ROUND_MODE__MASK;
}
#define A2XX_PA_SU_VTX_CNTL_QUANT_MODE__MASK 0x00000380
#define A2XX_PA_SU_VTX_CNTL_QUANT_MODE__SHIFT 7
static inline uint32_t A2XX_PA_SU_VTX_CNTL_QUANT_MODE(enum a2xx_pa_quantmode val)
{
return ((val) << A2XX_PA_SU_VTX_CNTL_QUANT_MODE__SHIFT) & A2XX_PA_SU_VTX_CNTL_QUANT_MODE__MASK;
}
 
#define REG_A2XX_PA_CL_GB_VERT_CLIP_ADJ 0x00002303
#define A2XX_PA_CL_GB_VERT_CLIP_ADJ__MASK 0xffffffff
#define A2XX_PA_CL_GB_VERT_CLIP_ADJ__SHIFT 0
static inline uint32_t A2XX_PA_CL_GB_VERT_CLIP_ADJ(float val)
{
return ((fui(val)) << A2XX_PA_CL_GB_VERT_CLIP_ADJ__SHIFT) & A2XX_PA_CL_GB_VERT_CLIP_ADJ__MASK;
}
 
#define REG_A2XX_PA_CL_GB_VERT_DISC_ADJ 0x00002304
#define A2XX_PA_CL_GB_VERT_DISC_ADJ__MASK 0xffffffff
#define A2XX_PA_CL_GB_VERT_DISC_ADJ__SHIFT 0
static inline uint32_t A2XX_PA_CL_GB_VERT_DISC_ADJ(float val)
{
return ((fui(val)) << A2XX_PA_CL_GB_VERT_DISC_ADJ__SHIFT) & A2XX_PA_CL_GB_VERT_DISC_ADJ__MASK;
}
 
#define REG_A2XX_PA_CL_GB_HORZ_CLIP_ADJ 0x00002305
#define A2XX_PA_CL_GB_HORZ_CLIP_ADJ__MASK 0xffffffff
#define A2XX_PA_CL_GB_HORZ_CLIP_ADJ__SHIFT 0
static inline uint32_t A2XX_PA_CL_GB_HORZ_CLIP_ADJ(float val)
{
return ((fui(val)) << A2XX_PA_CL_GB_HORZ_CLIP_ADJ__SHIFT) & A2XX_PA_CL_GB_HORZ_CLIP_ADJ__MASK;
}
 
#define REG_A2XX_PA_CL_GB_HORZ_DISC_ADJ 0x00002306
#define A2XX_PA_CL_GB_HORZ_DISC_ADJ__MASK 0xffffffff
#define A2XX_PA_CL_GB_HORZ_DISC_ADJ__SHIFT 0
static inline uint32_t A2XX_PA_CL_GB_HORZ_DISC_ADJ(float val)
{
return ((fui(val)) << A2XX_PA_CL_GB_HORZ_DISC_ADJ__SHIFT) & A2XX_PA_CL_GB_HORZ_DISC_ADJ__MASK;
}
 
#define REG_A2XX_SQ_VS_CONST 0x00002307
#define A2XX_SQ_VS_CONST_BASE__MASK 0x000001ff
#define A2XX_SQ_VS_CONST_BASE__SHIFT 0
static inline uint32_t A2XX_SQ_VS_CONST_BASE(uint32_t val)
{
return ((val) << A2XX_SQ_VS_CONST_BASE__SHIFT) & A2XX_SQ_VS_CONST_BASE__MASK;
}
#define A2XX_SQ_VS_CONST_SIZE__MASK 0x001ff000
#define A2XX_SQ_VS_CONST_SIZE__SHIFT 12
static inline uint32_t A2XX_SQ_VS_CONST_SIZE(uint32_t val)
{
return ((val) << A2XX_SQ_VS_CONST_SIZE__SHIFT) & A2XX_SQ_VS_CONST_SIZE__MASK;
}
 
#define REG_A2XX_SQ_PS_CONST 0x00002308
#define A2XX_SQ_PS_CONST_BASE__MASK 0x000001ff
#define A2XX_SQ_PS_CONST_BASE__SHIFT 0
static inline uint32_t A2XX_SQ_PS_CONST_BASE(uint32_t val)
{
return ((val) << A2XX_SQ_PS_CONST_BASE__SHIFT) & A2XX_SQ_PS_CONST_BASE__MASK;
}
#define A2XX_SQ_PS_CONST_SIZE__MASK 0x001ff000
#define A2XX_SQ_PS_CONST_SIZE__SHIFT 12
static inline uint32_t A2XX_SQ_PS_CONST_SIZE(uint32_t val)
{
return ((val) << A2XX_SQ_PS_CONST_SIZE__SHIFT) & A2XX_SQ_PS_CONST_SIZE__MASK;
}
 
#define REG_A2XX_SQ_DEBUG_MISC_0 0x00002309
 
#define REG_A2XX_SQ_DEBUG_MISC_1 0x0000230a
 
#define REG_A2XX_PA_SC_AA_MASK 0x00002312
 
#define REG_A2XX_VGT_VERTEX_REUSE_BLOCK_CNTL 0x00002316
 
#define REG_A2XX_VGT_OUT_DEALLOC_CNTL 0x00002317
 
#define REG_A2XX_RB_COPY_CONTROL 0x00002318
#define A2XX_RB_COPY_CONTROL_COPY_SAMPLE_SELECT__MASK 0x00000007
#define A2XX_RB_COPY_CONTROL_COPY_SAMPLE_SELECT__SHIFT 0
static inline uint32_t A2XX_RB_COPY_CONTROL_COPY_SAMPLE_SELECT(enum a2xx_rb_copy_sample_select val)
{
return ((val) << A2XX_RB_COPY_CONTROL_COPY_SAMPLE_SELECT__SHIFT) & A2XX_RB_COPY_CONTROL_COPY_SAMPLE_SELECT__MASK;
}
#define A2XX_RB_COPY_CONTROL_DEPTH_CLEAR_ENABLE 0x00000008
#define A2XX_RB_COPY_CONTROL_CLEAR_MASK__MASK 0x000000f0
#define A2XX_RB_COPY_CONTROL_CLEAR_MASK__SHIFT 4
static inline uint32_t A2XX_RB_COPY_CONTROL_CLEAR_MASK(uint32_t val)
{
return ((val) << A2XX_RB_COPY_CONTROL_CLEAR_MASK__SHIFT) & A2XX_RB_COPY_CONTROL_CLEAR_MASK__MASK;
}
 
#define REG_A2XX_RB_COPY_DEST_BASE 0x00002319
 
#define REG_A2XX_RB_COPY_DEST_PITCH 0x0000231a
#define A2XX_RB_COPY_DEST_PITCH__MASK 0xffffffff
#define A2XX_RB_COPY_DEST_PITCH__SHIFT 0
static inline uint32_t A2XX_RB_COPY_DEST_PITCH(uint32_t val)
{
return ((val >> 5) << A2XX_RB_COPY_DEST_PITCH__SHIFT) & A2XX_RB_COPY_DEST_PITCH__MASK;
}
 
#define REG_A2XX_RB_COPY_DEST_INFO 0x0000231b
#define A2XX_RB_COPY_DEST_INFO_DEST_ENDIAN__MASK 0x00000007
#define A2XX_RB_COPY_DEST_INFO_DEST_ENDIAN__SHIFT 0
static inline uint32_t A2XX_RB_COPY_DEST_INFO_DEST_ENDIAN(enum adreno_rb_surface_endian val)
{
return ((val) << A2XX_RB_COPY_DEST_INFO_DEST_ENDIAN__SHIFT) & A2XX_RB_COPY_DEST_INFO_DEST_ENDIAN__MASK;
}
#define A2XX_RB_COPY_DEST_INFO_LINEAR 0x00000008
#define A2XX_RB_COPY_DEST_INFO_FORMAT__MASK 0x000000f0
#define A2XX_RB_COPY_DEST_INFO_FORMAT__SHIFT 4
static inline uint32_t A2XX_RB_COPY_DEST_INFO_FORMAT(enum a2xx_colorformatx val)
{
return ((val) << A2XX_RB_COPY_DEST_INFO_FORMAT__SHIFT) & A2XX_RB_COPY_DEST_INFO_FORMAT__MASK;
}
#define A2XX_RB_COPY_DEST_INFO_SWAP__MASK 0x00000300
#define A2XX_RB_COPY_DEST_INFO_SWAP__SHIFT 8
static inline uint32_t A2XX_RB_COPY_DEST_INFO_SWAP(uint32_t val)
{
return ((val) << A2XX_RB_COPY_DEST_INFO_SWAP__SHIFT) & A2XX_RB_COPY_DEST_INFO_SWAP__MASK;
}
#define A2XX_RB_COPY_DEST_INFO_DITHER_MODE__MASK 0x00000c00
#define A2XX_RB_COPY_DEST_INFO_DITHER_MODE__SHIFT 10
static inline uint32_t A2XX_RB_COPY_DEST_INFO_DITHER_MODE(enum adreno_rb_dither_mode val)
{
return ((val) << A2XX_RB_COPY_DEST_INFO_DITHER_MODE__SHIFT) & A2XX_RB_COPY_DEST_INFO_DITHER_MODE__MASK;
}
#define A2XX_RB_COPY_DEST_INFO_DITHER_TYPE__MASK 0x00003000
#define A2XX_RB_COPY_DEST_INFO_DITHER_TYPE__SHIFT 12
static inline uint32_t A2XX_RB_COPY_DEST_INFO_DITHER_TYPE(enum a2xx_rb_dither_type val)
{
return ((val) << A2XX_RB_COPY_DEST_INFO_DITHER_TYPE__SHIFT) & A2XX_RB_COPY_DEST_INFO_DITHER_TYPE__MASK;
}
#define A2XX_RB_COPY_DEST_INFO_WRITE_RED 0x00004000
#define A2XX_RB_COPY_DEST_INFO_WRITE_GREEN 0x00008000
#define A2XX_RB_COPY_DEST_INFO_WRITE_BLUE 0x00010000
#define A2XX_RB_COPY_DEST_INFO_WRITE_ALPHA 0x00020000
 
#define REG_A2XX_RB_COPY_DEST_OFFSET 0x0000231c
#define A2XX_RB_COPY_DEST_OFFSET_X__MASK 0x00001fff
#define A2XX_RB_COPY_DEST_OFFSET_X__SHIFT 0
static inline uint32_t A2XX_RB_COPY_DEST_OFFSET_X(uint32_t val)
{
return ((val) << A2XX_RB_COPY_DEST_OFFSET_X__SHIFT) & A2XX_RB_COPY_DEST_OFFSET_X__MASK;
}
#define A2XX_RB_COPY_DEST_OFFSET_Y__MASK 0x03ffe000
#define A2XX_RB_COPY_DEST_OFFSET_Y__SHIFT 13
static inline uint32_t A2XX_RB_COPY_DEST_OFFSET_Y(uint32_t val)
{
return ((val) << A2XX_RB_COPY_DEST_OFFSET_Y__SHIFT) & A2XX_RB_COPY_DEST_OFFSET_Y__MASK;
}
 
#define REG_A2XX_RB_DEPTH_CLEAR 0x0000231d
 
#define REG_A2XX_RB_SAMPLE_COUNT_CTL 0x00002324
 
#define REG_A2XX_RB_COLOR_DEST_MASK 0x00002326
 
#define REG_A2XX_A225_GRAS_UCP0X 0x00002340
 
#define REG_A2XX_A225_GRAS_UCP5W 0x00002357
 
#define REG_A2XX_A225_GRAS_UCP_ENABLED 0x00002360
 
#define REG_A2XX_PA_SU_POLY_OFFSET_FRONT_SCALE 0x00002380
 
#define REG_A2XX_PA_SU_POLY_OFFSET_BACK_OFFSET 0x00002383
 
#define REG_A2XX_SQ_CONSTANT_0 0x00004000
 
#define REG_A2XX_SQ_FETCH_0 0x00004800
 
#define REG_A2XX_SQ_CF_BOOLEANS 0x00004900
 
#define REG_A2XX_SQ_CF_LOOP 0x00004908
 
#define REG_A2XX_COHER_SIZE_PM4 0x00000a29
 
#define REG_A2XX_COHER_BASE_PM4 0x00000a2a
 
#define REG_A2XX_COHER_STATUS_PM4 0x00000a2b
 
#define REG_A2XX_SQ_TEX_0 0x00000000
#define A2XX_SQ_TEX_0_CLAMP_X__MASK 0x00001c00
#define A2XX_SQ_TEX_0_CLAMP_X__SHIFT 10
static inline uint32_t A2XX_SQ_TEX_0_CLAMP_X(enum sq_tex_clamp val)
{
return ((val) << A2XX_SQ_TEX_0_CLAMP_X__SHIFT) & A2XX_SQ_TEX_0_CLAMP_X__MASK;
}
#define A2XX_SQ_TEX_0_CLAMP_Y__MASK 0x0000e000
#define A2XX_SQ_TEX_0_CLAMP_Y__SHIFT 13
static inline uint32_t A2XX_SQ_TEX_0_CLAMP_Y(enum sq_tex_clamp val)
{
return ((val) << A2XX_SQ_TEX_0_CLAMP_Y__SHIFT) & A2XX_SQ_TEX_0_CLAMP_Y__MASK;
}
#define A2XX_SQ_TEX_0_CLAMP_Z__MASK 0x00070000
#define A2XX_SQ_TEX_0_CLAMP_Z__SHIFT 16
static inline uint32_t A2XX_SQ_TEX_0_CLAMP_Z(enum sq_tex_clamp val)
{
return ((val) << A2XX_SQ_TEX_0_CLAMP_Z__SHIFT) & A2XX_SQ_TEX_0_CLAMP_Z__MASK;
}
#define A2XX_SQ_TEX_0_PITCH__MASK 0xffc00000
#define A2XX_SQ_TEX_0_PITCH__SHIFT 22
static inline uint32_t A2XX_SQ_TEX_0_PITCH(uint32_t val)
{
return ((val >> 5) << A2XX_SQ_TEX_0_PITCH__SHIFT) & A2XX_SQ_TEX_0_PITCH__MASK;
}
 
#define REG_A2XX_SQ_TEX_1 0x00000001
 
#define REG_A2XX_SQ_TEX_2 0x00000002
#define A2XX_SQ_TEX_2_WIDTH__MASK 0x00001fff
#define A2XX_SQ_TEX_2_WIDTH__SHIFT 0
static inline uint32_t A2XX_SQ_TEX_2_WIDTH(uint32_t val)
{
return ((val) << A2XX_SQ_TEX_2_WIDTH__SHIFT) & A2XX_SQ_TEX_2_WIDTH__MASK;
}
#define A2XX_SQ_TEX_2_HEIGHT__MASK 0x03ffe000
#define A2XX_SQ_TEX_2_HEIGHT__SHIFT 13
static inline uint32_t A2XX_SQ_TEX_2_HEIGHT(uint32_t val)
{
return ((val) << A2XX_SQ_TEX_2_HEIGHT__SHIFT) & A2XX_SQ_TEX_2_HEIGHT__MASK;
}
 
#define REG_A2XX_SQ_TEX_3 0x00000003
#define A2XX_SQ_TEX_3_SWIZ_X__MASK 0x0000000e
#define A2XX_SQ_TEX_3_SWIZ_X__SHIFT 1
static inline uint32_t A2XX_SQ_TEX_3_SWIZ_X(enum sq_tex_swiz val)
{
return ((val) << A2XX_SQ_TEX_3_SWIZ_X__SHIFT) & A2XX_SQ_TEX_3_SWIZ_X__MASK;
}
#define A2XX_SQ_TEX_3_SWIZ_Y__MASK 0x00000070
#define A2XX_SQ_TEX_3_SWIZ_Y__SHIFT 4
static inline uint32_t A2XX_SQ_TEX_3_SWIZ_Y(enum sq_tex_swiz val)
{
return ((val) << A2XX_SQ_TEX_3_SWIZ_Y__SHIFT) & A2XX_SQ_TEX_3_SWIZ_Y__MASK;
}
#define A2XX_SQ_TEX_3_SWIZ_Z__MASK 0x00000380
#define A2XX_SQ_TEX_3_SWIZ_Z__SHIFT 7
static inline uint32_t A2XX_SQ_TEX_3_SWIZ_Z(enum sq_tex_swiz val)
{
return ((val) << A2XX_SQ_TEX_3_SWIZ_Z__SHIFT) & A2XX_SQ_TEX_3_SWIZ_Z__MASK;
}
#define A2XX_SQ_TEX_3_SWIZ_W__MASK 0x00001c00
#define A2XX_SQ_TEX_3_SWIZ_W__SHIFT 10
static inline uint32_t A2XX_SQ_TEX_3_SWIZ_W(enum sq_tex_swiz val)
{
return ((val) << A2XX_SQ_TEX_3_SWIZ_W__SHIFT) & A2XX_SQ_TEX_3_SWIZ_W__MASK;
}
#define A2XX_SQ_TEX_3_XY_MAG_FILTER__MASK 0x00180000
#define A2XX_SQ_TEX_3_XY_MAG_FILTER__SHIFT 19
static inline uint32_t A2XX_SQ_TEX_3_XY_MAG_FILTER(enum sq_tex_filter val)
{
return ((val) << A2XX_SQ_TEX_3_XY_MAG_FILTER__SHIFT) & A2XX_SQ_TEX_3_XY_MAG_FILTER__MASK;
}
#define A2XX_SQ_TEX_3_XY_MIN_FILTER__MASK 0x00600000
#define A2XX_SQ_TEX_3_XY_MIN_FILTER__SHIFT 21
static inline uint32_t A2XX_SQ_TEX_3_XY_MIN_FILTER(enum sq_tex_filter val)
{
return ((val) << A2XX_SQ_TEX_3_XY_MIN_FILTER__SHIFT) & A2XX_SQ_TEX_3_XY_MIN_FILTER__MASK;
}
 
 
#endif /* A2XX_XML */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a2xx/disasm-a2xx.c
0,0 → 1,632
/*
* Copyright (c) 2012 Rob Clark <robdclark@gmail.com>
*
* 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 <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
 
#include "disasm.h"
#include "instr-a2xx.h"
 
static const char *levels[] = {
"\t",
"\t\t",
"\t\t\t",
"\t\t\t\t",
"\t\t\t\t\t",
"\t\t\t\t\t\t",
"\t\t\t\t\t\t\t",
"\t\t\t\t\t\t\t\t",
"\t\t\t\t\t\t\t\t\t",
"x",
"x",
"x",
"x",
"x",
"x",
};
 
static enum debug_t debug;
 
/*
* ALU instructions:
*/
 
static const char chan_names[] = {
'x', 'y', 'z', 'w',
/* these only apply to FETCH dst's: */
'0', '1', '?', '_',
};
 
static void print_srcreg(uint32_t num, uint32_t type,
uint32_t swiz, uint32_t negate, uint32_t abs)
{
if (negate)
printf("-");
if (abs)
printf("|");
printf("%c%u", type ? 'R' : 'C', num);
if (swiz) {
int i;
printf(".");
for (i = 0; i < 4; i++) {
printf("%c", chan_names[(swiz + i) & 0x3]);
swiz >>= 2;
}
}
if (abs)
printf("|");
}
 
static void print_dstreg(uint32_t num, uint32_t mask, uint32_t dst_exp)
{
printf("%s%u", dst_exp ? "export" : "R", num);
if (mask != 0xf) {
int i;
printf(".");
for (i = 0; i < 4; i++) {
printf("%c", (mask & 0x1) ? chan_names[i] : '_');
mask >>= 1;
}
}
}
 
static void print_export_comment(uint32_t num, enum shader_t type)
{
const char *name = NULL;
switch (type) {
case SHADER_VERTEX:
switch (num) {
case 62: name = "gl_Position"; break;
case 63: name = "gl_PointSize"; break;
}
break;
case SHADER_FRAGMENT:
switch (num) {
case 0: name = "gl_FragColor"; break;
}
break;
}
/* if we had a symbol table here, we could look
* up the name of the varying..
*/
if (name) {
printf("\t; %s", name);
}
}
 
struct {
uint32_t num_srcs;
const char *name;
} vector_instructions[0x20] = {
#define INSTR(opc, num_srcs) [opc] = { num_srcs, #opc }
INSTR(ADDv, 2),
INSTR(MULv, 2),
INSTR(MAXv, 2),
INSTR(MINv, 2),
INSTR(SETEv, 2),
INSTR(SETGTv, 2),
INSTR(SETGTEv, 2),
INSTR(SETNEv, 2),
INSTR(FRACv, 1),
INSTR(TRUNCv, 1),
INSTR(FLOORv, 1),
INSTR(MULADDv, 3),
INSTR(CNDEv, 3),
INSTR(CNDGTEv, 3),
INSTR(CNDGTv, 3),
INSTR(DOT4v, 2),
INSTR(DOT3v, 2),
INSTR(DOT2ADDv, 3), // ???
INSTR(CUBEv, 2),
INSTR(MAX4v, 1),
INSTR(PRED_SETE_PUSHv, 2),
INSTR(PRED_SETNE_PUSHv, 2),
INSTR(PRED_SETGT_PUSHv, 2),
INSTR(PRED_SETGTE_PUSHv, 2),
INSTR(KILLEv, 2),
INSTR(KILLGTv, 2),
INSTR(KILLGTEv, 2),
INSTR(KILLNEv, 2),
INSTR(DSTv, 2),
INSTR(MOVAv, 1),
}, scalar_instructions[0x40] = {
INSTR(ADDs, 1),
INSTR(ADD_PREVs, 1),
INSTR(MULs, 1),
INSTR(MUL_PREVs, 1),
INSTR(MUL_PREV2s, 1),
INSTR(MAXs, 1),
INSTR(MINs, 1),
INSTR(SETEs, 1),
INSTR(SETGTs, 1),
INSTR(SETGTEs, 1),
INSTR(SETNEs, 1),
INSTR(FRACs, 1),
INSTR(TRUNCs, 1),
INSTR(FLOORs, 1),
INSTR(EXP_IEEE, 1),
INSTR(LOG_CLAMP, 1),
INSTR(LOG_IEEE, 1),
INSTR(RECIP_CLAMP, 1),
INSTR(RECIP_FF, 1),
INSTR(RECIP_IEEE, 1),
INSTR(RECIPSQ_CLAMP, 1),
INSTR(RECIPSQ_FF, 1),
INSTR(RECIPSQ_IEEE, 1),
INSTR(MOVAs, 1),
INSTR(MOVA_FLOORs, 1),
INSTR(SUBs, 1),
INSTR(SUB_PREVs, 1),
INSTR(PRED_SETEs, 1),
INSTR(PRED_SETNEs, 1),
INSTR(PRED_SETGTs, 1),
INSTR(PRED_SETGTEs, 1),
INSTR(PRED_SET_INVs, 1),
INSTR(PRED_SET_POPs, 1),
INSTR(PRED_SET_CLRs, 1),
INSTR(PRED_SET_RESTOREs, 1),
INSTR(KILLEs, 1),
INSTR(KILLGTs, 1),
INSTR(KILLGTEs, 1),
INSTR(KILLNEs, 1),
INSTR(KILLONEs, 1),
INSTR(SQRT_IEEE, 1),
INSTR(MUL_CONST_0, 1),
INSTR(MUL_CONST_1, 1),
INSTR(ADD_CONST_0, 1),
INSTR(ADD_CONST_1, 1),
INSTR(SUB_CONST_0, 1),
INSTR(SUB_CONST_1, 1),
INSTR(SIN, 1),
INSTR(COS, 1),
INSTR(RETAIN_PREV, 1),
#undef INSTR
};
 
static int disasm_alu(uint32_t *dwords, uint32_t alu_off,
int level, int sync, enum shader_t type)
{
instr_alu_t *alu = (instr_alu_t *)dwords;
 
printf("%s", levels[level]);
if (debug & PRINT_RAW) {
printf("%02x: %08x %08x %08x\t", alu_off,
dwords[0], dwords[1], dwords[2]);
}
 
printf(" %sALU:\t", sync ? "(S)" : " ");
 
printf("%s", vector_instructions[alu->vector_opc].name);
 
if (alu->pred_select & 0x2) {
/* seems to work similar to conditional execution in ARM instruction
* set, so let's use a similar syntax for now:
*/
printf((alu->pred_select & 0x1) ? "EQ" : "NE");
}
 
printf("\t");
 
print_dstreg(alu->vector_dest, alu->vector_write_mask, alu->export_data);
printf(" = ");
if (vector_instructions[alu->vector_opc].num_srcs == 3) {
print_srcreg(alu->src3_reg, alu->src3_sel, alu->src3_swiz,
alu->src3_reg_negate, alu->src3_reg_abs);
printf(", ");
}
print_srcreg(alu->src1_reg, alu->src1_sel, alu->src1_swiz,
alu->src1_reg_negate, alu->src1_reg_abs);
if (vector_instructions[alu->vector_opc].num_srcs > 1) {
printf(", ");
print_srcreg(alu->src2_reg, alu->src2_sel, alu->src2_swiz,
alu->src2_reg_negate, alu->src2_reg_abs);
}
 
if (alu->vector_clamp)
printf(" CLAMP");
 
if (alu->export_data)
print_export_comment(alu->vector_dest, type);
 
printf("\n");
 
if (alu->scalar_write_mask || !alu->vector_write_mask) {
/* 2nd optional scalar op: */
 
printf("%s", levels[level]);
if (debug & PRINT_RAW)
printf(" \t");
 
if (scalar_instructions[alu->scalar_opc].name) {
printf("\t \t%s\t", scalar_instructions[alu->scalar_opc].name);
} else {
printf("\t \tOP(%u)\t", alu->scalar_opc);
}
 
print_dstreg(alu->scalar_dest, alu->scalar_write_mask, alu->export_data);
printf(" = ");
print_srcreg(alu->src3_reg, alu->src3_sel, alu->src3_swiz,
alu->src3_reg_negate, alu->src3_reg_abs);
// TODO ADD/MUL must have another src?!?
if (alu->scalar_clamp)
printf(" CLAMP");
if (alu->export_data)
print_export_comment(alu->scalar_dest, type);
printf("\n");
}
 
return 0;
}
 
 
/*
* FETCH instructions:
*/
 
struct {
const char *name;
} fetch_types[0xff] = {
#define TYPE(id) [id] = { #id }
TYPE(FMT_1_REVERSE),
TYPE(FMT_32_FLOAT),
TYPE(FMT_32_32_FLOAT),
TYPE(FMT_32_32_32_FLOAT),
TYPE(FMT_32_32_32_32_FLOAT),
TYPE(FMT_16),
TYPE(FMT_16_16),
TYPE(FMT_16_16_16_16),
TYPE(FMT_8),
TYPE(FMT_8_8),
TYPE(FMT_8_8_8_8),
TYPE(FMT_32),
TYPE(FMT_32_32),
TYPE(FMT_32_32_32_32),
#undef TYPE
};
 
static void print_fetch_dst(uint32_t dst_reg, uint32_t dst_swiz)
{
int i;
printf("\tR%u.", dst_reg);
for (i = 0; i < 4; i++) {
printf("%c", chan_names[dst_swiz & 0x7]);
dst_swiz >>= 3;
}
}
 
static void print_fetch_vtx(instr_fetch_t *fetch)
{
instr_fetch_vtx_t *vtx = &fetch->vtx;
 
if (vtx->pred_select) {
/* seems to work similar to conditional execution in ARM instruction
* set, so let's use a similar syntax for now:
*/
printf(vtx->pred_condition ? "EQ" : "NE");
}
 
print_fetch_dst(vtx->dst_reg, vtx->dst_swiz);
printf(" = R%u.", vtx->src_reg);
printf("%c", chan_names[vtx->src_swiz & 0x3]);
if (fetch_types[vtx->format].name) {
printf(" %s", fetch_types[vtx->format].name);
} else {
printf(" TYPE(0x%x)", vtx->format);
}
printf(" %s", vtx->format_comp_all ? "SIGNED" : "UNSIGNED");
if (!vtx->num_format_all)
printf(" NORMALIZED");
printf(" STRIDE(%u)", vtx->stride);
if (vtx->offset)
printf(" OFFSET(%u)", vtx->offset);
printf(" CONST(%u, %u)", vtx->const_index, vtx->const_index_sel);
if (0) {
// XXX
printf(" src_reg_am=%u", vtx->src_reg_am);
printf(" dst_reg_am=%u", vtx->dst_reg_am);
printf(" num_format_all=%u", vtx->num_format_all);
printf(" signed_rf_mode_all=%u", vtx->signed_rf_mode_all);
printf(" exp_adjust_all=%u", vtx->exp_adjust_all);
}
}
 
static void print_fetch_tex(instr_fetch_t *fetch)
{
static const char *filter[] = {
[TEX_FILTER_POINT] = "POINT",
[TEX_FILTER_LINEAR] = "LINEAR",
[TEX_FILTER_BASEMAP] = "BASEMAP",
};
static const char *aniso_filter[] = {
[ANISO_FILTER_DISABLED] = "DISABLED",
[ANISO_FILTER_MAX_1_1] = "MAX_1_1",
[ANISO_FILTER_MAX_2_1] = "MAX_2_1",
[ANISO_FILTER_MAX_4_1] = "MAX_4_1",
[ANISO_FILTER_MAX_8_1] = "MAX_8_1",
[ANISO_FILTER_MAX_16_1] = "MAX_16_1",
};
static const char *arbitrary_filter[] = {
[ARBITRARY_FILTER_2X4_SYM] = "2x4_SYM",
[ARBITRARY_FILTER_2X4_ASYM] = "2x4_ASYM",
[ARBITRARY_FILTER_4X2_SYM] = "4x2_SYM",
[ARBITRARY_FILTER_4X2_ASYM] = "4x2_ASYM",
[ARBITRARY_FILTER_4X4_SYM] = "4x4_SYM",
[ARBITRARY_FILTER_4X4_ASYM] = "4x4_ASYM",
};
static const char *sample_loc[] = {
[SAMPLE_CENTROID] = "CENTROID",
[SAMPLE_CENTER] = "CENTER",
};
instr_fetch_tex_t *tex = &fetch->tex;
uint32_t src_swiz = tex->src_swiz;
int i;
 
if (tex->pred_select) {
/* seems to work similar to conditional execution in ARM instruction
* set, so let's use a similar syntax for now:
*/
printf(tex->pred_condition ? "EQ" : "NE");
}
 
print_fetch_dst(tex->dst_reg, tex->dst_swiz);
printf(" = R%u.", tex->src_reg);
for (i = 0; i < 3; i++) {
printf("%c", chan_names[src_swiz & 0x3]);
src_swiz >>= 2;
}
printf(" CONST(%u)", tex->const_idx);
if (tex->fetch_valid_only)
printf(" VALID_ONLY");
if (tex->tx_coord_denorm)
printf(" DENORM");
if (tex->mag_filter != TEX_FILTER_USE_FETCH_CONST)
printf(" MAG(%s)", filter[tex->mag_filter]);
if (tex->min_filter != TEX_FILTER_USE_FETCH_CONST)
printf(" MIN(%s)", filter[tex->min_filter]);
if (tex->mip_filter != TEX_FILTER_USE_FETCH_CONST)
printf(" MIP(%s)", filter[tex->mip_filter]);
if (tex->aniso_filter != ANISO_FILTER_USE_FETCH_CONST)
printf(" ANISO(%s)", aniso_filter[tex->aniso_filter]);
if (tex->arbitrary_filter != ARBITRARY_FILTER_USE_FETCH_CONST)
printf(" ARBITRARY(%s)", arbitrary_filter[tex->arbitrary_filter]);
if (tex->vol_mag_filter != TEX_FILTER_USE_FETCH_CONST)
printf(" VOL_MAG(%s)", filter[tex->vol_mag_filter]);
if (tex->vol_min_filter != TEX_FILTER_USE_FETCH_CONST)
printf(" VOL_MIN(%s)", filter[tex->vol_min_filter]);
if (!tex->use_comp_lod) {
printf(" LOD(%u)", tex->use_comp_lod);
printf(" LOD_BIAS(%u)", tex->lod_bias);
}
if (tex->use_reg_gradients)
printf(" USE_REG_GRADIENTS");
printf(" LOCATION(%s)", sample_loc[tex->sample_location]);
if (tex->offset_x || tex->offset_y || tex->offset_z)
printf(" OFFSET(%u,%u,%u)", tex->offset_x, tex->offset_y, tex->offset_z);
}
 
struct {
const char *name;
void (*fxn)(instr_fetch_t *cf);
} fetch_instructions[] = {
#define INSTR(opc, name, fxn) [opc] = { name, fxn }
INSTR(VTX_FETCH, "VERTEX", print_fetch_vtx),
INSTR(TEX_FETCH, "SAMPLE", print_fetch_tex),
INSTR(TEX_GET_BORDER_COLOR_FRAC, "?", print_fetch_tex),
INSTR(TEX_GET_COMP_TEX_LOD, "?", print_fetch_tex),
INSTR(TEX_GET_GRADIENTS, "?", print_fetch_tex),
INSTR(TEX_GET_WEIGHTS, "?", print_fetch_tex),
INSTR(TEX_SET_TEX_LOD, "SET_TEX_LOD", print_fetch_tex),
INSTR(TEX_SET_GRADIENTS_H, "?", print_fetch_tex),
INSTR(TEX_SET_GRADIENTS_V, "?", print_fetch_tex),
INSTR(TEX_RESERVED_4, "?", print_fetch_tex),
#undef INSTR
};
 
static int disasm_fetch(uint32_t *dwords, uint32_t alu_off, int level, int sync)
{
instr_fetch_t *fetch = (instr_fetch_t *)dwords;
 
printf("%s", levels[level]);
if (debug & PRINT_RAW) {
printf("%02x: %08x %08x %08x\t", alu_off,
dwords[0], dwords[1], dwords[2]);
}
 
printf(" %sFETCH:\t", sync ? "(S)" : " ");
printf("%s", fetch_instructions[fetch->opc].name);
fetch_instructions[fetch->opc].fxn(fetch);
printf("\n");
 
return 0;
}
 
/*
* CF instructions:
*/
 
static int cf_exec(instr_cf_t *cf)
{
return (cf->opc == EXEC) ||
(cf->opc == EXEC_END) ||
(cf->opc == COND_EXEC) ||
(cf->opc == COND_EXEC_END) ||
(cf->opc == COND_PRED_EXEC) ||
(cf->opc == COND_PRED_EXEC_END) ||
(cf->opc == COND_EXEC_PRED_CLEAN) ||
(cf->opc == COND_EXEC_PRED_CLEAN_END);
}
 
static int cf_cond_exec(instr_cf_t *cf)
{
return (cf->opc == COND_EXEC) ||
(cf->opc == COND_EXEC_END) ||
(cf->opc == COND_PRED_EXEC) ||
(cf->opc == COND_PRED_EXEC_END) ||
(cf->opc == COND_EXEC_PRED_CLEAN) ||
(cf->opc == COND_EXEC_PRED_CLEAN_END);
}
 
static void print_cf_nop(instr_cf_t *cf)
{
}
 
static void print_cf_exec(instr_cf_t *cf)
{
printf(" ADDR(0x%x) CNT(0x%x)", cf->exec.address, cf->exec.count);
if (cf->exec.yeild)
printf(" YIELD");
if (cf->exec.vc)
printf(" VC(0x%x)", cf->exec.vc);
if (cf->exec.bool_addr)
printf(" BOOL_ADDR(0x%x)", cf->exec.bool_addr);
if (cf->exec.address_mode == ABSOLUTE_ADDR)
printf(" ABSOLUTE_ADDR");
if (cf_cond_exec(cf))
printf(" COND(%d)", cf->exec.condition);
}
 
static void print_cf_loop(instr_cf_t *cf)
{
printf(" ADDR(0x%x) LOOP_ID(%d)", cf->loop.address, cf->loop.loop_id);
if (cf->loop.address_mode == ABSOLUTE_ADDR)
printf(" ABSOLUTE_ADDR");
}
 
static void print_cf_jmp_call(instr_cf_t *cf)
{
printf(" ADDR(0x%x) DIR(%d)", cf->jmp_call.address, cf->jmp_call.direction);
if (cf->jmp_call.force_call)
printf(" FORCE_CALL");
if (cf->jmp_call.predicated_jmp)
printf(" COND(%d)", cf->jmp_call.condition);
if (cf->jmp_call.bool_addr)
printf(" BOOL_ADDR(0x%x)", cf->jmp_call.bool_addr);
if (cf->jmp_call.address_mode == ABSOLUTE_ADDR)
printf(" ABSOLUTE_ADDR");
}
 
static void print_cf_alloc(instr_cf_t *cf)
{
static const char *bufname[] = {
[SQ_NO_ALLOC] = "NO ALLOC",
[SQ_POSITION] = "POSITION",
[SQ_PARAMETER_PIXEL] = "PARAM/PIXEL",
[SQ_MEMORY] = "MEMORY",
};
printf(" %s SIZE(0x%x)", bufname[cf->alloc.buffer_select], cf->alloc.size);
if (cf->alloc.no_serial)
printf(" NO_SERIAL");
if (cf->alloc.alloc_mode) // ???
printf(" ALLOC_MODE");
}
 
struct {
const char *name;
void (*fxn)(instr_cf_t *cf);
} cf_instructions[] = {
#define INSTR(opc, fxn) [opc] = { #opc, fxn }
INSTR(NOP, print_cf_nop),
INSTR(EXEC, print_cf_exec),
INSTR(EXEC_END, print_cf_exec),
INSTR(COND_EXEC, print_cf_exec),
INSTR(COND_EXEC_END, print_cf_exec),
INSTR(COND_PRED_EXEC, print_cf_exec),
INSTR(COND_PRED_EXEC_END, print_cf_exec),
INSTR(LOOP_START, print_cf_loop),
INSTR(LOOP_END, print_cf_loop),
INSTR(COND_CALL, print_cf_jmp_call),
INSTR(RETURN, print_cf_jmp_call),
INSTR(COND_JMP, print_cf_jmp_call),
INSTR(ALLOC, print_cf_alloc),
INSTR(COND_EXEC_PRED_CLEAN, print_cf_exec),
INSTR(COND_EXEC_PRED_CLEAN_END, print_cf_exec),
INSTR(MARK_VS_FETCH_DONE, print_cf_nop), // ??
#undef INSTR
};
 
static void print_cf(instr_cf_t *cf, int level)
{
printf("%s", levels[level]);
if (debug & PRINT_RAW) {
uint16_t *words = (uint16_t *)cf;
printf(" %04x %04x %04x \t",
words[0], words[1], words[2]);
}
printf("%s", cf_instructions[cf->opc].name);
cf_instructions[cf->opc].fxn(cf);
printf("\n");
}
 
/*
* The adreno shader microcode consists of two parts:
* 1) A CF (control-flow) program, at the header of the compiled shader,
* which refers to ALU/FETCH instructions that follow it by address.
* 2) ALU and FETCH instructions
*/
 
int disasm_a2xx(uint32_t *dwords, int sizedwords, int level, enum shader_t type)
{
instr_cf_t *cfs = (instr_cf_t *)dwords;
int idx, max_idx;
 
for (idx = 0; ; idx++) {
instr_cf_t *cf = &cfs[idx];
if (cf_exec(cf)) {
max_idx = 2 * cf->exec.address;
break;
}
}
 
for (idx = 0; idx < max_idx; idx++) {
instr_cf_t *cf = &cfs[idx];
 
print_cf(cf, level);
 
if (cf_exec(cf)) {
uint32_t sequence = cf->exec.serialize;
uint32_t i;
for (i = 0; i < cf->exec.count; i++) {
uint32_t alu_off = (cf->exec.address + i);
if (sequence & 0x1) {
disasm_fetch(dwords + alu_off * 3, alu_off, level, sequence & 0x2);
} else {
disasm_alu(dwords + alu_off * 3, alu_off, level, sequence & 0x2, type);
}
sequence >>= 2;
}
}
}
 
return 0;
}
 
void disasm_set_debug(enum debug_t d)
{
debug = d;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a2xx/fd2_blend.c
0,0 → 1,107
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2012-2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "pipe/p_state.h"
#include "util/u_string.h"
#include "util/u_memory.h"
 
#include "fd2_blend.h"
#include "fd2_context.h"
#include "fd2_util.h"
 
 
static enum a2xx_rb_blend_opcode
blend_func(unsigned func)
{
switch (func) {
case PIPE_BLEND_ADD:
return BLEND_DST_PLUS_SRC;
case PIPE_BLEND_MIN:
return BLEND_MIN_DST_SRC;
case PIPE_BLEND_MAX:
return BLEND_MAX_DST_SRC;
case PIPE_BLEND_SUBTRACT:
return BLEND_SRC_MINUS_DST;
case PIPE_BLEND_REVERSE_SUBTRACT:
return BLEND_DST_MINUS_SRC;
default:
DBG("invalid blend func: %x", func);
return 0;
}
}
 
void *
fd2_blend_state_create(struct pipe_context *pctx,
const struct pipe_blend_state *cso)
{
const struct pipe_rt_blend_state *rt = &cso->rt[0];
struct fd2_blend_stateobj *so;
 
if (cso->logicop_enable) {
DBG("Unsupported! logicop");
return NULL;
}
 
if (cso->independent_blend_enable) {
DBG("Unsupported! independent blend state");
return NULL;
}
 
so = CALLOC_STRUCT(fd2_blend_stateobj);
if (!so)
return NULL;
 
so->base = *cso;
 
so->rb_colorcontrol = A2XX_RB_COLORCONTROL_ROP_CODE(12);
 
so->rb_blendcontrol =
A2XX_RB_BLEND_CONTROL_COLOR_SRCBLEND(fd_blend_factor(rt->rgb_src_factor)) |
A2XX_RB_BLEND_CONTROL_COLOR_COMB_FCN(blend_func(rt->rgb_func)) |
A2XX_RB_BLEND_CONTROL_COLOR_DESTBLEND(fd_blend_factor(rt->rgb_dst_factor)) |
A2XX_RB_BLEND_CONTROL_ALPHA_SRCBLEND(fd_blend_factor(rt->alpha_src_factor)) |
A2XX_RB_BLEND_CONTROL_ALPHA_COMB_FCN(blend_func(rt->alpha_func)) |
A2XX_RB_BLEND_CONTROL_ALPHA_DESTBLEND(fd_blend_factor(rt->alpha_dst_factor));
 
if (rt->colormask & PIPE_MASK_R)
so->rb_colormask |= A2XX_RB_COLOR_MASK_WRITE_RED;
if (rt->colormask & PIPE_MASK_G)
so->rb_colormask |= A2XX_RB_COLOR_MASK_WRITE_GREEN;
if (rt->colormask & PIPE_MASK_B)
so->rb_colormask |= A2XX_RB_COLOR_MASK_WRITE_BLUE;
if (rt->colormask & PIPE_MASK_A)
so->rb_colormask |= A2XX_RB_COLOR_MASK_WRITE_ALPHA;
 
if (!rt->blend_enable)
so->rb_colorcontrol |= A2XX_RB_COLORCONTROL_BLEND_DISABLE;
 
if (cso->dither)
so->rb_colorcontrol |= A2XX_RB_COLORCONTROL_DITHER_MODE(DITHER_ALWAYS);
 
return so;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a2xx/fd2_blend.h
0,0 → 1,51
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2012-2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FD2_BLEND_H_
#define FD2_BLEND_H_
 
#include "pipe/p_state.h"
#include "pipe/p_context.h"
 
struct fd2_blend_stateobj {
struct pipe_blend_state base;
uint32_t rb_blendcontrol;
uint32_t rb_colorcontrol; /* must be OR'd w/ zsa->rb_colorcontrol */
uint32_t rb_colormask;
};
 
static INLINE struct fd2_blend_stateobj *
fd2_blend_stateobj(struct pipe_blend_state *blend)
{
return (struct fd2_blend_stateobj *)blend;
}
 
void * fd2_blend_state_create(struct pipe_context *pctx,
const struct pipe_blend_state *cso);
 
#endif /* FD2_BLEND_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a2xx/fd2_compiler.c
0,0 → 1,1195
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "pipe/p_state.h"
#include "util/u_string.h"
#include "util/u_memory.h"
#include "util/u_inlines.h"
#include "tgsi/tgsi_parse.h"
#include "tgsi/tgsi_ureg.h"
#include "tgsi/tgsi_info.h"
#include "tgsi/tgsi_strings.h"
#include "tgsi/tgsi_dump.h"
 
#include "fd2_compiler.h"
#include "fd2_program.h"
#include "fd2_util.h"
 
#include "instr-a2xx.h"
#include "ir-a2xx.h"
 
struct fd2_compile_context {
struct fd_program_stateobj *prog;
struct fd2_shader_stateobj *so;
 
struct tgsi_parse_context parser;
unsigned type;
 
/* predicate stack: */
int pred_depth;
enum ir2_pred pred_stack[8];
 
/* Internal-Temporary and Predicate register assignment:
*
* Some TGSI instructions which translate into multiple actual
* instructions need one or more temporary registers, which are not
* assigned from TGSI perspective (ie. not TGSI_FILE_TEMPORARY).
* And some instructions (texture fetch) cannot write directly to
* output registers. We could be more clever and re-use dst or a
* src register in some cases. But for now don't try to be clever.
* Eventually we should implement an optimization pass that re-
* juggles the register usage and gets rid of unneeded temporaries.
*
* The predicate register must be valid across multiple TGSI
* instructions, but internal temporary's do not. For this reason,
* once the predicate register is requested, until it is no longer
* needed, it gets the first register slot after after the TGSI
* assigned temporaries (ie. num_regs[TGSI_FILE_TEMPORARY]), and the
* internal temporaries get the register slots above this.
*/
 
int pred_reg;
int num_internal_temps;
 
uint8_t num_regs[TGSI_FILE_COUNT];
 
/* maps input register idx to prog->export_linkage idx: */
uint8_t input_export_idx[64];
 
/* maps output register idx to prog->export_linkage idx: */
uint8_t output_export_idx[64];
 
/* idx/slot for last compiler generated immediate */
unsigned immediate_idx;
 
// TODO we can skip emit exports in the VS that the FS doesn't need..
// and get rid perhaps of num_param..
unsigned num_position, num_param;
unsigned position, psize;
 
uint64_t need_sync;
 
/* current exec CF instruction */
struct ir2_cf *cf;
};
 
static int
semantic_idx(struct tgsi_declaration_semantic *semantic)
{
int idx = semantic->Name;
if (idx == TGSI_SEMANTIC_GENERIC)
idx = TGSI_SEMANTIC_COUNT + semantic->Index;
return idx;
}
 
/* assign/get the input/export register # for given semantic idx as
* returned by semantic_idx():
*/
static int
export_linkage(struct fd2_compile_context *ctx, int idx)
{
struct fd_program_stateobj *prog = ctx->prog;
 
/* if first time we've seen this export, assign the next available slot: */
if (prog->export_linkage[idx] == 0xff)
prog->export_linkage[idx] = prog->num_exports++;
 
return prog->export_linkage[idx];
}
 
static unsigned
compile_init(struct fd2_compile_context *ctx, struct fd_program_stateobj *prog,
struct fd2_shader_stateobj *so)
{
unsigned ret;
 
ctx->prog = prog;
ctx->so = so;
ctx->cf = NULL;
ctx->pred_depth = 0;
 
ret = tgsi_parse_init(&ctx->parser, so->tokens);
if (ret != TGSI_PARSE_OK)
return ret;
 
ctx->type = ctx->parser.FullHeader.Processor.Processor;
ctx->position = ~0;
ctx->psize = ~0;
ctx->num_position = 0;
ctx->num_param = 0;
ctx->need_sync = 0;
ctx->immediate_idx = 0;
ctx->pred_reg = -1;
ctx->num_internal_temps = 0;
 
memset(ctx->num_regs, 0, sizeof(ctx->num_regs));
memset(ctx->input_export_idx, 0, sizeof(ctx->input_export_idx));
memset(ctx->output_export_idx, 0, sizeof(ctx->output_export_idx));
 
/* do first pass to extract declarations: */
while (!tgsi_parse_end_of_tokens(&ctx->parser)) {
tgsi_parse_token(&ctx->parser);
 
switch (ctx->parser.FullToken.Token.Type) {
case TGSI_TOKEN_TYPE_DECLARATION: {
struct tgsi_full_declaration *decl =
&ctx->parser.FullToken.FullDeclaration;
if (decl->Declaration.File == TGSI_FILE_OUTPUT) {
unsigned name = decl->Semantic.Name;
 
assert(decl->Declaration.Semantic); // TODO is this ever not true?
 
ctx->output_export_idx[decl->Range.First] =
semantic_idx(&decl->Semantic);
 
if (ctx->type == TGSI_PROCESSOR_VERTEX) {
switch (name) {
case TGSI_SEMANTIC_POSITION:
ctx->position = ctx->num_regs[TGSI_FILE_OUTPUT];
ctx->num_position++;
break;
case TGSI_SEMANTIC_PSIZE:
ctx->psize = ctx->num_regs[TGSI_FILE_OUTPUT];
ctx->num_position++;
break;
case TGSI_SEMANTIC_COLOR:
case TGSI_SEMANTIC_GENERIC:
ctx->num_param++;
break;
default:
DBG("unknown VS semantic name: %s",
tgsi_semantic_names[name]);
assert(0);
}
} else {
switch (name) {
case TGSI_SEMANTIC_COLOR:
case TGSI_SEMANTIC_GENERIC:
ctx->num_param++;
break;
default:
DBG("unknown PS semantic name: %s",
tgsi_semantic_names[name]);
assert(0);
}
}
} else if (decl->Declaration.File == TGSI_FILE_INPUT) {
ctx->input_export_idx[decl->Range.First] =
semantic_idx(&decl->Semantic);
}
ctx->num_regs[decl->Declaration.File] =
MAX2(ctx->num_regs[decl->Declaration.File], decl->Range.Last + 1);
break;
}
case TGSI_TOKEN_TYPE_IMMEDIATE: {
struct tgsi_full_immediate *imm =
&ctx->parser.FullToken.FullImmediate;
unsigned n = ctx->so->num_immediates++;
memcpy(ctx->so->immediates[n].val, imm->u, 16);
break;
}
default:
break;
}
}
 
/* TGSI generated immediates are always entire vec4's, ones we
* generate internally are not:
*/
ctx->immediate_idx = ctx->so->num_immediates * 4;
 
ctx->so->first_immediate = ctx->num_regs[TGSI_FILE_CONSTANT];
 
tgsi_parse_free(&ctx->parser);
 
return tgsi_parse_init(&ctx->parser, so->tokens);
}
 
static void
compile_free(struct fd2_compile_context *ctx)
{
tgsi_parse_free(&ctx->parser);
}
 
static struct ir2_cf *
next_exec_cf(struct fd2_compile_context *ctx)
{
struct ir2_cf *cf = ctx->cf;
if (!cf || cf->exec.instrs_count >= ARRAY_SIZE(ctx->cf->exec.instrs))
ctx->cf = cf = ir2_cf_create(ctx->so->ir, EXEC);
return cf;
}
 
static void
compile_vtx_fetch(struct fd2_compile_context *ctx)
{
struct ir2_instruction **vfetch_instrs = ctx->so->vfetch_instrs;
int i;
for (i = 0; i < ctx->num_regs[TGSI_FILE_INPUT]; i++) {
struct ir2_instruction *instr = ir2_instr_create(
next_exec_cf(ctx), IR2_FETCH);
instr->fetch.opc = VTX_FETCH;
 
ctx->need_sync |= 1 << (i+1);
 
ir2_reg_create(instr, i+1, "xyzw", 0);
ir2_reg_create(instr, 0, "x", 0);
 
if (i == 0)
instr->sync = true;
 
vfetch_instrs[i] = instr;
}
ctx->so->num_vfetch_instrs = i;
ctx->cf = NULL;
}
 
/*
* For vertex shaders (VS):
* --- ------ -------------
*
* Inputs: R1-R(num_input)
* Constants: C0-C(num_const-1)
* Immediates: C(num_const)-C(num_const+num_imm-1)
* Outputs: export0-export(n) and export62, export63
* n is # of outputs minus gl_Position (export62) and gl_PointSize (export63)
* Temps: R(num_input+1)-R(num_input+num_temps)
*
* R0 could be clobbered after the vertex fetch instructions.. so we
* could use it for one of the temporaries.
*
* TODO: maybe the vertex fetch part could fetch first input into R0 as
* the last vtx fetch instruction, which would let us use the same
* register layout in either case.. although this is not what the blob
* compiler does.
*
*
* For frag shaders (PS):
* --- ---- -------------
*
* Inputs: R0-R(num_input-1)
* Constants: same as VS
* Immediates: same as VS
* Outputs: export0-export(num_outputs)
* Temps: R(num_input)-R(num_input+num_temps-1)
*
* In either case, immediates are are postpended to the constants
* (uniforms).
*
*/
 
static unsigned
get_temp_gpr(struct fd2_compile_context *ctx, int idx)
{
unsigned num = idx + ctx->num_regs[TGSI_FILE_INPUT];
if (ctx->type == TGSI_PROCESSOR_VERTEX)
num++;
return num;
}
 
static struct ir2_register *
add_dst_reg(struct fd2_compile_context *ctx, struct ir2_instruction *alu,
const struct tgsi_dst_register *dst)
{
unsigned flags = 0, num = 0;
char swiz[5];
 
switch (dst->File) {
case TGSI_FILE_OUTPUT:
flags |= IR2_REG_EXPORT;
if (ctx->type == TGSI_PROCESSOR_VERTEX) {
if (dst->Index == ctx->position) {
num = 62;
} else if (dst->Index == ctx->psize) {
num = 63;
} else {
num = export_linkage(ctx,
ctx->output_export_idx[dst->Index]);
}
} else {
num = dst->Index;
}
break;
case TGSI_FILE_TEMPORARY:
num = get_temp_gpr(ctx, dst->Index);
break;
default:
DBG("unsupported dst register file: %s",
tgsi_file_name(dst->File));
assert(0);
break;
}
 
swiz[0] = (dst->WriteMask & TGSI_WRITEMASK_X) ? 'x' : '_';
swiz[1] = (dst->WriteMask & TGSI_WRITEMASK_Y) ? 'y' : '_';
swiz[2] = (dst->WriteMask & TGSI_WRITEMASK_Z) ? 'z' : '_';
swiz[3] = (dst->WriteMask & TGSI_WRITEMASK_W) ? 'w' : '_';
swiz[4] = '\0';
 
return ir2_reg_create(alu, num, swiz, flags);
}
 
static struct ir2_register *
add_src_reg(struct fd2_compile_context *ctx, struct ir2_instruction *alu,
const struct tgsi_src_register *src)
{
static const char swiz_vals[] = {
'x', 'y', 'z', 'w',
};
char swiz[5];
unsigned flags = 0, num = 0;
 
switch (src->File) {
case TGSI_FILE_CONSTANT:
num = src->Index;
flags |= IR2_REG_CONST;
break;
case TGSI_FILE_INPUT:
if (ctx->type == TGSI_PROCESSOR_VERTEX) {
num = src->Index + 1;
} else {
num = export_linkage(ctx,
ctx->input_export_idx[src->Index]);
}
break;
case TGSI_FILE_TEMPORARY:
num = get_temp_gpr(ctx, src->Index);
break;
case TGSI_FILE_IMMEDIATE:
num = src->Index + ctx->num_regs[TGSI_FILE_CONSTANT];
flags |= IR2_REG_CONST;
break;
default:
DBG("unsupported src register file: %s",
tgsi_file_name(src->File));
assert(0);
break;
}
 
if (src->Absolute)
flags |= IR2_REG_ABS;
if (src->Negate)
flags |= IR2_REG_NEGATE;
 
swiz[0] = swiz_vals[src->SwizzleX];
swiz[1] = swiz_vals[src->SwizzleY];
swiz[2] = swiz_vals[src->SwizzleZ];
swiz[3] = swiz_vals[src->SwizzleW];
swiz[4] = '\0';
 
if ((ctx->need_sync & (uint64_t)(1 << num)) &&
!(flags & IR2_REG_CONST)) {
alu->sync = true;
ctx->need_sync &= ~(uint64_t)(1 << num);
}
 
return ir2_reg_create(alu, num, swiz, flags);
}
 
static void
add_vector_clamp(struct tgsi_full_instruction *inst, struct ir2_instruction *alu)
{
switch (inst->Instruction.Saturate) {
case TGSI_SAT_NONE:
break;
case TGSI_SAT_ZERO_ONE:
alu->alu.vector_clamp = true;
break;
case TGSI_SAT_MINUS_PLUS_ONE:
DBG("unsupported saturate");
assert(0);
break;
}
}
 
static void
add_scalar_clamp(struct tgsi_full_instruction *inst, struct ir2_instruction *alu)
{
switch (inst->Instruction.Saturate) {
case TGSI_SAT_NONE:
break;
case TGSI_SAT_ZERO_ONE:
alu->alu.scalar_clamp = true;
break;
case TGSI_SAT_MINUS_PLUS_ONE:
DBG("unsupported saturate");
assert(0);
break;
}
}
 
static void
add_regs_vector_1(struct fd2_compile_context *ctx,
struct tgsi_full_instruction *inst, struct ir2_instruction *alu)
{
assert(inst->Instruction.NumSrcRegs == 1);
assert(inst->Instruction.NumDstRegs == 1);
 
add_dst_reg(ctx, alu, &inst->Dst[0].Register);
add_src_reg(ctx, alu, &inst->Src[0].Register);
add_src_reg(ctx, alu, &inst->Src[0].Register);
add_vector_clamp(inst, alu);
}
 
static void
add_regs_vector_2(struct fd2_compile_context *ctx,
struct tgsi_full_instruction *inst, struct ir2_instruction *alu)
{
assert(inst->Instruction.NumSrcRegs == 2);
assert(inst->Instruction.NumDstRegs == 1);
 
add_dst_reg(ctx, alu, &inst->Dst[0].Register);
add_src_reg(ctx, alu, &inst->Src[0].Register);
add_src_reg(ctx, alu, &inst->Src[1].Register);
add_vector_clamp(inst, alu);
}
 
static void
add_regs_vector_3(struct fd2_compile_context *ctx,
struct tgsi_full_instruction *inst, struct ir2_instruction *alu)
{
assert(inst->Instruction.NumSrcRegs == 3);
assert(inst->Instruction.NumDstRegs == 1);
 
add_dst_reg(ctx, alu, &inst->Dst[0].Register);
/* maybe should re-arrange the syntax some day, but
* in assembler/disassembler and what ir.c expects
* is: MULADDv Rdst = Rsrc2 + Rsrc0 * Rscr1
*/
add_src_reg(ctx, alu, &inst->Src[2].Register);
add_src_reg(ctx, alu, &inst->Src[0].Register);
add_src_reg(ctx, alu, &inst->Src[1].Register);
add_vector_clamp(inst, alu);
}
 
static void
add_regs_dummy_vector(struct ir2_instruction *alu)
{
/* create dummy, non-written vector dst/src regs
* for unused vector instr slot:
*/
ir2_reg_create(alu, 0, "____", 0); /* vector dst */
ir2_reg_create(alu, 0, NULL, 0); /* vector src1 */
ir2_reg_create(alu, 0, NULL, 0); /* vector src2 */
}
 
static void
add_regs_scalar_1(struct fd2_compile_context *ctx,
struct tgsi_full_instruction *inst, struct ir2_instruction *alu)
{
assert(inst->Instruction.NumSrcRegs == 1);
assert(inst->Instruction.NumDstRegs == 1);
 
add_regs_dummy_vector(alu);
 
add_dst_reg(ctx, alu, &inst->Dst[0].Register);
add_src_reg(ctx, alu, &inst->Src[0].Register);
add_scalar_clamp(inst, alu);
}
 
/*
* Helpers for TGSI instructions that don't map to a single shader instr:
*/
 
static void
src_from_dst(struct tgsi_src_register *src, struct tgsi_dst_register *dst)
{
src->File = dst->File;
src->Indirect = dst->Indirect;
src->Dimension = dst->Dimension;
src->Index = dst->Index;
src->Absolute = 0;
src->Negate = 0;
src->SwizzleX = TGSI_SWIZZLE_X;
src->SwizzleY = TGSI_SWIZZLE_Y;
src->SwizzleZ = TGSI_SWIZZLE_Z;
src->SwizzleW = TGSI_SWIZZLE_W;
}
 
/* Get internal-temp src/dst to use for a sequence of instructions
* generated by a single TGSI op.
*/
static void
get_internal_temp(struct fd2_compile_context *ctx,
struct tgsi_dst_register *tmp_dst,
struct tgsi_src_register *tmp_src)
{
int n;
 
tmp_dst->File = TGSI_FILE_TEMPORARY;
tmp_dst->WriteMask = TGSI_WRITEMASK_XYZW;
tmp_dst->Indirect = 0;
tmp_dst->Dimension = 0;
 
/* assign next temporary: */
n = ctx->num_internal_temps++;
if (ctx->pred_reg != -1)
n++;
 
tmp_dst->Index = ctx->num_regs[TGSI_FILE_TEMPORARY] + n;
 
src_from_dst(tmp_src, tmp_dst);
}
 
static void
get_predicate(struct fd2_compile_context *ctx, struct tgsi_dst_register *dst,
struct tgsi_src_register *src)
{
assert(ctx->pred_reg != -1);
 
dst->File = TGSI_FILE_TEMPORARY;
dst->WriteMask = TGSI_WRITEMASK_W;
dst->Indirect = 0;
dst->Dimension = 0;
dst->Index = get_temp_gpr(ctx, ctx->pred_reg);
 
if (src) {
src_from_dst(src, dst);
src->SwizzleX = TGSI_SWIZZLE_W;
src->SwizzleY = TGSI_SWIZZLE_W;
src->SwizzleZ = TGSI_SWIZZLE_W;
src->SwizzleW = TGSI_SWIZZLE_W;
}
}
 
static void
push_predicate(struct fd2_compile_context *ctx, struct tgsi_src_register *src)
{
struct ir2_instruction *alu;
struct tgsi_dst_register pred_dst;
 
/* NOTE blob compiler seems to always puts PRED_* instrs in a CF by
* themselves:
*/
ctx->cf = NULL;
 
if (ctx->pred_depth == 0) {
/* assign predicate register: */
ctx->pred_reg = ctx->num_regs[TGSI_FILE_TEMPORARY];
 
get_predicate(ctx, &pred_dst, NULL);
 
alu = ir2_instr_create_alu(next_exec_cf(ctx), ~0, PRED_SETNEs);
add_regs_dummy_vector(alu);
add_dst_reg(ctx, alu, &pred_dst);
add_src_reg(ctx, alu, src);
} else {
struct tgsi_src_register pred_src;
 
get_predicate(ctx, &pred_dst, &pred_src);
 
alu = ir2_instr_create_alu(next_exec_cf(ctx), MULv, ~0);
add_dst_reg(ctx, alu, &pred_dst);
add_src_reg(ctx, alu, &pred_src);
add_src_reg(ctx, alu, src);
 
// XXX need to make PRED_SETE_PUSHv IR2_PRED_NONE.. but need to make
// sure src reg is valid if it was calculated with a predicate
// condition..
alu->pred = IR2_PRED_NONE;
}
 
/* save previous pred state to restore in pop_predicate(): */
ctx->pred_stack[ctx->pred_depth++] = ctx->so->ir->pred;
 
ctx->cf = NULL;
}
 
static void
pop_predicate(struct fd2_compile_context *ctx)
{
/* NOTE blob compiler seems to always puts PRED_* instrs in a CF by
* themselves:
*/
ctx->cf = NULL;
 
/* restore previous predicate state: */
ctx->so->ir->pred = ctx->pred_stack[--ctx->pred_depth];
 
if (ctx->pred_depth != 0) {
struct ir2_instruction *alu;
struct tgsi_dst_register pred_dst;
struct tgsi_src_register pred_src;
 
get_predicate(ctx, &pred_dst, &pred_src);
 
alu = ir2_instr_create_alu(next_exec_cf(ctx), ~0, PRED_SET_POPs);
add_regs_dummy_vector(alu);
add_dst_reg(ctx, alu, &pred_dst);
add_src_reg(ctx, alu, &pred_src);
alu->pred = IR2_PRED_NONE;
} else {
/* predicate register no longer needed: */
ctx->pred_reg = -1;
}
 
ctx->cf = NULL;
}
 
static void
get_immediate(struct fd2_compile_context *ctx,
struct tgsi_src_register *reg, uint32_t val)
{
unsigned neg, swiz, idx, i;
/* actually maps 1:1 currently.. not sure if that is safe to rely on: */
static const unsigned swiz2tgsi[] = {
TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y, TGSI_SWIZZLE_Z, TGSI_SWIZZLE_W,
};
 
for (i = 0; i < ctx->immediate_idx; i++) {
swiz = i % 4;
idx = i / 4;
 
if (ctx->so->immediates[idx].val[swiz] == val) {
neg = 0;
break;
}
 
if (ctx->so->immediates[idx].val[swiz] == -val) {
neg = 1;
break;
}
}
 
if (i == ctx->immediate_idx) {
/* need to generate a new immediate: */
swiz = i % 4;
idx = i / 4;
neg = 0;
ctx->so->immediates[idx].val[swiz] = val;
ctx->so->num_immediates = idx + 1;
ctx->immediate_idx++;
}
 
reg->File = TGSI_FILE_IMMEDIATE;
reg->Indirect = 0;
reg->Dimension = 0;
reg->Index = idx;
reg->Absolute = 0;
reg->Negate = neg;
reg->SwizzleX = swiz2tgsi[swiz];
reg->SwizzleY = swiz2tgsi[swiz];
reg->SwizzleZ = swiz2tgsi[swiz];
reg->SwizzleW = swiz2tgsi[swiz];
}
 
/* POW(a,b) = EXP2(b * LOG2(a)) */
static void
translate_pow(struct fd2_compile_context *ctx,
struct tgsi_full_instruction *inst)
{
struct tgsi_dst_register tmp_dst;
struct tgsi_src_register tmp_src;
struct ir2_instruction *alu;
 
get_internal_temp(ctx, &tmp_dst, &tmp_src);
 
alu = ir2_instr_create_alu(next_exec_cf(ctx), ~0, LOG_CLAMP);
add_regs_dummy_vector(alu);
add_dst_reg(ctx, alu, &tmp_dst);
add_src_reg(ctx, alu, &inst->Src[0].Register);
 
alu = ir2_instr_create_alu(next_exec_cf(ctx), MULv, ~0);
add_dst_reg(ctx, alu, &tmp_dst);
add_src_reg(ctx, alu, &tmp_src);
add_src_reg(ctx, alu, &inst->Src[1].Register);
 
/* NOTE: some of the instructions, like EXP_IEEE, seem hard-
* coded to take their input from the w component.
*/
switch(inst->Dst[0].Register.WriteMask) {
case TGSI_WRITEMASK_X:
tmp_src.SwizzleW = TGSI_SWIZZLE_X;
break;
case TGSI_WRITEMASK_Y:
tmp_src.SwizzleW = TGSI_SWIZZLE_Y;
break;
case TGSI_WRITEMASK_Z:
tmp_src.SwizzleW = TGSI_SWIZZLE_Z;
break;
case TGSI_WRITEMASK_W:
tmp_src.SwizzleW = TGSI_SWIZZLE_W;
break;
default:
DBG("invalid writemask!");
assert(0);
break;
}
 
alu = ir2_instr_create_alu(next_exec_cf(ctx), ~0, EXP_IEEE);
add_regs_dummy_vector(alu);
add_dst_reg(ctx, alu, &inst->Dst[0].Register);
add_src_reg(ctx, alu, &tmp_src);
add_scalar_clamp(inst, alu);
}
 
static void
translate_tex(struct fd2_compile_context *ctx,
struct tgsi_full_instruction *inst, unsigned opc)
{
struct ir2_instruction *instr;
struct ir2_register *reg;
struct tgsi_dst_register tmp_dst;
struct tgsi_src_register tmp_src;
const struct tgsi_src_register *coord;
bool using_temp = (inst->Dst[0].Register.File == TGSI_FILE_OUTPUT) ||
(inst->Instruction.Saturate != TGSI_SAT_NONE);
int idx;
 
if (using_temp || (opc == TGSI_OPCODE_TXP))
get_internal_temp(ctx, &tmp_dst, &tmp_src);
 
if (opc == TGSI_OPCODE_TXP) {
static const char *swiz[] = {
[TGSI_SWIZZLE_X] = "xxxx",
[TGSI_SWIZZLE_Y] = "yyyy",
[TGSI_SWIZZLE_Z] = "zzzz",
[TGSI_SWIZZLE_W] = "wwww",
};
 
/* TXP - Projective Texture Lookup:
*
* coord.x = src0.x / src.w
* coord.y = src0.y / src.w
* coord.z = src0.z / src.w
* coord.w = src0.w
* bias = 0.0
*
* dst = texture_sample(unit, coord, bias)
*/
instr = ir2_instr_create_alu(next_exec_cf(ctx), MAXv, RECIP_IEEE);
 
/* MAXv: */
add_dst_reg(ctx, instr, &tmp_dst)->swizzle = "___w";
add_src_reg(ctx, instr, &inst->Src[0].Register);
add_src_reg(ctx, instr, &inst->Src[0].Register);
 
/* RECIP_IEEE: */
add_dst_reg(ctx, instr, &tmp_dst)->swizzle = "x___";
add_src_reg(ctx, instr, &inst->Src[0].Register)->swizzle =
swiz[inst->Src[0].Register.SwizzleW];
 
instr = ir2_instr_create_alu(next_exec_cf(ctx), MULv, ~0);
add_dst_reg(ctx, instr, &tmp_dst)->swizzle = "xyz_";
add_src_reg(ctx, instr, &tmp_src)->swizzle = "xxxx";
add_src_reg(ctx, instr, &inst->Src[0].Register);
 
coord = &tmp_src;
} else {
coord = &inst->Src[0].Register;
}
 
instr = ir2_instr_create(next_exec_cf(ctx), IR2_FETCH);
instr->fetch.opc = TEX_FETCH;
instr->fetch.is_cube = (inst->Texture.Texture == TGSI_TEXTURE_3D);
assert(inst->Texture.NumOffsets <= 1); // TODO what to do in other cases?
 
/* save off the tex fetch to be patched later with correct const_idx: */
idx = ctx->so->num_tfetch_instrs++;
ctx->so->tfetch_instrs[idx].samp_id = inst->Src[1].Register.Index;
ctx->so->tfetch_instrs[idx].instr = instr;
 
add_dst_reg(ctx, instr, using_temp ? &tmp_dst : &inst->Dst[0].Register);
reg = add_src_reg(ctx, instr, coord);
 
/* blob compiler always sets 3rd component to same as 1st for 2d: */
if (inst->Texture.Texture == TGSI_TEXTURE_2D)
reg->swizzle[2] = reg->swizzle[0];
 
/* dst register needs to be marked for sync: */
ctx->need_sync |= 1 << instr->regs[0]->num;
 
/* TODO we need some way to know if the tex fetch needs to sync on alu pipe.. */
instr->sync = true;
 
if (using_temp) {
/* texture fetch can't write directly to export, so if tgsi
* is telling us the dst register is in output file, we load
* the texture to a temp and the use ALU instruction to move
* to output
*/
instr = ir2_instr_create_alu(next_exec_cf(ctx), MAXv, ~0);
 
add_dst_reg(ctx, instr, &inst->Dst[0].Register);
add_src_reg(ctx, instr, &tmp_src);
add_src_reg(ctx, instr, &tmp_src);
add_vector_clamp(inst, instr);
}
}
 
/* SGE(a,b) = GTE((b - a), 1.0, 0.0) */
/* SLT(a,b) = GTE((b - a), 0.0, 1.0) */
static void
translate_sge_slt(struct fd2_compile_context *ctx,
struct tgsi_full_instruction *inst, unsigned opc)
{
struct ir2_instruction *instr;
struct tgsi_dst_register tmp_dst;
struct tgsi_src_register tmp_src;
struct tgsi_src_register tmp_const;
float c0, c1;
 
switch (opc) {
default:
assert(0);
case TGSI_OPCODE_SGE:
c0 = 1.0;
c1 = 0.0;
break;
case TGSI_OPCODE_SLT:
c0 = 0.0;
c1 = 1.0;
break;
}
 
get_internal_temp(ctx, &tmp_dst, &tmp_src);
 
instr = ir2_instr_create_alu(next_exec_cf(ctx), ADDv, ~0);
add_dst_reg(ctx, instr, &tmp_dst);
add_src_reg(ctx, instr, &inst->Src[0].Register)->flags |= IR2_REG_NEGATE;
add_src_reg(ctx, instr, &inst->Src[1].Register);
 
instr = ir2_instr_create_alu(next_exec_cf(ctx), CNDGTEv, ~0);
add_dst_reg(ctx, instr, &inst->Dst[0].Register);
/* maybe should re-arrange the syntax some day, but
* in assembler/disassembler and what ir.c expects
* is: MULADDv Rdst = Rsrc2 + Rsrc0 * Rscr1
*/
get_immediate(ctx, &tmp_const, fui(c0));
add_src_reg(ctx, instr, &tmp_const);
add_src_reg(ctx, instr, &tmp_src);
get_immediate(ctx, &tmp_const, fui(c1));
add_src_reg(ctx, instr, &tmp_const);
}
 
/* LRP(a,b,c) = (a * b) + ((1 - a) * c) */
static void
translate_lrp(struct fd2_compile_context *ctx,
struct tgsi_full_instruction *inst,
unsigned opc)
{
struct ir2_instruction *instr;
struct tgsi_dst_register tmp_dst1, tmp_dst2;
struct tgsi_src_register tmp_src1, tmp_src2;
struct tgsi_src_register tmp_const;
 
get_internal_temp(ctx, &tmp_dst1, &tmp_src1);
get_internal_temp(ctx, &tmp_dst2, &tmp_src2);
 
get_immediate(ctx, &tmp_const, fui(1.0));
 
/* tmp1 = (a * b) */
instr = ir2_instr_create_alu(next_exec_cf(ctx), MULv, ~0);
add_dst_reg(ctx, instr, &tmp_dst1);
add_src_reg(ctx, instr, &inst->Src[0].Register);
add_src_reg(ctx, instr, &inst->Src[1].Register);
 
/* tmp2 = (1 - a) */
instr = ir2_instr_create_alu(next_exec_cf(ctx), ADDv, ~0);
add_dst_reg(ctx, instr, &tmp_dst2);
add_src_reg(ctx, instr, &tmp_const);
add_src_reg(ctx, instr, &inst->Src[0].Register)->flags |= IR2_REG_NEGATE;
 
/* tmp2 = tmp2 * c */
instr = ir2_instr_create_alu(next_exec_cf(ctx), MULv, ~0);
add_dst_reg(ctx, instr, &tmp_dst2);
add_src_reg(ctx, instr, &tmp_src2);
add_src_reg(ctx, instr, &inst->Src[2].Register);
 
/* dst = tmp1 + tmp2 */
instr = ir2_instr_create_alu(next_exec_cf(ctx), ADDv, ~0);
add_dst_reg(ctx, instr, &inst->Dst[0].Register);
add_src_reg(ctx, instr, &tmp_src1);
add_src_reg(ctx, instr, &tmp_src2);
}
 
static void
translate_trig(struct fd2_compile_context *ctx,
struct tgsi_full_instruction *inst,
unsigned opc)
{
struct ir2_instruction *instr;
struct tgsi_dst_register tmp_dst;
struct tgsi_src_register tmp_src;
struct tgsi_src_register tmp_const;
instr_scalar_opc_t op;
 
switch (opc) {
default:
assert(0);
case TGSI_OPCODE_SIN:
op = SIN;
break;
case TGSI_OPCODE_COS:
op = COS;
break;
}
 
get_internal_temp(ctx, &tmp_dst, &tmp_src);
 
tmp_dst.WriteMask = TGSI_WRITEMASK_X;
tmp_src.SwizzleX = tmp_src.SwizzleY =
tmp_src.SwizzleZ = tmp_src.SwizzleW = TGSI_SWIZZLE_X;
 
/* maybe should re-arrange the syntax some day, but
* in assembler/disassembler and what ir.c expects
* is: MULADDv Rdst = Rsrc2 + Rsrc0 * Rscr1
*/
instr = ir2_instr_create_alu(next_exec_cf(ctx), MULADDv, ~0);
add_dst_reg(ctx, instr, &tmp_dst);
get_immediate(ctx, &tmp_const, fui(0.5));
add_src_reg(ctx, instr, &tmp_const);
add_src_reg(ctx, instr, &inst->Src[0].Register);
get_immediate(ctx, &tmp_const, fui(0.159155));
add_src_reg(ctx, instr, &tmp_const);
 
instr = ir2_instr_create_alu(next_exec_cf(ctx), FRACv, ~0);
add_dst_reg(ctx, instr, &tmp_dst);
add_src_reg(ctx, instr, &tmp_src);
add_src_reg(ctx, instr, &tmp_src);
 
instr = ir2_instr_create_alu(next_exec_cf(ctx), MULADDv, ~0);
add_dst_reg(ctx, instr, &tmp_dst);
get_immediate(ctx, &tmp_const, fui(-3.141593));
add_src_reg(ctx, instr, &tmp_const);
add_src_reg(ctx, instr, &tmp_src);
get_immediate(ctx, &tmp_const, fui(6.283185));
add_src_reg(ctx, instr, &tmp_const);
 
instr = ir2_instr_create_alu(next_exec_cf(ctx), ~0, op);
add_regs_dummy_vector(instr);
add_dst_reg(ctx, instr, &inst->Dst[0].Register);
add_src_reg(ctx, instr, &tmp_src);
}
 
/*
* Main part of compiler/translator:
*/
 
static void
translate_instruction(struct fd2_compile_context *ctx,
struct tgsi_full_instruction *inst)
{
unsigned opc = inst->Instruction.Opcode;
struct ir2_instruction *instr;
static struct ir2_cf *cf;
 
if (opc == TGSI_OPCODE_END)
return;
 
if (inst->Dst[0].Register.File == TGSI_FILE_OUTPUT) {
unsigned num = inst->Dst[0].Register.Index;
/* seems like we need to ensure that position vs param/pixel
* exports don't end up in the same EXEC clause.. easy way
* to do this is force a new EXEC clause on first appearance
* of an position or param/pixel export.
*/
if ((num == ctx->position) || (num == ctx->psize)) {
if (ctx->num_position > 0) {
ctx->cf = NULL;
ir2_cf_create_alloc(ctx->so->ir, SQ_POSITION,
ctx->num_position - 1);
ctx->num_position = 0;
}
} else {
if (ctx->num_param > 0) {
ctx->cf = NULL;
ir2_cf_create_alloc(ctx->so->ir, SQ_PARAMETER_PIXEL,
ctx->num_param - 1);
ctx->num_param = 0;
}
}
}
 
cf = next_exec_cf(ctx);
 
/* TODO turn this into a table: */
switch (opc) {
case TGSI_OPCODE_MOV:
instr = ir2_instr_create_alu(cf, MAXv, ~0);
add_regs_vector_1(ctx, inst, instr);
break;
case TGSI_OPCODE_RCP:
instr = ir2_instr_create_alu(cf, ~0, RECIP_IEEE);
add_regs_scalar_1(ctx, inst, instr);
break;
case TGSI_OPCODE_RSQ:
instr = ir2_instr_create_alu(cf, ~0, RECIPSQ_IEEE);
add_regs_scalar_1(ctx, inst, instr);
break;
case TGSI_OPCODE_SQRT:
instr = ir2_instr_create_alu(cf, ~0, SQRT_IEEE);
add_regs_scalar_1(ctx, inst, instr);
break;
case TGSI_OPCODE_MUL:
instr = ir2_instr_create_alu(cf, MULv, ~0);
add_regs_vector_2(ctx, inst, instr);
break;
case TGSI_OPCODE_ADD:
instr = ir2_instr_create_alu(cf, ADDv, ~0);
add_regs_vector_2(ctx, inst, instr);
break;
case TGSI_OPCODE_DP3:
instr = ir2_instr_create_alu(cf, DOT3v, ~0);
add_regs_vector_2(ctx, inst, instr);
break;
case TGSI_OPCODE_DP4:
instr = ir2_instr_create_alu(cf, DOT4v, ~0);
add_regs_vector_2(ctx, inst, instr);
break;
case TGSI_OPCODE_MIN:
instr = ir2_instr_create_alu(cf, MINv, ~0);
add_regs_vector_2(ctx, inst, instr);
break;
case TGSI_OPCODE_MAX:
instr = ir2_instr_create_alu(cf, MAXv, ~0);
add_regs_vector_2(ctx, inst, instr);
break;
case TGSI_OPCODE_SLT:
case TGSI_OPCODE_SGE:
translate_sge_slt(ctx, inst, opc);
break;
case TGSI_OPCODE_MAD:
instr = ir2_instr_create_alu(cf, MULADDv, ~0);
add_regs_vector_3(ctx, inst, instr);
break;
case TGSI_OPCODE_LRP:
translate_lrp(ctx, inst, opc);
break;
case TGSI_OPCODE_FRC:
instr = ir2_instr_create_alu(cf, FRACv, ~0);
add_regs_vector_1(ctx, inst, instr);
break;
case TGSI_OPCODE_FLR:
instr = ir2_instr_create_alu(cf, FLOORv, ~0);
add_regs_vector_1(ctx, inst, instr);
break;
case TGSI_OPCODE_EX2:
instr = ir2_instr_create_alu(cf, ~0, EXP_IEEE);
add_regs_scalar_1(ctx, inst, instr);
break;
case TGSI_OPCODE_POW:
translate_pow(ctx, inst);
break;
case TGSI_OPCODE_ABS:
instr = ir2_instr_create_alu(cf, MAXv, ~0);
add_regs_vector_1(ctx, inst, instr);
instr->regs[1]->flags |= IR2_REG_NEGATE; /* src0 */
break;
case TGSI_OPCODE_COS:
case TGSI_OPCODE_SIN:
translate_trig(ctx, inst, opc);
break;
case TGSI_OPCODE_TEX:
case TGSI_OPCODE_TXP:
translate_tex(ctx, inst, opc);
break;
case TGSI_OPCODE_CMP:
instr = ir2_instr_create_alu(cf, CNDGTEv, ~0);
add_regs_vector_3(ctx, inst, instr);
// TODO this should be src0 if regs where in sane order..
instr->regs[2]->flags ^= IR2_REG_NEGATE; /* src1 */
break;
case TGSI_OPCODE_IF:
push_predicate(ctx, &inst->Src[0].Register);
ctx->so->ir->pred = IR2_PRED_EQ;
break;
case TGSI_OPCODE_ELSE:
ctx->so->ir->pred = IR2_PRED_NE;
/* not sure if this is required in all cases, but blob compiler
* won't combine EQ and NE in same CF:
*/
ctx->cf = NULL;
break;
case TGSI_OPCODE_ENDIF:
pop_predicate(ctx);
break;
case TGSI_OPCODE_F2I:
instr = ir2_instr_create_alu(cf, TRUNCv, ~0);
add_regs_vector_1(ctx, inst, instr);
break;
default:
DBG("unknown TGSI opc: %s", tgsi_get_opcode_name(opc));
tgsi_dump(ctx->so->tokens, 0);
assert(0);
break;
}
 
/* internal temporaries are only valid for the duration of a single
* TGSI instruction:
*/
ctx->num_internal_temps = 0;
}
 
static void
compile_instructions(struct fd2_compile_context *ctx)
{
while (!tgsi_parse_end_of_tokens(&ctx->parser)) {
tgsi_parse_token(&ctx->parser);
 
switch (ctx->parser.FullToken.Token.Type) {
case TGSI_TOKEN_TYPE_INSTRUCTION:
translate_instruction(ctx,
&ctx->parser.FullToken.FullInstruction);
break;
default:
break;
}
}
 
ctx->cf->cf_type = EXEC_END;
}
 
int
fd2_compile_shader(struct fd_program_stateobj *prog,
struct fd2_shader_stateobj *so)
{
struct fd2_compile_context ctx;
 
ir2_shader_destroy(so->ir);
so->ir = ir2_shader_create();
so->num_vfetch_instrs = so->num_tfetch_instrs = so->num_immediates = 0;
 
if (compile_init(&ctx, prog, so) != TGSI_PARSE_OK)
return -1;
 
if (ctx.type == TGSI_PROCESSOR_VERTEX) {
compile_vtx_fetch(&ctx);
} else if (ctx.type == TGSI_PROCESSOR_FRAGMENT) {
prog->num_exports = 0;
memset(prog->export_linkage, 0xff,
sizeof(prog->export_linkage));
}
 
compile_instructions(&ctx);
 
compile_free(&ctx);
 
return 0;
}
 
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a2xx/fd2_compiler.h
0,0 → 1,38
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FD2_COMPILER_H_
#define FD2_COMPILER_H_
 
#include "fd2_program.h"
#include "fd2_util.h"
 
int fd2_compile_shader(struct fd_program_stateobj *prog,
struct fd2_shader_stateobj *so);
 
#endif /* FD2_COMPILER_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a2xx/fd2_context.c
0,0 → 1,125
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
 
#include "fd2_context.h"
#include "fd2_blend.h"
#include "fd2_draw.h"
#include "fd2_emit.h"
#include "fd2_gmem.h"
#include "fd2_program.h"
#include "fd2_rasterizer.h"
#include "fd2_texture.h"
#include "fd2_zsa.h"
 
static void
fd2_context_destroy(struct pipe_context *pctx)
{
fd_context_destroy(pctx);
}
 
static struct pipe_resource *
create_solid_vertexbuf(struct pipe_context *pctx)
{
static const float init_shader_const[] = {
/* for clear/gmem2mem: */
-1.000000, +1.000000, +1.000000, +1.100000,
+1.000000, +1.000000, -1.000000, -1.100000,
+1.000000, +1.100000, -1.100000, +1.000000,
/* for mem2gmem: (vertices) */
-1.000000, +1.000000, +1.000000, +1.000000,
+1.000000, +1.000000, -1.000000, -1.000000,
+1.000000, +1.000000, -1.000000, +1.000000,
/* for mem2gmem: (tex coords) */
+0.000000, +0.000000, +1.000000, +0.000000,
+0.000000, +1.000000, +1.000000, +1.000000,
};
struct pipe_resource *prsc = pipe_buffer_create(pctx->screen,
PIPE_BIND_CUSTOM, PIPE_USAGE_IMMUTABLE, sizeof(init_shader_const));
pipe_buffer_write(pctx, prsc, 0,
sizeof(init_shader_const), init_shader_const);
return prsc;
}
 
static const uint8_t a22x_primtypes[PIPE_PRIM_MAX] = {
[PIPE_PRIM_POINTS] = DI_PT_POINTLIST_A2XX,
[PIPE_PRIM_LINES] = DI_PT_LINELIST,
[PIPE_PRIM_LINE_STRIP] = DI_PT_LINESTRIP,
[PIPE_PRIM_LINE_LOOP] = DI_PT_LINELOOP,
[PIPE_PRIM_TRIANGLES] = DI_PT_TRILIST,
[PIPE_PRIM_TRIANGLE_STRIP] = DI_PT_TRISTRIP,
[PIPE_PRIM_TRIANGLE_FAN] = DI_PT_TRIFAN,
};
 
static const uint8_t a20x_primtypes[PIPE_PRIM_MAX] = {
[PIPE_PRIM_POINTS] = DI_PT_POINTLIST_A2XX,
[PIPE_PRIM_LINES] = DI_PT_LINELIST,
[PIPE_PRIM_LINE_STRIP] = DI_PT_LINESTRIP,
[PIPE_PRIM_TRIANGLES] = DI_PT_TRILIST,
[PIPE_PRIM_TRIANGLE_STRIP] = DI_PT_TRISTRIP,
[PIPE_PRIM_TRIANGLE_FAN] = DI_PT_TRIFAN,
};
 
struct pipe_context *
fd2_context_create(struct pipe_screen *pscreen, void *priv)
{
struct fd_screen *screen = fd_screen(pscreen);
struct fd2_context *fd2_ctx = CALLOC_STRUCT(fd2_context);
struct pipe_context *pctx;
 
if (!fd2_ctx)
return NULL;
 
pctx = &fd2_ctx->base.base;
 
fd2_ctx->base.dev = fd_device_ref(screen->dev);
fd2_ctx->base.screen = fd_screen(pscreen);
 
pctx->destroy = fd2_context_destroy;
pctx->create_blend_state = fd2_blend_state_create;
pctx->create_rasterizer_state = fd2_rasterizer_state_create;
pctx->create_depth_stencil_alpha_state = fd2_zsa_state_create;
 
fd2_draw_init(pctx);
fd2_gmem_init(pctx);
fd2_texture_init(pctx);
fd2_prog_init(pctx);
 
pctx = fd_context_init(&fd2_ctx->base, pscreen,
(screen->gpu_id >= 220) ? a22x_primtypes : a20x_primtypes,
priv);
if (!pctx)
return NULL;
 
/* construct vertex state used for solid ops (clear, and gmem<->mem) */
fd2_ctx->solid_vertexbuf = create_solid_vertexbuf(pctx);
 
fd2_emit_setup(&fd2_ctx->base);
 
return pctx;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a2xx/fd2_context.h
0,0 → 1,52
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FD2_CONTEXT_H_
#define FD2_CONTEXT_H_
 
#include "freedreno_context.h"
 
struct fd2_context {
struct fd_context base;
 
/* vertex buf used for clear/gmem->mem vertices, and mem->gmem
* vertices and tex coords:
*/
struct pipe_resource *solid_vertexbuf;
};
 
static INLINE struct fd2_context *
fd2_context(struct fd_context *ctx)
{
return (struct fd2_context *)ctx;
}
 
struct pipe_context *
fd2_context_create(struct pipe_screen *pscreen, void *priv);
 
#endif /* FD2_CONTEXT_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a2xx/fd2_draw.c
0,0 → 1,285
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2012-2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "pipe/p_state.h"
#include "util/u_string.h"
#include "util/u_memory.h"
#include "util/u_prim.h"
 
#include "freedreno_state.h"
#include "freedreno_resource.h"
 
#include "fd2_draw.h"
#include "fd2_context.h"
#include "fd2_emit.h"
#include "fd2_program.h"
#include "fd2_util.h"
#include "fd2_zsa.h"
 
 
static void
emit_cacheflush(struct fd_ringbuffer *ring)
{
unsigned i;
 
for (i = 0; i < 12; i++) {
OUT_PKT3(ring, CP_EVENT_WRITE, 1);
OUT_RING(ring, CACHE_FLUSH);
}
}
 
static void
emit_vertexbufs(struct fd_context *ctx)
{
struct fd_vertex_stateobj *vtx = ctx->vtx.vtx;
struct fd_vertexbuf_stateobj *vertexbuf = &ctx->vtx.vertexbuf;
struct fd2_vertex_buf bufs[PIPE_MAX_ATTRIBS];
unsigned i;
 
if (!vtx->num_elements)
return;
 
for (i = 0; i < vtx->num_elements; i++) {
struct pipe_vertex_element *elem = &vtx->pipe[i];
struct pipe_vertex_buffer *vb =
&vertexbuf->vb[elem->vertex_buffer_index];
bufs[i].offset = vb->buffer_offset;
bufs[i].size = fd_bo_size(fd_resource(vb->buffer)->bo);
bufs[i].prsc = vb->buffer;
}
 
// NOTE I believe the 0x78 (or 0x9c in solid_vp) relates to the
// CONST(20,0) (or CONST(26,0) in soliv_vp)
 
fd2_emit_vertex_bufs(ctx->ring, 0x78, bufs, vtx->num_elements);
}
 
static void
fd2_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info)
{
struct fd_ringbuffer *ring = ctx->ring;
 
if (ctx->dirty & FD_DIRTY_VTXBUF)
emit_vertexbufs(ctx);
 
fd2_emit_state(ctx, ctx->dirty);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_VGT_INDX_OFFSET));
OUT_RING(ring, info->start);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_VGT_VERTEX_REUSE_BLOCK_CNTL));
OUT_RING(ring, 0x0000003b);
 
OUT_PKT0(ring, REG_A2XX_TC_CNTL_STATUS, 1);
OUT_RING(ring, A2XX_TC_CNTL_STATUS_L2_INVALIDATE);
 
OUT_WFI (ring);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 3);
OUT_RING(ring, CP_REG(REG_A2XX_VGT_MAX_VTX_INDX));
OUT_RING(ring, info->max_index); /* VGT_MAX_VTX_INDX */
OUT_RING(ring, info->min_index); /* VGT_MIN_VTX_INDX */
 
fd_draw_emit(ctx, ring, ctx->primtypes[info->mode],
IGNORE_VISIBILITY, info);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_UNKNOWN_2010));
OUT_RING(ring, 0x00000000);
 
emit_cacheflush(ring);
}
 
 
static void
fd2_clear(struct fd_context *ctx, unsigned buffers,
const union pipe_color_union *color, double depth, unsigned stencil)
{
struct fd2_context *fd2_ctx = fd2_context(ctx);
struct fd_ringbuffer *ring = ctx->ring;
struct pipe_framebuffer_state *fb = &ctx->framebuffer;
uint32_t reg, colr = 0;
 
if ((buffers & PIPE_CLEAR_COLOR) && fb->nr_cbufs)
colr = pack_rgba(fb->cbufs[0]->format, color->f);
 
/* emit generic state now: */
fd2_emit_state(ctx, ctx->dirty &
(FD_DIRTY_BLEND | FD_DIRTY_VIEWPORT |
FD_DIRTY_FRAMEBUFFER | FD_DIRTY_SCISSOR));
 
fd2_emit_vertex_bufs(ring, 0x9c, (struct fd2_vertex_buf[]) {
{ .prsc = fd2_ctx->solid_vertexbuf, .size = 48 },
}, 1);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_VGT_INDX_OFFSET));
OUT_RING(ring, 0);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_VGT_VERTEX_REUSE_BLOCK_CNTL));
OUT_RING(ring, 0x0000028f);
 
fd2_program_emit(ring, &ctx->solid_prog);
 
OUT_PKT0(ring, REG_A2XX_TC_CNTL_STATUS, 1);
OUT_RING(ring, A2XX_TC_CNTL_STATUS_L2_INVALIDATE);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_CLEAR_COLOR));
OUT_RING(ring, colr);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_A220_RB_LRZ_VSC_CONTROL));
OUT_RING(ring, 0x00000084);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_RB_COPY_CONTROL));
reg = 0;
if (buffers & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) {
reg |= A2XX_RB_COPY_CONTROL_DEPTH_CLEAR_ENABLE;
switch (fd_pipe2depth(fb->zsbuf->format)) {
case DEPTHX_24_8:
if (buffers & PIPE_CLEAR_DEPTH)
reg |= A2XX_RB_COPY_CONTROL_CLEAR_MASK(0xe);
if (buffers & PIPE_CLEAR_STENCIL)
reg |= A2XX_RB_COPY_CONTROL_CLEAR_MASK(0x1);
break;
case DEPTHX_16:
if (buffers & PIPE_CLEAR_DEPTH)
reg |= A2XX_RB_COPY_CONTROL_CLEAR_MASK(0xf);
break;
default:
debug_assert(0);
break;
}
}
OUT_RING(ring, reg);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_RB_DEPTH_CLEAR));
reg = 0;
if (buffers & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) {
switch (fd_pipe2depth(fb->zsbuf->format)) {
case DEPTHX_24_8:
reg = (((uint32_t)(0xffffff * depth)) << 8) |
(stencil & 0xff);
break;
case DEPTHX_16:
reg = (uint32_t)(0xffffffff * depth);
break;
default:
debug_assert(0);
break;
}
}
OUT_RING(ring, reg);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_RB_DEPTHCONTROL));
reg = 0;
if (buffers & PIPE_CLEAR_DEPTH) {
reg |= A2XX_RB_DEPTHCONTROL_ZFUNC(FUNC_ALWAYS) |
A2XX_RB_DEPTHCONTROL_Z_ENABLE |
A2XX_RB_DEPTHCONTROL_Z_WRITE_ENABLE |
A2XX_RB_DEPTHCONTROL_EARLY_Z_ENABLE;
}
if (buffers & PIPE_CLEAR_STENCIL) {
reg |= A2XX_RB_DEPTHCONTROL_STENCILFUNC(FUNC_ALWAYS) |
A2XX_RB_DEPTHCONTROL_STENCIL_ENABLE |
A2XX_RB_DEPTHCONTROL_STENCILZPASS(STENCIL_REPLACE);
}
OUT_RING(ring, reg);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 3);
OUT_RING(ring, CP_REG(REG_A2XX_RB_STENCILREFMASK_BF));
OUT_RING(ring, 0xff000000 | A2XX_RB_STENCILREFMASK_BF_STENCILWRITEMASK(0xff));
OUT_RING(ring, 0xff000000 | A2XX_RB_STENCILREFMASK_STENCILWRITEMASK(0xff));
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_RB_COLORCONTROL));
OUT_RING(ring, A2XX_RB_COLORCONTROL_ALPHA_FUNC(FUNC_ALWAYS) |
A2XX_RB_COLORCONTROL_BLEND_DISABLE |
A2XX_RB_COLORCONTROL_ROP_CODE(12) |
A2XX_RB_COLORCONTROL_DITHER_MODE(DITHER_DISABLE) |
A2XX_RB_COLORCONTROL_DITHER_TYPE(DITHER_PIXEL));
 
OUT_PKT3(ring, CP_SET_CONSTANT, 3);
OUT_RING(ring, CP_REG(REG_A2XX_PA_CL_CLIP_CNTL));
OUT_RING(ring, 0x00000000); /* PA_CL_CLIP_CNTL */
OUT_RING(ring, A2XX_PA_SU_SC_MODE_CNTL_PROVOKING_VTX_LAST | /* PA_SU_SC_MODE_CNTL */
A2XX_PA_SU_SC_MODE_CNTL_FRONT_PTYPE(PC_DRAW_TRIANGLES) |
A2XX_PA_SU_SC_MODE_CNTL_BACK_PTYPE(PC_DRAW_TRIANGLES));
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_AA_MASK));
OUT_RING(ring, 0x0000ffff);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 3);
OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_WINDOW_SCISSOR_TL));
OUT_RING(ring, xy2d(0,0)); /* PA_SC_WINDOW_SCISSOR_TL */
OUT_RING(ring, xy2d(fb->width, /* PA_SC_WINDOW_SCISSOR_BR */
fb->height));
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_RB_COLOR_MASK));
if (buffers & PIPE_CLEAR_COLOR) {
OUT_RING(ring, A2XX_RB_COLOR_MASK_WRITE_RED |
A2XX_RB_COLOR_MASK_WRITE_GREEN |
A2XX_RB_COLOR_MASK_WRITE_BLUE |
A2XX_RB_COLOR_MASK_WRITE_ALPHA);
} else {
OUT_RING(ring, 0x0);
}
 
OUT_PKT3(ring, CP_SET_CONSTANT, 3);
OUT_RING(ring, CP_REG(REG_A2XX_VGT_MAX_VTX_INDX));
OUT_RING(ring, 3); /* VGT_MAX_VTX_INDX */
OUT_RING(ring, 0); /* VGT_MIN_VTX_INDX */
 
fd_draw(ctx, ring, DI_PT_RECTLIST, IGNORE_VISIBILITY,
DI_SRC_SEL_AUTO_INDEX, 3, 0, INDEX_SIZE_IGN, 0, 0, NULL);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_A220_RB_LRZ_VSC_CONTROL));
OUT_RING(ring, 0x00000000);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_RB_COPY_CONTROL));
OUT_RING(ring, 0x00000000);
}
 
void
fd2_draw_init(struct pipe_context *pctx)
{
struct fd_context *ctx = fd_context(pctx);
ctx->draw_vbo = fd2_draw_vbo;
ctx->clear = fd2_clear;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a2xx/fd2_draw.h
0,0 → 1,38
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2012-2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FD2_DRAW_H_
#define FD2_DRAW_H_
 
#include "pipe/p_context.h"
 
#include "freedreno_draw.h"
 
void fd2_draw_init(struct pipe_context *pctx);
 
#endif /* FD2_DRAW_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a2xx/fd2_emit.c
0,0 → 1,448
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2012-2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "pipe/p_state.h"
#include "util/u_string.h"
#include "util/u_memory.h"
#include "util/u_helpers.h"
 
#include "freedreno_resource.h"
 
#include "fd2_emit.h"
#include "fd2_blend.h"
#include "fd2_context.h"
#include "fd2_program.h"
#include "fd2_rasterizer.h"
#include "fd2_texture.h"
#include "fd2_util.h"
#include "fd2_zsa.h"
 
/* NOTE: just define the position for const regs statically.. the blob
* driver doesn't seem to change these dynamically, and I can't really
* think of a good reason to so..
*/
#define VS_CONST_BASE 0x20
#define PS_CONST_BASE 0x120
 
static void
emit_constants(struct fd_ringbuffer *ring, uint32_t base,
struct fd_constbuf_stateobj *constbuf,
struct fd2_shader_stateobj *shader)
{
uint32_t enabled_mask = constbuf->enabled_mask;
uint32_t start_base = base;
unsigned i;
 
// XXX TODO only emit dirty consts.. but we need to keep track if
// they are clobbered by a clear, gmem2mem, or mem2gmem..
constbuf->dirty_mask = enabled_mask;
 
/* emit user constants: */
while (enabled_mask) {
unsigned index = ffs(enabled_mask) - 1;
struct pipe_constant_buffer *cb = &constbuf->cb[index];
unsigned size = align(cb->buffer_size, 4) / 4; /* size in dwords */
 
// I expect that size should be a multiple of vec4's:
assert(size == align(size, 4));
 
/* hmm, sometimes we still seem to end up with consts bound,
* even if shader isn't using them, which ends up overwriting
* const reg's used for immediates.. this is a hack to work
* around that:
*/
if (shader && ((base - start_base) >= (shader->first_immediate * 4)))
break;
 
if (constbuf->dirty_mask & (1 << index)) {
const uint32_t *dwords;
 
if (cb->user_buffer) {
dwords = cb->user_buffer;
} else {
struct fd_resource *rsc = fd_resource(cb->buffer);
dwords = fd_bo_map(rsc->bo);
}
 
dwords = (uint32_t *)(((uint8_t *)dwords) + cb->buffer_offset);
 
OUT_PKT3(ring, CP_SET_CONSTANT, size + 1);
OUT_RING(ring, base);
for (i = 0; i < size; i++)
OUT_RING(ring, *(dwords++));
 
constbuf->dirty_mask &= ~(1 << index);
}
 
base += size;
enabled_mask &= ~(1 << index);
}
 
/* emit shader immediates: */
if (shader) {
for (i = 0; i < shader->num_immediates; i++) {
OUT_PKT3(ring, CP_SET_CONSTANT, 5);
OUT_RING(ring, start_base + (4 * (shader->first_immediate + i)));
OUT_RING(ring, shader->immediates[i].val[0]);
OUT_RING(ring, shader->immediates[i].val[1]);
OUT_RING(ring, shader->immediates[i].val[2]);
OUT_RING(ring, shader->immediates[i].val[3]);
base += 4;
}
}
}
 
typedef uint32_t texmask;
 
static texmask
emit_texture(struct fd_ringbuffer *ring, struct fd_context *ctx,
struct fd_texture_stateobj *tex, unsigned samp_id, texmask emitted)
{
unsigned const_idx = fd2_get_const_idx(ctx, tex, samp_id);
static const struct fd2_sampler_stateobj dummy_sampler = {};
const struct fd2_sampler_stateobj *sampler;
struct fd2_pipe_sampler_view *view;
 
if (emitted & (1 << const_idx))
return 0;
 
sampler = tex->samplers[samp_id] ?
fd2_sampler_stateobj(tex->samplers[samp_id]) :
&dummy_sampler;
view = fd2_pipe_sampler_view(tex->textures[samp_id]);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 7);
OUT_RING(ring, 0x00010000 + (0x6 * const_idx));
 
OUT_RING(ring, sampler->tex0 | view->tex0);
OUT_RELOC(ring, fd_resource(view->base.texture)->bo, 0, view->fmt, 0);
OUT_RING(ring, view->tex2);
OUT_RING(ring, sampler->tex3 | view->tex3);
OUT_RING(ring, sampler->tex4);
OUT_RING(ring, sampler->tex5);
 
return (1 << const_idx);
}
 
static void
emit_textures(struct fd_ringbuffer *ring, struct fd_context *ctx)
{
texmask emitted = 0;
unsigned i;
 
for (i = 0; i < ctx->verttex.num_samplers; i++)
if (ctx->verttex.samplers[i])
emitted |= emit_texture(ring, ctx, &ctx->verttex, i, emitted);
 
for (i = 0; i < ctx->fragtex.num_samplers; i++)
if (ctx->fragtex.samplers[i])
emitted |= emit_texture(ring, ctx, &ctx->fragtex, i, emitted);
}
 
void
fd2_emit_vertex_bufs(struct fd_ringbuffer *ring, uint32_t val,
struct fd2_vertex_buf *vbufs, uint32_t n)
{
unsigned i;
 
OUT_PKT3(ring, CP_SET_CONSTANT, 1 + (2 * n));
OUT_RING(ring, (0x1 << 16) | (val & 0xffff));
for (i = 0; i < n; i++) {
struct fd_resource *rsc = fd_resource(vbufs[i].prsc);
OUT_RELOC(ring, rsc->bo, vbufs[i].offset, 3, 0);
OUT_RING (ring, vbufs[i].size);
}
}
 
void
fd2_emit_state(struct fd_context *ctx, uint32_t dirty)
{
struct fd2_blend_stateobj *blend = fd2_blend_stateobj(ctx->blend);
struct fd2_zsa_stateobj *zsa = fd2_zsa_stateobj(ctx->zsa);
struct fd_ringbuffer *ring = ctx->ring;
 
/* NOTE: we probably want to eventually refactor this so each state
* object handles emitting it's own state.. although the mapping of
* state to registers is not always orthogonal, sometimes a single
* register contains bitfields coming from multiple state objects,
* so not sure the best way to deal with that yet.
*/
 
if (dirty & FD_DIRTY_SAMPLE_MASK) {
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_AA_MASK));
OUT_RING(ring, ctx->sample_mask);
}
 
if (dirty & (FD_DIRTY_ZSA | FD_DIRTY_STENCIL_REF)) {
struct pipe_stencil_ref *sr = &ctx->stencil_ref;
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_RB_DEPTHCONTROL));
OUT_RING(ring, zsa->rb_depthcontrol);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 4);
OUT_RING(ring, CP_REG(REG_A2XX_RB_STENCILREFMASK_BF));
OUT_RING(ring, zsa->rb_stencilrefmask_bf |
A2XX_RB_STENCILREFMASK_STENCILREF(sr->ref_value[1]));
OUT_RING(ring, zsa->rb_stencilrefmask |
A2XX_RB_STENCILREFMASK_STENCILREF(sr->ref_value[0]));
OUT_RING(ring, zsa->rb_alpha_ref);
}
 
if (dirty & (FD_DIRTY_RASTERIZER | FD_DIRTY_FRAMEBUFFER)) {
struct fd2_rasterizer_stateobj *rasterizer =
fd2_rasterizer_stateobj(ctx->rasterizer);
OUT_PKT3(ring, CP_SET_CONSTANT, 3);
OUT_RING(ring, CP_REG(REG_A2XX_PA_CL_CLIP_CNTL));
OUT_RING(ring, rasterizer->pa_cl_clip_cntl);
OUT_RING(ring, rasterizer->pa_su_sc_mode_cntl |
A2XX_PA_SU_SC_MODE_CNTL_VTX_WINDOW_OFFSET_ENABLE);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 5);
OUT_RING(ring, CP_REG(REG_A2XX_PA_SU_POINT_SIZE));
OUT_RING(ring, rasterizer->pa_su_point_size);
OUT_RING(ring, rasterizer->pa_su_point_minmax);
OUT_RING(ring, rasterizer->pa_su_line_cntl);
OUT_RING(ring, rasterizer->pa_sc_line_stipple);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 6);
OUT_RING(ring, CP_REG(REG_A2XX_PA_SU_VTX_CNTL));
OUT_RING(ring, rasterizer->pa_su_vtx_cntl);
OUT_RING(ring, fui(1.0)); /* PA_CL_GB_VERT_CLIP_ADJ */
OUT_RING(ring, fui(1.0)); /* PA_CL_GB_VERT_DISC_ADJ */
OUT_RING(ring, fui(1.0)); /* PA_CL_GB_HORZ_CLIP_ADJ */
OUT_RING(ring, fui(1.0)); /* PA_CL_GB_HORZ_DISC_ADJ */
}
 
if (dirty & FD_DIRTY_SCISSOR) {
struct pipe_scissor_state *scissor = fd_context_get_scissor(ctx);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 3);
OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_WINDOW_SCISSOR_TL));
OUT_RING(ring, xy2d(scissor->minx, /* PA_SC_WINDOW_SCISSOR_TL */
scissor->miny));
OUT_RING(ring, xy2d(scissor->maxx, /* PA_SC_WINDOW_SCISSOR_BR */
scissor->maxy));
 
ctx->max_scissor.minx = MIN2(ctx->max_scissor.minx, scissor->minx);
ctx->max_scissor.miny = MIN2(ctx->max_scissor.miny, scissor->miny);
ctx->max_scissor.maxx = MAX2(ctx->max_scissor.maxx, scissor->maxx);
ctx->max_scissor.maxy = MAX2(ctx->max_scissor.maxy, scissor->maxy);
}
 
if (dirty & FD_DIRTY_VIEWPORT) {
OUT_PKT3(ring, CP_SET_CONSTANT, 7);
OUT_RING(ring, CP_REG(REG_A2XX_PA_CL_VPORT_XSCALE));
OUT_RING(ring, fui(ctx->viewport.scale[0])); /* PA_CL_VPORT_XSCALE */
OUT_RING(ring, fui(ctx->viewport.translate[0])); /* PA_CL_VPORT_XOFFSET */
OUT_RING(ring, fui(ctx->viewport.scale[1])); /* PA_CL_VPORT_YSCALE */
OUT_RING(ring, fui(ctx->viewport.translate[1])); /* PA_CL_VPORT_YOFFSET */
OUT_RING(ring, fui(ctx->viewport.scale[2])); /* PA_CL_VPORT_ZSCALE */
OUT_RING(ring, fui(ctx->viewport.translate[2])); /* PA_CL_VPORT_ZOFFSET */
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_PA_CL_VTE_CNTL));
OUT_RING(ring, A2XX_PA_CL_VTE_CNTL_VTX_W0_FMT |
A2XX_PA_CL_VTE_CNTL_VPORT_X_SCALE_ENA |
A2XX_PA_CL_VTE_CNTL_VPORT_X_OFFSET_ENA |
A2XX_PA_CL_VTE_CNTL_VPORT_Y_SCALE_ENA |
A2XX_PA_CL_VTE_CNTL_VPORT_Y_OFFSET_ENA |
A2XX_PA_CL_VTE_CNTL_VPORT_Z_SCALE_ENA |
A2XX_PA_CL_VTE_CNTL_VPORT_Z_OFFSET_ENA);
}
 
if (dirty & (FD_DIRTY_PROG | FD_DIRTY_VTXSTATE | FD_DIRTY_TEXSTATE)) {
fd2_program_validate(ctx);
fd2_program_emit(ring, &ctx->prog);
}
 
if (dirty & (FD_DIRTY_PROG | FD_DIRTY_CONSTBUF)) {
emit_constants(ring, VS_CONST_BASE * 4,
&ctx->constbuf[PIPE_SHADER_VERTEX],
(dirty & FD_DIRTY_PROG) ? ctx->prog.vp : NULL);
emit_constants(ring, PS_CONST_BASE * 4,
&ctx->constbuf[PIPE_SHADER_FRAGMENT],
(dirty & FD_DIRTY_PROG) ? ctx->prog.fp : NULL);
}
 
if (dirty & (FD_DIRTY_BLEND | FD_DIRTY_ZSA)) {
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_RB_COLORCONTROL));
OUT_RING(ring, zsa->rb_colorcontrol | blend->rb_colorcontrol);
}
 
if (dirty & FD_DIRTY_BLEND) {
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_RB_BLEND_CONTROL));
OUT_RING(ring, blend->rb_blendcontrol);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_RB_COLOR_MASK));
OUT_RING(ring, blend->rb_colormask);
}
 
if (dirty & (FD_DIRTY_VERTTEX | FD_DIRTY_FRAGTEX | FD_DIRTY_PROG))
emit_textures(ring, ctx);
 
ctx->dirty &= ~dirty;
}
 
/* emit per-context initialization:
*/
void
fd2_emit_setup(struct fd_context *ctx)
{
struct fd_ringbuffer *ring = ctx->ring;
 
OUT_PKT0(ring, REG_A2XX_TP0_CHICKEN, 1);
OUT_RING(ring, 0x00000002);
 
OUT_PKT3(ring, CP_INVALIDATE_STATE, 1);
OUT_RING(ring, 0x00007fff);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_SQ_VS_CONST));
OUT_RING(ring, A2XX_SQ_VS_CONST_BASE(VS_CONST_BASE) |
A2XX_SQ_VS_CONST_SIZE(0x100));
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_SQ_PS_CONST));
OUT_RING(ring, A2XX_SQ_PS_CONST_BASE(PS_CONST_BASE) |
A2XX_SQ_PS_CONST_SIZE(0xe0));
 
OUT_PKT3(ring, CP_SET_CONSTANT, 3);
OUT_RING(ring, CP_REG(REG_A2XX_VGT_MAX_VTX_INDX));
OUT_RING(ring, 0xffffffff); /* VGT_MAX_VTX_INDX */
OUT_RING(ring, 0x00000000); /* VGT_MIN_VTX_INDX */
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_VGT_INDX_OFFSET));
OUT_RING(ring, 0x00000000);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_VGT_VERTEX_REUSE_BLOCK_CNTL));
OUT_RING(ring, 0x0000003b);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_SQ_CONTEXT_MISC));
OUT_RING(ring, A2XX_SQ_CONTEXT_MISC_SC_SAMPLE_CNTL(CENTERS_ONLY));
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_SQ_INTERPOLATOR_CNTL));
OUT_RING(ring, 0xffffffff);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_AA_CONFIG));
OUT_RING(ring, 0x00000000);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_LINE_CNTL));
OUT_RING(ring, 0x00000000);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_WINDOW_OFFSET));
OUT_RING(ring, 0x00000000);
 
// XXX we change this dynamically for draw/clear.. vs gmem<->mem..
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_RB_MODECONTROL));
OUT_RING(ring, A2XX_RB_MODECONTROL_EDRAM_MODE(COLOR_DEPTH));
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_RB_SAMPLE_POS));
OUT_RING(ring, 0x88888888);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_RB_COLOR_DEST_MASK));
OUT_RING(ring, 0xffffffff);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_RB_COPY_DEST_INFO));
OUT_RING(ring, A2XX_RB_COPY_DEST_INFO_FORMAT(COLORX_4_4_4_4) |
A2XX_RB_COPY_DEST_INFO_WRITE_RED |
A2XX_RB_COPY_DEST_INFO_WRITE_GREEN |
A2XX_RB_COPY_DEST_INFO_WRITE_BLUE |
A2XX_RB_COPY_DEST_INFO_WRITE_ALPHA);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 3);
OUT_RING(ring, CP_REG(REG_A2XX_SQ_WRAPPING_0));
OUT_RING(ring, 0x00000000); /* SQ_WRAPPING_0 */
OUT_RING(ring, 0x00000000); /* SQ_WRAPPING_1 */
 
OUT_PKT3(ring, CP_SET_DRAW_INIT_FLAGS, 1);
OUT_RING(ring, 0x00000000);
 
OUT_PKT3(ring, CP_WAIT_REG_EQ, 4);
OUT_RING(ring, 0x000005d0);
OUT_RING(ring, 0x00000000);
OUT_RING(ring, 0x5f601000);
OUT_RING(ring, 0x00000001);
 
OUT_PKT0(ring, REG_A2XX_SQ_INST_STORE_MANAGMENT, 1);
OUT_RING(ring, 0x00000180);
 
OUT_PKT3(ring, CP_INVALIDATE_STATE, 1);
OUT_RING(ring, 0x00000300);
 
OUT_PKT3(ring, CP_SET_SHADER_BASES, 1);
OUT_RING(ring, 0x80000180);
 
/* not sure what this form of CP_SET_CONSTANT is.. */
OUT_PKT3(ring, CP_SET_CONSTANT, 13);
OUT_RING(ring, 0x00000000);
OUT_RING(ring, 0x00000000);
OUT_RING(ring, 0x00000000);
OUT_RING(ring, 0x00000000);
OUT_RING(ring, 0x00000000);
OUT_RING(ring, 0x469c4000);
OUT_RING(ring, 0x3f800000);
OUT_RING(ring, 0x3f000000);
OUT_RING(ring, 0x00000000);
OUT_RING(ring, 0x40000000);
OUT_RING(ring, 0x3f400000);
OUT_RING(ring, 0x3ec00000);
OUT_RING(ring, 0x3e800000);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_RB_COLOR_MASK));
OUT_RING(ring, A2XX_RB_COLOR_MASK_WRITE_RED |
A2XX_RB_COLOR_MASK_WRITE_GREEN |
A2XX_RB_COLOR_MASK_WRITE_BLUE |
A2XX_RB_COLOR_MASK_WRITE_ALPHA);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 5);
OUT_RING(ring, CP_REG(REG_A2XX_RB_BLEND_RED));
OUT_RING(ring, 0x00000000); /* RB_BLEND_RED */
OUT_RING(ring, 0x00000000); /* RB_BLEND_GREEN */
OUT_RING(ring, 0x00000000); /* RB_BLEND_BLUE */
OUT_RING(ring, 0x000000ff); /* RB_BLEND_ALPHA */
 
fd_ringbuffer_flush(ring);
fd_ringmarker_mark(ctx->draw_start);
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a2xx/fd2_emit.h
0,0 → 1,48
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2012-2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FD2_EMIT_H
#define FD2_EMIT_H
 
#include "pipe/p_context.h"
 
#include "freedreno_context.h"
 
struct fd_ringbuffer;
 
struct fd2_vertex_buf {
unsigned offset, size;
struct pipe_resource *prsc;
};
 
void fd2_emit_vertex_bufs(struct fd_ringbuffer *ring, uint32_t val,
struct fd2_vertex_buf *vbufs, uint32_t n);
void fd2_emit_state(struct fd_context *ctx, uint32_t dirty);
void fd2_emit_setup(struct fd_context *ctx);
 
#endif /* FD2_EMIT_H */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a2xx/fd2_gmem.c
0,0 → 1,404
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "pipe/p_state.h"
#include "util/u_string.h"
#include "util/u_memory.h"
#include "util/u_inlines.h"
 
#include "freedreno_draw.h"
#include "freedreno_state.h"
#include "freedreno_resource.h"
 
#include "fd2_gmem.h"
#include "fd2_context.h"
#include "fd2_emit.h"
#include "fd2_program.h"
#include "fd2_util.h"
#include "fd2_zsa.h"
 
static uint32_t fmt2swap(enum pipe_format format)
{
switch (format) {
case PIPE_FORMAT_B8G8R8A8_UNORM:
/* TODO probably some more.. */
return 1;
default:
return 0;
}
}
 
/* transfer from gmem to system memory (ie. normal RAM) */
 
static void
emit_gmem2mem_surf(struct fd_context *ctx, uint32_t base,
struct pipe_surface *psurf)
{
struct fd_ringbuffer *ring = ctx->ring;
struct fd_resource *rsc = fd_resource(psurf->texture);
uint32_t swap = fmt2swap(psurf->format);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_RB_COLOR_INFO));
OUT_RING(ring, A2XX_RB_COLOR_INFO_SWAP(swap) |
A2XX_RB_COLOR_INFO_BASE(base) |
A2XX_RB_COLOR_INFO_FORMAT(fd2_pipe2color(psurf->format)));
 
OUT_PKT3(ring, CP_SET_CONSTANT, 5);
OUT_RING(ring, CP_REG(REG_A2XX_RB_COPY_CONTROL));
OUT_RING(ring, 0x00000000); /* RB_COPY_CONTROL */
OUT_RELOCW(ring, rsc->bo, 0, 0, 0); /* RB_COPY_DEST_BASE */
OUT_RING(ring, rsc->slices[0].pitch >> 5); /* RB_COPY_DEST_PITCH */
OUT_RING(ring, /* RB_COPY_DEST_INFO */
A2XX_RB_COPY_DEST_INFO_FORMAT(fd2_pipe2color(psurf->format)) |
A2XX_RB_COPY_DEST_INFO_LINEAR |
A2XX_RB_COPY_DEST_INFO_SWAP(swap) |
A2XX_RB_COPY_DEST_INFO_WRITE_RED |
A2XX_RB_COPY_DEST_INFO_WRITE_GREEN |
A2XX_RB_COPY_DEST_INFO_WRITE_BLUE |
A2XX_RB_COPY_DEST_INFO_WRITE_ALPHA);
 
OUT_WFI (ring);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 3);
OUT_RING(ring, CP_REG(REG_A2XX_VGT_MAX_VTX_INDX));
OUT_RING(ring, 3); /* VGT_MAX_VTX_INDX */
OUT_RING(ring, 0); /* VGT_MIN_VTX_INDX */
 
fd_draw(ctx, ring, DI_PT_RECTLIST, IGNORE_VISIBILITY,
DI_SRC_SEL_AUTO_INDEX, 3, 0, INDEX_SIZE_IGN, 0, 0, NULL);
}
 
static void
fd2_emit_tile_gmem2mem(struct fd_context *ctx, struct fd_tile *tile)
{
struct fd2_context *fd2_ctx = fd2_context(ctx);
struct fd_ringbuffer *ring = ctx->ring;
struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
 
fd2_emit_vertex_bufs(ring, 0x9c, (struct fd2_vertex_buf[]) {
{ .prsc = fd2_ctx->solid_vertexbuf, .size = 48 },
}, 1);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_WINDOW_OFFSET));
OUT_RING(ring, 0x00000000); /* PA_SC_WINDOW_OFFSET */
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_VGT_INDX_OFFSET));
OUT_RING(ring, 0);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_VGT_VERTEX_REUSE_BLOCK_CNTL));
OUT_RING(ring, 0x0000028f);
 
fd2_program_emit(ring, &ctx->solid_prog);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_AA_MASK));
OUT_RING(ring, 0x0000ffff);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_RB_DEPTHCONTROL));
OUT_RING(ring, A2XX_RB_DEPTHCONTROL_EARLY_Z_ENABLE);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_PA_SU_SC_MODE_CNTL));
OUT_RING(ring, A2XX_PA_SU_SC_MODE_CNTL_PROVOKING_VTX_LAST | /* PA_SU_SC_MODE_CNTL */
A2XX_PA_SU_SC_MODE_CNTL_FRONT_PTYPE(PC_DRAW_TRIANGLES) |
A2XX_PA_SU_SC_MODE_CNTL_BACK_PTYPE(PC_DRAW_TRIANGLES));
 
OUT_PKT3(ring, CP_SET_CONSTANT, 3);
OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_WINDOW_SCISSOR_TL));
OUT_RING(ring, xy2d(0, 0)); /* PA_SC_WINDOW_SCISSOR_TL */
OUT_RING(ring, xy2d(pfb->width, pfb->height)); /* PA_SC_WINDOW_SCISSOR_BR */
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_PA_CL_VTE_CNTL));
OUT_RING(ring, A2XX_PA_CL_VTE_CNTL_VTX_W0_FMT |
A2XX_PA_CL_VTE_CNTL_VPORT_X_SCALE_ENA |
A2XX_PA_CL_VTE_CNTL_VPORT_X_OFFSET_ENA |
A2XX_PA_CL_VTE_CNTL_VPORT_Y_SCALE_ENA |
A2XX_PA_CL_VTE_CNTL_VPORT_Y_OFFSET_ENA);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_PA_CL_CLIP_CNTL));
OUT_RING(ring, 0x00000000);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_RB_MODECONTROL));
OUT_RING(ring, A2XX_RB_MODECONTROL_EDRAM_MODE(EDRAM_COPY));
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_RB_COPY_DEST_OFFSET));
OUT_RING(ring, A2XX_RB_COPY_DEST_OFFSET_X(tile->xoff) |
A2XX_RB_COPY_DEST_OFFSET_Y(tile->yoff));
 
if (ctx->resolve & (FD_BUFFER_DEPTH | FD_BUFFER_STENCIL))
emit_gmem2mem_surf(ctx, tile->bin_w * tile->bin_h, pfb->zsbuf);
 
if (ctx->resolve & FD_BUFFER_COLOR)
emit_gmem2mem_surf(ctx, 0, pfb->cbufs[0]);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_RB_MODECONTROL));
OUT_RING(ring, A2XX_RB_MODECONTROL_EDRAM_MODE(COLOR_DEPTH));
}
 
/* transfer from system memory to gmem */
 
static void
emit_mem2gmem_surf(struct fd_context *ctx, uint32_t base,
struct pipe_surface *psurf)
{
struct fd_ringbuffer *ring = ctx->ring;
struct fd_resource *rsc = fd_resource(psurf->texture);
uint32_t swiz;
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_RB_COLOR_INFO));
OUT_RING(ring, A2XX_RB_COLOR_INFO_SWAP(fmt2swap(psurf->format)) |
A2XX_RB_COLOR_INFO_BASE(base) |
A2XX_RB_COLOR_INFO_FORMAT(fd2_pipe2color(psurf->format)));
 
swiz = fd2_tex_swiz(psurf->format, PIPE_SWIZZLE_RED, PIPE_SWIZZLE_GREEN,
PIPE_SWIZZLE_BLUE, PIPE_SWIZZLE_ALPHA);
 
/* emit fb as a texture: */
OUT_PKT3(ring, CP_SET_CONSTANT, 7);
OUT_RING(ring, 0x00010000);
OUT_RING(ring, A2XX_SQ_TEX_0_CLAMP_X(SQ_TEX_WRAP) |
A2XX_SQ_TEX_0_CLAMP_Y(SQ_TEX_WRAP) |
A2XX_SQ_TEX_0_CLAMP_Z(SQ_TEX_WRAP) |
A2XX_SQ_TEX_0_PITCH(rsc->slices[0].pitch));
OUT_RELOC(ring, rsc->bo, 0,
fd2_pipe2surface(psurf->format) | 0x800, 0);
OUT_RING(ring, A2XX_SQ_TEX_2_WIDTH(psurf->width - 1) |
A2XX_SQ_TEX_2_HEIGHT(psurf->height - 1));
OUT_RING(ring, 0x01000000 | // XXX
swiz |
A2XX_SQ_TEX_3_XY_MAG_FILTER(SQ_TEX_FILTER_POINT) |
A2XX_SQ_TEX_3_XY_MIN_FILTER(SQ_TEX_FILTER_POINT));
OUT_RING(ring, 0x00000000);
OUT_RING(ring, 0x00000200);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 3);
OUT_RING(ring, CP_REG(REG_A2XX_VGT_MAX_VTX_INDX));
OUT_RING(ring, 3); /* VGT_MAX_VTX_INDX */
OUT_RING(ring, 0); /* VGT_MIN_VTX_INDX */
 
fd_draw(ctx, ring, DI_PT_RECTLIST, IGNORE_VISIBILITY,
DI_SRC_SEL_AUTO_INDEX, 3, 0, INDEX_SIZE_IGN, 0, 0, NULL);
}
 
static void
fd2_emit_tile_mem2gmem(struct fd_context *ctx, struct fd_tile *tile)
{
struct fd2_context *fd2_ctx = fd2_context(ctx);
struct fd_ringbuffer *ring = ctx->ring;
struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
unsigned bin_w = tile->bin_w;
unsigned bin_h = tile->bin_h;
float x0, y0, x1, y1;
 
fd2_emit_vertex_bufs(ring, 0x9c, (struct fd2_vertex_buf[]) {
{ .prsc = fd2_ctx->solid_vertexbuf, .size = 48, .offset = 0x30 },
{ .prsc = fd2_ctx->solid_vertexbuf, .size = 32, .offset = 0x60 },
}, 2);
 
/* write texture coordinates to vertexbuf: */
x0 = ((float)tile->xoff) / ((float)pfb->width);
x1 = ((float)tile->xoff + bin_w) / ((float)pfb->width);
y0 = ((float)tile->yoff) / ((float)pfb->height);
y1 = ((float)tile->yoff + bin_h) / ((float)pfb->height);
OUT_PKT3(ring, CP_MEM_WRITE, 9);
OUT_RELOC(ring, fd_resource(fd2_ctx->solid_vertexbuf)->bo, 0x60, 0, 0);
OUT_RING(ring, fui(x0));
OUT_RING(ring, fui(y0));
OUT_RING(ring, fui(x1));
OUT_RING(ring, fui(y0));
OUT_RING(ring, fui(x0));
OUT_RING(ring, fui(y1));
OUT_RING(ring, fui(x1));
OUT_RING(ring, fui(y1));
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_VGT_INDX_OFFSET));
OUT_RING(ring, 0);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_VGT_VERTEX_REUSE_BLOCK_CNTL));
OUT_RING(ring, 0x0000003b);
 
fd2_program_emit(ring, &ctx->blit_prog[0]);
 
OUT_PKT0(ring, REG_A2XX_TC_CNTL_STATUS, 1);
OUT_RING(ring, A2XX_TC_CNTL_STATUS_L2_INVALIDATE);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_RB_DEPTHCONTROL));
OUT_RING(ring, A2XX_RB_DEPTHCONTROL_EARLY_Z_ENABLE);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_PA_SU_SC_MODE_CNTL));
OUT_RING(ring, A2XX_PA_SU_SC_MODE_CNTL_PROVOKING_VTX_LAST |
A2XX_PA_SU_SC_MODE_CNTL_FRONT_PTYPE(PC_DRAW_TRIANGLES) |
A2XX_PA_SU_SC_MODE_CNTL_BACK_PTYPE(PC_DRAW_TRIANGLES));
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_AA_MASK));
OUT_RING(ring, 0x0000ffff);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_RB_COLORCONTROL));
OUT_RING(ring, A2XX_RB_COLORCONTROL_ALPHA_FUNC(PIPE_FUNC_ALWAYS) |
A2XX_RB_COLORCONTROL_BLEND_DISABLE |
A2XX_RB_COLORCONTROL_ROP_CODE(12) |
A2XX_RB_COLORCONTROL_DITHER_MODE(DITHER_DISABLE) |
A2XX_RB_COLORCONTROL_DITHER_TYPE(DITHER_PIXEL));
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_RB_BLEND_CONTROL));
OUT_RING(ring, A2XX_RB_BLEND_CONTROL_COLOR_SRCBLEND(FACTOR_ONE) |
A2XX_RB_BLEND_CONTROL_COLOR_COMB_FCN(BLEND_DST_PLUS_SRC) |
A2XX_RB_BLEND_CONTROL_COLOR_DESTBLEND(FACTOR_ZERO) |
A2XX_RB_BLEND_CONTROL_ALPHA_SRCBLEND(FACTOR_ONE) |
A2XX_RB_BLEND_CONTROL_ALPHA_COMB_FCN(BLEND_DST_PLUS_SRC) |
A2XX_RB_BLEND_CONTROL_ALPHA_DESTBLEND(FACTOR_ZERO));
 
OUT_PKT3(ring, CP_SET_CONSTANT, 3);
OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_WINDOW_SCISSOR_TL));
OUT_RING(ring, A2XX_PA_SC_WINDOW_OFFSET_DISABLE |
xy2d(0,0)); /* PA_SC_WINDOW_SCISSOR_TL */
OUT_RING(ring, xy2d(bin_w, bin_h)); /* PA_SC_WINDOW_SCISSOR_BR */
 
OUT_PKT3(ring, CP_SET_CONSTANT, 5);
OUT_RING(ring, CP_REG(REG_A2XX_PA_CL_VPORT_XSCALE));
OUT_RING(ring, fui((float)bin_w/2.0)); /* PA_CL_VPORT_XSCALE */
OUT_RING(ring, fui((float)bin_w/2.0)); /* PA_CL_VPORT_XOFFSET */
OUT_RING(ring, fui(-(float)bin_h/2.0)); /* PA_CL_VPORT_YSCALE */
OUT_RING(ring, fui((float)bin_h/2.0)); /* PA_CL_VPORT_YOFFSET */
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_PA_CL_VTE_CNTL));
OUT_RING(ring, A2XX_PA_CL_VTE_CNTL_VTX_XY_FMT |
A2XX_PA_CL_VTE_CNTL_VTX_Z_FMT | // XXX check this???
A2XX_PA_CL_VTE_CNTL_VPORT_X_SCALE_ENA |
A2XX_PA_CL_VTE_CNTL_VPORT_X_OFFSET_ENA |
A2XX_PA_CL_VTE_CNTL_VPORT_Y_SCALE_ENA |
A2XX_PA_CL_VTE_CNTL_VPORT_Y_OFFSET_ENA);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_PA_CL_CLIP_CNTL));
OUT_RING(ring, 0x00000000);
 
if (fd_gmem_needs_restore(ctx, tile, FD_BUFFER_DEPTH | FD_BUFFER_STENCIL))
emit_mem2gmem_surf(ctx, bin_w * bin_h, pfb->zsbuf);
 
if (fd_gmem_needs_restore(ctx, tile, FD_BUFFER_COLOR))
emit_mem2gmem_surf(ctx, 0, pfb->cbufs[0]);
 
/* TODO blob driver seems to toss in a CACHE_FLUSH after each DRAW_INDX.. */
}
 
/* before first tile */
static void
fd2_emit_tile_init(struct fd_context *ctx)
{
struct fd_ringbuffer *ring = ctx->ring;
struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
struct fd_gmem_stateobj *gmem = &ctx->gmem;
enum pipe_format format = pipe_surface_format(pfb->cbufs[0]);
uint32_t reg;
 
OUT_PKT3(ring, CP_SET_CONSTANT, 4);
OUT_RING(ring, CP_REG(REG_A2XX_RB_SURFACE_INFO));
OUT_RING(ring, gmem->bin_w); /* RB_SURFACE_INFO */
OUT_RING(ring, A2XX_RB_COLOR_INFO_SWAP(fmt2swap(format)) |
A2XX_RB_COLOR_INFO_FORMAT(fd2_pipe2color(format)));
reg = A2XX_RB_DEPTH_INFO_DEPTH_BASE(align(gmem->bin_w * gmem->bin_h, 4));
if (pfb->zsbuf)
reg |= A2XX_RB_DEPTH_INFO_DEPTH_FORMAT(fd_pipe2depth(pfb->zsbuf->format));
OUT_RING(ring, reg); /* RB_DEPTH_INFO */
}
 
/* before mem2gmem */
static void
fd2_emit_tile_prep(struct fd_context *ctx, struct fd_tile *tile)
{
struct fd_ringbuffer *ring = ctx->ring;
struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
enum pipe_format format = pipe_surface_format(pfb->cbufs[0]);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_RB_COLOR_INFO));
OUT_RING(ring, A2XX_RB_COLOR_INFO_SWAP(1) | /* RB_COLOR_INFO */
A2XX_RB_COLOR_INFO_FORMAT(fd2_pipe2color(format)));
 
/* setup screen scissor for current tile (same for mem2gmem): */
OUT_PKT3(ring, CP_SET_CONSTANT, 3);
OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_SCREEN_SCISSOR_TL));
OUT_RING(ring, A2XX_PA_SC_SCREEN_SCISSOR_TL_X(0) |
A2XX_PA_SC_SCREEN_SCISSOR_TL_Y(0));
OUT_RING(ring, A2XX_PA_SC_SCREEN_SCISSOR_BR_X(tile->bin_w) |
A2XX_PA_SC_SCREEN_SCISSOR_BR_Y(tile->bin_h));
}
 
/* before IB to rendering cmds: */
static void
fd2_emit_tile_renderprep(struct fd_context *ctx, struct fd_tile *tile)
{
struct fd_ringbuffer *ring = ctx->ring;
struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
enum pipe_format format = pipe_surface_format(pfb->cbufs[0]);
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_RB_COLOR_INFO));
OUT_RING(ring, A2XX_RB_COLOR_INFO_SWAP(fmt2swap(format)) |
A2XX_RB_COLOR_INFO_FORMAT(fd2_pipe2color(format)));
 
/* setup window scissor and offset for current tile (different
* from mem2gmem):
*/
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_WINDOW_OFFSET));
OUT_RING(ring, A2XX_PA_SC_WINDOW_OFFSET_X(-tile->xoff) |
A2XX_PA_SC_WINDOW_OFFSET_Y(-tile->yoff));
}
 
void
fd2_gmem_init(struct pipe_context *pctx)
{
struct fd_context *ctx = fd_context(pctx);
 
ctx->emit_tile_init = fd2_emit_tile_init;
ctx->emit_tile_prep = fd2_emit_tile_prep;
ctx->emit_tile_mem2gmem = fd2_emit_tile_mem2gmem;
ctx->emit_tile_renderprep = fd2_emit_tile_renderprep;
ctx->emit_tile_gmem2mem = fd2_emit_tile_gmem2mem;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a2xx/fd2_gmem.h
0,0 → 1,36
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FD2_GMEM_H_
#define FD2_GMEM_H_
 
#include "pipe/p_context.h"
 
void fd2_gmem_init(struct pipe_context *pctx);
 
#endif /* FD2_GMEM_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a2xx/fd2_program.c
0,0 → 1,479
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "pipe/p_state.h"
#include "util/u_string.h"
#include "util/u_memory.h"
#include "util/u_inlines.h"
#include "util/u_format.h"
#include "tgsi/tgsi_dump.h"
#include "tgsi/tgsi_parse.h"
 
#include "freedreno_program.h"
 
#include "fd2_program.h"
#include "fd2_compiler.h"
#include "fd2_texture.h"
#include "fd2_util.h"
 
static struct fd2_shader_stateobj *
create_shader(enum shader_t type)
{
struct fd2_shader_stateobj *so = CALLOC_STRUCT(fd2_shader_stateobj);
if (!so)
return NULL;
so->type = type;
return so;
}
 
static void
delete_shader(struct fd2_shader_stateobj *so)
{
ir2_shader_destroy(so->ir);
free(so->tokens);
free(so->bin);
free(so);
}
 
static struct fd2_shader_stateobj *
assemble(struct fd2_shader_stateobj *so)
{
free(so->bin);
so->bin = ir2_shader_assemble(so->ir, &so->info);
if (!so->bin)
goto fail;
 
if (fd_mesa_debug & FD_DBG_DISASM) {
DBG("disassemble: type=%d", so->type);
disasm_a2xx(so->bin, so->info.sizedwords, 0, so->type);
}
 
return so;
 
fail:
debug_error("assemble failed!");
delete_shader(so);
return NULL;
}
 
static struct fd2_shader_stateobj *
compile(struct fd_program_stateobj *prog, struct fd2_shader_stateobj *so)
{
int ret;
 
if (fd_mesa_debug & FD_DBG_DISASM) {
DBG("dump tgsi: type=%d", so->type);
tgsi_dump(so->tokens, 0);
}
 
ret = fd2_compile_shader(prog, so);
if (ret)
goto fail;
 
/* NOTE: we don't assemble yet because for VS we don't know the
* type information for vertex fetch yet.. so those need to be
* patched up later before assembling.
*/
 
so->info.sizedwords = 0;
 
return so;
 
fail:
debug_error("compile failed!");
delete_shader(so);
return NULL;
}
 
static void
emit(struct fd_ringbuffer *ring, struct fd2_shader_stateobj *so)
{
unsigned i;
 
if (so->info.sizedwords == 0)
assemble(so);
 
OUT_PKT3(ring, CP_IM_LOAD_IMMEDIATE, 2 + so->info.sizedwords);
OUT_RING(ring, (so->type == SHADER_VERTEX) ? 0 : 1);
OUT_RING(ring, so->info.sizedwords);
for (i = 0; i < so->info.sizedwords; i++)
OUT_RING(ring, so->bin[i]);
}
 
static void *
fd2_fp_state_create(struct pipe_context *pctx,
const struct pipe_shader_state *cso)
{
struct fd2_shader_stateobj *so = create_shader(SHADER_FRAGMENT);
if (!so)
return NULL;
so->tokens = tgsi_dup_tokens(cso->tokens);
return so;
}
 
static void
fd2_fp_state_delete(struct pipe_context *pctx, void *hwcso)
{
struct fd2_shader_stateobj *so = hwcso;
delete_shader(so);
}
 
static void *
fd2_vp_state_create(struct pipe_context *pctx,
const struct pipe_shader_state *cso)
{
struct fd2_shader_stateobj *so = create_shader(SHADER_VERTEX);
if (!so)
return NULL;
so->tokens = tgsi_dup_tokens(cso->tokens);
return so;
}
 
static void
fd2_vp_state_delete(struct pipe_context *pctx, void *hwcso)
{
struct fd2_shader_stateobj *so = hwcso;
delete_shader(so);
}
 
static void
patch_vtx_fetches(struct fd_context *ctx, struct fd2_shader_stateobj *so,
struct fd_vertex_stateobj *vtx)
{
unsigned i;
 
assert(so->num_vfetch_instrs == vtx->num_elements);
 
/* update vtx fetch instructions: */
for (i = 0; i < so->num_vfetch_instrs; i++) {
struct ir2_instruction *instr = so->vfetch_instrs[i];
struct pipe_vertex_element *elem = &vtx->pipe[i];
struct pipe_vertex_buffer *vb =
&ctx->vtx.vertexbuf.vb[elem->vertex_buffer_index];
enum pipe_format format = elem->src_format;
const struct util_format_description *desc =
util_format_description(format);
unsigned j;
 
/* Find the first non-VOID channel. */
for (j = 0; j < 4; j++)
if (desc->channel[j].type != UTIL_FORMAT_TYPE_VOID)
break;
 
/* CI/CIS can probably be set in compiler instead: */
instr->fetch.const_idx = 20 + (i / 3);
instr->fetch.const_idx_sel = i % 3;
 
instr->fetch.fmt = fd2_pipe2surface(format);
instr->fetch.is_normalized = desc->channel[j].normalized;
instr->fetch.is_signed =
desc->channel[j].type == UTIL_FORMAT_TYPE_SIGNED;
instr->fetch.stride = vb->stride ? : 1;
instr->fetch.offset = elem->src_offset;
 
for (j = 0; j < 4; j++)
instr->regs[0]->swizzle[j] = "xyzw01__"[desc->swizzle[j]];
 
assert(instr->fetch.fmt != ~0);
 
DBG("vtx[%d]: %s (%d), ci=%d, cis=%d, id=%d, swizzle=%s, "
"stride=%d, offset=%d",
i, util_format_name(format),
instr->fetch.fmt,
instr->fetch.const_idx,
instr->fetch.const_idx_sel,
elem->instance_divisor,
instr->regs[0]->swizzle,
instr->fetch.stride,
instr->fetch.offset);
}
 
/* trigger re-assemble: */
so->info.sizedwords = 0;
}
 
static void
patch_tex_fetches(struct fd_context *ctx, struct fd2_shader_stateobj *so,
struct fd_texture_stateobj *tex)
{
unsigned i;
 
/* update tex fetch instructions: */
for (i = 0; i < so->num_tfetch_instrs; i++) {
struct ir2_instruction *instr = so->tfetch_instrs[i].instr;
unsigned samp_id = so->tfetch_instrs[i].samp_id;
unsigned const_idx = fd2_get_const_idx(ctx, tex, samp_id);
 
if (const_idx != instr->fetch.const_idx) {
instr->fetch.const_idx = const_idx;
/* trigger re-assemble: */
so->info.sizedwords = 0;
}
}
}
 
void
fd2_program_validate(struct fd_context *ctx)
{
struct fd_program_stateobj *prog = &ctx->prog;
 
/* if vertex or frag shader is dirty, we may need to recompile. Compile
* frag shader first, as that assigns the register slots for exports
* from the vertex shader. And therefore if frag shader has changed we
* need to recompile both vert and frag shader.
*/
if (prog->dirty & FD_SHADER_DIRTY_FP)
compile(prog, prog->fp);
 
if (prog->dirty & (FD_SHADER_DIRTY_FP | FD_SHADER_DIRTY_VP))
compile(prog, prog->vp);
 
if (prog->dirty)
ctx->dirty |= FD_DIRTY_PROG;
 
/* if necessary, fix up vertex fetch instructions: */
if (ctx->dirty & (FD_DIRTY_VTXSTATE | FD_DIRTY_PROG))
patch_vtx_fetches(ctx, prog->vp, ctx->vtx.vtx);
 
/* if necessary, fix up texture fetch instructions: */
if (ctx->dirty & (FD_DIRTY_TEXSTATE | FD_DIRTY_PROG)) {
patch_tex_fetches(ctx, prog->vp, &ctx->verttex);
patch_tex_fetches(ctx, prog->fp, &ctx->fragtex);
}
}
 
void
fd2_program_emit(struct fd_ringbuffer *ring,
struct fd_program_stateobj *prog)
{
struct ir2_shader_info *vsi =
&((struct fd2_shader_stateobj *)prog->vp)->info;
struct ir2_shader_info *fsi =
&((struct fd2_shader_stateobj *)prog->fp)->info;
uint8_t vs_gprs, fs_gprs, vs_export;
 
emit(ring, prog->vp);
emit(ring, prog->fp);
 
vs_gprs = (vsi->max_reg < 0) ? 0x80 : vsi->max_reg;
fs_gprs = (fsi->max_reg < 0) ? 0x80 : fsi->max_reg;
vs_export = MAX2(1, prog->num_exports) - 1;
 
OUT_PKT3(ring, CP_SET_CONSTANT, 2);
OUT_RING(ring, CP_REG(REG_A2XX_SQ_PROGRAM_CNTL));
OUT_RING(ring, A2XX_SQ_PROGRAM_CNTL_PS_EXPORT_MODE(POSITION_2_VECTORS_SPRITE) |
A2XX_SQ_PROGRAM_CNTL_VS_RESOURCE |
A2XX_SQ_PROGRAM_CNTL_PS_RESOURCE |
A2XX_SQ_PROGRAM_CNTL_VS_EXPORT_COUNT(vs_export) |
A2XX_SQ_PROGRAM_CNTL_PS_REGS(fs_gprs) |
A2XX_SQ_PROGRAM_CNTL_VS_REGS(vs_gprs));
 
prog->dirty = 0;
}
 
/* Creates shader:
* EXEC ADDR(0x2) CNT(0x1)
* (S)FETCH: SAMPLE R0.xyzw = R0.xyx CONST(0) LOCATION(CENTER)
* ALLOC PARAM/PIXEL SIZE(0x0)
* EXEC_END ADDR(0x3) CNT(0x1)
* ALU: MAXv export0 = R0, R0 ; gl_FragColor
* NOP
*/
static struct fd2_shader_stateobj *
create_blit_fp(void)
{
struct fd2_shader_stateobj *so = create_shader(SHADER_FRAGMENT);
struct ir2_cf *cf;
struct ir2_instruction *instr;
 
if (!so)
return NULL;
 
so->ir = ir2_shader_create();
 
cf = ir2_cf_create(so->ir, EXEC);
 
instr = ir2_instr_create_tex_fetch(cf, 0);
ir2_reg_create(instr, 0, "xyzw", 0);
ir2_reg_create(instr, 0, "xyx", 0);
instr->sync = true;
 
cf = ir2_cf_create_alloc(so->ir, SQ_PARAMETER_PIXEL, 0);
cf = ir2_cf_create(so->ir, EXEC_END);
 
instr = ir2_instr_create_alu(cf, MAXv, ~0);
ir2_reg_create(instr, 0, NULL, IR2_REG_EXPORT);
ir2_reg_create(instr, 0, NULL, 0);
ir2_reg_create(instr, 0, NULL, 0);
 
return assemble(so);
}
 
/* Creates shader:
* EXEC ADDR(0x3) CNT(0x2)
* FETCH: VERTEX R1.xy01 = R0.x FMT_32_32_FLOAT UNSIGNED STRIDE(8) CONST(26, 1)
* FETCH: VERTEX R2.xyz1 = R0.x FMT_32_32_32_FLOAT UNSIGNED STRIDE(12) CONST(26, 0)
* ALLOC POSITION SIZE(0x0)
* EXEC ADDR(0x5) CNT(0x1)
* ALU: MAXv export62 = R2, R2 ; gl_Position
* ALLOC PARAM/PIXEL SIZE(0x0)
* EXEC_END ADDR(0x6) CNT(0x1)
* ALU: MAXv export0 = R1, R1
* NOP
*/
static struct fd2_shader_stateobj *
create_blit_vp(void)
{
struct fd2_shader_stateobj *so = create_shader(SHADER_VERTEX);
struct ir2_cf *cf;
struct ir2_instruction *instr;
 
if (!so)
return NULL;
 
so->ir = ir2_shader_create();
 
cf = ir2_cf_create(so->ir, EXEC);
 
instr = ir2_instr_create_vtx_fetch(cf, 26, 1, FMT_32_32_FLOAT, false, 8);
instr->fetch.is_normalized = true;
ir2_reg_create(instr, 1, "xy01", 0);
ir2_reg_create(instr, 0, "x", 0);
 
instr = ir2_instr_create_vtx_fetch(cf, 26, 0, FMT_32_32_32_FLOAT, false, 12);
instr->fetch.is_normalized = true;
ir2_reg_create(instr, 2, "xyz1", 0);
ir2_reg_create(instr, 0, "x", 0);
 
cf = ir2_cf_create_alloc(so->ir, SQ_POSITION, 0);
cf = ir2_cf_create(so->ir, EXEC);
 
instr = ir2_instr_create_alu(cf, MAXv, ~0);
ir2_reg_create(instr, 62, NULL, IR2_REG_EXPORT);
ir2_reg_create(instr, 2, NULL, 0);
ir2_reg_create(instr, 2, NULL, 0);
 
cf = ir2_cf_create_alloc(so->ir, SQ_PARAMETER_PIXEL, 0);
cf = ir2_cf_create(so->ir, EXEC_END);
 
instr = ir2_instr_create_alu(cf, MAXv, ~0);
ir2_reg_create(instr, 0, NULL, IR2_REG_EXPORT);
ir2_reg_create(instr, 1, NULL, 0);
ir2_reg_create(instr, 1, NULL, 0);
 
return assemble(so);
}
 
/* Creates shader:
* ALLOC PARAM/PIXEL SIZE(0x0)
* EXEC_END ADDR(0x1) CNT(0x1)
* ALU: MAXv export0 = C0, C0 ; gl_FragColor
*/
static struct fd2_shader_stateobj *
create_solid_fp(void)
{
struct fd2_shader_stateobj *so = create_shader(SHADER_FRAGMENT);
struct ir2_cf *cf;
struct ir2_instruction *instr;
 
if (!so)
return NULL;
 
so->ir = ir2_shader_create();
 
cf = ir2_cf_create_alloc(so->ir, SQ_PARAMETER_PIXEL, 0);
cf = ir2_cf_create(so->ir, EXEC_END);
 
instr = ir2_instr_create_alu(cf, MAXv, ~0);
ir2_reg_create(instr, 0, NULL, IR2_REG_EXPORT);
ir2_reg_create(instr, 0, NULL, IR2_REG_CONST);
ir2_reg_create(instr, 0, NULL, IR2_REG_CONST);
 
return assemble(so);
}
 
/* Creates shader:
* EXEC ADDR(0x3) CNT(0x1)
* (S)FETCH: VERTEX R1.xyz1 = R0.x FMT_32_32_32_FLOAT
* UNSIGNED STRIDE(12) CONST(26, 0)
* ALLOC POSITION SIZE(0x0)
* EXEC ADDR(0x4) CNT(0x1)
* ALU: MAXv export62 = R1, R1 ; gl_Position
* ALLOC PARAM/PIXEL SIZE(0x0)
* EXEC_END ADDR(0x5) CNT(0x0)
*/
static struct fd2_shader_stateobj *
create_solid_vp(void)
{
struct fd2_shader_stateobj *so = create_shader(SHADER_VERTEX);
struct ir2_cf *cf;
struct ir2_instruction *instr;
 
if (!so)
return NULL;
 
so->ir = ir2_shader_create();
 
cf = ir2_cf_create(so->ir, EXEC);
 
instr = ir2_instr_create_vtx_fetch(cf, 26, 0, FMT_32_32_32_FLOAT, false, 12);
ir2_reg_create(instr, 1, "xyz1", 0);
ir2_reg_create(instr, 0, "x", 0);
 
cf = ir2_cf_create_alloc(so->ir, SQ_POSITION, 0);
cf = ir2_cf_create(so->ir, EXEC);
 
instr = ir2_instr_create_alu(cf, MAXv, ~0);
ir2_reg_create(instr, 62, NULL, IR2_REG_EXPORT);
ir2_reg_create(instr, 1, NULL, 0);
ir2_reg_create(instr, 1, NULL, 0);
 
cf = ir2_cf_create_alloc(so->ir, SQ_PARAMETER_PIXEL, 0);
cf = ir2_cf_create(so->ir, EXEC_END);
 
return assemble(so);
}
 
void
fd2_prog_init(struct pipe_context *pctx)
{
struct fd_context *ctx = fd_context(pctx);
 
pctx->create_fs_state = fd2_fp_state_create;
pctx->delete_fs_state = fd2_fp_state_delete;
 
pctx->create_vs_state = fd2_vp_state_create;
pctx->delete_vs_state = fd2_vp_state_delete;
 
fd_prog_init(pctx);
 
ctx->solid_prog.fp = create_solid_fp();
ctx->solid_prog.vp = create_solid_vp();
ctx->blit_prog[0].fp = create_blit_fp();
ctx->blit_prog[0].vp = create_blit_vp();
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a2xx/fd2_program.h
0,0 → 1,81
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2012-2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FD2_PROGRAM_H_
#define FD2_PROGRAM_H_
 
#include "pipe/p_context.h"
 
#include "freedreno_context.h"
 
#include "ir-a2xx.h"
#include "disasm.h"
 
struct fd2_shader_stateobj {
enum shader_t type;
 
uint32_t *bin;
 
struct tgsi_token *tokens;
 
/* note that we defer compiling shader until we know both vs and ps..
* and if one changes, we potentially need to recompile in order to
* get varying linkages correct:
*/
struct ir2_shader_info info;
struct ir2_shader *ir;
 
/* for vertex shaders, the fetch instructions which need to be
* patched up before assembly:
*/
unsigned num_vfetch_instrs;
struct ir2_instruction *vfetch_instrs[64];
 
/* for all shaders, any tex fetch instructions which need to be
* patched before assembly:
*/
unsigned num_tfetch_instrs;
struct {
unsigned samp_id;
struct ir2_instruction *instr;
} tfetch_instrs[64];
 
unsigned first_immediate; /* const reg # of first immediate */
unsigned num_immediates;
struct {
uint32_t val[4];
} immediates[64];
};
 
void fd2_program_emit(struct fd_ringbuffer *ring,
struct fd_program_stateobj *prog);
void fd2_program_validate(struct fd_context *ctx);
 
void fd2_prog_init(struct pipe_context *pctx);
 
#endif /* FD2_PROGRAM_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a2xx/fd2_rasterizer.c
0,0 → 1,113
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2012-2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
 
#include "pipe/p_state.h"
#include "util/u_string.h"
#include "util/u_memory.h"
 
#include "fd2_rasterizer.h"
#include "fd2_context.h"
#include "fd2_util.h"
 
 
void *
fd2_rasterizer_state_create(struct pipe_context *pctx,
const struct pipe_rasterizer_state *cso)
{
struct fd2_rasterizer_stateobj *so;
float psize_min, psize_max;
 
so = CALLOC_STRUCT(fd2_rasterizer_stateobj);
if (!so)
return NULL;
 
if (cso->point_size_per_vertex) {
psize_min = util_get_min_point_size(cso);
psize_max = 8192;
} else {
/* Force the point size to be as if the vertex output was disabled. */
psize_min = cso->point_size;
psize_max = cso->point_size;
}
 
so->base = *cso;
 
so->pa_sc_line_stipple = cso->line_stipple_enable ?
A2XX_PA_SC_LINE_STIPPLE_LINE_PATTERN(cso->line_stipple_pattern) |
A2XX_PA_SC_LINE_STIPPLE_REPEAT_COUNT(cso->line_stipple_factor) : 0;
 
so->pa_cl_clip_cntl = 0; // TODO
 
so->pa_su_vtx_cntl =
A2XX_PA_SU_VTX_CNTL_PIX_CENTER(cso->half_pixel_center ? PIXCENTER_OGL : PIXCENTER_D3D) |
A2XX_PA_SU_VTX_CNTL_QUANT_MODE(ONE_SIXTEENTH);
 
so->pa_su_point_size =
A2XX_PA_SU_POINT_SIZE_HEIGHT(cso->point_size/2) |
A2XX_PA_SU_POINT_SIZE_WIDTH(cso->point_size/2);
 
so->pa_su_point_minmax =
A2XX_PA_SU_POINT_MINMAX_MIN(psize_min/2) |
A2XX_PA_SU_POINT_MINMAX_MAX(psize_max/2);
 
so->pa_su_line_cntl =
A2XX_PA_SU_LINE_CNTL_WIDTH(cso->line_width/2);
 
so->pa_su_sc_mode_cntl =
A2XX_PA_SU_SC_MODE_CNTL_VTX_WINDOW_OFFSET_ENABLE |
A2XX_PA_SU_SC_MODE_CNTL_FRONT_PTYPE(fd_polygon_mode(cso->fill_front)) |
A2XX_PA_SU_SC_MODE_CNTL_BACK_PTYPE(fd_polygon_mode(cso->fill_back));
 
if (cso->cull_face & PIPE_FACE_FRONT)
so->pa_su_sc_mode_cntl |= A2XX_PA_SU_SC_MODE_CNTL_CULL_FRONT;
if (cso->cull_face & PIPE_FACE_BACK)
so->pa_su_sc_mode_cntl |= A2XX_PA_SU_SC_MODE_CNTL_CULL_BACK;
if (!cso->flatshade_first)
so->pa_su_sc_mode_cntl |= A2XX_PA_SU_SC_MODE_CNTL_PROVOKING_VTX_LAST;
if (!cso->front_ccw)
so->pa_su_sc_mode_cntl |= A2XX_PA_SU_SC_MODE_CNTL_FACE;
if (cso->line_stipple_enable)
so->pa_su_sc_mode_cntl |= A2XX_PA_SU_SC_MODE_CNTL_LINE_STIPPLE_ENABLE;
if (cso->multisample)
so->pa_su_sc_mode_cntl |= A2XX_PA_SU_SC_MODE_CNTL_MSAA_ENABLE;
 
if (cso->fill_front != PIPE_POLYGON_MODE_FILL ||
cso->fill_back != PIPE_POLYGON_MODE_FILL)
so->pa_su_sc_mode_cntl |= A2XX_PA_SU_SC_MODE_CNTL_POLYMODE(POLY_DUALMODE);
else
so->pa_su_sc_mode_cntl |= A2XX_PA_SU_SC_MODE_CNTL_POLYMODE(POLY_DISABLED);
 
if (cso->offset_tri)
so->pa_su_sc_mode_cntl |=
A2XX_PA_SU_SC_MODE_CNTL_POLY_OFFSET_FRONT_ENABLE |
A2XX_PA_SU_SC_MODE_CNTL_POLY_OFFSET_BACK_ENABLE |
A2XX_PA_SU_SC_MODE_CNTL_POLY_OFFSET_PARA_ENABLE;
 
return so;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a2xx/fd2_rasterizer.h
0,0 → 1,55
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2012-2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FD2_RASTERIZER_H_
#define FD2_RASTERIZER_H_
 
#include "pipe/p_state.h"
#include "pipe/p_context.h"
 
struct fd2_rasterizer_stateobj {
struct pipe_rasterizer_state base;
uint32_t pa_sc_line_stipple;
uint32_t pa_cl_clip_cntl;
uint32_t pa_su_vtx_cntl;
uint32_t pa_su_point_size;
uint32_t pa_su_point_minmax;
uint32_t pa_su_line_cntl;
uint32_t pa_su_sc_mode_cntl;
};
 
static INLINE struct fd2_rasterizer_stateobj *
fd2_rasterizer_stateobj(struct pipe_rasterizer_state *rast)
{
return (struct fd2_rasterizer_stateobj *)rast;
}
 
void * fd2_rasterizer_state_create(struct pipe_context *pctx,
const struct pipe_rasterizer_state *cso);
 
#endif /* FD2_RASTERIZER_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a2xx/fd2_screen.c
0,0 → 1,110
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "pipe/p_screen.h"
#include "util/u_format.h"
 
#include "fd2_screen.h"
#include "fd2_context.h"
#include "fd2_util.h"
 
static boolean
fd2_screen_is_format_supported(struct pipe_screen *pscreen,
enum pipe_format format,
enum pipe_texture_target target,
unsigned sample_count,
unsigned usage)
{
unsigned retval = 0;
 
if ((target >= PIPE_MAX_TEXTURE_TYPES) ||
(sample_count > 1) || /* TODO add MSAA */
!util_format_is_supported(format, usage)) {
DBG("not supported: format=%s, target=%d, sample_count=%d, usage=%x",
util_format_name(format), target, sample_count, usage);
return FALSE;
}
 
/* TODO figure out how to render to other formats.. */
if ((usage & PIPE_BIND_RENDER_TARGET) &&
((format != PIPE_FORMAT_B8G8R8A8_UNORM) &&
(format != PIPE_FORMAT_B8G8R8X8_UNORM))) {
DBG("not supported render target: format=%s, target=%d, sample_count=%d, usage=%x",
util_format_name(format), target, sample_count, usage);
return FALSE;
}
 
if ((usage & (PIPE_BIND_SAMPLER_VIEW |
PIPE_BIND_VERTEX_BUFFER)) &&
(fd2_pipe2surface(format) != ~0)) {
retval |= usage & (PIPE_BIND_SAMPLER_VIEW |
PIPE_BIND_VERTEX_BUFFER);
}
 
if ((usage & (PIPE_BIND_RENDER_TARGET |
PIPE_BIND_DISPLAY_TARGET |
PIPE_BIND_SCANOUT |
PIPE_BIND_SHARED)) &&
(fd2_pipe2color(format) != ~0)) {
retval |= usage & (PIPE_BIND_RENDER_TARGET |
PIPE_BIND_DISPLAY_TARGET |
PIPE_BIND_SCANOUT |
PIPE_BIND_SHARED);
}
 
if ((usage & PIPE_BIND_DEPTH_STENCIL) &&
(fd_pipe2depth(format) != ~0)) {
retval |= PIPE_BIND_DEPTH_STENCIL;
}
 
if ((usage & PIPE_BIND_INDEX_BUFFER) &&
(fd_pipe2index(format) != ~0)) {
retval |= PIPE_BIND_INDEX_BUFFER;
}
 
if (usage & PIPE_BIND_TRANSFER_READ)
retval |= PIPE_BIND_TRANSFER_READ;
if (usage & PIPE_BIND_TRANSFER_WRITE)
retval |= PIPE_BIND_TRANSFER_WRITE;
 
if (retval != usage) {
DBG("not supported: format=%s, target=%d, sample_count=%d, "
"usage=%x, retval=%x", util_format_name(format),
target, sample_count, usage, retval);
}
 
return retval == usage;
}
 
void
fd2_screen_init(struct pipe_screen *pscreen)
{
fd_screen(pscreen)->max_rts = 1;
pscreen->context_create = fd2_context_create;
pscreen->is_format_supported = fd2_screen_is_format_supported;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a2xx/fd2_screen.h
0,0 → 1,36
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FD2_SCREEN_H_
#define FD2_SCREEN_H_
 
#include "pipe/p_screen.h"
 
void fd2_screen_init(struct pipe_screen *pscreen);
 
#endif /* FD2_SCREEN_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a2xx/fd2_texture.c
0,0 → 1,178
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2012-2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "pipe/p_state.h"
#include "util/u_string.h"
#include "util/u_memory.h"
#include "util/u_inlines.h"
 
#include "fd2_texture.h"
#include "fd2_util.h"
 
static enum sq_tex_clamp
tex_clamp(unsigned wrap)
{
switch (wrap) {
case PIPE_TEX_WRAP_REPEAT:
return SQ_TEX_WRAP;
case PIPE_TEX_WRAP_CLAMP:
return SQ_TEX_CLAMP_HALF_BORDER;
case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
return SQ_TEX_CLAMP_LAST_TEXEL;
case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
return SQ_TEX_CLAMP_BORDER;
case PIPE_TEX_WRAP_MIRROR_REPEAT:
return SQ_TEX_MIRROR;
case PIPE_TEX_WRAP_MIRROR_CLAMP:
return SQ_TEX_MIRROR_ONCE_HALF_BORDER;
case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
return SQ_TEX_MIRROR_ONCE_LAST_TEXEL;
case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
return SQ_TEX_MIRROR_ONCE_BORDER;
default:
DBG("invalid wrap: %u", wrap);
return 0;
}
}
 
static enum sq_tex_filter
tex_filter(unsigned filter)
{
switch (filter) {
case PIPE_TEX_FILTER_NEAREST:
return SQ_TEX_FILTER_POINT;
case PIPE_TEX_FILTER_LINEAR:
return SQ_TEX_FILTER_BILINEAR;
default:
DBG("invalid filter: %u", filter);
return 0;
}
}
 
static void *
fd2_sampler_state_create(struct pipe_context *pctx,
const struct pipe_sampler_state *cso)
{
struct fd2_sampler_stateobj *so = CALLOC_STRUCT(fd2_sampler_stateobj);
 
if (!so)
return NULL;
 
so->base = *cso;
 
/* SQ_TEX0_PITCH() must be OR'd in later when we know the bound texture: */
so->tex0 =
A2XX_SQ_TEX_0_CLAMP_X(tex_clamp(cso->wrap_s)) |
A2XX_SQ_TEX_0_CLAMP_Y(tex_clamp(cso->wrap_t)) |
A2XX_SQ_TEX_0_CLAMP_Z(tex_clamp(cso->wrap_r));
 
so->tex3 =
A2XX_SQ_TEX_3_XY_MAG_FILTER(tex_filter(cso->mag_img_filter)) |
A2XX_SQ_TEX_3_XY_MIN_FILTER(tex_filter(cso->min_img_filter));
 
so->tex4 = 0x00000000; /* ??? */
so->tex5 = 0x00000200; /* ??? */
 
return so;
}
 
static void
fd2_sampler_states_bind(struct pipe_context *pctx,
unsigned shader, unsigned start,
unsigned nr, void **hwcso)
{
if (shader == PIPE_SHADER_FRAGMENT) {
struct fd_context *ctx = fd_context(pctx);
 
/* on a2xx, since there is a flat address space for textures/samplers,
* a change in # of fragment textures/samplers will trigger patching and
* re-emitting the vertex shader:
*/
if (nr != ctx->fragtex.num_samplers)
ctx->dirty |= FD_DIRTY_TEXSTATE;
}
 
fd_sampler_states_bind(pctx, shader, start, nr, hwcso);
}
 
static struct pipe_sampler_view *
fd2_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc,
const struct pipe_sampler_view *cso)
{
struct fd2_pipe_sampler_view *so = CALLOC_STRUCT(fd2_pipe_sampler_view);
struct fd_resource *rsc = fd_resource(prsc);
 
if (!so)
return NULL;
 
so->base = *cso;
pipe_reference(NULL, &prsc->reference);
so->base.texture = prsc;
so->base.reference.count = 1;
so->base.context = pctx;
 
so->fmt = fd2_pipe2surface(cso->format);
 
so->tex0 = A2XX_SQ_TEX_0_PITCH(rsc->slices[0].pitch);
so->tex2 =
A2XX_SQ_TEX_2_HEIGHT(prsc->height0 - 1) |
A2XX_SQ_TEX_2_WIDTH(prsc->width0 - 1);
so->tex3 = fd2_tex_swiz(cso->format, cso->swizzle_r, cso->swizzle_g,
cso->swizzle_b, cso->swizzle_a);
 
return &so->base;
}
 
/* map gallium sampler-id to hw const-idx.. adreno uses a flat address
* space of samplers (const-idx), so we need to map the gallium sampler-id
* which is per-shader to a global const-idx space.
*
* Fragment shader sampler maps directly to const-idx, and vertex shader
* is offset by the # of fragment shader samplers. If the # of fragment
* shader samplers changes, this shifts the vertex shader indexes.
*
* TODO maybe we can do frag shader 0..N and vert shader N..0 to avoid
* this??
*/
unsigned
fd2_get_const_idx(struct fd_context *ctx, struct fd_texture_stateobj *tex,
unsigned samp_id)
{
if (tex == &ctx->fragtex)
return samp_id;
return samp_id + ctx->fragtex.num_samplers;
}
 
void
fd2_texture_init(struct pipe_context *pctx)
{
pctx->create_sampler_state = fd2_sampler_state_create;
pctx->bind_sampler_states = fd2_sampler_states_bind;
pctx->create_sampler_view = fd2_sampler_view_create;
pctx->set_sampler_views = fd_set_sampler_views;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a2xx/fd2_texture.h
0,0 → 1,68
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2012-2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FD2_TEXTURE_H_
#define FD2_TEXTURE_H_
 
#include "pipe/p_context.h"
 
#include "freedreno_texture.h"
#include "freedreno_resource.h"
 
#include "fd2_context.h"
#include "fd2_util.h"
 
struct fd2_sampler_stateobj {
struct pipe_sampler_state base;
uint32_t tex0, tex3, tex4, tex5;
};
 
static INLINE struct fd2_sampler_stateobj *
fd2_sampler_stateobj(struct pipe_sampler_state *samp)
{
return (struct fd2_sampler_stateobj *)samp;
}
 
struct fd2_pipe_sampler_view {
struct pipe_sampler_view base;
enum a2xx_sq_surfaceformat fmt;
uint32_t tex0, tex2, tex3;
};
 
static INLINE struct fd2_pipe_sampler_view *
fd2_pipe_sampler_view(struct pipe_sampler_view *pview)
{
return (struct fd2_pipe_sampler_view *)pview;
}
 
unsigned fd2_get_const_idx(struct fd_context *ctx,
struct fd_texture_stateobj *tex, unsigned samp_id);
 
void fd2_texture_init(struct pipe_context *pctx);
 
#endif /* FD2_TEXTURE_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a2xx/fd2_util.c
0,0 → 1,322
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "pipe/p_defines.h"
#include "util/u_format.h"
 
#include "fd2_util.h"
 
enum a2xx_sq_surfaceformat
fd2_pipe2surface(enum pipe_format format)
{
switch (format) {
/* 8-bit buffers. */
case PIPE_FORMAT_A8_UNORM:
case PIPE_FORMAT_A8_SNORM:
case PIPE_FORMAT_A8_UINT:
case PIPE_FORMAT_A8_SINT:
case PIPE_FORMAT_I8_UNORM:
case PIPE_FORMAT_I8_SNORM:
case PIPE_FORMAT_I8_UINT:
case PIPE_FORMAT_I8_SINT:
case PIPE_FORMAT_L8_UNORM:
case PIPE_FORMAT_L8_SNORM:
case PIPE_FORMAT_L8_UINT:
case PIPE_FORMAT_L8_SINT:
case PIPE_FORMAT_L8_SRGB:
case PIPE_FORMAT_R8_UNORM:
case PIPE_FORMAT_R8_SNORM:
case PIPE_FORMAT_R8_UINT:
case PIPE_FORMAT_R8_SINT:
return FMT_8;
 
/* 16-bit buffers. */
case PIPE_FORMAT_B5G6R5_UNORM:
return FMT_5_6_5;
case PIPE_FORMAT_B5G5R5A1_UNORM:
case PIPE_FORMAT_B5G5R5X1_UNORM:
return FMT_1_5_5_5;
case PIPE_FORMAT_B4G4R4A4_UNORM:
case PIPE_FORMAT_B4G4R4X4_UNORM:
return FMT_4_4_4_4;
case PIPE_FORMAT_Z16_UNORM:
return FMT_16;
case PIPE_FORMAT_L8A8_UNORM:
case PIPE_FORMAT_L8A8_SNORM:
case PIPE_FORMAT_L8A8_UINT:
case PIPE_FORMAT_L8A8_SINT:
case PIPE_FORMAT_L8A8_SRGB:
case PIPE_FORMAT_R8G8_UNORM:
case PIPE_FORMAT_R8G8_SNORM:
case PIPE_FORMAT_R8G8_UINT:
case PIPE_FORMAT_R8G8_SINT:
return FMT_8_8;
case PIPE_FORMAT_R16_UNORM:
case PIPE_FORMAT_R16_SNORM:
case PIPE_FORMAT_R16_UINT:
case PIPE_FORMAT_R16_SINT:
case PIPE_FORMAT_A16_UNORM:
case PIPE_FORMAT_A16_SNORM:
case PIPE_FORMAT_A16_UINT:
case PIPE_FORMAT_A16_SINT:
case PIPE_FORMAT_L16_UNORM:
case PIPE_FORMAT_L16_SNORM:
case PIPE_FORMAT_L16_UINT:
case PIPE_FORMAT_L16_SINT:
case PIPE_FORMAT_I16_UNORM:
case PIPE_FORMAT_I16_SNORM:
case PIPE_FORMAT_I16_UINT:
case PIPE_FORMAT_I16_SINT:
return FMT_16;
case PIPE_FORMAT_R16_FLOAT:
case PIPE_FORMAT_A16_FLOAT:
case PIPE_FORMAT_L16_FLOAT:
case PIPE_FORMAT_I16_FLOAT:
return FMT_16_FLOAT;
 
/* 32-bit buffers. */
case PIPE_FORMAT_A8B8G8R8_SRGB:
case PIPE_FORMAT_A8B8G8R8_UNORM:
case PIPE_FORMAT_A8R8G8B8_UNORM:
case PIPE_FORMAT_B8G8R8A8_SRGB:
case PIPE_FORMAT_B8G8R8A8_UNORM:
case PIPE_FORMAT_B8G8R8X8_UNORM:
case PIPE_FORMAT_R8G8B8A8_SNORM:
case PIPE_FORMAT_R8G8B8A8_UNORM:
case PIPE_FORMAT_R8G8B8X8_UNORM:
case PIPE_FORMAT_R8SG8SB8UX8U_NORM:
case PIPE_FORMAT_X8B8G8R8_UNORM:
case PIPE_FORMAT_X8R8G8B8_UNORM:
case PIPE_FORMAT_R8G8B8_UNORM:
case PIPE_FORMAT_R8G8B8A8_SINT:
case PIPE_FORMAT_R8G8B8A8_UINT:
return FMT_8_8_8_8;
case PIPE_FORMAT_R10G10B10A2_UNORM:
case PIPE_FORMAT_R10G10B10X2_SNORM:
case PIPE_FORMAT_B10G10R10A2_UNORM:
case PIPE_FORMAT_B10G10R10A2_UINT:
case PIPE_FORMAT_R10SG10SB10SA2U_NORM:
return FMT_2_10_10_10;
case PIPE_FORMAT_Z24X8_UNORM:
case PIPE_FORMAT_Z24_UNORM_S8_UINT:
return FMT_24_8;
case PIPE_FORMAT_R32_UINT:
case PIPE_FORMAT_R32_SINT:
case PIPE_FORMAT_A32_UINT:
case PIPE_FORMAT_A32_SINT:
case PIPE_FORMAT_L32_UINT:
case PIPE_FORMAT_L32_SINT:
case PIPE_FORMAT_I32_UINT:
case PIPE_FORMAT_I32_SINT:
return FMT_32;
case PIPE_FORMAT_R32_FLOAT:
case PIPE_FORMAT_A32_FLOAT:
case PIPE_FORMAT_L32_FLOAT:
case PIPE_FORMAT_I32_FLOAT:
case PIPE_FORMAT_Z32_FLOAT:
return FMT_32_FLOAT;
case PIPE_FORMAT_R16G16_FLOAT:
case PIPE_FORMAT_L16A16_FLOAT:
return FMT_16_16_FLOAT;
case PIPE_FORMAT_R16G16_UNORM:
case PIPE_FORMAT_R16G16_SNORM:
case PIPE_FORMAT_R16G16_UINT:
case PIPE_FORMAT_R16G16_SINT:
case PIPE_FORMAT_L16A16_UNORM:
case PIPE_FORMAT_L16A16_SNORM:
case PIPE_FORMAT_L16A16_UINT:
case PIPE_FORMAT_L16A16_SINT:
return FMT_16_16;
 
/* 64-bit buffers. */
case PIPE_FORMAT_R16G16B16A16_UINT:
case PIPE_FORMAT_R16G16B16A16_SINT:
case PIPE_FORMAT_R16G16B16A16_UNORM:
case PIPE_FORMAT_R16G16B16A16_SNORM:
return FMT_16_16_16_16;
case PIPE_FORMAT_R16G16B16A16_FLOAT:
return FMT_16_16_16_16_FLOAT;
case PIPE_FORMAT_R32G32_FLOAT:
case PIPE_FORMAT_L32A32_FLOAT:
return FMT_32_32_FLOAT;
case PIPE_FORMAT_R32G32_SINT:
case PIPE_FORMAT_R32G32_UINT:
case PIPE_FORMAT_L32A32_UINT:
case PIPE_FORMAT_L32A32_SINT:
return FMT_32_32;
 
/* 96-bit buffers. */
case PIPE_FORMAT_R32G32B32_FLOAT:
return FMT_32_32_32_FLOAT;
 
/* 128-bit buffers. */
case PIPE_FORMAT_R32G32B32A32_SNORM:
case PIPE_FORMAT_R32G32B32A32_UNORM:
case PIPE_FORMAT_R32G32B32A32_SINT:
case PIPE_FORMAT_R32G32B32A32_UINT:
return FMT_32_32_32_32;
case PIPE_FORMAT_R32G32B32A32_FLOAT:
return FMT_32_32_32_32_FLOAT;
 
/* YUV buffers. */
case PIPE_FORMAT_UYVY:
return FMT_Cr_Y1_Cb_Y0;
case PIPE_FORMAT_YUYV:
return FMT_Y1_Cr_Y0_Cb;
 
default:
return ~0;
}
}
 
enum a2xx_colorformatx
fd2_pipe2color(enum pipe_format format)
{
switch (format) {
/* 8-bit buffers. */
case PIPE_FORMAT_A8_UNORM:
case PIPE_FORMAT_A8_SNORM:
case PIPE_FORMAT_A8_UINT:
case PIPE_FORMAT_A8_SINT:
case PIPE_FORMAT_I8_UNORM:
case PIPE_FORMAT_I8_SNORM:
case PIPE_FORMAT_I8_UINT:
case PIPE_FORMAT_I8_SINT:
case PIPE_FORMAT_L8_UNORM:
case PIPE_FORMAT_L8_SNORM:
case PIPE_FORMAT_L8_UINT:
case PIPE_FORMAT_L8_SINT:
case PIPE_FORMAT_L8_SRGB:
case PIPE_FORMAT_R8_UNORM:
case PIPE_FORMAT_R8_SNORM:
case PIPE_FORMAT_R8_UINT:
case PIPE_FORMAT_R8_SINT:
return COLORX_8;
 
/* 16-bit buffers. */
case PIPE_FORMAT_B5G6R5_UNORM:
return COLORX_5_6_5;
case PIPE_FORMAT_B5G5R5A1_UNORM:
case PIPE_FORMAT_B5G5R5X1_UNORM:
return COLORX_1_5_5_5;
case PIPE_FORMAT_B4G4R4A4_UNORM:
case PIPE_FORMAT_B4G4R4X4_UNORM:
return COLORX_4_4_4_4;
case PIPE_FORMAT_L8A8_UNORM:
case PIPE_FORMAT_L8A8_SNORM:
case PIPE_FORMAT_L8A8_UINT:
case PIPE_FORMAT_L8A8_SINT:
case PIPE_FORMAT_L8A8_SRGB:
case PIPE_FORMAT_R8G8_UNORM:
case PIPE_FORMAT_R8G8_SNORM:
case PIPE_FORMAT_R8G8_UINT:
case PIPE_FORMAT_R8G8_SINT:
case PIPE_FORMAT_Z16_UNORM:
return COLORX_8_8;
case PIPE_FORMAT_R16_FLOAT:
case PIPE_FORMAT_A16_FLOAT:
case PIPE_FORMAT_L16_FLOAT:
case PIPE_FORMAT_I16_FLOAT:
return COLORX_16_FLOAT;
 
/* 32-bit buffers. */
case PIPE_FORMAT_A8B8G8R8_SRGB:
case PIPE_FORMAT_A8B8G8R8_UNORM:
case PIPE_FORMAT_A8R8G8B8_UNORM:
case PIPE_FORMAT_B8G8R8A8_SRGB:
case PIPE_FORMAT_B8G8R8A8_UNORM:
case PIPE_FORMAT_B8G8R8X8_UNORM:
case PIPE_FORMAT_R8G8B8A8_SNORM:
case PIPE_FORMAT_R8G8B8A8_UNORM:
case PIPE_FORMAT_R8G8B8X8_UNORM:
case PIPE_FORMAT_R8SG8SB8UX8U_NORM:
case PIPE_FORMAT_X8B8G8R8_UNORM:
case PIPE_FORMAT_X8R8G8B8_UNORM:
case PIPE_FORMAT_R8G8B8_UNORM:
case PIPE_FORMAT_R8G8B8A8_SINT:
case PIPE_FORMAT_R8G8B8A8_UINT:
case PIPE_FORMAT_Z24_UNORM_S8_UINT:
case PIPE_FORMAT_Z24X8_UNORM:
return COLORX_8_8_8_8;
case PIPE_FORMAT_R32_FLOAT:
case PIPE_FORMAT_A32_FLOAT:
case PIPE_FORMAT_L32_FLOAT:
case PIPE_FORMAT_I32_FLOAT:
case PIPE_FORMAT_Z32_FLOAT:
return COLORX_32_FLOAT;
case PIPE_FORMAT_R16G16_FLOAT:
case PIPE_FORMAT_L16A16_FLOAT:
return COLORX_16_16_FLOAT;
 
/* 64-bit buffers. */
case PIPE_FORMAT_R16G16B16A16_FLOAT:
return COLORX_16_16_16_16_FLOAT;
case PIPE_FORMAT_R32G32_FLOAT:
case PIPE_FORMAT_L32A32_FLOAT:
return COLORX_32_32_FLOAT;
 
/* 128-bit buffers. */
case PIPE_FORMAT_R32G32B32A32_FLOAT:
return COLORX_32_32_32_32_FLOAT;
 
default:
return ~0;
}
}
 
static inline enum sq_tex_swiz
tex_swiz(unsigned swiz)
{
switch (swiz) {
default:
case PIPE_SWIZZLE_RED: return SQ_TEX_X;
case PIPE_SWIZZLE_GREEN: return SQ_TEX_Y;
case PIPE_SWIZZLE_BLUE: return SQ_TEX_Z;
case PIPE_SWIZZLE_ALPHA: return SQ_TEX_W;
case PIPE_SWIZZLE_ZERO: return SQ_TEX_ZERO;
case PIPE_SWIZZLE_ONE: return SQ_TEX_ONE;
}
}
 
uint32_t
fd2_tex_swiz(enum pipe_format format, unsigned swizzle_r, unsigned swizzle_g,
unsigned swizzle_b, unsigned swizzle_a)
{
const struct util_format_description *desc =
util_format_description(format);
uint8_t swiz[] = {
swizzle_r, swizzle_g, swizzle_b, swizzle_a,
PIPE_SWIZZLE_ZERO, PIPE_SWIZZLE_ONE,
PIPE_SWIZZLE_ONE, PIPE_SWIZZLE_ONE,
};
 
return A2XX_SQ_TEX_3_SWIZ_X(tex_swiz(swiz[desc->swizzle[0]])) |
A2XX_SQ_TEX_3_SWIZ_Y(tex_swiz(swiz[desc->swizzle[1]])) |
A2XX_SQ_TEX_3_SWIZ_Z(tex_swiz(swiz[desc->swizzle[2]])) |
A2XX_SQ_TEX_3_SWIZ_W(tex_swiz(swiz[desc->swizzle[3]]));
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a2xx/fd2_util.h
0,0 → 1,47
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2012-2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FD2_UTIL_H_
#define FD2_UTIL_H_
 
#include "freedreno_util.h"
 
#include "a2xx.xml.h"
 
enum a2xx_sq_surfaceformat fd2_pipe2surface(enum pipe_format format);
enum a2xx_colorformatx fd2_pipe2color(enum pipe_format format);
uint32_t fd2_tex_swiz(enum pipe_format format, unsigned swizzle_r,
unsigned swizzle_g, unsigned swizzle_b, unsigned swizzle_a);
 
/* convert x,y to dword */
static inline uint32_t xy2d(uint16_t x, uint16_t y)
{
return ((y & 0x3fff) << 16) | (x & 0x3fff);
}
 
#endif /* FD2_UTIL_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a2xx/fd2_zsa.c
0,0 → 1,96
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
 
#include "pipe/p_state.h"
#include "util/u_string.h"
#include "util/u_memory.h"
 
#include "fd2_zsa.h"
#include "fd2_context.h"
#include "fd2_util.h"
 
void *
fd2_zsa_state_create(struct pipe_context *pctx,
const struct pipe_depth_stencil_alpha_state *cso)
{
struct fd2_zsa_stateobj *so;
 
so = CALLOC_STRUCT(fd2_zsa_stateobj);
if (!so)
return NULL;
 
so->base = *cso;
 
so->rb_depthcontrol |=
A2XX_RB_DEPTHCONTROL_ZFUNC(cso->depth.func); /* maps 1:1 */
 
if (cso->depth.enabled)
so->rb_depthcontrol |= A2XX_RB_DEPTHCONTROL_Z_ENABLE;
if (cso->depth.writemask)
so->rb_depthcontrol |= A2XX_RB_DEPTHCONTROL_Z_WRITE_ENABLE;
 
if (cso->stencil[0].enabled) {
const struct pipe_stencil_state *s = &cso->stencil[0];
 
so->rb_depthcontrol |=
A2XX_RB_DEPTHCONTROL_STENCIL_ENABLE |
A2XX_RB_DEPTHCONTROL_STENCILFUNC(s->func) | /* maps 1:1 */
A2XX_RB_DEPTHCONTROL_STENCILFAIL(fd_stencil_op(s->fail_op)) |
A2XX_RB_DEPTHCONTROL_STENCILZPASS(fd_stencil_op(s->zpass_op)) |
A2XX_RB_DEPTHCONTROL_STENCILZFAIL(fd_stencil_op(s->zfail_op));
so->rb_stencilrefmask |=
0xff000000 | /* ??? */
A2XX_RB_STENCILREFMASK_STENCILWRITEMASK(s->writemask) |
A2XX_RB_STENCILREFMASK_STENCILMASK(s->valuemask);
 
if (cso->stencil[1].enabled) {
const struct pipe_stencil_state *bs = &cso->stencil[1];
 
so->rb_depthcontrol |=
A2XX_RB_DEPTHCONTROL_BACKFACE_ENABLE |
A2XX_RB_DEPTHCONTROL_STENCILFUNC_BF(bs->func) | /* maps 1:1 */
A2XX_RB_DEPTHCONTROL_STENCILFAIL_BF(fd_stencil_op(bs->fail_op)) |
A2XX_RB_DEPTHCONTROL_STENCILZPASS_BF(fd_stencil_op(bs->zpass_op)) |
A2XX_RB_DEPTHCONTROL_STENCILZFAIL_BF(fd_stencil_op(bs->zfail_op));
so->rb_stencilrefmask_bf |=
0xff000000 | /* ??? */
A2XX_RB_STENCILREFMASK_STENCILWRITEMASK(bs->writemask) |
A2XX_RB_STENCILREFMASK_STENCILMASK(bs->valuemask);
}
}
 
if (cso->alpha.enabled) {
so->rb_colorcontrol =
A2XX_RB_COLORCONTROL_ALPHA_FUNC(cso->alpha.func) |
A2XX_RB_COLORCONTROL_ALPHA_TEST_ENABLE;
so->rb_alpha_ref = fui(cso->alpha.ref_value);
}
 
return so;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a2xx/fd2_zsa.h
0,0 → 1,56
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2012-2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FD2_ZSA_H_
#define FD2_ZSA_H_
 
 
#include "pipe/p_state.h"
#include "pipe/p_context.h"
 
#include "freedreno_util.h"
 
struct fd2_zsa_stateobj {
struct pipe_depth_stencil_alpha_state base;
uint32_t rb_depthcontrol;
uint32_t rb_colorcontrol; /* must be OR'd w/ blend->rb_colorcontrol */
uint32_t rb_alpha_ref;
uint32_t rb_stencilrefmask;
uint32_t rb_stencilrefmask_bf;
};
 
static INLINE struct fd2_zsa_stateobj *
fd2_zsa_stateobj(struct pipe_depth_stencil_alpha_state *zsa)
{
return (struct fd2_zsa_stateobj *)zsa;
}
 
void * fd2_zsa_state_create(struct pipe_context *pctx,
const struct pipe_depth_stencil_alpha_state *cso);
 
#endif /* FD2_ZSA_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a2xx/instr-a2xx.h
0,0 → 1,390
/*
* Copyright (c) 2012 Rob Clark <robdclark@gmail.com>
*
* 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.
*/
 
#ifndef INSTR_A2XX_H_
#define INSTR_A2XX_H_
 
#define PACKED __attribute__((__packed__))
 
#include "util/u_math.h"
#include "adreno_common.xml.h"
#include "adreno_pm4.xml.h"
#include "a2xx.xml.h"
 
 
/*
* ALU instructions:
*/
 
typedef enum {
ADDs = 0,
ADD_PREVs = 1,
MULs = 2,
MUL_PREVs = 3,
MUL_PREV2s = 4,
MAXs = 5,
MINs = 6,
SETEs = 7,
SETGTs = 8,
SETGTEs = 9,
SETNEs = 10,
FRACs = 11,
TRUNCs = 12,
FLOORs = 13,
EXP_IEEE = 14,
LOG_CLAMP = 15,
LOG_IEEE = 16,
RECIP_CLAMP = 17,
RECIP_FF = 18,
RECIP_IEEE = 19,
RECIPSQ_CLAMP = 20,
RECIPSQ_FF = 21,
RECIPSQ_IEEE = 22,
MOVAs = 23,
MOVA_FLOORs = 24,
SUBs = 25,
SUB_PREVs = 26,
PRED_SETEs = 27,
PRED_SETNEs = 28,
PRED_SETGTs = 29,
PRED_SETGTEs = 30,
PRED_SET_INVs = 31,
PRED_SET_POPs = 32,
PRED_SET_CLRs = 33,
PRED_SET_RESTOREs = 34,
KILLEs = 35,
KILLGTs = 36,
KILLGTEs = 37,
KILLNEs = 38,
KILLONEs = 39,
SQRT_IEEE = 40,
MUL_CONST_0 = 42,
MUL_CONST_1 = 43,
ADD_CONST_0 = 44,
ADD_CONST_1 = 45,
SUB_CONST_0 = 46,
SUB_CONST_1 = 47,
SIN = 48,
COS = 49,
RETAIN_PREV = 50,
} instr_scalar_opc_t;
 
typedef enum {
ADDv = 0,
MULv = 1,
MAXv = 2,
MINv = 3,
SETEv = 4,
SETGTv = 5,
SETGTEv = 6,
SETNEv = 7,
FRACv = 8,
TRUNCv = 9,
FLOORv = 10,
MULADDv = 11,
CNDEv = 12,
CNDGTEv = 13,
CNDGTv = 14,
DOT4v = 15,
DOT3v = 16,
DOT2ADDv = 17,
CUBEv = 18,
MAX4v = 19,
PRED_SETE_PUSHv = 20,
PRED_SETNE_PUSHv = 21,
PRED_SETGT_PUSHv = 22,
PRED_SETGTE_PUSHv = 23,
KILLEv = 24,
KILLGTv = 25,
KILLGTEv = 26,
KILLNEv = 27,
DSTv = 28,
MOVAv = 29,
} instr_vector_opc_t;
 
typedef struct PACKED {
/* dword0: */
uint8_t vector_dest : 6;
uint8_t vector_dest_rel : 1;
uint8_t low_precision_16b_fp : 1;
uint8_t scalar_dest : 6;
uint8_t scalar_dest_rel : 1;
uint8_t export_data : 1;
uint8_t vector_write_mask : 4;
uint8_t scalar_write_mask : 4;
uint8_t vector_clamp : 1;
uint8_t scalar_clamp : 1;
instr_scalar_opc_t scalar_opc : 6;
/* dword1: */
uint8_t src3_swiz : 8;
uint8_t src2_swiz : 8;
uint8_t src1_swiz : 8;
uint8_t src3_reg_negate : 1;
uint8_t src2_reg_negate : 1;
uint8_t src1_reg_negate : 1;
uint8_t pred_select : 2;
uint8_t relative_addr : 1;
uint8_t const_1_rel_abs : 1;
uint8_t const_0_rel_abs : 1;
/* dword2: */
uint8_t src3_reg : 6;
uint8_t src3_reg_select : 1;
uint8_t src3_reg_abs : 1;
uint8_t src2_reg : 6;
uint8_t src2_reg_select : 1;
uint8_t src2_reg_abs : 1;
uint8_t src1_reg : 6;
uint8_t src1_reg_select : 1;
uint8_t src1_reg_abs : 1;
instr_vector_opc_t vector_opc : 5;
uint8_t src3_sel : 1;
uint8_t src2_sel : 1;
uint8_t src1_sel : 1;
} instr_alu_t;
 
 
 
/*
* CF instructions:
*/
 
typedef enum {
NOP = 0,
EXEC = 1,
EXEC_END = 2,
COND_EXEC = 3,
COND_EXEC_END = 4,
COND_PRED_EXEC = 5,
COND_PRED_EXEC_END = 6,
LOOP_START = 7,
LOOP_END = 8,
COND_CALL = 9,
RETURN = 10,
COND_JMP = 11,
ALLOC = 12,
COND_EXEC_PRED_CLEAN = 13,
COND_EXEC_PRED_CLEAN_END = 14,
MARK_VS_FETCH_DONE = 15,
} instr_cf_opc_t;
 
typedef enum {
RELATIVE_ADDR = 0,
ABSOLUTE_ADDR = 1,
} instr_addr_mode_t;
 
typedef enum {
SQ_NO_ALLOC = 0,
SQ_POSITION = 1,
SQ_PARAMETER_PIXEL = 2,
SQ_MEMORY = 3,
} instr_alloc_type_t;
 
typedef struct PACKED {
uint16_t address : 9;
uint8_t reserved0 : 3;
uint8_t count : 3;
uint8_t yeild : 1;
uint16_t serialize : 12;
uint8_t vc : 6; /* vertex cache? */
uint8_t bool_addr : 8;
uint8_t condition : 1;
instr_addr_mode_t address_mode : 1;
instr_cf_opc_t opc : 4;
} instr_cf_exec_t;
 
typedef struct PACKED {
uint16_t address : 10;
uint8_t reserved0 : 6;
uint8_t loop_id : 5;
uint32_t reserved1 : 22;
instr_addr_mode_t address_mode : 1;
instr_cf_opc_t opc : 4;
} instr_cf_loop_t;
 
typedef struct PACKED {
uint16_t address : 10;
uint8_t reserved0 : 3;
uint8_t force_call : 1;
uint8_t predicated_jmp : 1;
uint32_t reserved1 : 18;
uint8_t direction : 1;
uint8_t bool_addr : 8;
uint8_t condition : 1;
instr_addr_mode_t address_mode : 1;
instr_cf_opc_t opc : 4;
} instr_cf_jmp_call_t;
 
typedef struct PACKED {
uint8_t size : 4;
uint64_t reserved0 : 36;
uint8_t no_serial : 1;
instr_alloc_type_t buffer_select : 2;
uint8_t alloc_mode : 1;
instr_cf_opc_t opc : 4;
} instr_cf_alloc_t;
 
typedef union PACKED {
instr_cf_exec_t exec;
instr_cf_loop_t loop;
instr_cf_jmp_call_t jmp_call;
instr_cf_alloc_t alloc;
struct PACKED {
uint64_t dummy : 44;
instr_cf_opc_t opc : 4;
};
} instr_cf_t;
 
 
 
/*
* FETCH instructions:
*/
 
typedef enum {
VTX_FETCH = 0,
TEX_FETCH = 1,
TEX_GET_BORDER_COLOR_FRAC = 16,
TEX_GET_COMP_TEX_LOD = 17,
TEX_GET_GRADIENTS = 18,
TEX_GET_WEIGHTS = 19,
TEX_SET_TEX_LOD = 24,
TEX_SET_GRADIENTS_H = 25,
TEX_SET_GRADIENTS_V = 26,
TEX_RESERVED_4 = 27,
} instr_fetch_opc_t;
 
typedef enum {
TEX_FILTER_POINT = 0,
TEX_FILTER_LINEAR = 1,
TEX_FILTER_BASEMAP = 2, /* only applicable for mip-filter */
TEX_FILTER_USE_FETCH_CONST = 3,
} instr_tex_filter_t;
 
typedef enum {
ANISO_FILTER_DISABLED = 0,
ANISO_FILTER_MAX_1_1 = 1,
ANISO_FILTER_MAX_2_1 = 2,
ANISO_FILTER_MAX_4_1 = 3,
ANISO_FILTER_MAX_8_1 = 4,
ANISO_FILTER_MAX_16_1 = 5,
ANISO_FILTER_USE_FETCH_CONST = 7,
} instr_aniso_filter_t;
 
typedef enum {
ARBITRARY_FILTER_2X4_SYM = 0,
ARBITRARY_FILTER_2X4_ASYM = 1,
ARBITRARY_FILTER_4X2_SYM = 2,
ARBITRARY_FILTER_4X2_ASYM = 3,
ARBITRARY_FILTER_4X4_SYM = 4,
ARBITRARY_FILTER_4X4_ASYM = 5,
ARBITRARY_FILTER_USE_FETCH_CONST = 7,
} instr_arbitrary_filter_t;
 
typedef enum {
SAMPLE_CENTROID = 0,
SAMPLE_CENTER = 1,
} instr_sample_loc_t;
 
typedef enum a2xx_sq_surfaceformat instr_surf_fmt_t;
 
typedef struct PACKED {
/* dword0: */
instr_fetch_opc_t opc : 5;
uint8_t src_reg : 6;
uint8_t src_reg_am : 1;
uint8_t dst_reg : 6;
uint8_t dst_reg_am : 1;
uint8_t fetch_valid_only : 1;
uint8_t const_idx : 5;
uint8_t tx_coord_denorm : 1;
uint8_t src_swiz : 6;
/* dword1: */
uint16_t dst_swiz : 12;
instr_tex_filter_t mag_filter : 2;
instr_tex_filter_t min_filter : 2;
instr_tex_filter_t mip_filter : 2;
instr_aniso_filter_t aniso_filter : 3;
instr_arbitrary_filter_t arbitrary_filter : 3;
instr_tex_filter_t vol_mag_filter : 2;
instr_tex_filter_t vol_min_filter : 2;
uint8_t use_comp_lod : 1;
uint8_t use_reg_lod : 2; /* 0 for cube, 1 for 2d */
uint8_t pred_select : 1;
/* dword2: */
uint8_t use_reg_gradients : 1;
instr_sample_loc_t sample_location : 1;
uint8_t lod_bias : 7;
uint8_t unused : 7;
uint8_t offset_x : 5;
uint8_t offset_y : 5;
uint8_t offset_z : 5;
uint8_t pred_condition : 1;
} instr_fetch_tex_t;
 
typedef struct PACKED {
/* dword0: */
instr_fetch_opc_t opc : 5;
uint8_t src_reg : 6;
uint8_t src_reg_am : 1;
uint8_t dst_reg : 6;
uint8_t dst_reg_am : 1;
uint8_t must_be_one : 1;
uint8_t const_index : 5;
uint8_t const_index_sel : 2;
uint8_t reserved0 : 3;
uint8_t src_swiz : 2;
/* dword1: */
uint16_t dst_swiz : 12;
uint8_t format_comp_all : 1; /* '1' for signed, '0' for unsigned? */
uint8_t num_format_all : 1; /* '0' for normalized, '1' for unnormalized */
uint8_t signed_rf_mode_all : 1;
uint8_t reserved1 : 1;
instr_surf_fmt_t format : 6;
uint8_t reserved2 : 1;
uint8_t exp_adjust_all : 7;
uint8_t reserved3 : 1;
uint8_t pred_select : 1;
/* dword2: */
uint8_t stride : 8;
/* possibly offset and reserved4 are swapped on a200? */
uint8_t offset : 8;
uint8_t reserved4 : 8;
uint8_t reserved5 : 7;
uint8_t pred_condition : 1;
} instr_fetch_vtx_t;
 
typedef union PACKED {
instr_fetch_tex_t tex;
instr_fetch_vtx_t vtx;
struct PACKED {
/* dword0: */
instr_fetch_opc_t opc : 5;
uint32_t dummy0 : 27;
/* dword1: */
uint32_t dummy1 : 32;
/* dword2: */
uint32_t dummy2 : 32;
};
} instr_fetch_t;
 
#endif /* INSTR_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a2xx/ir-a2xx.c
0,0 → 1,636
/*
* Copyright (c) 2012 Rob Clark <robdclark@gmail.com>
*
* 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 "ir-a2xx.h"
 
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
 
#include "freedreno_util.h"
#include "instr-a2xx.h"
 
#define DEBUG_MSG(f, ...) do { if (0) DBG(f, ##__VA_ARGS__); } while (0)
#define WARN_MSG(f, ...) DBG("WARN: "f, ##__VA_ARGS__)
#define ERROR_MSG(f, ...) DBG("ERROR: "f, ##__VA_ARGS__)
 
#define REG_MASK 0x3f
 
static int cf_emit(struct ir2_cf *cf, instr_cf_t *instr);
 
static int instr_emit(struct ir2_instruction *instr, uint32_t *dwords,
uint32_t idx, struct ir2_shader_info *info);
 
static void reg_update_stats(struct ir2_register *reg,
struct ir2_shader_info *info, bool dest);
static uint32_t reg_fetch_src_swiz(struct ir2_register *reg, uint32_t n);
static uint32_t reg_fetch_dst_swiz(struct ir2_register *reg);
static uint32_t reg_alu_dst_swiz(struct ir2_register *reg);
static uint32_t reg_alu_src_swiz(struct ir2_register *reg);
 
/* simple allocator to carve allocations out of an up-front allocated heap,
* so that we can free everything easily in one shot.
*/
static void * ir2_alloc(struct ir2_shader *shader, int sz)
{
void *ptr = &shader->heap[shader->heap_idx];
shader->heap_idx += align(sz, 4);
return ptr;
}
 
static char * ir2_strdup(struct ir2_shader *shader, const char *str)
{
char *ptr = NULL;
if (str) {
int len = strlen(str);
ptr = ir2_alloc(shader, len+1);
memcpy(ptr, str, len);
ptr[len] = '\0';
}
return ptr;
}
 
struct ir2_shader * ir2_shader_create(void)
{
DEBUG_MSG("");
return calloc(1, sizeof(struct ir2_shader));
}
 
void ir2_shader_destroy(struct ir2_shader *shader)
{
DEBUG_MSG("");
free(shader);
}
 
/* resolve addr/cnt/sequence fields in the individual CF's */
static int shader_resolve(struct ir2_shader *shader, struct ir2_shader_info *info)
{
uint32_t addr;
unsigned i;
int j;
 
addr = shader->cfs_count / 2;
for (i = 0; i < shader->cfs_count; i++) {
struct ir2_cf *cf = shader->cfs[i];
if ((cf->cf_type == EXEC) || (cf->cf_type == EXEC_END)) {
uint32_t sequence = 0;
 
if (cf->exec.addr && (cf->exec.addr != addr))
WARN_MSG("invalid addr '%d' at CF %d", cf->exec.addr, i);
if (cf->exec.cnt && (cf->exec.cnt != cf->exec.instrs_count))
WARN_MSG("invalid cnt '%d' at CF %d", cf->exec.cnt, i);
 
for (j = cf->exec.instrs_count - 1; j >= 0; j--) {
struct ir2_instruction *instr = cf->exec.instrs[j];
sequence <<= 2;
if (instr->instr_type == IR2_FETCH)
sequence |= 0x1;
if (instr->sync)
sequence |= 0x2;
}
 
cf->exec.addr = addr;
cf->exec.cnt = cf->exec.instrs_count;
cf->exec.sequence = sequence;
 
addr += cf->exec.instrs_count;
}
}
 
info->sizedwords = 3 * addr;
 
return 0;
}
 
void * ir2_shader_assemble(struct ir2_shader *shader, struct ir2_shader_info *info)
{
uint32_t i, j;
uint32_t *ptr, *dwords = NULL;
uint32_t idx = 0;
int ret;
 
info->sizedwords = 0;
info->max_reg = -1;
info->max_input_reg = 0;
info->regs_written = 0;
 
/* we need an even # of CF's.. insert a NOP if needed */
if (shader->cfs_count != align(shader->cfs_count, 2))
ir2_cf_create(shader, NOP);
 
/* first pass, resolve sizes and addresses: */
ret = shader_resolve(shader, info);
if (ret) {
ERROR_MSG("resolve failed: %d", ret);
goto fail;
}
 
ptr = dwords = calloc(4, info->sizedwords);
 
/* second pass, emit CF program in pairs: */
for (i = 0; i < shader->cfs_count; i += 2) {
instr_cf_t *cfs = (instr_cf_t *)ptr;
ret = cf_emit(shader->cfs[i], &cfs[0]);
if (ret) {
ERROR_MSG("CF emit failed: %d\n", ret);
goto fail;
}
ret = cf_emit(shader->cfs[i+1], &cfs[1]);
if (ret) {
ERROR_MSG("CF emit failed: %d\n", ret);
goto fail;
}
ptr += 3;
assert((ptr - dwords) <= info->sizedwords);
}
 
/* third pass, emit ALU/FETCH: */
for (i = 0; i < shader->cfs_count; i++) {
struct ir2_cf *cf = shader->cfs[i];
if ((cf->cf_type == EXEC) || (cf->cf_type == EXEC_END)) {
for (j = 0; j < cf->exec.instrs_count; j++) {
ret = instr_emit(cf->exec.instrs[j], ptr, idx++, info);
if (ret) {
ERROR_MSG("instruction emit failed: %d", ret);
goto fail;
}
ptr += 3;
assert((ptr - dwords) <= info->sizedwords);
}
}
}
 
return dwords;
 
fail:
free(dwords);
return NULL;
}
 
 
struct ir2_cf * ir2_cf_create(struct ir2_shader *shader, instr_cf_opc_t cf_type)
{
struct ir2_cf *cf = ir2_alloc(shader, sizeof(struct ir2_cf));
DEBUG_MSG("%d", cf_type);
cf->shader = shader;
cf->cf_type = cf_type;
assert(shader->cfs_count < ARRAY_SIZE(shader->cfs));
shader->cfs[shader->cfs_count++] = cf;
return cf;
}
 
 
/*
* CF instructions:
*/
 
static int cf_emit(struct ir2_cf *cf, instr_cf_t *instr)
{
memset(instr, 0, sizeof(*instr));
 
instr->opc = cf->cf_type;
 
switch (cf->cf_type) {
case NOP:
break;
case EXEC:
case EXEC_END:
assert(cf->exec.addr <= 0x1ff);
assert(cf->exec.cnt <= 0x6);
assert(cf->exec.sequence <= 0xfff);
instr->exec.address = cf->exec.addr;
instr->exec.count = cf->exec.cnt;
instr->exec.serialize = cf->exec.sequence;
break;
case ALLOC:
assert(cf->alloc.size <= 0xf);
instr->alloc.size = cf->alloc.size;
switch (cf->alloc.type) {
case SQ_POSITION:
case SQ_PARAMETER_PIXEL:
instr->alloc.buffer_select = cf->alloc.type;
break;
default:
ERROR_MSG("invalid alloc type: %d", cf->alloc.type);
return -1;
}
break;
case COND_EXEC:
case COND_EXEC_END:
case COND_PRED_EXEC:
case COND_PRED_EXEC_END:
case LOOP_START:
case LOOP_END:
case COND_CALL:
case RETURN:
case COND_JMP:
case COND_EXEC_PRED_CLEAN:
case COND_EXEC_PRED_CLEAN_END:
case MARK_VS_FETCH_DONE:
ERROR_MSG("TODO");
return -1;
}
 
return 0;
}
 
 
struct ir2_instruction * ir2_instr_create(struct ir2_cf *cf, int instr_type)
{
struct ir2_instruction *instr =
ir2_alloc(cf->shader, sizeof(struct ir2_instruction));
DEBUG_MSG("%d", instr_type);
instr->shader = cf->shader;
instr->pred = cf->shader->pred;
instr->instr_type = instr_type;
assert(cf->exec.instrs_count < ARRAY_SIZE(cf->exec.instrs));
cf->exec.instrs[cf->exec.instrs_count++] = instr;
return instr;
}
 
 
/*
* FETCH instructions:
*/
 
static int instr_emit_fetch(struct ir2_instruction *instr,
uint32_t *dwords, uint32_t idx,
struct ir2_shader_info *info)
{
instr_fetch_t *fetch = (instr_fetch_t *)dwords;
int reg = 0;
struct ir2_register *dst_reg = instr->regs[reg++];
struct ir2_register *src_reg = instr->regs[reg++];
 
memset(fetch, 0, sizeof(*fetch));
 
reg_update_stats(dst_reg, info, true);
reg_update_stats(src_reg, info, false);
 
fetch->opc = instr->fetch.opc;
 
if (instr->fetch.opc == VTX_FETCH) {
instr_fetch_vtx_t *vtx = &fetch->vtx;
 
assert(instr->fetch.stride <= 0xff);
assert(instr->fetch.fmt <= 0x3f);
assert(instr->fetch.const_idx <= 0x1f);
assert(instr->fetch.const_idx_sel <= 0x3);
 
vtx->src_reg = src_reg->num;
vtx->src_swiz = reg_fetch_src_swiz(src_reg, 1);
vtx->dst_reg = dst_reg->num;
vtx->dst_swiz = reg_fetch_dst_swiz(dst_reg);
vtx->must_be_one = 1;
vtx->const_index = instr->fetch.const_idx;
vtx->const_index_sel = instr->fetch.const_idx_sel;
vtx->format_comp_all = !!instr->fetch.is_signed;
vtx->num_format_all = !instr->fetch.is_normalized;
vtx->format = instr->fetch.fmt;
vtx->stride = instr->fetch.stride;
vtx->offset = instr->fetch.offset;
 
if (instr->pred != IR2_PRED_NONE) {
vtx->pred_select = 1;
vtx->pred_condition = (instr->pred == IR2_PRED_EQ) ? 1 : 0;
}
 
/* XXX seems like every FETCH but the first has
* this bit set:
*/
vtx->reserved3 = (idx > 0) ? 0x1 : 0x0;
vtx->reserved0 = (idx > 0) ? 0x2 : 0x3;
} else if (instr->fetch.opc == TEX_FETCH) {
instr_fetch_tex_t *tex = &fetch->tex;
 
assert(instr->fetch.const_idx <= 0x1f);
 
tex->src_reg = src_reg->num;
tex->src_swiz = reg_fetch_src_swiz(src_reg, 3);
tex->dst_reg = dst_reg->num;
tex->dst_swiz = reg_fetch_dst_swiz(dst_reg);
tex->const_idx = instr->fetch.const_idx;
tex->mag_filter = TEX_FILTER_USE_FETCH_CONST;
tex->min_filter = TEX_FILTER_USE_FETCH_CONST;
tex->mip_filter = TEX_FILTER_USE_FETCH_CONST;
tex->aniso_filter = ANISO_FILTER_USE_FETCH_CONST;
tex->arbitrary_filter = ARBITRARY_FILTER_USE_FETCH_CONST;
tex->vol_mag_filter = TEX_FILTER_USE_FETCH_CONST;
tex->vol_min_filter = TEX_FILTER_USE_FETCH_CONST;
tex->use_comp_lod = 1;
tex->use_reg_lod = !instr->fetch.is_cube;
tex->sample_location = SAMPLE_CENTER;
 
if (instr->pred != IR2_PRED_NONE) {
tex->pred_select = 1;
tex->pred_condition = (instr->pred == IR2_PRED_EQ) ? 1 : 0;
}
 
} else {
ERROR_MSG("invalid fetch opc: %d\n", instr->fetch.opc);
return -1;
}
 
return 0;
}
 
/*
* ALU instructions:
*/
 
static int instr_emit_alu(struct ir2_instruction *instr, uint32_t *dwords,
struct ir2_shader_info *info)
{
int reg = 0;
instr_alu_t *alu = (instr_alu_t *)dwords;
struct ir2_register *dst_reg = instr->regs[reg++];
struct ir2_register *src1_reg;
struct ir2_register *src2_reg;
struct ir2_register *src3_reg;
 
memset(alu, 0, sizeof(*alu));
 
/* handle instructions w/ 3 src operands: */
switch (instr->alu.vector_opc) {
case MULADDv:
case CNDEv:
case CNDGTEv:
case CNDGTv:
case DOT2ADDv:
/* note: disassembler lists 3rd src first, ie:
* MULADDv Rdst = Rsrc3 + (Rsrc1 * Rsrc2)
* which is the reason for this strange ordering.
*/
src3_reg = instr->regs[reg++];
break;
default:
src3_reg = NULL;
break;
}
 
src1_reg = instr->regs[reg++];
src2_reg = instr->regs[reg++];
 
reg_update_stats(dst_reg, info, true);
reg_update_stats(src1_reg, info, false);
reg_update_stats(src2_reg, info, false);
 
assert((dst_reg->flags & ~IR2_REG_EXPORT) == 0);
assert(!dst_reg->swizzle || (strlen(dst_reg->swizzle) == 4));
assert((src1_reg->flags & IR2_REG_EXPORT) == 0);
assert(!src1_reg->swizzle || (strlen(src1_reg->swizzle) == 4));
assert((src2_reg->flags & IR2_REG_EXPORT) == 0);
assert(!src2_reg->swizzle || (strlen(src2_reg->swizzle) == 4));
 
if (instr->alu.vector_opc == ~0) {
alu->vector_opc = MAXv;
alu->vector_write_mask = 0;
} else {
alu->vector_opc = instr->alu.vector_opc;
alu->vector_write_mask = reg_alu_dst_swiz(dst_reg);
}
 
alu->vector_dest = dst_reg->num;
alu->export_data = !!(dst_reg->flags & IR2_REG_EXPORT);
 
// TODO predicate case/condition.. need to add to parser
 
alu->src2_reg = src2_reg->num;
alu->src2_swiz = reg_alu_src_swiz(src2_reg);
alu->src2_reg_negate = !!(src2_reg->flags & IR2_REG_NEGATE);
alu->src2_reg_abs = !!(src2_reg->flags & IR2_REG_ABS);
alu->src2_sel = !(src2_reg->flags & IR2_REG_CONST);
 
alu->src1_reg = src1_reg->num;
alu->src1_swiz = reg_alu_src_swiz(src1_reg);
alu->src1_reg_negate = !!(src1_reg->flags & IR2_REG_NEGATE);
alu->src1_reg_abs = !!(src1_reg->flags & IR2_REG_ABS);
alu->src1_sel = !(src1_reg->flags & IR2_REG_CONST);
 
alu->vector_clamp = instr->alu.vector_clamp;
alu->scalar_clamp = instr->alu.scalar_clamp;
 
if (instr->alu.scalar_opc != ~0) {
struct ir2_register *sdst_reg = instr->regs[reg++];
 
reg_update_stats(sdst_reg, info, true);
 
assert(sdst_reg->flags == dst_reg->flags);
 
if (src3_reg) {
assert(src3_reg == instr->regs[reg]);
reg++;
} else {
src3_reg = instr->regs[reg++];
}
 
alu->scalar_dest = sdst_reg->num;
alu->scalar_write_mask = reg_alu_dst_swiz(sdst_reg);
alu->scalar_opc = instr->alu.scalar_opc;
} else {
/* not sure if this is required, but adreno compiler seems
* to always set scalar opc to MAXs if it is not used:
*/
alu->scalar_opc = MAXs;
}
 
if (src3_reg) {
reg_update_stats(src3_reg, info, false);
 
alu->src3_reg = src3_reg->num;
alu->src3_swiz = reg_alu_src_swiz(src3_reg);
alu->src3_reg_negate = !!(src3_reg->flags & IR2_REG_NEGATE);
alu->src3_reg_abs = !!(src3_reg->flags & IR2_REG_ABS);
alu->src3_sel = !(src3_reg->flags & IR2_REG_CONST);
} else {
/* not sure if this is required, but adreno compiler seems
* to always set register bank for 3rd src if unused:
*/
alu->src3_sel = 1;
}
 
if (instr->pred != IR2_PRED_NONE) {
alu->pred_select = (instr->pred == IR2_PRED_EQ) ? 3 : 2;
}
 
return 0;
}
 
static int instr_emit(struct ir2_instruction *instr, uint32_t *dwords,
uint32_t idx, struct ir2_shader_info *info)
{
switch (instr->instr_type) {
case IR2_FETCH: return instr_emit_fetch(instr, dwords, idx, info);
case IR2_ALU: return instr_emit_alu(instr, dwords, info);
}
return -1;
}
 
 
struct ir2_register * ir2_reg_create(struct ir2_instruction *instr,
int num, const char *swizzle, int flags)
{
struct ir2_register *reg =
ir2_alloc(instr->shader, sizeof(struct ir2_register));
DEBUG_MSG("%x, %d, %s", flags, num, swizzle);
assert(num <= REG_MASK);
reg->flags = flags;
reg->num = num;
reg->swizzle = ir2_strdup(instr->shader, swizzle);
assert(instr->regs_count < ARRAY_SIZE(instr->regs));
instr->regs[instr->regs_count++] = reg;
return reg;
}
 
static void reg_update_stats(struct ir2_register *reg,
struct ir2_shader_info *info, bool dest)
{
if (!(reg->flags & (IR2_REG_CONST|IR2_REG_EXPORT))) {
info->max_reg = MAX2(info->max_reg, reg->num);
 
if (dest) {
info->regs_written |= (1 << reg->num);
} else if (!(info->regs_written & (1 << reg->num))) {
/* for registers that haven't been written, they must be an
* input register that the thread scheduler (presumably?)
* needs to know about:
*/
info->max_input_reg = MAX2(info->max_input_reg, reg->num);
}
}
}
 
static uint32_t reg_fetch_src_swiz(struct ir2_register *reg, uint32_t n)
{
uint32_t swiz = 0;
int i;
 
assert(reg->flags == 0);
assert(reg->swizzle);
 
DEBUG_MSG("fetch src R%d.%s", reg->num, reg->swizzle);
 
for (i = n-1; i >= 0; i--) {
swiz <<= 2;
switch (reg->swizzle[i]) {
default:
ERROR_MSG("invalid fetch src swizzle: %s", reg->swizzle);
case 'x': swiz |= 0x0; break;
case 'y': swiz |= 0x1; break;
case 'z': swiz |= 0x2; break;
case 'w': swiz |= 0x3; break;
}
}
 
return swiz;
}
 
static uint32_t reg_fetch_dst_swiz(struct ir2_register *reg)
{
uint32_t swiz = 0;
int i;
 
assert(reg->flags == 0);
assert(!reg->swizzle || (strlen(reg->swizzle) == 4));
 
DEBUG_MSG("fetch dst R%d.%s", reg->num, reg->swizzle);
 
if (reg->swizzle) {
for (i = 3; i >= 0; i--) {
swiz <<= 3;
switch (reg->swizzle[i]) {
default:
ERROR_MSG("invalid dst swizzle: %s", reg->swizzle);
case 'x': swiz |= 0x0; break;
case 'y': swiz |= 0x1; break;
case 'z': swiz |= 0x2; break;
case 'w': swiz |= 0x3; break;
case '0': swiz |= 0x4; break;
case '1': swiz |= 0x5; break;
case '_': swiz |= 0x7; break;
}
}
} else {
swiz = 0x688;
}
 
return swiz;
}
 
/* actually, a write-mask */
static uint32_t reg_alu_dst_swiz(struct ir2_register *reg)
{
uint32_t swiz = 0;
int i;
 
assert((reg->flags & ~IR2_REG_EXPORT) == 0);
assert(!reg->swizzle || (strlen(reg->swizzle) == 4));
 
DEBUG_MSG("alu dst R%d.%s", reg->num, reg->swizzle);
 
if (reg->swizzle) {
for (i = 3; i >= 0; i--) {
swiz <<= 1;
if (reg->swizzle[i] == "xyzw"[i]) {
swiz |= 0x1;
} else if (reg->swizzle[i] != '_') {
ERROR_MSG("invalid dst swizzle: %s", reg->swizzle);
break;
}
}
} else {
swiz = 0xf;
}
 
return swiz;
}
 
static uint32_t reg_alu_src_swiz(struct ir2_register *reg)
{
uint32_t swiz = 0;
int i;
 
assert((reg->flags & IR2_REG_EXPORT) == 0);
assert(!reg->swizzle || (strlen(reg->swizzle) == 4));
 
DEBUG_MSG("vector src R%d.%s", reg->num, reg->swizzle);
 
if (reg->swizzle) {
for (i = 3; i >= 0; i--) {
swiz <<= 2;
switch (reg->swizzle[i]) {
default:
ERROR_MSG("invalid vector src swizzle: %s", reg->swizzle);
case 'x': swiz |= (0x0 - i) & 0x3; break;
case 'y': swiz |= (0x1 - i) & 0x3; break;
case 'z': swiz |= (0x2 - i) & 0x3; break;
case 'w': swiz |= (0x3 - i) & 0x3; break;
}
}
} else {
swiz = 0x0;
}
 
return swiz;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a2xx/ir-a2xx.h
0,0 → 1,180
/*
* Copyright (c) 2012 Rob Clark <robdclark@gmail.com>
*
* 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.
*/
 
#ifndef IR2_H_
#define IR2_H_
 
#include <stdint.h>
#include <stdbool.h>
 
#include "instr-a2xx.h"
 
/* low level intermediate representation of an adreno a2xx shader program */
 
struct ir2_shader;
 
struct ir2_shader_info {
uint16_t sizedwords;
int8_t max_reg; /* highest GPR # used by shader */
uint8_t max_input_reg;
uint64_t regs_written;
};
 
struct ir2_register {
enum {
IR2_REG_CONST = 0x1,
IR2_REG_EXPORT = 0x2,
IR2_REG_NEGATE = 0x4,
IR2_REG_ABS = 0x8,
} flags;
int num;
char *swizzle;
};
 
enum ir2_pred {
IR2_PRED_NONE = 0,
IR2_PRED_EQ = 1,
IR2_PRED_NE = 2,
};
 
struct ir2_instruction {
struct ir2_shader *shader;
enum {
IR2_FETCH,
IR2_ALU,
} instr_type;
enum ir2_pred pred;
int sync;
unsigned regs_count;
struct ir2_register *regs[5];
union {
/* FETCH specific: */
struct {
instr_fetch_opc_t opc;
unsigned const_idx;
/* texture fetch specific: */
bool is_cube : 1;
/* vertex fetch specific: */
unsigned const_idx_sel;
enum a2xx_sq_surfaceformat fmt;
bool is_signed : 1;
bool is_normalized : 1;
uint32_t stride;
uint32_t offset;
} fetch;
/* ALU specific: */
struct {
instr_vector_opc_t vector_opc;
instr_scalar_opc_t scalar_opc;
bool vector_clamp : 1;
bool scalar_clamp : 1;
} alu;
};
};
 
struct ir2_cf {
struct ir2_shader *shader;
instr_cf_opc_t cf_type;
 
union {
/* EXEC/EXEC_END specific: */
struct {
unsigned instrs_count;
struct ir2_instruction *instrs[6];
uint32_t addr, cnt, sequence;
} exec;
/* ALLOC specific: */
struct {
instr_alloc_type_t type; /* SQ_POSITION or SQ_PARAMETER_PIXEL */
int size;
} alloc;
};
};
 
struct ir2_shader {
unsigned cfs_count;
struct ir2_cf *cfs[0x56];
uint32_t heap[100 * 4096];
unsigned heap_idx;
 
enum ir2_pred pred; /* pred inherited by newly created instrs */
};
 
struct ir2_shader * ir2_shader_create(void);
void ir2_shader_destroy(struct ir2_shader *shader);
void * ir2_shader_assemble(struct ir2_shader *shader,
struct ir2_shader_info *info);
 
struct ir2_cf * ir2_cf_create(struct ir2_shader *shader, instr_cf_opc_t cf_type);
 
struct ir2_instruction * ir2_instr_create(struct ir2_cf *cf, int instr_type);
 
struct ir2_register * ir2_reg_create(struct ir2_instruction *instr,
int num, const char *swizzle, int flags);
 
/* some helper fxns: */
 
static inline struct ir2_cf *
ir2_cf_create_alloc(struct ir2_shader *shader, instr_alloc_type_t type, int size)
{
struct ir2_cf *cf = ir2_cf_create(shader, ALLOC);
if (!cf)
return cf;
cf->alloc.type = type;
cf->alloc.size = size;
return cf;
}
static inline struct ir2_instruction *
ir2_instr_create_alu(struct ir2_cf *cf, instr_vector_opc_t vop, instr_scalar_opc_t sop)
{
struct ir2_instruction *instr = ir2_instr_create(cf, IR2_ALU);
if (!instr)
return instr;
instr->alu.vector_opc = vop;
instr->alu.scalar_opc = sop;
return instr;
}
static inline struct ir2_instruction *
ir2_instr_create_vtx_fetch(struct ir2_cf *cf, int ci, int cis,
enum a2xx_sq_surfaceformat fmt, bool is_signed, int stride)
{
struct ir2_instruction *instr = instr = ir2_instr_create(cf, IR2_FETCH);
instr->fetch.opc = VTX_FETCH;
instr->fetch.const_idx = ci;
instr->fetch.const_idx_sel = cis;
instr->fetch.fmt = fmt;
instr->fetch.is_signed = is_signed;
instr->fetch.stride = stride;
return instr;
}
static inline struct ir2_instruction *
ir2_instr_create_tex_fetch(struct ir2_cf *cf, int ci)
{
struct ir2_instruction *instr = instr = ir2_instr_create(cf, IR2_FETCH);
instr->fetch.opc = TEX_FETCH;
instr->fetch.const_idx = ci;
return instr;
}
 
 
#endif /* IR2_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a3xx/a3xx.xml.h
0,0 → 1,2828
#ifndef A3XX_XML
#define A3XX_XML
 
/* Autogenerated file, DO NOT EDIT manually!
 
This file was generated by the rules-ng-ng headergen tool in this git repository:
http://github.com/freedreno/envytools/
git clone https://github.com/freedreno/envytools.git
 
The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml ( 364 bytes, from 2013-11-30 14:47:15)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32901 bytes, from 2014-06-02 15:21:30)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10551 bytes, from 2014-11-13 22:44:30)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 14895 bytes, from 2015-04-19 15:23:28)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 66709 bytes, from 2015-04-12 18:16:35)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 59314 bytes, from 2015-04-19 16:21:40)
 
Copyright (C) 2013-2015 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
 
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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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.
*/
 
 
enum a3xx_tile_mode {
LINEAR = 0,
TILE_32X32 = 2,
};
 
enum a3xx_state_block_id {
HLSQ_BLOCK_ID_TP_TEX = 2,
HLSQ_BLOCK_ID_TP_MIPMAP = 3,
HLSQ_BLOCK_ID_SP_VS = 4,
HLSQ_BLOCK_ID_SP_FS = 6,
};
 
enum a3xx_cache_opcode {
INVALIDATE = 1,
};
 
enum a3xx_vtx_fmt {
VFMT_32_FLOAT = 0,
VFMT_32_32_FLOAT = 1,
VFMT_32_32_32_FLOAT = 2,
VFMT_32_32_32_32_FLOAT = 3,
VFMT_16_FLOAT = 4,
VFMT_16_16_FLOAT = 5,
VFMT_16_16_16_FLOAT = 6,
VFMT_16_16_16_16_FLOAT = 7,
VFMT_32_FIXED = 8,
VFMT_32_32_FIXED = 9,
VFMT_32_32_32_FIXED = 10,
VFMT_32_32_32_32_FIXED = 11,
VFMT_16_SINT = 16,
VFMT_16_16_SINT = 17,
VFMT_16_16_16_SINT = 18,
VFMT_16_16_16_16_SINT = 19,
VFMT_16_UINT = 20,
VFMT_16_16_UINT = 21,
VFMT_16_16_16_UINT = 22,
VFMT_16_16_16_16_UINT = 23,
VFMT_16_SNORM = 24,
VFMT_16_16_SNORM = 25,
VFMT_16_16_16_SNORM = 26,
VFMT_16_16_16_16_SNORM = 27,
VFMT_16_UNORM = 28,
VFMT_16_16_UNORM = 29,
VFMT_16_16_16_UNORM = 30,
VFMT_16_16_16_16_UNORM = 31,
VFMT_32_UINT = 32,
VFMT_32_32_UINT = 33,
VFMT_32_32_32_UINT = 34,
VFMT_32_32_32_32_UINT = 35,
VFMT_32_SINT = 36,
VFMT_32_32_SINT = 37,
VFMT_32_32_32_SINT = 38,
VFMT_32_32_32_32_SINT = 39,
VFMT_8_UINT = 40,
VFMT_8_8_UINT = 41,
VFMT_8_8_8_UINT = 42,
VFMT_8_8_8_8_UINT = 43,
VFMT_8_UNORM = 44,
VFMT_8_8_UNORM = 45,
VFMT_8_8_8_UNORM = 46,
VFMT_8_8_8_8_UNORM = 47,
VFMT_8_SINT = 48,
VFMT_8_8_SINT = 49,
VFMT_8_8_8_SINT = 50,
VFMT_8_8_8_8_SINT = 51,
VFMT_8_SNORM = 52,
VFMT_8_8_SNORM = 53,
VFMT_8_8_8_SNORM = 54,
VFMT_8_8_8_8_SNORM = 55,
VFMT_10_10_10_2_UINT = 60,
VFMT_10_10_10_2_UNORM = 61,
VFMT_10_10_10_2_SINT = 62,
VFMT_10_10_10_2_SNORM = 63,
};
 
enum a3xx_tex_fmt {
TFMT_5_6_5_UNORM = 4,
TFMT_5_5_5_1_UNORM = 5,
TFMT_4_4_4_4_UNORM = 7,
TFMT_Z16_UNORM = 9,
TFMT_X8Z24_UNORM = 10,
TFMT_Z32_FLOAT = 11,
TFMT_NV12_UV_TILED = 17,
TFMT_NV12_Y_TILED = 19,
TFMT_NV12_UV = 21,
TFMT_NV12_Y = 23,
TFMT_I420_Y = 24,
TFMT_I420_U = 26,
TFMT_I420_V = 27,
TFMT_ATC_RGB = 32,
TFMT_ATC_RGBA_EXPLICIT = 33,
TFMT_ETC1 = 34,
TFMT_ATC_RGBA_INTERPOLATED = 35,
TFMT_DXT1 = 36,
TFMT_DXT3 = 37,
TFMT_DXT5 = 38,
TFMT_10_10_10_2_UNORM = 41,
TFMT_9_9_9_E5_FLOAT = 42,
TFMT_11_11_10_FLOAT = 43,
TFMT_A8_UNORM = 44,
TFMT_L8_A8_UNORM = 47,
TFMT_8_UNORM = 48,
TFMT_8_8_UNORM = 49,
TFMT_8_8_8_UNORM = 50,
TFMT_8_8_8_8_UNORM = 51,
TFMT_8_SNORM = 52,
TFMT_8_8_SNORM = 53,
TFMT_8_8_8_SNORM = 54,
TFMT_8_8_8_8_SNORM = 55,
TFMT_8_UINT = 56,
TFMT_8_8_UINT = 57,
TFMT_8_8_8_UINT = 58,
TFMT_8_8_8_8_UINT = 59,
TFMT_8_SINT = 60,
TFMT_8_8_SINT = 61,
TFMT_8_8_8_SINT = 62,
TFMT_8_8_8_8_SINT = 63,
TFMT_16_FLOAT = 64,
TFMT_16_16_FLOAT = 65,
TFMT_16_16_16_16_FLOAT = 67,
TFMT_16_UINT = 68,
TFMT_16_16_UINT = 69,
TFMT_16_16_16_16_UINT = 71,
TFMT_16_SINT = 72,
TFMT_16_16_SINT = 73,
TFMT_16_16_16_16_SINT = 75,
TFMT_16_UNORM = 76,
TFMT_16_16_UNORM = 77,
TFMT_16_16_16_16_UNORM = 79,
TFMT_16_SNORM = 80,
TFMT_16_16_SNORM = 81,
TFMT_16_16_16_16_SNORM = 83,
TFMT_32_FLOAT = 84,
TFMT_32_32_FLOAT = 85,
TFMT_32_32_32_32_FLOAT = 87,
TFMT_32_UINT = 88,
TFMT_32_32_UINT = 89,
TFMT_32_32_32_32_UINT = 91,
TFMT_32_SINT = 92,
TFMT_32_32_SINT = 93,
TFMT_32_32_32_32_SINT = 95,
TFMT_ETC2_RG11_SNORM = 112,
TFMT_ETC2_RG11_UNORM = 113,
TFMT_ETC2_R11_SNORM = 114,
TFMT_ETC2_R11_UNORM = 115,
TFMT_ETC2_RGBA8 = 116,
TFMT_ETC2_RGB8A1 = 117,
TFMT_ETC2_RGB8 = 118,
};
 
enum a3xx_tex_fetchsize {
TFETCH_DISABLE = 0,
TFETCH_1_BYTE = 1,
TFETCH_2_BYTE = 2,
TFETCH_4_BYTE = 3,
TFETCH_8_BYTE = 4,
TFETCH_16_BYTE = 5,
};
 
enum a3xx_color_fmt {
RB_R5G6B5_UNORM = 0,
RB_R5G5B5A1_UNORM = 1,
RB_R4G4B4A4_UNORM = 3,
RB_R8G8B8_UNORM = 4,
RB_R8G8B8A8_UNORM = 8,
RB_R8G8B8A8_SNORM = 9,
RB_R8G8B8A8_UINT = 10,
RB_R8G8B8A8_SINT = 11,
RB_R8G8_UNORM = 12,
RB_R8G8_SNORM = 13,
RB_R8_UINT = 14,
RB_R8_SINT = 15,
RB_R10G10B10A2_UNORM = 16,
RB_A8_UNORM = 20,
RB_R8_UNORM = 21,
RB_R16_FLOAT = 24,
RB_R16G16_FLOAT = 25,
RB_R16G16B16A16_FLOAT = 27,
RB_R11G11B10_FLOAT = 28,
RB_R16_SNORM = 32,
RB_R16G16_SNORM = 33,
RB_R16G16B16A16_SNORM = 35,
RB_R16_UNORM = 36,
RB_R16G16_UNORM = 37,
RB_R16G16B16A16_UNORM = 39,
RB_R16_SINT = 40,
RB_R16G16_SINT = 41,
RB_R16G16B16A16_SINT = 43,
RB_R16_UINT = 44,
RB_R16G16_UINT = 45,
RB_R16G16B16A16_UINT = 47,
RB_R32_FLOAT = 48,
RB_R32G32_FLOAT = 49,
RB_R32G32B32A32_FLOAT = 51,
RB_R32_SINT = 52,
RB_R32G32_SINT = 53,
RB_R32G32B32A32_SINT = 55,
RB_R32_UINT = 56,
RB_R32G32_UINT = 57,
RB_R32G32B32A32_UINT = 59,
};
 
enum a3xx_sp_perfcounter_select {
SP_FS_CFLOW_INSTRUCTIONS = 12,
SP_FS_FULL_ALU_INSTRUCTIONS = 14,
SP0_ICL1_MISSES = 26,
SP_ALU_ACTIVE_CYCLES = 29,
};
 
enum a3xx_rop_code {
ROP_CLEAR = 0,
ROP_NOR = 1,
ROP_AND_INVERTED = 2,
ROP_COPY_INVERTED = 3,
ROP_AND_REVERSE = 4,
ROP_INVERT = 5,
ROP_XOR = 6,
ROP_NAND = 7,
ROP_AND = 8,
ROP_EQUIV = 9,
ROP_NOOP = 10,
ROP_OR_INVERTED = 11,
ROP_COPY = 12,
ROP_OR_REVERSE = 13,
ROP_OR = 14,
ROP_SET = 15,
};
 
enum a3xx_rb_blend_opcode {
BLEND_DST_PLUS_SRC = 0,
BLEND_SRC_MINUS_DST = 1,
BLEND_DST_MINUS_SRC = 2,
BLEND_MIN_DST_SRC = 3,
BLEND_MAX_DST_SRC = 4,
};
 
enum a3xx_intp_mode {
SMOOTH = 0,
FLAT = 1,
};
 
enum a3xx_repl_mode {
S = 1,
T = 2,
ONE_T = 3,
};
 
enum a3xx_tex_filter {
A3XX_TEX_NEAREST = 0,
A3XX_TEX_LINEAR = 1,
A3XX_TEX_ANISO = 2,
};
 
enum a3xx_tex_clamp {
A3XX_TEX_REPEAT = 0,
A3XX_TEX_CLAMP_TO_EDGE = 1,
A3XX_TEX_MIRROR_REPEAT = 2,
A3XX_TEX_CLAMP_TO_BORDER = 3,
A3XX_TEX_MIRROR_CLAMP = 4,
};
 
enum a3xx_tex_aniso {
A3XX_TEX_ANISO_1 = 0,
A3XX_TEX_ANISO_2 = 1,
A3XX_TEX_ANISO_4 = 2,
A3XX_TEX_ANISO_8 = 3,
A3XX_TEX_ANISO_16 = 4,
};
 
enum a3xx_tex_swiz {
A3XX_TEX_X = 0,
A3XX_TEX_Y = 1,
A3XX_TEX_Z = 2,
A3XX_TEX_W = 3,
A3XX_TEX_ZERO = 4,
A3XX_TEX_ONE = 5,
};
 
enum a3xx_tex_type {
A3XX_TEX_1D = 0,
A3XX_TEX_2D = 1,
A3XX_TEX_CUBE = 2,
A3XX_TEX_3D = 3,
};
 
#define A3XX_INT0_RBBM_GPU_IDLE 0x00000001
#define A3XX_INT0_RBBM_AHB_ERROR 0x00000002
#define A3XX_INT0_RBBM_REG_TIMEOUT 0x00000004
#define A3XX_INT0_RBBM_ME_MS_TIMEOUT 0x00000008
#define A3XX_INT0_RBBM_PFP_MS_TIMEOUT 0x00000010
#define A3XX_INT0_RBBM_ATB_BUS_OVERFLOW 0x00000020
#define A3XX_INT0_VFD_ERROR 0x00000040
#define A3XX_INT0_CP_SW_INT 0x00000080
#define A3XX_INT0_CP_T0_PACKET_IN_IB 0x00000100
#define A3XX_INT0_CP_OPCODE_ERROR 0x00000200
#define A3XX_INT0_CP_RESERVED_BIT_ERROR 0x00000400
#define A3XX_INT0_CP_HW_FAULT 0x00000800
#define A3XX_INT0_CP_DMA 0x00001000
#define A3XX_INT0_CP_IB2_INT 0x00002000
#define A3XX_INT0_CP_IB1_INT 0x00004000
#define A3XX_INT0_CP_RB_INT 0x00008000
#define A3XX_INT0_CP_REG_PROTECT_FAULT 0x00010000
#define A3XX_INT0_CP_RB_DONE_TS 0x00020000
#define A3XX_INT0_CP_VS_DONE_TS 0x00040000
#define A3XX_INT0_CP_PS_DONE_TS 0x00080000
#define A3XX_INT0_CACHE_FLUSH_TS 0x00100000
#define A3XX_INT0_CP_AHB_ERROR_HALT 0x00200000
#define A3XX_INT0_MISC_HANG_DETECT 0x01000000
#define A3XX_INT0_UCHE_OOB_ACCESS 0x02000000
#define REG_A3XX_RBBM_HW_VERSION 0x00000000
 
#define REG_A3XX_RBBM_HW_RELEASE 0x00000001
 
#define REG_A3XX_RBBM_HW_CONFIGURATION 0x00000002
 
#define REG_A3XX_RBBM_CLOCK_CTL 0x00000010
 
#define REG_A3XX_RBBM_SP_HYST_CNT 0x00000012
 
#define REG_A3XX_RBBM_SW_RESET_CMD 0x00000018
 
#define REG_A3XX_RBBM_AHB_CTL0 0x00000020
 
#define REG_A3XX_RBBM_AHB_CTL1 0x00000021
 
#define REG_A3XX_RBBM_AHB_CMD 0x00000022
 
#define REG_A3XX_RBBM_AHB_ERROR_STATUS 0x00000027
 
#define REG_A3XX_RBBM_GPR0_CTL 0x0000002e
 
#define REG_A3XX_RBBM_STATUS 0x00000030
#define A3XX_RBBM_STATUS_HI_BUSY 0x00000001
#define A3XX_RBBM_STATUS_CP_ME_BUSY 0x00000002
#define A3XX_RBBM_STATUS_CP_PFP_BUSY 0x00000004
#define A3XX_RBBM_STATUS_CP_NRT_BUSY 0x00004000
#define A3XX_RBBM_STATUS_VBIF_BUSY 0x00008000
#define A3XX_RBBM_STATUS_TSE_BUSY 0x00010000
#define A3XX_RBBM_STATUS_RAS_BUSY 0x00020000
#define A3XX_RBBM_STATUS_RB_BUSY 0x00040000
#define A3XX_RBBM_STATUS_PC_DCALL_BUSY 0x00080000
#define A3XX_RBBM_STATUS_PC_VSD_BUSY 0x00100000
#define A3XX_RBBM_STATUS_VFD_BUSY 0x00200000
#define A3XX_RBBM_STATUS_VPC_BUSY 0x00400000
#define A3XX_RBBM_STATUS_UCHE_BUSY 0x00800000
#define A3XX_RBBM_STATUS_SP_BUSY 0x01000000
#define A3XX_RBBM_STATUS_TPL1_BUSY 0x02000000
#define A3XX_RBBM_STATUS_MARB_BUSY 0x04000000
#define A3XX_RBBM_STATUS_VSC_BUSY 0x08000000
#define A3XX_RBBM_STATUS_ARB_BUSY 0x10000000
#define A3XX_RBBM_STATUS_HLSQ_BUSY 0x20000000
#define A3XX_RBBM_STATUS_GPU_BUSY_NOHC 0x40000000
#define A3XX_RBBM_STATUS_GPU_BUSY 0x80000000
 
#define REG_A3XX_RBBM_NQWAIT_UNTIL 0x00000040
 
#define REG_A3XX_RBBM_WAIT_IDLE_CLOCKS_CTL 0x00000033
 
#define REG_A3XX_RBBM_INTERFACE_HANG_INT_CTL 0x00000050
 
#define REG_A3XX_RBBM_INTERFACE_HANG_MASK_CTL0 0x00000051
 
#define REG_A3XX_RBBM_INTERFACE_HANG_MASK_CTL1 0x00000054
 
#define REG_A3XX_RBBM_INTERFACE_HANG_MASK_CTL2 0x00000057
 
#define REG_A3XX_RBBM_INTERFACE_HANG_MASK_CTL3 0x0000005a
 
#define REG_A3XX_RBBM_INT_SET_CMD 0x00000060
 
#define REG_A3XX_RBBM_INT_CLEAR_CMD 0x00000061
 
#define REG_A3XX_RBBM_INT_0_MASK 0x00000063
 
#define REG_A3XX_RBBM_INT_0_STATUS 0x00000064
 
#define REG_A3XX_RBBM_PERFCTR_CTL 0x00000080
#define A3XX_RBBM_PERFCTR_CTL_ENABLE 0x00000001
 
#define REG_A3XX_RBBM_PERFCTR_LOAD_CMD0 0x00000081
 
#define REG_A3XX_RBBM_PERFCTR_LOAD_CMD1 0x00000082
 
#define REG_A3XX_RBBM_PERFCTR_LOAD_VALUE_LO 0x00000084
 
#define REG_A3XX_RBBM_PERFCTR_LOAD_VALUE_HI 0x00000085
 
#define REG_A3XX_RBBM_PERFCOUNTER0_SELECT 0x00000086
 
#define REG_A3XX_RBBM_PERFCOUNTER1_SELECT 0x00000087
 
#define REG_A3XX_RBBM_GPU_BUSY_MASKED 0x00000088
 
#define REG_A3XX_RBBM_PERFCTR_CP_0_LO 0x00000090
 
#define REG_A3XX_RBBM_PERFCTR_CP_0_HI 0x00000091
 
#define REG_A3XX_RBBM_PERFCTR_RBBM_0_LO 0x00000092
 
#define REG_A3XX_RBBM_PERFCTR_RBBM_0_HI 0x00000093
 
#define REG_A3XX_RBBM_PERFCTR_RBBM_1_LO 0x00000094
 
#define REG_A3XX_RBBM_PERFCTR_RBBM_1_HI 0x00000095
 
#define REG_A3XX_RBBM_PERFCTR_PC_0_LO 0x00000096
 
#define REG_A3XX_RBBM_PERFCTR_PC_0_HI 0x00000097
 
#define REG_A3XX_RBBM_PERFCTR_PC_1_LO 0x00000098
 
#define REG_A3XX_RBBM_PERFCTR_PC_1_HI 0x00000099
 
#define REG_A3XX_RBBM_PERFCTR_PC_2_LO 0x0000009a
 
#define REG_A3XX_RBBM_PERFCTR_PC_2_HI 0x0000009b
 
#define REG_A3XX_RBBM_PERFCTR_PC_3_LO 0x0000009c
 
#define REG_A3XX_RBBM_PERFCTR_PC_3_HI 0x0000009d
 
#define REG_A3XX_RBBM_PERFCTR_VFD_0_LO 0x0000009e
 
#define REG_A3XX_RBBM_PERFCTR_VFD_0_HI 0x0000009f
 
#define REG_A3XX_RBBM_PERFCTR_VFD_1_LO 0x000000a0
 
#define REG_A3XX_RBBM_PERFCTR_VFD_1_HI 0x000000a1
 
#define REG_A3XX_RBBM_PERFCTR_HLSQ_0_LO 0x000000a2
 
#define REG_A3XX_RBBM_PERFCTR_HLSQ_0_HI 0x000000a3
 
#define REG_A3XX_RBBM_PERFCTR_HLSQ_1_LO 0x000000a4
 
#define REG_A3XX_RBBM_PERFCTR_HLSQ_1_HI 0x000000a5
 
#define REG_A3XX_RBBM_PERFCTR_HLSQ_2_LO 0x000000a6
 
#define REG_A3XX_RBBM_PERFCTR_HLSQ_2_HI 0x000000a7
 
#define REG_A3XX_RBBM_PERFCTR_HLSQ_3_LO 0x000000a8
 
#define REG_A3XX_RBBM_PERFCTR_HLSQ_3_HI 0x000000a9
 
#define REG_A3XX_RBBM_PERFCTR_HLSQ_4_LO 0x000000aa
 
#define REG_A3XX_RBBM_PERFCTR_HLSQ_4_HI 0x000000ab
 
#define REG_A3XX_RBBM_PERFCTR_HLSQ_5_LO 0x000000ac
 
#define REG_A3XX_RBBM_PERFCTR_HLSQ_5_HI 0x000000ad
 
#define REG_A3XX_RBBM_PERFCTR_VPC_0_LO 0x000000ae
 
#define REG_A3XX_RBBM_PERFCTR_VPC_0_HI 0x000000af
 
#define REG_A3XX_RBBM_PERFCTR_VPC_1_LO 0x000000b0
 
#define REG_A3XX_RBBM_PERFCTR_VPC_1_HI 0x000000b1
 
#define REG_A3XX_RBBM_PERFCTR_TSE_0_LO 0x000000b2
 
#define REG_A3XX_RBBM_PERFCTR_TSE_0_HI 0x000000b3
 
#define REG_A3XX_RBBM_PERFCTR_TSE_1_LO 0x000000b4
 
#define REG_A3XX_RBBM_PERFCTR_TSE_1_HI 0x000000b5
 
#define REG_A3XX_RBBM_PERFCTR_RAS_0_LO 0x000000b6
 
#define REG_A3XX_RBBM_PERFCTR_RAS_0_HI 0x000000b7
 
#define REG_A3XX_RBBM_PERFCTR_RAS_1_LO 0x000000b8
 
#define REG_A3XX_RBBM_PERFCTR_RAS_1_HI 0x000000b9
 
#define REG_A3XX_RBBM_PERFCTR_UCHE_0_LO 0x000000ba
 
#define REG_A3XX_RBBM_PERFCTR_UCHE_0_HI 0x000000bb
 
#define REG_A3XX_RBBM_PERFCTR_UCHE_1_LO 0x000000bc
 
#define REG_A3XX_RBBM_PERFCTR_UCHE_1_HI 0x000000bd
 
#define REG_A3XX_RBBM_PERFCTR_UCHE_2_LO 0x000000be
 
#define REG_A3XX_RBBM_PERFCTR_UCHE_2_HI 0x000000bf
 
#define REG_A3XX_RBBM_PERFCTR_UCHE_3_LO 0x000000c0
 
#define REG_A3XX_RBBM_PERFCTR_UCHE_3_HI 0x000000c1
 
#define REG_A3XX_RBBM_PERFCTR_UCHE_4_LO 0x000000c2
 
#define REG_A3XX_RBBM_PERFCTR_UCHE_4_HI 0x000000c3
 
#define REG_A3XX_RBBM_PERFCTR_UCHE_5_LO 0x000000c4
 
#define REG_A3XX_RBBM_PERFCTR_UCHE_5_HI 0x000000c5
 
#define REG_A3XX_RBBM_PERFCTR_TP_0_LO 0x000000c6
 
#define REG_A3XX_RBBM_PERFCTR_TP_0_HI 0x000000c7
 
#define REG_A3XX_RBBM_PERFCTR_TP_1_LO 0x000000c8
 
#define REG_A3XX_RBBM_PERFCTR_TP_1_HI 0x000000c9
 
#define REG_A3XX_RBBM_PERFCTR_TP_2_LO 0x000000ca
 
#define REG_A3XX_RBBM_PERFCTR_TP_2_HI 0x000000cb
 
#define REG_A3XX_RBBM_PERFCTR_TP_3_LO 0x000000cc
 
#define REG_A3XX_RBBM_PERFCTR_TP_3_HI 0x000000cd
 
#define REG_A3XX_RBBM_PERFCTR_TP_4_LO 0x000000ce
 
#define REG_A3XX_RBBM_PERFCTR_TP_4_HI 0x000000cf
 
#define REG_A3XX_RBBM_PERFCTR_TP_5_LO 0x000000d0
 
#define REG_A3XX_RBBM_PERFCTR_TP_5_HI 0x000000d1
 
#define REG_A3XX_RBBM_PERFCTR_SP_0_LO 0x000000d2
 
#define REG_A3XX_RBBM_PERFCTR_SP_0_HI 0x000000d3
 
#define REG_A3XX_RBBM_PERFCTR_SP_1_LO 0x000000d4
 
#define REG_A3XX_RBBM_PERFCTR_SP_1_HI 0x000000d5
 
#define REG_A3XX_RBBM_PERFCTR_SP_2_LO 0x000000d6
 
#define REG_A3XX_RBBM_PERFCTR_SP_2_HI 0x000000d7
 
#define REG_A3XX_RBBM_PERFCTR_SP_3_LO 0x000000d8
 
#define REG_A3XX_RBBM_PERFCTR_SP_3_HI 0x000000d9
 
#define REG_A3XX_RBBM_PERFCTR_SP_4_LO 0x000000da
 
#define REG_A3XX_RBBM_PERFCTR_SP_4_HI 0x000000db
 
#define REG_A3XX_RBBM_PERFCTR_SP_5_LO 0x000000dc
 
#define REG_A3XX_RBBM_PERFCTR_SP_5_HI 0x000000dd
 
#define REG_A3XX_RBBM_PERFCTR_SP_6_LO 0x000000de
 
#define REG_A3XX_RBBM_PERFCTR_SP_6_HI 0x000000df
 
#define REG_A3XX_RBBM_PERFCTR_SP_7_LO 0x000000e0
 
#define REG_A3XX_RBBM_PERFCTR_SP_7_HI 0x000000e1
 
#define REG_A3XX_RBBM_PERFCTR_RB_0_LO 0x000000e2
 
#define REG_A3XX_RBBM_PERFCTR_RB_0_HI 0x000000e3
 
#define REG_A3XX_RBBM_PERFCTR_RB_1_LO 0x000000e4
 
#define REG_A3XX_RBBM_PERFCTR_RB_1_HI 0x000000e5
 
#define REG_A3XX_RBBM_PERFCTR_PWR_0_LO 0x000000ea
 
#define REG_A3XX_RBBM_PERFCTR_PWR_0_HI 0x000000eb
 
#define REG_A3XX_RBBM_PERFCTR_PWR_1_LO 0x000000ec
 
#define REG_A3XX_RBBM_PERFCTR_PWR_1_HI 0x000000ed
 
#define REG_A3XX_RBBM_RBBM_CTL 0x00000100
 
#define REG_A3XX_RBBM_DEBUG_BUS_CTL 0x00000111
 
#define REG_A3XX_RBBM_DEBUG_BUS_DATA_STATUS 0x00000112
 
#define REG_A3XX_CP_PFP_UCODE_ADDR 0x000001c9
 
#define REG_A3XX_CP_PFP_UCODE_DATA 0x000001ca
 
#define REG_A3XX_CP_ROQ_ADDR 0x000001cc
 
#define REG_A3XX_CP_ROQ_DATA 0x000001cd
 
#define REG_A3XX_CP_MERCIU_ADDR 0x000001d1
 
#define REG_A3XX_CP_MERCIU_DATA 0x000001d2
 
#define REG_A3XX_CP_MERCIU_DATA2 0x000001d3
 
#define REG_A3XX_CP_MEQ_ADDR 0x000001da
 
#define REG_A3XX_CP_MEQ_DATA 0x000001db
 
#define REG_A3XX_CP_WFI_PEND_CTR 0x000001f5
 
#define REG_A3XX_RBBM_PM_OVERRIDE2 0x0000039d
 
#define REG_A3XX_CP_PERFCOUNTER_SELECT 0x00000445
 
#define REG_A3XX_CP_HW_FAULT 0x0000045c
 
#define REG_A3XX_CP_PROTECT_CTRL 0x0000045e
 
#define REG_A3XX_CP_PROTECT_STATUS 0x0000045f
 
static inline uint32_t REG_A3XX_CP_PROTECT(uint32_t i0) { return 0x00000460 + 0x1*i0; }
 
static inline uint32_t REG_A3XX_CP_PROTECT_REG(uint32_t i0) { return 0x00000460 + 0x1*i0; }
 
#define REG_A3XX_CP_AHB_FAULT 0x0000054d
 
#define REG_A3XX_SQ_GPR_MANAGEMENT 0x00000d00
 
#define REG_A3XX_SQ_INST_STORE_MANAGMENT 0x00000d02
 
#define REG_A3XX_TP0_CHICKEN 0x00000e1e
 
#define REG_A3XX_SP_GLOBAL_MEM_SIZE 0x00000e22
 
#define REG_A3XX_SP_GLOBAL_MEM_ADDR 0x00000e23
 
#define REG_A3XX_GRAS_CL_CLIP_CNTL 0x00002040
#define A3XX_GRAS_CL_CLIP_CNTL_IJ_PERSP_CENTER 0x00001000
#define A3XX_GRAS_CL_CLIP_CNTL_CLIP_DISABLE 0x00010000
#define A3XX_GRAS_CL_CLIP_CNTL_ZFAR_CLIP_DISABLE 0x00020000
#define A3XX_GRAS_CL_CLIP_CNTL_VP_CLIP_CODE_IGNORE 0x00080000
#define A3XX_GRAS_CL_CLIP_CNTL_VP_XFORM_DISABLE 0x00100000
#define A3XX_GRAS_CL_CLIP_CNTL_PERSP_DIVISION_DISABLE 0x00200000
#define A3XX_GRAS_CL_CLIP_CNTL_ZCOORD 0x00800000
#define A3XX_GRAS_CL_CLIP_CNTL_WCOORD 0x01000000
#define A3XX_GRAS_CL_CLIP_CNTL_ZCLIP_DISABLE 0x02000000
 
#define REG_A3XX_GRAS_CL_GB_CLIP_ADJ 0x00002044
#define A3XX_GRAS_CL_GB_CLIP_ADJ_HORZ__MASK 0x000003ff
#define A3XX_GRAS_CL_GB_CLIP_ADJ_HORZ__SHIFT 0
static inline uint32_t A3XX_GRAS_CL_GB_CLIP_ADJ_HORZ(uint32_t val)
{
return ((val) << A3XX_GRAS_CL_GB_CLIP_ADJ_HORZ__SHIFT) & A3XX_GRAS_CL_GB_CLIP_ADJ_HORZ__MASK;
}
#define A3XX_GRAS_CL_GB_CLIP_ADJ_VERT__MASK 0x000ffc00
#define A3XX_GRAS_CL_GB_CLIP_ADJ_VERT__SHIFT 10
static inline uint32_t A3XX_GRAS_CL_GB_CLIP_ADJ_VERT(uint32_t val)
{
return ((val) << A3XX_GRAS_CL_GB_CLIP_ADJ_VERT__SHIFT) & A3XX_GRAS_CL_GB_CLIP_ADJ_VERT__MASK;
}
 
#define REG_A3XX_GRAS_CL_VPORT_XOFFSET 0x00002048
#define A3XX_GRAS_CL_VPORT_XOFFSET__MASK 0xffffffff
#define A3XX_GRAS_CL_VPORT_XOFFSET__SHIFT 0
static inline uint32_t A3XX_GRAS_CL_VPORT_XOFFSET(float val)
{
return ((fui(val)) << A3XX_GRAS_CL_VPORT_XOFFSET__SHIFT) & A3XX_GRAS_CL_VPORT_XOFFSET__MASK;
}
 
#define REG_A3XX_GRAS_CL_VPORT_XSCALE 0x00002049
#define A3XX_GRAS_CL_VPORT_XSCALE__MASK 0xffffffff
#define A3XX_GRAS_CL_VPORT_XSCALE__SHIFT 0
static inline uint32_t A3XX_GRAS_CL_VPORT_XSCALE(float val)
{
return ((fui(val)) << A3XX_GRAS_CL_VPORT_XSCALE__SHIFT) & A3XX_GRAS_CL_VPORT_XSCALE__MASK;
}
 
#define REG_A3XX_GRAS_CL_VPORT_YOFFSET 0x0000204a
#define A3XX_GRAS_CL_VPORT_YOFFSET__MASK 0xffffffff
#define A3XX_GRAS_CL_VPORT_YOFFSET__SHIFT 0
static inline uint32_t A3XX_GRAS_CL_VPORT_YOFFSET(float val)
{
return ((fui(val)) << A3XX_GRAS_CL_VPORT_YOFFSET__SHIFT) & A3XX_GRAS_CL_VPORT_YOFFSET__MASK;
}
 
#define REG_A3XX_GRAS_CL_VPORT_YSCALE 0x0000204b
#define A3XX_GRAS_CL_VPORT_YSCALE__MASK 0xffffffff
#define A3XX_GRAS_CL_VPORT_YSCALE__SHIFT 0
static inline uint32_t A3XX_GRAS_CL_VPORT_YSCALE(float val)
{
return ((fui(val)) << A3XX_GRAS_CL_VPORT_YSCALE__SHIFT) & A3XX_GRAS_CL_VPORT_YSCALE__MASK;
}
 
#define REG_A3XX_GRAS_CL_VPORT_ZOFFSET 0x0000204c
#define A3XX_GRAS_CL_VPORT_ZOFFSET__MASK 0xffffffff
#define A3XX_GRAS_CL_VPORT_ZOFFSET__SHIFT 0
static inline uint32_t A3XX_GRAS_CL_VPORT_ZOFFSET(float val)
{
return ((fui(val)) << A3XX_GRAS_CL_VPORT_ZOFFSET__SHIFT) & A3XX_GRAS_CL_VPORT_ZOFFSET__MASK;
}
 
#define REG_A3XX_GRAS_CL_VPORT_ZSCALE 0x0000204d
#define A3XX_GRAS_CL_VPORT_ZSCALE__MASK 0xffffffff
#define A3XX_GRAS_CL_VPORT_ZSCALE__SHIFT 0
static inline uint32_t A3XX_GRAS_CL_VPORT_ZSCALE(float val)
{
return ((fui(val)) << A3XX_GRAS_CL_VPORT_ZSCALE__SHIFT) & A3XX_GRAS_CL_VPORT_ZSCALE__MASK;
}
 
#define REG_A3XX_GRAS_SU_POINT_MINMAX 0x00002068
#define A3XX_GRAS_SU_POINT_MINMAX_MIN__MASK 0x0000ffff
#define A3XX_GRAS_SU_POINT_MINMAX_MIN__SHIFT 0
static inline uint32_t A3XX_GRAS_SU_POINT_MINMAX_MIN(float val)
{
return ((((uint32_t)(val * 16.0))) << A3XX_GRAS_SU_POINT_MINMAX_MIN__SHIFT) & A3XX_GRAS_SU_POINT_MINMAX_MIN__MASK;
}
#define A3XX_GRAS_SU_POINT_MINMAX_MAX__MASK 0xffff0000
#define A3XX_GRAS_SU_POINT_MINMAX_MAX__SHIFT 16
static inline uint32_t A3XX_GRAS_SU_POINT_MINMAX_MAX(float val)
{
return ((((uint32_t)(val * 16.0))) << A3XX_GRAS_SU_POINT_MINMAX_MAX__SHIFT) & A3XX_GRAS_SU_POINT_MINMAX_MAX__MASK;
}
 
#define REG_A3XX_GRAS_SU_POINT_SIZE 0x00002069
#define A3XX_GRAS_SU_POINT_SIZE__MASK 0xffffffff
#define A3XX_GRAS_SU_POINT_SIZE__SHIFT 0
static inline uint32_t A3XX_GRAS_SU_POINT_SIZE(float val)
{
return ((((int32_t)(val * 16.0))) << A3XX_GRAS_SU_POINT_SIZE__SHIFT) & A3XX_GRAS_SU_POINT_SIZE__MASK;
}
 
#define REG_A3XX_GRAS_SU_POLY_OFFSET_SCALE 0x0000206c
#define A3XX_GRAS_SU_POLY_OFFSET_SCALE_VAL__MASK 0x00ffffff
#define A3XX_GRAS_SU_POLY_OFFSET_SCALE_VAL__SHIFT 0
static inline uint32_t A3XX_GRAS_SU_POLY_OFFSET_SCALE_VAL(float val)
{
return ((((int32_t)(val * 16384.0))) << A3XX_GRAS_SU_POLY_OFFSET_SCALE_VAL__SHIFT) & A3XX_GRAS_SU_POLY_OFFSET_SCALE_VAL__MASK;
}
 
#define REG_A3XX_GRAS_SU_POLY_OFFSET_OFFSET 0x0000206d
#define A3XX_GRAS_SU_POLY_OFFSET_OFFSET__MASK 0xffffffff
#define A3XX_GRAS_SU_POLY_OFFSET_OFFSET__SHIFT 0
static inline uint32_t A3XX_GRAS_SU_POLY_OFFSET_OFFSET(float val)
{
return ((((int32_t)(val * 64.0))) << A3XX_GRAS_SU_POLY_OFFSET_OFFSET__SHIFT) & A3XX_GRAS_SU_POLY_OFFSET_OFFSET__MASK;
}
 
#define REG_A3XX_GRAS_SU_MODE_CONTROL 0x00002070
#define A3XX_GRAS_SU_MODE_CONTROL_CULL_FRONT 0x00000001
#define A3XX_GRAS_SU_MODE_CONTROL_CULL_BACK 0x00000002
#define A3XX_GRAS_SU_MODE_CONTROL_FRONT_CW 0x00000004
#define A3XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH__MASK 0x000007f8
#define A3XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH__SHIFT 3
static inline uint32_t A3XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH(float val)
{
return ((((int32_t)(val * 4.0))) << A3XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH__SHIFT) & A3XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH__MASK;
}
#define A3XX_GRAS_SU_MODE_CONTROL_POLY_OFFSET 0x00000800
 
#define REG_A3XX_GRAS_SC_CONTROL 0x00002072
#define A3XX_GRAS_SC_CONTROL_RENDER_MODE__MASK 0x000000f0
#define A3XX_GRAS_SC_CONTROL_RENDER_MODE__SHIFT 4
static inline uint32_t A3XX_GRAS_SC_CONTROL_RENDER_MODE(enum a3xx_render_mode val)
{
return ((val) << A3XX_GRAS_SC_CONTROL_RENDER_MODE__SHIFT) & A3XX_GRAS_SC_CONTROL_RENDER_MODE__MASK;
}
#define A3XX_GRAS_SC_CONTROL_MSAA_SAMPLES__MASK 0x00000f00
#define A3XX_GRAS_SC_CONTROL_MSAA_SAMPLES__SHIFT 8
static inline uint32_t A3XX_GRAS_SC_CONTROL_MSAA_SAMPLES(enum a3xx_msaa_samples val)
{
return ((val) << A3XX_GRAS_SC_CONTROL_MSAA_SAMPLES__SHIFT) & A3XX_GRAS_SC_CONTROL_MSAA_SAMPLES__MASK;
}
#define A3XX_GRAS_SC_CONTROL_RASTER_MODE__MASK 0x0000f000
#define A3XX_GRAS_SC_CONTROL_RASTER_MODE__SHIFT 12
static inline uint32_t A3XX_GRAS_SC_CONTROL_RASTER_MODE(uint32_t val)
{
return ((val) << A3XX_GRAS_SC_CONTROL_RASTER_MODE__SHIFT) & A3XX_GRAS_SC_CONTROL_RASTER_MODE__MASK;
}
 
#define REG_A3XX_GRAS_SC_SCREEN_SCISSOR_TL 0x00002074
#define A3XX_GRAS_SC_SCREEN_SCISSOR_TL_WINDOW_OFFSET_DISABLE 0x80000000
#define A3XX_GRAS_SC_SCREEN_SCISSOR_TL_X__MASK 0x00007fff
#define A3XX_GRAS_SC_SCREEN_SCISSOR_TL_X__SHIFT 0
static inline uint32_t A3XX_GRAS_SC_SCREEN_SCISSOR_TL_X(uint32_t val)
{
return ((val) << A3XX_GRAS_SC_SCREEN_SCISSOR_TL_X__SHIFT) & A3XX_GRAS_SC_SCREEN_SCISSOR_TL_X__MASK;
}
#define A3XX_GRAS_SC_SCREEN_SCISSOR_TL_Y__MASK 0x7fff0000
#define A3XX_GRAS_SC_SCREEN_SCISSOR_TL_Y__SHIFT 16
static inline uint32_t A3XX_GRAS_SC_SCREEN_SCISSOR_TL_Y(uint32_t val)
{
return ((val) << A3XX_GRAS_SC_SCREEN_SCISSOR_TL_Y__SHIFT) & A3XX_GRAS_SC_SCREEN_SCISSOR_TL_Y__MASK;
}
 
#define REG_A3XX_GRAS_SC_SCREEN_SCISSOR_BR 0x00002075
#define A3XX_GRAS_SC_SCREEN_SCISSOR_BR_WINDOW_OFFSET_DISABLE 0x80000000
#define A3XX_GRAS_SC_SCREEN_SCISSOR_BR_X__MASK 0x00007fff
#define A3XX_GRAS_SC_SCREEN_SCISSOR_BR_X__SHIFT 0
static inline uint32_t A3XX_GRAS_SC_SCREEN_SCISSOR_BR_X(uint32_t val)
{
return ((val) << A3XX_GRAS_SC_SCREEN_SCISSOR_BR_X__SHIFT) & A3XX_GRAS_SC_SCREEN_SCISSOR_BR_X__MASK;
}
#define A3XX_GRAS_SC_SCREEN_SCISSOR_BR_Y__MASK 0x7fff0000
#define A3XX_GRAS_SC_SCREEN_SCISSOR_BR_Y__SHIFT 16
static inline uint32_t A3XX_GRAS_SC_SCREEN_SCISSOR_BR_Y(uint32_t val)
{
return ((val) << A3XX_GRAS_SC_SCREEN_SCISSOR_BR_Y__SHIFT) & A3XX_GRAS_SC_SCREEN_SCISSOR_BR_Y__MASK;
}
 
#define REG_A3XX_GRAS_SC_WINDOW_SCISSOR_TL 0x00002079
#define A3XX_GRAS_SC_WINDOW_SCISSOR_TL_WINDOW_OFFSET_DISABLE 0x80000000
#define A3XX_GRAS_SC_WINDOW_SCISSOR_TL_X__MASK 0x00007fff
#define A3XX_GRAS_SC_WINDOW_SCISSOR_TL_X__SHIFT 0
static inline uint32_t A3XX_GRAS_SC_WINDOW_SCISSOR_TL_X(uint32_t val)
{
return ((val) << A3XX_GRAS_SC_WINDOW_SCISSOR_TL_X__SHIFT) & A3XX_GRAS_SC_WINDOW_SCISSOR_TL_X__MASK;
}
#define A3XX_GRAS_SC_WINDOW_SCISSOR_TL_Y__MASK 0x7fff0000
#define A3XX_GRAS_SC_WINDOW_SCISSOR_TL_Y__SHIFT 16
static inline uint32_t A3XX_GRAS_SC_WINDOW_SCISSOR_TL_Y(uint32_t val)
{
return ((val) << A3XX_GRAS_SC_WINDOW_SCISSOR_TL_Y__SHIFT) & A3XX_GRAS_SC_WINDOW_SCISSOR_TL_Y__MASK;
}
 
#define REG_A3XX_GRAS_SC_WINDOW_SCISSOR_BR 0x0000207a
#define A3XX_GRAS_SC_WINDOW_SCISSOR_BR_WINDOW_OFFSET_DISABLE 0x80000000
#define A3XX_GRAS_SC_WINDOW_SCISSOR_BR_X__MASK 0x00007fff
#define A3XX_GRAS_SC_WINDOW_SCISSOR_BR_X__SHIFT 0
static inline uint32_t A3XX_GRAS_SC_WINDOW_SCISSOR_BR_X(uint32_t val)
{
return ((val) << A3XX_GRAS_SC_WINDOW_SCISSOR_BR_X__SHIFT) & A3XX_GRAS_SC_WINDOW_SCISSOR_BR_X__MASK;
}
#define A3XX_GRAS_SC_WINDOW_SCISSOR_BR_Y__MASK 0x7fff0000
#define A3XX_GRAS_SC_WINDOW_SCISSOR_BR_Y__SHIFT 16
static inline uint32_t A3XX_GRAS_SC_WINDOW_SCISSOR_BR_Y(uint32_t val)
{
return ((val) << A3XX_GRAS_SC_WINDOW_SCISSOR_BR_Y__SHIFT) & A3XX_GRAS_SC_WINDOW_SCISSOR_BR_Y__MASK;
}
 
#define REG_A3XX_RB_MODE_CONTROL 0x000020c0
#define A3XX_RB_MODE_CONTROL_GMEM_BYPASS 0x00000080
#define A3XX_RB_MODE_CONTROL_RENDER_MODE__MASK 0x00000700
#define A3XX_RB_MODE_CONTROL_RENDER_MODE__SHIFT 8
static inline uint32_t A3XX_RB_MODE_CONTROL_RENDER_MODE(enum a3xx_render_mode val)
{
return ((val) << A3XX_RB_MODE_CONTROL_RENDER_MODE__SHIFT) & A3XX_RB_MODE_CONTROL_RENDER_MODE__MASK;
}
#define A3XX_RB_MODE_CONTROL_MRT__MASK 0x00003000
#define A3XX_RB_MODE_CONTROL_MRT__SHIFT 12
static inline uint32_t A3XX_RB_MODE_CONTROL_MRT(uint32_t val)
{
return ((val) << A3XX_RB_MODE_CONTROL_MRT__SHIFT) & A3XX_RB_MODE_CONTROL_MRT__MASK;
}
#define A3XX_RB_MODE_CONTROL_MARB_CACHE_SPLIT_MODE 0x00008000
#define A3XX_RB_MODE_CONTROL_PACKER_TIMER_ENABLE 0x00010000
 
#define REG_A3XX_RB_RENDER_CONTROL 0x000020c1
#define A3XX_RB_RENDER_CONTROL_FACENESS 0x00000008
#define A3XX_RB_RENDER_CONTROL_BIN_WIDTH__MASK 0x00000ff0
#define A3XX_RB_RENDER_CONTROL_BIN_WIDTH__SHIFT 4
static inline uint32_t A3XX_RB_RENDER_CONTROL_BIN_WIDTH(uint32_t val)
{
return ((val >> 5) << A3XX_RB_RENDER_CONTROL_BIN_WIDTH__SHIFT) & A3XX_RB_RENDER_CONTROL_BIN_WIDTH__MASK;
}
#define A3XX_RB_RENDER_CONTROL_DISABLE_COLOR_PIPE 0x00001000
#define A3XX_RB_RENDER_CONTROL_ENABLE_GMEM 0x00002000
#define A3XX_RB_RENDER_CONTROL_XCOORD 0x00004000
#define A3XX_RB_RENDER_CONTROL_YCOORD 0x00008000
#define A3XX_RB_RENDER_CONTROL_ZCOORD 0x00010000
#define A3XX_RB_RENDER_CONTROL_WCOORD 0x00020000
#define A3XX_RB_RENDER_CONTROL_ALPHA_TEST 0x00400000
#define A3XX_RB_RENDER_CONTROL_ALPHA_TEST_FUNC__MASK 0x07000000
#define A3XX_RB_RENDER_CONTROL_ALPHA_TEST_FUNC__SHIFT 24
static inline uint32_t A3XX_RB_RENDER_CONTROL_ALPHA_TEST_FUNC(enum adreno_compare_func val)
{
return ((val) << A3XX_RB_RENDER_CONTROL_ALPHA_TEST_FUNC__SHIFT) & A3XX_RB_RENDER_CONTROL_ALPHA_TEST_FUNC__MASK;
}
 
#define REG_A3XX_RB_MSAA_CONTROL 0x000020c2
#define A3XX_RB_MSAA_CONTROL_DISABLE 0x00000400
#define A3XX_RB_MSAA_CONTROL_SAMPLES__MASK 0x0000f000
#define A3XX_RB_MSAA_CONTROL_SAMPLES__SHIFT 12
static inline uint32_t A3XX_RB_MSAA_CONTROL_SAMPLES(enum a3xx_msaa_samples val)
{
return ((val) << A3XX_RB_MSAA_CONTROL_SAMPLES__SHIFT) & A3XX_RB_MSAA_CONTROL_SAMPLES__MASK;
}
#define A3XX_RB_MSAA_CONTROL_SAMPLE_MASK__MASK 0xffff0000
#define A3XX_RB_MSAA_CONTROL_SAMPLE_MASK__SHIFT 16
static inline uint32_t A3XX_RB_MSAA_CONTROL_SAMPLE_MASK(uint32_t val)
{
return ((val) << A3XX_RB_MSAA_CONTROL_SAMPLE_MASK__SHIFT) & A3XX_RB_MSAA_CONTROL_SAMPLE_MASK__MASK;
}
 
#define REG_A3XX_RB_ALPHA_REF 0x000020c3
#define A3XX_RB_ALPHA_REF_UINT__MASK 0x0000ff00
#define A3XX_RB_ALPHA_REF_UINT__SHIFT 8
static inline uint32_t A3XX_RB_ALPHA_REF_UINT(uint32_t val)
{
return ((val) << A3XX_RB_ALPHA_REF_UINT__SHIFT) & A3XX_RB_ALPHA_REF_UINT__MASK;
}
#define A3XX_RB_ALPHA_REF_FLOAT__MASK 0xffff0000
#define A3XX_RB_ALPHA_REF_FLOAT__SHIFT 16
static inline uint32_t A3XX_RB_ALPHA_REF_FLOAT(float val)
{
return ((util_float_to_half(val)) << A3XX_RB_ALPHA_REF_FLOAT__SHIFT) & A3XX_RB_ALPHA_REF_FLOAT__MASK;
}
 
static inline uint32_t REG_A3XX_RB_MRT(uint32_t i0) { return 0x000020c4 + 0x4*i0; }
 
static inline uint32_t REG_A3XX_RB_MRT_CONTROL(uint32_t i0) { return 0x000020c4 + 0x4*i0; }
#define A3XX_RB_MRT_CONTROL_READ_DEST_ENABLE 0x00000008
#define A3XX_RB_MRT_CONTROL_BLEND 0x00000010
#define A3XX_RB_MRT_CONTROL_BLEND2 0x00000020
#define A3XX_RB_MRT_CONTROL_ROP_CODE__MASK 0x00000f00
#define A3XX_RB_MRT_CONTROL_ROP_CODE__SHIFT 8
static inline uint32_t A3XX_RB_MRT_CONTROL_ROP_CODE(enum a3xx_rop_code val)
{
return ((val) << A3XX_RB_MRT_CONTROL_ROP_CODE__SHIFT) & A3XX_RB_MRT_CONTROL_ROP_CODE__MASK;
}
#define A3XX_RB_MRT_CONTROL_DITHER_MODE__MASK 0x00003000
#define A3XX_RB_MRT_CONTROL_DITHER_MODE__SHIFT 12
static inline uint32_t A3XX_RB_MRT_CONTROL_DITHER_MODE(enum adreno_rb_dither_mode val)
{
return ((val) << A3XX_RB_MRT_CONTROL_DITHER_MODE__SHIFT) & A3XX_RB_MRT_CONTROL_DITHER_MODE__MASK;
}
#define A3XX_RB_MRT_CONTROL_COMPONENT_ENABLE__MASK 0x0f000000
#define A3XX_RB_MRT_CONTROL_COMPONENT_ENABLE__SHIFT 24
static inline uint32_t A3XX_RB_MRT_CONTROL_COMPONENT_ENABLE(uint32_t val)
{
return ((val) << A3XX_RB_MRT_CONTROL_COMPONENT_ENABLE__SHIFT) & A3XX_RB_MRT_CONTROL_COMPONENT_ENABLE__MASK;
}
 
static inline uint32_t REG_A3XX_RB_MRT_BUF_INFO(uint32_t i0) { return 0x000020c5 + 0x4*i0; }
#define A3XX_RB_MRT_BUF_INFO_COLOR_FORMAT__MASK 0x0000003f
#define A3XX_RB_MRT_BUF_INFO_COLOR_FORMAT__SHIFT 0
static inline uint32_t A3XX_RB_MRT_BUF_INFO_COLOR_FORMAT(enum a3xx_color_fmt val)
{
return ((val) << A3XX_RB_MRT_BUF_INFO_COLOR_FORMAT__SHIFT) & A3XX_RB_MRT_BUF_INFO_COLOR_FORMAT__MASK;
}
#define A3XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE__MASK 0x000000c0
#define A3XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE__SHIFT 6
static inline uint32_t A3XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE(enum a3xx_tile_mode val)
{
return ((val) << A3XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE__SHIFT) & A3XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE__MASK;
}
#define A3XX_RB_MRT_BUF_INFO_COLOR_SWAP__MASK 0x00000c00
#define A3XX_RB_MRT_BUF_INFO_COLOR_SWAP__SHIFT 10
static inline uint32_t A3XX_RB_MRT_BUF_INFO_COLOR_SWAP(enum a3xx_color_swap val)
{
return ((val) << A3XX_RB_MRT_BUF_INFO_COLOR_SWAP__SHIFT) & A3XX_RB_MRT_BUF_INFO_COLOR_SWAP__MASK;
}
#define A3XX_RB_MRT_BUF_INFO_COLOR_SRGB 0x00004000
#define A3XX_RB_MRT_BUF_INFO_COLOR_BUF_PITCH__MASK 0xfffe0000
#define A3XX_RB_MRT_BUF_INFO_COLOR_BUF_PITCH__SHIFT 17
static inline uint32_t A3XX_RB_MRT_BUF_INFO_COLOR_BUF_PITCH(uint32_t val)
{
return ((val >> 5) << A3XX_RB_MRT_BUF_INFO_COLOR_BUF_PITCH__SHIFT) & A3XX_RB_MRT_BUF_INFO_COLOR_BUF_PITCH__MASK;
}
 
static inline uint32_t REG_A3XX_RB_MRT_BUF_BASE(uint32_t i0) { return 0x000020c6 + 0x4*i0; }
#define A3XX_RB_MRT_BUF_BASE_COLOR_BUF_BASE__MASK 0xfffffff0
#define A3XX_RB_MRT_BUF_BASE_COLOR_BUF_BASE__SHIFT 4
static inline uint32_t A3XX_RB_MRT_BUF_BASE_COLOR_BUF_BASE(uint32_t val)
{
return ((val >> 5) << A3XX_RB_MRT_BUF_BASE_COLOR_BUF_BASE__SHIFT) & A3XX_RB_MRT_BUF_BASE_COLOR_BUF_BASE__MASK;
}
 
static inline uint32_t REG_A3XX_RB_MRT_BLEND_CONTROL(uint32_t i0) { return 0x000020c7 + 0x4*i0; }
#define A3XX_RB_MRT_BLEND_CONTROL_RGB_SRC_FACTOR__MASK 0x0000001f
#define A3XX_RB_MRT_BLEND_CONTROL_RGB_SRC_FACTOR__SHIFT 0
static inline uint32_t A3XX_RB_MRT_BLEND_CONTROL_RGB_SRC_FACTOR(enum adreno_rb_blend_factor val)
{
return ((val) << A3XX_RB_MRT_BLEND_CONTROL_RGB_SRC_FACTOR__SHIFT) & A3XX_RB_MRT_BLEND_CONTROL_RGB_SRC_FACTOR__MASK;
}
#define A3XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE__MASK 0x000000e0
#define A3XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE__SHIFT 5
static inline uint32_t A3XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE(enum a3xx_rb_blend_opcode val)
{
return ((val) << A3XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE__SHIFT) & A3XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE__MASK;
}
#define A3XX_RB_MRT_BLEND_CONTROL_RGB_DEST_FACTOR__MASK 0x00001f00
#define A3XX_RB_MRT_BLEND_CONTROL_RGB_DEST_FACTOR__SHIFT 8
static inline uint32_t A3XX_RB_MRT_BLEND_CONTROL_RGB_DEST_FACTOR(enum adreno_rb_blend_factor val)
{
return ((val) << A3XX_RB_MRT_BLEND_CONTROL_RGB_DEST_FACTOR__SHIFT) & A3XX_RB_MRT_BLEND_CONTROL_RGB_DEST_FACTOR__MASK;
}
#define A3XX_RB_MRT_BLEND_CONTROL_ALPHA_SRC_FACTOR__MASK 0x001f0000
#define A3XX_RB_MRT_BLEND_CONTROL_ALPHA_SRC_FACTOR__SHIFT 16
static inline uint32_t A3XX_RB_MRT_BLEND_CONTROL_ALPHA_SRC_FACTOR(enum adreno_rb_blend_factor val)
{
return ((val) << A3XX_RB_MRT_BLEND_CONTROL_ALPHA_SRC_FACTOR__SHIFT) & A3XX_RB_MRT_BLEND_CONTROL_ALPHA_SRC_FACTOR__MASK;
}
#define A3XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE__MASK 0x00e00000
#define A3XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE__SHIFT 21
static inline uint32_t A3XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE(enum a3xx_rb_blend_opcode val)
{
return ((val) << A3XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE__SHIFT) & A3XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE__MASK;
}
#define A3XX_RB_MRT_BLEND_CONTROL_ALPHA_DEST_FACTOR__MASK 0x1f000000
#define A3XX_RB_MRT_BLEND_CONTROL_ALPHA_DEST_FACTOR__SHIFT 24
static inline uint32_t A3XX_RB_MRT_BLEND_CONTROL_ALPHA_DEST_FACTOR(enum adreno_rb_blend_factor val)
{
return ((val) << A3XX_RB_MRT_BLEND_CONTROL_ALPHA_DEST_FACTOR__SHIFT) & A3XX_RB_MRT_BLEND_CONTROL_ALPHA_DEST_FACTOR__MASK;
}
#define A3XX_RB_MRT_BLEND_CONTROL_CLAMP_ENABLE 0x20000000
 
#define REG_A3XX_RB_BLEND_RED 0x000020e4
#define A3XX_RB_BLEND_RED_UINT__MASK 0x000000ff
#define A3XX_RB_BLEND_RED_UINT__SHIFT 0
static inline uint32_t A3XX_RB_BLEND_RED_UINT(uint32_t val)
{
return ((val) << A3XX_RB_BLEND_RED_UINT__SHIFT) & A3XX_RB_BLEND_RED_UINT__MASK;
}
#define A3XX_RB_BLEND_RED_FLOAT__MASK 0xffff0000
#define A3XX_RB_BLEND_RED_FLOAT__SHIFT 16
static inline uint32_t A3XX_RB_BLEND_RED_FLOAT(float val)
{
return ((util_float_to_half(val)) << A3XX_RB_BLEND_RED_FLOAT__SHIFT) & A3XX_RB_BLEND_RED_FLOAT__MASK;
}
 
#define REG_A3XX_RB_BLEND_GREEN 0x000020e5
#define A3XX_RB_BLEND_GREEN_UINT__MASK 0x000000ff
#define A3XX_RB_BLEND_GREEN_UINT__SHIFT 0
static inline uint32_t A3XX_RB_BLEND_GREEN_UINT(uint32_t val)
{
return ((val) << A3XX_RB_BLEND_GREEN_UINT__SHIFT) & A3XX_RB_BLEND_GREEN_UINT__MASK;
}
#define A3XX_RB_BLEND_GREEN_FLOAT__MASK 0xffff0000
#define A3XX_RB_BLEND_GREEN_FLOAT__SHIFT 16
static inline uint32_t A3XX_RB_BLEND_GREEN_FLOAT(float val)
{
return ((util_float_to_half(val)) << A3XX_RB_BLEND_GREEN_FLOAT__SHIFT) & A3XX_RB_BLEND_GREEN_FLOAT__MASK;
}
 
#define REG_A3XX_RB_BLEND_BLUE 0x000020e6
#define A3XX_RB_BLEND_BLUE_UINT__MASK 0x000000ff
#define A3XX_RB_BLEND_BLUE_UINT__SHIFT 0
static inline uint32_t A3XX_RB_BLEND_BLUE_UINT(uint32_t val)
{
return ((val) << A3XX_RB_BLEND_BLUE_UINT__SHIFT) & A3XX_RB_BLEND_BLUE_UINT__MASK;
}
#define A3XX_RB_BLEND_BLUE_FLOAT__MASK 0xffff0000
#define A3XX_RB_BLEND_BLUE_FLOAT__SHIFT 16
static inline uint32_t A3XX_RB_BLEND_BLUE_FLOAT(float val)
{
return ((util_float_to_half(val)) << A3XX_RB_BLEND_BLUE_FLOAT__SHIFT) & A3XX_RB_BLEND_BLUE_FLOAT__MASK;
}
 
#define REG_A3XX_RB_BLEND_ALPHA 0x000020e7
#define A3XX_RB_BLEND_ALPHA_UINT__MASK 0x000000ff
#define A3XX_RB_BLEND_ALPHA_UINT__SHIFT 0
static inline uint32_t A3XX_RB_BLEND_ALPHA_UINT(uint32_t val)
{
return ((val) << A3XX_RB_BLEND_ALPHA_UINT__SHIFT) & A3XX_RB_BLEND_ALPHA_UINT__MASK;
}
#define A3XX_RB_BLEND_ALPHA_FLOAT__MASK 0xffff0000
#define A3XX_RB_BLEND_ALPHA_FLOAT__SHIFT 16
static inline uint32_t A3XX_RB_BLEND_ALPHA_FLOAT(float val)
{
return ((util_float_to_half(val)) << A3XX_RB_BLEND_ALPHA_FLOAT__SHIFT) & A3XX_RB_BLEND_ALPHA_FLOAT__MASK;
}
 
#define REG_A3XX_RB_CLEAR_COLOR_DW0 0x000020e8
 
#define REG_A3XX_RB_CLEAR_COLOR_DW1 0x000020e9
 
#define REG_A3XX_RB_CLEAR_COLOR_DW2 0x000020ea
 
#define REG_A3XX_RB_CLEAR_COLOR_DW3 0x000020eb
 
#define REG_A3XX_RB_COPY_CONTROL 0x000020ec
#define A3XX_RB_COPY_CONTROL_MSAA_RESOLVE__MASK 0x00000003
#define A3XX_RB_COPY_CONTROL_MSAA_RESOLVE__SHIFT 0
static inline uint32_t A3XX_RB_COPY_CONTROL_MSAA_RESOLVE(enum a3xx_msaa_samples val)
{
return ((val) << A3XX_RB_COPY_CONTROL_MSAA_RESOLVE__SHIFT) & A3XX_RB_COPY_CONTROL_MSAA_RESOLVE__MASK;
}
#define A3XX_RB_COPY_CONTROL_DEPTHCLEAR 0x00000008
#define A3XX_RB_COPY_CONTROL_MODE__MASK 0x00000070
#define A3XX_RB_COPY_CONTROL_MODE__SHIFT 4
static inline uint32_t A3XX_RB_COPY_CONTROL_MODE(enum adreno_rb_copy_control_mode val)
{
return ((val) << A3XX_RB_COPY_CONTROL_MODE__SHIFT) & A3XX_RB_COPY_CONTROL_MODE__MASK;
}
#define A3XX_RB_COPY_CONTROL_FASTCLEAR__MASK 0x00000f00
#define A3XX_RB_COPY_CONTROL_FASTCLEAR__SHIFT 8
static inline uint32_t A3XX_RB_COPY_CONTROL_FASTCLEAR(uint32_t val)
{
return ((val) << A3XX_RB_COPY_CONTROL_FASTCLEAR__SHIFT) & A3XX_RB_COPY_CONTROL_FASTCLEAR__MASK;
}
#define A3XX_RB_COPY_CONTROL_UNK12 0x00001000
#define A3XX_RB_COPY_CONTROL_GMEM_BASE__MASK 0xffffc000
#define A3XX_RB_COPY_CONTROL_GMEM_BASE__SHIFT 14
static inline uint32_t A3XX_RB_COPY_CONTROL_GMEM_BASE(uint32_t val)
{
return ((val >> 14) << A3XX_RB_COPY_CONTROL_GMEM_BASE__SHIFT) & A3XX_RB_COPY_CONTROL_GMEM_BASE__MASK;
}
 
#define REG_A3XX_RB_COPY_DEST_BASE 0x000020ed
#define A3XX_RB_COPY_DEST_BASE_BASE__MASK 0xfffffff0
#define A3XX_RB_COPY_DEST_BASE_BASE__SHIFT 4
static inline uint32_t A3XX_RB_COPY_DEST_BASE_BASE(uint32_t val)
{
return ((val >> 5) << A3XX_RB_COPY_DEST_BASE_BASE__SHIFT) & A3XX_RB_COPY_DEST_BASE_BASE__MASK;
}
 
#define REG_A3XX_RB_COPY_DEST_PITCH 0x000020ee
#define A3XX_RB_COPY_DEST_PITCH_PITCH__MASK 0xffffffff
#define A3XX_RB_COPY_DEST_PITCH_PITCH__SHIFT 0
static inline uint32_t A3XX_RB_COPY_DEST_PITCH_PITCH(uint32_t val)
{
return ((val >> 5) << A3XX_RB_COPY_DEST_PITCH_PITCH__SHIFT) & A3XX_RB_COPY_DEST_PITCH_PITCH__MASK;
}
 
#define REG_A3XX_RB_COPY_DEST_INFO 0x000020ef
#define A3XX_RB_COPY_DEST_INFO_TILE__MASK 0x00000003
#define A3XX_RB_COPY_DEST_INFO_TILE__SHIFT 0
static inline uint32_t A3XX_RB_COPY_DEST_INFO_TILE(enum a3xx_tile_mode val)
{
return ((val) << A3XX_RB_COPY_DEST_INFO_TILE__SHIFT) & A3XX_RB_COPY_DEST_INFO_TILE__MASK;
}
#define A3XX_RB_COPY_DEST_INFO_FORMAT__MASK 0x000000fc
#define A3XX_RB_COPY_DEST_INFO_FORMAT__SHIFT 2
static inline uint32_t A3XX_RB_COPY_DEST_INFO_FORMAT(enum a3xx_color_fmt val)
{
return ((val) << A3XX_RB_COPY_DEST_INFO_FORMAT__SHIFT) & A3XX_RB_COPY_DEST_INFO_FORMAT__MASK;
}
#define A3XX_RB_COPY_DEST_INFO_SWAP__MASK 0x00000300
#define A3XX_RB_COPY_DEST_INFO_SWAP__SHIFT 8
static inline uint32_t A3XX_RB_COPY_DEST_INFO_SWAP(enum a3xx_color_swap val)
{
return ((val) << A3XX_RB_COPY_DEST_INFO_SWAP__SHIFT) & A3XX_RB_COPY_DEST_INFO_SWAP__MASK;
}
#define A3XX_RB_COPY_DEST_INFO_DITHER_MODE__MASK 0x00000c00
#define A3XX_RB_COPY_DEST_INFO_DITHER_MODE__SHIFT 10
static inline uint32_t A3XX_RB_COPY_DEST_INFO_DITHER_MODE(enum adreno_rb_dither_mode val)
{
return ((val) << A3XX_RB_COPY_DEST_INFO_DITHER_MODE__SHIFT) & A3XX_RB_COPY_DEST_INFO_DITHER_MODE__MASK;
}
#define A3XX_RB_COPY_DEST_INFO_COMPONENT_ENABLE__MASK 0x0003c000
#define A3XX_RB_COPY_DEST_INFO_COMPONENT_ENABLE__SHIFT 14
static inline uint32_t A3XX_RB_COPY_DEST_INFO_COMPONENT_ENABLE(uint32_t val)
{
return ((val) << A3XX_RB_COPY_DEST_INFO_COMPONENT_ENABLE__SHIFT) & A3XX_RB_COPY_DEST_INFO_COMPONENT_ENABLE__MASK;
}
#define A3XX_RB_COPY_DEST_INFO_ENDIAN__MASK 0x001c0000
#define A3XX_RB_COPY_DEST_INFO_ENDIAN__SHIFT 18
static inline uint32_t A3XX_RB_COPY_DEST_INFO_ENDIAN(enum adreno_rb_surface_endian val)
{
return ((val) << A3XX_RB_COPY_DEST_INFO_ENDIAN__SHIFT) & A3XX_RB_COPY_DEST_INFO_ENDIAN__MASK;
}
 
#define REG_A3XX_RB_DEPTH_CONTROL 0x00002100
#define A3XX_RB_DEPTH_CONTROL_FRAG_WRITES_Z 0x00000001
#define A3XX_RB_DEPTH_CONTROL_Z_ENABLE 0x00000002
#define A3XX_RB_DEPTH_CONTROL_Z_WRITE_ENABLE 0x00000004
#define A3XX_RB_DEPTH_CONTROL_EARLY_Z_DISABLE 0x00000008
#define A3XX_RB_DEPTH_CONTROL_ZFUNC__MASK 0x00000070
#define A3XX_RB_DEPTH_CONTROL_ZFUNC__SHIFT 4
static inline uint32_t A3XX_RB_DEPTH_CONTROL_ZFUNC(enum adreno_compare_func val)
{
return ((val) << A3XX_RB_DEPTH_CONTROL_ZFUNC__SHIFT) & A3XX_RB_DEPTH_CONTROL_ZFUNC__MASK;
}
#define A3XX_RB_DEPTH_CONTROL_BF_ENABLE 0x00000080
#define A3XX_RB_DEPTH_CONTROL_Z_TEST_ENABLE 0x80000000
 
#define REG_A3XX_RB_DEPTH_CLEAR 0x00002101
 
#define REG_A3XX_RB_DEPTH_INFO 0x00002102
#define A3XX_RB_DEPTH_INFO_DEPTH_FORMAT__MASK 0x00000003
#define A3XX_RB_DEPTH_INFO_DEPTH_FORMAT__SHIFT 0
static inline uint32_t A3XX_RB_DEPTH_INFO_DEPTH_FORMAT(enum adreno_rb_depth_format val)
{
return ((val) << A3XX_RB_DEPTH_INFO_DEPTH_FORMAT__SHIFT) & A3XX_RB_DEPTH_INFO_DEPTH_FORMAT__MASK;
}
#define A3XX_RB_DEPTH_INFO_DEPTH_BASE__MASK 0xfffff800
#define A3XX_RB_DEPTH_INFO_DEPTH_BASE__SHIFT 11
static inline uint32_t A3XX_RB_DEPTH_INFO_DEPTH_BASE(uint32_t val)
{
return ((val >> 12) << A3XX_RB_DEPTH_INFO_DEPTH_BASE__SHIFT) & A3XX_RB_DEPTH_INFO_DEPTH_BASE__MASK;
}
 
#define REG_A3XX_RB_DEPTH_PITCH 0x00002103
#define A3XX_RB_DEPTH_PITCH__MASK 0xffffffff
#define A3XX_RB_DEPTH_PITCH__SHIFT 0
static inline uint32_t A3XX_RB_DEPTH_PITCH(uint32_t val)
{
return ((val >> 3) << A3XX_RB_DEPTH_PITCH__SHIFT) & A3XX_RB_DEPTH_PITCH__MASK;
}
 
#define REG_A3XX_RB_STENCIL_CONTROL 0x00002104
#define A3XX_RB_STENCIL_CONTROL_STENCIL_ENABLE 0x00000001
#define A3XX_RB_STENCIL_CONTROL_STENCIL_ENABLE_BF 0x00000002
#define A3XX_RB_STENCIL_CONTROL_STENCIL_READ 0x00000004
#define A3XX_RB_STENCIL_CONTROL_FUNC__MASK 0x00000700
#define A3XX_RB_STENCIL_CONTROL_FUNC__SHIFT 8
static inline uint32_t A3XX_RB_STENCIL_CONTROL_FUNC(enum adreno_compare_func val)
{
return ((val) << A3XX_RB_STENCIL_CONTROL_FUNC__SHIFT) & A3XX_RB_STENCIL_CONTROL_FUNC__MASK;
}
#define A3XX_RB_STENCIL_CONTROL_FAIL__MASK 0x00003800
#define A3XX_RB_STENCIL_CONTROL_FAIL__SHIFT 11
static inline uint32_t A3XX_RB_STENCIL_CONTROL_FAIL(enum adreno_stencil_op val)
{
return ((val) << A3XX_RB_STENCIL_CONTROL_FAIL__SHIFT) & A3XX_RB_STENCIL_CONTROL_FAIL__MASK;
}
#define A3XX_RB_STENCIL_CONTROL_ZPASS__MASK 0x0001c000
#define A3XX_RB_STENCIL_CONTROL_ZPASS__SHIFT 14
static inline uint32_t A3XX_RB_STENCIL_CONTROL_ZPASS(enum adreno_stencil_op val)
{
return ((val) << A3XX_RB_STENCIL_CONTROL_ZPASS__SHIFT) & A3XX_RB_STENCIL_CONTROL_ZPASS__MASK;
}
#define A3XX_RB_STENCIL_CONTROL_ZFAIL__MASK 0x000e0000
#define A3XX_RB_STENCIL_CONTROL_ZFAIL__SHIFT 17
static inline uint32_t A3XX_RB_STENCIL_CONTROL_ZFAIL(enum adreno_stencil_op val)
{
return ((val) << A3XX_RB_STENCIL_CONTROL_ZFAIL__SHIFT) & A3XX_RB_STENCIL_CONTROL_ZFAIL__MASK;
}
#define A3XX_RB_STENCIL_CONTROL_FUNC_BF__MASK 0x00700000
#define A3XX_RB_STENCIL_CONTROL_FUNC_BF__SHIFT 20
static inline uint32_t A3XX_RB_STENCIL_CONTROL_FUNC_BF(enum adreno_compare_func val)
{
return ((val) << A3XX_RB_STENCIL_CONTROL_FUNC_BF__SHIFT) & A3XX_RB_STENCIL_CONTROL_FUNC_BF__MASK;
}
#define A3XX_RB_STENCIL_CONTROL_FAIL_BF__MASK 0x03800000
#define A3XX_RB_STENCIL_CONTROL_FAIL_BF__SHIFT 23
static inline uint32_t A3XX_RB_STENCIL_CONTROL_FAIL_BF(enum adreno_stencil_op val)
{
return ((val) << A3XX_RB_STENCIL_CONTROL_FAIL_BF__SHIFT) & A3XX_RB_STENCIL_CONTROL_FAIL_BF__MASK;
}
#define A3XX_RB_STENCIL_CONTROL_ZPASS_BF__MASK 0x1c000000
#define A3XX_RB_STENCIL_CONTROL_ZPASS_BF__SHIFT 26
static inline uint32_t A3XX_RB_STENCIL_CONTROL_ZPASS_BF(enum adreno_stencil_op val)
{
return ((val) << A3XX_RB_STENCIL_CONTROL_ZPASS_BF__SHIFT) & A3XX_RB_STENCIL_CONTROL_ZPASS_BF__MASK;
}
#define A3XX_RB_STENCIL_CONTROL_ZFAIL_BF__MASK 0xe0000000
#define A3XX_RB_STENCIL_CONTROL_ZFAIL_BF__SHIFT 29
static inline uint32_t A3XX_RB_STENCIL_CONTROL_ZFAIL_BF(enum adreno_stencil_op val)
{
return ((val) << A3XX_RB_STENCIL_CONTROL_ZFAIL_BF__SHIFT) & A3XX_RB_STENCIL_CONTROL_ZFAIL_BF__MASK;
}
 
#define REG_A3XX_RB_STENCIL_CLEAR 0x00002105
 
#define REG_A3XX_RB_STENCIL_INFO 0x00002106
#define A3XX_RB_STENCIL_INFO_STENCIL_BASE__MASK 0xfffff800
#define A3XX_RB_STENCIL_INFO_STENCIL_BASE__SHIFT 11
static inline uint32_t A3XX_RB_STENCIL_INFO_STENCIL_BASE(uint32_t val)
{
return ((val >> 12) << A3XX_RB_STENCIL_INFO_STENCIL_BASE__SHIFT) & A3XX_RB_STENCIL_INFO_STENCIL_BASE__MASK;
}
 
#define REG_A3XX_RB_STENCIL_PITCH 0x00002107
#define A3XX_RB_STENCIL_PITCH__MASK 0xffffffff
#define A3XX_RB_STENCIL_PITCH__SHIFT 0
static inline uint32_t A3XX_RB_STENCIL_PITCH(uint32_t val)
{
return ((val >> 3) << A3XX_RB_STENCIL_PITCH__SHIFT) & A3XX_RB_STENCIL_PITCH__MASK;
}
 
#define REG_A3XX_RB_STENCILREFMASK 0x00002108
#define A3XX_RB_STENCILREFMASK_STENCILREF__MASK 0x000000ff
#define A3XX_RB_STENCILREFMASK_STENCILREF__SHIFT 0
static inline uint32_t A3XX_RB_STENCILREFMASK_STENCILREF(uint32_t val)
{
return ((val) << A3XX_RB_STENCILREFMASK_STENCILREF__SHIFT) & A3XX_RB_STENCILREFMASK_STENCILREF__MASK;
}
#define A3XX_RB_STENCILREFMASK_STENCILMASK__MASK 0x0000ff00
#define A3XX_RB_STENCILREFMASK_STENCILMASK__SHIFT 8
static inline uint32_t A3XX_RB_STENCILREFMASK_STENCILMASK(uint32_t val)
{
return ((val) << A3XX_RB_STENCILREFMASK_STENCILMASK__SHIFT) & A3XX_RB_STENCILREFMASK_STENCILMASK__MASK;
}
#define A3XX_RB_STENCILREFMASK_STENCILWRITEMASK__MASK 0x00ff0000
#define A3XX_RB_STENCILREFMASK_STENCILWRITEMASK__SHIFT 16
static inline uint32_t A3XX_RB_STENCILREFMASK_STENCILWRITEMASK(uint32_t val)
{
return ((val) << A3XX_RB_STENCILREFMASK_STENCILWRITEMASK__SHIFT) & A3XX_RB_STENCILREFMASK_STENCILWRITEMASK__MASK;
}
 
#define REG_A3XX_RB_STENCILREFMASK_BF 0x00002109
#define A3XX_RB_STENCILREFMASK_BF_STENCILREF__MASK 0x000000ff
#define A3XX_RB_STENCILREFMASK_BF_STENCILREF__SHIFT 0
static inline uint32_t A3XX_RB_STENCILREFMASK_BF_STENCILREF(uint32_t val)
{
return ((val) << A3XX_RB_STENCILREFMASK_BF_STENCILREF__SHIFT) & A3XX_RB_STENCILREFMASK_BF_STENCILREF__MASK;
}
#define A3XX_RB_STENCILREFMASK_BF_STENCILMASK__MASK 0x0000ff00
#define A3XX_RB_STENCILREFMASK_BF_STENCILMASK__SHIFT 8
static inline uint32_t A3XX_RB_STENCILREFMASK_BF_STENCILMASK(uint32_t val)
{
return ((val) << A3XX_RB_STENCILREFMASK_BF_STENCILMASK__SHIFT) & A3XX_RB_STENCILREFMASK_BF_STENCILMASK__MASK;
}
#define A3XX_RB_STENCILREFMASK_BF_STENCILWRITEMASK__MASK 0x00ff0000
#define A3XX_RB_STENCILREFMASK_BF_STENCILWRITEMASK__SHIFT 16
static inline uint32_t A3XX_RB_STENCILREFMASK_BF_STENCILWRITEMASK(uint32_t val)
{
return ((val) << A3XX_RB_STENCILREFMASK_BF_STENCILWRITEMASK__SHIFT) & A3XX_RB_STENCILREFMASK_BF_STENCILWRITEMASK__MASK;
}
 
#define REG_A3XX_RB_LRZ_VSC_CONTROL 0x0000210c
#define A3XX_RB_LRZ_VSC_CONTROL_BINNING_ENABLE 0x00000002
 
#define REG_A3XX_RB_WINDOW_OFFSET 0x0000210e
#define A3XX_RB_WINDOW_OFFSET_X__MASK 0x0000ffff
#define A3XX_RB_WINDOW_OFFSET_X__SHIFT 0
static inline uint32_t A3XX_RB_WINDOW_OFFSET_X(uint32_t val)
{
return ((val) << A3XX_RB_WINDOW_OFFSET_X__SHIFT) & A3XX_RB_WINDOW_OFFSET_X__MASK;
}
#define A3XX_RB_WINDOW_OFFSET_Y__MASK 0xffff0000
#define A3XX_RB_WINDOW_OFFSET_Y__SHIFT 16
static inline uint32_t A3XX_RB_WINDOW_OFFSET_Y(uint32_t val)
{
return ((val) << A3XX_RB_WINDOW_OFFSET_Y__SHIFT) & A3XX_RB_WINDOW_OFFSET_Y__MASK;
}
 
#define REG_A3XX_RB_SAMPLE_COUNT_CONTROL 0x00002110
#define A3XX_RB_SAMPLE_COUNT_CONTROL_RESET 0x00000001
#define A3XX_RB_SAMPLE_COUNT_CONTROL_COPY 0x00000002
 
#define REG_A3XX_RB_SAMPLE_COUNT_ADDR 0x00002111
 
#define REG_A3XX_RB_Z_CLAMP_MIN 0x00002114
 
#define REG_A3XX_RB_Z_CLAMP_MAX 0x00002115
 
#define REG_A3XX_VGT_BIN_BASE 0x000021e1
 
#define REG_A3XX_VGT_BIN_SIZE 0x000021e2
 
#define REG_A3XX_PC_VSTREAM_CONTROL 0x000021e4
#define A3XX_PC_VSTREAM_CONTROL_SIZE__MASK 0x003f0000
#define A3XX_PC_VSTREAM_CONTROL_SIZE__SHIFT 16
static inline uint32_t A3XX_PC_VSTREAM_CONTROL_SIZE(uint32_t val)
{
return ((val) << A3XX_PC_VSTREAM_CONTROL_SIZE__SHIFT) & A3XX_PC_VSTREAM_CONTROL_SIZE__MASK;
}
#define A3XX_PC_VSTREAM_CONTROL_N__MASK 0x07c00000
#define A3XX_PC_VSTREAM_CONTROL_N__SHIFT 22
static inline uint32_t A3XX_PC_VSTREAM_CONTROL_N(uint32_t val)
{
return ((val) << A3XX_PC_VSTREAM_CONTROL_N__SHIFT) & A3XX_PC_VSTREAM_CONTROL_N__MASK;
}
 
#define REG_A3XX_PC_VERTEX_REUSE_BLOCK_CNTL 0x000021ea
 
#define REG_A3XX_PC_PRIM_VTX_CNTL 0x000021ec
#define A3XX_PC_PRIM_VTX_CNTL_STRIDE_IN_VPC__MASK 0x0000001f
#define A3XX_PC_PRIM_VTX_CNTL_STRIDE_IN_VPC__SHIFT 0
static inline uint32_t A3XX_PC_PRIM_VTX_CNTL_STRIDE_IN_VPC(uint32_t val)
{
return ((val) << A3XX_PC_PRIM_VTX_CNTL_STRIDE_IN_VPC__SHIFT) & A3XX_PC_PRIM_VTX_CNTL_STRIDE_IN_VPC__MASK;
}
#define A3XX_PC_PRIM_VTX_CNTL_POLYMODE_FRONT_PTYPE__MASK 0x000000e0
#define A3XX_PC_PRIM_VTX_CNTL_POLYMODE_FRONT_PTYPE__SHIFT 5
static inline uint32_t A3XX_PC_PRIM_VTX_CNTL_POLYMODE_FRONT_PTYPE(enum adreno_pa_su_sc_draw val)
{
return ((val) << A3XX_PC_PRIM_VTX_CNTL_POLYMODE_FRONT_PTYPE__SHIFT) & A3XX_PC_PRIM_VTX_CNTL_POLYMODE_FRONT_PTYPE__MASK;
}
#define A3XX_PC_PRIM_VTX_CNTL_POLYMODE_BACK_PTYPE__MASK 0x00000700
#define A3XX_PC_PRIM_VTX_CNTL_POLYMODE_BACK_PTYPE__SHIFT 8
static inline uint32_t A3XX_PC_PRIM_VTX_CNTL_POLYMODE_BACK_PTYPE(enum adreno_pa_su_sc_draw val)
{
return ((val) << A3XX_PC_PRIM_VTX_CNTL_POLYMODE_BACK_PTYPE__SHIFT) & A3XX_PC_PRIM_VTX_CNTL_POLYMODE_BACK_PTYPE__MASK;
}
#define A3XX_PC_PRIM_VTX_CNTL_POLYMODE_ENABLE 0x00001000
#define A3XX_PC_PRIM_VTX_CNTL_PRIMITIVE_RESTART 0x00100000
#define A3XX_PC_PRIM_VTX_CNTL_PROVOKING_VTX_LAST 0x02000000
#define A3XX_PC_PRIM_VTX_CNTL_PSIZE 0x04000000
 
#define REG_A3XX_PC_RESTART_INDEX 0x000021ed
 
#define REG_A3XX_HLSQ_CONTROL_0_REG 0x00002200
#define A3XX_HLSQ_CONTROL_0_REG_FSTHREADSIZE__MASK 0x00000010
#define A3XX_HLSQ_CONTROL_0_REG_FSTHREADSIZE__SHIFT 4
static inline uint32_t A3XX_HLSQ_CONTROL_0_REG_FSTHREADSIZE(enum a3xx_threadsize val)
{
return ((val) << A3XX_HLSQ_CONTROL_0_REG_FSTHREADSIZE__SHIFT) & A3XX_HLSQ_CONTROL_0_REG_FSTHREADSIZE__MASK;
}
#define A3XX_HLSQ_CONTROL_0_REG_FSSUPERTHREADENABLE 0x00000040
#define A3XX_HLSQ_CONTROL_0_REG_SPSHADERRESTART 0x00000200
#define A3XX_HLSQ_CONTROL_0_REG_RESERVED2 0x00000400
#define A3XX_HLSQ_CONTROL_0_REG_CHUNKDISABLE 0x04000000
#define A3XX_HLSQ_CONTROL_0_REG_CONSTMODE__MASK 0x08000000
#define A3XX_HLSQ_CONTROL_0_REG_CONSTMODE__SHIFT 27
static inline uint32_t A3XX_HLSQ_CONTROL_0_REG_CONSTMODE(uint32_t val)
{
return ((val) << A3XX_HLSQ_CONTROL_0_REG_CONSTMODE__SHIFT) & A3XX_HLSQ_CONTROL_0_REG_CONSTMODE__MASK;
}
#define A3XX_HLSQ_CONTROL_0_REG_LAZYUPDATEDISABLE 0x10000000
#define A3XX_HLSQ_CONTROL_0_REG_SPCONSTFULLUPDATE 0x20000000
#define A3XX_HLSQ_CONTROL_0_REG_TPFULLUPDATE 0x40000000
#define A3XX_HLSQ_CONTROL_0_REG_SINGLECONTEXT 0x80000000
 
#define REG_A3XX_HLSQ_CONTROL_1_REG 0x00002201
#define A3XX_HLSQ_CONTROL_1_REG_VSTHREADSIZE__MASK 0x00000040
#define A3XX_HLSQ_CONTROL_1_REG_VSTHREADSIZE__SHIFT 6
static inline uint32_t A3XX_HLSQ_CONTROL_1_REG_VSTHREADSIZE(enum a3xx_threadsize val)
{
return ((val) << A3XX_HLSQ_CONTROL_1_REG_VSTHREADSIZE__SHIFT) & A3XX_HLSQ_CONTROL_1_REG_VSTHREADSIZE__MASK;
}
#define A3XX_HLSQ_CONTROL_1_REG_VSSUPERTHREADENABLE 0x00000100
#define A3XX_HLSQ_CONTROL_1_REG_RESERVED1 0x00000200
#define A3XX_HLSQ_CONTROL_1_REG_ZWCOORD 0x02000000
 
#define REG_A3XX_HLSQ_CONTROL_2_REG 0x00002202
#define A3XX_HLSQ_CONTROL_2_REG_PRIMALLOCTHRESHOLD__MASK 0xfc000000
#define A3XX_HLSQ_CONTROL_2_REG_PRIMALLOCTHRESHOLD__SHIFT 26
static inline uint32_t A3XX_HLSQ_CONTROL_2_REG_PRIMALLOCTHRESHOLD(uint32_t val)
{
return ((val) << A3XX_HLSQ_CONTROL_2_REG_PRIMALLOCTHRESHOLD__SHIFT) & A3XX_HLSQ_CONTROL_2_REG_PRIMALLOCTHRESHOLD__MASK;
}
 
#define REG_A3XX_HLSQ_CONTROL_3_REG 0x00002203
#define A3XX_HLSQ_CONTROL_3_REG_REGID__MASK 0x000000ff
#define A3XX_HLSQ_CONTROL_3_REG_REGID__SHIFT 0
static inline uint32_t A3XX_HLSQ_CONTROL_3_REG_REGID(uint32_t val)
{
return ((val) << A3XX_HLSQ_CONTROL_3_REG_REGID__SHIFT) & A3XX_HLSQ_CONTROL_3_REG_REGID__MASK;
}
 
#define REG_A3XX_HLSQ_VS_CONTROL_REG 0x00002204
#define A3XX_HLSQ_VS_CONTROL_REG_CONSTLENGTH__MASK 0x00000fff
#define A3XX_HLSQ_VS_CONTROL_REG_CONSTLENGTH__SHIFT 0
static inline uint32_t A3XX_HLSQ_VS_CONTROL_REG_CONSTLENGTH(uint32_t val)
{
return ((val) << A3XX_HLSQ_VS_CONTROL_REG_CONSTLENGTH__SHIFT) & A3XX_HLSQ_VS_CONTROL_REG_CONSTLENGTH__MASK;
}
#define A3XX_HLSQ_VS_CONTROL_REG_CONSTSTARTOFFSET__MASK 0x00fff000
#define A3XX_HLSQ_VS_CONTROL_REG_CONSTSTARTOFFSET__SHIFT 12
static inline uint32_t A3XX_HLSQ_VS_CONTROL_REG_CONSTSTARTOFFSET(uint32_t val)
{
return ((val) << A3XX_HLSQ_VS_CONTROL_REG_CONSTSTARTOFFSET__SHIFT) & A3XX_HLSQ_VS_CONTROL_REG_CONSTSTARTOFFSET__MASK;
}
#define A3XX_HLSQ_VS_CONTROL_REG_INSTRLENGTH__MASK 0xff000000
#define A3XX_HLSQ_VS_CONTROL_REG_INSTRLENGTH__SHIFT 24
static inline uint32_t A3XX_HLSQ_VS_CONTROL_REG_INSTRLENGTH(uint32_t val)
{
return ((val) << A3XX_HLSQ_VS_CONTROL_REG_INSTRLENGTH__SHIFT) & A3XX_HLSQ_VS_CONTROL_REG_INSTRLENGTH__MASK;
}
 
#define REG_A3XX_HLSQ_FS_CONTROL_REG 0x00002205
#define A3XX_HLSQ_FS_CONTROL_REG_CONSTLENGTH__MASK 0x00000fff
#define A3XX_HLSQ_FS_CONTROL_REG_CONSTLENGTH__SHIFT 0
static inline uint32_t A3XX_HLSQ_FS_CONTROL_REG_CONSTLENGTH(uint32_t val)
{
return ((val) << A3XX_HLSQ_FS_CONTROL_REG_CONSTLENGTH__SHIFT) & A3XX_HLSQ_FS_CONTROL_REG_CONSTLENGTH__MASK;
}
#define A3XX_HLSQ_FS_CONTROL_REG_CONSTSTARTOFFSET__MASK 0x00fff000
#define A3XX_HLSQ_FS_CONTROL_REG_CONSTSTARTOFFSET__SHIFT 12
static inline uint32_t A3XX_HLSQ_FS_CONTROL_REG_CONSTSTARTOFFSET(uint32_t val)
{
return ((val) << A3XX_HLSQ_FS_CONTROL_REG_CONSTSTARTOFFSET__SHIFT) & A3XX_HLSQ_FS_CONTROL_REG_CONSTSTARTOFFSET__MASK;
}
#define A3XX_HLSQ_FS_CONTROL_REG_INSTRLENGTH__MASK 0xff000000
#define A3XX_HLSQ_FS_CONTROL_REG_INSTRLENGTH__SHIFT 24
static inline uint32_t A3XX_HLSQ_FS_CONTROL_REG_INSTRLENGTH(uint32_t val)
{
return ((val) << A3XX_HLSQ_FS_CONTROL_REG_INSTRLENGTH__SHIFT) & A3XX_HLSQ_FS_CONTROL_REG_INSTRLENGTH__MASK;
}
 
#define REG_A3XX_HLSQ_CONST_VSPRESV_RANGE_REG 0x00002206
#define A3XX_HLSQ_CONST_VSPRESV_RANGE_REG_STARTENTRY__MASK 0x0000ffff
#define A3XX_HLSQ_CONST_VSPRESV_RANGE_REG_STARTENTRY__SHIFT 0
static inline uint32_t A3XX_HLSQ_CONST_VSPRESV_RANGE_REG_STARTENTRY(uint32_t val)
{
return ((val) << A3XX_HLSQ_CONST_VSPRESV_RANGE_REG_STARTENTRY__SHIFT) & A3XX_HLSQ_CONST_VSPRESV_RANGE_REG_STARTENTRY__MASK;
}
#define A3XX_HLSQ_CONST_VSPRESV_RANGE_REG_ENDENTRY__MASK 0xffff0000
#define A3XX_HLSQ_CONST_VSPRESV_RANGE_REG_ENDENTRY__SHIFT 16
static inline uint32_t A3XX_HLSQ_CONST_VSPRESV_RANGE_REG_ENDENTRY(uint32_t val)
{
return ((val) << A3XX_HLSQ_CONST_VSPRESV_RANGE_REG_ENDENTRY__SHIFT) & A3XX_HLSQ_CONST_VSPRESV_RANGE_REG_ENDENTRY__MASK;
}
 
#define REG_A3XX_HLSQ_CONST_FSPRESV_RANGE_REG 0x00002207
#define A3XX_HLSQ_CONST_FSPRESV_RANGE_REG_STARTENTRY__MASK 0x0000ffff
#define A3XX_HLSQ_CONST_FSPRESV_RANGE_REG_STARTENTRY__SHIFT 0
static inline uint32_t A3XX_HLSQ_CONST_FSPRESV_RANGE_REG_STARTENTRY(uint32_t val)
{
return ((val) << A3XX_HLSQ_CONST_FSPRESV_RANGE_REG_STARTENTRY__SHIFT) & A3XX_HLSQ_CONST_FSPRESV_RANGE_REG_STARTENTRY__MASK;
}
#define A3XX_HLSQ_CONST_FSPRESV_RANGE_REG_ENDENTRY__MASK 0xffff0000
#define A3XX_HLSQ_CONST_FSPRESV_RANGE_REG_ENDENTRY__SHIFT 16
static inline uint32_t A3XX_HLSQ_CONST_FSPRESV_RANGE_REG_ENDENTRY(uint32_t val)
{
return ((val) << A3XX_HLSQ_CONST_FSPRESV_RANGE_REG_ENDENTRY__SHIFT) & A3XX_HLSQ_CONST_FSPRESV_RANGE_REG_ENDENTRY__MASK;
}
 
#define REG_A3XX_HLSQ_CL_NDRANGE_0_REG 0x0000220a
#define A3XX_HLSQ_CL_NDRANGE_0_REG_WORKDIM__MASK 0x00000003
#define A3XX_HLSQ_CL_NDRANGE_0_REG_WORKDIM__SHIFT 0
static inline uint32_t A3XX_HLSQ_CL_NDRANGE_0_REG_WORKDIM(uint32_t val)
{
return ((val) << A3XX_HLSQ_CL_NDRANGE_0_REG_WORKDIM__SHIFT) & A3XX_HLSQ_CL_NDRANGE_0_REG_WORKDIM__MASK;
}
#define A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE0__MASK 0x00000ffc
#define A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE0__SHIFT 2
static inline uint32_t A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE0(uint32_t val)
{
return ((val) << A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE0__SHIFT) & A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE0__MASK;
}
#define A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE1__MASK 0x003ff000
#define A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE1__SHIFT 12
static inline uint32_t A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE1(uint32_t val)
{
return ((val) << A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE1__SHIFT) & A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE1__MASK;
}
#define A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE2__MASK 0xffc00000
#define A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE2__SHIFT 22
static inline uint32_t A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE2(uint32_t val)
{
return ((val) << A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE2__SHIFT) & A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE2__MASK;
}
 
static inline uint32_t REG_A3XX_HLSQ_CL_GLOBAL_WORK(uint32_t i0) { return 0x0000220b + 0x2*i0; }
 
static inline uint32_t REG_A3XX_HLSQ_CL_GLOBAL_WORK_SIZE(uint32_t i0) { return 0x0000220b + 0x2*i0; }
 
static inline uint32_t REG_A3XX_HLSQ_CL_GLOBAL_WORK_OFFSET(uint32_t i0) { return 0x0000220c + 0x2*i0; }
 
#define REG_A3XX_HLSQ_CL_CONTROL_0_REG 0x00002211
 
#define REG_A3XX_HLSQ_CL_CONTROL_1_REG 0x00002212
 
#define REG_A3XX_HLSQ_CL_KERNEL_CONST_REG 0x00002214
 
static inline uint32_t REG_A3XX_HLSQ_CL_KERNEL_GROUP(uint32_t i0) { return 0x00002215 + 0x1*i0; }
 
static inline uint32_t REG_A3XX_HLSQ_CL_KERNEL_GROUP_RATIO(uint32_t i0) { return 0x00002215 + 0x1*i0; }
 
#define REG_A3XX_HLSQ_CL_KERNEL_GROUP_Y_REG 0x00002216
 
#define REG_A3XX_HLSQ_CL_KERNEL_GROUP_Z_REG 0x00002217
 
#define REG_A3XX_HLSQ_CL_WG_OFFSET_REG 0x0000221a
 
#define REG_A3XX_VFD_CONTROL_0 0x00002240
#define A3XX_VFD_CONTROL_0_TOTALATTRTOVS__MASK 0x0003ffff
#define A3XX_VFD_CONTROL_0_TOTALATTRTOVS__SHIFT 0
static inline uint32_t A3XX_VFD_CONTROL_0_TOTALATTRTOVS(uint32_t val)
{
return ((val) << A3XX_VFD_CONTROL_0_TOTALATTRTOVS__SHIFT) & A3XX_VFD_CONTROL_0_TOTALATTRTOVS__MASK;
}
#define A3XX_VFD_CONTROL_0_PACKETSIZE__MASK 0x003c0000
#define A3XX_VFD_CONTROL_0_PACKETSIZE__SHIFT 18
static inline uint32_t A3XX_VFD_CONTROL_0_PACKETSIZE(uint32_t val)
{
return ((val) << A3XX_VFD_CONTROL_0_PACKETSIZE__SHIFT) & A3XX_VFD_CONTROL_0_PACKETSIZE__MASK;
}
#define A3XX_VFD_CONTROL_0_STRMDECINSTRCNT__MASK 0x07c00000
#define A3XX_VFD_CONTROL_0_STRMDECINSTRCNT__SHIFT 22
static inline uint32_t A3XX_VFD_CONTROL_0_STRMDECINSTRCNT(uint32_t val)
{
return ((val) << A3XX_VFD_CONTROL_0_STRMDECINSTRCNT__SHIFT) & A3XX_VFD_CONTROL_0_STRMDECINSTRCNT__MASK;
}
#define A3XX_VFD_CONTROL_0_STRMFETCHINSTRCNT__MASK 0xf8000000
#define A3XX_VFD_CONTROL_0_STRMFETCHINSTRCNT__SHIFT 27
static inline uint32_t A3XX_VFD_CONTROL_0_STRMFETCHINSTRCNT(uint32_t val)
{
return ((val) << A3XX_VFD_CONTROL_0_STRMFETCHINSTRCNT__SHIFT) & A3XX_VFD_CONTROL_0_STRMFETCHINSTRCNT__MASK;
}
 
#define REG_A3XX_VFD_CONTROL_1 0x00002241
#define A3XX_VFD_CONTROL_1_MAXSTORAGE__MASK 0x0000ffff
#define A3XX_VFD_CONTROL_1_MAXSTORAGE__SHIFT 0
static inline uint32_t A3XX_VFD_CONTROL_1_MAXSTORAGE(uint32_t val)
{
return ((val) << A3XX_VFD_CONTROL_1_MAXSTORAGE__SHIFT) & A3XX_VFD_CONTROL_1_MAXSTORAGE__MASK;
}
#define A3XX_VFD_CONTROL_1_REGID4VTX__MASK 0x00ff0000
#define A3XX_VFD_CONTROL_1_REGID4VTX__SHIFT 16
static inline uint32_t A3XX_VFD_CONTROL_1_REGID4VTX(uint32_t val)
{
return ((val) << A3XX_VFD_CONTROL_1_REGID4VTX__SHIFT) & A3XX_VFD_CONTROL_1_REGID4VTX__MASK;
}
#define A3XX_VFD_CONTROL_1_REGID4INST__MASK 0xff000000
#define A3XX_VFD_CONTROL_1_REGID4INST__SHIFT 24
static inline uint32_t A3XX_VFD_CONTROL_1_REGID4INST(uint32_t val)
{
return ((val) << A3XX_VFD_CONTROL_1_REGID4INST__SHIFT) & A3XX_VFD_CONTROL_1_REGID4INST__MASK;
}
 
#define REG_A3XX_VFD_INDEX_MIN 0x00002242
 
#define REG_A3XX_VFD_INDEX_MAX 0x00002243
 
#define REG_A3XX_VFD_INSTANCEID_OFFSET 0x00002244
 
#define REG_A3XX_VFD_INDEX_OFFSET 0x00002245
 
#define REG_A3XX_VFD_INDEX_OFFSET 0x00002245
 
static inline uint32_t REG_A3XX_VFD_FETCH(uint32_t i0) { return 0x00002246 + 0x2*i0; }
 
static inline uint32_t REG_A3XX_VFD_FETCH_INSTR_0(uint32_t i0) { return 0x00002246 + 0x2*i0; }
#define A3XX_VFD_FETCH_INSTR_0_FETCHSIZE__MASK 0x0000007f
#define A3XX_VFD_FETCH_INSTR_0_FETCHSIZE__SHIFT 0
static inline uint32_t A3XX_VFD_FETCH_INSTR_0_FETCHSIZE(uint32_t val)
{
return ((val) << A3XX_VFD_FETCH_INSTR_0_FETCHSIZE__SHIFT) & A3XX_VFD_FETCH_INSTR_0_FETCHSIZE__MASK;
}
#define A3XX_VFD_FETCH_INSTR_0_BUFSTRIDE__MASK 0x0000ff80
#define A3XX_VFD_FETCH_INSTR_0_BUFSTRIDE__SHIFT 7
static inline uint32_t A3XX_VFD_FETCH_INSTR_0_BUFSTRIDE(uint32_t val)
{
return ((val) << A3XX_VFD_FETCH_INSTR_0_BUFSTRIDE__SHIFT) & A3XX_VFD_FETCH_INSTR_0_BUFSTRIDE__MASK;
}
#define A3XX_VFD_FETCH_INSTR_0_INSTANCED 0x00010000
#define A3XX_VFD_FETCH_INSTR_0_SWITCHNEXT 0x00020000
#define A3XX_VFD_FETCH_INSTR_0_INDEXCODE__MASK 0x00fc0000
#define A3XX_VFD_FETCH_INSTR_0_INDEXCODE__SHIFT 18
static inline uint32_t A3XX_VFD_FETCH_INSTR_0_INDEXCODE(uint32_t val)
{
return ((val) << A3XX_VFD_FETCH_INSTR_0_INDEXCODE__SHIFT) & A3XX_VFD_FETCH_INSTR_0_INDEXCODE__MASK;
}
#define A3XX_VFD_FETCH_INSTR_0_STEPRATE__MASK 0xff000000
#define A3XX_VFD_FETCH_INSTR_0_STEPRATE__SHIFT 24
static inline uint32_t A3XX_VFD_FETCH_INSTR_0_STEPRATE(uint32_t val)
{
return ((val) << A3XX_VFD_FETCH_INSTR_0_STEPRATE__SHIFT) & A3XX_VFD_FETCH_INSTR_0_STEPRATE__MASK;
}
 
static inline uint32_t REG_A3XX_VFD_FETCH_INSTR_1(uint32_t i0) { return 0x00002247 + 0x2*i0; }
 
static inline uint32_t REG_A3XX_VFD_DECODE(uint32_t i0) { return 0x00002266 + 0x1*i0; }
 
static inline uint32_t REG_A3XX_VFD_DECODE_INSTR(uint32_t i0) { return 0x00002266 + 0x1*i0; }
#define A3XX_VFD_DECODE_INSTR_WRITEMASK__MASK 0x0000000f
#define A3XX_VFD_DECODE_INSTR_WRITEMASK__SHIFT 0
static inline uint32_t A3XX_VFD_DECODE_INSTR_WRITEMASK(uint32_t val)
{
return ((val) << A3XX_VFD_DECODE_INSTR_WRITEMASK__SHIFT) & A3XX_VFD_DECODE_INSTR_WRITEMASK__MASK;
}
#define A3XX_VFD_DECODE_INSTR_CONSTFILL 0x00000010
#define A3XX_VFD_DECODE_INSTR_FORMAT__MASK 0x00000fc0
#define A3XX_VFD_DECODE_INSTR_FORMAT__SHIFT 6
static inline uint32_t A3XX_VFD_DECODE_INSTR_FORMAT(enum a3xx_vtx_fmt val)
{
return ((val) << A3XX_VFD_DECODE_INSTR_FORMAT__SHIFT) & A3XX_VFD_DECODE_INSTR_FORMAT__MASK;
}
#define A3XX_VFD_DECODE_INSTR_REGID__MASK 0x000ff000
#define A3XX_VFD_DECODE_INSTR_REGID__SHIFT 12
static inline uint32_t A3XX_VFD_DECODE_INSTR_REGID(uint32_t val)
{
return ((val) << A3XX_VFD_DECODE_INSTR_REGID__SHIFT) & A3XX_VFD_DECODE_INSTR_REGID__MASK;
}
#define A3XX_VFD_DECODE_INSTR_INT 0x00100000
#define A3XX_VFD_DECODE_INSTR_SWAP__MASK 0x00c00000
#define A3XX_VFD_DECODE_INSTR_SWAP__SHIFT 22
static inline uint32_t A3XX_VFD_DECODE_INSTR_SWAP(enum a3xx_color_swap val)
{
return ((val) << A3XX_VFD_DECODE_INSTR_SWAP__SHIFT) & A3XX_VFD_DECODE_INSTR_SWAP__MASK;
}
#define A3XX_VFD_DECODE_INSTR_SHIFTCNT__MASK 0x1f000000
#define A3XX_VFD_DECODE_INSTR_SHIFTCNT__SHIFT 24
static inline uint32_t A3XX_VFD_DECODE_INSTR_SHIFTCNT(uint32_t val)
{
return ((val) << A3XX_VFD_DECODE_INSTR_SHIFTCNT__SHIFT) & A3XX_VFD_DECODE_INSTR_SHIFTCNT__MASK;
}
#define A3XX_VFD_DECODE_INSTR_LASTCOMPVALID 0x20000000
#define A3XX_VFD_DECODE_INSTR_SWITCHNEXT 0x40000000
 
#define REG_A3XX_VFD_VS_THREADING_THRESHOLD 0x0000227e
#define A3XX_VFD_VS_THREADING_THRESHOLD_REGID_THRESHOLD__MASK 0x0000000f
#define A3XX_VFD_VS_THREADING_THRESHOLD_REGID_THRESHOLD__SHIFT 0
static inline uint32_t A3XX_VFD_VS_THREADING_THRESHOLD_REGID_THRESHOLD(uint32_t val)
{
return ((val) << A3XX_VFD_VS_THREADING_THRESHOLD_REGID_THRESHOLD__SHIFT) & A3XX_VFD_VS_THREADING_THRESHOLD_REGID_THRESHOLD__MASK;
}
#define A3XX_VFD_VS_THREADING_THRESHOLD_REGID_VTXCNT__MASK 0x0000ff00
#define A3XX_VFD_VS_THREADING_THRESHOLD_REGID_VTXCNT__SHIFT 8
static inline uint32_t A3XX_VFD_VS_THREADING_THRESHOLD_REGID_VTXCNT(uint32_t val)
{
return ((val) << A3XX_VFD_VS_THREADING_THRESHOLD_REGID_VTXCNT__SHIFT) & A3XX_VFD_VS_THREADING_THRESHOLD_REGID_VTXCNT__MASK;
}
 
#define REG_A3XX_VPC_ATTR 0x00002280
#define A3XX_VPC_ATTR_TOTALATTR__MASK 0x000001ff
#define A3XX_VPC_ATTR_TOTALATTR__SHIFT 0
static inline uint32_t A3XX_VPC_ATTR_TOTALATTR(uint32_t val)
{
return ((val) << A3XX_VPC_ATTR_TOTALATTR__SHIFT) & A3XX_VPC_ATTR_TOTALATTR__MASK;
}
#define A3XX_VPC_ATTR_PSIZE 0x00000200
#define A3XX_VPC_ATTR_THRDASSIGN__MASK 0x0ffff000
#define A3XX_VPC_ATTR_THRDASSIGN__SHIFT 12
static inline uint32_t A3XX_VPC_ATTR_THRDASSIGN(uint32_t val)
{
return ((val) << A3XX_VPC_ATTR_THRDASSIGN__SHIFT) & A3XX_VPC_ATTR_THRDASSIGN__MASK;
}
#define A3XX_VPC_ATTR_LMSIZE__MASK 0xf0000000
#define A3XX_VPC_ATTR_LMSIZE__SHIFT 28
static inline uint32_t A3XX_VPC_ATTR_LMSIZE(uint32_t val)
{
return ((val) << A3XX_VPC_ATTR_LMSIZE__SHIFT) & A3XX_VPC_ATTR_LMSIZE__MASK;
}
 
#define REG_A3XX_VPC_PACK 0x00002281
#define A3XX_VPC_PACK_NUMFPNONPOSVAR__MASK 0x0000ff00
#define A3XX_VPC_PACK_NUMFPNONPOSVAR__SHIFT 8
static inline uint32_t A3XX_VPC_PACK_NUMFPNONPOSVAR(uint32_t val)
{
return ((val) << A3XX_VPC_PACK_NUMFPNONPOSVAR__SHIFT) & A3XX_VPC_PACK_NUMFPNONPOSVAR__MASK;
}
#define A3XX_VPC_PACK_NUMNONPOSVSVAR__MASK 0x00ff0000
#define A3XX_VPC_PACK_NUMNONPOSVSVAR__SHIFT 16
static inline uint32_t A3XX_VPC_PACK_NUMNONPOSVSVAR(uint32_t val)
{
return ((val) << A3XX_VPC_PACK_NUMNONPOSVSVAR__SHIFT) & A3XX_VPC_PACK_NUMNONPOSVSVAR__MASK;
}
 
static inline uint32_t REG_A3XX_VPC_VARYING_INTERP(uint32_t i0) { return 0x00002282 + 0x1*i0; }
 
static inline uint32_t REG_A3XX_VPC_VARYING_INTERP_MODE(uint32_t i0) { return 0x00002282 + 0x1*i0; }
#define A3XX_VPC_VARYING_INTERP_MODE_C0__MASK 0x00000003
#define A3XX_VPC_VARYING_INTERP_MODE_C0__SHIFT 0
static inline uint32_t A3XX_VPC_VARYING_INTERP_MODE_C0(enum a3xx_intp_mode val)
{
return ((val) << A3XX_VPC_VARYING_INTERP_MODE_C0__SHIFT) & A3XX_VPC_VARYING_INTERP_MODE_C0__MASK;
}
#define A3XX_VPC_VARYING_INTERP_MODE_C1__MASK 0x0000000c
#define A3XX_VPC_VARYING_INTERP_MODE_C1__SHIFT 2
static inline uint32_t A3XX_VPC_VARYING_INTERP_MODE_C1(enum a3xx_intp_mode val)
{
return ((val) << A3XX_VPC_VARYING_INTERP_MODE_C1__SHIFT) & A3XX_VPC_VARYING_INTERP_MODE_C1__MASK;
}
#define A3XX_VPC_VARYING_INTERP_MODE_C2__MASK 0x00000030
#define A3XX_VPC_VARYING_INTERP_MODE_C2__SHIFT 4
static inline uint32_t A3XX_VPC_VARYING_INTERP_MODE_C2(enum a3xx_intp_mode val)
{
return ((val) << A3XX_VPC_VARYING_INTERP_MODE_C2__SHIFT) & A3XX_VPC_VARYING_INTERP_MODE_C2__MASK;
}
#define A3XX_VPC_VARYING_INTERP_MODE_C3__MASK 0x000000c0
#define A3XX_VPC_VARYING_INTERP_MODE_C3__SHIFT 6
static inline uint32_t A3XX_VPC_VARYING_INTERP_MODE_C3(enum a3xx_intp_mode val)
{
return ((val) << A3XX_VPC_VARYING_INTERP_MODE_C3__SHIFT) & A3XX_VPC_VARYING_INTERP_MODE_C3__MASK;
}
#define A3XX_VPC_VARYING_INTERP_MODE_C4__MASK 0x00000300
#define A3XX_VPC_VARYING_INTERP_MODE_C4__SHIFT 8
static inline uint32_t A3XX_VPC_VARYING_INTERP_MODE_C4(enum a3xx_intp_mode val)
{
return ((val) << A3XX_VPC_VARYING_INTERP_MODE_C4__SHIFT) & A3XX_VPC_VARYING_INTERP_MODE_C4__MASK;
}
#define A3XX_VPC_VARYING_INTERP_MODE_C5__MASK 0x00000c00
#define A3XX_VPC_VARYING_INTERP_MODE_C5__SHIFT 10
static inline uint32_t A3XX_VPC_VARYING_INTERP_MODE_C5(enum a3xx_intp_mode val)
{
return ((val) << A3XX_VPC_VARYING_INTERP_MODE_C5__SHIFT) & A3XX_VPC_VARYING_INTERP_MODE_C5__MASK;
}
#define A3XX_VPC_VARYING_INTERP_MODE_C6__MASK 0x00003000
#define A3XX_VPC_VARYING_INTERP_MODE_C6__SHIFT 12
static inline uint32_t A3XX_VPC_VARYING_INTERP_MODE_C6(enum a3xx_intp_mode val)
{
return ((val) << A3XX_VPC_VARYING_INTERP_MODE_C6__SHIFT) & A3XX_VPC_VARYING_INTERP_MODE_C6__MASK;
}
#define A3XX_VPC_VARYING_INTERP_MODE_C7__MASK 0x0000c000
#define A3XX_VPC_VARYING_INTERP_MODE_C7__SHIFT 14
static inline uint32_t A3XX_VPC_VARYING_INTERP_MODE_C7(enum a3xx_intp_mode val)
{
return ((val) << A3XX_VPC_VARYING_INTERP_MODE_C7__SHIFT) & A3XX_VPC_VARYING_INTERP_MODE_C7__MASK;
}
#define A3XX_VPC_VARYING_INTERP_MODE_C8__MASK 0x00030000
#define A3XX_VPC_VARYING_INTERP_MODE_C8__SHIFT 16
static inline uint32_t A3XX_VPC_VARYING_INTERP_MODE_C8(enum a3xx_intp_mode val)
{
return ((val) << A3XX_VPC_VARYING_INTERP_MODE_C8__SHIFT) & A3XX_VPC_VARYING_INTERP_MODE_C8__MASK;
}
#define A3XX_VPC_VARYING_INTERP_MODE_C9__MASK 0x000c0000
#define A3XX_VPC_VARYING_INTERP_MODE_C9__SHIFT 18
static inline uint32_t A3XX_VPC_VARYING_INTERP_MODE_C9(enum a3xx_intp_mode val)
{
return ((val) << A3XX_VPC_VARYING_INTERP_MODE_C9__SHIFT) & A3XX_VPC_VARYING_INTERP_MODE_C9__MASK;
}
#define A3XX_VPC_VARYING_INTERP_MODE_CA__MASK 0x00300000
#define A3XX_VPC_VARYING_INTERP_MODE_CA__SHIFT 20
static inline uint32_t A3XX_VPC_VARYING_INTERP_MODE_CA(enum a3xx_intp_mode val)
{
return ((val) << A3XX_VPC_VARYING_INTERP_MODE_CA__SHIFT) & A3XX_VPC_VARYING_INTERP_MODE_CA__MASK;
}
#define A3XX_VPC_VARYING_INTERP_MODE_CB__MASK 0x00c00000
#define A3XX_VPC_VARYING_INTERP_MODE_CB__SHIFT 22
static inline uint32_t A3XX_VPC_VARYING_INTERP_MODE_CB(enum a3xx_intp_mode val)
{
return ((val) << A3XX_VPC_VARYING_INTERP_MODE_CB__SHIFT) & A3XX_VPC_VARYING_INTERP_MODE_CB__MASK;
}
#define A3XX_VPC_VARYING_INTERP_MODE_CC__MASK 0x03000000
#define A3XX_VPC_VARYING_INTERP_MODE_CC__SHIFT 24
static inline uint32_t A3XX_VPC_VARYING_INTERP_MODE_CC(enum a3xx_intp_mode val)
{
return ((val) << A3XX_VPC_VARYING_INTERP_MODE_CC__SHIFT) & A3XX_VPC_VARYING_INTERP_MODE_CC__MASK;
}
#define A3XX_VPC_VARYING_INTERP_MODE_CD__MASK 0x0c000000
#define A3XX_VPC_VARYING_INTERP_MODE_CD__SHIFT 26
static inline uint32_t A3XX_VPC_VARYING_INTERP_MODE_CD(enum a3xx_intp_mode val)
{
return ((val) << A3XX_VPC_VARYING_INTERP_MODE_CD__SHIFT) & A3XX_VPC_VARYING_INTERP_MODE_CD__MASK;
}
#define A3XX_VPC_VARYING_INTERP_MODE_CE__MASK 0x30000000
#define A3XX_VPC_VARYING_INTERP_MODE_CE__SHIFT 28
static inline uint32_t A3XX_VPC_VARYING_INTERP_MODE_CE(enum a3xx_intp_mode val)
{
return ((val) << A3XX_VPC_VARYING_INTERP_MODE_CE__SHIFT) & A3XX_VPC_VARYING_INTERP_MODE_CE__MASK;
}
#define A3XX_VPC_VARYING_INTERP_MODE_CF__MASK 0xc0000000
#define A3XX_VPC_VARYING_INTERP_MODE_CF__SHIFT 30
static inline uint32_t A3XX_VPC_VARYING_INTERP_MODE_CF(enum a3xx_intp_mode val)
{
return ((val) << A3XX_VPC_VARYING_INTERP_MODE_CF__SHIFT) & A3XX_VPC_VARYING_INTERP_MODE_CF__MASK;
}
 
static inline uint32_t REG_A3XX_VPC_VARYING_PS_REPL(uint32_t i0) { return 0x00002286 + 0x1*i0; }
 
static inline uint32_t REG_A3XX_VPC_VARYING_PS_REPL_MODE(uint32_t i0) { return 0x00002286 + 0x1*i0; }
#define A3XX_VPC_VARYING_PS_REPL_MODE_C0__MASK 0x00000003
#define A3XX_VPC_VARYING_PS_REPL_MODE_C0__SHIFT 0
static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C0(enum a3xx_repl_mode val)
{
return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C0__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C0__MASK;
}
#define A3XX_VPC_VARYING_PS_REPL_MODE_C1__MASK 0x0000000c
#define A3XX_VPC_VARYING_PS_REPL_MODE_C1__SHIFT 2
static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C1(enum a3xx_repl_mode val)
{
return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C1__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C1__MASK;
}
#define A3XX_VPC_VARYING_PS_REPL_MODE_C2__MASK 0x00000030
#define A3XX_VPC_VARYING_PS_REPL_MODE_C2__SHIFT 4
static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C2(enum a3xx_repl_mode val)
{
return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C2__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C2__MASK;
}
#define A3XX_VPC_VARYING_PS_REPL_MODE_C3__MASK 0x000000c0
#define A3XX_VPC_VARYING_PS_REPL_MODE_C3__SHIFT 6
static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C3(enum a3xx_repl_mode val)
{
return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C3__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C3__MASK;
}
#define A3XX_VPC_VARYING_PS_REPL_MODE_C4__MASK 0x00000300
#define A3XX_VPC_VARYING_PS_REPL_MODE_C4__SHIFT 8
static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C4(enum a3xx_repl_mode val)
{
return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C4__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C4__MASK;
}
#define A3XX_VPC_VARYING_PS_REPL_MODE_C5__MASK 0x00000c00
#define A3XX_VPC_VARYING_PS_REPL_MODE_C5__SHIFT 10
static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C5(enum a3xx_repl_mode val)
{
return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C5__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C5__MASK;
}
#define A3XX_VPC_VARYING_PS_REPL_MODE_C6__MASK 0x00003000
#define A3XX_VPC_VARYING_PS_REPL_MODE_C6__SHIFT 12
static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C6(enum a3xx_repl_mode val)
{
return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C6__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C6__MASK;
}
#define A3XX_VPC_VARYING_PS_REPL_MODE_C7__MASK 0x0000c000
#define A3XX_VPC_VARYING_PS_REPL_MODE_C7__SHIFT 14
static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C7(enum a3xx_repl_mode val)
{
return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C7__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C7__MASK;
}
#define A3XX_VPC_VARYING_PS_REPL_MODE_C8__MASK 0x00030000
#define A3XX_VPC_VARYING_PS_REPL_MODE_C8__SHIFT 16
static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C8(enum a3xx_repl_mode val)
{
return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C8__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C8__MASK;
}
#define A3XX_VPC_VARYING_PS_REPL_MODE_C9__MASK 0x000c0000
#define A3XX_VPC_VARYING_PS_REPL_MODE_C9__SHIFT 18
static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C9(enum a3xx_repl_mode val)
{
return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C9__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C9__MASK;
}
#define A3XX_VPC_VARYING_PS_REPL_MODE_CA__MASK 0x00300000
#define A3XX_VPC_VARYING_PS_REPL_MODE_CA__SHIFT 20
static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_CA(enum a3xx_repl_mode val)
{
return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_CA__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_CA__MASK;
}
#define A3XX_VPC_VARYING_PS_REPL_MODE_CB__MASK 0x00c00000
#define A3XX_VPC_VARYING_PS_REPL_MODE_CB__SHIFT 22
static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_CB(enum a3xx_repl_mode val)
{
return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_CB__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_CB__MASK;
}
#define A3XX_VPC_VARYING_PS_REPL_MODE_CC__MASK 0x03000000
#define A3XX_VPC_VARYING_PS_REPL_MODE_CC__SHIFT 24
static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_CC(enum a3xx_repl_mode val)
{
return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_CC__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_CC__MASK;
}
#define A3XX_VPC_VARYING_PS_REPL_MODE_CD__MASK 0x0c000000
#define A3XX_VPC_VARYING_PS_REPL_MODE_CD__SHIFT 26
static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_CD(enum a3xx_repl_mode val)
{
return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_CD__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_CD__MASK;
}
#define A3XX_VPC_VARYING_PS_REPL_MODE_CE__MASK 0x30000000
#define A3XX_VPC_VARYING_PS_REPL_MODE_CE__SHIFT 28
static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_CE(enum a3xx_repl_mode val)
{
return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_CE__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_CE__MASK;
}
#define A3XX_VPC_VARYING_PS_REPL_MODE_CF__MASK 0xc0000000
#define A3XX_VPC_VARYING_PS_REPL_MODE_CF__SHIFT 30
static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_CF(enum a3xx_repl_mode val)
{
return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_CF__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_CF__MASK;
}
 
#define REG_A3XX_VPC_VARY_CYLWRAP_ENABLE_0 0x0000228a
 
#define REG_A3XX_VPC_VARY_CYLWRAP_ENABLE_1 0x0000228b
 
#define REG_A3XX_SP_SP_CTRL_REG 0x000022c0
#define A3XX_SP_SP_CTRL_REG_RESOLVE 0x00010000
#define A3XX_SP_SP_CTRL_REG_CONSTMODE__MASK 0x00040000
#define A3XX_SP_SP_CTRL_REG_CONSTMODE__SHIFT 18
static inline uint32_t A3XX_SP_SP_CTRL_REG_CONSTMODE(uint32_t val)
{
return ((val) << A3XX_SP_SP_CTRL_REG_CONSTMODE__SHIFT) & A3XX_SP_SP_CTRL_REG_CONSTMODE__MASK;
}
#define A3XX_SP_SP_CTRL_REG_BINNING 0x00080000
#define A3XX_SP_SP_CTRL_REG_SLEEPMODE__MASK 0x00300000
#define A3XX_SP_SP_CTRL_REG_SLEEPMODE__SHIFT 20
static inline uint32_t A3XX_SP_SP_CTRL_REG_SLEEPMODE(uint32_t val)
{
return ((val) << A3XX_SP_SP_CTRL_REG_SLEEPMODE__SHIFT) & A3XX_SP_SP_CTRL_REG_SLEEPMODE__MASK;
}
#define A3XX_SP_SP_CTRL_REG_L0MODE__MASK 0x00c00000
#define A3XX_SP_SP_CTRL_REG_L0MODE__SHIFT 22
static inline uint32_t A3XX_SP_SP_CTRL_REG_L0MODE(uint32_t val)
{
return ((val) << A3XX_SP_SP_CTRL_REG_L0MODE__SHIFT) & A3XX_SP_SP_CTRL_REG_L0MODE__MASK;
}
 
#define REG_A3XX_SP_VS_CTRL_REG0 0x000022c4
#define A3XX_SP_VS_CTRL_REG0_THREADMODE__MASK 0x00000001
#define A3XX_SP_VS_CTRL_REG0_THREADMODE__SHIFT 0
static inline uint32_t A3XX_SP_VS_CTRL_REG0_THREADMODE(enum a3xx_threadmode val)
{
return ((val) << A3XX_SP_VS_CTRL_REG0_THREADMODE__SHIFT) & A3XX_SP_VS_CTRL_REG0_THREADMODE__MASK;
}
#define A3XX_SP_VS_CTRL_REG0_INSTRBUFFERMODE__MASK 0x00000002
#define A3XX_SP_VS_CTRL_REG0_INSTRBUFFERMODE__SHIFT 1
static inline uint32_t A3XX_SP_VS_CTRL_REG0_INSTRBUFFERMODE(enum a3xx_instrbuffermode val)
{
return ((val) << A3XX_SP_VS_CTRL_REG0_INSTRBUFFERMODE__SHIFT) & A3XX_SP_VS_CTRL_REG0_INSTRBUFFERMODE__MASK;
}
#define A3XX_SP_VS_CTRL_REG0_CACHEINVALID 0x00000004
#define A3XX_SP_VS_CTRL_REG0_HALFREGFOOTPRINT__MASK 0x000003f0
#define A3XX_SP_VS_CTRL_REG0_HALFREGFOOTPRINT__SHIFT 4
static inline uint32_t A3XX_SP_VS_CTRL_REG0_HALFREGFOOTPRINT(uint32_t val)
{
return ((val) << A3XX_SP_VS_CTRL_REG0_HALFREGFOOTPRINT__SHIFT) & A3XX_SP_VS_CTRL_REG0_HALFREGFOOTPRINT__MASK;
}
#define A3XX_SP_VS_CTRL_REG0_FULLREGFOOTPRINT__MASK 0x0003fc00
#define A3XX_SP_VS_CTRL_REG0_FULLREGFOOTPRINT__SHIFT 10
static inline uint32_t A3XX_SP_VS_CTRL_REG0_FULLREGFOOTPRINT(uint32_t val)
{
return ((val) << A3XX_SP_VS_CTRL_REG0_FULLREGFOOTPRINT__SHIFT) & A3XX_SP_VS_CTRL_REG0_FULLREGFOOTPRINT__MASK;
}
#define A3XX_SP_VS_CTRL_REG0_INOUTREGOVERLAP__MASK 0x000c0000
#define A3XX_SP_VS_CTRL_REG0_INOUTREGOVERLAP__SHIFT 18
static inline uint32_t A3XX_SP_VS_CTRL_REG0_INOUTREGOVERLAP(uint32_t val)
{
return ((val) << A3XX_SP_VS_CTRL_REG0_INOUTREGOVERLAP__SHIFT) & A3XX_SP_VS_CTRL_REG0_INOUTREGOVERLAP__MASK;
}
#define A3XX_SP_VS_CTRL_REG0_THREADSIZE__MASK 0x00100000
#define A3XX_SP_VS_CTRL_REG0_THREADSIZE__SHIFT 20
static inline uint32_t A3XX_SP_VS_CTRL_REG0_THREADSIZE(enum a3xx_threadsize val)
{
return ((val) << A3XX_SP_VS_CTRL_REG0_THREADSIZE__SHIFT) & A3XX_SP_VS_CTRL_REG0_THREADSIZE__MASK;
}
#define A3XX_SP_VS_CTRL_REG0_SUPERTHREADMODE 0x00200000
#define A3XX_SP_VS_CTRL_REG0_PIXLODENABLE 0x00400000
#define A3XX_SP_VS_CTRL_REG0_COMPUTEMODE 0x00800000
#define A3XX_SP_VS_CTRL_REG0_LENGTH__MASK 0xff000000
#define A3XX_SP_VS_CTRL_REG0_LENGTH__SHIFT 24
static inline uint32_t A3XX_SP_VS_CTRL_REG0_LENGTH(uint32_t val)
{
return ((val) << A3XX_SP_VS_CTRL_REG0_LENGTH__SHIFT) & A3XX_SP_VS_CTRL_REG0_LENGTH__MASK;
}
 
#define REG_A3XX_SP_VS_CTRL_REG1 0x000022c5
#define A3XX_SP_VS_CTRL_REG1_CONSTLENGTH__MASK 0x000003ff
#define A3XX_SP_VS_CTRL_REG1_CONSTLENGTH__SHIFT 0
static inline uint32_t A3XX_SP_VS_CTRL_REG1_CONSTLENGTH(uint32_t val)
{
return ((val) << A3XX_SP_VS_CTRL_REG1_CONSTLENGTH__SHIFT) & A3XX_SP_VS_CTRL_REG1_CONSTLENGTH__MASK;
}
#define A3XX_SP_VS_CTRL_REG1_CONSTFOOTPRINT__MASK 0x000ffc00
#define A3XX_SP_VS_CTRL_REG1_CONSTFOOTPRINT__SHIFT 10
static inline uint32_t A3XX_SP_VS_CTRL_REG1_CONSTFOOTPRINT(uint32_t val)
{
return ((val) << A3XX_SP_VS_CTRL_REG1_CONSTFOOTPRINT__SHIFT) & A3XX_SP_VS_CTRL_REG1_CONSTFOOTPRINT__MASK;
}
#define A3XX_SP_VS_CTRL_REG1_INITIALOUTSTANDING__MASK 0x7f000000
#define A3XX_SP_VS_CTRL_REG1_INITIALOUTSTANDING__SHIFT 24
static inline uint32_t A3XX_SP_VS_CTRL_REG1_INITIALOUTSTANDING(uint32_t val)
{
return ((val) << A3XX_SP_VS_CTRL_REG1_INITIALOUTSTANDING__SHIFT) & A3XX_SP_VS_CTRL_REG1_INITIALOUTSTANDING__MASK;
}
 
#define REG_A3XX_SP_VS_PARAM_REG 0x000022c6
#define A3XX_SP_VS_PARAM_REG_POSREGID__MASK 0x000000ff
#define A3XX_SP_VS_PARAM_REG_POSREGID__SHIFT 0
static inline uint32_t A3XX_SP_VS_PARAM_REG_POSREGID(uint32_t val)
{
return ((val) << A3XX_SP_VS_PARAM_REG_POSREGID__SHIFT) & A3XX_SP_VS_PARAM_REG_POSREGID__MASK;
}
#define A3XX_SP_VS_PARAM_REG_PSIZEREGID__MASK 0x0000ff00
#define A3XX_SP_VS_PARAM_REG_PSIZEREGID__SHIFT 8
static inline uint32_t A3XX_SP_VS_PARAM_REG_PSIZEREGID(uint32_t val)
{
return ((val) << A3XX_SP_VS_PARAM_REG_PSIZEREGID__SHIFT) & A3XX_SP_VS_PARAM_REG_PSIZEREGID__MASK;
}
#define A3XX_SP_VS_PARAM_REG_TOTALVSOUTVAR__MASK 0xfff00000
#define A3XX_SP_VS_PARAM_REG_TOTALVSOUTVAR__SHIFT 20
static inline uint32_t A3XX_SP_VS_PARAM_REG_TOTALVSOUTVAR(uint32_t val)
{
return ((val) << A3XX_SP_VS_PARAM_REG_TOTALVSOUTVAR__SHIFT) & A3XX_SP_VS_PARAM_REG_TOTALVSOUTVAR__MASK;
}
 
static inline uint32_t REG_A3XX_SP_VS_OUT(uint32_t i0) { return 0x000022c7 + 0x1*i0; }
 
static inline uint32_t REG_A3XX_SP_VS_OUT_REG(uint32_t i0) { return 0x000022c7 + 0x1*i0; }
#define A3XX_SP_VS_OUT_REG_A_REGID__MASK 0x000001ff
#define A3XX_SP_VS_OUT_REG_A_REGID__SHIFT 0
static inline uint32_t A3XX_SP_VS_OUT_REG_A_REGID(uint32_t val)
{
return ((val) << A3XX_SP_VS_OUT_REG_A_REGID__SHIFT) & A3XX_SP_VS_OUT_REG_A_REGID__MASK;
}
#define A3XX_SP_VS_OUT_REG_A_COMPMASK__MASK 0x00001e00
#define A3XX_SP_VS_OUT_REG_A_COMPMASK__SHIFT 9
static inline uint32_t A3XX_SP_VS_OUT_REG_A_COMPMASK(uint32_t val)
{
return ((val) << A3XX_SP_VS_OUT_REG_A_COMPMASK__SHIFT) & A3XX_SP_VS_OUT_REG_A_COMPMASK__MASK;
}
#define A3XX_SP_VS_OUT_REG_B_REGID__MASK 0x01ff0000
#define A3XX_SP_VS_OUT_REG_B_REGID__SHIFT 16
static inline uint32_t A3XX_SP_VS_OUT_REG_B_REGID(uint32_t val)
{
return ((val) << A3XX_SP_VS_OUT_REG_B_REGID__SHIFT) & A3XX_SP_VS_OUT_REG_B_REGID__MASK;
}
#define A3XX_SP_VS_OUT_REG_B_COMPMASK__MASK 0x1e000000
#define A3XX_SP_VS_OUT_REG_B_COMPMASK__SHIFT 25
static inline uint32_t A3XX_SP_VS_OUT_REG_B_COMPMASK(uint32_t val)
{
return ((val) << A3XX_SP_VS_OUT_REG_B_COMPMASK__SHIFT) & A3XX_SP_VS_OUT_REG_B_COMPMASK__MASK;
}
 
static inline uint32_t REG_A3XX_SP_VS_VPC_DST(uint32_t i0) { return 0x000022d0 + 0x1*i0; }
 
static inline uint32_t REG_A3XX_SP_VS_VPC_DST_REG(uint32_t i0) { return 0x000022d0 + 0x1*i0; }
#define A3XX_SP_VS_VPC_DST_REG_OUTLOC0__MASK 0x000000ff
#define A3XX_SP_VS_VPC_DST_REG_OUTLOC0__SHIFT 0
static inline uint32_t A3XX_SP_VS_VPC_DST_REG_OUTLOC0(uint32_t val)
{
return ((val) << A3XX_SP_VS_VPC_DST_REG_OUTLOC0__SHIFT) & A3XX_SP_VS_VPC_DST_REG_OUTLOC0__MASK;
}
#define A3XX_SP_VS_VPC_DST_REG_OUTLOC1__MASK 0x0000ff00
#define A3XX_SP_VS_VPC_DST_REG_OUTLOC1__SHIFT 8
static inline uint32_t A3XX_SP_VS_VPC_DST_REG_OUTLOC1(uint32_t val)
{
return ((val) << A3XX_SP_VS_VPC_DST_REG_OUTLOC1__SHIFT) & A3XX_SP_VS_VPC_DST_REG_OUTLOC1__MASK;
}
#define A3XX_SP_VS_VPC_DST_REG_OUTLOC2__MASK 0x00ff0000
#define A3XX_SP_VS_VPC_DST_REG_OUTLOC2__SHIFT 16
static inline uint32_t A3XX_SP_VS_VPC_DST_REG_OUTLOC2(uint32_t val)
{
return ((val) << A3XX_SP_VS_VPC_DST_REG_OUTLOC2__SHIFT) & A3XX_SP_VS_VPC_DST_REG_OUTLOC2__MASK;
}
#define A3XX_SP_VS_VPC_DST_REG_OUTLOC3__MASK 0xff000000
#define A3XX_SP_VS_VPC_DST_REG_OUTLOC3__SHIFT 24
static inline uint32_t A3XX_SP_VS_VPC_DST_REG_OUTLOC3(uint32_t val)
{
return ((val) << A3XX_SP_VS_VPC_DST_REG_OUTLOC3__SHIFT) & A3XX_SP_VS_VPC_DST_REG_OUTLOC3__MASK;
}
 
#define REG_A3XX_SP_VS_OBJ_OFFSET_REG 0x000022d4
#define A3XX_SP_VS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__MASK 0x01ff0000
#define A3XX_SP_VS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__SHIFT 16
static inline uint32_t A3XX_SP_VS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET(uint32_t val)
{
return ((val) << A3XX_SP_VS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__SHIFT) & A3XX_SP_VS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__MASK;
}
#define A3XX_SP_VS_OBJ_OFFSET_REG_SHADEROBJOFFSET__MASK 0xfe000000
#define A3XX_SP_VS_OBJ_OFFSET_REG_SHADEROBJOFFSET__SHIFT 25
static inline uint32_t A3XX_SP_VS_OBJ_OFFSET_REG_SHADEROBJOFFSET(uint32_t val)
{
return ((val) << A3XX_SP_VS_OBJ_OFFSET_REG_SHADEROBJOFFSET__SHIFT) & A3XX_SP_VS_OBJ_OFFSET_REG_SHADEROBJOFFSET__MASK;
}
 
#define REG_A3XX_SP_VS_OBJ_START_REG 0x000022d5
 
#define REG_A3XX_SP_VS_PVT_MEM_PARAM_REG 0x000022d6
 
#define REG_A3XX_SP_VS_PVT_MEM_ADDR_REG 0x000022d7
 
#define REG_A3XX_SP_VS_PVT_MEM_SIZE_REG 0x000022d8
 
#define REG_A3XX_SP_VS_LENGTH_REG 0x000022df
#define A3XX_SP_VS_LENGTH_REG_SHADERLENGTH__MASK 0xffffffff
#define A3XX_SP_VS_LENGTH_REG_SHADERLENGTH__SHIFT 0
static inline uint32_t A3XX_SP_VS_LENGTH_REG_SHADERLENGTH(uint32_t val)
{
return ((val) << A3XX_SP_VS_LENGTH_REG_SHADERLENGTH__SHIFT) & A3XX_SP_VS_LENGTH_REG_SHADERLENGTH__MASK;
}
 
#define REG_A3XX_SP_FS_CTRL_REG0 0x000022e0
#define A3XX_SP_FS_CTRL_REG0_THREADMODE__MASK 0x00000001
#define A3XX_SP_FS_CTRL_REG0_THREADMODE__SHIFT 0
static inline uint32_t A3XX_SP_FS_CTRL_REG0_THREADMODE(enum a3xx_threadmode val)
{
return ((val) << A3XX_SP_FS_CTRL_REG0_THREADMODE__SHIFT) & A3XX_SP_FS_CTRL_REG0_THREADMODE__MASK;
}
#define A3XX_SP_FS_CTRL_REG0_INSTRBUFFERMODE__MASK 0x00000002
#define A3XX_SP_FS_CTRL_REG0_INSTRBUFFERMODE__SHIFT 1
static inline uint32_t A3XX_SP_FS_CTRL_REG0_INSTRBUFFERMODE(enum a3xx_instrbuffermode val)
{
return ((val) << A3XX_SP_FS_CTRL_REG0_INSTRBUFFERMODE__SHIFT) & A3XX_SP_FS_CTRL_REG0_INSTRBUFFERMODE__MASK;
}
#define A3XX_SP_FS_CTRL_REG0_CACHEINVALID 0x00000004
#define A3XX_SP_FS_CTRL_REG0_HALFREGFOOTPRINT__MASK 0x000003f0
#define A3XX_SP_FS_CTRL_REG0_HALFREGFOOTPRINT__SHIFT 4
static inline uint32_t A3XX_SP_FS_CTRL_REG0_HALFREGFOOTPRINT(uint32_t val)
{
return ((val) << A3XX_SP_FS_CTRL_REG0_HALFREGFOOTPRINT__SHIFT) & A3XX_SP_FS_CTRL_REG0_HALFREGFOOTPRINT__MASK;
}
#define A3XX_SP_FS_CTRL_REG0_FULLREGFOOTPRINT__MASK 0x0003fc00
#define A3XX_SP_FS_CTRL_REG0_FULLREGFOOTPRINT__SHIFT 10
static inline uint32_t A3XX_SP_FS_CTRL_REG0_FULLREGFOOTPRINT(uint32_t val)
{
return ((val) << A3XX_SP_FS_CTRL_REG0_FULLREGFOOTPRINT__SHIFT) & A3XX_SP_FS_CTRL_REG0_FULLREGFOOTPRINT__MASK;
}
#define A3XX_SP_FS_CTRL_REG0_INOUTREGOVERLAP__MASK 0x000c0000
#define A3XX_SP_FS_CTRL_REG0_INOUTREGOVERLAP__SHIFT 18
static inline uint32_t A3XX_SP_FS_CTRL_REG0_INOUTREGOVERLAP(uint32_t val)
{
return ((val) << A3XX_SP_FS_CTRL_REG0_INOUTREGOVERLAP__SHIFT) & A3XX_SP_FS_CTRL_REG0_INOUTREGOVERLAP__MASK;
}
#define A3XX_SP_FS_CTRL_REG0_THREADSIZE__MASK 0x00100000
#define A3XX_SP_FS_CTRL_REG0_THREADSIZE__SHIFT 20
static inline uint32_t A3XX_SP_FS_CTRL_REG0_THREADSIZE(enum a3xx_threadsize val)
{
return ((val) << A3XX_SP_FS_CTRL_REG0_THREADSIZE__SHIFT) & A3XX_SP_FS_CTRL_REG0_THREADSIZE__MASK;
}
#define A3XX_SP_FS_CTRL_REG0_SUPERTHREADMODE 0x00200000
#define A3XX_SP_FS_CTRL_REG0_PIXLODENABLE 0x00400000
#define A3XX_SP_FS_CTRL_REG0_COMPUTEMODE 0x00800000
#define A3XX_SP_FS_CTRL_REG0_LENGTH__MASK 0xff000000
#define A3XX_SP_FS_CTRL_REG0_LENGTH__SHIFT 24
static inline uint32_t A3XX_SP_FS_CTRL_REG0_LENGTH(uint32_t val)
{
return ((val) << A3XX_SP_FS_CTRL_REG0_LENGTH__SHIFT) & A3XX_SP_FS_CTRL_REG0_LENGTH__MASK;
}
 
#define REG_A3XX_SP_FS_CTRL_REG1 0x000022e1
#define A3XX_SP_FS_CTRL_REG1_CONSTLENGTH__MASK 0x000003ff
#define A3XX_SP_FS_CTRL_REG1_CONSTLENGTH__SHIFT 0
static inline uint32_t A3XX_SP_FS_CTRL_REG1_CONSTLENGTH(uint32_t val)
{
return ((val) << A3XX_SP_FS_CTRL_REG1_CONSTLENGTH__SHIFT) & A3XX_SP_FS_CTRL_REG1_CONSTLENGTH__MASK;
}
#define A3XX_SP_FS_CTRL_REG1_CONSTFOOTPRINT__MASK 0x000ffc00
#define A3XX_SP_FS_CTRL_REG1_CONSTFOOTPRINT__SHIFT 10
static inline uint32_t A3XX_SP_FS_CTRL_REG1_CONSTFOOTPRINT(uint32_t val)
{
return ((val) << A3XX_SP_FS_CTRL_REG1_CONSTFOOTPRINT__SHIFT) & A3XX_SP_FS_CTRL_REG1_CONSTFOOTPRINT__MASK;
}
#define A3XX_SP_FS_CTRL_REG1_INITIALOUTSTANDING__MASK 0x00f00000
#define A3XX_SP_FS_CTRL_REG1_INITIALOUTSTANDING__SHIFT 20
static inline uint32_t A3XX_SP_FS_CTRL_REG1_INITIALOUTSTANDING(uint32_t val)
{
return ((val) << A3XX_SP_FS_CTRL_REG1_INITIALOUTSTANDING__SHIFT) & A3XX_SP_FS_CTRL_REG1_INITIALOUTSTANDING__MASK;
}
#define A3XX_SP_FS_CTRL_REG1_HALFPRECVAROFFSET__MASK 0x3f000000
#define A3XX_SP_FS_CTRL_REG1_HALFPRECVAROFFSET__SHIFT 24
static inline uint32_t A3XX_SP_FS_CTRL_REG1_HALFPRECVAROFFSET(uint32_t val)
{
return ((val) << A3XX_SP_FS_CTRL_REG1_HALFPRECVAROFFSET__SHIFT) & A3XX_SP_FS_CTRL_REG1_HALFPRECVAROFFSET__MASK;
}
 
#define REG_A3XX_SP_FS_OBJ_OFFSET_REG 0x000022e2
#define A3XX_SP_FS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__MASK 0x01ff0000
#define A3XX_SP_FS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__SHIFT 16
static inline uint32_t A3XX_SP_FS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET(uint32_t val)
{
return ((val) << A3XX_SP_FS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__SHIFT) & A3XX_SP_FS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__MASK;
}
#define A3XX_SP_FS_OBJ_OFFSET_REG_SHADEROBJOFFSET__MASK 0xfe000000
#define A3XX_SP_FS_OBJ_OFFSET_REG_SHADEROBJOFFSET__SHIFT 25
static inline uint32_t A3XX_SP_FS_OBJ_OFFSET_REG_SHADEROBJOFFSET(uint32_t val)
{
return ((val) << A3XX_SP_FS_OBJ_OFFSET_REG_SHADEROBJOFFSET__SHIFT) & A3XX_SP_FS_OBJ_OFFSET_REG_SHADEROBJOFFSET__MASK;
}
 
#define REG_A3XX_SP_FS_OBJ_START_REG 0x000022e3
 
#define REG_A3XX_SP_FS_PVT_MEM_PARAM_REG 0x000022e4
 
#define REG_A3XX_SP_FS_PVT_MEM_ADDR_REG 0x000022e5
 
#define REG_A3XX_SP_FS_PVT_MEM_SIZE_REG 0x000022e6
 
#define REG_A3XX_SP_FS_FLAT_SHAD_MODE_REG_0 0x000022e8
 
#define REG_A3XX_SP_FS_FLAT_SHAD_MODE_REG_1 0x000022e9
 
#define REG_A3XX_SP_FS_OUTPUT_REG 0x000022ec
#define A3XX_SP_FS_OUTPUT_REG_MRT__MASK 0x00000003
#define A3XX_SP_FS_OUTPUT_REG_MRT__SHIFT 0
static inline uint32_t A3XX_SP_FS_OUTPUT_REG_MRT(uint32_t val)
{
return ((val) << A3XX_SP_FS_OUTPUT_REG_MRT__SHIFT) & A3XX_SP_FS_OUTPUT_REG_MRT__MASK;
}
#define A3XX_SP_FS_OUTPUT_REG_DEPTH_ENABLE 0x00000080
#define A3XX_SP_FS_OUTPUT_REG_DEPTH_REGID__MASK 0x0000ff00
#define A3XX_SP_FS_OUTPUT_REG_DEPTH_REGID__SHIFT 8
static inline uint32_t A3XX_SP_FS_OUTPUT_REG_DEPTH_REGID(uint32_t val)
{
return ((val) << A3XX_SP_FS_OUTPUT_REG_DEPTH_REGID__SHIFT) & A3XX_SP_FS_OUTPUT_REG_DEPTH_REGID__MASK;
}
 
static inline uint32_t REG_A3XX_SP_FS_MRT(uint32_t i0) { return 0x000022f0 + 0x1*i0; }
 
static inline uint32_t REG_A3XX_SP_FS_MRT_REG(uint32_t i0) { return 0x000022f0 + 0x1*i0; }
#define A3XX_SP_FS_MRT_REG_REGID__MASK 0x000000ff
#define A3XX_SP_FS_MRT_REG_REGID__SHIFT 0
static inline uint32_t A3XX_SP_FS_MRT_REG_REGID(uint32_t val)
{
return ((val) << A3XX_SP_FS_MRT_REG_REGID__SHIFT) & A3XX_SP_FS_MRT_REG_REGID__MASK;
}
#define A3XX_SP_FS_MRT_REG_HALF_PRECISION 0x00000100
#define A3XX_SP_FS_MRT_REG_SINT 0x00000400
#define A3XX_SP_FS_MRT_REG_UINT 0x00000800
 
static inline uint32_t REG_A3XX_SP_FS_IMAGE_OUTPUT(uint32_t i0) { return 0x000022f4 + 0x1*i0; }
 
static inline uint32_t REG_A3XX_SP_FS_IMAGE_OUTPUT_REG(uint32_t i0) { return 0x000022f4 + 0x1*i0; }
#define A3XX_SP_FS_IMAGE_OUTPUT_REG_MRTFORMAT__MASK 0x0000003f
#define A3XX_SP_FS_IMAGE_OUTPUT_REG_MRTFORMAT__SHIFT 0
static inline uint32_t A3XX_SP_FS_IMAGE_OUTPUT_REG_MRTFORMAT(enum a3xx_color_fmt val)
{
return ((val) << A3XX_SP_FS_IMAGE_OUTPUT_REG_MRTFORMAT__SHIFT) & A3XX_SP_FS_IMAGE_OUTPUT_REG_MRTFORMAT__MASK;
}
 
#define REG_A3XX_SP_FS_LENGTH_REG 0x000022ff
#define A3XX_SP_FS_LENGTH_REG_SHADERLENGTH__MASK 0xffffffff
#define A3XX_SP_FS_LENGTH_REG_SHADERLENGTH__SHIFT 0
static inline uint32_t A3XX_SP_FS_LENGTH_REG_SHADERLENGTH(uint32_t val)
{
return ((val) << A3XX_SP_FS_LENGTH_REG_SHADERLENGTH__SHIFT) & A3XX_SP_FS_LENGTH_REG_SHADERLENGTH__MASK;
}
 
#define REG_A3XX_PA_SC_AA_CONFIG 0x00002301
 
#define REG_A3XX_TPL1_TP_VS_TEX_OFFSET 0x00002340
#define A3XX_TPL1_TP_VS_TEX_OFFSET_SAMPLEROFFSET__MASK 0x000000ff
#define A3XX_TPL1_TP_VS_TEX_OFFSET_SAMPLEROFFSET__SHIFT 0
static inline uint32_t A3XX_TPL1_TP_VS_TEX_OFFSET_SAMPLEROFFSET(uint32_t val)
{
return ((val) << A3XX_TPL1_TP_VS_TEX_OFFSET_SAMPLEROFFSET__SHIFT) & A3XX_TPL1_TP_VS_TEX_OFFSET_SAMPLEROFFSET__MASK;
}
#define A3XX_TPL1_TP_VS_TEX_OFFSET_MEMOBJOFFSET__MASK 0x0000ff00
#define A3XX_TPL1_TP_VS_TEX_OFFSET_MEMOBJOFFSET__SHIFT 8
static inline uint32_t A3XX_TPL1_TP_VS_TEX_OFFSET_MEMOBJOFFSET(uint32_t val)
{
return ((val) << A3XX_TPL1_TP_VS_TEX_OFFSET_MEMOBJOFFSET__SHIFT) & A3XX_TPL1_TP_VS_TEX_OFFSET_MEMOBJOFFSET__MASK;
}
#define A3XX_TPL1_TP_VS_TEX_OFFSET_BASETABLEPTR__MASK 0xffff0000
#define A3XX_TPL1_TP_VS_TEX_OFFSET_BASETABLEPTR__SHIFT 16
static inline uint32_t A3XX_TPL1_TP_VS_TEX_OFFSET_BASETABLEPTR(uint32_t val)
{
return ((val) << A3XX_TPL1_TP_VS_TEX_OFFSET_BASETABLEPTR__SHIFT) & A3XX_TPL1_TP_VS_TEX_OFFSET_BASETABLEPTR__MASK;
}
 
#define REG_A3XX_TPL1_TP_VS_BORDER_COLOR_BASE_ADDR 0x00002341
 
#define REG_A3XX_TPL1_TP_FS_TEX_OFFSET 0x00002342
#define A3XX_TPL1_TP_FS_TEX_OFFSET_SAMPLEROFFSET__MASK 0x000000ff
#define A3XX_TPL1_TP_FS_TEX_OFFSET_SAMPLEROFFSET__SHIFT 0
static inline uint32_t A3XX_TPL1_TP_FS_TEX_OFFSET_SAMPLEROFFSET(uint32_t val)
{
return ((val) << A3XX_TPL1_TP_FS_TEX_OFFSET_SAMPLEROFFSET__SHIFT) & A3XX_TPL1_TP_FS_TEX_OFFSET_SAMPLEROFFSET__MASK;
}
#define A3XX_TPL1_TP_FS_TEX_OFFSET_MEMOBJOFFSET__MASK 0x0000ff00
#define A3XX_TPL1_TP_FS_TEX_OFFSET_MEMOBJOFFSET__SHIFT 8
static inline uint32_t A3XX_TPL1_TP_FS_TEX_OFFSET_MEMOBJOFFSET(uint32_t val)
{
return ((val) << A3XX_TPL1_TP_FS_TEX_OFFSET_MEMOBJOFFSET__SHIFT) & A3XX_TPL1_TP_FS_TEX_OFFSET_MEMOBJOFFSET__MASK;
}
#define A3XX_TPL1_TP_FS_TEX_OFFSET_BASETABLEPTR__MASK 0xffff0000
#define A3XX_TPL1_TP_FS_TEX_OFFSET_BASETABLEPTR__SHIFT 16
static inline uint32_t A3XX_TPL1_TP_FS_TEX_OFFSET_BASETABLEPTR(uint32_t val)
{
return ((val) << A3XX_TPL1_TP_FS_TEX_OFFSET_BASETABLEPTR__SHIFT) & A3XX_TPL1_TP_FS_TEX_OFFSET_BASETABLEPTR__MASK;
}
 
#define REG_A3XX_TPL1_TP_FS_BORDER_COLOR_BASE_ADDR 0x00002343
 
#define REG_A3XX_VBIF_CLKON 0x00003001
 
#define REG_A3XX_VBIF_FIXED_SORT_EN 0x0000300c
 
#define REG_A3XX_VBIF_FIXED_SORT_SEL0 0x0000300d
 
#define REG_A3XX_VBIF_FIXED_SORT_SEL1 0x0000300e
 
#define REG_A3XX_VBIF_ABIT_SORT 0x0000301c
 
#define REG_A3XX_VBIF_ABIT_SORT_CONF 0x0000301d
 
#define REG_A3XX_VBIF_GATE_OFF_WRREQ_EN 0x0000302a
 
#define REG_A3XX_VBIF_IN_RD_LIM_CONF0 0x0000302c
 
#define REG_A3XX_VBIF_IN_RD_LIM_CONF1 0x0000302d
 
#define REG_A3XX_VBIF_IN_WR_LIM_CONF0 0x00003030
 
#define REG_A3XX_VBIF_IN_WR_LIM_CONF1 0x00003031
 
#define REG_A3XX_VBIF_OUT_RD_LIM_CONF0 0x00003034
 
#define REG_A3XX_VBIF_OUT_WR_LIM_CONF0 0x00003035
 
#define REG_A3XX_VBIF_DDR_OUT_MAX_BURST 0x00003036
 
#define REG_A3XX_VBIF_ARB_CTL 0x0000303c
 
#define REG_A3XX_VBIF_ROUND_ROBIN_QOS_ARB 0x00003049
 
#define REG_A3XX_VBIF_OUT_AXI_AMEMTYPE_CONF0 0x00003058
 
#define REG_A3XX_VBIF_OUT_AXI_AOOO_EN 0x0000305e
 
#define REG_A3XX_VBIF_OUT_AXI_AOOO 0x0000305f
 
#define REG_A3XX_VBIF_PERF_CNT_EN 0x00003070
#define A3XX_VBIF_PERF_CNT_EN_CNT0 0x00000001
#define A3XX_VBIF_PERF_CNT_EN_CNT1 0x00000002
#define A3XX_VBIF_PERF_CNT_EN_PWRCNT0 0x00000004
#define A3XX_VBIF_PERF_CNT_EN_PWRCNT1 0x00000008
#define A3XX_VBIF_PERF_CNT_EN_PWRCNT2 0x00000010
 
#define REG_A3XX_VBIF_PERF_CNT_CLR 0x00003071
#define A3XX_VBIF_PERF_CNT_CLR_CNT0 0x00000001
#define A3XX_VBIF_PERF_CNT_CLR_CNT1 0x00000002
#define A3XX_VBIF_PERF_CNT_CLR_PWRCNT0 0x00000004
#define A3XX_VBIF_PERF_CNT_CLR_PWRCNT1 0x00000008
#define A3XX_VBIF_PERF_CNT_CLR_PWRCNT2 0x00000010
 
#define REG_A3XX_VBIF_PERF_CNT_SEL 0x00003072
 
#define REG_A3XX_VBIF_PERF_CNT0_LO 0x00003073
 
#define REG_A3XX_VBIF_PERF_CNT0_HI 0x00003074
 
#define REG_A3XX_VBIF_PERF_CNT1_LO 0x00003075
 
#define REG_A3XX_VBIF_PERF_CNT1_HI 0x00003076
 
#define REG_A3XX_VBIF_PERF_PWR_CNT0_LO 0x00003077
 
#define REG_A3XX_VBIF_PERF_PWR_CNT0_HI 0x00003078
 
#define REG_A3XX_VBIF_PERF_PWR_CNT1_LO 0x00003079
 
#define REG_A3XX_VBIF_PERF_PWR_CNT1_HI 0x0000307a
 
#define REG_A3XX_VBIF_PERF_PWR_CNT2_LO 0x0000307b
 
#define REG_A3XX_VBIF_PERF_PWR_CNT2_HI 0x0000307c
 
#define REG_A3XX_VSC_BIN_SIZE 0x00000c01
#define A3XX_VSC_BIN_SIZE_WIDTH__MASK 0x0000001f
#define A3XX_VSC_BIN_SIZE_WIDTH__SHIFT 0
static inline uint32_t A3XX_VSC_BIN_SIZE_WIDTH(uint32_t val)
{
return ((val >> 5) << A3XX_VSC_BIN_SIZE_WIDTH__SHIFT) & A3XX_VSC_BIN_SIZE_WIDTH__MASK;
}
#define A3XX_VSC_BIN_SIZE_HEIGHT__MASK 0x000003e0
#define A3XX_VSC_BIN_SIZE_HEIGHT__SHIFT 5
static inline uint32_t A3XX_VSC_BIN_SIZE_HEIGHT(uint32_t val)
{
return ((val >> 5) << A3XX_VSC_BIN_SIZE_HEIGHT__SHIFT) & A3XX_VSC_BIN_SIZE_HEIGHT__MASK;
}
 
#define REG_A3XX_VSC_SIZE_ADDRESS 0x00000c02
 
static inline uint32_t REG_A3XX_VSC_PIPE(uint32_t i0) { return 0x00000c06 + 0x3*i0; }
 
static inline uint32_t REG_A3XX_VSC_PIPE_CONFIG(uint32_t i0) { return 0x00000c06 + 0x3*i0; }
#define A3XX_VSC_PIPE_CONFIG_X__MASK 0x000003ff
#define A3XX_VSC_PIPE_CONFIG_X__SHIFT 0
static inline uint32_t A3XX_VSC_PIPE_CONFIG_X(uint32_t val)
{
return ((val) << A3XX_VSC_PIPE_CONFIG_X__SHIFT) & A3XX_VSC_PIPE_CONFIG_X__MASK;
}
#define A3XX_VSC_PIPE_CONFIG_Y__MASK 0x000ffc00
#define A3XX_VSC_PIPE_CONFIG_Y__SHIFT 10
static inline uint32_t A3XX_VSC_PIPE_CONFIG_Y(uint32_t val)
{
return ((val) << A3XX_VSC_PIPE_CONFIG_Y__SHIFT) & A3XX_VSC_PIPE_CONFIG_Y__MASK;
}
#define A3XX_VSC_PIPE_CONFIG_W__MASK 0x00f00000
#define A3XX_VSC_PIPE_CONFIG_W__SHIFT 20
static inline uint32_t A3XX_VSC_PIPE_CONFIG_W(uint32_t val)
{
return ((val) << A3XX_VSC_PIPE_CONFIG_W__SHIFT) & A3XX_VSC_PIPE_CONFIG_W__MASK;
}
#define A3XX_VSC_PIPE_CONFIG_H__MASK 0x0f000000
#define A3XX_VSC_PIPE_CONFIG_H__SHIFT 24
static inline uint32_t A3XX_VSC_PIPE_CONFIG_H(uint32_t val)
{
return ((val) << A3XX_VSC_PIPE_CONFIG_H__SHIFT) & A3XX_VSC_PIPE_CONFIG_H__MASK;
}
 
static inline uint32_t REG_A3XX_VSC_PIPE_DATA_ADDRESS(uint32_t i0) { return 0x00000c07 + 0x3*i0; }
 
static inline uint32_t REG_A3XX_VSC_PIPE_DATA_LENGTH(uint32_t i0) { return 0x00000c08 + 0x3*i0; }
 
#define REG_A3XX_VSC_BIN_CONTROL 0x00000c3c
#define A3XX_VSC_BIN_CONTROL_BINNING_ENABLE 0x00000001
 
#define REG_A3XX_UNKNOWN_0C3D 0x00000c3d
 
#define REG_A3XX_PC_PERFCOUNTER0_SELECT 0x00000c48
 
#define REG_A3XX_PC_PERFCOUNTER1_SELECT 0x00000c49
 
#define REG_A3XX_PC_PERFCOUNTER2_SELECT 0x00000c4a
 
#define REG_A3XX_PC_PERFCOUNTER3_SELECT 0x00000c4b
 
#define REG_A3XX_GRAS_TSE_DEBUG_ECO 0x00000c81
 
#define REG_A3XX_GRAS_PERFCOUNTER0_SELECT 0x00000c88
 
#define REG_A3XX_GRAS_PERFCOUNTER1_SELECT 0x00000c89
 
#define REG_A3XX_GRAS_PERFCOUNTER2_SELECT 0x00000c8a
 
#define REG_A3XX_GRAS_PERFCOUNTER3_SELECT 0x00000c8b
 
static inline uint32_t REG_A3XX_GRAS_CL_USER_PLANE(uint32_t i0) { return 0x00000ca0 + 0x4*i0; }
 
static inline uint32_t REG_A3XX_GRAS_CL_USER_PLANE_X(uint32_t i0) { return 0x00000ca0 + 0x4*i0; }
 
static inline uint32_t REG_A3XX_GRAS_CL_USER_PLANE_Y(uint32_t i0) { return 0x00000ca1 + 0x4*i0; }
 
static inline uint32_t REG_A3XX_GRAS_CL_USER_PLANE_Z(uint32_t i0) { return 0x00000ca2 + 0x4*i0; }
 
static inline uint32_t REG_A3XX_GRAS_CL_USER_PLANE_W(uint32_t i0) { return 0x00000ca3 + 0x4*i0; }
 
#define REG_A3XX_RB_GMEM_BASE_ADDR 0x00000cc0
 
#define REG_A3XX_RB_DEBUG_ECO_CONTROLS_ADDR 0x00000cc1
 
#define REG_A3XX_RB_PERFCOUNTER0_SELECT 0x00000cc6
 
#define REG_A3XX_RB_PERFCOUNTER1_SELECT 0x00000cc7
 
#define REG_A3XX_RB_FRAME_BUFFER_DIMENSION 0x00000ce0
#define A3XX_RB_FRAME_BUFFER_DIMENSION_WIDTH__MASK 0x00003fff
#define A3XX_RB_FRAME_BUFFER_DIMENSION_WIDTH__SHIFT 0
static inline uint32_t A3XX_RB_FRAME_BUFFER_DIMENSION_WIDTH(uint32_t val)
{
return ((val) << A3XX_RB_FRAME_BUFFER_DIMENSION_WIDTH__SHIFT) & A3XX_RB_FRAME_BUFFER_DIMENSION_WIDTH__MASK;
}
#define A3XX_RB_FRAME_BUFFER_DIMENSION_HEIGHT__MASK 0x0fffc000
#define A3XX_RB_FRAME_BUFFER_DIMENSION_HEIGHT__SHIFT 14
static inline uint32_t A3XX_RB_FRAME_BUFFER_DIMENSION_HEIGHT(uint32_t val)
{
return ((val) << A3XX_RB_FRAME_BUFFER_DIMENSION_HEIGHT__SHIFT) & A3XX_RB_FRAME_BUFFER_DIMENSION_HEIGHT__MASK;
}
 
#define REG_A3XX_HLSQ_PERFCOUNTER0_SELECT 0x00000e00
 
#define REG_A3XX_HLSQ_PERFCOUNTER1_SELECT 0x00000e01
 
#define REG_A3XX_HLSQ_PERFCOUNTER2_SELECT 0x00000e02
 
#define REG_A3XX_HLSQ_PERFCOUNTER3_SELECT 0x00000e03
 
#define REG_A3XX_HLSQ_PERFCOUNTER4_SELECT 0x00000e04
 
#define REG_A3XX_HLSQ_PERFCOUNTER5_SELECT 0x00000e05
 
#define REG_A3XX_UNKNOWN_0E43 0x00000e43
 
#define REG_A3XX_VFD_PERFCOUNTER0_SELECT 0x00000e44
 
#define REG_A3XX_VFD_PERFCOUNTER1_SELECT 0x00000e45
 
#define REG_A3XX_VPC_VPC_DEBUG_RAM_SEL 0x00000e61
 
#define REG_A3XX_VPC_VPC_DEBUG_RAM_READ 0x00000e62
 
#define REG_A3XX_VPC_PERFCOUNTER0_SELECT 0x00000e64
 
#define REG_A3XX_VPC_PERFCOUNTER1_SELECT 0x00000e65
 
#define REG_A3XX_UCHE_CACHE_MODE_CONTROL_REG 0x00000e82
 
#define REG_A3XX_UCHE_PERFCOUNTER0_SELECT 0x00000e84
 
#define REG_A3XX_UCHE_PERFCOUNTER1_SELECT 0x00000e85
 
#define REG_A3XX_UCHE_PERFCOUNTER2_SELECT 0x00000e86
 
#define REG_A3XX_UCHE_PERFCOUNTER3_SELECT 0x00000e87
 
#define REG_A3XX_UCHE_PERFCOUNTER4_SELECT 0x00000e88
 
#define REG_A3XX_UCHE_PERFCOUNTER5_SELECT 0x00000e89
 
#define REG_A3XX_UCHE_CACHE_INVALIDATE0_REG 0x00000ea0
#define A3XX_UCHE_CACHE_INVALIDATE0_REG_ADDR__MASK 0x0fffffff
#define A3XX_UCHE_CACHE_INVALIDATE0_REG_ADDR__SHIFT 0
static inline uint32_t A3XX_UCHE_CACHE_INVALIDATE0_REG_ADDR(uint32_t val)
{
return ((val) << A3XX_UCHE_CACHE_INVALIDATE0_REG_ADDR__SHIFT) & A3XX_UCHE_CACHE_INVALIDATE0_REG_ADDR__MASK;
}
 
#define REG_A3XX_UCHE_CACHE_INVALIDATE1_REG 0x00000ea1
#define A3XX_UCHE_CACHE_INVALIDATE1_REG_ADDR__MASK 0x0fffffff
#define A3XX_UCHE_CACHE_INVALIDATE1_REG_ADDR__SHIFT 0
static inline uint32_t A3XX_UCHE_CACHE_INVALIDATE1_REG_ADDR(uint32_t val)
{
return ((val) << A3XX_UCHE_CACHE_INVALIDATE1_REG_ADDR__SHIFT) & A3XX_UCHE_CACHE_INVALIDATE1_REG_ADDR__MASK;
}
#define A3XX_UCHE_CACHE_INVALIDATE1_REG_OPCODE__MASK 0x30000000
#define A3XX_UCHE_CACHE_INVALIDATE1_REG_OPCODE__SHIFT 28
static inline uint32_t A3XX_UCHE_CACHE_INVALIDATE1_REG_OPCODE(enum a3xx_cache_opcode val)
{
return ((val) << A3XX_UCHE_CACHE_INVALIDATE1_REG_OPCODE__SHIFT) & A3XX_UCHE_CACHE_INVALIDATE1_REG_OPCODE__MASK;
}
#define A3XX_UCHE_CACHE_INVALIDATE1_REG_ENTIRE_CACHE 0x80000000
 
#define REG_A3XX_UNKNOWN_0EA6 0x00000ea6
 
#define REG_A3XX_SP_PERFCOUNTER0_SELECT 0x00000ec4
 
#define REG_A3XX_SP_PERFCOUNTER1_SELECT 0x00000ec5
 
#define REG_A3XX_SP_PERFCOUNTER2_SELECT 0x00000ec6
 
#define REG_A3XX_SP_PERFCOUNTER3_SELECT 0x00000ec7
 
#define REG_A3XX_SP_PERFCOUNTER4_SELECT 0x00000ec8
 
#define REG_A3XX_SP_PERFCOUNTER5_SELECT 0x00000ec9
 
#define REG_A3XX_SP_PERFCOUNTER6_SELECT 0x00000eca
 
#define REG_A3XX_SP_PERFCOUNTER7_SELECT 0x00000ecb
 
#define REG_A3XX_UNKNOWN_0EE0 0x00000ee0
 
#define REG_A3XX_UNKNOWN_0F03 0x00000f03
 
#define REG_A3XX_TP_PERFCOUNTER0_SELECT 0x00000f04
 
#define REG_A3XX_TP_PERFCOUNTER1_SELECT 0x00000f05
 
#define REG_A3XX_TP_PERFCOUNTER2_SELECT 0x00000f06
 
#define REG_A3XX_TP_PERFCOUNTER3_SELECT 0x00000f07
 
#define REG_A3XX_TP_PERFCOUNTER4_SELECT 0x00000f08
 
#define REG_A3XX_TP_PERFCOUNTER5_SELECT 0x00000f09
 
#define REG_A3XX_VGT_CL_INITIATOR 0x000021f0
 
#define REG_A3XX_VGT_EVENT_INITIATOR 0x000021f9
 
#define REG_A3XX_VGT_DRAW_INITIATOR 0x000021fc
#define A3XX_VGT_DRAW_INITIATOR_PRIM_TYPE__MASK 0x0000003f
#define A3XX_VGT_DRAW_INITIATOR_PRIM_TYPE__SHIFT 0
static inline uint32_t A3XX_VGT_DRAW_INITIATOR_PRIM_TYPE(enum pc_di_primtype val)
{
return ((val) << A3XX_VGT_DRAW_INITIATOR_PRIM_TYPE__SHIFT) & A3XX_VGT_DRAW_INITIATOR_PRIM_TYPE__MASK;
}
#define A3XX_VGT_DRAW_INITIATOR_SOURCE_SELECT__MASK 0x000000c0
#define A3XX_VGT_DRAW_INITIATOR_SOURCE_SELECT__SHIFT 6
static inline uint32_t A3XX_VGT_DRAW_INITIATOR_SOURCE_SELECT(enum pc_di_src_sel val)
{
return ((val) << A3XX_VGT_DRAW_INITIATOR_SOURCE_SELECT__SHIFT) & A3XX_VGT_DRAW_INITIATOR_SOURCE_SELECT__MASK;
}
#define A3XX_VGT_DRAW_INITIATOR_VIS_CULL__MASK 0x00000600
#define A3XX_VGT_DRAW_INITIATOR_VIS_CULL__SHIFT 9
static inline uint32_t A3XX_VGT_DRAW_INITIATOR_VIS_CULL(enum pc_di_vis_cull_mode val)
{
return ((val) << A3XX_VGT_DRAW_INITIATOR_VIS_CULL__SHIFT) & A3XX_VGT_DRAW_INITIATOR_VIS_CULL__MASK;
}
#define A3XX_VGT_DRAW_INITIATOR_INDEX_SIZE__MASK 0x00000800
#define A3XX_VGT_DRAW_INITIATOR_INDEX_SIZE__SHIFT 11
static inline uint32_t A3XX_VGT_DRAW_INITIATOR_INDEX_SIZE(enum pc_di_index_size val)
{
return ((val) << A3XX_VGT_DRAW_INITIATOR_INDEX_SIZE__SHIFT) & A3XX_VGT_DRAW_INITIATOR_INDEX_SIZE__MASK;
}
#define A3XX_VGT_DRAW_INITIATOR_NOT_EOP 0x00001000
#define A3XX_VGT_DRAW_INITIATOR_SMALL_INDEX 0x00002000
#define A3XX_VGT_DRAW_INITIATOR_PRE_DRAW_INITIATOR_ENABLE 0x00004000
#define A3XX_VGT_DRAW_INITIATOR_NUM_INSTANCES__MASK 0xff000000
#define A3XX_VGT_DRAW_INITIATOR_NUM_INSTANCES__SHIFT 24
static inline uint32_t A3XX_VGT_DRAW_INITIATOR_NUM_INSTANCES(uint32_t val)
{
return ((val) << A3XX_VGT_DRAW_INITIATOR_NUM_INSTANCES__SHIFT) & A3XX_VGT_DRAW_INITIATOR_NUM_INSTANCES__MASK;
}
 
#define REG_A3XX_VGT_IMMED_DATA 0x000021fd
 
#define REG_A3XX_TEX_SAMP_0 0x00000000
#define A3XX_TEX_SAMP_0_MIPFILTER_LINEAR 0x00000002
#define A3XX_TEX_SAMP_0_XY_MAG__MASK 0x0000000c
#define A3XX_TEX_SAMP_0_XY_MAG__SHIFT 2
static inline uint32_t A3XX_TEX_SAMP_0_XY_MAG(enum a3xx_tex_filter val)
{
return ((val) << A3XX_TEX_SAMP_0_XY_MAG__SHIFT) & A3XX_TEX_SAMP_0_XY_MAG__MASK;
}
#define A3XX_TEX_SAMP_0_XY_MIN__MASK 0x00000030
#define A3XX_TEX_SAMP_0_XY_MIN__SHIFT 4
static inline uint32_t A3XX_TEX_SAMP_0_XY_MIN(enum a3xx_tex_filter val)
{
return ((val) << A3XX_TEX_SAMP_0_XY_MIN__SHIFT) & A3XX_TEX_SAMP_0_XY_MIN__MASK;
}
#define A3XX_TEX_SAMP_0_WRAP_S__MASK 0x000001c0
#define A3XX_TEX_SAMP_0_WRAP_S__SHIFT 6
static inline uint32_t A3XX_TEX_SAMP_0_WRAP_S(enum a3xx_tex_clamp val)
{
return ((val) << A3XX_TEX_SAMP_0_WRAP_S__SHIFT) & A3XX_TEX_SAMP_0_WRAP_S__MASK;
}
#define A3XX_TEX_SAMP_0_WRAP_T__MASK 0x00000e00
#define A3XX_TEX_SAMP_0_WRAP_T__SHIFT 9
static inline uint32_t A3XX_TEX_SAMP_0_WRAP_T(enum a3xx_tex_clamp val)
{
return ((val) << A3XX_TEX_SAMP_0_WRAP_T__SHIFT) & A3XX_TEX_SAMP_0_WRAP_T__MASK;
}
#define A3XX_TEX_SAMP_0_WRAP_R__MASK 0x00007000
#define A3XX_TEX_SAMP_0_WRAP_R__SHIFT 12
static inline uint32_t A3XX_TEX_SAMP_0_WRAP_R(enum a3xx_tex_clamp val)
{
return ((val) << A3XX_TEX_SAMP_0_WRAP_R__SHIFT) & A3XX_TEX_SAMP_0_WRAP_R__MASK;
}
#define A3XX_TEX_SAMP_0_ANISO__MASK 0x00038000
#define A3XX_TEX_SAMP_0_ANISO__SHIFT 15
static inline uint32_t A3XX_TEX_SAMP_0_ANISO(enum a3xx_tex_aniso val)
{
return ((val) << A3XX_TEX_SAMP_0_ANISO__SHIFT) & A3XX_TEX_SAMP_0_ANISO__MASK;
}
#define A3XX_TEX_SAMP_0_COMPARE_FUNC__MASK 0x00700000
#define A3XX_TEX_SAMP_0_COMPARE_FUNC__SHIFT 20
static inline uint32_t A3XX_TEX_SAMP_0_COMPARE_FUNC(enum adreno_compare_func val)
{
return ((val) << A3XX_TEX_SAMP_0_COMPARE_FUNC__SHIFT) & A3XX_TEX_SAMP_0_COMPARE_FUNC__MASK;
}
#define A3XX_TEX_SAMP_0_UNNORM_COORDS 0x80000000
 
#define REG_A3XX_TEX_SAMP_1 0x00000001
#define A3XX_TEX_SAMP_1_LOD_BIAS__MASK 0x000007ff
#define A3XX_TEX_SAMP_1_LOD_BIAS__SHIFT 0
static inline uint32_t A3XX_TEX_SAMP_1_LOD_BIAS(float val)
{
return ((((int32_t)(val * 64.0))) << A3XX_TEX_SAMP_1_LOD_BIAS__SHIFT) & A3XX_TEX_SAMP_1_LOD_BIAS__MASK;
}
#define A3XX_TEX_SAMP_1_MAX_LOD__MASK 0x003ff000
#define A3XX_TEX_SAMP_1_MAX_LOD__SHIFT 12
static inline uint32_t A3XX_TEX_SAMP_1_MAX_LOD(float val)
{
return ((((uint32_t)(val * 64.0))) << A3XX_TEX_SAMP_1_MAX_LOD__SHIFT) & A3XX_TEX_SAMP_1_MAX_LOD__MASK;
}
#define A3XX_TEX_SAMP_1_MIN_LOD__MASK 0xffc00000
#define A3XX_TEX_SAMP_1_MIN_LOD__SHIFT 22
static inline uint32_t A3XX_TEX_SAMP_1_MIN_LOD(float val)
{
return ((((uint32_t)(val * 64.0))) << A3XX_TEX_SAMP_1_MIN_LOD__SHIFT) & A3XX_TEX_SAMP_1_MIN_LOD__MASK;
}
 
#define REG_A3XX_TEX_CONST_0 0x00000000
#define A3XX_TEX_CONST_0_TILED 0x00000001
#define A3XX_TEX_CONST_0_SRGB 0x00000004
#define A3XX_TEX_CONST_0_SWIZ_X__MASK 0x00000070
#define A3XX_TEX_CONST_0_SWIZ_X__SHIFT 4
static inline uint32_t A3XX_TEX_CONST_0_SWIZ_X(enum a3xx_tex_swiz val)
{
return ((val) << A3XX_TEX_CONST_0_SWIZ_X__SHIFT) & A3XX_TEX_CONST_0_SWIZ_X__MASK;
}
#define A3XX_TEX_CONST_0_SWIZ_Y__MASK 0x00000380
#define A3XX_TEX_CONST_0_SWIZ_Y__SHIFT 7
static inline uint32_t A3XX_TEX_CONST_0_SWIZ_Y(enum a3xx_tex_swiz val)
{
return ((val) << A3XX_TEX_CONST_0_SWIZ_Y__SHIFT) & A3XX_TEX_CONST_0_SWIZ_Y__MASK;
}
#define A3XX_TEX_CONST_0_SWIZ_Z__MASK 0x00001c00
#define A3XX_TEX_CONST_0_SWIZ_Z__SHIFT 10
static inline uint32_t A3XX_TEX_CONST_0_SWIZ_Z(enum a3xx_tex_swiz val)
{
return ((val) << A3XX_TEX_CONST_0_SWIZ_Z__SHIFT) & A3XX_TEX_CONST_0_SWIZ_Z__MASK;
}
#define A3XX_TEX_CONST_0_SWIZ_W__MASK 0x0000e000
#define A3XX_TEX_CONST_0_SWIZ_W__SHIFT 13
static inline uint32_t A3XX_TEX_CONST_0_SWIZ_W(enum a3xx_tex_swiz val)
{
return ((val) << A3XX_TEX_CONST_0_SWIZ_W__SHIFT) & A3XX_TEX_CONST_0_SWIZ_W__MASK;
}
#define A3XX_TEX_CONST_0_MIPLVLS__MASK 0x000f0000
#define A3XX_TEX_CONST_0_MIPLVLS__SHIFT 16
static inline uint32_t A3XX_TEX_CONST_0_MIPLVLS(uint32_t val)
{
return ((val) << A3XX_TEX_CONST_0_MIPLVLS__SHIFT) & A3XX_TEX_CONST_0_MIPLVLS__MASK;
}
#define A3XX_TEX_CONST_0_FMT__MASK 0x1fc00000
#define A3XX_TEX_CONST_0_FMT__SHIFT 22
static inline uint32_t A3XX_TEX_CONST_0_FMT(enum a3xx_tex_fmt val)
{
return ((val) << A3XX_TEX_CONST_0_FMT__SHIFT) & A3XX_TEX_CONST_0_FMT__MASK;
}
#define A3XX_TEX_CONST_0_NOCONVERT 0x20000000
#define A3XX_TEX_CONST_0_TYPE__MASK 0xc0000000
#define A3XX_TEX_CONST_0_TYPE__SHIFT 30
static inline uint32_t A3XX_TEX_CONST_0_TYPE(enum a3xx_tex_type val)
{
return ((val) << A3XX_TEX_CONST_0_TYPE__SHIFT) & A3XX_TEX_CONST_0_TYPE__MASK;
}
 
#define REG_A3XX_TEX_CONST_1 0x00000001
#define A3XX_TEX_CONST_1_HEIGHT__MASK 0x00003fff
#define A3XX_TEX_CONST_1_HEIGHT__SHIFT 0
static inline uint32_t A3XX_TEX_CONST_1_HEIGHT(uint32_t val)
{
return ((val) << A3XX_TEX_CONST_1_HEIGHT__SHIFT) & A3XX_TEX_CONST_1_HEIGHT__MASK;
}
#define A3XX_TEX_CONST_1_WIDTH__MASK 0x0fffc000
#define A3XX_TEX_CONST_1_WIDTH__SHIFT 14
static inline uint32_t A3XX_TEX_CONST_1_WIDTH(uint32_t val)
{
return ((val) << A3XX_TEX_CONST_1_WIDTH__SHIFT) & A3XX_TEX_CONST_1_WIDTH__MASK;
}
#define A3XX_TEX_CONST_1_FETCHSIZE__MASK 0xf0000000
#define A3XX_TEX_CONST_1_FETCHSIZE__SHIFT 28
static inline uint32_t A3XX_TEX_CONST_1_FETCHSIZE(enum a3xx_tex_fetchsize val)
{
return ((val) << A3XX_TEX_CONST_1_FETCHSIZE__SHIFT) & A3XX_TEX_CONST_1_FETCHSIZE__MASK;
}
 
#define REG_A3XX_TEX_CONST_2 0x00000002
#define A3XX_TEX_CONST_2_INDX__MASK 0x000000ff
#define A3XX_TEX_CONST_2_INDX__SHIFT 0
static inline uint32_t A3XX_TEX_CONST_2_INDX(uint32_t val)
{
return ((val) << A3XX_TEX_CONST_2_INDX__SHIFT) & A3XX_TEX_CONST_2_INDX__MASK;
}
#define A3XX_TEX_CONST_2_PITCH__MASK 0x3ffff000
#define A3XX_TEX_CONST_2_PITCH__SHIFT 12
static inline uint32_t A3XX_TEX_CONST_2_PITCH(uint32_t val)
{
return ((val) << A3XX_TEX_CONST_2_PITCH__SHIFT) & A3XX_TEX_CONST_2_PITCH__MASK;
}
#define A3XX_TEX_CONST_2_SWAP__MASK 0xc0000000
#define A3XX_TEX_CONST_2_SWAP__SHIFT 30
static inline uint32_t A3XX_TEX_CONST_2_SWAP(enum a3xx_color_swap val)
{
return ((val) << A3XX_TEX_CONST_2_SWAP__SHIFT) & A3XX_TEX_CONST_2_SWAP__MASK;
}
 
#define REG_A3XX_TEX_CONST_3 0x00000003
#define A3XX_TEX_CONST_3_LAYERSZ1__MASK 0x00007fff
#define A3XX_TEX_CONST_3_LAYERSZ1__SHIFT 0
static inline uint32_t A3XX_TEX_CONST_3_LAYERSZ1(uint32_t val)
{
return ((val >> 12) << A3XX_TEX_CONST_3_LAYERSZ1__SHIFT) & A3XX_TEX_CONST_3_LAYERSZ1__MASK;
}
#define A3XX_TEX_CONST_3_DEPTH__MASK 0x0ffe0000
#define A3XX_TEX_CONST_3_DEPTH__SHIFT 17
static inline uint32_t A3XX_TEX_CONST_3_DEPTH(uint32_t val)
{
return ((val) << A3XX_TEX_CONST_3_DEPTH__SHIFT) & A3XX_TEX_CONST_3_DEPTH__MASK;
}
#define A3XX_TEX_CONST_3_LAYERSZ2__MASK 0xf0000000
#define A3XX_TEX_CONST_3_LAYERSZ2__SHIFT 28
static inline uint32_t A3XX_TEX_CONST_3_LAYERSZ2(uint32_t val)
{
return ((val >> 12) << A3XX_TEX_CONST_3_LAYERSZ2__SHIFT) & A3XX_TEX_CONST_3_LAYERSZ2__MASK;
}
 
 
#endif /* A3XX_XML */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a3xx/fd3_blend.c
0,0 → 1,135
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "pipe/p_state.h"
#include "util/u_blend.h"
#include "util/u_string.h"
#include "util/u_memory.h"
 
#include "fd3_blend.h"
#include "fd3_context.h"
#include "fd3_format.h"
 
 
static enum a3xx_rb_blend_opcode
blend_func(unsigned func)
{
switch (func) {
case PIPE_BLEND_ADD:
return BLEND_DST_PLUS_SRC;
case PIPE_BLEND_MIN:
return BLEND_MIN_DST_SRC;
case PIPE_BLEND_MAX:
return BLEND_MAX_DST_SRC;
case PIPE_BLEND_SUBTRACT:
return BLEND_SRC_MINUS_DST;
case PIPE_BLEND_REVERSE_SUBTRACT:
return BLEND_DST_MINUS_SRC;
default:
DBG("invalid blend func: %x", func);
return 0;
}
}
 
void *
fd3_blend_state_create(struct pipe_context *pctx,
const struct pipe_blend_state *cso)
{
struct fd3_blend_stateobj *so;
enum a3xx_rop_code rop = ROP_COPY;
bool reads_dest = false;
int i;
 
if (cso->logicop_enable) {
rop = cso->logicop_func; /* maps 1:1 */
 
switch (cso->logicop_func) {
case PIPE_LOGICOP_NOR:
case PIPE_LOGICOP_AND_INVERTED:
case PIPE_LOGICOP_AND_REVERSE:
case PIPE_LOGICOP_INVERT:
case PIPE_LOGICOP_XOR:
case PIPE_LOGICOP_NAND:
case PIPE_LOGICOP_AND:
case PIPE_LOGICOP_EQUIV:
case PIPE_LOGICOP_NOOP:
case PIPE_LOGICOP_OR_INVERTED:
case PIPE_LOGICOP_OR_REVERSE:
case PIPE_LOGICOP_OR:
reads_dest = true;
break;
}
}
 
so = CALLOC_STRUCT(fd3_blend_stateobj);
if (!so)
return NULL;
 
so->base = *cso;
 
for (i = 0; i < ARRAY_SIZE(so->rb_mrt); i++) {
const struct pipe_rt_blend_state *rt;
if (cso->independent_blend_enable)
rt = &cso->rt[i];
else
rt = &cso->rt[0];
 
so->rb_mrt[i].blend_control_rgb =
A3XX_RB_MRT_BLEND_CONTROL_RGB_SRC_FACTOR(fd_blend_factor(rt->rgb_src_factor)) |
A3XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE(blend_func(rt->rgb_func)) |
A3XX_RB_MRT_BLEND_CONTROL_RGB_DEST_FACTOR(fd_blend_factor(rt->rgb_dst_factor));
 
so->rb_mrt[i].blend_control_alpha =
A3XX_RB_MRT_BLEND_CONTROL_ALPHA_SRC_FACTOR(fd_blend_factor(rt->alpha_src_factor)) |
A3XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE(blend_func(rt->alpha_func)) |
A3XX_RB_MRT_BLEND_CONTROL_ALPHA_DEST_FACTOR(fd_blend_factor(rt->alpha_dst_factor));
 
so->rb_mrt[i].blend_control_no_alpha_rgb =
A3XX_RB_MRT_BLEND_CONTROL_RGB_SRC_FACTOR(fd_blend_factor(util_blend_dst_alpha_to_one(rt->rgb_src_factor))) |
A3XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE(blend_func(rt->rgb_func)) |
A3XX_RB_MRT_BLEND_CONTROL_RGB_DEST_FACTOR(fd_blend_factor(util_blend_dst_alpha_to_one(rt->rgb_dst_factor)));
 
so->rb_mrt[i].control =
A3XX_RB_MRT_CONTROL_ROP_CODE(rop) |
A3XX_RB_MRT_CONTROL_COMPONENT_ENABLE(rt->colormask);
 
if (rt->blend_enable)
so->rb_mrt[i].control |=
A3XX_RB_MRT_CONTROL_READ_DEST_ENABLE |
A3XX_RB_MRT_CONTROL_BLEND |
A3XX_RB_MRT_CONTROL_BLEND2;
 
if (reads_dest)
so->rb_mrt[i].control |= A3XX_RB_MRT_CONTROL_READ_DEST_ENABLE;
 
if (cso->dither)
so->rb_mrt[i].control |= A3XX_RB_MRT_CONTROL_DITHER_MODE(DITHER_ALWAYS);
}
 
return so;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a3xx/fd3_blend.h
0,0 → 1,57
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FD3_BLEND_H_
#define FD3_BLEND_H_
 
#include "pipe/p_state.h"
#include "pipe/p_context.h"
 
struct fd3_blend_stateobj {
struct pipe_blend_state base;
struct {
/* Blend control bits for color if there is an alpha channel */
uint32_t blend_control_rgb;
/* Blend control bits for color if there is no alpha channel */
uint32_t blend_control_no_alpha_rgb;
/* Blend control bits for alpha channel */
uint32_t blend_control_alpha;
uint32_t control;
} rb_mrt[4];
};
 
static INLINE struct fd3_blend_stateobj *
fd3_blend_stateobj(struct pipe_blend_state *blend)
{
return (struct fd3_blend_stateobj *)blend;
}
 
void * fd3_blend_state_create(struct pipe_context *pctx,
const struct pipe_blend_state *cso);
 
#endif /* FD3_BLEND_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a3xx/fd3_context.c
0,0 → 1,177
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
 
#include "fd3_context.h"
#include "fd3_blend.h"
#include "fd3_draw.h"
#include "fd3_emit.h"
#include "fd3_gmem.h"
#include "fd3_program.h"
#include "fd3_query.h"
#include "fd3_rasterizer.h"
#include "fd3_texture.h"
#include "fd3_zsa.h"
 
static void
fd3_context_destroy(struct pipe_context *pctx)
{
struct fd3_context *fd3_ctx = fd3_context(fd_context(pctx));
 
util_dynarray_fini(&fd3_ctx->rbrc_patches);
 
fd_bo_del(fd3_ctx->vs_pvt_mem);
fd_bo_del(fd3_ctx->fs_pvt_mem);
fd_bo_del(fd3_ctx->vsc_size_mem);
 
pctx->delete_vertex_elements_state(pctx, fd3_ctx->solid_vbuf_state.vtx);
pctx->delete_vertex_elements_state(pctx, fd3_ctx->blit_vbuf_state.vtx);
 
pipe_resource_reference(&fd3_ctx->solid_vbuf, NULL);
pipe_resource_reference(&fd3_ctx->blit_texcoord_vbuf, NULL);
 
u_upload_destroy(fd3_ctx->border_color_uploader);
 
fd_context_destroy(pctx);
}
 
/* TODO we could combine a few of these small buffers (solid_vbuf,
* blit_texcoord_vbuf, and vsc_size_mem, into a single buffer and
* save a tiny bit of memory
*/
 
static struct pipe_resource *
create_solid_vertexbuf(struct pipe_context *pctx)
{
static const float init_shader_const[] = {
-1.000000, +1.000000, +1.000000,
+1.000000, -1.000000, +1.000000,
};
struct pipe_resource *prsc = pipe_buffer_create(pctx->screen,
PIPE_BIND_CUSTOM, PIPE_USAGE_IMMUTABLE, sizeof(init_shader_const));
pipe_buffer_write(pctx, prsc, 0,
sizeof(init_shader_const), init_shader_const);
return prsc;
}
 
static struct pipe_resource *
create_blit_texcoord_vertexbuf(struct pipe_context *pctx)
{
struct pipe_resource *prsc = pipe_buffer_create(pctx->screen,
PIPE_BIND_CUSTOM, PIPE_USAGE_DYNAMIC, 16);
return prsc;
}
 
static const uint8_t primtypes[PIPE_PRIM_MAX] = {
[PIPE_PRIM_POINTS] = DI_PT_POINTLIST_A3XX,
[PIPE_PRIM_LINES] = DI_PT_LINELIST,
[PIPE_PRIM_LINE_STRIP] = DI_PT_LINESTRIP,
[PIPE_PRIM_LINE_LOOP] = DI_PT_LINELOOP,
[PIPE_PRIM_TRIANGLES] = DI_PT_TRILIST,
[PIPE_PRIM_TRIANGLE_STRIP] = DI_PT_TRISTRIP,
[PIPE_PRIM_TRIANGLE_FAN] = DI_PT_TRIFAN,
};
 
struct pipe_context *
fd3_context_create(struct pipe_screen *pscreen, void *priv)
{
struct fd_screen *screen = fd_screen(pscreen);
struct fd3_context *fd3_ctx = CALLOC_STRUCT(fd3_context);
struct pipe_context *pctx;
 
if (!fd3_ctx)
return NULL;
 
pctx = &fd3_ctx->base.base;
 
fd3_ctx->base.dev = fd_device_ref(screen->dev);
fd3_ctx->base.screen = fd_screen(pscreen);
 
pctx->destroy = fd3_context_destroy;
pctx->create_blend_state = fd3_blend_state_create;
pctx->create_rasterizer_state = fd3_rasterizer_state_create;
pctx->create_depth_stencil_alpha_state = fd3_zsa_state_create;
 
fd3_draw_init(pctx);
fd3_gmem_init(pctx);
fd3_texture_init(pctx);
fd3_prog_init(pctx);
 
pctx = fd_context_init(&fd3_ctx->base, pscreen, primtypes, priv);
if (!pctx)
return NULL;
 
util_dynarray_init(&fd3_ctx->rbrc_patches);
 
fd3_ctx->vs_pvt_mem = fd_bo_new(screen->dev, 0x2000,
DRM_FREEDRENO_GEM_TYPE_KMEM);
 
fd3_ctx->fs_pvt_mem = fd_bo_new(screen->dev, 0x2000,
DRM_FREEDRENO_GEM_TYPE_KMEM);
 
fd3_ctx->vsc_size_mem = fd_bo_new(screen->dev, 0x1000,
DRM_FREEDRENO_GEM_TYPE_KMEM);
 
fd3_ctx->solid_vbuf = create_solid_vertexbuf(pctx);
fd3_ctx->blit_texcoord_vbuf = create_blit_texcoord_vertexbuf(pctx);
 
/* setup solid_vbuf_state: */
fd3_ctx->solid_vbuf_state.vtx = pctx->create_vertex_elements_state(
pctx, 1, (struct pipe_vertex_element[]){{
.vertex_buffer_index = 0,
.src_offset = 0,
.src_format = PIPE_FORMAT_R32G32B32_FLOAT,
}});
fd3_ctx->solid_vbuf_state.vertexbuf.count = 1;
fd3_ctx->solid_vbuf_state.vertexbuf.vb[0].stride = 12;
fd3_ctx->solid_vbuf_state.vertexbuf.vb[0].buffer = fd3_ctx->solid_vbuf;
 
/* setup blit_vbuf_state: */
fd3_ctx->blit_vbuf_state.vtx = pctx->create_vertex_elements_state(
pctx, 2, (struct pipe_vertex_element[]){{
.vertex_buffer_index = 0,
.src_offset = 0,
.src_format = PIPE_FORMAT_R32G32_FLOAT,
}, {
.vertex_buffer_index = 1,
.src_offset = 0,
.src_format = PIPE_FORMAT_R32G32B32_FLOAT,
}});
fd3_ctx->blit_vbuf_state.vertexbuf.count = 2;
fd3_ctx->blit_vbuf_state.vertexbuf.vb[0].stride = 8;
fd3_ctx->blit_vbuf_state.vertexbuf.vb[0].buffer = fd3_ctx->blit_texcoord_vbuf;
fd3_ctx->blit_vbuf_state.vertexbuf.vb[1].stride = 12;
fd3_ctx->blit_vbuf_state.vertexbuf.vb[1].buffer = fd3_ctx->solid_vbuf;
 
fd3_query_context_init(pctx);
 
fd3_ctx->border_color_uploader = u_upload_create(pctx, 4096,
2 * PIPE_MAX_SAMPLERS * BORDERCOLOR_SIZE, 0);
 
return pctx;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a3xx/fd3_context.h
0,0 → 1,127
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FD3_CONTEXT_H_
#define FD3_CONTEXT_H_
 
#include "util/u_upload_mgr.h"
 
#include "freedreno_drmif.h"
 
#include "freedreno_context.h"
 
#include "ir3_shader.h"
 
 
struct fd3_context {
struct fd_context base;
 
/* Keep track of writes to RB_RENDER_CONTROL which need to be patched
* once we know whether or not to use GMEM, and GMEM tile pitch.
*/
struct util_dynarray rbrc_patches;
 
struct fd_bo *vs_pvt_mem, *fs_pvt_mem;
 
/* This only needs to be 4 * num_of_pipes bytes (ie. 32 bytes). We
* could combine it with another allocation.
*/
struct fd_bo *vsc_size_mem;
 
/* vertex buf used for clear/gmem->mem vertices, and mem->gmem
* vertices:
*/
struct pipe_resource *solid_vbuf;
 
/* vertex buf used for mem->gmem tex coords:
*/
struct pipe_resource *blit_texcoord_vbuf;
 
/* vertex state for solid_vbuf:
* - solid_vbuf / 12 / R32G32B32_FLOAT
*/
struct fd_vertex_state solid_vbuf_state;
 
/* vertex state for blit_prog:
* - blit_texcoord_vbuf / 8 / R32G32_FLOAT
* - solid_vbuf / 12 / R32G32B32_FLOAT
*/
struct fd_vertex_state blit_vbuf_state;
 
 
/*
* Border color layout *appears* to be as arrays of 0x40 byte
* elements, with frag shader elements starting at (16 x 0x40).
* But at some point I should probably experiment more with
* samplers in vertex shaders to be sure. Unclear about why
* there is this offset when there are separate VS and FS base
* addr regs.
*
* The first 8 bytes of each entry are the requested border
* color in fp16. Unclear about the rest.. could be used for
* other formats, or could simply be for aligning the pitch
* to 32 pixels.
*/
#define BORDERCOLOR_SIZE 0x40
 
struct u_upload_mgr *border_color_uploader;
struct pipe_resource *border_color_buf;
 
/* if *any* of bits are set in {v,f}saturate_{s,t,r} */
bool vsaturate, fsaturate;
 
/* bitmask of sampler which needs coords clamped for vertex
* shader:
*/
unsigned vsaturate_s, vsaturate_t, vsaturate_r;
 
/* bitmask of sampler which needs coords clamped for frag
* shader:
*/
unsigned fsaturate_s, fsaturate_t, fsaturate_r;
 
/* bitmask of integer texture samplers */
uint16_t vinteger_s, finteger_s;
 
/* some state changes require a different shader variant. Keep
* track of this so we know when we need to re-emit shader state
* due to variant change. See fixup_shader_state()
*/
struct ir3_shader_key last_key;
};
 
static INLINE struct fd3_context *
fd3_context(struct fd_context *ctx)
{
return (struct fd3_context *)ctx;
}
 
struct pipe_context *
fd3_context_create(struct pipe_screen *pscreen, void *priv);
 
#endif /* FD3_CONTEXT_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a3xx/fd3_draw.c
0,0 → 1,377
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "pipe/p_state.h"
#include "util/u_string.h"
#include "util/u_memory.h"
#include "util/u_prim.h"
#include "util/u_format.h"
 
#include "freedreno_state.h"
#include "freedreno_resource.h"
 
#include "fd3_draw.h"
#include "fd3_context.h"
#include "fd3_emit.h"
#include "fd3_program.h"
#include "fd3_format.h"
#include "fd3_zsa.h"
 
static inline uint32_t
add_sat(uint32_t a, int32_t b)
{
int64_t ret = (uint64_t)a + (int64_t)b;
if (ret > ~0U)
return ~0U;
if (ret < 0)
return 0;
return (uint32_t)ret;
}
 
static void
draw_impl(struct fd_context *ctx, struct fd_ringbuffer *ring,
struct fd3_emit *emit)
{
const struct pipe_draw_info *info = emit->info;
enum pc_di_primtype primtype = ctx->primtypes[info->mode];
 
fd3_emit_state(ctx, ring, emit);
 
if (emit->dirty & (FD_DIRTY_VTXBUF | FD_DIRTY_VTXSTATE))
fd3_emit_vertex_bufs(ring, emit);
 
OUT_PKT0(ring, REG_A3XX_PC_VERTEX_REUSE_BLOCK_CNTL, 1);
OUT_RING(ring, 0x0000000b); /* PC_VERTEX_REUSE_BLOCK_CNTL */
 
OUT_PKT0(ring, REG_A3XX_VFD_INDEX_MIN, 4);
OUT_RING(ring, add_sat(info->min_index, info->index_bias)); /* VFD_INDEX_MIN */
OUT_RING(ring, add_sat(info->max_index, info->index_bias)); /* VFD_INDEX_MAX */
OUT_RING(ring, info->start_instance); /* VFD_INSTANCEID_OFFSET */
OUT_RING(ring, info->indexed ? info->index_bias : info->start); /* VFD_INDEX_OFFSET */
 
OUT_PKT0(ring, REG_A3XX_PC_RESTART_INDEX, 1);
OUT_RING(ring, info->primitive_restart ? /* PC_RESTART_INDEX */
info->restart_index : 0xffffffff);
 
if (ctx->rasterizer && ctx->rasterizer->point_size_per_vertex &&
info->mode == PIPE_PRIM_POINTS)
primtype = DI_PT_POINTLIST_A2XX;
 
fd_draw_emit(ctx, ring,
primtype,
emit->key.binning_pass ? IGNORE_VISIBILITY : USE_VISIBILITY,
info);
}
 
/* fixup dirty shader state in case some "unrelated" (from the state-
* tracker's perspective) state change causes us to switch to a
* different variant.
*/
static void
fixup_shader_state(struct fd_context *ctx, struct ir3_shader_key *key)
{
struct fd3_context *fd3_ctx = fd3_context(ctx);
struct ir3_shader_key *last_key = &fd3_ctx->last_key;
 
if (!ir3_shader_key_equal(last_key, key)) {
ctx->dirty |= FD_DIRTY_PROG;
 
if (last_key->has_per_samp || key->has_per_samp) {
if ((last_key->vsaturate_s != key->vsaturate_s) ||
(last_key->vsaturate_t != key->vsaturate_t) ||
(last_key->vsaturate_r != key->vsaturate_r) ||
(last_key->vinteger_s != key->vinteger_s))
ctx->prog.dirty |= FD_SHADER_DIRTY_VP;
 
if ((last_key->fsaturate_s != key->fsaturate_s) ||
(last_key->fsaturate_t != key->fsaturate_t) ||
(last_key->fsaturate_r != key->fsaturate_r) ||
(last_key->finteger_s != key->finteger_s))
ctx->prog.dirty |= FD_SHADER_DIRTY_FP;
}
 
if (last_key->color_two_side != key->color_two_side)
ctx->prog.dirty |= FD_SHADER_DIRTY_FP;
 
if (last_key->half_precision != key->half_precision)
ctx->prog.dirty |= FD_SHADER_DIRTY_FP;
 
fd3_ctx->last_key = *key;
}
}
 
static void
fd3_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info)
{
struct fd3_context *fd3_ctx = fd3_context(ctx);
struct fd3_emit emit = {
.vtx = &ctx->vtx,
.prog = &ctx->prog,
.info = info,
.key = {
/* do binning pass first: */
.binning_pass = true,
.color_two_side = ctx->rasterizer ? ctx->rasterizer->light_twoside : false,
// TODO set .half_precision based on render target format,
// ie. float16 and smaller use half, float32 use full..
.half_precision = !!(fd_mesa_debug & FD_DBG_FRAGHALF),
.has_per_samp = (fd3_ctx->fsaturate || fd3_ctx->vsaturate ||
fd3_ctx->vinteger_s || fd3_ctx->finteger_s),
.vsaturate_s = fd3_ctx->vsaturate_s,
.vsaturate_t = fd3_ctx->vsaturate_t,
.vsaturate_r = fd3_ctx->vsaturate_r,
.fsaturate_s = fd3_ctx->fsaturate_s,
.fsaturate_t = fd3_ctx->fsaturate_t,
.fsaturate_r = fd3_ctx->fsaturate_r,
.vinteger_s = fd3_ctx->vinteger_s,
.finteger_s = fd3_ctx->finteger_s,
},
.rasterflat = ctx->rasterizer && ctx->rasterizer->flatshade,
.sprite_coord_enable = ctx->rasterizer ? ctx->rasterizer->sprite_coord_enable : 0,
.sprite_coord_mode = ctx->rasterizer ? ctx->rasterizer->sprite_coord_mode : false,
};
unsigned dirty;
 
fixup_shader_state(ctx, &emit.key);
 
dirty = ctx->dirty;
emit.dirty = dirty & ~(FD_DIRTY_BLEND);
draw_impl(ctx, ctx->binning_ring, &emit);
 
/* and now regular (non-binning) pass: */
emit.key.binning_pass = false;
emit.dirty = dirty;
emit.vp = NULL; /* we changed key so need to refetch vp */
draw_impl(ctx, ctx->ring, &emit);
}
 
/* clear operations ignore viewport state, so we need to reset it
* based on framebuffer state:
*/
static void
reset_viewport(struct fd_ringbuffer *ring, struct pipe_framebuffer_state *pfb)
{
float half_width = pfb->width * 0.5f;
float half_height = pfb->height * 0.5f;
 
OUT_PKT0(ring, REG_A3XX_GRAS_CL_VPORT_XOFFSET, 4);
OUT_RING(ring, A3XX_GRAS_CL_VPORT_XOFFSET(half_width - 0.5));
OUT_RING(ring, A3XX_GRAS_CL_VPORT_XSCALE(half_width));
OUT_RING(ring, A3XX_GRAS_CL_VPORT_YOFFSET(half_height - 0.5));
OUT_RING(ring, A3XX_GRAS_CL_VPORT_YSCALE(-half_height));
}
 
/* binning pass cmds for a clear:
* NOTE: newer blob drivers don't use binning for clear, which is probably
* preferable since it is low vtx count. However that doesn't seem to
* actually work for me. Not sure if it is depending on support for
* clear pass (rather than using solid-fill shader), or something else
* that newer blob is doing differently. Once that is figured out, we
* can remove fd3_clear_binning().
*/
static void
fd3_clear_binning(struct fd_context *ctx, unsigned dirty)
{
struct fd3_context *fd3_ctx = fd3_context(ctx);
struct fd_ringbuffer *ring = ctx->binning_ring;
struct fd3_emit emit = {
.vtx = &fd3_ctx->solid_vbuf_state,
.prog = &ctx->solid_prog,
.key = {
.binning_pass = true,
.half_precision = true,
},
.dirty = dirty,
};
 
fd3_emit_state(ctx, ring, &emit);
fd3_emit_vertex_bufs(ring, &emit);
reset_viewport(ring, &ctx->framebuffer);
 
OUT_PKT0(ring, REG_A3XX_PC_PRIM_VTX_CNTL, 1);
OUT_RING(ring, A3XX_PC_PRIM_VTX_CNTL_STRIDE_IN_VPC(0) |
A3XX_PC_PRIM_VTX_CNTL_POLYMODE_FRONT_PTYPE(PC_DRAW_TRIANGLES) |
A3XX_PC_PRIM_VTX_CNTL_POLYMODE_BACK_PTYPE(PC_DRAW_TRIANGLES) |
A3XX_PC_PRIM_VTX_CNTL_PROVOKING_VTX_LAST);
OUT_PKT0(ring, REG_A3XX_VFD_INDEX_MIN, 4);
OUT_RING(ring, 0); /* VFD_INDEX_MIN */
OUT_RING(ring, 2); /* VFD_INDEX_MAX */
OUT_RING(ring, 0); /* VFD_INSTANCEID_OFFSET */
OUT_RING(ring, 0); /* VFD_INDEX_OFFSET */
OUT_PKT0(ring, REG_A3XX_PC_RESTART_INDEX, 1);
OUT_RING(ring, 0xffffffff); /* PC_RESTART_INDEX */
 
fd_event_write(ctx, ring, PERFCOUNTER_STOP);
 
fd_draw(ctx, ring, DI_PT_RECTLIST, IGNORE_VISIBILITY,
DI_SRC_SEL_AUTO_INDEX, 2, 0, INDEX_SIZE_IGN, 0, 0, NULL);
}
 
static void
fd3_clear(struct fd_context *ctx, unsigned buffers,
const union pipe_color_union *color, double depth, unsigned stencil)
{
struct fd3_context *fd3_ctx = fd3_context(ctx);
struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
struct fd_ringbuffer *ring = ctx->ring;
unsigned dirty = ctx->dirty;
unsigned i;
struct fd3_emit emit = {
.vtx = &fd3_ctx->solid_vbuf_state,
.prog = &ctx->solid_prog,
.key = {
.half_precision = (fd3_half_precision(pfb->cbufs[0]) &&
fd3_half_precision(pfb->cbufs[1]) &&
fd3_half_precision(pfb->cbufs[2]) &&
fd3_half_precision(pfb->cbufs[3])),
},
};
 
dirty &= FD_DIRTY_FRAMEBUFFER | FD_DIRTY_SCISSOR;
dirty |= FD_DIRTY_PROG;
emit.dirty = dirty;
 
fd3_clear_binning(ctx, dirty);
 
/* emit generic state now: */
fd3_emit_state(ctx, ring, &emit);
reset_viewport(ring, &ctx->framebuffer);
 
OUT_PKT0(ring, REG_A3XX_RB_BLEND_ALPHA, 1);
OUT_RING(ring, A3XX_RB_BLEND_ALPHA_UINT(0xff) |
A3XX_RB_BLEND_ALPHA_FLOAT(1.0));
 
OUT_PKT0(ring, REG_A3XX_RB_RENDER_CONTROL, 1);
OUT_RINGP(ring, A3XX_RB_RENDER_CONTROL_ALPHA_TEST_FUNC(FUNC_NEVER),
&fd3_ctx->rbrc_patches);
 
if (buffers & PIPE_CLEAR_DEPTH) {
OUT_PKT0(ring, REG_A3XX_RB_DEPTH_CONTROL, 1);
OUT_RING(ring, A3XX_RB_DEPTH_CONTROL_Z_WRITE_ENABLE |
A3XX_RB_DEPTH_CONTROL_Z_ENABLE |
A3XX_RB_DEPTH_CONTROL_ZFUNC(FUNC_ALWAYS));
 
fd_wfi(ctx, ring);
OUT_PKT0(ring, REG_A3XX_GRAS_CL_VPORT_ZOFFSET, 2);
OUT_RING(ring, A3XX_GRAS_CL_VPORT_ZOFFSET(0.0));
OUT_RING(ring, A3XX_GRAS_CL_VPORT_ZSCALE(depth));
ctx->dirty |= FD_DIRTY_VIEWPORT;
} else {
OUT_PKT0(ring, REG_A3XX_RB_DEPTH_CONTROL, 1);
OUT_RING(ring, A3XX_RB_DEPTH_CONTROL_ZFUNC(FUNC_NEVER));
}
 
if (buffers & PIPE_CLEAR_STENCIL) {
OUT_PKT0(ring, REG_A3XX_RB_STENCILREFMASK, 2);
OUT_RING(ring, A3XX_RB_STENCILREFMASK_STENCILREF(stencil) |
A3XX_RB_STENCILREFMASK_STENCILMASK(stencil) |
A3XX_RB_STENCILREFMASK_STENCILWRITEMASK(0xff));
OUT_RING(ring, A3XX_RB_STENCILREFMASK_STENCILREF(0) |
A3XX_RB_STENCILREFMASK_STENCILMASK(0) |
0xff000000 | // XXX ???
A3XX_RB_STENCILREFMASK_STENCILWRITEMASK(0xff));
 
OUT_PKT0(ring, REG_A3XX_RB_STENCIL_CONTROL, 1);
OUT_RING(ring, A3XX_RB_STENCIL_CONTROL_STENCIL_ENABLE |
A3XX_RB_STENCIL_CONTROL_FUNC(FUNC_ALWAYS) |
A3XX_RB_STENCIL_CONTROL_FAIL(STENCIL_KEEP) |
A3XX_RB_STENCIL_CONTROL_ZPASS(STENCIL_REPLACE) |
A3XX_RB_STENCIL_CONTROL_ZFAIL(STENCIL_KEEP) |
A3XX_RB_STENCIL_CONTROL_FUNC_BF(FUNC_NEVER) |
A3XX_RB_STENCIL_CONTROL_FAIL_BF(STENCIL_KEEP) |
A3XX_RB_STENCIL_CONTROL_ZPASS_BF(STENCIL_KEEP) |
A3XX_RB_STENCIL_CONTROL_ZFAIL_BF(STENCIL_KEEP));
} else {
OUT_PKT0(ring, REG_A3XX_RB_STENCILREFMASK, 2);
OUT_RING(ring, A3XX_RB_STENCILREFMASK_STENCILREF(0) |
A3XX_RB_STENCILREFMASK_STENCILMASK(0) |
A3XX_RB_STENCILREFMASK_STENCILWRITEMASK(0));
OUT_RING(ring, A3XX_RB_STENCILREFMASK_BF_STENCILREF(0) |
A3XX_RB_STENCILREFMASK_BF_STENCILMASK(0) |
A3XX_RB_STENCILREFMASK_BF_STENCILWRITEMASK(0));
 
OUT_PKT0(ring, REG_A3XX_RB_STENCIL_CONTROL, 1);
OUT_RING(ring, A3XX_RB_STENCIL_CONTROL_FUNC(FUNC_NEVER) |
A3XX_RB_STENCIL_CONTROL_FAIL(STENCIL_KEEP) |
A3XX_RB_STENCIL_CONTROL_ZPASS(STENCIL_KEEP) |
A3XX_RB_STENCIL_CONTROL_ZFAIL(STENCIL_KEEP) |
A3XX_RB_STENCIL_CONTROL_FUNC_BF(FUNC_NEVER) |
A3XX_RB_STENCIL_CONTROL_FAIL_BF(STENCIL_KEEP) |
A3XX_RB_STENCIL_CONTROL_ZPASS_BF(STENCIL_KEEP) |
A3XX_RB_STENCIL_CONTROL_ZFAIL_BF(STENCIL_KEEP));
}
 
for (i = 0; i < 4; i++) {
OUT_PKT0(ring, REG_A3XX_RB_MRT_CONTROL(i), 1);
OUT_RING(ring, A3XX_RB_MRT_CONTROL_ROP_CODE(ROP_COPY) |
A3XX_RB_MRT_CONTROL_DITHER_MODE(DITHER_ALWAYS) |
COND(buffers & (PIPE_CLEAR_COLOR0 << i),
A3XX_RB_MRT_CONTROL_COMPONENT_ENABLE(0xf)));
 
OUT_PKT0(ring, REG_A3XX_RB_MRT_BLEND_CONTROL(i), 1);
OUT_RING(ring, A3XX_RB_MRT_BLEND_CONTROL_RGB_SRC_FACTOR(FACTOR_ONE) |
A3XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE(BLEND_DST_PLUS_SRC) |
A3XX_RB_MRT_BLEND_CONTROL_RGB_DEST_FACTOR(FACTOR_ZERO) |
A3XX_RB_MRT_BLEND_CONTROL_ALPHA_SRC_FACTOR(FACTOR_ONE) |
A3XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE(BLEND_DST_PLUS_SRC) |
A3XX_RB_MRT_BLEND_CONTROL_ALPHA_DEST_FACTOR(FACTOR_ZERO));
}
 
OUT_PKT0(ring, REG_A3XX_GRAS_SU_MODE_CONTROL, 1);
OUT_RING(ring, A3XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH(0));
 
fd3_emit_vertex_bufs(ring, &emit);
 
fd3_emit_constant(ring, SB_FRAG_SHADER, 0, 0, 4, color->ui, NULL);
 
OUT_PKT0(ring, REG_A3XX_PC_PRIM_VTX_CNTL, 1);
OUT_RING(ring, A3XX_PC_PRIM_VTX_CNTL_STRIDE_IN_VPC(0) |
A3XX_PC_PRIM_VTX_CNTL_POLYMODE_FRONT_PTYPE(PC_DRAW_TRIANGLES) |
A3XX_PC_PRIM_VTX_CNTL_POLYMODE_BACK_PTYPE(PC_DRAW_TRIANGLES) |
A3XX_PC_PRIM_VTX_CNTL_PROVOKING_VTX_LAST);
OUT_PKT0(ring, REG_A3XX_VFD_INDEX_MIN, 4);
OUT_RING(ring, 0); /* VFD_INDEX_MIN */
OUT_RING(ring, 2); /* VFD_INDEX_MAX */
OUT_RING(ring, 0); /* VFD_INSTANCEID_OFFSET */
OUT_RING(ring, 0); /* VFD_INDEX_OFFSET */
OUT_PKT0(ring, REG_A3XX_PC_RESTART_INDEX, 1);
OUT_RING(ring, 0xffffffff); /* PC_RESTART_INDEX */
 
fd_event_write(ctx, ring, PERFCOUNTER_STOP);
 
fd_draw(ctx, ring, DI_PT_RECTLIST, USE_VISIBILITY,
DI_SRC_SEL_AUTO_INDEX, 2, 0, INDEX_SIZE_IGN, 0, 0, NULL);
}
 
void
fd3_draw_init(struct pipe_context *pctx)
{
struct fd_context *ctx = fd_context(pctx);
ctx->draw_vbo = fd3_draw_vbo;
ctx->clear = fd3_clear;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a3xx/fd3_draw.h
0,0 → 1,38
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FD3_DRAW_H_
#define FD3_DRAW_H_
 
#include "pipe/p_context.h"
 
#include "freedreno_draw.h"
 
void fd3_draw_init(struct pipe_context *pctx);
 
#endif /* FD3_DRAW_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a3xx/fd3_emit.c
0,0 → 1,932
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "pipe/p_state.h"
#include "util/u_string.h"
#include "util/u_memory.h"
#include "util/u_helpers.h"
#include "util/u_format.h"
 
#include "freedreno_resource.h"
 
#include "fd3_emit.h"
#include "fd3_blend.h"
#include "fd3_context.h"
#include "fd3_program.h"
#include "fd3_rasterizer.h"
#include "fd3_texture.h"
#include "fd3_format.h"
#include "fd3_zsa.h"
 
/* regid: base const register
* prsc or dwords: buffer containing constant values
* sizedwords: size of const value buffer
*/
void
fd3_emit_constant(struct fd_ringbuffer *ring,
enum adreno_state_block sb,
uint32_t regid, uint32_t offset, uint32_t sizedwords,
const uint32_t *dwords, struct pipe_resource *prsc)
{
uint32_t i, sz;
enum adreno_state_src src;
 
if (prsc) {
sz = 0;
src = SS_INDIRECT;
} else {
sz = sizedwords;
src = SS_DIRECT;
}
 
OUT_PKT3(ring, CP_LOAD_STATE, 2 + sz);
OUT_RING(ring, CP_LOAD_STATE_0_DST_OFF(regid/2) |
CP_LOAD_STATE_0_STATE_SRC(src) |
CP_LOAD_STATE_0_STATE_BLOCK(sb) |
CP_LOAD_STATE_0_NUM_UNIT(sizedwords/2));
if (prsc) {
struct fd_bo *bo = fd_resource(prsc)->bo;
OUT_RELOC(ring, bo, offset,
CP_LOAD_STATE_1_STATE_TYPE(ST_CONSTANTS), 0);
} else {
OUT_RING(ring, CP_LOAD_STATE_1_EXT_SRC_ADDR(0) |
CP_LOAD_STATE_1_STATE_TYPE(ST_CONSTANTS));
dwords = (uint32_t *)&((uint8_t *)dwords)[offset];
}
for (i = 0; i < sz; i++) {
OUT_RING(ring, dwords[i]);
}
}
 
static void
emit_constants(struct fd_ringbuffer *ring,
enum adreno_state_block sb,
struct fd_constbuf_stateobj *constbuf,
struct ir3_shader_variant *shader,
bool emit_immediates)
{
uint32_t enabled_mask = constbuf->enabled_mask;
uint32_t max_const;
int i;
 
// XXX TODO only emit dirty consts.. but we need to keep track if
// they are clobbered by a clear, gmem2mem, or mem2gmem..
constbuf->dirty_mask = enabled_mask;
 
/* in particular, with binning shader we may end up with unused
* consts, ie. we could end up w/ constlen that is smaller
* than first_immediate. In that case truncate the user consts
* early to avoid HLSQ lockup caused by writing too many consts
*/
max_const = MIN2(shader->first_driver_param, shader->constlen);
 
/* emit user constants: */
if (enabled_mask & 1) {
const unsigned index = 0;
struct pipe_constant_buffer *cb = &constbuf->cb[index];
unsigned size = align(cb->buffer_size, 4) / 4; /* size in dwords */
 
// I expect that size should be a multiple of vec4's:
assert(size == align(size, 4));
 
/* and even if the start of the const buffer is before
* first_immediate, the end may not be:
*/
size = MIN2(size, 4 * max_const);
 
if (size && constbuf->dirty_mask & (1 << index)) {
fd3_emit_constant(ring, sb, 0,
cb->buffer_offset, size,
cb->user_buffer, cb->buffer);
constbuf->dirty_mask &= ~(1 << index);
}
 
enabled_mask &= ~(1 << index);
}
 
if (shader->constlen > shader->first_driver_param) {
uint32_t params = MIN2(4, shader->constlen - shader->first_driver_param);
/* emit ubos: */
OUT_PKT3(ring, CP_LOAD_STATE, 2 + params * 4);
OUT_RING(ring, CP_LOAD_STATE_0_DST_OFF(shader->first_driver_param * 2) |
CP_LOAD_STATE_0_STATE_SRC(SS_DIRECT) |
CP_LOAD_STATE_0_STATE_BLOCK(sb) |
CP_LOAD_STATE_0_NUM_UNIT(params * 2));
OUT_RING(ring, CP_LOAD_STATE_1_EXT_SRC_ADDR(0) |
CP_LOAD_STATE_1_STATE_TYPE(ST_CONSTANTS));
 
for (i = 1; i <= params * 4; i++) {
struct pipe_constant_buffer *cb = &constbuf->cb[i];
assert(!cb->user_buffer);
if ((enabled_mask & (1 << i)) && cb->buffer)
OUT_RELOC(ring, fd_resource(cb->buffer)->bo, cb->buffer_offset, 0, 0);
else
OUT_RING(ring, 0xbad00000 | ((i - 1) << 16));
}
}
 
/* emit shader immediates: */
if (shader && emit_immediates) {
int size = shader->immediates_count;
uint32_t base = shader->first_immediate;
 
/* truncate size to avoid writing constants that shader
* does not use:
*/
size = MIN2(size + base, shader->constlen) - base;
 
/* convert out of vec4: */
base *= 4;
size *= 4;
 
if (size > 0) {
fd3_emit_constant(ring, sb, base,
0, size, shader->immediates[0].val, NULL);
}
}
}
 
#define VERT_TEX_OFF 0
#define FRAG_TEX_OFF 16
#define BASETABLE_SZ A3XX_MAX_MIP_LEVELS
 
static void
emit_textures(struct fd_context *ctx, struct fd_ringbuffer *ring,
enum adreno_state_block sb, struct fd_texture_stateobj *tex)
{
static const unsigned tex_off[] = {
[SB_VERT_TEX] = VERT_TEX_OFF,
[SB_FRAG_TEX] = FRAG_TEX_OFF,
};
static const enum adreno_state_block mipaddr[] = {
[SB_VERT_TEX] = SB_VERT_MIPADDR,
[SB_FRAG_TEX] = SB_FRAG_MIPADDR,
};
static const uint32_t bcolor_reg[] = {
[SB_VERT_TEX] = REG_A3XX_TPL1_TP_VS_BORDER_COLOR_BASE_ADDR,
[SB_FRAG_TEX] = REG_A3XX_TPL1_TP_FS_BORDER_COLOR_BASE_ADDR,
};
struct fd3_context *fd3_ctx = fd3_context(ctx);
unsigned i, j, off;
void *ptr;
 
u_upload_alloc(fd3_ctx->border_color_uploader,
0, 2 * PIPE_MAX_SAMPLERS * BORDERCOLOR_SIZE, &off,
&fd3_ctx->border_color_buf,
&ptr);
 
if (tex->num_samplers > 0) {
/* output sampler state: */
OUT_PKT3(ring, CP_LOAD_STATE, 2 + (2 * tex->num_samplers));
OUT_RING(ring, CP_LOAD_STATE_0_DST_OFF(tex_off[sb]) |
CP_LOAD_STATE_0_STATE_SRC(SS_DIRECT) |
CP_LOAD_STATE_0_STATE_BLOCK(sb) |
CP_LOAD_STATE_0_NUM_UNIT(tex->num_samplers));
OUT_RING(ring, CP_LOAD_STATE_1_STATE_TYPE(ST_SHADER) |
CP_LOAD_STATE_1_EXT_SRC_ADDR(0));
for (i = 0; i < tex->num_samplers; i++) {
static const struct fd3_sampler_stateobj dummy_sampler = {};
const struct fd3_sampler_stateobj *sampler = tex->samplers[i] ?
fd3_sampler_stateobj(tex->samplers[i]) :
&dummy_sampler;
uint16_t *bcolor = (uint16_t *)((uint8_t *)ptr +
(BORDERCOLOR_SIZE * tex_off[sb]) +
(BORDERCOLOR_SIZE * i));
uint32_t *bcolor32 = (uint32_t *)&bcolor[16];
 
/*
* XXX HACK ALERT XXX
*
* The border colors need to be swizzled in a particular
* format-dependent order. Even though samplers don't know about
* formats, we can assume that with a GL state tracker, there's a
* 1:1 correspondence between sampler and texture. Take advantage
* of that knowledge.
*/
if (i < tex->num_textures && tex->textures[i]) {
const struct util_format_description *desc =
util_format_description(tex->textures[i]->format);
for (j = 0; j < 4; j++) {
if (desc->swizzle[j] >= 4)
continue;
 
const struct util_format_channel_description *chan =
&desc->channel[desc->swizzle[j]];
int size = chan->size;
 
/* The Z16 texture format we use seems to look in the
* 32-bit border color slots
*/
if (desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS)
size = 32;
 
/* Formats like R11G11B10 or RGB9_E5 don't specify
* per-channel sizes properly.
*/
if (desc->layout == UTIL_FORMAT_LAYOUT_OTHER)
size = 16;
 
if (chan->pure_integer && size > 16)
bcolor32[desc->swizzle[j] + 4] =
sampler->base.border_color.i[j];
else if (size > 16)
bcolor32[desc->swizzle[j]] =
fui(sampler->base.border_color.f[j]);
else if (chan->pure_integer)
bcolor[desc->swizzle[j] + 8] =
sampler->base.border_color.i[j];
else
bcolor[desc->swizzle[j]] =
util_float_to_half(sampler->base.border_color.f[j]);
}
}
 
OUT_RING(ring, sampler->texsamp0);
OUT_RING(ring, sampler->texsamp1);
}
}
 
if (tex->num_textures > 0) {
/* emit texture state: */
OUT_PKT3(ring, CP_LOAD_STATE, 2 + (4 * tex->num_textures));
OUT_RING(ring, CP_LOAD_STATE_0_DST_OFF(tex_off[sb]) |
CP_LOAD_STATE_0_STATE_SRC(SS_DIRECT) |
CP_LOAD_STATE_0_STATE_BLOCK(sb) |
CP_LOAD_STATE_0_NUM_UNIT(tex->num_textures));
OUT_RING(ring, CP_LOAD_STATE_1_STATE_TYPE(ST_CONSTANTS) |
CP_LOAD_STATE_1_EXT_SRC_ADDR(0));
for (i = 0; i < tex->num_textures; i++) {
static const struct fd3_pipe_sampler_view dummy_view = {};
const struct fd3_pipe_sampler_view *view = tex->textures[i] ?
fd3_pipe_sampler_view(tex->textures[i]) :
&dummy_view;
OUT_RING(ring, view->texconst0);
OUT_RING(ring, view->texconst1);
OUT_RING(ring, view->texconst2 |
A3XX_TEX_CONST_2_INDX(BASETABLE_SZ * i));
OUT_RING(ring, view->texconst3);
}
 
/* emit mipaddrs: */
OUT_PKT3(ring, CP_LOAD_STATE, 2 + (BASETABLE_SZ * tex->num_textures));
OUT_RING(ring, CP_LOAD_STATE_0_DST_OFF(BASETABLE_SZ * tex_off[sb]) |
CP_LOAD_STATE_0_STATE_SRC(SS_DIRECT) |
CP_LOAD_STATE_0_STATE_BLOCK(mipaddr[sb]) |
CP_LOAD_STATE_0_NUM_UNIT(BASETABLE_SZ * tex->num_textures));
OUT_RING(ring, CP_LOAD_STATE_1_STATE_TYPE(ST_CONSTANTS) |
CP_LOAD_STATE_1_EXT_SRC_ADDR(0));
for (i = 0; i < tex->num_textures; i++) {
static const struct fd3_pipe_sampler_view dummy_view = {
.base.u.tex.first_level = 1,
};
const struct fd3_pipe_sampler_view *view = tex->textures[i] ?
fd3_pipe_sampler_view(tex->textures[i]) :
&dummy_view;
struct fd_resource *rsc = fd_resource(view->base.texture);
unsigned start = view->base.u.tex.first_level;
unsigned end = view->base.u.tex.last_level;
 
for (j = 0; j < (end - start + 1); j++) {
struct fd_resource_slice *slice =
fd_resource_slice(rsc, j + start);
OUT_RELOC(ring, rsc->bo, slice->offset, 0, 0);
}
 
/* pad the remaining entries w/ null: */
for (; j < BASETABLE_SZ; j++) {
OUT_RING(ring, 0x00000000);
}
}
}
 
OUT_PKT0(ring, bcolor_reg[sb], 1);
OUT_RELOC(ring, fd_resource(fd3_ctx->border_color_buf)->bo, off, 0, 0);
 
u_upload_unmap(fd3_ctx->border_color_uploader);
}
 
/* emit texture state for mem->gmem restore operation.. eventually it would
* be good to get rid of this and use normal CSO/etc state for more of these
* special cases, but for now the compiler is not sufficient..
*
* Also, for using normal state, not quite sure how to handle the special
* case format (fd3_gmem_restore_format()) stuff for restoring depth/stencil.
*/
void
fd3_emit_gmem_restore_tex(struct fd_ringbuffer *ring,
struct pipe_surface **psurf,
int bufs)
{
int i, j;
 
/* output sampler state: */
OUT_PKT3(ring, CP_LOAD_STATE, 2 + 2 * bufs);
OUT_RING(ring, CP_LOAD_STATE_0_DST_OFF(FRAG_TEX_OFF) |
CP_LOAD_STATE_0_STATE_SRC(SS_DIRECT) |
CP_LOAD_STATE_0_STATE_BLOCK(SB_FRAG_TEX) |
CP_LOAD_STATE_0_NUM_UNIT(bufs));
OUT_RING(ring, CP_LOAD_STATE_1_STATE_TYPE(ST_SHADER) |
CP_LOAD_STATE_1_EXT_SRC_ADDR(0));
for (i = 0; i < bufs; i++) {
OUT_RING(ring, A3XX_TEX_SAMP_0_XY_MAG(A3XX_TEX_NEAREST) |
A3XX_TEX_SAMP_0_XY_MIN(A3XX_TEX_NEAREST) |
A3XX_TEX_SAMP_0_WRAP_S(A3XX_TEX_CLAMP_TO_EDGE) |
A3XX_TEX_SAMP_0_WRAP_T(A3XX_TEX_CLAMP_TO_EDGE) |
A3XX_TEX_SAMP_0_WRAP_R(A3XX_TEX_REPEAT));
OUT_RING(ring, 0x00000000);
}
 
/* emit texture state: */
OUT_PKT3(ring, CP_LOAD_STATE, 2 + 4 * bufs);
OUT_RING(ring, CP_LOAD_STATE_0_DST_OFF(FRAG_TEX_OFF) |
CP_LOAD_STATE_0_STATE_SRC(SS_DIRECT) |
CP_LOAD_STATE_0_STATE_BLOCK(SB_FRAG_TEX) |
CP_LOAD_STATE_0_NUM_UNIT(bufs));
OUT_RING(ring, CP_LOAD_STATE_1_STATE_TYPE(ST_CONSTANTS) |
CP_LOAD_STATE_1_EXT_SRC_ADDR(0));
for (i = 0; i < bufs; i++) {
if (!psurf[i]) {
OUT_RING(ring, A3XX_TEX_CONST_0_TYPE(A3XX_TEX_2D) |
A3XX_TEX_CONST_0_SWIZ_X(A3XX_TEX_ONE) |
A3XX_TEX_CONST_0_SWIZ_Y(A3XX_TEX_ONE) |
A3XX_TEX_CONST_0_SWIZ_Z(A3XX_TEX_ONE) |
A3XX_TEX_CONST_0_SWIZ_W(A3XX_TEX_ONE));
OUT_RING(ring, 0x00000000);
OUT_RING(ring, A3XX_TEX_CONST_2_INDX(BASETABLE_SZ * i));
OUT_RING(ring, 0x00000000);
continue;
}
 
struct fd_resource *rsc = fd_resource(psurf[i]->texture);
enum pipe_format format = fd3_gmem_restore_format(psurf[i]->format);
/* The restore blit_zs shader expects stencil in sampler 0, and depth
* in sampler 1
*/
if (rsc->stencil && i == 0) {
rsc = rsc->stencil;
format = fd3_gmem_restore_format(rsc->base.b.format);
}
 
unsigned lvl = psurf[i]->u.tex.level;
struct fd_resource_slice *slice = fd_resource_slice(rsc, lvl);
 
debug_assert(psurf[i]->u.tex.first_layer == psurf[i]->u.tex.last_layer);
 
OUT_RING(ring, A3XX_TEX_CONST_0_FMT(fd3_pipe2tex(format)) |
A3XX_TEX_CONST_0_TYPE(A3XX_TEX_2D) |
fd3_tex_swiz(format, PIPE_SWIZZLE_RED, PIPE_SWIZZLE_GREEN,
PIPE_SWIZZLE_BLUE, PIPE_SWIZZLE_ALPHA));
OUT_RING(ring, A3XX_TEX_CONST_1_FETCHSIZE(TFETCH_DISABLE) |
A3XX_TEX_CONST_1_WIDTH(psurf[i]->width) |
A3XX_TEX_CONST_1_HEIGHT(psurf[i]->height));
OUT_RING(ring, A3XX_TEX_CONST_2_PITCH(slice->pitch * rsc->cpp) |
A3XX_TEX_CONST_2_INDX(BASETABLE_SZ * i));
OUT_RING(ring, 0x00000000);
}
 
/* emit mipaddrs: */
OUT_PKT3(ring, CP_LOAD_STATE, 2 + BASETABLE_SZ * bufs);
OUT_RING(ring, CP_LOAD_STATE_0_DST_OFF(BASETABLE_SZ * FRAG_TEX_OFF) |
CP_LOAD_STATE_0_STATE_SRC(SS_DIRECT) |
CP_LOAD_STATE_0_STATE_BLOCK(SB_FRAG_MIPADDR) |
CP_LOAD_STATE_0_NUM_UNIT(BASETABLE_SZ * bufs));
OUT_RING(ring, CP_LOAD_STATE_1_STATE_TYPE(ST_CONSTANTS) |
CP_LOAD_STATE_1_EXT_SRC_ADDR(0));
for (i = 0; i < bufs; i++) {
if (psurf[i]) {
struct fd_resource *rsc = fd_resource(psurf[i]->texture);
/* Matches above logic for blit_zs shader */
if (rsc->stencil && i == 0)
rsc = rsc->stencil;
unsigned lvl = psurf[i]->u.tex.level;
uint32_t offset = fd_resource_offset(rsc, lvl, psurf[i]->u.tex.first_layer);
OUT_RELOC(ring, rsc->bo, offset, 0, 0);
} else {
OUT_RING(ring, 0x00000000);
}
 
/* pad the remaining entries w/ null: */
for (j = 1; j < BASETABLE_SZ; j++) {
OUT_RING(ring, 0x00000000);
}
}
}
 
void
fd3_emit_vertex_bufs(struct fd_ringbuffer *ring, struct fd3_emit *emit)
{
int32_t i, j, last = -1;
uint32_t total_in = 0;
const struct fd_vertex_state *vtx = emit->vtx;
struct ir3_shader_variant *vp = fd3_emit_get_vp(emit);
unsigned vertex_regid = regid(63, 0), instance_regid = regid(63, 0);
 
for (i = 0; i < vp->inputs_count; i++) {
uint8_t semantic = sem2name(vp->inputs[i].semantic);
if (semantic == TGSI_SEMANTIC_VERTEXID_NOBASE)
vertex_regid = vp->inputs[i].regid;
else if (semantic == TGSI_SEMANTIC_INSTANCEID)
instance_regid = vp->inputs[i].regid;
else if (i < vtx->vtx->num_elements && vp->inputs[i].compmask)
last = i;
}
 
/* hw doesn't like to be configured for zero vbo's, it seems: */
if (vtx->vtx->num_elements == 0 &&
vertex_regid == regid(63, 0) &&
instance_regid == regid(63, 0))
return;
 
for (i = 0, j = 0; i <= last; i++) {
assert(sem2name(vp->inputs[i].semantic) == 0);
if (vp->inputs[i].compmask) {
struct pipe_vertex_element *elem = &vtx->vtx->pipe[i];
const struct pipe_vertex_buffer *vb =
&vtx->vertexbuf.vb[elem->vertex_buffer_index];
struct fd_resource *rsc = fd_resource(vb->buffer);
enum pipe_format pfmt = elem->src_format;
enum a3xx_vtx_fmt fmt = fd3_pipe2vtx(pfmt);
bool switchnext = (i != last) ||
vertex_regid != regid(63, 0) ||
instance_regid != regid(63, 0);
bool isint = util_format_is_pure_integer(pfmt);
uint32_t fs = util_format_get_blocksize(pfmt);
 
debug_assert(fmt != ~0);
 
OUT_PKT0(ring, REG_A3XX_VFD_FETCH(j), 2);
OUT_RING(ring, A3XX_VFD_FETCH_INSTR_0_FETCHSIZE(fs - 1) |
A3XX_VFD_FETCH_INSTR_0_BUFSTRIDE(vb->stride) |
COND(switchnext, A3XX_VFD_FETCH_INSTR_0_SWITCHNEXT) |
A3XX_VFD_FETCH_INSTR_0_INDEXCODE(j) |
COND(elem->instance_divisor, A3XX_VFD_FETCH_INSTR_0_INSTANCED) |
A3XX_VFD_FETCH_INSTR_0_STEPRATE(MAX2(1, elem->instance_divisor)));
OUT_RELOC(ring, rsc->bo, vb->buffer_offset + elem->src_offset, 0, 0);
 
OUT_PKT0(ring, REG_A3XX_VFD_DECODE_INSTR(j), 1);
OUT_RING(ring, A3XX_VFD_DECODE_INSTR_CONSTFILL |
A3XX_VFD_DECODE_INSTR_WRITEMASK(vp->inputs[i].compmask) |
A3XX_VFD_DECODE_INSTR_FORMAT(fmt) |
A3XX_VFD_DECODE_INSTR_SWAP(fd3_pipe2swap(pfmt)) |
A3XX_VFD_DECODE_INSTR_REGID(vp->inputs[i].regid) |
A3XX_VFD_DECODE_INSTR_SHIFTCNT(fs) |
A3XX_VFD_DECODE_INSTR_LASTCOMPVALID |
COND(isint, A3XX_VFD_DECODE_INSTR_INT) |
COND(switchnext, A3XX_VFD_DECODE_INSTR_SWITCHNEXT));
 
total_in += vp->inputs[i].ncomp;
j++;
}
}
 
OUT_PKT0(ring, REG_A3XX_VFD_CONTROL_0, 2);
OUT_RING(ring, A3XX_VFD_CONTROL_0_TOTALATTRTOVS(total_in) |
A3XX_VFD_CONTROL_0_PACKETSIZE(2) |
A3XX_VFD_CONTROL_0_STRMDECINSTRCNT(j) |
A3XX_VFD_CONTROL_0_STRMFETCHINSTRCNT(j));
OUT_RING(ring, A3XX_VFD_CONTROL_1_MAXSTORAGE(1) | // XXX
A3XX_VFD_CONTROL_1_REGID4VTX(vertex_regid) |
A3XX_VFD_CONTROL_1_REGID4INST(instance_regid));
}
 
void
fd3_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring,
struct fd3_emit *emit)
{
struct ir3_shader_variant *vp = fd3_emit_get_vp(emit);
struct ir3_shader_variant *fp = fd3_emit_get_fp(emit);
uint32_t dirty = emit->dirty;
 
emit_marker(ring, 5);
 
if (dirty & FD_DIRTY_SAMPLE_MASK) {
OUT_PKT0(ring, REG_A3XX_RB_MSAA_CONTROL, 1);
OUT_RING(ring, A3XX_RB_MSAA_CONTROL_DISABLE |
A3XX_RB_MSAA_CONTROL_SAMPLES(MSAA_ONE) |
A3XX_RB_MSAA_CONTROL_SAMPLE_MASK(ctx->sample_mask));
}
 
if ((dirty & (FD_DIRTY_ZSA | FD_DIRTY_PROG)) && !emit->key.binning_pass) {
uint32_t val = fd3_zsa_stateobj(ctx->zsa)->rb_render_control;
 
val |= COND(fp->frag_face, A3XX_RB_RENDER_CONTROL_FACENESS);
val |= COND(fp->frag_coord, A3XX_RB_RENDER_CONTROL_XCOORD |
A3XX_RB_RENDER_CONTROL_YCOORD |
A3XX_RB_RENDER_CONTROL_ZCOORD |
A3XX_RB_RENDER_CONTROL_WCOORD);
 
/* I suppose if we needed to (which I don't *think* we need
* to), we could emit this for binning pass too. But we
* would need to keep a different patch-list for binning
* vs render pass.
*/
 
OUT_PKT0(ring, REG_A3XX_RB_RENDER_CONTROL, 1);
OUT_RINGP(ring, val, &fd3_context(ctx)->rbrc_patches);
}
 
if (dirty & (FD_DIRTY_ZSA | FD_DIRTY_STENCIL_REF)) {
struct fd3_zsa_stateobj *zsa = fd3_zsa_stateobj(ctx->zsa);
struct pipe_stencil_ref *sr = &ctx->stencil_ref;
 
OUT_PKT0(ring, REG_A3XX_RB_ALPHA_REF, 1);
OUT_RING(ring, zsa->rb_alpha_ref);
 
OUT_PKT0(ring, REG_A3XX_RB_STENCIL_CONTROL, 1);
OUT_RING(ring, zsa->rb_stencil_control);
 
OUT_PKT0(ring, REG_A3XX_RB_STENCILREFMASK, 2);
OUT_RING(ring, zsa->rb_stencilrefmask |
A3XX_RB_STENCILREFMASK_STENCILREF(sr->ref_value[0]));
OUT_RING(ring, zsa->rb_stencilrefmask_bf |
A3XX_RB_STENCILREFMASK_BF_STENCILREF(sr->ref_value[1]));
}
 
if (dirty & (FD_DIRTY_ZSA | FD_DIRTY_PROG)) {
uint32_t val = fd3_zsa_stateobj(ctx->zsa)->rb_depth_control;
if (fp->writes_pos) {
val |= A3XX_RB_DEPTH_CONTROL_FRAG_WRITES_Z;
val |= A3XX_RB_DEPTH_CONTROL_EARLY_Z_DISABLE;
}
if (fp->has_kill) {
val |= A3XX_RB_DEPTH_CONTROL_EARLY_Z_DISABLE;
}
OUT_PKT0(ring, REG_A3XX_RB_DEPTH_CONTROL, 1);
OUT_RING(ring, val);
}
 
if (dirty & FD_DIRTY_RASTERIZER) {
struct fd3_rasterizer_stateobj *rasterizer =
fd3_rasterizer_stateobj(ctx->rasterizer);
 
OUT_PKT0(ring, REG_A3XX_GRAS_SU_MODE_CONTROL, 1);
OUT_RING(ring, rasterizer->gras_su_mode_control);
 
OUT_PKT0(ring, REG_A3XX_GRAS_SU_POINT_MINMAX, 2);
OUT_RING(ring, rasterizer->gras_su_point_minmax);
OUT_RING(ring, rasterizer->gras_su_point_size);
 
OUT_PKT0(ring, REG_A3XX_GRAS_SU_POLY_OFFSET_SCALE, 2);
OUT_RING(ring, rasterizer->gras_su_poly_offset_scale);
OUT_RING(ring, rasterizer->gras_su_poly_offset_offset);
}
 
if (dirty & (FD_DIRTY_RASTERIZER | FD_DIRTY_PROG)) {
uint32_t val = fd3_rasterizer_stateobj(ctx->rasterizer)
->gras_cl_clip_cntl;
val |= COND(fp->writes_pos, A3XX_GRAS_CL_CLIP_CNTL_ZCLIP_DISABLE);
val |= COND(fp->frag_coord, A3XX_GRAS_CL_CLIP_CNTL_ZCOORD |
A3XX_GRAS_CL_CLIP_CNTL_WCOORD);
OUT_PKT0(ring, REG_A3XX_GRAS_CL_CLIP_CNTL, 1);
OUT_RING(ring, val);
}
 
/* NOTE: since primitive_restart is not actually part of any
* state object, we need to make sure that we always emit
* PRIM_VTX_CNTL.. either that or be more clever and detect
* when it changes.
*/
if (emit->info) {
const struct pipe_draw_info *info = emit->info;
uint32_t val = fd3_rasterizer_stateobj(ctx->rasterizer)
->pc_prim_vtx_cntl;
 
if (!emit->key.binning_pass) {
uint32_t stride_in_vpc = align(fp->total_in, 4) / 4;
if (stride_in_vpc > 0)
stride_in_vpc = MAX2(stride_in_vpc, 2);
val |= A3XX_PC_PRIM_VTX_CNTL_STRIDE_IN_VPC(stride_in_vpc);
}
 
if (info->indexed && info->primitive_restart) {
val |= A3XX_PC_PRIM_VTX_CNTL_PRIMITIVE_RESTART;
}
 
val |= COND(vp->writes_psize, A3XX_PC_PRIM_VTX_CNTL_PSIZE);
 
OUT_PKT0(ring, REG_A3XX_PC_PRIM_VTX_CNTL, 1);
OUT_RING(ring, val);
}
 
if (dirty & FD_DIRTY_SCISSOR) {
struct pipe_scissor_state *scissor = fd_context_get_scissor(ctx);
 
OUT_PKT0(ring, REG_A3XX_GRAS_SC_WINDOW_SCISSOR_TL, 2);
OUT_RING(ring, A3XX_GRAS_SC_WINDOW_SCISSOR_TL_X(scissor->minx) |
A3XX_GRAS_SC_WINDOW_SCISSOR_TL_Y(scissor->miny));
OUT_RING(ring, A3XX_GRAS_SC_WINDOW_SCISSOR_BR_X(scissor->maxx - 1) |
A3XX_GRAS_SC_WINDOW_SCISSOR_BR_Y(scissor->maxy - 1));
 
ctx->max_scissor.minx = MIN2(ctx->max_scissor.minx, scissor->minx);
ctx->max_scissor.miny = MIN2(ctx->max_scissor.miny, scissor->miny);
ctx->max_scissor.maxx = MAX2(ctx->max_scissor.maxx, scissor->maxx);
ctx->max_scissor.maxy = MAX2(ctx->max_scissor.maxy, scissor->maxy);
}
 
if (dirty & FD_DIRTY_VIEWPORT) {
fd_wfi(ctx, ring);
OUT_PKT0(ring, REG_A3XX_GRAS_CL_VPORT_XOFFSET, 6);
OUT_RING(ring, A3XX_GRAS_CL_VPORT_XOFFSET(ctx->viewport.translate[0] - 0.5));
OUT_RING(ring, A3XX_GRAS_CL_VPORT_XSCALE(ctx->viewport.scale[0]));
OUT_RING(ring, A3XX_GRAS_CL_VPORT_YOFFSET(ctx->viewport.translate[1] - 0.5));
OUT_RING(ring, A3XX_GRAS_CL_VPORT_YSCALE(ctx->viewport.scale[1]));
OUT_RING(ring, A3XX_GRAS_CL_VPORT_ZOFFSET(ctx->viewport.translate[2]));
OUT_RING(ring, A3XX_GRAS_CL_VPORT_ZSCALE(ctx->viewport.scale[2]));
}
 
if (dirty & (FD_DIRTY_PROG | FD_DIRTY_FRAMEBUFFER)) {
struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
fd3_program_emit(ring, emit, pfb->nr_cbufs, pfb->cbufs);
}
 
/* TODO we should not need this or fd_wfi() before emit_constants():
*/
OUT_PKT3(ring, CP_EVENT_WRITE, 1);
OUT_RING(ring, HLSQ_FLUSH);
 
if ((dirty & (FD_DIRTY_PROG | FD_DIRTY_CONSTBUF)) &&
/* evil hack to deal sanely with clear path: */
(emit->prog == &ctx->prog)) {
fd_wfi(ctx, ring);
emit_constants(ring, SB_VERT_SHADER,
&ctx->constbuf[PIPE_SHADER_VERTEX],
vp, emit->prog->dirty & FD_SHADER_DIRTY_VP);
if (!emit->key.binning_pass) {
emit_constants(ring, SB_FRAG_SHADER,
&ctx->constbuf[PIPE_SHADER_FRAGMENT],
fp, emit->prog->dirty & FD_SHADER_DIRTY_FP);
}
}
 
/* emit driver params every time */
if (emit->info && emit->prog == &ctx->prog) {
uint32_t vertex_params[4] = {
emit->info->indexed ? emit->info->index_bias : emit->info->start,
0,
0,
0
};
if (vp->constlen >= vp->first_driver_param + 4) {
fd3_emit_constant(ring, SB_VERT_SHADER,
(vp->first_driver_param + 4) * 4,
0, 4, vertex_params, NULL);
}
}
 
if ((dirty & (FD_DIRTY_BLEND | FD_DIRTY_FRAMEBUFFER)) && ctx->blend) {
struct fd3_blend_stateobj *blend = fd3_blend_stateobj(ctx->blend);
uint32_t i;
 
for (i = 0; i < ARRAY_SIZE(blend->rb_mrt); i++) {
enum pipe_format format = pipe_surface_format(ctx->framebuffer.cbufs[i]);
const struct util_format_description *desc =
util_format_description(format);
bool is_float = util_format_is_float(format);
bool is_int = util_format_is_pure_integer(format);
bool has_alpha = util_format_has_alpha(format);
uint32_t control = blend->rb_mrt[i].control;
uint32_t blend_control = blend->rb_mrt[i].blend_control_alpha;
 
if (is_int) {
control &= (A3XX_RB_MRT_CONTROL_COMPONENT_ENABLE__MASK |
A3XX_RB_MRT_CONTROL_DITHER_MODE__MASK);
control |= A3XX_RB_MRT_CONTROL_ROP_CODE(ROP_COPY);
}
 
if (format == PIPE_FORMAT_NONE)
control &= ~A3XX_RB_MRT_CONTROL_COMPONENT_ENABLE__MASK;
 
if (has_alpha) {
blend_control |= blend->rb_mrt[i].blend_control_rgb;
} else {
blend_control |= blend->rb_mrt[i].blend_control_no_alpha_rgb;
control &= ~A3XX_RB_MRT_CONTROL_BLEND2;
}
 
if (format && util_format_get_component_bits(
format, UTIL_FORMAT_COLORSPACE_RGB, 0) < 8) {
const struct pipe_rt_blend_state *rt;
if (ctx->blend->independent_blend_enable)
rt = &ctx->blend->rt[i];
else
rt = &ctx->blend->rt[0];
 
if (!util_format_colormask_full(desc, rt->colormask))
control |= A3XX_RB_MRT_CONTROL_READ_DEST_ENABLE;
}
 
OUT_PKT0(ring, REG_A3XX_RB_MRT_CONTROL(i), 1);
OUT_RING(ring, control);
 
OUT_PKT0(ring, REG_A3XX_RB_MRT_BLEND_CONTROL(i), 1);
OUT_RING(ring, blend_control |
COND(!is_float, A3XX_RB_MRT_BLEND_CONTROL_CLAMP_ENABLE));
}
}
 
if (dirty & FD_DIRTY_BLEND_COLOR) {
struct pipe_blend_color *bcolor = &ctx->blend_color;
OUT_PKT0(ring, REG_A3XX_RB_BLEND_RED, 4);
OUT_RING(ring, A3XX_RB_BLEND_RED_UINT(bcolor->color[0] * 255.0) |
A3XX_RB_BLEND_RED_FLOAT(bcolor->color[0]));
OUT_RING(ring, A3XX_RB_BLEND_GREEN_UINT(bcolor->color[1] * 255.0) |
A3XX_RB_BLEND_GREEN_FLOAT(bcolor->color[1]));
OUT_RING(ring, A3XX_RB_BLEND_BLUE_UINT(bcolor->color[2] * 255.0) |
A3XX_RB_BLEND_BLUE_FLOAT(bcolor->color[2]));
OUT_RING(ring, A3XX_RB_BLEND_ALPHA_UINT(bcolor->color[3] * 255.0) |
A3XX_RB_BLEND_ALPHA_FLOAT(bcolor->color[3]));
}
 
if (dirty & (FD_DIRTY_VERTTEX | FD_DIRTY_FRAGTEX))
fd_wfi(ctx, ring);
 
if (dirty & FD_DIRTY_VERTTEX) {
if (vp->has_samp)
emit_textures(ctx, ring, SB_VERT_TEX, &ctx->verttex);
else
dirty &= ~FD_DIRTY_VERTTEX;
}
 
if (dirty & FD_DIRTY_FRAGTEX) {
if (fp->has_samp)
emit_textures(ctx, ring, SB_FRAG_TEX, &ctx->fragtex);
else
dirty &= ~FD_DIRTY_FRAGTEX;
}
 
ctx->dirty &= ~dirty;
}
 
/* emit setup at begin of new cmdstream buffer (don't rely on previous
* state, there could have been a context switch between ioctls):
*/
void
fd3_emit_restore(struct fd_context *ctx)
{
struct fd3_context *fd3_ctx = fd3_context(ctx);
struct fd_ringbuffer *ring = ctx->ring;
int i;
 
if (ctx->screen->gpu_id == 320) {
OUT_PKT3(ring, CP_REG_RMW, 3);
OUT_RING(ring, REG_A3XX_RBBM_CLOCK_CTL);
OUT_RING(ring, 0xfffcffff);
OUT_RING(ring, 0x00000000);
}
 
fd_wfi(ctx, ring);
OUT_PKT3(ring, CP_INVALIDATE_STATE, 1);
OUT_RING(ring, 0x00007fff);
 
OUT_PKT0(ring, REG_A3XX_SP_VS_PVT_MEM_PARAM_REG, 3);
OUT_RING(ring, 0x08000001); /* SP_VS_PVT_MEM_CTRL_REG */
OUT_RELOC(ring, fd3_ctx->vs_pvt_mem, 0,0,0); /* SP_VS_PVT_MEM_ADDR_REG */
OUT_RING(ring, 0x00000000); /* SP_VS_PVT_MEM_SIZE_REG */
 
OUT_PKT0(ring, REG_A3XX_SP_FS_PVT_MEM_PARAM_REG, 3);
OUT_RING(ring, 0x08000001); /* SP_FS_PVT_MEM_CTRL_REG */
OUT_RELOC(ring, fd3_ctx->fs_pvt_mem, 0,0,0); /* SP_FS_PVT_MEM_ADDR_REG */
OUT_RING(ring, 0x00000000); /* SP_FS_PVT_MEM_SIZE_REG */
 
OUT_PKT0(ring, REG_A3XX_PC_VERTEX_REUSE_BLOCK_CNTL, 1);
OUT_RING(ring, 0x0000000b); /* PC_VERTEX_REUSE_BLOCK_CNTL */
 
OUT_PKT0(ring, REG_A3XX_GRAS_SC_CONTROL, 1);
OUT_RING(ring, A3XX_GRAS_SC_CONTROL_RENDER_MODE(RB_RENDERING_PASS) |
A3XX_GRAS_SC_CONTROL_MSAA_SAMPLES(MSAA_ONE) |
A3XX_GRAS_SC_CONTROL_RASTER_MODE(0));
 
OUT_PKT0(ring, REG_A3XX_RB_MSAA_CONTROL, 2);
OUT_RING(ring, A3XX_RB_MSAA_CONTROL_DISABLE |
A3XX_RB_MSAA_CONTROL_SAMPLES(MSAA_ONE) |
A3XX_RB_MSAA_CONTROL_SAMPLE_MASK(0xffff));
OUT_RING(ring, 0x00000000); /* RB_ALPHA_REF */
 
OUT_PKT0(ring, REG_A3XX_GRAS_CL_GB_CLIP_ADJ, 1);
OUT_RING(ring, A3XX_GRAS_CL_GB_CLIP_ADJ_HORZ(0) |
A3XX_GRAS_CL_GB_CLIP_ADJ_VERT(0));
 
OUT_PKT0(ring, REG_A3XX_GRAS_TSE_DEBUG_ECO, 1);
OUT_RING(ring, 0x00000001); /* GRAS_TSE_DEBUG_ECO */
 
OUT_PKT0(ring, REG_A3XX_TPL1_TP_VS_TEX_OFFSET, 1);
OUT_RING(ring, A3XX_TPL1_TP_VS_TEX_OFFSET_SAMPLEROFFSET(VERT_TEX_OFF) |
A3XX_TPL1_TP_VS_TEX_OFFSET_MEMOBJOFFSET(VERT_TEX_OFF) |
A3XX_TPL1_TP_VS_TEX_OFFSET_BASETABLEPTR(BASETABLE_SZ * VERT_TEX_OFF));
 
OUT_PKT0(ring, REG_A3XX_TPL1_TP_FS_TEX_OFFSET, 1);
OUT_RING(ring, A3XX_TPL1_TP_FS_TEX_OFFSET_SAMPLEROFFSET(FRAG_TEX_OFF) |
A3XX_TPL1_TP_FS_TEX_OFFSET_MEMOBJOFFSET(FRAG_TEX_OFF) |
A3XX_TPL1_TP_FS_TEX_OFFSET_BASETABLEPTR(BASETABLE_SZ * FRAG_TEX_OFF));
 
OUT_PKT0(ring, REG_A3XX_VPC_VARY_CYLWRAP_ENABLE_0, 2);
OUT_RING(ring, 0x00000000); /* VPC_VARY_CYLWRAP_ENABLE_0 */
OUT_RING(ring, 0x00000000); /* VPC_VARY_CYLWRAP_ENABLE_1 */
 
OUT_PKT0(ring, REG_A3XX_UNKNOWN_0E43, 1);
OUT_RING(ring, 0x00000001); /* UNKNOWN_0E43 */
 
OUT_PKT0(ring, REG_A3XX_UNKNOWN_0F03, 1);
OUT_RING(ring, 0x00000001); /* UNKNOWN_0F03 */
 
OUT_PKT0(ring, REG_A3XX_UNKNOWN_0EE0, 1);
OUT_RING(ring, 0x00000003); /* UNKNOWN_0EE0 */
 
OUT_PKT0(ring, REG_A3XX_UNKNOWN_0C3D, 1);
OUT_RING(ring, 0x00000001); /* UNKNOWN_0C3D */
 
OUT_PKT0(ring, REG_A3XX_HLSQ_PERFCOUNTER0_SELECT, 1);
OUT_RING(ring, 0x00000000); /* HLSQ_PERFCOUNTER0_SELECT */
 
OUT_PKT0(ring, REG_A3XX_HLSQ_CONST_VSPRESV_RANGE_REG, 2);
OUT_RING(ring, A3XX_HLSQ_CONST_VSPRESV_RANGE_REG_STARTENTRY(0) |
A3XX_HLSQ_CONST_VSPRESV_RANGE_REG_ENDENTRY(0));
OUT_RING(ring, A3XX_HLSQ_CONST_FSPRESV_RANGE_REG_STARTENTRY(0) |
A3XX_HLSQ_CONST_FSPRESV_RANGE_REG_ENDENTRY(0));
 
OUT_PKT0(ring, REG_A3XX_UCHE_CACHE_INVALIDATE0_REG, 2);
OUT_RING(ring, A3XX_UCHE_CACHE_INVALIDATE0_REG_ADDR(0));
OUT_RING(ring, A3XX_UCHE_CACHE_INVALIDATE1_REG_ADDR(0) |
A3XX_UCHE_CACHE_INVALIDATE1_REG_OPCODE(INVALIDATE) |
A3XX_UCHE_CACHE_INVALIDATE1_REG_ENTIRE_CACHE);
 
OUT_PKT0(ring, REG_A3XX_GRAS_CL_CLIP_CNTL, 1);
OUT_RING(ring, 0x00000000); /* GRAS_CL_CLIP_CNTL */
 
OUT_PKT0(ring, REG_A3XX_GRAS_SU_POINT_MINMAX, 2);
OUT_RING(ring, 0xffc00010); /* GRAS_SU_POINT_MINMAX */
OUT_RING(ring, 0x00000008); /* GRAS_SU_POINT_SIZE */
 
OUT_PKT0(ring, REG_A3XX_PC_RESTART_INDEX, 1);
OUT_RING(ring, 0xffffffff); /* PC_RESTART_INDEX */
 
OUT_PKT0(ring, REG_A3XX_RB_WINDOW_OFFSET, 1);
OUT_RING(ring, A3XX_RB_WINDOW_OFFSET_X(0) |
A3XX_RB_WINDOW_OFFSET_Y(0));
 
OUT_PKT0(ring, REG_A3XX_RB_BLEND_RED, 4);
OUT_RING(ring, A3XX_RB_BLEND_RED_UINT(0) |
A3XX_RB_BLEND_RED_FLOAT(0.0));
OUT_RING(ring, A3XX_RB_BLEND_GREEN_UINT(0) |
A3XX_RB_BLEND_GREEN_FLOAT(0.0));
OUT_RING(ring, A3XX_RB_BLEND_BLUE_UINT(0) |
A3XX_RB_BLEND_BLUE_FLOAT(0.0));
OUT_RING(ring, A3XX_RB_BLEND_ALPHA_UINT(0xff) |
A3XX_RB_BLEND_ALPHA_FLOAT(1.0));
 
for (i = 0; i < 6; i++) {
OUT_PKT0(ring, REG_A3XX_GRAS_CL_USER_PLANE(i), 4);
OUT_RING(ring, 0x00000000); /* GRAS_CL_USER_PLANE[i].X */
OUT_RING(ring, 0x00000000); /* GRAS_CL_USER_PLANE[i].Y */
OUT_RING(ring, 0x00000000); /* GRAS_CL_USER_PLANE[i].Z */
OUT_RING(ring, 0x00000000); /* GRAS_CL_USER_PLANE[i].W */
}
 
OUT_PKT0(ring, REG_A3XX_PC_VSTREAM_CONTROL, 1);
OUT_RING(ring, 0x00000000);
 
fd_event_write(ctx, ring, CACHE_FLUSH);
 
if (is_a3xx_p0(ctx->screen)) {
OUT_PKT3(ring, CP_DRAW_INDX, 3);
OUT_RING(ring, 0x00000000);
OUT_RING(ring, DRAW(1, DI_SRC_SEL_AUTO_INDEX,
INDEX_SIZE_IGN, IGNORE_VISIBILITY, 0));
OUT_RING(ring, 0); /* NumIndices */
}
 
OUT_PKT3(ring, CP_NOP, 4);
OUT_RING(ring, 0x00000000);
OUT_RING(ring, 0x00000000);
OUT_RING(ring, 0x00000000);
OUT_RING(ring, 0x00000000);
 
fd_wfi(ctx, ring);
 
ctx->needs_rb_fbd = true;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a3xx/fd3_emit.h
0,0 → 1,93
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FD3_EMIT_H
#define FD3_EMIT_H
 
#include "pipe/p_context.h"
 
#include "freedreno_context.h"
#include "fd3_format.h"
#include "fd3_program.h"
#include "ir3_shader.h"
 
struct fd_ringbuffer;
enum adreno_state_block;
 
void fd3_emit_constant(struct fd_ringbuffer *ring,
enum adreno_state_block sb,
uint32_t regid, uint32_t offset, uint32_t sizedwords,
const uint32_t *dwords, struct pipe_resource *prsc);
 
void fd3_emit_gmem_restore_tex(struct fd_ringbuffer *ring,
struct pipe_surface **psurf, int bufs);
 
/* grouped together emit-state for prog/vertex/state emit: */
struct fd3_emit {
const struct fd_vertex_state *vtx;
const struct fd_program_stateobj *prog;
const struct pipe_draw_info *info;
struct ir3_shader_key key;
uint32_t dirty;
 
uint32_t sprite_coord_enable;
bool sprite_coord_mode;
bool rasterflat;
 
/* cached to avoid repeated lookups of same variants: */
struct ir3_shader_variant *vp, *fp;
};
 
static inline struct ir3_shader_variant *
fd3_emit_get_vp(struct fd3_emit *emit)
{
if (!emit->vp) {
struct fd3_shader_stateobj *so = emit->prog->vp;
emit->vp = ir3_shader_variant(so->shader, emit->key);
}
return emit->vp;
}
 
static inline struct ir3_shader_variant *
fd3_emit_get_fp(struct fd3_emit *emit)
{
if (!emit->fp) {
struct fd3_shader_stateobj *so = emit->prog->fp;
emit->fp = ir3_shader_variant(so->shader, emit->key);
}
return emit->fp;
}
 
void fd3_emit_vertex_bufs(struct fd_ringbuffer *ring, struct fd3_emit *emit);
 
void fd3_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring,
struct fd3_emit *emit);
 
void fd3_emit_restore(struct fd_context *ctx);
 
#endif /* FD3_EMIT_H */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a3xx/fd3_format.c
0,0 → 1,384
/*
* Copyright (C) 2013 Rob Clark <robclark@freedesktop.org>
*
* 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 "pipe/p_defines.h"
#include "util/u_format.h"
 
#include "fd3_format.h"
 
/* Specifies the table of all the formats and their features. Also supplies
* the helpers that look up various data in those tables.
*/
 
struct fd3_format {
enum a3xx_vtx_fmt vtx;
enum a3xx_tex_fmt tex;
enum a3xx_color_fmt rb;
enum a3xx_color_swap swap;
boolean present;
};
 
#define RB_NONE ~0
 
/* vertex + texture */
#define VT(pipe, fmt, rbfmt, swapfmt) \
[PIPE_FORMAT_ ## pipe] = { \
.present = 1, \
.vtx = VFMT_ ## fmt, \
.tex = TFMT_ ## fmt, \
.rb = RB_ ## rbfmt, \
.swap = swapfmt \
}
 
/* texture-only */
#define _T(pipe, fmt, rbfmt, swapfmt) \
[PIPE_FORMAT_ ## pipe] = { \
.present = 1, \
.vtx = ~0, \
.tex = TFMT_ ## fmt, \
.rb = RB_ ## rbfmt, \
.swap = swapfmt \
}
 
/* vertex-only */
#define V_(pipe, fmt, rbfmt, swapfmt) \
[PIPE_FORMAT_ ## pipe] = { \
.present = 1, \
.vtx = VFMT_ ## fmt, \
.tex = ~0, \
.rb = RB_ ## rbfmt, \
.swap = swapfmt \
}
 
static struct fd3_format formats[PIPE_FORMAT_COUNT] = {
/* 8-bit */
VT(R8_UNORM, 8_UNORM, R8_UNORM, WZYX),
VT(R8_SNORM, 8_SNORM, NONE, WZYX),
VT(R8_UINT, 8_UINT, R8_UINT, WZYX),
VT(R8_SINT, 8_SINT, R8_SINT, WZYX),
V_(R8_USCALED, 8_UINT, NONE, WZYX),
V_(R8_SSCALED, 8_UINT, NONE, WZYX),
 
_T(A8_UNORM, 8_UNORM, A8_UNORM, WZYX),
_T(L8_UNORM, 8_UNORM, R8_UNORM, WZYX),
_T(I8_UNORM, 8_UNORM, NONE, WZYX),
 
_T(A8_UINT, 8_UINT, NONE, WZYX),
_T(A8_SINT, 8_SINT, NONE, WZYX),
_T(L8_UINT, 8_UINT, NONE, WZYX),
_T(L8_SINT, 8_SINT, NONE, WZYX),
_T(I8_UINT, 8_UINT, NONE, WZYX),
_T(I8_SINT, 8_SINT, NONE, WZYX),
 
_T(S8_UINT, 8_UINT, R8_UNORM, WZYX),
 
/* 16-bit */
VT(R16_UNORM, 16_UNORM, NONE, WZYX),
VT(R16_SNORM, 16_SNORM, NONE, WZYX),
VT(R16_UINT, 16_UINT, R16_UINT, WZYX),
VT(R16_SINT, 16_SINT, R16_SINT, WZYX),
V_(R16_USCALED, 16_UINT, NONE, WZYX),
V_(R16_SSCALED, 16_UINT, NONE, WZYX),
VT(R16_FLOAT, 16_FLOAT, R16_FLOAT,WZYX),
 
_T(A16_UINT, 16_UINT, NONE, WZYX),
_T(A16_SINT, 16_SINT, NONE, WZYX),
_T(L16_UINT, 16_UINT, NONE, WZYX),
_T(L16_SINT, 16_SINT, NONE, WZYX),
_T(I16_UINT, 16_UINT, NONE, WZYX),
_T(I16_SINT, 16_SINT, NONE, WZYX),
 
VT(R8G8_UNORM, 8_8_UNORM, R8G8_UNORM, WZYX),
VT(R8G8_SNORM, 8_8_SNORM, R8G8_SNORM, WZYX),
VT(R8G8_UINT, 8_8_UINT, NONE, WZYX),
VT(R8G8_SINT, 8_8_SINT, NONE, WZYX),
V_(R8G8_USCALED, 8_8_UINT, NONE, WZYX),
V_(R8G8_SSCALED, 8_8_SINT, NONE, WZYX),
 
_T(L8A8_UINT, 8_8_UINT, NONE, WZYX),
_T(L8A8_SINT, 8_8_SINT, NONE, WZYX),
 
_T(Z16_UNORM, Z16_UNORM, R8G8_UNORM, WZYX),
_T(B5G6R5_UNORM, 5_6_5_UNORM, R5G6B5_UNORM, WXYZ),
_T(B5G5R5A1_UNORM, 5_5_5_1_UNORM, R5G5B5A1_UNORM, WXYZ),
_T(B5G5R5X1_UNORM, 5_5_5_1_UNORM, R5G5B5A1_UNORM, WXYZ),
_T(B4G4R4A4_UNORM, 4_4_4_4_UNORM, R4G4B4A4_UNORM, WXYZ),
 
/* 24-bit */
V_(R8G8B8_UNORM, 8_8_8_UNORM, NONE, WZYX),
V_(R8G8B8_SNORM, 8_8_8_SNORM, NONE, WZYX),
V_(R8G8B8_UINT, 8_8_8_UINT, NONE, WZYX),
V_(R8G8B8_SINT, 8_8_8_SINT, NONE, WZYX),
V_(R8G8B8_USCALED, 8_8_8_UINT, NONE, WZYX),
V_(R8G8B8_SSCALED, 8_8_8_SINT, NONE, WZYX),
 
/* 32-bit */
VT(R32_UINT, 32_UINT, R32_UINT, WZYX),
VT(R32_SINT, 32_SINT, R32_SINT, WZYX),
V_(R32_USCALED, 32_UINT, NONE, WZYX),
V_(R32_SSCALED, 32_UINT, NONE, WZYX),
VT(R32_FLOAT, 32_FLOAT, R32_FLOAT,WZYX),
V_(R32_FIXED, 32_FIXED, NONE, WZYX),
 
_T(A32_UINT, 32_UINT, NONE, WZYX),
_T(A32_SINT, 32_SINT, NONE, WZYX),
_T(L32_UINT, 32_UINT, NONE, WZYX),
_T(L32_SINT, 32_SINT, NONE, WZYX),
_T(I32_UINT, 32_UINT, NONE, WZYX),
_T(I32_SINT, 32_SINT, NONE, WZYX),
 
VT(R16G16_UNORM, 16_16_UNORM, NONE, WZYX),
VT(R16G16_SNORM, 16_16_SNORM, NONE, WZYX),
VT(R16G16_UINT, 16_16_UINT, R16G16_UINT, WZYX),
VT(R16G16_SINT, 16_16_SINT, R16G16_SINT, WZYX),
V_(R16G16_USCALED, 16_16_UINT, NONE, WZYX),
V_(R16G16_SSCALED, 16_16_SINT, NONE, WZYX),
VT(R16G16_FLOAT, 16_16_FLOAT, R16G16_FLOAT,WZYX),
 
_T(L16A16_UINT, 16_16_UINT, NONE, WZYX),
_T(L16A16_SINT, 16_16_SINT, NONE, WZYX),
 
VT(R8G8B8A8_UNORM, 8_8_8_8_UNORM, R8G8B8A8_UNORM, WZYX),
_T(R8G8B8X8_UNORM, 8_8_8_8_UNORM, R8G8B8A8_UNORM, WZYX),
_T(R8G8B8A8_SRGB, 8_8_8_8_UNORM, R8G8B8A8_UNORM, WZYX),
_T(R8G8B8X8_SRGB, 8_8_8_8_UNORM, R8G8B8A8_UNORM, WZYX),
VT(R8G8B8A8_SNORM, 8_8_8_8_SNORM, R8G8B8A8_SNORM, WZYX),
VT(R8G8B8A8_UINT, 8_8_8_8_UINT, R8G8B8A8_UINT, WZYX),
VT(R8G8B8A8_SINT, 8_8_8_8_SINT, R8G8B8A8_SINT, WZYX),
V_(R8G8B8A8_USCALED, 8_8_8_8_UINT, NONE, WZYX),
V_(R8G8B8A8_SSCALED, 8_8_8_8_SINT, NONE, WZYX),
 
VT(B8G8R8A8_UNORM, 8_8_8_8_UNORM, R8G8B8A8_UNORM, WXYZ),
_T(B8G8R8X8_UNORM, 8_8_8_8_UNORM, R8G8B8A8_UNORM, WXYZ),
VT(B8G8R8A8_SRGB, 8_8_8_8_UNORM, R8G8B8A8_UNORM, WXYZ),
_T(B8G8R8X8_SRGB, 8_8_8_8_UNORM, R8G8B8A8_UNORM, WXYZ),
 
VT(A8B8G8R8_UNORM, 8_8_8_8_UNORM, R8G8B8A8_UNORM, XYZW),
_T(X8B8G8R8_UNORM, 8_8_8_8_UNORM, R8G8B8A8_UNORM, XYZW),
_T(A8B8G8R8_SRGB, 8_8_8_8_UNORM, R8G8B8A8_UNORM, XYZW),
_T(X8B8G8R8_SRGB, 8_8_8_8_UNORM, R8G8B8A8_UNORM, XYZW),
 
VT(A8R8G8B8_UNORM, 8_8_8_8_UNORM, R8G8B8A8_UNORM, ZYXW),
_T(X8R8G8B8_UNORM, 8_8_8_8_UNORM, R8G8B8A8_UNORM, ZYXW),
_T(A8R8G8B8_SRGB, 8_8_8_8_UNORM, R8G8B8A8_UNORM, ZYXW),
_T(X8R8G8B8_SRGB, 8_8_8_8_UNORM, R8G8B8A8_UNORM, ZYXW),
 
VT(R10G10B10A2_UNORM, 10_10_10_2_UNORM, R10G10B10A2_UNORM, WZYX),
VT(B10G10R10A2_UNORM, 10_10_10_2_UNORM, R10G10B10A2_UNORM, WXYZ),
_T(B10G10R10X2_UNORM, 10_10_10_2_UNORM, R10G10B10A2_UNORM, WXYZ),
V_(R10G10B10A2_SNORM, 10_10_10_2_SNORM, NONE, WZYX),
V_(R10G10B10A2_UINT, 10_10_10_2_UINT, NONE, WZYX),
V_(R10G10B10A2_USCALED, 10_10_10_2_UINT, NONE, WZYX),
V_(R10G10B10A2_SSCALED, 10_10_10_2_SINT, NONE, WZYX),
 
_T(R11G11B10_FLOAT, 11_11_10_FLOAT, R11G11B10_FLOAT, WZYX),
_T(R9G9B9E5_FLOAT, 9_9_9_E5_FLOAT, NONE, WZYX),
 
_T(Z24X8_UNORM, X8Z24_UNORM, R8G8B8A8_UNORM, WZYX),
_T(Z24_UNORM_S8_UINT, X8Z24_UNORM, R8G8B8A8_UNORM, WZYX),
_T(Z32_FLOAT, Z32_FLOAT, R8G8B8A8_UNORM, WZYX),
_T(Z32_FLOAT_S8X24_UINT, Z32_FLOAT,R8G8B8A8_UNORM, WZYX),
 
/* 48-bit */
V_(R16G16B16_UNORM, 16_16_16_UNORM, NONE, WZYX),
V_(R16G16B16_SNORM, 16_16_16_SNORM, NONE, WZYX),
V_(R16G16B16_UINT, 16_16_16_UINT, NONE, WZYX),
V_(R16G16B16_SINT, 16_16_16_SINT, NONE, WZYX),
V_(R16G16B16_USCALED, 16_16_16_UINT, NONE, WZYX),
V_(R16G16B16_SSCALED, 16_16_16_SINT, NONE, WZYX),
V_(R16G16B16_FLOAT, 16_16_16_FLOAT, NONE, WZYX),
 
/* 64-bit */
VT(R16G16B16A16_UNORM, 16_16_16_16_UNORM, NONE, WZYX),
VT(R16G16B16A16_SNORM, 16_16_16_16_SNORM, NONE, WZYX),
VT(R16G16B16A16_UINT, 16_16_16_16_UINT, R16G16B16A16_UINT, WZYX),
_T(R16G16B16X16_UINT, 16_16_16_16_UINT, R16G16B16A16_UINT, WZYX),
VT(R16G16B16A16_SINT, 16_16_16_16_SINT, R16G16B16A16_SINT, WZYX),
_T(R16G16B16X16_SINT, 16_16_16_16_SINT, R16G16B16A16_SINT, WZYX),
V_(R16G16B16A16_USCALED, 16_16_16_16_UINT, NONE, WZYX),
V_(R16G16B16A16_SSCALED, 16_16_16_16_SINT, NONE, WZYX),
VT(R16G16B16A16_FLOAT, 16_16_16_16_FLOAT, R16G16B16A16_FLOAT, WZYX),
_T(R16G16B16X16_FLOAT, 16_16_16_16_FLOAT, R16G16B16A16_FLOAT, WZYX),
 
VT(R32G32_UINT, 32_32_UINT, R32G32_UINT, WZYX),
VT(R32G32_SINT, 32_32_SINT, R32G32_SINT, WZYX),
V_(R32G32_USCALED, 32_32_UINT, NONE, WZYX),
V_(R32G32_SSCALED, 32_32_SINT, NONE, WZYX),
VT(R32G32_FLOAT, 32_32_FLOAT, R32G32_FLOAT,WZYX),
V_(R32G32_FIXED, 32_32_FIXED, NONE, WZYX),
 
_T(L32A32_UINT, 32_32_UINT, NONE, WZYX),
_T(L32A32_SINT, 32_32_SINT, NONE, WZYX),
 
/* 96-bit */
V_(R32G32B32_UINT, 32_32_32_UINT, NONE, WZYX),
V_(R32G32B32_SINT, 32_32_32_SINT, NONE, WZYX),
V_(R32G32B32_USCALED, 32_32_32_UINT, NONE, WZYX),
V_(R32G32B32_SSCALED, 32_32_32_SINT, NONE, WZYX),
V_(R32G32B32_FLOAT, 32_32_32_FLOAT, NONE, WZYX),
V_(R32G32B32_FIXED, 32_32_32_FIXED, NONE, WZYX),
 
/* 128-bit */
VT(R32G32B32A32_UINT, 32_32_32_32_UINT, R32G32B32A32_UINT, WZYX),
_T(R32G32B32X32_UINT, 32_32_32_32_UINT, R32G32B32A32_UINT, WZYX),
VT(R32G32B32A32_SINT, 32_32_32_32_SINT, R32G32B32A32_SINT, WZYX),
_T(R32G32B32X32_SINT, 32_32_32_32_SINT, R32G32B32A32_SINT, WZYX),
V_(R32G32B32A32_USCALED, 32_32_32_32_UINT, NONE, WZYX),
V_(R32G32B32A32_SSCALED, 32_32_32_32_SINT, NONE, WZYX),
VT(R32G32B32A32_FLOAT, 32_32_32_32_FLOAT, R32G32B32A32_FLOAT, WZYX),
_T(R32G32B32X32_FLOAT, 32_32_32_32_FLOAT, R32G32B32A32_FLOAT, WZYX),
V_(R32G32B32A32_FIXED, 32_32_32_32_FIXED, NONE, WZYX),
 
/* compressed */
_T(ETC1_RGB8, ETC1, NONE, WZYX),
_T(ETC2_RGB8, ETC2_RGB8, NONE, WZYX),
_T(ETC2_SRGB8, ETC2_RGB8, NONE, WZYX),
_T(ETC2_RGB8A1, ETC2_RGB8A1, NONE, WZYX),
_T(ETC2_SRGB8A1, ETC2_RGB8A1, NONE, WZYX),
_T(ETC2_RGBA8, ETC2_RGBA8, NONE, WZYX),
_T(ETC2_SRGBA8, ETC2_RGBA8, NONE, WZYX),
_T(ETC2_R11_UNORM, ETC2_R11_UNORM, NONE, WZYX),
_T(ETC2_R11_SNORM, ETC2_R11_SNORM, NONE, WZYX),
_T(ETC2_RG11_UNORM, ETC2_RG11_UNORM, NONE, WZYX),
_T(ETC2_RG11_SNORM, ETC2_RG11_SNORM, NONE, WZYX),
};
 
enum a3xx_vtx_fmt
fd3_pipe2vtx(enum pipe_format format)
{
if (!formats[format].present)
return ~0;
return formats[format].vtx;
}
 
enum a3xx_tex_fmt
fd3_pipe2tex(enum pipe_format format)
{
if (!formats[format].present)
return ~0;
return formats[format].tex;
}
 
enum a3xx_color_fmt
fd3_pipe2color(enum pipe_format format)
{
if (!formats[format].present)
return ~0;
return formats[format].rb;
}
 
enum a3xx_color_swap
fd3_pipe2swap(enum pipe_format format)
{
if (!formats[format].present)
return WZYX;
return formats[format].swap;
}
 
enum a3xx_tex_fetchsize
fd3_pipe2fetchsize(enum pipe_format format)
{
if (format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT)
format = PIPE_FORMAT_Z32_FLOAT;
switch (util_format_get_blocksizebits(format)) {
case 8: return TFETCH_1_BYTE;
case 16: return TFETCH_2_BYTE;
case 32: return TFETCH_4_BYTE;
case 64: return TFETCH_8_BYTE;
case 128: return TFETCH_16_BYTE;
default:
debug_printf("Unknown block size for format %s: %d\n",
util_format_name(format),
util_format_get_blocksizebits(format));
return TFETCH_DISABLE;
}
}
 
/* we need to special case a bit the depth/stencil restore, because we are
* using the texture sampler to blit into the depth/stencil buffer, *not*
* into a color buffer. Otherwise fd3_tex_swiz() will do the wrong thing,
* as it is assuming that you are sampling into normal render target..
*/
enum pipe_format
fd3_gmem_restore_format(enum pipe_format format)
{
switch (format) {
case PIPE_FORMAT_Z24X8_UNORM:
case PIPE_FORMAT_Z24_UNORM_S8_UINT:
return PIPE_FORMAT_R8G8B8A8_UNORM;
case PIPE_FORMAT_Z16_UNORM:
return PIPE_FORMAT_R8G8_UNORM;
case PIPE_FORMAT_S8_UINT:
return PIPE_FORMAT_R8_UNORM;
default:
return format;
}
}
 
enum a3xx_color_fmt
fd3_fs_output_format(enum pipe_format format)
{
if (util_format_is_srgb(format))
return RB_R16G16B16A16_FLOAT;
switch (format) {
case PIPE_FORMAT_R16_FLOAT:
case PIPE_FORMAT_R16G16_FLOAT:
case PIPE_FORMAT_R11G11B10_FLOAT:
return RB_R16G16B16A16_FLOAT;
default:
return fd3_pipe2color(format);
}
}
 
static inline enum a3xx_tex_swiz
tex_swiz(unsigned swiz)
{
switch (swiz) {
default:
case PIPE_SWIZZLE_RED: return A3XX_TEX_X;
case PIPE_SWIZZLE_GREEN: return A3XX_TEX_Y;
case PIPE_SWIZZLE_BLUE: return A3XX_TEX_Z;
case PIPE_SWIZZLE_ALPHA: return A3XX_TEX_W;
case PIPE_SWIZZLE_ZERO: return A3XX_TEX_ZERO;
case PIPE_SWIZZLE_ONE: return A3XX_TEX_ONE;
}
}
 
uint32_t
fd3_tex_swiz(enum pipe_format format, unsigned swizzle_r, unsigned swizzle_g,
unsigned swizzle_b, unsigned swizzle_a)
{
const struct util_format_description *desc =
util_format_description(format);
unsigned char swiz[4] = {
swizzle_r, swizzle_g, swizzle_b, swizzle_a,
}, rswiz[4];
 
util_format_compose_swizzles(desc->swizzle, swiz, rswiz);
 
return A3XX_TEX_CONST_0_SWIZ_X(tex_swiz(rswiz[0])) |
A3XX_TEX_CONST_0_SWIZ_Y(tex_swiz(rswiz[1])) |
A3XX_TEX_CONST_0_SWIZ_Z(tex_swiz(rswiz[2])) |
A3XX_TEX_CONST_0_SWIZ_W(tex_swiz(rswiz[3]));
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a3xx/fd3_format.h
0,0 → 1,67
/*
* Copyright (C) 2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
*/
 
#ifndef FD3_FORMAT_H_
#define FD3_FORMAT_H_
 
#include "util/u_format.h"
#include "freedreno_util.h"
 
#include "a3xx.xml.h"
 
enum a3xx_vtx_fmt fd3_pipe2vtx(enum pipe_format format);
enum a3xx_tex_fmt fd3_pipe2tex(enum pipe_format format);
enum a3xx_tex_fetchsize fd3_pipe2fetchsize(enum pipe_format format);
enum a3xx_color_fmt fd3_pipe2color(enum pipe_format format);
enum pipe_format fd3_gmem_restore_format(enum pipe_format format);
enum a3xx_color_fmt fd3_fs_output_format(enum pipe_format format);
enum a3xx_color_swap fd3_pipe2swap(enum pipe_format format);
 
uint32_t fd3_tex_swiz(enum pipe_format format, unsigned swizzle_r,
unsigned swizzle_g, unsigned swizzle_b, unsigned swizzle_a);
 
static INLINE bool
fd3_half_precision(const struct pipe_surface *surface)
{
enum pipe_format format;
if (!surface)
return true;
 
format = surface->format;
 
/* colors are provided in consts, which go through cov.f32f16, which will
* break these values
*/
if (util_format_is_pure_integer(format))
return false;
 
/* avoid losing precision on 32-bit float formats */
if (util_format_is_float(format) &&
util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 0) == 32)
return false;
 
return true;
}
 
#endif /* FD3_FORMAT_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a3xx/fd3_gmem.c
0,0 → 1,1057
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "pipe/p_state.h"
#include "util/u_string.h"
#include "util/u_memory.h"
#include "util/u_inlines.h"
#include "util/u_format.h"
 
#include "freedreno_draw.h"
#include "freedreno_state.h"
#include "freedreno_resource.h"
 
#include "fd3_gmem.h"
#include "fd3_context.h"
#include "fd3_emit.h"
#include "fd3_program.h"
#include "fd3_format.h"
#include "fd3_zsa.h"
 
static void
emit_mrt(struct fd_ringbuffer *ring, unsigned nr_bufs,
struct pipe_surface **bufs, uint32_t *bases, uint32_t bin_w,
bool decode_srgb)
{
enum a3xx_tile_mode tile_mode;
unsigned i;
 
if (bin_w) {
tile_mode = TILE_32X32;
} else {
tile_mode = LINEAR;
}
 
for (i = 0; i < 4; i++) {
enum pipe_format pformat = 0;
enum a3xx_color_fmt format = 0;
enum a3xx_color_swap swap = WZYX;
bool srgb = false;
struct fd_resource *rsc = NULL;
struct fd_resource_slice *slice = NULL;
uint32_t stride = 0;
uint32_t base = 0;
uint32_t offset = 0;
 
if ((i < nr_bufs) && bufs[i]) {
struct pipe_surface *psurf = bufs[i];
 
rsc = fd_resource(psurf->texture);
pformat = psurf->format;
/* In case we're drawing to Z32F_S8, the "color" actually goes to
* the stencil
*/
if (rsc->stencil) {
rsc = rsc->stencil;
pformat = rsc->base.b.format;
bases++;
}
slice = fd_resource_slice(rsc, psurf->u.tex.level);
format = fd3_pipe2color(pformat);
swap = fd3_pipe2swap(pformat);
if (decode_srgb)
srgb = util_format_is_srgb(pformat);
else
pformat = util_format_linear(pformat);
 
debug_assert(psurf->u.tex.first_layer == psurf->u.tex.last_layer);
 
offset = fd_resource_offset(rsc, psurf->u.tex.level,
psurf->u.tex.first_layer);
 
if (bin_w) {
stride = bin_w * rsc->cpp;
 
if (bases) {
base = bases[i];
}
} else {
stride = slice->pitch * rsc->cpp;
}
} else if (i < nr_bufs && bases) {
base = bases[i];
}
 
OUT_PKT0(ring, REG_A3XX_RB_MRT_BUF_INFO(i), 2);
OUT_RING(ring, A3XX_RB_MRT_BUF_INFO_COLOR_FORMAT(format) |
A3XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE(tile_mode) |
A3XX_RB_MRT_BUF_INFO_COLOR_BUF_PITCH(stride) |
A3XX_RB_MRT_BUF_INFO_COLOR_SWAP(swap) |
COND(srgb, A3XX_RB_MRT_BUF_INFO_COLOR_SRGB));
if (bin_w || (i >= nr_bufs) || !bufs[i]) {
OUT_RING(ring, A3XX_RB_MRT_BUF_BASE_COLOR_BUF_BASE(base));
} else {
OUT_RELOCW(ring, rsc->bo, offset, 0, -1);
}
 
OUT_PKT0(ring, REG_A3XX_SP_FS_IMAGE_OUTPUT_REG(i), 1);
OUT_RING(ring, COND((i < nr_bufs) && bufs[i],
A3XX_SP_FS_IMAGE_OUTPUT_REG_MRTFORMAT(
fd3_fs_output_format(pformat))));
}
}
 
static bool
use_hw_binning(struct fd_context *ctx)
{
struct fd_gmem_stateobj *gmem = &ctx->gmem;
 
/* workaround: combining scissor optimization and hw binning
* seems problematic. Seems like we end up with a mismatch
* between binning pass and rendering pass, wrt. where the hw
* thinks the vertices belong. And the blob driver doesn't
* seem to implement anything like scissor optimization, so
* not entirely sure what I might be missing.
*
* But scissor optimization is mainly for window managers,
* which don't have many vertices (and therefore doesn't
* benefit much from binning pass).
*
* So for now just disable binning if scissor optimization is
* used.
*/
if (gmem->minx || gmem->miny)
return false;
 
return fd_binning_enabled && ((gmem->nbins_x * gmem->nbins_y) > 2);
}
 
/* workaround for (hlsq?) lockup with hw binning on a3xx patchlevel 0 */
static void update_vsc_pipe(struct fd_context *ctx);
static void
emit_binning_workaround(struct fd_context *ctx)
{
struct fd3_context *fd3_ctx = fd3_context(ctx);
struct fd_gmem_stateobj *gmem = &ctx->gmem;
struct fd_ringbuffer *ring = ctx->ring;
struct fd3_emit emit = {
.vtx = &fd3_ctx->solid_vbuf_state,
.prog = &ctx->solid_prog,
.key = {
.half_precision = true,
},
};
 
OUT_PKT0(ring, REG_A3XX_RB_MODE_CONTROL, 2);
OUT_RING(ring, A3XX_RB_MODE_CONTROL_RENDER_MODE(RB_RESOLVE_PASS) |
A3XX_RB_MODE_CONTROL_MARB_CACHE_SPLIT_MODE |
A3XX_RB_MODE_CONTROL_MRT(0));
OUT_RING(ring, A3XX_RB_RENDER_CONTROL_BIN_WIDTH(32) |
A3XX_RB_RENDER_CONTROL_DISABLE_COLOR_PIPE |
A3XX_RB_RENDER_CONTROL_ALPHA_TEST_FUNC(FUNC_NEVER));
 
OUT_PKT0(ring, REG_A3XX_RB_COPY_CONTROL, 4);
OUT_RING(ring, A3XX_RB_COPY_CONTROL_MSAA_RESOLVE(MSAA_ONE) |
A3XX_RB_COPY_CONTROL_MODE(0) |
A3XX_RB_COPY_CONTROL_GMEM_BASE(0));
OUT_RELOCW(ring, fd_resource(fd3_ctx->solid_vbuf)->bo, 0x20, 0, -1); /* RB_COPY_DEST_BASE */
OUT_RING(ring, A3XX_RB_COPY_DEST_PITCH_PITCH(128));
OUT_RING(ring, A3XX_RB_COPY_DEST_INFO_TILE(LINEAR) |
A3XX_RB_COPY_DEST_INFO_FORMAT(RB_R8G8B8A8_UNORM) |
A3XX_RB_COPY_DEST_INFO_SWAP(WZYX) |
A3XX_RB_COPY_DEST_INFO_COMPONENT_ENABLE(0xf) |
A3XX_RB_COPY_DEST_INFO_ENDIAN(ENDIAN_NONE));
 
OUT_PKT0(ring, REG_A3XX_GRAS_SC_CONTROL, 1);
OUT_RING(ring, A3XX_GRAS_SC_CONTROL_RENDER_MODE(RB_RESOLVE_PASS) |
A3XX_GRAS_SC_CONTROL_MSAA_SAMPLES(MSAA_ONE) |
A3XX_GRAS_SC_CONTROL_RASTER_MODE(1));
 
fd3_program_emit(ring, &emit, 0, NULL);
fd3_emit_vertex_bufs(ring, &emit);
 
OUT_PKT0(ring, REG_A3XX_HLSQ_CONTROL_0_REG, 4);
OUT_RING(ring, A3XX_HLSQ_CONTROL_0_REG_FSTHREADSIZE(FOUR_QUADS) |
A3XX_HLSQ_CONTROL_0_REG_FSSUPERTHREADENABLE |
A3XX_HLSQ_CONTROL_0_REG_RESERVED2 |
A3XX_HLSQ_CONTROL_0_REG_SPCONSTFULLUPDATE);
OUT_RING(ring, A3XX_HLSQ_CONTROL_1_REG_VSTHREADSIZE(TWO_QUADS) |
A3XX_HLSQ_CONTROL_1_REG_VSSUPERTHREADENABLE);
OUT_RING(ring, A3XX_HLSQ_CONTROL_2_REG_PRIMALLOCTHRESHOLD(31));
OUT_RING(ring, 0); /* HLSQ_CONTROL_3_REG */
 
OUT_PKT0(ring, REG_A3XX_HLSQ_CONST_FSPRESV_RANGE_REG, 1);
OUT_RING(ring, A3XX_HLSQ_CONST_FSPRESV_RANGE_REG_STARTENTRY(0x20) |
A3XX_HLSQ_CONST_FSPRESV_RANGE_REG_ENDENTRY(0x20));
 
OUT_PKT0(ring, REG_A3XX_RB_MSAA_CONTROL, 1);
OUT_RING(ring, A3XX_RB_MSAA_CONTROL_DISABLE |
A3XX_RB_MSAA_CONTROL_SAMPLES(MSAA_ONE) |
A3XX_RB_MSAA_CONTROL_SAMPLE_MASK(0xffff));
 
OUT_PKT0(ring, REG_A3XX_RB_DEPTH_CONTROL, 1);
OUT_RING(ring, A3XX_RB_DEPTH_CONTROL_ZFUNC(FUNC_NEVER));
 
OUT_PKT0(ring, REG_A3XX_RB_STENCIL_CONTROL, 1);
OUT_RING(ring, A3XX_RB_STENCIL_CONTROL_FUNC(FUNC_NEVER) |
A3XX_RB_STENCIL_CONTROL_FAIL(STENCIL_KEEP) |
A3XX_RB_STENCIL_CONTROL_ZPASS(STENCIL_KEEP) |
A3XX_RB_STENCIL_CONTROL_ZFAIL(STENCIL_KEEP) |
A3XX_RB_STENCIL_CONTROL_FUNC_BF(FUNC_NEVER) |
A3XX_RB_STENCIL_CONTROL_FAIL_BF(STENCIL_KEEP) |
A3XX_RB_STENCIL_CONTROL_ZPASS_BF(STENCIL_KEEP) |
A3XX_RB_STENCIL_CONTROL_ZFAIL_BF(STENCIL_KEEP));
 
OUT_PKT0(ring, REG_A3XX_GRAS_SU_MODE_CONTROL, 1);
OUT_RING(ring, A3XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH(0.0));
 
OUT_PKT0(ring, REG_A3XX_VFD_INDEX_MIN, 4);
OUT_RING(ring, 0); /* VFD_INDEX_MIN */
OUT_RING(ring, 2); /* VFD_INDEX_MAX */
OUT_RING(ring, 0); /* VFD_INSTANCEID_OFFSET */
OUT_RING(ring, 0); /* VFD_INDEX_OFFSET */
 
OUT_PKT0(ring, REG_A3XX_PC_PRIM_VTX_CNTL, 1);
OUT_RING(ring, A3XX_PC_PRIM_VTX_CNTL_STRIDE_IN_VPC(0) |
A3XX_PC_PRIM_VTX_CNTL_POLYMODE_FRONT_PTYPE(PC_DRAW_TRIANGLES) |
A3XX_PC_PRIM_VTX_CNTL_POLYMODE_BACK_PTYPE(PC_DRAW_TRIANGLES) |
A3XX_PC_PRIM_VTX_CNTL_PROVOKING_VTX_LAST);
 
OUT_PKT0(ring, REG_A3XX_GRAS_SC_WINDOW_SCISSOR_TL, 2);
OUT_RING(ring, A3XX_GRAS_SC_WINDOW_SCISSOR_TL_X(0) |
A3XX_GRAS_SC_WINDOW_SCISSOR_TL_Y(1));
OUT_RING(ring, A3XX_GRAS_SC_WINDOW_SCISSOR_BR_X(0) |
A3XX_GRAS_SC_WINDOW_SCISSOR_BR_Y(1));
 
OUT_PKT0(ring, REG_A3XX_GRAS_SC_SCREEN_SCISSOR_TL, 2);
OUT_RING(ring, A3XX_GRAS_SC_SCREEN_SCISSOR_TL_X(0) |
A3XX_GRAS_SC_SCREEN_SCISSOR_TL_Y(0));
OUT_RING(ring, A3XX_GRAS_SC_SCREEN_SCISSOR_BR_X(31) |
A3XX_GRAS_SC_SCREEN_SCISSOR_BR_Y(0));
 
fd_wfi(ctx, ring);
OUT_PKT0(ring, REG_A3XX_GRAS_CL_VPORT_XOFFSET, 6);
OUT_RING(ring, A3XX_GRAS_CL_VPORT_XOFFSET(0.0));
OUT_RING(ring, A3XX_GRAS_CL_VPORT_XSCALE(1.0));
OUT_RING(ring, A3XX_GRAS_CL_VPORT_YOFFSET(0.0));
OUT_RING(ring, A3XX_GRAS_CL_VPORT_YSCALE(1.0));
OUT_RING(ring, A3XX_GRAS_CL_VPORT_ZOFFSET(0.0));
OUT_RING(ring, A3XX_GRAS_CL_VPORT_ZSCALE(1.0));
 
OUT_PKT0(ring, REG_A3XX_GRAS_CL_CLIP_CNTL, 1);
OUT_RING(ring, A3XX_GRAS_CL_CLIP_CNTL_CLIP_DISABLE |
A3XX_GRAS_CL_CLIP_CNTL_ZFAR_CLIP_DISABLE |
A3XX_GRAS_CL_CLIP_CNTL_VP_CLIP_CODE_IGNORE |
A3XX_GRAS_CL_CLIP_CNTL_VP_XFORM_DISABLE |
A3XX_GRAS_CL_CLIP_CNTL_PERSP_DIVISION_DISABLE);
 
OUT_PKT0(ring, REG_A3XX_GRAS_CL_GB_CLIP_ADJ, 1);
OUT_RING(ring, A3XX_GRAS_CL_GB_CLIP_ADJ_HORZ(0) |
A3XX_GRAS_CL_GB_CLIP_ADJ_VERT(0));
 
OUT_PKT3(ring, CP_DRAW_INDX_2, 5);
OUT_RING(ring, 0x00000000); /* viz query info. */
OUT_RING(ring, DRAW(DI_PT_RECTLIST, DI_SRC_SEL_IMMEDIATE,
INDEX_SIZE_32_BIT, IGNORE_VISIBILITY, 0));
OUT_RING(ring, 2); /* NumIndices */
OUT_RING(ring, 2);
OUT_RING(ring, 1);
fd_reset_wfi(ctx);
 
OUT_PKT0(ring, REG_A3XX_HLSQ_CONTROL_0_REG, 1);
OUT_RING(ring, A3XX_HLSQ_CONTROL_0_REG_FSTHREADSIZE(TWO_QUADS));
 
OUT_PKT0(ring, REG_A3XX_VFD_PERFCOUNTER0_SELECT, 1);
OUT_RING(ring, 0x00000000);
 
fd_wfi(ctx, ring);
OUT_PKT0(ring, REG_A3XX_VSC_BIN_SIZE, 1);
OUT_RING(ring, A3XX_VSC_BIN_SIZE_WIDTH(gmem->bin_w) |
A3XX_VSC_BIN_SIZE_HEIGHT(gmem->bin_h));
 
OUT_PKT0(ring, REG_A3XX_GRAS_SC_CONTROL, 1);
OUT_RING(ring, A3XX_GRAS_SC_CONTROL_RENDER_MODE(RB_RENDERING_PASS) |
A3XX_GRAS_SC_CONTROL_MSAA_SAMPLES(MSAA_ONE) |
A3XX_GRAS_SC_CONTROL_RASTER_MODE(0));
 
OUT_PKT0(ring, REG_A3XX_GRAS_CL_CLIP_CNTL, 1);
OUT_RING(ring, 0x00000000);
}
 
/* transfer from gmem to system memory (ie. normal RAM) */
 
static void
emit_gmem2mem_surf(struct fd_context *ctx,
enum adreno_rb_copy_control_mode mode,
bool stencil,
uint32_t base, struct pipe_surface *psurf)
{
struct fd_ringbuffer *ring = ctx->ring;
struct fd_resource *rsc = fd_resource(psurf->texture);
enum pipe_format format = psurf->format;
if (stencil) {
rsc = rsc->stencil;
format = rsc->base.b.format;
}
struct fd_resource_slice *slice = fd_resource_slice(rsc, psurf->u.tex.level);
uint32_t offset = fd_resource_offset(rsc, psurf->u.tex.level,
psurf->u.tex.first_layer);
 
debug_assert(psurf->u.tex.first_layer == psurf->u.tex.last_layer);
 
OUT_PKT0(ring, REG_A3XX_RB_COPY_CONTROL, 4);
OUT_RING(ring, A3XX_RB_COPY_CONTROL_MSAA_RESOLVE(MSAA_ONE) |
A3XX_RB_COPY_CONTROL_MODE(mode) |
A3XX_RB_COPY_CONTROL_GMEM_BASE(base) |
COND(format == PIPE_FORMAT_Z32_FLOAT ||
format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT,
A3XX_RB_COPY_CONTROL_UNK12));
 
OUT_RELOCW(ring, rsc->bo, offset, 0, -1); /* RB_COPY_DEST_BASE */
OUT_RING(ring, A3XX_RB_COPY_DEST_PITCH_PITCH(slice->pitch * rsc->cpp));
OUT_RING(ring, A3XX_RB_COPY_DEST_INFO_TILE(LINEAR) |
A3XX_RB_COPY_DEST_INFO_FORMAT(fd3_pipe2color(format)) |
A3XX_RB_COPY_DEST_INFO_COMPONENT_ENABLE(0xf) |
A3XX_RB_COPY_DEST_INFO_ENDIAN(ENDIAN_NONE) |
A3XX_RB_COPY_DEST_INFO_SWAP(fd3_pipe2swap(format)));
 
fd_draw(ctx, ring, DI_PT_RECTLIST, IGNORE_VISIBILITY,
DI_SRC_SEL_AUTO_INDEX, 2, 0, INDEX_SIZE_IGN, 0, 0, NULL);
}
 
static void
fd3_emit_tile_gmem2mem(struct fd_context *ctx, struct fd_tile *tile)
{
struct fd3_context *fd3_ctx = fd3_context(ctx);
struct fd_ringbuffer *ring = ctx->ring;
struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
struct fd3_emit emit = {
.vtx = &fd3_ctx->solid_vbuf_state,
.prog = &ctx->solid_prog,
.key = {
.half_precision = true,
},
};
int i;
 
OUT_PKT0(ring, REG_A3XX_RB_DEPTH_CONTROL, 1);
OUT_RING(ring, A3XX_RB_DEPTH_CONTROL_ZFUNC(FUNC_NEVER));
 
OUT_PKT0(ring, REG_A3XX_RB_STENCIL_CONTROL, 1);
OUT_RING(ring, A3XX_RB_STENCIL_CONTROL_FUNC(FUNC_NEVER) |
A3XX_RB_STENCIL_CONTROL_FAIL(STENCIL_KEEP) |
A3XX_RB_STENCIL_CONTROL_ZPASS(STENCIL_KEEP) |
A3XX_RB_STENCIL_CONTROL_ZFAIL(STENCIL_KEEP) |
A3XX_RB_STENCIL_CONTROL_FUNC_BF(FUNC_NEVER) |
A3XX_RB_STENCIL_CONTROL_FAIL_BF(STENCIL_KEEP) |
A3XX_RB_STENCIL_CONTROL_ZPASS_BF(STENCIL_KEEP) |
A3XX_RB_STENCIL_CONTROL_ZFAIL_BF(STENCIL_KEEP));
 
OUT_PKT0(ring, REG_A3XX_RB_STENCILREFMASK, 2);
OUT_RING(ring, 0xff000000 |
A3XX_RB_STENCILREFMASK_STENCILREF(0) |
A3XX_RB_STENCILREFMASK_STENCILMASK(0) |
A3XX_RB_STENCILREFMASK_STENCILWRITEMASK(0xff));
OUT_RING(ring, 0xff000000 |
A3XX_RB_STENCILREFMASK_STENCILREF(0) |
A3XX_RB_STENCILREFMASK_STENCILMASK(0) |
A3XX_RB_STENCILREFMASK_STENCILWRITEMASK(0xff));
 
OUT_PKT0(ring, REG_A3XX_GRAS_SU_MODE_CONTROL, 1);
OUT_RING(ring, A3XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH(0));
 
OUT_PKT0(ring, REG_A3XX_GRAS_CL_CLIP_CNTL, 1);
OUT_RING(ring, 0x00000000); /* GRAS_CL_CLIP_CNTL */
 
fd_wfi(ctx, ring);
OUT_PKT0(ring, REG_A3XX_GRAS_CL_VPORT_XOFFSET, 6);
OUT_RING(ring, A3XX_GRAS_CL_VPORT_XOFFSET((float)pfb->width/2.0 - 0.5));
OUT_RING(ring, A3XX_GRAS_CL_VPORT_XSCALE((float)pfb->width/2.0));
OUT_RING(ring, A3XX_GRAS_CL_VPORT_YOFFSET((float)pfb->height/2.0 - 0.5));
OUT_RING(ring, A3XX_GRAS_CL_VPORT_YSCALE(-(float)pfb->height/2.0));
OUT_RING(ring, A3XX_GRAS_CL_VPORT_ZOFFSET(0.0));
OUT_RING(ring, A3XX_GRAS_CL_VPORT_ZSCALE(1.0));
 
OUT_PKT0(ring, REG_A3XX_RB_MODE_CONTROL, 1);
OUT_RING(ring, A3XX_RB_MODE_CONTROL_RENDER_MODE(RB_RESOLVE_PASS) |
A3XX_RB_MODE_CONTROL_MARB_CACHE_SPLIT_MODE |
A3XX_RB_MODE_CONTROL_MRT(0));
 
OUT_PKT0(ring, REG_A3XX_RB_RENDER_CONTROL, 1);
OUT_RING(ring, A3XX_RB_RENDER_CONTROL_DISABLE_COLOR_PIPE |
A3XX_RB_RENDER_CONTROL_ENABLE_GMEM |
A3XX_RB_RENDER_CONTROL_ALPHA_TEST_FUNC(FUNC_NEVER) |
A3XX_RB_RENDER_CONTROL_BIN_WIDTH(ctx->gmem.bin_w));
 
OUT_PKT0(ring, REG_A3XX_GRAS_SC_CONTROL, 1);
OUT_RING(ring, A3XX_GRAS_SC_CONTROL_RENDER_MODE(RB_RESOLVE_PASS) |
A3XX_GRAS_SC_CONTROL_MSAA_SAMPLES(MSAA_ONE) |
A3XX_GRAS_SC_CONTROL_RASTER_MODE(1));
 
OUT_PKT0(ring, REG_A3XX_PC_PRIM_VTX_CNTL, 1);
OUT_RING(ring, A3XX_PC_PRIM_VTX_CNTL_STRIDE_IN_VPC(0) |
A3XX_PC_PRIM_VTX_CNTL_POLYMODE_FRONT_PTYPE(PC_DRAW_TRIANGLES) |
A3XX_PC_PRIM_VTX_CNTL_POLYMODE_BACK_PTYPE(PC_DRAW_TRIANGLES) |
A3XX_PC_PRIM_VTX_CNTL_PROVOKING_VTX_LAST);
 
OUT_PKT0(ring, REG_A3XX_GRAS_SC_WINDOW_SCISSOR_TL, 2);
OUT_RING(ring, A3XX_GRAS_SC_WINDOW_SCISSOR_TL_X(0) |
A3XX_GRAS_SC_WINDOW_SCISSOR_TL_Y(0));
OUT_RING(ring, A3XX_GRAS_SC_WINDOW_SCISSOR_BR_X(pfb->width - 1) |
A3XX_GRAS_SC_WINDOW_SCISSOR_BR_Y(pfb->height - 1));
 
OUT_PKT0(ring, REG_A3XX_VFD_INDEX_MIN, 4);
OUT_RING(ring, 0); /* VFD_INDEX_MIN */
OUT_RING(ring, 2); /* VFD_INDEX_MAX */
OUT_RING(ring, 0); /* VFD_INSTANCEID_OFFSET */
OUT_RING(ring, 0); /* VFD_INDEX_OFFSET */
 
fd3_program_emit(ring, &emit, 0, NULL);
fd3_emit_vertex_bufs(ring, &emit);
 
if (ctx->resolve & (FD_BUFFER_DEPTH | FD_BUFFER_STENCIL)) {
struct fd_resource *rsc = fd_resource(pfb->zsbuf->texture);
if (!rsc->stencil || ctx->resolve & FD_BUFFER_DEPTH)
emit_gmem2mem_surf(ctx, RB_COPY_DEPTH_STENCIL, false,
ctx->gmem.zsbuf_base[0], pfb->zsbuf);
if (rsc->stencil && ctx->resolve & FD_BUFFER_STENCIL)
emit_gmem2mem_surf(ctx, RB_COPY_DEPTH_STENCIL, true,
ctx->gmem.zsbuf_base[1], pfb->zsbuf);
}
 
if (ctx->resolve & FD_BUFFER_COLOR) {
for (i = 0; i < pfb->nr_cbufs; i++) {
if (!pfb->cbufs[i])
continue;
if (!(ctx->resolve & (PIPE_CLEAR_COLOR0 << i)))
continue;
emit_gmem2mem_surf(ctx, RB_COPY_RESOLVE, false,
ctx->gmem.cbuf_base[i], pfb->cbufs[i]);
}
}
 
OUT_PKT0(ring, REG_A3XX_RB_MODE_CONTROL, 1);
OUT_RING(ring, A3XX_RB_MODE_CONTROL_RENDER_MODE(RB_RENDERING_PASS) |
A3XX_RB_MODE_CONTROL_MARB_CACHE_SPLIT_MODE |
A3XX_RB_MODE_CONTROL_MRT(MAX2(1, pfb->nr_cbufs) - 1));
 
OUT_PKT0(ring, REG_A3XX_GRAS_SC_CONTROL, 1);
OUT_RING(ring, A3XX_GRAS_SC_CONTROL_RENDER_MODE(RB_RENDERING_PASS) |
A3XX_GRAS_SC_CONTROL_MSAA_SAMPLES(MSAA_ONE) |
A3XX_GRAS_SC_CONTROL_RASTER_MODE(0));
}
 
/* transfer from system memory to gmem */
 
static void
emit_mem2gmem_surf(struct fd_context *ctx, uint32_t bases[],
struct pipe_surface **psurf, uint32_t bufs, uint32_t bin_w)
{
struct fd_ringbuffer *ring = ctx->ring;
struct pipe_surface *zsbufs[2];
 
assert(bufs > 0);
 
OUT_PKT0(ring, REG_A3XX_RB_MODE_CONTROL, 1);
OUT_RING(ring, A3XX_RB_MODE_CONTROL_RENDER_MODE(RB_RENDERING_PASS) |
A3XX_RB_MODE_CONTROL_MARB_CACHE_SPLIT_MODE |
A3XX_RB_MODE_CONTROL_MRT(bufs - 1));
 
emit_mrt(ring, bufs, psurf, bases, bin_w, false);
 
if (psurf[0] && (psurf[0]->format == PIPE_FORMAT_Z32_FLOAT ||
psurf[0]->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT)) {
/* Depth is stored as unorm in gmem, so we have to write it in using a
* special blit shader which writes depth.
*/
OUT_PKT0(ring, REG_A3XX_RB_DEPTH_CONTROL, 1);
OUT_RING(ring, (A3XX_RB_DEPTH_CONTROL_FRAG_WRITES_Z |
A3XX_RB_DEPTH_CONTROL_Z_WRITE_ENABLE |
A3XX_RB_DEPTH_CONTROL_Z_ENABLE |
A3XX_RB_DEPTH_CONTROL_EARLY_Z_DISABLE |
A3XX_RB_DEPTH_CONTROL_ZFUNC(FUNC_ALWAYS)));
 
OUT_PKT0(ring, REG_A3XX_RB_DEPTH_INFO, 2);
OUT_RING(ring, A3XX_RB_DEPTH_INFO_DEPTH_BASE(bases[0]) |
A3XX_RB_DEPTH_INFO_DEPTH_FORMAT(DEPTHX_32));
OUT_RING(ring, A3XX_RB_DEPTH_PITCH(4 * ctx->gmem.bin_w));
 
if (psurf[0]->format == PIPE_FORMAT_Z32_FLOAT) {
OUT_PKT0(ring, REG_A3XX_RB_MRT_CONTROL(0), 1);
OUT_RING(ring, 0);
} else {
/* The gmem_restore_tex logic will put the first buffer's stencil
* as color. Supply it with the proper information to make that
* happen.
*/
zsbufs[0] = zsbufs[1] = psurf[0];
psurf = zsbufs;
bufs = 2;
}
} else {
OUT_PKT0(ring, REG_A3XX_SP_FS_OUTPUT_REG, 1);
OUT_RING(ring, A3XX_SP_FS_OUTPUT_REG_MRT(bufs - 1));
}
 
fd3_emit_gmem_restore_tex(ring, psurf, bufs);
 
fd_draw(ctx, ring, DI_PT_RECTLIST, IGNORE_VISIBILITY,
DI_SRC_SEL_AUTO_INDEX, 2, 0, INDEX_SIZE_IGN, 0, 0, NULL);
}
 
static void
fd3_emit_tile_mem2gmem(struct fd_context *ctx, struct fd_tile *tile)
{
struct fd3_context *fd3_ctx = fd3_context(ctx);
struct fd_gmem_stateobj *gmem = &ctx->gmem;
struct fd_ringbuffer *ring = ctx->ring;
struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
struct fd3_emit emit = {
.vtx = &fd3_ctx->blit_vbuf_state,
.sprite_coord_enable = 1,
/* NOTE: They all use the same VP, this is for vtx bufs. */
.prog = &ctx->blit_prog[0],
.key = {
.half_precision = (fd3_half_precision(pfb->cbufs[0]) &&
fd3_half_precision(pfb->cbufs[1]) &&
fd3_half_precision(pfb->cbufs[2]) &&
fd3_half_precision(pfb->cbufs[3]))
},
};
float x0, y0, x1, y1;
unsigned bin_w = tile->bin_w;
unsigned bin_h = tile->bin_h;
unsigned i;
 
/* write texture coordinates to vertexbuf: */
x0 = ((float)tile->xoff) / ((float)pfb->width);
x1 = ((float)tile->xoff + bin_w) / ((float)pfb->width);
y0 = ((float)tile->yoff) / ((float)pfb->height);
y1 = ((float)tile->yoff + bin_h) / ((float)pfb->height);
 
OUT_PKT3(ring, CP_MEM_WRITE, 5);
OUT_RELOCW(ring, fd_resource(fd3_ctx->blit_texcoord_vbuf)->bo, 0, 0, 0);
OUT_RING(ring, fui(x0));
OUT_RING(ring, fui(y0));
OUT_RING(ring, fui(x1));
OUT_RING(ring, fui(y1));
 
for (i = 0; i < 4; i++) {
OUT_PKT0(ring, REG_A3XX_RB_MRT_CONTROL(i), 1);
OUT_RING(ring, A3XX_RB_MRT_CONTROL_ROP_CODE(ROP_COPY) |
A3XX_RB_MRT_CONTROL_DITHER_MODE(DITHER_DISABLE) |
A3XX_RB_MRT_CONTROL_COMPONENT_ENABLE(0xf));
 
OUT_PKT0(ring, REG_A3XX_RB_MRT_BLEND_CONTROL(i), 1);
OUT_RING(ring, A3XX_RB_MRT_BLEND_CONTROL_RGB_SRC_FACTOR(FACTOR_ONE) |
A3XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE(BLEND_DST_PLUS_SRC) |
A3XX_RB_MRT_BLEND_CONTROL_RGB_DEST_FACTOR(FACTOR_ZERO) |
A3XX_RB_MRT_BLEND_CONTROL_ALPHA_SRC_FACTOR(FACTOR_ONE) |
A3XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE(BLEND_DST_PLUS_SRC) |
A3XX_RB_MRT_BLEND_CONTROL_ALPHA_DEST_FACTOR(FACTOR_ZERO));
}
 
OUT_PKT0(ring, REG_A3XX_RB_RENDER_CONTROL, 1);
OUT_RING(ring, A3XX_RB_RENDER_CONTROL_ALPHA_TEST_FUNC(FUNC_ALWAYS) |
A3XX_RB_RENDER_CONTROL_BIN_WIDTH(gmem->bin_w));
 
fd_wfi(ctx, ring);
OUT_PKT0(ring, REG_A3XX_RB_DEPTH_CONTROL, 1);
OUT_RING(ring, A3XX_RB_DEPTH_CONTROL_ZFUNC(FUNC_LESS));
 
OUT_PKT0(ring, REG_A3XX_RB_DEPTH_INFO, 2);
OUT_RING(ring, 0);
OUT_RING(ring, 0);
 
OUT_PKT0(ring, REG_A3XX_GRAS_CL_CLIP_CNTL, 1);
OUT_RING(ring, A3XX_GRAS_CL_CLIP_CNTL_IJ_PERSP_CENTER); /* GRAS_CL_CLIP_CNTL */
 
fd_wfi(ctx, ring);
OUT_PKT0(ring, REG_A3XX_GRAS_CL_VPORT_XOFFSET, 6);
OUT_RING(ring, A3XX_GRAS_CL_VPORT_XOFFSET((float)bin_w/2.0 - 0.5));
OUT_RING(ring, A3XX_GRAS_CL_VPORT_XSCALE((float)bin_w/2.0));
OUT_RING(ring, A3XX_GRAS_CL_VPORT_YOFFSET((float)bin_h/2.0 - 0.5));
OUT_RING(ring, A3XX_GRAS_CL_VPORT_YSCALE(-(float)bin_h/2.0));
OUT_RING(ring, A3XX_GRAS_CL_VPORT_ZOFFSET(0.0));
OUT_RING(ring, A3XX_GRAS_CL_VPORT_ZSCALE(1.0));
 
OUT_PKT0(ring, REG_A3XX_GRAS_SC_WINDOW_SCISSOR_TL, 2);
OUT_RING(ring, A3XX_GRAS_SC_WINDOW_SCISSOR_TL_X(0) |
A3XX_GRAS_SC_WINDOW_SCISSOR_TL_Y(0));
OUT_RING(ring, A3XX_GRAS_SC_WINDOW_SCISSOR_BR_X(bin_w - 1) |
A3XX_GRAS_SC_WINDOW_SCISSOR_BR_Y(bin_h - 1));
 
OUT_PKT0(ring, REG_A3XX_GRAS_SC_SCREEN_SCISSOR_TL, 2);
OUT_RING(ring, A3XX_GRAS_SC_SCREEN_SCISSOR_TL_X(0) |
A3XX_GRAS_SC_SCREEN_SCISSOR_TL_Y(0));
OUT_RING(ring, A3XX_GRAS_SC_SCREEN_SCISSOR_BR_X(bin_w - 1) |
A3XX_GRAS_SC_SCREEN_SCISSOR_BR_Y(bin_h - 1));
 
OUT_PKT0(ring, REG_A3XX_RB_STENCIL_CONTROL, 1);
OUT_RING(ring, 0x2 |
A3XX_RB_STENCIL_CONTROL_FUNC(FUNC_ALWAYS) |
A3XX_RB_STENCIL_CONTROL_FAIL(STENCIL_KEEP) |
A3XX_RB_STENCIL_CONTROL_ZPASS(STENCIL_KEEP) |
A3XX_RB_STENCIL_CONTROL_ZFAIL(STENCIL_KEEP) |
A3XX_RB_STENCIL_CONTROL_FUNC_BF(FUNC_ALWAYS) |
A3XX_RB_STENCIL_CONTROL_FAIL_BF(STENCIL_KEEP) |
A3XX_RB_STENCIL_CONTROL_ZPASS_BF(STENCIL_KEEP) |
A3XX_RB_STENCIL_CONTROL_ZFAIL_BF(STENCIL_KEEP));
 
OUT_PKT0(ring, REG_A3XX_RB_STENCIL_INFO, 2);
OUT_RING(ring, 0); /* RB_STENCIL_INFO */
OUT_RING(ring, 0); /* RB_STENCIL_PITCH */
 
OUT_PKT0(ring, REG_A3XX_GRAS_SC_CONTROL, 1);
OUT_RING(ring, A3XX_GRAS_SC_CONTROL_RENDER_MODE(RB_RENDERING_PASS) |
A3XX_GRAS_SC_CONTROL_MSAA_SAMPLES(MSAA_ONE) |
A3XX_GRAS_SC_CONTROL_RASTER_MODE(1));
 
OUT_PKT0(ring, REG_A3XX_PC_PRIM_VTX_CNTL, 1);
OUT_RING(ring, A3XX_PC_PRIM_VTX_CNTL_STRIDE_IN_VPC(2) |
A3XX_PC_PRIM_VTX_CNTL_POLYMODE_FRONT_PTYPE(PC_DRAW_TRIANGLES) |
A3XX_PC_PRIM_VTX_CNTL_POLYMODE_BACK_PTYPE(PC_DRAW_TRIANGLES) |
A3XX_PC_PRIM_VTX_CNTL_PROVOKING_VTX_LAST);
 
OUT_PKT0(ring, REG_A3XX_VFD_INDEX_MIN, 4);
OUT_RING(ring, 0); /* VFD_INDEX_MIN */
OUT_RING(ring, 2); /* VFD_INDEX_MAX */
OUT_RING(ring, 0); /* VFD_INSTANCEID_OFFSET */
OUT_RING(ring, 0); /* VFD_INDEX_OFFSET */
 
fd3_emit_vertex_bufs(ring, &emit);
 
/* for gmem pitch/base calculations, we need to use the non-
* truncated tile sizes:
*/
bin_w = gmem->bin_w;
bin_h = gmem->bin_h;
 
if (fd_gmem_needs_restore(ctx, tile, FD_BUFFER_COLOR)) {
emit.prog = &ctx->blit_prog[pfb->nr_cbufs - 1];
fd3_program_emit(ring, &emit, pfb->nr_cbufs, pfb->cbufs);
emit_mem2gmem_surf(ctx, gmem->cbuf_base, pfb->cbufs, pfb->nr_cbufs, bin_w);
}
 
if (fd_gmem_needs_restore(ctx, tile, FD_BUFFER_DEPTH | FD_BUFFER_STENCIL)) {
if (pfb->zsbuf->format != PIPE_FORMAT_Z32_FLOAT_S8X24_UINT &&
pfb->zsbuf->format != PIPE_FORMAT_Z32_FLOAT) {
/* Non-float can use a regular color write. It's split over 8-bit
* components, so half precision is always sufficient.
*/
emit.prog = &ctx->blit_prog[0];
emit.key.half_precision = true;
} else {
/* Float depth needs special blit shader that writes depth */
if (pfb->zsbuf->format == PIPE_FORMAT_Z32_FLOAT)
emit.prog = &ctx->blit_z;
else
emit.prog = &ctx->blit_zs;
emit.key.half_precision = false;
}
fd3_program_emit(ring, &emit, 1, &pfb->zsbuf);
emit_mem2gmem_surf(ctx, gmem->zsbuf_base, &pfb->zsbuf, 1, bin_w);
}
 
OUT_PKT0(ring, REG_A3XX_GRAS_SC_CONTROL, 1);
OUT_RING(ring, A3XX_GRAS_SC_CONTROL_RENDER_MODE(RB_RENDERING_PASS) |
A3XX_GRAS_SC_CONTROL_MSAA_SAMPLES(MSAA_ONE) |
A3XX_GRAS_SC_CONTROL_RASTER_MODE(0));
 
OUT_PKT0(ring, REG_A3XX_RB_MODE_CONTROL, 1);
OUT_RING(ring, A3XX_RB_MODE_CONTROL_RENDER_MODE(RB_RENDERING_PASS) |
A3XX_RB_MODE_CONTROL_MARB_CACHE_SPLIT_MODE |
A3XX_RB_MODE_CONTROL_MRT(MAX2(1, pfb->nr_cbufs) - 1));
}
 
static void
patch_draws(struct fd_context *ctx, enum pc_di_vis_cull_mode vismode)
{
unsigned i;
for (i = 0; i < fd_patch_num_elements(&ctx->draw_patches); i++) {
struct fd_cs_patch *patch = fd_patch_element(&ctx->draw_patches, i);
*patch->cs = patch->val | DRAW(0, 0, 0, vismode, 0);
}
util_dynarray_resize(&ctx->draw_patches, 0);
}
 
static void
patch_rbrc(struct fd_context *ctx, uint32_t val)
{
struct fd3_context *fd3_ctx = fd3_context(ctx);
unsigned i;
for (i = 0; i < fd_patch_num_elements(&fd3_ctx->rbrc_patches); i++) {
struct fd_cs_patch *patch = fd_patch_element(&fd3_ctx->rbrc_patches, i);
*patch->cs = patch->val | val;
}
util_dynarray_resize(&fd3_ctx->rbrc_patches, 0);
}
 
/* for rendering directly to system memory: */
static void
fd3_emit_sysmem_prep(struct fd_context *ctx)
{
struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
struct fd_ringbuffer *ring = ctx->ring;
uint32_t i, pitch = 0;
 
for (i = 0; i < pfb->nr_cbufs; i++) {
struct pipe_surface *psurf = pfb->cbufs[i];
if (!psurf)
continue;
pitch = fd_resource(psurf->texture)->slices[psurf->u.tex.level].pitch;
}
 
fd3_emit_restore(ctx);
 
OUT_PKT0(ring, REG_A3XX_RB_FRAME_BUFFER_DIMENSION, 1);
OUT_RING(ring, A3XX_RB_FRAME_BUFFER_DIMENSION_WIDTH(pfb->width) |
A3XX_RB_FRAME_BUFFER_DIMENSION_HEIGHT(pfb->height));
 
emit_mrt(ring, pfb->nr_cbufs, pfb->cbufs, NULL, 0, true);
 
/* setup scissor/offset for current tile: */
OUT_PKT0(ring, REG_A3XX_RB_WINDOW_OFFSET, 1);
OUT_RING(ring, A3XX_RB_WINDOW_OFFSET_X(0) |
A3XX_RB_WINDOW_OFFSET_Y(0));
 
OUT_PKT0(ring, REG_A3XX_GRAS_SC_SCREEN_SCISSOR_TL, 2);
OUT_RING(ring, A3XX_GRAS_SC_SCREEN_SCISSOR_TL_X(0) |
A3XX_GRAS_SC_SCREEN_SCISSOR_TL_Y(0));
OUT_RING(ring, A3XX_GRAS_SC_SCREEN_SCISSOR_BR_X(pfb->width - 1) |
A3XX_GRAS_SC_SCREEN_SCISSOR_BR_Y(pfb->height - 1));
 
OUT_PKT0(ring, REG_A3XX_RB_MODE_CONTROL, 1);
OUT_RING(ring, A3XX_RB_MODE_CONTROL_RENDER_MODE(RB_RENDERING_PASS) |
A3XX_RB_MODE_CONTROL_GMEM_BYPASS |
A3XX_RB_MODE_CONTROL_MARB_CACHE_SPLIT_MODE |
A3XX_RB_MODE_CONTROL_MRT(MAX2(1, pfb->nr_cbufs) - 1));
 
patch_draws(ctx, IGNORE_VISIBILITY);
patch_rbrc(ctx, A3XX_RB_RENDER_CONTROL_BIN_WIDTH(pitch));
}
 
static void
update_vsc_pipe(struct fd_context *ctx)
{
struct fd3_context *fd3_ctx = fd3_context(ctx);
struct fd_ringbuffer *ring = ctx->ring;
int i;
 
OUT_PKT0(ring, REG_A3XX_VSC_SIZE_ADDRESS, 1);
OUT_RELOCW(ring, fd3_ctx->vsc_size_mem, 0, 0, 0); /* VSC_SIZE_ADDRESS */
 
for (i = 0; i < 8; i++) {
struct fd_vsc_pipe *pipe = &ctx->pipe[i];
 
if (!pipe->bo) {
pipe->bo = fd_bo_new(ctx->dev, 0x40000,
DRM_FREEDRENO_GEM_TYPE_KMEM);
}
 
OUT_PKT0(ring, REG_A3XX_VSC_PIPE(i), 3);
OUT_RING(ring, A3XX_VSC_PIPE_CONFIG_X(pipe->x) |
A3XX_VSC_PIPE_CONFIG_Y(pipe->y) |
A3XX_VSC_PIPE_CONFIG_W(pipe->w) |
A3XX_VSC_PIPE_CONFIG_H(pipe->h));
OUT_RELOCW(ring, pipe->bo, 0, 0, 0); /* VSC_PIPE[i].DATA_ADDRESS */
OUT_RING(ring, fd_bo_size(pipe->bo) - 32); /* VSC_PIPE[i].DATA_LENGTH */
}
}
 
static void
emit_binning_pass(struct fd_context *ctx)
{
struct fd_gmem_stateobj *gmem = &ctx->gmem;
struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
struct fd_ringbuffer *ring = ctx->ring;
int i;
 
uint32_t x1 = gmem->minx;
uint32_t y1 = gmem->miny;
uint32_t x2 = gmem->minx + gmem->width - 1;
uint32_t y2 = gmem->miny + gmem->height - 1;
 
if (ctx->screen->gpu_id == 320) {
emit_binning_workaround(ctx);
fd_wfi(ctx, ring);
OUT_PKT3(ring, CP_INVALIDATE_STATE, 1);
OUT_RING(ring, 0x00007fff);
}
 
OUT_PKT0(ring, REG_A3XX_VSC_BIN_CONTROL, 1);
OUT_RING(ring, A3XX_VSC_BIN_CONTROL_BINNING_ENABLE);
 
OUT_PKT0(ring, REG_A3XX_GRAS_SC_CONTROL, 1);
OUT_RING(ring, A3XX_GRAS_SC_CONTROL_RENDER_MODE(RB_TILING_PASS) |
A3XX_GRAS_SC_CONTROL_MSAA_SAMPLES(MSAA_ONE) |
A3XX_GRAS_SC_CONTROL_RASTER_MODE(0));
 
OUT_PKT0(ring, REG_A3XX_RB_FRAME_BUFFER_DIMENSION, 1);
OUT_RING(ring, A3XX_RB_FRAME_BUFFER_DIMENSION_WIDTH(pfb->width) |
A3XX_RB_FRAME_BUFFER_DIMENSION_HEIGHT(pfb->height));
 
OUT_PKT0(ring, REG_A3XX_RB_RENDER_CONTROL, 1);
OUT_RING(ring, A3XX_RB_RENDER_CONTROL_ALPHA_TEST_FUNC(FUNC_NEVER) |
A3XX_RB_RENDER_CONTROL_DISABLE_COLOR_PIPE |
A3XX_RB_RENDER_CONTROL_BIN_WIDTH(gmem->bin_w));
 
/* setup scissor/offset for whole screen: */
OUT_PKT0(ring, REG_A3XX_RB_WINDOW_OFFSET, 1);
OUT_RING(ring, A3XX_RB_WINDOW_OFFSET_X(x1) |
A3XX_RB_WINDOW_OFFSET_Y(y1));
 
OUT_PKT0(ring, REG_A3XX_RB_LRZ_VSC_CONTROL, 1);
OUT_RING(ring, A3XX_RB_LRZ_VSC_CONTROL_BINNING_ENABLE);
 
OUT_PKT0(ring, REG_A3XX_GRAS_SC_SCREEN_SCISSOR_TL, 2);
OUT_RING(ring, A3XX_GRAS_SC_SCREEN_SCISSOR_TL_X(x1) |
A3XX_GRAS_SC_SCREEN_SCISSOR_TL_Y(y1));
OUT_RING(ring, A3XX_GRAS_SC_SCREEN_SCISSOR_BR_X(x2) |
A3XX_GRAS_SC_SCREEN_SCISSOR_BR_Y(y2));
 
OUT_PKT0(ring, REG_A3XX_RB_MODE_CONTROL, 1);
OUT_RING(ring, A3XX_RB_MODE_CONTROL_RENDER_MODE(RB_TILING_PASS) |
A3XX_RB_MODE_CONTROL_MARB_CACHE_SPLIT_MODE |
A3XX_RB_MODE_CONTROL_MRT(0));
 
for (i = 0; i < 4; i++) {
OUT_PKT0(ring, REG_A3XX_RB_MRT_CONTROL(i), 1);
OUT_RING(ring, A3XX_RB_MRT_CONTROL_ROP_CODE(ROP_CLEAR) |
A3XX_RB_MRT_CONTROL_DITHER_MODE(DITHER_DISABLE) |
A3XX_RB_MRT_CONTROL_COMPONENT_ENABLE(0));
}
 
OUT_PKT0(ring, REG_A3XX_PC_VSTREAM_CONTROL, 1);
OUT_RING(ring, A3XX_PC_VSTREAM_CONTROL_SIZE(1) |
A3XX_PC_VSTREAM_CONTROL_N(0));
 
/* emit IB to binning drawcmds: */
OUT_IB(ring, ctx->binning_start, ctx->binning_end);
fd_reset_wfi(ctx);
 
fd_wfi(ctx, ring);
 
/* and then put stuff back the way it was: */
 
OUT_PKT0(ring, REG_A3XX_VSC_BIN_CONTROL, 1);
OUT_RING(ring, 0x00000000);
 
OUT_PKT0(ring, REG_A3XX_SP_SP_CTRL_REG, 1);
OUT_RING(ring, A3XX_SP_SP_CTRL_REG_RESOLVE |
A3XX_SP_SP_CTRL_REG_CONSTMODE(1) |
A3XX_SP_SP_CTRL_REG_SLEEPMODE(1) |
A3XX_SP_SP_CTRL_REG_L0MODE(0));
 
OUT_PKT0(ring, REG_A3XX_RB_LRZ_VSC_CONTROL, 1);
OUT_RING(ring, 0x00000000);
 
OUT_PKT0(ring, REG_A3XX_GRAS_SC_CONTROL, 1);
OUT_RING(ring, A3XX_GRAS_SC_CONTROL_RENDER_MODE(RB_RENDERING_PASS) |
A3XX_GRAS_SC_CONTROL_MSAA_SAMPLES(MSAA_ONE) |
A3XX_GRAS_SC_CONTROL_RASTER_MODE(0));
 
OUT_PKT0(ring, REG_A3XX_RB_MODE_CONTROL, 2);
OUT_RING(ring, A3XX_RB_MODE_CONTROL_RENDER_MODE(RB_RENDERING_PASS) |
A3XX_RB_MODE_CONTROL_MARB_CACHE_SPLIT_MODE |
A3XX_RB_MODE_CONTROL_MRT(pfb->nr_cbufs - 1));
OUT_RING(ring, A3XX_RB_RENDER_CONTROL_ENABLE_GMEM |
A3XX_RB_RENDER_CONTROL_ALPHA_TEST_FUNC(FUNC_NEVER) |
A3XX_RB_RENDER_CONTROL_BIN_WIDTH(gmem->bin_w));
 
fd_event_write(ctx, ring, CACHE_FLUSH);
fd_wfi(ctx, ring);
 
if (ctx->screen->gpu_id == 320) {
/* dummy-draw workaround: */
OUT_PKT3(ring, CP_DRAW_INDX, 3);
OUT_RING(ring, 0x00000000);
OUT_RING(ring, DRAW(1, DI_SRC_SEL_AUTO_INDEX,
INDEX_SIZE_IGN, IGNORE_VISIBILITY, 0));
OUT_RING(ring, 0); /* NumIndices */
fd_reset_wfi(ctx);
}
 
OUT_PKT3(ring, CP_NOP, 4);
OUT_RING(ring, 0x00000000);
OUT_RING(ring, 0x00000000);
OUT_RING(ring, 0x00000000);
OUT_RING(ring, 0x00000000);
 
fd_wfi(ctx, ring);
 
if (ctx->screen->gpu_id == 320) {
emit_binning_workaround(ctx);
}
}
 
/* before first tile */
static void
fd3_emit_tile_init(struct fd_context *ctx)
{
struct fd_ringbuffer *ring = ctx->ring;
struct fd_gmem_stateobj *gmem = &ctx->gmem;
uint32_t rb_render_control;
 
fd3_emit_restore(ctx);
 
/* note: use gmem->bin_w/h, the bin_w/h parameters may be truncated
* at the right and bottom edge tiles
*/
OUT_PKT0(ring, REG_A3XX_VSC_BIN_SIZE, 1);
OUT_RING(ring, A3XX_VSC_BIN_SIZE_WIDTH(gmem->bin_w) |
A3XX_VSC_BIN_SIZE_HEIGHT(gmem->bin_h));
 
update_vsc_pipe(ctx);
 
if (use_hw_binning(ctx)) {
/* mark the end of the binning cmds: */
fd_ringmarker_mark(ctx->binning_end);
 
/* emit hw binning pass: */
emit_binning_pass(ctx);
 
patch_draws(ctx, USE_VISIBILITY);
} else {
patch_draws(ctx, IGNORE_VISIBILITY);
}
 
rb_render_control = A3XX_RB_RENDER_CONTROL_ENABLE_GMEM |
A3XX_RB_RENDER_CONTROL_BIN_WIDTH(gmem->bin_w);
 
patch_rbrc(ctx, rb_render_control);
}
 
/* before mem2gmem */
static void
fd3_emit_tile_prep(struct fd_context *ctx, struct fd_tile *tile)
{
struct fd_ringbuffer *ring = ctx->ring;
struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
 
if (ctx->needs_rb_fbd) {
fd_wfi(ctx, ring);
OUT_PKT0(ring, REG_A3XX_RB_FRAME_BUFFER_DIMENSION, 1);
OUT_RING(ring, A3XX_RB_FRAME_BUFFER_DIMENSION_WIDTH(pfb->width) |
A3XX_RB_FRAME_BUFFER_DIMENSION_HEIGHT(pfb->height));
ctx->needs_rb_fbd = false;
}
 
OUT_PKT0(ring, REG_A3XX_RB_MODE_CONTROL, 1);
OUT_RING(ring, A3XX_RB_MODE_CONTROL_RENDER_MODE(RB_RENDERING_PASS) |
A3XX_RB_MODE_CONTROL_MARB_CACHE_SPLIT_MODE |
A3XX_RB_MODE_CONTROL_MRT(MAX2(1, pfb->nr_cbufs) - 1));
}
 
/* before IB to rendering cmds: */
static void
fd3_emit_tile_renderprep(struct fd_context *ctx, struct fd_tile *tile)
{
struct fd3_context *fd3_ctx = fd3_context(ctx);
struct fd_ringbuffer *ring = ctx->ring;
struct fd_gmem_stateobj *gmem = &ctx->gmem;
struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
 
uint32_t x1 = tile->xoff;
uint32_t y1 = tile->yoff;
uint32_t x2 = tile->xoff + tile->bin_w - 1;
uint32_t y2 = tile->yoff + tile->bin_h - 1;
 
uint32_t reg;
 
OUT_PKT0(ring, REG_A3XX_RB_DEPTH_INFO, 2);
reg = A3XX_RB_DEPTH_INFO_DEPTH_BASE(gmem->zsbuf_base[0]);
if (pfb->zsbuf) {
reg |= A3XX_RB_DEPTH_INFO_DEPTH_FORMAT(fd_pipe2depth(pfb->zsbuf->format));
}
OUT_RING(ring, reg);
if (pfb->zsbuf) {
struct fd_resource *rsc = fd_resource(pfb->zsbuf->texture);
OUT_RING(ring, A3XX_RB_DEPTH_PITCH(rsc->cpp * gmem->bin_w));
if (rsc->stencil) {
OUT_PKT0(ring, REG_A3XX_RB_STENCIL_INFO, 2);
OUT_RING(ring, A3XX_RB_STENCIL_INFO_STENCIL_BASE(gmem->zsbuf_base[1]));
OUT_RING(ring, A3XX_RB_STENCIL_PITCH(rsc->stencil->cpp * gmem->bin_w));
}
} else {
OUT_RING(ring, 0x00000000);
}
 
if (use_hw_binning(ctx)) {
struct fd_vsc_pipe *pipe = &ctx->pipe[tile->p];
 
assert(pipe->w * pipe->h);
 
fd_event_write(ctx, ring, HLSQ_FLUSH);
fd_wfi(ctx, ring);
 
OUT_PKT0(ring, REG_A3XX_PC_VSTREAM_CONTROL, 1);
OUT_RING(ring, A3XX_PC_VSTREAM_CONTROL_SIZE(pipe->w * pipe->h) |
A3XX_PC_VSTREAM_CONTROL_N(tile->n));
 
 
OUT_PKT3(ring, CP_SET_BIN_DATA, 2);
OUT_RELOC(ring, pipe->bo, 0, 0, 0); /* BIN_DATA_ADDR <- VSC_PIPE[p].DATA_ADDRESS */
OUT_RELOC(ring, fd3_ctx->vsc_size_mem, /* BIN_SIZE_ADDR <- VSC_SIZE_ADDRESS + (p * 4) */
(tile->p * 4), 0, 0);
} else {
OUT_PKT0(ring, REG_A3XX_PC_VSTREAM_CONTROL, 1);
OUT_RING(ring, 0x00000000);
}
 
OUT_PKT3(ring, CP_SET_BIN, 3);
OUT_RING(ring, 0x00000000);
OUT_RING(ring, CP_SET_BIN_1_X1(x1) | CP_SET_BIN_1_Y1(y1));
OUT_RING(ring, CP_SET_BIN_2_X2(x2) | CP_SET_BIN_2_Y2(y2));
 
emit_mrt(ring, pfb->nr_cbufs, pfb->cbufs, gmem->cbuf_base, gmem->bin_w, true);
 
/* setup scissor/offset for current tile: */
OUT_PKT0(ring, REG_A3XX_RB_WINDOW_OFFSET, 1);
OUT_RING(ring, A3XX_RB_WINDOW_OFFSET_X(tile->xoff) |
A3XX_RB_WINDOW_OFFSET_Y(tile->yoff));
 
OUT_PKT0(ring, REG_A3XX_GRAS_SC_SCREEN_SCISSOR_TL, 2);
OUT_RING(ring, A3XX_GRAS_SC_SCREEN_SCISSOR_TL_X(x1) |
A3XX_GRAS_SC_SCREEN_SCISSOR_TL_Y(y1));
OUT_RING(ring, A3XX_GRAS_SC_SCREEN_SCISSOR_BR_X(x2) |
A3XX_GRAS_SC_SCREEN_SCISSOR_BR_Y(y2));
}
 
void
fd3_gmem_init(struct pipe_context *pctx)
{
struct fd_context *ctx = fd_context(pctx);
 
ctx->emit_sysmem_prep = fd3_emit_sysmem_prep;
ctx->emit_tile_init = fd3_emit_tile_init;
ctx->emit_tile_prep = fd3_emit_tile_prep;
ctx->emit_tile_mem2gmem = fd3_emit_tile_mem2gmem;
ctx->emit_tile_renderprep = fd3_emit_tile_renderprep;
ctx->emit_tile_gmem2mem = fd3_emit_tile_gmem2mem;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a3xx/fd3_gmem.h
0,0 → 1,36
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FD3_GMEM_H_
#define FD3_GMEM_H_
 
#include "pipe/p_context.h"
 
void fd3_gmem_init(struct pipe_context *pctx);
 
#endif /* FD3_GMEM_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a3xx/fd3_program.c
0,0 → 1,481
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "pipe/p_state.h"
#include "util/u_string.h"
#include "util/u_memory.h"
#include "util/u_inlines.h"
#include "util/u_format.h"
 
#include "freedreno_program.h"
 
#include "fd3_program.h"
#include "fd3_emit.h"
#include "fd3_texture.h"
#include "fd3_format.h"
 
static void
delete_shader_stateobj(struct fd3_shader_stateobj *so)
{
ir3_shader_destroy(so->shader);
free(so);
}
 
static struct fd3_shader_stateobj *
create_shader_stateobj(struct pipe_context *pctx, const struct pipe_shader_state *cso,
enum shader_t type)
{
struct fd3_shader_stateobj *so = CALLOC_STRUCT(fd3_shader_stateobj);
so->shader = ir3_shader_create(pctx, cso->tokens, type);
return so;
}
 
static void *
fd3_fp_state_create(struct pipe_context *pctx,
const struct pipe_shader_state *cso)
{
return create_shader_stateobj(pctx, cso, SHADER_FRAGMENT);
}
 
static void
fd3_fp_state_delete(struct pipe_context *pctx, void *hwcso)
{
struct fd3_shader_stateobj *so = hwcso;
delete_shader_stateobj(so);
}
 
static void *
fd3_vp_state_create(struct pipe_context *pctx,
const struct pipe_shader_state *cso)
{
return create_shader_stateobj(pctx, cso, SHADER_VERTEX);
}
 
static void
fd3_vp_state_delete(struct pipe_context *pctx, void *hwcso)
{
struct fd3_shader_stateobj *so = hwcso;
delete_shader_stateobj(so);
}
 
static void
emit_shader(struct fd_ringbuffer *ring, const struct ir3_shader_variant *so)
{
const struct ir3_info *si = &so->info;
enum adreno_state_block sb;
enum adreno_state_src src;
uint32_t i, sz, *bin;
 
if (so->type == SHADER_VERTEX) {
sb = SB_VERT_SHADER;
} else {
sb = SB_FRAG_SHADER;
}
 
if (fd_mesa_debug & FD_DBG_DIRECT) {
sz = si->sizedwords;
src = SS_DIRECT;
bin = fd_bo_map(so->bo);
} else {
sz = 0;
src = SS_INDIRECT;
bin = NULL;
}
 
OUT_PKT3(ring, CP_LOAD_STATE, 2 + sz);
OUT_RING(ring, CP_LOAD_STATE_0_DST_OFF(0) |
CP_LOAD_STATE_0_STATE_SRC(src) |
CP_LOAD_STATE_0_STATE_BLOCK(sb) |
CP_LOAD_STATE_0_NUM_UNIT(so->instrlen));
if (bin) {
OUT_RING(ring, CP_LOAD_STATE_1_EXT_SRC_ADDR(0) |
CP_LOAD_STATE_1_STATE_TYPE(ST_SHADER));
} else {
OUT_RELOC(ring, so->bo, 0,
CP_LOAD_STATE_1_STATE_TYPE(ST_SHADER), 0);
}
for (i = 0; i < sz; i++) {
OUT_RING(ring, bin[i]);
}
}
 
void
fd3_program_emit(struct fd_ringbuffer *ring, struct fd3_emit *emit,
int nr, struct pipe_surface **bufs)
{
const struct ir3_shader_variant *vp, *fp;
const struct ir3_info *vsi, *fsi;
enum a3xx_instrbuffermode fpbuffer, vpbuffer;
uint32_t fpbuffersz, vpbuffersz, fsoff;
uint32_t pos_regid, posz_regid, psize_regid, color_regid[4] = {0};
int constmode;
int i, j, k;
 
vp = fd3_emit_get_vp(emit);
 
if (emit->key.binning_pass) {
/* use dummy stateobj to simplify binning vs non-binning: */
static const struct ir3_shader_variant binning_fp = {};
fp = &binning_fp;
} else {
fp = fd3_emit_get_fp(emit);
}
 
vsi = &vp->info;
fsi = &fp->info;
 
fpbuffer = BUFFER;
vpbuffer = BUFFER;
fpbuffersz = fp->instrlen;
vpbuffersz = vp->instrlen;
 
/*
* Decide whether to use BUFFER or CACHE mode for VS and FS. It
* appears like 256 is the hard limit, but when the combined size
* exceeds 128 then blob will try to keep FS in BUFFER mode and
* switch to CACHE for VS until VS is too large. The blob seems
* to switch FS out of BUFFER mode at slightly under 128. But
* a bit fuzzy on the decision tree, so use slightly conservative
* limits.
*
* TODO check if these thresholds for BUFFER vs CACHE mode are the
* same for all a3xx or whether we need to consider the gpuid
*/
 
if ((fpbuffersz + vpbuffersz) > 128) {
if (fpbuffersz < 112) {
/* FP:BUFFER VP:CACHE */
vpbuffer = CACHE;
vpbuffersz = 256 - fpbuffersz;
} else if (vpbuffersz < 112) {
/* FP:CACHE VP:BUFFER */
fpbuffer = CACHE;
fpbuffersz = 256 - vpbuffersz;
} else {
/* FP:CACHE VP:CACHE */
vpbuffer = fpbuffer = CACHE;
vpbuffersz = fpbuffersz = 192;
}
}
 
if (fpbuffer == BUFFER) {
fsoff = 128 - fpbuffersz;
} else {
fsoff = 256 - fpbuffersz;
}
 
/* seems like vs->constlen + fs->constlen > 256, then CONSTMODE=1 */
constmode = ((vp->constlen + fp->constlen) > 256) ? 1 : 0;
 
pos_regid = ir3_find_output_regid(vp,
ir3_semantic_name(TGSI_SEMANTIC_POSITION, 0));
posz_regid = ir3_find_output_regid(fp,
ir3_semantic_name(TGSI_SEMANTIC_POSITION, 0));
psize_regid = ir3_find_output_regid(vp,
ir3_semantic_name(TGSI_SEMANTIC_PSIZE, 0));
if (fp->color0_mrt) {
color_regid[0] = color_regid[1] = color_regid[2] = color_regid[3] =
ir3_find_output_regid(fp, ir3_semantic_name(TGSI_SEMANTIC_COLOR, 0));
} else {
for (int i = 0; i < fp->outputs_count; i++) {
ir3_semantic sem = fp->outputs[i].semantic;
unsigned idx = sem2idx(sem);
if (sem2name(sem) != TGSI_SEMANTIC_COLOR)
continue;
assert(idx < 4);
color_regid[idx] = fp->outputs[i].regid;
}
}
 
/* adjust regids for alpha output formats. there is no alpha render
* format, so it's just treated like red
*/
for (i = 0; i < nr; i++)
if (util_format_is_alpha(pipe_surface_format(bufs[i])))
color_regid[i] += 3;
 
/* we could probably divide this up into things that need to be
* emitted if frag-prog is dirty vs if vert-prog is dirty..
*/
 
OUT_PKT0(ring, REG_A3XX_HLSQ_CONTROL_0_REG, 6);
OUT_RING(ring, A3XX_HLSQ_CONTROL_0_REG_FSTHREADSIZE(FOUR_QUADS) |
A3XX_HLSQ_CONTROL_0_REG_CONSTMODE(constmode) |
/* NOTE: I guess SHADERRESTART and CONSTFULLUPDATE maybe
* flush some caches? I think we only need to set those
* bits if we have updated const or shader..
*/
A3XX_HLSQ_CONTROL_0_REG_SPSHADERRESTART |
A3XX_HLSQ_CONTROL_0_REG_SPCONSTFULLUPDATE);
OUT_RING(ring, A3XX_HLSQ_CONTROL_1_REG_VSTHREADSIZE(TWO_QUADS) |
A3XX_HLSQ_CONTROL_1_REG_VSSUPERTHREADENABLE |
COND(fp->frag_coord, A3XX_HLSQ_CONTROL_1_REG_ZWCOORD));
OUT_RING(ring, A3XX_HLSQ_CONTROL_2_REG_PRIMALLOCTHRESHOLD(31));
OUT_RING(ring, A3XX_HLSQ_CONTROL_3_REG_REGID(fp->pos_regid));
OUT_RING(ring, A3XX_HLSQ_VS_CONTROL_REG_CONSTLENGTH(vp->constlen) |
A3XX_HLSQ_VS_CONTROL_REG_CONSTSTARTOFFSET(0) |
A3XX_HLSQ_VS_CONTROL_REG_INSTRLENGTH(vpbuffersz));
OUT_RING(ring, A3XX_HLSQ_FS_CONTROL_REG_CONSTLENGTH(fp->constlen) |
A3XX_HLSQ_FS_CONTROL_REG_CONSTSTARTOFFSET(128) |
A3XX_HLSQ_FS_CONTROL_REG_INSTRLENGTH(fpbuffersz));
 
OUT_PKT0(ring, REG_A3XX_SP_SP_CTRL_REG, 1);
OUT_RING(ring, A3XX_SP_SP_CTRL_REG_CONSTMODE(constmode) |
COND(emit->key.binning_pass, A3XX_SP_SP_CTRL_REG_BINNING) |
A3XX_SP_SP_CTRL_REG_SLEEPMODE(1) |
A3XX_SP_SP_CTRL_REG_L0MODE(0));
 
OUT_PKT0(ring, REG_A3XX_SP_VS_LENGTH_REG, 1);
OUT_RING(ring, A3XX_SP_VS_LENGTH_REG_SHADERLENGTH(vp->instrlen));
 
OUT_PKT0(ring, REG_A3XX_SP_VS_CTRL_REG0, 3);
OUT_RING(ring, A3XX_SP_VS_CTRL_REG0_THREADMODE(MULTI) |
A3XX_SP_VS_CTRL_REG0_INSTRBUFFERMODE(vpbuffer) |
COND(vpbuffer == CACHE, A3XX_SP_VS_CTRL_REG0_CACHEINVALID) |
A3XX_SP_VS_CTRL_REG0_HALFREGFOOTPRINT(vsi->max_half_reg + 1) |
A3XX_SP_VS_CTRL_REG0_FULLREGFOOTPRINT(vsi->max_reg + 1) |
A3XX_SP_VS_CTRL_REG0_INOUTREGOVERLAP(0) |
A3XX_SP_VS_CTRL_REG0_THREADSIZE(TWO_QUADS) |
A3XX_SP_VS_CTRL_REG0_SUPERTHREADMODE |
COND(vp->has_samp, A3XX_SP_VS_CTRL_REG0_PIXLODENABLE) |
A3XX_SP_VS_CTRL_REG0_LENGTH(vpbuffersz));
OUT_RING(ring, A3XX_SP_VS_CTRL_REG1_CONSTLENGTH(vp->constlen) |
A3XX_SP_VS_CTRL_REG1_INITIALOUTSTANDING(vp->total_in) |
A3XX_SP_VS_CTRL_REG1_CONSTFOOTPRINT(MAX2(vp->constlen + 1, 0)));
OUT_RING(ring, A3XX_SP_VS_PARAM_REG_POSREGID(pos_regid) |
A3XX_SP_VS_PARAM_REG_PSIZEREGID(psize_regid) |
A3XX_SP_VS_PARAM_REG_TOTALVSOUTVAR(align(fp->total_in, 4) / 4));
 
for (i = 0, j = -1; (i < 8) && (j < (int)fp->inputs_count); i++) {
uint32_t reg = 0;
 
OUT_PKT0(ring, REG_A3XX_SP_VS_OUT_REG(i), 1);
 
j = ir3_next_varying(fp, j);
if (j < fp->inputs_count) {
k = ir3_find_output(vp, fp->inputs[j].semantic);
reg |= A3XX_SP_VS_OUT_REG_A_REGID(vp->outputs[k].regid);
reg |= A3XX_SP_VS_OUT_REG_A_COMPMASK(fp->inputs[j].compmask);
}
 
j = ir3_next_varying(fp, j);
if (j < fp->inputs_count) {
k = ir3_find_output(vp, fp->inputs[j].semantic);
reg |= A3XX_SP_VS_OUT_REG_B_REGID(vp->outputs[k].regid);
reg |= A3XX_SP_VS_OUT_REG_B_COMPMASK(fp->inputs[j].compmask);
}
 
OUT_RING(ring, reg);
}
 
for (i = 0, j = -1; (i < 4) && (j < (int)fp->inputs_count); i++) {
uint32_t reg = 0;
 
OUT_PKT0(ring, REG_A3XX_SP_VS_VPC_DST_REG(i), 1);
 
j = ir3_next_varying(fp, j);
if (j < fp->inputs_count)
reg |= A3XX_SP_VS_VPC_DST_REG_OUTLOC0(fp->inputs[j].inloc);
j = ir3_next_varying(fp, j);
if (j < fp->inputs_count)
reg |= A3XX_SP_VS_VPC_DST_REG_OUTLOC1(fp->inputs[j].inloc);
j = ir3_next_varying(fp, j);
if (j < fp->inputs_count)
reg |= A3XX_SP_VS_VPC_DST_REG_OUTLOC2(fp->inputs[j].inloc);
j = ir3_next_varying(fp, j);
if (j < fp->inputs_count)
reg |= A3XX_SP_VS_VPC_DST_REG_OUTLOC3(fp->inputs[j].inloc);
 
OUT_RING(ring, reg);
}
 
OUT_PKT0(ring, REG_A3XX_SP_VS_OBJ_OFFSET_REG, 2);
OUT_RING(ring, A3XX_SP_VS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET(0) |
A3XX_SP_VS_OBJ_OFFSET_REG_SHADEROBJOFFSET(0));
OUT_RELOC(ring, vp->bo, 0, 0, 0); /* SP_VS_OBJ_START_REG */
 
if (emit->key.binning_pass) {
OUT_PKT0(ring, REG_A3XX_SP_FS_LENGTH_REG, 1);
OUT_RING(ring, 0x00000000);
 
OUT_PKT0(ring, REG_A3XX_SP_FS_CTRL_REG0, 2);
OUT_RING(ring, A3XX_SP_FS_CTRL_REG0_THREADMODE(MULTI) |
A3XX_SP_FS_CTRL_REG0_INSTRBUFFERMODE(BUFFER));
OUT_RING(ring, 0x00000000);
 
OUT_PKT0(ring, REG_A3XX_SP_FS_OBJ_OFFSET_REG, 1);
OUT_RING(ring, A3XX_SP_FS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET(128) |
A3XX_SP_FS_OBJ_OFFSET_REG_SHADEROBJOFFSET(0));
} else {
OUT_PKT0(ring, REG_A3XX_SP_FS_LENGTH_REG, 1);
OUT_RING(ring, A3XX_SP_FS_LENGTH_REG_SHADERLENGTH(fp->instrlen));
 
OUT_PKT0(ring, REG_A3XX_SP_FS_CTRL_REG0, 2);
OUT_RING(ring, A3XX_SP_FS_CTRL_REG0_THREADMODE(MULTI) |
A3XX_SP_FS_CTRL_REG0_INSTRBUFFERMODE(fpbuffer) |
COND(fpbuffer == CACHE, A3XX_SP_FS_CTRL_REG0_CACHEINVALID) |
A3XX_SP_FS_CTRL_REG0_HALFREGFOOTPRINT(fsi->max_half_reg + 1) |
A3XX_SP_FS_CTRL_REG0_FULLREGFOOTPRINT(fsi->max_reg + 1) |
A3XX_SP_FS_CTRL_REG0_INOUTREGOVERLAP(1) |
A3XX_SP_FS_CTRL_REG0_THREADSIZE(FOUR_QUADS) |
A3XX_SP_FS_CTRL_REG0_SUPERTHREADMODE |
COND(fp->has_samp > 0, A3XX_SP_FS_CTRL_REG0_PIXLODENABLE) |
A3XX_SP_FS_CTRL_REG0_LENGTH(fpbuffersz));
OUT_RING(ring, A3XX_SP_FS_CTRL_REG1_CONSTLENGTH(fp->constlen) |
A3XX_SP_FS_CTRL_REG1_INITIALOUTSTANDING(fp->total_in) |
A3XX_SP_FS_CTRL_REG1_CONSTFOOTPRINT(MAX2(fp->constlen + 1, 0)) |
A3XX_SP_FS_CTRL_REG1_HALFPRECVAROFFSET(63));
 
OUT_PKT0(ring, REG_A3XX_SP_FS_OBJ_OFFSET_REG, 2);
OUT_RING(ring, A3XX_SP_FS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET(
MAX2(128, vp->constlen)) |
A3XX_SP_FS_OBJ_OFFSET_REG_SHADEROBJOFFSET(fsoff));
OUT_RELOC(ring, fp->bo, 0, 0, 0); /* SP_FS_OBJ_START_REG */
}
 
OUT_PKT0(ring, REG_A3XX_SP_FS_OUTPUT_REG, 1);
OUT_RING(ring,
COND(fp->writes_pos, A3XX_SP_FS_OUTPUT_REG_DEPTH_ENABLE) |
A3XX_SP_FS_OUTPUT_REG_DEPTH_REGID(posz_regid) |
A3XX_SP_FS_OUTPUT_REG_MRT(MAX2(1, nr) - 1));
 
OUT_PKT0(ring, REG_A3XX_SP_FS_MRT_REG(0), 4);
for (i = 0; i < 4; i++) {
uint32_t mrt_reg = A3XX_SP_FS_MRT_REG_REGID(color_regid[i]) |
COND(fp->key.half_precision, A3XX_SP_FS_MRT_REG_HALF_PRECISION);
 
if (i < nr) {
enum pipe_format fmt = pipe_surface_format(bufs[i]);
mrt_reg |= COND(util_format_is_pure_uint(fmt), A3XX_SP_FS_MRT_REG_UINT) |
COND(util_format_is_pure_sint(fmt), A3XX_SP_FS_MRT_REG_SINT);
}
OUT_RING(ring, mrt_reg);
}
 
if (emit->key.binning_pass) {
OUT_PKT0(ring, REG_A3XX_VPC_ATTR, 2);
OUT_RING(ring, A3XX_VPC_ATTR_THRDASSIGN(1) |
A3XX_VPC_ATTR_LMSIZE(1) |
COND(vp->writes_psize, A3XX_VPC_ATTR_PSIZE));
OUT_RING(ring, 0x00000000);
} else {
uint32_t vinterp[4], flatshade[2], vpsrepl[4];
 
memset(vinterp, 0, sizeof(vinterp));
memset(flatshade, 0, sizeof(flatshade));
memset(vpsrepl, 0, sizeof(vpsrepl));
 
/* figure out VARYING_INTERP / FLAT_SHAD register values: */
for (j = -1; (j = ir3_next_varying(fp, j)) < (int)fp->inputs_count; ) {
uint32_t interp = fp->inputs[j].interpolate;
 
/* TODO might be cleaner to just +8 in SP_VS_VPC_DST_REG
* instead.. rather than -8 everywhere else..
*/
uint32_t inloc = fp->inputs[j].inloc - 8;
 
/* currently assuming varyings aligned to 4 (not
* packed):
*/
debug_assert((inloc % 4) == 0);
 
if ((interp == TGSI_INTERPOLATE_CONSTANT) ||
((interp == TGSI_INTERPOLATE_COLOR) && emit->rasterflat)) {
uint32_t loc = inloc;
for (i = 0; i < 4; i++, loc++) {
vinterp[loc / 16] |= FLAT << ((loc % 16) * 2);
flatshade[loc / 32] |= 1 << (loc % 32);
}
}
 
/* Replace the .xy coordinates with S/T from the point sprite. Set
* interpolation bits for .zw such that they become .01
*/
if (emit->sprite_coord_enable & (1 << sem2idx(fp->inputs[j].semantic))) {
vpsrepl[inloc / 16] |= (emit->sprite_coord_mode ? 0x0d : 0x09)
<< ((inloc % 16) * 2);
vinterp[(inloc + 2) / 16] |= 2 << (((inloc + 2) % 16) * 2);
vinterp[(inloc + 3) / 16] |= 3 << (((inloc + 3) % 16) * 2);
}
}
 
OUT_PKT0(ring, REG_A3XX_VPC_ATTR, 2);
OUT_RING(ring, A3XX_VPC_ATTR_TOTALATTR(fp->total_in) |
A3XX_VPC_ATTR_THRDASSIGN(1) |
A3XX_VPC_ATTR_LMSIZE(1) |
COND(vp->writes_psize, A3XX_VPC_ATTR_PSIZE));
OUT_RING(ring, A3XX_VPC_PACK_NUMFPNONPOSVAR(fp->total_in) |
A3XX_VPC_PACK_NUMNONPOSVSVAR(fp->total_in));
 
OUT_PKT0(ring, REG_A3XX_VPC_VARYING_INTERP_MODE(0), 4);
OUT_RING(ring, vinterp[0]); /* VPC_VARYING_INTERP[0].MODE */
OUT_RING(ring, vinterp[1]); /* VPC_VARYING_INTERP[1].MODE */
OUT_RING(ring, vinterp[2]); /* VPC_VARYING_INTERP[2].MODE */
OUT_RING(ring, vinterp[3]); /* VPC_VARYING_INTERP[3].MODE */
 
OUT_PKT0(ring, REG_A3XX_VPC_VARYING_PS_REPL_MODE(0), 4);
OUT_RING(ring, vpsrepl[0]); /* VPC_VARYING_PS_REPL[0].MODE */
OUT_RING(ring, vpsrepl[1]); /* VPC_VARYING_PS_REPL[1].MODE */
OUT_RING(ring, vpsrepl[2]); /* VPC_VARYING_PS_REPL[2].MODE */
OUT_RING(ring, vpsrepl[3]); /* VPC_VARYING_PS_REPL[3].MODE */
 
OUT_PKT0(ring, REG_A3XX_SP_FS_FLAT_SHAD_MODE_REG_0, 2);
OUT_RING(ring, flatshade[0]); /* SP_FS_FLAT_SHAD_MODE_REG_0 */
OUT_RING(ring, flatshade[1]); /* SP_FS_FLAT_SHAD_MODE_REG_1 */
}
 
OUT_PKT0(ring, REG_A3XX_VFD_VS_THREADING_THRESHOLD, 1);
OUT_RING(ring, A3XX_VFD_VS_THREADING_THRESHOLD_REGID_THRESHOLD(15) |
A3XX_VFD_VS_THREADING_THRESHOLD_REGID_VTXCNT(252));
 
if (vpbuffer == BUFFER)
emit_shader(ring, vp);
 
OUT_PKT0(ring, REG_A3XX_VFD_PERFCOUNTER0_SELECT, 1);
OUT_RING(ring, 0x00000000); /* VFD_PERFCOUNTER0_SELECT */
 
if (!emit->key.binning_pass) {
if (fpbuffer == BUFFER)
emit_shader(ring, fp);
 
OUT_PKT0(ring, REG_A3XX_VFD_PERFCOUNTER0_SELECT, 1);
OUT_RING(ring, 0x00000000); /* VFD_PERFCOUNTER0_SELECT */
}
}
 
void
fd3_prog_init(struct pipe_context *pctx)
{
pctx->create_fs_state = fd3_fp_state_create;
pctx->delete_fs_state = fd3_fp_state_delete;
 
pctx->create_vs_state = fd3_vp_state_create;
pctx->delete_vs_state = fd3_vp_state_delete;
 
fd_prog_init(pctx);
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a3xx/fd3_program.h
0,0 → 1,53
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FD3_PROGRAM_H_
#define FD3_PROGRAM_H_
 
#include "pipe/p_context.h"
#include "freedreno_context.h"
#include "ir3_shader.h"
 
struct fd3_shader_stateobj {
struct ir3_shader *shader;
};
 
struct fd3_emit;
 
void fd3_program_emit(struct fd_ringbuffer *ring, struct fd3_emit *emit,
int nr, struct pipe_surface **bufs);
 
void fd3_prog_init(struct pipe_context *pctx);
 
static inline struct ir3_shader_variant *
fd3_shader_variant(struct fd3_shader_stateobj *so, struct ir3_shader_key key)
{
return ir3_shader_variant(so->shader, key);
}
 
#endif /* FD3_PROGRAM_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a3xx/fd3_query.c
0,0 → 1,138
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "freedreno_query_hw.h"
#include "freedreno_context.h"
#include "freedreno_util.h"
 
#include "fd3_query.h"
#include "fd3_format.h"
 
 
struct fd_rb_samp_ctrs {
uint64_t ctr[16];
};
 
/*
* Occlusion Query:
*
* OCCLUSION_COUNTER and OCCLUSION_PREDICATE differ only in how they
* interpret results
*/
 
static struct fd_hw_sample *
occlusion_get_sample(struct fd_context *ctx, struct fd_ringbuffer *ring)
{
struct fd_hw_sample *samp =
fd_hw_sample_init(ctx, sizeof(struct fd_rb_samp_ctrs));
 
/* Set RB_SAMPLE_COUNT_ADDR to samp->offset plus value of
* HW_QUERY_BASE_REG register:
*/
OUT_PKT3(ring, CP_SET_CONSTANT, 3);
OUT_RING(ring, CP_REG(REG_A3XX_RB_SAMPLE_COUNT_ADDR) | 0x80000000);
OUT_RING(ring, HW_QUERY_BASE_REG);
OUT_RING(ring, samp->offset);
 
OUT_PKT0(ring, REG_A3XX_RB_SAMPLE_COUNT_CONTROL, 1);
OUT_RING(ring, A3XX_RB_SAMPLE_COUNT_CONTROL_COPY);
 
OUT_PKT3(ring, CP_DRAW_INDX, 3);
OUT_RING(ring, 0x00000000);
OUT_RING(ring, DRAW(DI_PT_POINTLIST_A2XX, DI_SRC_SEL_AUTO_INDEX,
INDEX_SIZE_IGN, USE_VISIBILITY, 0));
OUT_RING(ring, 0); /* NumIndices */
 
fd_event_write(ctx, ring, ZPASS_DONE);
 
OUT_PKT0(ring, REG_A3XX_RBBM_PERFCTR_CTL, 1);
OUT_RING(ring, A3XX_RBBM_PERFCTR_CTL_ENABLE);
 
OUT_PKT0(ring, REG_A3XX_VBIF_PERF_CNT_EN, 1);
OUT_RING(ring, A3XX_VBIF_PERF_CNT_EN_CNT0 |
A3XX_VBIF_PERF_CNT_EN_CNT1 |
A3XX_VBIF_PERF_CNT_EN_PWRCNT0 |
A3XX_VBIF_PERF_CNT_EN_PWRCNT1 |
A3XX_VBIF_PERF_CNT_EN_PWRCNT2);
 
return samp;
}
 
static uint64_t
count_samples(const struct fd_rb_samp_ctrs *start,
const struct fd_rb_samp_ctrs *end)
{
uint64_t n = 0;
unsigned i;
 
/* not quite sure what all of these are, possibly different
* counters for each MRT render target:
*/
for (i = 0; i < 16; i += 4)
n += end->ctr[i] - start->ctr[i];
 
return n;
}
 
static void
occlusion_counter_accumulate_result(struct fd_context *ctx,
const void *start, const void *end,
union pipe_query_result *result)
{
uint64_t n = count_samples(start, end);
result->u64 += n;
}
 
static void
occlusion_predicate_accumulate_result(struct fd_context *ctx,
const void *start, const void *end,
union pipe_query_result *result)
{
uint64_t n = count_samples(start, end);
result->b |= (n > 0);
}
 
static const struct fd_hw_sample_provider occlusion_counter = {
.query_type = PIPE_QUERY_OCCLUSION_COUNTER,
.active = FD_STAGE_DRAW,
.get_sample = occlusion_get_sample,
.accumulate_result = occlusion_counter_accumulate_result,
};
 
static const struct fd_hw_sample_provider occlusion_predicate = {
.query_type = PIPE_QUERY_OCCLUSION_PREDICATE,
.active = FD_STAGE_DRAW,
.get_sample = occlusion_get_sample,
.accumulate_result = occlusion_predicate_accumulate_result,
};
 
void fd3_query_context_init(struct pipe_context *pctx)
{
fd_hw_query_register_provider(pctx, &occlusion_counter);
fd_hw_query_register_provider(pctx, &occlusion_predicate);
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a3xx/fd3_query.h
0,0 → 1,36
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FD3_QUERY_H_
#define FD3_QUERY_H_
 
#include "pipe/p_context.h"
 
void fd3_query_context_init(struct pipe_context *pctx);
 
#endif /* FD3_QUERY_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a3xx/fd3_rasterizer.c
0,0 → 1,104
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
 
#include "pipe/p_state.h"
#include "util/u_string.h"
#include "util/u_memory.h"
 
#include "fd3_rasterizer.h"
#include "fd3_context.h"
#include "fd3_format.h"
 
void *
fd3_rasterizer_state_create(struct pipe_context *pctx,
const struct pipe_rasterizer_state *cso)
{
struct fd3_rasterizer_stateobj *so;
float psize_min, psize_max;
 
so = CALLOC_STRUCT(fd3_rasterizer_stateobj);
if (!so)
return NULL;
 
so->base = *cso;
 
if (cso->point_size_per_vertex) {
psize_min = util_get_min_point_size(cso);
psize_max = 4092;
} else {
/* Force the point size to be as if the vertex output was disabled. */
psize_min = cso->point_size;
psize_max = cso->point_size;
}
 
/*
if (cso->line_stipple_enable) {
??? TODO line stipple
}
TODO cso->half_pixel_center
if (cso->multisample)
TODO
*/
so->gras_cl_clip_cntl = A3XX_GRAS_CL_CLIP_CNTL_IJ_PERSP_CENTER; /* ??? */
so->gras_su_point_minmax =
A3XX_GRAS_SU_POINT_MINMAX_MIN(psize_min) |
A3XX_GRAS_SU_POINT_MINMAX_MAX(psize_max);
so->gras_su_point_size = A3XX_GRAS_SU_POINT_SIZE(cso->point_size);
so->gras_su_poly_offset_scale =
A3XX_GRAS_SU_POLY_OFFSET_SCALE_VAL(cso->offset_scale);
so->gras_su_poly_offset_offset =
A3XX_GRAS_SU_POLY_OFFSET_OFFSET(cso->offset_units);
 
so->gras_su_mode_control =
A3XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH(cso->line_width/2.0);
 
so->pc_prim_vtx_cntl =
A3XX_PC_PRIM_VTX_CNTL_POLYMODE_FRONT_PTYPE(fd_polygon_mode(cso->fill_front)) |
A3XX_PC_PRIM_VTX_CNTL_POLYMODE_BACK_PTYPE(fd_polygon_mode(cso->fill_back));
 
if (cso->fill_front != PIPE_POLYGON_MODE_FILL ||
cso->fill_back != PIPE_POLYGON_MODE_FILL)
so->pc_prim_vtx_cntl |= A3XX_PC_PRIM_VTX_CNTL_POLYMODE_ENABLE;
 
if (cso->cull_face & PIPE_FACE_FRONT)
so->gras_su_mode_control |= A3XX_GRAS_SU_MODE_CONTROL_CULL_FRONT;
if (cso->cull_face & PIPE_FACE_BACK)
so->gras_su_mode_control |= A3XX_GRAS_SU_MODE_CONTROL_CULL_BACK;
if (!cso->front_ccw)
so->gras_su_mode_control |= A3XX_GRAS_SU_MODE_CONTROL_FRONT_CW;
if (!cso->flatshade_first)
so->pc_prim_vtx_cntl |= A3XX_PC_PRIM_VTX_CNTL_PROVOKING_VTX_LAST;
 
if (cso->offset_tri)
so->gras_su_mode_control |= A3XX_GRAS_SU_MODE_CONTROL_POLY_OFFSET;
if (!cso->depth_clip)
so->gras_cl_clip_cntl |= A3XX_GRAS_CL_CLIP_CNTL_CLIP_DISABLE;
 
return so;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a3xx/fd3_rasterizer.h
0,0 → 1,56
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FD3_RASTERIZER_H_
#define FD3_RASTERIZER_H_
 
#include "pipe/p_state.h"
#include "pipe/p_context.h"
 
struct fd3_rasterizer_stateobj {
struct pipe_rasterizer_state base;
uint32_t gras_su_point_minmax;
uint32_t gras_su_point_size;
uint32_t gras_su_poly_offset_scale;
uint32_t gras_su_poly_offset_offset;
 
uint32_t gras_su_mode_control;
uint32_t gras_cl_clip_cntl;
uint32_t pc_prim_vtx_cntl;
};
 
static INLINE struct fd3_rasterizer_stateobj *
fd3_rasterizer_stateobj(struct pipe_rasterizer_state *rast)
{
return (struct fd3_rasterizer_stateobj *)rast;
}
 
void * fd3_rasterizer_state_create(struct pipe_context *pctx,
const struct pipe_rasterizer_state *cso);
 
#endif /* FD3_RASTERIZER_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a3xx/fd3_screen.c
0,0 → 1,109
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "pipe/p_screen.h"
#include "util/u_format.h"
 
#include "fd3_screen.h"
#include "fd3_context.h"
#include "fd3_format.h"
 
static boolean
fd3_screen_is_format_supported(struct pipe_screen *pscreen,
enum pipe_format format,
enum pipe_texture_target target,
unsigned sample_count,
unsigned usage)
{
unsigned retval = 0;
 
if ((target >= PIPE_MAX_TEXTURE_TYPES) ||
(sample_count > 1) || /* TODO add MSAA */
!util_format_is_supported(format, usage)) {
DBG("not supported: format=%s, target=%d, sample_count=%d, usage=%x",
util_format_name(format), target, sample_count, usage);
return FALSE;
}
 
if ((usage & PIPE_BIND_VERTEX_BUFFER) &&
(fd3_pipe2vtx(format) != ~0)) {
retval |= PIPE_BIND_VERTEX_BUFFER;
}
 
if ((usage & PIPE_BIND_SAMPLER_VIEW) &&
(fd3_pipe2tex(format) != ~0)) {
retval |= PIPE_BIND_SAMPLER_VIEW;
}
 
if ((usage & (PIPE_BIND_RENDER_TARGET |
PIPE_BIND_DISPLAY_TARGET |
PIPE_BIND_SCANOUT |
PIPE_BIND_SHARED |
PIPE_BIND_BLENDABLE)) &&
(fd3_pipe2color(format) != ~0) &&
(fd3_pipe2tex(format) != ~0)) {
retval |= usage & (PIPE_BIND_RENDER_TARGET |
PIPE_BIND_DISPLAY_TARGET |
PIPE_BIND_SCANOUT |
PIPE_BIND_SHARED);
if (!util_format_is_pure_integer(format))
retval |= usage & PIPE_BIND_BLENDABLE;
}
 
if ((usage & PIPE_BIND_DEPTH_STENCIL) &&
(fd_pipe2depth(format) != ~0) &&
(fd3_pipe2tex(format) != ~0)) {
retval |= PIPE_BIND_DEPTH_STENCIL;
}
 
if ((usage & PIPE_BIND_INDEX_BUFFER) &&
(fd_pipe2index(format) != ~0)) {
retval |= PIPE_BIND_INDEX_BUFFER;
}
 
if (usage & PIPE_BIND_TRANSFER_READ)
retval |= PIPE_BIND_TRANSFER_READ;
if (usage & PIPE_BIND_TRANSFER_WRITE)
retval |= PIPE_BIND_TRANSFER_WRITE;
 
if (retval != usage) {
DBG("not supported: format=%s, target=%d, sample_count=%d, "
"usage=%x, retval=%x", util_format_name(format),
target, sample_count, usage, retval);
}
 
return retval == usage;
}
 
void
fd3_screen_init(struct pipe_screen *pscreen)
{
fd_screen(pscreen)->max_rts = 4;
pscreen->context_create = fd3_context_create;
pscreen->is_format_supported = fd3_screen_is_format_supported;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a3xx/fd3_screen.h
0,0 → 1,36
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FD3_SCREEN_H_
#define FD3_SCREEN_H_
 
#include "pipe/p_screen.h"
 
void fd3_screen_init(struct pipe_screen *pscreen);
 
#endif /* FD3_SCREEN_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a3xx/fd3_texture.c
0,0 → 1,306
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "pipe/p_state.h"
#include "util/u_string.h"
#include "util/u_memory.h"
#include "util/u_inlines.h"
#include "util/u_format.h"
 
#include "fd3_texture.h"
#include "fd3_format.h"
 
static enum a3xx_tex_clamp
tex_clamp(unsigned wrap, bool clamp_to_edge)
{
/* Hardware does not support _CLAMP, but we emulate it: */
if (wrap == PIPE_TEX_WRAP_CLAMP) {
wrap = (clamp_to_edge) ?
PIPE_TEX_WRAP_CLAMP_TO_EDGE : PIPE_TEX_WRAP_CLAMP_TO_BORDER;
}
 
switch (wrap) {
case PIPE_TEX_WRAP_REPEAT:
return A3XX_TEX_REPEAT;
case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
return A3XX_TEX_CLAMP_TO_EDGE;
case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
return A3XX_TEX_CLAMP_TO_BORDER;
case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
/* only works for PoT.. need to emulate otherwise! */
return A3XX_TEX_MIRROR_CLAMP;
case PIPE_TEX_WRAP_MIRROR_REPEAT:
return A3XX_TEX_MIRROR_REPEAT;
case PIPE_TEX_WRAP_MIRROR_CLAMP:
case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
/* these two we could perhaps emulate, but we currently
* just don't advertise PIPE_CAP_TEXTURE_MIRROR_CLAMP
*/
default:
DBG("invalid wrap: %u", wrap);
return 0;
}
}
 
static enum a3xx_tex_filter
tex_filter(unsigned filter, bool aniso)
{
switch (filter) {
case PIPE_TEX_FILTER_NEAREST:
return A3XX_TEX_NEAREST;
case PIPE_TEX_FILTER_LINEAR:
return aniso ? A3XX_TEX_ANISO : A3XX_TEX_LINEAR;
default:
DBG("invalid filter: %u", filter);
return 0;
}
}
 
static void *
fd3_sampler_state_create(struct pipe_context *pctx,
const struct pipe_sampler_state *cso)
{
struct fd3_sampler_stateobj *so = CALLOC_STRUCT(fd3_sampler_stateobj);
unsigned aniso = util_last_bit(MIN2(cso->max_anisotropy >> 1, 8));
bool miplinear = false;
bool clamp_to_edge;
 
if (!so)
return NULL;
 
if (cso->min_mip_filter == PIPE_TEX_MIPFILTER_LINEAR)
miplinear = true;
 
so->base = *cso;
 
/*
* For nearest filtering, _CLAMP means _CLAMP_TO_EDGE; for linear
* filtering, _CLAMP means _CLAMP_TO_BORDER while additionally
* clamping the texture coordinates to [0.0, 1.0].
*
* The clamping will be taken care of in the shaders. There are two
* filters here, but let the minification one has a say.
*/
clamp_to_edge = (cso->min_img_filter == PIPE_TEX_FILTER_NEAREST);
if (!clamp_to_edge) {
so->saturate_s = (cso->wrap_s == PIPE_TEX_WRAP_CLAMP);
so->saturate_t = (cso->wrap_t == PIPE_TEX_WRAP_CLAMP);
so->saturate_r = (cso->wrap_r == PIPE_TEX_WRAP_CLAMP);
}
 
so->texsamp0 =
COND(!cso->normalized_coords, A3XX_TEX_SAMP_0_UNNORM_COORDS) |
COND(miplinear, A3XX_TEX_SAMP_0_MIPFILTER_LINEAR) |
A3XX_TEX_SAMP_0_XY_MAG(tex_filter(cso->mag_img_filter, aniso)) |
A3XX_TEX_SAMP_0_XY_MIN(tex_filter(cso->min_img_filter, aniso)) |
A3XX_TEX_SAMP_0_ANISO(aniso) |
A3XX_TEX_SAMP_0_WRAP_S(tex_clamp(cso->wrap_s, clamp_to_edge)) |
A3XX_TEX_SAMP_0_WRAP_T(tex_clamp(cso->wrap_t, clamp_to_edge)) |
A3XX_TEX_SAMP_0_WRAP_R(tex_clamp(cso->wrap_r, clamp_to_edge));
 
if (cso->compare_mode)
so->texsamp0 |= A3XX_TEX_SAMP_0_COMPARE_FUNC(cso->compare_func); /* maps 1:1 */
 
if (cso->min_mip_filter != PIPE_TEX_MIPFILTER_NONE) {
so->texsamp1 =
A3XX_TEX_SAMP_1_LOD_BIAS(cso->lod_bias) |
A3XX_TEX_SAMP_1_MIN_LOD(cso->min_lod) |
A3XX_TEX_SAMP_1_MAX_LOD(cso->max_lod);
} else {
so->texsamp1 = 0x00000000;
}
 
return so;
}
 
static void
fd3_sampler_states_bind(struct pipe_context *pctx,
unsigned shader, unsigned start,
unsigned nr, void **hwcso)
{
struct fd_context *ctx = fd_context(pctx);
struct fd3_context *fd3_ctx = fd3_context(ctx);
uint16_t saturate_s = 0, saturate_t = 0, saturate_r = 0;
unsigned i;
 
for (i = 0; i < nr; i++) {
if (hwcso[i]) {
struct fd3_sampler_stateobj *sampler =
fd3_sampler_stateobj(hwcso[i]);
if (sampler->saturate_s)
saturate_s |= (1 << i);
if (sampler->saturate_t)
saturate_t |= (1 << i);
if (sampler->saturate_r)
saturate_r |= (1 << i);
}
}
 
fd_sampler_states_bind(pctx, shader, start, nr, hwcso);
 
if (shader == PIPE_SHADER_FRAGMENT) {
fd3_ctx->fsaturate =
(saturate_s != 0) ||
(saturate_t != 0) ||
(saturate_r != 0);
fd3_ctx->fsaturate_s = saturate_s;
fd3_ctx->fsaturate_t = saturate_t;
fd3_ctx->fsaturate_r = saturate_r;
} else if (shader == PIPE_SHADER_VERTEX) {
fd3_ctx->vsaturate =
(saturate_s != 0) ||
(saturate_t != 0) ||
(saturate_r != 0);
fd3_ctx->vsaturate_s = saturate_s;
fd3_ctx->vsaturate_t = saturate_t;
fd3_ctx->vsaturate_r = saturate_r;
}
}
 
static enum a3xx_tex_type
tex_type(unsigned target)
{
switch (target) {
default:
assert(0);
case PIPE_BUFFER:
case PIPE_TEXTURE_1D:
case PIPE_TEXTURE_1D_ARRAY:
return A3XX_TEX_1D;
case PIPE_TEXTURE_RECT:
case PIPE_TEXTURE_2D:
case PIPE_TEXTURE_2D_ARRAY:
return A3XX_TEX_2D;
case PIPE_TEXTURE_3D:
return A3XX_TEX_3D;
case PIPE_TEXTURE_CUBE:
case PIPE_TEXTURE_CUBE_ARRAY:
return A3XX_TEX_CUBE;
}
}
 
static struct pipe_sampler_view *
fd3_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc,
const struct pipe_sampler_view *cso)
{
struct fd3_pipe_sampler_view *so = CALLOC_STRUCT(fd3_pipe_sampler_view);
struct fd_resource *rsc = fd_resource(prsc);
unsigned lvl = cso->u.tex.first_level;
unsigned miplevels = cso->u.tex.last_level - lvl;
uint32_t sz2 = 0;
 
if (!so)
return NULL;
 
so->base = *cso;
pipe_reference(NULL, &prsc->reference);
so->base.texture = prsc;
so->base.reference.count = 1;
so->base.context = pctx;
 
so->texconst0 =
A3XX_TEX_CONST_0_TYPE(tex_type(prsc->target)) |
A3XX_TEX_CONST_0_FMT(fd3_pipe2tex(cso->format)) |
A3XX_TEX_CONST_0_MIPLVLS(miplevels) |
fd3_tex_swiz(cso->format, cso->swizzle_r, cso->swizzle_g,
cso->swizzle_b, cso->swizzle_a);
 
if (util_format_is_srgb(cso->format))
so->texconst0 |= A3XX_TEX_CONST_0_SRGB;
 
so->texconst1 =
A3XX_TEX_CONST_1_FETCHSIZE(fd3_pipe2fetchsize(cso->format)) |
A3XX_TEX_CONST_1_WIDTH(u_minify(prsc->width0, lvl)) |
A3XX_TEX_CONST_1_HEIGHT(u_minify(prsc->height0, lvl));
/* when emitted, A3XX_TEX_CONST_2_INDX() must be OR'd in: */
so->texconst2 =
A3XX_TEX_CONST_2_PITCH(rsc->slices[lvl].pitch * rsc->cpp);
switch (prsc->target) {
case PIPE_TEXTURE_1D_ARRAY:
case PIPE_TEXTURE_2D_ARRAY:
so->texconst3 =
A3XX_TEX_CONST_3_DEPTH(prsc->array_size - 1) |
A3XX_TEX_CONST_3_LAYERSZ1(rsc->slices[0].size0);
break;
case PIPE_TEXTURE_3D:
so->texconst3 =
A3XX_TEX_CONST_3_DEPTH(u_minify(prsc->depth0, lvl)) |
A3XX_TEX_CONST_3_LAYERSZ1(rsc->slices[lvl].size0);
while (lvl < cso->u.tex.last_level && sz2 != rsc->slices[lvl+1].size0)
sz2 = rsc->slices[++lvl].size0;
so->texconst3 |= A3XX_TEX_CONST_3_LAYERSZ2(sz2);
break;
default:
so->texconst3 = 0x00000000;
break;
}
 
return &so->base;
}
 
static void
fd3_set_sampler_views(struct pipe_context *pctx, unsigned shader,
unsigned start, unsigned nr,
struct pipe_sampler_view **views)
{
struct fd_context *ctx = fd_context(pctx);
struct fd3_context *fd3_ctx = fd3_context(ctx);
struct fd_texture_stateobj *tex;
uint16_t integer_s = 0, *ptr;
int i;
 
fd_set_sampler_views(pctx, shader, start, nr, views);
 
switch (shader) {
case PIPE_SHADER_FRAGMENT:
tex = &ctx->fragtex;
ptr = &fd3_ctx->finteger_s;
break;
case PIPE_SHADER_VERTEX:
tex = &ctx->verttex;
ptr = &fd3_ctx->vinteger_s;
break;
default:
return;
}
 
for (i = 0; i < tex->num_textures; i++)
if (util_format_is_pure_integer(tex->textures[i]->format))
integer_s |= 1 << i;
*ptr = integer_s;
}
 
 
void
fd3_texture_init(struct pipe_context *pctx)
{
pctx->create_sampler_state = fd3_sampler_state_create;
pctx->bind_sampler_states = fd3_sampler_states_bind;
pctx->create_sampler_view = fd3_sampler_view_create;
pctx->set_sampler_views = fd3_set_sampler_views;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a3xx/fd3_texture.h
0,0 → 1,68
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FD3_TEXTURE_H_
#define FD3_TEXTURE_H_
 
#include "pipe/p_context.h"
 
#include "freedreno_texture.h"
#include "freedreno_resource.h"
 
#include "fd3_context.h"
#include "fd3_format.h"
 
struct fd3_sampler_stateobj {
struct pipe_sampler_state base;
uint32_t texsamp0, texsamp1;
bool saturate_s, saturate_t, saturate_r;
};
 
static INLINE struct fd3_sampler_stateobj *
fd3_sampler_stateobj(struct pipe_sampler_state *samp)
{
return (struct fd3_sampler_stateobj *)samp;
}
 
struct fd3_pipe_sampler_view {
struct pipe_sampler_view base;
uint32_t texconst0, texconst1, texconst2, texconst3;
};
 
static INLINE struct fd3_pipe_sampler_view *
fd3_pipe_sampler_view(struct pipe_sampler_view *pview)
{
return (struct fd3_pipe_sampler_view *)pview;
}
 
unsigned fd3_get_const_idx(struct fd_context *ctx,
struct fd_texture_stateobj *tex, unsigned samp_id);
 
void fd3_texture_init(struct pipe_context *pctx);
 
#endif /* FD3_TEXTURE_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a3xx/fd3_zsa.c
0,0 → 1,104
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
 
#include "pipe/p_state.h"
#include "util/u_string.h"
#include "util/u_memory.h"
 
#include "fd3_zsa.h"
#include "fd3_context.h"
#include "fd3_format.h"
 
void *
fd3_zsa_state_create(struct pipe_context *pctx,
const struct pipe_depth_stencil_alpha_state *cso)
{
struct fd3_zsa_stateobj *so;
 
so = CALLOC_STRUCT(fd3_zsa_stateobj);
if (!so)
return NULL;
 
so->base = *cso;
 
so->rb_depth_control |=
A3XX_RB_DEPTH_CONTROL_ZFUNC(cso->depth.func); /* maps 1:1 */
 
if (cso->depth.enabled)
so->rb_depth_control |=
A3XX_RB_DEPTH_CONTROL_Z_ENABLE |
A3XX_RB_DEPTH_CONTROL_Z_TEST_ENABLE;
 
if (cso->depth.writemask)
so->rb_depth_control |= A3XX_RB_DEPTH_CONTROL_Z_WRITE_ENABLE;
 
if (cso->stencil[0].enabled) {
const struct pipe_stencil_state *s = &cso->stencil[0];
 
so->rb_stencil_control |=
A3XX_RB_STENCIL_CONTROL_STENCIL_READ |
A3XX_RB_STENCIL_CONTROL_STENCIL_ENABLE |
A3XX_RB_STENCIL_CONTROL_FUNC(s->func) | /* maps 1:1 */
A3XX_RB_STENCIL_CONTROL_FAIL(fd_stencil_op(s->fail_op)) |
A3XX_RB_STENCIL_CONTROL_ZPASS(fd_stencil_op(s->zpass_op)) |
A3XX_RB_STENCIL_CONTROL_ZFAIL(fd_stencil_op(s->zfail_op));
so->rb_stencilrefmask |=
0xff000000 | /* ??? */
A3XX_RB_STENCILREFMASK_STENCILWRITEMASK(s->writemask) |
A3XX_RB_STENCILREFMASK_STENCILMASK(s->valuemask);
 
if (cso->stencil[1].enabled) {
const struct pipe_stencil_state *bs = &cso->stencil[1];
 
so->rb_stencil_control |=
A3XX_RB_STENCIL_CONTROL_STENCIL_ENABLE_BF |
A3XX_RB_STENCIL_CONTROL_FUNC_BF(bs->func) | /* maps 1:1 */
A3XX_RB_STENCIL_CONTROL_FAIL_BF(fd_stencil_op(bs->fail_op)) |
A3XX_RB_STENCIL_CONTROL_ZPASS_BF(fd_stencil_op(bs->zpass_op)) |
A3XX_RB_STENCIL_CONTROL_ZFAIL_BF(fd_stencil_op(bs->zfail_op));
so->rb_stencilrefmask_bf |=
0xff000000 | /* ??? */
A3XX_RB_STENCILREFMASK_STENCILWRITEMASK(bs->writemask) |
A3XX_RB_STENCILREFMASK_STENCILMASK(bs->valuemask);
}
}
 
if (cso->alpha.enabled) {
so->rb_render_control =
A3XX_RB_RENDER_CONTROL_ALPHA_TEST |
A3XX_RB_RENDER_CONTROL_ALPHA_TEST_FUNC(cso->alpha.func);
so->rb_alpha_ref =
A3XX_RB_ALPHA_REF_UINT(cso->alpha.ref_value * 255.0) |
A3XX_RB_ALPHA_REF_FLOAT(cso->alpha.ref_value);
so->rb_depth_control |=
A3XX_RB_DEPTH_CONTROL_EARLY_Z_DISABLE;
}
 
return so;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a3xx/fd3_zsa.h
0,0 → 1,57
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FD3_ZSA_H_
#define FD3_ZSA_H_
 
 
#include "pipe/p_state.h"
#include "pipe/p_context.h"
 
#include "freedreno_util.h"
 
struct fd3_zsa_stateobj {
struct pipe_depth_stencil_alpha_state base;
uint32_t rb_render_control;
uint32_t rb_alpha_ref;
uint32_t rb_depth_control;
uint32_t rb_stencil_control;
uint32_t rb_stencilrefmask;
uint32_t rb_stencilrefmask_bf;
};
 
static INLINE struct fd3_zsa_stateobj *
fd3_zsa_stateobj(struct pipe_depth_stencil_alpha_state *zsa)
{
return (struct fd3_zsa_stateobj *)zsa;
}
 
void * fd3_zsa_state_create(struct pipe_context *pctx,
const struct pipe_depth_stencil_alpha_state *cso);
 
#endif /* FD3_ZSA_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a4xx/a4xx.xml.h
0,0 → 1,2618
#ifndef A4XX_XML
#define A4XX_XML
 
/* Autogenerated file, DO NOT EDIT manually!
 
This file was generated by the rules-ng-ng headergen tool in this git repository:
http://github.com/freedreno/envytools/
git clone https://github.com/freedreno/envytools.git
 
The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml ( 364 bytes, from 2013-11-30 14:47:15)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32901 bytes, from 2014-06-02 15:21:30)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10551 bytes, from 2014-11-13 22:44:30)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 14895 bytes, from 2015-04-19 15:23:28)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 66709 bytes, from 2015-04-12 18:16:35)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 59314 bytes, from 2015-04-19 16:21:40)
 
Copyright (C) 2013-2015 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
 
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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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.
*/
 
 
enum a4xx_color_fmt {
RB4_A8_UNORM = 1,
RB4_R8_UNORM = 2,
RB4_R4G4B4A4_UNORM = 8,
RB4_R5G5B5A1_UNORM = 10,
RB4_R5G6R5_UNORM = 14,
RB4_R8G8_UNORM = 15,
RB4_R8G8_SNORM = 16,
RB4_R8G8_UINT = 17,
RB4_R8G8_SINT = 18,
RB4_R16_FLOAT = 21,
RB4_R16_UINT = 22,
RB4_R16_SINT = 23,
RB4_R8G8B8_UNORM = 25,
RB4_R8G8B8A8_UNORM = 26,
RB4_R8G8B8A8_SNORM = 28,
RB4_R8G8B8A8_UINT = 29,
RB4_R8G8B8A8_SINT = 30,
RB4_R10G10B10A2_UNORM = 31,
RB4_R10G10B10A2_UINT = 34,
RB4_R11G11B10_FLOAT = 39,
RB4_R16G16_FLOAT = 42,
RB4_R16G16_UINT = 43,
RB4_R16G16_SINT = 44,
RB4_R32_FLOAT = 45,
RB4_R32_UINT = 46,
RB4_R32_SINT = 47,
RB4_R16G16B16A16_FLOAT = 54,
RB4_R16G16B16A16_UINT = 55,
RB4_R16G16B16A16_SINT = 56,
RB4_R32G32_FLOAT = 57,
RB4_R32G32_UINT = 58,
RB4_R32G32_SINT = 59,
RB4_R32G32B32A32_FLOAT = 60,
RB4_R32G32B32A32_UINT = 61,
RB4_R32G32B32A32_SINT = 62,
};
 
enum a4xx_tile_mode {
TILE4_LINEAR = 0,
TILE4_3 = 3,
};
 
enum a4xx_rb_blend_opcode {
BLEND_DST_PLUS_SRC = 0,
BLEND_SRC_MINUS_DST = 1,
BLEND_DST_MINUS_SRC = 2,
BLEND_MIN_DST_SRC = 3,
BLEND_MAX_DST_SRC = 4,
};
 
enum a4xx_vtx_fmt {
VFMT4_32_FLOAT = 1,
VFMT4_32_32_FLOAT = 2,
VFMT4_32_32_32_FLOAT = 3,
VFMT4_32_32_32_32_FLOAT = 4,
VFMT4_16_FLOAT = 5,
VFMT4_16_16_FLOAT = 6,
VFMT4_16_16_16_FLOAT = 7,
VFMT4_16_16_16_16_FLOAT = 8,
VFMT4_32_FIXED = 9,
VFMT4_32_32_FIXED = 10,
VFMT4_32_32_32_FIXED = 11,
VFMT4_32_32_32_32_FIXED = 12,
VFMT4_16_SINT = 16,
VFMT4_16_16_SINT = 17,
VFMT4_16_16_16_SINT = 18,
VFMT4_16_16_16_16_SINT = 19,
VFMT4_16_UINT = 20,
VFMT4_16_16_UINT = 21,
VFMT4_16_16_16_UINT = 22,
VFMT4_16_16_16_16_UINT = 23,
VFMT4_16_SNORM = 24,
VFMT4_16_16_SNORM = 25,
VFMT4_16_16_16_SNORM = 26,
VFMT4_16_16_16_16_SNORM = 27,
VFMT4_16_UNORM = 28,
VFMT4_16_16_UNORM = 29,
VFMT4_16_16_16_UNORM = 30,
VFMT4_16_16_16_16_UNORM = 31,
VFMT4_32_UINT = 32,
VFMT4_32_32_UINT = 33,
VFMT4_32_32_32_UINT = 34,
VFMT4_32_32_32_32_UINT = 35,
VFMT4_32_SINT = 36,
VFMT4_32_32_SINT = 37,
VFMT4_32_32_32_SINT = 38,
VFMT4_32_32_32_32_SINT = 39,
VFMT4_8_UINT = 40,
VFMT4_8_8_UINT = 41,
VFMT4_8_8_8_UINT = 42,
VFMT4_8_8_8_8_UINT = 43,
VFMT4_8_UNORM = 44,
VFMT4_8_8_UNORM = 45,
VFMT4_8_8_8_UNORM = 46,
VFMT4_8_8_8_8_UNORM = 47,
VFMT4_8_SINT = 48,
VFMT4_8_8_SINT = 49,
VFMT4_8_8_8_SINT = 50,
VFMT4_8_8_8_8_SINT = 51,
VFMT4_8_SNORM = 52,
VFMT4_8_8_SNORM = 53,
VFMT4_8_8_8_SNORM = 54,
VFMT4_8_8_8_8_SNORM = 55,
VFMT4_10_10_10_2_UINT = 60,
VFMT4_10_10_10_2_UNORM = 61,
VFMT4_10_10_10_2_SINT = 62,
VFMT4_10_10_10_2_SNORM = 63,
};
 
enum a4xx_tex_fmt {
TFMT4_5_6_5_UNORM = 11,
TFMT4_5_5_5_1_UNORM = 10,
TFMT4_4_4_4_4_UNORM = 8,
TFMT4_X8Z24_UNORM = 71,
TFMT4_10_10_10_2_UNORM = 33,
TFMT4_A8_UNORM = 3,
TFMT4_L8_A8_UNORM = 13,
TFMT4_8_UNORM = 4,
TFMT4_8_8_UNORM = 14,
TFMT4_8_8_8_8_UNORM = 28,
TFMT4_8_8_SNORM = 15,
TFMT4_8_8_8_8_SNORM = 29,
TFMT4_8_8_UINT = 16,
TFMT4_8_8_8_8_UINT = 30,
TFMT4_8_8_SINT = 17,
TFMT4_8_8_8_8_SINT = 31,
TFMT4_16_UINT = 21,
TFMT4_16_16_UINT = 41,
TFMT4_16_16_16_16_UINT = 54,
TFMT4_16_SINT = 22,
TFMT4_16_16_SINT = 42,
TFMT4_16_16_16_16_SINT = 55,
TFMT4_32_UINT = 44,
TFMT4_32_32_UINT = 57,
TFMT4_32_32_32_32_UINT = 64,
TFMT4_32_SINT = 45,
TFMT4_32_32_SINT = 58,
TFMT4_32_32_32_32_SINT = 65,
TFMT4_16_FLOAT = 20,
TFMT4_16_16_FLOAT = 40,
TFMT4_16_16_16_16_FLOAT = 53,
TFMT4_32_FLOAT = 43,
TFMT4_32_32_FLOAT = 56,
TFMT4_32_32_32_32_FLOAT = 63,
TFMT4_9_9_9_E5_FLOAT = 32,
TFMT4_11_11_10_FLOAT = 37,
TFMT4_ATC_RGB = 100,
TFMT4_ATC_RGBA_EXPLICIT = 101,
TFMT4_ATC_RGBA_INTERPOLATED = 102,
TFMT4_ETC2_RG11_UNORM = 103,
TFMT4_ETC2_RG11_SNORM = 104,
TFMT4_ETC2_R11_UNORM = 105,
TFMT4_ETC2_R11_SNORM = 106,
TFMT4_ETC1 = 107,
TFMT4_ETC2_RGB8 = 108,
TFMT4_ETC2_RGBA8 = 109,
TFMT4_ETC2_RGB8A1 = 110,
TFMT4_ASTC_4x4 = 111,
TFMT4_ASTC_5x4 = 112,
TFMT4_ASTC_5x5 = 113,
TFMT4_ASTC_6x5 = 114,
TFMT4_ASTC_6x6 = 115,
TFMT4_ASTC_8x5 = 116,
TFMT4_ASTC_8x6 = 117,
TFMT4_ASTC_8x8 = 118,
TFMT4_ASTC_10x5 = 119,
TFMT4_ASTC_10x6 = 120,
TFMT4_ASTC_10x8 = 121,
TFMT4_ASTC_10x10 = 122,
TFMT4_ASTC_12x10 = 123,
TFMT4_ASTC_12x12 = 124,
};
 
enum a4xx_tex_fetchsize {
TFETCH4_1_BYTE = 0,
TFETCH4_2_BYTE = 1,
TFETCH4_4_BYTE = 2,
TFETCH4_8_BYTE = 3,
TFETCH4_16_BYTE = 4,
};
 
enum a4xx_depth_format {
DEPTH4_NONE = 0,
DEPTH4_16 = 1,
DEPTH4_24_8 = 2,
};
 
enum a4xx_tess_spacing {
EQUAL_SPACING = 0,
ODD_SPACING = 2,
EVEN_SPACING = 3,
};
 
enum a4xx_tex_filter {
A4XX_TEX_NEAREST = 0,
A4XX_TEX_LINEAR = 1,
A4XX_TEX_ANISO = 2,
};
 
enum a4xx_tex_clamp {
A4XX_TEX_REPEAT = 0,
A4XX_TEX_CLAMP_TO_EDGE = 1,
A4XX_TEX_MIRROR_REPEAT = 2,
A4XX_TEX_CLAMP_NONE = 3,
};
 
enum a4xx_tex_aniso {
A4XX_TEX_ANISO_1 = 0,
A4XX_TEX_ANISO_2 = 1,
A4XX_TEX_ANISO_4 = 2,
A4XX_TEX_ANISO_8 = 3,
A4XX_TEX_ANISO_16 = 4,
};
 
enum a4xx_tex_swiz {
A4XX_TEX_X = 0,
A4XX_TEX_Y = 1,
A4XX_TEX_Z = 2,
A4XX_TEX_W = 3,
A4XX_TEX_ZERO = 4,
A4XX_TEX_ONE = 5,
};
 
enum a4xx_tex_type {
A4XX_TEX_1D = 0,
A4XX_TEX_2D = 1,
A4XX_TEX_CUBE = 2,
A4XX_TEX_3D = 3,
};
 
#define A4XX_CGC_HLSQ_EARLY_CYC__MASK 0x00700000
#define A4XX_CGC_HLSQ_EARLY_CYC__SHIFT 20
static inline uint32_t A4XX_CGC_HLSQ_EARLY_CYC(uint32_t val)
{
return ((val) << A4XX_CGC_HLSQ_EARLY_CYC__SHIFT) & A4XX_CGC_HLSQ_EARLY_CYC__MASK;
}
#define A4XX_INT0_RBBM_GPU_IDLE 0x00000001
#define A4XX_INT0_RBBM_AHB_ERROR 0x00000002
#define A4XX_INT0_RBBM_REG_TIMEOUT 0x00000004
#define A4XX_INT0_RBBM_ME_MS_TIMEOUT 0x00000008
#define A4XX_INT0_RBBM_PFP_MS_TIMEOUT 0x00000010
#define A4XX_INT0_RBBM_ATB_BUS_OVERFLOW 0x00000020
#define A4XX_INT0_VFD_ERROR 0x00000040
#define A4XX_INT0_CP_SW_INT 0x00000080
#define A4XX_INT0_CP_T0_PACKET_IN_IB 0x00000100
#define A4XX_INT0_CP_OPCODE_ERROR 0x00000200
#define A4XX_INT0_CP_RESERVED_BIT_ERROR 0x00000400
#define A4XX_INT0_CP_HW_FAULT 0x00000800
#define A4XX_INT0_CP_DMA 0x00001000
#define A4XX_INT0_CP_IB2_INT 0x00002000
#define A4XX_INT0_CP_IB1_INT 0x00004000
#define A4XX_INT0_CP_RB_INT 0x00008000
#define A4XX_INT0_CP_REG_PROTECT_FAULT 0x00010000
#define A4XX_INT0_CP_RB_DONE_TS 0x00020000
#define A4XX_INT0_CP_VS_DONE_TS 0x00040000
#define A4XX_INT0_CP_PS_DONE_TS 0x00080000
#define A4XX_INT0_CACHE_FLUSH_TS 0x00100000
#define A4XX_INT0_CP_AHB_ERROR_HALT 0x00200000
#define A4XX_INT0_MISC_HANG_DETECT 0x01000000
#define A4XX_INT0_UCHE_OOB_ACCESS 0x02000000
#define REG_A4XX_RB_GMEM_BASE_ADDR 0x00000cc0
 
#define REG_A4XX_RB_PERFCTR_RB_SEL_0 0x00000cc7
 
#define REG_A4XX_RB_PERFCTR_RB_SEL_1 0x00000cc8
 
#define REG_A4XX_RB_PERFCTR_RB_SEL_2 0x00000cc9
 
#define REG_A4XX_RB_PERFCTR_RB_SEL_3 0x00000cca
 
#define REG_A4XX_RB_PERFCTR_RB_SEL_4 0x00000ccb
 
#define REG_A4XX_RB_PERFCTR_RB_SEL_5 0x00000ccc
 
#define REG_A4XX_RB_PERFCTR_RB_SEL_6 0x00000ccd
 
#define REG_A4XX_RB_PERFCTR_RB_SEL_7 0x00000cce
 
#define REG_A4XX_RB_PERFCTR_CCU_SEL_3 0x00000cd2
 
#define REG_A4XX_RB_FRAME_BUFFER_DIMENSION 0x00000ce0
#define A4XX_RB_FRAME_BUFFER_DIMENSION_WIDTH__MASK 0x00003fff
#define A4XX_RB_FRAME_BUFFER_DIMENSION_WIDTH__SHIFT 0
static inline uint32_t A4XX_RB_FRAME_BUFFER_DIMENSION_WIDTH(uint32_t val)
{
return ((val) << A4XX_RB_FRAME_BUFFER_DIMENSION_WIDTH__SHIFT) & A4XX_RB_FRAME_BUFFER_DIMENSION_WIDTH__MASK;
}
#define A4XX_RB_FRAME_BUFFER_DIMENSION_HEIGHT__MASK 0x3fff0000
#define A4XX_RB_FRAME_BUFFER_DIMENSION_HEIGHT__SHIFT 16
static inline uint32_t A4XX_RB_FRAME_BUFFER_DIMENSION_HEIGHT(uint32_t val)
{
return ((val) << A4XX_RB_FRAME_BUFFER_DIMENSION_HEIGHT__SHIFT) & A4XX_RB_FRAME_BUFFER_DIMENSION_HEIGHT__MASK;
}
 
#define REG_A4XX_RB_CLEAR_COLOR_DW0 0x000020cc
 
#define REG_A4XX_RB_CLEAR_COLOR_DW1 0x000020cd
 
#define REG_A4XX_RB_CLEAR_COLOR_DW2 0x000020ce
 
#define REG_A4XX_RB_CLEAR_COLOR_DW3 0x000020cf
 
#define REG_A4XX_RB_MODE_CONTROL 0x000020a0
#define A4XX_RB_MODE_CONTROL_WIDTH__MASK 0x0000003f
#define A4XX_RB_MODE_CONTROL_WIDTH__SHIFT 0
static inline uint32_t A4XX_RB_MODE_CONTROL_WIDTH(uint32_t val)
{
return ((val >> 5) << A4XX_RB_MODE_CONTROL_WIDTH__SHIFT) & A4XX_RB_MODE_CONTROL_WIDTH__MASK;
}
#define A4XX_RB_MODE_CONTROL_HEIGHT__MASK 0x00003f00
#define A4XX_RB_MODE_CONTROL_HEIGHT__SHIFT 8
static inline uint32_t A4XX_RB_MODE_CONTROL_HEIGHT(uint32_t val)
{
return ((val >> 5) << A4XX_RB_MODE_CONTROL_HEIGHT__SHIFT) & A4XX_RB_MODE_CONTROL_HEIGHT__MASK;
}
 
#define REG_A4XX_RB_RENDER_CONTROL 0x000020a1
#define A4XX_RB_RENDER_CONTROL_BINNING_PASS 0x00000001
#define A4XX_RB_RENDER_CONTROL_DISABLE_COLOR_PIPE 0x00000020
 
#define REG_A4XX_RB_MSAA_CONTROL 0x000020a2
#define A4XX_RB_MSAA_CONTROL_DISABLE 0x00001000
#define A4XX_RB_MSAA_CONTROL_SAMPLES__MASK 0x0000e000
#define A4XX_RB_MSAA_CONTROL_SAMPLES__SHIFT 13
static inline uint32_t A4XX_RB_MSAA_CONTROL_SAMPLES(uint32_t val)
{
return ((val) << A4XX_RB_MSAA_CONTROL_SAMPLES__SHIFT) & A4XX_RB_MSAA_CONTROL_SAMPLES__MASK;
}
 
#define REG_A4XX_RB_RENDER_CONTROL2 0x000020a3
#define A4XX_RB_RENDER_CONTROL2_XCOORD 0x00000001
#define A4XX_RB_RENDER_CONTROL2_YCOORD 0x00000002
#define A4XX_RB_RENDER_CONTROL2_ZCOORD 0x00000004
#define A4XX_RB_RENDER_CONTROL2_WCOORD 0x00000008
#define A4XX_RB_RENDER_CONTROL2_SAMPLEMASK 0x00000010
#define A4XX_RB_RENDER_CONTROL2_FACENESS 0x00000020
#define A4XX_RB_RENDER_CONTROL2_SAMPLEID 0x00000040
#define A4XX_RB_RENDER_CONTROL2_MSAA_SAMPLES__MASK 0x00000380
#define A4XX_RB_RENDER_CONTROL2_MSAA_SAMPLES__SHIFT 7
static inline uint32_t A4XX_RB_RENDER_CONTROL2_MSAA_SAMPLES(uint32_t val)
{
return ((val) << A4XX_RB_RENDER_CONTROL2_MSAA_SAMPLES__SHIFT) & A4XX_RB_RENDER_CONTROL2_MSAA_SAMPLES__MASK;
}
#define A4XX_RB_RENDER_CONTROL2_SAMPLEID_HR 0x00000800
#define A4XX_RB_RENDER_CONTROL2_VARYING 0x00001000
 
static inline uint32_t REG_A4XX_RB_MRT(uint32_t i0) { return 0x000020a4 + 0x5*i0; }
 
static inline uint32_t REG_A4XX_RB_MRT_CONTROL(uint32_t i0) { return 0x000020a4 + 0x5*i0; }
#define A4XX_RB_MRT_CONTROL_READ_DEST_ENABLE 0x00000008
#define A4XX_RB_MRT_CONTROL_BLEND 0x00000010
#define A4XX_RB_MRT_CONTROL_BLEND2 0x00000020
#define A4XX_RB_MRT_CONTROL_FASTCLEAR 0x00000400
#define A4XX_RB_MRT_CONTROL_B11 0x00000800
#define A4XX_RB_MRT_CONTROL_COMPONENT_ENABLE__MASK 0x0f000000
#define A4XX_RB_MRT_CONTROL_COMPONENT_ENABLE__SHIFT 24
static inline uint32_t A4XX_RB_MRT_CONTROL_COMPONENT_ENABLE(uint32_t val)
{
return ((val) << A4XX_RB_MRT_CONTROL_COMPONENT_ENABLE__SHIFT) & A4XX_RB_MRT_CONTROL_COMPONENT_ENABLE__MASK;
}
 
static inline uint32_t REG_A4XX_RB_MRT_BUF_INFO(uint32_t i0) { return 0x000020a5 + 0x5*i0; }
#define A4XX_RB_MRT_BUF_INFO_COLOR_FORMAT__MASK 0x0000003f
#define A4XX_RB_MRT_BUF_INFO_COLOR_FORMAT__SHIFT 0
static inline uint32_t A4XX_RB_MRT_BUF_INFO_COLOR_FORMAT(enum a4xx_color_fmt val)
{
return ((val) << A4XX_RB_MRT_BUF_INFO_COLOR_FORMAT__SHIFT) & A4XX_RB_MRT_BUF_INFO_COLOR_FORMAT__MASK;
}
#define A4XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE__MASK 0x000000c0
#define A4XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE__SHIFT 6
static inline uint32_t A4XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE(enum a4xx_tile_mode val)
{
return ((val) << A4XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE__SHIFT) & A4XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE__MASK;
}
#define A4XX_RB_MRT_BUF_INFO_DITHER_MODE__MASK 0x00000600
#define A4XX_RB_MRT_BUF_INFO_DITHER_MODE__SHIFT 9
static inline uint32_t A4XX_RB_MRT_BUF_INFO_DITHER_MODE(enum adreno_rb_dither_mode val)
{
return ((val) << A4XX_RB_MRT_BUF_INFO_DITHER_MODE__SHIFT) & A4XX_RB_MRT_BUF_INFO_DITHER_MODE__MASK;
}
#define A4XX_RB_MRT_BUF_INFO_COLOR_SWAP__MASK 0x00001800
#define A4XX_RB_MRT_BUF_INFO_COLOR_SWAP__SHIFT 11
static inline uint32_t A4XX_RB_MRT_BUF_INFO_COLOR_SWAP(enum a3xx_color_swap val)
{
return ((val) << A4XX_RB_MRT_BUF_INFO_COLOR_SWAP__SHIFT) & A4XX_RB_MRT_BUF_INFO_COLOR_SWAP__MASK;
}
#define A4XX_RB_MRT_BUF_INFO_COLOR_SRGB 0x00002000
#define A4XX_RB_MRT_BUF_INFO_COLOR_BUF_PITCH__MASK 0x007fc000
#define A4XX_RB_MRT_BUF_INFO_COLOR_BUF_PITCH__SHIFT 14
static inline uint32_t A4XX_RB_MRT_BUF_INFO_COLOR_BUF_PITCH(uint32_t val)
{
return ((val >> 4) << A4XX_RB_MRT_BUF_INFO_COLOR_BUF_PITCH__SHIFT) & A4XX_RB_MRT_BUF_INFO_COLOR_BUF_PITCH__MASK;
}
 
static inline uint32_t REG_A4XX_RB_MRT_BASE(uint32_t i0) { return 0x000020a6 + 0x5*i0; }
 
static inline uint32_t REG_A4XX_RB_MRT_CONTROL3(uint32_t i0) { return 0x000020a7 + 0x5*i0; }
#define A4XX_RB_MRT_CONTROL3_STRIDE__MASK 0x0001fff8
#define A4XX_RB_MRT_CONTROL3_STRIDE__SHIFT 3
static inline uint32_t A4XX_RB_MRT_CONTROL3_STRIDE(uint32_t val)
{
return ((val) << A4XX_RB_MRT_CONTROL3_STRIDE__SHIFT) & A4XX_RB_MRT_CONTROL3_STRIDE__MASK;
}
 
static inline uint32_t REG_A4XX_RB_MRT_BLEND_CONTROL(uint32_t i0) { return 0x000020a8 + 0x5*i0; }
#define A4XX_RB_MRT_BLEND_CONTROL_RGB_SRC_FACTOR__MASK 0x0000001f
#define A4XX_RB_MRT_BLEND_CONTROL_RGB_SRC_FACTOR__SHIFT 0
static inline uint32_t A4XX_RB_MRT_BLEND_CONTROL_RGB_SRC_FACTOR(enum adreno_rb_blend_factor val)
{
return ((val) << A4XX_RB_MRT_BLEND_CONTROL_RGB_SRC_FACTOR__SHIFT) & A4XX_RB_MRT_BLEND_CONTROL_RGB_SRC_FACTOR__MASK;
}
#define A4XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE__MASK 0x000000e0
#define A4XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE__SHIFT 5
static inline uint32_t A4XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE(enum a4xx_rb_blend_opcode val)
{
return ((val) << A4XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE__SHIFT) & A4XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE__MASK;
}
#define A4XX_RB_MRT_BLEND_CONTROL_RGB_DEST_FACTOR__MASK 0x00001f00
#define A4XX_RB_MRT_BLEND_CONTROL_RGB_DEST_FACTOR__SHIFT 8
static inline uint32_t A4XX_RB_MRT_BLEND_CONTROL_RGB_DEST_FACTOR(enum adreno_rb_blend_factor val)
{
return ((val) << A4XX_RB_MRT_BLEND_CONTROL_RGB_DEST_FACTOR__SHIFT) & A4XX_RB_MRT_BLEND_CONTROL_RGB_DEST_FACTOR__MASK;
}
#define A4XX_RB_MRT_BLEND_CONTROL_ALPHA_SRC_FACTOR__MASK 0x001f0000
#define A4XX_RB_MRT_BLEND_CONTROL_ALPHA_SRC_FACTOR__SHIFT 16
static inline uint32_t A4XX_RB_MRT_BLEND_CONTROL_ALPHA_SRC_FACTOR(enum adreno_rb_blend_factor val)
{
return ((val) << A4XX_RB_MRT_BLEND_CONTROL_ALPHA_SRC_FACTOR__SHIFT) & A4XX_RB_MRT_BLEND_CONTROL_ALPHA_SRC_FACTOR__MASK;
}
#define A4XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE__MASK 0x00e00000
#define A4XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE__SHIFT 21
static inline uint32_t A4XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE(enum a4xx_rb_blend_opcode val)
{
return ((val) << A4XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE__SHIFT) & A4XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE__MASK;
}
#define A4XX_RB_MRT_BLEND_CONTROL_ALPHA_DEST_FACTOR__MASK 0x1f000000
#define A4XX_RB_MRT_BLEND_CONTROL_ALPHA_DEST_FACTOR__SHIFT 24
static inline uint32_t A4XX_RB_MRT_BLEND_CONTROL_ALPHA_DEST_FACTOR(enum adreno_rb_blend_factor val)
{
return ((val) << A4XX_RB_MRT_BLEND_CONTROL_ALPHA_DEST_FACTOR__SHIFT) & A4XX_RB_MRT_BLEND_CONTROL_ALPHA_DEST_FACTOR__MASK;
}
 
#define REG_A4XX_RB_BLEND_RED 0x000020f3
#define A4XX_RB_BLEND_RED_UINT__MASK 0x00007fff
#define A4XX_RB_BLEND_RED_UINT__SHIFT 0
static inline uint32_t A4XX_RB_BLEND_RED_UINT(uint32_t val)
{
return ((val) << A4XX_RB_BLEND_RED_UINT__SHIFT) & A4XX_RB_BLEND_RED_UINT__MASK;
}
#define A4XX_RB_BLEND_RED_FLOAT__MASK 0xffff0000
#define A4XX_RB_BLEND_RED_FLOAT__SHIFT 16
static inline uint32_t A4XX_RB_BLEND_RED_FLOAT(float val)
{
return ((util_float_to_half(val)) << A4XX_RB_BLEND_RED_FLOAT__SHIFT) & A4XX_RB_BLEND_RED_FLOAT__MASK;
}
 
#define REG_A4XX_RB_BLEND_GREEN 0x000020f4
#define A4XX_RB_BLEND_GREEN_UINT__MASK 0x00007fff
#define A4XX_RB_BLEND_GREEN_UINT__SHIFT 0
static inline uint32_t A4XX_RB_BLEND_GREEN_UINT(uint32_t val)
{
return ((val) << A4XX_RB_BLEND_GREEN_UINT__SHIFT) & A4XX_RB_BLEND_GREEN_UINT__MASK;
}
#define A4XX_RB_BLEND_GREEN_FLOAT__MASK 0xffff0000
#define A4XX_RB_BLEND_GREEN_FLOAT__SHIFT 16
static inline uint32_t A4XX_RB_BLEND_GREEN_FLOAT(float val)
{
return ((util_float_to_half(val)) << A4XX_RB_BLEND_GREEN_FLOAT__SHIFT) & A4XX_RB_BLEND_GREEN_FLOAT__MASK;
}
 
#define REG_A4XX_RB_BLEND_BLUE 0x000020f5
#define A4XX_RB_BLEND_BLUE_UINT__MASK 0x00007fff
#define A4XX_RB_BLEND_BLUE_UINT__SHIFT 0
static inline uint32_t A4XX_RB_BLEND_BLUE_UINT(uint32_t val)
{
return ((val) << A4XX_RB_BLEND_BLUE_UINT__SHIFT) & A4XX_RB_BLEND_BLUE_UINT__MASK;
}
#define A4XX_RB_BLEND_BLUE_FLOAT__MASK 0xffff0000
#define A4XX_RB_BLEND_BLUE_FLOAT__SHIFT 16
static inline uint32_t A4XX_RB_BLEND_BLUE_FLOAT(float val)
{
return ((util_float_to_half(val)) << A4XX_RB_BLEND_BLUE_FLOAT__SHIFT) & A4XX_RB_BLEND_BLUE_FLOAT__MASK;
}
 
#define REG_A4XX_RB_BLEND_ALPHA 0x000020f6
#define A4XX_RB_BLEND_ALPHA_UINT__MASK 0x00007fff
#define A4XX_RB_BLEND_ALPHA_UINT__SHIFT 0
static inline uint32_t A4XX_RB_BLEND_ALPHA_UINT(uint32_t val)
{
return ((val) << A4XX_RB_BLEND_ALPHA_UINT__SHIFT) & A4XX_RB_BLEND_ALPHA_UINT__MASK;
}
#define A4XX_RB_BLEND_ALPHA_FLOAT__MASK 0xffff0000
#define A4XX_RB_BLEND_ALPHA_FLOAT__SHIFT 16
static inline uint32_t A4XX_RB_BLEND_ALPHA_FLOAT(float val)
{
return ((util_float_to_half(val)) << A4XX_RB_BLEND_ALPHA_FLOAT__SHIFT) & A4XX_RB_BLEND_ALPHA_FLOAT__MASK;
}
 
#define REG_A4XX_RB_ALPHA_CONTROL 0x000020f8
#define A4XX_RB_ALPHA_CONTROL_ALPHA_REF__MASK 0x000000ff
#define A4XX_RB_ALPHA_CONTROL_ALPHA_REF__SHIFT 0
static inline uint32_t A4XX_RB_ALPHA_CONTROL_ALPHA_REF(uint32_t val)
{
return ((val) << A4XX_RB_ALPHA_CONTROL_ALPHA_REF__SHIFT) & A4XX_RB_ALPHA_CONTROL_ALPHA_REF__MASK;
}
#define A4XX_RB_ALPHA_CONTROL_ALPHA_TEST 0x00000100
#define A4XX_RB_ALPHA_CONTROL_ALPHA_TEST_FUNC__MASK 0x00000e00
#define A4XX_RB_ALPHA_CONTROL_ALPHA_TEST_FUNC__SHIFT 9
static inline uint32_t A4XX_RB_ALPHA_CONTROL_ALPHA_TEST_FUNC(enum adreno_compare_func val)
{
return ((val) << A4XX_RB_ALPHA_CONTROL_ALPHA_TEST_FUNC__SHIFT) & A4XX_RB_ALPHA_CONTROL_ALPHA_TEST_FUNC__MASK;
}
 
#define REG_A4XX_RB_FS_OUTPUT 0x000020f9
#define A4XX_RB_FS_OUTPUT_ENABLE_BLEND__MASK 0x000000ff
#define A4XX_RB_FS_OUTPUT_ENABLE_BLEND__SHIFT 0
static inline uint32_t A4XX_RB_FS_OUTPUT_ENABLE_BLEND(uint32_t val)
{
return ((val) << A4XX_RB_FS_OUTPUT_ENABLE_BLEND__SHIFT) & A4XX_RB_FS_OUTPUT_ENABLE_BLEND__MASK;
}
#define A4XX_RB_FS_OUTPUT_FAST_CLEAR 0x00000100
#define A4XX_RB_FS_OUTPUT_SAMPLE_MASK__MASK 0xffff0000
#define A4XX_RB_FS_OUTPUT_SAMPLE_MASK__SHIFT 16
static inline uint32_t A4XX_RB_FS_OUTPUT_SAMPLE_MASK(uint32_t val)
{
return ((val) << A4XX_RB_FS_OUTPUT_SAMPLE_MASK__SHIFT) & A4XX_RB_FS_OUTPUT_SAMPLE_MASK__MASK;
}
 
#define REG_A4XX_RB_RENDER_COMPONENTS 0x000020fb
#define A4XX_RB_RENDER_COMPONENTS_RT0__MASK 0x0000000f
#define A4XX_RB_RENDER_COMPONENTS_RT0__SHIFT 0
static inline uint32_t A4XX_RB_RENDER_COMPONENTS_RT0(uint32_t val)
{
return ((val) << A4XX_RB_RENDER_COMPONENTS_RT0__SHIFT) & A4XX_RB_RENDER_COMPONENTS_RT0__MASK;
}
#define A4XX_RB_RENDER_COMPONENTS_RT1__MASK 0x000000f0
#define A4XX_RB_RENDER_COMPONENTS_RT1__SHIFT 4
static inline uint32_t A4XX_RB_RENDER_COMPONENTS_RT1(uint32_t val)
{
return ((val) << A4XX_RB_RENDER_COMPONENTS_RT1__SHIFT) & A4XX_RB_RENDER_COMPONENTS_RT1__MASK;
}
#define A4XX_RB_RENDER_COMPONENTS_RT2__MASK 0x00000f00
#define A4XX_RB_RENDER_COMPONENTS_RT2__SHIFT 8
static inline uint32_t A4XX_RB_RENDER_COMPONENTS_RT2(uint32_t val)
{
return ((val) << A4XX_RB_RENDER_COMPONENTS_RT2__SHIFT) & A4XX_RB_RENDER_COMPONENTS_RT2__MASK;
}
#define A4XX_RB_RENDER_COMPONENTS_RT3__MASK 0x0000f000
#define A4XX_RB_RENDER_COMPONENTS_RT3__SHIFT 12
static inline uint32_t A4XX_RB_RENDER_COMPONENTS_RT3(uint32_t val)
{
return ((val) << A4XX_RB_RENDER_COMPONENTS_RT3__SHIFT) & A4XX_RB_RENDER_COMPONENTS_RT3__MASK;
}
#define A4XX_RB_RENDER_COMPONENTS_RT4__MASK 0x000f0000
#define A4XX_RB_RENDER_COMPONENTS_RT4__SHIFT 16
static inline uint32_t A4XX_RB_RENDER_COMPONENTS_RT4(uint32_t val)
{
return ((val) << A4XX_RB_RENDER_COMPONENTS_RT4__SHIFT) & A4XX_RB_RENDER_COMPONENTS_RT4__MASK;
}
#define A4XX_RB_RENDER_COMPONENTS_RT5__MASK 0x00f00000
#define A4XX_RB_RENDER_COMPONENTS_RT5__SHIFT 20
static inline uint32_t A4XX_RB_RENDER_COMPONENTS_RT5(uint32_t val)
{
return ((val) << A4XX_RB_RENDER_COMPONENTS_RT5__SHIFT) & A4XX_RB_RENDER_COMPONENTS_RT5__MASK;
}
#define A4XX_RB_RENDER_COMPONENTS_RT6__MASK 0x0f000000
#define A4XX_RB_RENDER_COMPONENTS_RT6__SHIFT 24
static inline uint32_t A4XX_RB_RENDER_COMPONENTS_RT6(uint32_t val)
{
return ((val) << A4XX_RB_RENDER_COMPONENTS_RT6__SHIFT) & A4XX_RB_RENDER_COMPONENTS_RT6__MASK;
}
#define A4XX_RB_RENDER_COMPONENTS_RT7__MASK 0xf0000000
#define A4XX_RB_RENDER_COMPONENTS_RT7__SHIFT 28
static inline uint32_t A4XX_RB_RENDER_COMPONENTS_RT7(uint32_t val)
{
return ((val) << A4XX_RB_RENDER_COMPONENTS_RT7__SHIFT) & A4XX_RB_RENDER_COMPONENTS_RT7__MASK;
}
 
#define REG_A4XX_RB_COPY_CONTROL 0x000020fc
#define A4XX_RB_COPY_CONTROL_MSAA_RESOLVE__MASK 0x00000003
#define A4XX_RB_COPY_CONTROL_MSAA_RESOLVE__SHIFT 0
static inline uint32_t A4XX_RB_COPY_CONTROL_MSAA_RESOLVE(enum a3xx_msaa_samples val)
{
return ((val) << A4XX_RB_COPY_CONTROL_MSAA_RESOLVE__SHIFT) & A4XX_RB_COPY_CONTROL_MSAA_RESOLVE__MASK;
}
#define A4XX_RB_COPY_CONTROL_MODE__MASK 0x00000070
#define A4XX_RB_COPY_CONTROL_MODE__SHIFT 4
static inline uint32_t A4XX_RB_COPY_CONTROL_MODE(enum adreno_rb_copy_control_mode val)
{
return ((val) << A4XX_RB_COPY_CONTROL_MODE__SHIFT) & A4XX_RB_COPY_CONTROL_MODE__MASK;
}
#define A4XX_RB_COPY_CONTROL_FASTCLEAR__MASK 0x00000f00
#define A4XX_RB_COPY_CONTROL_FASTCLEAR__SHIFT 8
static inline uint32_t A4XX_RB_COPY_CONTROL_FASTCLEAR(uint32_t val)
{
return ((val) << A4XX_RB_COPY_CONTROL_FASTCLEAR__SHIFT) & A4XX_RB_COPY_CONTROL_FASTCLEAR__MASK;
}
#define A4XX_RB_COPY_CONTROL_GMEM_BASE__MASK 0xffffc000
#define A4XX_RB_COPY_CONTROL_GMEM_BASE__SHIFT 14
static inline uint32_t A4XX_RB_COPY_CONTROL_GMEM_BASE(uint32_t val)
{
return ((val >> 14) << A4XX_RB_COPY_CONTROL_GMEM_BASE__SHIFT) & A4XX_RB_COPY_CONTROL_GMEM_BASE__MASK;
}
 
#define REG_A4XX_RB_COPY_DEST_BASE 0x000020fd
#define A4XX_RB_COPY_DEST_BASE_BASE__MASK 0xffffffe0
#define A4XX_RB_COPY_DEST_BASE_BASE__SHIFT 5
static inline uint32_t A4XX_RB_COPY_DEST_BASE_BASE(uint32_t val)
{
return ((val >> 5) << A4XX_RB_COPY_DEST_BASE_BASE__SHIFT) & A4XX_RB_COPY_DEST_BASE_BASE__MASK;
}
 
#define REG_A4XX_RB_COPY_DEST_PITCH 0x000020fe
#define A4XX_RB_COPY_DEST_PITCH_PITCH__MASK 0xffffffff
#define A4XX_RB_COPY_DEST_PITCH_PITCH__SHIFT 0
static inline uint32_t A4XX_RB_COPY_DEST_PITCH_PITCH(uint32_t val)
{
return ((val >> 5) << A4XX_RB_COPY_DEST_PITCH_PITCH__SHIFT) & A4XX_RB_COPY_DEST_PITCH_PITCH__MASK;
}
 
#define REG_A4XX_RB_COPY_DEST_INFO 0x000020ff
#define A4XX_RB_COPY_DEST_INFO_FORMAT__MASK 0x000000fc
#define A4XX_RB_COPY_DEST_INFO_FORMAT__SHIFT 2
static inline uint32_t A4XX_RB_COPY_DEST_INFO_FORMAT(enum a4xx_color_fmt val)
{
return ((val) << A4XX_RB_COPY_DEST_INFO_FORMAT__SHIFT) & A4XX_RB_COPY_DEST_INFO_FORMAT__MASK;
}
#define A4XX_RB_COPY_DEST_INFO_SWAP__MASK 0x00000300
#define A4XX_RB_COPY_DEST_INFO_SWAP__SHIFT 8
static inline uint32_t A4XX_RB_COPY_DEST_INFO_SWAP(enum a3xx_color_swap val)
{
return ((val) << A4XX_RB_COPY_DEST_INFO_SWAP__SHIFT) & A4XX_RB_COPY_DEST_INFO_SWAP__MASK;
}
#define A4XX_RB_COPY_DEST_INFO_DITHER_MODE__MASK 0x00000c00
#define A4XX_RB_COPY_DEST_INFO_DITHER_MODE__SHIFT 10
static inline uint32_t A4XX_RB_COPY_DEST_INFO_DITHER_MODE(enum adreno_rb_dither_mode val)
{
return ((val) << A4XX_RB_COPY_DEST_INFO_DITHER_MODE__SHIFT) & A4XX_RB_COPY_DEST_INFO_DITHER_MODE__MASK;
}
#define A4XX_RB_COPY_DEST_INFO_COMPONENT_ENABLE__MASK 0x0003c000
#define A4XX_RB_COPY_DEST_INFO_COMPONENT_ENABLE__SHIFT 14
static inline uint32_t A4XX_RB_COPY_DEST_INFO_COMPONENT_ENABLE(uint32_t val)
{
return ((val) << A4XX_RB_COPY_DEST_INFO_COMPONENT_ENABLE__SHIFT) & A4XX_RB_COPY_DEST_INFO_COMPONENT_ENABLE__MASK;
}
#define A4XX_RB_COPY_DEST_INFO_ENDIAN__MASK 0x001c0000
#define A4XX_RB_COPY_DEST_INFO_ENDIAN__SHIFT 18
static inline uint32_t A4XX_RB_COPY_DEST_INFO_ENDIAN(enum adreno_rb_surface_endian val)
{
return ((val) << A4XX_RB_COPY_DEST_INFO_ENDIAN__SHIFT) & A4XX_RB_COPY_DEST_INFO_ENDIAN__MASK;
}
#define A4XX_RB_COPY_DEST_INFO_TILE__MASK 0x03000000
#define A4XX_RB_COPY_DEST_INFO_TILE__SHIFT 24
static inline uint32_t A4XX_RB_COPY_DEST_INFO_TILE(enum a4xx_tile_mode val)
{
return ((val) << A4XX_RB_COPY_DEST_INFO_TILE__SHIFT) & A4XX_RB_COPY_DEST_INFO_TILE__MASK;
}
 
#define REG_A4XX_RB_FS_OUTPUT_REG 0x00002100
#define A4XX_RB_FS_OUTPUT_REG_MRT__MASK 0x0000000f
#define A4XX_RB_FS_OUTPUT_REG_MRT__SHIFT 0
static inline uint32_t A4XX_RB_FS_OUTPUT_REG_MRT(uint32_t val)
{
return ((val) << A4XX_RB_FS_OUTPUT_REG_MRT__SHIFT) & A4XX_RB_FS_OUTPUT_REG_MRT__MASK;
}
#define A4XX_RB_FS_OUTPUT_REG_FRAG_WRITES_Z 0x00000020
 
#define REG_A4XX_RB_DEPTH_CONTROL 0x00002101
#define A4XX_RB_DEPTH_CONTROL_FRAG_WRITES_Z 0x00000001
#define A4XX_RB_DEPTH_CONTROL_Z_ENABLE 0x00000002
#define A4XX_RB_DEPTH_CONTROL_Z_WRITE_ENABLE 0x00000004
#define A4XX_RB_DEPTH_CONTROL_ZFUNC__MASK 0x00000070
#define A4XX_RB_DEPTH_CONTROL_ZFUNC__SHIFT 4
static inline uint32_t A4XX_RB_DEPTH_CONTROL_ZFUNC(enum adreno_compare_func val)
{
return ((val) << A4XX_RB_DEPTH_CONTROL_ZFUNC__SHIFT) & A4XX_RB_DEPTH_CONTROL_ZFUNC__MASK;
}
#define A4XX_RB_DEPTH_CONTROL_BF_ENABLE 0x00000080
#define A4XX_RB_DEPTH_CONTROL_EARLY_Z_DISABLE 0x00010000
#define A4XX_RB_DEPTH_CONTROL_Z_TEST_ENABLE 0x80000000
 
#define REG_A4XX_RB_DEPTH_CLEAR 0x00002102
 
#define REG_A4XX_RB_DEPTH_INFO 0x00002103
#define A4XX_RB_DEPTH_INFO_DEPTH_FORMAT__MASK 0x00000003
#define A4XX_RB_DEPTH_INFO_DEPTH_FORMAT__SHIFT 0
static inline uint32_t A4XX_RB_DEPTH_INFO_DEPTH_FORMAT(enum a4xx_depth_format val)
{
return ((val) << A4XX_RB_DEPTH_INFO_DEPTH_FORMAT__SHIFT) & A4XX_RB_DEPTH_INFO_DEPTH_FORMAT__MASK;
}
#define A4XX_RB_DEPTH_INFO_DEPTH_BASE__MASK 0xfffff000
#define A4XX_RB_DEPTH_INFO_DEPTH_BASE__SHIFT 12
static inline uint32_t A4XX_RB_DEPTH_INFO_DEPTH_BASE(uint32_t val)
{
return ((val >> 12) << A4XX_RB_DEPTH_INFO_DEPTH_BASE__SHIFT) & A4XX_RB_DEPTH_INFO_DEPTH_BASE__MASK;
}
 
#define REG_A4XX_RB_DEPTH_PITCH 0x00002104
#define A4XX_RB_DEPTH_PITCH__MASK 0xffffffff
#define A4XX_RB_DEPTH_PITCH__SHIFT 0
static inline uint32_t A4XX_RB_DEPTH_PITCH(uint32_t val)
{
return ((val >> 5) << A4XX_RB_DEPTH_PITCH__SHIFT) & A4XX_RB_DEPTH_PITCH__MASK;
}
 
#define REG_A4XX_RB_DEPTH_PITCH2 0x00002105
#define A4XX_RB_DEPTH_PITCH2__MASK 0xffffffff
#define A4XX_RB_DEPTH_PITCH2__SHIFT 0
static inline uint32_t A4XX_RB_DEPTH_PITCH2(uint32_t val)
{
return ((val >> 5) << A4XX_RB_DEPTH_PITCH2__SHIFT) & A4XX_RB_DEPTH_PITCH2__MASK;
}
 
#define REG_A4XX_RB_STENCIL_CONTROL 0x00002106
#define A4XX_RB_STENCIL_CONTROL_STENCIL_ENABLE 0x00000001
#define A4XX_RB_STENCIL_CONTROL_STENCIL_ENABLE_BF 0x00000002
#define A4XX_RB_STENCIL_CONTROL_STENCIL_READ 0x00000004
#define A4XX_RB_STENCIL_CONTROL_FUNC__MASK 0x00000700
#define A4XX_RB_STENCIL_CONTROL_FUNC__SHIFT 8
static inline uint32_t A4XX_RB_STENCIL_CONTROL_FUNC(enum adreno_compare_func val)
{
return ((val) << A4XX_RB_STENCIL_CONTROL_FUNC__SHIFT) & A4XX_RB_STENCIL_CONTROL_FUNC__MASK;
}
#define A4XX_RB_STENCIL_CONTROL_FAIL__MASK 0x00003800
#define A4XX_RB_STENCIL_CONTROL_FAIL__SHIFT 11
static inline uint32_t A4XX_RB_STENCIL_CONTROL_FAIL(enum adreno_stencil_op val)
{
return ((val) << A4XX_RB_STENCIL_CONTROL_FAIL__SHIFT) & A4XX_RB_STENCIL_CONTROL_FAIL__MASK;
}
#define A4XX_RB_STENCIL_CONTROL_ZPASS__MASK 0x0001c000
#define A4XX_RB_STENCIL_CONTROL_ZPASS__SHIFT 14
static inline uint32_t A4XX_RB_STENCIL_CONTROL_ZPASS(enum adreno_stencil_op val)
{
return ((val) << A4XX_RB_STENCIL_CONTROL_ZPASS__SHIFT) & A4XX_RB_STENCIL_CONTROL_ZPASS__MASK;
}
#define A4XX_RB_STENCIL_CONTROL_ZFAIL__MASK 0x000e0000
#define A4XX_RB_STENCIL_CONTROL_ZFAIL__SHIFT 17
static inline uint32_t A4XX_RB_STENCIL_CONTROL_ZFAIL(enum adreno_stencil_op val)
{
return ((val) << A4XX_RB_STENCIL_CONTROL_ZFAIL__SHIFT) & A4XX_RB_STENCIL_CONTROL_ZFAIL__MASK;
}
#define A4XX_RB_STENCIL_CONTROL_FUNC_BF__MASK 0x00700000
#define A4XX_RB_STENCIL_CONTROL_FUNC_BF__SHIFT 20
static inline uint32_t A4XX_RB_STENCIL_CONTROL_FUNC_BF(enum adreno_compare_func val)
{
return ((val) << A4XX_RB_STENCIL_CONTROL_FUNC_BF__SHIFT) & A4XX_RB_STENCIL_CONTROL_FUNC_BF__MASK;
}
#define A4XX_RB_STENCIL_CONTROL_FAIL_BF__MASK 0x03800000
#define A4XX_RB_STENCIL_CONTROL_FAIL_BF__SHIFT 23
static inline uint32_t A4XX_RB_STENCIL_CONTROL_FAIL_BF(enum adreno_stencil_op val)
{
return ((val) << A4XX_RB_STENCIL_CONTROL_FAIL_BF__SHIFT) & A4XX_RB_STENCIL_CONTROL_FAIL_BF__MASK;
}
#define A4XX_RB_STENCIL_CONTROL_ZPASS_BF__MASK 0x1c000000
#define A4XX_RB_STENCIL_CONTROL_ZPASS_BF__SHIFT 26
static inline uint32_t A4XX_RB_STENCIL_CONTROL_ZPASS_BF(enum adreno_stencil_op val)
{
return ((val) << A4XX_RB_STENCIL_CONTROL_ZPASS_BF__SHIFT) & A4XX_RB_STENCIL_CONTROL_ZPASS_BF__MASK;
}
#define A4XX_RB_STENCIL_CONTROL_ZFAIL_BF__MASK 0xe0000000
#define A4XX_RB_STENCIL_CONTROL_ZFAIL_BF__SHIFT 29
static inline uint32_t A4XX_RB_STENCIL_CONTROL_ZFAIL_BF(enum adreno_stencil_op val)
{
return ((val) << A4XX_RB_STENCIL_CONTROL_ZFAIL_BF__SHIFT) & A4XX_RB_STENCIL_CONTROL_ZFAIL_BF__MASK;
}
 
#define REG_A4XX_RB_STENCIL_CONTROL2 0x00002107
#define A4XX_RB_STENCIL_CONTROL2_STENCIL_BUFFER 0x00000001
 
#define REG_A4XX_RB_STENCILREFMASK 0x0000210b
#define A4XX_RB_STENCILREFMASK_STENCILREF__MASK 0x000000ff
#define A4XX_RB_STENCILREFMASK_STENCILREF__SHIFT 0
static inline uint32_t A4XX_RB_STENCILREFMASK_STENCILREF(uint32_t val)
{
return ((val) << A4XX_RB_STENCILREFMASK_STENCILREF__SHIFT) & A4XX_RB_STENCILREFMASK_STENCILREF__MASK;
}
#define A4XX_RB_STENCILREFMASK_STENCILMASK__MASK 0x0000ff00
#define A4XX_RB_STENCILREFMASK_STENCILMASK__SHIFT 8
static inline uint32_t A4XX_RB_STENCILREFMASK_STENCILMASK(uint32_t val)
{
return ((val) << A4XX_RB_STENCILREFMASK_STENCILMASK__SHIFT) & A4XX_RB_STENCILREFMASK_STENCILMASK__MASK;
}
#define A4XX_RB_STENCILREFMASK_STENCILWRITEMASK__MASK 0x00ff0000
#define A4XX_RB_STENCILREFMASK_STENCILWRITEMASK__SHIFT 16
static inline uint32_t A4XX_RB_STENCILREFMASK_STENCILWRITEMASK(uint32_t val)
{
return ((val) << A4XX_RB_STENCILREFMASK_STENCILWRITEMASK__SHIFT) & A4XX_RB_STENCILREFMASK_STENCILWRITEMASK__MASK;
}
 
#define REG_A4XX_RB_STENCILREFMASK_BF 0x0000210c
#define A4XX_RB_STENCILREFMASK_BF_STENCILREF__MASK 0x000000ff
#define A4XX_RB_STENCILREFMASK_BF_STENCILREF__SHIFT 0
static inline uint32_t A4XX_RB_STENCILREFMASK_BF_STENCILREF(uint32_t val)
{
return ((val) << A4XX_RB_STENCILREFMASK_BF_STENCILREF__SHIFT) & A4XX_RB_STENCILREFMASK_BF_STENCILREF__MASK;
}
#define A4XX_RB_STENCILREFMASK_BF_STENCILMASK__MASK 0x0000ff00
#define A4XX_RB_STENCILREFMASK_BF_STENCILMASK__SHIFT 8
static inline uint32_t A4XX_RB_STENCILREFMASK_BF_STENCILMASK(uint32_t val)
{
return ((val) << A4XX_RB_STENCILREFMASK_BF_STENCILMASK__SHIFT) & A4XX_RB_STENCILREFMASK_BF_STENCILMASK__MASK;
}
#define A4XX_RB_STENCILREFMASK_BF_STENCILWRITEMASK__MASK 0x00ff0000
#define A4XX_RB_STENCILREFMASK_BF_STENCILWRITEMASK__SHIFT 16
static inline uint32_t A4XX_RB_STENCILREFMASK_BF_STENCILWRITEMASK(uint32_t val)
{
return ((val) << A4XX_RB_STENCILREFMASK_BF_STENCILWRITEMASK__SHIFT) & A4XX_RB_STENCILREFMASK_BF_STENCILWRITEMASK__MASK;
}
 
#define REG_A4XX_RB_BIN_OFFSET 0x0000210d
#define A4XX_RB_BIN_OFFSET_WINDOW_OFFSET_DISABLE 0x80000000
#define A4XX_RB_BIN_OFFSET_X__MASK 0x00007fff
#define A4XX_RB_BIN_OFFSET_X__SHIFT 0
static inline uint32_t A4XX_RB_BIN_OFFSET_X(uint32_t val)
{
return ((val) << A4XX_RB_BIN_OFFSET_X__SHIFT) & A4XX_RB_BIN_OFFSET_X__MASK;
}
#define A4XX_RB_BIN_OFFSET_Y__MASK 0x7fff0000
#define A4XX_RB_BIN_OFFSET_Y__SHIFT 16
static inline uint32_t A4XX_RB_BIN_OFFSET_Y(uint32_t val)
{
return ((val) << A4XX_RB_BIN_OFFSET_Y__SHIFT) & A4XX_RB_BIN_OFFSET_Y__MASK;
}
 
static inline uint32_t REG_A4XX_RB_VPORT_Z_CLAMP(uint32_t i0) { return 0x00002120 + 0x2*i0; }
 
static inline uint32_t REG_A4XX_RB_VPORT_Z_CLAMP_MIN(uint32_t i0) { return 0x00002120 + 0x2*i0; }
 
static inline uint32_t REG_A4XX_RB_VPORT_Z_CLAMP_MAX(uint32_t i0) { return 0x00002121 + 0x2*i0; }
 
#define REG_A4XX_RBBM_HW_VERSION 0x00000000
 
#define REG_A4XX_RBBM_HW_CONFIGURATION 0x00000002
 
static inline uint32_t REG_A4XX_RBBM_CLOCK_CTL_TP(uint32_t i0) { return 0x00000004 + 0x1*i0; }
 
static inline uint32_t REG_A4XX_RBBM_CLOCK_CTL_TP_REG(uint32_t i0) { return 0x00000004 + 0x1*i0; }
 
static inline uint32_t REG_A4XX_RBBM_CLOCK_CTL2_TP(uint32_t i0) { return 0x00000008 + 0x1*i0; }
 
static inline uint32_t REG_A4XX_RBBM_CLOCK_CTL2_TP_REG(uint32_t i0) { return 0x00000008 + 0x1*i0; }
 
static inline uint32_t REG_A4XX_RBBM_CLOCK_HYST_TP(uint32_t i0) { return 0x0000000c + 0x1*i0; }
 
static inline uint32_t REG_A4XX_RBBM_CLOCK_HYST_TP_REG(uint32_t i0) { return 0x0000000c + 0x1*i0; }
 
static inline uint32_t REG_A4XX_RBBM_CLOCK_DELAY_TP(uint32_t i0) { return 0x00000010 + 0x1*i0; }
 
static inline uint32_t REG_A4XX_RBBM_CLOCK_DELAY_TP_REG(uint32_t i0) { return 0x00000010 + 0x1*i0; }
 
#define REG_A4XX_RBBM_CLOCK_CTL_UCHE 0x00000014
 
#define REG_A4XX_RBBM_CLOCK_CTL2_UCHE 0x00000015
 
#define REG_A4XX_RBBM_CLOCK_CTL3_UCHE 0x00000016
 
#define REG_A4XX_RBBM_CLOCK_CTL4_UCHE 0x00000017
 
#define REG_A4XX_RBBM_CLOCK_HYST_UCHE 0x00000018
 
#define REG_A4XX_RBBM_CLOCK_DELAY_UCHE 0x00000019
 
#define REG_A4XX_RBBM_CLOCK_MODE_GPC 0x0000001a
 
#define REG_A4XX_RBBM_CLOCK_DELAY_GPC 0x0000001b
 
#define REG_A4XX_RBBM_CLOCK_HYST_GPC 0x0000001c
 
#define REG_A4XX_RBBM_CLOCK_CTL_TSE_RAS_RBBM 0x0000001d
 
#define REG_A4XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM 0x0000001e
 
#define REG_A4XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM 0x0000001f
 
#define REG_A4XX_RBBM_CLOCK_CTL 0x00000020
 
#define REG_A4XX_RBBM_SP_HYST_CNT 0x00000021
 
#define REG_A4XX_RBBM_SW_RESET_CMD 0x00000022
 
#define REG_A4XX_RBBM_AHB_CTL0 0x00000023
 
#define REG_A4XX_RBBM_AHB_CTL1 0x00000024
 
#define REG_A4XX_RBBM_AHB_CMD 0x00000025
 
#define REG_A4XX_RBBM_RB_SUB_BLOCK_SEL_CTL 0x00000026
 
#define REG_A4XX_RBBM_RAM_ACC_63_32 0x00000028
 
#define REG_A4XX_RBBM_WAIT_IDLE_CLOCKS_CTL 0x0000002b
 
#define REG_A4XX_RBBM_INTERFACE_HANG_INT_CTL 0x0000002f
 
#define REG_A4XX_RBBM_INTERFACE_HANG_MASK_CTL4 0x00000034
 
#define REG_A4XX_RBBM_INT_CLEAR_CMD 0x00000036
 
#define REG_A4XX_RBBM_INT_0_MASK 0x00000037
 
#define REG_A4XX_RBBM_RBBM_CTL 0x0000003e
 
#define REG_A4XX_RBBM_AHB_DEBUG_CTL 0x0000003f
 
#define REG_A4XX_RBBM_VBIF_DEBUG_CTL 0x00000041
 
#define REG_A4XX_RBBM_CLOCK_CTL2 0x00000042
 
#define REG_A4XX_RBBM_BLOCK_SW_RESET_CMD 0x00000045
 
#define REG_A4XX_RBBM_RESET_CYCLES 0x00000047
 
#define REG_A4XX_RBBM_EXT_TRACE_BUS_CTL 0x00000049
 
#define REG_A4XX_RBBM_CFG_DEBBUS_SEL_A 0x0000004a
 
#define REG_A4XX_RBBM_CFG_DEBBUS_SEL_B 0x0000004b
 
#define REG_A4XX_RBBM_CFG_DEBBUS_SEL_C 0x0000004c
 
#define REG_A4XX_RBBM_CFG_DEBBUS_SEL_D 0x0000004d
 
#define REG_A4XX_RBBM_PERFCTR_CP_0_LO 0x0000009c
 
static inline uint32_t REG_A4XX_RBBM_CLOCK_CTL_SP(uint32_t i0) { return 0x00000068 + 0x1*i0; }
 
static inline uint32_t REG_A4XX_RBBM_CLOCK_CTL_SP_REG(uint32_t i0) { return 0x00000068 + 0x1*i0; }
 
static inline uint32_t REG_A4XX_RBBM_CLOCK_CTL2_SP(uint32_t i0) { return 0x0000006c + 0x1*i0; }
 
static inline uint32_t REG_A4XX_RBBM_CLOCK_CTL2_SP_REG(uint32_t i0) { return 0x0000006c + 0x1*i0; }
 
static inline uint32_t REG_A4XX_RBBM_CLOCK_HYST_SP(uint32_t i0) { return 0x00000070 + 0x1*i0; }
 
static inline uint32_t REG_A4XX_RBBM_CLOCK_HYST_SP_REG(uint32_t i0) { return 0x00000070 + 0x1*i0; }
 
static inline uint32_t REG_A4XX_RBBM_CLOCK_DELAY_SP(uint32_t i0) { return 0x00000074 + 0x1*i0; }
 
static inline uint32_t REG_A4XX_RBBM_CLOCK_DELAY_SP_REG(uint32_t i0) { return 0x00000074 + 0x1*i0; }
 
static inline uint32_t REG_A4XX_RBBM_CLOCK_CTL_RB(uint32_t i0) { return 0x00000078 + 0x1*i0; }
 
static inline uint32_t REG_A4XX_RBBM_CLOCK_CTL_RB_REG(uint32_t i0) { return 0x00000078 + 0x1*i0; }
 
static inline uint32_t REG_A4XX_RBBM_CLOCK_CTL2_RB(uint32_t i0) { return 0x0000007c + 0x1*i0; }
 
static inline uint32_t REG_A4XX_RBBM_CLOCK_CTL2_RB_REG(uint32_t i0) { return 0x0000007c + 0x1*i0; }
 
static inline uint32_t REG_A4XX_RBBM_CLOCK_CTL_MARB_CCU(uint32_t i0) { return 0x00000082 + 0x1*i0; }
 
static inline uint32_t REG_A4XX_RBBM_CLOCK_CTL_MARB_CCU_REG(uint32_t i0) { return 0x00000082 + 0x1*i0; }
 
static inline uint32_t REG_A4XX_RBBM_CLOCK_HYST_RB_MARB_CCU(uint32_t i0) { return 0x00000086 + 0x1*i0; }
 
static inline uint32_t REG_A4XX_RBBM_CLOCK_HYST_RB_MARB_CCU_REG(uint32_t i0) { return 0x00000086 + 0x1*i0; }
 
#define REG_A4XX_RBBM_CLOCK_HYST_COM_DCOM 0x00000080
 
#define REG_A4XX_RBBM_CLOCK_CTL_COM_DCOM 0x00000081
 
#define REG_A4XX_RBBM_CLOCK_CTL_HLSQ 0x0000008a
 
#define REG_A4XX_RBBM_CLOCK_HYST_HLSQ 0x0000008b
 
#define REG_A4XX_RBBM_CLOCK_DELAY_HLSQ 0x0000008c
 
#define REG_A4XX_RBBM_CLOCK_DELAY_COM_DCOM 0x0000008d
 
static inline uint32_t REG_A4XX_RBBM_CLOCK_DELAY_RB_MARB_CCU_L1(uint32_t i0) { return 0x0000008e + 0x1*i0; }
 
static inline uint32_t REG_A4XX_RBBM_CLOCK_DELAY_RB_MARB_CCU_L1_REG(uint32_t i0) { return 0x0000008e + 0x1*i0; }
 
#define REG_A4XX_RBBM_PERFCTR_PWR_1_LO 0x00000168
 
#define REG_A4XX_RBBM_PERFCTR_CTL 0x00000170
 
#define REG_A4XX_RBBM_PERFCTR_LOAD_CMD0 0x00000171
 
#define REG_A4XX_RBBM_PERFCTR_LOAD_CMD1 0x00000172
 
#define REG_A4XX_RBBM_PERFCTR_LOAD_CMD2 0x00000173
 
#define REG_A4XX_RBBM_PERFCTR_LOAD_VALUE_LO 0x00000174
 
#define REG_A4XX_RBBM_PERFCTR_LOAD_VALUE_HI 0x00000175
 
#define REG_A4XX_RBBM_GPU_BUSY_MASKED 0x0000017a
 
#define REG_A4XX_RBBM_INT_0_STATUS 0x0000017d
 
#define REG_A4XX_RBBM_CLOCK_STATUS 0x00000182
 
#define REG_A4XX_RBBM_AHB_STATUS 0x00000189
 
#define REG_A4XX_RBBM_AHB_ME_SPLIT_STATUS 0x0000018c
 
#define REG_A4XX_RBBM_AHB_PFP_SPLIT_STATUS 0x0000018d
 
#define REG_A4XX_RBBM_AHB_ERROR_STATUS 0x0000018f
 
#define REG_A4XX_RBBM_STATUS 0x00000191
#define A4XX_RBBM_STATUS_HI_BUSY 0x00000001
#define A4XX_RBBM_STATUS_CP_ME_BUSY 0x00000002
#define A4XX_RBBM_STATUS_CP_PFP_BUSY 0x00000004
#define A4XX_RBBM_STATUS_CP_NRT_BUSY 0x00004000
#define A4XX_RBBM_STATUS_VBIF_BUSY 0x00008000
#define A4XX_RBBM_STATUS_TSE_BUSY 0x00010000
#define A4XX_RBBM_STATUS_RAS_BUSY 0x00020000
#define A4XX_RBBM_STATUS_RB_BUSY 0x00040000
#define A4XX_RBBM_STATUS_PC_DCALL_BUSY 0x00080000
#define A4XX_RBBM_STATUS_PC_VSD_BUSY 0x00100000
#define A4XX_RBBM_STATUS_VFD_BUSY 0x00200000
#define A4XX_RBBM_STATUS_VPC_BUSY 0x00400000
#define A4XX_RBBM_STATUS_UCHE_BUSY 0x00800000
#define A4XX_RBBM_STATUS_SP_BUSY 0x01000000
#define A4XX_RBBM_STATUS_TPL1_BUSY 0x02000000
#define A4XX_RBBM_STATUS_MARB_BUSY 0x04000000
#define A4XX_RBBM_STATUS_VSC_BUSY 0x08000000
#define A4XX_RBBM_STATUS_ARB_BUSY 0x10000000
#define A4XX_RBBM_STATUS_HLSQ_BUSY 0x20000000
#define A4XX_RBBM_STATUS_GPU_BUSY_NOHC 0x40000000
#define A4XX_RBBM_STATUS_GPU_BUSY 0x80000000
 
#define REG_A4XX_RBBM_INTERFACE_RRDY_STATUS5 0x0000019f
 
#define REG_A4XX_CP_SCRATCH_UMASK 0x00000228
 
#define REG_A4XX_CP_SCRATCH_ADDR 0x00000229
 
#define REG_A4XX_CP_RB_BASE 0x00000200
 
#define REG_A4XX_CP_RB_CNTL 0x00000201
 
#define REG_A4XX_CP_RB_WPTR 0x00000205
 
#define REG_A4XX_CP_RB_RPTR_ADDR 0x00000203
 
#define REG_A4XX_CP_RB_RPTR 0x00000204
 
#define REG_A4XX_CP_IB1_BASE 0x00000206
 
#define REG_A4XX_CP_IB1_BUFSZ 0x00000207
 
#define REG_A4XX_CP_IB2_BASE 0x00000208
 
#define REG_A4XX_CP_IB2_BUFSZ 0x00000209
 
#define REG_A4XX_CP_ME_NRT_ADDR 0x0000020c
 
#define REG_A4XX_CP_ME_NRT_DATA 0x0000020d
 
#define REG_A4XX_CP_ME_RB_DONE_DATA 0x00000217
 
#define REG_A4XX_CP_QUEUE_THRESH2 0x00000219
 
#define REG_A4XX_CP_MERCIU_SIZE 0x0000021b
 
#define REG_A4XX_CP_ROQ_ADDR 0x0000021c
 
#define REG_A4XX_CP_ROQ_DATA 0x0000021d
 
#define REG_A4XX_CP_MEQ_ADDR 0x0000021e
 
#define REG_A4XX_CP_MEQ_DATA 0x0000021f
 
#define REG_A4XX_CP_MERCIU_ADDR 0x00000220
 
#define REG_A4XX_CP_MERCIU_DATA 0x00000221
 
#define REG_A4XX_CP_MERCIU_DATA2 0x00000222
 
#define REG_A4XX_CP_PFP_UCODE_ADDR 0x00000223
 
#define REG_A4XX_CP_PFP_UCODE_DATA 0x00000224
 
#define REG_A4XX_CP_ME_RAM_WADDR 0x00000225
 
#define REG_A4XX_CP_ME_RAM_RADDR 0x00000226
 
#define REG_A4XX_CP_ME_RAM_DATA 0x00000227
 
#define REG_A4XX_CP_PREEMPT 0x0000022a
 
#define REG_A4XX_CP_CNTL 0x0000022c
 
#define REG_A4XX_CP_ME_CNTL 0x0000022d
 
#define REG_A4XX_CP_DEBUG 0x0000022e
 
#define REG_A4XX_CP_DEBUG_ECO_CONTROL 0x00000231
 
#define REG_A4XX_CP_DRAW_STATE_ADDR 0x00000232
 
#define REG_A4XX_CP_PROTECT_REG_0 0x00000240
 
static inline uint32_t REG_A4XX_CP_PROTECT(uint32_t i0) { return 0x00000240 + 0x1*i0; }
 
static inline uint32_t REG_A4XX_CP_PROTECT_REG(uint32_t i0) { return 0x00000240 + 0x1*i0; }
 
#define REG_A4XX_CP_PROTECT_CTRL 0x00000250
 
#define REG_A4XX_CP_ST_BASE 0x000004c0
 
#define REG_A4XX_CP_STQ_AVAIL 0x000004ce
 
#define REG_A4XX_CP_MERCIU_STAT 0x000004d0
 
#define REG_A4XX_CP_WFI_PEND_CTR 0x000004d2
 
#define REG_A4XX_CP_HW_FAULT 0x000004d8
 
#define REG_A4XX_CP_PROTECT_STATUS 0x000004da
 
#define REG_A4XX_CP_EVENTS_IN_FLIGHT 0x000004dd
 
#define REG_A4XX_CP_PERFCTR_CP_SEL_0 0x00000500
 
#define REG_A4XX_CP_PERFCOMBINER_SELECT 0x0000050b
 
static inline uint32_t REG_A4XX_CP_SCRATCH(uint32_t i0) { return 0x00000578 + 0x1*i0; }
 
static inline uint32_t REG_A4XX_CP_SCRATCH_REG(uint32_t i0) { return 0x00000578 + 0x1*i0; }
 
#define REG_A4XX_SP_VS_STATUS 0x00000ec0
 
#define REG_A4XX_SP_PERFCTR_SP_SEL_11 0x00000ecf
 
#define REG_A4XX_SP_SP_CTRL_REG 0x000022c0
#define A4XX_SP_SP_CTRL_REG_BINNING_PASS 0x00080000
 
#define REG_A4XX_SP_INSTR_CACHE_CTRL 0x000022c1
#define A4XX_SP_INSTR_CACHE_CTRL_VS_BUFFER 0x00000080
#define A4XX_SP_INSTR_CACHE_CTRL_FS_BUFFER 0x00000100
#define A4XX_SP_INSTR_CACHE_CTRL_INSTR_BUFFER 0x00000400
 
#define REG_A4XX_SP_VS_CTRL_REG0 0x000022c4
#define A4XX_SP_VS_CTRL_REG0_THREADMODE__MASK 0x00000001
#define A4XX_SP_VS_CTRL_REG0_THREADMODE__SHIFT 0
static inline uint32_t A4XX_SP_VS_CTRL_REG0_THREADMODE(enum a3xx_threadmode val)
{
return ((val) << A4XX_SP_VS_CTRL_REG0_THREADMODE__SHIFT) & A4XX_SP_VS_CTRL_REG0_THREADMODE__MASK;
}
#define A4XX_SP_VS_CTRL_REG0_VARYING 0x00000002
#define A4XX_SP_VS_CTRL_REG0_CACHEINVALID 0x00000004
#define A4XX_SP_VS_CTRL_REG0_HALFREGFOOTPRINT__MASK 0x000003f0
#define A4XX_SP_VS_CTRL_REG0_HALFREGFOOTPRINT__SHIFT 4
static inline uint32_t A4XX_SP_VS_CTRL_REG0_HALFREGFOOTPRINT(uint32_t val)
{
return ((val) << A4XX_SP_VS_CTRL_REG0_HALFREGFOOTPRINT__SHIFT) & A4XX_SP_VS_CTRL_REG0_HALFREGFOOTPRINT__MASK;
}
#define A4XX_SP_VS_CTRL_REG0_FULLREGFOOTPRINT__MASK 0x0003fc00
#define A4XX_SP_VS_CTRL_REG0_FULLREGFOOTPRINT__SHIFT 10
static inline uint32_t A4XX_SP_VS_CTRL_REG0_FULLREGFOOTPRINT(uint32_t val)
{
return ((val) << A4XX_SP_VS_CTRL_REG0_FULLREGFOOTPRINT__SHIFT) & A4XX_SP_VS_CTRL_REG0_FULLREGFOOTPRINT__MASK;
}
#define A4XX_SP_VS_CTRL_REG0_INOUTREGOVERLAP__MASK 0x000c0000
#define A4XX_SP_VS_CTRL_REG0_INOUTREGOVERLAP__SHIFT 18
static inline uint32_t A4XX_SP_VS_CTRL_REG0_INOUTREGOVERLAP(uint32_t val)
{
return ((val) << A4XX_SP_VS_CTRL_REG0_INOUTREGOVERLAP__SHIFT) & A4XX_SP_VS_CTRL_REG0_INOUTREGOVERLAP__MASK;
}
#define A4XX_SP_VS_CTRL_REG0_THREADSIZE__MASK 0x00100000
#define A4XX_SP_VS_CTRL_REG0_THREADSIZE__SHIFT 20
static inline uint32_t A4XX_SP_VS_CTRL_REG0_THREADSIZE(enum a3xx_threadsize val)
{
return ((val) << A4XX_SP_VS_CTRL_REG0_THREADSIZE__SHIFT) & A4XX_SP_VS_CTRL_REG0_THREADSIZE__MASK;
}
#define A4XX_SP_VS_CTRL_REG0_SUPERTHREADMODE 0x00200000
#define A4XX_SP_VS_CTRL_REG0_PIXLODENABLE 0x00400000
 
#define REG_A4XX_SP_VS_CTRL_REG1 0x000022c5
#define A4XX_SP_VS_CTRL_REG1_CONSTLENGTH__MASK 0x000000ff
#define A4XX_SP_VS_CTRL_REG1_CONSTLENGTH__SHIFT 0
static inline uint32_t A4XX_SP_VS_CTRL_REG1_CONSTLENGTH(uint32_t val)
{
return ((val) << A4XX_SP_VS_CTRL_REG1_CONSTLENGTH__SHIFT) & A4XX_SP_VS_CTRL_REG1_CONSTLENGTH__MASK;
}
#define A4XX_SP_VS_CTRL_REG1_INITIALOUTSTANDING__MASK 0x7f000000
#define A4XX_SP_VS_CTRL_REG1_INITIALOUTSTANDING__SHIFT 24
static inline uint32_t A4XX_SP_VS_CTRL_REG1_INITIALOUTSTANDING(uint32_t val)
{
return ((val) << A4XX_SP_VS_CTRL_REG1_INITIALOUTSTANDING__SHIFT) & A4XX_SP_VS_CTRL_REG1_INITIALOUTSTANDING__MASK;
}
 
#define REG_A4XX_SP_VS_PARAM_REG 0x000022c6
#define A4XX_SP_VS_PARAM_REG_POSREGID__MASK 0x000000ff
#define A4XX_SP_VS_PARAM_REG_POSREGID__SHIFT 0
static inline uint32_t A4XX_SP_VS_PARAM_REG_POSREGID(uint32_t val)
{
return ((val) << A4XX_SP_VS_PARAM_REG_POSREGID__SHIFT) & A4XX_SP_VS_PARAM_REG_POSREGID__MASK;
}
#define A4XX_SP_VS_PARAM_REG_PSIZEREGID__MASK 0x0000ff00
#define A4XX_SP_VS_PARAM_REG_PSIZEREGID__SHIFT 8
static inline uint32_t A4XX_SP_VS_PARAM_REG_PSIZEREGID(uint32_t val)
{
return ((val) << A4XX_SP_VS_PARAM_REG_PSIZEREGID__SHIFT) & A4XX_SP_VS_PARAM_REG_PSIZEREGID__MASK;
}
#define A4XX_SP_VS_PARAM_REG_TOTALVSOUTVAR__MASK 0xfff00000
#define A4XX_SP_VS_PARAM_REG_TOTALVSOUTVAR__SHIFT 20
static inline uint32_t A4XX_SP_VS_PARAM_REG_TOTALVSOUTVAR(uint32_t val)
{
return ((val) << A4XX_SP_VS_PARAM_REG_TOTALVSOUTVAR__SHIFT) & A4XX_SP_VS_PARAM_REG_TOTALVSOUTVAR__MASK;
}
 
static inline uint32_t REG_A4XX_SP_VS_OUT(uint32_t i0) { return 0x000022c7 + 0x1*i0; }
 
static inline uint32_t REG_A4XX_SP_VS_OUT_REG(uint32_t i0) { return 0x000022c7 + 0x1*i0; }
#define A4XX_SP_VS_OUT_REG_A_REGID__MASK 0x000001ff
#define A4XX_SP_VS_OUT_REG_A_REGID__SHIFT 0
static inline uint32_t A4XX_SP_VS_OUT_REG_A_REGID(uint32_t val)
{
return ((val) << A4XX_SP_VS_OUT_REG_A_REGID__SHIFT) & A4XX_SP_VS_OUT_REG_A_REGID__MASK;
}
#define A4XX_SP_VS_OUT_REG_A_COMPMASK__MASK 0x00001e00
#define A4XX_SP_VS_OUT_REG_A_COMPMASK__SHIFT 9
static inline uint32_t A4XX_SP_VS_OUT_REG_A_COMPMASK(uint32_t val)
{
return ((val) << A4XX_SP_VS_OUT_REG_A_COMPMASK__SHIFT) & A4XX_SP_VS_OUT_REG_A_COMPMASK__MASK;
}
#define A4XX_SP_VS_OUT_REG_B_REGID__MASK 0x01ff0000
#define A4XX_SP_VS_OUT_REG_B_REGID__SHIFT 16
static inline uint32_t A4XX_SP_VS_OUT_REG_B_REGID(uint32_t val)
{
return ((val) << A4XX_SP_VS_OUT_REG_B_REGID__SHIFT) & A4XX_SP_VS_OUT_REG_B_REGID__MASK;
}
#define A4XX_SP_VS_OUT_REG_B_COMPMASK__MASK 0x1e000000
#define A4XX_SP_VS_OUT_REG_B_COMPMASK__SHIFT 25
static inline uint32_t A4XX_SP_VS_OUT_REG_B_COMPMASK(uint32_t val)
{
return ((val) << A4XX_SP_VS_OUT_REG_B_COMPMASK__SHIFT) & A4XX_SP_VS_OUT_REG_B_COMPMASK__MASK;
}
 
static inline uint32_t REG_A4XX_SP_VS_VPC_DST(uint32_t i0) { return 0x000022d8 + 0x1*i0; }
 
static inline uint32_t REG_A4XX_SP_VS_VPC_DST_REG(uint32_t i0) { return 0x000022d8 + 0x1*i0; }
#define A4XX_SP_VS_VPC_DST_REG_OUTLOC0__MASK 0x000000ff
#define A4XX_SP_VS_VPC_DST_REG_OUTLOC0__SHIFT 0
static inline uint32_t A4XX_SP_VS_VPC_DST_REG_OUTLOC0(uint32_t val)
{
return ((val) << A4XX_SP_VS_VPC_DST_REG_OUTLOC0__SHIFT) & A4XX_SP_VS_VPC_DST_REG_OUTLOC0__MASK;
}
#define A4XX_SP_VS_VPC_DST_REG_OUTLOC1__MASK 0x0000ff00
#define A4XX_SP_VS_VPC_DST_REG_OUTLOC1__SHIFT 8
static inline uint32_t A4XX_SP_VS_VPC_DST_REG_OUTLOC1(uint32_t val)
{
return ((val) << A4XX_SP_VS_VPC_DST_REG_OUTLOC1__SHIFT) & A4XX_SP_VS_VPC_DST_REG_OUTLOC1__MASK;
}
#define A4XX_SP_VS_VPC_DST_REG_OUTLOC2__MASK 0x00ff0000
#define A4XX_SP_VS_VPC_DST_REG_OUTLOC2__SHIFT 16
static inline uint32_t A4XX_SP_VS_VPC_DST_REG_OUTLOC2(uint32_t val)
{
return ((val) << A4XX_SP_VS_VPC_DST_REG_OUTLOC2__SHIFT) & A4XX_SP_VS_VPC_DST_REG_OUTLOC2__MASK;
}
#define A4XX_SP_VS_VPC_DST_REG_OUTLOC3__MASK 0xff000000
#define A4XX_SP_VS_VPC_DST_REG_OUTLOC3__SHIFT 24
static inline uint32_t A4XX_SP_VS_VPC_DST_REG_OUTLOC3(uint32_t val)
{
return ((val) << A4XX_SP_VS_VPC_DST_REG_OUTLOC3__SHIFT) & A4XX_SP_VS_VPC_DST_REG_OUTLOC3__MASK;
}
 
#define REG_A4XX_SP_VS_OBJ_OFFSET_REG 0x000022e0
#define A4XX_SP_VS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__MASK 0x01ff0000
#define A4XX_SP_VS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__SHIFT 16
static inline uint32_t A4XX_SP_VS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET(uint32_t val)
{
return ((val) << A4XX_SP_VS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__SHIFT) & A4XX_SP_VS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__MASK;
}
#define A4XX_SP_VS_OBJ_OFFSET_REG_SHADEROBJOFFSET__MASK 0xfe000000
#define A4XX_SP_VS_OBJ_OFFSET_REG_SHADEROBJOFFSET__SHIFT 25
static inline uint32_t A4XX_SP_VS_OBJ_OFFSET_REG_SHADEROBJOFFSET(uint32_t val)
{
return ((val) << A4XX_SP_VS_OBJ_OFFSET_REG_SHADEROBJOFFSET__SHIFT) & A4XX_SP_VS_OBJ_OFFSET_REG_SHADEROBJOFFSET__MASK;
}
 
#define REG_A4XX_SP_VS_OBJ_START 0x000022e1
 
#define REG_A4XX_SP_VS_PVT_MEM_PARAM 0x000022e2
 
#define REG_A4XX_SP_VS_PVT_MEM_ADDR 0x000022e3
 
#define REG_A4XX_SP_VS_LENGTH_REG 0x000022e5
 
#define REG_A4XX_SP_FS_CTRL_REG0 0x000022e8
#define A4XX_SP_FS_CTRL_REG0_THREADMODE__MASK 0x00000001
#define A4XX_SP_FS_CTRL_REG0_THREADMODE__SHIFT 0
static inline uint32_t A4XX_SP_FS_CTRL_REG0_THREADMODE(enum a3xx_threadmode val)
{
return ((val) << A4XX_SP_FS_CTRL_REG0_THREADMODE__SHIFT) & A4XX_SP_FS_CTRL_REG0_THREADMODE__MASK;
}
#define A4XX_SP_FS_CTRL_REG0_VARYING 0x00000002
#define A4XX_SP_FS_CTRL_REG0_CACHEINVALID 0x00000004
#define A4XX_SP_FS_CTRL_REG0_HALFREGFOOTPRINT__MASK 0x000003f0
#define A4XX_SP_FS_CTRL_REG0_HALFREGFOOTPRINT__SHIFT 4
static inline uint32_t A4XX_SP_FS_CTRL_REG0_HALFREGFOOTPRINT(uint32_t val)
{
return ((val) << A4XX_SP_FS_CTRL_REG0_HALFREGFOOTPRINT__SHIFT) & A4XX_SP_FS_CTRL_REG0_HALFREGFOOTPRINT__MASK;
}
#define A4XX_SP_FS_CTRL_REG0_FULLREGFOOTPRINT__MASK 0x0003fc00
#define A4XX_SP_FS_CTRL_REG0_FULLREGFOOTPRINT__SHIFT 10
static inline uint32_t A4XX_SP_FS_CTRL_REG0_FULLREGFOOTPRINT(uint32_t val)
{
return ((val) << A4XX_SP_FS_CTRL_REG0_FULLREGFOOTPRINT__SHIFT) & A4XX_SP_FS_CTRL_REG0_FULLREGFOOTPRINT__MASK;
}
#define A4XX_SP_FS_CTRL_REG0_INOUTREGOVERLAP__MASK 0x000c0000
#define A4XX_SP_FS_CTRL_REG0_INOUTREGOVERLAP__SHIFT 18
static inline uint32_t A4XX_SP_FS_CTRL_REG0_INOUTREGOVERLAP(uint32_t val)
{
return ((val) << A4XX_SP_FS_CTRL_REG0_INOUTREGOVERLAP__SHIFT) & A4XX_SP_FS_CTRL_REG0_INOUTREGOVERLAP__MASK;
}
#define A4XX_SP_FS_CTRL_REG0_THREADSIZE__MASK 0x00100000
#define A4XX_SP_FS_CTRL_REG0_THREADSIZE__SHIFT 20
static inline uint32_t A4XX_SP_FS_CTRL_REG0_THREADSIZE(enum a3xx_threadsize val)
{
return ((val) << A4XX_SP_FS_CTRL_REG0_THREADSIZE__SHIFT) & A4XX_SP_FS_CTRL_REG0_THREADSIZE__MASK;
}
#define A4XX_SP_FS_CTRL_REG0_SUPERTHREADMODE 0x00200000
#define A4XX_SP_FS_CTRL_REG0_PIXLODENABLE 0x00400000
 
#define REG_A4XX_SP_FS_CTRL_REG1 0x000022e9
#define A4XX_SP_FS_CTRL_REG1_CONSTLENGTH__MASK 0x000000ff
#define A4XX_SP_FS_CTRL_REG1_CONSTLENGTH__SHIFT 0
static inline uint32_t A4XX_SP_FS_CTRL_REG1_CONSTLENGTH(uint32_t val)
{
return ((val) << A4XX_SP_FS_CTRL_REG1_CONSTLENGTH__SHIFT) & A4XX_SP_FS_CTRL_REG1_CONSTLENGTH__MASK;
}
#define A4XX_SP_FS_CTRL_REG1_FACENESS 0x00080000
#define A4XX_SP_FS_CTRL_REG1_VARYING 0x00100000
#define A4XX_SP_FS_CTRL_REG1_FRAGCOORD 0x00200000
 
#define REG_A4XX_SP_FS_OBJ_OFFSET_REG 0x000022ea
#define A4XX_SP_FS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__MASK 0x01ff0000
#define A4XX_SP_FS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__SHIFT 16
static inline uint32_t A4XX_SP_FS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET(uint32_t val)
{
return ((val) << A4XX_SP_FS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__SHIFT) & A4XX_SP_FS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__MASK;
}
#define A4XX_SP_FS_OBJ_OFFSET_REG_SHADEROBJOFFSET__MASK 0xfe000000
#define A4XX_SP_FS_OBJ_OFFSET_REG_SHADEROBJOFFSET__SHIFT 25
static inline uint32_t A4XX_SP_FS_OBJ_OFFSET_REG_SHADEROBJOFFSET(uint32_t val)
{
return ((val) << A4XX_SP_FS_OBJ_OFFSET_REG_SHADEROBJOFFSET__SHIFT) & A4XX_SP_FS_OBJ_OFFSET_REG_SHADEROBJOFFSET__MASK;
}
 
#define REG_A4XX_SP_FS_OBJ_START 0x000022eb
 
#define REG_A4XX_SP_FS_PVT_MEM_PARAM 0x000022ec
 
#define REG_A4XX_SP_FS_PVT_MEM_ADDR 0x000022ed
 
#define REG_A4XX_SP_FS_LENGTH_REG 0x000022ef
 
#define REG_A4XX_SP_FS_OUTPUT_REG 0x000022f0
#define A4XX_SP_FS_OUTPUT_REG_MRT__MASK 0x0000000f
#define A4XX_SP_FS_OUTPUT_REG_MRT__SHIFT 0
static inline uint32_t A4XX_SP_FS_OUTPUT_REG_MRT(uint32_t val)
{
return ((val) << A4XX_SP_FS_OUTPUT_REG_MRT__SHIFT) & A4XX_SP_FS_OUTPUT_REG_MRT__MASK;
}
#define A4XX_SP_FS_OUTPUT_REG_DEPTH_ENABLE 0x00000080
#define A4XX_SP_FS_OUTPUT_REG_DEPTH_REGID__MASK 0x0000ff00
#define A4XX_SP_FS_OUTPUT_REG_DEPTH_REGID__SHIFT 8
static inline uint32_t A4XX_SP_FS_OUTPUT_REG_DEPTH_REGID(uint32_t val)
{
return ((val) << A4XX_SP_FS_OUTPUT_REG_DEPTH_REGID__SHIFT) & A4XX_SP_FS_OUTPUT_REG_DEPTH_REGID__MASK;
}
#define A4XX_SP_FS_OUTPUT_REG_SAMPLEMASK_REGID__MASK 0xff000000
#define A4XX_SP_FS_OUTPUT_REG_SAMPLEMASK_REGID__SHIFT 24
static inline uint32_t A4XX_SP_FS_OUTPUT_REG_SAMPLEMASK_REGID(uint32_t val)
{
return ((val) << A4XX_SP_FS_OUTPUT_REG_SAMPLEMASK_REGID__SHIFT) & A4XX_SP_FS_OUTPUT_REG_SAMPLEMASK_REGID__MASK;
}
 
static inline uint32_t REG_A4XX_SP_FS_MRT(uint32_t i0) { return 0x000022f1 + 0x1*i0; }
 
static inline uint32_t REG_A4XX_SP_FS_MRT_REG(uint32_t i0) { return 0x000022f1 + 0x1*i0; }
#define A4XX_SP_FS_MRT_REG_REGID__MASK 0x000000ff
#define A4XX_SP_FS_MRT_REG_REGID__SHIFT 0
static inline uint32_t A4XX_SP_FS_MRT_REG_REGID(uint32_t val)
{
return ((val) << A4XX_SP_FS_MRT_REG_REGID__SHIFT) & A4XX_SP_FS_MRT_REG_REGID__MASK;
}
#define A4XX_SP_FS_MRT_REG_HALF_PRECISION 0x00000100
#define A4XX_SP_FS_MRT_REG_MRTFORMAT__MASK 0x0003f000
#define A4XX_SP_FS_MRT_REG_MRTFORMAT__SHIFT 12
static inline uint32_t A4XX_SP_FS_MRT_REG_MRTFORMAT(enum a4xx_color_fmt val)
{
return ((val) << A4XX_SP_FS_MRT_REG_MRTFORMAT__SHIFT) & A4XX_SP_FS_MRT_REG_MRTFORMAT__MASK;
}
 
#define REG_A4XX_SP_HS_OBJ_OFFSET_REG 0x0000230d
#define A4XX_SP_HS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__MASK 0x01ff0000
#define A4XX_SP_HS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__SHIFT 16
static inline uint32_t A4XX_SP_HS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET(uint32_t val)
{
return ((val) << A4XX_SP_HS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__SHIFT) & A4XX_SP_HS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__MASK;
}
#define A4XX_SP_HS_OBJ_OFFSET_REG_SHADEROBJOFFSET__MASK 0xfe000000
#define A4XX_SP_HS_OBJ_OFFSET_REG_SHADEROBJOFFSET__SHIFT 25
static inline uint32_t A4XX_SP_HS_OBJ_OFFSET_REG_SHADEROBJOFFSET(uint32_t val)
{
return ((val) << A4XX_SP_HS_OBJ_OFFSET_REG_SHADEROBJOFFSET__SHIFT) & A4XX_SP_HS_OBJ_OFFSET_REG_SHADEROBJOFFSET__MASK;
}
 
#define REG_A4XX_SP_HS_OBJ_START 0x0000230e
 
#define REG_A4XX_SP_HS_PVT_MEM_PARAM 0x0000230f
 
#define REG_A4XX_SP_HS_PVT_MEM_ADDR 0x00002310
 
#define REG_A4XX_SP_HS_LENGTH_REG 0x00002312
 
#define REG_A4XX_SP_DS_OBJ_OFFSET_REG 0x00002334
#define A4XX_SP_DS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__MASK 0x01ff0000
#define A4XX_SP_DS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__SHIFT 16
static inline uint32_t A4XX_SP_DS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET(uint32_t val)
{
return ((val) << A4XX_SP_DS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__SHIFT) & A4XX_SP_DS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__MASK;
}
#define A4XX_SP_DS_OBJ_OFFSET_REG_SHADEROBJOFFSET__MASK 0xfe000000
#define A4XX_SP_DS_OBJ_OFFSET_REG_SHADEROBJOFFSET__SHIFT 25
static inline uint32_t A4XX_SP_DS_OBJ_OFFSET_REG_SHADEROBJOFFSET(uint32_t val)
{
return ((val) << A4XX_SP_DS_OBJ_OFFSET_REG_SHADEROBJOFFSET__SHIFT) & A4XX_SP_DS_OBJ_OFFSET_REG_SHADEROBJOFFSET__MASK;
}
 
#define REG_A4XX_SP_DS_OBJ_START 0x00002335
 
#define REG_A4XX_SP_DS_PVT_MEM_PARAM 0x00002336
 
#define REG_A4XX_SP_DS_PVT_MEM_ADDR 0x00002337
 
#define REG_A4XX_SP_DS_LENGTH_REG 0x00002339
 
#define REG_A4XX_SP_GS_OBJ_OFFSET_REG 0x0000235b
#define A4XX_SP_GS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__MASK 0x01ff0000
#define A4XX_SP_GS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__SHIFT 16
static inline uint32_t A4XX_SP_GS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET(uint32_t val)
{
return ((val) << A4XX_SP_GS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__SHIFT) & A4XX_SP_GS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__MASK;
}
#define A4XX_SP_GS_OBJ_OFFSET_REG_SHADEROBJOFFSET__MASK 0xfe000000
#define A4XX_SP_GS_OBJ_OFFSET_REG_SHADEROBJOFFSET__SHIFT 25
static inline uint32_t A4XX_SP_GS_OBJ_OFFSET_REG_SHADEROBJOFFSET(uint32_t val)
{
return ((val) << A4XX_SP_GS_OBJ_OFFSET_REG_SHADEROBJOFFSET__SHIFT) & A4XX_SP_GS_OBJ_OFFSET_REG_SHADEROBJOFFSET__MASK;
}
 
#define REG_A4XX_SP_GS_OBJ_START 0x0000235c
 
#define REG_A4XX_SP_GS_PVT_MEM_PARAM 0x0000235d
 
#define REG_A4XX_SP_GS_PVT_MEM_ADDR 0x0000235e
 
#define REG_A4XX_SP_GS_LENGTH_REG 0x00002360
 
#define REG_A4XX_VPC_DEBUG_RAM_SEL 0x00000e60
 
#define REG_A4XX_VPC_DEBUG_RAM_READ 0x00000e61
 
#define REG_A4XX_VPC_DEBUG_ECO_CONTROL 0x00000e64
 
#define REG_A4XX_VPC_PERFCTR_VPC_SEL_3 0x00000e68
 
#define REG_A4XX_VPC_ATTR 0x00002140
#define A4XX_VPC_ATTR_TOTALATTR__MASK 0x000001ff
#define A4XX_VPC_ATTR_TOTALATTR__SHIFT 0
static inline uint32_t A4XX_VPC_ATTR_TOTALATTR(uint32_t val)
{
return ((val) << A4XX_VPC_ATTR_TOTALATTR__SHIFT) & A4XX_VPC_ATTR_TOTALATTR__MASK;
}
#define A4XX_VPC_ATTR_PSIZE 0x00000200
#define A4XX_VPC_ATTR_THRDASSIGN__MASK 0x00003000
#define A4XX_VPC_ATTR_THRDASSIGN__SHIFT 12
static inline uint32_t A4XX_VPC_ATTR_THRDASSIGN(uint32_t val)
{
return ((val) << A4XX_VPC_ATTR_THRDASSIGN__SHIFT) & A4XX_VPC_ATTR_THRDASSIGN__MASK;
}
#define A4XX_VPC_ATTR_ENABLE 0x02000000
 
#define REG_A4XX_VPC_PACK 0x00002141
#define A4XX_VPC_PACK_NUMBYPASSVAR__MASK 0x000000ff
#define A4XX_VPC_PACK_NUMBYPASSVAR__SHIFT 0
static inline uint32_t A4XX_VPC_PACK_NUMBYPASSVAR(uint32_t val)
{
return ((val) << A4XX_VPC_PACK_NUMBYPASSVAR__SHIFT) & A4XX_VPC_PACK_NUMBYPASSVAR__MASK;
}
#define A4XX_VPC_PACK_NUMFPNONPOSVAR__MASK 0x0000ff00
#define A4XX_VPC_PACK_NUMFPNONPOSVAR__SHIFT 8
static inline uint32_t A4XX_VPC_PACK_NUMFPNONPOSVAR(uint32_t val)
{
return ((val) << A4XX_VPC_PACK_NUMFPNONPOSVAR__SHIFT) & A4XX_VPC_PACK_NUMFPNONPOSVAR__MASK;
}
#define A4XX_VPC_PACK_NUMNONPOSVSVAR__MASK 0x00ff0000
#define A4XX_VPC_PACK_NUMNONPOSVSVAR__SHIFT 16
static inline uint32_t A4XX_VPC_PACK_NUMNONPOSVSVAR(uint32_t val)
{
return ((val) << A4XX_VPC_PACK_NUMNONPOSVSVAR__SHIFT) & A4XX_VPC_PACK_NUMNONPOSVSVAR__MASK;
}
 
static inline uint32_t REG_A4XX_VPC_VARYING_INTERP(uint32_t i0) { return 0x00002142 + 0x1*i0; }
 
static inline uint32_t REG_A4XX_VPC_VARYING_INTERP_MODE(uint32_t i0) { return 0x00002142 + 0x1*i0; }
 
static inline uint32_t REG_A4XX_VPC_VARYING_PS_REPL(uint32_t i0) { return 0x0000214a + 0x1*i0; }
 
static inline uint32_t REG_A4XX_VPC_VARYING_PS_REPL_MODE(uint32_t i0) { return 0x0000214a + 0x1*i0; }
 
#define REG_A4XX_VPC_SO_FLUSH_WADDR_3 0x0000216e
 
#define REG_A4XX_VSC_BIN_SIZE 0x00000c00
#define A4XX_VSC_BIN_SIZE_WIDTH__MASK 0x0000001f
#define A4XX_VSC_BIN_SIZE_WIDTH__SHIFT 0
static inline uint32_t A4XX_VSC_BIN_SIZE_WIDTH(uint32_t val)
{
return ((val >> 5) << A4XX_VSC_BIN_SIZE_WIDTH__SHIFT) & A4XX_VSC_BIN_SIZE_WIDTH__MASK;
}
#define A4XX_VSC_BIN_SIZE_HEIGHT__MASK 0x000003e0
#define A4XX_VSC_BIN_SIZE_HEIGHT__SHIFT 5
static inline uint32_t A4XX_VSC_BIN_SIZE_HEIGHT(uint32_t val)
{
return ((val >> 5) << A4XX_VSC_BIN_SIZE_HEIGHT__SHIFT) & A4XX_VSC_BIN_SIZE_HEIGHT__MASK;
}
 
#define REG_A4XX_VSC_SIZE_ADDRESS 0x00000c01
 
#define REG_A4XX_VSC_SIZE_ADDRESS2 0x00000c02
 
#define REG_A4XX_VSC_DEBUG_ECO_CONTROL 0x00000c03
 
static inline uint32_t REG_A4XX_VSC_PIPE_CONFIG(uint32_t i0) { return 0x00000c08 + 0x1*i0; }
 
static inline uint32_t REG_A4XX_VSC_PIPE_CONFIG_REG(uint32_t i0) { return 0x00000c08 + 0x1*i0; }
#define A4XX_VSC_PIPE_CONFIG_REG_X__MASK 0x000003ff
#define A4XX_VSC_PIPE_CONFIG_REG_X__SHIFT 0
static inline uint32_t A4XX_VSC_PIPE_CONFIG_REG_X(uint32_t val)
{
return ((val) << A4XX_VSC_PIPE_CONFIG_REG_X__SHIFT) & A4XX_VSC_PIPE_CONFIG_REG_X__MASK;
}
#define A4XX_VSC_PIPE_CONFIG_REG_Y__MASK 0x000ffc00
#define A4XX_VSC_PIPE_CONFIG_REG_Y__SHIFT 10
static inline uint32_t A4XX_VSC_PIPE_CONFIG_REG_Y(uint32_t val)
{
return ((val) << A4XX_VSC_PIPE_CONFIG_REG_Y__SHIFT) & A4XX_VSC_PIPE_CONFIG_REG_Y__MASK;
}
#define A4XX_VSC_PIPE_CONFIG_REG_W__MASK 0x00f00000
#define A4XX_VSC_PIPE_CONFIG_REG_W__SHIFT 20
static inline uint32_t A4XX_VSC_PIPE_CONFIG_REG_W(uint32_t val)
{
return ((val) << A4XX_VSC_PIPE_CONFIG_REG_W__SHIFT) & A4XX_VSC_PIPE_CONFIG_REG_W__MASK;
}
#define A4XX_VSC_PIPE_CONFIG_REG_H__MASK 0x0f000000
#define A4XX_VSC_PIPE_CONFIG_REG_H__SHIFT 24
static inline uint32_t A4XX_VSC_PIPE_CONFIG_REG_H(uint32_t val)
{
return ((val) << A4XX_VSC_PIPE_CONFIG_REG_H__SHIFT) & A4XX_VSC_PIPE_CONFIG_REG_H__MASK;
}
 
static inline uint32_t REG_A4XX_VSC_PIPE_DATA_ADDRESS(uint32_t i0) { return 0x00000c10 + 0x1*i0; }
 
static inline uint32_t REG_A4XX_VSC_PIPE_DATA_ADDRESS_REG(uint32_t i0) { return 0x00000c10 + 0x1*i0; }
 
static inline uint32_t REG_A4XX_VSC_PIPE_DATA_LENGTH(uint32_t i0) { return 0x00000c18 + 0x1*i0; }
 
static inline uint32_t REG_A4XX_VSC_PIPE_DATA_LENGTH_REG(uint32_t i0) { return 0x00000c18 + 0x1*i0; }
 
#define REG_A4XX_VSC_PIPE_PARTIAL_POSN_1 0x00000c41
 
#define REG_A4XX_VSC_PERFCTR_VSC_SEL_0 0x00000c50
 
#define REG_A4XX_VSC_PERFCTR_VSC_SEL_1 0x00000c51
 
#define REG_A4XX_VFD_DEBUG_CONTROL 0x00000e40
 
#define REG_A4XX_VFD_PERFCTR_VFD_SEL_7 0x00000e4a
 
#define REG_A4XX_VGT_CL_INITIATOR 0x000021d0
 
#define REG_A4XX_VGT_EVENT_INITIATOR 0x000021d9
 
#define REG_A4XX_VFD_CONTROL_0 0x00002200
#define A4XX_VFD_CONTROL_0_TOTALATTRTOVS__MASK 0x000000ff
#define A4XX_VFD_CONTROL_0_TOTALATTRTOVS__SHIFT 0
static inline uint32_t A4XX_VFD_CONTROL_0_TOTALATTRTOVS(uint32_t val)
{
return ((val) << A4XX_VFD_CONTROL_0_TOTALATTRTOVS__SHIFT) & A4XX_VFD_CONTROL_0_TOTALATTRTOVS__MASK;
}
#define A4XX_VFD_CONTROL_0_BYPASSATTROVS__MASK 0x0001fe00
#define A4XX_VFD_CONTROL_0_BYPASSATTROVS__SHIFT 9
static inline uint32_t A4XX_VFD_CONTROL_0_BYPASSATTROVS(uint32_t val)
{
return ((val) << A4XX_VFD_CONTROL_0_BYPASSATTROVS__SHIFT) & A4XX_VFD_CONTROL_0_BYPASSATTROVS__MASK;
}
#define A4XX_VFD_CONTROL_0_STRMDECINSTRCNT__MASK 0x03f00000
#define A4XX_VFD_CONTROL_0_STRMDECINSTRCNT__SHIFT 20
static inline uint32_t A4XX_VFD_CONTROL_0_STRMDECINSTRCNT(uint32_t val)
{
return ((val) << A4XX_VFD_CONTROL_0_STRMDECINSTRCNT__SHIFT) & A4XX_VFD_CONTROL_0_STRMDECINSTRCNT__MASK;
}
#define A4XX_VFD_CONTROL_0_STRMFETCHINSTRCNT__MASK 0xfc000000
#define A4XX_VFD_CONTROL_0_STRMFETCHINSTRCNT__SHIFT 26
static inline uint32_t A4XX_VFD_CONTROL_0_STRMFETCHINSTRCNT(uint32_t val)
{
return ((val) << A4XX_VFD_CONTROL_0_STRMFETCHINSTRCNT__SHIFT) & A4XX_VFD_CONTROL_0_STRMFETCHINSTRCNT__MASK;
}
 
#define REG_A4XX_VFD_CONTROL_1 0x00002201
#define A4XX_VFD_CONTROL_1_MAXSTORAGE__MASK 0x0000ffff
#define A4XX_VFD_CONTROL_1_MAXSTORAGE__SHIFT 0
static inline uint32_t A4XX_VFD_CONTROL_1_MAXSTORAGE(uint32_t val)
{
return ((val) << A4XX_VFD_CONTROL_1_MAXSTORAGE__SHIFT) & A4XX_VFD_CONTROL_1_MAXSTORAGE__MASK;
}
#define A4XX_VFD_CONTROL_1_REGID4VTX__MASK 0x00ff0000
#define A4XX_VFD_CONTROL_1_REGID4VTX__SHIFT 16
static inline uint32_t A4XX_VFD_CONTROL_1_REGID4VTX(uint32_t val)
{
return ((val) << A4XX_VFD_CONTROL_1_REGID4VTX__SHIFT) & A4XX_VFD_CONTROL_1_REGID4VTX__MASK;
}
#define A4XX_VFD_CONTROL_1_REGID4INST__MASK 0xff000000
#define A4XX_VFD_CONTROL_1_REGID4INST__SHIFT 24
static inline uint32_t A4XX_VFD_CONTROL_1_REGID4INST(uint32_t val)
{
return ((val) << A4XX_VFD_CONTROL_1_REGID4INST__SHIFT) & A4XX_VFD_CONTROL_1_REGID4INST__MASK;
}
 
#define REG_A4XX_VFD_CONTROL_2 0x00002202
 
#define REG_A4XX_VFD_CONTROL_3 0x00002203
#define A4XX_VFD_CONTROL_3_REGID_VTXCNT__MASK 0x0000ff00
#define A4XX_VFD_CONTROL_3_REGID_VTXCNT__SHIFT 8
static inline uint32_t A4XX_VFD_CONTROL_3_REGID_VTXCNT(uint32_t val)
{
return ((val) << A4XX_VFD_CONTROL_3_REGID_VTXCNT__SHIFT) & A4XX_VFD_CONTROL_3_REGID_VTXCNT__MASK;
}
 
#define REG_A4XX_VFD_CONTROL_4 0x00002204
 
#define REG_A4XX_VFD_INDEX_OFFSET 0x00002208
 
static inline uint32_t REG_A4XX_VFD_FETCH(uint32_t i0) { return 0x0000220a + 0x4*i0; }
 
static inline uint32_t REG_A4XX_VFD_FETCH_INSTR_0(uint32_t i0) { return 0x0000220a + 0x4*i0; }
#define A4XX_VFD_FETCH_INSTR_0_FETCHSIZE__MASK 0x0000007f
#define A4XX_VFD_FETCH_INSTR_0_FETCHSIZE__SHIFT 0
static inline uint32_t A4XX_VFD_FETCH_INSTR_0_FETCHSIZE(uint32_t val)
{
return ((val) << A4XX_VFD_FETCH_INSTR_0_FETCHSIZE__SHIFT) & A4XX_VFD_FETCH_INSTR_0_FETCHSIZE__MASK;
}
#define A4XX_VFD_FETCH_INSTR_0_BUFSTRIDE__MASK 0x0001ff80
#define A4XX_VFD_FETCH_INSTR_0_BUFSTRIDE__SHIFT 7
static inline uint32_t A4XX_VFD_FETCH_INSTR_0_BUFSTRIDE(uint32_t val)
{
return ((val) << A4XX_VFD_FETCH_INSTR_0_BUFSTRIDE__SHIFT) & A4XX_VFD_FETCH_INSTR_0_BUFSTRIDE__MASK;
}
#define A4XX_VFD_FETCH_INSTR_0_SWITCHNEXT 0x00080000
#define A4XX_VFD_FETCH_INSTR_0_INSTANCED 0x00100000
 
static inline uint32_t REG_A4XX_VFD_FETCH_INSTR_1(uint32_t i0) { return 0x0000220b + 0x4*i0; }
 
static inline uint32_t REG_A4XX_VFD_FETCH_INSTR_2(uint32_t i0) { return 0x0000220c + 0x4*i0; }
#define A4XX_VFD_FETCH_INSTR_2_SIZE__MASK 0xfffffff0
#define A4XX_VFD_FETCH_INSTR_2_SIZE__SHIFT 4
static inline uint32_t A4XX_VFD_FETCH_INSTR_2_SIZE(uint32_t val)
{
return ((val >> 4) << A4XX_VFD_FETCH_INSTR_2_SIZE__SHIFT) & A4XX_VFD_FETCH_INSTR_2_SIZE__MASK;
}
 
static inline uint32_t REG_A4XX_VFD_FETCH_INSTR_3(uint32_t i0) { return 0x0000220d + 0x4*i0; }
#define A4XX_VFD_FETCH_INSTR_3_STEPRATE__MASK 0x000001ff
#define A4XX_VFD_FETCH_INSTR_3_STEPRATE__SHIFT 0
static inline uint32_t A4XX_VFD_FETCH_INSTR_3_STEPRATE(uint32_t val)
{
return ((val) << A4XX_VFD_FETCH_INSTR_3_STEPRATE__SHIFT) & A4XX_VFD_FETCH_INSTR_3_STEPRATE__MASK;
}
 
static inline uint32_t REG_A4XX_VFD_DECODE(uint32_t i0) { return 0x0000228a + 0x1*i0; }
 
static inline uint32_t REG_A4XX_VFD_DECODE_INSTR(uint32_t i0) { return 0x0000228a + 0x1*i0; }
#define A4XX_VFD_DECODE_INSTR_WRITEMASK__MASK 0x0000000f
#define A4XX_VFD_DECODE_INSTR_WRITEMASK__SHIFT 0
static inline uint32_t A4XX_VFD_DECODE_INSTR_WRITEMASK(uint32_t val)
{
return ((val) << A4XX_VFD_DECODE_INSTR_WRITEMASK__SHIFT) & A4XX_VFD_DECODE_INSTR_WRITEMASK__MASK;
}
#define A4XX_VFD_DECODE_INSTR_CONSTFILL 0x00000010
#define A4XX_VFD_DECODE_INSTR_FORMAT__MASK 0x00000fc0
#define A4XX_VFD_DECODE_INSTR_FORMAT__SHIFT 6
static inline uint32_t A4XX_VFD_DECODE_INSTR_FORMAT(enum a4xx_vtx_fmt val)
{
return ((val) << A4XX_VFD_DECODE_INSTR_FORMAT__SHIFT) & A4XX_VFD_DECODE_INSTR_FORMAT__MASK;
}
#define A4XX_VFD_DECODE_INSTR_REGID__MASK 0x000ff000
#define A4XX_VFD_DECODE_INSTR_REGID__SHIFT 12
static inline uint32_t A4XX_VFD_DECODE_INSTR_REGID(uint32_t val)
{
return ((val) << A4XX_VFD_DECODE_INSTR_REGID__SHIFT) & A4XX_VFD_DECODE_INSTR_REGID__MASK;
}
#define A4XX_VFD_DECODE_INSTR_INT 0x00100000
#define A4XX_VFD_DECODE_INSTR_SWAP__MASK 0x00c00000
#define A4XX_VFD_DECODE_INSTR_SWAP__SHIFT 22
static inline uint32_t A4XX_VFD_DECODE_INSTR_SWAP(enum a3xx_color_swap val)
{
return ((val) << A4XX_VFD_DECODE_INSTR_SWAP__SHIFT) & A4XX_VFD_DECODE_INSTR_SWAP__MASK;
}
#define A4XX_VFD_DECODE_INSTR_SHIFTCNT__MASK 0x1f000000
#define A4XX_VFD_DECODE_INSTR_SHIFTCNT__SHIFT 24
static inline uint32_t A4XX_VFD_DECODE_INSTR_SHIFTCNT(uint32_t val)
{
return ((val) << A4XX_VFD_DECODE_INSTR_SHIFTCNT__SHIFT) & A4XX_VFD_DECODE_INSTR_SHIFTCNT__MASK;
}
#define A4XX_VFD_DECODE_INSTR_LASTCOMPVALID 0x20000000
#define A4XX_VFD_DECODE_INSTR_SWITCHNEXT 0x40000000
 
#define REG_A4XX_TPL1_DEBUG_ECO_CONTROL 0x00000f00
 
#define REG_A4XX_TPL1_PERFCTR_TP_SEL_7 0x00000f0b
 
#define REG_A4XX_TPL1_TP_TEX_OFFSET 0x00002380
 
#define REG_A4XX_TPL1_TP_TEX_COUNT 0x00002381
#define A4XX_TPL1_TP_TEX_COUNT_VS__MASK 0x000000ff
#define A4XX_TPL1_TP_TEX_COUNT_VS__SHIFT 0
static inline uint32_t A4XX_TPL1_TP_TEX_COUNT_VS(uint32_t val)
{
return ((val) << A4XX_TPL1_TP_TEX_COUNT_VS__SHIFT) & A4XX_TPL1_TP_TEX_COUNT_VS__MASK;
}
#define A4XX_TPL1_TP_TEX_COUNT_HS__MASK 0x0000ff00
#define A4XX_TPL1_TP_TEX_COUNT_HS__SHIFT 8
static inline uint32_t A4XX_TPL1_TP_TEX_COUNT_HS(uint32_t val)
{
return ((val) << A4XX_TPL1_TP_TEX_COUNT_HS__SHIFT) & A4XX_TPL1_TP_TEX_COUNT_HS__MASK;
}
#define A4XX_TPL1_TP_TEX_COUNT_DS__MASK 0x00ff0000
#define A4XX_TPL1_TP_TEX_COUNT_DS__SHIFT 16
static inline uint32_t A4XX_TPL1_TP_TEX_COUNT_DS(uint32_t val)
{
return ((val) << A4XX_TPL1_TP_TEX_COUNT_DS__SHIFT) & A4XX_TPL1_TP_TEX_COUNT_DS__MASK;
}
#define A4XX_TPL1_TP_TEX_COUNT_GS__MASK 0xff000000
#define A4XX_TPL1_TP_TEX_COUNT_GS__SHIFT 24
static inline uint32_t A4XX_TPL1_TP_TEX_COUNT_GS(uint32_t val)
{
return ((val) << A4XX_TPL1_TP_TEX_COUNT_GS__SHIFT) & A4XX_TPL1_TP_TEX_COUNT_GS__MASK;
}
 
#define REG_A4XX_TPL1_TP_VS_BORDER_COLOR_BASE_ADDR 0x00002384
 
#define REG_A4XX_TPL1_TP_HS_BORDER_COLOR_BASE_ADDR 0x00002387
 
#define REG_A4XX_TPL1_TP_DS_BORDER_COLOR_BASE_ADDR 0x0000238a
 
#define REG_A4XX_TPL1_TP_GS_BORDER_COLOR_BASE_ADDR 0x0000238d
 
#define REG_A4XX_TPL1_TP_FS_TEX_COUNT 0x000023a0
 
#define REG_A4XX_TPL1_TP_FS_BORDER_COLOR_BASE_ADDR 0x000023a1
 
#define REG_A4XX_TPL1_TP_CS_TEXMEMOBJ_BASE_ADDR 0x000023a6
 
#define REG_A4XX_GRAS_TSE_STATUS 0x00000c80
 
#define REG_A4XX_GRAS_DEBUG_ECO_CONTROL 0x00000c81
 
#define REG_A4XX_GRAS_PERFCTR_TSE_SEL_0 0x00000c88
 
#define REG_A4XX_GRAS_PERFCTR_TSE_SEL_3 0x00000c8b
 
#define REG_A4XX_GRAS_CL_CLIP_CNTL 0x00002000
 
#define REG_A4XX_GRAS_CLEAR_CNTL 0x00002003
#define A4XX_GRAS_CLEAR_CNTL_NOT_FASTCLEAR 0x00000001
 
#define REG_A4XX_GRAS_CL_GB_CLIP_ADJ 0x00002004
#define A4XX_GRAS_CL_GB_CLIP_ADJ_HORZ__MASK 0x000003ff
#define A4XX_GRAS_CL_GB_CLIP_ADJ_HORZ__SHIFT 0
static inline uint32_t A4XX_GRAS_CL_GB_CLIP_ADJ_HORZ(uint32_t val)
{
return ((val) << A4XX_GRAS_CL_GB_CLIP_ADJ_HORZ__SHIFT) & A4XX_GRAS_CL_GB_CLIP_ADJ_HORZ__MASK;
}
#define A4XX_GRAS_CL_GB_CLIP_ADJ_VERT__MASK 0x000ffc00
#define A4XX_GRAS_CL_GB_CLIP_ADJ_VERT__SHIFT 10
static inline uint32_t A4XX_GRAS_CL_GB_CLIP_ADJ_VERT(uint32_t val)
{
return ((val) << A4XX_GRAS_CL_GB_CLIP_ADJ_VERT__SHIFT) & A4XX_GRAS_CL_GB_CLIP_ADJ_VERT__MASK;
}
 
#define REG_A4XX_GRAS_CL_VPORT_XOFFSET_0 0x00002008
#define A4XX_GRAS_CL_VPORT_XOFFSET_0__MASK 0xffffffff
#define A4XX_GRAS_CL_VPORT_XOFFSET_0__SHIFT 0
static inline uint32_t A4XX_GRAS_CL_VPORT_XOFFSET_0(float val)
{
return ((fui(val)) << A4XX_GRAS_CL_VPORT_XOFFSET_0__SHIFT) & A4XX_GRAS_CL_VPORT_XOFFSET_0__MASK;
}
 
#define REG_A4XX_GRAS_CL_VPORT_XSCALE_0 0x00002009
#define A4XX_GRAS_CL_VPORT_XSCALE_0__MASK 0xffffffff
#define A4XX_GRAS_CL_VPORT_XSCALE_0__SHIFT 0
static inline uint32_t A4XX_GRAS_CL_VPORT_XSCALE_0(float val)
{
return ((fui(val)) << A4XX_GRAS_CL_VPORT_XSCALE_0__SHIFT) & A4XX_GRAS_CL_VPORT_XSCALE_0__MASK;
}
 
#define REG_A4XX_GRAS_CL_VPORT_YOFFSET_0 0x0000200a
#define A4XX_GRAS_CL_VPORT_YOFFSET_0__MASK 0xffffffff
#define A4XX_GRAS_CL_VPORT_YOFFSET_0__SHIFT 0
static inline uint32_t A4XX_GRAS_CL_VPORT_YOFFSET_0(float val)
{
return ((fui(val)) << A4XX_GRAS_CL_VPORT_YOFFSET_0__SHIFT) & A4XX_GRAS_CL_VPORT_YOFFSET_0__MASK;
}
 
#define REG_A4XX_GRAS_CL_VPORT_YSCALE_0 0x0000200b
#define A4XX_GRAS_CL_VPORT_YSCALE_0__MASK 0xffffffff
#define A4XX_GRAS_CL_VPORT_YSCALE_0__SHIFT 0
static inline uint32_t A4XX_GRAS_CL_VPORT_YSCALE_0(float val)
{
return ((fui(val)) << A4XX_GRAS_CL_VPORT_YSCALE_0__SHIFT) & A4XX_GRAS_CL_VPORT_YSCALE_0__MASK;
}
 
#define REG_A4XX_GRAS_CL_VPORT_ZOFFSET_0 0x0000200c
#define A4XX_GRAS_CL_VPORT_ZOFFSET_0__MASK 0xffffffff
#define A4XX_GRAS_CL_VPORT_ZOFFSET_0__SHIFT 0
static inline uint32_t A4XX_GRAS_CL_VPORT_ZOFFSET_0(float val)
{
return ((fui(val)) << A4XX_GRAS_CL_VPORT_ZOFFSET_0__SHIFT) & A4XX_GRAS_CL_VPORT_ZOFFSET_0__MASK;
}
 
#define REG_A4XX_GRAS_CL_VPORT_ZSCALE_0 0x0000200d
#define A4XX_GRAS_CL_VPORT_ZSCALE_0__MASK 0xffffffff
#define A4XX_GRAS_CL_VPORT_ZSCALE_0__SHIFT 0
static inline uint32_t A4XX_GRAS_CL_VPORT_ZSCALE_0(float val)
{
return ((fui(val)) << A4XX_GRAS_CL_VPORT_ZSCALE_0__SHIFT) & A4XX_GRAS_CL_VPORT_ZSCALE_0__MASK;
}
 
#define REG_A4XX_GRAS_SU_POINT_MINMAX 0x00002070
#define A4XX_GRAS_SU_POINT_MINMAX_MIN__MASK 0x0000ffff
#define A4XX_GRAS_SU_POINT_MINMAX_MIN__SHIFT 0
static inline uint32_t A4XX_GRAS_SU_POINT_MINMAX_MIN(float val)
{
return ((((uint32_t)(val * 16.0))) << A4XX_GRAS_SU_POINT_MINMAX_MIN__SHIFT) & A4XX_GRAS_SU_POINT_MINMAX_MIN__MASK;
}
#define A4XX_GRAS_SU_POINT_MINMAX_MAX__MASK 0xffff0000
#define A4XX_GRAS_SU_POINT_MINMAX_MAX__SHIFT 16
static inline uint32_t A4XX_GRAS_SU_POINT_MINMAX_MAX(float val)
{
return ((((uint32_t)(val * 16.0))) << A4XX_GRAS_SU_POINT_MINMAX_MAX__SHIFT) & A4XX_GRAS_SU_POINT_MINMAX_MAX__MASK;
}
 
#define REG_A4XX_GRAS_SU_POINT_SIZE 0x00002071
#define A4XX_GRAS_SU_POINT_SIZE__MASK 0xffffffff
#define A4XX_GRAS_SU_POINT_SIZE__SHIFT 0
static inline uint32_t A4XX_GRAS_SU_POINT_SIZE(float val)
{
return ((((int32_t)(val * 16.0))) << A4XX_GRAS_SU_POINT_SIZE__SHIFT) & A4XX_GRAS_SU_POINT_SIZE__MASK;
}
 
#define REG_A4XX_GRAS_ALPHA_CONTROL 0x00002073
#define A4XX_GRAS_ALPHA_CONTROL_ALPHA_TEST_ENABLE 0x00000004
 
#define REG_A4XX_GRAS_SU_POLY_OFFSET_SCALE 0x00002074
#define A4XX_GRAS_SU_POLY_OFFSET_SCALE__MASK 0xffffffff
#define A4XX_GRAS_SU_POLY_OFFSET_SCALE__SHIFT 0
static inline uint32_t A4XX_GRAS_SU_POLY_OFFSET_SCALE(float val)
{
return ((fui(val)) << A4XX_GRAS_SU_POLY_OFFSET_SCALE__SHIFT) & A4XX_GRAS_SU_POLY_OFFSET_SCALE__MASK;
}
 
#define REG_A4XX_GRAS_SU_POLY_OFFSET_OFFSET 0x00002075
#define A4XX_GRAS_SU_POLY_OFFSET_OFFSET__MASK 0xffffffff
#define A4XX_GRAS_SU_POLY_OFFSET_OFFSET__SHIFT 0
static inline uint32_t A4XX_GRAS_SU_POLY_OFFSET_OFFSET(float val)
{
return ((fui(val)) << A4XX_GRAS_SU_POLY_OFFSET_OFFSET__SHIFT) & A4XX_GRAS_SU_POLY_OFFSET_OFFSET__MASK;
}
 
#define REG_A4XX_GRAS_SU_POLY_OFFSET_CLAMP 0x00002076
#define A4XX_GRAS_SU_POLY_OFFSET_CLAMP__MASK 0xffffffff
#define A4XX_GRAS_SU_POLY_OFFSET_CLAMP__SHIFT 0
static inline uint32_t A4XX_GRAS_SU_POLY_OFFSET_CLAMP(float val)
{
return ((fui(val)) << A4XX_GRAS_SU_POLY_OFFSET_CLAMP__SHIFT) & A4XX_GRAS_SU_POLY_OFFSET_CLAMP__MASK;
}
 
#define REG_A4XX_GRAS_DEPTH_CONTROL 0x00002077
#define A4XX_GRAS_DEPTH_CONTROL_FORMAT__MASK 0x00000003
#define A4XX_GRAS_DEPTH_CONTROL_FORMAT__SHIFT 0
static inline uint32_t A4XX_GRAS_DEPTH_CONTROL_FORMAT(enum a4xx_depth_format val)
{
return ((val) << A4XX_GRAS_DEPTH_CONTROL_FORMAT__SHIFT) & A4XX_GRAS_DEPTH_CONTROL_FORMAT__MASK;
}
 
#define REG_A4XX_GRAS_SU_MODE_CONTROL 0x00002078
#define A4XX_GRAS_SU_MODE_CONTROL_CULL_FRONT 0x00000001
#define A4XX_GRAS_SU_MODE_CONTROL_CULL_BACK 0x00000002
#define A4XX_GRAS_SU_MODE_CONTROL_FRONT_CW 0x00000004
#define A4XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH__MASK 0x000007f8
#define A4XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH__SHIFT 3
static inline uint32_t A4XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH(float val)
{
return ((((int32_t)(val * 4.0))) << A4XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH__SHIFT) & A4XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH__MASK;
}
#define A4XX_GRAS_SU_MODE_CONTROL_POLY_OFFSET 0x00000800
#define A4XX_GRAS_SU_MODE_CONTROL_RENDERING_PASS 0x00100000
 
#define REG_A4XX_GRAS_SC_CONTROL 0x0000207b
#define A4XX_GRAS_SC_CONTROL_RENDER_MODE__MASK 0x0000000c
#define A4XX_GRAS_SC_CONTROL_RENDER_MODE__SHIFT 2
static inline uint32_t A4XX_GRAS_SC_CONTROL_RENDER_MODE(enum a3xx_render_mode val)
{
return ((val) << A4XX_GRAS_SC_CONTROL_RENDER_MODE__SHIFT) & A4XX_GRAS_SC_CONTROL_RENDER_MODE__MASK;
}
#define A4XX_GRAS_SC_CONTROL_MSAA_SAMPLES__MASK 0x00000380
#define A4XX_GRAS_SC_CONTROL_MSAA_SAMPLES__SHIFT 7
static inline uint32_t A4XX_GRAS_SC_CONTROL_MSAA_SAMPLES(uint32_t val)
{
return ((val) << A4XX_GRAS_SC_CONTROL_MSAA_SAMPLES__SHIFT) & A4XX_GRAS_SC_CONTROL_MSAA_SAMPLES__MASK;
}
#define A4XX_GRAS_SC_CONTROL_MSAA_DISABLE 0x00000800
#define A4XX_GRAS_SC_CONTROL_RASTER_MODE__MASK 0x0000f000
#define A4XX_GRAS_SC_CONTROL_RASTER_MODE__SHIFT 12
static inline uint32_t A4XX_GRAS_SC_CONTROL_RASTER_MODE(uint32_t val)
{
return ((val) << A4XX_GRAS_SC_CONTROL_RASTER_MODE__SHIFT) & A4XX_GRAS_SC_CONTROL_RASTER_MODE__MASK;
}
 
#define REG_A4XX_GRAS_SC_SCREEN_SCISSOR_TL 0x0000207c
#define A4XX_GRAS_SC_SCREEN_SCISSOR_TL_WINDOW_OFFSET_DISABLE 0x80000000
#define A4XX_GRAS_SC_SCREEN_SCISSOR_TL_X__MASK 0x00007fff
#define A4XX_GRAS_SC_SCREEN_SCISSOR_TL_X__SHIFT 0
static inline uint32_t A4XX_GRAS_SC_SCREEN_SCISSOR_TL_X(uint32_t val)
{
return ((val) << A4XX_GRAS_SC_SCREEN_SCISSOR_TL_X__SHIFT) & A4XX_GRAS_SC_SCREEN_SCISSOR_TL_X__MASK;
}
#define A4XX_GRAS_SC_SCREEN_SCISSOR_TL_Y__MASK 0x7fff0000
#define A4XX_GRAS_SC_SCREEN_SCISSOR_TL_Y__SHIFT 16
static inline uint32_t A4XX_GRAS_SC_SCREEN_SCISSOR_TL_Y(uint32_t val)
{
return ((val) << A4XX_GRAS_SC_SCREEN_SCISSOR_TL_Y__SHIFT) & A4XX_GRAS_SC_SCREEN_SCISSOR_TL_Y__MASK;
}
 
#define REG_A4XX_GRAS_SC_SCREEN_SCISSOR_BR 0x0000207d
#define A4XX_GRAS_SC_SCREEN_SCISSOR_BR_WINDOW_OFFSET_DISABLE 0x80000000
#define A4XX_GRAS_SC_SCREEN_SCISSOR_BR_X__MASK 0x00007fff
#define A4XX_GRAS_SC_SCREEN_SCISSOR_BR_X__SHIFT 0
static inline uint32_t A4XX_GRAS_SC_SCREEN_SCISSOR_BR_X(uint32_t val)
{
return ((val) << A4XX_GRAS_SC_SCREEN_SCISSOR_BR_X__SHIFT) & A4XX_GRAS_SC_SCREEN_SCISSOR_BR_X__MASK;
}
#define A4XX_GRAS_SC_SCREEN_SCISSOR_BR_Y__MASK 0x7fff0000
#define A4XX_GRAS_SC_SCREEN_SCISSOR_BR_Y__SHIFT 16
static inline uint32_t A4XX_GRAS_SC_SCREEN_SCISSOR_BR_Y(uint32_t val)
{
return ((val) << A4XX_GRAS_SC_SCREEN_SCISSOR_BR_Y__SHIFT) & A4XX_GRAS_SC_SCREEN_SCISSOR_BR_Y__MASK;
}
 
#define REG_A4XX_GRAS_SC_WINDOW_SCISSOR_BR 0x0000209c
#define A4XX_GRAS_SC_WINDOW_SCISSOR_BR_WINDOW_OFFSET_DISABLE 0x80000000
#define A4XX_GRAS_SC_WINDOW_SCISSOR_BR_X__MASK 0x00007fff
#define A4XX_GRAS_SC_WINDOW_SCISSOR_BR_X__SHIFT 0
static inline uint32_t A4XX_GRAS_SC_WINDOW_SCISSOR_BR_X(uint32_t val)
{
return ((val) << A4XX_GRAS_SC_WINDOW_SCISSOR_BR_X__SHIFT) & A4XX_GRAS_SC_WINDOW_SCISSOR_BR_X__MASK;
}
#define A4XX_GRAS_SC_WINDOW_SCISSOR_BR_Y__MASK 0x7fff0000
#define A4XX_GRAS_SC_WINDOW_SCISSOR_BR_Y__SHIFT 16
static inline uint32_t A4XX_GRAS_SC_WINDOW_SCISSOR_BR_Y(uint32_t val)
{
return ((val) << A4XX_GRAS_SC_WINDOW_SCISSOR_BR_Y__SHIFT) & A4XX_GRAS_SC_WINDOW_SCISSOR_BR_Y__MASK;
}
 
#define REG_A4XX_GRAS_SC_WINDOW_SCISSOR_TL 0x0000209d
#define A4XX_GRAS_SC_WINDOW_SCISSOR_TL_WINDOW_OFFSET_DISABLE 0x80000000
#define A4XX_GRAS_SC_WINDOW_SCISSOR_TL_X__MASK 0x00007fff
#define A4XX_GRAS_SC_WINDOW_SCISSOR_TL_X__SHIFT 0
static inline uint32_t A4XX_GRAS_SC_WINDOW_SCISSOR_TL_X(uint32_t val)
{
return ((val) << A4XX_GRAS_SC_WINDOW_SCISSOR_TL_X__SHIFT) & A4XX_GRAS_SC_WINDOW_SCISSOR_TL_X__MASK;
}
#define A4XX_GRAS_SC_WINDOW_SCISSOR_TL_Y__MASK 0x7fff0000
#define A4XX_GRAS_SC_WINDOW_SCISSOR_TL_Y__SHIFT 16
static inline uint32_t A4XX_GRAS_SC_WINDOW_SCISSOR_TL_Y(uint32_t val)
{
return ((val) << A4XX_GRAS_SC_WINDOW_SCISSOR_TL_Y__SHIFT) & A4XX_GRAS_SC_WINDOW_SCISSOR_TL_Y__MASK;
}
 
#define REG_A4XX_GRAS_SC_EXTENT_WINDOW_BR 0x0000209e
#define A4XX_GRAS_SC_EXTENT_WINDOW_BR_WINDOW_OFFSET_DISABLE 0x80000000
#define A4XX_GRAS_SC_EXTENT_WINDOW_BR_X__MASK 0x00007fff
#define A4XX_GRAS_SC_EXTENT_WINDOW_BR_X__SHIFT 0
static inline uint32_t A4XX_GRAS_SC_EXTENT_WINDOW_BR_X(uint32_t val)
{
return ((val) << A4XX_GRAS_SC_EXTENT_WINDOW_BR_X__SHIFT) & A4XX_GRAS_SC_EXTENT_WINDOW_BR_X__MASK;
}
#define A4XX_GRAS_SC_EXTENT_WINDOW_BR_Y__MASK 0x7fff0000
#define A4XX_GRAS_SC_EXTENT_WINDOW_BR_Y__SHIFT 16
static inline uint32_t A4XX_GRAS_SC_EXTENT_WINDOW_BR_Y(uint32_t val)
{
return ((val) << A4XX_GRAS_SC_EXTENT_WINDOW_BR_Y__SHIFT) & A4XX_GRAS_SC_EXTENT_WINDOW_BR_Y__MASK;
}
 
#define REG_A4XX_GRAS_SC_EXTENT_WINDOW_TL 0x0000209f
#define A4XX_GRAS_SC_EXTENT_WINDOW_TL_WINDOW_OFFSET_DISABLE 0x80000000
#define A4XX_GRAS_SC_EXTENT_WINDOW_TL_X__MASK 0x00007fff
#define A4XX_GRAS_SC_EXTENT_WINDOW_TL_X__SHIFT 0
static inline uint32_t A4XX_GRAS_SC_EXTENT_WINDOW_TL_X(uint32_t val)
{
return ((val) << A4XX_GRAS_SC_EXTENT_WINDOW_TL_X__SHIFT) & A4XX_GRAS_SC_EXTENT_WINDOW_TL_X__MASK;
}
#define A4XX_GRAS_SC_EXTENT_WINDOW_TL_Y__MASK 0x7fff0000
#define A4XX_GRAS_SC_EXTENT_WINDOW_TL_Y__SHIFT 16
static inline uint32_t A4XX_GRAS_SC_EXTENT_WINDOW_TL_Y(uint32_t val)
{
return ((val) << A4XX_GRAS_SC_EXTENT_WINDOW_TL_Y__SHIFT) & A4XX_GRAS_SC_EXTENT_WINDOW_TL_Y__MASK;
}
 
#define REG_A4XX_UCHE_CACHE_MODE_CONTROL 0x00000e80
 
#define REG_A4XX_UCHE_TRAP_BASE_LO 0x00000e83
 
#define REG_A4XX_UCHE_TRAP_BASE_HI 0x00000e84
 
#define REG_A4XX_UCHE_CACHE_STATUS 0x00000e88
 
#define REG_A4XX_UCHE_INVALIDATE0 0x00000e8a
 
#define REG_A4XX_UCHE_INVALIDATE1 0x00000e8b
 
#define REG_A4XX_UCHE_CACHE_WAYS_VFD 0x00000e8c
 
#define REG_A4XX_UCHE_PERFCTR_UCHE_SEL_7 0x00000e95
 
#define REG_A4XX_HLSQ_TIMEOUT_THRESHOLD 0x00000e00
 
#define REG_A4XX_HLSQ_DEBUG_ECO_CONTROL 0x00000e04
 
#define REG_A4XX_HLSQ_PERF_PIPE_MASK 0x00000e0e
 
#define REG_A4XX_HLSQ_CONTROL_0_REG 0x000023c0
#define A4XX_HLSQ_CONTROL_0_REG_FSTHREADSIZE__MASK 0x00000010
#define A4XX_HLSQ_CONTROL_0_REG_FSTHREADSIZE__SHIFT 4
static inline uint32_t A4XX_HLSQ_CONTROL_0_REG_FSTHREADSIZE(enum a3xx_threadsize val)
{
return ((val) << A4XX_HLSQ_CONTROL_0_REG_FSTHREADSIZE__SHIFT) & A4XX_HLSQ_CONTROL_0_REG_FSTHREADSIZE__MASK;
}
#define A4XX_HLSQ_CONTROL_0_REG_FSSUPERTHREADENABLE 0x00000040
#define A4XX_HLSQ_CONTROL_0_REG_SPSHADERRESTART 0x00000200
#define A4XX_HLSQ_CONTROL_0_REG_RESERVED2 0x00000400
#define A4XX_HLSQ_CONTROL_0_REG_CHUNKDISABLE 0x04000000
#define A4XX_HLSQ_CONTROL_0_REG_CONSTMODE__MASK 0x08000000
#define A4XX_HLSQ_CONTROL_0_REG_CONSTMODE__SHIFT 27
static inline uint32_t A4XX_HLSQ_CONTROL_0_REG_CONSTMODE(uint32_t val)
{
return ((val) << A4XX_HLSQ_CONTROL_0_REG_CONSTMODE__SHIFT) & A4XX_HLSQ_CONTROL_0_REG_CONSTMODE__MASK;
}
#define A4XX_HLSQ_CONTROL_0_REG_LAZYUPDATEDISABLE 0x10000000
#define A4XX_HLSQ_CONTROL_0_REG_SPCONSTFULLUPDATE 0x20000000
#define A4XX_HLSQ_CONTROL_0_REG_TPFULLUPDATE 0x40000000
#define A4XX_HLSQ_CONTROL_0_REG_SINGLECONTEXT 0x80000000
 
#define REG_A4XX_HLSQ_CONTROL_1_REG 0x000023c1
#define A4XX_HLSQ_CONTROL_1_REG_VSTHREADSIZE__MASK 0x00000040
#define A4XX_HLSQ_CONTROL_1_REG_VSTHREADSIZE__SHIFT 6
static inline uint32_t A4XX_HLSQ_CONTROL_1_REG_VSTHREADSIZE(enum a3xx_threadsize val)
{
return ((val) << A4XX_HLSQ_CONTROL_1_REG_VSTHREADSIZE__SHIFT) & A4XX_HLSQ_CONTROL_1_REG_VSTHREADSIZE__MASK;
}
#define A4XX_HLSQ_CONTROL_1_REG_VSSUPERTHREADENABLE 0x00000100
#define A4XX_HLSQ_CONTROL_1_REG_RESERVED1 0x00000200
#define A4XX_HLSQ_CONTROL_1_REG_COORDREGID__MASK 0x00ff0000
#define A4XX_HLSQ_CONTROL_1_REG_COORDREGID__SHIFT 16
static inline uint32_t A4XX_HLSQ_CONTROL_1_REG_COORDREGID(uint32_t val)
{
return ((val) << A4XX_HLSQ_CONTROL_1_REG_COORDREGID__SHIFT) & A4XX_HLSQ_CONTROL_1_REG_COORDREGID__MASK;
}
#define A4XX_HLSQ_CONTROL_1_REG_ZWCOORDREGID__MASK 0xff000000
#define A4XX_HLSQ_CONTROL_1_REG_ZWCOORDREGID__SHIFT 24
static inline uint32_t A4XX_HLSQ_CONTROL_1_REG_ZWCOORDREGID(uint32_t val)
{
return ((val) << A4XX_HLSQ_CONTROL_1_REG_ZWCOORDREGID__SHIFT) & A4XX_HLSQ_CONTROL_1_REG_ZWCOORDREGID__MASK;
}
 
#define REG_A4XX_HLSQ_CONTROL_2_REG 0x000023c2
#define A4XX_HLSQ_CONTROL_2_REG_PRIMALLOCTHRESHOLD__MASK 0xfc000000
#define A4XX_HLSQ_CONTROL_2_REG_PRIMALLOCTHRESHOLD__SHIFT 26
static inline uint32_t A4XX_HLSQ_CONTROL_2_REG_PRIMALLOCTHRESHOLD(uint32_t val)
{
return ((val) << A4XX_HLSQ_CONTROL_2_REG_PRIMALLOCTHRESHOLD__SHIFT) & A4XX_HLSQ_CONTROL_2_REG_PRIMALLOCTHRESHOLD__MASK;
}
#define A4XX_HLSQ_CONTROL_2_REG_FACEREGID__MASK 0x000003fc
#define A4XX_HLSQ_CONTROL_2_REG_FACEREGID__SHIFT 2
static inline uint32_t A4XX_HLSQ_CONTROL_2_REG_FACEREGID(uint32_t val)
{
return ((val) << A4XX_HLSQ_CONTROL_2_REG_FACEREGID__SHIFT) & A4XX_HLSQ_CONTROL_2_REG_FACEREGID__MASK;
}
#define A4XX_HLSQ_CONTROL_2_REG_SAMPLEID_REGID__MASK 0x0003fc00
#define A4XX_HLSQ_CONTROL_2_REG_SAMPLEID_REGID__SHIFT 10
static inline uint32_t A4XX_HLSQ_CONTROL_2_REG_SAMPLEID_REGID(uint32_t val)
{
return ((val) << A4XX_HLSQ_CONTROL_2_REG_SAMPLEID_REGID__SHIFT) & A4XX_HLSQ_CONTROL_2_REG_SAMPLEID_REGID__MASK;
}
#define A4XX_HLSQ_CONTROL_2_REG_SAMPLEMASK_REGID__MASK 0x03fc0000
#define A4XX_HLSQ_CONTROL_2_REG_SAMPLEMASK_REGID__SHIFT 18
static inline uint32_t A4XX_HLSQ_CONTROL_2_REG_SAMPLEMASK_REGID(uint32_t val)
{
return ((val) << A4XX_HLSQ_CONTROL_2_REG_SAMPLEMASK_REGID__SHIFT) & A4XX_HLSQ_CONTROL_2_REG_SAMPLEMASK_REGID__MASK;
}
 
#define REG_A4XX_HLSQ_CONTROL_3_REG 0x000023c3
#define A4XX_HLSQ_CONTROL_3_REG_REGID__MASK 0x000000ff
#define A4XX_HLSQ_CONTROL_3_REG_REGID__SHIFT 0
static inline uint32_t A4XX_HLSQ_CONTROL_3_REG_REGID(uint32_t val)
{
return ((val) << A4XX_HLSQ_CONTROL_3_REG_REGID__SHIFT) & A4XX_HLSQ_CONTROL_3_REG_REGID__MASK;
}
 
#define REG_A4XX_HLSQ_VS_CONTROL_REG 0x000023c5
#define A4XX_HLSQ_VS_CONTROL_REG_CONSTLENGTH__MASK 0x000000ff
#define A4XX_HLSQ_VS_CONTROL_REG_CONSTLENGTH__SHIFT 0
static inline uint32_t A4XX_HLSQ_VS_CONTROL_REG_CONSTLENGTH(uint32_t val)
{
return ((val) << A4XX_HLSQ_VS_CONTROL_REG_CONSTLENGTH__SHIFT) & A4XX_HLSQ_VS_CONTROL_REG_CONSTLENGTH__MASK;
}
#define A4XX_HLSQ_VS_CONTROL_REG_CONSTOBJECTOFFSET__MASK 0x0000ff00
#define A4XX_HLSQ_VS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT 8
static inline uint32_t A4XX_HLSQ_VS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)
{
return ((val) << A4XX_HLSQ_VS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A4XX_HLSQ_VS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;
}
#define A4XX_HLSQ_VS_CONTROL_REG_ENABLED 0x00010000
#define A4XX_HLSQ_VS_CONTROL_REG_SHADEROBJOFFSET__MASK 0x00fe0000
#define A4XX_HLSQ_VS_CONTROL_REG_SHADEROBJOFFSET__SHIFT 17
static inline uint32_t A4XX_HLSQ_VS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val)
{
return ((val) << A4XX_HLSQ_VS_CONTROL_REG_SHADEROBJOFFSET__SHIFT) & A4XX_HLSQ_VS_CONTROL_REG_SHADEROBJOFFSET__MASK;
}
#define A4XX_HLSQ_VS_CONTROL_REG_INSTRLENGTH__MASK 0xff000000
#define A4XX_HLSQ_VS_CONTROL_REG_INSTRLENGTH__SHIFT 24
static inline uint32_t A4XX_HLSQ_VS_CONTROL_REG_INSTRLENGTH(uint32_t val)
{
return ((val) << A4XX_HLSQ_VS_CONTROL_REG_INSTRLENGTH__SHIFT) & A4XX_HLSQ_VS_CONTROL_REG_INSTRLENGTH__MASK;
}
 
#define REG_A4XX_HLSQ_FS_CONTROL_REG 0x000023c6
#define A4XX_HLSQ_FS_CONTROL_REG_CONSTLENGTH__MASK 0x000000ff
#define A4XX_HLSQ_FS_CONTROL_REG_CONSTLENGTH__SHIFT 0
static inline uint32_t A4XX_HLSQ_FS_CONTROL_REG_CONSTLENGTH(uint32_t val)
{
return ((val) << A4XX_HLSQ_FS_CONTROL_REG_CONSTLENGTH__SHIFT) & A4XX_HLSQ_FS_CONTROL_REG_CONSTLENGTH__MASK;
}
#define A4XX_HLSQ_FS_CONTROL_REG_CONSTOBJECTOFFSET__MASK 0x0000ff00
#define A4XX_HLSQ_FS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT 8
static inline uint32_t A4XX_HLSQ_FS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)
{
return ((val) << A4XX_HLSQ_FS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A4XX_HLSQ_FS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;
}
#define A4XX_HLSQ_FS_CONTROL_REG_ENABLED 0x00010000
#define A4XX_HLSQ_FS_CONTROL_REG_SHADEROBJOFFSET__MASK 0x00fe0000
#define A4XX_HLSQ_FS_CONTROL_REG_SHADEROBJOFFSET__SHIFT 17
static inline uint32_t A4XX_HLSQ_FS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val)
{
return ((val) << A4XX_HLSQ_FS_CONTROL_REG_SHADEROBJOFFSET__SHIFT) & A4XX_HLSQ_FS_CONTROL_REG_SHADEROBJOFFSET__MASK;
}
#define A4XX_HLSQ_FS_CONTROL_REG_INSTRLENGTH__MASK 0xff000000
#define A4XX_HLSQ_FS_CONTROL_REG_INSTRLENGTH__SHIFT 24
static inline uint32_t A4XX_HLSQ_FS_CONTROL_REG_INSTRLENGTH(uint32_t val)
{
return ((val) << A4XX_HLSQ_FS_CONTROL_REG_INSTRLENGTH__SHIFT) & A4XX_HLSQ_FS_CONTROL_REG_INSTRLENGTH__MASK;
}
 
#define REG_A4XX_HLSQ_HS_CONTROL_REG 0x000023c7
#define A4XX_HLSQ_HS_CONTROL_REG_CONSTLENGTH__MASK 0x000000ff
#define A4XX_HLSQ_HS_CONTROL_REG_CONSTLENGTH__SHIFT 0
static inline uint32_t A4XX_HLSQ_HS_CONTROL_REG_CONSTLENGTH(uint32_t val)
{
return ((val) << A4XX_HLSQ_HS_CONTROL_REG_CONSTLENGTH__SHIFT) & A4XX_HLSQ_HS_CONTROL_REG_CONSTLENGTH__MASK;
}
#define A4XX_HLSQ_HS_CONTROL_REG_CONSTOBJECTOFFSET__MASK 0x0000ff00
#define A4XX_HLSQ_HS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT 8
static inline uint32_t A4XX_HLSQ_HS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)
{
return ((val) << A4XX_HLSQ_HS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A4XX_HLSQ_HS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;
}
#define A4XX_HLSQ_HS_CONTROL_REG_ENABLED 0x00010000
#define A4XX_HLSQ_HS_CONTROL_REG_SHADEROBJOFFSET__MASK 0x00fe0000
#define A4XX_HLSQ_HS_CONTROL_REG_SHADEROBJOFFSET__SHIFT 17
static inline uint32_t A4XX_HLSQ_HS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val)
{
return ((val) << A4XX_HLSQ_HS_CONTROL_REG_SHADEROBJOFFSET__SHIFT) & A4XX_HLSQ_HS_CONTROL_REG_SHADEROBJOFFSET__MASK;
}
#define A4XX_HLSQ_HS_CONTROL_REG_INSTRLENGTH__MASK 0xff000000
#define A4XX_HLSQ_HS_CONTROL_REG_INSTRLENGTH__SHIFT 24
static inline uint32_t A4XX_HLSQ_HS_CONTROL_REG_INSTRLENGTH(uint32_t val)
{
return ((val) << A4XX_HLSQ_HS_CONTROL_REG_INSTRLENGTH__SHIFT) & A4XX_HLSQ_HS_CONTROL_REG_INSTRLENGTH__MASK;
}
 
#define REG_A4XX_HLSQ_DS_CONTROL_REG 0x000023c8
#define A4XX_HLSQ_DS_CONTROL_REG_CONSTLENGTH__MASK 0x000000ff
#define A4XX_HLSQ_DS_CONTROL_REG_CONSTLENGTH__SHIFT 0
static inline uint32_t A4XX_HLSQ_DS_CONTROL_REG_CONSTLENGTH(uint32_t val)
{
return ((val) << A4XX_HLSQ_DS_CONTROL_REG_CONSTLENGTH__SHIFT) & A4XX_HLSQ_DS_CONTROL_REG_CONSTLENGTH__MASK;
}
#define A4XX_HLSQ_DS_CONTROL_REG_CONSTOBJECTOFFSET__MASK 0x0000ff00
#define A4XX_HLSQ_DS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT 8
static inline uint32_t A4XX_HLSQ_DS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)
{
return ((val) << A4XX_HLSQ_DS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A4XX_HLSQ_DS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;
}
#define A4XX_HLSQ_DS_CONTROL_REG_ENABLED 0x00010000
#define A4XX_HLSQ_DS_CONTROL_REG_SHADEROBJOFFSET__MASK 0x00fe0000
#define A4XX_HLSQ_DS_CONTROL_REG_SHADEROBJOFFSET__SHIFT 17
static inline uint32_t A4XX_HLSQ_DS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val)
{
return ((val) << A4XX_HLSQ_DS_CONTROL_REG_SHADEROBJOFFSET__SHIFT) & A4XX_HLSQ_DS_CONTROL_REG_SHADEROBJOFFSET__MASK;
}
#define A4XX_HLSQ_DS_CONTROL_REG_INSTRLENGTH__MASK 0xff000000
#define A4XX_HLSQ_DS_CONTROL_REG_INSTRLENGTH__SHIFT 24
static inline uint32_t A4XX_HLSQ_DS_CONTROL_REG_INSTRLENGTH(uint32_t val)
{
return ((val) << A4XX_HLSQ_DS_CONTROL_REG_INSTRLENGTH__SHIFT) & A4XX_HLSQ_DS_CONTROL_REG_INSTRLENGTH__MASK;
}
 
#define REG_A4XX_HLSQ_GS_CONTROL_REG 0x000023c9
#define A4XX_HLSQ_GS_CONTROL_REG_CONSTLENGTH__MASK 0x000000ff
#define A4XX_HLSQ_GS_CONTROL_REG_CONSTLENGTH__SHIFT 0
static inline uint32_t A4XX_HLSQ_GS_CONTROL_REG_CONSTLENGTH(uint32_t val)
{
return ((val) << A4XX_HLSQ_GS_CONTROL_REG_CONSTLENGTH__SHIFT) & A4XX_HLSQ_GS_CONTROL_REG_CONSTLENGTH__MASK;
}
#define A4XX_HLSQ_GS_CONTROL_REG_CONSTOBJECTOFFSET__MASK 0x0000ff00
#define A4XX_HLSQ_GS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT 8
static inline uint32_t A4XX_HLSQ_GS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)
{
return ((val) << A4XX_HLSQ_GS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A4XX_HLSQ_GS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;
}
#define A4XX_HLSQ_GS_CONTROL_REG_ENABLED 0x00010000
#define A4XX_HLSQ_GS_CONTROL_REG_SHADEROBJOFFSET__MASK 0x00fe0000
#define A4XX_HLSQ_GS_CONTROL_REG_SHADEROBJOFFSET__SHIFT 17
static inline uint32_t A4XX_HLSQ_GS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val)
{
return ((val) << A4XX_HLSQ_GS_CONTROL_REG_SHADEROBJOFFSET__SHIFT) & A4XX_HLSQ_GS_CONTROL_REG_SHADEROBJOFFSET__MASK;
}
#define A4XX_HLSQ_GS_CONTROL_REG_INSTRLENGTH__MASK 0xff000000
#define A4XX_HLSQ_GS_CONTROL_REG_INSTRLENGTH__SHIFT 24
static inline uint32_t A4XX_HLSQ_GS_CONTROL_REG_INSTRLENGTH(uint32_t val)
{
return ((val) << A4XX_HLSQ_GS_CONTROL_REG_INSTRLENGTH__SHIFT) & A4XX_HLSQ_GS_CONTROL_REG_INSTRLENGTH__MASK;
}
 
#define REG_A4XX_HLSQ_UPDATE_CONTROL 0x000023db
 
#define REG_A4XX_PC_BINNING_COMMAND 0x00000d00
#define A4XX_PC_BINNING_COMMAND_BINNING_ENABLE 0x00000001
 
#define REG_A4XX_PC_DRAWCALL_SETUP_OVERRIDE 0x00000d0c
 
#define REG_A4XX_PC_PERFCTR_PC_SEL_0 0x00000d10
 
#define REG_A4XX_PC_PERFCTR_PC_SEL_7 0x00000d17
 
#define REG_A4XX_PC_BIN_BASE 0x000021c0
 
#define REG_A4XX_PC_PRIM_VTX_CNTL 0x000021c4
#define A4XX_PC_PRIM_VTX_CNTL_VAROUT__MASK 0x0000000f
#define A4XX_PC_PRIM_VTX_CNTL_VAROUT__SHIFT 0
static inline uint32_t A4XX_PC_PRIM_VTX_CNTL_VAROUT(uint32_t val)
{
return ((val) << A4XX_PC_PRIM_VTX_CNTL_VAROUT__SHIFT) & A4XX_PC_PRIM_VTX_CNTL_VAROUT__MASK;
}
#define A4XX_PC_PRIM_VTX_CNTL_PRIMITIVE_RESTART 0x00100000
#define A4XX_PC_PRIM_VTX_CNTL_PROVOKING_VTX_LAST 0x02000000
#define A4XX_PC_PRIM_VTX_CNTL_PSIZE 0x04000000
 
#define REG_A4XX_UNKNOWN_21C5 0x000021c5
 
#define REG_A4XX_PC_RESTART_INDEX 0x000021c6
 
#define REG_A4XX_PC_GS_PARAM 0x000021e5
#define A4XX_PC_GS_PARAM_MAX_VERTICES__MASK 0x000003ff
#define A4XX_PC_GS_PARAM_MAX_VERTICES__SHIFT 0
static inline uint32_t A4XX_PC_GS_PARAM_MAX_VERTICES(uint32_t val)
{
return ((val) << A4XX_PC_GS_PARAM_MAX_VERTICES__SHIFT) & A4XX_PC_GS_PARAM_MAX_VERTICES__MASK;
}
#define A4XX_PC_GS_PARAM_INVOCATIONS__MASK 0x0000f800
#define A4XX_PC_GS_PARAM_INVOCATIONS__SHIFT 11
static inline uint32_t A4XX_PC_GS_PARAM_INVOCATIONS(uint32_t val)
{
return ((val) << A4XX_PC_GS_PARAM_INVOCATIONS__SHIFT) & A4XX_PC_GS_PARAM_INVOCATIONS__MASK;
}
#define A4XX_PC_GS_PARAM_PRIMTYPE__MASK 0x01800000
#define A4XX_PC_GS_PARAM_PRIMTYPE__SHIFT 23
static inline uint32_t A4XX_PC_GS_PARAM_PRIMTYPE(enum adreno_pa_su_sc_draw val)
{
return ((val) << A4XX_PC_GS_PARAM_PRIMTYPE__SHIFT) & A4XX_PC_GS_PARAM_PRIMTYPE__MASK;
}
#define A4XX_PC_GS_PARAM_LAYER 0x80000000
 
#define REG_A4XX_PC_HS_PARAM 0x000021e7
#define A4XX_PC_HS_PARAM_VERTICES_OUT__MASK 0x0000003f
#define A4XX_PC_HS_PARAM_VERTICES_OUT__SHIFT 0
static inline uint32_t A4XX_PC_HS_PARAM_VERTICES_OUT(uint32_t val)
{
return ((val) << A4XX_PC_HS_PARAM_VERTICES_OUT__SHIFT) & A4XX_PC_HS_PARAM_VERTICES_OUT__MASK;
}
#define A4XX_PC_HS_PARAM_SPACING__MASK 0x00600000
#define A4XX_PC_HS_PARAM_SPACING__SHIFT 21
static inline uint32_t A4XX_PC_HS_PARAM_SPACING(enum a4xx_tess_spacing val)
{
return ((val) << A4XX_PC_HS_PARAM_SPACING__SHIFT) & A4XX_PC_HS_PARAM_SPACING__MASK;
}
#define A4XX_PC_HS_PARAM_PRIMTYPE__MASK 0x01800000
#define A4XX_PC_HS_PARAM_PRIMTYPE__SHIFT 23
static inline uint32_t A4XX_PC_HS_PARAM_PRIMTYPE(enum adreno_pa_su_sc_draw val)
{
return ((val) << A4XX_PC_HS_PARAM_PRIMTYPE__SHIFT) & A4XX_PC_HS_PARAM_PRIMTYPE__MASK;
}
 
#define REG_A4XX_VBIF_VERSION 0x00003000
 
#define REG_A4XX_VBIF_CLKON 0x00003001
#define A4XX_VBIF_CLKON_FORCE_ON_TESTBUS 0x00000001
 
#define REG_A4XX_VBIF_ABIT_SORT 0x0000301c
 
#define REG_A4XX_VBIF_ABIT_SORT_CONF 0x0000301d
 
#define REG_A4XX_VBIF_GATE_OFF_WRREQ_EN 0x0000302a
 
#define REG_A4XX_VBIF_IN_RD_LIM_CONF0 0x0000302c
 
#define REG_A4XX_VBIF_IN_RD_LIM_CONF1 0x0000302d
 
#define REG_A4XX_VBIF_IN_WR_LIM_CONF0 0x00003030
 
#define REG_A4XX_VBIF_IN_WR_LIM_CONF1 0x00003031
 
#define REG_A4XX_VBIF_ROUND_ROBIN_QOS_ARB 0x00003049
 
#define REG_A4XX_UNKNOWN_0CC5 0x00000cc5
 
#define REG_A4XX_UNKNOWN_0CC6 0x00000cc6
 
#define REG_A4XX_UNKNOWN_0D01 0x00000d01
 
#define REG_A4XX_UNKNOWN_0E05 0x00000e05
 
#define REG_A4XX_UNKNOWN_0E42 0x00000e42
 
#define REG_A4XX_UNKNOWN_0EC2 0x00000ec2
 
#define REG_A4XX_UNKNOWN_0EC3 0x00000ec3
 
#define REG_A4XX_UNKNOWN_0F03 0x00000f03
 
#define REG_A4XX_UNKNOWN_2001 0x00002001
 
#define REG_A4XX_UNKNOWN_209B 0x0000209b
 
#define REG_A4XX_UNKNOWN_20EF 0x000020ef
 
#define REG_A4XX_UNKNOWN_20F0 0x000020f0
 
#define REG_A4XX_UNKNOWN_20F1 0x000020f1
 
#define REG_A4XX_UNKNOWN_20F2 0x000020f2
 
#define REG_A4XX_UNKNOWN_20F7 0x000020f7
#define A4XX_UNKNOWN_20F7__MASK 0xffffffff
#define A4XX_UNKNOWN_20F7__SHIFT 0
static inline uint32_t A4XX_UNKNOWN_20F7(float val)
{
return ((fui(val)) << A4XX_UNKNOWN_20F7__SHIFT) & A4XX_UNKNOWN_20F7__MASK;
}
 
#define REG_A4XX_UNKNOWN_2152 0x00002152
 
#define REG_A4XX_UNKNOWN_2153 0x00002153
 
#define REG_A4XX_UNKNOWN_2154 0x00002154
 
#define REG_A4XX_UNKNOWN_2155 0x00002155
 
#define REG_A4XX_UNKNOWN_2156 0x00002156
 
#define REG_A4XX_UNKNOWN_2157 0x00002157
 
#define REG_A4XX_UNKNOWN_21C3 0x000021c3
 
#define REG_A4XX_UNKNOWN_21E6 0x000021e6
 
#define REG_A4XX_UNKNOWN_2209 0x00002209
 
#define REG_A4XX_UNKNOWN_22D7 0x000022d7
 
#define REG_A4XX_TEX_SAMP_0 0x00000000
#define A4XX_TEX_SAMP_0_MIPFILTER_LINEAR_NEAR 0x00000001
#define A4XX_TEX_SAMP_0_XY_MAG__MASK 0x00000006
#define A4XX_TEX_SAMP_0_XY_MAG__SHIFT 1
static inline uint32_t A4XX_TEX_SAMP_0_XY_MAG(enum a4xx_tex_filter val)
{
return ((val) << A4XX_TEX_SAMP_0_XY_MAG__SHIFT) & A4XX_TEX_SAMP_0_XY_MAG__MASK;
}
#define A4XX_TEX_SAMP_0_XY_MIN__MASK 0x00000018
#define A4XX_TEX_SAMP_0_XY_MIN__SHIFT 3
static inline uint32_t A4XX_TEX_SAMP_0_XY_MIN(enum a4xx_tex_filter val)
{
return ((val) << A4XX_TEX_SAMP_0_XY_MIN__SHIFT) & A4XX_TEX_SAMP_0_XY_MIN__MASK;
}
#define A4XX_TEX_SAMP_0_WRAP_S__MASK 0x000000e0
#define A4XX_TEX_SAMP_0_WRAP_S__SHIFT 5
static inline uint32_t A4XX_TEX_SAMP_0_WRAP_S(enum a4xx_tex_clamp val)
{
return ((val) << A4XX_TEX_SAMP_0_WRAP_S__SHIFT) & A4XX_TEX_SAMP_0_WRAP_S__MASK;
}
#define A4XX_TEX_SAMP_0_WRAP_T__MASK 0x00000700
#define A4XX_TEX_SAMP_0_WRAP_T__SHIFT 8
static inline uint32_t A4XX_TEX_SAMP_0_WRAP_T(enum a4xx_tex_clamp val)
{
return ((val) << A4XX_TEX_SAMP_0_WRAP_T__SHIFT) & A4XX_TEX_SAMP_0_WRAP_T__MASK;
}
#define A4XX_TEX_SAMP_0_WRAP_R__MASK 0x00003800
#define A4XX_TEX_SAMP_0_WRAP_R__SHIFT 11
static inline uint32_t A4XX_TEX_SAMP_0_WRAP_R(enum a4xx_tex_clamp val)
{
return ((val) << A4XX_TEX_SAMP_0_WRAP_R__SHIFT) & A4XX_TEX_SAMP_0_WRAP_R__MASK;
}
#define A4XX_TEX_SAMP_0_ANISO__MASK 0x0001c000
#define A4XX_TEX_SAMP_0_ANISO__SHIFT 14
static inline uint32_t A4XX_TEX_SAMP_0_ANISO(enum a4xx_tex_aniso val)
{
return ((val) << A4XX_TEX_SAMP_0_ANISO__SHIFT) & A4XX_TEX_SAMP_0_ANISO__MASK;
}
 
#define REG_A4XX_TEX_SAMP_1 0x00000001
#define A4XX_TEX_SAMP_1_COMPARE_FUNC__MASK 0x0000000e
#define A4XX_TEX_SAMP_1_COMPARE_FUNC__SHIFT 1
static inline uint32_t A4XX_TEX_SAMP_1_COMPARE_FUNC(enum adreno_compare_func val)
{
return ((val) << A4XX_TEX_SAMP_1_COMPARE_FUNC__SHIFT) & A4XX_TEX_SAMP_1_COMPARE_FUNC__MASK;
}
#define A4XX_TEX_SAMP_1_UNNORM_COORDS 0x00000020
#define A4XX_TEX_SAMP_1_MIPFILTER_LINEAR_FAR 0x00000040
#define A4XX_TEX_SAMP_1_MAX_LOD__MASK 0x000fff00
#define A4XX_TEX_SAMP_1_MAX_LOD__SHIFT 8
static inline uint32_t A4XX_TEX_SAMP_1_MAX_LOD(float val)
{
return ((((uint32_t)(val * 256.0))) << A4XX_TEX_SAMP_1_MAX_LOD__SHIFT) & A4XX_TEX_SAMP_1_MAX_LOD__MASK;
}
#define A4XX_TEX_SAMP_1_MIN_LOD__MASK 0xfff00000
#define A4XX_TEX_SAMP_1_MIN_LOD__SHIFT 20
static inline uint32_t A4XX_TEX_SAMP_1_MIN_LOD(float val)
{
return ((((uint32_t)(val * 256.0))) << A4XX_TEX_SAMP_1_MIN_LOD__SHIFT) & A4XX_TEX_SAMP_1_MIN_LOD__MASK;
}
 
#define REG_A4XX_TEX_CONST_0 0x00000000
#define A4XX_TEX_CONST_0_TILED 0x00000001
#define A4XX_TEX_CONST_0_SRGB 0x00000004
#define A4XX_TEX_CONST_0_SWIZ_X__MASK 0x00000070
#define A4XX_TEX_CONST_0_SWIZ_X__SHIFT 4
static inline uint32_t A4XX_TEX_CONST_0_SWIZ_X(enum a4xx_tex_swiz val)
{
return ((val) << A4XX_TEX_CONST_0_SWIZ_X__SHIFT) & A4XX_TEX_CONST_0_SWIZ_X__MASK;
}
#define A4XX_TEX_CONST_0_SWIZ_Y__MASK 0x00000380
#define A4XX_TEX_CONST_0_SWIZ_Y__SHIFT 7
static inline uint32_t A4XX_TEX_CONST_0_SWIZ_Y(enum a4xx_tex_swiz val)
{
return ((val) << A4XX_TEX_CONST_0_SWIZ_Y__SHIFT) & A4XX_TEX_CONST_0_SWIZ_Y__MASK;
}
#define A4XX_TEX_CONST_0_SWIZ_Z__MASK 0x00001c00
#define A4XX_TEX_CONST_0_SWIZ_Z__SHIFT 10
static inline uint32_t A4XX_TEX_CONST_0_SWIZ_Z(enum a4xx_tex_swiz val)
{
return ((val) << A4XX_TEX_CONST_0_SWIZ_Z__SHIFT) & A4XX_TEX_CONST_0_SWIZ_Z__MASK;
}
#define A4XX_TEX_CONST_0_SWIZ_W__MASK 0x0000e000
#define A4XX_TEX_CONST_0_SWIZ_W__SHIFT 13
static inline uint32_t A4XX_TEX_CONST_0_SWIZ_W(enum a4xx_tex_swiz val)
{
return ((val) << A4XX_TEX_CONST_0_SWIZ_W__SHIFT) & A4XX_TEX_CONST_0_SWIZ_W__MASK;
}
#define A4XX_TEX_CONST_0_MIPLVLS__MASK 0x000f0000
#define A4XX_TEX_CONST_0_MIPLVLS__SHIFT 16
static inline uint32_t A4XX_TEX_CONST_0_MIPLVLS(uint32_t val)
{
return ((val) << A4XX_TEX_CONST_0_MIPLVLS__SHIFT) & A4XX_TEX_CONST_0_MIPLVLS__MASK;
}
#define A4XX_TEX_CONST_0_FMT__MASK 0x1fc00000
#define A4XX_TEX_CONST_0_FMT__SHIFT 22
static inline uint32_t A4XX_TEX_CONST_0_FMT(enum a4xx_tex_fmt val)
{
return ((val) << A4XX_TEX_CONST_0_FMT__SHIFT) & A4XX_TEX_CONST_0_FMT__MASK;
}
#define A4XX_TEX_CONST_0_TYPE__MASK 0x60000000
#define A4XX_TEX_CONST_0_TYPE__SHIFT 29
static inline uint32_t A4XX_TEX_CONST_0_TYPE(enum a4xx_tex_type val)
{
return ((val) << A4XX_TEX_CONST_0_TYPE__SHIFT) & A4XX_TEX_CONST_0_TYPE__MASK;
}
 
#define REG_A4XX_TEX_CONST_1 0x00000001
#define A4XX_TEX_CONST_1_HEIGHT__MASK 0x00007fff
#define A4XX_TEX_CONST_1_HEIGHT__SHIFT 0
static inline uint32_t A4XX_TEX_CONST_1_HEIGHT(uint32_t val)
{
return ((val) << A4XX_TEX_CONST_1_HEIGHT__SHIFT) & A4XX_TEX_CONST_1_HEIGHT__MASK;
}
#define A4XX_TEX_CONST_1_WIDTH__MASK 0x1fff8000
#define A4XX_TEX_CONST_1_WIDTH__SHIFT 15
static inline uint32_t A4XX_TEX_CONST_1_WIDTH(uint32_t val)
{
return ((val) << A4XX_TEX_CONST_1_WIDTH__SHIFT) & A4XX_TEX_CONST_1_WIDTH__MASK;
}
 
#define REG_A4XX_TEX_CONST_2 0x00000002
#define A4XX_TEX_CONST_2_FETCHSIZE__MASK 0x0000000f
#define A4XX_TEX_CONST_2_FETCHSIZE__SHIFT 0
static inline uint32_t A4XX_TEX_CONST_2_FETCHSIZE(enum a4xx_tex_fetchsize val)
{
return ((val) << A4XX_TEX_CONST_2_FETCHSIZE__SHIFT) & A4XX_TEX_CONST_2_FETCHSIZE__MASK;
}
#define A4XX_TEX_CONST_2_PITCH__MASK 0x3ffffe00
#define A4XX_TEX_CONST_2_PITCH__SHIFT 9
static inline uint32_t A4XX_TEX_CONST_2_PITCH(uint32_t val)
{
return ((val) << A4XX_TEX_CONST_2_PITCH__SHIFT) & A4XX_TEX_CONST_2_PITCH__MASK;
}
#define A4XX_TEX_CONST_2_SWAP__MASK 0xc0000000
#define A4XX_TEX_CONST_2_SWAP__SHIFT 30
static inline uint32_t A4XX_TEX_CONST_2_SWAP(enum a3xx_color_swap val)
{
return ((val) << A4XX_TEX_CONST_2_SWAP__SHIFT) & A4XX_TEX_CONST_2_SWAP__MASK;
}
 
#define REG_A4XX_TEX_CONST_3 0x00000003
#define A4XX_TEX_CONST_3_LAYERSZ__MASK 0x00003fff
#define A4XX_TEX_CONST_3_LAYERSZ__SHIFT 0
static inline uint32_t A4XX_TEX_CONST_3_LAYERSZ(uint32_t val)
{
return ((val >> 12) << A4XX_TEX_CONST_3_LAYERSZ__SHIFT) & A4XX_TEX_CONST_3_LAYERSZ__MASK;
}
#define A4XX_TEX_CONST_3_DEPTH__MASK 0x7ffc0000
#define A4XX_TEX_CONST_3_DEPTH__SHIFT 18
static inline uint32_t A4XX_TEX_CONST_3_DEPTH(uint32_t val)
{
return ((val) << A4XX_TEX_CONST_3_DEPTH__SHIFT) & A4XX_TEX_CONST_3_DEPTH__MASK;
}
 
#define REG_A4XX_TEX_CONST_4 0x00000004
#define A4XX_TEX_CONST_4_LAYERSZ__MASK 0x0000000f
#define A4XX_TEX_CONST_4_LAYERSZ__SHIFT 0
static inline uint32_t A4XX_TEX_CONST_4_LAYERSZ(uint32_t val)
{
return ((val >> 12) << A4XX_TEX_CONST_4_LAYERSZ__SHIFT) & A4XX_TEX_CONST_4_LAYERSZ__MASK;
}
#define A4XX_TEX_CONST_4_BASE__MASK 0xffffffe0
#define A4XX_TEX_CONST_4_BASE__SHIFT 5
static inline uint32_t A4XX_TEX_CONST_4_BASE(uint32_t val)
{
return ((val >> 5) << A4XX_TEX_CONST_4_BASE__SHIFT) & A4XX_TEX_CONST_4_BASE__MASK;
}
 
#define REG_A4XX_TEX_CONST_5 0x00000005
 
#define REG_A4XX_TEX_CONST_6 0x00000006
 
#define REG_A4XX_TEX_CONST_7 0x00000007
 
 
#endif /* A4XX_XML */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a4xx/fd4_blend.c
0,0 → 1,129
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "pipe/p_state.h"
#include "util/u_string.h"
#include "util/u_memory.h"
 
#include "fd4_blend.h"
#include "fd4_context.h"
#include "fd4_format.h"
 
static enum a4xx_rb_blend_opcode
blend_func(unsigned func)
{
switch (func) {
case PIPE_BLEND_ADD:
return BLEND_DST_PLUS_SRC;
case PIPE_BLEND_MIN:
return BLEND_MIN_DST_SRC;
case PIPE_BLEND_MAX:
return BLEND_MAX_DST_SRC;
case PIPE_BLEND_SUBTRACT:
return BLEND_SRC_MINUS_DST;
case PIPE_BLEND_REVERSE_SUBTRACT:
return BLEND_DST_MINUS_SRC;
default:
DBG("invalid blend func: %x", func);
return 0;
}
}
 
void *
fd4_blend_state_create(struct pipe_context *pctx,
const struct pipe_blend_state *cso)
{
struct fd4_blend_stateobj *so;
// enum a3xx_rop_code rop = ROP_COPY;
bool reads_dest = false;
int i;
 
if (cso->logicop_enable) {
// rop = cso->logicop_func; /* maps 1:1 */
 
switch (cso->logicop_func) {
case PIPE_LOGICOP_NOR:
case PIPE_LOGICOP_AND_INVERTED:
case PIPE_LOGICOP_AND_REVERSE:
case PIPE_LOGICOP_INVERT:
case PIPE_LOGICOP_XOR:
case PIPE_LOGICOP_NAND:
case PIPE_LOGICOP_AND:
case PIPE_LOGICOP_EQUIV:
case PIPE_LOGICOP_NOOP:
case PIPE_LOGICOP_OR_INVERTED:
case PIPE_LOGICOP_OR_REVERSE:
case PIPE_LOGICOP_OR:
reads_dest = true;
break;
}
}
 
if (cso->independent_blend_enable) {
DBG("Unsupported! independent blend state");
return NULL;
}
 
so = CALLOC_STRUCT(fd4_blend_stateobj);
if (!so)
return NULL;
 
so->base = *cso;
 
for (i = 0; i < ARRAY_SIZE(so->rb_mrt); i++) {
const struct pipe_rt_blend_state *rt = &cso->rt[i];
 
so->rb_mrt[i].blend_control =
A4XX_RB_MRT_BLEND_CONTROL_RGB_SRC_FACTOR(fd_blend_factor(rt->rgb_src_factor)) |
A4XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE(blend_func(rt->rgb_func)) |
A4XX_RB_MRT_BLEND_CONTROL_RGB_DEST_FACTOR(fd_blend_factor(rt->rgb_dst_factor)) |
A4XX_RB_MRT_BLEND_CONTROL_ALPHA_SRC_FACTOR(fd_blend_factor(rt->alpha_src_factor)) |
A4XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE(blend_func(rt->alpha_func)) |
A4XX_RB_MRT_BLEND_CONTROL_ALPHA_DEST_FACTOR(fd_blend_factor(rt->alpha_dst_factor));
 
so->rb_mrt[i].control =
0xc00 | /* XXX ROP_CODE ?? */
A4XX_RB_MRT_CONTROL_COMPONENT_ENABLE(rt->colormask);
 
if (rt->blend_enable) {
so->rb_mrt[i].control |=
A4XX_RB_MRT_CONTROL_READ_DEST_ENABLE |
A4XX_RB_MRT_CONTROL_BLEND |
A4XX_RB_MRT_CONTROL_BLEND2;
so->rb_fs_output |= A4XX_RB_FS_OUTPUT_ENABLE_BLEND(1);
}
 
if (reads_dest)
so->rb_mrt[i].control |= A4XX_RB_MRT_CONTROL_READ_DEST_ENABLE;
 
if (cso->dither)
so->rb_mrt[i].buf_info |= A4XX_RB_MRT_BUF_INFO_DITHER_MODE(DITHER_ALWAYS);
}
 
return so;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a4xx/fd4_blend.h
0,0 → 1,54
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FD4_BLEND_H_
#define FD4_BLEND_H_
 
#include "pipe/p_state.h"
#include "pipe/p_context.h"
 
struct fd4_blend_stateobj {
struct pipe_blend_state base;
struct {
uint32_t control;
uint32_t buf_info;
uint32_t blend_control;
} rb_mrt[8];
uint32_t rb_fs_output;
};
 
static INLINE struct fd4_blend_stateobj *
fd4_blend_stateobj(struct pipe_blend_state *blend)
{
return (struct fd4_blend_stateobj *)blend;
}
 
void * fd4_blend_state_create(struct pipe_context *pctx,
const struct pipe_blend_state *cso);
 
#endif /* FD4_BLEND_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a4xx/fd4_context.c
0,0 → 1,172
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
 
#include "fd4_context.h"
#include "fd4_blend.h"
#include "fd4_draw.h"
#include "fd4_emit.h"
#include "fd4_gmem.h"
#include "fd4_program.h"
#include "fd4_query.h"
#include "fd4_rasterizer.h"
#include "fd4_texture.h"
#include "fd4_zsa.h"
 
static void
fd4_context_destroy(struct pipe_context *pctx)
{
struct fd4_context *fd4_ctx = fd4_context(fd_context(pctx));
 
util_dynarray_fini(&fd4_ctx->rbrc_patches);
 
fd_bo_del(fd4_ctx->vs_pvt_mem);
fd_bo_del(fd4_ctx->fs_pvt_mem);
fd_bo_del(fd4_ctx->vsc_size_mem);
 
pctx->delete_vertex_elements_state(pctx, fd4_ctx->solid_vbuf_state.vtx);
pctx->delete_vertex_elements_state(pctx, fd4_ctx->blit_vbuf_state.vtx);
 
pipe_resource_reference(&fd4_ctx->solid_vbuf, NULL);
pipe_resource_reference(&fd4_ctx->blit_texcoord_vbuf, NULL);
 
fd_context_destroy(pctx);
}
 
/* TODO we could combine a few of these small buffers (solid_vbuf,
* blit_texcoord_vbuf, and vsc_size_mem, into a single buffer and
* save a tiny bit of memory
*/
 
static struct pipe_resource *
create_solid_vertexbuf(struct pipe_context *pctx)
{
static const float init_shader_const[] = {
-1.000000, +1.000000, +1.000000,
+1.000000, -1.000000, +1.000000,
};
struct pipe_resource *prsc = pipe_buffer_create(pctx->screen,
PIPE_BIND_CUSTOM, PIPE_USAGE_IMMUTABLE, sizeof(init_shader_const));
pipe_buffer_write(pctx, prsc, 0,
sizeof(init_shader_const), init_shader_const);
return prsc;
}
 
static struct pipe_resource *
create_blit_texcoord_vertexbuf(struct pipe_context *pctx)
{
struct pipe_resource *prsc = pipe_buffer_create(pctx->screen,
PIPE_BIND_CUSTOM, PIPE_USAGE_DYNAMIC, 16);
return prsc;
}
 
static const uint8_t primtypes[PIPE_PRIM_MAX] = {
[PIPE_PRIM_POINTS] = DI_PT_POINTLIST_A3XX,
[PIPE_PRIM_LINES] = DI_PT_LINELIST,
[PIPE_PRIM_LINE_STRIP] = DI_PT_LINESTRIP,
[PIPE_PRIM_LINE_LOOP] = DI_PT_LINELOOP,
[PIPE_PRIM_TRIANGLES] = DI_PT_TRILIST,
[PIPE_PRIM_TRIANGLE_STRIP] = DI_PT_TRISTRIP,
[PIPE_PRIM_TRIANGLE_FAN] = DI_PT_TRIFAN,
};
 
struct pipe_context *
fd4_context_create(struct pipe_screen *pscreen, void *priv)
{
struct fd_screen *screen = fd_screen(pscreen);
struct fd4_context *fd4_ctx = CALLOC_STRUCT(fd4_context);
struct pipe_context *pctx;
 
if (!fd4_ctx)
return NULL;
 
pctx = &fd4_ctx->base.base;
 
fd4_ctx->base.dev = fd_device_ref(screen->dev);
fd4_ctx->base.screen = fd_screen(pscreen);
 
pctx->destroy = fd4_context_destroy;
pctx->create_blend_state = fd4_blend_state_create;
pctx->create_rasterizer_state = fd4_rasterizer_state_create;
pctx->create_depth_stencil_alpha_state = fd4_zsa_state_create;
 
fd4_draw_init(pctx);
fd4_gmem_init(pctx);
fd4_texture_init(pctx);
fd4_prog_init(pctx);
 
pctx = fd_context_init(&fd4_ctx->base, pscreen, primtypes, priv);
if (!pctx)
return NULL;
 
util_dynarray_init(&fd4_ctx->rbrc_patches);
 
fd4_ctx->vs_pvt_mem = fd_bo_new(screen->dev, 0x2000,
DRM_FREEDRENO_GEM_TYPE_KMEM);
 
fd4_ctx->fs_pvt_mem = fd_bo_new(screen->dev, 0x2000,
DRM_FREEDRENO_GEM_TYPE_KMEM);
 
fd4_ctx->vsc_size_mem = fd_bo_new(screen->dev, 0x1000,
DRM_FREEDRENO_GEM_TYPE_KMEM);
 
fd4_ctx->solid_vbuf = create_solid_vertexbuf(pctx);
fd4_ctx->blit_texcoord_vbuf = create_blit_texcoord_vertexbuf(pctx);
 
/* setup solid_vbuf_state: */
fd4_ctx->solid_vbuf_state.vtx = pctx->create_vertex_elements_state(
pctx, 1, (struct pipe_vertex_element[]){{
.vertex_buffer_index = 0,
.src_offset = 0,
.src_format = PIPE_FORMAT_R32G32B32_FLOAT,
}});
fd4_ctx->solid_vbuf_state.vertexbuf.count = 1;
fd4_ctx->solid_vbuf_state.vertexbuf.vb[0].stride = 12;
fd4_ctx->solid_vbuf_state.vertexbuf.vb[0].buffer = fd4_ctx->solid_vbuf;
 
/* setup blit_vbuf_state: */
fd4_ctx->blit_vbuf_state.vtx = pctx->create_vertex_elements_state(
pctx, 2, (struct pipe_vertex_element[]){{
.vertex_buffer_index = 0,
.src_offset = 0,
.src_format = PIPE_FORMAT_R32G32_FLOAT,
}, {
.vertex_buffer_index = 1,
.src_offset = 0,
.src_format = PIPE_FORMAT_R32G32B32_FLOAT,
}});
fd4_ctx->blit_vbuf_state.vertexbuf.count = 2;
fd4_ctx->blit_vbuf_state.vertexbuf.vb[0].stride = 8;
fd4_ctx->blit_vbuf_state.vertexbuf.vb[0].buffer = fd4_ctx->blit_texcoord_vbuf;
fd4_ctx->blit_vbuf_state.vertexbuf.vb[1].stride = 12;
fd4_ctx->blit_vbuf_state.vertexbuf.vb[1].buffer = fd4_ctx->solid_vbuf;
 
fd4_query_context_init(pctx);
 
return pctx;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a4xx/fd4_context.h
0,0 → 1,105
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FD4_CONTEXT_H_
#define FD4_CONTEXT_H_
 
#include "freedreno_drmif.h"
 
#include "freedreno_context.h"
 
#include "ir3_shader.h"
 
struct fd4_context {
struct fd_context base;
 
/* Keep track of writes to RB_RENDER_CONTROL which need to be patched
* once we know whether or not to use GMEM, and GMEM tile pitch.
*/
struct util_dynarray rbrc_patches;
 
struct fd_bo *vs_pvt_mem, *fs_pvt_mem;
 
/* This only needs to be 4 * num_of_pipes bytes (ie. 32 bytes). We
* could combine it with another allocation.
*/
struct fd_bo *vsc_size_mem;
 
/* vertex buf used for clear/gmem->mem vertices, and mem->gmem
* vertices:
*/
struct pipe_resource *solid_vbuf;
 
/* vertex buf used for mem->gmem tex coords:
*/
struct pipe_resource *blit_texcoord_vbuf;
 
/* vertex state for solid_vbuf:
* - solid_vbuf / 12 / R32G32B32_FLOAT
*/
struct fd_vertex_state solid_vbuf_state;
 
/* vertex state for blit_prog:
* - blit_texcoord_vbuf / 8 / R32G32_FLOAT
* - solid_vbuf / 12 / R32G32B32_FLOAT
*/
struct fd_vertex_state blit_vbuf_state;
 
/* if *any* of bits are set in {v,f}saturate_{s,t,r} */
bool vsaturate, fsaturate;
 
/* bitmask of sampler which needs coords clamped for vertex
* shader:
*/
uint16_t vsaturate_s, vsaturate_t, vsaturate_r;
 
/* bitmask of sampler which needs coords clamped for frag
* shader:
*/
uint16_t fsaturate_s, fsaturate_t, fsaturate_r;
 
/* bitmask of integer texture samplers */
uint16_t vinteger_s, finteger_s;
 
/* some state changes require a different shader variant. Keep
* track of this so we know when we need to re-emit shader state
* due to variant change. See fixup_shader_state()
*/
struct ir3_shader_key last_key;
};
 
static INLINE struct fd4_context *
fd4_context(struct fd_context *ctx)
{
return (struct fd4_context *)ctx;
}
 
struct pipe_context *
fd4_context_create(struct pipe_screen *pscreen, void *priv);
 
#endif /* FD4_CONTEXT_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a4xx/fd4_draw.c
0,0 → 1,333
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "pipe/p_state.h"
#include "util/u_string.h"
#include "util/u_memory.h"
#include "util/u_prim.h"
 
#include "freedreno_state.h"
#include "freedreno_resource.h"
 
#include "fd4_draw.h"
#include "fd4_context.h"
#include "fd4_emit.h"
#include "fd4_program.h"
#include "fd4_format.h"
#include "fd4_zsa.h"
 
 
static void
draw_impl(struct fd_context *ctx, struct fd_ringbuffer *ring,
struct fd4_emit *emit)
{
const struct pipe_draw_info *info = emit->info;
 
fd4_emit_state(ctx, ring, emit);
 
if (emit->dirty & (FD_DIRTY_VTXBUF | FD_DIRTY_VTXSTATE))
fd4_emit_vertex_bufs(ring, emit);
 
OUT_PKT0(ring, REG_A4XX_VFD_INDEX_OFFSET, 2);
OUT_RING(ring, info->indexed ? info->index_bias : info->start); /* VFD_INDEX_OFFSET */
OUT_RING(ring, info->start_instance); /* ??? UNKNOWN_2209 */
 
OUT_PKT0(ring, REG_A4XX_PC_RESTART_INDEX, 1);
OUT_RING(ring, info->primitive_restart ? /* PC_RESTART_INDEX */
info->restart_index : 0xffffffff);
 
fd4_draw_emit(ctx, ring,
emit->key.binning_pass ? IGNORE_VISIBILITY : USE_VISIBILITY,
info);
}
 
/* fixup dirty shader state in case some "unrelated" (from the state-
* tracker's perspective) state change causes us to switch to a
* different variant.
*/
static void
fixup_shader_state(struct fd_context *ctx, struct ir3_shader_key *key)
{
struct fd4_context *fd4_ctx = fd4_context(ctx);
struct ir3_shader_key *last_key = &fd4_ctx->last_key;
 
if (!ir3_shader_key_equal(last_key, key)) {
ctx->dirty |= FD_DIRTY_PROG;
 
if (last_key->has_per_samp || key->has_per_samp) {
if ((last_key->vsaturate_s != key->vsaturate_s) ||
(last_key->vsaturate_t != key->vsaturate_t) ||
(last_key->vsaturate_r != key->vsaturate_r) ||
(last_key->vinteger_s != key->vinteger_s))
ctx->prog.dirty |= FD_SHADER_DIRTY_VP;
 
if ((last_key->fsaturate_s != key->fsaturate_s) ||
(last_key->fsaturate_t != key->fsaturate_t) ||
(last_key->fsaturate_r != key->fsaturate_r))
ctx->prog.dirty |= FD_SHADER_DIRTY_FP;
}
 
if (last_key->color_two_side != key->color_two_side)
ctx->prog.dirty |= FD_SHADER_DIRTY_FP;
 
if (last_key->half_precision != key->half_precision)
ctx->prog.dirty |= FD_SHADER_DIRTY_FP;
 
if (last_key->rasterflat != key->rasterflat)
ctx->prog.dirty |= FD_SHADER_DIRTY_FP;
 
fd4_ctx->last_key = *key;
}
}
 
static void
fd4_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info)
{
struct fd4_context *fd4_ctx = fd4_context(ctx);
struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
struct fd4_emit emit = {
.vtx = &ctx->vtx,
.prog = &ctx->prog,
.info = info,
.key = {
/* do binning pass first: */
.binning_pass = true,
.color_two_side = ctx->rasterizer ? ctx->rasterizer->light_twoside : false,
.rasterflat = ctx->rasterizer && ctx->rasterizer->flatshade,
// TODO set .half_precision based on render target format,
// ie. float16 and smaller use half, float32 use full..
.half_precision = !!(fd_mesa_debug & FD_DBG_FRAGHALF),
.has_per_samp = (fd4_ctx->fsaturate || fd4_ctx->vsaturate ||
fd4_ctx->vinteger_s || fd4_ctx->finteger_s),
.vsaturate_s = fd4_ctx->vsaturate_s,
.vsaturate_t = fd4_ctx->vsaturate_t,
.vsaturate_r = fd4_ctx->vsaturate_r,
.fsaturate_s = fd4_ctx->fsaturate_s,
.fsaturate_t = fd4_ctx->fsaturate_t,
.fsaturate_r = fd4_ctx->fsaturate_r,
.vinteger_s = fd4_ctx->vinteger_s,
.finteger_s = fd4_ctx->finteger_s,
},
.format = fd4_emit_format(pfb->cbufs[0]),
.pformat = pipe_surface_format(pfb->cbufs[0]),
};
unsigned dirty;
 
fixup_shader_state(ctx, &emit.key);
 
dirty = ctx->dirty;
emit.dirty = dirty & ~(FD_DIRTY_BLEND);
draw_impl(ctx, ctx->binning_ring, &emit);
 
/* and now regular (non-binning) pass: */
emit.key.binning_pass = false;
emit.dirty = dirty;
emit.vp = NULL; /* we changed key so need to refetch vp */
draw_impl(ctx, ctx->ring, &emit);
}
 
/* clear operations ignore viewport state, so we need to reset it
* based on framebuffer state:
*/
static void
reset_viewport(struct fd_ringbuffer *ring, struct pipe_framebuffer_state *pfb)
{
float half_width = pfb->width * 0.5f;
float half_height = pfb->height * 0.5f;
 
OUT_PKT0(ring, REG_A4XX_GRAS_CL_VPORT_XOFFSET_0, 4);
OUT_RING(ring, A4XX_GRAS_CL_VPORT_XOFFSET_0(half_width));
OUT_RING(ring, A4XX_GRAS_CL_VPORT_XSCALE_0(half_width));
OUT_RING(ring, A4XX_GRAS_CL_VPORT_YOFFSET_0(half_height));
OUT_RING(ring, A4XX_GRAS_CL_VPORT_YSCALE_0(-half_height));
}
 
static void
fd4_clear(struct fd_context *ctx, unsigned buffers,
const union pipe_color_union *color, double depth, unsigned stencil)
{
struct fd4_context *fd4_ctx = fd4_context(ctx);
struct fd_ringbuffer *ring = ctx->ring;
struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
unsigned dirty = ctx->dirty;
unsigned ce, i;
struct fd4_emit emit = {
.vtx = &fd4_ctx->solid_vbuf_state,
.prog = &ctx->solid_prog,
.key = {
.half_precision = true,
},
.format = fd4_emit_format(pfb->cbufs[0]),
};
uint32_t colr = 0;
 
if ((buffers & PIPE_CLEAR_COLOR) && pfb->nr_cbufs)
colr = pack_rgba(pfb->cbufs[0]->format, color->f);
 
dirty &= FD_DIRTY_FRAMEBUFFER | FD_DIRTY_SCISSOR;
dirty |= FD_DIRTY_PROG;
emit.dirty = dirty;
 
OUT_PKT0(ring, REG_A4XX_PC_PRIM_VTX_CNTL, 1);
OUT_RING(ring, A4XX_PC_PRIM_VTX_CNTL_PROVOKING_VTX_LAST);
 
/* emit generic state now: */
fd4_emit_state(ctx, ring, &emit);
reset_viewport(ring, pfb);
 
if (buffers & PIPE_CLEAR_DEPTH) {
OUT_PKT0(ring, REG_A4XX_RB_DEPTH_CONTROL, 1);
OUT_RING(ring, A4XX_RB_DEPTH_CONTROL_Z_WRITE_ENABLE |
A4XX_RB_DEPTH_CONTROL_Z_ENABLE |
A4XX_RB_DEPTH_CONTROL_ZFUNC(FUNC_ALWAYS));
 
fd_wfi(ctx, ring);
OUT_PKT0(ring, REG_A4XX_GRAS_CL_VPORT_ZOFFSET_0, 2);
OUT_RING(ring, A4XX_GRAS_CL_VPORT_ZOFFSET_0(0.0));
OUT_RING(ring, A4XX_GRAS_CL_VPORT_ZSCALE_0(depth));
ctx->dirty |= FD_DIRTY_VIEWPORT;
} else {
OUT_PKT0(ring, REG_A4XX_RB_DEPTH_CONTROL, 1);
OUT_RING(ring, A4XX_RB_DEPTH_CONTROL_ZFUNC(FUNC_NEVER));
}
 
if (buffers & PIPE_CLEAR_STENCIL) {
OUT_PKT0(ring, REG_A4XX_RB_STENCILREFMASK, 2);
OUT_RING(ring, A4XX_RB_STENCILREFMASK_STENCILREF(stencil) |
A4XX_RB_STENCILREFMASK_STENCILMASK(stencil) |
A4XX_RB_STENCILREFMASK_STENCILWRITEMASK(0xff));
OUT_RING(ring, A4XX_RB_STENCILREFMASK_STENCILREF(0) |
A4XX_RB_STENCILREFMASK_STENCILMASK(0) |
0xff000000 | // XXX ???
A4XX_RB_STENCILREFMASK_STENCILWRITEMASK(0xff));
 
OUT_PKT0(ring, REG_A4XX_RB_STENCIL_CONTROL, 2);
OUT_RING(ring, A4XX_RB_STENCIL_CONTROL_STENCIL_ENABLE |
A4XX_RB_STENCIL_CONTROL_FUNC(FUNC_ALWAYS) |
A4XX_RB_STENCIL_CONTROL_FAIL(STENCIL_KEEP) |
A4XX_RB_STENCIL_CONTROL_ZPASS(STENCIL_REPLACE) |
A4XX_RB_STENCIL_CONTROL_ZFAIL(STENCIL_KEEP) |
A4XX_RB_STENCIL_CONTROL_FUNC_BF(FUNC_NEVER) |
A4XX_RB_STENCIL_CONTROL_FAIL_BF(STENCIL_KEEP) |
A4XX_RB_STENCIL_CONTROL_ZPASS_BF(STENCIL_KEEP) |
A4XX_RB_STENCIL_CONTROL_ZFAIL_BF(STENCIL_KEEP));
OUT_RING(ring, A4XX_RB_STENCIL_CONTROL2_STENCIL_BUFFER);
} else {
OUT_PKT0(ring, REG_A4XX_RB_STENCILREFMASK, 2);
OUT_RING(ring, A4XX_RB_STENCILREFMASK_STENCILREF(0) |
A4XX_RB_STENCILREFMASK_STENCILMASK(0) |
A4XX_RB_STENCILREFMASK_STENCILWRITEMASK(0));
OUT_RING(ring, A4XX_RB_STENCILREFMASK_BF_STENCILREF(0) |
A4XX_RB_STENCILREFMASK_BF_STENCILMASK(0) |
A4XX_RB_STENCILREFMASK_BF_STENCILWRITEMASK(0));
 
OUT_PKT0(ring, REG_A4XX_RB_STENCIL_CONTROL, 2);
OUT_RING(ring, A4XX_RB_STENCIL_CONTROL_FUNC(FUNC_NEVER) |
A4XX_RB_STENCIL_CONTROL_FAIL(STENCIL_KEEP) |
A4XX_RB_STENCIL_CONTROL_ZPASS(STENCIL_KEEP) |
A4XX_RB_STENCIL_CONTROL_ZFAIL(STENCIL_KEEP) |
A4XX_RB_STENCIL_CONTROL_FUNC_BF(FUNC_NEVER) |
A4XX_RB_STENCIL_CONTROL_FAIL_BF(STENCIL_KEEP) |
A4XX_RB_STENCIL_CONTROL_ZPASS_BF(STENCIL_KEEP) |
A4XX_RB_STENCIL_CONTROL_ZFAIL_BF(STENCIL_KEEP));
OUT_RING(ring, 0x00000000); /* RB_STENCIL_CONTROL2 */
}
 
if (buffers & PIPE_CLEAR_COLOR) {
OUT_PKT0(ring, REG_A4XX_RB_ALPHA_CONTROL, 1);
OUT_RING(ring, A4XX_RB_ALPHA_CONTROL_ALPHA_TEST_FUNC(FUNC_NEVER));
ce = 0xf;
} else {
ce = 0x0;
}
 
for (i = 0; i < 8; i++) {
OUT_PKT0(ring, REG_A4XX_RB_MRT_CONTROL(i), 1);
OUT_RING(ring, A4XX_RB_MRT_CONTROL_FASTCLEAR |
A4XX_RB_MRT_CONTROL_B11 |
A4XX_RB_MRT_CONTROL_COMPONENT_ENABLE(ce));
 
OUT_PKT0(ring, REG_A4XX_RB_MRT_BLEND_CONTROL(i), 1);
OUT_RING(ring, A4XX_RB_MRT_BLEND_CONTROL_RGB_SRC_FACTOR(FACTOR_ONE) |
A4XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE(BLEND_DST_PLUS_SRC) |
A4XX_RB_MRT_BLEND_CONTROL_RGB_DEST_FACTOR(FACTOR_ZERO) |
A4XX_RB_MRT_BLEND_CONTROL_ALPHA_SRC_FACTOR(FACTOR_ONE) |
A4XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE(BLEND_DST_PLUS_SRC) |
A4XX_RB_MRT_BLEND_CONTROL_ALPHA_DEST_FACTOR(FACTOR_ZERO));
}
 
fd4_emit_vertex_bufs(ring, &emit);
 
OUT_PKT0(ring, REG_A4XX_GRAS_ALPHA_CONTROL, 1);
OUT_RING(ring, 0x0); /* XXX GRAS_ALPHA_CONTROL */
 
OUT_PKT0(ring, REG_A4XX_GRAS_CLEAR_CNTL, 1);
OUT_RING(ring, 0x00000000);
 
OUT_PKT0(ring, REG_A4XX_RB_CLEAR_COLOR_DW0, 4);
OUT_RING(ring, colr); /* RB_CLEAR_COLOR_DW0 */
OUT_RING(ring, colr); /* RB_CLEAR_COLOR_DW1 */
OUT_RING(ring, colr); /* RB_CLEAR_COLOR_DW2 */
OUT_RING(ring, colr); /* RB_CLEAR_COLOR_DW3 */
 
/* until fastclear works: */
fd4_emit_constant(ring, SB_FRAG_SHADER, 0, 0, 4, color->ui, NULL);
 
OUT_PKT0(ring, REG_A4XX_VFD_INDEX_OFFSET, 2);
OUT_RING(ring, 0); /* VFD_INDEX_OFFSET */
OUT_RING(ring, 0); /* ??? UNKNOWN_2209 */
 
OUT_PKT0(ring, REG_A4XX_PC_RESTART_INDEX, 1);
OUT_RING(ring, 0xffffffff); /* PC_RESTART_INDEX */
 
OUT_PKT3(ring, CP_UNKNOWN_1A, 1);
OUT_RING(ring, 0x00000001);
 
fd4_draw(ctx, ring, DI_PT_RECTLIST, USE_VISIBILITY,
DI_SRC_SEL_AUTO_INDEX, 2, 1, INDEX_SIZE_IGN, 0, 0, NULL);
 
OUT_PKT3(ring, CP_UNKNOWN_1A, 1);
OUT_RING(ring, 0x00000000);
 
OUT_PKT0(ring, REG_A4XX_GRAS_CLEAR_CNTL, 1);
OUT_RING(ring, A4XX_GRAS_CLEAR_CNTL_NOT_FASTCLEAR);
 
OUT_PKT0(ring, REG_A4XX_GRAS_SC_CONTROL, 1);
OUT_RING(ring, A4XX_GRAS_SC_CONTROL_RENDER_MODE(RB_RENDERING_PASS) |
A4XX_GRAS_SC_CONTROL_MSAA_DISABLE |
A4XX_GRAS_SC_CONTROL_MSAA_SAMPLES(MSAA_ONE) |
A4XX_GRAS_SC_CONTROL_RASTER_MODE(0));
}
 
void
fd4_draw_init(struct pipe_context *pctx)
{
struct fd_context *ctx = fd_context(pctx);
ctx->draw_vbo = fd4_draw_vbo;
ctx->clear = fd4_clear;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a4xx/fd4_draw.h
0,0 → 1,134
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FD4_DRAW_H_
#define FD4_DRAW_H_
 
#include "pipe/p_context.h"
 
#include "freedreno_draw.h"
 
void fd4_draw_init(struct pipe_context *pctx);
 
/* draw packet changed on a4xx, so cannot reuse one from a2xx/a3xx.. */
 
static inline uint32_t DRAW4(enum pc_di_primtype prim_type,
enum pc_di_src_sel source_select, enum a4xx_index_size index_size,
enum pc_di_vis_cull_mode vis_cull_mode)
{
return (prim_type << 0) |
(source_select << 6) |
(index_size << 10);
}
 
static inline void
fd4_draw(struct fd_context *ctx, struct fd_ringbuffer *ring,
enum pc_di_primtype primtype,
enum pc_di_vis_cull_mode vismode,
enum pc_di_src_sel src_sel, uint32_t count,
uint32_t instances, enum a4xx_index_size idx_type,
uint32_t idx_size, uint32_t idx_offset,
struct fd_bo *idx_bo)
{
/* for debug after a lock up, write a unique counter value
* to scratch7 for each draw, to make it easier to match up
* register dumps to cmdstream. The combination of IB
* (scratch6) and DRAW is enough to "triangulate" the
* particular draw that caused lockup.
*/
emit_marker(ring, 7);
 
OUT_PKT3(ring, CP_DRAW_INDX_OFFSET, idx_bo ? 6 : 3);
if (vismode == USE_VISIBILITY) {
/* leave vis mode blank for now, it will be patched up when
* we know if we are binning or not
*/
OUT_RINGP(ring, DRAW4(primtype, src_sel, idx_type, 0),
&ctx->draw_patches);
} else {
OUT_RING(ring, DRAW4(primtype, src_sel, idx_type, vismode));
}
OUT_RING(ring, instances); /* NumInstances */
OUT_RING(ring, count); /* NumIndices */
if (idx_bo) {
OUT_RING(ring, 0x0); /* XXX */
OUT_RELOC(ring, idx_bo, idx_offset, 0, 0);
OUT_RING (ring, idx_size);
}
 
emit_marker(ring, 7);
 
fd_reset_wfi(ctx);
}
 
 
static inline enum pc_di_index_size
fd4_size2indextype(unsigned index_size)
{
switch (index_size) {
case 1: return INDEX4_SIZE_8_BIT;
case 2: return INDEX4_SIZE_16_BIT;
case 4: return INDEX4_SIZE_32_BIT;
}
DBG("unsupported index size: %d", index_size);
assert(0);
return INDEX4_SIZE_32_BIT;
}
static inline void
fd4_draw_emit(struct fd_context *ctx, struct fd_ringbuffer *ring,
enum pc_di_vis_cull_mode vismode,
const struct pipe_draw_info *info)
{
struct pipe_index_buffer *idx = &ctx->indexbuf;
struct fd_bo *idx_bo = NULL;
enum a4xx_index_size idx_type;
enum pc_di_src_sel src_sel;
uint32_t idx_size, idx_offset;
 
if (info->indexed) {
assert(!idx->user_buffer);
 
idx_bo = fd_resource(idx->buffer)->bo;
idx_type = fd4_size2indextype(idx->index_size);
idx_size = idx->index_size * info->count;
idx_offset = idx->offset + (info->start * idx->index_size);
src_sel = DI_SRC_SEL_DMA;
} else {
idx_bo = NULL;
idx_type = INDEX4_SIZE_32_BIT;
idx_size = 0;
idx_offset = 0;
src_sel = DI_SRC_SEL_AUTO_INDEX;
}
 
fd4_draw(ctx, ring, ctx->primtypes[info->mode], vismode, src_sel,
info->count, info->instance_count,
idx_type, idx_size, idx_offset, idx_bo);
}
 
#endif /* FD4_DRAW_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a4xx/fd4_emit.c
0,0 → 1,765
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "pipe/p_state.h"
#include "util/u_string.h"
#include "util/u_memory.h"
#include "util/u_helpers.h"
#include "util/u_format.h"
 
#include "freedreno_resource.h"
 
#include "fd4_emit.h"
#include "fd4_blend.h"
#include "fd4_context.h"
#include "fd4_program.h"
#include "fd4_rasterizer.h"
#include "fd4_texture.h"
#include "fd4_format.h"
#include "fd4_zsa.h"
 
/* regid: base const register
* prsc or dwords: buffer containing constant values
* sizedwords: size of const value buffer
*/
void
fd4_emit_constant(struct fd_ringbuffer *ring,
enum adreno_state_block sb,
uint32_t regid, uint32_t offset, uint32_t sizedwords,
const uint32_t *dwords, struct pipe_resource *prsc)
{
uint32_t i, sz;
enum adreno_state_src src;
 
if (prsc) {
sz = 0;
src = 0x2; // TODO ??
} else {
sz = sizedwords;
src = SS_DIRECT;
}
 
OUT_PKT3(ring, CP_LOAD_STATE, 2 + sz);
OUT_RING(ring, CP_LOAD_STATE_0_DST_OFF(regid/4) |
CP_LOAD_STATE_0_STATE_SRC(src) |
CP_LOAD_STATE_0_STATE_BLOCK(sb) |
CP_LOAD_STATE_0_NUM_UNIT(sizedwords/4));
if (prsc) {
struct fd_bo *bo = fd_resource(prsc)->bo;
OUT_RELOC(ring, bo, offset,
CP_LOAD_STATE_1_STATE_TYPE(ST_CONSTANTS), 0);
} else {
OUT_RING(ring, CP_LOAD_STATE_1_EXT_SRC_ADDR(0) |
CP_LOAD_STATE_1_STATE_TYPE(ST_CONSTANTS));
dwords = (uint32_t *)&((uint8_t *)dwords)[offset];
}
for (i = 0; i < sz; i++) {
OUT_RING(ring, dwords[i]);
}
}
 
static void
emit_constants(struct fd_ringbuffer *ring,
enum adreno_state_block sb,
struct fd_constbuf_stateobj *constbuf,
struct ir3_shader_variant *shader,
bool emit_immediates)
{
uint32_t enabled_mask = constbuf->enabled_mask;
uint32_t max_const;
int i;
 
// XXX TODO only emit dirty consts.. but we need to keep track if
// they are clobbered by a clear, gmem2mem, or mem2gmem..
constbuf->dirty_mask = enabled_mask;
 
/* in particular, with binning shader we may end up with unused
* consts, ie. we could end up w/ constlen that is smaller
* than first_immediate. In that case truncate the user consts
* early to avoid HLSQ lockup caused by writing too many consts
*/
max_const = MIN2(shader->first_driver_param, shader->constlen);
 
/* emit user constants: */
if (enabled_mask & 1) {
const unsigned index = 0;
struct pipe_constant_buffer *cb = &constbuf->cb[index];
unsigned size = align(cb->buffer_size, 4) / 4; /* size in dwords */
 
// I expect that size should be a multiple of vec4's:
assert(size == align(size, 4));
 
/* and even if the start of the const buffer is before
* first_immediate, the end may not be:
*/
size = MIN2(size, 4 * max_const);
 
if (size && (constbuf->dirty_mask & (1 << index))) {
fd4_emit_constant(ring, sb, 0,
cb->buffer_offset, size,
cb->user_buffer, cb->buffer);
constbuf->dirty_mask &= ~(1 << index);
}
 
enabled_mask &= ~(1 << index);
}
 
/* emit ubos: */
if (shader->constlen > shader->first_driver_param) {
uint32_t params = MIN2(4, shader->constlen - shader->first_driver_param);
OUT_PKT3(ring, CP_LOAD_STATE, 2 + params * 4);
OUT_RING(ring, CP_LOAD_STATE_0_DST_OFF(shader->first_driver_param) |
CP_LOAD_STATE_0_STATE_SRC(SS_DIRECT) |
CP_LOAD_STATE_0_STATE_BLOCK(sb) |
CP_LOAD_STATE_0_NUM_UNIT(params));
OUT_RING(ring, CP_LOAD_STATE_1_EXT_SRC_ADDR(0) |
CP_LOAD_STATE_1_STATE_TYPE(ST_CONSTANTS));
 
for (i = 1; i <= params * 4; i++) {
struct pipe_constant_buffer *cb = &constbuf->cb[i];
assert(!cb->user_buffer);
if ((enabled_mask & (1 << i)) && cb->buffer)
OUT_RELOC(ring, fd_resource(cb->buffer)->bo, cb->buffer_offset, 0, 0);
else
OUT_RING(ring, 0xbad00000 | ((i - 1) << 16));
}
}
 
/* emit shader immediates: */
if (shader && emit_immediates) {
int size = shader->immediates_count;
uint32_t base = shader->first_immediate;
 
/* truncate size to avoid writing constants that shader
* does not use:
*/
size = MIN2(size + base, shader->constlen) - base;
 
/* convert out of vec4: */
base *= 4;
size *= 4;
 
if (size > 0) {
fd4_emit_constant(ring, sb, base,
0, size, shader->immediates[0].val, NULL);
}
}
}
 
static void
emit_textures(struct fd_context *ctx, struct fd_ringbuffer *ring,
enum adreno_state_block sb, struct fd_texture_stateobj *tex)
{
unsigned i;
 
if (tex->num_samplers > 0) {
int num_samplers;
 
/* not sure if this is an a420.0 workaround, but we seem
* to need to emit these in pairs.. emit a final dummy
* entry if odd # of samplers:
*/
num_samplers = align(tex->num_samplers, 2);
 
/* output sampler state: */
OUT_PKT3(ring, CP_LOAD_STATE, 2 + (2 * num_samplers));
OUT_RING(ring, CP_LOAD_STATE_0_DST_OFF(0) |
CP_LOAD_STATE_0_STATE_SRC(SS_DIRECT) |
CP_LOAD_STATE_0_STATE_BLOCK(sb) |
CP_LOAD_STATE_0_NUM_UNIT(num_samplers));
OUT_RING(ring, CP_LOAD_STATE_1_STATE_TYPE(ST_SHADER) |
CP_LOAD_STATE_1_EXT_SRC_ADDR(0));
for (i = 0; i < tex->num_samplers; i++) {
static const struct fd4_sampler_stateobj dummy_sampler = {};
const struct fd4_sampler_stateobj *sampler = tex->samplers[i] ?
fd4_sampler_stateobj(tex->samplers[i]) :
&dummy_sampler;
OUT_RING(ring, sampler->texsamp0);
OUT_RING(ring, sampler->texsamp1);
}
 
for (; i < num_samplers; i++) {
OUT_RING(ring, 0x00000000);
OUT_RING(ring, 0x00000000);
}
}
 
if (tex->num_textures > 0) {
/* emit texture state: */
OUT_PKT3(ring, CP_LOAD_STATE, 2 + (8 * tex->num_textures));
OUT_RING(ring, CP_LOAD_STATE_0_DST_OFF(0) |
CP_LOAD_STATE_0_STATE_SRC(SS_DIRECT) |
CP_LOAD_STATE_0_STATE_BLOCK(sb) |
CP_LOAD_STATE_0_NUM_UNIT(tex->num_textures));
OUT_RING(ring, CP_LOAD_STATE_1_STATE_TYPE(ST_CONSTANTS) |
CP_LOAD_STATE_1_EXT_SRC_ADDR(0));
for (i = 0; i < tex->num_textures; i++) {
static const struct fd4_pipe_sampler_view dummy_view = {};
const struct fd4_pipe_sampler_view *view = tex->textures[i] ?
fd4_pipe_sampler_view(tex->textures[i]) :
&dummy_view;
struct fd_resource *rsc = fd_resource(view->base.texture);
unsigned start = view->base.u.tex.first_level;
uint32_t offset = fd_resource_offset(rsc, start, 0);
 
OUT_RING(ring, view->texconst0);
OUT_RING(ring, view->texconst1);
OUT_RING(ring, view->texconst2);
OUT_RING(ring, view->texconst3);
OUT_RELOC(ring, rsc->bo, offset, view->textconst4, 0);
OUT_RING(ring, 0x00000000);
OUT_RING(ring, 0x00000000);
OUT_RING(ring, 0x00000000);
}
}
}
 
/* emit texture state for mem->gmem restore operation.. eventually it would
* be good to get rid of this and use normal CSO/etc state for more of these
* special cases..
*/
void
fd4_emit_gmem_restore_tex(struct fd_ringbuffer *ring, struct pipe_surface *psurf)
{
struct fd_resource *rsc = fd_resource(psurf->texture);
unsigned lvl = psurf->u.tex.level;
struct fd_resource_slice *slice = fd_resource_slice(rsc, lvl);
uint32_t offset = fd_resource_offset(rsc, lvl, psurf->u.tex.first_layer);
enum pipe_format format = fd4_gmem_restore_format(psurf->format);
 
debug_assert(psurf->u.tex.first_layer == psurf->u.tex.last_layer);
 
/* output sampler state: */
OUT_PKT3(ring, CP_LOAD_STATE, 4);
OUT_RING(ring, CP_LOAD_STATE_0_DST_OFF(0) |
CP_LOAD_STATE_0_STATE_SRC(SS_DIRECT) |
CP_LOAD_STATE_0_STATE_BLOCK(SB_FRAG_TEX) |
CP_LOAD_STATE_0_NUM_UNIT(1));
OUT_RING(ring, CP_LOAD_STATE_1_STATE_TYPE(ST_SHADER) |
CP_LOAD_STATE_1_EXT_SRC_ADDR(0));
OUT_RING(ring, A4XX_TEX_SAMP_0_XY_MAG(A4XX_TEX_NEAREST) |
A4XX_TEX_SAMP_0_XY_MIN(A4XX_TEX_NEAREST) |
A4XX_TEX_SAMP_0_WRAP_S(A4XX_TEX_CLAMP_TO_EDGE) |
A4XX_TEX_SAMP_0_WRAP_T(A4XX_TEX_CLAMP_TO_EDGE) |
A4XX_TEX_SAMP_0_WRAP_R(A4XX_TEX_REPEAT));
OUT_RING(ring, 0x00000000);
 
/* emit texture state: */
OUT_PKT3(ring, CP_LOAD_STATE, 10);
OUT_RING(ring, CP_LOAD_STATE_0_DST_OFF(0) |
CP_LOAD_STATE_0_STATE_SRC(SS_DIRECT) |
CP_LOAD_STATE_0_STATE_BLOCK(SB_FRAG_TEX) |
CP_LOAD_STATE_0_NUM_UNIT(1));
OUT_RING(ring, CP_LOAD_STATE_1_STATE_TYPE(ST_CONSTANTS) |
CP_LOAD_STATE_1_EXT_SRC_ADDR(0));
OUT_RING(ring, A4XX_TEX_CONST_0_FMT(fd4_pipe2tex(format)) |
A4XX_TEX_CONST_0_TYPE(A4XX_TEX_2D) |
fd4_tex_swiz(format, PIPE_SWIZZLE_RED, PIPE_SWIZZLE_GREEN,
PIPE_SWIZZLE_BLUE, PIPE_SWIZZLE_ALPHA));
OUT_RING(ring, A4XX_TEX_CONST_1_WIDTH(psurf->width) |
A4XX_TEX_CONST_1_HEIGHT(psurf->height));
OUT_RING(ring, A4XX_TEX_CONST_2_PITCH(slice->pitch * rsc->cpp));
OUT_RING(ring, 0x00000000);
OUT_RELOC(ring, rsc->bo, offset, 0, 0);
OUT_RING(ring, 0x00000000);
OUT_RING(ring, 0x00000000);
OUT_RING(ring, 0x00000000);
}
 
void
fd4_emit_vertex_bufs(struct fd_ringbuffer *ring, struct fd4_emit *emit)
{
int32_t i, j, last = -1;
uint32_t total_in = 0;
const struct fd_vertex_state *vtx = emit->vtx;
struct ir3_shader_variant *vp = fd4_emit_get_vp(emit);
unsigned vertex_regid = regid(63, 0), instance_regid = regid(63, 0);
 
for (i = 0; i < vp->inputs_count; i++) {
uint8_t semantic = sem2name(vp->inputs[i].semantic);
if (semantic == TGSI_SEMANTIC_VERTEXID_NOBASE)
vertex_regid = vp->inputs[i].regid;
else if (semantic == TGSI_SEMANTIC_INSTANCEID)
instance_regid = vp->inputs[i].regid;
else if ((i < vtx->vtx->num_elements) && vp->inputs[i].compmask)
last = i;
}
 
/* hw doesn't like to be configured for zero vbo's, it seems: */
if ((vtx->vtx->num_elements == 0) &&
(vertex_regid == regid(63, 0)) &&
(instance_regid == regid(63, 0)))
return;
 
for (i = 0, j = 0; i <= last; i++) {
assert(sem2name(vp->inputs[i].semantic) == 0);
if (vp->inputs[i].compmask) {
struct pipe_vertex_element *elem = &vtx->vtx->pipe[i];
const struct pipe_vertex_buffer *vb =
&vtx->vertexbuf.vb[elem->vertex_buffer_index];
struct fd_resource *rsc = fd_resource(vb->buffer);
enum pipe_format pfmt = elem->src_format;
enum a4xx_vtx_fmt fmt = fd4_pipe2vtx(pfmt);
bool switchnext = (i != last) ||
(vertex_regid != regid(63, 0)) ||
(instance_regid != regid(63, 0));
bool isint = util_format_is_pure_integer(pfmt);
uint32_t fs = util_format_get_blocksize(pfmt);
uint32_t off = vb->buffer_offset + elem->src_offset;
uint32_t size = fd_bo_size(rsc->bo) - off;
debug_assert(fmt != ~0);
 
OUT_PKT0(ring, REG_A4XX_VFD_FETCH(j), 4);
OUT_RING(ring, A4XX_VFD_FETCH_INSTR_0_FETCHSIZE(fs - 1) |
A4XX_VFD_FETCH_INSTR_0_BUFSTRIDE(vb->stride) |
COND(elem->instance_divisor, A4XX_VFD_FETCH_INSTR_0_INSTANCED) |
COND(switchnext, A4XX_VFD_FETCH_INSTR_0_SWITCHNEXT));
OUT_RELOC(ring, rsc->bo, off, 0, 0);
OUT_RING(ring, A4XX_VFD_FETCH_INSTR_2_SIZE(size));
OUT_RING(ring, A4XX_VFD_FETCH_INSTR_3_STEPRATE(MAX2(1, elem->instance_divisor)));
 
OUT_PKT0(ring, REG_A4XX_VFD_DECODE_INSTR(j), 1);
OUT_RING(ring, A4XX_VFD_DECODE_INSTR_CONSTFILL |
A4XX_VFD_DECODE_INSTR_WRITEMASK(vp->inputs[i].compmask) |
A4XX_VFD_DECODE_INSTR_FORMAT(fmt) |
A4XX_VFD_DECODE_INSTR_SWAP(fd4_pipe2swap(pfmt)) |
A4XX_VFD_DECODE_INSTR_REGID(vp->inputs[i].regid) |
A4XX_VFD_DECODE_INSTR_SHIFTCNT(fs) |
A4XX_VFD_DECODE_INSTR_LASTCOMPVALID |
COND(isint, A4XX_VFD_DECODE_INSTR_INT) |
COND(switchnext, A4XX_VFD_DECODE_INSTR_SWITCHNEXT));
 
total_in += vp->inputs[i].ncomp;
j++;
}
}
 
OUT_PKT0(ring, REG_A4XX_VFD_CONTROL_0, 5);
OUT_RING(ring, A4XX_VFD_CONTROL_0_TOTALATTRTOVS(total_in) |
0xa0000 | /* XXX */
A4XX_VFD_CONTROL_0_STRMDECINSTRCNT(j) |
A4XX_VFD_CONTROL_0_STRMFETCHINSTRCNT(j));
OUT_RING(ring, A4XX_VFD_CONTROL_1_MAXSTORAGE(129) | // XXX
A4XX_VFD_CONTROL_1_REGID4VTX(vertex_regid) |
A4XX_VFD_CONTROL_1_REGID4INST(instance_regid));
OUT_RING(ring, 0x00000000); /* XXX VFD_CONTROL_2 */
OUT_RING(ring, A4XX_VFD_CONTROL_3_REGID_VTXCNT(regid(63, 0)));
OUT_RING(ring, 0x00000000); /* XXX VFD_CONTROL_4 */
 
/* cache invalidate, otherwise vertex fetch could see
* stale vbo contents:
*/
OUT_PKT0(ring, REG_A4XX_UCHE_INVALIDATE0, 2);
OUT_RING(ring, 0x00000000);
OUT_RING(ring, 0x00000012);
}
 
void
fd4_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring,
struct fd4_emit *emit)
{
struct ir3_shader_variant *vp = fd4_emit_get_vp(emit);
struct ir3_shader_variant *fp = fd4_emit_get_fp(emit);
uint32_t dirty = emit->dirty;
 
emit_marker(ring, 5);
 
if ((dirty & (FD_DIRTY_ZSA | FD_DIRTY_PROG)) && !emit->key.binning_pass) {
uint32_t val = fd4_zsa_stateobj(ctx->zsa)->rb_render_control;
 
/* I suppose if we needed to (which I don't *think* we need
* to), we could emit this for binning pass too. But we
* would need to keep a different patch-list for binning
* vs render pass.
*/
 
OUT_PKT0(ring, REG_A4XX_RB_RENDER_CONTROL, 1);
OUT_RINGP(ring, val, &fd4_context(ctx)->rbrc_patches);
}
 
if (dirty & FD_DIRTY_ZSA) {
struct fd4_zsa_stateobj *zsa = fd4_zsa_stateobj(ctx->zsa);
 
OUT_PKT0(ring, REG_A4XX_RB_ALPHA_CONTROL, 1);
OUT_RING(ring, zsa->rb_alpha_control);
 
OUT_PKT0(ring, REG_A4XX_RB_STENCIL_CONTROL, 2);
OUT_RING(ring, zsa->rb_stencil_control);
OUT_RING(ring, zsa->rb_stencil_control2);
}
 
if (dirty & (FD_DIRTY_ZSA | FD_DIRTY_STENCIL_REF)) {
struct fd4_zsa_stateobj *zsa = fd4_zsa_stateobj(ctx->zsa);
struct pipe_stencil_ref *sr = &ctx->stencil_ref;
 
OUT_PKT0(ring, REG_A4XX_RB_STENCILREFMASK, 2);
OUT_RING(ring, zsa->rb_stencilrefmask |
A4XX_RB_STENCILREFMASK_STENCILREF(sr->ref_value[0]));
OUT_RING(ring, zsa->rb_stencilrefmask_bf |
A4XX_RB_STENCILREFMASK_BF_STENCILREF(sr->ref_value[1]));
}
 
if (dirty & (FD_DIRTY_ZSA | FD_DIRTY_PROG)) {
struct fd4_zsa_stateobj *zsa = fd4_zsa_stateobj(ctx->zsa);
bool fragz = fp->has_kill | fp->writes_pos;
 
OUT_PKT0(ring, REG_A4XX_RB_DEPTH_CONTROL, 1);
OUT_RING(ring, zsa->rb_depth_control |
COND(fragz, A4XX_RB_DEPTH_CONTROL_EARLY_Z_DISABLE));
 
/* maybe this register/bitfield needs a better name.. this
* appears to be just disabling early-z
*/
OUT_PKT0(ring, REG_A4XX_GRAS_ALPHA_CONTROL, 1);
OUT_RING(ring, zsa->gras_alpha_control |
COND(fragz, A4XX_GRAS_ALPHA_CONTROL_ALPHA_TEST_ENABLE));
}
 
if (dirty & FD_DIRTY_RASTERIZER) {
struct fd4_rasterizer_stateobj *rasterizer =
fd4_rasterizer_stateobj(ctx->rasterizer);
 
OUT_PKT0(ring, REG_A4XX_GRAS_SU_MODE_CONTROL, 1);
OUT_RING(ring, rasterizer->gras_su_mode_control |
A4XX_GRAS_SU_MODE_CONTROL_RENDERING_PASS);
 
OUT_PKT0(ring, REG_A4XX_GRAS_SU_POINT_MINMAX, 2);
OUT_RING(ring, rasterizer->gras_su_point_minmax);
OUT_RING(ring, rasterizer->gras_su_point_size);
 
OUT_PKT0(ring, REG_A4XX_GRAS_SU_POLY_OFFSET_SCALE, 2);
OUT_RING(ring, rasterizer->gras_su_poly_offset_scale);
OUT_RING(ring, rasterizer->gras_su_poly_offset_offset);
 
OUT_PKT0(ring, REG_A4XX_GRAS_CL_CLIP_CNTL, 1);
OUT_RING(ring, rasterizer->gras_cl_clip_cntl);
}
 
/* NOTE: since primitive_restart is not actually part of any
* state object, we need to make sure that we always emit
* PRIM_VTX_CNTL.. either that or be more clever and detect
* when it changes.
*/
if (emit->info) {
const struct pipe_draw_info *info = emit->info;
uint32_t val = fd4_rasterizer_stateobj(ctx->rasterizer)
->pc_prim_vtx_cntl;
 
if (info->indexed && info->primitive_restart)
val |= A4XX_PC_PRIM_VTX_CNTL_PRIMITIVE_RESTART;
 
val |= COND(vp->writes_psize, A4XX_PC_PRIM_VTX_CNTL_PSIZE);
 
if (fp->total_in > 0) {
uint32_t varout = align(fp->total_in, 16) / 16;
if (varout > 1)
varout = align(varout, 2);
val |= A4XX_PC_PRIM_VTX_CNTL_VAROUT(varout);
}
 
OUT_PKT0(ring, REG_A4XX_PC_PRIM_VTX_CNTL, 2);
OUT_RING(ring, val);
OUT_RING(ring, 0x12); /* XXX UNKNOWN_21C5 */
}
 
if (dirty & FD_DIRTY_SCISSOR) {
struct pipe_scissor_state *scissor = fd_context_get_scissor(ctx);
 
OUT_PKT0(ring, REG_A4XX_GRAS_SC_WINDOW_SCISSOR_BR, 2);
OUT_RING(ring, A4XX_GRAS_SC_WINDOW_SCISSOR_BR_X(scissor->maxx - 1) |
A4XX_GRAS_SC_WINDOW_SCISSOR_BR_Y(scissor->maxy - 1));
OUT_RING(ring, A4XX_GRAS_SC_WINDOW_SCISSOR_TL_X(scissor->minx) |
A4XX_GRAS_SC_WINDOW_SCISSOR_TL_Y(scissor->miny));
 
ctx->max_scissor.minx = MIN2(ctx->max_scissor.minx, scissor->minx);
ctx->max_scissor.miny = MIN2(ctx->max_scissor.miny, scissor->miny);
ctx->max_scissor.maxx = MAX2(ctx->max_scissor.maxx, scissor->maxx);
ctx->max_scissor.maxy = MAX2(ctx->max_scissor.maxy, scissor->maxy);
}
 
if (dirty & FD_DIRTY_VIEWPORT) {
fd_wfi(ctx, ring);
OUT_PKT0(ring, REG_A4XX_GRAS_CL_VPORT_XOFFSET_0, 6);
OUT_RING(ring, A4XX_GRAS_CL_VPORT_XOFFSET_0(ctx->viewport.translate[0]));
OUT_RING(ring, A4XX_GRAS_CL_VPORT_XSCALE_0(ctx->viewport.scale[0]));
OUT_RING(ring, A4XX_GRAS_CL_VPORT_YOFFSET_0(ctx->viewport.translate[1]));
OUT_RING(ring, A4XX_GRAS_CL_VPORT_YSCALE_0(ctx->viewport.scale[1]));
OUT_RING(ring, A4XX_GRAS_CL_VPORT_ZOFFSET_0(ctx->viewport.translate[2]));
OUT_RING(ring, A4XX_GRAS_CL_VPORT_ZSCALE_0(ctx->viewport.scale[2]));
}
 
if (dirty & FD_DIRTY_PROG)
fd4_program_emit(ring, emit);
 
if ((dirty & (FD_DIRTY_PROG | FD_DIRTY_CONSTBUF)) &&
/* evil hack to deal sanely with clear path: */
(emit->prog == &ctx->prog)) {
fd_wfi(ctx, ring);
emit_constants(ring, SB_VERT_SHADER,
&ctx->constbuf[PIPE_SHADER_VERTEX],
vp, emit->prog->dirty & FD_SHADER_DIRTY_VP);
if (!emit->key.binning_pass) {
emit_constants(ring, SB_FRAG_SHADER,
&ctx->constbuf[PIPE_SHADER_FRAGMENT],
fp, emit->prog->dirty & FD_SHADER_DIRTY_FP);
}
}
 
/* emit driver params every time */
if (emit->info && emit->prog == &ctx->prog) {
uint32_t vertex_params[4] = {
emit->info->indexed ? emit->info->index_bias : emit->info->start,
0,
0,
0
};
if (vp->constlen >= vp->first_driver_param + 4) {
fd4_emit_constant(ring, SB_VERT_SHADER,
(vp->first_driver_param + 4) * 4,
0, 4, vertex_params, NULL);
}
}
 
if ((dirty & FD_DIRTY_BLEND) && ctx->blend) {
struct fd4_blend_stateobj *blend = fd4_blend_stateobj(ctx->blend);
uint32_t i;
 
for (i = 0; i < 8; i++) {
OUT_PKT0(ring, REG_A4XX_RB_MRT_CONTROL(i), 1);
OUT_RING(ring, blend->rb_mrt[i].control);
 
OUT_PKT0(ring, REG_A4XX_RB_MRT_BLEND_CONTROL(i), 1);
OUT_RING(ring, blend->rb_mrt[i].blend_control);
}
 
OUT_PKT0(ring, REG_A4XX_RB_FS_OUTPUT, 1);
OUT_RING(ring, blend->rb_fs_output |
A4XX_RB_FS_OUTPUT_SAMPLE_MASK(0xffff));
}
 
if (dirty & FD_DIRTY_BLEND_COLOR) {
struct pipe_blend_color *bcolor = &ctx->blend_color;
OUT_PKT0(ring, REG_A4XX_RB_BLEND_RED, 4);
OUT_RING(ring, A4XX_RB_BLEND_RED_UINT(bcolor->color[0] * 255.0) |
A4XX_RB_BLEND_RED_FLOAT(bcolor->color[0]));
OUT_RING(ring, A4XX_RB_BLEND_GREEN_UINT(bcolor->color[1] * 255.0) |
A4XX_RB_BLEND_GREEN_FLOAT(bcolor->color[1]));
OUT_RING(ring, A4XX_RB_BLEND_BLUE_UINT(bcolor->color[2] * 255.0) |
A4XX_RB_BLEND_BLUE_FLOAT(bcolor->color[2]));
OUT_RING(ring, A4XX_RB_BLEND_ALPHA_UINT(bcolor->color[3] * 255.0) |
A4XX_RB_BLEND_ALPHA_FLOAT(bcolor->color[3]));
}
 
if (dirty & FD_DIRTY_VERTTEX) {
if (vp->has_samp)
emit_textures(ctx, ring, SB_VERT_TEX, &ctx->verttex);
else
dirty &= ~FD_DIRTY_VERTTEX;
}
 
if (dirty & FD_DIRTY_FRAGTEX) {
if (fp->has_samp)
emit_textures(ctx, ring, SB_FRAG_TEX, &ctx->fragtex);
else
dirty &= ~FD_DIRTY_FRAGTEX;
}
 
ctx->dirty &= ~dirty;
}
 
/* emit setup at begin of new cmdstream buffer (don't rely on previous
* state, there could have been a context switch between ioctls):
*/
void
fd4_emit_restore(struct fd_context *ctx)
{
struct fd4_context *fd4_ctx = fd4_context(ctx);
struct fd_ringbuffer *ring = ctx->ring;
 
OUT_PKT0(ring, REG_A4XX_RBBM_PERFCTR_CTL, 1);
OUT_RING(ring, 0x00000001);
 
OUT_PKT0(ring, REG_A4XX_GRAS_DEBUG_ECO_CONTROL, 1);
OUT_RING(ring, 0x00000000);
 
OUT_PKT0(ring, REG_A4XX_UNKNOWN_0EC3, 1);
OUT_RING(ring, 0x00000006);
 
OUT_PKT0(ring, REG_A4XX_UNKNOWN_0F03, 1);
OUT_RING(ring, 0x0000003a);
 
OUT_PKT0(ring, REG_A4XX_UNKNOWN_0D01, 1);
OUT_RING(ring, 0x00000001);
 
OUT_PKT0(ring, REG_A4XX_UNKNOWN_0E42, 1);
OUT_RING(ring, 0x00000000);
 
OUT_PKT0(ring, REG_A4XX_UCHE_CACHE_WAYS_VFD, 1);
OUT_RING(ring, 0x00000007);
 
OUT_PKT0(ring, REG_A4XX_UCHE_CACHE_MODE_CONTROL, 1);
OUT_RING(ring, 0x00000000);
 
OUT_PKT0(ring, REG_A4XX_UCHE_INVALIDATE0, 2);
OUT_RING(ring, 0x00000000);
OUT_RING(ring, 0x00000012);
 
OUT_PKT0(ring, REG_A4XX_UNKNOWN_0E05, 1);
OUT_RING(ring, 0x00000000);
 
OUT_PKT0(ring, REG_A4XX_UNKNOWN_0CC5, 1);
OUT_RING(ring, 0x00000006);
 
OUT_PKT0(ring, REG_A4XX_UNKNOWN_0CC6, 1);
OUT_RING(ring, 0x00000000);
 
OUT_PKT0(ring, REG_A4XX_UNKNOWN_0EC2, 1);
OUT_RING(ring, 0x00040000);
 
OUT_PKT0(ring, REG_A4XX_UNKNOWN_2001, 1);
OUT_RING(ring, 0x00000000);
 
OUT_PKT3(ring, CP_INVALIDATE_STATE, 1);
OUT_RING(ring, 0x00001000);
 
OUT_PKT0(ring, REG_A4XX_UNKNOWN_20EF, 1);
OUT_RING(ring, 0x00000000);
 
OUT_PKT0(ring, REG_A4XX_UNKNOWN_20F0, 1);
OUT_RING(ring, 0x00000000);
 
OUT_PKT0(ring, REG_A4XX_UNKNOWN_20F1, 1);
OUT_RING(ring, 0x00000000);
 
OUT_PKT0(ring, REG_A4XX_UNKNOWN_20F2, 1);
OUT_RING(ring, 0x00000000);
 
OUT_PKT0(ring, REG_A4XX_RB_BLEND_RED, 4);
OUT_RING(ring, A4XX_RB_BLEND_RED_UINT(0) |
A4XX_RB_BLEND_RED_FLOAT(0.0));
OUT_RING(ring, A4XX_RB_BLEND_GREEN_UINT(0) |
A4XX_RB_BLEND_GREEN_FLOAT(0.0));
OUT_RING(ring, A4XX_RB_BLEND_BLUE_UINT(0) |
A4XX_RB_BLEND_BLUE_FLOAT(0.0));
OUT_RING(ring, A4XX_RB_BLEND_ALPHA_UINT(0x7fff) |
A4XX_RB_BLEND_ALPHA_FLOAT(1.0));
 
OUT_PKT0(ring, REG_A4XX_UNKNOWN_20F7, 1);
OUT_RING(ring, 0x3f800000);
 
OUT_PKT0(ring, REG_A4XX_UNKNOWN_2152, 1);
OUT_RING(ring, 0x00000000);
 
OUT_PKT0(ring, REG_A4XX_UNKNOWN_2153, 1);
OUT_RING(ring, 0x00000000);
 
OUT_PKT0(ring, REG_A4XX_UNKNOWN_2154, 1);
OUT_RING(ring, 0x00000000);
 
OUT_PKT0(ring, REG_A4XX_UNKNOWN_2155, 1);
OUT_RING(ring, 0x00000000);
 
OUT_PKT0(ring, REG_A4XX_UNKNOWN_2156, 1);
OUT_RING(ring, 0x00000000);
 
OUT_PKT0(ring, REG_A4XX_UNKNOWN_2157, 1);
OUT_RING(ring, 0x00000000);
 
OUT_PKT0(ring, REG_A4XX_UNKNOWN_21C3, 1);
OUT_RING(ring, 0x0000001d);
 
OUT_PKT0(ring, REG_A4XX_PC_GS_PARAM, 1);
OUT_RING(ring, 0x00000000);
 
OUT_PKT0(ring, REG_A4XX_UNKNOWN_21E6, 1);
OUT_RING(ring, 0x00000001);
 
OUT_PKT0(ring, REG_A4XX_PC_HS_PARAM, 1);
OUT_RING(ring, 0x00000000);
 
OUT_PKT0(ring, REG_A4XX_UNKNOWN_22D7, 1);
OUT_RING(ring, 0x00000000);
 
OUT_PKT0(ring, REG_A4XX_TPL1_TP_TEX_OFFSET, 1);
OUT_RING(ring, 0x00000000);
 
OUT_PKT0(ring, REG_A4XX_TPL1_TP_TEX_COUNT, 1);
OUT_RING(ring, A4XX_TPL1_TP_TEX_COUNT_VS(16) |
A4XX_TPL1_TP_TEX_COUNT_HS(0) |
A4XX_TPL1_TP_TEX_COUNT_DS(0) |
A4XX_TPL1_TP_TEX_COUNT_GS(0));
 
OUT_PKT0(ring, REG_A4XX_TPL1_TP_FS_TEX_COUNT, 1);
OUT_RING(ring, 16);
 
/* we don't use this yet.. probably best to disable.. */
OUT_PKT3(ring, CP_SET_DRAW_STATE, 2);
OUT_RING(ring, CP_SET_DRAW_STATE_0_COUNT(0) |
CP_SET_DRAW_STATE_0_DISABLE_ALL_GROUPS |
CP_SET_DRAW_STATE_0_GROUP_ID(0));
OUT_RING(ring, CP_SET_DRAW_STATE_1_ADDR(0));
 
OUT_PKT0(ring, REG_A4XX_SP_VS_PVT_MEM_PARAM, 2);
OUT_RING(ring, 0x08000001); /* SP_VS_PVT_MEM_PARAM */
OUT_RELOC(ring, fd4_ctx->vs_pvt_mem, 0,0,0); /* SP_VS_PVT_MEM_ADDR */
 
OUT_PKT0(ring, REG_A4XX_SP_FS_PVT_MEM_PARAM, 2);
OUT_RING(ring, 0x08000001); /* SP_FS_PVT_MEM_PARAM */
OUT_RELOC(ring, fd4_ctx->fs_pvt_mem, 0,0,0); /* SP_FS_PVT_MEM_ADDR */
 
OUT_PKT0(ring, REG_A4XX_GRAS_SC_CONTROL, 1);
OUT_RING(ring, A4XX_GRAS_SC_CONTROL_RENDER_MODE(RB_RENDERING_PASS) |
A4XX_GRAS_SC_CONTROL_MSAA_DISABLE |
A4XX_GRAS_SC_CONTROL_MSAA_SAMPLES(MSAA_ONE) |
A4XX_GRAS_SC_CONTROL_RASTER_MODE(0));
 
OUT_PKT0(ring, REG_A4XX_RB_MSAA_CONTROL, 1);
OUT_RING(ring, A4XX_RB_MSAA_CONTROL_DISABLE |
A4XX_RB_MSAA_CONTROL_SAMPLES(MSAA_ONE));
 
OUT_PKT0(ring, REG_A4XX_GRAS_CL_GB_CLIP_ADJ, 1);
OUT_RING(ring, A4XX_GRAS_CL_GB_CLIP_ADJ_HORZ(0) |
A4XX_GRAS_CL_GB_CLIP_ADJ_VERT(0));
 
OUT_PKT0(ring, REG_A4XX_RB_ALPHA_CONTROL, 1);
OUT_RING(ring, A4XX_RB_ALPHA_CONTROL_ALPHA_TEST_FUNC(FUNC_ALWAYS));
 
OUT_PKT0(ring, REG_A4XX_RB_FS_OUTPUT, 1);
OUT_RING(ring, A4XX_RB_FS_OUTPUT_SAMPLE_MASK(0xffff));
 
OUT_PKT0(ring, REG_A4XX_RB_RENDER_COMPONENTS, 1);
OUT_RING(ring, A4XX_RB_RENDER_COMPONENTS_RT0(0xf));
 
OUT_PKT0(ring, REG_A4XX_GRAS_CLEAR_CNTL, 1);
OUT_RING(ring, A4XX_GRAS_CLEAR_CNTL_NOT_FASTCLEAR);
 
OUT_PKT0(ring, REG_A4XX_GRAS_ALPHA_CONTROL, 1);
OUT_RING(ring, 0x0);
 
ctx->needs_rb_fbd = true;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a4xx/fd4_emit.h
0,0 → 1,99
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FD4_EMIT_H
#define FD4_EMIT_H
 
#include "pipe/p_context.h"
 
#include "freedreno_context.h"
#include "fd4_format.h"
#include "fd4_program.h"
#include "ir3_shader.h"
 
struct fd_ringbuffer;
enum adreno_state_block;
 
void fd4_emit_constant(struct fd_ringbuffer *ring,
enum adreno_state_block sb,
uint32_t regid, uint32_t offset, uint32_t sizedwords,
const uint32_t *dwords, struct pipe_resource *prsc);
 
void fd4_emit_gmem_restore_tex(struct fd_ringbuffer *ring,
struct pipe_surface *psurf);
 
/* grouped together emit-state for prog/vertex/state emit: */
struct fd4_emit {
const struct fd_vertex_state *vtx;
const struct fd_program_stateobj *prog;
const struct pipe_draw_info *info;
struct ir3_shader_key key;
enum a4xx_color_fmt format;
enum pipe_format pformat;
uint32_t dirty;
 
/* cached to avoid repeated lookups of same variants: */
struct ir3_shader_variant *vp, *fp;
/* TODO: other shader stages.. */
};
 
static inline enum a4xx_color_fmt fd4_emit_format(struct pipe_surface *surf)
{
if (!surf)
return 0;
return fd4_pipe2color(surf->format);
}
 
static inline struct ir3_shader_variant *
fd4_emit_get_vp(struct fd4_emit *emit)
{
if (!emit->vp) {
struct fd4_shader_stateobj *so = emit->prog->vp;
emit->vp = ir3_shader_variant(so->shader, emit->key);
}
return emit->vp;
}
 
static inline struct ir3_shader_variant *
fd4_emit_get_fp(struct fd4_emit *emit)
{
if (!emit->fp) {
struct fd4_shader_stateobj *so = emit->prog->fp;
emit->fp = ir3_shader_variant(so->shader, emit->key);
}
return emit->fp;
}
 
void fd4_emit_vertex_bufs(struct fd_ringbuffer *ring, struct fd4_emit *emit);
 
void fd4_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring,
struct fd4_emit *emit);
 
void fd4_emit_restore(struct fd_context *ctx);
 
#endif /* FD4_EMIT_H */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a4xx/fd4_format.c
0,0 → 1,366
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "pipe/p_defines.h"
#include "util/u_format.h"
 
#include "fd4_format.h"
 
 
/* Specifies the table of all the formats and their features. Also supplies
* the helpers that look up various data in those tables.
*/
 
struct fd4_format {
enum a4xx_vtx_fmt vtx;
enum a4xx_tex_fmt tex;
enum a4xx_color_fmt rb;
enum a3xx_color_swap swap;
boolean present;
};
 
#define RB4_NONE ~0
 
/* vertex + texture */
#define VT(pipe, fmt, rbfmt, swapfmt) \
[PIPE_FORMAT_ ## pipe] = { \
.present = 1, \
.vtx = VFMT4_ ## fmt, \
.tex = TFMT4_ ## fmt, \
.rb = RB4_ ## rbfmt, \
.swap = swapfmt \
}
 
/* texture-only */
#define _T(pipe, fmt, rbfmt, swapfmt) \
[PIPE_FORMAT_ ## pipe] = { \
.present = 1, \
.vtx = ~0, \
.tex = TFMT4_ ## fmt, \
.rb = RB4_ ## rbfmt, \
.swap = swapfmt \
}
 
/* vertex-only */
#define V_(pipe, fmt, rbfmt, swapfmt) \
[PIPE_FORMAT_ ## pipe] = { \
.present = 1, \
.vtx = VFMT4_ ## fmt, \
.tex = ~0, \
.rb = RB4_ ## rbfmt, \
.swap = swapfmt \
}
 
static struct fd4_format formats[PIPE_FORMAT_COUNT] = {
/* 8-bit */
VT(R8_UNORM, 8_UNORM, R8_UNORM, WZYX),
V_(R8_SNORM, 8_SNORM, NONE, WZYX),
V_(R8_UINT, 8_UINT, NONE, WZYX),
V_(R8_SINT, 8_SINT, NONE, WZYX),
V_(R8_USCALED, 8_UINT, NONE, WZYX),
V_(R8_SSCALED, 8_UINT, NONE, WZYX),
 
_T(A8_UNORM, 8_UNORM, A8_UNORM, WZYX),
_T(L8_UNORM, 8_UNORM, R8_UNORM, WZYX),
_T(I8_UNORM, 8_UNORM, NONE, WZYX),
 
/* 16-bit */
V_(R16_UNORM, 16_UNORM, NONE, WZYX),
V_(R16_SNORM, 16_SNORM, NONE, WZYX),
VT(R16_UINT, 16_UINT, R16_UINT, WZYX),
VT(R16_SINT, 16_SINT, R16_SINT, WZYX),
V_(R16_USCALED, 16_UINT, NONE, WZYX),
V_(R16_SSCALED, 16_UINT, NONE, WZYX),
VT(R16_FLOAT, 16_FLOAT, NONE, WZYX),
 
_T(A16_UINT, 16_UINT, NONE, WZYX),
_T(A16_SINT, 16_SINT, NONE, WZYX),
_T(L16_UINT, 16_UINT, NONE, WZYX),
_T(L16_SINT, 16_SINT, NONE, WZYX),
_T(I16_UINT, 16_UINT, NONE, WZYX),
_T(I16_SINT, 16_SINT, NONE, WZYX),
 
VT(R8G8_UNORM, 8_8_UNORM, R8G8_UNORM, WZYX),
VT(R8G8_SNORM, 8_8_SNORM, R8G8_SNORM, WZYX),
VT(R8G8_UINT, 8_8_UINT, NONE, WZYX),
VT(R8G8_SINT, 8_8_SINT, NONE, WZYX),
V_(R8G8_USCALED, 8_8_UINT, NONE, WZYX),
V_(R8G8_SSCALED, 8_8_SINT, NONE, WZYX),
 
_T(L8A8_UINT, 8_8_UINT, NONE, WZYX),
_T(L8A8_SINT, 8_8_SINT, NONE, WZYX),
 
_T(B5G5R5A1_UNORM, 5_5_5_1_UNORM, R5G5B5A1_UNORM, WXYZ),
_T(B5G5R5X1_UNORM, 5_5_5_1_UNORM, R5G5B5A1_UNORM, WXYZ),
_T(B4G4R4A4_UNORM, 4_4_4_4_UNORM, R4G4B4A4_UNORM, WXYZ),
 
/* 24-bit */
V_(R8G8B8_UNORM, 8_8_8_UNORM, NONE, WZYX),
V_(R8G8B8_SNORM, 8_8_8_SNORM, NONE, WZYX),
V_(R8G8B8_UINT, 8_8_8_UINT, NONE, WZYX),
V_(R8G8B8_SINT, 8_8_8_SINT, NONE, WZYX),
V_(R8G8B8_USCALED, 8_8_8_UINT, NONE, WZYX),
V_(R8G8B8_SSCALED, 8_8_8_SINT, NONE, WZYX),
 
/* 32-bit */
VT(R32_UINT, 32_UINT, R32_UINT, WZYX),
VT(R32_SINT, 32_SINT, R32_SINT, WZYX),
V_(R32_USCALED, 32_UINT, NONE, WZYX),
V_(R32_SSCALED, 32_UINT, NONE, WZYX),
VT(R32_FLOAT, 32_FLOAT, NONE, WZYX),
V_(R32_FIXED, 32_FIXED, NONE, WZYX),
 
_T(A32_UINT, 32_UINT, NONE, WZYX),
_T(A32_SINT, 32_SINT, NONE, WZYX),
_T(L32_UINT, 32_UINT, NONE, WZYX),
_T(L32_SINT, 32_SINT, NONE, WZYX),
_T(I32_UINT, 32_UINT, NONE, WZYX),
_T(I32_SINT, 32_SINT, NONE, WZYX),
 
V_(R16G16_UNORM, 16_16_UNORM, NONE, WZYX),
V_(R16G16_SNORM, 16_16_SNORM, NONE, WZYX),
VT(R16G16_UINT, 16_16_UINT, R16G16_UINT, WZYX),
VT(R16G16_SINT, 16_16_SINT, R16G16_SINT, WZYX),
V_(R16G16_USCALED, 16_16_UINT, NONE, WZYX),
V_(R16G16_SSCALED, 16_16_SINT, NONE, WZYX),
VT(R16G16_FLOAT, 16_16_FLOAT, NONE, WZYX),
 
_T(L16A16_UINT, 16_16_UINT, NONE, WZYX),
_T(L16A16_SINT, 16_16_SINT, NONE, WZYX),
 
VT(R8G8B8A8_UNORM, 8_8_8_8_UNORM, R8G8B8A8_UNORM, WZYX),
_T(R8G8B8X8_UNORM, 8_8_8_8_UNORM, R8G8B8A8_UNORM, WZYX),
_T(R8G8B8A8_SRGB, 8_8_8_8_UNORM, R8G8B8A8_UNORM, WZYX),
_T(R8G8B8X8_SRGB, 8_8_8_8_UNORM, R8G8B8A8_UNORM, WZYX),
VT(R8G8B8A8_SNORM, 8_8_8_8_SNORM, R8G8B8A8_SNORM, WZYX),
VT(R8G8B8A8_UINT, 8_8_8_8_UINT, R8G8B8A8_UINT, WZYX),
VT(R8G8B8A8_SINT, 8_8_8_8_SINT, R8G8B8A8_SINT, WZYX),
V_(R8G8B8A8_USCALED, 8_8_8_8_UINT, NONE, WZYX),
V_(R8G8B8A8_SSCALED, 8_8_8_8_SINT, NONE, WZYX),
 
VT(B8G8R8A8_UNORM, 8_8_8_8_UNORM, R8G8B8A8_UNORM, WXYZ),
_T(B8G8R8X8_UNORM, 8_8_8_8_UNORM, R8G8B8A8_UNORM, WXYZ),
VT(B8G8R8A8_SRGB, 8_8_8_8_UNORM, R8G8B8A8_UNORM, WXYZ),
_T(B8G8R8X8_SRGB, 8_8_8_8_UNORM, R8G8B8A8_UNORM, WXYZ),
 
VT(A8B8G8R8_UNORM, 8_8_8_8_UNORM, R8G8B8A8_UNORM, XYZW),
_T(X8B8G8R8_UNORM, 8_8_8_8_UNORM, R8G8B8A8_UNORM, XYZW),
_T(A8B8G8R8_SRGB, 8_8_8_8_UNORM, R8G8B8A8_UNORM, XYZW),
_T(X8B8G8R8_SRGB, 8_8_8_8_UNORM, R8G8B8A8_UNORM, XYZW),
 
VT(A8R8G8B8_UNORM, 8_8_8_8_UNORM, R8G8B8A8_UNORM, ZYXW),
_T(X8R8G8B8_UNORM, 8_8_8_8_UNORM, R8G8B8A8_UNORM, ZYXW),
_T(A8R8G8B8_SRGB, 8_8_8_8_UNORM, R8G8B8A8_UNORM, ZYXW),
_T(X8R8G8B8_SRGB, 8_8_8_8_UNORM, R8G8B8A8_UNORM, ZYXW),
 
VT(R10G10B10A2_UNORM, 10_10_10_2_UNORM, R10G10B10A2_UNORM, WZYX),
VT(B10G10R10A2_UNORM, 10_10_10_2_UNORM, R10G10B10A2_UNORM, WXYZ),
_T(B10G10R10X2_UNORM, 10_10_10_2_UNORM, R10G10B10A2_UNORM, WXYZ),
V_(R10G10B10A2_SNORM, 10_10_10_2_SNORM, NONE, WZYX),
V_(R10G10B10A2_UINT, 10_10_10_2_UINT, NONE, WZYX),
V_(R10G10B10A2_USCALED, 10_10_10_2_UINT, NONE, WZYX),
V_(R10G10B10A2_SSCALED, 10_10_10_2_SINT, NONE, WZYX),
 
_T(R11G11B10_FLOAT, 11_11_10_FLOAT, R11G11B10_FLOAT, WZYX),
_T(R9G9B9E5_FLOAT, 9_9_9_E5_FLOAT, NONE, WZYX),
 
_T(Z24X8_UNORM, X8Z24_UNORM, R8G8B8A8_UNORM, WZYX),
_T(Z24_UNORM_S8_UINT, X8Z24_UNORM, R8G8B8A8_UNORM, WZYX),
/*_T(Z32_FLOAT, Z32_FLOAT, R8G8B8A8_UNORM, WZYX),*/
 
/* 48-bit */
V_(R16G16B16_UNORM, 16_16_16_UNORM, NONE, WZYX),
V_(R16G16B16_SNORM, 16_16_16_SNORM, NONE, WZYX),
V_(R16G16B16_UINT, 16_16_16_UINT, NONE, WZYX),
V_(R16G16B16_SINT, 16_16_16_SINT, NONE, WZYX),
V_(R16G16B16_USCALED, 16_16_16_UINT, NONE, WZYX),
V_(R16G16B16_SSCALED, 16_16_16_SINT, NONE, WZYX),
V_(R16G16B16_FLOAT, 16_16_16_FLOAT, NONE, WZYX),
 
/* 64-bit */
V_(R16G16B16A16_UNORM, 16_16_16_16_UNORM, NONE, WZYX),
V_(R16G16B16A16_SNORM, 16_16_16_16_SNORM, NONE, WZYX),
VT(R16G16B16A16_UINT, 16_16_16_16_UINT, R16G16B16A16_UINT, WZYX),
_T(R16G16B16X16_UINT, 16_16_16_16_UINT, R16G16B16A16_UINT, WZYX),
VT(R16G16B16A16_SINT, 16_16_16_16_SINT, R16G16B16A16_SINT, WZYX),
_T(R16G16B16X16_SINT, 16_16_16_16_SINT, R16G16B16A16_SINT, WZYX),
V_(R16G16B16A16_USCALED, 16_16_16_16_UINT, NONE, WZYX),
V_(R16G16B16A16_SSCALED, 16_16_16_16_SINT, NONE, WZYX),
VT(R16G16B16A16_FLOAT, 16_16_16_16_FLOAT, R16G16B16A16_FLOAT, WZYX),
_T(R16G16B16X16_FLOAT, 16_16_16_16_FLOAT, R16G16B16A16_FLOAT, WZYX),
 
VT(R32G32_UINT, 32_32_UINT, R32G32_UINT, WZYX),
VT(R32G32_SINT, 32_32_SINT, R32G32_SINT, WZYX),
V_(R32G32_USCALED, 32_32_UINT, NONE, WZYX),
V_(R32G32_SSCALED, 32_32_SINT, NONE, WZYX),
VT(R32G32_FLOAT, 32_32_FLOAT, NONE, WZYX),
V_(R32G32_FIXED, 32_32_FIXED, NONE, WZYX),
 
_T(L32A32_UINT, 32_32_UINT, NONE, WZYX),
_T(L32A32_SINT, 32_32_SINT, NONE, WZYX),
 
/* 96-bit */
V_(R32G32B32_UINT, 32_32_32_UINT, NONE, WZYX),
V_(R32G32B32_SINT, 32_32_32_SINT, NONE, WZYX),
V_(R32G32B32_USCALED, 32_32_32_UINT, NONE, WZYX),
V_(R32G32B32_SSCALED, 32_32_32_SINT, NONE, WZYX),
V_(R32G32B32_FLOAT, 32_32_32_FLOAT, NONE, WZYX),
V_(R32G32B32_FIXED, 32_32_32_FIXED, NONE, WZYX),
 
/* 128-bit */
VT(R32G32B32A32_UINT, 32_32_32_32_UINT, R32G32B32A32_UINT, WZYX),
_T(R32G32B32X32_UINT, 32_32_32_32_UINT, R32G32B32A32_UINT, WZYX),
VT(R32G32B32A32_SINT, 32_32_32_32_SINT, R32G32B32A32_SINT, WZYX),
_T(R32G32B32X32_SINT, 32_32_32_32_SINT, R32G32B32A32_SINT, WZYX),
V_(R32G32B32A32_USCALED, 32_32_32_32_UINT, NONE, WZYX),
V_(R32G32B32A32_SSCALED, 32_32_32_32_SINT, NONE, WZYX),
VT(R32G32B32A32_FLOAT, 32_32_32_32_FLOAT, R32G32B32A32_FLOAT, WZYX),
_T(R32G32B32X32_FLOAT, 32_32_32_32_FLOAT, R32G32B32A32_FLOAT, WZYX),
V_(R32G32B32A32_FIXED, 32_32_32_32_FIXED, NONE, WZYX),
};
 
/* convert pipe format to vertex buffer format: */
enum a4xx_vtx_fmt
fd4_pipe2vtx(enum pipe_format format)
{
if (!formats[format].present)
return ~0;
return formats[format].vtx;
}
 
/* convert pipe format to texture sampler format: */
enum a4xx_tex_fmt
fd4_pipe2tex(enum pipe_format format)
{
if (!formats[format].present)
return ~0;
return formats[format].tex;
}
 
/* convert pipe format to MRT / copydest format used for render-target: */
enum a4xx_color_fmt
fd4_pipe2color(enum pipe_format format)
{
if (!formats[format].present)
return ~0;
return formats[format].rb;
}
 
enum a3xx_color_swap
fd4_pipe2swap(enum pipe_format format)
{
if (!formats[format].present)
return WZYX;
return formats[format].swap;
}
 
enum a4xx_tex_fetchsize
fd4_pipe2fetchsize(enum pipe_format format)
{
switch (util_format_get_blocksizebits(format)) {
case 8: return TFETCH4_1_BYTE;
case 16: return TFETCH4_2_BYTE;
case 32: return TFETCH4_4_BYTE;
case 64: return TFETCH4_8_BYTE;
case 128: return TFETCH4_16_BYTE;
default:
debug_printf("Unknown block size for format %s: %d\n",
util_format_name(format),
util_format_get_blocksizebits(format));
return TFETCH4_1_BYTE;
}
}
 
/* we need to special case a bit the depth/stencil restore, because we are
* using the texture sampler to blit into the depth/stencil buffer, *not*
* into a color buffer. Otherwise fd4_tex_swiz() will do the wrong thing,
* as it is assuming that you are sampling into normal render target..
*
* TODO looks like we can probably share w/ a3xx..
*/
enum pipe_format
fd4_gmem_restore_format(enum pipe_format format)
{
switch (format) {
case PIPE_FORMAT_Z24X8_UNORM:
case PIPE_FORMAT_Z24_UNORM_S8_UINT:
return PIPE_FORMAT_R8G8B8A8_UNORM;
case PIPE_FORMAT_Z16_UNORM:
return PIPE_FORMAT_R8G8_UNORM;
default:
return format;
}
}
 
enum a4xx_depth_format
fd4_pipe2depth(enum pipe_format format)
{
switch (format) {
case PIPE_FORMAT_Z16_UNORM:
return DEPTH4_16;
case PIPE_FORMAT_Z24X8_UNORM:
case PIPE_FORMAT_Z24_UNORM_S8_UINT:
case PIPE_FORMAT_X8Z24_UNORM:
case PIPE_FORMAT_S8_UINT_Z24_UNORM:
return DEPTH4_24_8;
default:
return ~0;
}
}
 
static inline enum a4xx_tex_swiz
tex_swiz(unsigned swiz)
{
switch (swiz) {
default:
case PIPE_SWIZZLE_RED: return A4XX_TEX_X;
case PIPE_SWIZZLE_GREEN: return A4XX_TEX_Y;
case PIPE_SWIZZLE_BLUE: return A4XX_TEX_Z;
case PIPE_SWIZZLE_ALPHA: return A4XX_TEX_W;
case PIPE_SWIZZLE_ZERO: return A4XX_TEX_ZERO;
case PIPE_SWIZZLE_ONE: return A4XX_TEX_ONE;
}
}
 
uint32_t
fd4_tex_swiz(enum pipe_format format, unsigned swizzle_r, unsigned swizzle_g,
unsigned swizzle_b, unsigned swizzle_a)
{
const struct util_format_description *desc =
util_format_description(format);
unsigned char swiz[4] = {
swizzle_r, swizzle_g, swizzle_b, swizzle_a,
}, rswiz[4];
 
util_format_compose_swizzles(desc->swizzle, swiz, rswiz);
 
return A4XX_TEX_CONST_0_SWIZ_X(tex_swiz(rswiz[0])) |
A4XX_TEX_CONST_0_SWIZ_Y(tex_swiz(rswiz[1])) |
A4XX_TEX_CONST_0_SWIZ_Z(tex_swiz(rswiz[2])) |
A4XX_TEX_CONST_0_SWIZ_W(tex_swiz(rswiz[3]));
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a4xx/fd4_format.h
0,0 → 1,47
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FD4_UTIL_H_
#define FD4_UTIL_H_
 
#include "freedreno_util.h"
 
#include "a4xx.xml.h"
 
enum a4xx_vtx_fmt fd4_pipe2vtx(enum pipe_format format);
enum a4xx_tex_fmt fd4_pipe2tex(enum pipe_format format);
enum a4xx_color_fmt fd4_pipe2color(enum pipe_format format);
enum pipe_format fd4_gmem_restore_format(enum pipe_format format);
enum a3xx_color_swap fd4_pipe2swap(enum pipe_format format);
enum a4xx_tex_fetchsize fd4_pipe2fetchsize(enum pipe_format format);
enum a4xx_depth_format fd4_pipe2depth(enum pipe_format format);
 
uint32_t fd4_tex_swiz(enum pipe_format format, unsigned swizzle_r,
unsigned swizzle_g, unsigned swizzle_b, unsigned swizzle_a);
 
#endif /* FD4_UTIL_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a4xx/fd4_gmem.c
0,0 → 1,614
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "pipe/p_state.h"
#include "util/u_string.h"
#include "util/u_memory.h"
#include "util/u_inlines.h"
#include "util/u_format.h"
 
#include "freedreno_draw.h"
#include "freedreno_state.h"
#include "freedreno_resource.h"
 
#include "fd4_gmem.h"
#include "fd4_context.h"
#include "fd4_draw.h"
#include "fd4_emit.h"
#include "fd4_program.h"
#include "fd4_format.h"
#include "fd4_zsa.h"
 
static const struct ir3_shader_key key = {
// XXX should set this based on render target format! We don't
// want half_precision if float32 render target!!!
.half_precision = true,
};
 
static void
emit_mrt(struct fd_ringbuffer *ring, unsigned nr_bufs,
struct pipe_surface **bufs, uint32_t *bases, uint32_t bin_w)
{
enum a4xx_tile_mode tile_mode;
unsigned i;
 
if (bin_w) {
tile_mode = 2;
} else {
tile_mode = TILE4_LINEAR;
}
 
for (i = 0; i < 8; i++) {
enum a4xx_color_fmt format = 0;
enum a3xx_color_swap swap = WZYX;
struct fd_resource *rsc = NULL;
struct fd_resource_slice *slice = NULL;
uint32_t stride = 0;
uint32_t base = 0;
uint32_t offset = 0;
 
if ((i < nr_bufs) && bufs[i]) {
struct pipe_surface *psurf = bufs[i];
 
rsc = fd_resource(psurf->texture);
slice = fd_resource_slice(rsc, psurf->u.tex.level);
format = fd4_pipe2color(psurf->format);
swap = fd4_pipe2swap(psurf->format);
 
debug_assert(psurf->u.tex.first_layer == psurf->u.tex.last_layer);
 
offset = fd_resource_offset(rsc, psurf->u.tex.level,
psurf->u.tex.first_layer);
 
if (bin_w) {
stride = bin_w * rsc->cpp;
 
if (bases) {
base = bases[i];
}
} else {
stride = slice->pitch * rsc->cpp;
}
}
 
OUT_PKT0(ring, REG_A4XX_RB_MRT_BUF_INFO(i), 3);
OUT_RING(ring, A4XX_RB_MRT_BUF_INFO_COLOR_FORMAT(format) |
A4XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE(tile_mode) |
A4XX_RB_MRT_BUF_INFO_COLOR_BUF_PITCH(stride) |
A4XX_RB_MRT_BUF_INFO_COLOR_SWAP(swap));
if (bin_w || (i >= nr_bufs)) {
OUT_RING(ring, base);
OUT_RING(ring, A4XX_RB_MRT_CONTROL3_STRIDE(stride));
} else {
OUT_RELOCW(ring, rsc->bo, offset, 0, 0);
/* RB_MRT[i].CONTROL3.STRIDE not emitted by c2d..
* not sure if we need to skip it for bypass or
* not.
*/
OUT_RING(ring, A4XX_RB_MRT_CONTROL3_STRIDE(0));
}
}
}
 
static uint32_t
depth_base(struct fd_context *ctx)
{
struct fd_gmem_stateobj *gmem = &ctx->gmem;
struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
uint32_t cpp = 4;
if (pfb->cbufs[0]) {
struct fd_resource *rsc =
fd_resource(pfb->cbufs[0]->texture);
cpp = rsc->cpp;
}
return align(gmem->bin_w * gmem->bin_h * cpp, 0x4000);
}
 
/* transfer from gmem to system memory (ie. normal RAM) */
 
static void
emit_gmem2mem_surf(struct fd_context *ctx,
uint32_t base, struct pipe_surface *psurf)
{
struct fd_ringbuffer *ring = ctx->ring;
struct fd_resource *rsc = fd_resource(psurf->texture);
struct fd_resource_slice *slice = &rsc->slices[psurf->u.tex.level];
uint32_t offset = fd_resource_offset(rsc, psurf->u.tex.level,
psurf->u.tex.first_layer);
 
debug_assert(psurf->u.tex.first_layer == psurf->u.tex.last_layer);
 
OUT_PKT0(ring, REG_A4XX_RB_COPY_CONTROL, 4);
OUT_RING(ring, A4XX_RB_COPY_CONTROL_MSAA_RESOLVE(MSAA_ONE) |
A4XX_RB_COPY_CONTROL_MODE(RB_COPY_RESOLVE) |
A4XX_RB_COPY_CONTROL_GMEM_BASE(base));
OUT_RELOCW(ring, rsc->bo, offset, 0, 0); /* RB_COPY_DEST_BASE */
OUT_RING(ring, A4XX_RB_COPY_DEST_PITCH_PITCH(slice->pitch * rsc->cpp));
OUT_RING(ring, A4XX_RB_COPY_DEST_INFO_TILE(TILE4_LINEAR) |
A4XX_RB_COPY_DEST_INFO_FORMAT(fd4_pipe2color(psurf->format)) |
A4XX_RB_COPY_DEST_INFO_COMPONENT_ENABLE(0xf) |
A4XX_RB_COPY_DEST_INFO_ENDIAN(ENDIAN_NONE) |
A4XX_RB_COPY_DEST_INFO_SWAP(fd4_pipe2swap(psurf->format)));
 
fd4_draw(ctx, ring, DI_PT_RECTLIST, IGNORE_VISIBILITY,
DI_SRC_SEL_AUTO_INDEX, 2, 1, INDEX_SIZE_IGN, 0, 0, NULL);
}
 
static void
fd4_emit_tile_gmem2mem(struct fd_context *ctx, struct fd_tile *tile)
{
struct fd4_context *fd4_ctx = fd4_context(ctx);
struct fd_ringbuffer *ring = ctx->ring;
struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
struct fd4_emit emit = {
.vtx = &fd4_ctx->solid_vbuf_state,
.prog = &ctx->solid_prog,
.key = key,
.format = fd4_emit_format(pfb->cbufs[0]),
};
 
OUT_PKT0(ring, REG_A4XX_RB_DEPTH_CONTROL, 1);
OUT_RING(ring, A4XX_RB_DEPTH_CONTROL_ZFUNC(FUNC_NEVER));
 
OUT_PKT0(ring, REG_A4XX_RB_STENCIL_CONTROL, 2);
OUT_RING(ring, A4XX_RB_STENCIL_CONTROL_FUNC(FUNC_NEVER) |
A4XX_RB_STENCIL_CONTROL_FAIL(STENCIL_KEEP) |
A4XX_RB_STENCIL_CONTROL_ZPASS(STENCIL_KEEP) |
A4XX_RB_STENCIL_CONTROL_ZFAIL(STENCIL_KEEP) |
A4XX_RB_STENCIL_CONTROL_FUNC_BF(FUNC_NEVER) |
A4XX_RB_STENCIL_CONTROL_FAIL_BF(STENCIL_KEEP) |
A4XX_RB_STENCIL_CONTROL_ZPASS_BF(STENCIL_KEEP) |
A4XX_RB_STENCIL_CONTROL_ZFAIL_BF(STENCIL_KEEP));
OUT_RING(ring, 0x00000000); /* RB_STENCIL_CONTROL2 */
 
OUT_PKT0(ring, REG_A4XX_RB_STENCILREFMASK, 2);
OUT_RING(ring, 0xff000000 |
A4XX_RB_STENCILREFMASK_STENCILREF(0) |
A4XX_RB_STENCILREFMASK_STENCILMASK(0) |
A4XX_RB_STENCILREFMASK_STENCILWRITEMASK(0xff));
OUT_RING(ring, 0xff000000 |
A4XX_RB_STENCILREFMASK_BF_STENCILREF(0) |
A4XX_RB_STENCILREFMASK_BF_STENCILMASK(0) |
A4XX_RB_STENCILREFMASK_BF_STENCILWRITEMASK(0xff));
 
OUT_PKT0(ring, REG_A4XX_GRAS_SU_MODE_CONTROL, 1);
OUT_RING(ring, A4XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH(0));
 
fd_wfi(ctx, ring);
 
OUT_PKT0(ring, REG_A4XX_GRAS_CL_CLIP_CNTL, 1);
OUT_RING(ring, 0x80000); /* GRAS_CL_CLIP_CNTL */
 
OUT_PKT0(ring, REG_A4XX_GRAS_CL_VPORT_XOFFSET_0, 6);
OUT_RING(ring, A4XX_GRAS_CL_VPORT_XOFFSET_0((float)pfb->width/2.0));
OUT_RING(ring, A4XX_GRAS_CL_VPORT_XSCALE_0((float)pfb->width/2.0));
OUT_RING(ring, A4XX_GRAS_CL_VPORT_YOFFSET_0((float)pfb->height/2.0));
OUT_RING(ring, A4XX_GRAS_CL_VPORT_YSCALE_0(-(float)pfb->height/2.0));
OUT_RING(ring, A4XX_GRAS_CL_VPORT_ZOFFSET_0(0.0));
OUT_RING(ring, A4XX_GRAS_CL_VPORT_ZSCALE_0(1.0));
 
OUT_PKT0(ring, REG_A4XX_RB_RENDER_CONTROL, 1);
OUT_RING(ring, A4XX_RB_RENDER_CONTROL_DISABLE_COLOR_PIPE |
0xa); /* XXX */
 
OUT_PKT0(ring, REG_A4XX_GRAS_SC_CONTROL, 1);
OUT_RING(ring, A4XX_GRAS_SC_CONTROL_RENDER_MODE(RB_RESOLVE_PASS) |
A4XX_GRAS_SC_CONTROL_MSAA_DISABLE |
A4XX_GRAS_SC_CONTROL_MSAA_SAMPLES(MSAA_ONE) |
A4XX_GRAS_SC_CONTROL_RASTER_MODE(1));
 
OUT_PKT0(ring, REG_A4XX_PC_PRIM_VTX_CNTL, 1);
OUT_RING(ring, A4XX_PC_PRIM_VTX_CNTL_PROVOKING_VTX_LAST);
 
OUT_PKT0(ring, REG_A4XX_GRAS_ALPHA_CONTROL, 1);
OUT_RING(ring, 0x00000002);
 
OUT_PKT0(ring, REG_A4XX_GRAS_SC_WINDOW_SCISSOR_BR, 2);
OUT_RING(ring, A4XX_GRAS_SC_WINDOW_SCISSOR_BR_X(pfb->width - 1) |
A4XX_GRAS_SC_WINDOW_SCISSOR_BR_Y(pfb->height - 1));
OUT_RING(ring, A4XX_GRAS_SC_WINDOW_SCISSOR_TL_X(0) |
A4XX_GRAS_SC_WINDOW_SCISSOR_TL_Y(0));
 
OUT_PKT0(ring, REG_A4XX_VFD_INDEX_OFFSET, 2);
OUT_RING(ring, 0); /* VFD_INDEX_OFFSET */
OUT_RING(ring, 0); /* ??? UNKNOWN_2209 */
 
fd4_program_emit(ring, &emit);
fd4_emit_vertex_bufs(ring, &emit);
 
if (ctx->resolve & (FD_BUFFER_DEPTH | FD_BUFFER_STENCIL)) {
uint32_t base = depth_base(ctx);
emit_gmem2mem_surf(ctx, base, pfb->zsbuf);
}
 
if (ctx->resolve & FD_BUFFER_COLOR) {
emit_gmem2mem_surf(ctx, 0, pfb->cbufs[0]);
}
 
OUT_PKT0(ring, REG_A4XX_GRAS_SC_CONTROL, 1);
OUT_RING(ring, A4XX_GRAS_SC_CONTROL_RENDER_MODE(RB_RENDERING_PASS) |
A4XX_GRAS_SC_CONTROL_MSAA_DISABLE |
A4XX_GRAS_SC_CONTROL_MSAA_SAMPLES(MSAA_ONE) |
A4XX_GRAS_SC_CONTROL_RASTER_MODE(0));
}
 
/* transfer from system memory to gmem */
 
static void
emit_mem2gmem_surf(struct fd_context *ctx, uint32_t base,
struct pipe_surface *psurf, uint32_t bin_w)
{
struct fd_ringbuffer *ring = ctx->ring;
 
emit_mrt(ring, 1, &psurf, &base, bin_w);
 
fd4_emit_gmem_restore_tex(ring, psurf);
 
fd4_draw(ctx, ring, DI_PT_RECTLIST, IGNORE_VISIBILITY,
DI_SRC_SEL_AUTO_INDEX, 2, 1, INDEX_SIZE_IGN, 0, 0, NULL);
}
 
static void
fd4_emit_tile_mem2gmem(struct fd_context *ctx, struct fd_tile *tile)
{
struct fd4_context *fd4_ctx = fd4_context(ctx);
struct fd_gmem_stateobj *gmem = &ctx->gmem;
struct fd_ringbuffer *ring = ctx->ring;
struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
struct fd4_emit emit = {
.vtx = &fd4_ctx->blit_vbuf_state,
.prog = &ctx->blit_prog[0],
.key = key,
.format = fd4_emit_format(pfb->cbufs[0]),
};
float x0, y0, x1, y1;
unsigned bin_w = tile->bin_w;
unsigned bin_h = tile->bin_h;
unsigned i;
 
/* write texture coordinates to vertexbuf: */
x0 = ((float)tile->xoff) / ((float)pfb->width);
x1 = ((float)tile->xoff + bin_w) / ((float)pfb->width);
y0 = ((float)tile->yoff) / ((float)pfb->height);
y1 = ((float)tile->yoff + bin_h) / ((float)pfb->height);
 
OUT_PKT3(ring, CP_MEM_WRITE, 5);
OUT_RELOCW(ring, fd_resource(fd4_ctx->blit_texcoord_vbuf)->bo, 0, 0, 0);
OUT_RING(ring, fui(x0));
OUT_RING(ring, fui(y0));
OUT_RING(ring, fui(x1));
OUT_RING(ring, fui(y1));
 
for (i = 0; i < 8; i++) {
OUT_PKT0(ring, REG_A4XX_RB_MRT_CONTROL(i), 1);
OUT_RING(ring, A4XX_RB_MRT_CONTROL_FASTCLEAR |
A4XX_RB_MRT_CONTROL_B11 |
A4XX_RB_MRT_CONTROL_COMPONENT_ENABLE(0xf));
 
OUT_PKT0(ring, REG_A4XX_RB_MRT_BLEND_CONTROL(i), 1);
OUT_RING(ring, A4XX_RB_MRT_BLEND_CONTROL_RGB_SRC_FACTOR(FACTOR_ONE) |
A4XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE(BLEND_DST_PLUS_SRC) |
A4XX_RB_MRT_BLEND_CONTROL_RGB_DEST_FACTOR(FACTOR_ZERO) |
A4XX_RB_MRT_BLEND_CONTROL_ALPHA_SRC_FACTOR(FACTOR_ONE) |
A4XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE(BLEND_DST_PLUS_SRC) |
A4XX_RB_MRT_BLEND_CONTROL_ALPHA_DEST_FACTOR(FACTOR_ZERO));
}
 
OUT_PKT0(ring, REG_A4XX_RB_RENDER_CONTROL, 1);
OUT_RING(ring, 0x8); /* XXX RB_RENDER_CONTROL */
 
OUT_PKT0(ring, REG_A4XX_RB_DEPTH_CONTROL, 1);
OUT_RING(ring, A4XX_RB_DEPTH_CONTROL_ZFUNC(FUNC_LESS));
 
OUT_PKT0(ring, REG_A4XX_GRAS_CL_CLIP_CNTL, 1);
OUT_RING(ring, 0x280000); /* XXX GRAS_CL_CLIP_CNTL */
 
OUT_PKT0(ring, REG_A4XX_GRAS_SU_MODE_CONTROL, 1);
OUT_RING(ring, A4XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH(0) |
A4XX_GRAS_SU_MODE_CONTROL_RENDERING_PASS);
 
OUT_PKT0(ring, REG_A4XX_GRAS_CL_VPORT_XOFFSET_0, 6);
OUT_RING(ring, A4XX_GRAS_CL_VPORT_XOFFSET_0((float)bin_w/2.0));
OUT_RING(ring, A4XX_GRAS_CL_VPORT_XSCALE_0((float)bin_w/2.0));
OUT_RING(ring, A4XX_GRAS_CL_VPORT_YOFFSET_0((float)bin_h/2.0));
OUT_RING(ring, A4XX_GRAS_CL_VPORT_YSCALE_0(-(float)bin_h/2.0));
OUT_RING(ring, A4XX_GRAS_CL_VPORT_ZOFFSET_0(0.0));
OUT_RING(ring, A4XX_GRAS_CL_VPORT_ZSCALE_0(1.0));
 
OUT_PKT0(ring, REG_A4XX_GRAS_SC_WINDOW_SCISSOR_BR, 2);
OUT_RING(ring, A4XX_GRAS_SC_WINDOW_SCISSOR_BR_X(bin_w - 1) |
A4XX_GRAS_SC_WINDOW_SCISSOR_BR_Y(bin_h - 1));
OUT_RING(ring, A4XX_GRAS_SC_WINDOW_SCISSOR_TL_X(0) |
A4XX_GRAS_SC_WINDOW_SCISSOR_TL_Y(0));
 
OUT_PKT0(ring, REG_A4XX_GRAS_SC_SCREEN_SCISSOR_TL, 2);
OUT_RING(ring, A4XX_GRAS_SC_SCREEN_SCISSOR_TL_X(0) |
A4XX_GRAS_SC_SCREEN_SCISSOR_TL_Y(0));
OUT_RING(ring, A4XX_GRAS_SC_SCREEN_SCISSOR_BR_X(bin_w - 1) |
A4XX_GRAS_SC_SCREEN_SCISSOR_BR_Y(bin_h - 1));
 
OUT_PKT0(ring, REG_A4XX_RB_MODE_CONTROL, 1);
OUT_RING(ring, A4XX_RB_MODE_CONTROL_WIDTH(gmem->bin_w) |
A4XX_RB_MODE_CONTROL_HEIGHT(gmem->bin_h));
 
OUT_PKT0(ring, REG_A4XX_RB_STENCIL_CONTROL, 2);
OUT_RING(ring, A4XX_RB_STENCIL_CONTROL_FUNC(FUNC_ALWAYS) |
A4XX_RB_STENCIL_CONTROL_FAIL(STENCIL_KEEP) |
A4XX_RB_STENCIL_CONTROL_ZPASS(STENCIL_KEEP) |
A4XX_RB_STENCIL_CONTROL_ZFAIL(STENCIL_KEEP) |
A4XX_RB_STENCIL_CONTROL_FUNC_BF(FUNC_ALWAYS) |
A4XX_RB_STENCIL_CONTROL_FAIL_BF(STENCIL_KEEP) |
A4XX_RB_STENCIL_CONTROL_ZPASS_BF(STENCIL_KEEP) |
A4XX_RB_STENCIL_CONTROL_ZFAIL_BF(STENCIL_KEEP));
OUT_RING(ring, 0x00000000); /* RB_STENCIL_CONTROL2 */
 
OUT_PKT0(ring, REG_A4XX_GRAS_SC_CONTROL, 1);
OUT_RING(ring, A4XX_GRAS_SC_CONTROL_RENDER_MODE(RB_RENDERING_PASS) |
A4XX_GRAS_SC_CONTROL_MSAA_DISABLE |
A4XX_GRAS_SC_CONTROL_MSAA_SAMPLES(MSAA_ONE) |
A4XX_GRAS_SC_CONTROL_RASTER_MODE(1));
 
OUT_PKT0(ring, REG_A4XX_PC_PRIM_VTX_CNTL, 1);
OUT_RING(ring, A4XX_PC_PRIM_VTX_CNTL_PROVOKING_VTX_LAST |
A4XX_PC_PRIM_VTX_CNTL_VAROUT(1));
 
OUT_PKT0(ring, REG_A4XX_VFD_INDEX_OFFSET, 2);
OUT_RING(ring, 0); /* VFD_INDEX_OFFSET */
OUT_RING(ring, 0); /* ??? UNKNOWN_2209 */
 
fd4_program_emit(ring, &emit);
fd4_emit_vertex_bufs(ring, &emit);
 
/* for gmem pitch/base calculations, we need to use the non-
* truncated tile sizes:
*/
bin_w = gmem->bin_w;
bin_h = gmem->bin_h;
 
if (fd_gmem_needs_restore(ctx, tile, FD_BUFFER_DEPTH | FD_BUFFER_STENCIL))
emit_mem2gmem_surf(ctx, depth_base(ctx), pfb->zsbuf, bin_w);
 
if (fd_gmem_needs_restore(ctx, tile, FD_BUFFER_COLOR))
emit_mem2gmem_surf(ctx, 0, pfb->cbufs[0], bin_w);
 
OUT_PKT0(ring, REG_A4XX_GRAS_SC_CONTROL, 1);
OUT_RING(ring, A4XX_GRAS_SC_CONTROL_RENDER_MODE(RB_RENDERING_PASS) |
A4XX_GRAS_SC_CONTROL_MSAA_SAMPLES(MSAA_ONE) |
A4XX_GRAS_SC_CONTROL_RASTER_MODE(0));
 
OUT_PKT0(ring, REG_A4XX_RB_MODE_CONTROL, 1);
OUT_RING(ring, A4XX_RB_MODE_CONTROL_WIDTH(gmem->bin_w) |
A4XX_RB_MODE_CONTROL_HEIGHT(gmem->bin_h) |
0x00010000); /* XXX */
}
 
static void
patch_draws(struct fd_context *ctx, enum pc_di_vis_cull_mode vismode)
{
unsigned i;
for (i = 0; i < fd_patch_num_elements(&ctx->draw_patches); i++) {
struct fd_cs_patch *patch = fd_patch_element(&ctx->draw_patches, i);
*patch->cs = patch->val | DRAW4(0, 0, 0, vismode);
}
util_dynarray_resize(&ctx->draw_patches, 0);
}
 
static void
patch_rbrc(struct fd_context *ctx, uint32_t val)
{
struct fd4_context *fd4_ctx = fd4_context(ctx);
unsigned i;
for (i = 0; i < fd_patch_num_elements(&fd4_ctx->rbrc_patches); i++) {
struct fd_cs_patch *patch = fd_patch_element(&fd4_ctx->rbrc_patches, i);
*patch->cs = patch->val | val;
}
util_dynarray_resize(&fd4_ctx->rbrc_patches, 0);
}
 
/* for rendering directly to system memory: */
static void
fd4_emit_sysmem_prep(struct fd_context *ctx)
{
struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
struct fd_ringbuffer *ring = ctx->ring;
 
fd4_emit_restore(ctx);
 
OUT_PKT0(ring, REG_A4XX_RB_FRAME_BUFFER_DIMENSION, 1);
OUT_RING(ring, A4XX_RB_FRAME_BUFFER_DIMENSION_WIDTH(pfb->width) |
A4XX_RB_FRAME_BUFFER_DIMENSION_HEIGHT(pfb->height));
 
emit_mrt(ring, pfb->nr_cbufs, pfb->cbufs, NULL, 0);
 
/* setup scissor/offset for current tile: */
OUT_PKT0(ring, REG_A4XX_RB_BIN_OFFSET, 1);
OUT_RING(ring, A4XX_RB_BIN_OFFSET_X(0) |
A4XX_RB_BIN_OFFSET_Y(0));
 
OUT_PKT0(ring, REG_A4XX_GRAS_SC_SCREEN_SCISSOR_TL, 2);
OUT_RING(ring, A4XX_GRAS_SC_SCREEN_SCISSOR_TL_X(0) |
A4XX_GRAS_SC_SCREEN_SCISSOR_TL_Y(0));
OUT_RING(ring, A4XX_GRAS_SC_SCREEN_SCISSOR_BR_X(pfb->width - 1) |
A4XX_GRAS_SC_SCREEN_SCISSOR_BR_Y(pfb->height - 1));
 
OUT_PKT0(ring, REG_A4XX_RB_MODE_CONTROL, 1);
OUT_RING(ring, A4XX_RB_MODE_CONTROL_WIDTH(0) |
A4XX_RB_MODE_CONTROL_HEIGHT(0) |
0x00c00000); /* XXX */
 
patch_draws(ctx, IGNORE_VISIBILITY);
patch_rbrc(ctx, 0); // XXX
}
 
static void
update_vsc_pipe(struct fd_context *ctx)
{
struct fd4_context *fd4_ctx = fd4_context(ctx);
struct fd_ringbuffer *ring = ctx->ring;
int i;
 
OUT_PKT0(ring, REG_A4XX_VSC_SIZE_ADDRESS, 1);
OUT_RELOCW(ring, fd4_ctx->vsc_size_mem, 0, 0, 0); /* VSC_SIZE_ADDRESS */
 
OUT_PKT0(ring, REG_A4XX_VSC_PIPE_CONFIG_REG(0), 8);
for (i = 0; i < 8; i++) {
struct fd_vsc_pipe *pipe = &ctx->pipe[i];
OUT_RING(ring, A4XX_VSC_PIPE_CONFIG_REG_X(pipe->x) |
A4XX_VSC_PIPE_CONFIG_REG_Y(pipe->y) |
A4XX_VSC_PIPE_CONFIG_REG_W(pipe->w) |
A4XX_VSC_PIPE_CONFIG_REG_H(pipe->h));
}
 
OUT_PKT0(ring, REG_A4XX_VSC_PIPE_DATA_ADDRESS_REG(0), 8);
for (i = 0; i < 8; i++) {
struct fd_vsc_pipe *pipe = &ctx->pipe[i];
if (!pipe->bo) {
pipe->bo = fd_bo_new(ctx->dev, 0x40000,
DRM_FREEDRENO_GEM_TYPE_KMEM);
}
OUT_RELOCW(ring, pipe->bo, 0, 0, 0); /* VSC_PIPE_DATA_ADDRESS[i] */
}
 
OUT_PKT0(ring, REG_A4XX_VSC_PIPE_DATA_LENGTH_REG(0), 8);
for (i = 0; i < 8; i++) {
struct fd_vsc_pipe *pipe = &ctx->pipe[i];
OUT_RING(ring, fd_bo_size(pipe->bo) - 32); /* VSC_PIPE_DATA_LENGTH[i] */
}
}
 
/* before first tile */
static void
fd4_emit_tile_init(struct fd_context *ctx)
{
struct fd_ringbuffer *ring = ctx->ring;
struct fd_gmem_stateobj *gmem = &ctx->gmem;
uint32_t rb_render_control;
 
fd4_emit_restore(ctx);
 
OUT_PKT0(ring, REG_A4XX_VSC_BIN_SIZE, 1);
OUT_RING(ring, A4XX_VSC_BIN_SIZE_WIDTH(gmem->bin_w) |
A4XX_VSC_BIN_SIZE_HEIGHT(gmem->bin_h));
 
OUT_PKT0(ring, REG_A4XX_RB_MODE_CONTROL, 1);
OUT_RING(ring, A4XX_RB_MODE_CONTROL_WIDTH(gmem->bin_w) |
A4XX_RB_MODE_CONTROL_HEIGHT(gmem->bin_h) |
0x00010000); /* XXX */
 
update_vsc_pipe(ctx);
patch_draws(ctx, IGNORE_VISIBILITY);
 
rb_render_control = 0; // XXX or BINNING_PASS.. but maybe we can emit only from gmem
patch_rbrc(ctx, rb_render_control);
}
 
/* before mem2gmem */
static void
fd4_emit_tile_prep(struct fd_context *ctx, struct fd_tile *tile)
{
struct fd_ringbuffer *ring = ctx->ring;
struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
struct fd_gmem_stateobj *gmem = &ctx->gmem;
uint32_t reg;
 
OUT_PKT0(ring, REG_A4XX_RB_DEPTH_INFO, 3);
reg = A4XX_RB_DEPTH_INFO_DEPTH_BASE(depth_base(ctx));
if (pfb->zsbuf) {
reg |= A4XX_RB_DEPTH_INFO_DEPTH_FORMAT(fd4_pipe2depth(pfb->zsbuf->format));
}
OUT_RING(ring, reg);
if (pfb->zsbuf) {
uint32_t cpp = util_format_get_blocksize(pfb->zsbuf->format);
OUT_RING(ring, A4XX_RB_DEPTH_PITCH(cpp * gmem->bin_w));
OUT_RING(ring, A4XX_RB_DEPTH_PITCH2(cpp * gmem->bin_w));
} else {
OUT_RING(ring, 0x00000000);
OUT_RING(ring, 0x00000000);
}
 
OUT_PKT0(ring, REG_A4XX_GRAS_DEPTH_CONTROL, 1);
if (pfb->zsbuf) {
OUT_RING(ring, A4XX_GRAS_DEPTH_CONTROL_FORMAT(
fd4_pipe2depth(pfb->zsbuf->format)));
} else {
OUT_RING(ring, A4XX_GRAS_DEPTH_CONTROL_FORMAT(DEPTH4_NONE));
}
 
if (ctx->needs_rb_fbd) {
fd_wfi(ctx, ring);
OUT_PKT0(ring, REG_A4XX_RB_FRAME_BUFFER_DIMENSION, 1);
OUT_RING(ring, A4XX_RB_FRAME_BUFFER_DIMENSION_WIDTH(pfb->width) |
A4XX_RB_FRAME_BUFFER_DIMENSION_HEIGHT(pfb->height));
ctx->needs_rb_fbd = false;
}
}
 
/* before IB to rendering cmds: */
static void
fd4_emit_tile_renderprep(struct fd_context *ctx, struct fd_tile *tile)
{
struct fd_ringbuffer *ring = ctx->ring;
struct fd_gmem_stateobj *gmem = &ctx->gmem;
struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
 
uint32_t x1 = tile->xoff;
uint32_t y1 = tile->yoff;
uint32_t x2 = tile->xoff + tile->bin_w - 1;
uint32_t y2 = tile->yoff + tile->bin_h - 1;
 
OUT_PKT3(ring, CP_SET_BIN, 3);
OUT_RING(ring, 0x00000000);
OUT_RING(ring, CP_SET_BIN_1_X1(x1) | CP_SET_BIN_1_Y1(y1));
OUT_RING(ring, CP_SET_BIN_2_X2(x2) | CP_SET_BIN_2_Y2(y2));
 
emit_mrt(ring, pfb->nr_cbufs, pfb->cbufs, NULL, gmem->bin_w);
 
/* setup scissor/offset for current tile: */
OUT_PKT0(ring, REG_A4XX_RB_BIN_OFFSET, 1);
OUT_RING(ring, A4XX_RB_BIN_OFFSET_X(tile->xoff) |
A4XX_RB_BIN_OFFSET_Y(tile->yoff));
 
OUT_PKT0(ring, REG_A4XX_GRAS_SC_SCREEN_SCISSOR_TL, 2);
OUT_RING(ring, A4XX_GRAS_SC_SCREEN_SCISSOR_TL_X(x1) |
A4XX_GRAS_SC_SCREEN_SCISSOR_TL_Y(y1));
OUT_RING(ring, A4XX_GRAS_SC_SCREEN_SCISSOR_BR_X(x2) |
A4XX_GRAS_SC_SCREEN_SCISSOR_BR_Y(y2));
}
 
void
fd4_gmem_init(struct pipe_context *pctx)
{
struct fd_context *ctx = fd_context(pctx);
 
ctx->emit_sysmem_prep = fd4_emit_sysmem_prep;
ctx->emit_tile_init = fd4_emit_tile_init;
ctx->emit_tile_prep = fd4_emit_tile_prep;
ctx->emit_tile_mem2gmem = fd4_emit_tile_mem2gmem;
ctx->emit_tile_renderprep = fd4_emit_tile_renderprep;
ctx->emit_tile_gmem2mem = fd4_emit_tile_gmem2mem;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a4xx/fd4_gmem.h
0,0 → 1,36
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FD4_GMEM_H_
#define FD4_GMEM_H_
 
#include "pipe/p_context.h"
 
void fd4_gmem_init(struct pipe_context *pctx);
 
#endif /* FD4_GMEM_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a4xx/fd4_program.c
0,0 → 1,548
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "pipe/p_state.h"
#include "util/u_string.h"
#include "util/u_memory.h"
#include "util/u_inlines.h"
#include "util/u_format.h"
#include "tgsi/tgsi_dump.h"
#include "tgsi/tgsi_parse.h"
 
#include "freedreno_program.h"
 
#include "fd4_program.h"
#include "fd4_emit.h"
#include "fd4_texture.h"
#include "fd4_format.h"
 
static void
delete_shader_stateobj(struct fd4_shader_stateobj *so)
{
ir3_shader_destroy(so->shader);
free(so);
}
 
static struct fd4_shader_stateobj *
create_shader_stateobj(struct pipe_context *pctx, const struct pipe_shader_state *cso,
enum shader_t type)
{
struct fd4_shader_stateobj *so = CALLOC_STRUCT(fd4_shader_stateobj);
so->shader = ir3_shader_create(pctx, cso->tokens, type);
return so;
}
 
static void *
fd4_fp_state_create(struct pipe_context *pctx,
const struct pipe_shader_state *cso)
{
return create_shader_stateobj(pctx, cso, SHADER_FRAGMENT);
}
 
static void
fd4_fp_state_delete(struct pipe_context *pctx, void *hwcso)
{
struct fd4_shader_stateobj *so = hwcso;
delete_shader_stateobj(so);
}
 
static void *
fd4_vp_state_create(struct pipe_context *pctx,
const struct pipe_shader_state *cso)
{
return create_shader_stateobj(pctx, cso, SHADER_VERTEX);
}
 
static void
fd4_vp_state_delete(struct pipe_context *pctx, void *hwcso)
{
struct fd4_shader_stateobj *so = hwcso;
delete_shader_stateobj(so);
}
 
static void
emit_shader(struct fd_ringbuffer *ring, const struct ir3_shader_variant *so)
{
const struct ir3_info *si = &so->info;
enum adreno_state_block sb;
enum adreno_state_src src;
uint32_t i, sz, *bin;
 
if (so->type == SHADER_VERTEX) {
sb = SB_VERT_SHADER;
} else {
sb = SB_FRAG_SHADER;
}
 
if (fd_mesa_debug & FD_DBG_DIRECT) {
sz = si->sizedwords;
src = SS_DIRECT;
bin = fd_bo_map(so->bo);
} else {
sz = 0;
src = 2; // enums different on a4xx..
bin = NULL;
}
 
OUT_PKT3(ring, CP_LOAD_STATE, 2 + sz);
OUT_RING(ring, CP_LOAD_STATE_0_DST_OFF(0) |
CP_LOAD_STATE_0_STATE_SRC(src) |
CP_LOAD_STATE_0_STATE_BLOCK(sb) |
CP_LOAD_STATE_0_NUM_UNIT(so->instrlen));
if (bin) {
OUT_RING(ring, CP_LOAD_STATE_1_EXT_SRC_ADDR(0) |
CP_LOAD_STATE_1_STATE_TYPE(ST_SHADER));
} else {
OUT_RELOC(ring, so->bo, 0,
CP_LOAD_STATE_1_STATE_TYPE(ST_SHADER), 0);
}
for (i = 0; i < sz; i++) {
OUT_RING(ring, bin[i]);
}
}
 
struct stage {
const struct ir3_shader_variant *v;
const struct ir3_info *i;
/* const sizes are in units of 4 * vec4 */
uint8_t constoff;
uint8_t constlen;
/* instr sizes are in units of 16 instructions */
uint8_t instroff;
uint8_t instrlen;
};
 
enum {
VS = 0,
FS = 1,
HS = 2,
DS = 3,
GS = 4,
MAX_STAGES
};
 
static void
setup_stages(struct fd4_emit *emit, struct stage *s)
{
unsigned i;
 
s[VS].v = fd4_emit_get_vp(emit);
 
if (emit->key.binning_pass) {
/* use dummy stateobj to simplify binning vs non-binning: */
static const struct ir3_shader_variant binning_fp = {};
s[FS].v = &binning_fp;
} else {
s[FS].v = fd4_emit_get_fp(emit);
}
 
s[HS].v = s[DS].v = s[GS].v = NULL; /* for now */
 
for (i = 0; i < MAX_STAGES; i++) {
if (s[i].v) {
s[i].i = &s[i].v->info;
/* constlen is in units of 4 * vec4: */
s[i].constlen = align(s[i].v->constlen, 4) / 4;
/* instrlen is already in units of 16 instr.. although
* probably we should ditch that and not make the compiler
* care about instruction group size of a3xx vs a4xx
*/
s[i].instrlen = s[i].v->instrlen;
} else {
s[i].i = NULL;
s[i].constlen = 0;
s[i].instrlen = 0;
}
}
 
/* NOTE: at least for gles2, blob partitions VS at bottom of const
* space and FS taking entire remaining space. We probably don't
* need to do that the same way, but for now mimic what the blob
* does to make it easier to diff against register values from blob
*
* NOTE: if VS.instrlen + FS.instrlen > 64, then one or both shaders
* is run from external memory.
*/
if ((s[VS].instrlen + s[FS].instrlen) > 64) {
/* prioritize FS for internal memory: */
if (s[FS].instrlen < 64) {
/* if FS can fit, kick VS out to external memory: */
s[VS].instrlen = 0;
} else if (s[VS].instrlen < 64) {
/* otherwise if VS can fit, kick out FS: */
s[FS].instrlen = 0;
} else {
/* neither can fit, run both from external memory: */
s[VS].instrlen = 0;
s[FS].instrlen = 0;
}
}
s[VS].constlen = 66;
s[FS].constlen = 128 - s[VS].constlen;
s[VS].instroff = 0;
s[VS].constoff = 0;
s[FS].instroff = 64 - s[FS].instrlen;
s[FS].constoff = s[VS].constlen;
s[HS].instroff = s[DS].instroff = s[GS].instroff = s[FS].instroff;
s[HS].constoff = s[DS].constoff = s[GS].constoff = s[FS].constoff;
}
 
void
fd4_program_emit(struct fd_ringbuffer *ring, struct fd4_emit *emit)
{
struct stage s[MAX_STAGES];
uint32_t pos_regid, posz_regid, psize_regid, color_regid;
uint32_t face_regid, coord_regid, zwcoord_regid;
int constmode;
int i, j, k;
 
setup_stages(emit, s);
 
/* blob seems to always use constmode currently: */
constmode = 1;
 
pos_regid = ir3_find_output_regid(s[VS].v,
ir3_semantic_name(TGSI_SEMANTIC_POSITION, 0));
posz_regid = ir3_find_output_regid(s[FS].v,
ir3_semantic_name(TGSI_SEMANTIC_POSITION, 0));
psize_regid = ir3_find_output_regid(s[VS].v,
ir3_semantic_name(TGSI_SEMANTIC_PSIZE, 0));
color_regid = ir3_find_output_regid(s[FS].v,
ir3_semantic_name(TGSI_SEMANTIC_COLOR, 0));
 
if (util_format_is_alpha(emit->pformat))
color_regid += 3;
 
/* TODO get these dynamically: */
face_regid = s[FS].v->frag_face ? regid(0,0) : regid(63,0);
coord_regid = s[FS].v->frag_coord ? regid(0,0) : regid(63,0);
zwcoord_regid = s[FS].v->frag_coord ? regid(0,2) : regid(63,0);
 
/* we could probably divide this up into things that need to be
* emitted if frag-prog is dirty vs if vert-prog is dirty..
*/
 
OUT_PKT0(ring, REG_A4XX_HLSQ_UPDATE_CONTROL, 1);
OUT_RING(ring, 0x00000003);
 
OUT_PKT0(ring, REG_A4XX_HLSQ_CONTROL_0_REG, 5);
OUT_RING(ring, A4XX_HLSQ_CONTROL_0_REG_FSTHREADSIZE(FOUR_QUADS) |
A4XX_HLSQ_CONTROL_0_REG_CONSTMODE(constmode) |
A4XX_HLSQ_CONTROL_0_REG_FSSUPERTHREADENABLE |
/* NOTE: I guess SHADERRESTART and CONSTFULLUPDATE maybe
* flush some caches? I think we only need to set those
* bits if we have updated const or shader..
*/
A4XX_HLSQ_CONTROL_0_REG_SPSHADERRESTART |
A4XX_HLSQ_CONTROL_0_REG_SPCONSTFULLUPDATE);
OUT_RING(ring, A4XX_HLSQ_CONTROL_1_REG_VSTHREADSIZE(TWO_QUADS) |
A4XX_HLSQ_CONTROL_1_REG_VSSUPERTHREADENABLE |
A4XX_HLSQ_CONTROL_1_REG_COORDREGID(coord_regid) |
A4XX_HLSQ_CONTROL_1_REG_ZWCOORDREGID(zwcoord_regid));
OUT_RING(ring, A4XX_HLSQ_CONTROL_2_REG_PRIMALLOCTHRESHOLD(63) |
0x3f3f000 | /* XXX */
A4XX_HLSQ_CONTROL_2_REG_FACEREGID(face_regid));
OUT_RING(ring, A4XX_HLSQ_CONTROL_3_REG_REGID(s[FS].v->pos_regid) |
0xfcfcfc00);
OUT_RING(ring, 0x00fcfcfc); /* XXX HLSQ_CONTROL_4 */
 
OUT_PKT0(ring, REG_A4XX_HLSQ_VS_CONTROL_REG, 5);
OUT_RING(ring, A4XX_HLSQ_VS_CONTROL_REG_CONSTLENGTH(s[VS].constlen) |
A4XX_HLSQ_VS_CONTROL_REG_CONSTOBJECTOFFSET(s[VS].constoff) |
A4XX_HLSQ_VS_CONTROL_REG_INSTRLENGTH(s[VS].instrlen) |
A4XX_HLSQ_VS_CONTROL_REG_SHADEROBJOFFSET(s[VS].instroff));
OUT_RING(ring, A4XX_HLSQ_FS_CONTROL_REG_CONSTLENGTH(s[FS].constlen) |
A4XX_HLSQ_FS_CONTROL_REG_CONSTOBJECTOFFSET(s[FS].constoff) |
A4XX_HLSQ_FS_CONTROL_REG_INSTRLENGTH(s[FS].instrlen) |
A4XX_HLSQ_FS_CONTROL_REG_SHADEROBJOFFSET(s[FS].instroff));
OUT_RING(ring, A4XX_HLSQ_HS_CONTROL_REG_CONSTLENGTH(s[HS].constlen) |
A4XX_HLSQ_HS_CONTROL_REG_CONSTOBJECTOFFSET(s[HS].constoff) |
A4XX_HLSQ_HS_CONTROL_REG_INSTRLENGTH(s[HS].instrlen) |
A4XX_HLSQ_HS_CONTROL_REG_SHADEROBJOFFSET(s[HS].instroff));
OUT_RING(ring, A4XX_HLSQ_DS_CONTROL_REG_CONSTLENGTH(s[DS].constlen) |
A4XX_HLSQ_DS_CONTROL_REG_CONSTOBJECTOFFSET(s[DS].constoff) |
A4XX_HLSQ_DS_CONTROL_REG_INSTRLENGTH(s[DS].instrlen) |
A4XX_HLSQ_DS_CONTROL_REG_SHADEROBJOFFSET(s[DS].instroff));
OUT_RING(ring, A4XX_HLSQ_GS_CONTROL_REG_CONSTLENGTH(s[GS].constlen) |
A4XX_HLSQ_GS_CONTROL_REG_CONSTOBJECTOFFSET(s[GS].constoff) |
A4XX_HLSQ_GS_CONTROL_REG_INSTRLENGTH(s[GS].instrlen) |
A4XX_HLSQ_GS_CONTROL_REG_SHADEROBJOFFSET(s[GS].instroff));
 
OUT_PKT0(ring, REG_A4XX_SP_SP_CTRL_REG, 1);
OUT_RING(ring, 0x140010 | /* XXX */
COND(emit->key.binning_pass, A4XX_SP_SP_CTRL_REG_BINNING_PASS));
 
OUT_PKT0(ring, REG_A4XX_SP_INSTR_CACHE_CTRL, 1);
OUT_RING(ring, 0x7f | /* XXX */
COND(s[VS].instrlen, A4XX_SP_INSTR_CACHE_CTRL_VS_BUFFER) |
COND(s[FS].instrlen, A4XX_SP_INSTR_CACHE_CTRL_FS_BUFFER) |
COND(s[VS].instrlen && s[FS].instrlen,
A4XX_SP_INSTR_CACHE_CTRL_INSTR_BUFFER));
 
OUT_PKT0(ring, REG_A4XX_SP_VS_LENGTH_REG, 1);
OUT_RING(ring, s[VS].v->instrlen); /* SP_VS_LENGTH_REG */
 
OUT_PKT0(ring, REG_A4XX_SP_VS_CTRL_REG0, 3);
OUT_RING(ring, A4XX_SP_VS_CTRL_REG0_THREADMODE(MULTI) |
A4XX_SP_VS_CTRL_REG0_HALFREGFOOTPRINT(s[VS].i->max_half_reg + 1) |
A4XX_SP_VS_CTRL_REG0_FULLREGFOOTPRINT(s[VS].i->max_reg + 1) |
A4XX_SP_VS_CTRL_REG0_INOUTREGOVERLAP(0) |
A4XX_SP_VS_CTRL_REG0_THREADSIZE(TWO_QUADS) |
A4XX_SP_VS_CTRL_REG0_SUPERTHREADMODE |
COND(s[VS].v->has_samp, A4XX_SP_VS_CTRL_REG0_PIXLODENABLE));
OUT_RING(ring, A4XX_SP_VS_CTRL_REG1_CONSTLENGTH(s[VS].constlen) |
A4XX_SP_VS_CTRL_REG1_INITIALOUTSTANDING(s[VS].v->total_in));
OUT_RING(ring, A4XX_SP_VS_PARAM_REG_POSREGID(pos_regid) |
A4XX_SP_VS_PARAM_REG_PSIZEREGID(psize_regid) |
A4XX_SP_VS_PARAM_REG_TOTALVSOUTVAR(align(s[FS].v->total_in, 4) / 4));
 
for (i = 0, j = -1; (i < 16) && (j < (int)s[FS].v->inputs_count); i++) {
uint32_t reg = 0;
 
OUT_PKT0(ring, REG_A4XX_SP_VS_OUT_REG(i), 1);
 
j = ir3_next_varying(s[FS].v, j);
if (j < s[FS].v->inputs_count) {
k = ir3_find_output(s[VS].v, s[FS].v->inputs[j].semantic);
reg |= A4XX_SP_VS_OUT_REG_A_REGID(s[VS].v->outputs[k].regid);
reg |= A4XX_SP_VS_OUT_REG_A_COMPMASK(s[FS].v->inputs[j].compmask);
}
 
j = ir3_next_varying(s[FS].v, j);
if (j < s[FS].v->inputs_count) {
k = ir3_find_output(s[VS].v, s[FS].v->inputs[j].semantic);
reg |= A4XX_SP_VS_OUT_REG_B_REGID(s[VS].v->outputs[k].regid);
reg |= A4XX_SP_VS_OUT_REG_B_COMPMASK(s[FS].v->inputs[j].compmask);
}
 
OUT_RING(ring, reg);
}
 
for (i = 0, j = -1; (i < 8) && (j < (int)s[FS].v->inputs_count); i++) {
uint32_t reg = 0;
 
OUT_PKT0(ring, REG_A4XX_SP_VS_VPC_DST_REG(i), 1);
 
j = ir3_next_varying(s[FS].v, j);
if (j < s[FS].v->inputs_count)
reg |= A4XX_SP_VS_VPC_DST_REG_OUTLOC0(s[FS].v->inputs[j].inloc);
j = ir3_next_varying(s[FS].v, j);
if (j < s[FS].v->inputs_count)
reg |= A4XX_SP_VS_VPC_DST_REG_OUTLOC1(s[FS].v->inputs[j].inloc);
j = ir3_next_varying(s[FS].v, j);
if (j < s[FS].v->inputs_count)
reg |= A4XX_SP_VS_VPC_DST_REG_OUTLOC2(s[FS].v->inputs[j].inloc);
j = ir3_next_varying(s[FS].v, j);
if (j < s[FS].v->inputs_count)
reg |= A4XX_SP_VS_VPC_DST_REG_OUTLOC3(s[FS].v->inputs[j].inloc);
 
OUT_RING(ring, reg);
}
 
OUT_PKT0(ring, REG_A4XX_SP_VS_OBJ_OFFSET_REG, 2);
OUT_RING(ring, A4XX_SP_VS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET(s[VS].constoff) |
A4XX_SP_VS_OBJ_OFFSET_REG_SHADEROBJOFFSET(s[VS].instroff));
OUT_RELOC(ring, s[VS].v->bo, 0, 0, 0); /* SP_VS_OBJ_START_REG */
 
OUT_PKT0(ring, REG_A4XX_SP_FS_LENGTH_REG, 1);
OUT_RING(ring, s[FS].v->instrlen); /* SP_FS_LENGTH_REG */
 
OUT_PKT0(ring, REG_A4XX_SP_FS_CTRL_REG0, 2);
OUT_RING(ring, A4XX_SP_FS_CTRL_REG0_THREADMODE(MULTI) |
COND(s[FS].v->total_in > 0, A4XX_SP_FS_CTRL_REG0_VARYING) |
A4XX_SP_FS_CTRL_REG0_HALFREGFOOTPRINT(s[FS].i->max_half_reg + 1) |
A4XX_SP_FS_CTRL_REG0_FULLREGFOOTPRINT(s[FS].i->max_reg + 1) |
A4XX_SP_FS_CTRL_REG0_INOUTREGOVERLAP(1) |
A4XX_SP_FS_CTRL_REG0_THREADSIZE(FOUR_QUADS) |
A4XX_SP_FS_CTRL_REG0_SUPERTHREADMODE |
COND(s[FS].v->has_samp, A4XX_SP_FS_CTRL_REG0_PIXLODENABLE));
OUT_RING(ring, A4XX_SP_FS_CTRL_REG1_CONSTLENGTH(s[FS].constlen) |
0x80000000 | /* XXX */
COND(s[FS].v->frag_face, A4XX_SP_FS_CTRL_REG1_FACENESS) |
COND(s[FS].v->total_in > 0, A4XX_SP_FS_CTRL_REG1_VARYING) |
COND(s[FS].v->frag_coord, A4XX_SP_FS_CTRL_REG1_FRAGCOORD));
 
OUT_PKT0(ring, REG_A4XX_SP_FS_OBJ_OFFSET_REG, 2);
OUT_RING(ring, A4XX_SP_FS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET(s[FS].constoff) |
A4XX_SP_FS_OBJ_OFFSET_REG_SHADEROBJOFFSET(s[FS].instroff));
if (emit->key.binning_pass)
OUT_RING(ring, 0x00000000);
else
OUT_RELOC(ring, s[FS].v->bo, 0, 0, 0); /* SP_FS_OBJ_START_REG */
 
OUT_PKT0(ring, REG_A4XX_SP_HS_OBJ_OFFSET_REG, 1);
OUT_RING(ring, A4XX_SP_HS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET(s[HS].constoff) |
A4XX_SP_HS_OBJ_OFFSET_REG_SHADEROBJOFFSET(s[HS].instroff));
 
OUT_PKT0(ring, REG_A4XX_SP_DS_OBJ_OFFSET_REG, 1);
OUT_RING(ring, A4XX_SP_DS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET(s[DS].constoff) |
A4XX_SP_DS_OBJ_OFFSET_REG_SHADEROBJOFFSET(s[DS].instroff));
 
OUT_PKT0(ring, REG_A4XX_SP_GS_OBJ_OFFSET_REG, 1);
OUT_RING(ring, A4XX_SP_GS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET(s[GS].constoff) |
A4XX_SP_GS_OBJ_OFFSET_REG_SHADEROBJOFFSET(s[GS].instroff));
 
OUT_PKT0(ring, REG_A4XX_RB_RENDER_CONTROL2, 1);
OUT_RING(ring, A4XX_RB_RENDER_CONTROL2_MSAA_SAMPLES(0) |
COND(s[FS].v->total_in > 0, A4XX_RB_RENDER_CONTROL2_VARYING) |
COND(s[FS].v->frag_face, A4XX_RB_RENDER_CONTROL2_FACENESS) |
COND(s[FS].v->frag_coord, A4XX_RB_RENDER_CONTROL2_XCOORD |
A4XX_RB_RENDER_CONTROL2_YCOORD |
// TODO enabling gl_FragCoord.z is causing lockups on 0ad (but seems
// to work everywhere else).
// A4XX_RB_RENDER_CONTROL2_ZCOORD |
A4XX_RB_RENDER_CONTROL2_WCOORD));
 
OUT_PKT0(ring, REG_A4XX_RB_FS_OUTPUT_REG, 1);
OUT_RING(ring, A4XX_RB_FS_OUTPUT_REG_MRT(1) |
COND(s[FS].v->writes_pos, A4XX_RB_FS_OUTPUT_REG_FRAG_WRITES_Z));
 
OUT_PKT0(ring, REG_A4XX_SP_FS_OUTPUT_REG, 1);
if (s[FS].v->writes_pos) {
OUT_RING(ring, 0x00000001 |
A4XX_SP_FS_OUTPUT_REG_DEPTH_ENABLE |
A4XX_SP_FS_OUTPUT_REG_DEPTH_REGID(posz_regid));
} else {
OUT_RING(ring, 0x00000001);
}
 
OUT_PKT0(ring, REG_A4XX_SP_FS_MRT_REG(0), 8);
OUT_RING(ring, A4XX_SP_FS_MRT_REG_REGID(color_regid) |
A4XX_SP_FS_MRT_REG_MRTFORMAT(emit->format) |
COND(emit->key.half_precision, A4XX_SP_FS_MRT_REG_HALF_PRECISION));
OUT_RING(ring, A4XX_SP_FS_MRT_REG_REGID(0));
OUT_RING(ring, A4XX_SP_FS_MRT_REG_REGID(0));
OUT_RING(ring, A4XX_SP_FS_MRT_REG_REGID(0));
OUT_RING(ring, A4XX_SP_FS_MRT_REG_REGID(0));
OUT_RING(ring, A4XX_SP_FS_MRT_REG_REGID(0));
OUT_RING(ring, A4XX_SP_FS_MRT_REG_REGID(0));
OUT_RING(ring, A4XX_SP_FS_MRT_REG_REGID(0));
 
if (emit->key.binning_pass) {
OUT_PKT0(ring, REG_A4XX_VPC_ATTR, 2);
OUT_RING(ring, A4XX_VPC_ATTR_THRDASSIGN(1) |
0x40000000 | /* XXX */
COND(s[VS].v->writes_psize, A4XX_VPC_ATTR_PSIZE));
OUT_RING(ring, 0x00000000);
} else {
uint32_t vinterp[8], flatshade[2];
 
memset(vinterp, 0, sizeof(vinterp));
memset(flatshade, 0, sizeof(flatshade));
 
/* looks like we need to do int varyings in the frag
* shader on a4xx (no flatshad reg? or a420.0 bug?):
*
* (sy)(ss)nop
* (sy)ldlv.u32 r0.x,l[r0.x], 1
* ldlv.u32 r0.y,l[r0.x+1], 1
* (ss)bary.f (ei)r63.x, 0, r0.x
* (ss)(rpt1)cov.s32f16 hr0.x, (r)r0.x
* (rpt5)nop
* sam (f16)(xyzw)hr0.x, hr0.x, s#0, t#0
*
* Possibly on later a4xx variants we'll be able to use
* something like the code below instead of workaround
* in the shader:
*/
#if 0
/* figure out VARYING_INTERP / FLAT_SHAD register values: */
for (j = -1; (j = ir3_next_varying(s[FS].v, j)) < (int)s[FS].v->inputs_count; ) {
uint32_t interp = s[FS].v->inputs[j].interpolate;
if ((interp == TGSI_INTERPOLATE_CONSTANT) ||
((interp == TGSI_INTERPOLATE_COLOR) && emit->rasterflat)) {
/* TODO might be cleaner to just +8 in SP_VS_VPC_DST_REG
* instead.. rather than -8 everywhere else..
*/
uint32_t loc = s[FS].v->inputs[j].inloc - 8;
 
/* currently assuming varyings aligned to 4 (not
* packed):
*/
debug_assert((loc % 4) == 0);
 
for (i = 0; i < 4; i++, loc++) {
vinterp[loc / 16] |= 1 << ((loc % 16) * 2);
flatshade[loc / 32] |= 1 << (loc % 32);
}
}
}
#endif
 
OUT_PKT0(ring, REG_A4XX_VPC_ATTR, 2);
OUT_RING(ring, A4XX_VPC_ATTR_TOTALATTR(s[FS].v->total_in) |
A4XX_VPC_ATTR_THRDASSIGN(1) |
COND(s[FS].v->total_in > 0, A4XX_VPC_ATTR_ENABLE) |
0x40000000 | /* XXX */
COND(s[VS].v->writes_psize, A4XX_VPC_ATTR_PSIZE));
OUT_RING(ring, A4XX_VPC_PACK_NUMFPNONPOSVAR(s[FS].v->total_in) |
A4XX_VPC_PACK_NUMNONPOSVSVAR(s[FS].v->total_in));
 
OUT_PKT0(ring, REG_A4XX_VPC_VARYING_INTERP_MODE(0), 8);
for (i = 0; i < 8; i++)
OUT_RING(ring, vinterp[i]); /* VPC_VARYING_INTERP[i].MODE */
 
OUT_PKT0(ring, REG_A4XX_VPC_VARYING_PS_REPL_MODE(0), 8);
for (i = 0; i < 8; i++)
OUT_RING(ring, s[FS].v->shader->vpsrepl[i]); /* VPC_VARYING_PS_REPL[i] */
}
 
if (s[VS].instrlen)
emit_shader(ring, s[VS].v);
 
if (!emit->key.binning_pass)
if (s[FS].instrlen)
emit_shader(ring, s[FS].v);
}
 
/* hack.. until we figure out how to deal w/ vpsrepl properly.. */
static void
fix_blit_fp(struct pipe_context *pctx)
{
struct fd_context *ctx = fd_context(pctx);
struct fd4_shader_stateobj *so = ctx->blit_prog[0].fp;
 
so->shader->vpsrepl[0] = 0x99999999;
so->shader->vpsrepl[1] = 0x99999999;
so->shader->vpsrepl[2] = 0x99999999;
so->shader->vpsrepl[3] = 0x99999999;
}
 
void
fd4_prog_init(struct pipe_context *pctx)
{
pctx->create_fs_state = fd4_fp_state_create;
pctx->delete_fs_state = fd4_fp_state_delete;
 
pctx->create_vs_state = fd4_vp_state_create;
pctx->delete_vs_state = fd4_vp_state_delete;
 
fd_prog_init(pctx);
 
fix_blit_fp(pctx);
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a4xx/fd4_program.h
0,0 → 1,46
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FD4_PROGRAM_H_
#define FD4_PROGRAM_H_
 
#include "pipe/p_context.h"
#include "freedreno_context.h"
#include "ir3_shader.h"
 
struct fd4_shader_stateobj {
struct ir3_shader *shader;
};
 
struct fd4_emit;
 
void fd4_program_emit(struct fd_ringbuffer *ring, struct fd4_emit *emit);
 
void fd4_prog_init(struct pipe_context *pctx);
 
#endif /* FD4_PROGRAM_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a4xx/fd4_query.c
0,0 → 1,39
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "freedreno_query_hw.h"
#include "freedreno_context.h"
#include "freedreno_util.h"
 
#include "fd4_query.h"
#include "fd4_format.h"
 
void fd4_query_context_init(struct pipe_context *pctx)
{
/* TODO */
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a4xx/fd4_query.h
0,0 → 1,36
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FD4_QUERY_H_
#define FD4_QUERY_H_
 
#include "pipe/p_context.h"
 
void fd4_query_context_init(struct pipe_context *pctx);
 
#endif /* FD4_QUERY_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a4xx/fd4_rasterizer.c
0,0 → 1,94
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
 
#include "pipe/p_state.h"
#include "util/u_string.h"
#include "util/u_memory.h"
 
#include "fd4_rasterizer.h"
#include "fd4_context.h"
#include "fd4_format.h"
 
void *
fd4_rasterizer_state_create(struct pipe_context *pctx,
const struct pipe_rasterizer_state *cso)
{
struct fd4_rasterizer_stateobj *so;
float psize_min, psize_max;
 
so = CALLOC_STRUCT(fd4_rasterizer_stateobj);
if (!so)
return NULL;
 
so->base = *cso;
 
if (cso->point_size_per_vertex) {
psize_min = util_get_min_point_size(cso);
psize_max = 8192;
} else {
/* Force the point size to be as if the vertex output was disabled. */
psize_min = cso->point_size;
psize_max = cso->point_size;
}
 
/*
if (cso->line_stipple_enable) {
??? TODO line stipple
}
TODO cso->half_pixel_center
if (cso->multisample)
TODO
*/
so->gras_cl_clip_cntl = 0x80000; /* ??? */
so->gras_su_point_minmax =
A4XX_GRAS_SU_POINT_MINMAX_MIN(psize_min/2) |
A4XX_GRAS_SU_POINT_MINMAX_MAX(psize_max/2);
so->gras_su_point_size = A4XX_GRAS_SU_POINT_SIZE(cso->point_size/2);
so->gras_su_poly_offset_scale =
A4XX_GRAS_SU_POLY_OFFSET_SCALE(cso->offset_scale);
so->gras_su_poly_offset_offset =
A4XX_GRAS_SU_POLY_OFFSET_OFFSET(cso->offset_units);
 
so->gras_su_mode_control =
A4XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH(cso->line_width/2.0);
 
if (cso->cull_face & PIPE_FACE_FRONT)
so->gras_su_mode_control |= A4XX_GRAS_SU_MODE_CONTROL_CULL_FRONT;
if (cso->cull_face & PIPE_FACE_BACK)
so->gras_su_mode_control |= A4XX_GRAS_SU_MODE_CONTROL_CULL_BACK;
if (!cso->front_ccw)
so->gras_su_mode_control |= A4XX_GRAS_SU_MODE_CONTROL_FRONT_CW;
if (!cso->flatshade_first)
so->pc_prim_vtx_cntl |= A4XX_PC_PRIM_VTX_CNTL_PROVOKING_VTX_LAST;
 
if (cso->offset_tri)
so->gras_su_mode_control |= A4XX_GRAS_SU_MODE_CONTROL_POLY_OFFSET;
 
return so;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a4xx/fd4_rasterizer.h
0,0 → 1,56
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FD4_RASTERIZER_H_
#define FD4_RASTERIZER_H_
 
#include "pipe/p_state.h"
#include "pipe/p_context.h"
 
struct fd4_rasterizer_stateobj {
struct pipe_rasterizer_state base;
uint32_t gras_su_point_minmax;
uint32_t gras_su_point_size;
uint32_t gras_su_poly_offset_scale;
uint32_t gras_su_poly_offset_offset;
 
uint32_t gras_su_mode_control;
uint32_t gras_cl_clip_cntl;
uint32_t pc_prim_vtx_cntl;
};
 
static INLINE struct fd4_rasterizer_stateobj *
fd4_rasterizer_stateobj(struct pipe_rasterizer_state *rast)
{
return (struct fd4_rasterizer_stateobj *)rast;
}
 
void * fd4_rasterizer_state_create(struct pipe_context *pctx,
const struct pipe_rasterizer_state *cso);
 
#endif /* FD4_RASTERIZER_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a4xx/fd4_screen.c
0,0 → 1,106
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "pipe/p_screen.h"
#include "util/u_format.h"
 
#include "fd4_screen.h"
#include "fd4_context.h"
#include "fd4_format.h"
 
static boolean
fd4_screen_is_format_supported(struct pipe_screen *pscreen,
enum pipe_format format,
enum pipe_texture_target target,
unsigned sample_count,
unsigned usage)
{
unsigned retval = 0;
 
if ((target >= PIPE_MAX_TEXTURE_TYPES) ||
(sample_count > 1) || /* TODO add MSAA */
!util_format_is_supported(format, usage)) {
DBG("not supported: format=%s, target=%d, sample_count=%d, usage=%x",
util_format_name(format), target, sample_count, usage);
return FALSE;
}
 
if ((usage & PIPE_BIND_VERTEX_BUFFER) &&
(fd4_pipe2vtx(format) != ~0)) {
retval |= PIPE_BIND_VERTEX_BUFFER;
}
 
if ((usage & PIPE_BIND_SAMPLER_VIEW) &&
(fd4_pipe2tex(format) != ~0)) {
retval |= PIPE_BIND_SAMPLER_VIEW;
}
 
if ((usage & (PIPE_BIND_RENDER_TARGET |
PIPE_BIND_DISPLAY_TARGET |
PIPE_BIND_SCANOUT |
PIPE_BIND_SHARED)) &&
(fd4_pipe2color(format) != ~0) &&
(fd4_pipe2tex(format) != ~0)) {
retval |= usage & (PIPE_BIND_RENDER_TARGET |
PIPE_BIND_DISPLAY_TARGET |
PIPE_BIND_SCANOUT |
PIPE_BIND_SHARED);
}
 
if ((usage & PIPE_BIND_DEPTH_STENCIL) &&
(fd4_pipe2depth(format) != ~0) &&
(fd4_pipe2tex(format) != ~0)) {
retval |= PIPE_BIND_DEPTH_STENCIL;
}
 
if ((usage & PIPE_BIND_INDEX_BUFFER) &&
(fd_pipe2index(format) != ~0)) {
retval |= PIPE_BIND_INDEX_BUFFER;
}
 
if (usage & PIPE_BIND_TRANSFER_READ)
retval |= PIPE_BIND_TRANSFER_READ;
if (usage & PIPE_BIND_TRANSFER_WRITE)
retval |= PIPE_BIND_TRANSFER_WRITE;
 
if (retval != usage) {
DBG("not supported: format=%s, target=%d, sample_count=%d, "
"usage=%x, retval=%x", util_format_name(format),
target, sample_count, usage, retval);
}
 
return retval == usage;
}
 
void
fd4_screen_init(struct pipe_screen *pscreen)
{
fd_screen(pscreen)->max_rts = 1;
pscreen->context_create = fd4_context_create;
pscreen->is_format_supported = fd4_screen_is_format_supported;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a4xx/fd4_screen.h
0,0 → 1,36
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FD4_SCREEN_H_
#define FD4_SCREEN_H_
 
#include "pipe/p_screen.h"
 
void fd4_screen_init(struct pipe_screen *pscreen);
 
#endif /* FD4_SCREEN_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a4xx/fd4_texture.c
0,0 → 1,247
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "pipe/p_state.h"
#include "util/u_string.h"
#include "util/u_memory.h"
#include "util/u_inlines.h"
#include "util/u_format.h"
 
#include "fd4_texture.h"
#include "fd4_format.h"
 
/* TODO do we need to emulate clamp-to-edge like a3xx? */
static enum a4xx_tex_clamp
tex_clamp(unsigned wrap)
{
/* hardware probably supports more, but we can't coax all the
* wrap/clamp modes out of the GLESv2 blob driver.
*
* TODO once we have basics working, go back and just try
* different values and see what happens
*/
switch (wrap) {
case PIPE_TEX_WRAP_REPEAT:
return A4XX_TEX_REPEAT;
case PIPE_TEX_WRAP_CLAMP:
case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
return A4XX_TEX_CLAMP_TO_EDGE;
case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
// TODO
// return A4XX_TEX_CLAMP_TO_BORDER;
case PIPE_TEX_WRAP_MIRROR_CLAMP:
case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
// TODO
// return A4XX_TEX_MIRROR_CLAMP;
case PIPE_TEX_WRAP_MIRROR_REPEAT:
return A4XX_TEX_MIRROR_REPEAT;
default:
DBG("invalid wrap: %u", wrap);
return 0;
}
}
 
static enum a4xx_tex_filter
tex_filter(unsigned filter, bool aniso)
{
switch (filter) {
case PIPE_TEX_FILTER_NEAREST:
return A4XX_TEX_NEAREST;
case PIPE_TEX_FILTER_LINEAR:
return aniso ? A4XX_TEX_ANISO : A4XX_TEX_LINEAR;
default:
DBG("invalid filter: %u", filter);
return 0;
}
}
 
static void *
fd4_sampler_state_create(struct pipe_context *pctx,
const struct pipe_sampler_state *cso)
{
struct fd4_sampler_stateobj *so = CALLOC_STRUCT(fd4_sampler_stateobj);
unsigned aniso = util_last_bit(MIN2(cso->max_anisotropy >> 1, 8));
bool miplinear = false;
 
if (!so)
return NULL;
 
if (cso->min_mip_filter == PIPE_TEX_MIPFILTER_LINEAR)
miplinear = true;
 
so->base = *cso;
 
so->texsamp0 =
COND(miplinear, A4XX_TEX_SAMP_0_MIPFILTER_LINEAR_NEAR) |
A4XX_TEX_SAMP_0_XY_MAG(tex_filter(cso->mag_img_filter, aniso)) |
A4XX_TEX_SAMP_0_XY_MIN(tex_filter(cso->min_img_filter, aniso)) |
A4XX_TEX_SAMP_0_ANISO(aniso) |
A4XX_TEX_SAMP_0_WRAP_S(tex_clamp(cso->wrap_s)) |
A4XX_TEX_SAMP_0_WRAP_T(tex_clamp(cso->wrap_t)) |
A4XX_TEX_SAMP_0_WRAP_R(tex_clamp(cso->wrap_r));
 
so->texsamp1 =
// COND(miplinear, A4XX_TEX_SAMP_1_MIPFILTER_LINEAR_FAR) |
COND(!cso->normalized_coords, A4XX_TEX_SAMP_1_UNNORM_COORDS);
 
if (cso->min_mip_filter != PIPE_TEX_MIPFILTER_NONE) {
so->texsamp1 |=
A4XX_TEX_SAMP_1_MIN_LOD(cso->min_lod) |
A4XX_TEX_SAMP_1_MAX_LOD(cso->max_lod);
}
 
if (cso->compare_mode)
so->texsamp1 |= A4XX_TEX_SAMP_1_COMPARE_FUNC(cso->compare_func); /* maps 1:1 */
 
return so;
}
 
static enum a4xx_tex_type
tex_type(unsigned target)
{
switch (target) {
default:
assert(0);
case PIPE_BUFFER:
case PIPE_TEXTURE_1D:
case PIPE_TEXTURE_1D_ARRAY:
return A4XX_TEX_1D;
case PIPE_TEXTURE_RECT:
case PIPE_TEXTURE_2D:
case PIPE_TEXTURE_2D_ARRAY:
return A4XX_TEX_2D;
case PIPE_TEXTURE_3D:
return A4XX_TEX_3D;
case PIPE_TEXTURE_CUBE:
case PIPE_TEXTURE_CUBE_ARRAY:
return A4XX_TEX_CUBE;
}
}
 
static struct pipe_sampler_view *
fd4_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc,
const struct pipe_sampler_view *cso)
{
struct fd4_pipe_sampler_view *so = CALLOC_STRUCT(fd4_pipe_sampler_view);
struct fd_resource *rsc = fd_resource(prsc);
unsigned lvl = cso->u.tex.first_level;
unsigned miplevels = cso->u.tex.last_level - lvl;
 
if (!so)
return NULL;
 
so->base = *cso;
pipe_reference(NULL, &prsc->reference);
so->base.texture = prsc;
so->base.reference.count = 1;
so->base.context = pctx;
 
so->texconst0 =
A4XX_TEX_CONST_0_TYPE(tex_type(prsc->target)) |
A4XX_TEX_CONST_0_FMT(fd4_pipe2tex(cso->format)) |
A4XX_TEX_CONST_0_MIPLVLS(miplevels) |
fd4_tex_swiz(cso->format, cso->swizzle_r, cso->swizzle_g,
cso->swizzle_b, cso->swizzle_a);
 
if (util_format_is_srgb(cso->format))
so->texconst0 |= A4XX_TEX_CONST_0_SRGB;
 
so->texconst1 =
A4XX_TEX_CONST_1_WIDTH(u_minify(prsc->width0, lvl)) |
A4XX_TEX_CONST_1_HEIGHT(u_minify(prsc->height0, lvl));
so->texconst2 =
A4XX_TEX_CONST_2_FETCHSIZE(fd4_pipe2fetchsize(cso->format)) |
A4XX_TEX_CONST_2_PITCH(rsc->slices[lvl].pitch * rsc->cpp);
 
switch (prsc->target) {
case PIPE_TEXTURE_1D_ARRAY:
case PIPE_TEXTURE_2D_ARRAY:
so->texconst3 =
A4XX_TEX_CONST_3_DEPTH(prsc->array_size) |
A4XX_TEX_CONST_3_LAYERSZ(rsc->layer_size);
break;
case PIPE_TEXTURE_CUBE:
case PIPE_TEXTURE_CUBE_ARRAY: /* ?? not sure about _CUBE_ARRAY */
so->texconst3 =
A4XX_TEX_CONST_3_DEPTH(1) |
A4XX_TEX_CONST_3_LAYERSZ(rsc->layer_size);
break;
case PIPE_TEXTURE_3D:
so->texconst3 =
A4XX_TEX_CONST_3_DEPTH(u_minify(prsc->depth0, lvl)) |
A4XX_TEX_CONST_3_LAYERSZ(rsc->slices[0].size0);
break;
default:
so->texconst3 = 0x00000000;
break;
}
 
return &so->base;
}
 
static void
fd4_set_sampler_views(struct pipe_context *pctx, unsigned shader,
unsigned start, unsigned nr, struct pipe_sampler_view **views)
{
struct fd_context *ctx = fd_context(pctx);
struct fd4_context *fd4_ctx = fd4_context(ctx);
struct fd_texture_stateobj *tex;
uint16_t integer_s = 0, *ptr;
int i;
 
fd_set_sampler_views(pctx, shader, start, nr, views);
 
switch (shader) {
case PIPE_SHADER_FRAGMENT:
tex = &ctx->fragtex;
ptr = &fd4_ctx->finteger_s;
break;
case PIPE_SHADER_VERTEX:
tex = &ctx->verttex;
ptr = &fd4_ctx->vinteger_s;
break;
default:
return;
}
 
for (i = 0; i < tex->num_textures; i++)
if (util_format_is_pure_integer(tex->textures[i]->format))
integer_s |= 1 << i;
 
*ptr = integer_s;
}
 
void
fd4_texture_init(struct pipe_context *pctx)
{
pctx->create_sampler_state = fd4_sampler_state_create;
pctx->bind_sampler_states = fd_sampler_states_bind;
pctx->create_sampler_view = fd4_sampler_view_create;
pctx->set_sampler_views = fd4_set_sampler_views;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a4xx/fd4_texture.h
0,0 → 1,67
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FD4_TEXTURE_H_
#define FD4_TEXTURE_H_
 
#include "pipe/p_context.h"
 
#include "freedreno_texture.h"
#include "freedreno_resource.h"
 
#include "fd4_context.h"
#include "fd4_format.h"
 
struct fd4_sampler_stateobj {
struct pipe_sampler_state base;
uint32_t texsamp0, texsamp1;
};
 
static INLINE struct fd4_sampler_stateobj *
fd4_sampler_stateobj(struct pipe_sampler_state *samp)
{
return (struct fd4_sampler_stateobj *)samp;
}
 
struct fd4_pipe_sampler_view {
struct pipe_sampler_view base;
uint32_t texconst0, texconst1, texconst2, texconst3, textconst4;
};
 
static INLINE struct fd4_pipe_sampler_view *
fd4_pipe_sampler_view(struct pipe_sampler_view *pview)
{
return (struct fd4_pipe_sampler_view *)pview;
}
 
unsigned fd4_get_const_idx(struct fd_context *ctx,
struct fd_texture_stateobj *tex, unsigned samp_id);
 
void fd4_texture_init(struct pipe_context *pctx);
 
#endif /* FD4_TEXTURE_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a4xx/fd4_zsa.c
0,0 → 1,109
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
 
#include "pipe/p_state.h"
#include "util/u_string.h"
#include "util/u_memory.h"
 
#include "fd4_zsa.h"
#include "fd4_context.h"
#include "fd4_format.h"
 
void *
fd4_zsa_state_create(struct pipe_context *pctx,
const struct pipe_depth_stencil_alpha_state *cso)
{
struct fd4_zsa_stateobj *so;
 
so = CALLOC_STRUCT(fd4_zsa_stateobj);
if (!so)
return NULL;
 
so->base = *cso;
 
so->rb_depth_control |=
A4XX_RB_DEPTH_CONTROL_ZFUNC(cso->depth.func); /* maps 1:1 */
 
if (cso->depth.enabled)
so->rb_depth_control |=
A4XX_RB_DEPTH_CONTROL_Z_ENABLE |
A4XX_RB_DEPTH_CONTROL_Z_TEST_ENABLE;
 
if (cso->depth.writemask)
so->rb_depth_control |= A4XX_RB_DEPTH_CONTROL_Z_WRITE_ENABLE;
 
if (cso->stencil[0].enabled) {
const struct pipe_stencil_state *s = &cso->stencil[0];
 
so->rb_stencil_control |=
A4XX_RB_STENCIL_CONTROL_STENCIL_READ |
A4XX_RB_STENCIL_CONTROL_STENCIL_ENABLE |
A4XX_RB_STENCIL_CONTROL_FUNC(s->func) | /* maps 1:1 */
A4XX_RB_STENCIL_CONTROL_FAIL(fd_stencil_op(s->fail_op)) |
A4XX_RB_STENCIL_CONTROL_ZPASS(fd_stencil_op(s->zpass_op)) |
A4XX_RB_STENCIL_CONTROL_ZFAIL(fd_stencil_op(s->zfail_op));
so->rb_stencil_control2 |=
A4XX_RB_STENCIL_CONTROL2_STENCIL_BUFFER;
so->rb_stencilrefmask |=
0xff000000 | /* ??? */
A4XX_RB_STENCILREFMASK_STENCILWRITEMASK(s->writemask) |
A4XX_RB_STENCILREFMASK_STENCILMASK(s->valuemask);
 
if (cso->stencil[1].enabled) {
const struct pipe_stencil_state *bs = &cso->stencil[1];
 
so->rb_stencil_control |=
A4XX_RB_STENCIL_CONTROL_STENCIL_ENABLE_BF |
A4XX_RB_STENCIL_CONTROL_FUNC_BF(bs->func) | /* maps 1:1 */
A4XX_RB_STENCIL_CONTROL_FAIL_BF(fd_stencil_op(bs->fail_op)) |
A4XX_RB_STENCIL_CONTROL_ZPASS_BF(fd_stencil_op(bs->zpass_op)) |
A4XX_RB_STENCIL_CONTROL_ZFAIL_BF(fd_stencil_op(bs->zfail_op));
so->rb_stencilrefmask_bf |=
0xff000000 | /* ??? */
A4XX_RB_STENCILREFMASK_BF_STENCILWRITEMASK(bs->writemask) |
A4XX_RB_STENCILREFMASK_BF_STENCILMASK(bs->valuemask);
}
}
 
if (cso->alpha.enabled) {
uint32_t ref = cso->alpha.ref_value * 255.0;
so->gras_alpha_control =
A4XX_GRAS_ALPHA_CONTROL_ALPHA_TEST_ENABLE;
so->rb_alpha_control =
A4XX_RB_ALPHA_CONTROL_ALPHA_TEST |
A4XX_RB_ALPHA_CONTROL_ALPHA_REF(ref) |
A4XX_RB_ALPHA_CONTROL_ALPHA_TEST_FUNC(cso->alpha.func);
so->rb_depth_control |=
A4XX_RB_DEPTH_CONTROL_EARLY_Z_DISABLE;
}
 
so->rb_render_control = 0x8; /* XXX */
 
return so;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/a4xx/fd4_zsa.h
0,0 → 1,59
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FD4_ZSA_H_
#define FD4_ZSA_H_
 
 
#include "pipe/p_state.h"
#include "pipe/p_context.h"
 
#include "freedreno_util.h"
 
struct fd4_zsa_stateobj {
struct pipe_depth_stencil_alpha_state base;
uint32_t gras_alpha_control;
uint32_t rb_alpha_control;
uint32_t rb_render_control;
uint32_t rb_depth_control;
uint32_t rb_stencil_control;
uint32_t rb_stencil_control2;
uint32_t rb_stencilrefmask;
uint32_t rb_stencilrefmask_bf;
};
 
static INLINE struct fd4_zsa_stateobj *
fd4_zsa_stateobj(struct pipe_depth_stencil_alpha_state *zsa)
{
return (struct fd4_zsa_stateobj *)zsa;
}
 
void * fd4_zsa_state_create(struct pipe_context *pctx,
const struct pipe_depth_stencil_alpha_state *cso);
 
#endif /* FD4_ZSA_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/adreno_common.xml.h
0,0 → 1,446
#ifndef ADRENO_COMMON_XML
#define ADRENO_COMMON_XML
 
/* Autogenerated file, DO NOT EDIT manually!
 
This file was generated by the rules-ng-ng headergen tool in this git repository:
http://github.com/freedreno/envytools/
git clone https://github.com/freedreno/envytools.git
 
The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml ( 364 bytes, from 2013-11-30 14:47:15)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32901 bytes, from 2014-06-02 15:21:30)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10551 bytes, from 2014-11-13 22:44:30)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 14895 bytes, from 2015-04-19 15:23:28)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 66709 bytes, from 2015-04-12 18:16:35)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 59314 bytes, from 2015-04-19 16:21:40)
 
Copyright (C) 2013-2014 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
 
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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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.
*/
 
 
enum adreno_pa_su_sc_draw {
PC_DRAW_POINTS = 0,
PC_DRAW_LINES = 1,
PC_DRAW_TRIANGLES = 2,
};
 
enum adreno_compare_func {
FUNC_NEVER = 0,
FUNC_LESS = 1,
FUNC_EQUAL = 2,
FUNC_LEQUAL = 3,
FUNC_GREATER = 4,
FUNC_NOTEQUAL = 5,
FUNC_GEQUAL = 6,
FUNC_ALWAYS = 7,
};
 
enum adreno_stencil_op {
STENCIL_KEEP = 0,
STENCIL_ZERO = 1,
STENCIL_REPLACE = 2,
STENCIL_INCR_CLAMP = 3,
STENCIL_DECR_CLAMP = 4,
STENCIL_INVERT = 5,
STENCIL_INCR_WRAP = 6,
STENCIL_DECR_WRAP = 7,
};
 
enum adreno_rb_blend_factor {
FACTOR_ZERO = 0,
FACTOR_ONE = 1,
FACTOR_SRC_COLOR = 4,
FACTOR_ONE_MINUS_SRC_COLOR = 5,
FACTOR_SRC_ALPHA = 6,
FACTOR_ONE_MINUS_SRC_ALPHA = 7,
FACTOR_DST_COLOR = 8,
FACTOR_ONE_MINUS_DST_COLOR = 9,
FACTOR_DST_ALPHA = 10,
FACTOR_ONE_MINUS_DST_ALPHA = 11,
FACTOR_CONSTANT_COLOR = 12,
FACTOR_ONE_MINUS_CONSTANT_COLOR = 13,
FACTOR_CONSTANT_ALPHA = 14,
FACTOR_ONE_MINUS_CONSTANT_ALPHA = 15,
FACTOR_SRC_ALPHA_SATURATE = 16,
};
 
enum adreno_rb_surface_endian {
ENDIAN_NONE = 0,
ENDIAN_8IN16 = 1,
ENDIAN_8IN32 = 2,
ENDIAN_16IN32 = 3,
ENDIAN_8IN64 = 4,
ENDIAN_8IN128 = 5,
};
 
enum adreno_rb_dither_mode {
DITHER_DISABLE = 0,
DITHER_ALWAYS = 1,
DITHER_IF_ALPHA_OFF = 2,
};
 
enum adreno_rb_depth_format {
DEPTHX_16 = 0,
DEPTHX_24_8 = 1,
DEPTHX_32 = 2,
};
 
enum adreno_rb_copy_control_mode {
RB_COPY_RESOLVE = 1,
RB_COPY_CLEAR = 2,
RB_COPY_DEPTH_STENCIL = 5,
};
 
enum a3xx_render_mode {
RB_RENDERING_PASS = 0,
RB_TILING_PASS = 1,
RB_RESOLVE_PASS = 2,
RB_COMPUTE_PASS = 3,
};
 
enum a3xx_msaa_samples {
MSAA_ONE = 0,
MSAA_TWO = 1,
MSAA_FOUR = 2,
};
 
enum a3xx_threadmode {
MULTI = 0,
SINGLE = 1,
};
 
enum a3xx_instrbuffermode {
CACHE = 0,
BUFFER = 1,
};
 
enum a3xx_threadsize {
TWO_QUADS = 0,
FOUR_QUADS = 1,
};
 
enum a3xx_color_swap {
WZYX = 0,
WXYZ = 1,
ZYXW = 2,
XYZW = 3,
};
 
#define REG_AXXX_CP_RB_BASE 0x000001c0
 
#define REG_AXXX_CP_RB_CNTL 0x000001c1
#define AXXX_CP_RB_CNTL_BUFSZ__MASK 0x0000003f
#define AXXX_CP_RB_CNTL_BUFSZ__SHIFT 0
static inline uint32_t AXXX_CP_RB_CNTL_BUFSZ(uint32_t val)
{
return ((val) << AXXX_CP_RB_CNTL_BUFSZ__SHIFT) & AXXX_CP_RB_CNTL_BUFSZ__MASK;
}
#define AXXX_CP_RB_CNTL_BLKSZ__MASK 0x00003f00
#define AXXX_CP_RB_CNTL_BLKSZ__SHIFT 8
static inline uint32_t AXXX_CP_RB_CNTL_BLKSZ(uint32_t val)
{
return ((val) << AXXX_CP_RB_CNTL_BLKSZ__SHIFT) & AXXX_CP_RB_CNTL_BLKSZ__MASK;
}
#define AXXX_CP_RB_CNTL_BUF_SWAP__MASK 0x00030000
#define AXXX_CP_RB_CNTL_BUF_SWAP__SHIFT 16
static inline uint32_t AXXX_CP_RB_CNTL_BUF_SWAP(uint32_t val)
{
return ((val) << AXXX_CP_RB_CNTL_BUF_SWAP__SHIFT) & AXXX_CP_RB_CNTL_BUF_SWAP__MASK;
}
#define AXXX_CP_RB_CNTL_POLL_EN 0x00100000
#define AXXX_CP_RB_CNTL_NO_UPDATE 0x08000000
#define AXXX_CP_RB_CNTL_RPTR_WR_EN 0x80000000
 
#define REG_AXXX_CP_RB_RPTR_ADDR 0x000001c3
#define AXXX_CP_RB_RPTR_ADDR_SWAP__MASK 0x00000003
#define AXXX_CP_RB_RPTR_ADDR_SWAP__SHIFT 0
static inline uint32_t AXXX_CP_RB_RPTR_ADDR_SWAP(uint32_t val)
{
return ((val) << AXXX_CP_RB_RPTR_ADDR_SWAP__SHIFT) & AXXX_CP_RB_RPTR_ADDR_SWAP__MASK;
}
#define AXXX_CP_RB_RPTR_ADDR_ADDR__MASK 0xfffffffc
#define AXXX_CP_RB_RPTR_ADDR_ADDR__SHIFT 2
static inline uint32_t AXXX_CP_RB_RPTR_ADDR_ADDR(uint32_t val)
{
return ((val >> 2) << AXXX_CP_RB_RPTR_ADDR_ADDR__SHIFT) & AXXX_CP_RB_RPTR_ADDR_ADDR__MASK;
}
 
#define REG_AXXX_CP_RB_RPTR 0x000001c4
 
#define REG_AXXX_CP_RB_WPTR 0x000001c5
 
#define REG_AXXX_CP_RB_WPTR_DELAY 0x000001c6
 
#define REG_AXXX_CP_RB_RPTR_WR 0x000001c7
 
#define REG_AXXX_CP_RB_WPTR_BASE 0x000001c8
 
#define REG_AXXX_CP_QUEUE_THRESHOLDS 0x000001d5
#define AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB1_START__MASK 0x0000000f
#define AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB1_START__SHIFT 0
static inline uint32_t AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB1_START(uint32_t val)
{
return ((val) << AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB1_START__SHIFT) & AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB1_START__MASK;
}
#define AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB2_START__MASK 0x00000f00
#define AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB2_START__SHIFT 8
static inline uint32_t AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB2_START(uint32_t val)
{
return ((val) << AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB2_START__SHIFT) & AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB2_START__MASK;
}
#define AXXX_CP_QUEUE_THRESHOLDS_CSQ_ST_START__MASK 0x000f0000
#define AXXX_CP_QUEUE_THRESHOLDS_CSQ_ST_START__SHIFT 16
static inline uint32_t AXXX_CP_QUEUE_THRESHOLDS_CSQ_ST_START(uint32_t val)
{
return ((val) << AXXX_CP_QUEUE_THRESHOLDS_CSQ_ST_START__SHIFT) & AXXX_CP_QUEUE_THRESHOLDS_CSQ_ST_START__MASK;
}
 
#define REG_AXXX_CP_MEQ_THRESHOLDS 0x000001d6
#define AXXX_CP_MEQ_THRESHOLDS_MEQ_END__MASK 0x001f0000
#define AXXX_CP_MEQ_THRESHOLDS_MEQ_END__SHIFT 16
static inline uint32_t AXXX_CP_MEQ_THRESHOLDS_MEQ_END(uint32_t val)
{
return ((val) << AXXX_CP_MEQ_THRESHOLDS_MEQ_END__SHIFT) & AXXX_CP_MEQ_THRESHOLDS_MEQ_END__MASK;
}
#define AXXX_CP_MEQ_THRESHOLDS_ROQ_END__MASK 0x1f000000
#define AXXX_CP_MEQ_THRESHOLDS_ROQ_END__SHIFT 24
static inline uint32_t AXXX_CP_MEQ_THRESHOLDS_ROQ_END(uint32_t val)
{
return ((val) << AXXX_CP_MEQ_THRESHOLDS_ROQ_END__SHIFT) & AXXX_CP_MEQ_THRESHOLDS_ROQ_END__MASK;
}
 
#define REG_AXXX_CP_CSQ_AVAIL 0x000001d7
#define AXXX_CP_CSQ_AVAIL_RING__MASK 0x0000007f
#define AXXX_CP_CSQ_AVAIL_RING__SHIFT 0
static inline uint32_t AXXX_CP_CSQ_AVAIL_RING(uint32_t val)
{
return ((val) << AXXX_CP_CSQ_AVAIL_RING__SHIFT) & AXXX_CP_CSQ_AVAIL_RING__MASK;
}
#define AXXX_CP_CSQ_AVAIL_IB1__MASK 0x00007f00
#define AXXX_CP_CSQ_AVAIL_IB1__SHIFT 8
static inline uint32_t AXXX_CP_CSQ_AVAIL_IB1(uint32_t val)
{
return ((val) << AXXX_CP_CSQ_AVAIL_IB1__SHIFT) & AXXX_CP_CSQ_AVAIL_IB1__MASK;
}
#define AXXX_CP_CSQ_AVAIL_IB2__MASK 0x007f0000
#define AXXX_CP_CSQ_AVAIL_IB2__SHIFT 16
static inline uint32_t AXXX_CP_CSQ_AVAIL_IB2(uint32_t val)
{
return ((val) << AXXX_CP_CSQ_AVAIL_IB2__SHIFT) & AXXX_CP_CSQ_AVAIL_IB2__MASK;
}
 
#define REG_AXXX_CP_STQ_AVAIL 0x000001d8
#define AXXX_CP_STQ_AVAIL_ST__MASK 0x0000007f
#define AXXX_CP_STQ_AVAIL_ST__SHIFT 0
static inline uint32_t AXXX_CP_STQ_AVAIL_ST(uint32_t val)
{
return ((val) << AXXX_CP_STQ_AVAIL_ST__SHIFT) & AXXX_CP_STQ_AVAIL_ST__MASK;
}
 
#define REG_AXXX_CP_MEQ_AVAIL 0x000001d9
#define AXXX_CP_MEQ_AVAIL_MEQ__MASK 0x0000001f
#define AXXX_CP_MEQ_AVAIL_MEQ__SHIFT 0
static inline uint32_t AXXX_CP_MEQ_AVAIL_MEQ(uint32_t val)
{
return ((val) << AXXX_CP_MEQ_AVAIL_MEQ__SHIFT) & AXXX_CP_MEQ_AVAIL_MEQ__MASK;
}
 
#define REG_AXXX_SCRATCH_UMSK 0x000001dc
#define AXXX_SCRATCH_UMSK_UMSK__MASK 0x000000ff
#define AXXX_SCRATCH_UMSK_UMSK__SHIFT 0
static inline uint32_t AXXX_SCRATCH_UMSK_UMSK(uint32_t val)
{
return ((val) << AXXX_SCRATCH_UMSK_UMSK__SHIFT) & AXXX_SCRATCH_UMSK_UMSK__MASK;
}
#define AXXX_SCRATCH_UMSK_SWAP__MASK 0x00030000
#define AXXX_SCRATCH_UMSK_SWAP__SHIFT 16
static inline uint32_t AXXX_SCRATCH_UMSK_SWAP(uint32_t val)
{
return ((val) << AXXX_SCRATCH_UMSK_SWAP__SHIFT) & AXXX_SCRATCH_UMSK_SWAP__MASK;
}
 
#define REG_AXXX_SCRATCH_ADDR 0x000001dd
 
#define REG_AXXX_CP_ME_RDADDR 0x000001ea
 
#define REG_AXXX_CP_STATE_DEBUG_INDEX 0x000001ec
 
#define REG_AXXX_CP_STATE_DEBUG_DATA 0x000001ed
 
#define REG_AXXX_CP_INT_CNTL 0x000001f2
 
#define REG_AXXX_CP_INT_STATUS 0x000001f3
 
#define REG_AXXX_CP_INT_ACK 0x000001f4
 
#define REG_AXXX_CP_ME_CNTL 0x000001f6
#define AXXX_CP_ME_CNTL_BUSY 0x20000000
#define AXXX_CP_ME_CNTL_HALT 0x10000000
 
#define REG_AXXX_CP_ME_STATUS 0x000001f7
 
#define REG_AXXX_CP_ME_RAM_WADDR 0x000001f8
 
#define REG_AXXX_CP_ME_RAM_RADDR 0x000001f9
 
#define REG_AXXX_CP_ME_RAM_DATA 0x000001fa
 
#define REG_AXXX_CP_DEBUG 0x000001fc
#define AXXX_CP_DEBUG_PREDICATE_DISABLE 0x00800000
#define AXXX_CP_DEBUG_PROG_END_PTR_ENABLE 0x01000000
#define AXXX_CP_DEBUG_MIU_128BIT_WRITE_ENABLE 0x02000000
#define AXXX_CP_DEBUG_PREFETCH_PASS_NOPS 0x04000000
#define AXXX_CP_DEBUG_DYNAMIC_CLK_DISABLE 0x08000000
#define AXXX_CP_DEBUG_PREFETCH_MATCH_DISABLE 0x10000000
#define AXXX_CP_DEBUG_SIMPLE_ME_FLOW_CONTROL 0x40000000
#define AXXX_CP_DEBUG_MIU_WRITE_PACK_DISABLE 0x80000000
 
#define REG_AXXX_CP_CSQ_RB_STAT 0x000001fd
#define AXXX_CP_CSQ_RB_STAT_RPTR__MASK 0x0000007f
#define AXXX_CP_CSQ_RB_STAT_RPTR__SHIFT 0
static inline uint32_t AXXX_CP_CSQ_RB_STAT_RPTR(uint32_t val)
{
return ((val) << AXXX_CP_CSQ_RB_STAT_RPTR__SHIFT) & AXXX_CP_CSQ_RB_STAT_RPTR__MASK;
}
#define AXXX_CP_CSQ_RB_STAT_WPTR__MASK 0x007f0000
#define AXXX_CP_CSQ_RB_STAT_WPTR__SHIFT 16
static inline uint32_t AXXX_CP_CSQ_RB_STAT_WPTR(uint32_t val)
{
return ((val) << AXXX_CP_CSQ_RB_STAT_WPTR__SHIFT) & AXXX_CP_CSQ_RB_STAT_WPTR__MASK;
}
 
#define REG_AXXX_CP_CSQ_IB1_STAT 0x000001fe
#define AXXX_CP_CSQ_IB1_STAT_RPTR__MASK 0x0000007f
#define AXXX_CP_CSQ_IB1_STAT_RPTR__SHIFT 0
static inline uint32_t AXXX_CP_CSQ_IB1_STAT_RPTR(uint32_t val)
{
return ((val) << AXXX_CP_CSQ_IB1_STAT_RPTR__SHIFT) & AXXX_CP_CSQ_IB1_STAT_RPTR__MASK;
}
#define AXXX_CP_CSQ_IB1_STAT_WPTR__MASK 0x007f0000
#define AXXX_CP_CSQ_IB1_STAT_WPTR__SHIFT 16
static inline uint32_t AXXX_CP_CSQ_IB1_STAT_WPTR(uint32_t val)
{
return ((val) << AXXX_CP_CSQ_IB1_STAT_WPTR__SHIFT) & AXXX_CP_CSQ_IB1_STAT_WPTR__MASK;
}
 
#define REG_AXXX_CP_CSQ_IB2_STAT 0x000001ff
#define AXXX_CP_CSQ_IB2_STAT_RPTR__MASK 0x0000007f
#define AXXX_CP_CSQ_IB2_STAT_RPTR__SHIFT 0
static inline uint32_t AXXX_CP_CSQ_IB2_STAT_RPTR(uint32_t val)
{
return ((val) << AXXX_CP_CSQ_IB2_STAT_RPTR__SHIFT) & AXXX_CP_CSQ_IB2_STAT_RPTR__MASK;
}
#define AXXX_CP_CSQ_IB2_STAT_WPTR__MASK 0x007f0000
#define AXXX_CP_CSQ_IB2_STAT_WPTR__SHIFT 16
static inline uint32_t AXXX_CP_CSQ_IB2_STAT_WPTR(uint32_t val)
{
return ((val) << AXXX_CP_CSQ_IB2_STAT_WPTR__SHIFT) & AXXX_CP_CSQ_IB2_STAT_WPTR__MASK;
}
 
#define REG_AXXX_CP_NON_PREFETCH_CNTRS 0x00000440
 
#define REG_AXXX_CP_STQ_ST_STAT 0x00000443
 
#define REG_AXXX_CP_ST_BASE 0x0000044d
 
#define REG_AXXX_CP_ST_BUFSZ 0x0000044e
 
#define REG_AXXX_CP_MEQ_STAT 0x0000044f
 
#define REG_AXXX_CP_MIU_TAG_STAT 0x00000452
 
#define REG_AXXX_CP_BIN_MASK_LO 0x00000454
 
#define REG_AXXX_CP_BIN_MASK_HI 0x00000455
 
#define REG_AXXX_CP_BIN_SELECT_LO 0x00000456
 
#define REG_AXXX_CP_BIN_SELECT_HI 0x00000457
 
#define REG_AXXX_CP_IB1_BASE 0x00000458
 
#define REG_AXXX_CP_IB1_BUFSZ 0x00000459
 
#define REG_AXXX_CP_IB2_BASE 0x0000045a
 
#define REG_AXXX_CP_IB2_BUFSZ 0x0000045b
 
#define REG_AXXX_CP_STAT 0x0000047f
 
#define REG_AXXX_CP_SCRATCH_REG0 0x00000578
 
#define REG_AXXX_CP_SCRATCH_REG1 0x00000579
 
#define REG_AXXX_CP_SCRATCH_REG2 0x0000057a
 
#define REG_AXXX_CP_SCRATCH_REG3 0x0000057b
 
#define REG_AXXX_CP_SCRATCH_REG4 0x0000057c
 
#define REG_AXXX_CP_SCRATCH_REG5 0x0000057d
 
#define REG_AXXX_CP_SCRATCH_REG6 0x0000057e
 
#define REG_AXXX_CP_SCRATCH_REG7 0x0000057f
 
#define REG_AXXX_CP_ME_VS_EVENT_SRC 0x00000600
 
#define REG_AXXX_CP_ME_VS_EVENT_ADDR 0x00000601
 
#define REG_AXXX_CP_ME_VS_EVENT_DATA 0x00000602
 
#define REG_AXXX_CP_ME_VS_EVENT_ADDR_SWM 0x00000603
 
#define REG_AXXX_CP_ME_VS_EVENT_DATA_SWM 0x00000604
 
#define REG_AXXX_CP_ME_PS_EVENT_SRC 0x00000605
 
#define REG_AXXX_CP_ME_PS_EVENT_ADDR 0x00000606
 
#define REG_AXXX_CP_ME_PS_EVENT_DATA 0x00000607
 
#define REG_AXXX_CP_ME_PS_EVENT_ADDR_SWM 0x00000608
 
#define REG_AXXX_CP_ME_PS_EVENT_DATA_SWM 0x00000609
 
#define REG_AXXX_CP_ME_CF_EVENT_SRC 0x0000060a
 
#define REG_AXXX_CP_ME_CF_EVENT_ADDR 0x0000060b
 
#define REG_AXXX_CP_ME_CF_EVENT_DATA 0x0000060c
 
#define REG_AXXX_CP_ME_NRT_ADDR 0x0000060d
 
#define REG_AXXX_CP_ME_NRT_DATA 0x0000060e
 
#define REG_AXXX_CP_ME_VS_FETCH_DONE_SRC 0x00000612
 
#define REG_AXXX_CP_ME_VS_FETCH_DONE_ADDR 0x00000613
 
#define REG_AXXX_CP_ME_VS_FETCH_DONE_DATA 0x00000614
 
 
#endif /* ADRENO_COMMON_XML */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/adreno_pm4.xml.h
0,0 → 1,502
#ifndef ADRENO_PM4_XML
#define ADRENO_PM4_XML
 
/* Autogenerated file, DO NOT EDIT manually!
 
This file was generated by the rules-ng-ng headergen tool in this git repository:
http://github.com/freedreno/envytools/
git clone https://github.com/freedreno/envytools.git
 
The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml ( 364 bytes, from 2013-11-30 14:47:15)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32901 bytes, from 2014-06-02 15:21:30)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10551 bytes, from 2014-11-13 22:44:30)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 14895 bytes, from 2015-04-19 15:23:28)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 66709 bytes, from 2015-04-12 18:16:35)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 59314 bytes, from 2015-04-19 16:21:40)
 
Copyright (C) 2013-2015 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
 
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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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.
*/
 
 
enum vgt_event_type {
VS_DEALLOC = 0,
PS_DEALLOC = 1,
VS_DONE_TS = 2,
PS_DONE_TS = 3,
CACHE_FLUSH_TS = 4,
CONTEXT_DONE = 5,
CACHE_FLUSH = 6,
HLSQ_FLUSH = 7,
VIZQUERY_START = 7,
VIZQUERY_END = 8,
SC_WAIT_WC = 9,
RST_PIX_CNT = 13,
RST_VTX_CNT = 14,
TILE_FLUSH = 15,
CACHE_FLUSH_AND_INV_TS_EVENT = 20,
ZPASS_DONE = 21,
CACHE_FLUSH_AND_INV_EVENT = 22,
PERFCOUNTER_START = 23,
PERFCOUNTER_STOP = 24,
VS_FETCH_DONE = 27,
FACENESS_FLUSH = 28,
};
 
enum pc_di_primtype {
DI_PT_NONE = 0,
DI_PT_POINTLIST_A2XX = 1,
DI_PT_LINELIST = 2,
DI_PT_LINESTRIP = 3,
DI_PT_TRILIST = 4,
DI_PT_TRIFAN = 5,
DI_PT_TRISTRIP = 6,
DI_PT_LINELOOP = 7,
DI_PT_RECTLIST = 8,
DI_PT_POINTLIST_A3XX = 9,
DI_PT_LINE_ADJ = 10,
DI_PT_LINESTRIP_ADJ = 11,
DI_PT_TRI_ADJ = 12,
DI_PT_TRISTRIP_ADJ = 13,
DI_PT_PATCHES = 34,
};
 
enum pc_di_src_sel {
DI_SRC_SEL_DMA = 0,
DI_SRC_SEL_IMMEDIATE = 1,
DI_SRC_SEL_AUTO_INDEX = 2,
DI_SRC_SEL_RESERVED = 3,
};
 
enum pc_di_index_size {
INDEX_SIZE_IGN = 0,
INDEX_SIZE_16_BIT = 0,
INDEX_SIZE_32_BIT = 1,
INDEX_SIZE_8_BIT = 2,
INDEX_SIZE_INVALID = 0,
};
 
enum pc_di_vis_cull_mode {
IGNORE_VISIBILITY = 0,
USE_VISIBILITY = 1,
};
 
enum adreno_pm4_packet_type {
CP_TYPE0_PKT = 0,
CP_TYPE1_PKT = 0x40000000,
CP_TYPE2_PKT = 0x80000000,
CP_TYPE3_PKT = 0xc0000000,
};
 
enum adreno_pm4_type3_packets {
CP_ME_INIT = 72,
CP_NOP = 16,
CP_INDIRECT_BUFFER = 63,
CP_INDIRECT_BUFFER_PFD = 55,
CP_WAIT_FOR_IDLE = 38,
CP_WAIT_REG_MEM = 60,
CP_WAIT_REG_EQ = 82,
CP_WAIT_REG_GTE = 83,
CP_WAIT_UNTIL_READ = 92,
CP_WAIT_IB_PFD_COMPLETE = 93,
CP_REG_RMW = 33,
CP_SET_BIN_DATA = 47,
CP_REG_TO_MEM = 62,
CP_MEM_WRITE = 61,
CP_MEM_WRITE_CNTR = 79,
CP_COND_EXEC = 68,
CP_COND_WRITE = 69,
CP_EVENT_WRITE = 70,
CP_EVENT_WRITE_SHD = 88,
CP_EVENT_WRITE_CFL = 89,
CP_EVENT_WRITE_ZPD = 91,
CP_RUN_OPENCL = 49,
CP_DRAW_INDX = 34,
CP_DRAW_INDX_2 = 54,
CP_DRAW_INDX_BIN = 52,
CP_DRAW_INDX_2_BIN = 53,
CP_VIZ_QUERY = 35,
CP_SET_STATE = 37,
CP_SET_CONSTANT = 45,
CP_IM_LOAD = 39,
CP_IM_LOAD_IMMEDIATE = 43,
CP_LOAD_CONSTANT_CONTEXT = 46,
CP_INVALIDATE_STATE = 59,
CP_SET_SHADER_BASES = 74,
CP_SET_BIN_MASK = 80,
CP_SET_BIN_SELECT = 81,
CP_CONTEXT_UPDATE = 94,
CP_INTERRUPT = 64,
CP_IM_STORE = 44,
CP_SET_DRAW_INIT_FLAGS = 75,
CP_SET_PROTECTED_MODE = 95,
CP_BOOTSTRAP_UCODE = 111,
CP_LOAD_STATE = 48,
CP_COND_INDIRECT_BUFFER_PFE = 58,
CP_COND_INDIRECT_BUFFER_PFD = 50,
CP_INDIRECT_BUFFER_PFE = 63,
CP_SET_BIN = 76,
CP_TEST_TWO_MEMS = 113,
CP_REG_WR_NO_CTXT = 120,
CP_RECORD_PFP_TIMESTAMP = 17,
CP_WAIT_FOR_ME = 19,
CP_SET_DRAW_STATE = 67,
CP_DRAW_INDX_OFFSET = 56,
CP_DRAW_INDIRECT = 40,
CP_DRAW_INDX_INDIRECT = 41,
CP_DRAW_AUTO = 36,
CP_UNKNOWN_19 = 25,
CP_UNKNOWN_1A = 26,
CP_UNKNOWN_4E = 78,
CP_WIDE_REG_WRITE = 116,
IN_IB_PREFETCH_END = 23,
IN_SUBBLK_PREFETCH = 31,
IN_INSTR_PREFETCH = 32,
IN_INSTR_MATCH = 71,
IN_CONST_PREFETCH = 73,
IN_INCR_UPDT_STATE = 85,
IN_INCR_UPDT_CONST = 86,
IN_INCR_UPDT_INSTR = 87,
};
 
enum adreno_state_block {
SB_VERT_TEX = 0,
SB_VERT_MIPADDR = 1,
SB_FRAG_TEX = 2,
SB_FRAG_MIPADDR = 3,
SB_VERT_SHADER = 4,
SB_GEOM_SHADER = 5,
SB_FRAG_SHADER = 6,
};
 
enum adreno_state_type {
ST_SHADER = 0,
ST_CONSTANTS = 1,
};
 
enum adreno_state_src {
SS_DIRECT = 0,
SS_INDIRECT = 4,
};
 
enum a4xx_index_size {
INDEX4_SIZE_8_BIT = 0,
INDEX4_SIZE_16_BIT = 1,
INDEX4_SIZE_32_BIT = 2,
};
 
#define REG_CP_LOAD_STATE_0 0x00000000
#define CP_LOAD_STATE_0_DST_OFF__MASK 0x0000ffff
#define CP_LOAD_STATE_0_DST_OFF__SHIFT 0
static inline uint32_t CP_LOAD_STATE_0_DST_OFF(uint32_t val)
{
return ((val) << CP_LOAD_STATE_0_DST_OFF__SHIFT) & CP_LOAD_STATE_0_DST_OFF__MASK;
}
#define CP_LOAD_STATE_0_STATE_SRC__MASK 0x00070000
#define CP_LOAD_STATE_0_STATE_SRC__SHIFT 16
static inline uint32_t CP_LOAD_STATE_0_STATE_SRC(enum adreno_state_src val)
{
return ((val) << CP_LOAD_STATE_0_STATE_SRC__SHIFT) & CP_LOAD_STATE_0_STATE_SRC__MASK;
}
#define CP_LOAD_STATE_0_STATE_BLOCK__MASK 0x00380000
#define CP_LOAD_STATE_0_STATE_BLOCK__SHIFT 19
static inline uint32_t CP_LOAD_STATE_0_STATE_BLOCK(enum adreno_state_block val)
{
return ((val) << CP_LOAD_STATE_0_STATE_BLOCK__SHIFT) & CP_LOAD_STATE_0_STATE_BLOCK__MASK;
}
#define CP_LOAD_STATE_0_NUM_UNIT__MASK 0x7fc00000
#define CP_LOAD_STATE_0_NUM_UNIT__SHIFT 22
static inline uint32_t CP_LOAD_STATE_0_NUM_UNIT(uint32_t val)
{
return ((val) << CP_LOAD_STATE_0_NUM_UNIT__SHIFT) & CP_LOAD_STATE_0_NUM_UNIT__MASK;
}
 
#define REG_CP_LOAD_STATE_1 0x00000001
#define CP_LOAD_STATE_1_STATE_TYPE__MASK 0x00000003
#define CP_LOAD_STATE_1_STATE_TYPE__SHIFT 0
static inline uint32_t CP_LOAD_STATE_1_STATE_TYPE(enum adreno_state_type val)
{
return ((val) << CP_LOAD_STATE_1_STATE_TYPE__SHIFT) & CP_LOAD_STATE_1_STATE_TYPE__MASK;
}
#define CP_LOAD_STATE_1_EXT_SRC_ADDR__MASK 0xfffffffc
#define CP_LOAD_STATE_1_EXT_SRC_ADDR__SHIFT 2
static inline uint32_t CP_LOAD_STATE_1_EXT_SRC_ADDR(uint32_t val)
{
return ((val >> 2) << CP_LOAD_STATE_1_EXT_SRC_ADDR__SHIFT) & CP_LOAD_STATE_1_EXT_SRC_ADDR__MASK;
}
 
#define REG_CP_DRAW_INDX_0 0x00000000
#define CP_DRAW_INDX_0_VIZ_QUERY__MASK 0xffffffff
#define CP_DRAW_INDX_0_VIZ_QUERY__SHIFT 0
static inline uint32_t CP_DRAW_INDX_0_VIZ_QUERY(uint32_t val)
{
return ((val) << CP_DRAW_INDX_0_VIZ_QUERY__SHIFT) & CP_DRAW_INDX_0_VIZ_QUERY__MASK;
}
 
#define REG_CP_DRAW_INDX_1 0x00000001
#define CP_DRAW_INDX_1_PRIM_TYPE__MASK 0x0000003f
#define CP_DRAW_INDX_1_PRIM_TYPE__SHIFT 0
static inline uint32_t CP_DRAW_INDX_1_PRIM_TYPE(enum pc_di_primtype val)
{
return ((val) << CP_DRAW_INDX_1_PRIM_TYPE__SHIFT) & CP_DRAW_INDX_1_PRIM_TYPE__MASK;
}
#define CP_DRAW_INDX_1_SOURCE_SELECT__MASK 0x000000c0
#define CP_DRAW_INDX_1_SOURCE_SELECT__SHIFT 6
static inline uint32_t CP_DRAW_INDX_1_SOURCE_SELECT(enum pc_di_src_sel val)
{
return ((val) << CP_DRAW_INDX_1_SOURCE_SELECT__SHIFT) & CP_DRAW_INDX_1_SOURCE_SELECT__MASK;
}
#define CP_DRAW_INDX_1_VIS_CULL__MASK 0x00000600
#define CP_DRAW_INDX_1_VIS_CULL__SHIFT 9
static inline uint32_t CP_DRAW_INDX_1_VIS_CULL(enum pc_di_vis_cull_mode val)
{
return ((val) << CP_DRAW_INDX_1_VIS_CULL__SHIFT) & CP_DRAW_INDX_1_VIS_CULL__MASK;
}
#define CP_DRAW_INDX_1_INDEX_SIZE__MASK 0x00000800
#define CP_DRAW_INDX_1_INDEX_SIZE__SHIFT 11
static inline uint32_t CP_DRAW_INDX_1_INDEX_SIZE(enum pc_di_index_size val)
{
return ((val) << CP_DRAW_INDX_1_INDEX_SIZE__SHIFT) & CP_DRAW_INDX_1_INDEX_SIZE__MASK;
}
#define CP_DRAW_INDX_1_NOT_EOP 0x00001000
#define CP_DRAW_INDX_1_SMALL_INDEX 0x00002000
#define CP_DRAW_INDX_1_PRE_DRAW_INITIATOR_ENABLE 0x00004000
#define CP_DRAW_INDX_1_NUM_INSTANCES__MASK 0xff000000
#define CP_DRAW_INDX_1_NUM_INSTANCES__SHIFT 24
static inline uint32_t CP_DRAW_INDX_1_NUM_INSTANCES(uint32_t val)
{
return ((val) << CP_DRAW_INDX_1_NUM_INSTANCES__SHIFT) & CP_DRAW_INDX_1_NUM_INSTANCES__MASK;
}
 
#define REG_CP_DRAW_INDX_2 0x00000002
#define CP_DRAW_INDX_2_NUM_INDICES__MASK 0xffffffff
#define CP_DRAW_INDX_2_NUM_INDICES__SHIFT 0
static inline uint32_t CP_DRAW_INDX_2_NUM_INDICES(uint32_t val)
{
return ((val) << CP_DRAW_INDX_2_NUM_INDICES__SHIFT) & CP_DRAW_INDX_2_NUM_INDICES__MASK;
}
 
#define REG_CP_DRAW_INDX_3 0x00000003
#define CP_DRAW_INDX_3_INDX_BASE__MASK 0xffffffff
#define CP_DRAW_INDX_3_INDX_BASE__SHIFT 0
static inline uint32_t CP_DRAW_INDX_3_INDX_BASE(uint32_t val)
{
return ((val) << CP_DRAW_INDX_3_INDX_BASE__SHIFT) & CP_DRAW_INDX_3_INDX_BASE__MASK;
}
 
#define REG_CP_DRAW_INDX_4 0x00000004
#define CP_DRAW_INDX_4_INDX_SIZE__MASK 0xffffffff
#define CP_DRAW_INDX_4_INDX_SIZE__SHIFT 0
static inline uint32_t CP_DRAW_INDX_4_INDX_SIZE(uint32_t val)
{
return ((val) << CP_DRAW_INDX_4_INDX_SIZE__SHIFT) & CP_DRAW_INDX_4_INDX_SIZE__MASK;
}
 
#define REG_CP_DRAW_INDX_2_0 0x00000000
#define CP_DRAW_INDX_2_0_VIZ_QUERY__MASK 0xffffffff
#define CP_DRAW_INDX_2_0_VIZ_QUERY__SHIFT 0
static inline uint32_t CP_DRAW_INDX_2_0_VIZ_QUERY(uint32_t val)
{
return ((val) << CP_DRAW_INDX_2_0_VIZ_QUERY__SHIFT) & CP_DRAW_INDX_2_0_VIZ_QUERY__MASK;
}
 
#define REG_CP_DRAW_INDX_2_1 0x00000001
#define CP_DRAW_INDX_2_1_PRIM_TYPE__MASK 0x0000003f
#define CP_DRAW_INDX_2_1_PRIM_TYPE__SHIFT 0
static inline uint32_t CP_DRAW_INDX_2_1_PRIM_TYPE(enum pc_di_primtype val)
{
return ((val) << CP_DRAW_INDX_2_1_PRIM_TYPE__SHIFT) & CP_DRAW_INDX_2_1_PRIM_TYPE__MASK;
}
#define CP_DRAW_INDX_2_1_SOURCE_SELECT__MASK 0x000000c0
#define CP_DRAW_INDX_2_1_SOURCE_SELECT__SHIFT 6
static inline uint32_t CP_DRAW_INDX_2_1_SOURCE_SELECT(enum pc_di_src_sel val)
{
return ((val) << CP_DRAW_INDX_2_1_SOURCE_SELECT__SHIFT) & CP_DRAW_INDX_2_1_SOURCE_SELECT__MASK;
}
#define CP_DRAW_INDX_2_1_VIS_CULL__MASK 0x00000600
#define CP_DRAW_INDX_2_1_VIS_CULL__SHIFT 9
static inline uint32_t CP_DRAW_INDX_2_1_VIS_CULL(enum pc_di_vis_cull_mode val)
{
return ((val) << CP_DRAW_INDX_2_1_VIS_CULL__SHIFT) & CP_DRAW_INDX_2_1_VIS_CULL__MASK;
}
#define CP_DRAW_INDX_2_1_INDEX_SIZE__MASK 0x00000800
#define CP_DRAW_INDX_2_1_INDEX_SIZE__SHIFT 11
static inline uint32_t CP_DRAW_INDX_2_1_INDEX_SIZE(enum pc_di_index_size val)
{
return ((val) << CP_DRAW_INDX_2_1_INDEX_SIZE__SHIFT) & CP_DRAW_INDX_2_1_INDEX_SIZE__MASK;
}
#define CP_DRAW_INDX_2_1_NOT_EOP 0x00001000
#define CP_DRAW_INDX_2_1_SMALL_INDEX 0x00002000
#define CP_DRAW_INDX_2_1_PRE_DRAW_INITIATOR_ENABLE 0x00004000
#define CP_DRAW_INDX_2_1_NUM_INSTANCES__MASK 0xff000000
#define CP_DRAW_INDX_2_1_NUM_INSTANCES__SHIFT 24
static inline uint32_t CP_DRAW_INDX_2_1_NUM_INSTANCES(uint32_t val)
{
return ((val) << CP_DRAW_INDX_2_1_NUM_INSTANCES__SHIFT) & CP_DRAW_INDX_2_1_NUM_INSTANCES__MASK;
}
 
#define REG_CP_DRAW_INDX_2_2 0x00000002
#define CP_DRAW_INDX_2_2_NUM_INDICES__MASK 0xffffffff
#define CP_DRAW_INDX_2_2_NUM_INDICES__SHIFT 0
static inline uint32_t CP_DRAW_INDX_2_2_NUM_INDICES(uint32_t val)
{
return ((val) << CP_DRAW_INDX_2_2_NUM_INDICES__SHIFT) & CP_DRAW_INDX_2_2_NUM_INDICES__MASK;
}
 
#define REG_CP_DRAW_INDX_OFFSET_0 0x00000000
#define CP_DRAW_INDX_OFFSET_0_PRIM_TYPE__MASK 0x0000003f
#define CP_DRAW_INDX_OFFSET_0_PRIM_TYPE__SHIFT 0
static inline uint32_t CP_DRAW_INDX_OFFSET_0_PRIM_TYPE(enum pc_di_primtype val)
{
return ((val) << CP_DRAW_INDX_OFFSET_0_PRIM_TYPE__SHIFT) & CP_DRAW_INDX_OFFSET_0_PRIM_TYPE__MASK;
}
#define CP_DRAW_INDX_OFFSET_0_SOURCE_SELECT__MASK 0x000000c0
#define CP_DRAW_INDX_OFFSET_0_SOURCE_SELECT__SHIFT 6
static inline uint32_t CP_DRAW_INDX_OFFSET_0_SOURCE_SELECT(enum pc_di_src_sel val)
{
return ((val) << CP_DRAW_INDX_OFFSET_0_SOURCE_SELECT__SHIFT) & CP_DRAW_INDX_OFFSET_0_SOURCE_SELECT__MASK;
}
#define CP_DRAW_INDX_OFFSET_0_TESSELLATE 0x00000100
#define CP_DRAW_INDX_OFFSET_0_INDEX_SIZE__MASK 0x00000c00
#define CP_DRAW_INDX_OFFSET_0_INDEX_SIZE__SHIFT 10
static inline uint32_t CP_DRAW_INDX_OFFSET_0_INDEX_SIZE(enum a4xx_index_size val)
{
return ((val) << CP_DRAW_INDX_OFFSET_0_INDEX_SIZE__SHIFT) & CP_DRAW_INDX_OFFSET_0_INDEX_SIZE__MASK;
}
#define CP_DRAW_INDX_OFFSET_0_TESS_MODE__MASK 0x01f00000
#define CP_DRAW_INDX_OFFSET_0_TESS_MODE__SHIFT 20
static inline uint32_t CP_DRAW_INDX_OFFSET_0_TESS_MODE(uint32_t val)
{
return ((val) << CP_DRAW_INDX_OFFSET_0_TESS_MODE__SHIFT) & CP_DRAW_INDX_OFFSET_0_TESS_MODE__MASK;
}
 
#define REG_CP_DRAW_INDX_OFFSET_1 0x00000001
#define CP_DRAW_INDX_OFFSET_1_NUM_INSTANCES__MASK 0xffffffff
#define CP_DRAW_INDX_OFFSET_1_NUM_INSTANCES__SHIFT 0
static inline uint32_t CP_DRAW_INDX_OFFSET_1_NUM_INSTANCES(uint32_t val)
{
return ((val) << CP_DRAW_INDX_OFFSET_1_NUM_INSTANCES__SHIFT) & CP_DRAW_INDX_OFFSET_1_NUM_INSTANCES__MASK;
}
 
#define REG_CP_DRAW_INDX_OFFSET_2 0x00000002
#define CP_DRAW_INDX_OFFSET_2_NUM_INDICES__MASK 0xffffffff
#define CP_DRAW_INDX_OFFSET_2_NUM_INDICES__SHIFT 0
static inline uint32_t CP_DRAW_INDX_OFFSET_2_NUM_INDICES(uint32_t val)
{
return ((val) << CP_DRAW_INDX_OFFSET_2_NUM_INDICES__SHIFT) & CP_DRAW_INDX_OFFSET_2_NUM_INDICES__MASK;
}
 
#define REG_CP_DRAW_INDX_OFFSET_3 0x00000003
 
#define REG_CP_DRAW_INDX_OFFSET_4 0x00000004
#define CP_DRAW_INDX_OFFSET_4_INDX_BASE__MASK 0xffffffff
#define CP_DRAW_INDX_OFFSET_4_INDX_BASE__SHIFT 0
static inline uint32_t CP_DRAW_INDX_OFFSET_4_INDX_BASE(uint32_t val)
{
return ((val) << CP_DRAW_INDX_OFFSET_4_INDX_BASE__SHIFT) & CP_DRAW_INDX_OFFSET_4_INDX_BASE__MASK;
}
 
#define REG_CP_DRAW_INDX_OFFSET_5 0x00000005
#define CP_DRAW_INDX_OFFSET_5_INDX_SIZE__MASK 0xffffffff
#define CP_DRAW_INDX_OFFSET_5_INDX_SIZE__SHIFT 0
static inline uint32_t CP_DRAW_INDX_OFFSET_5_INDX_SIZE(uint32_t val)
{
return ((val) << CP_DRAW_INDX_OFFSET_5_INDX_SIZE__SHIFT) & CP_DRAW_INDX_OFFSET_5_INDX_SIZE__MASK;
}
 
#define REG_CP_SET_DRAW_STATE_0 0x00000000
#define CP_SET_DRAW_STATE_0_COUNT__MASK 0x0000ffff
#define CP_SET_DRAW_STATE_0_COUNT__SHIFT 0
static inline uint32_t CP_SET_DRAW_STATE_0_COUNT(uint32_t val)
{
return ((val) << CP_SET_DRAW_STATE_0_COUNT__SHIFT) & CP_SET_DRAW_STATE_0_COUNT__MASK;
}
#define CP_SET_DRAW_STATE_0_DIRTY 0x00010000
#define CP_SET_DRAW_STATE_0_DISABLE 0x00020000
#define CP_SET_DRAW_STATE_0_DISABLE_ALL_GROUPS 0x00040000
#define CP_SET_DRAW_STATE_0_LOAD_IMMED 0x00080000
#define CP_SET_DRAW_STATE_0_GROUP_ID__MASK 0x1f000000
#define CP_SET_DRAW_STATE_0_GROUP_ID__SHIFT 24
static inline uint32_t CP_SET_DRAW_STATE_0_GROUP_ID(uint32_t val)
{
return ((val) << CP_SET_DRAW_STATE_0_GROUP_ID__SHIFT) & CP_SET_DRAW_STATE_0_GROUP_ID__MASK;
}
 
#define REG_CP_SET_DRAW_STATE_1 0x00000001
#define CP_SET_DRAW_STATE_1_ADDR__MASK 0xffffffff
#define CP_SET_DRAW_STATE_1_ADDR__SHIFT 0
static inline uint32_t CP_SET_DRAW_STATE_1_ADDR(uint32_t val)
{
return ((val) << CP_SET_DRAW_STATE_1_ADDR__SHIFT) & CP_SET_DRAW_STATE_1_ADDR__MASK;
}
 
#define REG_CP_SET_BIN_0 0x00000000
 
#define REG_CP_SET_BIN_1 0x00000001
#define CP_SET_BIN_1_X1__MASK 0x0000ffff
#define CP_SET_BIN_1_X1__SHIFT 0
static inline uint32_t CP_SET_BIN_1_X1(uint32_t val)
{
return ((val) << CP_SET_BIN_1_X1__SHIFT) & CP_SET_BIN_1_X1__MASK;
}
#define CP_SET_BIN_1_Y1__MASK 0xffff0000
#define CP_SET_BIN_1_Y1__SHIFT 16
static inline uint32_t CP_SET_BIN_1_Y1(uint32_t val)
{
return ((val) << CP_SET_BIN_1_Y1__SHIFT) & CP_SET_BIN_1_Y1__MASK;
}
 
#define REG_CP_SET_BIN_2 0x00000002
#define CP_SET_BIN_2_X2__MASK 0x0000ffff
#define CP_SET_BIN_2_X2__SHIFT 0
static inline uint32_t CP_SET_BIN_2_X2(uint32_t val)
{
return ((val) << CP_SET_BIN_2_X2__SHIFT) & CP_SET_BIN_2_X2__MASK;
}
#define CP_SET_BIN_2_Y2__MASK 0xffff0000
#define CP_SET_BIN_2_Y2__SHIFT 16
static inline uint32_t CP_SET_BIN_2_Y2(uint32_t val)
{
return ((val) << CP_SET_BIN_2_Y2__SHIFT) & CP_SET_BIN_2_Y2__MASK;
}
 
#define REG_CP_SET_BIN_DATA_0 0x00000000
#define CP_SET_BIN_DATA_0_BIN_DATA_ADDR__MASK 0xffffffff
#define CP_SET_BIN_DATA_0_BIN_DATA_ADDR__SHIFT 0
static inline uint32_t CP_SET_BIN_DATA_0_BIN_DATA_ADDR(uint32_t val)
{
return ((val) << CP_SET_BIN_DATA_0_BIN_DATA_ADDR__SHIFT) & CP_SET_BIN_DATA_0_BIN_DATA_ADDR__MASK;
}
 
#define REG_CP_SET_BIN_DATA_1 0x00000001
#define CP_SET_BIN_DATA_1_BIN_SIZE_ADDRESS__MASK 0xffffffff
#define CP_SET_BIN_DATA_1_BIN_SIZE_ADDRESS__SHIFT 0
static inline uint32_t CP_SET_BIN_DATA_1_BIN_SIZE_ADDRESS(uint32_t val)
{
return ((val) << CP_SET_BIN_DATA_1_BIN_SIZE_ADDRESS__SHIFT) & CP_SET_BIN_DATA_1_BIN_SIZE_ADDRESS__MASK;
}
 
 
#endif /* ADRENO_PM4_XML */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/disasm.h
0,0 → 1,43
/*
* Copyright © 2012 Rob Clark <robclark@freedesktop.org>
*
* 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.
*/
 
#ifndef DISASM_H_
#define DISASM_H_
 
enum shader_t {
SHADER_VERTEX,
SHADER_FRAGMENT,
SHADER_COMPUTE,
};
 
/* bitmask of debug flags */
enum debug_t {
PRINT_RAW = 0x1, /* dump raw hexdump */
PRINT_VERBOSE = 0x2,
};
 
int disasm_a2xx(uint32_t *dwords, int sizedwords, int level, enum shader_t type);
int disasm_a3xx(uint32_t *dwords, int sizedwords, int level, enum shader_t type);
void disasm_set_debug(enum debug_t debug);
 
#endif /* DISASM_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/freedreno_context.c
0,0 → 1,252
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "freedreno_context.h"
#include "freedreno_draw.h"
#include "freedreno_fence.h"
#include "freedreno_program.h"
#include "freedreno_resource.h"
#include "freedreno_texture.h"
#include "freedreno_state.h"
#include "freedreno_gmem.h"
#include "freedreno_query.h"
#include "freedreno_query_hw.h"
#include "freedreno_util.h"
 
static struct fd_ringbuffer *next_rb(struct fd_context *ctx)
{
struct fd_ringbuffer *ring;
uint32_t ts;
 
/* grab next ringbuffer: */
ring = ctx->rings[(ctx->rings_idx++) % ARRAY_SIZE(ctx->rings)];
 
/* wait for new rb to be idle: */
ts = fd_ringbuffer_timestamp(ring);
if (ts) {
DBG("wait: %u", ts);
fd_pipe_wait(ctx->screen->pipe, ts);
}
 
fd_ringbuffer_reset(ring);
 
return ring;
}
 
static void
fd_context_next_rb(struct pipe_context *pctx)
{
struct fd_context *ctx = fd_context(pctx);
struct fd_ringbuffer *ring;
 
fd_ringmarker_del(ctx->draw_start);
fd_ringmarker_del(ctx->draw_end);
 
ring = next_rb(ctx);
 
ctx->draw_start = fd_ringmarker_new(ring);
ctx->draw_end = fd_ringmarker_new(ring);
 
fd_ringbuffer_set_parent(ring, NULL);
ctx->ring = ring;
 
fd_ringmarker_del(ctx->binning_start);
fd_ringmarker_del(ctx->binning_end);
 
ring = next_rb(ctx);
 
ctx->binning_start = fd_ringmarker_new(ring);
ctx->binning_end = fd_ringmarker_new(ring);
 
fd_ringbuffer_set_parent(ring, ctx->ring);
ctx->binning_ring = ring;
}
 
/* emit accumulated render cmds, needed for example if render target has
* changed, or for flush()
*/
void
fd_context_render(struct pipe_context *pctx)
{
struct fd_context *ctx = fd_context(pctx);
struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
struct fd_resource *rsc, *rsc_tmp;
int i;
 
DBG("needs_flush: %d", ctx->needs_flush);
 
if (!ctx->needs_flush)
return;
 
fd_gmem_render_tiles(ctx);
 
DBG("%p/%p/%p", ctx->ring->start, ctx->ring->cur, ctx->ring->end);
 
/* if size in dwords is more than half the buffer size, then wait and
* wrap around:
*/
if ((ctx->ring->cur - ctx->ring->start) > ctx->ring->size/8)
fd_context_next_rb(pctx);
 
ctx->needs_flush = false;
ctx->cleared = ctx->partial_cleared = ctx->restore = ctx->resolve = 0;
ctx->gmem_reason = 0;
ctx->num_draws = 0;
 
for (i = 0; i < pfb->nr_cbufs; i++)
if (pfb->cbufs[i])
fd_resource(pfb->cbufs[i]->texture)->dirty = false;
if (pfb->zsbuf) {
rsc = fd_resource(pfb->zsbuf->texture);
rsc->dirty = false;
if (rsc->stencil)
rsc->stencil->dirty = false;
}
 
/* go through all the used resources and clear their reading flag */
LIST_FOR_EACH_ENTRY_SAFE(rsc, rsc_tmp, &ctx->used_resources, list) {
assert(rsc->reading);
rsc->reading = false;
list_delinit(&rsc->list);
}
 
assert(LIST_IS_EMPTY(&ctx->used_resources));
}
 
static void
fd_context_flush(struct pipe_context *pctx, struct pipe_fence_handle **fence,
unsigned flags)
{
fd_context_render(pctx);
 
if (fence)
*fence = fd_fence_create(pctx);
}
 
void
fd_context_destroy(struct pipe_context *pctx)
{
struct fd_context *ctx = fd_context(pctx);
unsigned i;
 
DBG("");
 
fd_prog_fini(pctx);
fd_hw_query_fini(pctx);
 
util_dynarray_fini(&ctx->draw_patches);
 
if (ctx->blitter)
util_blitter_destroy(ctx->blitter);
 
if (ctx->primconvert)
util_primconvert_destroy(ctx->primconvert);
 
util_slab_destroy(&ctx->transfer_pool);
 
fd_ringmarker_del(ctx->draw_start);
fd_ringmarker_del(ctx->draw_end);
fd_ringmarker_del(ctx->binning_start);
fd_ringmarker_del(ctx->binning_end);
 
for (i = 0; i < ARRAY_SIZE(ctx->rings); i++)
fd_ringbuffer_del(ctx->rings[i]);
 
for (i = 0; i < ARRAY_SIZE(ctx->pipe); i++) {
struct fd_vsc_pipe *pipe = &ctx->pipe[i];
if (!pipe->bo)
break;
fd_bo_del(pipe->bo);
}
 
fd_device_del(ctx->dev);
 
FREE(ctx);
}
 
struct pipe_context *
fd_context_init(struct fd_context *ctx, struct pipe_screen *pscreen,
const uint8_t *primtypes, void *priv)
{
struct fd_screen *screen = fd_screen(pscreen);
struct pipe_context *pctx;
int i;
 
ctx->screen = screen;
 
ctx->primtypes = primtypes;
ctx->primtype_mask = 0;
for (i = 0; i < PIPE_PRIM_MAX; i++)
if (primtypes[i])
ctx->primtype_mask |= (1 << i);
 
/* need some sane default in case state tracker doesn't
* set some state:
*/
ctx->sample_mask = 0xffff;
 
pctx = &ctx->base;
pctx->screen = pscreen;
pctx->priv = priv;
pctx->flush = fd_context_flush;
 
for (i = 0; i < ARRAY_SIZE(ctx->rings); i++) {
ctx->rings[i] = fd_ringbuffer_new(screen->pipe, 0x100000);
if (!ctx->rings[i])
goto fail;
}
 
fd_context_next_rb(pctx);
fd_reset_wfi(ctx);
 
util_dynarray_init(&ctx->draw_patches);
 
util_slab_create(&ctx->transfer_pool, sizeof(struct fd_transfer),
16, UTIL_SLAB_SINGLETHREADED);
 
fd_draw_init(pctx);
fd_resource_context_init(pctx);
fd_query_context_init(pctx);
fd_texture_init(pctx);
fd_state_init(pctx);
fd_hw_query_init(pctx);
 
ctx->blitter = util_blitter_create(pctx);
if (!ctx->blitter)
goto fail;
 
ctx->primconvert = util_primconvert_create(pctx, ctx->primtype_mask);
if (!ctx->primconvert)
goto fail;
 
return pctx;
 
fail:
pctx->destroy(pctx);
return NULL;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/freedreno_context.h
0,0 → 1,416
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FREEDRENO_CONTEXT_H_
#define FREEDRENO_CONTEXT_H_
 
#include "pipe/p_context.h"
#include "indices/u_primconvert.h"
#include "util/u_blitter.h"
#include "util/list.h"
#include "util/u_slab.h"
#include "util/u_string.h"
 
#include "freedreno_screen.h"
#include "freedreno_gmem.h"
#include "freedreno_util.h"
 
struct fd_vertex_stateobj;
 
struct fd_texture_stateobj {
struct pipe_sampler_view *textures[PIPE_MAX_SAMPLERS];
unsigned num_textures;
struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
unsigned num_samplers;
unsigned dirty_samplers;
};
 
struct fd_program_stateobj {
void *vp, *fp;
enum {
FD_SHADER_DIRTY_VP = (1 << 0),
FD_SHADER_DIRTY_FP = (1 << 1),
} dirty;
uint8_t num_exports;
/* Indexed by semantic name or TGSI_SEMANTIC_COUNT + semantic index
* for TGSI_SEMANTIC_GENERIC. Special vs exports (position and point-
* size) are not included in this
*/
uint8_t export_linkage[63];
};
 
struct fd_constbuf_stateobj {
struct pipe_constant_buffer cb[PIPE_MAX_CONSTANT_BUFFERS];
uint32_t enabled_mask;
uint32_t dirty_mask;
};
 
struct fd_vertexbuf_stateobj {
struct pipe_vertex_buffer vb[PIPE_MAX_ATTRIBS];
unsigned count;
uint32_t enabled_mask;
uint32_t dirty_mask;
};
 
struct fd_vertex_stateobj {
struct pipe_vertex_element pipe[PIPE_MAX_ATTRIBS];
unsigned num_elements;
};
 
/* group together the vertex and vertexbuf state.. for ease of passing
* around, and because various internal operations (gmem<->mem, etc)
* need their own vertex state:
*/
struct fd_vertex_state {
struct fd_vertex_stateobj *vtx;
struct fd_vertexbuf_stateobj vertexbuf;
};
 
/* Bitmask of stages in rendering that a particular query query is
* active. Queries will be automatically started/stopped (generating
* additional fd_hw_sample_period's) on entrance/exit from stages that
* are applicable to the query.
*
* NOTE: set the stage to NULL at end of IB to ensure no query is still
* active. Things aren't going to work out the way you want if a query
* is active across IB's (or between tile IB and draw IB)
*/
enum fd_render_stage {
FD_STAGE_NULL = 0x00,
FD_STAGE_DRAW = 0x01,
FD_STAGE_CLEAR = 0x02,
/* TODO before queries which include MEM2GMEM or GMEM2MEM will
* work we will need to call fd_hw_query_prepare() from somewhere
* appropriate so that queries in the tiling IB get backed with
* memory to write results to.
*/
FD_STAGE_MEM2GMEM = 0x04,
FD_STAGE_GMEM2MEM = 0x08,
/* used for driver internal draws (ie. util_blitter_blit()): */
FD_STAGE_BLIT = 0x10,
};
 
#define MAX_HW_SAMPLE_PROVIDERS 4
struct fd_hw_sample_provider;
struct fd_hw_sample;
 
struct fd_context {
struct pipe_context base;
 
struct fd_device *dev;
struct fd_screen *screen;
 
struct blitter_context *blitter;
struct primconvert_context *primconvert;
 
/* slab for pipe_transfer allocations: */
struct util_slab_mempool transfer_pool;
 
/* slabs for fd_hw_sample and fd_hw_sample_period allocations: */
struct util_slab_mempool sample_pool;
struct util_slab_mempool sample_period_pool;
 
/* next sample offset.. incremented for each sample in the batch/
* submit, reset to zero on next submit.
*/
uint32_t next_sample_offset;
 
/* sample-providers for hw queries: */
const struct fd_hw_sample_provider *sample_providers[MAX_HW_SAMPLE_PROVIDERS];
 
/* cached samples (in case multiple queries need to reference
* the same sample snapshot)
*/
struct fd_hw_sample *sample_cache[MAX_HW_SAMPLE_PROVIDERS];
 
/* tracking for current stage, to know when to start/stop
* any active queries:
*/
enum fd_render_stage stage;
 
/* list of active queries: */
struct list_head active_queries;
 
/* list of queries that are not active, but were active in the
* current submit:
*/
struct list_head current_queries;
 
/* current query result bo and tile stride: */
struct fd_bo *query_bo;
uint32_t query_tile_stride;
 
/* list of resources used by currently-unsubmitted renders */
struct list_head used_resources;
 
/* table with PIPE_PRIM_MAX entries mapping PIPE_PRIM_x to
* DI_PT_x value to use for draw initiator. There are some
* slight differences between generation:
*/
const uint8_t *primtypes;
uint32_t primtype_mask;
 
/* shaders used by clear, and gmem->mem blits: */
struct fd_program_stateobj solid_prog; // TODO move to screen?
 
/* shaders used by mem->gmem blits: */
struct fd_program_stateobj blit_prog[8]; // TODO move to screen?
struct fd_program_stateobj blit_z, blit_zs;
 
/* do we need to mem2gmem before rendering. We don't, if for example,
* there was a glClear() that invalidated the entire previous buffer
* contents. Keep track of which buffer(s) are cleared, or needs
* restore. Masks of PIPE_CLEAR_*
*
* The 'cleared' bits will be set for buffers which are *entirely*
* cleared, and 'partial_cleared' bits will be set if you must
* check cleared_scissor.
*/
enum {
/* align bitmask values w/ PIPE_CLEAR_*.. since that is convenient.. */
FD_BUFFER_COLOR = PIPE_CLEAR_COLOR,
FD_BUFFER_DEPTH = PIPE_CLEAR_DEPTH,
FD_BUFFER_STENCIL = PIPE_CLEAR_STENCIL,
FD_BUFFER_ALL = FD_BUFFER_COLOR | FD_BUFFER_DEPTH | FD_BUFFER_STENCIL,
} cleared, partial_cleared, restore, resolve;
 
bool needs_flush;
 
/* To decide whether to render to system memory, keep track of the
* number of draws, and whether any of them require multisample,
* depth_test (or depth write), stencil_test, blending, and
* color_logic_Op (since those functions are disabled when by-
* passing GMEM.
*/
enum {
FD_GMEM_CLEARS_DEPTH_STENCIL = 0x01,
FD_GMEM_DEPTH_ENABLED = 0x02,
FD_GMEM_STENCIL_ENABLED = 0x04,
 
FD_GMEM_MSAA_ENABLED = 0x08,
FD_GMEM_BLEND_ENABLED = 0x10,
FD_GMEM_LOGICOP_ENABLED = 0x20,
} gmem_reason;
unsigned num_draws; /* number of draws in current batch */
 
/* Stats/counters:
*/
struct {
uint64_t prims_emitted;
uint64_t draw_calls;
uint64_t batch_total, batch_sysmem, batch_gmem, batch_restore;
} stats;
 
/* we can't really sanely deal with wraparound point in ringbuffer
* and because of the way tiling works we can't really flush at
* arbitrary points (without a big performance hit). When we get
* too close to the end of the current ringbuffer, cycle to the next
* one (and wait for pending rendering from next rb to complete).
* We want the # of ringbuffers to be high enough that we don't
* normally have to wait before resetting to the start of the next
* rb.
*/
struct fd_ringbuffer *rings[8];
unsigned rings_idx;
 
/* NOTE: currently using a single ringbuffer for both draw and
* tiling commands, we need to make sure we need to leave enough
* room at the end to append the tiling commands when we flush.
* 0x7000 dwords should be a couple times more than we ever need
* so should be a nice conservative threshold.
*/
#define FD_TILING_COMMANDS_DWORDS 0x7000
 
/* normal draw/clear cmds: */
struct fd_ringbuffer *ring;
struct fd_ringmarker *draw_start, *draw_end;
 
/* binning pass draw/clear cmds: */
struct fd_ringbuffer *binning_ring;
struct fd_ringmarker *binning_start, *binning_end;
 
/* Keep track if WAIT_FOR_IDLE is needed for registers we need
* to update via RMW:
*/
bool needs_wfi;
 
/* Do we need to re-emit RB_FRAME_BUFFER_DIMENSION? At least on a3xx
* it is not a banked context register, so it needs a WFI to update.
* Keep track if it has actually changed, to avoid unneeded WFI.
* */
bool needs_rb_fbd;
 
/* Keep track of DRAW initiators that need to be patched up depending
* on whether we using binning or not:
*/
struct util_dynarray draw_patches;
 
struct pipe_scissor_state scissor;
 
/* we don't have a disable/enable bit for scissor, so instead we keep
* a disabled-scissor state which matches the entire bound framebuffer
* and use that when scissor is not enabled.
*/
struct pipe_scissor_state disabled_scissor;
 
/* Track the maximal bounds of the scissor of all the draws within a
* batch. Used at the tile rendering step (fd_gmem_render_tiles(),
* mem2gmem/gmem2mem) to avoid needlessly moving data in/out of gmem.
*/
struct pipe_scissor_state max_scissor;
 
/* Track the cleared scissor for color/depth/stencil, so we know
* which, if any, tiles need to be restored (mem2gmem). Only valid
* if the corresponding bit in ctx->cleared is set.
*/
struct {
struct pipe_scissor_state color, depth, stencil;
} cleared_scissor;
 
/* Current gmem/tiling configuration.. gets updated on render_tiles()
* if out of date with current maximal-scissor/cpp:
*/
struct fd_gmem_stateobj gmem;
struct fd_vsc_pipe pipe[8];
struct fd_tile tile[256];
 
/* which state objects need to be re-emit'd: */
enum {
FD_DIRTY_BLEND = (1 << 0),
FD_DIRTY_RASTERIZER = (1 << 1),
FD_DIRTY_ZSA = (1 << 2),
FD_DIRTY_FRAGTEX = (1 << 3),
FD_DIRTY_VERTTEX = (1 << 4),
FD_DIRTY_TEXSTATE = (1 << 5),
FD_DIRTY_PROG = (1 << 6),
FD_DIRTY_BLEND_COLOR = (1 << 7),
FD_DIRTY_STENCIL_REF = (1 << 8),
FD_DIRTY_SAMPLE_MASK = (1 << 9),
FD_DIRTY_FRAMEBUFFER = (1 << 10),
FD_DIRTY_STIPPLE = (1 << 11),
FD_DIRTY_VIEWPORT = (1 << 12),
FD_DIRTY_CONSTBUF = (1 << 13),
FD_DIRTY_VTXSTATE = (1 << 14),
FD_DIRTY_VTXBUF = (1 << 15),
FD_DIRTY_INDEXBUF = (1 << 16),
FD_DIRTY_SCISSOR = (1 << 17),
} dirty;
 
struct pipe_blend_state *blend;
struct pipe_rasterizer_state *rasterizer;
struct pipe_depth_stencil_alpha_state *zsa;
 
struct fd_texture_stateobj verttex, fragtex;
 
struct fd_program_stateobj prog;
 
struct fd_vertex_state vtx;
 
struct pipe_blend_color blend_color;
struct pipe_stencil_ref stencil_ref;
unsigned sample_mask;
struct pipe_framebuffer_state framebuffer;
struct pipe_poly_stipple stipple;
struct pipe_viewport_state viewport;
struct fd_constbuf_stateobj constbuf[PIPE_SHADER_TYPES];
struct pipe_index_buffer indexbuf;
 
/* GMEM/tile handling fxns: */
void (*emit_tile_init)(struct fd_context *ctx);
void (*emit_tile_prep)(struct fd_context *ctx, struct fd_tile *tile);
void (*emit_tile_mem2gmem)(struct fd_context *ctx, struct fd_tile *tile);
void (*emit_tile_renderprep)(struct fd_context *ctx, struct fd_tile *tile);
void (*emit_tile_gmem2mem)(struct fd_context *ctx, struct fd_tile *tile);
 
/* optional, for GMEM bypass: */
void (*emit_sysmem_prep)(struct fd_context *ctx);
 
/* draw: */
void (*draw_vbo)(struct fd_context *pctx, const struct pipe_draw_info *info);
void (*clear)(struct fd_context *ctx, unsigned buffers,
const union pipe_color_union *color, double depth, unsigned stencil);
};
 
static INLINE struct fd_context *
fd_context(struct pipe_context *pctx)
{
return (struct fd_context *)pctx;
}
 
static INLINE struct pipe_scissor_state *
fd_context_get_scissor(struct fd_context *ctx)
{
if (ctx->rasterizer && ctx->rasterizer->scissor)
return &ctx->scissor;
return &ctx->disabled_scissor;
}
 
static INLINE bool
fd_supported_prim(struct fd_context *ctx, unsigned prim)
{
return (1 << prim) & ctx->primtype_mask;
}
 
static INLINE void
fd_reset_wfi(struct fd_context *ctx)
{
ctx->needs_wfi = true;
}
 
/* emit a WAIT_FOR_IDLE only if needed, ie. if there has not already
* been one since last draw:
*/
static inline void
fd_wfi(struct fd_context *ctx, struct fd_ringbuffer *ring)
{
if (ctx->needs_wfi) {
OUT_WFI(ring);
ctx->needs_wfi = false;
}
}
 
/* emit a CP_EVENT_WRITE:
*/
static inline void
fd_event_write(struct fd_context *ctx, struct fd_ringbuffer *ring,
enum vgt_event_type evt)
{
OUT_PKT3(ring, CP_EVENT_WRITE, 1);
OUT_RING(ring, evt);
fd_reset_wfi(ctx);
}
 
struct pipe_context * fd_context_init(struct fd_context *ctx,
struct pipe_screen *pscreen, const uint8_t *primtypes,
void *priv);
 
void fd_context_render(struct pipe_context *pctx);
 
void fd_context_destroy(struct pipe_context *pctx);
 
#endif /* FREEDRENO_CONTEXT_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/freedreno_draw.c
0,0 → 1,277
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "pipe/p_state.h"
#include "util/u_string.h"
#include "util/u_memory.h"
#include "util/u_prim.h"
#include "util/u_format.h"
 
#include "freedreno_draw.h"
#include "freedreno_context.h"
#include "freedreno_state.h"
#include "freedreno_resource.h"
#include "freedreno_query_hw.h"
#include "freedreno_util.h"
 
static void
resource_reading(struct fd_context *ctx, struct pipe_resource *prsc)
{
struct fd_resource *rsc;
 
if (!prsc)
return;
 
rsc = fd_resource(prsc);
rsc->reading = true;
list_delinit(&rsc->list);
list_addtail(&rsc->list, &ctx->used_resources);
}
 
static void
fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
{
struct fd_context *ctx = fd_context(pctx);
struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
struct pipe_scissor_state *scissor = fd_context_get_scissor(ctx);
unsigned i, buffers = 0;
 
/* if we supported transform feedback, we'd have to disable this: */
if (((scissor->maxx - scissor->minx) *
(scissor->maxy - scissor->miny)) == 0) {
return;
}
 
/* emulate unsupported primitives: */
if (!fd_supported_prim(ctx, info->mode)) {
util_primconvert_save_index_buffer(ctx->primconvert, &ctx->indexbuf);
util_primconvert_save_rasterizer_state(ctx->primconvert, ctx->rasterizer);
util_primconvert_draw_vbo(ctx->primconvert, info);
return;
}
 
ctx->needs_flush = true;
 
/*
* Figure out the buffers/features we need:
*/
 
if (fd_depth_enabled(ctx)) {
buffers |= FD_BUFFER_DEPTH;
fd_resource(pfb->zsbuf->texture)->dirty = true;
ctx->gmem_reason |= FD_GMEM_DEPTH_ENABLED;
}
 
if (fd_stencil_enabled(ctx)) {
struct fd_resource *rsc = fd_resource(pfb->zsbuf->texture);
buffers |= FD_BUFFER_STENCIL;
if (rsc->stencil)
rsc->stencil->dirty = true;
else
rsc->dirty = true;
ctx->gmem_reason |= FD_GMEM_STENCIL_ENABLED;
}
 
if (fd_logicop_enabled(ctx))
ctx->gmem_reason |= FD_GMEM_LOGICOP_ENABLED;
 
for (i = 0; i < pfb->nr_cbufs; i++) {
struct pipe_resource *surf;
 
if (!pfb->cbufs[i])
continue;
 
surf = pfb->cbufs[i]->texture;
 
fd_resource(surf)->dirty = true;
buffers |= PIPE_CLEAR_COLOR0 << i;
 
if (surf->nr_samples > 1)
ctx->gmem_reason |= FD_GMEM_MSAA_ENABLED;
 
if (fd_blend_enabled(ctx, i))
ctx->gmem_reason |= FD_GMEM_BLEND_ENABLED;
}
 
/* Skip over buffer 0, that is sent along with the command stream */
for (i = 1; i < PIPE_MAX_CONSTANT_BUFFERS; i++) {
resource_reading(ctx, ctx->constbuf[PIPE_SHADER_VERTEX].cb[i].buffer);
resource_reading(ctx, ctx->constbuf[PIPE_SHADER_FRAGMENT].cb[i].buffer);
}
 
/* Mark VBOs as being read */
for (i = 0; i < ctx->vtx.vertexbuf.count; i++) {
assert(!ctx->vtx.vertexbuf.vb[i].user_buffer);
resource_reading(ctx, ctx->vtx.vertexbuf.vb[i].buffer);
}
 
/* Mark index buffer as being read */
resource_reading(ctx, ctx->indexbuf.buffer);
 
/* Mark textures as being read */
for (i = 0; i < ctx->verttex.num_textures; i++)
if (ctx->verttex.textures[i])
resource_reading(ctx, ctx->verttex.textures[i]->texture);
for (i = 0; i < ctx->fragtex.num_textures; i++)
if (ctx->fragtex.textures[i])
resource_reading(ctx, ctx->fragtex.textures[i]->texture);
 
ctx->num_draws++;
 
ctx->stats.draw_calls++;
ctx->stats.prims_emitted +=
u_reduced_prims_for_vertices(info->mode, info->count);
 
/* any buffers that haven't been cleared yet, we need to restore: */
ctx->restore |= buffers & (FD_BUFFER_ALL & ~ctx->cleared);
/* and any buffers used, need to be resolved: */
ctx->resolve |= buffers;
 
DBG("%x num_draws=%u (%s/%s)", buffers, ctx->num_draws,
util_format_short_name(pipe_surface_format(pfb->cbufs[0])),
util_format_short_name(pipe_surface_format(pfb->zsbuf)));
 
fd_hw_query_set_stage(ctx, ctx->ring, FD_STAGE_DRAW);
ctx->draw_vbo(ctx, info);
 
/* if an app (or, well, piglit test) does many thousands of draws
* without flush (or anything which implicitly flushes, like
* changing render targets), we can exceed the ringbuffer size.
* Since we don't currently have a sane way to wrapparound, and
* we use the same buffer for both draw and tiling commands, for
* now we need to do this hack and trigger flush if we are running
* low on remaining space for cmds:
*/
if (((ctx->ring->cur - ctx->ring->start) >
(ctx->ring->size/4 - FD_TILING_COMMANDS_DWORDS)) ||
(fd_mesa_debug & FD_DBG_FLUSH))
fd_context_render(pctx);
}
 
/* TODO figure out how to make better use of existing state mechanism
* for clear (and possibly gmem->mem / mem->gmem) so we can (a) keep
* track of what state really actually changes, and (b) reduce the code
* in the a2xx/a3xx parts.
*/
 
static void
fd_clear(struct pipe_context *pctx, unsigned buffers,
const union pipe_color_union *color, double depth, unsigned stencil)
{
struct fd_context *ctx = fd_context(pctx);
struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
struct pipe_scissor_state *scissor = fd_context_get_scissor(ctx);
unsigned cleared_buffers;
int i;
 
/* for bookkeeping about which buffers have been cleared (and thus
* can fully or partially skip mem2gmem) we need to ignore buffers
* that have already had a draw, in case apps do silly things like
* clear after draw (ie. if you only clear the color buffer, but
* something like alpha-test causes side effects from the draw in
* the depth buffer, etc)
*/
cleared_buffers = buffers & (FD_BUFFER_ALL & ~ctx->restore);
 
/* do we have full-screen scissor? */
if (!memcmp(scissor, &ctx->disabled_scissor, sizeof(*scissor))) {
ctx->cleared |= cleared_buffers;
} else {
ctx->partial_cleared |= cleared_buffers;
if (cleared_buffers & PIPE_CLEAR_COLOR)
ctx->cleared_scissor.color = *scissor;
if (cleared_buffers & PIPE_CLEAR_DEPTH)
ctx->cleared_scissor.depth = *scissor;
if (cleared_buffers & PIPE_CLEAR_STENCIL)
ctx->cleared_scissor.stencil = *scissor;
}
ctx->resolve |= buffers;
ctx->needs_flush = true;
 
if (buffers & PIPE_CLEAR_COLOR)
for (i = 0; i < pfb->nr_cbufs; i++)
if (buffers & (PIPE_CLEAR_COLOR0 << i))
fd_resource(pfb->cbufs[i]->texture)->dirty = true;
 
if (buffers & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) {
struct fd_resource *rsc = fd_resource(pfb->zsbuf->texture);
if (rsc->stencil && buffers & PIPE_CLEAR_STENCIL)
rsc->stencil->dirty = true;
if (!rsc->stencil || buffers & PIPE_CLEAR_DEPTH)
rsc->dirty = true;
 
ctx->gmem_reason |= FD_GMEM_CLEARS_DEPTH_STENCIL;
}
 
DBG("%x depth=%f, stencil=%u (%s/%s)", buffers, depth, stencil,
util_format_short_name(pipe_surface_format(pfb->cbufs[0])),
util_format_short_name(pipe_surface_format(pfb->zsbuf)));
 
fd_hw_query_set_stage(ctx, ctx->ring, FD_STAGE_CLEAR);
 
ctx->clear(ctx, buffers, color, depth, stencil);
 
ctx->dirty |= FD_DIRTY_ZSA |
FD_DIRTY_VIEWPORT |
FD_DIRTY_RASTERIZER |
FD_DIRTY_SAMPLE_MASK |
FD_DIRTY_PROG |
FD_DIRTY_CONSTBUF |
FD_DIRTY_BLEND;
 
if (fd_mesa_debug & FD_DBG_DCLEAR)
ctx->dirty = 0xffffffff;
}
 
static void
fd_clear_render_target(struct pipe_context *pctx, struct pipe_surface *ps,
const union pipe_color_union *color,
unsigned x, unsigned y, unsigned w, unsigned h)
{
DBG("TODO: x=%u, y=%u, w=%u, h=%u", x, y, w, h);
}
 
static void
fd_clear_depth_stencil(struct pipe_context *pctx, struct pipe_surface *ps,
unsigned buffers, double depth, unsigned stencil,
unsigned x, unsigned y, unsigned w, unsigned h)
{
DBG("TODO: buffers=%u, depth=%f, stencil=%u, x=%u, y=%u, w=%u, h=%u",
buffers, depth, stencil, x, y, w, h);
}
 
void
fd_draw_init(struct pipe_context *pctx)
{
list_inithead(&fd_context(pctx)->used_resources);
 
pctx->draw_vbo = fd_draw_vbo;
pctx->clear = fd_clear;
pctx->clear_render_target = fd_clear_render_target;
pctx->clear_depth_stencil = fd_clear_depth_stencil;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/freedreno_draw.h
0,0 → 1,147
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FREEDRENO_DRAW_H_
#define FREEDRENO_DRAW_H_
 
#include "pipe/p_state.h"
#include "pipe/p_context.h"
 
#include "freedreno_context.h"
#include "freedreno_resource.h"
#include "freedreno_screen.h"
#include "freedreno_util.h"
 
struct fd_ringbuffer;
 
void fd_draw_init(struct pipe_context *pctx);
 
static inline void
fd_draw(struct fd_context *ctx, struct fd_ringbuffer *ring,
enum pc_di_primtype primtype,
enum pc_di_vis_cull_mode vismode,
enum pc_di_src_sel src_sel, uint32_t count,
uint8_t instances,
enum pc_di_index_size idx_type,
uint32_t idx_size, uint32_t idx_offset,
struct fd_bo *idx_bo)
{
/* for debug after a lock up, write a unique counter value
* to scratch7 for each draw, to make it easier to match up
* register dumps to cmdstream. The combination of IB
* (scratch6) and DRAW is enough to "triangulate" the
* particular draw that caused lockup.
*/
emit_marker(ring, 7);
 
if (is_a3xx_p0(ctx->screen)) {
/* dummy-draw workaround: */
OUT_PKT3(ring, CP_DRAW_INDX, 3);
OUT_RING(ring, 0x00000000);
OUT_RING(ring, DRAW(1, DI_SRC_SEL_AUTO_INDEX,
INDEX_SIZE_IGN, USE_VISIBILITY, 0));
OUT_RING(ring, 0); /* NumIndices */
 
/* ugg, hard-code register offset to avoid pulling in the
* a3xx register headers into something #included from a2xx
*/
OUT_PKT0(ring, 0x2206, 1); /* A3XX_HLSQ_CONST_VSPRESV_RANGE_REG */
OUT_RING(ring, 0);
}
 
OUT_PKT3(ring, CP_DRAW_INDX, idx_bo ? 5 : 3);
OUT_RING(ring, 0x00000000); /* viz query info. */
if (vismode == USE_VISIBILITY) {
/* leave vis mode blank for now, it will be patched up when
* we know if we are binning or not
*/
OUT_RINGP(ring, DRAW(primtype, src_sel, idx_type, 0, instances),
&ctx->draw_patches);
} else {
OUT_RING(ring, DRAW(primtype, src_sel, idx_type, vismode, instances));
}
OUT_RING(ring, count); /* NumIndices */
if (idx_bo) {
OUT_RELOC(ring, idx_bo, idx_offset, 0, 0);
OUT_RING (ring, idx_size);
}
 
emit_marker(ring, 7);
 
fd_reset_wfi(ctx);
}
 
 
static inline enum pc_di_index_size
size2indextype(unsigned index_size)
{
switch (index_size) {
case 1: return INDEX_SIZE_8_BIT;
case 2: return INDEX_SIZE_16_BIT;
case 4: return INDEX_SIZE_32_BIT;
}
DBG("unsupported index size: %d", index_size);
assert(0);
return INDEX_SIZE_IGN;
}
 
/* this is same for a2xx/a3xx, so split into helper: */
static inline void
fd_draw_emit(struct fd_context *ctx, struct fd_ringbuffer *ring,
enum pc_di_primtype primtype,
enum pc_di_vis_cull_mode vismode,
const struct pipe_draw_info *info)
{
struct pipe_index_buffer *idx = &ctx->indexbuf;
struct fd_bo *idx_bo = NULL;
enum pc_di_index_size idx_type = INDEX_SIZE_IGN;
enum pc_di_src_sel src_sel;
uint32_t idx_size, idx_offset;
 
if (info->indexed) {
assert(!idx->user_buffer);
 
idx_bo = fd_resource(idx->buffer)->bo;
idx_type = size2indextype(idx->index_size);
idx_size = idx->index_size * info->count;
idx_offset = idx->offset + (info->start * idx->index_size);
src_sel = DI_SRC_SEL_DMA;
} else {
idx_bo = NULL;
idx_type = INDEX_SIZE_IGN;
idx_size = 0;
idx_offset = 0;
src_sel = DI_SRC_SEL_AUTO_INDEX;
}
 
fd_draw(ctx, ring, primtype, vismode, src_sel,
info->count, info->instance_count - 1,
idx_type, idx_size, idx_offset, idx_bo);
}
 
#endif /* FREEDRENO_DRAW_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/freedreno_fence.c
0,0 → 1,94
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "util/u_inlines.h"
 
#include "freedreno_fence.h"
#include "freedreno_context.h"
#include "freedreno_util.h"
 
struct pipe_fence_handle {
struct pipe_reference reference;
struct fd_context *ctx;
struct fd_screen *screen;
uint32_t timestamp;
};
 
void
fd_screen_fence_ref(struct pipe_screen *pscreen,
struct pipe_fence_handle **ptr,
struct pipe_fence_handle *pfence)
{
if (pipe_reference(&(*ptr)->reference, &pfence->reference))
FREE(*ptr);
 
*ptr = pfence;
}
 
/* TODO we need to spiff out libdrm_freedreno a bit to allow passing
* the timeout.. and maybe a better way to check if fence has been
* signaled. The current implementation is a bit lame for now to
* avoid bumping libdrm version requirement.
*/
 
boolean fd_screen_fence_signalled(struct pipe_screen *screen,
struct pipe_fence_handle *fence)
{
uint32_t timestamp = fd_ringbuffer_timestamp(fence->ctx->ring);
 
/* TODO util helper for compare w/ rollover? */
return timestamp >= fence->timestamp;
}
 
boolean fd_screen_fence_finish(struct pipe_screen *screen,
struct pipe_fence_handle *fence,
uint64_t timeout)
{
if (fd_pipe_wait(fence->screen->pipe, fence->timestamp))
return false;
 
return true;
}
 
struct pipe_fence_handle * fd_fence_create(struct pipe_context *pctx)
{
struct pipe_fence_handle *fence;
struct fd_context *ctx = fd_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 = fd_ringbuffer_timestamp(ctx->ring);
 
return fence;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/freedreno_fence.h
0,0 → 1,44
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FREEDRENO_FENCE_H_
#define FREEDRENO_FENCE_H_
 
#include "pipe/p_context.h"
 
void fd_screen_fence_ref(struct pipe_screen *pscreen,
struct pipe_fence_handle **ptr,
struct pipe_fence_handle *pfence);
boolean fd_screen_fence_signalled(struct pipe_screen *screen,
struct pipe_fence_handle *pfence);
boolean fd_screen_fence_finish(struct pipe_screen *screen,
struct pipe_fence_handle *pfence,
uint64_t timeout);
struct pipe_fence_handle * fd_fence_create(struct pipe_context *pctx);
 
#endif /* FREEDRENO_FENCE_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/freedreno_gmem.c
0,0 → 1,456
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "pipe/p_state.h"
#include "util/u_string.h"
#include "util/u_memory.h"
#include "util/u_inlines.h"
#include "util/u_format.h"
 
#include "freedreno_gmem.h"
#include "freedreno_context.h"
#include "freedreno_resource.h"
#include "freedreno_query_hw.h"
#include "freedreno_util.h"
 
/*
* GMEM is the small (ie. 256KiB for a200, 512KiB for a220, etc) tile buffer
* inside the GPU. All rendering happens to GMEM. Larger render targets
* are split into tiles that are small enough for the color (and depth and/or
* stencil, if enabled) buffers to fit within GMEM. Before rendering a tile,
* if there was not a clear invalidating the previous tile contents, we need
* to restore the previous tiles contents (system mem -> GMEM), and after all
* the draw calls, before moving to the next tile, we need to save the tile
* contents (GMEM -> system mem).
*
* The code in this file handles dealing with GMEM and tiling.
*
* The structure of the ringbuffer ends up being:
*
* +--<---<-- IB ---<---+---<---+---<---<---<--+
* | | | |
* v ^ ^ ^
* ------------------------------------------------------
* | clear/draw cmds | Tile0 | Tile1 | .... | TileN |
* ------------------------------------------------------
* ^
* |
* address submitted in issueibcmds
*
* Where the per-tile section handles scissor setup, mem2gmem restore (if
* needed), IB to draw cmds earlier in the ringbuffer, and then gmem2mem
* resolve.
*/
 
static uint32_t bin_width(struct fd_context *ctx)
{
if (is_a4xx(ctx->screen))
return 1024;
if (is_a3xx(ctx->screen))
return 992;
return 512;
}
 
static uint32_t
total_size(uint8_t cbuf_cpp[], uint8_t zsbuf_cpp[2],
uint32_t bin_w, uint32_t bin_h, struct fd_gmem_stateobj *gmem)
{
uint32_t total = 0, i;
 
for (i = 0; i < 4; i++) {
if (cbuf_cpp[i]) {
gmem->cbuf_base[i] = align(total, 0x4000);
total = gmem->cbuf_base[i] + cbuf_cpp[i] * bin_w * bin_h;
}
}
 
if (zsbuf_cpp[0]) {
gmem->zsbuf_base[0] = align(total, 0x4000);
total = gmem->zsbuf_base[0] + zsbuf_cpp[0] * bin_w * bin_h;
}
 
if (zsbuf_cpp[1]) {
gmem->zsbuf_base[1] = align(total, 0x4000);
total = gmem->zsbuf_base[1] + zsbuf_cpp[1] * bin_w * bin_h;
}
 
return total;
}
 
static void
calculate_tiles(struct fd_context *ctx)
{
struct fd_gmem_stateobj *gmem = &ctx->gmem;
struct pipe_scissor_state *scissor = &ctx->max_scissor;
struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
uint32_t gmem_size = ctx->screen->gmemsize_bytes;
uint32_t minx, miny, width, height;
uint32_t nbins_x = 1, nbins_y = 1;
uint32_t bin_w, bin_h;
uint32_t max_width = bin_width(ctx);
uint8_t cbuf_cpp[4] = {0}, zsbuf_cpp[2] = {0};
uint32_t i, j, t, xoff, yoff;
uint32_t tpp_x, tpp_y;
bool has_zs = !!(ctx->resolve & (FD_BUFFER_DEPTH | FD_BUFFER_STENCIL));
int tile_n[ARRAY_SIZE(ctx->pipe)];
 
if (has_zs) {
struct fd_resource *rsc = fd_resource(pfb->zsbuf->texture);
zsbuf_cpp[0] = rsc->cpp;
if (rsc->stencil)
zsbuf_cpp[1] = rsc->stencil->cpp;
}
for (i = 0; i < pfb->nr_cbufs; i++) {
if (pfb->cbufs[i])
cbuf_cpp[i] = util_format_get_blocksize(pfb->cbufs[i]->format);
else
cbuf_cpp[i] = 4;
}
 
if (!memcmp(gmem->zsbuf_cpp, zsbuf_cpp, sizeof(zsbuf_cpp)) &&
!memcmp(gmem->cbuf_cpp, cbuf_cpp, sizeof(cbuf_cpp)) &&
!memcmp(&gmem->scissor, scissor, sizeof(gmem->scissor))) {
/* everything is up-to-date */
return;
}
 
if (fd_mesa_debug & FD_DBG_NOSCIS) {
minx = 0;
miny = 0;
width = pfb->width;
height = pfb->height;
} else {
minx = scissor->minx & ~31; /* round down to multiple of 32 */
miny = scissor->miny & ~31;
width = scissor->maxx - minx;
height = scissor->maxy - miny;
}
 
bin_w = align(width, 32);
bin_h = align(height, 32);
 
/* first, find a bin width that satisfies the maximum width
* restrictions:
*/
while (bin_w > max_width) {
nbins_x++;
bin_w = align(width / nbins_x, 32);
}
 
/* then find a bin width/height that satisfies the memory
* constraints:
*/
DBG("binning input: cbuf cpp: %d %d %d %d, zsbuf cpp: %d; %dx%d",
cbuf_cpp[0], cbuf_cpp[1], cbuf_cpp[2], cbuf_cpp[3], zsbuf_cpp[0],
width, height);
while (total_size(cbuf_cpp, zsbuf_cpp, bin_w, bin_h, gmem) > gmem_size) {
if (bin_w > bin_h) {
nbins_x++;
bin_w = align(width / nbins_x, 32);
} else {
nbins_y++;
bin_h = align(height / nbins_y, 32);
}
}
 
DBG("using %d bins of size %dx%d", nbins_x*nbins_y, bin_w, bin_h);
 
gmem->scissor = *scissor;
memcpy(gmem->cbuf_cpp, cbuf_cpp, sizeof(cbuf_cpp));
memcpy(gmem->zsbuf_cpp, zsbuf_cpp, sizeof(zsbuf_cpp));
gmem->bin_h = bin_h;
gmem->bin_w = bin_w;
gmem->nbins_x = nbins_x;
gmem->nbins_y = nbins_y;
gmem->minx = minx;
gmem->miny = miny;
gmem->width = width;
gmem->height = height;
 
/*
* Assign tiles and pipes:
*
* At some point it might be worth playing with different
* strategies and seeing if that makes much impact on
* performance.
*/
 
#define div_round_up(v, a) (((v) + (a) - 1) / (a))
/* figure out number of tiles per pipe: */
tpp_x = tpp_y = 1;
while (div_round_up(nbins_y, tpp_y) > 8)
tpp_y += 2;
while ((div_round_up(nbins_y, tpp_y) *
div_round_up(nbins_x, tpp_x)) > 8)
tpp_x += 1;
 
/* configure pipes: */
xoff = yoff = 0;
for (i = 0; i < ARRAY_SIZE(ctx->pipe); i++) {
struct fd_vsc_pipe *pipe = &ctx->pipe[i];
 
if (xoff >= nbins_x) {
xoff = 0;
yoff += tpp_y;
}
 
if (yoff >= nbins_y) {
break;
}
 
pipe->x = xoff;
pipe->y = yoff;
pipe->w = MIN2(tpp_x, nbins_x - xoff);
pipe->h = MIN2(tpp_y, nbins_y - yoff);
 
xoff += tpp_x;
}
 
for (; i < ARRAY_SIZE(ctx->pipe); i++) {
struct fd_vsc_pipe *pipe = &ctx->pipe[i];
pipe->x = pipe->y = pipe->w = pipe->h = 0;
}
 
#if 0 /* debug */
printf("%dx%d ... tpp=%dx%d\n", nbins_x, nbins_y, tpp_x, tpp_y);
for (i = 0; i < 8; i++) {
struct fd_vsc_pipe *pipe = &ctx->pipe[i];
printf("pipe[%d]: %ux%u @ %u,%u\n", i,
pipe->w, pipe->h, pipe->x, pipe->y);
}
#endif
 
/* configure tiles: */
t = 0;
yoff = miny;
memset(tile_n, 0, sizeof(tile_n));
for (i = 0; i < nbins_y; i++) {
uint32_t bw, bh;
 
xoff = minx;
 
/* clip bin height: */
bh = MIN2(bin_h, miny + height - yoff);
 
for (j = 0; j < nbins_x; j++) {
struct fd_tile *tile = &ctx->tile[t];
uint32_t p;
 
assert(t < ARRAY_SIZE(ctx->tile));
 
/* pipe number: */
p = ((i / tpp_y) * div_round_up(nbins_x, tpp_x)) + (j / tpp_x);
 
/* clip bin width: */
bw = MIN2(bin_w, minx + width - xoff);
 
tile->n = tile_n[p]++;
tile->p = p;
tile->bin_w = bw;
tile->bin_h = bh;
tile->xoff = xoff;
tile->yoff = yoff;
 
t++;
 
xoff += bw;
}
 
yoff += bh;
}
 
#if 0 /* debug */
t = 0;
for (i = 0; i < nbins_y; i++) {
for (j = 0; j < nbins_x; j++) {
struct fd_tile *tile = &ctx->tile[t++];
printf("|p:%u n:%u|", tile->p, tile->n);
}
printf("\n");
}
#endif
}
 
static void
render_tiles(struct fd_context *ctx)
{
struct fd_gmem_stateobj *gmem = &ctx->gmem;
int i;
 
ctx->emit_tile_init(ctx);
 
if (ctx->restore)
ctx->stats.batch_restore++;
 
for (i = 0; i < (gmem->nbins_x * gmem->nbins_y); i++) {
struct fd_tile *tile = &ctx->tile[i];
 
DBG("bin_h=%d, yoff=%d, bin_w=%d, xoff=%d",
tile->bin_h, tile->yoff, tile->bin_w, tile->xoff);
 
ctx->emit_tile_prep(ctx, tile);
 
if (ctx->restore) {
fd_hw_query_set_stage(ctx, ctx->ring, FD_STAGE_MEM2GMEM);
ctx->emit_tile_mem2gmem(ctx, tile);
fd_hw_query_set_stage(ctx, ctx->ring, FD_STAGE_NULL);
}
 
ctx->emit_tile_renderprep(ctx, tile);
 
fd_hw_query_prepare_tile(ctx, i, ctx->ring);
 
/* emit IB to drawcmds: */
OUT_IB(ctx->ring, ctx->draw_start, ctx->draw_end);
fd_reset_wfi(ctx);
 
/* emit gmem2mem to transfer tile back to system memory: */
fd_hw_query_set_stage(ctx, ctx->ring, FD_STAGE_GMEM2MEM);
ctx->emit_tile_gmem2mem(ctx, tile);
fd_hw_query_set_stage(ctx, ctx->ring, FD_STAGE_NULL);
}
}
 
static void
render_sysmem(struct fd_context *ctx)
{
ctx->emit_sysmem_prep(ctx);
 
fd_hw_query_prepare_tile(ctx, 0, ctx->ring);
 
/* emit IB to drawcmds: */
OUT_IB(ctx->ring, ctx->draw_start, ctx->draw_end);
fd_reset_wfi(ctx);
}
 
void
fd_gmem_render_tiles(struct fd_context *ctx)
{
struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
bool sysmem = false;
 
if (ctx->emit_sysmem_prep) {
if (ctx->cleared || ctx->gmem_reason || (ctx->num_draws > 5)) {
DBG("GMEM: cleared=%x, gmem_reason=%x, num_draws=%u",
ctx->cleared, ctx->gmem_reason, ctx->num_draws);
} else if (!(fd_mesa_debug & FD_DBG_NOBYPASS)) {
sysmem = true;
}
}
 
/* close out the draw cmds by making sure any active queries are
* paused:
*/
fd_hw_query_set_stage(ctx, ctx->ring, FD_STAGE_NULL);
 
/* mark the end of the clear/draw cmds before emitting per-tile cmds: */
fd_ringmarker_mark(ctx->draw_end);
fd_ringmarker_mark(ctx->binning_end);
 
fd_reset_wfi(ctx);
 
ctx->stats.batch_total++;
 
if (sysmem) {
DBG("rendering sysmem (%s/%s)",
util_format_short_name(pipe_surface_format(pfb->cbufs[0])),
util_format_short_name(pipe_surface_format(pfb->zsbuf)));
fd_hw_query_prepare(ctx, 1);
render_sysmem(ctx);
ctx->stats.batch_sysmem++;
} else {
struct fd_gmem_stateobj *gmem = &ctx->gmem;
calculate_tiles(ctx);
DBG("rendering %dx%d tiles (%s/%s)", gmem->nbins_x, gmem->nbins_y,
util_format_short_name(pipe_surface_format(pfb->cbufs[0])),
util_format_short_name(pipe_surface_format(pfb->zsbuf)));
fd_hw_query_prepare(ctx, gmem->nbins_x * gmem->nbins_y);
render_tiles(ctx);
ctx->stats.batch_gmem++;
}
 
/* GPU executes starting from tile cmds, which IB back to draw cmds: */
fd_ringmarker_flush(ctx->draw_end);
 
/* mark start for next draw/binning cmds: */
fd_ringmarker_mark(ctx->draw_start);
fd_ringmarker_mark(ctx->binning_start);
 
fd_reset_wfi(ctx);
 
/* reset maximal bounds: */
ctx->max_scissor.minx = ctx->max_scissor.miny = ~0;
ctx->max_scissor.maxx = ctx->max_scissor.maxy = 0;
 
ctx->dirty = ~0;
}
 
/* tile needs restore if it isn't completely contained within the
* cleared scissor:
*/
static bool
skip_restore(struct pipe_scissor_state *scissor, struct fd_tile *tile)
{
unsigned minx = tile->xoff;
unsigned maxx = tile->xoff + tile->bin_w;
unsigned miny = tile->yoff;
unsigned maxy = tile->yoff + tile->bin_h;
return (minx >= scissor->minx) && (maxx <= scissor->maxx) &&
(miny >= scissor->miny) && (maxy <= scissor->maxy);
}
 
/* When deciding whether a tile needs mem2gmem, we need to take into
* account the scissor rect(s) that were cleared. To simplify we only
* consider the last scissor rect for each buffer, since the common
* case would be a single clear.
*/
bool
fd_gmem_needs_restore(struct fd_context *ctx, struct fd_tile *tile,
uint32_t buffers)
{
if (!(ctx->restore & buffers))
return false;
 
/* if buffers partially cleared, then slow-path to figure out
* if this particular tile needs restoring:
*/
if ((buffers & FD_BUFFER_COLOR) &&
(ctx->partial_cleared & FD_BUFFER_COLOR) &&
skip_restore(&ctx->cleared_scissor.color, tile))
return false;
if ((buffers & FD_BUFFER_DEPTH) &&
(ctx->partial_cleared & FD_BUFFER_DEPTH) &&
skip_restore(&ctx->cleared_scissor.depth, tile))
return false;
if ((buffers & FD_BUFFER_STENCIL) &&
(ctx->partial_cleared & FD_BUFFER_STENCIL) &&
skip_restore(&ctx->cleared_scissor.stencil, tile))
return false;
 
return true;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/freedreno_gmem.h
0,0 → 1,67
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FREEDRENO_GMEM_H_
#define FREEDRENO_GMEM_H_
 
#include "pipe/p_context.h"
 
/* per-pipe configuration for hw binning: */
struct fd_vsc_pipe {
struct fd_bo *bo;
uint8_t x, y, w, h; /* VSC_PIPE[p].CONFIG */
};
 
/* per-tile configuration for hw binning: */
struct fd_tile {
uint8_t p; /* index into vsc_pipe[]s */
uint8_t n; /* slot within pipe */
uint16_t bin_w, bin_h;
uint16_t xoff, yoff;
};
 
struct fd_gmem_stateobj {
struct pipe_scissor_state scissor;
uint32_t cbuf_base[4];
uint32_t zsbuf_base[2];
uint8_t cbuf_cpp[4];
uint8_t zsbuf_cpp[2];
uint16_t bin_h, nbins_y;
uint16_t bin_w, nbins_x;
uint16_t minx, miny;
uint16_t width, height;
};
 
struct fd_context;
 
void fd_gmem_render_tiles(struct fd_context *ctx);
 
bool fd_gmem_needs_restore(struct fd_context *ctx, struct fd_tile *tile,
uint32_t buffers);
 
#endif /* FREEDRENO_GMEM_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/freedreno_program.c
0,0 → 1,161
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "tgsi/tgsi_text.h"
#include "tgsi/tgsi_ureg.h"
 
#include "freedreno_program.h"
#include "freedreno_context.h"
 
static void
fd_fp_state_bind(struct pipe_context *pctx, void *hwcso)
{
struct fd_context *ctx = fd_context(pctx);
ctx->prog.fp = hwcso;
ctx->prog.dirty |= FD_SHADER_DIRTY_FP;
ctx->dirty |= FD_DIRTY_PROG;
}
 
static void
fd_vp_state_bind(struct pipe_context *pctx, void *hwcso)
{
struct fd_context *ctx = fd_context(pctx);
ctx->prog.vp = hwcso;
ctx->prog.dirty |= FD_SHADER_DIRTY_VP;
ctx->dirty |= FD_DIRTY_PROG;
}
 
static const char *solid_fp =
"FRAG \n"
"PROPERTY FS_COLOR0_WRITES_ALL_CBUFS 1 \n"
"DCL CONST[0] \n"
"DCL OUT[0], COLOR \n"
" 0: MOV OUT[0], CONST[0] \n"
" 1: END \n";
 
static const char *solid_vp =
"VERT \n"
"DCL IN[0] \n"
"DCL OUT[0], POSITION \n"
" 0: MOV OUT[0], IN[0] \n"
" 1: END \n";
 
static const char *blit_vp =
"VERT \n"
"DCL IN[0] \n"
"DCL IN[1] \n"
"DCL OUT[0], TEXCOORD[0] \n"
"DCL OUT[1], POSITION \n"
" 0: MOV OUT[0], IN[0] \n"
" 0: MOV OUT[1], IN[1] \n"
" 1: END \n";
 
static void * assemble_tgsi(struct pipe_context *pctx,
const char *src, bool frag)
{
struct tgsi_token toks[32];
struct pipe_shader_state cso = {
.tokens = toks,
};
 
tgsi_text_translate(src, toks, ARRAY_SIZE(toks));
 
if (frag)
return pctx->create_fs_state(pctx, &cso);
else
return pctx->create_vs_state(pctx, &cso);
}
 
static void *
fd_prog_blit(struct pipe_context *pctx, int rts, bool depth)
{
int i;
struct ureg_src tc;
struct ureg_program *ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
if (!ureg)
return NULL;
 
tc = ureg_DECL_fs_input(
ureg, TGSI_SEMANTIC_GENERIC, 0, TGSI_INTERPOLATE_PERSPECTIVE);
for (i = 0; i < rts; i++)
ureg_TEX(ureg, ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, i),
TGSI_TEXTURE_2D, tc, ureg_DECL_sampler(ureg, i));
if (depth)
ureg_TEX(ureg,
ureg_writemask(
ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0),
TGSI_WRITEMASK_Z),
TGSI_TEXTURE_2D, tc, ureg_DECL_sampler(ureg, rts));
 
ureg_END(ureg);
 
return ureg_create_shader_and_destroy(ureg, pctx);
}
 
 
void fd_prog_init(struct pipe_context *pctx)
{
struct fd_context *ctx = fd_context(pctx);
int i;
 
pctx->bind_fs_state = fd_fp_state_bind;
pctx->bind_vs_state = fd_vp_state_bind;
 
// XXX for now, let a2xx keep it's own hand-rolled shaders
// for solid and blit progs:
if (ctx->screen->gpu_id < 300)
return;
 
ctx->solid_prog.fp = assemble_tgsi(pctx, solid_fp, true);
ctx->solid_prog.vp = assemble_tgsi(pctx, solid_vp, false);
ctx->blit_prog[0].vp = assemble_tgsi(pctx, blit_vp, false);
ctx->blit_prog[0].fp = fd_prog_blit(pctx, 1, false);
for (i = 1; i < ctx->screen->max_rts; i++) {
ctx->blit_prog[i].vp = ctx->blit_prog[0].vp;
ctx->blit_prog[i].fp = fd_prog_blit(pctx, i + 1, false);
}
 
ctx->blit_z.vp = ctx->blit_prog[0].vp;
ctx->blit_z.fp = fd_prog_blit(pctx, 0, true);
ctx->blit_zs.vp = ctx->blit_prog[0].vp;
ctx->blit_zs.fp = fd_prog_blit(pctx, 1, true);
}
 
void fd_prog_fini(struct pipe_context *pctx)
{
struct fd_context *ctx = fd_context(pctx);
int i;
 
pctx->delete_vs_state(pctx, ctx->solid_prog.vp);
pctx->delete_fs_state(pctx, ctx->solid_prog.fp);
pctx->delete_vs_state(pctx, ctx->blit_prog[0].vp);
for (i = 0; i < ctx->screen->max_rts; i++)
pctx->delete_fs_state(pctx, ctx->blit_prog[i].fp);
pctx->delete_fs_state(pctx, ctx->blit_z.fp);
pctx->delete_fs_state(pctx, ctx->blit_zs.fp);
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/freedreno_program.h
0,0 → 1,37
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FREEDRENO_PROGRAM_H_
#define FREEDRENO_PROGRAM_H_
 
#include "pipe/p_context.h"
 
void fd_prog_init(struct pipe_context *pctx);
void fd_prog_fini(struct pipe_context *pctx);
 
#endif /* FREEDRENO_PROGRAM_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/freedreno_query.c
0,0 → 1,121
/* -*- mode: C; c-file-style: "k&r"; ttxab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "pipe/p_state.h"
#include "util/u_memory.h"
 
#include "freedreno_query.h"
#include "freedreno_query_sw.h"
#include "freedreno_query_hw.h"
#include "freedreno_context.h"
#include "freedreno_util.h"
 
/*
* Pipe Query interface:
*/
 
static struct pipe_query *
fd_create_query(struct pipe_context *pctx, unsigned query_type, unsigned index)
{
struct fd_context *ctx = fd_context(pctx);
struct fd_query *q;
 
q = fd_sw_create_query(ctx, query_type);
if (!q)
q = fd_hw_create_query(ctx, query_type);
 
return (struct pipe_query *) q;
}
 
static void
fd_destroy_query(struct pipe_context *pctx, struct pipe_query *pq)
{
struct fd_query *q = fd_query(pq);
q->funcs->destroy_query(fd_context(pctx), q);
}
 
static boolean
fd_begin_query(struct pipe_context *pctx, struct pipe_query *pq)
{
struct fd_query *q = fd_query(pq);
return q->funcs->begin_query(fd_context(pctx), q);
}
 
static void
fd_end_query(struct pipe_context *pctx, struct pipe_query *pq)
{
struct fd_query *q = fd_query(pq);
q->funcs->end_query(fd_context(pctx), q);
}
 
static boolean
fd_get_query_result(struct pipe_context *pctx, struct pipe_query *pq,
boolean wait, union pipe_query_result *result)
{
struct fd_query *q = fd_query(pq);
return q->funcs->get_query_result(fd_context(pctx), q, wait, result);
}
 
static int
fd_get_driver_query_info(struct pipe_screen *pscreen,
unsigned index, struct pipe_driver_query_info *info)
{
struct pipe_driver_query_info list[] = {
{"draw-calls", FD_QUERY_DRAW_CALLS, {0}},
{"batches", FD_QUERY_BATCH_TOTAL, {0}},
{"batches-sysmem", FD_QUERY_BATCH_SYSMEM, {0}},
{"batches-gmem", FD_QUERY_BATCH_GMEM, {0}},
{"restores", FD_QUERY_BATCH_RESTORE, {0}},
{"prims-emitted", PIPE_QUERY_PRIMITIVES_EMITTED, {0}},
};
 
if (!info)
return ARRAY_SIZE(list);
 
if (index >= ARRAY_SIZE(list))
return 0;
 
*info = list[index];
return 1;
}
 
void
fd_query_screen_init(struct pipe_screen *pscreen)
{
pscreen->get_driver_query_info = fd_get_driver_query_info;
}
 
void
fd_query_context_init(struct pipe_context *pctx)
{
pctx->create_query = fd_create_query;
pctx->destroy_query = fd_destroy_query;
pctx->begin_query = fd_begin_query;
pctx->end_query = fd_end_query;
pctx->get_query_result = fd_get_query_result;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/freedreno_query.h
0,0 → 1,68
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FREEDRENO_QUERY_H_
#define FREEDRENO_QUERY_H_
 
#include "pipe/p_context.h"
 
struct fd_context;
struct fd_query;
 
struct fd_query_funcs {
void (*destroy_query)(struct fd_context *ctx,
struct fd_query *q);
boolean (*begin_query)(struct fd_context *ctx, struct fd_query *q);
void (*end_query)(struct fd_context *ctx, struct fd_query *q);
boolean (*get_query_result)(struct fd_context *ctx,
struct fd_query *q, boolean wait,
union pipe_query_result *result);
};
 
struct fd_query {
const struct fd_query_funcs *funcs;
bool active;
int type;
};
 
static inline struct fd_query *
fd_query(struct pipe_query *pq)
{
return (struct fd_query *)pq;
}
 
#define FD_QUERY_DRAW_CALLS (PIPE_QUERY_DRIVER_SPECIFIC + 0)
#define FD_QUERY_BATCH_TOTAL (PIPE_QUERY_DRIVER_SPECIFIC + 1) /* total # of batches (submits) */
#define FD_QUERY_BATCH_SYSMEM (PIPE_QUERY_DRIVER_SPECIFIC + 2) /* batches using system memory (GMEM bypass) */
#define FD_QUERY_BATCH_GMEM (PIPE_QUERY_DRIVER_SPECIFIC + 3) /* batches using GMEM */
#define FD_QUERY_BATCH_RESTORE (PIPE_QUERY_DRIVER_SPECIFIC + 4) /* batches requiring GMEM restore */
 
void fd_query_screen_init(struct pipe_screen *pscreen);
void fd_query_context_init(struct pipe_context *pctx);
 
#endif /* FREEDRENO_QUERY_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/freedreno_query_hw.c
0,0 → 1,467
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "pipe/p_state.h"
#include "util/u_memory.h"
#include "util/u_inlines.h"
 
#include "freedreno_query_hw.h"
#include "freedreno_context.h"
#include "freedreno_util.h"
 
struct fd_hw_sample_period {
struct fd_hw_sample *start, *end;
struct list_head list;
};
 
/* maps query_type to sample provider idx: */
static int pidx(unsigned query_type)
{
switch (query_type) {
case PIPE_QUERY_OCCLUSION_COUNTER:
return 0;
case PIPE_QUERY_OCCLUSION_PREDICATE:
return 1;
default:
return -1;
}
}
 
static struct fd_hw_sample *
get_sample(struct fd_context *ctx, struct fd_ringbuffer *ring,
unsigned query_type)
{
struct fd_hw_sample *samp = NULL;
int idx = pidx(query_type);
 
if (!ctx->sample_cache[idx]) {
ctx->sample_cache[idx] =
ctx->sample_providers[idx]->get_sample(ctx, ring);
}
 
fd_hw_sample_reference(ctx, &samp, ctx->sample_cache[idx]);
 
return samp;
}
 
static void
clear_sample_cache(struct fd_context *ctx)
{
int i;
 
for (i = 0; i < ARRAY_SIZE(ctx->sample_cache); i++)
fd_hw_sample_reference(ctx, &ctx->sample_cache[i], NULL);
}
 
static bool
is_active(struct fd_hw_query *hq, enum fd_render_stage stage)
{
return !!(hq->provider->active & stage);
}
 
 
static void
resume_query(struct fd_context *ctx, struct fd_hw_query *hq,
struct fd_ringbuffer *ring)
{
assert(!hq->period);
hq->period = util_slab_alloc(&ctx->sample_period_pool);
list_inithead(&hq->period->list);
hq->period->start = get_sample(ctx, ring, hq->base.type);
/* NOTE: util_slab_alloc() does not zero out the buffer: */
hq->period->end = NULL;
}
 
static void
pause_query(struct fd_context *ctx, struct fd_hw_query *hq,
struct fd_ringbuffer *ring)
{
assert(hq->period && !hq->period->end);
hq->period->end = get_sample(ctx, ring, hq->base.type);
list_addtail(&hq->period->list, &hq->current_periods);
hq->period = NULL;
}
 
static void
destroy_periods(struct fd_context *ctx, struct list_head *list)
{
struct fd_hw_sample_period *period, *s;
LIST_FOR_EACH_ENTRY_SAFE(period, s, list, list) {
fd_hw_sample_reference(ctx, &period->start, NULL);
fd_hw_sample_reference(ctx, &period->end, NULL);
list_del(&period->list);
util_slab_free(&ctx->sample_period_pool, period);
}
}
 
static void
fd_hw_destroy_query(struct fd_context *ctx, struct fd_query *q)
{
struct fd_hw_query *hq = fd_hw_query(q);
 
destroy_periods(ctx, &hq->periods);
destroy_periods(ctx, &hq->current_periods);
list_del(&hq->list);
 
free(hq);
}
 
static boolean
fd_hw_begin_query(struct fd_context *ctx, struct fd_query *q)
{
struct fd_hw_query *hq = fd_hw_query(q);
if (q->active)
return false;
 
/* begin_query() should clear previous results: */
destroy_periods(ctx, &hq->periods);
 
if (is_active(hq, ctx->stage))
resume_query(ctx, hq, ctx->ring);
 
q->active = true;
 
/* add to active list: */
list_del(&hq->list);
list_addtail(&hq->list, &ctx->active_queries);
return true;
}
 
static void
fd_hw_end_query(struct fd_context *ctx, struct fd_query *q)
{
struct fd_hw_query *hq = fd_hw_query(q);
if (!q->active)
return;
if (is_active(hq, ctx->stage))
pause_query(ctx, hq, ctx->ring);
q->active = false;
/* move to current list: */
list_del(&hq->list);
list_addtail(&hq->list, &ctx->current_queries);
}
 
/* helper to get ptr to specified sample: */
static void * sampptr(struct fd_hw_sample *samp, uint32_t n, void *ptr)
{
return ((char *)ptr) + (samp->tile_stride * n) + samp->offset;
}
 
static boolean
fd_hw_get_query_result(struct fd_context *ctx, struct fd_query *q,
boolean wait, union pipe_query_result *result)
{
struct fd_hw_query *hq = fd_hw_query(q);
const struct fd_hw_sample_provider *p = hq->provider;
struct fd_hw_sample_period *period;
 
if (q->active)
return false;
 
/* if the app tries to read back the query result before the
* batch is submitted, that forces us to flush so that there
* are actually results to wait for:
*/
if (!LIST_IS_EMPTY(&hq->list)) {
/* if app didn't actually trigger any cmdstream, then
* we have nothing to do:
*/
if (!ctx->needs_flush)
return true;
DBG("reading query result forces flush!");
fd_context_render(&ctx->base);
}
 
util_query_clear_result(result, q->type);
 
if (LIST_IS_EMPTY(&hq->periods))
return true;
 
assert(LIST_IS_EMPTY(&hq->list));
assert(LIST_IS_EMPTY(&hq->current_periods));
assert(!hq->period);
 
/* if !wait, then check the last sample (the one most likely to
* not be ready yet) and bail if it is not ready:
*/
if (!wait) {
int ret;
 
period = LIST_ENTRY(struct fd_hw_sample_period,
hq->periods.prev, list);
 
ret = fd_bo_cpu_prep(period->end->bo, ctx->screen->pipe,
DRM_FREEDRENO_PREP_READ | DRM_FREEDRENO_PREP_NOSYNC);
if (ret)
return false;
 
fd_bo_cpu_fini(period->end->bo);
}
 
/* sum the result across all sample periods: */
LIST_FOR_EACH_ENTRY(period, &hq->periods, list) {
struct fd_hw_sample *start = period->start;
struct fd_hw_sample *end = period->end;
unsigned i;
 
/* start and end samples should be from same batch: */
assert(start->bo == end->bo);
assert(start->num_tiles == end->num_tiles);
 
for (i = 0; i < start->num_tiles; i++) {
void *ptr;
 
fd_bo_cpu_prep(start->bo, ctx->screen->pipe,
DRM_FREEDRENO_PREP_READ);
 
ptr = fd_bo_map(start->bo);
 
p->accumulate_result(ctx, sampptr(period->start, i, ptr),
sampptr(period->end, i, ptr), result);
 
fd_bo_cpu_fini(start->bo);
}
}
 
return true;
}
 
static const struct fd_query_funcs hw_query_funcs = {
.destroy_query = fd_hw_destroy_query,
.begin_query = fd_hw_begin_query,
.end_query = fd_hw_end_query,
.get_query_result = fd_hw_get_query_result,
};
 
struct fd_query *
fd_hw_create_query(struct fd_context *ctx, unsigned query_type)
{
struct fd_hw_query *hq;
struct fd_query *q;
int idx = pidx(query_type);
 
if ((idx < 0) || !ctx->sample_providers[idx])
return NULL;
 
hq = CALLOC_STRUCT(fd_hw_query);
if (!hq)
return NULL;
 
hq->provider = ctx->sample_providers[idx];
 
list_inithead(&hq->periods);
list_inithead(&hq->current_periods);
list_inithead(&hq->list);
 
q = &hq->base;
q->funcs = &hw_query_funcs;
q->type = query_type;
 
return q;
}
 
struct fd_hw_sample *
fd_hw_sample_init(struct fd_context *ctx, uint32_t size)
{
struct fd_hw_sample *samp = util_slab_alloc(&ctx->sample_pool);
pipe_reference_init(&samp->reference, 1);
samp->size = size;
samp->offset = ctx->next_sample_offset;
/* NOTE: util_slab_alloc() does not zero out the buffer: */
samp->bo = NULL;
samp->num_tiles = 0;
samp->tile_stride = 0;
ctx->next_sample_offset += size;
return samp;
}
 
void
__fd_hw_sample_destroy(struct fd_context *ctx, struct fd_hw_sample *samp)
{
if (samp->bo)
fd_bo_del(samp->bo);
util_slab_free(&ctx->sample_pool, samp);
}
 
static void
prepare_sample(struct fd_hw_sample *samp, struct fd_bo *bo,
uint32_t num_tiles, uint32_t tile_stride)
{
if (samp->bo) {
assert(samp->bo == bo);
assert(samp->num_tiles == num_tiles);
assert(samp->tile_stride == tile_stride);
return;
}
samp->bo = bo;
samp->num_tiles = num_tiles;
samp->tile_stride = tile_stride;
}
 
static void
prepare_query(struct fd_hw_query *hq, struct fd_bo *bo,
uint32_t num_tiles, uint32_t tile_stride)
{
struct fd_hw_sample_period *period, *s;
 
/* prepare all the samples in the query: */
LIST_FOR_EACH_ENTRY_SAFE(period, s, &hq->current_periods, list) {
prepare_sample(period->start, bo, num_tiles, tile_stride);
prepare_sample(period->end, bo, num_tiles, tile_stride);
 
/* move from current_periods list to periods list: */
list_del(&period->list);
list_addtail(&period->list, &hq->periods);
}
}
 
static void
prepare_queries(struct fd_context *ctx, struct fd_bo *bo,
uint32_t num_tiles, uint32_t tile_stride,
struct list_head *list, bool remove)
{
struct fd_hw_query *hq, *s;
LIST_FOR_EACH_ENTRY_SAFE(hq, s, list, list) {
prepare_query(hq, bo, num_tiles, tile_stride);
if (remove)
list_delinit(&hq->list);
}
}
 
/* called from gmem code once total storage requirements are known (ie.
* number of samples times number of tiles)
*/
void
fd_hw_query_prepare(struct fd_context *ctx, uint32_t num_tiles)
{
uint32_t tile_stride = ctx->next_sample_offset;
struct fd_bo *bo;
 
if (ctx->query_bo)
fd_bo_del(ctx->query_bo);
 
if (tile_stride > 0) {
bo = fd_bo_new(ctx->dev, tile_stride * num_tiles,
DRM_FREEDRENO_GEM_CACHE_WCOMBINE |
DRM_FREEDRENO_GEM_TYPE_KMEM);
} else {
bo = NULL;
}
 
ctx->query_bo = bo;
ctx->query_tile_stride = tile_stride;
 
prepare_queries(ctx, bo, num_tiles, tile_stride,
&ctx->active_queries, false);
prepare_queries(ctx, bo, num_tiles, tile_stride,
&ctx->current_queries, true);
 
/* reset things for next batch: */
ctx->next_sample_offset = 0;
}
 
void
fd_hw_query_prepare_tile(struct fd_context *ctx, uint32_t n,
struct fd_ringbuffer *ring)
{
uint32_t tile_stride = ctx->query_tile_stride;
uint32_t offset = tile_stride * n;
 
/* bail if no queries: */
if (tile_stride == 0)
return;
 
fd_wfi(ctx, ring);
OUT_PKT0 (ring, HW_QUERY_BASE_REG, 1);
OUT_RELOCW(ring, ctx->query_bo, offset, 0, 0);
}
 
void
fd_hw_query_set_stage(struct fd_context *ctx, struct fd_ringbuffer *ring,
enum fd_render_stage stage)
{
/* special case: internal blits (like mipmap level generation)
* go through normal draw path (via util_blitter_blit()).. but
* we need to ignore the FD_STAGE_DRAW which will be set, so we
* don't enable queries which should be paused during internal
* blits:
*/
if ((ctx->stage == FD_STAGE_BLIT) &&
(stage != FD_STAGE_NULL))
return;
 
if (stage != ctx->stage) {
struct fd_hw_query *hq;
LIST_FOR_EACH_ENTRY(hq, &ctx->active_queries, list) {
bool was_active = is_active(hq, ctx->stage);
bool now_active = is_active(hq, stage);
 
if (now_active && !was_active)
resume_query(ctx, hq, ring);
else if (was_active && !now_active)
pause_query(ctx, hq, ring);
}
}
clear_sample_cache(ctx);
ctx->stage = stage;
}
 
void
fd_hw_query_register_provider(struct pipe_context *pctx,
const struct fd_hw_sample_provider *provider)
{
struct fd_context *ctx = fd_context(pctx);
int idx = pidx(provider->query_type);
 
assert((0 <= idx) && (idx < MAX_HW_SAMPLE_PROVIDERS));
assert(!ctx->sample_providers[idx]);
 
ctx->sample_providers[idx] = provider;
}
 
void
fd_hw_query_init(struct pipe_context *pctx)
{
struct fd_context *ctx = fd_context(pctx);
 
util_slab_create(&ctx->sample_pool, sizeof(struct fd_hw_sample),
16, UTIL_SLAB_SINGLETHREADED);
util_slab_create(&ctx->sample_period_pool, sizeof(struct fd_hw_sample_period),
16, UTIL_SLAB_SINGLETHREADED);
list_inithead(&ctx->active_queries);
list_inithead(&ctx->current_queries);
}
 
void
fd_hw_query_fini(struct pipe_context *pctx)
{
struct fd_context *ctx = fd_context(pctx);
 
util_slab_destroy(&ctx->sample_pool);
util_slab_destroy(&ctx->sample_period_pool);
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/freedreno_query_hw.h
0,0 → 1,164
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FREEDRENO_QUERY_HW_H_
#define FREEDRENO_QUERY_HW_H_
 
#include "util/list.h"
 
#include "freedreno_query.h"
#include "freedreno_context.h"
 
 
/*
* HW Queries:
*
* See: https://github.com/freedreno/freedreno/wiki/Queries#hardware-queries
*
* Hardware queries will be specific to gpu generation, but they need
* some common infrastructure for triggering start/stop samples at
* various points (for example, to exclude mem2gmem/gmem2mem or clear)
* as well as per tile tracking.
*
* NOTE: in at least some cases hw writes sample values to memory addr
* specified in some register. So we don't really have the option to
* just sample the same counter multiple times for multiple different
* queries with the same query_type. So we cache per sample provider
* the most recent sample since the last draw. This way multiple
* sample periods for multiple queries can reference the same sample.
*
* fd_hw_sample_provider:
* - one per query type, registered/implemented by gpu generation
* specific code
* - can construct fd_hw_samples on demand
* - most recent sample (since last draw) cached so multiple
* different queries can ref the same sample
*
* fd_hw_sample:
* - abstracts one snapshot of counter value(s) across N tiles
* - backing object not allocated until submit time when number
* of samples and number of tiles is known
*
* fd_hw_sample_period:
* - consists of start and stop sample
* - a query accumulates a list of sample periods
* - the query result is the sum of the sample periods
*/
 
struct fd_hw_sample_provider {
unsigned query_type;
 
/* stages applicable to the query type: */
enum fd_render_stage active;
 
/* when a new sample is required, emit appropriate cmdstream
* and return a sample object:
*/
struct fd_hw_sample *(*get_sample)(struct fd_context *ctx,
struct fd_ringbuffer *ring);
 
/* accumulate the results from specified sample period: */
void (*accumulate_result)(struct fd_context *ctx,
const void *start, const void *end,
union pipe_query_result *result);
};
 
struct fd_hw_sample {
struct pipe_reference reference; /* keep this first */
 
/* offset and size of the sample are know at the time the
* sample is constructed.
*/
uint32_t size;
uint32_t offset;
 
/* backing object, offset/stride/etc are determined not when
* the sample is constructed, but when the batch is submitted.
* This way we can defer allocation until total # of requested
* samples, and total # of tiles, is known.
*/
struct fd_bo *bo;
uint32_t num_tiles;
uint32_t tile_stride;
};
 
struct fd_hw_sample_period;
 
struct fd_hw_query {
struct fd_query base;
 
const struct fd_hw_sample_provider *provider;
 
/* list of fd_hw_sample_period in previous submits: */
struct list_head periods;
 
/* list of fd_hw_sample_period's in current submit: */
struct list_head current_periods;
 
/* if active and not paused, the current sample period (not
* yet added to current_periods):
*/
struct fd_hw_sample_period *period;
 
struct list_head list; /* list-node in ctx->active_queries */
};
 
static inline struct fd_hw_query *
fd_hw_query(struct fd_query *q)
{
return (struct fd_hw_query *)q;
}
 
struct fd_query * fd_hw_create_query(struct fd_context *ctx, unsigned query_type);
/* helper for sample providers: */
struct fd_hw_sample * fd_hw_sample_init(struct fd_context *ctx, uint32_t size);
/* don't call directly, use fd_hw_sample_reference() */
void __fd_hw_sample_destroy(struct fd_context *ctx, struct fd_hw_sample *samp);
void fd_hw_query_prepare(struct fd_context *ctx, uint32_t num_tiles);
void fd_hw_query_prepare_tile(struct fd_context *ctx, uint32_t n,
struct fd_ringbuffer *ring);
void fd_hw_query_set_stage(struct fd_context *ctx,
struct fd_ringbuffer *ring, enum fd_render_stage stage);
void fd_hw_query_register_provider(struct pipe_context *pctx,
const struct fd_hw_sample_provider *provider);
void fd_hw_query_init(struct pipe_context *pctx);
void fd_hw_query_fini(struct pipe_context *pctx);
 
static inline void
fd_hw_sample_reference(struct fd_context *ctx,
struct fd_hw_sample **ptr, struct fd_hw_sample *samp)
{
struct fd_hw_sample *old_samp = *ptr;
 
if (pipe_reference(&(*ptr)->reference, &samp->reference))
__fd_hw_sample_destroy(ctx, old_samp);
if (ptr)
*ptr = samp;
}
 
#endif /* FREEDRENO_QUERY_HW_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/freedreno_query_sw.c
0,0 → 1,166
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "pipe/p_state.h"
#include "util/u_string.h"
#include "util/u_memory.h"
#include "util/u_inlines.h"
#include "os/os_time.h"
 
#include "freedreno_query_sw.h"
#include "freedreno_context.h"
#include "freedreno_util.h"
 
/*
* SW Queries:
*
* In the core, we have some support for basic sw counters
*/
 
static void
fd_sw_destroy_query(struct fd_context *ctx, struct fd_query *q)
{
struct fd_sw_query *sq = fd_sw_query(q);
free(sq);
}
 
static uint64_t
read_counter(struct fd_context *ctx, int type)
{
switch (type) {
case PIPE_QUERY_PRIMITIVES_GENERATED:
/* for now same thing as _PRIMITIVES_EMITTED */
case PIPE_QUERY_PRIMITIVES_EMITTED:
return ctx->stats.prims_emitted;
case FD_QUERY_DRAW_CALLS:
return ctx->stats.draw_calls;
case FD_QUERY_BATCH_TOTAL:
return ctx->stats.batch_total;
case FD_QUERY_BATCH_SYSMEM:
return ctx->stats.batch_sysmem;
case FD_QUERY_BATCH_GMEM:
return ctx->stats.batch_gmem;
case FD_QUERY_BATCH_RESTORE:
return ctx->stats.batch_restore;
}
return 0;
}
 
static bool
is_rate_query(struct fd_query *q)
{
switch (q->type) {
case FD_QUERY_BATCH_TOTAL:
case FD_QUERY_BATCH_SYSMEM:
case FD_QUERY_BATCH_GMEM:
case FD_QUERY_BATCH_RESTORE:
return true;
default:
return false;
}
}
 
static boolean
fd_sw_begin_query(struct fd_context *ctx, struct fd_query *q)
{
struct fd_sw_query *sq = fd_sw_query(q);
q->active = true;
sq->begin_value = read_counter(ctx, q->type);
if (is_rate_query(q))
sq->begin_time = os_time_get();
return true;
}
 
static void
fd_sw_end_query(struct fd_context *ctx, struct fd_query *q)
{
struct fd_sw_query *sq = fd_sw_query(q);
q->active = false;
sq->end_value = read_counter(ctx, q->type);
if (is_rate_query(q))
sq->end_time = os_time_get();
}
 
static boolean
fd_sw_get_query_result(struct fd_context *ctx, struct fd_query *q,
boolean wait, union pipe_query_result *result)
{
struct fd_sw_query *sq = fd_sw_query(q);
 
if (q->active)
return false;
 
util_query_clear_result(result, q->type);
 
result->u64 = sq->end_value - sq->begin_value;
 
if (is_rate_query(q)) {
double fps = (result->u64 * 1000000) /
(double)(sq->end_time - sq->begin_time);
result->u64 = (uint64_t)fps;
}
 
return true;
}
 
static const struct fd_query_funcs sw_query_funcs = {
.destroy_query = fd_sw_destroy_query,
.begin_query = fd_sw_begin_query,
.end_query = fd_sw_end_query,
.get_query_result = fd_sw_get_query_result,
};
 
struct fd_query *
fd_sw_create_query(struct fd_context *ctx, unsigned query_type)
{
struct fd_sw_query *sq;
struct fd_query *q;
 
switch (query_type) {
case PIPE_QUERY_PRIMITIVES_GENERATED:
case PIPE_QUERY_PRIMITIVES_EMITTED:
case FD_QUERY_DRAW_CALLS:
case FD_QUERY_BATCH_TOTAL:
case FD_QUERY_BATCH_SYSMEM:
case FD_QUERY_BATCH_GMEM:
case FD_QUERY_BATCH_RESTORE:
break;
default:
return NULL;
}
 
sq = CALLOC_STRUCT(fd_sw_query);
if (!sq)
return NULL;
 
q = &sq->base;
q->funcs = &sw_query_funcs;
q->type = query_type;
 
return q;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/freedreno_query_sw.h
0,0 → 1,55
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FREEDRENO_QUERY_SW_H_
#define FREEDRENO_QUERY_SW_H_
 
#include "freedreno_query.h"
 
/*
* SW Queries:
*
* In the core, we have some support for basic sw counters
*/
 
struct fd_sw_query {
struct fd_query base;
uint64_t begin_value, end_value;
uint64_t begin_time, end_time;
};
 
static inline struct fd_sw_query *
fd_sw_query(struct fd_query *q)
{
return (struct fd_sw_query *)q;
}
 
struct fd_query * fd_sw_create_query(struct fd_context *ctx,
unsigned query_type);
 
#endif /* FREEDRENO_QUERY_SW_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/freedreno_resource.c
0,0 → 1,703
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "util/u_format.h"
#include "util/u_format_zs.h"
#include "util/u_inlines.h"
#include "util/u_transfer.h"
#include "util/u_string.h"
#include "util/u_surface.h"
 
#include "freedreno_resource.h"
#include "freedreno_screen.h"
#include "freedreno_surface.h"
#include "freedreno_context.h"
#include "freedreno_query_hw.h"
#include "freedreno_util.h"
 
#include <errno.h>
 
static void
fd_invalidate_resource(struct fd_context *ctx, struct pipe_resource *prsc)
{
int i;
 
/* Go through the entire state and see if the resource is bound
* anywhere. If it is, mark the relevant state as dirty. This is called on
* realloc_bo.
*/
 
/* Constbufs */
for (i = 1; i < PIPE_MAX_CONSTANT_BUFFERS && !(ctx->dirty & FD_DIRTY_CONSTBUF); i++) {
if (ctx->constbuf[PIPE_SHADER_VERTEX].cb[i].buffer == prsc)
ctx->dirty |= FD_DIRTY_CONSTBUF;
if (ctx->constbuf[PIPE_SHADER_FRAGMENT].cb[i].buffer == prsc)
ctx->dirty |= FD_DIRTY_CONSTBUF;
}
 
/* VBOs */
for (i = 0; i < ctx->vtx.vertexbuf.count && !(ctx->dirty & FD_DIRTY_VTXBUF); i++) {
if (ctx->vtx.vertexbuf.vb[i].buffer == prsc)
ctx->dirty |= FD_DIRTY_VTXBUF;
}
 
/* Index buffer */
if (ctx->indexbuf.buffer == prsc)
ctx->dirty |= FD_DIRTY_INDEXBUF;
 
/* Textures */
for (i = 0; i < ctx->verttex.num_textures && !(ctx->dirty & FD_DIRTY_VERTTEX); i++) {
if (ctx->verttex.textures[i]->texture == prsc)
ctx->dirty |= FD_DIRTY_VERTTEX;
}
for (i = 0; i < ctx->fragtex.num_textures && !(ctx->dirty & FD_DIRTY_FRAGTEX); i++) {
if (ctx->fragtex.textures[i]->texture == prsc)
ctx->dirty |= FD_DIRTY_FRAGTEX;
}
}
 
static void
realloc_bo(struct fd_resource *rsc, uint32_t size)
{
struct fd_screen *screen = fd_screen(rsc->base.b.screen);
uint32_t flags = DRM_FREEDRENO_GEM_CACHE_WCOMBINE |
DRM_FREEDRENO_GEM_TYPE_KMEM; /* TODO */
 
/* if we start using things other than write-combine,
* be sure to check for PIPE_RESOURCE_FLAG_MAP_COHERENT
*/
 
if (rsc->bo)
fd_bo_del(rsc->bo);
 
rsc->bo = fd_bo_new(screen->dev, size, flags);
rsc->timestamp = 0;
rsc->dirty = rsc->reading = false;
list_delinit(&rsc->list);
util_range_set_empty(&rsc->valid_buffer_range);
}
 
/* Currently this is only used for flushing Z32_S8 texture transfers, but
* eventually it should handle everything.
*/
static void
fd_resource_flush(struct fd_transfer *trans, const struct pipe_box *box)
{
struct fd_resource *rsc = fd_resource(trans->base.resource);
struct fd_resource_slice *slice = fd_resource_slice(rsc, trans->base.level);
struct fd_resource_slice *sslice = fd_resource_slice(rsc->stencil, trans->base.level);
enum pipe_format format = trans->base.resource->format;
 
float *depth = fd_bo_map(rsc->bo) + slice->offset +
(trans->base.box.y + box->y) * slice->pitch * 4 + (trans->base.box.x + box->x) * 4;
uint8_t *stencil = fd_bo_map(rsc->stencil->bo) + sslice->offset +
(trans->base.box.y + box->y) * sslice->pitch + trans->base.box.x + box->x;
 
assert(format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT ||
format == PIPE_FORMAT_X32_S8X24_UINT);
 
if (format != PIPE_FORMAT_X32_S8X24_UINT)
util_format_z32_float_s8x24_uint_unpack_z_float(
depth, slice->pitch * 4,
trans->staging, trans->base.stride,
box->width, box->height);
 
util_format_z32_float_s8x24_uint_unpack_s_8uint(
stencil, sslice->pitch,
trans->staging, trans->base.stride,
box->width, box->height);
}
 
static void fd_resource_transfer_flush_region(struct pipe_context *pctx,
struct pipe_transfer *ptrans,
const struct pipe_box *box)
{
struct fd_resource *rsc = fd_resource(ptrans->resource);
struct fd_transfer *trans = fd_transfer(ptrans);
 
if (ptrans->resource->target == PIPE_BUFFER)
util_range_add(&rsc->valid_buffer_range,
ptrans->box.x + box->x,
ptrans->box.x + box->x + box->width);
 
if (trans->staging)
fd_resource_flush(trans, box);
}
 
static void
fd_resource_transfer_unmap(struct pipe_context *pctx,
struct pipe_transfer *ptrans)
{
struct fd_context *ctx = fd_context(pctx);
struct fd_resource *rsc = fd_resource(ptrans->resource);
struct fd_transfer *trans = fd_transfer(ptrans);
 
if (trans->staging && !(ptrans->usage & PIPE_TRANSFER_FLUSH_EXPLICIT)) {
struct pipe_box box;
u_box_2d(0, 0, ptrans->box.width, ptrans->box.height, &box);
fd_resource_flush(trans, &box);
}
 
if (!(ptrans->usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
fd_bo_cpu_fini(rsc->bo);
if (rsc->stencil)
fd_bo_cpu_fini(rsc->stencil->bo);
}
 
util_range_add(&rsc->valid_buffer_range,
ptrans->box.x,
ptrans->box.x + ptrans->box.width);
 
pipe_resource_reference(&ptrans->resource, NULL);
util_slab_free(&ctx->transfer_pool, ptrans);
 
if (trans->staging)
free(trans->staging);
}
 
static void *
fd_resource_transfer_map(struct pipe_context *pctx,
struct pipe_resource *prsc,
unsigned level, unsigned usage,
const struct pipe_box *box,
struct pipe_transfer **pptrans)
{
struct fd_context *ctx = fd_context(pctx);
struct fd_resource *rsc = fd_resource(prsc);
struct fd_resource_slice *slice = fd_resource_slice(rsc, level);
struct fd_transfer *trans;
struct pipe_transfer *ptrans;
enum pipe_format format = prsc->format;
uint32_t op = 0;
uint32_t offset;
char *buf;
int ret = 0;
 
DBG("prsc=%p, level=%u, usage=%x, box=%dx%d+%d,%d", prsc, level, usage,
box->width, box->height, box->x, box->y);
 
ptrans = util_slab_alloc(&ctx->transfer_pool);
if (!ptrans)
return NULL;
 
/* util_slab_alloc() doesn't zero: */
trans = fd_transfer(ptrans);
memset(trans, 0, sizeof(*trans));
 
pipe_resource_reference(&ptrans->resource, prsc);
ptrans->level = level;
ptrans->usage = usage;
ptrans->box = *box;
ptrans->stride = slice->pitch * rsc->cpp;
ptrans->layer_stride = slice->size0;
 
if (usage & PIPE_TRANSFER_READ)
op |= DRM_FREEDRENO_PREP_READ;
 
if (usage & PIPE_TRANSFER_WRITE)
op |= DRM_FREEDRENO_PREP_WRITE;
 
if (usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) {
realloc_bo(rsc, fd_bo_size(rsc->bo));
if (rsc->stencil)
realloc_bo(rsc->stencil, fd_bo_size(rsc->stencil->bo));
fd_invalidate_resource(ctx, prsc);
} else if ((usage & PIPE_TRANSFER_WRITE) &&
prsc->target == PIPE_BUFFER &&
!util_ranges_intersect(&rsc->valid_buffer_range,
box->x, box->x + box->width)) {
/* We are trying to write to a previously uninitialized range. No need
* to wait.
*/
} else if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
/* If the GPU is writing to the resource, or if it is reading from the
* resource and we're trying to write to it, flush the renders.
*/
if (rsc->dirty || (rsc->stencil && rsc->stencil->dirty) ||
((ptrans->usage & PIPE_TRANSFER_WRITE) && rsc->reading))
fd_context_render(pctx);
 
/* The GPU keeps track of how the various bo's are being used, and
* will wait if necessary for the proper operation to have
* completed.
*/
ret = fd_bo_cpu_prep(rsc->bo, ctx->screen->pipe, op);
if (ret)
goto fail;
}
 
buf = fd_bo_map(rsc->bo);
if (!buf) {
fd_resource_transfer_unmap(pctx, ptrans);
return NULL;
}
 
if (rsc->layer_first) {
offset = slice->offset +
box->y / util_format_get_blockheight(format) * ptrans->stride +
box->x / util_format_get_blockwidth(format) * rsc->cpp +
box->z * rsc->layer_size;
} else {
offset = slice->offset +
box->y / util_format_get_blockheight(format) * ptrans->stride +
box->x / util_format_get_blockwidth(format) * rsc->cpp +
box->z * slice->size0;
}
 
if (prsc->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT ||
prsc->format == PIPE_FORMAT_X32_S8X24_UINT) {
trans->base.stride = trans->base.box.width * rsc->cpp * 2;
trans->staging = malloc(trans->base.stride * trans->base.box.height);
if (!trans->staging)
goto fail;
 
/* if we're not discarding the whole range (or resource), we must copy
* the real data in.
*/
if (!(usage & (PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE |
PIPE_TRANSFER_DISCARD_RANGE))) {
struct fd_resource_slice *sslice =
fd_resource_slice(rsc->stencil, level);
void *sbuf = fd_bo_map(rsc->stencil->bo);
if (!sbuf)
goto fail;
 
float *depth = (float *)(buf + slice->offset +
box->y * slice->pitch * 4 + box->x * 4);
uint8_t *stencil = sbuf + sslice->offset +
box->y * sslice->pitch + box->x;
 
if (format != PIPE_FORMAT_X32_S8X24_UINT)
util_format_z32_float_s8x24_uint_pack_z_float(
trans->staging, trans->base.stride,
depth, slice->pitch * 4,
box->width, box->height);
 
util_format_z32_float_s8x24_uint_pack_s_8uint(
trans->staging, trans->base.stride,
stencil, sslice->pitch,
box->width, box->height);
}
 
buf = trans->staging;
offset = 0;
}
 
*pptrans = ptrans;
 
return buf + offset;
 
fail:
fd_resource_transfer_unmap(pctx, ptrans);
return NULL;
}
 
static void
fd_resource_destroy(struct pipe_screen *pscreen,
struct pipe_resource *prsc)
{
struct fd_resource *rsc = fd_resource(prsc);
if (rsc->bo)
fd_bo_del(rsc->bo);
list_delinit(&rsc->list);
util_range_destroy(&rsc->valid_buffer_range);
FREE(rsc);
}
 
static boolean
fd_resource_get_handle(struct pipe_screen *pscreen,
struct pipe_resource *prsc,
struct winsys_handle *handle)
{
struct fd_resource *rsc = fd_resource(prsc);
 
return fd_screen_bo_get_handle(pscreen, rsc->bo,
rsc->slices[0].pitch * rsc->cpp, handle);
}
 
 
static const struct u_resource_vtbl fd_resource_vtbl = {
.resource_get_handle = fd_resource_get_handle,
.resource_destroy = fd_resource_destroy,
.transfer_map = fd_resource_transfer_map,
.transfer_flush_region = fd_resource_transfer_flush_region,
.transfer_unmap = fd_resource_transfer_unmap,
.transfer_inline_write = u_default_transfer_inline_write,
};
 
static uint32_t
setup_slices(struct fd_resource *rsc, uint32_t alignment)
{
struct pipe_resource *prsc = &rsc->base.b;
uint32_t level, size = 0;
uint32_t width = prsc->width0;
uint32_t height = prsc->height0;
uint32_t depth = prsc->depth0;
/* in layer_first layout, the level (slice) contains just one
* layer (since in fact the layer contains the slices)
*/
uint32_t layers_in_level = rsc->layer_first ? 1 : prsc->array_size;
 
for (level = 0; level <= prsc->last_level; level++) {
struct fd_resource_slice *slice = fd_resource_slice(rsc, level);
 
slice->pitch = width = align(width, 32);
slice->offset = size;
/* 1d array and 2d array textures must all have the same layer size
* for each miplevel on a3xx. 3d textures can have different layer
* sizes for high levels, but the hw auto-sizer is buggy (or at least
* different than what this code does), so as soon as the layer size
* range gets into range, we stop reducing it.
*/
if (prsc->target == PIPE_TEXTURE_3D && (
level == 1 ||
(level > 1 && rsc->slices[level - 1].size0 > 0xf000)))
slice->size0 = align(slice->pitch * height * rsc->cpp, alignment);
else if (level == 0 || rsc->layer_first || alignment == 1)
slice->size0 = align(slice->pitch * height * rsc->cpp, alignment);
else
slice->size0 = rsc->slices[level - 1].size0;
 
size += slice->size0 * depth * layers_in_level;
 
width = u_minify(width, 1);
height = u_minify(height, 1);
depth = u_minify(depth, 1);
}
 
return size;
}
 
static uint32_t
slice_alignment(struct pipe_screen *pscreen, const struct pipe_resource *tmpl)
{
/* on a3xx, 2d array and 3d textures seem to want their
* layers aligned to page boundaries:
*/
switch (tmpl->target) {
case PIPE_TEXTURE_3D:
case PIPE_TEXTURE_1D_ARRAY:
case PIPE_TEXTURE_2D_ARRAY:
return 4096;
default:
return 1;
}
}
 
/**
* Create a new texture object, using the given template info.
*/
static struct pipe_resource *
fd_resource_create(struct pipe_screen *pscreen,
const struct pipe_resource *tmpl)
{
struct fd_resource *rsc = CALLOC_STRUCT(fd_resource);
struct pipe_resource *prsc = &rsc->base.b;
uint32_t size;
 
DBG("target=%d, format=%s, %ux%ux%u, array_size=%u, last_level=%u, "
"nr_samples=%u, usage=%u, bind=%x, flags=%x",
tmpl->target, util_format_name(tmpl->format),
tmpl->width0, tmpl->height0, tmpl->depth0,
tmpl->array_size, tmpl->last_level, tmpl->nr_samples,
tmpl->usage, tmpl->bind, tmpl->flags);
 
if (!rsc)
return NULL;
 
*prsc = *tmpl;
 
pipe_reference_init(&prsc->reference, 1);
list_inithead(&rsc->list);
prsc->screen = pscreen;
 
util_range_init(&rsc->valid_buffer_range);
 
rsc->base.vtbl = &fd_resource_vtbl;
if (tmpl->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT)
rsc->cpp = util_format_get_blocksize(PIPE_FORMAT_Z32_FLOAT);
else
rsc->cpp = util_format_get_blocksize(tmpl->format);
 
assert(rsc->cpp);
 
if (is_a4xx(fd_screen(pscreen))) {
switch (tmpl->target) {
case PIPE_TEXTURE_3D:
/* TODO 3D_ARRAY? */
rsc->layer_first = false;
break;
default:
rsc->layer_first = true;
break;
}
}
 
size = setup_slices(rsc, slice_alignment(pscreen, tmpl));
 
if (rsc->layer_first) {
rsc->layer_size = align(size, 4096);
size = rsc->layer_size * prsc->array_size;
}
 
realloc_bo(rsc, size);
if (!rsc->bo)
goto fail;
 
/* There is no native Z32F_S8 sampling or rendering format, so this must
* be emulated via two separate textures. The depth texture still keeps
* its Z32F_S8 format though, and we also keep a reference to a separate
* S8 texture.
*/
if (tmpl->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT) {
struct pipe_resource stencil = *tmpl;
stencil.format = PIPE_FORMAT_S8_UINT;
rsc->stencil = fd_resource(fd_resource_create(pscreen, &stencil));
if (!rsc->stencil)
goto fail;
}
 
return prsc;
fail:
fd_resource_destroy(pscreen, prsc);
return NULL;
}
 
/**
* Create a texture from a winsys_handle. The handle is often created in
* another process by first creating a pipe texture and then calling
* resource_get_handle.
*/
static struct pipe_resource *
fd_resource_from_handle(struct pipe_screen *pscreen,
const struct pipe_resource *tmpl,
struct winsys_handle *handle)
{
struct fd_resource *rsc = CALLOC_STRUCT(fd_resource);
struct fd_resource_slice *slice = &rsc->slices[0];
struct pipe_resource *prsc = &rsc->base.b;
 
DBG("target=%d, format=%s, %ux%ux%u, array_size=%u, last_level=%u, "
"nr_samples=%u, usage=%u, bind=%x, flags=%x",
tmpl->target, util_format_name(tmpl->format),
tmpl->width0, tmpl->height0, tmpl->depth0,
tmpl->array_size, tmpl->last_level, tmpl->nr_samples,
tmpl->usage, tmpl->bind, tmpl->flags);
 
if (!rsc)
return NULL;
 
*prsc = *tmpl;
 
pipe_reference_init(&prsc->reference, 1);
list_inithead(&rsc->list);
prsc->screen = pscreen;
 
util_range_init(&rsc->valid_buffer_range);
 
rsc->bo = fd_screen_bo_from_handle(pscreen, handle, &slice->pitch);
if (!rsc->bo)
goto fail;
 
rsc->base.vtbl = &fd_resource_vtbl;
rsc->cpp = util_format_get_blocksize(tmpl->format);
slice->pitch /= rsc->cpp;
 
assert(rsc->cpp);
 
return prsc;
 
fail:
fd_resource_destroy(pscreen, prsc);
return NULL;
}
 
static void fd_blitter_pipe_begin(struct fd_context *ctx);
static void fd_blitter_pipe_end(struct fd_context *ctx);
 
/**
* _copy_region using pipe (3d engine)
*/
static bool
fd_blitter_pipe_copy_region(struct fd_context *ctx,
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)
{
/* not until we allow rendertargets to be buffers */
if (dst->target == PIPE_BUFFER || src->target == PIPE_BUFFER)
return false;
 
if (!util_blitter_is_copy_supported(ctx->blitter, dst, src))
return false;
 
fd_blitter_pipe_begin(ctx);
util_blitter_copy_texture(ctx->blitter,
dst, dst_level, dstx, dsty, dstz,
src, src_level, src_box);
fd_blitter_pipe_end(ctx);
 
return true;
}
 
/**
* Copy a block of pixels from one resource to another.
* The resource must be of the same format.
* Resources with nr_samples > 1 are not allowed.
*/
static void
fd_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 fd_context *ctx = fd_context(pctx);
 
/* TODO if we have 2d core, or other DMA engine that could be used
* for simple copies and reasonably easily synchronized with the 3d
* core, this is where we'd plug it in..
*/
 
/* try blit on 3d pipe: */
if (fd_blitter_pipe_copy_region(ctx,
dst, dst_level, dstx, dsty, dstz,
src, src_level, src_box))
return;
 
/* else fallback to pure sw: */
util_resource_copy_region(pctx,
dst, dst_level, dstx, dsty, dstz,
src, src_level, src_box);
}
 
/**
* Optimal hardware path for blitting pixels.
* Scaling, format conversion, up- and downsampling (resolve) are allowed.
*/
static void
fd_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info)
{
struct fd_context *ctx = fd_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 (util_try_blit_via_copy_region(pctx, &info)) {
return; /* done */
}
 
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;
}
 
fd_blitter_pipe_begin(ctx);
util_blitter_blit(ctx->blitter, &info);
fd_blitter_pipe_end(ctx);
}
 
static void
fd_blitter_pipe_begin(struct fd_context *ctx)
{
util_blitter_save_vertex_buffer_slot(ctx->blitter, ctx->vtx.vertexbuf.vb);
util_blitter_save_vertex_elements(ctx->blitter, ctx->vtx.vtx);
util_blitter_save_vertex_shader(ctx->blitter, ctx->prog.vp);
util_blitter_save_rasterizer(ctx->blitter, ctx->rasterizer);
util_blitter_save_viewport(ctx->blitter, &ctx->viewport);
util_blitter_save_scissor(ctx->blitter, &ctx->scissor);
util_blitter_save_fragment_shader(ctx->blitter, ctx->prog.fp);
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);
util_blitter_save_sample_mask(ctx->blitter, ctx->sample_mask);
util_blitter_save_framebuffer(ctx->blitter, &ctx->framebuffer);
util_blitter_save_fragment_sampler_states(ctx->blitter,
ctx->fragtex.num_samplers,
(void **)ctx->fragtex.samplers);
util_blitter_save_fragment_sampler_views(ctx->blitter,
ctx->fragtex.num_textures, ctx->fragtex.textures);
 
fd_hw_query_set_stage(ctx, ctx->ring, FD_STAGE_BLIT);
}
 
static void
fd_blitter_pipe_end(struct fd_context *ctx)
{
fd_hw_query_set_stage(ctx, ctx->ring, FD_STAGE_NULL);
}
 
static void
fd_flush_resource(struct pipe_context *pctx, struct pipe_resource *prsc)
{
struct fd_resource *rsc = fd_resource(prsc);
 
if (rsc->dirty || (rsc->stencil && rsc->stencil->dirty))
fd_context_render(pctx);
}
 
void
fd_resource_screen_init(struct pipe_screen *pscreen)
{
pscreen->resource_create = fd_resource_create;
pscreen->resource_from_handle = fd_resource_from_handle;
pscreen->resource_get_handle = u_resource_get_handle_vtbl;
pscreen->resource_destroy = u_resource_destroy_vtbl;
}
 
void
fd_resource_context_init(struct pipe_context *pctx)
{
pctx->transfer_map = u_transfer_map_vtbl;
pctx->transfer_flush_region = u_transfer_flush_region_vtbl;
pctx->transfer_unmap = u_transfer_unmap_vtbl;
pctx->transfer_inline_write = u_transfer_inline_write_vtbl;
pctx->create_surface = fd_create_surface;
pctx->surface_destroy = fd_surface_destroy;
pctx->resource_copy_region = fd_resource_copy_region;
pctx->blit = fd_blit;
pctx->flush_resource = fd_flush_resource;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/freedreno_resource.h
0,0 → 1,123
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FREEDRENO_RESOURCE_H_
#define FREEDRENO_RESOURCE_H_
 
#include "util/list.h"
#include "util/u_range.h"
#include "util/u_transfer.h"
 
#include "freedreno_util.h"
 
/* Texture Layout on a3xx:
*
* Each mipmap-level contains all of it's layers (ie. all cubmap
* faces, all 1d/2d array elements, etc). The texture sampler is
* programmed with the start address of each mipmap level, and hw
* derives the layer offset within the level.
*
* Texture Layout on a4xx:
*
* For cubemap and 2d array, each layer contains all of it's mipmap
* levels (layer_first layout).
*
* 3d textures are layed out as on a3xx, but unknown about 3d-array
* textures.
*
* In either case, the slice represents the per-miplevel information,
* but in layer_first layout it only includes the first layer, and
* an additional offset of (rsc->layer_size * layer) must be added.
*/
struct fd_resource_slice {
uint32_t offset; /* offset of first layer in slice */
uint32_t pitch;
uint32_t size0; /* size of first layer in slice */
};
 
struct fd_resource {
struct u_resource base;
struct fd_bo *bo;
uint32_t cpp;
bool layer_first; /* see above description */
uint32_t layer_size;
struct fd_resource_slice slices[MAX_MIP_LEVELS];
uint32_t timestamp;
bool dirty, reading;
/* buffer range that has been initialized */
struct util_range valid_buffer_range;
 
/* reference to the resource holding stencil data for a z32_s8 texture */
struct fd_resource *stencil;
 
struct list_head list;
};
 
static INLINE struct fd_resource *
fd_resource(struct pipe_resource *ptex)
{
return (struct fd_resource *)ptex;
}
 
struct fd_transfer {
struct pipe_transfer base;
void *staging;
};
 
static INLINE struct fd_transfer *
fd_transfer(struct pipe_transfer *ptrans)
{
return (struct fd_transfer *)ptrans;
}
 
static INLINE struct fd_resource_slice *
fd_resource_slice(struct fd_resource *rsc, unsigned level)
{
assert(level <= rsc->base.b.last_level);
return &rsc->slices[level];
}
 
/* get offset for specified mipmap level and texture/array layer */
static INLINE uint32_t
fd_resource_offset(struct fd_resource *rsc, unsigned level, unsigned layer)
{
struct fd_resource_slice *slice = fd_resource_slice(rsc, level);
unsigned offset;
if (rsc->layer_first) {
offset = slice->offset + (rsc->layer_size * layer);
} else {
offset = slice->offset + (slice->size0 * layer);
}
debug_assert(offset < fd_bo_size(rsc->bo));
return offset;
}
 
void fd_resource_screen_init(struct pipe_screen *pscreen);
void fd_resource_context_init(struct pipe_context *pctx);
 
#endif /* FREEDRENO_RESOURCE_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/freedreno_screen.c
0,0 → 1,561
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
 
#include "pipe/p_defines.h"
#include "pipe/p_screen.h"
#include "pipe/p_state.h"
 
#include "util/u_memory.h"
#include "util/u_inlines.h"
#include "util/u_format.h"
#include "util/u_format_s3tc.h"
#include "util/u_string.h"
#include "util/u_debug.h"
 
#include "os/os_time.h"
 
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
 
#include "freedreno_screen.h"
#include "freedreno_resource.h"
#include "freedreno_fence.h"
#include "freedreno_query.h"
#include "freedreno_util.h"
 
#include "a2xx/fd2_screen.h"
#include "a3xx/fd3_screen.h"
#include "a4xx/fd4_screen.h"
 
/* XXX this should go away */
#include "state_tracker/drm_driver.h"
 
static const struct debug_named_value debug_options[] = {
{"msgs", FD_DBG_MSGS, "Print debug messages"},
{"disasm", FD_DBG_DISASM, "Dump TGSI and adreno shader disassembly"},
{"dclear", FD_DBG_DCLEAR, "Mark all state dirty after clear"},
{"flush", FD_DBG_FLUSH, "Force flush after every draw"},
{"noscis", FD_DBG_NOSCIS, "Disable scissor optimization"},
{"direct", FD_DBG_DIRECT, "Force inline (SS_DIRECT) state loads"},
{"nobypass", FD_DBG_NOBYPASS, "Disable GMEM bypass"},
{"fraghalf", FD_DBG_FRAGHALF, "Use half-precision in fragment shader"},
{"nobin", FD_DBG_NOBIN, "Disable hw binning"},
{"optmsgs", FD_DBG_OPTMSGS,"Enable optimizer debug messages"},
{"optdump", FD_DBG_OPTDUMP,"Dump shader DAG to .dot files"},
{"glsl120", FD_DBG_GLSL120,"Temporary flag to force GLSL 120 (rather than 130) on a3xx+"},
{"nocp", FD_DBG_NOCP, "Disable copy-propagation"},
{"nir", FD_DBG_NIR, "Enable experimental NIR compiler"},
DEBUG_NAMED_VALUE_END
};
 
DEBUG_GET_ONCE_FLAGS_OPTION(fd_mesa_debug, "FD_MESA_DEBUG", debug_options, 0)
 
int fd_mesa_debug = 0;
bool fd_binning_enabled = true;
static bool glsl120 = false;
 
static const char *
fd_screen_get_name(struct pipe_screen *pscreen)
{
static char buffer[128];
util_snprintf(buffer, sizeof(buffer), "FD%03d",
fd_screen(pscreen)->device_id);
return buffer;
}
 
static const char *
fd_screen_get_vendor(struct pipe_screen *pscreen)
{
return "freedreno";
}
 
static const char *
fd_screen_get_device_vendor(struct pipe_screen *pscreen)
{
return "Qualcomm";
}
 
 
static uint64_t
fd_screen_get_timestamp(struct pipe_screen *pscreen)
{
int64_t cpu_time = os_time_get() * 1000;
return cpu_time + fd_screen(pscreen)->cpu_gpu_time_delta;
}
 
static void
fd_screen_destroy(struct pipe_screen *pscreen)
{
struct fd_screen *screen = fd_screen(pscreen);
 
if (screen->pipe)
fd_pipe_del(screen->pipe);
 
if (screen->dev)
fd_device_del(screen->dev);
 
free(screen);
}
 
/*
TODO either move caps to a2xx/a3xx specific code, or maybe have some
tables for things that differ if the delta is not too much..
*/
static int
fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
{
struct fd_screen *screen = fd_screen(pscreen);
 
/* this is probably not totally correct.. but it's a start: */
switch (param) {
/* Supported features (boolean caps). */
case PIPE_CAP_NPOT_TEXTURES:
case PIPE_CAP_MIXED_FRAMEBUFFER_SIZES:
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_TEXTURE_SWIZZLE:
case PIPE_CAP_MIXED_COLORBUFFER_FORMATS:
case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT:
case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER:
case PIPE_CAP_SEAMLESS_CUBE_MAP:
case PIPE_CAP_VERTEX_COLOR_UNCLAMPED:
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_BUFFER_MAP_PERSISTENT_COHERENT:
case PIPE_CAP_VERTEXID_NOBASE:
return 1;
 
case PIPE_CAP_SHADER_STENCIL_EXPORT:
case PIPE_CAP_TGSI_TEXCOORD:
case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER:
case PIPE_CAP_CONDITIONAL_RENDER:
case PIPE_CAP_TEXTURE_MULTISAMPLE:
case PIPE_CAP_TEXTURE_BARRIER:
case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
case PIPE_CAP_CUBE_MAP_ARRAY:
case PIPE_CAP_TEXTURE_BUFFER_OBJECTS:
case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
case PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE:
case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS:
case PIPE_CAP_START_INSTANCE:
case PIPE_CAP_COMPUTE:
return 0;
 
case PIPE_CAP_SM3:
case PIPE_CAP_PRIMITIVE_RESTART:
case PIPE_CAP_TGSI_INSTANCEID:
case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR:
return is_a3xx(screen) || is_a4xx(screen);
 
case PIPE_CAP_INDEP_BLEND_ENABLE:
case PIPE_CAP_INDEP_BLEND_FUNC:
case PIPE_CAP_DEPTH_CLIP_DISABLE:
return is_a3xx(screen);
 
case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:
return 256;
 
case PIPE_CAP_GLSL_FEATURE_LEVEL:
if (glsl120)
return 120;
return (is_a3xx(screen) || is_a4xx(screen)) ? 130 : 120;
 
/* Unsupported features. */
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_HALF_INTEGER:
case PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS:
case PIPE_CAP_FRAGMENT_COLOR_CLAMPED:
case PIPE_CAP_VERTEX_COLOR_CLAMPED:
case PIPE_CAP_USER_VERTEX_BUFFERS:
case PIPE_CAP_USER_INDEX_BUFFERS:
case PIPE_CAP_QUERY_PIPELINE_STATISTICS:
case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK:
case PIPE_CAP_TGSI_VS_LAYER_VIEWPORT:
case PIPE_CAP_MAX_TEXTURE_GATHER_COMPONENTS:
case PIPE_CAP_TEXTURE_GATHER_SM5:
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_POLYGON_OFFSET_CLAMP:
case PIPE_CAP_MULTISAMPLE_Z_RESOLVE:
case PIPE_CAP_RESOURCE_FROM_USER_MEMORY:
case PIPE_CAP_DEVICE_RESET_STATUS_QUERY:
return 0;
 
case PIPE_CAP_MAX_VIEWPORTS:
return 1;
 
/* 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 2048;
 
/* Texturing. */
case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
return MAX_MIP_LEVELS;
case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
return 11;
 
case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS:
return (is_a3xx(screen) || is_a4xx(screen)) ? 256 : 0;
 
/* Render targets. */
case PIPE_CAP_MAX_RENDER_TARGETS:
return screen->max_rts;
 
/* Queries. */
case PIPE_CAP_QUERY_TIME_ELAPSED:
case PIPE_CAP_QUERY_TIMESTAMP:
return 0;
case PIPE_CAP_OCCLUSION_QUERY:
/* TODO still missing on a4xx, but we lie to get gl2..
* it's not a feature, it's a bug!
*/
return is_a3xx(screen) || is_a4xx(screen);
 
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_ENDIANNESS:
return PIPE_ENDIAN_LITTLE;
 
case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT:
return 64;
 
case PIPE_CAP_VENDOR_ID:
return 0x5143;
case PIPE_CAP_DEVICE_ID:
return 0xFFFFFFFF;
case PIPE_CAP_ACCELERATED:
return 1;
case PIPE_CAP_VIDEO_MEMORY:
DBG("FINISHME: The value returned is incorrect\n");
return 10;
case PIPE_CAP_UMA:
return 1;
}
debug_printf("unknown param %d\n", param);
return 0;
}
 
static float
fd_screen_get_paramf(struct pipe_screen *pscreen, enum pipe_capf param)
{
switch (param) {
case PIPE_CAPF_MAX_LINE_WIDTH:
case PIPE_CAPF_MAX_LINE_WIDTH_AA:
case PIPE_CAPF_MAX_POINT_WIDTH:
case PIPE_CAPF_MAX_POINT_WIDTH_AA:
return 4092.0f;
case PIPE_CAPF_MAX_TEXTURE_ANISOTROPY:
return 16.0f;
case PIPE_CAPF_MAX_TEXTURE_LOD_BIAS:
return 15.0f;
case PIPE_CAPF_GUARD_BAND_LEFT:
case PIPE_CAPF_GUARD_BAND_TOP:
case PIPE_CAPF_GUARD_BAND_RIGHT:
case PIPE_CAPF_GUARD_BAND_BOTTOM:
return 0.0f;
}
debug_printf("unknown paramf %d\n", param);
return 0;
}
 
static int
fd_screen_get_shader_param(struct pipe_screen *pscreen, unsigned shader,
enum pipe_shader_cap param)
{
struct fd_screen *screen = fd_screen(pscreen);
 
switch(shader)
{
case PIPE_SHADER_FRAGMENT:
case PIPE_SHADER_VERTEX:
break;
case PIPE_SHADER_COMPUTE:
case PIPE_SHADER_GEOMETRY:
/* maye we could emulate.. */
return 0;
default:
DBG("unknown shader type %d", shader);
return 0;
}
 
/* this is probably not totally correct.. but it's a start: */
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 16384;
case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH:
return 8; /* XXX */
case PIPE_SHADER_CAP_MAX_INPUTS:
case PIPE_SHADER_CAP_MAX_OUTPUTS:
return 16;
case PIPE_SHADER_CAP_MAX_TEMPS:
return 64; /* Max native temporaries. */
case PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE:
/* NOTE: seems to be limit for a3xx is actually 512 but
* split between VS and FS. Use lower limit of 256 to
* avoid getting into impossible situations:
*/
return ((is_a3xx(screen) || is_a4xx(screen)) ? 4096 : 64) * sizeof(float[4]);
case PIPE_SHADER_CAP_MAX_CONST_BUFFERS:
return (is_a3xx(screen) || is_a4xx(screen)) ? 16 : 1;
case PIPE_SHADER_CAP_MAX_PREDS:
return 0; /* nothing uses this */
case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED:
return 1;
case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR:
case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR:
case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR:
case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR:
return 1;
case PIPE_SHADER_CAP_SUBROUTINES:
case PIPE_SHADER_CAP_DOUBLES:
case PIPE_SHADER_CAP_TGSI_DROUND_SUPPORTED:
case PIPE_SHADER_CAP_TGSI_DFRACEXP_DLDEXP_SUPPORTED:
case PIPE_SHADER_CAP_TGSI_FMA_SUPPORTED:
return 0;
case PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED:
return 1;
case PIPE_SHADER_CAP_INTEGERS:
if (glsl120)
return 0;
return (is_a3xx(screen) || is_a4xx(screen)) ? 1 : 0;
case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:
case PIPE_SHADER_CAP_MAX_SAMPLER_VIEWS:
return 16;
case PIPE_SHADER_CAP_PREFERRED_IR:
return PIPE_SHADER_IR_TGSI;
}
debug_printf("unknown shader param %d\n", param);
return 0;
}
 
boolean
fd_screen_bo_get_handle(struct pipe_screen *pscreen,
struct fd_bo *bo,
unsigned stride,
struct winsys_handle *whandle)
{
whandle->stride = stride;
 
if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) {
return fd_bo_get_name(bo, &whandle->handle) == 0;
} else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) {
whandle->handle = fd_bo_handle(bo);
return TRUE;
} else if (whandle->type == DRM_API_HANDLE_TYPE_FD) {
whandle->handle = fd_bo_dmabuf(bo);
return TRUE;
} else {
return FALSE;
}
}
 
struct fd_bo *
fd_screen_bo_from_handle(struct pipe_screen *pscreen,
struct winsys_handle *whandle,
unsigned *out_stride)
{
struct fd_screen *screen = fd_screen(pscreen);
struct fd_bo *bo;
 
if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) {
bo = fd_bo_from_name(screen->dev, whandle->handle);
} else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) {
bo = fd_bo_from_handle(screen->dev, whandle->handle, 0);
} else if (whandle->type == DRM_API_HANDLE_TYPE_FD) {
bo = fd_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 *
fd_screen_create(struct fd_device *dev)
{
struct fd_screen *screen = CALLOC_STRUCT(fd_screen);
struct pipe_screen *pscreen;
uint64_t val;
 
fd_mesa_debug = debug_get_option_fd_mesa_debug();
 
if (fd_mesa_debug & FD_DBG_NOBIN)
fd_binning_enabled = false;
 
glsl120 = !!(fd_mesa_debug & FD_DBG_GLSL120);
 
if (!screen)
return NULL;
 
pscreen = &screen->base;
 
screen->dev = dev;
 
// maybe this should be in context?
screen->pipe = fd_pipe_new(screen->dev, FD_PIPE_3D);
if (!screen->pipe) {
DBG("could not create 3d pipe");
goto fail;
}
 
if (fd_pipe_get_param(screen->pipe, FD_GMEM_SIZE, &val)) {
DBG("could not get GMEM size");
goto fail;
}
screen->gmemsize_bytes = val;
 
if (fd_pipe_get_param(screen->pipe, FD_DEVICE_ID, &val)) {
DBG("could not get device-id");
goto fail;
}
screen->device_id = val;
 
if (fd_pipe_get_param(screen->pipe, FD_GPU_ID, &val)) {
DBG("could not get gpu-id");
goto fail;
}
screen->gpu_id = val;
 
if (fd_pipe_get_param(screen->pipe, FD_CHIP_ID, &val)) {
DBG("could not get chip-id");
/* older kernels may not have this property: */
unsigned core = screen->gpu_id / 100;
unsigned major = (screen->gpu_id % 100) / 10;
unsigned minor = screen->gpu_id % 10;
unsigned patch = 0; /* assume the worst */
val = (patch & 0xff) | ((minor & 0xff) << 8) |
((major & 0xff) << 16) | ((core & 0xff) << 24);
}
screen->chip_id = val;
 
DBG("Pipe Info:");
DBG(" GPU-id: %d", screen->gpu_id);
DBG(" Chip-id: 0x%08x", screen->chip_id);
DBG(" GMEM size: 0x%08x", screen->gmemsize_bytes);
 
/* explicitly checking for GPU revisions that are known to work. This
* may be overly conservative for a3xx, where spoofing the gpu_id with
* the blob driver seems to generate identical cmdstream dumps. But
* on a2xx, there seem to be small differences between the GPU revs
* so it is probably better to actually test first on real hardware
* before enabling:
*
* If you have a different adreno version, feel free to add it to one
* of the cases below and see what happens. And if it works, please
* send a patch ;-)
*/
switch (screen->gpu_id) {
case 220:
fd2_screen_init(pscreen);
break;
case 307:
case 320:
case 330:
fd3_screen_init(pscreen);
break;
case 420:
fd4_screen_init(pscreen);
break;
default:
debug_printf("unsupported GPU: a%03d\n", screen->gpu_id);
goto fail;
}
 
pscreen->destroy = fd_screen_destroy;
pscreen->get_param = fd_screen_get_param;
pscreen->get_paramf = fd_screen_get_paramf;
pscreen->get_shader_param = fd_screen_get_shader_param;
 
fd_resource_screen_init(pscreen);
fd_query_screen_init(pscreen);
 
pscreen->get_name = fd_screen_get_name;
pscreen->get_vendor = fd_screen_get_vendor;
pscreen->get_device_vendor = fd_screen_get_device_vendor;
 
pscreen->get_timestamp = fd_screen_get_timestamp;
 
pscreen->fence_reference = fd_screen_fence_ref;
pscreen->fence_signalled = fd_screen_fence_signalled;
pscreen->fence_finish = fd_screen_fence_finish;
 
util_format_s3tc_init();
 
return pscreen;
 
fail:
fd_screen_destroy(pscreen);
return NULL;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/freedreno_screen.h
0,0 → 1,92
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FREEDRENO_SCREEN_H_
#define FREEDRENO_SCREEN_H_
 
#include <freedreno_drmif.h>
#include <freedreno_ringbuffer.h>
 
#include "pipe/p_screen.h"
#include "util/u_memory.h"
 
typedef uint32_t u32;
 
struct fd_bo;
 
struct fd_screen {
struct pipe_screen base;
 
uint32_t gmemsize_bytes;
uint32_t device_id;
uint32_t gpu_id; /* 220, 305, etc */
uint32_t chip_id; /* coreid:8 majorrev:8 minorrev:8 patch:8 */
uint32_t max_rts;
 
struct fd_device *dev;
struct fd_pipe *pipe;
 
int64_t cpu_gpu_time_delta;
};
 
static INLINE struct fd_screen *
fd_screen(struct pipe_screen *pscreen)
{
return (struct fd_screen *)pscreen;
}
 
boolean fd_screen_bo_get_handle(struct pipe_screen *pscreen,
struct fd_bo *bo,
unsigned stride,
struct winsys_handle *whandle);
struct fd_bo * fd_screen_bo_from_handle(struct pipe_screen *pscreen,
struct winsys_handle *whandle,
unsigned *out_stride);
 
struct pipe_screen * fd_screen_create(struct fd_device *dev);
 
/* is a3xx patch revision 0? */
static inline boolean
is_a3xx_p0(struct fd_screen *screen)
{
return (screen->chip_id & 0xff0000ff) == 0x03000000;
}
 
static inline boolean
is_a3xx(struct fd_screen *screen)
{
return (screen->gpu_id >= 300) && (screen->gpu_id < 400);
}
 
static inline boolean
is_a4xx(struct fd_screen *screen)
{
return (screen->gpu_id >= 400) && (screen->gpu_id < 500);
}
 
#endif /* FREEDRENO_SCREEN_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/freedreno_state.c
0,0 → 1,331
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "pipe/p_state.h"
#include "util/u_string.h"
#include "util/u_memory.h"
#include "util/u_helpers.h"
 
#include "freedreno_state.h"
#include "freedreno_context.h"
#include "freedreno_resource.h"
#include "freedreno_texture.h"
#include "freedreno_gmem.h"
#include "freedreno_util.h"
 
/* All the generic state handling.. In case of CSO's that are specific
* to the GPU version, when the bind and the delete are common they can
* go in here.
*/
 
static void
fd_set_blend_color(struct pipe_context *pctx,
const struct pipe_blend_color *blend_color)
{
struct fd_context *ctx = fd_context(pctx);
ctx->blend_color = *blend_color;
ctx->dirty |= FD_DIRTY_BLEND_COLOR;
}
 
static void
fd_set_stencil_ref(struct pipe_context *pctx,
const struct pipe_stencil_ref *stencil_ref)
{
struct fd_context *ctx = fd_context(pctx);
ctx->stencil_ref =* stencil_ref;
ctx->dirty |= FD_DIRTY_STENCIL_REF;
}
 
static void
fd_set_clip_state(struct pipe_context *pctx,
const struct pipe_clip_state *clip)
{
DBG("TODO: ");
}
 
static void
fd_set_sample_mask(struct pipe_context *pctx, unsigned sample_mask)
{
struct fd_context *ctx = fd_context(pctx);
ctx->sample_mask = (uint16_t)sample_mask;
ctx->dirty |= FD_DIRTY_SAMPLE_MASK;
}
 
/* notes from calim on #dri-devel:
* index==0 will be non-UBO (ie. glUniformXYZ()) all packed together padded
* out to vec4's
* I should be able to consider that I own the user_ptr until the next
* set_constant_buffer() call, at which point I don't really care about the
* previous values.
* index>0 will be UBO's.. well, I'll worry about that later
*/
static void
fd_set_constant_buffer(struct pipe_context *pctx, uint shader, uint index,
struct pipe_constant_buffer *cb)
{
struct fd_context *ctx = fd_context(pctx);
struct fd_constbuf_stateobj *so = &ctx->constbuf[shader];
 
/* Note that the state tracker can unbind constant buffers by
* passing NULL here.
*/
if (unlikely(!cb)) {
so->enabled_mask &= ~(1 << index);
so->dirty_mask &= ~(1 << index);
pipe_resource_reference(&so->cb[index].buffer, NULL);
return;
}
 
pipe_resource_reference(&so->cb[index].buffer, cb->buffer);
so->cb[index].buffer_offset = cb->buffer_offset;
so->cb[index].buffer_size = cb->buffer_size;
so->cb[index].user_buffer = cb->user_buffer;
 
so->enabled_mask |= 1 << index;
so->dirty_mask |= 1 << index;
ctx->dirty |= FD_DIRTY_CONSTBUF;
}
 
static void
fd_set_framebuffer_state(struct pipe_context *pctx,
const struct pipe_framebuffer_state *framebuffer)
{
struct fd_context *ctx = fd_context(pctx);
struct pipe_framebuffer_state *cso = &ctx->framebuffer;
 
DBG("%d: cbufs[0]=%p, zsbuf=%p", ctx->needs_flush,
framebuffer->cbufs[0], framebuffer->zsbuf);
 
fd_context_render(pctx);
 
if ((cso->width != framebuffer->width) ||
(cso->height != framebuffer->height))
ctx->needs_rb_fbd = true;
 
util_copy_framebuffer_state(cso, framebuffer);
 
ctx->dirty |= FD_DIRTY_FRAMEBUFFER;
 
ctx->disabled_scissor.minx = 0;
ctx->disabled_scissor.miny = 0;
ctx->disabled_scissor.maxx = cso->width;
ctx->disabled_scissor.maxy = cso->height;
 
ctx->dirty |= FD_DIRTY_SCISSOR;
}
 
static void
fd_set_polygon_stipple(struct pipe_context *pctx,
const struct pipe_poly_stipple *stipple)
{
struct fd_context *ctx = fd_context(pctx);
ctx->stipple = *stipple;
ctx->dirty |= FD_DIRTY_STIPPLE;
}
 
static void
fd_set_scissor_states(struct pipe_context *pctx,
unsigned start_slot,
unsigned num_scissors,
const struct pipe_scissor_state *scissor)
{
struct fd_context *ctx = fd_context(pctx);
 
ctx->scissor = *scissor;
ctx->dirty |= FD_DIRTY_SCISSOR;
}
 
static void
fd_set_viewport_states(struct pipe_context *pctx,
unsigned start_slot,
unsigned num_viewports,
const struct pipe_viewport_state *viewport)
{
struct fd_context *ctx = fd_context(pctx);
ctx->viewport = *viewport;
ctx->dirty |= FD_DIRTY_VIEWPORT;
}
 
static void
fd_set_vertex_buffers(struct pipe_context *pctx,
unsigned start_slot, unsigned count,
const struct pipe_vertex_buffer *vb)
{
struct fd_context *ctx = fd_context(pctx);
struct fd_vertexbuf_stateobj *so = &ctx->vtx.vertexbuf;
int i;
 
/* on a2xx, pitch is encoded in the vtx fetch instruction, so
* we need to mark VTXSTATE as dirty as well to trigger patching
* and re-emitting the vtx shader:
*/
for (i = 0; i < count; i++) {
bool new_enabled = vb && (vb[i].buffer || vb[i].user_buffer);
bool old_enabled = so->vb[i].buffer || so->vb[i].user_buffer;
uint32_t new_stride = vb ? vb[i].stride : 0;
uint32_t old_stride = so->vb[i].stride;
if ((new_enabled != old_enabled) || (new_stride != old_stride)) {
ctx->dirty |= FD_DIRTY_VTXSTATE;
break;
}
}
 
util_set_vertex_buffers_mask(so->vb, &so->enabled_mask, vb, start_slot, count);
so->count = util_last_bit(so->enabled_mask);
 
ctx->dirty |= FD_DIRTY_VTXBUF;
}
 
static void
fd_set_index_buffer(struct pipe_context *pctx,
const struct pipe_index_buffer *ib)
{
struct fd_context *ctx = fd_context(pctx);
 
if (ib) {
pipe_resource_reference(&ctx->indexbuf.buffer, ib->buffer);
ctx->indexbuf.index_size = ib->index_size;
ctx->indexbuf.offset = ib->offset;
ctx->indexbuf.user_buffer = ib->user_buffer;
} else {
pipe_resource_reference(&ctx->indexbuf.buffer, NULL);
}
 
ctx->dirty |= FD_DIRTY_INDEXBUF;
}
 
static void
fd_blend_state_bind(struct pipe_context *pctx, void *hwcso)
{
struct fd_context *ctx = fd_context(pctx);
ctx->blend = hwcso;
ctx->dirty |= FD_DIRTY_BLEND;
}
 
static void
fd_blend_state_delete(struct pipe_context *pctx, void *hwcso)
{
FREE(hwcso);
}
 
static void
fd_rasterizer_state_bind(struct pipe_context *pctx, void *hwcso)
{
struct fd_context *ctx = fd_context(pctx);
struct pipe_scissor_state *old_scissor = fd_context_get_scissor(ctx);
 
ctx->rasterizer = hwcso;
ctx->dirty |= FD_DIRTY_RASTERIZER;
 
/* if scissor enable bit changed we need to mark scissor
* state as dirty as well:
* NOTE: we can do a shallow compare, since we only care
* if it changed to/from &ctx->disable_scissor
*/
if (old_scissor != fd_context_get_scissor(ctx))
ctx->dirty |= FD_DIRTY_SCISSOR;
}
 
static void
fd_rasterizer_state_delete(struct pipe_context *pctx, void *hwcso)
{
FREE(hwcso);
}
 
static void
fd_zsa_state_bind(struct pipe_context *pctx, void *hwcso)
{
struct fd_context *ctx = fd_context(pctx);
ctx->zsa = hwcso;
ctx->dirty |= FD_DIRTY_ZSA;
}
 
static void
fd_zsa_state_delete(struct pipe_context *pctx, void *hwcso)
{
FREE(hwcso);
}
 
static void *
fd_vertex_state_create(struct pipe_context *pctx, unsigned num_elements,
const struct pipe_vertex_element *elements)
{
struct fd_vertex_stateobj *so = CALLOC_STRUCT(fd_vertex_stateobj);
 
if (!so)
return NULL;
 
memcpy(so->pipe, elements, sizeof(*elements) * num_elements);
so->num_elements = num_elements;
 
return so;
}
 
static void
fd_vertex_state_delete(struct pipe_context *pctx, void *hwcso)
{
FREE(hwcso);
}
 
static void
fd_vertex_state_bind(struct pipe_context *pctx, void *hwcso)
{
struct fd_context *ctx = fd_context(pctx);
ctx->vtx.vtx = hwcso;
ctx->dirty |= FD_DIRTY_VTXSTATE;
}
 
void
fd_state_init(struct pipe_context *pctx)
{
pctx->set_blend_color = fd_set_blend_color;
pctx->set_stencil_ref = fd_set_stencil_ref;
pctx->set_clip_state = fd_set_clip_state;
pctx->set_sample_mask = fd_set_sample_mask;
pctx->set_constant_buffer = fd_set_constant_buffer;
pctx->set_framebuffer_state = fd_set_framebuffer_state;
pctx->set_polygon_stipple = fd_set_polygon_stipple;
pctx->set_scissor_states = fd_set_scissor_states;
pctx->set_viewport_states = fd_set_viewport_states;
 
pctx->set_vertex_buffers = fd_set_vertex_buffers;
pctx->set_index_buffer = fd_set_index_buffer;
 
pctx->bind_blend_state = fd_blend_state_bind;
pctx->delete_blend_state = fd_blend_state_delete;
 
pctx->bind_rasterizer_state = fd_rasterizer_state_bind;
pctx->delete_rasterizer_state = fd_rasterizer_state_delete;
 
pctx->bind_depth_stencil_alpha_state = fd_zsa_state_bind;
pctx->delete_depth_stencil_alpha_state = fd_zsa_state_delete;
 
pctx->create_vertex_elements_state = fd_vertex_state_create;
pctx->delete_vertex_elements_state = fd_vertex_state_delete;
pctx->bind_vertex_elements_state = fd_vertex_state_bind;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/freedreno_state.h
0,0 → 1,57
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FREEDRENO_STATE_H_
#define FREEDRENO_STATE_H_
 
#include "pipe/p_context.h"
#include "freedreno_context.h"
 
static inline bool fd_depth_enabled(struct fd_context *ctx)
{
return ctx->zsa && ctx->zsa->depth.enabled;
}
 
static inline bool fd_stencil_enabled(struct fd_context *ctx)
{
return ctx->zsa && ctx->zsa->stencil[0].enabled;
}
 
static inline bool fd_logicop_enabled(struct fd_context *ctx)
{
return ctx->blend && ctx->blend->logicop_enable;
}
 
static inline bool fd_blend_enabled(struct fd_context *ctx, unsigned n)
{
return ctx->blend && ctx->blend->rt[n].blend_enable;
}
 
void fd_state_init(struct pipe_context *pctx);
 
#endif /* FREEDRENO_STATE_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/freedreno_surface.c
0,0 → 1,73
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "freedreno_surface.h"
#include "freedreno_resource.h"
#include "freedreno_util.h"
 
#include "util/u_memory.h"
#include "util/u_inlines.h"
 
struct pipe_surface *
fd_create_surface(struct pipe_context *pctx,
struct pipe_resource *ptex,
const struct pipe_surface *surf_tmpl)
{
// struct fd_resource* tex = fd_resource(ptex);
struct fd_surface* surface = CALLOC_STRUCT(fd_surface);
 
assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer);
 
if (surface) {
struct pipe_surface *psurf = &surface->base;
unsigned level = surf_tmpl->u.tex.level;
 
pipe_reference_init(&psurf->reference, 1);
pipe_resource_reference(&psurf->texture, ptex);
 
psurf->context = pctx;
psurf->format = surf_tmpl->format;
psurf->width = u_minify(ptex->width0, level);
psurf->height = u_minify(ptex->height0, level);
psurf->u.tex.level = level;
psurf->u.tex.first_layer = surf_tmpl->u.tex.first_layer;
psurf->u.tex.last_layer = surf_tmpl->u.tex.last_layer;
 
// TODO
DBG("TODO: %ux%u", psurf->width, psurf->height);
}
 
return &surface->base;
}
 
void
fd_surface_destroy(struct pipe_context *pctx, struct pipe_surface *psurf)
{
pipe_resource_reference(&psurf->texture, NULL);
FREE(psurf);
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/freedreno_surface.h
0,0 → 1,54
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FREEDRENO_SURFACE_H_
#define FREEDRENO_SURFACE_H_
 
#include "pipe/p_state.h"
 
struct fd_surface {
struct pipe_surface base;
uint32_t offset;
uint32_t pitch;
uint32_t width;
uint16_t height;
uint16_t depth;
};
 
static INLINE struct fd_surface *
fd_surface(struct pipe_surface *psurf)
{
return (struct fd_surface *)psurf;
}
 
struct pipe_surface* fd_create_surface(struct pipe_context *pctx,
struct pipe_resource *ptex,
const struct pipe_surface *surf_tmpl);
void fd_surface_destroy(struct pipe_context *pctx, struct pipe_surface *psurf);
 
#endif /* FREEDRENO_SURFACE_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/freedreno_texture.c
0,0 → 1,164
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "pipe/p_state.h"
#include "util/u_string.h"
#include "util/u_memory.h"
#include "util/u_inlines.h"
 
#include "freedreno_texture.h"
#include "freedreno_context.h"
#include "freedreno_util.h"
 
static void
fd_sampler_state_delete(struct pipe_context *pctx, void *hwcso)
{
FREE(hwcso);
}
 
static void
fd_sampler_view_destroy(struct pipe_context *pctx,
struct pipe_sampler_view *view)
{
pipe_resource_reference(&view->texture, NULL);
FREE(view);
}
 
static void bind_sampler_states(struct fd_texture_stateobj *tex,
unsigned nr, void **hwcso)
{
unsigned i;
unsigned new_nr = 0;
 
for (i = 0; i < nr; i++) {
if (hwcso[i])
new_nr = i + 1;
tex->samplers[i] = hwcso[i];
tex->dirty_samplers |= (1 << i);
}
 
for (; i < tex->num_samplers; i++) {
tex->samplers[i] = NULL;
tex->dirty_samplers |= (1 << i);
}
 
tex->num_samplers = new_nr;
}
 
static void set_sampler_views(struct fd_texture_stateobj *tex,
unsigned nr, struct pipe_sampler_view **views)
{
unsigned i;
unsigned new_nr = 0;
 
for (i = 0; i < nr; i++) {
if (views[i])
new_nr = i + 1;
pipe_sampler_view_reference(&tex->textures[i], views[i]);
tex->dirty_samplers |= (1 << i);
}
 
for (; i < tex->num_textures; i++) {
pipe_sampler_view_reference(&tex->textures[i], NULL);
tex->dirty_samplers |= (1 << i);
}
 
tex->num_textures = new_nr;
}
 
void
fd_sampler_states_bind(struct pipe_context *pctx,
unsigned shader, unsigned start,
unsigned nr, void **hwcso)
{
struct fd_context *ctx = fd_context(pctx);
 
assert(start == 0);
 
if (shader == PIPE_SHADER_FRAGMENT) {
bind_sampler_states(&ctx->fragtex, nr, hwcso);
ctx->dirty |= FD_DIRTY_FRAGTEX;
}
else if (shader == PIPE_SHADER_VERTEX) {
bind_sampler_states(&ctx->verttex, nr, hwcso);
ctx->dirty |= FD_DIRTY_VERTTEX;
}
}
 
 
static void
fd_fragtex_set_sampler_views(struct pipe_context *pctx, unsigned nr,
struct pipe_sampler_view **views)
{
struct fd_context *ctx = fd_context(pctx);
 
/* on a2xx, since there is a flat address space for textures/samplers,
* a change in # of fragment textures/samplers will trigger patching and
* re-emitting the vertex shader:
*/
if (nr != ctx->fragtex.num_textures)
ctx->dirty |= FD_DIRTY_TEXSTATE;
 
set_sampler_views(&ctx->fragtex, nr, views);
ctx->dirty |= FD_DIRTY_FRAGTEX;
}
 
static void
fd_verttex_set_sampler_views(struct pipe_context *pctx, unsigned nr,
struct pipe_sampler_view **views)
{
struct fd_context *ctx = fd_context(pctx);
set_sampler_views(&ctx->verttex, nr, views);
ctx->dirty |= FD_DIRTY_VERTTEX;
}
 
void
fd_set_sampler_views(struct pipe_context *pctx, unsigned shader,
unsigned start, unsigned nr,
struct pipe_sampler_view **views)
{
assert(start == 0);
switch (shader) {
case PIPE_SHADER_FRAGMENT:
fd_fragtex_set_sampler_views(pctx, nr, views);
break;
case PIPE_SHADER_VERTEX:
fd_verttex_set_sampler_views(pctx, nr, views);
break;
default:
;
}
}
 
void
fd_texture_init(struct pipe_context *pctx)
{
pctx->delete_sampler_state = fd_sampler_state_delete;
 
pctx->sampler_view_destroy = fd_sampler_view_destroy;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/freedreno_texture.h
0,0 → 1,44
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FREEDRENO_TEXTURE_H_
#define FREEDRENO_TEXTURE_H_
 
#include "pipe/p_context.h"
 
void fd_sampler_states_bind(struct pipe_context *pctx,
unsigned shader, unsigned start,
unsigned nr, void **hwcso);
 
void fd_set_sampler_views(struct pipe_context *pctx, unsigned shader,
unsigned start, unsigned nr,
struct pipe_sampler_view **views);
 
void fd_texture_init(struct pipe_context *pctx);
 
#endif /* FREEDRENO_TEXTURE_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/freedreno_util.c
0,0 → 1,157
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "pipe/p_defines.h"
#include "util/u_format.h"
 
#include "freedreno_util.h"
 
unsigned marker_cnt;
 
enum adreno_rb_depth_format
fd_pipe2depth(enum pipe_format format)
{
switch (format) {
case PIPE_FORMAT_Z16_UNORM:
return DEPTHX_16;
case PIPE_FORMAT_Z24X8_UNORM:
case PIPE_FORMAT_Z24_UNORM_S8_UINT:
case PIPE_FORMAT_X8Z24_UNORM:
case PIPE_FORMAT_S8_UINT_Z24_UNORM:
return DEPTHX_24_8;
case PIPE_FORMAT_Z32_FLOAT:
case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
return DEPTHX_32;
default:
return ~0;
}
}
 
enum pc_di_index_size
fd_pipe2index(enum pipe_format format)
{
switch (format) {
case PIPE_FORMAT_I8_UINT:
return INDEX_SIZE_8_BIT;
case PIPE_FORMAT_I16_UINT:
return INDEX_SIZE_16_BIT;
case PIPE_FORMAT_I32_UINT:
return INDEX_SIZE_32_BIT;
default:
return ~0;
}
}
 
 
enum adreno_rb_blend_factor
fd_blend_factor(unsigned factor)
{
switch (factor) {
case PIPE_BLENDFACTOR_ONE:
return FACTOR_ONE;
case PIPE_BLENDFACTOR_SRC_COLOR:
return FACTOR_SRC_COLOR;
case PIPE_BLENDFACTOR_SRC_ALPHA:
return FACTOR_SRC_ALPHA;
case PIPE_BLENDFACTOR_DST_ALPHA:
return FACTOR_DST_ALPHA;
case PIPE_BLENDFACTOR_DST_COLOR:
return FACTOR_DST_COLOR;
case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
return FACTOR_SRC_ALPHA_SATURATE;
case PIPE_BLENDFACTOR_CONST_COLOR:
return FACTOR_CONSTANT_COLOR;
case PIPE_BLENDFACTOR_CONST_ALPHA:
return FACTOR_CONSTANT_ALPHA;
case PIPE_BLENDFACTOR_ZERO:
case 0:
return FACTOR_ZERO;
case PIPE_BLENDFACTOR_INV_SRC_COLOR:
return FACTOR_ONE_MINUS_SRC_COLOR;
case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
return FACTOR_ONE_MINUS_SRC_ALPHA;
case PIPE_BLENDFACTOR_INV_DST_ALPHA:
return FACTOR_ONE_MINUS_DST_ALPHA;
case PIPE_BLENDFACTOR_INV_DST_COLOR:
return FACTOR_ONE_MINUS_DST_COLOR;
case PIPE_BLENDFACTOR_INV_CONST_COLOR:
return FACTOR_ONE_MINUS_CONSTANT_COLOR;
case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
return FACTOR_ONE_MINUS_CONSTANT_ALPHA;
case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
case PIPE_BLENDFACTOR_SRC1_COLOR:
case PIPE_BLENDFACTOR_SRC1_ALPHA:
/* I don't think these are supported */
default:
DBG("invalid blend factor: %x", factor);
return 0;
}
}
 
enum adreno_pa_su_sc_draw
fd_polygon_mode(unsigned mode)
{
switch (mode) {
case PIPE_POLYGON_MODE_POINT:
return PC_DRAW_POINTS;
case PIPE_POLYGON_MODE_LINE:
return PC_DRAW_LINES;
case PIPE_POLYGON_MODE_FILL:
return PC_DRAW_TRIANGLES;
default:
DBG("invalid polygon mode: %u", mode);
return 0;
}
}
 
enum adreno_stencil_op
fd_stencil_op(unsigned op)
{
switch (op) {
case PIPE_STENCIL_OP_KEEP:
return STENCIL_KEEP;
case PIPE_STENCIL_OP_ZERO:
return STENCIL_ZERO;
case PIPE_STENCIL_OP_REPLACE:
return STENCIL_REPLACE;
case PIPE_STENCIL_OP_INCR:
return STENCIL_INCR_CLAMP;
case PIPE_STENCIL_OP_DECR:
return STENCIL_DECR_CLAMP;
case PIPE_STENCIL_OP_INCR_WRAP:
return STENCIL_INCR_WRAP;
case PIPE_STENCIL_OP_DECR_WRAP:
return STENCIL_DECR_WRAP;
case PIPE_STENCIL_OP_INVERT:
return STENCIL_INVERT;
default:
DBG("invalid stencil op: %u", op);
return 0;
}
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/freedreno_util.h
0,0 → 1,267
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef FREEDRENO_UTIL_H_
#define FREEDRENO_UTIL_H_
 
#include <freedreno_drmif.h>
#include <freedreno_ringbuffer.h>
 
#include "pipe/p_format.h"
#include "pipe/p_state.h"
#include "util/u_debug.h"
#include "util/u_math.h"
#include "util/u_half.h"
#include "util/u_dynarray.h"
#include "util/u_pack_color.h"
 
#include "adreno_common.xml.h"
#include "adreno_pm4.xml.h"
 
enum adreno_rb_depth_format fd_pipe2depth(enum pipe_format format);
enum pc_di_index_size fd_pipe2index(enum pipe_format format);
enum adreno_rb_blend_factor fd_blend_factor(unsigned factor);
enum adreno_pa_su_sc_draw fd_polygon_mode(unsigned mode);
enum adreno_stencil_op fd_stencil_op(unsigned op);
 
#define A3XX_MAX_MIP_LEVELS 14
/* TBD if it is same on a2xx, but for now: */
#define MAX_MIP_LEVELS A3XX_MAX_MIP_LEVELS
 
#define FD_DBG_MSGS 0x0001
#define FD_DBG_DISASM 0x0002
#define FD_DBG_DCLEAR 0x0004
#define FD_DBG_FLUSH 0x0008
#define FD_DBG_NOSCIS 0x0010
#define FD_DBG_DIRECT 0x0020
#define FD_DBG_NOBYPASS 0x0040
#define FD_DBG_FRAGHALF 0x0080
#define FD_DBG_NOBIN 0x0100
#define FD_DBG_OPTMSGS 0x0400
#define FD_DBG_OPTDUMP 0x0800
#define FD_DBG_GLSL120 0x1000
#define FD_DBG_NOCP 0x2000
#define FD_DBG_NIR 0x4000
 
extern int fd_mesa_debug;
extern bool fd_binning_enabled;
 
#define DBG(fmt, ...) \
do { if (fd_mesa_debug & FD_DBG_MSGS) \
debug_printf("%s:%d: "fmt "\n", \
__FUNCTION__, __LINE__, ##__VA_ARGS__); } while (0)
 
/* for conditionally setting boolean flag(s): */
#define COND(bool, val) ((bool) ? (val) : 0)
 
#define CP_REG(reg) ((0x4 << 16) | ((unsigned int)((reg) - (0x2000))))
 
static inline uint32_t DRAW(enum pc_di_primtype prim_type,
enum pc_di_src_sel source_select, enum pc_di_index_size index_size,
enum pc_di_vis_cull_mode vis_cull_mode,
uint8_t instances)
{
return (prim_type << 0) |
(source_select << 6) |
((index_size & 1) << 11) |
((index_size >> 1) << 13) |
(vis_cull_mode << 9) |
(1 << 14) |
(instances << 24);
}
 
/* for tracking cmdstream positions that need to be patched: */
struct fd_cs_patch {
uint32_t *cs;
uint32_t val;
};
#define fd_patch_num_elements(buf) ((buf)->size / sizeof(struct fd_cs_patch))
#define fd_patch_element(buf, i) util_dynarray_element(buf, struct fd_cs_patch, i)
 
static inline enum pipe_format
pipe_surface_format(struct pipe_surface *psurf)
{
if (!psurf)
return PIPE_FORMAT_NONE;
return psurf->format;
}
 
#define LOG_DWORDS 0
 
static inline void emit_marker(struct fd_ringbuffer *ring, int scratch_idx);
 
static inline void
OUT_RING(struct fd_ringbuffer *ring, uint32_t data)
{
if (LOG_DWORDS) {
DBG("ring[%p]: OUT_RING %04x: %08x", ring,
(uint32_t)(ring->cur - ring->last_start), data);
}
*(ring->cur++) = data;
}
 
/* like OUT_RING() but appends a cmdstream patch point to 'buf' */
static inline void
OUT_RINGP(struct fd_ringbuffer *ring, uint32_t data,
struct util_dynarray *buf)
{
if (LOG_DWORDS) {
DBG("ring[%p]: OUT_RINGP %04x: %08x", ring,
(uint32_t)(ring->cur - ring->last_start), data);
}
util_dynarray_append(buf, struct fd_cs_patch, ((struct fd_cs_patch){
.cs = ring->cur++,
.val = data,
}));
}
 
static inline void
OUT_RELOC(struct fd_ringbuffer *ring, struct fd_bo *bo,
uint32_t offset, uint32_t or, int32_t shift)
{
if (LOG_DWORDS) {
DBG("ring[%p]: OUT_RELOC %04x: %p+%u << %d", ring,
(uint32_t)(ring->cur - ring->last_start), bo, offset, shift);
}
fd_ringbuffer_reloc(ring, &(struct fd_reloc){
.bo = bo,
.flags = FD_RELOC_READ,
.offset = offset,
.or = or,
.shift = shift,
});
}
 
static inline void
OUT_RELOCW(struct fd_ringbuffer *ring, struct fd_bo *bo,
uint32_t offset, uint32_t or, int32_t shift)
{
if (LOG_DWORDS) {
DBG("ring[%p]: OUT_RELOCW %04x: %p+%u << %d", ring,
(uint32_t)(ring->cur - ring->last_start), bo, offset, shift);
}
fd_ringbuffer_reloc(ring, &(struct fd_reloc){
.bo = bo,
.flags = FD_RELOC_READ | FD_RELOC_WRITE,
.offset = offset,
.or = or,
.shift = shift,
});
}
 
static inline void BEGIN_RING(struct fd_ringbuffer *ring, uint32_t ndwords)
{
if ((ring->cur + ndwords) >= ring->end) {
/* this probably won't really work if we have multiple tiles..
* but it is ok for 2d.. we might need different behavior
* depending on 2d or 3d pipe.
*/
DBG("uh oh..");
}
}
 
static inline void
OUT_PKT0(struct fd_ringbuffer *ring, uint16_t regindx, uint16_t cnt)
{
BEGIN_RING(ring, cnt+1);
OUT_RING(ring, CP_TYPE0_PKT | ((cnt-1) << 16) | (regindx & 0x7FFF));
}
 
static inline void
OUT_PKT3(struct fd_ringbuffer *ring, uint8_t opcode, uint16_t cnt)
{
BEGIN_RING(ring, cnt+1);
OUT_RING(ring, CP_TYPE3_PKT | ((cnt-1) << 16) | ((opcode & 0xFF) << 8));
}
 
static inline void
OUT_WFI(struct fd_ringbuffer *ring)
{
OUT_PKT3(ring, CP_WAIT_FOR_IDLE, 1);
OUT_RING(ring, 0x00000000);
}
 
static inline void
OUT_IB(struct fd_ringbuffer *ring, struct fd_ringmarker *start,
struct fd_ringmarker *end)
{
uint32_t dwords = fd_ringmarker_dwords(start, end);
 
assert(dwords > 0);
 
/* for debug after a lock up, write a unique counter value
* to scratch6 for each IB, to make it easier to match up
* register dumps to cmdstream. The combination of IB and
* DRAW (scratch7) is enough to "triangulate" the particular
* draw that caused lockup.
*/
emit_marker(ring, 6);
 
OUT_PKT3(ring, CP_INDIRECT_BUFFER_PFD, 2);
fd_ringbuffer_emit_reloc_ring(ring, start, end);
OUT_RING(ring, dwords);
 
emit_marker(ring, 6);
}
 
/* CP_SCRATCH_REG4 is used to hold base address for query results: */
#define HW_QUERY_BASE_REG REG_AXXX_CP_SCRATCH_REG4
 
static inline void
emit_marker(struct fd_ringbuffer *ring, int scratch_idx)
{
extern unsigned marker_cnt;
unsigned reg = REG_AXXX_CP_SCRATCH_REG0 + scratch_idx;
assert(reg != HW_QUERY_BASE_REG);
if (reg == HW_QUERY_BASE_REG)
return;
OUT_PKT0(ring, reg, 1);
OUT_RING(ring, ++marker_cnt);
}
 
/* helper to get numeric value from environment variable.. mostly
* just leaving this here because it is helpful to brute-force figure
* out unknown formats, etc, which blob driver does not support:
*/
static inline uint32_t env2u(const char *envvar)
{
char *str = getenv(envvar);
if (str)
return strtoul(str, NULL, 0);
return 0;
}
 
static inline uint32_t
pack_rgba(enum pipe_format format, const float *rgba)
{
union util_color uc;
util_pack_color(rgba, format, &uc);
return uc.ui[0];
}
 
#endif /* FREEDRENO_UTIL_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/ir3/disasm-a3xx.c
0,0 → 1,797
/*
* Copyright (c) 2013 Rob Clark <robdclark@gmail.com>
*
* 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 <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
 
#include <util/u_debug.h>
 
#include "disasm.h"
#include "instr-a3xx.h"
 
static enum debug_t debug;
 
#define printf debug_printf
 
static const char *levels[] = {
"",
"\t",
"\t\t",
"\t\t\t",
"\t\t\t\t",
"\t\t\t\t\t",
"\t\t\t\t\t\t",
"\t\t\t\t\t\t\t",
"\t\t\t\t\t\t\t\t",
"\t\t\t\t\t\t\t\t\t",
"x",
"x",
"x",
"x",
"x",
"x",
};
 
static const char *component = "xyzw";
 
static const char *type[] = {
[TYPE_F16] = "f16",
[TYPE_F32] = "f32",
[TYPE_U16] = "u16",
[TYPE_U32] = "u32",
[TYPE_S16] = "s16",
[TYPE_S32] = "s32",
[TYPE_U8] = "u8",
[TYPE_S8] = "s8",
};
 
static void print_reg(reg_t reg, bool full, bool r, bool c, bool im,
bool neg, bool abs, bool addr_rel)
{
const char type = c ? 'c' : 'r';
 
// XXX I prefer - and || for neg/abs, but preserving format used
// by libllvm-a3xx for easy diffing..
 
if (abs && neg)
printf("(absneg)");
else if (neg)
printf("(neg)");
else if (abs)
printf("(abs)");
 
if (r)
printf("(r)");
 
if (im) {
printf("%d", reg.iim_val);
} else if (addr_rel) {
/* I would just use %+d but trying to make it diff'able with
* libllvm-a3xx...
*/
if (reg.iim_val < 0)
printf("%s%c<a0.x - %d>", full ? "" : "h", type, -reg.iim_val);
else if (reg.iim_val > 0)
printf("%s%c<a0.x + %d>", full ? "" : "h", type, reg.iim_val);
else
printf("%s%c<a0.x>", full ? "" : "h", type);
} else if ((reg.num == REG_A0) && !c) {
printf("a0.%c", component[reg.comp]);
} else if ((reg.num == REG_P0) && !c) {
printf("p0.%c", component[reg.comp]);
} else {
printf("%s%c%d.%c", full ? "" : "h", type, reg.num, component[reg.comp]);
}
}
 
 
/* current instruction repeat flag: */
static unsigned repeat;
 
static void print_reg_dst(reg_t reg, bool full, bool addr_rel)
{
print_reg(reg, full, false, false, false, false, false, addr_rel);
}
 
static void print_reg_src(reg_t reg, bool full, bool r, bool c, bool im,
bool neg, bool abs, bool addr_rel)
{
print_reg(reg, full, r, c, im, neg, abs, addr_rel);
}
 
static void print_instr_cat0(instr_t *instr)
{
instr_cat0_t *cat0 = &instr->cat0;
 
switch (cat0->opc) {
case OPC_KILL:
printf(" %sp0.%c", cat0->inv ? "!" : "",
component[cat0->comp]);
break;
case OPC_BR:
printf(" %sp0.%c, #%d", cat0->inv ? "!" : "",
component[cat0->comp], cat0->immed);
break;
case OPC_JUMP:
case OPC_CALL:
printf(" #%d", cat0->immed);
break;
}
 
if ((debug & PRINT_VERBOSE) && (cat0->dummy1|cat0->dummy2|cat0->dummy3|cat0->dummy4))
printf("\t{0: %x,%x,%x,%x}", cat0->dummy1, cat0->dummy2, cat0->dummy3, cat0->dummy4);
}
 
static void print_instr_cat1(instr_t *instr)
{
instr_cat1_t *cat1 = &instr->cat1;
 
if (cat1->ul)
printf("(ul)");
 
if (cat1->src_type == cat1->dst_type) {
if ((cat1->src_type == TYPE_S16) && (((reg_t)cat1->dst).num == REG_A0)) {
/* special case (nmemonic?): */
printf("mova");
} else {
printf("mov.%s%s", type[cat1->src_type], type[cat1->dst_type]);
}
} else {
printf("cov.%s%s", type[cat1->src_type], type[cat1->dst_type]);
}
 
printf(" ");
 
if (cat1->even)
printf("(even)");
 
if (cat1->pos_inf)
printf("(pos_infinity)");
 
print_reg_dst((reg_t)(cat1->dst), type_size(cat1->dst_type) == 32,
cat1->dst_rel);
 
printf(", ");
 
/* ugg, have to special case this.. vs print_reg().. */
if (cat1->src_im) {
if (type_float(cat1->src_type))
printf("(%f)", cat1->fim_val);
else if (type_uint(cat1->src_type))
printf("0x%08x", cat1->uim_val);
else
printf("%d", cat1->iim_val);
} else if (cat1->src_rel && !cat1->src_c) {
/* I would just use %+d but trying to make it diff'able with
* libllvm-a3xx...
*/
char type = cat1->src_rel_c ? 'c' : 'r';
if (cat1->off < 0)
printf("%c<a0.x - %d>", type, -cat1->off);
else if (cat1->off > 0)
printf("%c<a0.x + %d>", type, cat1->off);
else
printf("c<a0.x>");
} else {
print_reg_src((reg_t)(cat1->src), type_size(cat1->src_type) == 32,
cat1->src_r, cat1->src_c, cat1->src_im, false, false, false);
}
 
if ((debug & PRINT_VERBOSE) && (cat1->must_be_0))
printf("\t{1: %x}", cat1->must_be_0);
}
 
static void print_instr_cat2(instr_t *instr)
{
instr_cat2_t *cat2 = &instr->cat2;
static const char *cond[] = {
"lt",
"le",
"gt",
"ge",
"eq",
"ne",
"?6?",
};
 
switch (cat2->opc) {
case OPC_CMPS_F:
case OPC_CMPS_U:
case OPC_CMPS_S:
case OPC_CMPV_F:
case OPC_CMPV_U:
case OPC_CMPV_S:
printf(".%s", cond[cat2->cond]);
break;
}
 
printf(" ");
if (cat2->ei)
printf("(ei)");
print_reg_dst((reg_t)(cat2->dst), cat2->full ^ cat2->dst_half, false);
printf(", ");
 
if (cat2->c1.src1_c) {
print_reg_src((reg_t)(cat2->c1.src1), cat2->full, cat2->src1_r,
cat2->c1.src1_c, cat2->src1_im, cat2->src1_neg,
cat2->src1_abs, false);
} else if (cat2->rel1.src1_rel) {
print_reg_src((reg_t)(cat2->rel1.src1), cat2->full, cat2->src1_r,
cat2->rel1.src1_c, cat2->src1_im, cat2->src1_neg,
cat2->src1_abs, cat2->rel1.src1_rel);
} else {
print_reg_src((reg_t)(cat2->src1), cat2->full, cat2->src1_r,
false, cat2->src1_im, cat2->src1_neg,
cat2->src1_abs, false);
}
 
switch (cat2->opc) {
case OPC_ABSNEG_F:
case OPC_ABSNEG_S:
case OPC_CLZ_B:
case OPC_CLZ_S:
case OPC_SIGN_F:
case OPC_FLOOR_F:
case OPC_CEIL_F:
case OPC_RNDNE_F:
case OPC_RNDAZ_F:
case OPC_TRUNC_F:
case OPC_NOT_B:
case OPC_BFREV_B:
case OPC_SETRM:
case OPC_CBITS_B:
/* these only have one src reg */
break;
default:
printf(", ");
if (cat2->c2.src2_c) {
print_reg_src((reg_t)(cat2->c2.src2), cat2->full, cat2->src2_r,
cat2->c2.src2_c, cat2->src2_im, cat2->src2_neg,
cat2->src2_abs, false);
} else if (cat2->rel2.src2_rel) {
print_reg_src((reg_t)(cat2->rel2.src2), cat2->full, cat2->src2_r,
cat2->rel2.src2_c, cat2->src2_im, cat2->src2_neg,
cat2->src2_abs, cat2->rel2.src2_rel);
} else {
print_reg_src((reg_t)(cat2->src2), cat2->full, cat2->src2_r,
false, cat2->src2_im, cat2->src2_neg,
cat2->src2_abs, false);
}
break;
}
}
 
static void print_instr_cat3(instr_t *instr)
{
instr_cat3_t *cat3 = &instr->cat3;
bool full = instr_cat3_full(cat3);
 
printf(" ");
print_reg_dst((reg_t)(cat3->dst), full ^ cat3->dst_half, false);
printf(", ");
if (cat3->c1.src1_c) {
print_reg_src((reg_t)(cat3->c1.src1), full,
cat3->src1_r, cat3->c1.src1_c, false, cat3->src1_neg,
false, false);
} else if (cat3->rel1.src1_rel) {
print_reg_src((reg_t)(cat3->rel1.src1), full,
cat3->src1_r, cat3->rel1.src1_c, false, cat3->src1_neg,
false, cat3->rel1.src1_rel);
} else {
print_reg_src((reg_t)(cat3->src1), full,
cat3->src1_r, false, false, cat3->src1_neg,
false, false);
}
printf(", ");
print_reg_src((reg_t)cat3->src2, full,
cat3->src2_r, cat3->src2_c, false, cat3->src2_neg,
false, false);
printf(", ");
if (cat3->c2.src3_c) {
print_reg_src((reg_t)(cat3->c2.src3), full,
cat3->src3_r, cat3->c2.src3_c, false, cat3->src3_neg,
false, false);
} else if (cat3->rel2.src3_rel) {
print_reg_src((reg_t)(cat3->rel2.src3), full,
cat3->src3_r, cat3->rel2.src3_c, false, cat3->src3_neg,
false, cat3->rel2.src3_rel);
} else {
print_reg_src((reg_t)(cat3->src3), full,
cat3->src3_r, false, false, cat3->src3_neg,
false, false);
}
}
 
static void print_instr_cat4(instr_t *instr)
{
instr_cat4_t *cat4 = &instr->cat4;
 
printf(" ");
print_reg_dst((reg_t)(cat4->dst), cat4->full ^ cat4->dst_half, false);
printf(", ");
 
if (cat4->c.src_c) {
print_reg_src((reg_t)(cat4->c.src), cat4->full,
cat4->src_r, cat4->c.src_c, cat4->src_im,
cat4->src_neg, cat4->src_abs, false);
} else if (cat4->rel.src_rel) {
print_reg_src((reg_t)(cat4->rel.src), cat4->full,
cat4->src_r, cat4->rel.src_c, cat4->src_im,
cat4->src_neg, cat4->src_abs, cat4->rel.src_rel);
} else {
print_reg_src((reg_t)(cat4->src), cat4->full,
cat4->src_r, false, cat4->src_im,
cat4->src_neg, cat4->src_abs, false);
}
 
if ((debug & PRINT_VERBOSE) && (cat4->dummy1|cat4->dummy2))
printf("\t{4: %x,%x}", cat4->dummy1, cat4->dummy2);
}
 
static void print_instr_cat5(instr_t *instr)
{
static const struct {
bool src1, src2, samp, tex;
} info[0x1f] = {
[OPC_ISAM] = { true, false, true, true, },
[OPC_ISAML] = { true, true, true, true, },
[OPC_ISAMM] = { true, false, true, true, },
[OPC_SAM] = { true, false, true, true, },
[OPC_SAMB] = { true, true, true, true, },
[OPC_SAML] = { true, true, true, true, },
[OPC_SAMGQ] = { true, false, true, true, },
[OPC_GETLOD] = { true, false, true, true, },
[OPC_CONV] = { true, true, true, true, },
[OPC_CONVM] = { true, true, true, true, },
[OPC_GETSIZE] = { true, false, false, true, },
[OPC_GETBUF] = { false, false, false, true, },
[OPC_GETPOS] = { true, false, false, true, },
[OPC_GETINFO] = { false, false, false, true, },
[OPC_DSX] = { true, false, false, false, },
[OPC_DSY] = { true, false, false, false, },
[OPC_GATHER4R] = { true, false, true, true, },
[OPC_GATHER4G] = { true, false, true, true, },
[OPC_GATHER4B] = { true, false, true, true, },
[OPC_GATHER4A] = { true, false, true, true, },
[OPC_SAMGP0] = { true, false, true, true, },
[OPC_SAMGP1] = { true, false, true, true, },
[OPC_SAMGP2] = { true, false, true, true, },
[OPC_SAMGP3] = { true, false, true, true, },
[OPC_DSXPP_1] = { true, false, false, false, },
[OPC_DSYPP_1] = { true, false, false, false, },
[OPC_RGETPOS] = { false, false, false, false, },
[OPC_RGETINFO] = { false, false, false, false, },
};
instr_cat5_t *cat5 = &instr->cat5;
int i;
 
if (cat5->is_3d) printf(".3d");
if (cat5->is_a) printf(".a");
if (cat5->is_o) printf(".o");
if (cat5->is_p) printf(".p");
if (cat5->is_s) printf(".s");
if (cat5->is_s2en) printf(".s2en");
 
printf(" ");
 
switch (cat5->opc) {
case OPC_DSXPP_1:
case OPC_DSYPP_1:
break;
default:
printf("(%s)", type[cat5->type]);
break;
}
 
printf("(");
for (i = 0; i < 4; i++)
if (cat5->wrmask & (1 << i))
printf("%c", "xyzw"[i]);
printf(")");
 
print_reg_dst((reg_t)(cat5->dst), type_size(cat5->type) == 32, false);
 
if (info[cat5->opc].src1) {
printf(", ");
print_reg_src((reg_t)(cat5->src1), cat5->full, false, false, false,
false, false, false);
}
 
if (cat5->is_s2en) {
printf(", ");
print_reg_src((reg_t)(cat5->s2en.src2), cat5->full, false, false, false,
false, false, false);
printf(", ");
print_reg_src((reg_t)(cat5->s2en.src3), false, false, false, false,
false, false, false);
} else {
if (cat5->is_o || info[cat5->opc].src2) {
printf(", ");
print_reg_src((reg_t)(cat5->norm.src2), cat5->full,
false, false, false, false, false, false);
}
if (info[cat5->opc].samp)
printf(", s#%d", cat5->norm.samp);
if (info[cat5->opc].tex)
printf(", t#%d", cat5->norm.tex);
}
 
if (debug & PRINT_VERBOSE) {
if (cat5->is_s2en) {
if ((debug & PRINT_VERBOSE) && (cat5->s2en.dummy1|cat5->s2en.dummy2|cat5->dummy2))
printf("\t{5: %x,%x,%x}", cat5->s2en.dummy1, cat5->s2en.dummy2, cat5->dummy2);
} else {
if ((debug & PRINT_VERBOSE) && (cat5->norm.dummy1|cat5->dummy2))
printf("\t{5: %x,%x}", cat5->norm.dummy1, cat5->dummy2);
}
}
}
 
static void print_instr_cat6(instr_t *instr)
{
instr_cat6_t *cat6 = &instr->cat6;
char sd = 0, ss = 0; /* dst/src address space */
bool full = type_size(cat6->type) == 32;
bool nodst = false;
 
printf(".%s ", type[cat6->type]);
 
switch (cat6->opc) {
case OPC_STG:
sd = 'g';
break;
case OPC_STP:
sd = 'p';
break;
case OPC_STL:
case OPC_STLW:
sd = 'l';
break;
 
case OPC_LDG:
ss = 'g';
break;
case OPC_LDP:
ss = 'p';
break;
case OPC_LDL:
case OPC_LDLW:
case OPC_LDLV:
ss = 'l';
break;
 
case OPC_L2G:
ss = 'l';
sd = 'g';
break;
 
case OPC_G2L:
ss = 'g';
sd = 'l';
break;
 
case OPC_PREFETCH:
ss = 'g';
nodst = true;
break;
 
case OPC_STI:
full = false; // XXX or inverts??
break;
}
 
if (cat6->has_off) {
if (!nodst) {
if (sd)
printf("%c[", sd);
print_reg_dst((reg_t)(cat6->a.dst), full, false);
if (sd)
printf("]");
printf(", ");
}
if (ss)
printf("%c[", ss);
print_reg_src((reg_t)(cat6->a.src1), true,
false, false, cat6->a.src1_im, false, false, false);
if (cat6->a.off)
printf("%+d", cat6->a.off);
if (ss)
printf("]");
printf(", ");
print_reg_src((reg_t)(cat6->a.src2), full,
false, false, cat6->a.src2_im, false, false, false);
} else {
if (!nodst) {
if (sd)
printf("%c[", sd);
print_reg_dst((reg_t)(cat6->b.dst), full, false);
if (sd)
printf("]");
printf(", ");
}
if (ss)
printf("%c[", ss);
print_reg_src((reg_t)(cat6->b.src1), true,
false, false, cat6->b.src1_im, false, false, false);
if (ss)
printf("]");
printf(", ");
print_reg_src((reg_t)(cat6->b.src2), full,
false, false, cat6->b.src2_im, false, false, false);
}
 
if (debug & PRINT_VERBOSE) {
switch (cat6->opc) {
case OPC_LDG:
case OPC_LDP:
/* load instructions: */
if (cat6->a.dummy2|cat6->a.dummy3)
printf("\t{6: %x,%x}", cat6->a.dummy2, cat6->a.dummy3);
break;
case OPC_STG:
case OPC_STP:
case OPC_STI:
/* store instructions: */
if (cat6->b.dummy2|cat6->b.dummy2)
printf("\t{6: %x,%x}", cat6->b.dummy2, cat6->b.dummy3);
if (cat6->b.ignore0)
printf("\t{?? %x}", cat6->b.ignore0);
break;
}
}
}
 
/* size of largest OPC field of all the instruction categories: */
#define NOPC_BITS 6
 
struct opc_info {
uint16_t cat;
uint16_t opc;
const char *name;
void (*print)(instr_t *instr);
} opcs[1 << (3+NOPC_BITS)] = {
#define OPC(cat, opc, name) [((cat) << NOPC_BITS) | (opc)] = { (cat), (opc), #name, print_instr_cat##cat }
/* category 0: */
OPC(0, OPC_NOP, nop),
OPC(0, OPC_BR, br),
OPC(0, OPC_JUMP, jump),
OPC(0, OPC_CALL, call),
OPC(0, OPC_RET, ret),
OPC(0, OPC_KILL, kill),
OPC(0, OPC_END, end),
OPC(0, OPC_EMIT, emit),
OPC(0, OPC_CUT, cut),
OPC(0, OPC_CHMASK, chmask),
OPC(0, OPC_CHSH, chsh),
OPC(0, OPC_FLOW_REV, flow_rev),
 
/* category 1: */
OPC(1, 0, ),
 
/* category 2: */
OPC(2, OPC_ADD_F, add.f),
OPC(2, OPC_MIN_F, min.f),
OPC(2, OPC_MAX_F, max.f),
OPC(2, OPC_MUL_F, mul.f),
OPC(2, OPC_SIGN_F, sign.f),
OPC(2, OPC_CMPS_F, cmps.f),
OPC(2, OPC_ABSNEG_F, absneg.f),
OPC(2, OPC_CMPV_F, cmpv.f),
OPC(2, OPC_FLOOR_F, floor.f),
OPC(2, OPC_CEIL_F, ceil.f),
OPC(2, OPC_RNDNE_F, rndne.f),
OPC(2, OPC_RNDAZ_F, rndaz.f),
OPC(2, OPC_TRUNC_F, trunc.f),
OPC(2, OPC_ADD_U, add.u),
OPC(2, OPC_ADD_S, add.s),
OPC(2, OPC_SUB_U, sub.u),
OPC(2, OPC_SUB_S, sub.s),
OPC(2, OPC_CMPS_U, cmps.u),
OPC(2, OPC_CMPS_S, cmps.s),
OPC(2, OPC_MIN_U, min.u),
OPC(2, OPC_MIN_S, min.s),
OPC(2, OPC_MAX_U, max.u),
OPC(2, OPC_MAX_S, max.s),
OPC(2, OPC_ABSNEG_S, absneg.s),
OPC(2, OPC_AND_B, and.b),
OPC(2, OPC_OR_B, or.b),
OPC(2, OPC_NOT_B, not.b),
OPC(2, OPC_XOR_B, xor.b),
OPC(2, OPC_CMPV_U, cmpv.u),
OPC(2, OPC_CMPV_S, cmpv.s),
OPC(2, OPC_MUL_U, mul.u),
OPC(2, OPC_MUL_S, mul.s),
OPC(2, OPC_MULL_U, mull.u),
OPC(2, OPC_BFREV_B, bfrev.b),
OPC(2, OPC_CLZ_S, clz.s),
OPC(2, OPC_CLZ_B, clz.b),
OPC(2, OPC_SHL_B, shl.b),
OPC(2, OPC_SHR_B, shr.b),
OPC(2, OPC_ASHR_B, ashr.b),
OPC(2, OPC_BARY_F, bary.f),
OPC(2, OPC_MGEN_B, mgen.b),
OPC(2, OPC_GETBIT_B, getbit.b),
OPC(2, OPC_SETRM, setrm),
OPC(2, OPC_CBITS_B, cbits.b),
OPC(2, OPC_SHB, shb),
OPC(2, OPC_MSAD, msad),
 
/* category 3: */
OPC(3, OPC_MAD_U16, mad.u16),
OPC(3, OPC_MADSH_U16, madsh.u16),
OPC(3, OPC_MAD_S16, mad.s16),
OPC(3, OPC_MADSH_M16, madsh.m16),
OPC(3, OPC_MAD_U24, mad.u24),
OPC(3, OPC_MAD_S24, mad.s24),
OPC(3, OPC_MAD_F16, mad.f16),
OPC(3, OPC_MAD_F32, mad.f32),
OPC(3, OPC_SEL_B16, sel.b16),
OPC(3, OPC_SEL_B32, sel.b32),
OPC(3, OPC_SEL_S16, sel.s16),
OPC(3, OPC_SEL_S32, sel.s32),
OPC(3, OPC_SEL_F16, sel.f16),
OPC(3, OPC_SEL_F32, sel.f32),
OPC(3, OPC_SAD_S16, sad.s16),
OPC(3, OPC_SAD_S32, sad.s32),
 
/* category 4: */
OPC(4, OPC_RCP, rcp),
OPC(4, OPC_RSQ, rsq),
OPC(4, OPC_LOG2, log2),
OPC(4, OPC_EXP2, exp2),
OPC(4, OPC_SIN, sin),
OPC(4, OPC_COS, cos),
OPC(4, OPC_SQRT, sqrt),
 
/* category 5: */
OPC(5, OPC_ISAM, isam),
OPC(5, OPC_ISAML, isaml),
OPC(5, OPC_ISAMM, isamm),
OPC(5, OPC_SAM, sam),
OPC(5, OPC_SAMB, samb),
OPC(5, OPC_SAML, saml),
OPC(5, OPC_SAMGQ, samgq),
OPC(5, OPC_GETLOD, getlod),
OPC(5, OPC_CONV, conv),
OPC(5, OPC_CONVM, convm),
OPC(5, OPC_GETSIZE, getsize),
OPC(5, OPC_GETBUF, getbuf),
OPC(5, OPC_GETPOS, getpos),
OPC(5, OPC_GETINFO, getinfo),
OPC(5, OPC_DSX, dsx),
OPC(5, OPC_DSY, dsy),
OPC(5, OPC_GATHER4R, gather4r),
OPC(5, OPC_GATHER4G, gather4g),
OPC(5, OPC_GATHER4B, gather4b),
OPC(5, OPC_GATHER4A, gather4a),
OPC(5, OPC_SAMGP0, samgp0),
OPC(5, OPC_SAMGP1, samgp1),
OPC(5, OPC_SAMGP2, samgp2),
OPC(5, OPC_SAMGP3, samgp3),
OPC(5, OPC_DSXPP_1, dsxpp.1),
OPC(5, OPC_DSYPP_1, dsypp.1),
OPC(5, OPC_RGETPOS, rgetpos),
OPC(5, OPC_RGETINFO, rgetinfo),
 
 
/* category 6: */
OPC(6, OPC_LDG, ldg),
OPC(6, OPC_LDL, ldl),
OPC(6, OPC_LDP, ldp),
OPC(6, OPC_STG, stg),
OPC(6, OPC_STL, stl),
OPC(6, OPC_STP, stp),
OPC(6, OPC_STI, sti),
OPC(6, OPC_G2L, g2l),
OPC(6, OPC_L2G, l2g),
OPC(6, OPC_PREFETCH, prefetch),
OPC(6, OPC_LDLW, ldlw),
OPC(6, OPC_STLW, stlw),
OPC(6, OPC_RESFMT, resfmt),
OPC(6, OPC_RESINFO, resinf),
OPC(6, OPC_ATOMIC_ADD_L, atomic.add.l),
OPC(6, OPC_ATOMIC_SUB_L, atomic.sub.l),
OPC(6, OPC_ATOMIC_XCHG_L, atomic.xchg.l),
OPC(6, OPC_ATOMIC_INC_L, atomic.inc.l),
OPC(6, OPC_ATOMIC_DEC_L, atomic.dec.l),
OPC(6, OPC_ATOMIC_CMPXCHG_L, atomic.cmpxchg.l),
OPC(6, OPC_ATOMIC_MIN_L, atomic.min.l),
OPC(6, OPC_ATOMIC_MAX_L, atomic.max.l),
OPC(6, OPC_ATOMIC_AND_L, atomic.and.l),
OPC(6, OPC_ATOMIC_OR_L, atomic.or.l),
OPC(6, OPC_ATOMIC_XOR_L, atomic.xor.l),
OPC(6, OPC_LDGB_TYPED_4D, ldgb.typed.4d),
OPC(6, OPC_STGB_4D_4, stgb.4d.4),
OPC(6, OPC_STIB, stib),
OPC(6, OPC_LDC_4, ldc.4),
OPC(6, OPC_LDLV, ldlv),
 
 
#undef OPC
};
 
#define GETINFO(instr) (&(opcs[((instr)->opc_cat << NOPC_BITS) | instr_opc(instr)]))
 
// XXX hack.. probably should move this table somewhere common:
#include "ir3.h"
const char *ir3_instr_name(struct ir3_instruction *instr)
{
if (instr->category == -1) return "??meta??";
return opcs[(instr->category << NOPC_BITS) | instr->opc].name;
}
 
static void print_instr(uint32_t *dwords, int level, int n)
{
instr_t *instr = (instr_t *)dwords;
uint32_t opc = instr_opc(instr);
const char *name;
 
if (debug & PRINT_VERBOSE)
printf("%s%04d[%08xx_%08xx] ", levels[level], n, dwords[1], dwords[0]);
 
/* NOTE: order flags are printed is a bit fugly.. but for now I
* try to match the order in llvm-a3xx disassembler for easy
* diff'ing..
*/
 
if (instr->sync)
printf("(sy)");
if (instr->ss && (instr->opc_cat <= 4))
printf("(ss)");
if (instr->jmp_tgt)
printf("(jp)");
if (instr->repeat && (instr->opc_cat <= 4)) {
printf("(rpt%d)", instr->repeat);
repeat = instr->repeat;
} else {
repeat = 0;
}
if (instr->ul && ((2 <= instr->opc_cat) && (instr->opc_cat <= 4)))
printf("(ul)");
 
name = GETINFO(instr)->name;
 
if (name) {
printf("%s", name);
GETINFO(instr)->print(instr);
} else {
printf("unknown(%d,%d)", instr->opc_cat, opc);
}
 
printf("\n");
}
 
int disasm_a3xx(uint32_t *dwords, int sizedwords, int level, enum shader_t type)
{
int i;
 
assert((sizedwords % 2) == 0);
 
for (i = 0; i < sizedwords; i += 2)
print_instr(&dwords[i], level, i/2);
 
return 0;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/ir3/instr-a3xx.h
0,0 → 1,702
/*
* Copyright (c) 2013 Rob Clark <robdclark@gmail.com>
*
* 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.
*/
 
#ifndef INSTR_A3XX_H_
#define INSTR_A3XX_H_
 
#define PACKED __attribute__((__packed__))
 
#include <stdint.h>
#include <assert.h>
 
typedef enum {
/* category 0: */
OPC_NOP = 0,
OPC_BR = 1,
OPC_JUMP = 2,
OPC_CALL = 3,
OPC_RET = 4,
OPC_KILL = 5,
OPC_END = 6,
OPC_EMIT = 7,
OPC_CUT = 8,
OPC_CHMASK = 9,
OPC_CHSH = 10,
OPC_FLOW_REV = 11,
 
/* category 1: */
/* no opc.. all category 1 are variants of mov */
 
/* category 2: */
OPC_ADD_F = 0,
OPC_MIN_F = 1,
OPC_MAX_F = 2,
OPC_MUL_F = 3,
OPC_SIGN_F = 4,
OPC_CMPS_F = 5,
OPC_ABSNEG_F = 6,
OPC_CMPV_F = 7,
/* 8 - invalid */
OPC_FLOOR_F = 9,
OPC_CEIL_F = 10,
OPC_RNDNE_F = 11,
OPC_RNDAZ_F = 12,
OPC_TRUNC_F = 13,
/* 14-15 - invalid */
OPC_ADD_U = 16,
OPC_ADD_S = 17,
OPC_SUB_U = 18,
OPC_SUB_S = 19,
OPC_CMPS_U = 20,
OPC_CMPS_S = 21,
OPC_MIN_U = 22,
OPC_MIN_S = 23,
OPC_MAX_U = 24,
OPC_MAX_S = 25,
OPC_ABSNEG_S = 26,
/* 27 - invalid */
OPC_AND_B = 28,
OPC_OR_B = 29,
OPC_NOT_B = 30,
OPC_XOR_B = 31,
/* 32 - invalid */
OPC_CMPV_U = 33,
OPC_CMPV_S = 34,
/* 35-47 - invalid */
OPC_MUL_U = 48,
OPC_MUL_S = 49,
OPC_MULL_U = 50,
OPC_BFREV_B = 51,
OPC_CLZ_S = 52,
OPC_CLZ_B = 53,
OPC_SHL_B = 54,
OPC_SHR_B = 55,
OPC_ASHR_B = 56,
OPC_BARY_F = 57,
OPC_MGEN_B = 58,
OPC_GETBIT_B = 59,
OPC_SETRM = 60,
OPC_CBITS_B = 61,
OPC_SHB = 62,
OPC_MSAD = 63,
 
/* category 3: */
OPC_MAD_U16 = 0,
OPC_MADSH_U16 = 1,
OPC_MAD_S16 = 2,
OPC_MADSH_M16 = 3, /* should this be .s16? */
OPC_MAD_U24 = 4,
OPC_MAD_S24 = 5,
OPC_MAD_F16 = 6,
OPC_MAD_F32 = 7,
OPC_SEL_B16 = 8,
OPC_SEL_B32 = 9,
OPC_SEL_S16 = 10,
OPC_SEL_S32 = 11,
OPC_SEL_F16 = 12,
OPC_SEL_F32 = 13,
OPC_SAD_S16 = 14,
OPC_SAD_S32 = 15,
 
/* category 4: */
OPC_RCP = 0,
OPC_RSQ = 1,
OPC_LOG2 = 2,
OPC_EXP2 = 3,
OPC_SIN = 4,
OPC_COS = 5,
OPC_SQRT = 6,
// 7-63 - invalid
 
/* category 5: */
OPC_ISAM = 0,
OPC_ISAML = 1,
OPC_ISAMM = 2,
OPC_SAM = 3,
OPC_SAMB = 4,
OPC_SAML = 5,
OPC_SAMGQ = 6,
OPC_GETLOD = 7,
OPC_CONV = 8,
OPC_CONVM = 9,
OPC_GETSIZE = 10,
OPC_GETBUF = 11,
OPC_GETPOS = 12,
OPC_GETINFO = 13,
OPC_DSX = 14,
OPC_DSY = 15,
OPC_GATHER4R = 16,
OPC_GATHER4G = 17,
OPC_GATHER4B = 18,
OPC_GATHER4A = 19,
OPC_SAMGP0 = 20,
OPC_SAMGP1 = 21,
OPC_SAMGP2 = 22,
OPC_SAMGP3 = 23,
OPC_DSXPP_1 = 24,
OPC_DSYPP_1 = 25,
OPC_RGETPOS = 26,
OPC_RGETINFO = 27,
 
/* category 6: */
OPC_LDG = 0, /* load-global */
OPC_LDL = 1,
OPC_LDP = 2,
OPC_STG = 3, /* store-global */
OPC_STL = 4,
OPC_STP = 5,
OPC_STI = 6,
OPC_G2L = 7,
OPC_L2G = 8,
OPC_PREFETCH = 9,
OPC_LDLW = 10,
OPC_STLW = 11,
OPC_RESFMT = 14,
OPC_RESINFO = 15,
OPC_ATOMIC_ADD_L = 16,
OPC_ATOMIC_SUB_L = 17,
OPC_ATOMIC_XCHG_L = 18,
OPC_ATOMIC_INC_L = 19,
OPC_ATOMIC_DEC_L = 20,
OPC_ATOMIC_CMPXCHG_L = 21,
OPC_ATOMIC_MIN_L = 22,
OPC_ATOMIC_MAX_L = 23,
OPC_ATOMIC_AND_L = 24,
OPC_ATOMIC_OR_L = 25,
OPC_ATOMIC_XOR_L = 26,
OPC_LDGB_TYPED_4D = 27,
OPC_STGB_4D_4 = 28,
OPC_STIB = 29,
OPC_LDC_4 = 30,
OPC_LDLV = 31,
 
/* meta instructions (category -1): */
/* placeholder instr to mark inputs/outputs: */
OPC_META_INPUT = 0,
OPC_META_OUTPUT = 1,
/* The "fan-in" and "fan-out" instructions are used for keeping
* track of instructions that write to multiple dst registers
* (fan-out) like texture sample instructions, or read multiple
* consecutive scalar registers (fan-in) (bary.f, texture samp)
*/
OPC_META_FO = 2,
OPC_META_FI = 3,
/* branches/flow control */
OPC_META_FLOW = 4,
OPC_META_PHI = 5,
 
} opc_t;
 
typedef enum {
TYPE_F16 = 0,
TYPE_F32 = 1,
TYPE_U16 = 2,
TYPE_U32 = 3,
TYPE_S16 = 4,
TYPE_S32 = 5,
TYPE_U8 = 6,
TYPE_S8 = 7, // XXX I assume?
} type_t;
 
static inline uint32_t type_size(type_t type)
{
switch (type) {
case TYPE_F32:
case TYPE_U32:
case TYPE_S32:
return 32;
case TYPE_F16:
case TYPE_U16:
case TYPE_S16:
return 16;
case TYPE_U8:
case TYPE_S8:
return 8;
default:
assert(0); /* invalid type */
return 0;
}
}
 
static inline int type_float(type_t type)
{
return (type == TYPE_F32) || (type == TYPE_F16);
}
 
static inline int type_uint(type_t type)
{
return (type == TYPE_U32) || (type == TYPE_U16) || (type == TYPE_U8);
}
 
static inline int type_sint(type_t type)
{
return (type == TYPE_S32) || (type == TYPE_S16) || (type == TYPE_S8);
}
 
typedef union PACKED {
/* normal gpr or const src register: */
struct PACKED {
uint32_t comp : 2;
uint32_t num : 10;
};
/* for immediate val: */
int32_t iim_val : 11;
/* to make compiler happy: */
uint32_t dummy32;
uint32_t dummy10 : 10;
uint32_t dummy11 : 11;
uint32_t dummy12 : 12;
uint32_t dummy13 : 13;
uint32_t dummy8 : 8;
} reg_t;
 
/* special registers: */
#define REG_A0 61 /* address register */
#define REG_P0 62 /* predicate register */
 
static inline int reg_special(reg_t reg)
{
return (reg.num == REG_A0) || (reg.num == REG_P0);
}
 
typedef struct PACKED {
/* dword0: */
int16_t immed : 16;
uint32_t dummy1 : 16;
 
/* dword1: */
uint32_t dummy2 : 8;
uint32_t repeat : 3;
uint32_t dummy3 : 1;
uint32_t ss : 1;
uint32_t dummy4 : 7;
uint32_t inv : 1;
uint32_t comp : 2;
uint32_t opc : 4;
uint32_t jmp_tgt : 1;
uint32_t sync : 1;
uint32_t opc_cat : 3;
} instr_cat0_t;
 
typedef struct PACKED {
/* dword0: */
union PACKED {
/* for normal src register: */
struct PACKED {
uint32_t src : 11;
/* at least low bit of pad must be zero or it will
* look like a address relative src
*/
uint32_t pad : 21;
};
/* for address relative: */
struct PACKED {
int32_t off : 10;
uint32_t src_rel_c : 1;
uint32_t src_rel : 1;
uint32_t unknown : 20;
};
/* for immediate: */
int32_t iim_val;
uint32_t uim_val;
float fim_val;
};
 
/* dword1: */
uint32_t dst : 8;
uint32_t repeat : 3;
uint32_t src_r : 1;
uint32_t ss : 1;
uint32_t ul : 1;
uint32_t dst_type : 3;
uint32_t dst_rel : 1;
uint32_t src_type : 3;
uint32_t src_c : 1;
uint32_t src_im : 1;
uint32_t even : 1;
uint32_t pos_inf : 1;
uint32_t must_be_0 : 2;
uint32_t jmp_tgt : 1;
uint32_t sync : 1;
uint32_t opc_cat : 3;
} instr_cat1_t;
 
typedef struct PACKED {
/* dword0: */
union PACKED {
struct PACKED {
uint32_t src1 : 11;
uint32_t must_be_zero1: 2;
uint32_t src1_im : 1; /* immediate */
uint32_t src1_neg : 1; /* negate */
uint32_t src1_abs : 1; /* absolute value */
};
struct PACKED {
uint32_t src1 : 10;
uint32_t src1_c : 1; /* relative-const */
uint32_t src1_rel : 1; /* relative address */
uint32_t must_be_zero : 1;
uint32_t dummy : 3;
} rel1;
struct PACKED {
uint32_t src1 : 12;
uint32_t src1_c : 1; /* const */
uint32_t dummy : 3;
} c1;
};
 
union PACKED {
struct PACKED {
uint32_t src2 : 11;
uint32_t must_be_zero2: 2;
uint32_t src2_im : 1; /* immediate */
uint32_t src2_neg : 1; /* negate */
uint32_t src2_abs : 1; /* absolute value */
};
struct PACKED {
uint32_t src2 : 10;
uint32_t src2_c : 1; /* relative-const */
uint32_t src2_rel : 1; /* relative address */
uint32_t must_be_zero : 1;
uint32_t dummy : 3;
} rel2;
struct PACKED {
uint32_t src2 : 12;
uint32_t src2_c : 1; /* const */
uint32_t dummy : 3;
} c2;
};
 
/* dword1: */
uint32_t dst : 8;
uint32_t repeat : 3;
uint32_t src1_r : 1;
uint32_t ss : 1;
uint32_t ul : 1; /* dunno */
uint32_t dst_half : 1; /* or widen/narrow.. ie. dst hrN <-> rN */
uint32_t ei : 1;
uint32_t cond : 3;
uint32_t src2_r : 1;
uint32_t full : 1; /* not half */
uint32_t opc : 6;
uint32_t jmp_tgt : 1;
uint32_t sync : 1;
uint32_t opc_cat : 3;
} instr_cat2_t;
 
typedef struct PACKED {
/* dword0: */
union PACKED {
struct PACKED {
uint32_t src1 : 11;
uint32_t must_be_zero1: 2;
uint32_t src2_c : 1;
uint32_t src1_neg : 1;
uint32_t src2_r : 1;
};
struct PACKED {
uint32_t src1 : 10;
uint32_t src1_c : 1;
uint32_t src1_rel : 1;
uint32_t must_be_zero : 1;
uint32_t dummy : 3;
} rel1;
struct PACKED {
uint32_t src1 : 12;
uint32_t src1_c : 1;
uint32_t dummy : 3;
} c1;
};
 
union PACKED {
struct PACKED {
uint32_t src3 : 11;
uint32_t must_be_zero2: 2;
uint32_t src3_r : 1;
uint32_t src2_neg : 1;
uint32_t src3_neg : 1;
};
struct PACKED {
uint32_t src3 : 10;
uint32_t src3_c : 1;
uint32_t src3_rel : 1;
uint32_t must_be_zero : 1;
uint32_t dummy : 3;
} rel2;
struct PACKED {
uint32_t src3 : 12;
uint32_t src3_c : 1;
uint32_t dummy : 3;
} c2;
};
 
/* dword1: */
uint32_t dst : 8;
uint32_t repeat : 3;
uint32_t src1_r : 1;
uint32_t ss : 1;
uint32_t ul : 1;
uint32_t dst_half : 1; /* or widen/narrow.. ie. dst hrN <-> rN */
uint32_t src2 : 8;
uint32_t opc : 4;
uint32_t jmp_tgt : 1;
uint32_t sync : 1;
uint32_t opc_cat : 3;
} instr_cat3_t;
 
static inline bool instr_cat3_full(instr_cat3_t *cat3)
{
switch (cat3->opc) {
case OPC_MAD_F16:
case OPC_MAD_U16:
case OPC_MAD_S16:
case OPC_SEL_B16:
case OPC_SEL_S16:
case OPC_SEL_F16:
case OPC_SAD_S16:
case OPC_SAD_S32: // really??
return false;
default:
return true;
}
}
 
typedef struct PACKED {
/* dword0: */
union PACKED {
struct PACKED {
uint32_t src : 11;
uint32_t must_be_zero1: 2;
uint32_t src_im : 1; /* immediate */
uint32_t src_neg : 1; /* negate */
uint32_t src_abs : 1; /* absolute value */
};
struct PACKED {
uint32_t src : 10;
uint32_t src_c : 1; /* relative-const */
uint32_t src_rel : 1; /* relative address */
uint32_t must_be_zero : 1;
uint32_t dummy : 3;
} rel;
struct PACKED {
uint32_t src : 12;
uint32_t src_c : 1; /* const */
uint32_t dummy : 3;
} c;
};
uint32_t dummy1 : 16; /* seem to be ignored */
 
/* dword1: */
uint32_t dst : 8;
uint32_t repeat : 3;
uint32_t src_r : 1;
uint32_t ss : 1;
uint32_t ul : 1;
uint32_t dst_half : 1; /* or widen/narrow.. ie. dst hrN <-> rN */
uint32_t dummy2 : 5; /* seem to be ignored */
uint32_t full : 1; /* not half */
uint32_t opc : 6;
uint32_t jmp_tgt : 1;
uint32_t sync : 1;
uint32_t opc_cat : 3;
} instr_cat4_t;
 
typedef struct PACKED {
/* dword0: */
union PACKED {
/* normal case: */
struct PACKED {
uint32_t full : 1; /* not half */
uint32_t src1 : 8;
uint32_t src2 : 8;
uint32_t dummy1 : 4; /* seem to be ignored */
uint32_t samp : 4;
uint32_t tex : 7;
} norm;
/* s2en case: */
struct PACKED {
uint32_t full : 1; /* not half */
uint32_t src1 : 8;
uint32_t src2 : 11;
uint32_t dummy1 : 1;
uint32_t src3 : 8;
uint32_t dummy2 : 3;
} s2en;
/* same in either case: */
// XXX I think, confirm this
struct PACKED {
uint32_t full : 1; /* not half */
uint32_t src1 : 8;
uint32_t pad : 23;
};
};
 
/* dword1: */
uint32_t dst : 8;
uint32_t wrmask : 4; /* write-mask */
uint32_t type : 3;
uint32_t dummy2 : 1; /* seems to be ignored */
uint32_t is_3d : 1;
 
uint32_t is_a : 1;
uint32_t is_s : 1;
uint32_t is_s2en : 1;
uint32_t is_o : 1;
uint32_t is_p : 1;
 
uint32_t opc : 5;
uint32_t jmp_tgt : 1;
uint32_t sync : 1;
uint32_t opc_cat : 3;
} instr_cat5_t;
 
/* [src1 + off], src2: */
typedef struct PACKED {
/* dword0: */
uint32_t mustbe1 : 1;
int32_t off : 13;
uint32_t src1 : 8;
uint32_t src1_im : 1;
uint32_t src2_im : 1;
uint32_t src2 : 8;
 
/* dword1: */
uint32_t dst : 8;
uint32_t dummy2 : 9;
uint32_t type : 3;
uint32_t dummy3 : 2;
uint32_t opc : 5;
uint32_t jmp_tgt : 1;
uint32_t sync : 1;
uint32_t opc_cat : 3;
} instr_cat6a_t;
 
/* [src1], src2: */
typedef struct PACKED {
/* dword0: */
uint32_t mustbe0 : 1;
uint32_t src1 : 8;
uint32_t ignore0 : 13;
uint32_t src1_im : 1;
uint32_t src2_im : 1;
uint32_t src2 : 8;
 
/* dword1: */
uint32_t dst : 8;
uint32_t dummy2 : 9;
uint32_t type : 3;
uint32_t dummy3 : 2;
uint32_t opc : 5;
uint32_t jmp_tgt : 1;
uint32_t sync : 1;
uint32_t opc_cat : 3;
} instr_cat6b_t;
 
/* I think some of the other cat6 instructions use additional
* sub-encodings..
*/
 
typedef union PACKED {
instr_cat6a_t a;
instr_cat6b_t b;
struct PACKED {
/* dword0: */
uint32_t has_off : 1;
uint32_t pad1 : 31;
 
/* dword1: */
uint32_t dst : 8;
uint32_t dummy2 : 9;
uint32_t type : 3;
uint32_t dummy3 : 2;
uint32_t opc : 5;
uint32_t jmp_tgt : 1;
uint32_t sync : 1;
uint32_t opc_cat : 3;
};
} instr_cat6_t;
 
typedef union PACKED {
instr_cat0_t cat0;
instr_cat1_t cat1;
instr_cat2_t cat2;
instr_cat3_t cat3;
instr_cat4_t cat4;
instr_cat5_t cat5;
instr_cat6_t cat6;
struct PACKED {
/* dword0: */
uint64_t pad1 : 40;
uint32_t repeat : 3; /* cat0-cat4 */
uint32_t pad2 : 1;
uint32_t ss : 1; /* cat1-cat4 (cat0??) */
uint32_t ul : 1; /* cat2-cat4 (and cat1 in blob.. which may be bug??) */
uint32_t pad3 : 13;
uint32_t jmp_tgt : 1;
uint32_t sync : 1;
uint32_t opc_cat : 3;
 
};
} instr_t;
 
static inline uint32_t instr_opc(instr_t *instr)
{
switch (instr->opc_cat) {
case 0: return instr->cat0.opc;
case 1: return 0;
case 2: return instr->cat2.opc;
case 3: return instr->cat3.opc;
case 4: return instr->cat4.opc;
case 5: return instr->cat5.opc;
case 6: return instr->cat6.opc;
default: return 0;
}
}
 
static inline bool is_mad(opc_t opc)
{
switch (opc) {
case OPC_MAD_U16:
case OPC_MAD_S16:
case OPC_MAD_U24:
case OPC_MAD_S24:
case OPC_MAD_F16:
case OPC_MAD_F32:
return true;
default:
return false;
}
}
 
static inline bool is_madsh(opc_t opc)
{
switch (opc) {
case OPC_MADSH_U16:
case OPC_MADSH_M16:
return true;
default:
return false;
}
}
 
#endif /* INSTR_A3XX_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/ir3/ir3.c
0,0 → 1,703
/*
* Copyright (c) 2012 Rob Clark <robdclark@gmail.com>
*
* 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 "ir3.h"
 
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdbool.h>
#include <errno.h>
 
#include "freedreno_util.h"
#include "instr-a3xx.h"
 
#define CHUNK_SZ 1020
 
struct ir3_heap_chunk {
struct ir3_heap_chunk *next;
uint32_t heap[CHUNK_SZ];
};
 
static void grow_heap(struct ir3 *shader)
{
struct ir3_heap_chunk *chunk = calloc(1, sizeof(*chunk));
chunk->next = shader->chunk;
shader->chunk = chunk;
shader->heap_idx = 0;
}
 
/* simple allocator to carve allocations out of an up-front allocated heap,
* so that we can free everything easily in one shot.
*/
void * ir3_alloc(struct ir3 *shader, int sz)
{
void *ptr;
 
sz = align(sz, 4) / 4;
 
if ((shader->heap_idx + sz) > CHUNK_SZ)
grow_heap(shader);
 
ptr = &shader->chunk->heap[shader->heap_idx];
shader->heap_idx += sz;
 
return ptr;
}
 
struct ir3 * ir3_create(void)
{
struct ir3 *shader =
calloc(1, sizeof(struct ir3));
grow_heap(shader);
return shader;
}
 
void ir3_destroy(struct ir3 *shader)
{
while (shader->chunk) {
struct ir3_heap_chunk *chunk = shader->chunk;
shader->chunk = chunk->next;
free(chunk);
}
free(shader->instrs);
free(shader->baryfs);
free(shader);
}
 
#define iassert(cond) do { \
if (!(cond)) { \
assert(cond); \
return -1; \
} } while (0)
 
static uint32_t reg(struct ir3_register *reg, struct ir3_info *info,
uint32_t repeat, uint32_t valid_flags)
{
reg_t val = { .dummy32 = 0 };
 
if (reg->flags & ~valid_flags) {
debug_printf("INVALID FLAGS: %x vs %x\n",
reg->flags, valid_flags);
}
 
if (!(reg->flags & IR3_REG_R))
repeat = 0;
 
if (reg->flags & IR3_REG_IMMED) {
val.iim_val = reg->iim_val;
} else {
unsigned components;
 
if (reg->flags & IR3_REG_RELATIV) {
components = reg->size;
val.dummy10 = reg->offset;
} else {
components = util_last_bit(reg->wrmask);
val.comp = reg->num & 0x3;
val.num = reg->num >> 2;
}
 
int16_t max = (reg->num + repeat + components - 1) >> 2;
 
if (reg->flags & IR3_REG_CONST) {
info->max_const = MAX2(info->max_const, max);
} else if (val.num == 63) {
/* ignore writes to dummy register r63.x */
} else if ((max != REG_A0) && (max != REG_P0)) {
if (reg->flags & IR3_REG_HALF) {
info->max_half_reg = MAX2(info->max_half_reg, max);
} else {
info->max_reg = MAX2(info->max_reg, max);
}
}
}
 
return val.dummy32;
}
 
static int emit_cat0(struct ir3_instruction *instr, void *ptr,
struct ir3_info *info)
{
instr_cat0_t *cat0 = ptr;
 
cat0->immed = instr->cat0.immed;
cat0->repeat = instr->repeat;
cat0->ss = !!(instr->flags & IR3_INSTR_SS);
cat0->inv = instr->cat0.inv;
cat0->comp = instr->cat0.comp;
cat0->opc = instr->opc;
cat0->jmp_tgt = !!(instr->flags & IR3_INSTR_JP);
cat0->sync = !!(instr->flags & IR3_INSTR_SY);
cat0->opc_cat = 0;
 
return 0;
}
 
static uint32_t type_flags(type_t type)
{
return (type_size(type) == 32) ? 0 : IR3_REG_HALF;
}
 
static int emit_cat1(struct ir3_instruction *instr, void *ptr,
struct ir3_info *info)
{
struct ir3_register *dst = instr->regs[0];
struct ir3_register *src = instr->regs[1];
instr_cat1_t *cat1 = ptr;
 
iassert(instr->regs_count == 2);
iassert(!((dst->flags ^ type_flags(instr->cat1.dst_type)) & IR3_REG_HALF));
iassert((src->flags & IR3_REG_IMMED) ||
!((src->flags ^ type_flags(instr->cat1.src_type)) & IR3_REG_HALF));
 
if (src->flags & IR3_REG_IMMED) {
cat1->iim_val = src->iim_val;
cat1->src_im = 1;
} else if (src->flags & IR3_REG_RELATIV) {
cat1->off = reg(src, info, instr->repeat,
IR3_REG_R | IR3_REG_CONST | IR3_REG_HALF | IR3_REG_RELATIV);
cat1->src_rel = 1;
cat1->src_rel_c = !!(src->flags & IR3_REG_CONST);
} else {
cat1->src = reg(src, info, instr->repeat,
IR3_REG_R | IR3_REG_CONST | IR3_REG_HALF);
cat1->src_c = !!(src->flags & IR3_REG_CONST);
}
 
cat1->dst = reg(dst, info, instr->repeat,
IR3_REG_RELATIV | IR3_REG_EVEN |
IR3_REG_R | IR3_REG_POS_INF | IR3_REG_HALF);
cat1->repeat = instr->repeat;
cat1->src_r = !!(src->flags & IR3_REG_R);
cat1->ss = !!(instr->flags & IR3_INSTR_SS);
cat1->ul = !!(instr->flags & IR3_INSTR_UL);
cat1->dst_type = instr->cat1.dst_type;
cat1->dst_rel = !!(dst->flags & IR3_REG_RELATIV);
cat1->src_type = instr->cat1.src_type;
cat1->even = !!(dst->flags & IR3_REG_EVEN);
cat1->pos_inf = !!(dst->flags & IR3_REG_POS_INF);
cat1->jmp_tgt = !!(instr->flags & IR3_INSTR_JP);
cat1->sync = !!(instr->flags & IR3_INSTR_SY);
cat1->opc_cat = 1;
 
return 0;
}
 
static int emit_cat2(struct ir3_instruction *instr, void *ptr,
struct ir3_info *info)
{
struct ir3_register *dst = instr->regs[0];
struct ir3_register *src1 = instr->regs[1];
struct ir3_register *src2 = instr->regs[2];
instr_cat2_t *cat2 = ptr;
unsigned absneg = ir3_cat2_absneg(instr->opc);
 
iassert((instr->regs_count == 2) || (instr->regs_count == 3));
 
if (src1->flags & IR3_REG_RELATIV) {
iassert(src1->num < (1 << 10));
cat2->rel1.src1 = reg(src1, info, instr->repeat,
IR3_REG_RELATIV | IR3_REG_CONST | IR3_REG_R |
IR3_REG_HALF | absneg);
cat2->rel1.src1_c = !!(src1->flags & IR3_REG_CONST);
cat2->rel1.src1_rel = 1;
} else if (src1->flags & IR3_REG_CONST) {
iassert(src1->num < (1 << 12));
cat2->c1.src1 = reg(src1, info, instr->repeat,
IR3_REG_CONST | IR3_REG_R | IR3_REG_HALF);
cat2->c1.src1_c = 1;
} else {
iassert(src1->num < (1 << 11));
cat2->src1 = reg(src1, info, instr->repeat,
IR3_REG_IMMED | IR3_REG_R | IR3_REG_HALF |
absneg);
}
cat2->src1_im = !!(src1->flags & IR3_REG_IMMED);
cat2->src1_neg = !!(src1->flags & (IR3_REG_FNEG | IR3_REG_SNEG | IR3_REG_BNOT));
cat2->src1_abs = !!(src1->flags & (IR3_REG_FABS | IR3_REG_SABS));
cat2->src1_r = !!(src1->flags & IR3_REG_R);
 
if (src2) {
iassert((src2->flags & IR3_REG_IMMED) ||
!((src1->flags ^ src2->flags) & IR3_REG_HALF));
 
if (src2->flags & IR3_REG_RELATIV) {
iassert(src2->num < (1 << 10));
cat2->rel2.src2 = reg(src2, info, instr->repeat,
IR3_REG_RELATIV | IR3_REG_CONST | IR3_REG_R |
IR3_REG_HALF | absneg);
cat2->rel2.src2_c = !!(src2->flags & IR3_REG_CONST);
cat2->rel2.src2_rel = 1;
} else if (src2->flags & IR3_REG_CONST) {
iassert(src2->num < (1 << 12));
cat2->c2.src2 = reg(src2, info, instr->repeat,
IR3_REG_CONST | IR3_REG_R | IR3_REG_HALF);
cat2->c2.src2_c = 1;
} else {
iassert(src2->num < (1 << 11));
cat2->src2 = reg(src2, info, instr->repeat,
IR3_REG_IMMED | IR3_REG_R | IR3_REG_HALF |
absneg);
}
 
cat2->src2_im = !!(src2->flags & IR3_REG_IMMED);
cat2->src2_neg = !!(src2->flags & (IR3_REG_FNEG | IR3_REG_SNEG | IR3_REG_BNOT));
cat2->src2_abs = !!(src2->flags & (IR3_REG_FABS | IR3_REG_SABS));
cat2->src2_r = !!(src2->flags & IR3_REG_R);
}
 
cat2->dst = reg(dst, info, instr->repeat,
IR3_REG_R | IR3_REG_EI | IR3_REG_HALF);
cat2->repeat = instr->repeat;
cat2->ss = !!(instr->flags & IR3_INSTR_SS);
cat2->ul = !!(instr->flags & IR3_INSTR_UL);
cat2->dst_half = !!((src1->flags ^ dst->flags) & IR3_REG_HALF);
cat2->ei = !!(dst->flags & IR3_REG_EI);
cat2->cond = instr->cat2.condition;
cat2->full = ! (src1->flags & IR3_REG_HALF);
cat2->opc = instr->opc;
cat2->jmp_tgt = !!(instr->flags & IR3_INSTR_JP);
cat2->sync = !!(instr->flags & IR3_INSTR_SY);
cat2->opc_cat = 2;
 
return 0;
}
 
static int emit_cat3(struct ir3_instruction *instr, void *ptr,
struct ir3_info *info)
{
struct ir3_register *dst = instr->regs[0];
struct ir3_register *src1 = instr->regs[1];
struct ir3_register *src2 = instr->regs[2];
struct ir3_register *src3 = instr->regs[3];
unsigned absneg = ir3_cat3_absneg(instr->opc);
instr_cat3_t *cat3 = ptr;
uint32_t src_flags = 0;
 
switch (instr->opc) {
case OPC_MAD_F16:
case OPC_MAD_U16:
case OPC_MAD_S16:
case OPC_SEL_B16:
case OPC_SEL_S16:
case OPC_SEL_F16:
case OPC_SAD_S16:
case OPC_SAD_S32: // really??
src_flags |= IR3_REG_HALF;
break;
default:
break;
}
 
iassert(instr->regs_count == 4);
iassert(!((src1->flags ^ src_flags) & IR3_REG_HALF));
iassert(!((src2->flags ^ src_flags) & IR3_REG_HALF));
iassert(!((src3->flags ^ src_flags) & IR3_REG_HALF));
 
if (src1->flags & IR3_REG_RELATIV) {
iassert(src1->num < (1 << 10));
cat3->rel1.src1 = reg(src1, info, instr->repeat,
IR3_REG_RELATIV | IR3_REG_CONST | IR3_REG_R |
IR3_REG_HALF | absneg);
cat3->rel1.src1_c = !!(src1->flags & IR3_REG_CONST);
cat3->rel1.src1_rel = 1;
} else if (src1->flags & IR3_REG_CONST) {
iassert(src1->num < (1 << 12));
cat3->c1.src1 = reg(src1, info, instr->repeat,
IR3_REG_CONST | IR3_REG_R | IR3_REG_HALF);
cat3->c1.src1_c = 1;
} else {
iassert(src1->num < (1 << 11));
cat3->src1 = reg(src1, info, instr->repeat,
IR3_REG_R | IR3_REG_HALF | absneg);
}
 
cat3->src1_neg = !!(src1->flags & (IR3_REG_FNEG | IR3_REG_SNEG | IR3_REG_BNOT));
cat3->src1_r = !!(src1->flags & IR3_REG_R);
 
cat3->src2 = reg(src2, info, instr->repeat,
IR3_REG_CONST | IR3_REG_R | IR3_REG_HALF | absneg);
cat3->src2_c = !!(src2->flags & IR3_REG_CONST);
cat3->src2_neg = !!(src2->flags & (IR3_REG_FNEG | IR3_REG_SNEG | IR3_REG_BNOT));
cat3->src2_r = !!(src2->flags & IR3_REG_R);
 
 
if (src3->flags & IR3_REG_RELATIV) {
iassert(src3->num < (1 << 10));
cat3->rel2.src3 = reg(src3, info, instr->repeat,
IR3_REG_RELATIV | IR3_REG_CONST | IR3_REG_R |
IR3_REG_HALF | absneg);
cat3->rel2.src3_c = !!(src3->flags & IR3_REG_CONST);
cat3->rel2.src3_rel = 1;
} else if (src3->flags & IR3_REG_CONST) {
iassert(src3->num < (1 << 12));
cat3->c2.src3 = reg(src3, info, instr->repeat,
IR3_REG_CONST | IR3_REG_R | IR3_REG_HALF);
cat3->c2.src3_c = 1;
} else {
iassert(src3->num < (1 << 11));
cat3->src3 = reg(src3, info, instr->repeat,
IR3_REG_R | IR3_REG_HALF | absneg);
}
 
cat3->src3_neg = !!(src3->flags & (IR3_REG_FNEG | IR3_REG_SNEG | IR3_REG_BNOT));
cat3->src3_r = !!(src3->flags & IR3_REG_R);
 
cat3->dst = reg(dst, info, instr->repeat, IR3_REG_R | IR3_REG_HALF);
cat3->repeat = instr->repeat;
cat3->ss = !!(instr->flags & IR3_INSTR_SS);
cat3->ul = !!(instr->flags & IR3_INSTR_UL);
cat3->dst_half = !!((src_flags ^ dst->flags) & IR3_REG_HALF);
cat3->opc = instr->opc;
cat3->jmp_tgt = !!(instr->flags & IR3_INSTR_JP);
cat3->sync = !!(instr->flags & IR3_INSTR_SY);
cat3->opc_cat = 3;
 
return 0;
}
 
static int emit_cat4(struct ir3_instruction *instr, void *ptr,
struct ir3_info *info)
{
struct ir3_register *dst = instr->regs[0];
struct ir3_register *src = instr->regs[1];
instr_cat4_t *cat4 = ptr;
 
iassert(instr->regs_count == 2);
 
if (src->flags & IR3_REG_RELATIV) {
iassert(src->num < (1 << 10));
cat4->rel.src = reg(src, info, instr->repeat,
IR3_REG_RELATIV | IR3_REG_CONST | IR3_REG_FNEG |
IR3_REG_FABS | IR3_REG_R | IR3_REG_HALF);
cat4->rel.src_c = !!(src->flags & IR3_REG_CONST);
cat4->rel.src_rel = 1;
} else if (src->flags & IR3_REG_CONST) {
iassert(src->num < (1 << 12));
cat4->c.src = reg(src, info, instr->repeat,
IR3_REG_CONST | IR3_REG_FNEG | IR3_REG_FABS |
IR3_REG_R | IR3_REG_HALF);
cat4->c.src_c = 1;
} else {
iassert(src->num < (1 << 11));
cat4->src = reg(src, info, instr->repeat,
IR3_REG_IMMED | IR3_REG_FNEG | IR3_REG_FABS |
IR3_REG_R | IR3_REG_HALF);
}
 
cat4->src_im = !!(src->flags & IR3_REG_IMMED);
cat4->src_neg = !!(src->flags & IR3_REG_FNEG);
cat4->src_abs = !!(src->flags & IR3_REG_FABS);
cat4->src_r = !!(src->flags & IR3_REG_R);
 
cat4->dst = reg(dst, info, instr->repeat, IR3_REG_R | IR3_REG_HALF);
cat4->repeat = instr->repeat;
cat4->ss = !!(instr->flags & IR3_INSTR_SS);
cat4->ul = !!(instr->flags & IR3_INSTR_UL);
cat4->dst_half = !!((src->flags ^ dst->flags) & IR3_REG_HALF);
cat4->full = ! (src->flags & IR3_REG_HALF);
cat4->opc = instr->opc;
cat4->jmp_tgt = !!(instr->flags & IR3_INSTR_JP);
cat4->sync = !!(instr->flags & IR3_INSTR_SY);
cat4->opc_cat = 4;
 
return 0;
}
 
static int emit_cat5(struct ir3_instruction *instr, void *ptr,
struct ir3_info *info)
{
struct ir3_register *dst = instr->regs[0];
struct ir3_register *src1 = instr->regs[1];
struct ir3_register *src2 = instr->regs[2];
struct ir3_register *src3 = instr->regs[3];
instr_cat5_t *cat5 = ptr;
 
iassert(!((dst->flags ^ type_flags(instr->cat5.type)) & IR3_REG_HALF));
 
if (src1) {
cat5->full = ! (src1->flags & IR3_REG_HALF);
cat5->src1 = reg(src1, info, instr->repeat, IR3_REG_HALF);
}
 
 
if (instr->flags & IR3_INSTR_S2EN) {
if (src2) {
iassert(!((src1->flags ^ src2->flags) & IR3_REG_HALF));
cat5->s2en.src2 = reg(src2, info, instr->repeat, IR3_REG_HALF);
}
if (src3) {
iassert(src3->flags & IR3_REG_HALF);
cat5->s2en.src3 = reg(src3, info, instr->repeat, IR3_REG_HALF);
}
iassert(!(instr->cat5.samp | instr->cat5.tex));
} else {
iassert(!src3);
if (src2) {
iassert(!((src1->flags ^ src2->flags) & IR3_REG_HALF));
cat5->norm.src2 = reg(src2, info, instr->repeat, IR3_REG_HALF);
}
cat5->norm.samp = instr->cat5.samp;
cat5->norm.tex = instr->cat5.tex;
}
 
cat5->dst = reg(dst, info, instr->repeat, IR3_REG_R | IR3_REG_HALF);
cat5->wrmask = dst->wrmask;
cat5->type = instr->cat5.type;
cat5->is_3d = !!(instr->flags & IR3_INSTR_3D);
cat5->is_a = !!(instr->flags & IR3_INSTR_A);
cat5->is_s = !!(instr->flags & IR3_INSTR_S);
cat5->is_s2en = !!(instr->flags & IR3_INSTR_S2EN);
cat5->is_o = !!(instr->flags & IR3_INSTR_O);
cat5->is_p = !!(instr->flags & IR3_INSTR_P);
cat5->opc = instr->opc;
cat5->jmp_tgt = !!(instr->flags & IR3_INSTR_JP);
cat5->sync = !!(instr->flags & IR3_INSTR_SY);
cat5->opc_cat = 5;
 
return 0;
}
 
static int emit_cat6(struct ir3_instruction *instr, void *ptr,
struct ir3_info *info)
{
struct ir3_register *dst = instr->regs[0];
struct ir3_register *src1 = instr->regs[1];
struct ir3_register *src2 = (instr->regs_count >= 3) ? instr->regs[2] : NULL;
instr_cat6_t *cat6 = ptr;
 
iassert(instr->regs_count >= 2);
 
if (instr->cat6.offset || instr->opc == OPC_LDG) {
instr_cat6a_t *cat6a = ptr;
 
cat6->has_off = true;
 
cat6a->dst = reg(dst, info, instr->repeat, IR3_REG_R | IR3_REG_HALF);
cat6a->src1 = reg(src1, info, instr->repeat, IR3_REG_IMMED);
cat6a->src1_im = !!(src1->flags & IR3_REG_IMMED);
if (src2) {
cat6a->src2 = reg(src2, info, instr->repeat, IR3_REG_IMMED);
cat6a->src2_im = !!(src2->flags & IR3_REG_IMMED);
}
cat6a->off = instr->cat6.offset;
} else {
instr_cat6b_t *cat6b = ptr;
 
cat6->has_off = false;
 
cat6b->dst = reg(dst, info, instr->repeat, IR3_REG_R | IR3_REG_HALF);
cat6b->src1 = reg(src1, info, instr->repeat, IR3_REG_IMMED);
cat6b->src1_im = !!(src1->flags & IR3_REG_IMMED);
if (src2) {
cat6b->src2 = reg(src2, info, instr->repeat, IR3_REG_IMMED);
cat6b->src2_im = !!(src2->flags & IR3_REG_IMMED);
}
}
 
cat6->type = instr->cat6.type;
cat6->opc = instr->opc;
cat6->jmp_tgt = !!(instr->flags & IR3_INSTR_JP);
cat6->sync = !!(instr->flags & IR3_INSTR_SY);
cat6->opc_cat = 6;
 
return 0;
}
 
static int (*emit[])(struct ir3_instruction *instr, void *ptr,
struct ir3_info *info) = {
emit_cat0, emit_cat1, emit_cat2, emit_cat3, emit_cat4, emit_cat5, emit_cat6,
};
 
void * ir3_assemble(struct ir3 *shader, struct ir3_info *info,
uint32_t gpu_id)
{
uint32_t *ptr, *dwords;
uint32_t i;
 
info->max_reg = -1;
info->max_half_reg = -1;
info->max_const = -1;
info->instrs_count = 0;
 
/* need a integer number of instruction "groups" (sets of 16
* instructions on a4xx or sets of 4 instructions on a3xx),
* so pad out w/ NOPs if needed: (NOTE each instruction is 64bits)
*/
if (gpu_id >= 400) {
info->sizedwords = 2 * align(shader->instrs_count, 16);
} else {
info->sizedwords = 2 * align(shader->instrs_count, 4);
}
 
ptr = dwords = calloc(4, info->sizedwords);
 
for (i = 0; i < shader->instrs_count; i++) {
struct ir3_instruction *instr = shader->instrs[i];
int ret = emit[instr->category](instr, dwords, info);
if (ret)
goto fail;
info->instrs_count += 1 + instr->repeat;
dwords += 2;
}
 
return ptr;
 
fail:
free(ptr);
return NULL;
}
 
static struct ir3_register * reg_create(struct ir3 *shader,
int num, int flags)
{
struct ir3_register *reg =
ir3_alloc(shader, sizeof(struct ir3_register));
reg->wrmask = 1;
reg->flags = flags;
reg->num = num;
return reg;
}
 
static void insert_instr(struct ir3 *shader,
struct ir3_instruction *instr)
{
#ifdef DEBUG
static uint32_t serialno = 0;
instr->serialno = ++serialno;
#endif
array_insert(shader->instrs, instr);
 
if (is_input(instr))
array_insert(shader->baryfs, instr);
}
 
struct ir3_block * ir3_block_create(struct ir3 *shader,
unsigned ntmp, unsigned nin, unsigned nout)
{
struct ir3_block *block;
unsigned size;
char *ptr;
 
size = sizeof(*block);
size += sizeof(block->temporaries[0]) * ntmp;
size += sizeof(block->inputs[0]) * nin;
size += sizeof(block->outputs[0]) * nout;
 
ptr = ir3_alloc(shader, size);
 
block = (void *)ptr;
ptr += sizeof(*block);
 
block->temporaries = (void *)ptr;
block->ntemporaries = ntmp;
ptr += sizeof(block->temporaries[0]) * ntmp;
 
block->inputs = (void *)ptr;
block->ninputs = nin;
ptr += sizeof(block->inputs[0]) * nin;
 
block->outputs = (void *)ptr;
block->noutputs = nout;
ptr += sizeof(block->outputs[0]) * nout;
 
block->shader = shader;
 
return block;
}
 
static struct ir3_instruction *instr_create(struct ir3_block *block, int nreg)
{
struct ir3_instruction *instr;
unsigned sz = sizeof(*instr) + (nreg * sizeof(instr->regs[0]));
char *ptr = ir3_alloc(block->shader, sz);
 
instr = (struct ir3_instruction *)ptr;
ptr += sizeof(*instr);
instr->regs = (struct ir3_register **)ptr;
 
#ifdef DEBUG
instr->regs_max = nreg;
#endif
 
return instr;
}
 
struct ir3_instruction * ir3_instr_create2(struct ir3_block *block,
int category, opc_t opc, int nreg)
{
struct ir3_instruction *instr = instr_create(block, nreg);
instr->block = block;
instr->category = category;
instr->opc = opc;
insert_instr(block->shader, instr);
return instr;
}
 
struct ir3_instruction * ir3_instr_create(struct ir3_block *block,
int category, opc_t opc)
{
/* NOTE: we could be slightly more clever, at least for non-meta,
* and choose # of regs based on category.
*/
return ir3_instr_create2(block, category, opc, 4);
}
 
/* only used by old compiler: */
struct ir3_instruction * ir3_instr_clone(struct ir3_instruction *instr)
{
struct ir3_instruction *new_instr = instr_create(instr->block,
instr->regs_count);
struct ir3_register **regs;
unsigned i;
 
regs = new_instr->regs;
*new_instr = *instr;
new_instr->regs = regs;
 
insert_instr(instr->block->shader, new_instr);
 
/* clone registers: */
new_instr->regs_count = 0;
for (i = 0; i < instr->regs_count; i++) {
struct ir3_register *reg = instr->regs[i];
struct ir3_register *new_reg =
ir3_reg_create(new_instr, reg->num, reg->flags);
*new_reg = *reg;
}
 
return new_instr;
}
 
struct ir3_register * ir3_reg_create(struct ir3_instruction *instr,
int num, int flags)
{
struct ir3_register *reg = reg_create(instr->block->shader, num, flags);
#ifdef DEBUG
debug_assert(instr->regs_count < instr->regs_max);
#endif
instr->regs[instr->regs_count++] = reg;
return reg;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/ir3/ir3.h
0,0 → 1,1053
/*
* Copyright (c) 2013 Rob Clark <robdclark@gmail.com>
*
* 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.
*/
 
#ifndef IR3_H_
#define IR3_H_
 
#include <stdint.h>
#include <stdbool.h>
 
#include "util/u_debug.h"
 
#include "instr-a3xx.h"
#include "disasm.h" /* TODO move 'enum shader_t' somewhere else.. */
 
/* low level intermediate representation of an adreno shader program */
 
struct ir3;
struct ir3_instruction;
struct ir3_block;
 
struct ir3_info {
uint16_t sizedwords;
uint16_t instrs_count; /* expanded to account for rpt's */
/* NOTE: max_reg, etc, does not include registers not touched
* by the shader (ie. vertex fetched via VFD_DECODE but not
* touched by shader)
*/
int8_t max_reg; /* highest GPR # used by shader */
int8_t max_half_reg;
int16_t max_const;
};
 
struct ir3_register {
enum {
IR3_REG_CONST = 0x001,
IR3_REG_IMMED = 0x002,
IR3_REG_HALF = 0x004,
IR3_REG_RELATIV= 0x008,
IR3_REG_R = 0x010,
/* Most instructions, it seems, can do float abs/neg but not
* integer. The CP pass needs to know what is intended (int or
* float) in order to do the right thing. For this reason the
* abs/neg flags are split out into float and int variants. In
* addition, .b (bitwise) operations, the negate is actually a
* bitwise not, so split that out into a new flag to make it
* more clear.
*/
IR3_REG_FNEG = 0x020,
IR3_REG_FABS = 0x040,
IR3_REG_SNEG = 0x080,
IR3_REG_SABS = 0x100,
IR3_REG_BNOT = 0x200,
IR3_REG_EVEN = 0x400,
IR3_REG_POS_INF= 0x800,
/* (ei) flag, end-input? Set on last bary, presumably to signal
* that the shader needs no more input:
*/
IR3_REG_EI = 0x1000,
/* meta-flags, for intermediate stages of IR, ie.
* before register assignment is done:
*/
IR3_REG_SSA = 0x2000, /* 'instr' is ptr to assigning instr */
IR3_REG_IA = 0x4000, /* meta-input dst is "assigned" */
IR3_REG_ADDR = 0x8000, /* register is a0.x */
} flags;
union {
/* normal registers:
* the component is in the low two bits of the reg #, so
* rN.x becomes: (N << 2) | x
*/
int num;
/* immediate: */
int32_t iim_val;
uint32_t uim_val;
float fim_val;
/* relative: */
int offset;
};
 
/* for IR3_REG_SSA, src registers contain ptr back to
* assigning instruction.
*/
struct ir3_instruction *instr;
 
union {
/* used for cat5 instructions, but also for internal/IR level
* tracking of what registers are read/written by an instruction.
* wrmask may be a bad name since it is used to represent both
* src and dst that touch multiple adjacent registers.
*/
unsigned wrmask;
/* for relative addressing, 32bits for array size is too small,
* but otoh we don't need to deal with disjoint sets, so instead
* use a simple size field (number of scalar components).
*/
unsigned size;
};
};
 
struct ir3_instruction {
struct ir3_block *block;
int category;
opc_t opc;
enum {
/* (sy) flag is set on first instruction, and after sample
* instructions (probably just on RAW hazard).
*/
IR3_INSTR_SY = 0x001,
/* (ss) flag is set on first instruction, and first instruction
* to depend on the result of "long" instructions (RAW hazard):
*
* rcp, rsq, log2, exp2, sin, cos, sqrt
*
* It seems to synchronize until all in-flight instructions are
* completed, for example:
*
* rsq hr1.w, hr1.w
* add.f hr2.z, (neg)hr2.z, hc0.y
* mul.f hr2.w, (neg)hr2.y, (neg)hr2.y
* rsq hr2.x, hr2.x
* (rpt1)nop
* mad.f16 hr2.w, hr2.z, hr2.z, hr2.w
* nop
* mad.f16 hr2.w, (neg)hr0.w, (neg)hr0.w, hr2.w
* (ss)(rpt2)mul.f hr1.x, (r)hr1.x, hr1.w
* (rpt2)mul.f hr0.x, (neg)(r)hr0.x, hr2.x
*
* The last mul.f does not have (ss) set, presumably because the
* (ss) on the previous instruction does the job.
*
* The blob driver also seems to set it on WAR hazards, although
* not really clear if this is needed or just blob compiler being
* sloppy. So far I haven't found a case where removing the (ss)
* causes problems for WAR hazard, but I could just be getting
* lucky:
*
* rcp r1.y, r3.y
* (ss)(rpt2)mad.f32 r3.y, (r)c9.x, r1.x, (r)r3.z
*
*/
IR3_INSTR_SS = 0x002,
/* (jp) flag is set on jump targets:
*/
IR3_INSTR_JP = 0x004,
IR3_INSTR_UL = 0x008,
IR3_INSTR_3D = 0x010,
IR3_INSTR_A = 0x020,
IR3_INSTR_O = 0x040,
IR3_INSTR_P = 0x080,
IR3_INSTR_S = 0x100,
IR3_INSTR_S2EN = 0x200,
/* meta-flags, for intermediate stages of IR, ie.
* before register assignment is done:
*/
IR3_INSTR_MARK = 0x1000,
} flags;
int repeat;
#ifdef DEBUG
unsigned regs_max;
#endif
unsigned regs_count;
struct ir3_register **regs;
union {
struct {
char inv;
char comp;
int immed;
} cat0;
struct {
type_t src_type, dst_type;
} cat1;
struct {
enum {
IR3_COND_LT = 0,
IR3_COND_LE = 1,
IR3_COND_GT = 2,
IR3_COND_GE = 3,
IR3_COND_EQ = 4,
IR3_COND_NE = 5,
} condition;
} cat2;
struct {
unsigned samp, tex;
type_t type;
} cat5;
struct {
type_t type;
int offset;
int iim_val;
} cat6;
/* for meta-instructions, just used to hold extra data
* before instruction scheduling, etc
*/
struct {
int off; /* component/offset */
} fo;
struct {
int aid;
} fi;
struct {
struct ir3_block *if_block, *else_block;
} flow;
struct {
struct ir3_block *block;
} inout;
 
/* XXX keep this as big as all other union members! */
uint32_t info[3];
};
 
/* transient values used during various algorithms: */
union {
/* The instruction depth is the max dependency distance to output.
*
* You can also think of it as the "cost", if we did any sort of
* optimization for register footprint. Ie. a value that is just
* result of moving a const to a reg would have a low cost, so to
* it could make sense to duplicate the instruction at various
* points where the result is needed to reduce register footprint.
*
* DEPTH_UNUSED used to mark unused instructions after depth
* calculation pass.
*/
#define DEPTH_UNUSED ~0
unsigned depth;
};
 
/* Used during CP and RA stages. For fanin and shader inputs/
* outputs where we need a sequence of consecutive registers,
* keep track of each src instructions left (ie 'n-1') and right
* (ie 'n+1') neighbor. The front-end must insert enough mov's
* to ensure that each instruction has at most one left and at
* most one right neighbor. During the copy-propagation pass,
* we only remove mov's when we can preserve this constraint.
* And during the RA stage, we use the neighbor information to
* allocate a block of registers in one shot.
*
* TODO: maybe just add something like:
* struct ir3_instruction_ref {
* struct ir3_instruction *instr;
* unsigned cnt;
* }
*
* Or can we get away without the refcnt stuff? It seems like
* it should be overkill.. the problem is if, potentially after
* already eliminating some mov's, if you have a single mov that
* needs to be grouped with it's neighbors in two different
* places (ex. shader output and a fanin).
*/
struct {
struct ir3_instruction *left, *right;
uint16_t left_cnt, right_cnt;
} cp;
 
/* an instruction can reference at most one address register amongst
* it's src/dst registers. Beyond that, you need to insert mov's.
*/
struct ir3_instruction *address;
 
/* in case of a instruction with relative dst instruction, we need to
* capture the dependency on the fanin for the previous values of
* the array elements. Since we don't know at compile time actually
* which array elements are written, this serves to preserve the
* unconditional write to array elements prior to the conditional
* write.
*
* TODO only cat1 can do indirect write.. we could maybe move this
* into instr->cat1.fanin (but would require the frontend to insert
* the extra mov)
*/
struct ir3_instruction *fanin;
 
struct ir3_instruction *next;
#ifdef DEBUG
uint32_t serialno;
#endif
};
 
static inline struct ir3_instruction *
ir3_neighbor_first(struct ir3_instruction *instr)
{
while (instr->cp.left)
instr = instr->cp.left;
return instr;
}
 
static inline int ir3_neighbor_count(struct ir3_instruction *instr)
{
int num = 1;
 
debug_assert(!instr->cp.left);
 
while (instr->cp.right) {
num++;
instr = instr->cp.right;
}
 
return num;
}
 
struct ir3_heap_chunk;
 
struct ir3 {
unsigned instrs_count, instrs_sz;
struct ir3_instruction **instrs;
 
/* Track bary.f (and ldlv) instructions.. this is needed in
* scheduling to ensure that all varying fetches happen before
* any potential kill instructions. The hw gets grumpy if all
* threads in a group are killed before the last bary.f gets
* a chance to signal end of input (ei).
*/
unsigned baryfs_count, baryfs_sz;
struct ir3_instruction **baryfs;
 
/* Track all indirect instructions (read and write). To avoid
* deadlock scenario where an address register gets scheduled,
* but other dependent src instructions cannot be scheduled due
* to dependency on a *different* address register value, the
* scheduler needs to ensure that all dependencies other than
* the instruction other than the address register are scheduled
* before the one that writes the address register. Having a
* convenient list of instructions that reference some address
* register simplifies this.
*/
unsigned indirects_count, indirects_sz;
struct ir3_instruction **indirects;
 
struct ir3_block *block;
unsigned heap_idx;
struct ir3_heap_chunk *chunk;
};
 
struct ir3_block {
struct ir3 *shader;
unsigned ntemporaries, ninputs, noutputs;
/* maps TGSI_FILE_TEMPORARY index back to the assigning instruction: */
struct ir3_instruction **temporaries;
struct ir3_instruction **inputs;
struct ir3_instruction **outputs;
/* only a single address register: */
struct ir3_instruction *address;
struct ir3_block *parent;
struct ir3_instruction *head;
};
 
struct ir3 * ir3_create(void);
void ir3_destroy(struct ir3 *shader);
void * ir3_assemble(struct ir3 *shader,
struct ir3_info *info, uint32_t gpu_id);
void * ir3_alloc(struct ir3 *shader, int sz);
 
struct ir3_block * ir3_block_create(struct ir3 *shader,
unsigned ntmp, unsigned nin, unsigned nout);
 
struct ir3_instruction * ir3_instr_create(struct ir3_block *block,
int category, opc_t opc);
struct ir3_instruction * ir3_instr_create2(struct ir3_block *block,
int category, opc_t opc, int nreg);
struct ir3_instruction * ir3_instr_clone(struct ir3_instruction *instr);
const char *ir3_instr_name(struct ir3_instruction *instr);
 
struct ir3_register * ir3_reg_create(struct ir3_instruction *instr,
int num, int flags);
 
 
static inline bool ir3_instr_check_mark(struct ir3_instruction *instr)
{
if (instr->flags & IR3_INSTR_MARK)
return true; /* already visited */
instr->flags |= IR3_INSTR_MARK;
return false;
}
 
static inline void ir3_clear_mark(struct ir3 *shader)
{
/* TODO would be nice to drop the instruction array.. for
* new compiler, _clear_mark() is all we use it for, and
* we could probably manage a linked list instead..
*
* Also, we'll probably want to mark instructions within
* a block, so tracking the list of instrs globally is
* unlikely to be what we want.
*/
unsigned i;
for (i = 0; i < shader->instrs_count; i++) {
struct ir3_instruction *instr = shader->instrs[i];
instr->flags &= ~IR3_INSTR_MARK;
}
}
 
static inline int ir3_instr_regno(struct ir3_instruction *instr,
struct ir3_register *reg)
{
unsigned i;
for (i = 0; i < instr->regs_count; i++)
if (reg == instr->regs[i])
return i;
return -1;
}
 
 
#define MAX_ARRAYS 16
 
/* comp:
* 0 - x
* 1 - y
* 2 - z
* 3 - w
*/
static inline uint32_t regid(int num, int comp)
{
return (num << 2) | (comp & 0x3);
}
 
static inline uint32_t reg_num(struct ir3_register *reg)
{
return reg->num >> 2;
}
 
static inline uint32_t reg_comp(struct ir3_register *reg)
{
return reg->num & 0x3;
}
 
static inline bool is_flow(struct ir3_instruction *instr)
{
return (instr->category == 0);
}
 
static inline bool is_kill(struct ir3_instruction *instr)
{
return is_flow(instr) && (instr->opc == OPC_KILL);
}
 
static inline bool is_nop(struct ir3_instruction *instr)
{
return is_flow(instr) && (instr->opc == OPC_NOP);
}
 
/* Is it a non-transformative (ie. not type changing) mov? This can
* also include absneg.s/absneg.f, which for the most part can be
* treated as a mov (single src argument).
*/
static inline bool is_same_type_mov(struct ir3_instruction *instr)
{
struct ir3_register *dst = instr->regs[0];
 
/* mov's that write to a0.x or p0.x are special: */
if (dst->num == regid(REG_P0, 0))
return false;
if (dst->num == regid(REG_A0, 0))
return false;
 
if ((instr->category == 1) &&
(instr->cat1.src_type == instr->cat1.dst_type))
return true;
if ((instr->category == 2) && ((instr->opc == OPC_ABSNEG_F) ||
(instr->opc == OPC_ABSNEG_S)))
return true;
return false;
}
 
static inline bool is_alu(struct ir3_instruction *instr)
{
return (1 <= instr->category) && (instr->category <= 3);
}
 
static inline bool is_sfu(struct ir3_instruction *instr)
{
return (instr->category == 4);
}
 
static inline bool is_tex(struct ir3_instruction *instr)
{
return (instr->category == 5);
}
 
static inline bool is_mem(struct ir3_instruction *instr)
{
return (instr->category == 6);
}
 
static inline bool is_input(struct ir3_instruction *instr)
{
/* in some cases, ldlv is used to fetch varying without
* interpolation.. fortunately inloc is the first src
* register in either case
*/
if (is_mem(instr) && (instr->opc == OPC_LDLV))
return true;
return (instr->category == 2) && (instr->opc == OPC_BARY_F);
}
 
static inline bool is_meta(struct ir3_instruction *instr)
{
/* TODO how should we count PHI (and maybe fan-in/out) which
* might actually contribute some instructions to the final
* result?
*/
return (instr->category == -1);
}
 
static inline bool writes_addr(struct ir3_instruction *instr)
{
if (instr->regs_count > 0) {
struct ir3_register *dst = instr->regs[0];
return !!(dst->flags & IR3_REG_ADDR);
}
return false;
}
 
static inline bool writes_pred(struct ir3_instruction *instr)
{
if (instr->regs_count > 0) {
struct ir3_register *dst = instr->regs[0];
return reg_num(dst) == REG_P0;
}
return false;
}
 
/* returns defining instruction for reg */
/* TODO better name */
static inline struct ir3_instruction *ssa(struct ir3_register *reg)
{
if (reg->flags & IR3_REG_SSA)
return reg->instr;
return NULL;
}
 
static inline bool conflicts(struct ir3_instruction *a,
struct ir3_instruction *b)
{
return (a && b) && (a != b);
}
 
static inline bool reg_gpr(struct ir3_register *r)
{
if (r->flags & (IR3_REG_CONST | IR3_REG_IMMED | IR3_REG_ADDR))
return false;
if ((reg_num(r) == REG_A0) || (reg_num(r) == REG_P0))
return false;
return true;
}
 
/* some cat2 instructions (ie. those which are not float) can embed an
* immediate:
*/
static inline bool ir3_cat2_int(opc_t opc)
{
switch (opc) {
case OPC_ADD_U:
case OPC_ADD_S:
case OPC_SUB_U:
case OPC_SUB_S:
case OPC_CMPS_U:
case OPC_CMPS_S:
case OPC_MIN_U:
case OPC_MIN_S:
case OPC_MAX_U:
case OPC_MAX_S:
case OPC_CMPV_U:
case OPC_CMPV_S:
case OPC_MUL_U:
case OPC_MUL_S:
case OPC_MULL_U:
case OPC_CLZ_S:
case OPC_ABSNEG_S:
case OPC_AND_B:
case OPC_OR_B:
case OPC_NOT_B:
case OPC_XOR_B:
case OPC_BFREV_B:
case OPC_CLZ_B:
case OPC_SHL_B:
case OPC_SHR_B:
case OPC_ASHR_B:
case OPC_MGEN_B:
case OPC_GETBIT_B:
case OPC_CBITS_B:
case OPC_BARY_F:
return true;
 
default:
return false;
}
}
 
 
/* map cat2 instruction to valid abs/neg flags: */
static inline unsigned ir3_cat2_absneg(opc_t opc)
{
switch (opc) {
case OPC_ADD_F:
case OPC_MIN_F:
case OPC_MAX_F:
case OPC_MUL_F:
case OPC_SIGN_F:
case OPC_CMPS_F:
case OPC_ABSNEG_F:
case OPC_CMPV_F:
case OPC_FLOOR_F:
case OPC_CEIL_F:
case OPC_RNDNE_F:
case OPC_RNDAZ_F:
case OPC_TRUNC_F:
case OPC_BARY_F:
return IR3_REG_FABS | IR3_REG_FNEG;
 
case OPC_ADD_U:
case OPC_ADD_S:
case OPC_SUB_U:
case OPC_SUB_S:
case OPC_CMPS_U:
case OPC_CMPS_S:
case OPC_MIN_U:
case OPC_MIN_S:
case OPC_MAX_U:
case OPC_MAX_S:
case OPC_CMPV_U:
case OPC_CMPV_S:
case OPC_MUL_U:
case OPC_MUL_S:
case OPC_MULL_U:
case OPC_CLZ_S:
return 0;
 
case OPC_ABSNEG_S:
return IR3_REG_SABS | IR3_REG_SNEG;
 
case OPC_AND_B:
case OPC_OR_B:
case OPC_NOT_B:
case OPC_XOR_B:
case OPC_BFREV_B:
case OPC_CLZ_B:
case OPC_SHL_B:
case OPC_SHR_B:
case OPC_ASHR_B:
case OPC_MGEN_B:
case OPC_GETBIT_B:
case OPC_CBITS_B:
return IR3_REG_BNOT;
 
default:
return 0;
}
}
 
/* map cat3 instructions to valid abs/neg flags: */
static inline unsigned ir3_cat3_absneg(opc_t opc)
{
switch (opc) {
case OPC_MAD_F16:
case OPC_MAD_F32:
case OPC_SEL_F16:
case OPC_SEL_F32:
return IR3_REG_FNEG;
 
case OPC_MAD_U16:
case OPC_MADSH_U16:
case OPC_MAD_S16:
case OPC_MADSH_M16:
case OPC_MAD_U24:
case OPC_MAD_S24:
case OPC_SEL_S16:
case OPC_SEL_S32:
case OPC_SAD_S16:
case OPC_SAD_S32:
/* neg *may* work on 3rd src.. */
 
case OPC_SEL_B16:
case OPC_SEL_B32:
 
default:
return 0;
}
}
 
#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)
 
/* iterator for an instructions's sources (reg), also returns src #: */
#define foreach_src_n(__srcreg, __n, __instr) \
if ((__instr)->regs_count) \
for (unsigned __cnt = (__instr)->regs_count - 1, __n = 0; __n < __cnt; __n++) \
if ((__srcreg = (__instr)->regs[__n + 1]))
 
/* iterator for an instructions's sources (reg): */
#define foreach_src(__srcreg, __instr) \
foreach_src_n(__srcreg, __i, __instr)
 
static inline unsigned __ssa_src_cnt(struct ir3_instruction *instr)
{
if (instr->fanin)
return instr->regs_count + 2;
if (instr->address)
return instr->regs_count + 1;
return instr->regs_count;
}
 
static inline struct ir3_instruction * __ssa_src_n(struct ir3_instruction *instr, unsigned n)
{
if (n == (instr->regs_count + 1))
return instr->fanin;
if (n == (instr->regs_count + 0))
return instr->address;
return ssa(instr->regs[n]);
}
 
#define __src_cnt(__instr) ((__instr)->address ? (__instr)->regs_count : (__instr)->regs_count - 1)
 
/* iterator for an instruction's SSA sources (instr), also returns src #: */
#define foreach_ssa_src_n(__srcinst, __n, __instr) \
if ((__instr)->regs_count) \
for (unsigned __cnt = __ssa_src_cnt(__instr) - 1, __n = 0; __n < __cnt; __n++) \
if ((__srcinst = __ssa_src_n(__instr, __n + 1)))
 
/* iterator for an instruction's SSA sources (instr): */
#define foreach_ssa_src(__srcinst, __instr) \
foreach_ssa_src_n(__srcinst, __i, __instr)
 
 
/* dump: */
#include <stdio.h>
void ir3_dump(struct ir3 *shader, const char *name,
struct ir3_block *block /* XXX maybe 'block' ptr should move to ir3? */,
FILE *f);
void ir3_dump_instr_single(struct ir3_instruction *instr);
void ir3_dump_instr_list(struct ir3_instruction *instr);
 
/* flatten if/else: */
int ir3_block_flatten(struct ir3_block *block);
 
/* depth calculation: */
int ir3_delayslots(struct ir3_instruction *assigner,
struct ir3_instruction *consumer, unsigned n);
void ir3_block_depth(struct ir3_block *block);
 
/* copy-propagate: */
void ir3_block_cp(struct ir3_block *block);
 
/* group neightbors and insert mov's to resolve conflicts: */
void ir3_block_group(struct ir3_block *block);
 
/* scheduling: */
int ir3_block_sched(struct ir3_block *block);
 
/* register assignment: */
int ir3_block_ra(struct ir3_block *block, enum shader_t type,
bool frag_coord, bool frag_face);
 
/* legalize: */
void ir3_block_legalize(struct ir3_block *block,
bool *has_samp, int *max_bary);
 
/* ************************************************************************* */
/* instruction helpers */
 
static inline struct ir3_instruction *
ir3_MOV(struct ir3_block *block, struct ir3_instruction *src, type_t type)
{
struct ir3_instruction *instr =
ir3_instr_create(block, 1, 0);
ir3_reg_create(instr, 0, 0); /* dst */
ir3_reg_create(instr, 0, IR3_REG_SSA)->instr = src;
instr->cat1.src_type = type;
instr->cat1.dst_type = type;
return instr;
}
 
static inline struct ir3_instruction *
ir3_COV(struct ir3_block *block, struct ir3_instruction *src,
type_t src_type, type_t dst_type)
{
struct ir3_instruction *instr =
ir3_instr_create(block, 1, 0);
ir3_reg_create(instr, 0, 0); /* dst */
ir3_reg_create(instr, 0, IR3_REG_SSA)->instr = src;
instr->cat1.src_type = src_type;
instr->cat1.dst_type = dst_type;
return instr;
}
 
#define INSTR1(CAT, name) \
static inline struct ir3_instruction * \
ir3_##name(struct ir3_block *block, \
struct ir3_instruction *a, unsigned aflags) \
{ \
struct ir3_instruction *instr = \
ir3_instr_create(block, CAT, OPC_##name); \
ir3_reg_create(instr, 0, 0); /* dst */ \
ir3_reg_create(instr, 0, IR3_REG_SSA | aflags)->instr = a; \
return instr; \
}
 
#define INSTR2(CAT, name) \
static inline struct ir3_instruction * \
ir3_##name(struct ir3_block *block, \
struct ir3_instruction *a, unsigned aflags, \
struct ir3_instruction *b, unsigned bflags) \
{ \
struct ir3_instruction *instr = \
ir3_instr_create(block, CAT, OPC_##name); \
ir3_reg_create(instr, 0, 0); /* dst */ \
ir3_reg_create(instr, 0, IR3_REG_SSA | aflags)->instr = a; \
ir3_reg_create(instr, 0, IR3_REG_SSA | bflags)->instr = b; \
return instr; \
}
 
#define INSTR3(CAT, name) \
static inline struct ir3_instruction * \
ir3_##name(struct ir3_block *block, \
struct ir3_instruction *a, unsigned aflags, \
struct ir3_instruction *b, unsigned bflags, \
struct ir3_instruction *c, unsigned cflags) \
{ \
struct ir3_instruction *instr = \
ir3_instr_create(block, CAT, OPC_##name); \
ir3_reg_create(instr, 0, 0); /* dst */ \
ir3_reg_create(instr, 0, IR3_REG_SSA | aflags)->instr = a; \
ir3_reg_create(instr, 0, IR3_REG_SSA | bflags)->instr = b; \
ir3_reg_create(instr, 0, IR3_REG_SSA | cflags)->instr = c; \
return instr; \
}
 
/* cat0 instructions: */
INSTR1(0, KILL);
 
/* cat2 instructions, most 2 src but some 1 src: */
INSTR2(2, ADD_F)
INSTR2(2, MIN_F)
INSTR2(2, MAX_F)
INSTR2(2, MUL_F)
INSTR1(2, SIGN_F)
INSTR2(2, CMPS_F)
INSTR1(2, ABSNEG_F)
INSTR2(2, CMPV_F)
INSTR1(2, FLOOR_F)
INSTR1(2, CEIL_F)
INSTR1(2, RNDNE_F)
INSTR1(2, RNDAZ_F)
INSTR1(2, TRUNC_F)
INSTR2(2, ADD_U)
INSTR2(2, ADD_S)
INSTR2(2, SUB_U)
INSTR2(2, SUB_S)
INSTR2(2, CMPS_U)
INSTR2(2, CMPS_S)
INSTR2(2, MIN_U)
INSTR2(2, MIN_S)
INSTR2(2, MAX_U)
INSTR2(2, MAX_S)
INSTR1(2, ABSNEG_S)
INSTR2(2, AND_B)
INSTR2(2, OR_B)
INSTR1(2, NOT_B)
INSTR2(2, XOR_B)
INSTR2(2, CMPV_U)
INSTR2(2, CMPV_S)
INSTR2(2, MUL_U)
INSTR2(2, MUL_S)
INSTR2(2, MULL_U)
INSTR1(2, BFREV_B)
INSTR1(2, CLZ_S)
INSTR1(2, CLZ_B)
INSTR2(2, SHL_B)
INSTR2(2, SHR_B)
INSTR2(2, ASHR_B)
INSTR2(2, BARY_F)
INSTR2(2, MGEN_B)
INSTR2(2, GETBIT_B)
INSTR1(2, SETRM)
INSTR1(2, CBITS_B)
INSTR2(2, SHB)
INSTR2(2, MSAD)
 
/* cat3 instructions: */
INSTR3(3, MAD_U16)
INSTR3(3, MADSH_U16)
INSTR3(3, MAD_S16)
INSTR3(3, MADSH_M16)
INSTR3(3, MAD_U24)
INSTR3(3, MAD_S24)
INSTR3(3, MAD_F16)
INSTR3(3, MAD_F32)
INSTR3(3, SEL_B16)
INSTR3(3, SEL_B32)
INSTR3(3, SEL_S16)
INSTR3(3, SEL_S32)
INSTR3(3, SEL_F16)
INSTR3(3, SEL_F32)
INSTR3(3, SAD_S16)
INSTR3(3, SAD_S32)
 
/* cat4 instructions: */
INSTR1(4, RCP)
INSTR1(4, RSQ)
INSTR1(4, LOG2)
INSTR1(4, EXP2)
INSTR1(4, SIN)
INSTR1(4, COS)
INSTR1(4, SQRT)
 
/* cat5 instructions: */
INSTR1(5, DSX)
INSTR1(5, DSY)
 
static inline struct ir3_instruction *
ir3_SAM(struct ir3_block *block, opc_t opc, type_t type,
unsigned wrmask, unsigned flags, unsigned samp, unsigned tex,
struct ir3_instruction *src0, struct ir3_instruction *src1)
{
struct ir3_instruction *sam;
struct ir3_register *reg;
 
sam = ir3_instr_create(block, 5, opc);
sam->flags |= flags;
ir3_reg_create(sam, 0, 0)->wrmask = wrmask;
if (src0) {
reg = ir3_reg_create(sam, 0, IR3_REG_SSA);
reg->wrmask = (1 << (src0->regs_count - 1)) - 1;
reg->instr = src0;
}
if (src1) {
reg = ir3_reg_create(sam, 0, IR3_REG_SSA);
reg->instr = src1;
reg->wrmask = (1 << (src1->regs_count - 1)) - 1;
}
sam->cat5.samp = samp;
sam->cat5.tex = tex;
sam->cat5.type = type;
 
return sam;
}
 
/* cat6 instructions: */
INSTR2(6, LDLV)
INSTR2(6, LDG)
 
/* ************************************************************************* */
/* split this out or find some helper to use.. like main/bitset.h.. */
 
#include <string.h>
 
#define MAX_REG 256
 
typedef uint8_t regmask_t[2 * MAX_REG / 8];
 
static inline unsigned regmask_idx(struct ir3_register *reg)
{
unsigned num = reg->num;
debug_assert(num < MAX_REG);
if (reg->flags & IR3_REG_HALF)
num += MAX_REG;
return num;
}
 
static inline void regmask_init(regmask_t *regmask)
{
memset(regmask, 0, sizeof(*regmask));
}
 
static inline void regmask_set(regmask_t *regmask, struct ir3_register *reg)
{
unsigned idx = regmask_idx(reg);
if (reg->flags & IR3_REG_RELATIV) {
unsigned i;
for (i = 0; i < reg->size; i++, idx++)
(*regmask)[idx / 8] |= 1 << (idx % 8);
} else {
unsigned mask;
for (mask = reg->wrmask; mask; mask >>= 1, idx++)
if (mask & 1)
(*regmask)[idx / 8] |= 1 << (idx % 8);
}
}
 
static inline void regmask_or(regmask_t *dst, regmask_t *a, regmask_t *b)
{
unsigned i;
for (i = 0; i < ARRAY_SIZE(*dst); i++)
(*dst)[i] = (*a)[i] | (*b)[i];
}
 
/* set bits in a if not set in b, conceptually:
* a |= (reg & ~b)
*/
static inline void regmask_set_if_not(regmask_t *a,
struct ir3_register *reg, regmask_t *b)
{
unsigned idx = regmask_idx(reg);
if (reg->flags & IR3_REG_RELATIV) {
unsigned i;
for (i = 0; i < reg->size; i++, idx++)
if (!((*b)[idx / 8] & (1 << (idx % 8))))
(*a)[idx / 8] |= 1 << (idx % 8);
} else {
unsigned mask;
for (mask = reg->wrmask; mask; mask >>= 1, idx++)
if (mask & 1)
if (!((*b)[idx / 8] & (1 << (idx % 8))))
(*a)[idx / 8] |= 1 << (idx % 8);
}
}
 
static inline bool regmask_get(regmask_t *regmask,
struct ir3_register *reg)
{
unsigned idx = regmask_idx(reg);
if (reg->flags & IR3_REG_RELATIV) {
unsigned i;
for (i = 0; i < reg->size; i++, idx++)
if ((*regmask)[idx / 8] & (1 << (idx % 8)))
return true;
} else {
unsigned mask;
for (mask = reg->wrmask; mask; mask >>= 1, idx++)
if (mask & 1)
if ((*regmask)[idx / 8] & (1 << (idx % 8)))
return true;
}
return false;
}
 
/* ************************************************************************* */
 
#endif /* IR3_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/ir3/ir3_cmdline.c
0,0 → 1,370
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdlib.h>
#include <err.h>
 
#include "tgsi/tgsi_parse.h"
#include "tgsi/tgsi_text.h"
#include "tgsi/tgsi_dump.h"
 
#include "freedreno_util.h"
 
#include "ir3_compiler.h"
#include "instr-a3xx.h"
#include "ir3.h"
 
static void dump_reg(const char *name, uint32_t r)
{
if (r != regid(63,0))
debug_printf("; %s: r%d.%c\n", name, r >> 2, "xyzw"[r & 0x3]);
}
 
static void dump_semantic(struct ir3_shader_variant *so,
unsigned sem, const char *name)
{
uint32_t regid;
regid = ir3_find_output_regid(so, ir3_semantic_name(sem, 0));
dump_reg(name, regid);
}
 
static void dump_info(struct ir3_shader_variant *so, const char *str)
{
uint32_t *bin;
const char *type = (so->type == SHADER_VERTEX) ? "VERT" : "FRAG";
 
// for debug, dump some before/after info:
// TODO make gpu_id configurable on cmdline
bin = ir3_shader_assemble(so, 320);
if (fd_mesa_debug & FD_DBG_DISASM) {
struct ir3_block *block = so->ir->block;
struct ir3_register *reg;
uint8_t regid;
unsigned i;
 
debug_printf("; %s: %s\n", type, str);
 
for (i = 0; i < block->ninputs; i++) {
if (!block->inputs[i]) {
debug_printf("; in%d unused\n", i);
continue;
}
reg = block->inputs[i]->regs[0];
regid = reg->num;
debug_printf("@in(%sr%d.%c)\tin%d\n",
(reg->flags & IR3_REG_HALF) ? "h" : "",
(regid >> 2), "xyzw"[regid & 0x3], i);
}
 
for (i = 0; i < block->noutputs; i++) {
if (!block->outputs[i]) {
debug_printf("; out%d unused\n", i);
continue;
}
/* kill shows up as a virtual output.. skip it! */
if (is_kill(block->outputs[i]))
continue;
reg = block->outputs[i]->regs[0];
regid = reg->num;
debug_printf("@out(%sr%d.%c)\tout%d\n",
(reg->flags & IR3_REG_HALF) ? "h" : "",
(regid >> 2), "xyzw"[regid & 0x3], i);
}
 
for (i = 0; i < so->immediates_count; i++) {
debug_printf("@const(c%d.x)\t", so->first_immediate + i);
debug_printf("0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
so->immediates[i].val[0],
so->immediates[i].val[1],
so->immediates[i].val[2],
so->immediates[i].val[3]);
}
 
disasm_a3xx(bin, so->info.sizedwords, 0, so->type);
 
debug_printf("; %s: outputs:", type);
for (i = 0; i < so->outputs_count; i++) {
uint8_t regid = so->outputs[i].regid;
ir3_semantic sem = so->outputs[i].semantic;
debug_printf(" r%d.%c (%u:%u)",
(regid >> 2), "xyzw"[regid & 0x3],
sem2name(sem), sem2idx(sem));
}
debug_printf("\n");
debug_printf("; %s: inputs:", type);
for (i = 0; i < so->inputs_count; i++) {
uint8_t regid = so->inputs[i].regid;
ir3_semantic sem = so->inputs[i].semantic;
debug_printf(" r%d.%c (%u:%u,cm=%x,il=%u,b=%u)",
(regid >> 2), "xyzw"[regid & 0x3],
sem2name(sem), sem2idx(sem),
so->inputs[i].compmask,
so->inputs[i].inloc,
so->inputs[i].bary);
}
debug_printf("\n");
}
 
/* print generic shader info: */
debug_printf("; %s: %u instructions, %d half, %d full\n", type,
so->info.instrs_count,
so->info.max_half_reg + 1,
so->info.max_reg + 1);
 
/* print shader type specific info: */
switch (so->type) {
case SHADER_VERTEX:
dump_semantic(so, TGSI_SEMANTIC_POSITION, "pos");
dump_semantic(so, TGSI_SEMANTIC_PSIZE, "psize");
break;
case SHADER_FRAGMENT:
dump_reg("pos (bary)", so->pos_regid);
dump_semantic(so, TGSI_SEMANTIC_POSITION, "posz");
dump_semantic(so, TGSI_SEMANTIC_COLOR, "color");
/* these two are hard-coded since we don't know how to
* program them to anything but all 0's...
*/
if (so->frag_coord)
debug_printf("; fragcoord: r0.x\n");
if (so->frag_face)
debug_printf("; fragface: hr0.x\n");
break;
case SHADER_COMPUTE:
break;
}
free(bin);
 
debug_printf("\n");
}
 
 
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 reset_variant(struct ir3_shader_variant *v, const char *msg)
{
printf("; %s\n", msg);
v->inputs_count = 0;
v->outputs_count = 0;
v->total_in = 0;
v->has_samp = false;
v->immediates_count = 0;
}
 
static void print_usage(void)
{
printf("Usage: ir3_compiler [OPTIONS]... FILE\n");
printf(" --verbose - verbose compiler/debug messages\n");
printf(" --binning-pass - generate binning pass shader (VERT)\n");
printf(" --color-two-side - emulate two-sided color (FRAG)\n");
printf(" --half-precision - use half-precision\n");
printf(" --saturate-s MASK - bitmask of samplers to saturate S coord\n");
printf(" --saturate-t MASK - bitmask of samplers to saturate T coord\n");
printf(" --saturate-r MASK - bitmask of samplers to saturate R coord\n");
printf(" --nocp - disable copy propagation\n");
printf(" --nir - use NIR compiler\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 ir3_shader_variant v;
struct ir3_shader_key key = {};
const char *info;
void *ptr;
size_t size;
int use_nir = 0;
 
fd_mesa_debug |= FD_DBG_DISASM;
 
/* cmdline args which impact shader variant get spit out in a
* comment on the first line.. a quick/dirty way to preserve
* that info so when ir3test recompiles the shader with a new
* compiler version, we use the same shader-key settings:
*/
debug_printf("; options:");
 
while (n < argc) {
if (!strcmp(argv[n], "--verbose")) {
fd_mesa_debug |= FD_DBG_OPTDUMP | FD_DBG_MSGS | FD_DBG_OPTMSGS;
n++;
continue;
}
 
if (!strcmp(argv[n], "--binning-pass")) {
debug_printf(" %s", argv[n]);
key.binning_pass = true;
n++;
continue;
}
 
if (!strcmp(argv[n], "--color-two-side")) {
debug_printf(" %s", argv[n]);
key.color_two_side = true;
n++;
continue;
}
 
if (!strcmp(argv[n], "--half-precision")) {
debug_printf(" %s", argv[n]);
key.half_precision = true;
n++;
continue;
}
 
if (!strcmp(argv[n], "--saturate-s")) {
debug_printf(" %s %s", argv[n], argv[n+1]);
key.vsaturate_s = key.fsaturate_s = strtol(argv[n+1], NULL, 0);
n += 2;
continue;
}
 
if (!strcmp(argv[n], "--saturate-t")) {
debug_printf(" %s %s", argv[n], argv[n+1]);
key.vsaturate_t = key.fsaturate_t = strtol(argv[n+1], NULL, 0);
n += 2;
continue;
}
 
if (!strcmp(argv[n], "--saturate-r")) {
debug_printf(" %s %s", argv[n], argv[n+1]);
key.vsaturate_r = key.fsaturate_r = strtol(argv[n+1], NULL, 0);
n += 2;
continue;
}
 
if (!strcmp(argv[n], "--nocp")) {
fd_mesa_debug |= FD_DBG_NOCP;
n++;
continue;
}
if (!strcmp(argv[n], "--nir")) {
use_nir = true;
n++;
continue;
}
 
if (!strcmp(argv[n], "--help")) {
print_usage();
return 0;
}
 
break;
}
debug_printf("\n");
 
filename = argv[n];
 
memset(&v, 0, sizeof(v));
v.key = key;
 
ret = read_file(filename, &ptr, &size);
if (ret) {
print_usage();
return ret;
}
 
if (fd_mesa_debug & FD_DBG_OPTMSGS)
debug_printf("%s\n", (char *)ptr);
 
if (!tgsi_text_translate(ptr, toks, Elements(toks)))
errx(1, "could not parse `%s'", filename);
 
tgsi_parse_init(&parse, toks);
switch (parse.FullHeader.Processor.Processor) {
case TGSI_PROCESSOR_FRAGMENT:
v.type = SHADER_FRAGMENT;
break;
case TGSI_PROCESSOR_VERTEX:
v.type = SHADER_VERTEX;
break;
case TGSI_PROCESSOR_COMPUTE:
v.type = SHADER_COMPUTE;
break;
}
 
if (use_nir) {
info = "NIR compiler";
ret = ir3_compile_shader_nir(&v, toks, key);
} else {
info = "TGSI compiler";
ret = ir3_compile_shader(&v, toks, key, true);
}
 
if (ret) {
reset_variant(&v, "compiler failed, trying without copy propagation!");
info = "compiler (no copy propagation)";
ret = ir3_compile_shader(&v, toks, key, false);
}
 
if (ret) {
fprintf(stderr, "compiler failed!\n");
return ret;
}
dump_info(&v, info);
}
 
void _mesa_error_no_memory(const char *caller);
 
void
_mesa_error_no_memory(const char *caller)
{
fprintf(stderr, "Mesa error: out of memory in %s", caller);
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/ir3/ir3_compiler.c
0,0 → 1,3739
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include <stdarg.h>
 
#include "pipe/p_state.h"
#include "util/u_string.h"
#include "util/u_memory.h"
#include "util/u_inlines.h"
#include "tgsi/tgsi_lowering.h"
#include "tgsi/tgsi_parse.h"
#include "tgsi/tgsi_ureg.h"
#include "tgsi/tgsi_info.h"
#include "tgsi/tgsi_strings.h"
#include "tgsi/tgsi_dump.h"
#include "tgsi/tgsi_scan.h"
 
#include "freedreno_util.h"
 
#include "ir3_compiler.h"
#include "ir3_shader.h"
 
#include "instr-a3xx.h"
#include "ir3.h"
 
struct ir3_compile_context {
const struct tgsi_token *tokens;
bool free_tokens;
struct ir3 *ir;
struct ir3_shader_variant *so;
uint16_t integer_s;
 
struct ir3_block *block;
struct ir3_instruction *current_instr;
 
/* we need to defer updates to block->outputs[] until the end
* of an instruction (so we don't see new value until *after*
* the src registers are processed)
*/
struct {
struct ir3_instruction *instr, **instrp;
} output_updates[64];
unsigned num_output_updates;
 
/* are we in a sequence of "atomic" instructions?
*/
bool atomic;
 
/* For fragment shaders, from the hw perspective the only
* actual input is r0.xy position register passed to bary.f.
* But TGSI doesn't know that, it still declares things as
* IN[] registers. So we do all the input tracking normally
* and fix things up after compile_instructions()
*
* NOTE that frag_pos is the hardware position (possibly it
* is actually an index or tag or some such.. it is *not*
* values that can be directly used for gl_FragCoord..)
*/
struct ir3_instruction *frag_pos, *frag_face, *frag_coord[4];
 
/* For vertex shaders, keep track of the system values sources */
struct ir3_instruction *vertex_id, *basevertex, *instance_id;
 
struct tgsi_parse_context parser;
unsigned type;
 
struct tgsi_shader_info info;
 
/* hmm, would be nice if tgsi_scan_shader figured this out
* for us:
*/
struct {
unsigned first, last;
struct ir3_instruction *fanin;
} array[MAX_ARRAYS];
uint32_t array_dirty;
/* offset into array[], per file, of first array info */
uint8_t array_offsets[TGSI_FILE_COUNT];
 
/* for calculating input/output positions/linkages: */
unsigned next_inloc;
 
/* a4xx (at least patchlevel 0) cannot seem to flat-interpolate
* so we need to use ldlv.u32 to load the varying directly:
*/
bool flat_bypass;
 
unsigned num_internal_temps;
struct tgsi_src_register internal_temps[8];
 
/* for looking up which system value is which */
unsigned sysval_semantics[8];
 
/* idx/slot for last compiler generated immediate */
unsigned immediate_idx;
 
/* stack of branch instructions that mark (potentially nested)
* branch if/else/loop/etc
*/
struct {
struct ir3_instruction *instr, *cond;
bool inv; /* true iff in else leg of branch */
} branch[16];
unsigned int branch_count;
 
/* list of kill instructions: */
struct ir3_instruction *kill[16];
unsigned int kill_count;
 
/* used when dst is same as one of the src, to avoid overwriting a
* src element before the remaining scalar instructions that make
* up the vector operation
*/
struct tgsi_dst_register tmp_dst;
struct tgsi_src_register *tmp_src;
 
/* just for catching incorrect use of get_dst()/put_dst():
*/
bool using_tmp_dst;
};
 
 
static void vectorize(struct ir3_compile_context *ctx,
struct ir3_instruction *instr, struct tgsi_dst_register *dst,
int nsrcs, ...);
static void create_mov(struct ir3_compile_context *ctx,
struct tgsi_dst_register *dst, struct tgsi_src_register *src);
static type_t get_ftype(struct ir3_compile_context *ctx);
static type_t get_utype(struct ir3_compile_context *ctx);
 
static unsigned setup_arrays(struct ir3_compile_context *ctx, unsigned file, unsigned i)
{
/* ArrayID 0 for a given file is the legacy array spanning the entire file: */
ctx->array[i].first = 0;
ctx->array[i].last = ctx->info.file_max[file];
ctx->array_offsets[file] = i;
i += ctx->info.array_max[file] + 1;
return i;
}
 
static unsigned
compile_init(struct ir3_compile_context *ctx, struct ir3_shader_variant *so,
const struct tgsi_token *tokens)
{
unsigned ret, i;
struct tgsi_shader_info *info = &ctx->info;
struct tgsi_lowering_config lconfig = {
.color_two_side = so->key.color_two_side,
.lower_DST = true,
.lower_XPD = true,
.lower_SCS = true,
.lower_LRP = true,
.lower_FRC = true,
.lower_POW = true,
.lower_LIT = true,
.lower_EXP = true,
.lower_LOG = true,
.lower_DP4 = true,
.lower_DP3 = true,
.lower_DPH = true,
.lower_DP2 = true,
.lower_DP2A = true,
};
 
switch (so->type) {
case SHADER_FRAGMENT:
case SHADER_COMPUTE:
lconfig.saturate_s = so->key.fsaturate_s;
lconfig.saturate_t = so->key.fsaturate_t;
lconfig.saturate_r = so->key.fsaturate_r;
ctx->integer_s = so->key.finteger_s;
break;
case SHADER_VERTEX:
lconfig.saturate_s = so->key.vsaturate_s;
lconfig.saturate_t = so->key.vsaturate_t;
lconfig.saturate_r = so->key.vsaturate_r;
ctx->integer_s = so->key.vinteger_s;
break;
}
 
if (!so->shader) {
/* hack for standalone compiler which does not have
* screen/context:
*/
} else if (ir3_shader_gpuid(so->shader) >= 400) {
/* a4xx seems to have *no* sam.p */
lconfig.lower_TXP = ~0; /* lower all txp */
/* need special handling for "flat" */
ctx->flat_bypass = true;
} else {
/* a3xx just needs to avoid sam.p for 3d tex */
lconfig.lower_TXP = (1 << TGSI_TEXTURE_3D);
/* no special handling for "flat" */
ctx->flat_bypass = false;
}
 
ctx->tokens = tgsi_transform_lowering(&lconfig, tokens, &ctx->info);
ctx->free_tokens = !!ctx->tokens;
if (!ctx->tokens) {
/* no lowering */
ctx->tokens = tokens;
}
ctx->ir = so->ir;
ctx->so = so;
ctx->array_dirty = 0;
ctx->next_inloc = 8;
ctx->num_internal_temps = 0;
ctx->branch_count = 0;
ctx->kill_count = 0;
ctx->block = NULL;
ctx->current_instr = NULL;
ctx->num_output_updates = 0;
ctx->atomic = false;
ctx->frag_pos = NULL;
ctx->frag_face = NULL;
ctx->vertex_id = NULL;
ctx->instance_id = NULL;
ctx->tmp_src = NULL;
ctx->using_tmp_dst = false;
 
memset(ctx->frag_coord, 0, sizeof(ctx->frag_coord));
memset(ctx->array, 0, sizeof(ctx->array));
memset(ctx->array_offsets, 0, sizeof(ctx->array_offsets));
 
#define FM(x) (1 << TGSI_FILE_##x)
/* NOTE: if relative addressing is used, we set constlen in
* the compiler (to worst-case value) since we don't know in
* the assembler what the max addr reg value can be:
*/
if (info->indirect_files & FM(CONSTANT))
so->constlen = MIN2(255, ctx->info.const_file_max[0] + 1);
 
i = 0;
i += setup_arrays(ctx, TGSI_FILE_INPUT, i);
i += setup_arrays(ctx, TGSI_FILE_TEMPORARY, i);
i += setup_arrays(ctx, TGSI_FILE_OUTPUT, i);
/* any others? we don't track arrays for const..*/
 
/* Immediates go after constants: */
so->first_immediate = so->first_driver_param =
info->const_file_max[0] + 1;
/* 1 unit for the vertex id base */
if (so->type == SHADER_VERTEX)
so->first_immediate++;
/* 4 (vec4) units for ubo base addresses */
so->first_immediate += 4;
ctx->immediate_idx = 4 * (ctx->info.file_max[TGSI_FILE_IMMEDIATE] + 1);
 
ret = tgsi_parse_init(&ctx->parser, ctx->tokens);
if (ret != TGSI_PARSE_OK)
return ret;
 
ctx->type = ctx->parser.FullHeader.Processor.Processor;
 
return ret;
}
 
static void
compile_error(struct ir3_compile_context *ctx, const char *format, ...)
{
va_list ap;
va_start(ap, format);
_debug_vprintf(format, ap);
va_end(ap);
tgsi_dump(ctx->tokens, 0);
debug_assert(0);
}
 
#define compile_assert(ctx, cond) do { \
if (!(cond)) compile_error((ctx), "failed assert: "#cond"\n"); \
} while (0)
 
static void
compile_free(struct ir3_compile_context *ctx)
{
if (ctx->free_tokens)
free((void *)ctx->tokens);
tgsi_parse_free(&ctx->parser);
}
 
struct instr_translater {
void (*fxn)(const struct instr_translater *t,
struct ir3_compile_context *ctx,
struct tgsi_full_instruction *inst);
unsigned tgsi_opc;
opc_t opc;
opc_t hopc; /* opc to use for half_precision mode, if different */
unsigned arg;
};
 
static void
instr_finish(struct ir3_compile_context *ctx)
{
unsigned i;
 
if (ctx->atomic)
return;
 
for (i = 0; i < ctx->num_output_updates; i++)
*(ctx->output_updates[i].instrp) = ctx->output_updates[i].instr;
 
ctx->num_output_updates = 0;
 
while (ctx->array_dirty) {
unsigned aid = ffs(ctx->array_dirty) - 1;
ctx->array[aid].fanin = NULL;
ctx->array_dirty &= ~(1 << aid);
}
}
 
/* For "atomic" groups of instructions, for example the four scalar
* instructions to perform a vec4 operation. Basically this just
* blocks out handling of output_updates so the next scalar instruction
* still sees the result from before the start of the atomic group.
*
* NOTE: when used properly, this could probably replace get/put_dst()
* stuff.
*/
static void
instr_atomic_start(struct ir3_compile_context *ctx)
{
ctx->atomic = true;
}
 
static void
instr_atomic_end(struct ir3_compile_context *ctx)
{
ctx->atomic = false;
instr_finish(ctx);
}
 
static struct ir3_instruction *
instr_create(struct ir3_compile_context *ctx, int category, opc_t opc)
{
instr_finish(ctx);
return (ctx->current_instr = ir3_instr_create(ctx->block, category, opc));
}
 
static struct ir3_block *
push_block(struct ir3_compile_context *ctx)
{
struct ir3_block *block;
unsigned ntmp, nin, nout;
 
#define SCALAR_REGS(file) (4 * (ctx->info.file_max[TGSI_FILE_ ## file] + 1))
 
/* hmm, give ourselves room to create 8 extra temporaries (vec4):
*/
ntmp = SCALAR_REGS(TEMPORARY);
ntmp += 8 * 4;
 
nout = SCALAR_REGS(OUTPUT);
nin = SCALAR_REGS(INPUT) + SCALAR_REGS(SYSTEM_VALUE);
 
/* for outermost block, 'inputs' are the actual shader INPUT
* register file. Reads from INPUT registers always go back to
* top block. For nested blocks, 'inputs' is used to track any
* TEMPORARY file register from one of the enclosing blocks that
* is ready in this block.
*/
if (!ctx->block) {
/* NOTE: fragment shaders actually have two inputs (r0.xy, the
* position)
*/
if (ctx->type == TGSI_PROCESSOR_FRAGMENT) {
int n = 2;
if (ctx->info.reads_position)
n += 4;
if (ctx->info.uses_frontface)
n += 4;
nin = MAX2(n, nin);
nout += ARRAY_SIZE(ctx->kill);
}
} else {
nin = ntmp;
}
 
block = ir3_block_create(ctx->ir, ntmp, nin, nout);
 
if ((ctx->type == TGSI_PROCESSOR_FRAGMENT) && !ctx->block)
block->noutputs -= ARRAY_SIZE(ctx->kill);
 
block->parent = ctx->block;
ctx->block = block;
 
return block;
}
 
static void
pop_block(struct ir3_compile_context *ctx)
{
ctx->block = ctx->block->parent;
compile_assert(ctx, ctx->block);
}
 
static struct ir3_instruction *
create_output(struct ir3_block *block, struct ir3_instruction *instr,
unsigned n)
{
struct ir3_instruction *out;
 
out = ir3_instr_create(block, -1, OPC_META_OUTPUT);
out->inout.block = block;
ir3_reg_create(out, n, 0);
if (instr)
ir3_reg_create(out, 0, IR3_REG_SSA)->instr = instr;
 
return out;
}
 
static struct ir3_instruction *
create_input(struct ir3_block *block, struct ir3_instruction *instr,
unsigned n)
{
struct ir3_instruction *in;
 
in = ir3_instr_create(block, -1, OPC_META_INPUT);
in->inout.block = block;
ir3_reg_create(in, n, 0);
if (instr)
ir3_reg_create(in, 0, IR3_REG_SSA)->instr = instr;
 
return in;
}
 
static struct ir3_instruction *
block_input(struct ir3_block *block, unsigned n)
{
/* references to INPUT register file always go back up to
* top level:
*/
if (block->parent)
return block_input(block->parent, n);
return block->inputs[n];
}
 
/* return temporary in scope, creating if needed meta-input node
* to track block inputs
*/
static struct ir3_instruction *
block_temporary(struct ir3_block *block, unsigned n)
{
/* references to TEMPORARY register file, find the nearest
* enclosing block which has already assigned this temporary,
* creating meta-input instructions along the way to keep
* track of block inputs
*/
if (block->parent && !block->temporaries[n]) {
/* if already have input for this block, reuse: */
if (!block->inputs[n])
block->inputs[n] = block_temporary(block->parent, n);
 
/* and create new input to return: */
return create_input(block, block->inputs[n], n);
}
return block->temporaries[n];
}
 
static struct ir3_instruction *
create_immed(struct ir3_compile_context *ctx, float val)
{
/* NOTE: *don't* use instr_create() here!
*/
struct ir3_instruction *instr;
instr = ir3_instr_create(ctx->block, 1, 0);
instr->cat1.src_type = get_ftype(ctx);
instr->cat1.dst_type = get_ftype(ctx);
ir3_reg_create(instr, 0, 0);
ir3_reg_create(instr, 0, IR3_REG_IMMED)->fim_val = val;
return instr;
}
 
static void
ssa_instr_set(struct ir3_compile_context *ctx, unsigned file, unsigned n,
struct ir3_instruction *instr)
{
struct ir3_block *block = ctx->block;
unsigned idx = ctx->num_output_updates;
 
compile_assert(ctx, idx < ARRAY_SIZE(ctx->output_updates));
 
/* NOTE: defer update of temporaries[idx] or output[idx]
* until instr_finish(), so that if the current instruction
* reads the same TEMP/OUT[] it gets the old value:
*
* bleh.. this might be a bit easier to just figure out
* in instr_finish(). But at that point we've already
* lost information about OUTPUT vs TEMPORARY register
* file..
*/
 
switch (file) {
case TGSI_FILE_OUTPUT:
compile_assert(ctx, n < block->noutputs);
ctx->output_updates[idx].instrp = &block->outputs[n];
ctx->output_updates[idx].instr = instr;
ctx->num_output_updates++;
break;
case TGSI_FILE_TEMPORARY:
compile_assert(ctx, n < block->ntemporaries);
ctx->output_updates[idx].instrp = &block->temporaries[n];
ctx->output_updates[idx].instr = instr;
ctx->num_output_updates++;
break;
case TGSI_FILE_ADDRESS:
compile_assert(ctx, n < 1);
ctx->output_updates[idx].instrp = &block->address;
ctx->output_updates[idx].instr = instr;
ctx->num_output_updates++;
break;
}
}
 
static struct ir3_instruction *
ssa_instr_get(struct ir3_compile_context *ctx, unsigned file, unsigned n)
{
struct ir3_block *block = ctx->block;
struct ir3_instruction *instr = NULL;
 
switch (file) {
case TGSI_FILE_INPUT:
instr = block_input(ctx->block, n);
break;
case TGSI_FILE_OUTPUT:
/* really this should just happen in case of 'MOV_SAT OUT[n], ..',
* for the following clamp instructions:
*/
instr = block->outputs[n];
/* we don't have to worry about read from an OUTPUT that was
* assigned outside of the current block, because the _SAT
* clamp instructions will always be in the same block as
* the original instruction which wrote the OUTPUT
*/
compile_assert(ctx, instr);
break;
case TGSI_FILE_TEMPORARY:
instr = block_temporary(ctx->block, n);
if (!instr) {
/* this can happen when registers (or components of a TGSI
* register) are used as src before they have been assigned
* (undefined contents). To avoid confusing the rest of the
* compiler, and to generally keep things peachy, substitute
* an instruction that sets the src to 0.0. Or to keep
* things undefined, I could plug in a random number? :-P
*
* NOTE: *don't* use instr_create() here!
*/
instr = create_immed(ctx, 0.0);
/* no need to recreate the immed for every access: */
block->temporaries[n] = instr;
}
break;
case TGSI_FILE_SYSTEM_VALUE:
switch (ctx->sysval_semantics[n >> 2]) {
case TGSI_SEMANTIC_VERTEXID_NOBASE:
instr = ctx->vertex_id;
break;
case TGSI_SEMANTIC_BASEVERTEX:
instr = ctx->basevertex;
break;
case TGSI_SEMANTIC_INSTANCEID:
instr = ctx->instance_id;
break;
}
break;
}
 
return instr;
}
 
static int dst_array_id(struct ir3_compile_context *ctx,
const struct tgsi_dst_register *dst)
{
// XXX complete hack to recover tgsi_full_dst_register...
// nothing that isn't wrapped in a tgsi_full_dst_register
// should be indirect
const struct tgsi_full_dst_register *fdst = (const void *)dst;
return fdst->Indirect.ArrayID + ctx->array_offsets[dst->File];
}
 
static int src_array_id(struct ir3_compile_context *ctx,
const struct tgsi_src_register *src)
{
// XXX complete hack to recover tgsi_full_src_register...
// nothing that isn't wrapped in a tgsi_full_src_register
// should be indirect
const struct tgsi_full_src_register *fsrc = (const void *)src;
debug_assert(src->File != TGSI_FILE_CONSTANT);
return fsrc->Indirect.ArrayID + ctx->array_offsets[src->File];
}
 
static struct ir3_instruction *
array_fanin(struct ir3_compile_context *ctx, unsigned aid, unsigned file)
{
struct ir3_instruction *instr;
 
if (ctx->array[aid].fanin) {
instr = ctx->array[aid].fanin;
} else {
unsigned first = ctx->array[aid].first;
unsigned last = ctx->array[aid].last;
unsigned i, j;
 
instr = ir3_instr_create2(ctx->block, -1, OPC_META_FI,
1 + (4 * (last + 1 - first)));
ir3_reg_create(instr, 0, 0);
for (i = first; i <= last; i++) {
for (j = 0; j < 4; j++) {
unsigned n = regid(i, j);
ir3_reg_create(instr, 0, IR3_REG_SSA)->instr =
ssa_instr_get(ctx, file, n);
}
}
ctx->array[aid].fanin = instr;
ctx->array_dirty |= (1 << aid);
}
 
return instr;
}
 
static void
ssa_dst(struct ir3_compile_context *ctx, struct ir3_instruction *instr,
const struct tgsi_dst_register *dst, unsigned chan)
{
if (dst->Indirect) {
struct ir3_register *reg = instr->regs[0];
unsigned i, aid = dst_array_id(ctx, dst);
unsigned first = ctx->array[aid].first;
unsigned last = ctx->array[aid].last;
unsigned off = dst->Index - first; /* vec4 offset */
 
reg->size = 4 * (1 + last - first);
reg->offset = regid(off, chan);
 
instr->fanin = array_fanin(ctx, aid, dst->File);
 
/* annotate with the array-id, to help out the register-
* assignment stage. At least for the case of indirect
* writes, we should capture enough dependencies to
* preserve the order of reads/writes of the array, so
* the multiple "names" for the array should end up all
* assigned to the same registers.
*/
instr->fanin->fi.aid = aid;
 
/* Since we are scalarizing vec4 tgsi instructions/regs, we
* run into a slight complication here. To do the naive thing
* and setup a fanout for each scalar array element would end
* up with the result that the instructions generated for each
* component of the vec4 would end up clobbering each other.
* So we take advantage here of knowing that the array index
* (after the shl.b) will be a multiple of four, and only set
* every fourth scalar component in the array. See also
* fixup_ssa_dst_array()
*/
for (i = first; i <= last; i++) {
struct ir3_instruction *split;
unsigned n = regid(i, chan);
int off = (4 * (i - first)) + chan;
 
if (is_meta(instr) && (instr->opc == OPC_META_FO))
off -= instr->fo.off;
 
split = ir3_instr_create(ctx->block, -1, OPC_META_FO);
split->fo.off = off;
ir3_reg_create(split, 0, 0);
ir3_reg_create(split, 0, IR3_REG_SSA)->instr = instr;
 
ssa_instr_set(ctx, dst->File, n, split);
}
} else {
/* normal case (not relative addressed GPR) */
ssa_instr_set(ctx, dst->File, regid(dst->Index, chan), instr);
}
}
 
static void
ssa_src(struct ir3_compile_context *ctx, struct ir3_register *reg,
const struct tgsi_src_register *src, unsigned chan)
{
struct ir3_instruction *instr;
 
if (src->Indirect && (src->File != TGSI_FILE_CONSTANT)) {
/* for relative addressing of gpr's (due to register assignment)
* we must generate a fanin instruction to collect all possible
* array elements that the instruction could address together:
*/
unsigned aid = src_array_id(ctx, src);
unsigned first = ctx->array[aid].first;
unsigned last = ctx->array[aid].last;
unsigned off = src->Index - first; /* vec4 offset */
 
reg->size = 4 * (1 + last - first);
reg->offset = regid(off, chan);
 
instr = array_fanin(ctx, aid, src->File);
} else if (src->File == TGSI_FILE_CONSTANT && src->Dimension) {
const struct tgsi_full_src_register *fsrc = (const void *)src;
struct ir3_instruction *temp = NULL;
int ubo_regid = regid(ctx->so->first_driver_param, 0) +
fsrc->Dimension.Index - 1;
int offset = 0;
 
/* We don't handle indirect UBO array accesses... yet. */
compile_assert(ctx, !fsrc->Dimension.Indirect);
/* UBOs start at index 1. */
compile_assert(ctx, fsrc->Dimension.Index > 0);
 
if (src->Indirect) {
/* In case of an indirect index, it will have been loaded into an
* address register. There will be a sequence of
*
* shl.b x, val, 2
* mova a0, x
*
* We rely on this sequence to get the original val out and shift
* it by 4, since we're dealing in vec4 units.
*/
compile_assert(ctx, ctx->block->address);
compile_assert(ctx, ctx->block->address->regs[1]->instr->opc ==
OPC_SHL_B);
 
temp = instr = instr_create(ctx, 2, OPC_SHL_B);
ir3_reg_create(instr, 0, 0);
ir3_reg_create(instr, 0, IR3_REG_HALF | IR3_REG_SSA)->instr =
ctx->block->address->regs[1]->instr->regs[1]->instr;
ir3_reg_create(instr, 0, IR3_REG_IMMED)->iim_val = 4;
} else if (src->Index >= 64) {
/* Otherwise it's a plain index (in vec4 units). Move it into a
* register.
*/
temp = instr = instr_create(ctx, 1, 0);
instr->cat1.src_type = get_utype(ctx);
instr->cat1.dst_type = get_utype(ctx);
ir3_reg_create(instr, 0, 0);
ir3_reg_create(instr, 0, IR3_REG_IMMED)->iim_val = src->Index * 16;
} else {
/* The offset is small enough to fit into the ldg instruction
* directly.
*/
offset = src->Index * 16;
}
 
if (temp) {
/* If there was an offset (most common), add it to the buffer
* address.
*/
instr = instr_create(ctx, 2, OPC_ADD_S);
ir3_reg_create(instr, 0, 0);
ir3_reg_create(instr, 0, IR3_REG_SSA)->instr = temp;
ir3_reg_create(instr, ubo_regid, IR3_REG_CONST);
} else {
/* Otherwise just load the buffer address directly */
instr = instr_create(ctx, 1, 0);
instr->cat1.src_type = get_utype(ctx);
instr->cat1.dst_type = get_utype(ctx);
ir3_reg_create(instr, 0, 0);
ir3_reg_create(instr, ubo_regid, IR3_REG_CONST);
}
 
temp = instr;
 
instr = instr_create(ctx, 6, OPC_LDG);
instr->cat6.type = TYPE_U32;
instr->cat6.offset = offset + chan * 4;
ir3_reg_create(instr, 0, 0);
ir3_reg_create(instr, 0, IR3_REG_SSA)->instr = temp;
ir3_reg_create(instr, 0, IR3_REG_IMMED)->iim_val = 1;
 
reg->flags &= ~(IR3_REG_RELATIV | IR3_REG_CONST);
} else {
/* normal case (not relative addressed GPR) */
instr = ssa_instr_get(ctx, src->File, regid(src->Index, chan));
}
 
if (instr) {
reg->flags |= IR3_REG_SSA;
reg->instr = instr;
} else if (reg->flags & IR3_REG_SSA) {
/* special hack for trans_samp() which calls ssa_src() directly
* to build up the collect (fanin) for const src.. (so SSA flag
* set but no src instr... it basically gets lucky because we
* default to 0.0 for "undefined" src instructions, which is
* what it wants. We probably need to give it a better way to
* do this, but for now this hack:
*/
reg->instr = create_immed(ctx, 0.0);
}
}
 
static struct ir3_register *
add_dst_reg_wrmask(struct ir3_compile_context *ctx,
struct ir3_instruction *instr, const struct tgsi_dst_register *dst,
unsigned chan, unsigned wrmask)
{
unsigned flags = 0, num = 0;
struct ir3_register *reg;
 
switch (dst->File) {
case TGSI_FILE_OUTPUT:
case TGSI_FILE_TEMPORARY:
/* uses SSA */
break;
case TGSI_FILE_ADDRESS:
flags |= IR3_REG_ADDR;
/* uses SSA */
break;
default:
compile_error(ctx, "unsupported dst register file: %s\n",
tgsi_file_name(dst->File));
break;
}
 
if (dst->Indirect) {
flags |= IR3_REG_RELATIV;
 
/* shouldn't happen, and we can't cope with it below: */
compile_assert(ctx, wrmask == 0x1);
 
compile_assert(ctx, ctx->block->address);
if (instr->address)
compile_assert(ctx, ctx->block->address == instr->address);
 
instr->address = ctx->block->address;
array_insert(ctx->ir->indirects, instr);
}
 
reg = ir3_reg_create(instr, regid(num, chan), flags);
reg->wrmask = wrmask;
 
if (wrmask == 0x1) {
/* normal case */
ssa_dst(ctx, instr, dst, chan);
} else if ((dst->File == TGSI_FILE_TEMPORARY) ||
(dst->File == TGSI_FILE_OUTPUT) ||
(dst->File == TGSI_FILE_ADDRESS)) {
struct ir3_instruction *prev = NULL;
unsigned i;
 
compile_assert(ctx, !dst->Indirect);
 
/* if instruction writes multiple, we need to create
* some place-holder collect the registers:
*/
for (i = 0; i < 4; i++) {
/* NOTE: slightly ugly that we setup neighbor ptrs
* for FO here, but handle FI in CP pass.. we should
* probably just always setup neighbor ptrs in the
* frontend?
*/
struct ir3_instruction *split =
ir3_instr_create(ctx->block, -1, OPC_META_FO);
split->fo.off = i;
/* unused dst reg: */
/* NOTE: set SSA flag on dst here, because unused FO's
* which don't get scheduled will end up not in the
* instruction list when RA sets SSA flag on each dst.
* Slight hack. We really should set SSA flag on
* every dst register in the frontend.
*/
ir3_reg_create(split, 0, IR3_REG_SSA);
/* and src reg used to hold original instr */
ir3_reg_create(split, 0, IR3_REG_SSA)->instr = instr;
if (prev) {
split->cp.left = prev;
split->cp.left_cnt++;
prev->cp.right = split;
prev->cp.right_cnt++;
}
if ((wrmask & (1 << i)) && !ctx->atomic)
ssa_dst(ctx, split, dst, chan+i);
prev = split;
}
}
 
return reg;
}
 
static struct ir3_register *
add_dst_reg(struct ir3_compile_context *ctx, struct ir3_instruction *instr,
const struct tgsi_dst_register *dst, unsigned chan)
{
return add_dst_reg_wrmask(ctx, instr, dst, chan, 0x1);
}
 
static struct ir3_register *
add_src_reg_wrmask(struct ir3_compile_context *ctx,
struct ir3_instruction *instr, const struct tgsi_src_register *src,
unsigned chan, unsigned wrmask)
{
unsigned flags = 0, num = 0;
struct ir3_register *reg;
 
switch (src->File) {
case TGSI_FILE_IMMEDIATE:
/* TODO if possible, use actual immediate instead of const.. but
* TGSI has vec4 immediates, we can only embed scalar (of limited
* size, depending on instruction..)
*/
flags |= IR3_REG_CONST;
num = src->Index + ctx->so->first_immediate;
break;
case TGSI_FILE_CONSTANT:
flags |= IR3_REG_CONST;
num = src->Index;
break;
case TGSI_FILE_OUTPUT:
/* NOTE: we should only end up w/ OUTPUT file for things like
* clamp()'ing saturated dst instructions
*/
case TGSI_FILE_INPUT:
case TGSI_FILE_TEMPORARY:
case TGSI_FILE_SYSTEM_VALUE:
/* uses SSA */
break;
default:
compile_error(ctx, "unsupported src register file: %s\n",
tgsi_file_name(src->File));
break;
}
 
/* We seem to have 8 bits (6.2) for dst register always, so I think
* it is safe to assume GPR cannot be >=64
*
* cat3 instructions only have 8 bits for src2, but cannot take a
* const for src2
*
* cat5 and cat6 in some cases only has 8 bits, but cannot take a
* const for any src.
*
* Other than that we seem to have 12 bits to encode const src,
* except for cat1 which may only have 11 bits (but that seems like
* a bug)
*/
if (flags & IR3_REG_CONST)
compile_assert(ctx, src->Index < (1 << 9));
else
compile_assert(ctx, src->Index < (1 << 6));
 
/* NOTE: abs/neg modifiers in tgsi only apply to float */
if (src->Absolute)
flags |= IR3_REG_FABS;
if (src->Negate)
flags |= IR3_REG_FNEG;
 
if (src->Indirect) {
flags |= IR3_REG_RELATIV;
 
/* shouldn't happen, and we can't cope with it below: */
compile_assert(ctx, wrmask == 0x1);
 
compile_assert(ctx, ctx->block->address);
if (instr->address)
compile_assert(ctx, ctx->block->address == instr->address);
 
instr->address = ctx->block->address;
array_insert(ctx->ir->indirects, instr);
}
 
reg = ir3_reg_create(instr, regid(num, chan), flags);
reg->wrmask = wrmask;
 
if (wrmask == 0x1) {
/* normal case */
ssa_src(ctx, reg, src, chan);
} else if ((src->File == TGSI_FILE_TEMPORARY) ||
(src->File == TGSI_FILE_OUTPUT) ||
(src->File == TGSI_FILE_INPUT)) {
struct ir3_instruction *collect;
unsigned i;
 
compile_assert(ctx, !src->Indirect);
 
/* if instruction reads multiple, we need to create
* some place-holder collect the registers:
*/
collect = ir3_instr_create(ctx->block, -1, OPC_META_FI);
ir3_reg_create(collect, 0, 0); /* unused dst reg */
 
for (i = 0; i < 4; i++) {
if (wrmask & (1 << i)) {
/* and src reg used point to the original instr */
ssa_src(ctx, ir3_reg_create(collect, 0, IR3_REG_SSA),
src, chan + i);
} else if (wrmask & ~((i << i) - 1)) {
/* if any remaining components, then dummy
* placeholder src reg to fill in the blanks:
*/
ir3_reg_create(collect, 0, 0);
}
}
 
reg->flags |= IR3_REG_SSA;
reg->instr = collect;
}
 
return reg;
}
 
static struct ir3_register *
add_src_reg(struct ir3_compile_context *ctx, struct ir3_instruction *instr,
const struct tgsi_src_register *src, unsigned chan)
{
return add_src_reg_wrmask(ctx, instr, src, chan, 0x1);
}
 
static void
src_from_dst(struct tgsi_src_register *src, struct tgsi_dst_register *dst)
{
src->File = dst->File;
src->Indirect = dst->Indirect;
src->Dimension = dst->Dimension;
src->Index = dst->Index;
src->Absolute = 0;
src->Negate = 0;
src->SwizzleX = TGSI_SWIZZLE_X;
src->SwizzleY = TGSI_SWIZZLE_Y;
src->SwizzleZ = TGSI_SWIZZLE_Z;
src->SwizzleW = TGSI_SWIZZLE_W;
}
 
/* Get internal-temp src/dst to use for a sequence of instructions
* generated by a single TGSI op.
*/
static struct tgsi_src_register *
get_internal_temp(struct ir3_compile_context *ctx,
struct tgsi_dst_register *tmp_dst)
{
struct tgsi_src_register *tmp_src;
int n;
 
tmp_dst->File = TGSI_FILE_TEMPORARY;
tmp_dst->WriteMask = TGSI_WRITEMASK_XYZW;
tmp_dst->Indirect = 0;
tmp_dst->Dimension = 0;
 
/* assign next temporary: */
n = ctx->num_internal_temps++;
compile_assert(ctx, n < ARRAY_SIZE(ctx->internal_temps));
tmp_src = &ctx->internal_temps[n];
 
tmp_dst->Index = ctx->info.file_max[TGSI_FILE_TEMPORARY] + n + 1;
 
src_from_dst(tmp_src, tmp_dst);
 
return tmp_src;
}
 
static inline bool
is_const(struct tgsi_src_register *src)
{
return (src->File == TGSI_FILE_CONSTANT) ||
(src->File == TGSI_FILE_IMMEDIATE);
}
 
static inline bool
is_relative(struct tgsi_src_register *src)
{
return src->Indirect;
}
 
static inline bool
is_rel_or_const(struct tgsi_src_register *src)
{
return is_relative(src) || is_const(src);
}
 
static type_t
get_ftype(struct ir3_compile_context *ctx)
{
return TYPE_F32;
}
 
static type_t
get_utype(struct ir3_compile_context *ctx)
{
return TYPE_U32;
}
 
static type_t
get_stype(struct ir3_compile_context *ctx)
{
return TYPE_S32;
}
 
static unsigned
src_swiz(struct tgsi_src_register *src, int chan)
{
switch (chan) {
case 0: return src->SwizzleX;
case 1: return src->SwizzleY;
case 2: return src->SwizzleZ;
case 3: return src->SwizzleW;
}
assert(0);
return 0;
}
 
/* for instructions that cannot take a const register as src, if needed
* generate a move to temporary gpr:
*/
static struct tgsi_src_register *
get_unconst(struct ir3_compile_context *ctx, struct tgsi_src_register *src)
{
struct tgsi_dst_register tmp_dst;
struct tgsi_src_register *tmp_src;
 
compile_assert(ctx, is_rel_or_const(src));
 
tmp_src = get_internal_temp(ctx, &tmp_dst);
 
create_mov(ctx, &tmp_dst, src);
 
return tmp_src;
}
 
static void
get_immediate(struct ir3_compile_context *ctx,
struct tgsi_src_register *reg, uint32_t val)
{
unsigned neg, swiz, idx, i;
/* actually maps 1:1 currently.. not sure if that is safe to rely on: */
static const unsigned swiz2tgsi[] = {
TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y, TGSI_SWIZZLE_Z, TGSI_SWIZZLE_W,
};
 
for (i = 0; i < ctx->immediate_idx; i++) {
swiz = i % 4;
idx = i / 4;
 
if (ctx->so->immediates[idx].val[swiz] == val) {
neg = 0;
break;
}
 
if (ctx->so->immediates[idx].val[swiz] == -val) {
neg = 1;
break;
}
}
 
if (i == ctx->immediate_idx) {
/* need to generate a new immediate: */
swiz = i % 4;
idx = i / 4;
neg = 0;
ctx->so->immediates[idx].val[swiz] = val;
ctx->so->immediates_count = idx + 1;
ctx->immediate_idx++;
}
 
reg->File = TGSI_FILE_IMMEDIATE;
reg->Indirect = 0;
reg->Dimension = 0;
reg->Index = idx;
reg->Absolute = 0;
reg->Negate = neg;
reg->SwizzleX = swiz2tgsi[swiz];
reg->SwizzleY = swiz2tgsi[swiz];
reg->SwizzleZ = swiz2tgsi[swiz];
reg->SwizzleW = swiz2tgsi[swiz];
}
 
static void
create_mov(struct ir3_compile_context *ctx, struct tgsi_dst_register *dst,
struct tgsi_src_register *src)
{
type_t type_mov = get_ftype(ctx);
unsigned i;
 
for (i = 0; i < 4; i++) {
/* move to destination: */
if (dst->WriteMask & (1 << i)) {
struct ir3_instruction *instr;
 
if (src->Absolute || src->Negate) {
/* can't have abs or neg on a mov instr, so use
* absneg.f instead to handle these cases:
*/
instr = instr_create(ctx, 2, OPC_ABSNEG_F);
} else {
instr = instr_create(ctx, 1, 0);
instr->cat1.src_type = type_mov;
instr->cat1.dst_type = type_mov;
}
 
add_dst_reg(ctx, instr, dst, i);
add_src_reg(ctx, instr, src, src_swiz(src, i));
}
}
}
 
static void
create_clamp(struct ir3_compile_context *ctx,
struct tgsi_dst_register *dst, struct tgsi_src_register *val,
struct tgsi_src_register *minval, struct tgsi_src_register *maxval)
{
struct ir3_instruction *instr;
 
instr = instr_create(ctx, 2, OPC_MAX_F);
vectorize(ctx, instr, dst, 2, val, 0, minval, 0);
 
instr = instr_create(ctx, 2, OPC_MIN_F);
vectorize(ctx, instr, dst, 2, val, 0, maxval, 0);
}
 
static void
create_clamp_imm(struct ir3_compile_context *ctx,
struct tgsi_dst_register *dst,
uint32_t minval, uint32_t maxval)
{
struct tgsi_src_register minconst, maxconst;
struct tgsi_src_register src;
 
src_from_dst(&src, dst);
 
get_immediate(ctx, &minconst, minval);
get_immediate(ctx, &maxconst, maxval);
 
create_clamp(ctx, dst, &src, &minconst, &maxconst);
}
 
static struct tgsi_dst_register *
get_dst(struct ir3_compile_context *ctx, struct tgsi_full_instruction *inst)
{
struct tgsi_dst_register *dst = &inst->Dst[0].Register;
unsigned i;
 
compile_assert(ctx, !ctx->using_tmp_dst);
ctx->using_tmp_dst = true;
 
for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
struct tgsi_src_register *src = &inst->Src[i].Register;
if ((src->File == dst->File) && (src->Index == dst->Index)) {
if ((dst->WriteMask == TGSI_WRITEMASK_XYZW) &&
(src->SwizzleX == TGSI_SWIZZLE_X) &&
(src->SwizzleY == TGSI_SWIZZLE_Y) &&
(src->SwizzleZ == TGSI_SWIZZLE_Z) &&
(src->SwizzleW == TGSI_SWIZZLE_W))
continue;
ctx->tmp_src = get_internal_temp(ctx, &ctx->tmp_dst);
ctx->tmp_dst.WriteMask = dst->WriteMask;
dst = &ctx->tmp_dst;
break;
}
}
return dst;
}
 
static void
put_dst(struct ir3_compile_context *ctx, struct tgsi_full_instruction *inst,
struct tgsi_dst_register *dst)
{
compile_assert(ctx, ctx->using_tmp_dst);
ctx->using_tmp_dst = false;
 
/* if necessary, add mov back into original dst: */
if (dst != &inst->Dst[0].Register) {
create_mov(ctx, &inst->Dst[0].Register, ctx->tmp_src);
}
}
 
/* helper to generate the necessary repeat and/or additional instructions
* to turn a scalar instruction into a vector operation:
*/
static void
vectorize(struct ir3_compile_context *ctx, struct ir3_instruction *instr,
struct tgsi_dst_register *dst, int nsrcs, ...)
{
va_list ap;
int i, j, n = 0;
 
instr_atomic_start(ctx);
 
for (i = 0; i < 4; i++) {
if (dst->WriteMask & (1 << i)) {
struct ir3_instruction *cur;
 
if (n++ == 0) {
cur = instr;
} else {
cur = instr_create(ctx, instr->category, instr->opc);
memcpy(cur->info, instr->info, sizeof(cur->info));
}
 
add_dst_reg(ctx, cur, dst, i);
 
va_start(ap, nsrcs);
for (j = 0; j < nsrcs; j++) {
struct tgsi_src_register *src =
va_arg(ap, struct tgsi_src_register *);
unsigned flags = va_arg(ap, unsigned);
struct ir3_register *reg;
if (flags & IR3_REG_IMMED) {
reg = ir3_reg_create(cur, 0, IR3_REG_IMMED);
/* this is an ugly cast.. should have put flags first! */
reg->iim_val = *(int *)&src;
} else {
reg = add_src_reg(ctx, cur, src, src_swiz(src, i));
}
reg->flags |= flags & ~(IR3_REG_FNEG | IR3_REG_SNEG);
if (flags & IR3_REG_FNEG)
reg->flags ^= IR3_REG_FNEG;
if (flags & IR3_REG_SNEG)
reg->flags ^= IR3_REG_SNEG;
}
va_end(ap);
}
}
 
instr_atomic_end(ctx);
}
 
/*
* Handlers for TGSI instructions which do not have a 1:1 mapping to
* native instructions:
*/
 
static void
trans_clamp(const struct instr_translater *t,
struct ir3_compile_context *ctx,
struct tgsi_full_instruction *inst)
{
struct tgsi_dst_register *dst = get_dst(ctx, inst);
struct tgsi_src_register *src0 = &inst->Src[0].Register;
struct tgsi_src_register *src1 = &inst->Src[1].Register;
struct tgsi_src_register *src2 = &inst->Src[2].Register;
 
create_clamp(ctx, dst, src0, src1, src2);
 
put_dst(ctx, inst, dst);
}
 
/* ARL(x) = x, but mova from hrN.x to a0.. */
static void
trans_arl(const struct instr_translater *t,
struct ir3_compile_context *ctx,
struct tgsi_full_instruction *inst)
{
struct ir3_instruction *instr;
struct tgsi_dst_register tmp_dst;
struct tgsi_src_register *tmp_src;
struct tgsi_dst_register *dst = &inst->Dst[0].Register;
struct tgsi_src_register *src = &inst->Src[0].Register;
unsigned chan = src->SwizzleX;
 
compile_assert(ctx, dst->File == TGSI_FILE_ADDRESS);
 
/* NOTE: we allocate a temporary from a flat register
* namespace (ignoring half vs full). It turns out
* not to really matter since registers get reassigned
* later in ir3_ra which (hopefully!) can deal a bit
* better with mixed half and full precision.
*/
tmp_src = get_internal_temp(ctx, &tmp_dst);
 
/* cov.{u,f}{32,16}s16 Rtmp, Rsrc */
instr = instr_create(ctx, 1, 0);
instr->cat1.src_type = (t->tgsi_opc == TGSI_OPCODE_ARL) ?
get_ftype(ctx) : get_utype(ctx);
instr->cat1.dst_type = TYPE_S16;
add_dst_reg(ctx, instr, &tmp_dst, chan)->flags |= IR3_REG_HALF;
add_src_reg(ctx, instr, src, chan);
 
/* shl.b Rtmp, Rtmp, 2 */
instr = instr_create(ctx, 2, OPC_SHL_B);
add_dst_reg(ctx, instr, &tmp_dst, chan)->flags |= IR3_REG_HALF;
add_src_reg(ctx, instr, tmp_src, chan)->flags |= IR3_REG_HALF;
ir3_reg_create(instr, 0, IR3_REG_IMMED)->iim_val = 2;
 
/* mova a0, Rtmp */
instr = instr_create(ctx, 1, 0);
instr->cat1.src_type = TYPE_S16;
instr->cat1.dst_type = TYPE_S16;
add_dst_reg(ctx, instr, dst, 0)->flags |= IR3_REG_HALF;
add_src_reg(ctx, instr, tmp_src, chan)->flags |= IR3_REG_HALF;
}
 
/*
* texture fetch/sample instructions:
*/
 
struct tex_info {
int8_t order[4];
int8_t args;
unsigned src_wrmask, flags;
};
 
struct target_info {
uint8_t dims;
uint8_t cube;
uint8_t array;
uint8_t shadow;
};
 
static const struct target_info tex_targets[] = {
[TGSI_TEXTURE_1D] = { 1, 0, 0, 0 },
[TGSI_TEXTURE_2D] = { 2, 0, 0, 0 },
[TGSI_TEXTURE_3D] = { 3, 0, 0, 0 },
[TGSI_TEXTURE_CUBE] = { 3, 1, 0, 0 },
[TGSI_TEXTURE_RECT] = { 2, 0, 0, 0 },
[TGSI_TEXTURE_SHADOW1D] = { 1, 0, 0, 1 },
[TGSI_TEXTURE_SHADOW2D] = { 2, 0, 0, 1 },
[TGSI_TEXTURE_SHADOWRECT] = { 2, 0, 0, 1 },
[TGSI_TEXTURE_1D_ARRAY] = { 1, 0, 1, 0 },
[TGSI_TEXTURE_2D_ARRAY] = { 2, 0, 1, 0 },
[TGSI_TEXTURE_SHADOW1D_ARRAY] = { 1, 0, 1, 1 },
[TGSI_TEXTURE_SHADOW2D_ARRAY] = { 2, 0, 1, 1 },
[TGSI_TEXTURE_SHADOWCUBE] = { 3, 1, 0, 1 },
[TGSI_TEXTURE_2D_MSAA] = { 2, 0, 0, 0 },
[TGSI_TEXTURE_2D_ARRAY_MSAA] = { 2, 0, 1, 0 },
[TGSI_TEXTURE_CUBE_ARRAY] = { 3, 1, 1, 0 },
[TGSI_TEXTURE_SHADOWCUBE_ARRAY] = { 3, 1, 1, 1 },
};
 
static void
fill_tex_info(struct ir3_compile_context *ctx,
struct tgsi_full_instruction *inst,
struct tex_info *info)
{
const struct target_info *tgt = &tex_targets[inst->Texture.Texture];
 
if (tgt->dims == 3)
info->flags |= IR3_INSTR_3D;
if (tgt->array)
info->flags |= IR3_INSTR_A;
if (tgt->shadow)
info->flags |= IR3_INSTR_S;
 
switch (inst->Instruction.Opcode) {
case TGSI_OPCODE_TXB:
case TGSI_OPCODE_TXB2:
case TGSI_OPCODE_TXL:
case TGSI_OPCODE_TXF:
info->args = 2;
break;
case TGSI_OPCODE_TXP:
info->flags |= IR3_INSTR_P;
/* fallthrough */
case TGSI_OPCODE_TEX:
case TGSI_OPCODE_TXD:
info->args = 1;
break;
}
 
/*
* lay out the first argument in the proper order:
* - actual coordinates first
* - shadow reference
* - array index
* - projection w
*
* bias/lod go into the second arg
*/
int arg, pos = 0;
for (arg = 0; arg < tgt->dims; arg++)
info->order[arg] = pos++;
if (tgt->dims == 1)
info->order[pos++] = -1;
if (tgt->shadow)
info->order[pos++] = MAX2(arg + tgt->array, 2);
if (tgt->array)
info->order[pos++] = arg++;
if (info->flags & IR3_INSTR_P)
info->order[pos++] = 3;
 
info->src_wrmask = (1 << pos) - 1;
 
for (; pos < 4; pos++)
info->order[pos] = -1;
 
assert(pos <= 4);
}
 
static bool check_swiz(struct tgsi_src_register *src, const int8_t order[4])
{
unsigned i;
for (i = 1; (i < 4) && order[i] >= 0; i++)
if (src_swiz(src, i) != (src_swiz(src, 0) + order[i]))
return false;
return true;
}
 
static bool is_1d(unsigned tex)
{
return tex_targets[tex].dims == 1;
}
 
static struct tgsi_src_register *
get_tex_coord(struct ir3_compile_context *ctx,
struct tgsi_full_instruction *inst,
const struct tex_info *tinf)
{
struct tgsi_src_register *coord = &inst->Src[0].Register;
struct ir3_instruction *instr;
unsigned tex = inst->Texture.Texture;
struct tgsi_dst_register tmp_dst;
struct tgsi_src_register *tmp_src;
type_t type_mov = get_ftype(ctx);
unsigned j;
 
/* need to move things around: */
tmp_src = get_internal_temp(ctx, &tmp_dst);
 
for (j = 0; j < 4; j++) {
if (tinf->order[j] < 0)
continue;
instr = instr_create(ctx, 1, 0); /* mov */
instr->cat1.src_type = type_mov;
instr->cat1.dst_type = type_mov;
add_dst_reg(ctx, instr, &tmp_dst, j);
add_src_reg(ctx, instr, coord,
src_swiz(coord, tinf->order[j]));
}
 
/* fix up .y coord: */
if (is_1d(tex)) {
struct ir3_register *imm;
instr = instr_create(ctx, 1, 0); /* mov */
instr->cat1.src_type = type_mov;
instr->cat1.dst_type = type_mov;
add_dst_reg(ctx, instr, &tmp_dst, 1); /* .y */
imm = ir3_reg_create(instr, 0, IR3_REG_IMMED);
if (inst->Instruction.Opcode == TGSI_OPCODE_TXF)
imm->iim_val = 0;
else
imm->fim_val = 0.5;
}
 
return tmp_src;
}
 
static void
trans_samp(const struct instr_translater *t,
struct ir3_compile_context *ctx,
struct tgsi_full_instruction *inst)
{
struct ir3_instruction *instr, *collect;
struct ir3_register *reg;
struct tgsi_dst_register *dst = &inst->Dst[0].Register;
struct tgsi_src_register *orig, *coord, *samp, *offset, *dpdx, *dpdy;
struct tgsi_src_register zero;
const struct target_info *tgt = &tex_targets[inst->Texture.Texture];
struct tex_info tinf;
int i;
 
memset(&tinf, 0, sizeof(tinf));
fill_tex_info(ctx, inst, &tinf);
coord = get_tex_coord(ctx, inst, &tinf);
get_immediate(ctx, &zero, 0);
 
switch (inst->Instruction.Opcode) {
case TGSI_OPCODE_TXB2:
orig = &inst->Src[1].Register;
samp = &inst->Src[2].Register;
break;
case TGSI_OPCODE_TXD:
orig = &inst->Src[0].Register;
dpdx = &inst->Src[1].Register;
dpdy = &inst->Src[2].Register;
samp = &inst->Src[3].Register;
if (is_rel_or_const(dpdx))
dpdx = get_unconst(ctx, dpdx);
if (is_rel_or_const(dpdy))
dpdy = get_unconst(ctx, dpdy);
break;
default:
orig = &inst->Src[0].Register;
samp = &inst->Src[1].Register;
break;
}
if (tinf.args > 1 && is_rel_or_const(orig))
orig = get_unconst(ctx, orig);
 
/* scale up integer coords for TXF based on the LOD */
if (inst->Instruction.Opcode == TGSI_OPCODE_TXF) {
struct tgsi_dst_register tmp_dst;
struct tgsi_src_register *tmp_src;
type_t type_mov = get_utype(ctx);
 
tmp_src = get_internal_temp(ctx, &tmp_dst);
for (i = 0; i < tgt->dims; i++) {
instr = instr_create(ctx, 2, OPC_SHL_B);
add_dst_reg(ctx, instr, &tmp_dst, i);
add_src_reg(ctx, instr, coord, src_swiz(coord, i));
add_src_reg(ctx, instr, orig, orig->SwizzleW);
}
if (tgt->dims < 2) {
instr = instr_create(ctx, 1, 0);
instr->cat1.src_type = type_mov;
instr->cat1.dst_type = type_mov;
add_dst_reg(ctx, instr, &tmp_dst, i);
add_src_reg(ctx, instr, &zero, zero.SwizzleX);
i++;
}
if (tgt->array) {
instr = instr_create(ctx, 1, 0);
instr->cat1.src_type = type_mov;
instr->cat1.dst_type = type_mov;
add_dst_reg(ctx, instr, &tmp_dst, i);
add_src_reg(ctx, instr, coord, src_swiz(coord, i));
}
coord = tmp_src;
}
 
if (inst->Texture.NumOffsets) {
struct tgsi_texture_offset *tex_offset = &inst->TexOffsets[0];
struct tgsi_src_register offset_src = {0};
 
offset_src.File = tex_offset->File;
offset_src.Index = tex_offset->Index;
offset_src.SwizzleX = tex_offset->SwizzleX;
offset_src.SwizzleY = tex_offset->SwizzleY;
offset_src.SwizzleZ = tex_offset->SwizzleZ;
offset = get_unconst(ctx, &offset_src);
tinf.flags |= IR3_INSTR_O;
}
 
instr = instr_create(ctx, 5, t->opc);
if (ctx->integer_s & (1 << samp->Index))
instr->cat5.type = get_utype(ctx);
else
instr->cat5.type = get_ftype(ctx);
instr->cat5.samp = samp->Index;
instr->cat5.tex = samp->Index;
instr->flags |= tinf.flags;
 
add_dst_reg_wrmask(ctx, instr, dst, 0, dst->WriteMask);
 
reg = ir3_reg_create(instr, 0, IR3_REG_SSA);
 
collect = ir3_instr_create2(ctx->block, -1, OPC_META_FI, 12);
ir3_reg_create(collect, 0, 0);
for (i = 0; i < 4; i++) {
if (tinf.src_wrmask & (1 << i))
ssa_src(ctx, ir3_reg_create(collect, 0, IR3_REG_SSA),
coord, src_swiz(coord, i));
else if (tinf.src_wrmask & ~((1 << i) - 1))
ir3_reg_create(collect, 0, 0);
}
 
/* Attach derivatives onto the end of the fan-in. Derivatives start after
* the 4th argument, so make sure that fi is padded up to 4 first.
*/
if (inst->Instruction.Opcode == TGSI_OPCODE_TXD) {
while (collect->regs_count < 5)
ssa_src(ctx, ir3_reg_create(collect, 0, IR3_REG_SSA),
&zero, zero.SwizzleX);
for (i = 0; i < tgt->dims; i++)
ssa_src(ctx, ir3_reg_create(collect, 0, IR3_REG_SSA), dpdx, i);
if (tgt->dims < 2)
ssa_src(ctx, ir3_reg_create(collect, 0, IR3_REG_SSA),
&zero, zero.SwizzleX);
for (i = 0; i < tgt->dims; i++)
ssa_src(ctx, ir3_reg_create(collect, 0, IR3_REG_SSA), dpdy, i);
if (tgt->dims < 2)
ssa_src(ctx, ir3_reg_create(collect, 0, IR3_REG_SSA),
&zero, zero.SwizzleX);
tinf.src_wrmask |= ((1 << (2 * MAX2(tgt->dims, 2))) - 1) << 4;
}
 
reg->instr = collect;
reg->wrmask = tinf.src_wrmask;
 
/* The second argument contains the offsets, followed by the lod/bias
* argument. This is constructed more manually due to the dynamic nature.
*/
if (inst->Texture.NumOffsets == 0 && tinf.args == 1)
return;
 
reg = ir3_reg_create(instr, 0, IR3_REG_SSA);
 
collect = ir3_instr_create2(ctx->block, -1, OPC_META_FI, 5);
ir3_reg_create(collect, 0, 0);
 
if (inst->Texture.NumOffsets) {
for (i = 0; i < tgt->dims; i++)
ssa_src(ctx, ir3_reg_create(collect, 0, IR3_REG_SSA),
offset, i);
if (tgt->dims < 2)
ssa_src(ctx, ir3_reg_create(collect, 0, IR3_REG_SSA),
&zero, zero.SwizzleX);
}
if (inst->Instruction.Opcode == TGSI_OPCODE_TXB2)
ssa_src(ctx, ir3_reg_create(collect, 0, IR3_REG_SSA),
orig, orig->SwizzleX);
else if (tinf.args > 1)
ssa_src(ctx, ir3_reg_create(collect, 0, IR3_REG_SSA),
orig, orig->SwizzleW);
 
reg->instr = collect;
reg->wrmask = (1 << (collect->regs_count - 1)) - 1;
}
 
static void
trans_txq(const struct instr_translater *t,
struct ir3_compile_context *ctx,
struct tgsi_full_instruction *inst)
{
struct ir3_instruction *instr;
struct tgsi_dst_register *dst = &inst->Dst[0].Register;
struct tgsi_src_register *level = &inst->Src[0].Register;
struct tgsi_src_register *samp = &inst->Src[1].Register;
const struct target_info *tgt = &tex_targets[inst->Texture.Texture];
struct tex_info tinf;
 
memset(&tinf, 0, sizeof(tinf));
fill_tex_info(ctx, inst, &tinf);
if (is_rel_or_const(level))
level = get_unconst(ctx, level);
 
instr = instr_create(ctx, 5, OPC_GETSIZE);
instr->cat5.type = get_utype(ctx);
instr->cat5.samp = samp->Index;
instr->cat5.tex = samp->Index;
instr->flags |= tinf.flags;
 
if (tgt->array && (dst->WriteMask & (1 << tgt->dims))) {
/* Array size actually ends up in .w rather than .z. This doesn't
* matter for miplevel 0, but for higher mips the value in z is
* minified whereas w stays. Also, the value in TEX_CONST_3_DEPTH is
* returned, which means that we have to add 1 to it for arrays.
*/
struct tgsi_dst_register tmp_dst;
struct tgsi_src_register *tmp_src;
type_t type_mov = get_utype(ctx);
 
tmp_src = get_internal_temp(ctx, &tmp_dst);
add_dst_reg_wrmask(ctx, instr, &tmp_dst, 0,
dst->WriteMask | TGSI_WRITEMASK_W);
add_src_reg_wrmask(ctx, instr, level, level->SwizzleX, 0x1);
 
if (dst->WriteMask & TGSI_WRITEMASK_X) {
instr = instr_create(ctx, 1, 0);
instr->cat1.src_type = type_mov;
instr->cat1.dst_type = type_mov;
add_dst_reg(ctx, instr, dst, 0);
add_src_reg(ctx, instr, tmp_src, src_swiz(tmp_src, 0));
}
 
if (tgt->dims == 2) {
if (dst->WriteMask & TGSI_WRITEMASK_Y) {
instr = instr_create(ctx, 1, 0);
instr->cat1.src_type = type_mov;
instr->cat1.dst_type = type_mov;
add_dst_reg(ctx, instr, dst, 1);
add_src_reg(ctx, instr, tmp_src, src_swiz(tmp_src, 1));
}
}
 
instr = instr_create(ctx, 2, OPC_ADD_U);
add_dst_reg(ctx, instr, dst, tgt->dims);
add_src_reg(ctx, instr, tmp_src, src_swiz(tmp_src, 3));
ir3_reg_create(instr, 0, IR3_REG_IMMED)->iim_val = 1;
} else {
add_dst_reg_wrmask(ctx, instr, dst, 0, dst->WriteMask);
add_src_reg_wrmask(ctx, instr, level, level->SwizzleX, 0x1);
}
 
if (dst->WriteMask & TGSI_WRITEMASK_W) {
/* The # of levels comes from getinfo.z. We need to add 1 to it, since
* the value in TEX_CONST_0 is zero-based.
*/
struct tgsi_dst_register tmp_dst;
struct tgsi_src_register *tmp_src;
 
tmp_src = get_internal_temp(ctx, &tmp_dst);
instr = instr_create(ctx, 5, OPC_GETINFO);
instr->cat5.type = get_utype(ctx);
instr->cat5.samp = samp->Index;
instr->cat5.tex = samp->Index;
add_dst_reg_wrmask(ctx, instr, &tmp_dst, 0, TGSI_WRITEMASK_Z);
 
instr = instr_create(ctx, 2, OPC_ADD_U);
add_dst_reg(ctx, instr, dst, 3);
add_src_reg(ctx, instr, tmp_src, src_swiz(tmp_src, 2));
ir3_reg_create(instr, 0, IR3_REG_IMMED)->iim_val = 1;
}
}
 
/* DDX/DDY */
static void
trans_deriv(const struct instr_translater *t,
struct ir3_compile_context *ctx,
struct tgsi_full_instruction *inst)
{
struct ir3_instruction *instr;
struct tgsi_dst_register *dst = &inst->Dst[0].Register;
struct tgsi_src_register *src = &inst->Src[0].Register;
static const int8_t order[4] = {0, 1, 2, 3};
 
if (!check_swiz(src, order)) {
struct tgsi_dst_register tmp_dst;
struct tgsi_src_register *tmp_src;
 
tmp_src = get_internal_temp(ctx, &tmp_dst);
create_mov(ctx, &tmp_dst, src);
 
src = tmp_src;
}
 
/* This might be a workaround for hw bug? Blob compiler always
* seems to work two components at a time for dsy/dsx. It does
* actually seem to work in some cases (or at least some piglit
* tests) for four components at a time. But seems more reliable
* to split this into two instructions like the blob compiler
* does:
*/
 
instr = instr_create(ctx, 5, t->opc);
instr->cat5.type = get_ftype(ctx);
add_dst_reg_wrmask(ctx, instr, dst, 0, dst->WriteMask & 0x3);
add_src_reg_wrmask(ctx, instr, src, 0, dst->WriteMask & 0x3);
 
instr = instr_create(ctx, 5, t->opc);
instr->cat5.type = get_ftype(ctx);
add_dst_reg_wrmask(ctx, instr, dst, 2, (dst->WriteMask >> 2) & 0x3);
add_src_reg_wrmask(ctx, instr, src, 2, (dst->WriteMask >> 2) & 0x3);
}
 
/*
* SEQ(a,b) = (a == b) ? 1.0 : 0.0
* cmps.f.eq tmp0, a, b
* cov.u16f16 dst, tmp0
*
* SNE(a,b) = (a != b) ? 1.0 : 0.0
* cmps.f.ne tmp0, a, b
* cov.u16f16 dst, tmp0
*
* SGE(a,b) = (a >= b) ? 1.0 : 0.0
* cmps.f.ge tmp0, a, b
* cov.u16f16 dst, tmp0
*
* SLE(a,b) = (a <= b) ? 1.0 : 0.0
* cmps.f.le tmp0, a, b
* cov.u16f16 dst, tmp0
*
* SGT(a,b) = (a > b) ? 1.0 : 0.0
* cmps.f.gt tmp0, a, b
* cov.u16f16 dst, tmp0
*
* SLT(a,b) = (a < b) ? 1.0 : 0.0
* cmps.f.lt tmp0, a, b
* cov.u16f16 dst, tmp0
*
* CMP(a,b,c) = (a < 0.0) ? b : c
* cmps.f.lt tmp0, a, {0.0}
* sel.b16 dst, b, tmp0, c
*/
static void
trans_cmp(const struct instr_translater *t,
struct ir3_compile_context *ctx,
struct tgsi_full_instruction *inst)
{
struct ir3_instruction *instr;
struct tgsi_dst_register tmp_dst;
struct tgsi_src_register *tmp_src;
struct tgsi_src_register constval0;
/* final instruction for CMP() uses orig src1 and src2: */
struct tgsi_dst_register *dst = get_dst(ctx, inst);
struct tgsi_src_register *a0, *a1, *a2;
unsigned condition;
 
tmp_src = get_internal_temp(ctx, &tmp_dst);
 
a0 = &inst->Src[0].Register; /* a */
a1 = &inst->Src[1].Register; /* b */
 
switch (t->tgsi_opc) {
case TGSI_OPCODE_SEQ:
case TGSI_OPCODE_FSEQ:
condition = IR3_COND_EQ;
break;
case TGSI_OPCODE_SNE:
case TGSI_OPCODE_FSNE:
condition = IR3_COND_NE;
break;
case TGSI_OPCODE_SGE:
case TGSI_OPCODE_FSGE:
condition = IR3_COND_GE;
break;
case TGSI_OPCODE_SLT:
case TGSI_OPCODE_FSLT:
condition = IR3_COND_LT;
break;
case TGSI_OPCODE_SLE:
condition = IR3_COND_LE;
break;
case TGSI_OPCODE_SGT:
condition = IR3_COND_GT;
break;
case TGSI_OPCODE_CMP:
get_immediate(ctx, &constval0, fui(0.0));
a0 = &inst->Src[0].Register; /* a */
a1 = &constval0; /* {0.0} */
condition = IR3_COND_LT;
break;
default:
compile_assert(ctx, 0);
return;
}
 
if (is_const(a0) && is_const(a1))
a0 = get_unconst(ctx, a0);
 
/* cmps.f.<cond> tmp, a0, a1 */
instr = instr_create(ctx, 2, OPC_CMPS_F);
instr->cat2.condition = condition;
vectorize(ctx, instr, &tmp_dst, 2, a0, 0, a1, 0);
 
switch (t->tgsi_opc) {
case TGSI_OPCODE_SEQ:
case TGSI_OPCODE_SGE:
case TGSI_OPCODE_SLE:
case TGSI_OPCODE_SNE:
case TGSI_OPCODE_SGT:
case TGSI_OPCODE_SLT:
/* cov.u16f16 dst, tmp0 */
instr = instr_create(ctx, 1, 0);
instr->cat1.src_type = get_utype(ctx);
instr->cat1.dst_type = get_ftype(ctx);
vectorize(ctx, instr, dst, 1, tmp_src, 0);
break;
case TGSI_OPCODE_FSEQ:
case TGSI_OPCODE_FSGE:
case TGSI_OPCODE_FSNE:
case TGSI_OPCODE_FSLT:
/* absneg.s dst, (neg)tmp0 */
instr = instr_create(ctx, 2, OPC_ABSNEG_S);
vectorize(ctx, instr, dst, 1, tmp_src, IR3_REG_SNEG);
break;
case TGSI_OPCODE_CMP:
a1 = &inst->Src[1].Register;
a2 = &inst->Src[2].Register;
/* sel.{b32,b16} dst, src2, tmp, src1 */
instr = instr_create(ctx, 3, OPC_SEL_B32);
vectorize(ctx, instr, dst, 3, a1, 0, tmp_src, 0, a2, 0);
 
break;
}
 
put_dst(ctx, inst, dst);
}
 
/*
* USNE(a,b) = (a != b) ? ~0 : 0
* cmps.u32.ne dst, a, b
*
* USEQ(a,b) = (a == b) ? ~0 : 0
* cmps.u32.eq dst, a, b
*
* ISGE(a,b) = (a > b) ? ~0 : 0
* cmps.s32.ge dst, a, b
*
* USGE(a,b) = (a > b) ? ~0 : 0
* cmps.u32.ge dst, a, b
*
* ISLT(a,b) = (a < b) ? ~0 : 0
* cmps.s32.lt dst, a, b
*
* USLT(a,b) = (a < b) ? ~0 : 0
* cmps.u32.lt dst, a, b
*
*/
static void
trans_icmp(const struct instr_translater *t,
struct ir3_compile_context *ctx,
struct tgsi_full_instruction *inst)
{
struct ir3_instruction *instr;
struct tgsi_dst_register *dst = get_dst(ctx, inst);
struct tgsi_dst_register tmp_dst;
struct tgsi_src_register *tmp_src;
struct tgsi_src_register *a0, *a1;
unsigned condition;
 
a0 = &inst->Src[0].Register; /* a */
a1 = &inst->Src[1].Register; /* b */
 
switch (t->tgsi_opc) {
case TGSI_OPCODE_USNE:
condition = IR3_COND_NE;
break;
case TGSI_OPCODE_USEQ:
condition = IR3_COND_EQ;
break;
case TGSI_OPCODE_ISGE:
case TGSI_OPCODE_USGE:
condition = IR3_COND_GE;
break;
case TGSI_OPCODE_ISLT:
case TGSI_OPCODE_USLT:
condition = IR3_COND_LT;
break;
 
default:
compile_assert(ctx, 0);
return;
}
 
if (is_const(a0) && is_const(a1))
a0 = get_unconst(ctx, a0);
 
tmp_src = get_internal_temp(ctx, &tmp_dst);
/* cmps.{u32,s32}.<cond> tmp, a0, a1 */
instr = instr_create(ctx, 2, t->opc);
instr->cat2.condition = condition;
vectorize(ctx, instr, &tmp_dst, 2, a0, 0, a1, 0);
 
/* absneg.s dst, (neg)tmp */
instr = instr_create(ctx, 2, OPC_ABSNEG_S);
vectorize(ctx, instr, dst, 1, tmp_src, IR3_REG_SNEG);
 
put_dst(ctx, inst, dst);
}
 
/*
* UCMP(a,b,c) = a ? b : c
* sel.b16 dst, b, a, c
*/
static void
trans_ucmp(const struct instr_translater *t,
struct ir3_compile_context *ctx,
struct tgsi_full_instruction *inst)
{
struct ir3_instruction *instr;
struct tgsi_dst_register *dst = get_dst(ctx, inst);
struct tgsi_src_register *a0, *a1, *a2;
 
a0 = &inst->Src[0].Register; /* a */
a1 = &inst->Src[1].Register; /* b */
a2 = &inst->Src[2].Register; /* c */
 
if (is_rel_or_const(a0))
a0 = get_unconst(ctx, a0);
 
/* sel.{b32,b16} dst, b, a, c */
instr = instr_create(ctx, 3, OPC_SEL_B32);
vectorize(ctx, instr, dst, 3, a1, 0, a0, 0, a2, 0);
put_dst(ctx, inst, dst);
}
 
/*
* ISSG(a) = a < 0 ? -1 : a > 0 ? 1 : 0
* cmps.s.lt tmp_neg, a, 0 # 1 if a is negative
* cmps.s.gt tmp_pos, a, 0 # 1 if a is positive
* sub.u dst, tmp_pos, tmp_neg
*/
static void
trans_issg(const struct instr_translater *t,
struct ir3_compile_context *ctx,
struct tgsi_full_instruction *inst)
{
struct ir3_instruction *instr;
struct tgsi_dst_register *dst = get_dst(ctx, inst);
struct tgsi_src_register *a = &inst->Src[0].Register;
struct tgsi_dst_register neg_dst, pos_dst;
struct tgsi_src_register *neg_src, *pos_src;
 
neg_src = get_internal_temp(ctx, &neg_dst);
pos_src = get_internal_temp(ctx, &pos_dst);
 
/* cmps.s.lt neg, a, 0 */
instr = instr_create(ctx, 2, OPC_CMPS_S);
instr->cat2.condition = IR3_COND_LT;
vectorize(ctx, instr, &neg_dst, 2, a, 0, 0, IR3_REG_IMMED);
 
/* cmps.s.gt pos, a, 0 */
instr = instr_create(ctx, 2, OPC_CMPS_S);
instr->cat2.condition = IR3_COND_GT;
vectorize(ctx, instr, &pos_dst, 2, a, 0, 0, IR3_REG_IMMED);
 
/* sub.u dst, pos, neg */
instr = instr_create(ctx, 2, OPC_SUB_U);
vectorize(ctx, instr, dst, 2, pos_src, 0, neg_src, 0);
 
put_dst(ctx, inst, dst);
}
 
 
 
/*
* Conditional / Flow control
*/
 
static void
push_branch(struct ir3_compile_context *ctx, bool inv,
struct ir3_instruction *instr, struct ir3_instruction *cond)
{
unsigned int idx = ctx->branch_count++;
compile_assert(ctx, idx < ARRAY_SIZE(ctx->branch));
ctx->branch[idx].instr = instr;
ctx->branch[idx].inv = inv;
/* else side of branch has same condition: */
if (!inv)
ctx->branch[idx].cond = cond;
}
 
static struct ir3_instruction *
pop_branch(struct ir3_compile_context *ctx)
{
unsigned int idx = --ctx->branch_count;
return ctx->branch[idx].instr;
}
 
static void
trans_if(const struct instr_translater *t,
struct ir3_compile_context *ctx,
struct tgsi_full_instruction *inst)
{
struct ir3_instruction *instr, *cond;
struct tgsi_src_register *src = &inst->Src[0].Register;
struct tgsi_dst_register tmp_dst;
struct tgsi_src_register *tmp_src;
struct tgsi_src_register constval;
 
get_immediate(ctx, &constval, fui(0.0));
tmp_src = get_internal_temp(ctx, &tmp_dst);
 
if (is_const(src))
src = get_unconst(ctx, src);
 
/* cmps.{f,u}.ne tmp0, b, {0.0} */
instr = instr_create(ctx, 2, t->opc);
add_dst_reg(ctx, instr, &tmp_dst, 0);
add_src_reg(ctx, instr, src, src->SwizzleX);
add_src_reg(ctx, instr, &constval, constval.SwizzleX);
instr->cat2.condition = IR3_COND_NE;
 
compile_assert(ctx, instr->regs[1]->flags & IR3_REG_SSA); /* because get_unconst() */
cond = instr->regs[1]->instr;
 
/* meta:flow tmp0 */
instr = instr_create(ctx, -1, OPC_META_FLOW);
ir3_reg_create(instr, 0, 0); /* dummy dst */
add_src_reg(ctx, instr, tmp_src, TGSI_SWIZZLE_X);
 
push_branch(ctx, false, instr, cond);
instr->flow.if_block = push_block(ctx);
}
 
static void
trans_else(const struct instr_translater *t,
struct ir3_compile_context *ctx,
struct tgsi_full_instruction *inst)
{
struct ir3_instruction *instr;
 
pop_block(ctx);
 
instr = pop_branch(ctx);
 
compile_assert(ctx, (instr->category == -1) &&
(instr->opc == OPC_META_FLOW));
 
push_branch(ctx, true, instr, NULL);
instr->flow.else_block = push_block(ctx);
}
 
static struct ir3_instruction *
find_temporary(struct ir3_block *block, unsigned n)
{
if (block->parent && !block->temporaries[n])
return find_temporary(block->parent, n);
return block->temporaries[n];
}
 
static struct ir3_instruction *
find_output(struct ir3_block *block, unsigned n)
{
if (block->parent && !block->outputs[n])
return find_output(block->parent, n);
return block->outputs[n];
}
 
static struct ir3_instruction *
create_phi(struct ir3_compile_context *ctx, struct ir3_instruction *cond,
struct ir3_instruction *a, struct ir3_instruction *b)
{
struct ir3_instruction *phi;
 
compile_assert(ctx, cond);
 
/* Either side of the condition could be null.. which
* indicates a variable written on only one side of the
* branch. Normally this should only be variables not
* used outside of that side of the branch. So we could
* just 'return a ? a : b;' in that case. But for better
* defined undefined behavior we just stick in imm{0.0}.
* In the common case of a value only used within the
* one side of the branch, the PHI instruction will not
* get scheduled
*/
if (!a)
a = create_immed(ctx, 0.0);
if (!b)
b = create_immed(ctx, 0.0);
 
phi = instr_create(ctx, -1, OPC_META_PHI);
ir3_reg_create(phi, 0, 0); /* dummy dst */
ir3_reg_create(phi, 0, IR3_REG_SSA)->instr = cond;
ir3_reg_create(phi, 0, IR3_REG_SSA)->instr = a;
ir3_reg_create(phi, 0, IR3_REG_SSA)->instr = b;
 
return phi;
}
 
static void
trans_endif(const struct instr_translater *t,
struct ir3_compile_context *ctx,
struct tgsi_full_instruction *inst)
{
struct ir3_instruction *instr;
struct ir3_block *ifb, *elseb;
struct ir3_instruction **ifout, **elseout;
unsigned i, ifnout = 0, elsenout = 0;
 
pop_block(ctx);
 
instr = pop_branch(ctx);
 
compile_assert(ctx, (instr->category == -1) &&
(instr->opc == OPC_META_FLOW));
 
ifb = instr->flow.if_block;
elseb = instr->flow.else_block;
/* if there is no else block, the parent block is used for the
* branch-not-taken src of the PHI instructions:
*/
if (!elseb)
elseb = ifb->parent;
 
/* worst case sizes: */
ifnout = ifb->ntemporaries + ifb->noutputs;
elsenout = elseb->ntemporaries + elseb->noutputs;
 
ifout = ir3_alloc(ctx->ir, sizeof(ifb->outputs[0]) * ifnout);
if (elseb != ifb->parent)
elseout = ir3_alloc(ctx->ir, sizeof(ifb->outputs[0]) * elsenout);
 
ifnout = 0;
elsenout = 0;
 
/* generate PHI instructions for any temporaries written: */
for (i = 0; i < ifb->ntemporaries; i++) {
struct ir3_instruction *a = ifb->temporaries[i];
struct ir3_instruction *b = elseb->temporaries[i];
 
/* if temporary written in if-block, or if else block
* is present and temporary written in else-block:
*/
if (a || ((elseb != ifb->parent) && b)) {
struct ir3_instruction *phi;
 
/* if only written on one side, find the closest
* enclosing update on other side:
*/
if (!a)
a = find_temporary(ifb, i);
if (!b)
b = find_temporary(elseb, i);
 
ifout[ifnout] = a;
a = create_output(ifb, a, ifnout++);
 
if (elseb != ifb->parent) {
elseout[elsenout] = b;
b = create_output(elseb, b, elsenout++);
}
 
phi = create_phi(ctx, instr, a, b);
ctx->block->temporaries[i] = phi;
}
}
 
compile_assert(ctx, ifb->noutputs == elseb->noutputs);
 
/* .. and any outputs written: */
for (i = 0; i < ifb->noutputs; i++) {
struct ir3_instruction *a = ifb->outputs[i];
struct ir3_instruction *b = elseb->outputs[i];
 
/* if output written in if-block, or if else block
* is present and output written in else-block:
*/
if (a || ((elseb != ifb->parent) && b)) {
struct ir3_instruction *phi;
 
/* if only written on one side, find the closest
* enclosing update on other side:
*/
if (!a)
a = find_output(ifb, i);
if (!b)
b = find_output(elseb, i);
 
ifout[ifnout] = a;
a = create_output(ifb, a, ifnout++);
 
if (elseb != ifb->parent) {
elseout[elsenout] = b;
b = create_output(elseb, b, elsenout++);
}
 
phi = create_phi(ctx, instr, a, b);
ctx->block->outputs[i] = phi;
}
}
 
ifb->noutputs = ifnout;
ifb->outputs = ifout;
 
if (elseb != ifb->parent) {
elseb->noutputs = elsenout;
elseb->outputs = elseout;
}
 
// TODO maybe we want to compact block->inputs?
}
 
/*
* Kill
*/
 
static void
trans_kill(const struct instr_translater *t,
struct ir3_compile_context *ctx,
struct tgsi_full_instruction *inst)
{
struct ir3_instruction *instr, *immed, *cond = NULL;
bool inv = false;
 
/* unconditional kill, use enclosing if condition: */
if (ctx->branch_count > 0) {
unsigned int idx = ctx->branch_count - 1;
cond = ctx->branch[idx].cond;
inv = ctx->branch[idx].inv;
} else {
cond = create_immed(ctx, 1.0);
}
 
compile_assert(ctx, cond);
 
immed = create_immed(ctx, 0.0);
 
/* cmps.f.ne p0.x, cond, {0.0} */
instr = instr_create(ctx, 2, OPC_CMPS_F);
instr->cat2.condition = IR3_COND_NE;
ir3_reg_create(instr, regid(REG_P0, 0), 0);
ir3_reg_create(instr, 0, IR3_REG_SSA)->instr = cond;
ir3_reg_create(instr, 0, IR3_REG_SSA)->instr = immed;
cond = instr;
 
/* kill p0.x */
instr = instr_create(ctx, 0, OPC_KILL);
instr->cat0.inv = inv;
ir3_reg_create(instr, 0, 0); /* dummy dst */
ir3_reg_create(instr, 0, IR3_REG_SSA)->instr = cond;
 
ctx->kill[ctx->kill_count++] = instr;
 
ctx->so->has_kill = true;
}
 
/*
* Kill-If
*/
 
static void
trans_killif(const struct instr_translater *t,
struct ir3_compile_context *ctx,
struct tgsi_full_instruction *inst)
{
struct tgsi_src_register *src = &inst->Src[0].Register;
struct ir3_instruction *instr, *immed, *cond = NULL;
bool inv = false;
 
immed = create_immed(ctx, 0.0);
 
/* cmps.f.ne p0.x, cond, {0.0} */
instr = instr_create(ctx, 2, OPC_CMPS_F);
instr->cat2.condition = IR3_COND_NE;
ir3_reg_create(instr, regid(REG_P0, 0), 0);
ir3_reg_create(instr, 0, IR3_REG_SSA)->instr = immed;
add_src_reg(ctx, instr, src, src->SwizzleX);
 
cond = instr;
 
/* kill p0.x */
instr = instr_create(ctx, 0, OPC_KILL);
instr->cat0.inv = inv;
ir3_reg_create(instr, 0, 0); /* dummy dst */
ir3_reg_create(instr, 0, IR3_REG_SSA)->instr = cond;
 
ctx->kill[ctx->kill_count++] = instr;
 
ctx->so->has_kill = true;
 
}
/*
* I2F / U2F / F2I / F2U
*/
 
static void
trans_cov(const struct instr_translater *t,
struct ir3_compile_context *ctx,
struct tgsi_full_instruction *inst)
{
struct ir3_instruction *instr;
struct tgsi_dst_register *dst = get_dst(ctx, inst);
struct tgsi_src_register *src = &inst->Src[0].Register;
 
// cov.f32s32 dst, tmp0 /
instr = instr_create(ctx, 1, 0);
switch (t->tgsi_opc) {
case TGSI_OPCODE_U2F:
instr->cat1.src_type = TYPE_U32;
instr->cat1.dst_type = TYPE_F32;
break;
case TGSI_OPCODE_I2F:
instr->cat1.src_type = TYPE_S32;
instr->cat1.dst_type = TYPE_F32;
break;
case TGSI_OPCODE_F2U:
instr->cat1.src_type = TYPE_F32;
instr->cat1.dst_type = TYPE_U32;
break;
case TGSI_OPCODE_F2I:
instr->cat1.src_type = TYPE_F32;
instr->cat1.dst_type = TYPE_S32;
break;
 
}
vectorize(ctx, instr, dst, 1, src, 0);
put_dst(ctx, inst, dst);
}
 
/*
* UMUL / UMAD
*
* There is no 32-bit multiply instruction, so splitting a and b into high and
* low components, we get that
*
* dst = al * bl + ah * bl << 16 + al * bh << 16
*
* mull.u tmp0, a, b (mul low, i.e. al * bl)
* madsh.m16 tmp1, a, b, tmp0 (mul-add shift high mix, i.e. ah * bl << 16)
* madsh.m16 dst, b, a, tmp1 (i.e. al * bh << 16)
*
* For UMAD, add in the extra argument after mull.u.
*/
static void
trans_umul(const struct instr_translater *t,
struct ir3_compile_context *ctx,
struct tgsi_full_instruction *inst)
{
struct ir3_instruction *instr;
struct tgsi_dst_register *dst = get_dst(ctx, inst);
struct tgsi_src_register *a = &inst->Src[0].Register;
struct tgsi_src_register *b = &inst->Src[1].Register;
 
struct tgsi_dst_register tmp0_dst, tmp1_dst;
struct tgsi_src_register *tmp0_src, *tmp1_src;
 
tmp0_src = get_internal_temp(ctx, &tmp0_dst);
tmp1_src = get_internal_temp(ctx, &tmp1_dst);
 
if (is_rel_or_const(a))
a = get_unconst(ctx, a);
if (is_rel_or_const(b))
b = get_unconst(ctx, b);
 
/* mull.u tmp0, a, b */
instr = instr_create(ctx, 2, OPC_MULL_U);
vectorize(ctx, instr, &tmp0_dst, 2, a, 0, b, 0);
 
if (t->tgsi_opc == TGSI_OPCODE_UMAD) {
struct tgsi_src_register *c = &inst->Src[2].Register;
 
/* add.u tmp0, tmp0, c */
instr = instr_create(ctx, 2, OPC_ADD_U);
vectorize(ctx, instr, &tmp0_dst, 2, tmp0_src, 0, c, 0);
}
 
/* madsh.m16 tmp1, a, b, tmp0 */
instr = instr_create(ctx, 3, OPC_MADSH_M16);
vectorize(ctx, instr, &tmp1_dst, 3, a, 0, b, 0, tmp0_src, 0);
 
/* madsh.m16 dst, b, a, tmp1 */
instr = instr_create(ctx, 3, OPC_MADSH_M16);
vectorize(ctx, instr, dst, 3, b, 0, a, 0, tmp1_src, 0);
put_dst(ctx, inst, dst);
}
 
/*
* IDIV / UDIV / MOD / UMOD
*
* See NV50LegalizeSSA::handleDIV for the origin of this implementation. For
* MOD/UMOD, it becomes a - [IU]DIV(a, modulus) * modulus.
*/
static void
trans_idiv(const struct instr_translater *t,
struct ir3_compile_context *ctx,
struct tgsi_full_instruction *inst)
{
struct ir3_instruction *instr;
struct tgsi_dst_register *dst = get_dst(ctx, inst), *premod_dst = dst;
struct tgsi_src_register *a = &inst->Src[0].Register;
struct tgsi_src_register *b = &inst->Src[1].Register;
 
struct tgsi_dst_register af_dst, bf_dst, q_dst, r_dst, a_dst, b_dst;
struct tgsi_src_register *af_src, *bf_src, *q_src, *r_src, *a_src, *b_src;
 
struct tgsi_src_register negative_2, thirty_one;
type_t src_type;
 
if (t->tgsi_opc == TGSI_OPCODE_IDIV || t->tgsi_opc == TGSI_OPCODE_MOD)
src_type = get_stype(ctx);
else
src_type = get_utype(ctx);
 
af_src = get_internal_temp(ctx, &af_dst);
bf_src = get_internal_temp(ctx, &bf_dst);
q_src = get_internal_temp(ctx, &q_dst);
r_src = get_internal_temp(ctx, &r_dst);
a_src = get_internal_temp(ctx, &a_dst);
b_src = get_internal_temp(ctx, &b_dst);
 
get_immediate(ctx, &negative_2, -2);
get_immediate(ctx, &thirty_one, 31);
 
if (t->tgsi_opc == TGSI_OPCODE_MOD || t->tgsi_opc == TGSI_OPCODE_UMOD)
premod_dst = &q_dst;
 
/* cov.[us]32f32 af, numerator */
instr = instr_create(ctx, 1, 0);
instr->cat1.src_type = src_type;
instr->cat1.dst_type = get_ftype(ctx);
vectorize(ctx, instr, &af_dst, 1, a, 0);
 
/* cov.[us]32f32 bf, denominator */
instr = instr_create(ctx, 1, 0);
instr->cat1.src_type = src_type;
instr->cat1.dst_type = get_ftype(ctx);
vectorize(ctx, instr, &bf_dst, 1, b, 0);
 
/* Get the absolute values for IDIV */
if (type_sint(src_type)) {
/* absneg.f af, (abs)af */
instr = instr_create(ctx, 2, OPC_ABSNEG_F);
vectorize(ctx, instr, &af_dst, 1, af_src, IR3_REG_FABS);
 
/* absneg.f bf, (abs)bf */
instr = instr_create(ctx, 2, OPC_ABSNEG_F);
vectorize(ctx, instr, &bf_dst, 1, bf_src, IR3_REG_FABS);
 
/* absneg.s a, (abs)numerator */
instr = instr_create(ctx, 2, OPC_ABSNEG_S);
vectorize(ctx, instr, &a_dst, 1, a, IR3_REG_SABS);
 
/* absneg.s b, (abs)denominator */
instr = instr_create(ctx, 2, OPC_ABSNEG_S);
vectorize(ctx, instr, &b_dst, 1, b, IR3_REG_SABS);
} else {
/* mov.u32u32 a, numerator */
instr = instr_create(ctx, 1, 0);
instr->cat1.src_type = src_type;
instr->cat1.dst_type = src_type;
vectorize(ctx, instr, &a_dst, 1, a, 0);
 
/* mov.u32u32 b, denominator */
instr = instr_create(ctx, 1, 0);
instr->cat1.src_type = src_type;
instr->cat1.dst_type = src_type;
vectorize(ctx, instr, &b_dst, 1, b, 0);
}
 
/* rcp.f bf, bf */
instr = instr_create(ctx, 4, OPC_RCP);
vectorize(ctx, instr, &bf_dst, 1, bf_src, 0);
 
/* That's right, subtract 2 as an integer from the float */
/* add.u bf, bf, -2 */
instr = instr_create(ctx, 2, OPC_ADD_U);
vectorize(ctx, instr, &bf_dst, 2, bf_src, 0, &negative_2, 0);
 
/* mul.f q, af, bf */
instr = instr_create(ctx, 2, OPC_MUL_F);
vectorize(ctx, instr, &q_dst, 2, af_src, 0, bf_src, 0);
 
/* cov.f32[us]32 q, q */
instr = instr_create(ctx, 1, 0);
instr->cat1.src_type = get_ftype(ctx);
instr->cat1.dst_type = src_type;
vectorize(ctx, instr, &q_dst, 1, q_src, 0);
 
/* integer multiply q by b */
/* mull.u r, q, b */
instr = instr_create(ctx, 2, OPC_MULL_U);
vectorize(ctx, instr, &r_dst, 2, q_src, 0, b_src, 0);
 
/* madsh.m16 r, q, b, r */
instr = instr_create(ctx, 3, OPC_MADSH_M16);
vectorize(ctx, instr, &r_dst, 3, q_src, 0, b_src, 0, r_src, 0);
 
/* madsh.m16, r, b, q, r */
instr = instr_create(ctx, 3, OPC_MADSH_M16);
vectorize(ctx, instr, &r_dst, 3, b_src, 0, q_src, 0, r_src, 0);
 
/* sub.u r, a, r */
instr = instr_create(ctx, 2, OPC_SUB_U);
vectorize(ctx, instr, &r_dst, 2, a_src, 0, r_src, 0);
 
/* cov.u32f32, r, r */
instr = instr_create(ctx, 1, 0);
instr->cat1.src_type = get_utype(ctx);
instr->cat1.dst_type = get_ftype(ctx);
vectorize(ctx, instr, &r_dst, 1, r_src, 0);
 
/* mul.f r, r, bf */
instr = instr_create(ctx, 2, OPC_MUL_F);
vectorize(ctx, instr, &r_dst, 2, r_src, 0, bf_src, 0);
 
/* cov.f32u32 r, r */
instr = instr_create(ctx, 1, 0);
instr->cat1.src_type = get_ftype(ctx);
instr->cat1.dst_type = get_utype(ctx);
vectorize(ctx, instr, &r_dst, 1, r_src, 0);
 
/* add.u q, q, r */
instr = instr_create(ctx, 2, OPC_ADD_U);
vectorize(ctx, instr, &q_dst, 2, q_src, 0, r_src, 0);
 
/* mull.u r, q, b */
instr = instr_create(ctx, 2, OPC_MULL_U);
vectorize(ctx, instr, &r_dst, 2, q_src, 0, b_src, 0);
 
/* madsh.m16 r, q, b, r */
instr = instr_create(ctx, 3, OPC_MADSH_M16);
vectorize(ctx, instr, &r_dst, 3, q_src, 0, b_src, 0, r_src, 0);
 
/* madsh.m16 r, b, q, r */
instr = instr_create(ctx, 3, OPC_MADSH_M16);
vectorize(ctx, instr, &r_dst, 3, b_src, 0, q_src, 0, r_src, 0);
 
/* sub.u r, a, r */
instr = instr_create(ctx, 2, OPC_SUB_U);
vectorize(ctx, instr, &r_dst, 2, a_src, 0, r_src, 0);
 
/* cmps.u.ge r, r, b */
instr = instr_create(ctx, 2, OPC_CMPS_U);
instr->cat2.condition = IR3_COND_GE;
vectorize(ctx, instr, &r_dst, 2, r_src, 0, b_src, 0);
 
if (type_uint(src_type)) {
/* add.u dst, q, r */
instr = instr_create(ctx, 2, OPC_ADD_U);
vectorize(ctx, instr, premod_dst, 2, q_src, 0, r_src, 0);
} else {
/* add.u q, q, r */
instr = instr_create(ctx, 2, OPC_ADD_U);
vectorize(ctx, instr, &q_dst, 2, q_src, 0, r_src, 0);
 
/* negate result based on the original arguments */
if (is_const(a) && is_const(b))
a = get_unconst(ctx, a);
 
/* xor.b r, numerator, denominator */
instr = instr_create(ctx, 2, OPC_XOR_B);
vectorize(ctx, instr, &r_dst, 2, a, 0, b, 0);
 
/* shr.b r, r, 31 */
instr = instr_create(ctx, 2, OPC_SHR_B);
vectorize(ctx, instr, &r_dst, 2, r_src, 0, &thirty_one, 0);
 
/* absneg.s b, (neg)q */
instr = instr_create(ctx, 2, OPC_ABSNEG_S);
vectorize(ctx, instr, &b_dst, 1, q_src, IR3_REG_SNEG);
 
/* sel.b dst, b, r, q */
instr = instr_create(ctx, 3, OPC_SEL_B32);
vectorize(ctx, instr, premod_dst, 3, b_src, 0, r_src, 0, q_src, 0);
}
 
if (t->tgsi_opc == TGSI_OPCODE_MOD || t->tgsi_opc == TGSI_OPCODE_UMOD) {
/* The division result will have ended up in q. */
 
if (is_rel_or_const(b))
b = get_unconst(ctx, b);
 
/* mull.u r, q, b */
instr = instr_create(ctx, 2, OPC_MULL_U);
vectorize(ctx, instr, &r_dst, 2, q_src, 0, b, 0);
 
/* madsh.m16 r, q, b, r */
instr = instr_create(ctx, 3, OPC_MADSH_M16);
vectorize(ctx, instr, &r_dst, 3, q_src, 0, b, 0, r_src, 0);
 
/* madsh.m16 r, b, q, r */
instr = instr_create(ctx, 3, OPC_MADSH_M16);
vectorize(ctx, instr, &r_dst, 3, b, 0, q_src, 0, r_src, 0);
 
/* sub.u dst, a, r */
instr = instr_create(ctx, 2, OPC_SUB_U);
vectorize(ctx, instr, dst, 2, a, 0, r_src, 0);
}
 
put_dst(ctx, inst, dst);
}
 
/*
* Handlers for TGSI instructions which do have 1:1 mapping to native
* instructions:
*/
 
static void
instr_cat0(const struct instr_translater *t,
struct ir3_compile_context *ctx,
struct tgsi_full_instruction *inst)
{
instr_create(ctx, 0, t->opc);
}
 
static void
instr_cat1(const struct instr_translater *t,
struct ir3_compile_context *ctx,
struct tgsi_full_instruction *inst)
{
struct tgsi_dst_register *dst = &inst->Dst[0].Register;
struct tgsi_src_register *src = &inst->Src[0].Register;
 
/* NOTE: atomic start/end, rather than in create_mov() since
* create_mov() is used already w/in atomic sequences (and
* we aren't clever enough to deal with the nesting)
*/
instr_atomic_start(ctx);
create_mov(ctx, dst, src);
instr_atomic_end(ctx);
}
 
static void
instr_cat2(const struct instr_translater *t,
struct ir3_compile_context *ctx,
struct tgsi_full_instruction *inst)
{
struct tgsi_dst_register *dst = get_dst(ctx, inst);
struct tgsi_src_register *src0 = &inst->Src[0].Register;
struct tgsi_src_register *src1 = &inst->Src[1].Register;
struct ir3_instruction *instr;
unsigned src0_flags = 0, src1_flags = 0;
 
switch (t->tgsi_opc) {
case TGSI_OPCODE_ABS:
src0_flags = IR3_REG_FABS;
break;
case TGSI_OPCODE_IABS:
src0_flags = IR3_REG_SABS;
break;
case TGSI_OPCODE_INEG:
src0_flags = IR3_REG_SNEG;
break;
case TGSI_OPCODE_SUB:
src1_flags = IR3_REG_FNEG;
break;
}
 
switch (t->opc) {
case OPC_ABSNEG_F:
case OPC_ABSNEG_S:
case OPC_CLZ_B:
case OPC_CLZ_S:
case OPC_SIGN_F:
case OPC_FLOOR_F:
case OPC_CEIL_F:
case OPC_RNDNE_F:
case OPC_RNDAZ_F:
case OPC_TRUNC_F:
case OPC_NOT_B:
case OPC_BFREV_B:
case OPC_SETRM:
case OPC_CBITS_B:
/* these only have one src reg */
instr = instr_create(ctx, 2, t->opc);
vectorize(ctx, instr, dst, 1, src0, src0_flags);
break;
default:
if (is_const(src0) && is_const(src1))
src0 = get_unconst(ctx, src0);
 
instr = instr_create(ctx, 2, t->opc);
vectorize(ctx, instr, dst, 2, src0, src0_flags,
src1, src1_flags);
break;
}
 
put_dst(ctx, inst, dst);
}
 
static void
instr_cat3(const struct instr_translater *t,
struct ir3_compile_context *ctx,
struct tgsi_full_instruction *inst)
{
struct tgsi_dst_register *dst = get_dst(ctx, inst);
struct tgsi_src_register *src0 = &inst->Src[0].Register;
struct tgsi_src_register *src1 = &inst->Src[1].Register;
struct ir3_instruction *instr;
 
/* in particular, can't handle const for src1 for cat3..
* for mad, we can swap first two src's if needed:
*/
if (is_rel_or_const(src1)) {
if (is_mad(t->opc) && !is_rel_or_const(src0)) {
struct tgsi_src_register *tmp;
tmp = src0;
src0 = src1;
src1 = tmp;
} else {
src1 = get_unconst(ctx, src1);
}
}
 
instr = instr_create(ctx, 3, t->opc);
vectorize(ctx, instr, dst, 3, src0, 0, src1, 0,
&inst->Src[2].Register, 0);
put_dst(ctx, inst, dst);
}
 
static void
instr_cat4(const struct instr_translater *t,
struct ir3_compile_context *ctx,
struct tgsi_full_instruction *inst)
{
struct tgsi_dst_register *dst = get_dst(ctx, inst);
struct tgsi_src_register *src = &inst->Src[0].Register;
struct ir3_instruction *instr;
unsigned i;
 
/* seems like blob compiler avoids const as src.. */
if (is_const(src))
src = get_unconst(ctx, src);
 
/* we need to replicate into each component: */
for (i = 0; i < 4; i++) {
if (dst->WriteMask & (1 << i)) {
instr = instr_create(ctx, 4, t->opc);
add_dst_reg(ctx, instr, dst, i);
add_src_reg(ctx, instr, src, src->SwizzleX);
}
}
 
put_dst(ctx, inst, dst);
}
 
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, instr_cat1),
INSTR(RCP, instr_cat4, .opc = OPC_RCP),
INSTR(RSQ, instr_cat4, .opc = OPC_RSQ),
INSTR(SQRT, instr_cat4, .opc = OPC_SQRT),
INSTR(MUL, instr_cat2, .opc = OPC_MUL_F),
INSTR(ADD, instr_cat2, .opc = OPC_ADD_F),
INSTR(SUB, instr_cat2, .opc = OPC_ADD_F),
INSTR(MIN, instr_cat2, .opc = OPC_MIN_F),
INSTR(MAX, instr_cat2, .opc = OPC_MAX_F),
INSTR(UADD, instr_cat2, .opc = OPC_ADD_U),
INSTR(IMIN, instr_cat2, .opc = OPC_MIN_S),
INSTR(UMIN, instr_cat2, .opc = OPC_MIN_U),
INSTR(IMAX, instr_cat2, .opc = OPC_MAX_S),
INSTR(UMAX, instr_cat2, .opc = OPC_MAX_U),
INSTR(AND, instr_cat2, .opc = OPC_AND_B),
INSTR(OR, instr_cat2, .opc = OPC_OR_B),
INSTR(NOT, instr_cat2, .opc = OPC_NOT_B),
INSTR(XOR, instr_cat2, .opc = OPC_XOR_B),
INSTR(UMUL, trans_umul),
INSTR(UMAD, trans_umul),
INSTR(UDIV, trans_idiv),
INSTR(IDIV, trans_idiv),
INSTR(MOD, trans_idiv),
INSTR(UMOD, trans_idiv),
INSTR(SHL, instr_cat2, .opc = OPC_SHL_B),
INSTR(USHR, instr_cat2, .opc = OPC_SHR_B),
INSTR(ISHR, instr_cat2, .opc = OPC_ASHR_B),
INSTR(IABS, instr_cat2, .opc = OPC_ABSNEG_S),
INSTR(INEG, instr_cat2, .opc = OPC_ABSNEG_S),
INSTR(AND, instr_cat2, .opc = OPC_AND_B),
INSTR(MAD, instr_cat3, .opc = OPC_MAD_F32, .hopc = OPC_MAD_F16),
INSTR(TRUNC, instr_cat2, .opc = OPC_TRUNC_F),
INSTR(CLAMP, trans_clamp),
INSTR(FLR, instr_cat2, .opc = OPC_FLOOR_F),
INSTR(ROUND, instr_cat2, .opc = OPC_RNDNE_F),
INSTR(SSG, instr_cat2, .opc = OPC_SIGN_F),
INSTR(CEIL, instr_cat2, .opc = OPC_CEIL_F),
INSTR(ARL, trans_arl),
INSTR(UARL, trans_arl),
INSTR(EX2, instr_cat4, .opc = OPC_EXP2),
INSTR(LG2, instr_cat4, .opc = OPC_LOG2),
INSTR(ABS, instr_cat2, .opc = OPC_ABSNEG_F),
INSTR(COS, instr_cat4, .opc = OPC_COS),
INSTR(SIN, instr_cat4, .opc = OPC_SIN),
INSTR(TEX, trans_samp, .opc = OPC_SAM),
INSTR(TXP, trans_samp, .opc = OPC_SAM),
INSTR(TXB, trans_samp, .opc = OPC_SAMB),
INSTR(TXB2, trans_samp, .opc = OPC_SAMB),
INSTR(TXL, trans_samp, .opc = OPC_SAML),
INSTR(TXD, trans_samp, .opc = OPC_SAMGQ),
INSTR(TXF, trans_samp, .opc = OPC_ISAML),
INSTR(TXQ, trans_txq),
INSTR(DDX, trans_deriv, .opc = OPC_DSX),
INSTR(DDY, trans_deriv, .opc = OPC_DSY),
INSTR(SGT, trans_cmp),
INSTR(SLT, trans_cmp),
INSTR(FSLT, trans_cmp),
INSTR(SGE, trans_cmp),
INSTR(FSGE, trans_cmp),
INSTR(SLE, trans_cmp),
INSTR(SNE, trans_cmp),
INSTR(FSNE, trans_cmp),
INSTR(SEQ, trans_cmp),
INSTR(FSEQ, trans_cmp),
INSTR(CMP, trans_cmp),
INSTR(USNE, trans_icmp, .opc = OPC_CMPS_U),
INSTR(USEQ, trans_icmp, .opc = OPC_CMPS_U),
INSTR(ISGE, trans_icmp, .opc = OPC_CMPS_S),
INSTR(USGE, trans_icmp, .opc = OPC_CMPS_U),
INSTR(ISLT, trans_icmp, .opc = OPC_CMPS_S),
INSTR(USLT, trans_icmp, .opc = OPC_CMPS_U),
INSTR(UCMP, trans_ucmp),
INSTR(ISSG, trans_issg),
INSTR(IF, trans_if, .opc = OPC_CMPS_F),
INSTR(UIF, trans_if, .opc = OPC_CMPS_U),
INSTR(ELSE, trans_else),
INSTR(ENDIF, trans_endif),
INSTR(END, instr_cat0, .opc = OPC_END),
INSTR(KILL, trans_kill, .opc = OPC_KILL),
INSTR(KILL_IF, trans_killif, .opc = OPC_KILL),
INSTR(I2F, trans_cov),
INSTR(U2F, trans_cov),
INSTR(F2I, trans_cov),
INSTR(F2U, trans_cov),
};
 
static ir3_semantic
decl_semantic(const struct tgsi_declaration_semantic *sem)
{
return ir3_semantic_name(sem->Name, sem->Index);
}
 
static struct ir3_instruction *
decl_in_frag_bary(struct ir3_compile_context *ctx, unsigned regid,
unsigned j, unsigned inloc, bool use_ldlv)
{
struct ir3_instruction *instr;
struct ir3_register *src;
 
if (use_ldlv) {
/* ldlv.u32 dst, l[#inloc], 1 */
instr = instr_create(ctx, 6, OPC_LDLV);
instr->cat6.type = TYPE_U32;
instr->cat6.iim_val = 1;
ir3_reg_create(instr, regid, 0); /* dummy dst */
ir3_reg_create(instr, 0, IR3_REG_IMMED)->iim_val = inloc;
ir3_reg_create(instr, 0, IR3_REG_IMMED)->iim_val = 1;
 
return instr;
}
 
/* bary.f dst, #inloc, r0.x */
instr = instr_create(ctx, 2, OPC_BARY_F);
ir3_reg_create(instr, regid, 0); /* dummy dst */
ir3_reg_create(instr, 0, IR3_REG_IMMED)->iim_val = inloc;
src = ir3_reg_create(instr, 0, IR3_REG_SSA);
src->wrmask = 0x3;
src->instr = ctx->frag_pos;
 
return instr;
}
 
/* TGSI_SEMANTIC_POSITION
* """"""""""""""""""""""
*
* For fragment shaders, TGSI_SEMANTIC_POSITION is used to indicate that
* fragment shader input contains the fragment's window position. The X
* component starts at zero and always increases from left to right.
* The Y component starts at zero and always increases but Y=0 may either
* indicate the top of the window or the bottom depending on the fragment
* coordinate origin convention (see TGSI_PROPERTY_FS_COORD_ORIGIN).
* The Z coordinate ranges from 0 to 1 to represent depth from the front
* to the back of the Z buffer. The W component contains the reciprocol
* of the interpolated vertex position W component.
*/
static struct ir3_instruction *
decl_in_frag_coord(struct ir3_compile_context *ctx, unsigned regid,
unsigned j)
{
struct ir3_instruction *instr, *src;
 
compile_assert(ctx, !ctx->frag_coord[j]);
 
ctx->frag_coord[j] = create_input(ctx->block, NULL, 0);
 
 
switch (j) {
case 0: /* .x */
case 1: /* .y */
/* for frag_coord, we get unsigned values.. we need
* to subtract (integer) 8 and divide by 16 (right-
* shift by 4) then convert to float:
*/
 
/* add.s tmp, src, -8 */
instr = instr_create(ctx, 2, OPC_ADD_S);
ir3_reg_create(instr, regid, 0); /* dummy dst */
ir3_reg_create(instr, 0, IR3_REG_SSA)->instr = ctx->frag_coord[j];
ir3_reg_create(instr, 0, IR3_REG_IMMED)->iim_val = -8;
src = instr;
 
/* shr.b tmp, tmp, 4 */
instr = instr_create(ctx, 2, OPC_SHR_B);
ir3_reg_create(instr, regid, 0); /* dummy dst */
ir3_reg_create(instr, 0, IR3_REG_SSA)->instr = src;
ir3_reg_create(instr, 0, IR3_REG_IMMED)->iim_val = 4;
src = instr;
 
/* mov.u32f32 dst, tmp */
instr = instr_create(ctx, 1, 0);
instr->cat1.src_type = TYPE_U32;
instr->cat1.dst_type = TYPE_F32;
ir3_reg_create(instr, regid, 0); /* dummy dst */
ir3_reg_create(instr, 0, IR3_REG_SSA)->instr = src;
 
break;
case 2: /* .z */
case 3: /* .w */
/* seems that we can use these as-is: */
instr = ctx->frag_coord[j];
break;
default:
compile_error(ctx, "invalid channel\n");
instr = create_immed(ctx, 0.0);
break;
}
 
return instr;
}
 
/* TGSI_SEMANTIC_FACE
* """"""""""""""""""
*
* This label applies to fragment shader inputs only and indicates that
* the register contains front/back-face information of the form (F, 0,
* 0, 1). The first component will be positive when the fragment belongs
* to a front-facing polygon, and negative when the fragment belongs to a
* back-facing polygon.
*/
static struct ir3_instruction *
decl_in_frag_face(struct ir3_compile_context *ctx, unsigned regid,
unsigned j)
{
struct ir3_instruction *instr, *src;
 
switch (j) {
case 0: /* .x */
compile_assert(ctx, !ctx->frag_face);
 
ctx->frag_face = create_input(ctx->block, NULL, 0);
 
/* for faceness, we always get -1 or 0 (int).. but TGSI expects
* positive vs negative float.. and piglit further seems to
* expect -1.0 or 1.0:
*
* mul.s tmp, hr0.x, 2
* add.s tmp, tmp, 1
* mov.s16f32, dst, tmp
*
*/
 
instr = instr_create(ctx, 2, OPC_MUL_S);
ir3_reg_create(instr, regid, 0); /* dummy dst */
ir3_reg_create(instr, 0, IR3_REG_SSA)->instr = ctx->frag_face;
ir3_reg_create(instr, 0, IR3_REG_IMMED)->iim_val = 2;
src = instr;
 
instr = instr_create(ctx, 2, OPC_ADD_S);
ir3_reg_create(instr, regid, 0); /* dummy dst */
ir3_reg_create(instr, 0, IR3_REG_SSA)->instr = src;
ir3_reg_create(instr, 0, IR3_REG_IMMED)->iim_val = 1;
src = instr;
 
instr = instr_create(ctx, 1, 0); /* mov */
instr->cat1.src_type = TYPE_S32;
instr->cat1.dst_type = TYPE_F32;
ir3_reg_create(instr, regid, 0); /* dummy dst */
ir3_reg_create(instr, 0, IR3_REG_SSA)->instr = src;
 
break;
case 1: /* .y */
case 2: /* .z */
instr = create_immed(ctx, 0.0);
break;
case 3: /* .w */
instr = create_immed(ctx, 1.0);
break;
default:
compile_error(ctx, "invalid channel\n");
instr = create_immed(ctx, 0.0);
break;
}
 
return instr;
}
 
static void
decl_in(struct ir3_compile_context *ctx, struct tgsi_full_declaration *decl)
{
struct ir3_shader_variant *so = ctx->so;
unsigned name = decl->Semantic.Name;
unsigned i;
 
/* I don't think we should get frag shader input without
* semantic info? Otherwise how do inputs get linked to
* vert outputs?
*/
compile_assert(ctx, (ctx->type == TGSI_PROCESSOR_VERTEX) ||
decl->Declaration.Semantic);
 
for (i = decl->Range.First; i <= decl->Range.Last; i++) {
unsigned n = so->inputs_count++;
unsigned r = regid(i, 0);
unsigned ncomp, j;
 
/* we'll figure out the actual components used after scheduling */
ncomp = 4;
 
DBG("decl in -> r%d", i);
 
compile_assert(ctx, n < ARRAY_SIZE(so->inputs));
 
so->inputs[n].semantic = decl_semantic(&decl->Semantic);
so->inputs[n].compmask = (1 << ncomp) - 1;
so->inputs[n].regid = r;
so->inputs[n].inloc = ctx->next_inloc;
so->inputs[n].interpolate = decl->Interp.Interpolate;
 
for (j = 0; j < ncomp; j++) {
struct ir3_instruction *instr = NULL;
 
if (ctx->type == TGSI_PROCESSOR_FRAGMENT) {
/* for fragment shaders, POSITION and FACE are handled
* specially, not using normal varying / bary.f
*/
if (name == TGSI_SEMANTIC_POSITION) {
so->inputs[n].bary = false;
so->frag_coord = true;
instr = decl_in_frag_coord(ctx, r + j, j);
} else if (name == TGSI_SEMANTIC_FACE) {
so->inputs[n].bary = false;
so->frag_face = true;
instr = decl_in_frag_face(ctx, r + j, j);
} else {
bool use_ldlv = false;
 
/* if no interpolation given, pick based on
* semantic:
*/
if (!decl->Declaration.Interpolate) {
switch (decl->Semantic.Name) {
case TGSI_SEMANTIC_COLOR:
so->inputs[n].interpolate =
TGSI_INTERPOLATE_COLOR;
break;
default:
so->inputs[n].interpolate =
TGSI_INTERPOLATE_LINEAR;
}
}
 
if (ctx->flat_bypass) {
switch (so->inputs[n].interpolate) {
case TGSI_INTERPOLATE_COLOR:
if (!ctx->so->key.rasterflat)
break;
/* fallthrough */
case TGSI_INTERPOLATE_CONSTANT:
use_ldlv = true;
break;
}
}
 
so->inputs[n].bary = true;
 
instr = decl_in_frag_bary(ctx, r + j, j,
so->inputs[n].inloc + j - 8, use_ldlv);
}
} else {
instr = create_input(ctx->block, NULL, (i * 4) + j);
}
 
ctx->block->inputs[(i * 4) + j] = instr;
}
 
if (so->inputs[n].bary || (ctx->type == TGSI_PROCESSOR_VERTEX)) {
ctx->next_inloc += ncomp;
so->total_in += ncomp;
}
}
}
 
static void
decl_sv(struct ir3_compile_context *ctx, struct tgsi_full_declaration *decl)
{
struct ir3_shader_variant *so = ctx->so;
unsigned r = regid(so->inputs_count, 0);
unsigned n = so->inputs_count++;
 
DBG("decl sv -> r%d", n);
 
compile_assert(ctx, n < ARRAY_SIZE(so->inputs));
compile_assert(ctx, decl->Range.First < ARRAY_SIZE(ctx->sysval_semantics));
 
ctx->sysval_semantics[decl->Range.First] = decl->Semantic.Name;
so->inputs[n].semantic = decl_semantic(&decl->Semantic);
so->inputs[n].compmask = 1;
so->inputs[n].regid = r;
so->inputs[n].inloc = ctx->next_inloc;
so->inputs[n].interpolate = TGSI_INTERPOLATE_CONSTANT;
 
struct ir3_instruction *instr = NULL;
 
switch (decl->Semantic.Name) {
case TGSI_SEMANTIC_VERTEXID_NOBASE:
ctx->vertex_id = instr = create_input(ctx->block, NULL, r);
break;
case TGSI_SEMANTIC_BASEVERTEX:
ctx->basevertex = instr = instr_create(ctx, 1, 0);
instr->cat1.src_type = get_stype(ctx);
instr->cat1.dst_type = get_stype(ctx);
ir3_reg_create(instr, 0, 0);
ir3_reg_create(instr, regid(so->first_driver_param + 4, 0),
IR3_REG_CONST);
break;
case TGSI_SEMANTIC_INSTANCEID:
ctx->instance_id = instr = create_input(ctx->block, NULL, r);
break;
default:
compile_error(ctx, "Unknown semantic: %s\n",
tgsi_semantic_names[decl->Semantic.Name]);
}
 
ctx->block->inputs[r] = instr;
ctx->next_inloc++;
so->total_in++;
}
 
static void
decl_out(struct ir3_compile_context *ctx, struct tgsi_full_declaration *decl)
{
struct ir3_shader_variant *so = ctx->so;
unsigned comp = 0;
unsigned name = decl->Semantic.Name;
unsigned i;
 
compile_assert(ctx, decl->Declaration.Semantic);
 
DBG("decl out[%d] -> r%d", name, decl->Range.First);
 
if (ctx->type == TGSI_PROCESSOR_VERTEX) {
switch (name) {
case TGSI_SEMANTIC_POSITION:
so->writes_pos = true;
break;
case TGSI_SEMANTIC_PSIZE:
so->writes_psize = true;
break;
case TGSI_SEMANTIC_COLOR:
case TGSI_SEMANTIC_BCOLOR:
case TGSI_SEMANTIC_GENERIC:
case TGSI_SEMANTIC_FOG:
case TGSI_SEMANTIC_TEXCOORD:
break;
default:
compile_error(ctx, "unknown VS semantic name: %s\n",
tgsi_semantic_names[name]);
}
} else {
switch (name) {
case TGSI_SEMANTIC_POSITION:
comp = 2; /* tgsi will write to .z component */
so->writes_pos = true;
break;
case TGSI_SEMANTIC_COLOR:
break;
default:
compile_error(ctx, "unknown FS semantic name: %s\n",
tgsi_semantic_names[name]);
}
}
 
for (i = decl->Range.First; i <= decl->Range.Last; i++) {
unsigned n = so->outputs_count++;
unsigned ncomp, j;
 
ncomp = 4;
 
compile_assert(ctx, n < ARRAY_SIZE(so->outputs));
 
so->outputs[n].semantic = decl_semantic(&decl->Semantic);
so->outputs[n].regid = regid(i, comp);
 
/* avoid undefined outputs, stick a dummy mov from imm{0.0},
* which if the output is actually assigned will be over-
* written
*/
for (j = 0; j < ncomp; j++)
ctx->block->outputs[(i * 4) + j] = create_immed(ctx, 0.0);
}
}
 
/* from TGSI perspective, we actually have inputs. But most of the "inputs"
* for a fragment shader are just bary.f instructions. The *actual* inputs
* from the hw perspective are the frag_pos and optionally frag_coord and
* frag_face.
*/
static void
fixup_frag_inputs(struct ir3_compile_context *ctx)
{
struct ir3_shader_variant *so = ctx->so;
struct ir3_block *block = ctx->block;
struct ir3_instruction **inputs;
struct ir3_instruction *instr;
int n, regid = 0;
 
block->ninputs = 0;
 
n = 4; /* always have frag_pos */
n += COND(so->frag_face, 4);
n += COND(so->frag_coord, 4);
 
inputs = ir3_alloc(ctx->ir, n * (sizeof(struct ir3_instruction *)));
 
if (so->frag_face) {
/* this ultimately gets assigned to hr0.x so doesn't conflict
* with frag_coord/frag_pos..
*/
inputs[block->ninputs++] = ctx->frag_face;
ctx->frag_face->regs[0]->num = 0;
 
/* remaining channels not used, but let's avoid confusing
* other parts that expect inputs to come in groups of vec4
*/
inputs[block->ninputs++] = NULL;
inputs[block->ninputs++] = NULL;
inputs[block->ninputs++] = NULL;
}
 
/* since we don't know where to set the regid for frag_coord,
* we have to use r0.x for it. But we don't want to *always*
* use r1.x for frag_pos as that could increase the register
* footprint on simple shaders:
*/
if (so->frag_coord) {
ctx->frag_coord[0]->regs[0]->num = regid++;
ctx->frag_coord[1]->regs[0]->num = regid++;
ctx->frag_coord[2]->regs[0]->num = regid++;
ctx->frag_coord[3]->regs[0]->num = regid++;
 
inputs[block->ninputs++] = ctx->frag_coord[0];
inputs[block->ninputs++] = ctx->frag_coord[1];
inputs[block->ninputs++] = ctx->frag_coord[2];
inputs[block->ninputs++] = ctx->frag_coord[3];
}
 
/* we always have frag_pos: */
so->pos_regid = regid;
 
/* r0.x */
instr = create_input(block, NULL, block->ninputs);
instr->regs[0]->num = regid++;
inputs[block->ninputs++] = instr;
ctx->frag_pos->regs[1]->instr = instr;
 
/* r0.y */
instr = create_input(block, NULL, block->ninputs);
instr->regs[0]->num = regid++;
inputs[block->ninputs++] = instr;
ctx->frag_pos->regs[2]->instr = instr;
 
block->inputs = inputs;
}
 
static void
compile_instructions(struct ir3_compile_context *ctx)
{
push_block(ctx);
 
/* for fragment shader, we have a single input register (usually
* r0.xy) which is used as the base for bary.f varying fetch instrs:
*/
if (ctx->type == TGSI_PROCESSOR_FRAGMENT) {
struct ir3_instruction *instr;
instr = ir3_instr_create(ctx->block, -1, OPC_META_FI);
ir3_reg_create(instr, 0, 0);
ir3_reg_create(instr, 0, IR3_REG_SSA); /* r0.x */
ir3_reg_create(instr, 0, IR3_REG_SSA); /* r0.y */
ctx->frag_pos = instr;
}
 
while (!tgsi_parse_end_of_tokens(&ctx->parser)) {
tgsi_parse_token(&ctx->parser);
 
switch (ctx->parser.FullToken.Token.Type) {
case TGSI_TOKEN_TYPE_DECLARATION: {
struct tgsi_full_declaration *decl =
&ctx->parser.FullToken.FullDeclaration;
unsigned file = decl->Declaration.File;
if (file == TGSI_FILE_OUTPUT) {
decl_out(ctx, decl);
} else if (file == TGSI_FILE_INPUT) {
decl_in(ctx, decl);
} else if (decl->Declaration.File == TGSI_FILE_SYSTEM_VALUE) {
decl_sv(ctx, decl);
}
 
if ((file != TGSI_FILE_CONSTANT) && decl->Declaration.Array) {
int aid = decl->Array.ArrayID + ctx->array_offsets[file];
 
compile_assert(ctx, aid < ARRAY_SIZE(ctx->array));
 
/* legacy ArrayID==0 stuff probably isn't going to work
* well (and is at least untested).. let's just scream:
*/
compile_assert(ctx, aid != 0);
 
ctx->array[aid].first = decl->Range.First;
ctx->array[aid].last = decl->Range.Last;
}
break;
}
case TGSI_TOKEN_TYPE_IMMEDIATE: {
/* TODO: if we know the immediate is small enough, and only
* used with instructions that can embed an immediate, we
* can skip this:
*/
struct tgsi_full_immediate *imm =
&ctx->parser.FullToken.FullImmediate;
unsigned n = ctx->so->immediates_count++;
compile_assert(ctx, n < ARRAY_SIZE(ctx->so->immediates));
memcpy(ctx->so->immediates[n].val, imm->u, 16);
break;
}
case TGSI_TOKEN_TYPE_INSTRUCTION: {
struct tgsi_full_instruction *inst =
&ctx->parser.FullToken.FullInstruction;
unsigned opc = inst->Instruction.Opcode;
const struct instr_translater *t = &translaters[opc];
 
if (t->fxn) {
t->fxn(t, ctx, inst);
ctx->num_internal_temps = 0;
 
compile_assert(ctx, !ctx->using_tmp_dst);
} else {
compile_error(ctx, "unknown TGSI opc: %s\n",
tgsi_get_opcode_name(opc));
}
 
switch (inst->Instruction.Saturate) {
case TGSI_SAT_ZERO_ONE:
create_clamp_imm(ctx, &inst->Dst[0].Register,
fui(0.0), fui(1.0));
break;
case TGSI_SAT_MINUS_PLUS_ONE:
create_clamp_imm(ctx, &inst->Dst[0].Register,
fui(-1.0), fui(1.0));
break;
}
 
instr_finish(ctx);
 
break;
}
case TGSI_TOKEN_TYPE_PROPERTY: {
struct tgsi_full_property *prop =
&ctx->parser.FullToken.FullProperty;
switch (prop->Property.PropertyName) {
case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS:
ctx->so->color0_mrt = !!prop->u[0].Data;
break;
}
}
default:
break;
}
}
}
 
static void
compile_dump(struct ir3_compile_context *ctx)
{
const char *name = (ctx->so->type == SHADER_VERTEX) ? "vert" : "frag";
static unsigned n = 0;
char fname[16];
FILE *f;
snprintf(fname, sizeof(fname), "%s-%04u.dot", name, n++);
f = fopen(fname, "w");
if (!f)
return;
ir3_block_depth(ctx->block);
ir3_dump(ctx->ir, name, ctx->block, f);
fclose(f);
}
 
int
ir3_compile_shader(struct ir3_shader_variant *so,
const struct tgsi_token *tokens, struct ir3_shader_key key,
bool cp)
{
struct ir3_compile_context ctx;
struct ir3_block *block;
struct ir3_instruction **inputs;
unsigned i, j, actual_in;
int ret = 0, max_bary;
 
assert(!so->ir);
 
so->ir = ir3_create();
 
assert(so->ir);
 
if (compile_init(&ctx, so, tokens) != TGSI_PARSE_OK) {
DBG("INIT failed!");
ret = -1;
goto out;
}
 
/* for now, until the edge cases are worked out: */
if (ctx.info.indirect_files_written & (FM(TEMPORARY) | FM(INPUT) | FM(OUTPUT)))
cp = false;
 
compile_instructions(&ctx);
 
block = ctx.block;
so->ir->block = block;
 
/* keep track of the inputs from TGSI perspective.. */
inputs = block->inputs;
 
/* but fixup actual inputs for frag shader: */
if (ctx.type == TGSI_PROCESSOR_FRAGMENT)
fixup_frag_inputs(&ctx);
 
/* at this point, for binning pass, throw away unneeded outputs: */
if (key.binning_pass) {
for (i = 0, j = 0; i < so->outputs_count; i++) {
unsigned name = sem2name(so->outputs[i].semantic);
unsigned idx = sem2idx(so->outputs[i].semantic);
 
/* throw away everything but first position/psize */
if ((idx == 0) && ((name == TGSI_SEMANTIC_POSITION) ||
(name == TGSI_SEMANTIC_PSIZE))) {
if (i != j) {
so->outputs[j] = so->outputs[i];
block->outputs[(j*4)+0] = block->outputs[(i*4)+0];
block->outputs[(j*4)+1] = block->outputs[(i*4)+1];
block->outputs[(j*4)+2] = block->outputs[(i*4)+2];
block->outputs[(j*4)+3] = block->outputs[(i*4)+3];
}
j++;
}
}
so->outputs_count = j;
block->noutputs = j * 4;
}
 
/* if we want half-precision outputs, mark the output registers
* as half:
*/
if (key.half_precision) {
for (i = 0; i < block->noutputs; i++) {
if (!block->outputs[i])
continue;
block->outputs[i]->regs[0]->flags |= IR3_REG_HALF;
}
}
 
/* at this point, we want the kill's in the outputs array too,
* so that they get scheduled (since they have no dst).. we've
* already ensured that the array is big enough in push_block():
*/
if (ctx.type == TGSI_PROCESSOR_FRAGMENT) {
for (i = 0; i < ctx.kill_count; i++)
block->outputs[block->noutputs++] = ctx.kill[i];
}
 
if (fd_mesa_debug & FD_DBG_OPTDUMP)
compile_dump(&ctx);
 
ret = ir3_block_flatten(block);
if (ret < 0) {
DBG("FLATTEN failed!");
goto out;
}
if ((ret > 0) && (fd_mesa_debug & FD_DBG_OPTDUMP))
compile_dump(&ctx);
 
if (fd_mesa_debug & FD_DBG_OPTMSGS) {
printf("BEFORE CP:\n");
ir3_dump_instr_list(block->head);
}
 
ir3_block_depth(block);
 
/* First remove all the extra mov's (which we could skip if the
* front-end was clever enough not to insert them in the first
* place). Then figure out left/right neighbors, re-inserting
* extra mov's when needed to avoid conflicts.
*/
if (cp && !(fd_mesa_debug & FD_DBG_NOCP))
ir3_block_cp(block);
 
if (fd_mesa_debug & FD_DBG_OPTMSGS) {
printf("BEFORE GROUPING:\n");
ir3_dump_instr_list(block->head);
}
 
/* Group left/right neighbors, inserting mov's where needed to
* solve conflicts:
*/
ir3_block_group(block);
 
if (fd_mesa_debug & FD_DBG_OPTDUMP)
compile_dump(&ctx);
 
ir3_block_depth(block);
 
if (fd_mesa_debug & FD_DBG_OPTMSGS) {
printf("AFTER DEPTH:\n");
ir3_dump_instr_list(block->head);
}
 
ret = ir3_block_sched(block);
if (ret) {
DBG("SCHED failed!");
goto out;
}
 
if (fd_mesa_debug & FD_DBG_OPTMSGS) {
printf("AFTER SCHED:\n");
ir3_dump_instr_list(block->head);
}
 
ret = ir3_block_ra(block, so->type, so->frag_coord, so->frag_face);
if (ret) {
DBG("RA failed!");
goto out;
}
 
if (fd_mesa_debug & FD_DBG_OPTMSGS) {
printf("AFTER RA:\n");
ir3_dump_instr_list(block->head);
}
 
ir3_block_legalize(block, &so->has_samp, &max_bary);
 
/* fixup input/outputs: */
for (i = 0; i < so->outputs_count; i++) {
so->outputs[i].regid = block->outputs[i*4]->regs[0]->num;
/* preserve hack for depth output.. tgsi writes depth to .z,
* but what we give the hw is the scalar register:
*/
if ((ctx.type == TGSI_PROCESSOR_FRAGMENT) &&
(sem2name(so->outputs[i].semantic) == TGSI_SEMANTIC_POSITION))
so->outputs[i].regid += 2;
}
/* Note that some or all channels of an input may be unused: */
actual_in = 0;
for (i = 0; i < so->inputs_count; i++) {
unsigned j, regid = ~0, compmask = 0;
so->inputs[i].ncomp = 0;
for (j = 0; j < 4; j++) {
struct ir3_instruction *in = inputs[(i*4) + j];
if (in) {
compmask |= (1 << j);
regid = in->regs[0]->num - j;
actual_in++;
so->inputs[i].ncomp++;
}
}
so->inputs[i].regid = regid;
so->inputs[i].compmask = compmask;
}
 
/* fragment shader always gets full vec4's even if it doesn't
* fetch all components, but vertex shader we need to update
* with the actual number of components fetch, otherwise thing
* will hang due to mismaptch between VFD_DECODE's and
* TOTALATTRTOVS
*/
if (so->type == SHADER_VERTEX)
so->total_in = actual_in;
else
so->total_in = align(max_bary + 1, 4);
 
out:
if (ret) {
ir3_destroy(so->ir);
so->ir = NULL;
}
compile_free(&ctx);
 
return ret;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/ir3/ir3_compiler.h
0,0 → 1,42
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2013 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef IR3_COMPILER_H_
#define IR3_COMPILER_H_
 
#include "ir3_shader.h"
 
 
int ir3_compile_shader_nir(struct ir3_shader_variant *so,
const struct tgsi_token *tokens, struct ir3_shader_key key);
 
int ir3_compile_shader(struct ir3_shader_variant *so,
const struct tgsi_token *tokens,
struct ir3_shader_key key, bool cp);
 
#endif /* IR3_COMPILER_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c
0,0 → 1,2120
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2015 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include <stdarg.h>
 
#include "pipe/p_state.h"
#include "util/u_string.h"
#include "util/u_memory.h"
#include "util/u_inlines.h"
#include "tgsi/tgsi_lowering.h"
#include "tgsi/tgsi_strings.h"
 
#include "nir/tgsi_to_nir.h"
#include "glsl/shader_enums.h"
 
#include "freedreno_util.h"
 
#include "ir3_compiler.h"
#include "ir3_shader.h"
#include "ir3_nir.h"
 
#include "instr-a3xx.h"
#include "ir3.h"
 
 
static struct ir3_instruction * create_immed(struct ir3_block *block, uint32_t val);
 
struct ir3_compile {
const struct tgsi_token *tokens;
struct nir_shader *s;
 
struct ir3 *ir;
struct ir3_shader_variant *so;
 
/* bitmask of which samplers are integer: */
uint16_t integer_s;
 
struct ir3_block *block;
 
/* For fragment shaders, from the hw perspective the only
* actual input is r0.xy position register passed to bary.f.
* But TGSI doesn't know that, it still declares things as
* IN[] registers. So we do all the input tracking normally
* and fix things up after compile_instructions()
*
* NOTE that frag_pos is the hardware position (possibly it
* is actually an index or tag or some such.. it is *not*
* values that can be directly used for gl_FragCoord..)
*/
struct ir3_instruction *frag_pos, *frag_face, *frag_coord[4];
 
/* For vertex shaders, keep track of the system values sources */
struct ir3_instruction *vertex_id, *basevertex, *instance_id;
 
/* mapping from nir_register to defining instruction: */
struct hash_table *def_ht;
 
/* mapping from nir_variable to ir3_array: */
struct hash_table *var_ht;
unsigned num_arrays;
 
/* a common pattern for indirect addressing is to request the
* same address register multiple times. To avoid generating
* duplicate instruction sequences (which our backend does not
* try to clean up, since that should be done as the NIR stage)
* we cache the address value generated for a given src value:
*/
struct hash_table *addr_ht;
 
/* for calculating input/output positions/linkages: */
unsigned next_inloc;
 
/* a4xx (at least patchlevel 0) cannot seem to flat-interpolate
* so we need to use ldlv.u32 to load the varying directly:
*/
bool flat_bypass;
 
/* on a3xx, we need to add one to # of array levels:
*/
bool levels_add_one;
 
/* for looking up which system value is which */
unsigned sysval_semantics[8];
 
/* list of kill instructions: */
struct ir3_instruction *kill[16];
unsigned int kill_count;
 
/* set if we encounter something we can't handle yet, so we
* can bail cleanly and fallback to TGSI compiler f/e
*/
bool error;
};
 
 
static struct nir_shader *to_nir(const struct tgsi_token *tokens)
{
struct nir_shader_compiler_options options = {
.lower_fpow = true,
.lower_fsat = true,
.lower_scmp = true,
.lower_flrp = true,
.native_integers = true,
};
bool progress;
 
struct nir_shader *s = tgsi_to_nir(tokens, &options);
 
if (fd_mesa_debug & FD_DBG_OPTMSGS) {
debug_printf("----------------------\n");
nir_print_shader(s, stdout);
debug_printf("----------------------\n");
}
 
nir_opt_global_to_local(s);
nir_convert_to_ssa(s);
nir_lower_idiv(s);
 
do {
progress = false;
 
nir_lower_vars_to_ssa(s);
nir_lower_alu_to_scalar(s);
 
progress |= nir_copy_prop(s);
progress |= nir_opt_dce(s);
progress |= nir_opt_cse(s);
progress |= ir3_nir_lower_if_else(s);
progress |= nir_opt_algebraic(s);
progress |= nir_opt_constant_folding(s);
 
} while (progress);
 
nir_remove_dead_variables(s);
nir_validate_shader(s);
 
if (fd_mesa_debug & FD_DBG_OPTMSGS) {
debug_printf("----------------------\n");
nir_print_shader(s, stdout);
debug_printf("----------------------\n");
}
 
return s;
}
 
/* TODO nir doesn't lower everything for us yet, but ideally it would: */
static const struct tgsi_token *
lower_tgsi(const struct tgsi_token *tokens, struct ir3_shader_variant *so)
{
struct tgsi_shader_info info;
struct tgsi_lowering_config lconfig = {
.color_two_side = so->key.color_two_side,
.lower_FRC = true,
};
 
switch (so->type) {
case SHADER_FRAGMENT:
case SHADER_COMPUTE:
lconfig.saturate_s = so->key.fsaturate_s;
lconfig.saturate_t = so->key.fsaturate_t;
lconfig.saturate_r = so->key.fsaturate_r;
break;
case SHADER_VERTEX:
lconfig.saturate_s = so->key.vsaturate_s;
lconfig.saturate_t = so->key.vsaturate_t;
lconfig.saturate_r = so->key.vsaturate_r;
break;
}
 
if (!so->shader) {
/* hack for standalone compiler which does not have
* screen/context:
*/
} else if (ir3_shader_gpuid(so->shader) >= 400) {
/* a4xx seems to have *no* sam.p */
lconfig.lower_TXP = ~0; /* lower all txp */
} else {
/* a3xx just needs to avoid sam.p for 3d tex */
lconfig.lower_TXP = (1 << TGSI_TEXTURE_3D);
}
 
return tgsi_transform_lowering(&lconfig, tokens, &info);
}
 
static struct ir3_compile *
compile_init(struct ir3_shader_variant *so,
const struct tgsi_token *tokens)
{
struct ir3_compile *ctx = rzalloc(NULL, struct ir3_compile);
const struct tgsi_token *lowered_tokens;
 
if (!so->shader) {
/* hack for standalone compiler which does not have
* screen/context:
*/
} else if (ir3_shader_gpuid(so->shader) >= 400) {
/* need special handling for "flat" */
ctx->flat_bypass = true;
ctx->levels_add_one = false;
} else {
/* no special handling for "flat" */
ctx->flat_bypass = false;
ctx->levels_add_one = true;
}
 
switch (so->type) {
case SHADER_FRAGMENT:
case SHADER_COMPUTE:
ctx->integer_s = so->key.finteger_s;
break;
case SHADER_VERTEX:
ctx->integer_s = so->key.vinteger_s;
break;
}
 
ctx->ir = so->ir;
ctx->so = so;
ctx->next_inloc = 8;
ctx->def_ht = _mesa_hash_table_create(ctx,
_mesa_hash_pointer, _mesa_key_pointer_equal);
ctx->var_ht = _mesa_hash_table_create(ctx,
_mesa_hash_pointer, _mesa_key_pointer_equal);
ctx->addr_ht = _mesa_hash_table_create(ctx,
_mesa_hash_pointer, _mesa_key_pointer_equal);
 
lowered_tokens = lower_tgsi(tokens, so);
if (!lowered_tokens)
lowered_tokens = tokens;
ctx->s = to_nir(lowered_tokens);
 
if (lowered_tokens != tokens)
free((void *)lowered_tokens);
 
so->first_driver_param = so->first_immediate = ctx->s->num_uniforms;
 
/* one (vec4) slot for vertex id base: */
if (so->type == SHADER_VERTEX)
so->first_immediate++;
 
/* reserve 4 (vec4) slots for ubo base addresses: */
so->first_immediate += 4;
 
return ctx;
}
 
static void
compile_error(struct ir3_compile *ctx, const char *format, ...)
{
va_list ap;
va_start(ap, format);
_debug_vprintf(format, ap);
va_end(ap);
nir_print_shader(ctx->s, stdout);
ctx->error = true;
debug_assert(0);
}
 
#define compile_assert(ctx, cond) do { \
if (!(cond)) compile_error((ctx), "failed assert: "#cond"\n"); \
} while (0)
 
static void
compile_free(struct ir3_compile *ctx)
{
ralloc_free(ctx);
}
 
 
struct ir3_array {
unsigned length, aid;
struct ir3_instruction *arr[];
};
 
static void
declare_var(struct ir3_compile *ctx, nir_variable *var)
{
unsigned length = glsl_get_length(var->type) * 4; /* always vec4, at least with ttn */
struct ir3_array *arr = ralloc_size(ctx, sizeof(*arr) +
(length * sizeof(arr->arr[0])));
arr->length = length;
arr->aid = ++ctx->num_arrays;
/* Some shaders end up reading array elements without first writing..
* so initialize things to prevent null instr ptrs later:
*/
for (unsigned i = 0; i < length; i++)
arr->arr[i] = create_immed(ctx->block, 0);
_mesa_hash_table_insert(ctx->var_ht, var, arr);
}
 
static struct ir3_array *
get_var(struct ir3_compile *ctx, nir_variable *var)
{
struct hash_entry *entry = _mesa_hash_table_search(ctx->var_ht, var);
return entry->data;
}
 
/* allocate a n element value array (to be populated by caller) and
* insert in def_ht
*/
static struct ir3_instruction **
__get_dst(struct ir3_compile *ctx, void *key, unsigned n)
{
struct ir3_instruction **value =
ralloc_array(ctx->def_ht, struct ir3_instruction *, n);
_mesa_hash_table_insert(ctx->def_ht, key, value);
return value;
}
 
static struct ir3_instruction **
get_dst(struct ir3_compile *ctx, nir_dest *dst, unsigned n)
{
if (dst->is_ssa) {
return __get_dst(ctx, &dst->ssa, n);
} else {
return __get_dst(ctx, dst->reg.reg, n);
}
}
 
static struct ir3_instruction **
get_dst_ssa(struct ir3_compile *ctx, nir_ssa_def *dst, unsigned n)
{
return __get_dst(ctx, dst, n);
}
 
static struct ir3_instruction **
get_src(struct ir3_compile *ctx, nir_src *src)
{
struct hash_entry *entry;
if (src->is_ssa) {
entry = _mesa_hash_table_search(ctx->def_ht, src->ssa);
} else {
entry = _mesa_hash_table_search(ctx->def_ht, src->reg.reg);
}
compile_assert(ctx, entry);
return entry->data;
}
 
static struct ir3_instruction *
create_immed(struct ir3_block *block, uint32_t val)
{
struct ir3_instruction *mov;
 
mov = ir3_instr_create(block, 1, 0);
mov->cat1.src_type = TYPE_U32;
mov->cat1.dst_type = TYPE_U32;
ir3_reg_create(mov, 0, 0);
ir3_reg_create(mov, 0, IR3_REG_IMMED)->uim_val = val;
 
return mov;
}
 
static struct ir3_instruction *
create_addr(struct ir3_block *block, struct ir3_instruction *src)
{
struct ir3_instruction *instr, *immed;
 
/* TODO in at least some cases, the backend could probably be
* made clever enough to propagate IR3_REG_HALF..
*/
instr = ir3_COV(block, src, TYPE_U32, TYPE_S16);
instr->regs[0]->flags |= IR3_REG_HALF;
 
immed = create_immed(block, 2);
immed->regs[0]->flags |= IR3_REG_HALF;
 
instr = ir3_SHL_B(block, instr, 0, immed, 0);
instr->regs[0]->flags |= IR3_REG_HALF;
instr->regs[1]->flags |= IR3_REG_HALF;
 
instr = ir3_MOV(block, instr, TYPE_S16);
instr->regs[0]->flags |= IR3_REG_ADDR | IR3_REG_HALF;
instr->regs[1]->flags |= IR3_REG_HALF;
 
return instr;
}
 
/* caches addr values to avoid generating multiple cov/shl/mova
* sequences for each use of a given NIR level src as address
*/
static struct ir3_instruction *
get_addr(struct ir3_compile *ctx, struct ir3_instruction *src)
{
struct ir3_instruction *addr;
struct hash_entry *entry;
entry = _mesa_hash_table_search(ctx->addr_ht, src);
if (entry)
return entry->data;
 
/* TODO do we need to cache per block? */
addr = create_addr(ctx->block, src);
_mesa_hash_table_insert(ctx->addr_ht, src, addr);
 
return addr;
}
 
static struct ir3_instruction *
create_uniform(struct ir3_compile *ctx, unsigned n)
{
struct ir3_instruction *mov;
 
mov = ir3_instr_create(ctx->block, 1, 0);
/* TODO get types right? */
mov->cat1.src_type = TYPE_F32;
mov->cat1.dst_type = TYPE_F32;
ir3_reg_create(mov, 0, 0);
ir3_reg_create(mov, n, IR3_REG_CONST);
 
return mov;
}
 
static struct ir3_instruction *
create_uniform_indirect(struct ir3_compile *ctx, unsigned n,
struct ir3_instruction *address)
{
struct ir3_instruction *mov;
 
mov = ir3_instr_create(ctx->block, 1, 0);
mov->cat1.src_type = TYPE_U32;
mov->cat1.dst_type = TYPE_U32;
ir3_reg_create(mov, 0, 0);
ir3_reg_create(mov, n, IR3_REG_CONST | IR3_REG_RELATIV);
mov->address = address;
 
array_insert(ctx->ir->indirects, mov);
 
return mov;
}
 
static struct ir3_instruction *
create_collect(struct ir3_block *block, struct ir3_instruction **arr,
unsigned arrsz)
{
struct ir3_instruction *collect;
 
if (arrsz == 0)
return NULL;
 
collect = ir3_instr_create2(block, -1, OPC_META_FI, 1 + arrsz);
ir3_reg_create(collect, 0, 0);
for (unsigned i = 0; i < arrsz; i++)
ir3_reg_create(collect, 0, IR3_REG_SSA)->instr = arr[i];
 
return collect;
}
 
static struct ir3_instruction *
create_indirect_load(struct ir3_compile *ctx, unsigned arrsz, unsigned n,
struct ir3_instruction *address, struct ir3_instruction *collect)
{
struct ir3_block *block = ctx->block;
struct ir3_instruction *mov;
struct ir3_register *src;
 
mov = ir3_instr_create(block, 1, 0);
mov->cat1.src_type = TYPE_U32;
mov->cat1.dst_type = TYPE_U32;
ir3_reg_create(mov, 0, 0);
src = ir3_reg_create(mov, 0, IR3_REG_SSA | IR3_REG_RELATIV);
src->instr = collect;
src->size = arrsz;
src->offset = n;
mov->address = address;
 
array_insert(ctx->ir->indirects, mov);
 
return mov;
}
 
static struct ir3_instruction *
create_indirect_store(struct ir3_compile *ctx, unsigned arrsz, unsigned n,
struct ir3_instruction *src, struct ir3_instruction *address,
struct ir3_instruction *collect)
{
struct ir3_block *block = ctx->block;
struct ir3_instruction *mov;
struct ir3_register *dst;
 
mov = ir3_instr_create(block, 1, 0);
mov->cat1.src_type = TYPE_U32;
mov->cat1.dst_type = TYPE_U32;
dst = ir3_reg_create(mov, 0, IR3_REG_RELATIV);
dst->size = arrsz;
dst->offset = n;
ir3_reg_create(mov, 0, IR3_REG_SSA)->instr = src;
mov->address = address;
mov->fanin = collect;
 
array_insert(ctx->ir->indirects, mov);
 
return mov;
}
 
static struct ir3_instruction *
create_input(struct ir3_block *block, struct ir3_instruction *instr,
unsigned n)
{
struct ir3_instruction *in;
 
in = ir3_instr_create(block, -1, OPC_META_INPUT);
in->inout.block = block;
ir3_reg_create(in, n, 0);
if (instr)
ir3_reg_create(in, 0, IR3_REG_SSA)->instr = instr;
 
return in;
}
 
static struct ir3_instruction *
create_frag_input(struct ir3_compile *ctx, unsigned n, bool use_ldlv)
{
struct ir3_block *block = ctx->block;
struct ir3_instruction *instr;
struct ir3_instruction *inloc = create_immed(block, n);
 
if (use_ldlv) {
instr = ir3_LDLV(block, inloc, 0, create_immed(block, 1), 0);
instr->cat6.type = TYPE_U32;
instr->cat6.iim_val = 1;
} else {
instr = ir3_BARY_F(block, inloc, 0, ctx->frag_pos, 0);
instr->regs[2]->wrmask = 0x3;
}
 
return instr;
}
 
static struct ir3_instruction *
create_frag_coord(struct ir3_compile *ctx, unsigned comp)
{
struct ir3_block *block = ctx->block;
struct ir3_instruction *instr;
 
compile_assert(ctx, !ctx->frag_coord[comp]);
 
ctx->frag_coord[comp] = create_input(ctx->block, NULL, 0);
 
switch (comp) {
case 0: /* .x */
case 1: /* .y */
/* for frag_coord, we get unsigned values.. we need
* to subtract (integer) 8 and divide by 16 (right-
* shift by 4) then convert to float:
*
* sub.s tmp, src, 8
* shr.b tmp, tmp, 4
* mov.u32f32 dst, tmp
*
*/
instr = ir3_SUB_S(block, ctx->frag_coord[comp], 0,
create_immed(block, 8), 0);
instr = ir3_SHR_B(block, instr, 0,
create_immed(block, 4), 0);
instr = ir3_COV(block, instr, TYPE_U32, TYPE_F32);
 
return instr;
case 2: /* .z */
case 3: /* .w */
default:
/* seems that we can use these as-is: */
return ctx->frag_coord[comp];
}
}
 
static struct ir3_instruction *
create_frag_face(struct ir3_compile *ctx, unsigned comp)
{
struct ir3_block *block = ctx->block;
struct ir3_instruction *instr;
 
switch (comp) {
case 0: /* .x */
compile_assert(ctx, !ctx->frag_face);
 
ctx->frag_face = create_input(block, NULL, 0);
 
/* for faceness, we always get -1 or 0 (int).. but TGSI expects
* positive vs negative float.. and piglit further seems to
* expect -1.0 or 1.0:
*
* mul.s tmp, hr0.x, 2
* add.s tmp, tmp, 1
* mov.s32f32, dst, tmp
*
*/
instr = ir3_MUL_S(block, ctx->frag_face, 0,
create_immed(block, 2), 0);
instr = ir3_ADD_S(block, instr, 0,
create_immed(block, 1), 0);
instr = ir3_COV(block, instr, TYPE_S32, TYPE_F32);
 
return instr;
case 1: /* .y */
case 2: /* .z */
return create_immed(block, fui(0.0));
default:
case 3: /* .w */
return create_immed(block, fui(1.0));
}
}
 
/* helper for instructions that produce multiple consecutive scalar
* outputs which need to have a split/fanout meta instruction inserted
*/
static void
split_dest(struct ir3_block *block, struct ir3_instruction **dst,
struct ir3_instruction *src)
{
struct ir3_instruction *prev = NULL;
for (int i = 0, j = 0; i < 4; i++) {
struct ir3_instruction *split =
ir3_instr_create(block, -1, OPC_META_FO);
ir3_reg_create(split, 0, IR3_REG_SSA);
ir3_reg_create(split, 0, IR3_REG_SSA)->instr = src;
split->fo.off = i;
 
if (prev) {
split->cp.left = prev;
split->cp.left_cnt++;
prev->cp.right = split;
prev->cp.right_cnt++;
}
prev = split;
 
if (src->regs[0]->wrmask & (1 << i))
dst[j++] = split;
}
}
 
/*
* Adreno uses uint rather than having dedicated bool type,
* which (potentially) requires some conversion, in particular
* when using output of an bool instr to int input, or visa
* versa.
*
* | Adreno | NIR |
* -------+---------+-------+-
* true | 1 | ~0 |
* false | 0 | 0 |
*
* To convert from an adreno bool (uint) to nir, use:
*
* absneg.s dst, (neg)src
*
* To convert back in the other direction:
*
* absneg.s dst, (abs)arc
*
* The CP step can clean up the absneg.s that cancel each other
* out, and with a slight bit of extra cleverness (to recognize
* the instructions which produce either a 0 or 1) can eliminate
* the absneg.s's completely when an instruction that wants
* 0/1 consumes the result. For example, when a nir 'bcsel'
* consumes the result of 'feq'. So we should be able to get by
* without a boolean resolve step, and without incuring any
* extra penalty in instruction count.
*/
 
/* NIR bool -> native (adreno): */
static struct ir3_instruction *
ir3_b2n(struct ir3_block *block, struct ir3_instruction *instr)
{
return ir3_ABSNEG_S(block, instr, IR3_REG_SABS);
}
 
/* native (adreno) -> NIR bool: */
static struct ir3_instruction *
ir3_n2b(struct ir3_block *block, struct ir3_instruction *instr)
{
return ir3_ABSNEG_S(block, instr, IR3_REG_SNEG);
}
 
/*
* alu/sfu instructions:
*/
 
static void
emit_alu(struct ir3_compile *ctx, nir_alu_instr *alu)
{
const nir_op_info *info = &nir_op_infos[alu->op];
struct ir3_instruction **dst, *src[info->num_inputs];
struct ir3_block *b = ctx->block;
 
dst = get_dst(ctx, &alu->dest.dest, MAX2(info->output_size, 1));
 
/* Vectors are special in that they have non-scalarized writemasks,
* and just take the first swizzle channel for each argument in
* order into each writemask channel.
*/
if ((alu->op == nir_op_vec2) ||
(alu->op == nir_op_vec3) ||
(alu->op == nir_op_vec4)) {
 
for (int i = 0; i < info->num_inputs; i++) {
nir_alu_src *asrc = &alu->src[i];
 
compile_assert(ctx, !asrc->abs);
compile_assert(ctx, !asrc->negate);
 
src[i] = get_src(ctx, &asrc->src)[asrc->swizzle[0]];
if (!src[i])
src[i] = create_immed(ctx->block, 0);
dst[i] = ir3_MOV(b, src[i], TYPE_U32);
}
 
return;
}
 
/* General case: We can just grab the one used channel per src. */
for (int i = 0; i < info->num_inputs; i++) {
unsigned chan = ffs(alu->dest.write_mask) - 1;
nir_alu_src *asrc = &alu->src[i];
 
compile_assert(ctx, !asrc->abs);
compile_assert(ctx, !asrc->negate);
 
src[i] = get_src(ctx, &asrc->src)[asrc->swizzle[chan]];
 
compile_assert(ctx, src[i]);
}
 
switch (alu->op) {
case nir_op_f2i:
dst[0] = ir3_COV(b, src[0], TYPE_F32, TYPE_S32);
break;
case nir_op_f2u:
dst[0] = ir3_COV(b, src[0], TYPE_F32, TYPE_U32);
break;
case nir_op_i2f:
dst[0] = ir3_COV(b, src[0], TYPE_S32, TYPE_F32);
break;
case nir_op_u2f:
dst[0] = ir3_COV(b, src[0], TYPE_U32, TYPE_F32);
break;
case nir_op_imov:
dst[0] = ir3_MOV(b, src[0], TYPE_S32);
break;
case nir_op_fmov:
dst[0] = ir3_MOV(b, src[0], TYPE_F32);
break;
case nir_op_f2b:
dst[0] = ir3_CMPS_F(b, src[0], 0, create_immed(b, fui(0.0)), 0);
dst[0]->cat2.condition = IR3_COND_NE;
dst[0] = ir3_n2b(b, dst[0]);
break;
case nir_op_b2f:
dst[0] = ir3_COV(b, ir3_b2n(b, src[0]), TYPE_U32, TYPE_F32);
break;
case nir_op_b2i:
dst[0] = ir3_b2n(b, src[0]);
break;
case nir_op_i2b:
dst[0] = ir3_CMPS_S(b, src[0], 0, create_immed(b, 0), 0);
dst[0]->cat2.condition = IR3_COND_NE;
dst[0] = ir3_n2b(b, dst[0]);
break;
 
case nir_op_fneg:
dst[0] = ir3_ABSNEG_F(b, src[0], IR3_REG_FNEG);
break;
case nir_op_fabs:
dst[0] = ir3_ABSNEG_F(b, src[0], IR3_REG_FABS);
break;
case nir_op_fmax:
dst[0] = ir3_MAX_F(b, src[0], 0, src[1], 0);
break;
case nir_op_fmin:
dst[0] = ir3_MIN_F(b, src[0], 0, src[1], 0);
break;
case nir_op_fmul:
dst[0] = ir3_MUL_F(b, src[0], 0, src[1], 0);
break;
case nir_op_fadd:
dst[0] = ir3_ADD_F(b, src[0], 0, src[1], 0);
break;
case nir_op_fsub:
dst[0] = ir3_ADD_F(b, src[0], 0, src[1], IR3_REG_FNEG);
break;
case nir_op_ffma:
dst[0] = ir3_MAD_F32(b, src[0], 0, src[1], 0, src[2], 0);
break;
case nir_op_fddx:
dst[0] = ir3_DSX(b, src[0], 0);
dst[0]->cat5.type = TYPE_F32;
break;
case nir_op_fddy:
dst[0] = ir3_DSY(b, src[0], 0);
dst[0]->cat5.type = TYPE_F32;
break;
break;
case nir_op_flt:
dst[0] = ir3_CMPS_F(b, src[0], 0, src[1], 0);
dst[0]->cat2.condition = IR3_COND_LT;
dst[0] = ir3_n2b(b, dst[0]);
break;
case nir_op_fge:
dst[0] = ir3_CMPS_F(b, src[0], 0, src[1], 0);
dst[0]->cat2.condition = IR3_COND_GE;
dst[0] = ir3_n2b(b, dst[0]);
break;
case nir_op_feq:
dst[0] = ir3_CMPS_F(b, src[0], 0, src[1], 0);
dst[0]->cat2.condition = IR3_COND_EQ;
dst[0] = ir3_n2b(b, dst[0]);
break;
case nir_op_fne:
dst[0] = ir3_CMPS_F(b, src[0], 0, src[1], 0);
dst[0]->cat2.condition = IR3_COND_NE;
dst[0] = ir3_n2b(b, dst[0]);
break;
case nir_op_fceil:
dst[0] = ir3_CEIL_F(b, src[0], 0);
break;
case nir_op_ffloor:
dst[0] = ir3_FLOOR_F(b, src[0], 0);
break;
case nir_op_ftrunc:
dst[0] = ir3_TRUNC_F(b, src[0], 0);
break;
case nir_op_fround_even:
dst[0] = ir3_RNDNE_F(b, src[0], 0);
break;
case nir_op_fsign:
dst[0] = ir3_SIGN_F(b, src[0], 0);
break;
 
case nir_op_fsin:
dst[0] = ir3_SIN(b, src[0], 0);
break;
case nir_op_fcos:
dst[0] = ir3_COS(b, src[0], 0);
break;
case nir_op_frsq:
dst[0] = ir3_RSQ(b, src[0], 0);
break;
case nir_op_frcp:
dst[0] = ir3_RCP(b, src[0], 0);
break;
case nir_op_flog2:
dst[0] = ir3_LOG2(b, src[0], 0);
break;
case nir_op_fexp2:
dst[0] = ir3_EXP2(b, src[0], 0);
break;
case nir_op_fsqrt:
dst[0] = ir3_SQRT(b, src[0], 0);
break;
 
case nir_op_iabs:
dst[0] = ir3_ABSNEG_S(b, src[0], IR3_REG_SABS);
break;
case nir_op_iadd:
dst[0] = ir3_ADD_U(b, src[0], 0, src[1], 0);
break;
case nir_op_iand:
dst[0] = ir3_AND_B(b, src[0], 0, src[1], 0);
break;
case nir_op_imax:
dst[0] = ir3_MAX_S(b, src[0], 0, src[1], 0);
break;
case nir_op_imin:
dst[0] = ir3_MIN_S(b, src[0], 0, src[1], 0);
break;
case nir_op_imul:
/*
* dst = (al * bl) + (ah * bl << 16) + (al * bh << 16)
* mull.u tmp0, a, b ; mul low, i.e. al * bl
* madsh.m16 tmp1, a, b, tmp0 ; mul-add shift high mix, i.e. ah * bl << 16
* madsh.m16 dst, b, a, tmp1 ; i.e. al * bh << 16
*/
dst[0] = ir3_MADSH_M16(b, src[1], 0, src[0], 0,
ir3_MADSH_M16(b, src[0], 0, src[1], 0,
ir3_MULL_U(b, src[0], 0, src[1], 0), 0), 0);
break;
case nir_op_ineg:
dst[0] = ir3_ABSNEG_S(b, src[0], IR3_REG_SNEG);
break;
case nir_op_inot:
dst[0] = ir3_NOT_B(b, src[0], 0);
break;
case nir_op_ior:
dst[0] = ir3_OR_B(b, src[0], 0, src[1], 0);
break;
case nir_op_ishl:
dst[0] = ir3_SHL_B(b, src[0], 0, src[1], 0);
break;
case nir_op_ishr:
dst[0] = ir3_ASHR_B(b, src[0], 0, src[1], 0);
break;
case nir_op_isign: {
/* maybe this would be sane to lower in nir.. */
struct ir3_instruction *neg, *pos;
 
neg = ir3_CMPS_S(b, src[0], 0, create_immed(b, 0), 0);
neg->cat2.condition = IR3_COND_LT;
 
pos = ir3_CMPS_S(b, src[0], 0, create_immed(b, 0), 0);
pos->cat2.condition = IR3_COND_GT;
 
dst[0] = ir3_SUB_U(b, pos, 0, neg, 0);
 
break;
}
case nir_op_isub:
dst[0] = ir3_SUB_U(b, src[0], 0, src[1], 0);
break;
case nir_op_ixor:
dst[0] = ir3_XOR_B(b, src[0], 0, src[1], 0);
break;
case nir_op_ushr:
dst[0] = ir3_SHR_B(b, src[0], 0, src[1], 0);
break;
case nir_op_ilt:
dst[0] = ir3_CMPS_S(b, src[0], 0, src[1], 0);
dst[0]->cat2.condition = IR3_COND_LT;
dst[0] = ir3_n2b(b, dst[0]);
break;
case nir_op_ige:
dst[0] = ir3_CMPS_S(b, src[0], 0, src[1], 0);
dst[0]->cat2.condition = IR3_COND_GE;
dst[0] = ir3_n2b(b, dst[0]);
break;
case nir_op_ieq:
dst[0] = ir3_CMPS_S(b, src[0], 0, src[1], 0);
dst[0]->cat2.condition = IR3_COND_EQ;
dst[0] = ir3_n2b(b, dst[0]);
break;
case nir_op_ine:
dst[0] = ir3_CMPS_S(b, src[0], 0, src[1], 0);
dst[0]->cat2.condition = IR3_COND_NE;
dst[0] = ir3_n2b(b, dst[0]);
break;
case nir_op_ult:
dst[0] = ir3_CMPS_U(b, src[0], 0, src[1], 0);
dst[0]->cat2.condition = IR3_COND_LT;
dst[0] = ir3_n2b(b, dst[0]);
break;
case nir_op_uge:
dst[0] = ir3_CMPS_U(b, src[0], 0, src[1], 0);
dst[0]->cat2.condition = IR3_COND_GE;
dst[0] = ir3_n2b(b, dst[0]);
break;
 
case nir_op_bcsel:
dst[0] = ir3_SEL_B32(b, src[1], 0, ir3_b2n(b, src[0]), 0, src[2], 0);
break;
 
default:
compile_error(ctx, "Unhandled ALU op: %s\n",
nir_op_infos[alu->op].name);
break;
}
}
 
/* handles direct/indirect UBO reads: */
static void
emit_intrinsic_load_ubo(struct ir3_compile *ctx, nir_intrinsic_instr *intr,
struct ir3_instruction **dst)
{
struct ir3_block *b = ctx->block;
struct ir3_instruction *addr, *src0, *src1;
/* UBO addresses are the first driver params: */
unsigned ubo = regid(ctx->so->first_driver_param, 0);
unsigned off = intr->const_index[0];
 
/* First src is ubo index, which could either be an immed or not: */
src0 = get_src(ctx, &intr->src[0])[0];
if (is_same_type_mov(src0) &&
(src0->regs[1]->flags & IR3_REG_IMMED)) {
addr = create_uniform(ctx, ubo + src0->regs[1]->iim_val);
} else {
addr = create_uniform_indirect(ctx, ubo, get_addr(ctx, src0));
}
 
if (intr->intrinsic == nir_intrinsic_load_ubo_indirect) {
/* For load_ubo_indirect, second src is indirect offset: */
src1 = get_src(ctx, &intr->src[1])[0];
 
/* and add offset to addr: */
addr = ir3_ADD_S(b, addr, 0, src1, 0);
}
 
/* if offset is to large to encode in the ldg, split it out: */
if ((off + (intr->num_components * 4)) > 1024) {
/* split out the minimal amount to improve the odds that
* cp can fit the immediate in the add.s instruction:
*/
unsigned off2 = off + (intr->num_components * 4) - 1024;
addr = ir3_ADD_S(b, addr, 0, create_immed(b, off2), 0);
off -= off2;
}
 
for (int i = 0; i < intr->num_components; i++) {
struct ir3_instruction *load =
ir3_LDG(b, addr, 0, create_immed(b, 1), 0);
load->cat6.type = TYPE_U32;
load->cat6.offset = off + i * 4; /* byte offset */
dst[i] = load;
}
}
 
/* handles array reads: */
static void
emit_intrinisic_load_var(struct ir3_compile *ctx, nir_intrinsic_instr *intr,
struct ir3_instruction **dst)
{
nir_deref_var *dvar = intr->variables[0];
nir_deref_array *darr = nir_deref_as_array(dvar->deref.child);
struct ir3_array *arr = get_var(ctx, dvar->var);
 
compile_assert(ctx, dvar->deref.child &&
(dvar->deref.child->deref_type == nir_deref_type_array));
 
switch (darr->deref_array_type) {
case nir_deref_array_type_direct:
/* direct access does not require anything special: */
for (int i = 0; i < intr->num_components; i++) {
unsigned n = darr->base_offset * 4 + i;
compile_assert(ctx, n < arr->length);
dst[i] = arr->arr[n];
}
break;
case nir_deref_array_type_indirect: {
/* for indirect, we need to collect all the array elements: */
struct ir3_instruction *collect =
create_collect(ctx->block, arr->arr, arr->length);
struct ir3_instruction *addr =
get_addr(ctx, get_src(ctx, &darr->indirect)[0]);
for (int i = 0; i < intr->num_components; i++) {
unsigned n = darr->base_offset * 4 + i;
compile_assert(ctx, n < arr->length);
dst[i] = create_indirect_load(ctx, arr->length, n, addr, collect);
}
break;
}
default:
compile_error(ctx, "Unhandled load deref type: %u\n",
darr->deref_array_type);
break;
}
}
 
/* handles array writes: */
static void
emit_intrinisic_store_var(struct ir3_compile *ctx, nir_intrinsic_instr *intr)
{
nir_deref_var *dvar = intr->variables[0];
nir_deref_array *darr = nir_deref_as_array(dvar->deref.child);
struct ir3_array *arr = get_var(ctx, dvar->var);
struct ir3_instruction **src;
 
compile_assert(ctx, dvar->deref.child &&
(dvar->deref.child->deref_type == nir_deref_type_array));
 
src = get_src(ctx, &intr->src[0]);
 
switch (darr->deref_array_type) {
case nir_deref_array_type_direct:
/* direct access does not require anything special: */
for (int i = 0; i < intr->num_components; i++) {
unsigned n = darr->base_offset * 4 + i;
compile_assert(ctx, n < arr->length);
arr->arr[n] = src[i];
}
break;
case nir_deref_array_type_indirect: {
/* for indirect, create indirect-store and fan that out: */
struct ir3_instruction *collect =
create_collect(ctx->block, arr->arr, arr->length);
struct ir3_instruction *addr =
get_addr(ctx, get_src(ctx, &darr->indirect)[0]);
for (int i = 0; i < intr->num_components; i++) {
struct ir3_instruction *store;
unsigned n = darr->base_offset * 4 + i;
compile_assert(ctx, n < arr->length);
 
store = create_indirect_store(ctx, arr->length,
n, src[i], addr, collect);
 
store->fanin->fi.aid = arr->aid;
 
/* TODO: probably split this out to be used for
* store_output_indirect? or move this into
* create_indirect_store()?
*/
for (int j = i; j < arr->length; j += 4) {
struct ir3_instruction *split;
 
split = ir3_instr_create(ctx->block, -1, OPC_META_FO);
split->fo.off = j;
ir3_reg_create(split, 0, 0);
ir3_reg_create(split, 0, IR3_REG_SSA)->instr = store;
 
arr->arr[j] = split;
}
}
break;
}
default:
compile_error(ctx, "Unhandled store deref type: %u\n",
darr->deref_array_type);
break;
}
}
 
static void add_sysval_input(struct ir3_compile *ctx, unsigned name,
struct ir3_instruction *instr)
{
struct ir3_shader_variant *so = ctx->so;
unsigned r = regid(so->inputs_count, 0);
unsigned n = so->inputs_count++;
 
so->inputs[n].semantic = ir3_semantic_name(name, 0);
so->inputs[n].compmask = 1;
so->inputs[n].regid = r;
so->inputs[n].interpolate = TGSI_INTERPOLATE_CONSTANT;
so->total_in++;
 
ctx->block->ninputs = MAX2(ctx->block->ninputs, r + 1);
ctx->block->inputs[r] = instr;
}
 
static void
emit_intrinisic(struct ir3_compile *ctx, nir_intrinsic_instr *intr)
{
const nir_intrinsic_info *info = &nir_intrinsic_infos[intr->intrinsic];
struct ir3_instruction **dst, **src;
struct ir3_block *b = ctx->block;
unsigned idx = intr->const_index[0];
 
if (info->has_dest) {
dst = get_dst(ctx, &intr->dest, intr->num_components);
}
 
switch (intr->intrinsic) {
case nir_intrinsic_load_uniform:
compile_assert(ctx, intr->const_index[1] == 1);
for (int i = 0; i < intr->num_components; i++) {
unsigned n = idx * 4 + i;
dst[i] = create_uniform(ctx, n);
}
break;
case nir_intrinsic_load_uniform_indirect:
compile_assert(ctx, intr->const_index[1] == 1);
src = get_src(ctx, &intr->src[0]);
for (int i = 0; i < intr->num_components; i++) {
unsigned n = idx * 4 + i;
dst[i] = create_uniform_indirect(ctx, n,
get_addr(ctx, src[0]));
}
break;
case nir_intrinsic_load_ubo:
case nir_intrinsic_load_ubo_indirect:
emit_intrinsic_load_ubo(ctx, intr, dst);
break;
case nir_intrinsic_load_input:
compile_assert(ctx, intr->const_index[1] == 1);
for (int i = 0; i < intr->num_components; i++) {
unsigned n = idx * 4 + i;
dst[i] = b->inputs[n];
}
break;
case nir_intrinsic_load_input_indirect:
compile_assert(ctx, intr->const_index[1] == 1);
src = get_src(ctx, &intr->src[0]);
struct ir3_instruction *collect =
create_collect(b, b->inputs, b->ninputs);
struct ir3_instruction *addr = get_addr(ctx, src[0]);
for (int i = 0; i < intr->num_components; i++) {
unsigned n = idx * 4 + i;
dst[i] = create_indirect_load(ctx, b->ninputs, n, addr, collect);
}
break;
case nir_intrinsic_load_var:
emit_intrinisic_load_var(ctx, intr, dst);
break;
case nir_intrinsic_store_var:
emit_intrinisic_store_var(ctx, intr);
break;
case nir_intrinsic_store_output:
compile_assert(ctx, intr->const_index[1] == 1);
src = get_src(ctx, &intr->src[0]);
for (int i = 0; i < intr->num_components; i++) {
unsigned n = idx * 4 + i;
b->outputs[n] = src[i];
}
break;
case nir_intrinsic_load_base_vertex:
if (!ctx->basevertex) {
/* first four vec4 sysval's reserved for UBOs: */
unsigned r = regid(ctx->so->first_driver_param + 4, 0);
ctx->basevertex = create_uniform(ctx, r);
add_sysval_input(ctx, TGSI_SEMANTIC_BASEVERTEX,
ctx->basevertex);
}
dst[0] = ctx->basevertex;
break;
case nir_intrinsic_load_vertex_id_zero_base:
if (!ctx->vertex_id) {
ctx->vertex_id = create_input(ctx->block, NULL, 0);
add_sysval_input(ctx, TGSI_SEMANTIC_VERTEXID_NOBASE,
ctx->vertex_id);
}
dst[0] = ctx->vertex_id;
break;
case nir_intrinsic_load_instance_id:
if (!ctx->instance_id) {
ctx->instance_id = create_input(ctx->block, NULL, 0);
add_sysval_input(ctx, TGSI_SEMANTIC_INSTANCEID,
ctx->instance_id);
}
dst[0] = ctx->instance_id;
break;
case nir_intrinsic_discard_if:
case nir_intrinsic_discard: {
struct ir3_instruction *cond, *kill;
 
if (intr->intrinsic == nir_intrinsic_discard_if) {
/* conditional discard: */
src = get_src(ctx, &intr->src[0]);
cond = ir3_b2n(b, src[0]);
} else {
/* unconditional discard: */
cond = create_immed(b, 1);
}
 
cond = ir3_CMPS_S(b, cond, 0, create_immed(b, 0), 0);
cond->cat2.condition = IR3_COND_NE;
 
/* condition always goes in predicate register: */
cond->regs[0]->num = regid(REG_P0, 0);
 
kill = ir3_KILL(b, cond, 0);
 
ctx->kill[ctx->kill_count++] = kill;
ctx->so->has_kill = true;
 
break;
}
default:
compile_error(ctx, "Unhandled intrinsic type: %s\n",
nir_intrinsic_infos[intr->intrinsic].name);
break;
}
}
 
static void
emit_load_const(struct ir3_compile *ctx, nir_load_const_instr *instr)
{
struct ir3_instruction **dst = get_dst_ssa(ctx, &instr->def,
instr->def.num_components);
for (int i = 0; i < instr->def.num_components; i++)
dst[i] = create_immed(ctx->block, instr->value.u[i]);
}
 
static void
emit_undef(struct ir3_compile *ctx, nir_ssa_undef_instr *undef)
{
struct ir3_instruction **dst = get_dst_ssa(ctx, &undef->def,
undef->def.num_components);
/* backend doesn't want undefined instructions, so just plug
* in 0.0..
*/
for (int i = 0; i < undef->def.num_components; i++)
dst[i] = create_immed(ctx->block, fui(0.0));
}
 
/*
* texture fetch/sample instructions:
*/
 
static void
tex_info(nir_tex_instr *tex, unsigned *flagsp, unsigned *coordsp)
{
unsigned coords, flags = 0;
 
/* note: would use tex->coord_components.. except txs.. also,
* since array index goes after shadow ref, we don't want to
* count it:
*/
switch (tex->sampler_dim) {
case GLSL_SAMPLER_DIM_1D:
case GLSL_SAMPLER_DIM_BUF:
coords = 1;
break;
case GLSL_SAMPLER_DIM_2D:
case GLSL_SAMPLER_DIM_RECT:
case GLSL_SAMPLER_DIM_EXTERNAL:
case GLSL_SAMPLER_DIM_MS:
coords = 2;
break;
case GLSL_SAMPLER_DIM_3D:
case GLSL_SAMPLER_DIM_CUBE:
coords = 3;
flags |= IR3_INSTR_3D;
break;
}
 
if (tex->is_shadow)
flags |= IR3_INSTR_S;
 
if (tex->is_array)
flags |= IR3_INSTR_A;
 
*flagsp = flags;
*coordsp = coords;
}
 
static void
emit_tex(struct ir3_compile *ctx, nir_tex_instr *tex)
{
struct ir3_block *b = ctx->block;
struct ir3_instruction **dst, *sam, *src0[12], *src1[4];
struct ir3_instruction **coord, *lod, *compare, *proj, **off, **ddx, **ddy;
bool has_bias = false, has_lod = false, has_proj = false, has_off = false;
unsigned i, coords, flags;
unsigned nsrc0 = 0, nsrc1 = 0;
type_t type;
opc_t opc;
 
/* TODO: might just be one component for gathers? */
dst = get_dst(ctx, &tex->dest, 4);
 
for (unsigned i = 0; i < tex->num_srcs; i++) {
switch (tex->src[i].src_type) {
case nir_tex_src_coord:
coord = get_src(ctx, &tex->src[i].src);
break;
case nir_tex_src_bias:
lod = get_src(ctx, &tex->src[i].src)[0];
has_bias = true;
break;
case nir_tex_src_lod:
lod = get_src(ctx, &tex->src[i].src)[0];
has_lod = true;
break;
case nir_tex_src_comparitor: /* shadow comparator */
compare = get_src(ctx, &tex->src[i].src)[0];
break;
case nir_tex_src_projector:
proj = get_src(ctx, &tex->src[i].src)[0];
has_proj = true;
break;
case nir_tex_src_offset:
off = get_src(ctx, &tex->src[i].src);
has_off = true;
break;
case nir_tex_src_ddx:
ddx = get_src(ctx, &tex->src[i].src);
break;
case nir_tex_src_ddy:
ddy = get_src(ctx, &tex->src[i].src);
break;
default:
compile_error(ctx, "Unhandled NIR tex serc type: %d\n",
tex->src[i].src_type);
return;
}
}
 
switch (tex->op) {
case nir_texop_tex: opc = OPC_SAM; break;
case nir_texop_txb: opc = OPC_SAMB; break;
case nir_texop_txl: opc = OPC_SAML; break;
case nir_texop_txd: opc = OPC_SAMGQ; break;
case nir_texop_txf: opc = OPC_ISAML; break;
case nir_texop_txf_ms:
case nir_texop_txs:
case nir_texop_lod:
case nir_texop_tg4:
case nir_texop_query_levels:
compile_error(ctx, "Unhandled NIR tex type: %d\n", tex->op);
return;
}
 
tex_info(tex, &flags, &coords);
 
/* scale up integer coords for TXF based on the LOD */
if (opc == OPC_ISAML) {
assert(has_lod);
for (i = 0; i < coords; i++)
coord[i] = ir3_SHL_B(b, coord[i], 0, lod, 0);
}
/*
* lay out the first argument in the proper order:
* - actual coordinates first
* - shadow reference
* - array index
* - projection w
* - starting at offset 4, dpdx.xy, dpdy.xy
*
* bias/lod go into the second arg
*/
 
/* insert tex coords: */
for (i = 0; i < coords; i++)
src0[nsrc0++] = coord[i];
 
if (coords == 1) {
/* hw doesn't do 1d, so we treat it as 2d with
* height of 1, and patch up the y coord.
* TODO: y coord should be (int)0 in some cases..
*/
src0[nsrc0++] = create_immed(b, fui(0.5));
}
 
if (tex->is_shadow)
src0[nsrc0++] = compare;
 
if (tex->is_array)
src0[nsrc0++] = coord[coords];
 
if (has_proj) {
src0[nsrc0++] = proj;
flags |= IR3_INSTR_P;
}
 
/* pad to 4, then ddx/ddy: */
if (tex->op == nir_texop_txd) {
while (nsrc0 < 4)
src0[nsrc0++] = create_immed(b, fui(0.0));
for (i = 0; i < coords; i++)
src0[nsrc0++] = ddx[i];
if (coords < 2)
src0[nsrc0++] = create_immed(b, fui(0.0));
for (i = 0; i < coords; i++)
src0[nsrc0++] = ddy[i];
if (coords < 2)
src0[nsrc0++] = create_immed(b, fui(0.0));
}
 
/*
* second argument (if applicable):
* - offsets
* - lod
* - bias
*/
if (has_off | has_lod | has_bias) {
if (has_off) {
for (i = 0; i < coords; i++)
src1[nsrc1++] = off[i];
if (coords < 2)
src1[nsrc1++] = create_immed(b, fui(0.0));
flags |= IR3_INSTR_O;
}
 
if (has_lod | has_bias)
src1[nsrc1++] = lod;
}
 
switch (tex->dest_type) {
case nir_type_invalid:
case nir_type_float:
type = TYPE_F32;
break;
case nir_type_int:
type = TYPE_S32;
break;
case nir_type_unsigned:
case nir_type_bool:
type = TYPE_U32;
break;
}
 
sam = ir3_SAM(b, opc, type, TGSI_WRITEMASK_XYZW,
flags, tex->sampler_index, tex->sampler_index,
create_collect(b, src0, nsrc0),
create_collect(b, src1, nsrc1));
 
split_dest(b, dst, sam);
}
 
static void
emit_tex_query_levels(struct ir3_compile *ctx, nir_tex_instr *tex)
{
struct ir3_block *b = ctx->block;
struct ir3_instruction **dst, *sam;
 
dst = get_dst(ctx, &tex->dest, 1);
 
sam = ir3_SAM(b, OPC_GETINFO, TYPE_U32, TGSI_WRITEMASK_Z, 0,
tex->sampler_index, tex->sampler_index, NULL, NULL);
 
/* even though there is only one component, since it ends
* up in .z rather than .x, we need a split_dest()
*/
split_dest(b, dst, sam);
 
/* The # of levels comes from getinfo.z. We need to add 1 to it, since
* the value in TEX_CONST_0 is zero-based.
*/
if (ctx->levels_add_one)
dst[0] = ir3_ADD_U(b, dst[0], 0, create_immed(b, 1), 0);
}
 
static void
emit_tex_txs(struct ir3_compile *ctx, nir_tex_instr *tex)
{
struct ir3_block *b = ctx->block;
struct ir3_instruction **dst, *sam, *lod;
unsigned flags, coords;
 
tex_info(tex, &flags, &coords);
 
dst = get_dst(ctx, &tex->dest, 4);
 
compile_assert(ctx, tex->num_srcs == 1);
compile_assert(ctx, tex->src[0].src_type == nir_tex_src_lod);
 
lod = get_src(ctx, &tex->src[0].src)[0];
 
sam = ir3_SAM(b, OPC_GETSIZE, TYPE_U32, TGSI_WRITEMASK_XYZW, flags,
tex->sampler_index, tex->sampler_index, lod, NULL);
 
split_dest(b, dst, sam);
 
/* Array size actually ends up in .w rather than .z. This doesn't
* matter for miplevel 0, but for higher mips the value in z is
* minified whereas w stays. Also, the value in TEX_CONST_3_DEPTH is
* returned, which means that we have to add 1 to it for arrays.
*/
if (tex->is_array) {
if (ctx->levels_add_one) {
dst[coords] = ir3_ADD_U(b, dst[3], 0, create_immed(b, 1), 0);
} else {
dst[coords] = ir3_MOV(b, dst[3], TYPE_U32);
}
}
}
 
static void
emit_instr(struct ir3_compile *ctx, nir_instr *instr)
{
switch (instr->type) {
case nir_instr_type_alu:
emit_alu(ctx, nir_instr_as_alu(instr));
break;
case nir_instr_type_intrinsic:
emit_intrinisic(ctx, nir_instr_as_intrinsic(instr));
break;
case nir_instr_type_load_const:
emit_load_const(ctx, nir_instr_as_load_const(instr));
break;
case nir_instr_type_ssa_undef:
emit_undef(ctx, nir_instr_as_ssa_undef(instr));
break;
case nir_instr_type_tex: {
nir_tex_instr *tex = nir_instr_as_tex(instr);
/* couple tex instructions get special-cased:
*/
switch (tex->op) {
case nir_texop_txs:
emit_tex_txs(ctx, tex);
break;
case nir_texop_query_levels:
emit_tex_query_levels(ctx, tex);
break;
default:
emit_tex(ctx, tex);
break;
}
break;
}
case nir_instr_type_call:
case nir_instr_type_jump:
case nir_instr_type_phi:
case nir_instr_type_parallel_copy:
compile_error(ctx, "Unhandled NIR instruction type: %d\n", instr->type);
break;
}
}
 
static void
emit_block(struct ir3_compile *ctx, nir_block *block)
{
nir_foreach_instr(block, instr) {
emit_instr(ctx, instr);
if (ctx->error)
return;
}
}
 
static void
emit_function(struct ir3_compile *ctx, nir_function_impl *impl)
{
foreach_list_typed(nir_cf_node, node, node, &impl->body) {
switch (node->type) {
case nir_cf_node_block:
emit_block(ctx, nir_cf_node_as_block(node));
break;
case nir_cf_node_if:
case nir_cf_node_loop:
case nir_cf_node_function:
compile_error(ctx, "TODO\n");
break;
}
if (ctx->error)
return;
}
}
 
static void
setup_input(struct ir3_compile *ctx, nir_variable *in)
{
struct ir3_shader_variant *so = ctx->so;
unsigned array_len = MAX2(glsl_get_length(in->type), 1);
unsigned ncomp = glsl_get_components(in->type);
/* XXX: map loc slots to semantics */
unsigned semantic_name = in->data.location;
unsigned semantic_index = in->data.index;
unsigned n = in->data.driver_location;
 
DBG("; in: %u:%u, len=%ux%u, loc=%u\n",
semantic_name, semantic_index, array_len,
ncomp, n);
 
so->inputs[n].semantic =
ir3_semantic_name(semantic_name, semantic_index);
so->inputs[n].compmask = (1 << ncomp) - 1;
so->inputs[n].inloc = ctx->next_inloc;
so->inputs[n].interpolate = 0;
so->inputs_count = MAX2(so->inputs_count, n + 1);
 
/* the fdN_program_emit() code expects tgsi consts here, so map
* things back to tgsi for now:
*/
switch (in->data.interpolation) {
case INTERP_QUALIFIER_FLAT:
so->inputs[n].interpolate = TGSI_INTERPOLATE_CONSTANT;
break;
case INTERP_QUALIFIER_NOPERSPECTIVE:
so->inputs[n].interpolate = TGSI_INTERPOLATE_LINEAR;
break;
case INTERP_QUALIFIER_SMOOTH:
so->inputs[n].interpolate = TGSI_INTERPOLATE_PERSPECTIVE;
break;
}
 
for (int i = 0; i < ncomp; i++) {
struct ir3_instruction *instr = NULL;
unsigned idx = (n * 4) + i;
 
if (ctx->so->type == SHADER_FRAGMENT) {
if (semantic_name == TGSI_SEMANTIC_POSITION) {
so->inputs[n].bary = false;
so->frag_coord = true;
instr = create_frag_coord(ctx, i);
} else if (semantic_name == TGSI_SEMANTIC_FACE) {
so->inputs[n].bary = false;
so->frag_face = true;
instr = create_frag_face(ctx, i);
} else {
bool use_ldlv = false;
 
/* with NIR, we need to infer TGSI_INTERPOLATE_COLOR
* from the semantic name:
*/
if ((in->data.interpolation == INTERP_QUALIFIER_NONE) &&
((semantic_name == TGSI_SEMANTIC_COLOR) ||
(semantic_name == TGSI_SEMANTIC_BCOLOR)))
so->inputs[n].interpolate = TGSI_INTERPOLATE_COLOR;
 
if (ctx->flat_bypass) {
/* with NIR, we need to infer TGSI_INTERPOLATE_COLOR
* from the semantic name:
*/
switch (so->inputs[n].interpolate) {
case TGSI_INTERPOLATE_COLOR:
if (!ctx->so->key.rasterflat)
break;
/* fallthrough */
case TGSI_INTERPOLATE_CONSTANT:
use_ldlv = true;
break;
}
}
 
so->inputs[n].bary = true;
 
instr = create_frag_input(ctx,
so->inputs[n].inloc + i - 8, use_ldlv);
}
} else {
instr = create_input(ctx->block, NULL, idx);
}
 
ctx->block->inputs[idx] = instr;
}
 
if (so->inputs[n].bary || (ctx->so->type == SHADER_VERTEX)) {
ctx->next_inloc += ncomp;
so->total_in += ncomp;
}
}
 
static void
setup_output(struct ir3_compile *ctx, nir_variable *out)
{
struct ir3_shader_variant *so = ctx->so;
unsigned array_len = MAX2(glsl_get_length(out->type), 1);
unsigned ncomp = glsl_get_components(out->type);
/* XXX: map loc slots to semantics */
unsigned semantic_name = out->data.location;
unsigned semantic_index = out->data.index;
unsigned n = out->data.driver_location;
unsigned comp = 0;
 
DBG("; out: %u:%u, len=%ux%u, loc=%u\n",
semantic_name, semantic_index, array_len,
ncomp, n);
 
if (ctx->so->type == SHADER_VERTEX) {
switch (semantic_name) {
case TGSI_SEMANTIC_POSITION:
so->writes_pos = true;
break;
case TGSI_SEMANTIC_PSIZE:
so->writes_psize = true;
break;
case TGSI_SEMANTIC_COLOR:
case TGSI_SEMANTIC_BCOLOR:
case TGSI_SEMANTIC_GENERIC:
case TGSI_SEMANTIC_FOG:
case TGSI_SEMANTIC_TEXCOORD:
break;
default:
compile_error(ctx, "unknown VS semantic name: %s\n",
tgsi_semantic_names[semantic_name]);
}
} else {
switch (semantic_name) {
case TGSI_SEMANTIC_POSITION:
comp = 2; /* tgsi will write to .z component */
so->writes_pos = true;
break;
case TGSI_SEMANTIC_COLOR:
break;
default:
compile_error(ctx, "unknown FS semantic name: %s\n",
tgsi_semantic_names[semantic_name]);
}
}
 
compile_assert(ctx, n < ARRAY_SIZE(so->outputs));
 
so->outputs[n].semantic =
ir3_semantic_name(semantic_name, semantic_index);
so->outputs[n].regid = regid(n, comp);
so->outputs_count = MAX2(so->outputs_count, n + 1);
 
for (int i = 0; i < ncomp; i++) {
unsigned idx = (n * 4) + i;
 
ctx->block->outputs[idx] = create_immed(ctx->block, fui(0.0));
}
}
 
static void
emit_instructions(struct ir3_compile *ctx)
{
unsigned ninputs = exec_list_length(&ctx->s->inputs) * 4;
unsigned noutputs = exec_list_length(&ctx->s->outputs) * 4;
 
/* we need to allocate big enough outputs array so that
* we can stuff the kill's at the end. Likewise for vtx
* shaders, we need to leave room for sysvals:
*/
if (ctx->so->type == SHADER_FRAGMENT) {
noutputs += ARRAY_SIZE(ctx->kill);
} else if (ctx->so->type == SHADER_VERTEX) {
ninputs += 8;
}
 
ctx->block = ir3_block_create(ctx->ir, 0, ninputs, noutputs);
 
if (ctx->so->type == SHADER_FRAGMENT) {
ctx->block->noutputs -= ARRAY_SIZE(ctx->kill);
} else if (ctx->so->type == SHADER_VERTEX) {
ctx->block->ninputs -= 8;
}
 
/* for fragment shader, we have a single input register (usually
* r0.xy) which is used as the base for bary.f varying fetch instrs:
*/
if (ctx->so->type == SHADER_FRAGMENT) {
// TODO maybe a helper for fi since we need it a few places..
struct ir3_instruction *instr;
instr = ir3_instr_create(ctx->block, -1, OPC_META_FI);
ir3_reg_create(instr, 0, 0);
ir3_reg_create(instr, 0, IR3_REG_SSA); /* r0.x */
ir3_reg_create(instr, 0, IR3_REG_SSA); /* r0.y */
ctx->frag_pos = instr;
}
 
/* Setup inputs: */
foreach_list_typed(nir_variable, var, node, &ctx->s->inputs) {
setup_input(ctx, var);
}
 
/* Setup outputs: */
foreach_list_typed(nir_variable, var, node, &ctx->s->outputs) {
setup_output(ctx, var);
}
 
/* Setup variables (which should only be arrays): */
foreach_list_typed(nir_variable, var, node, &ctx->s->globals) {
declare_var(ctx, var);
}
 
/* Find the main function and emit the body: */
nir_foreach_overload(ctx->s, overload) {
compile_assert(ctx, strcmp(overload->function->name, "main") == 0);
compile_assert(ctx, overload->impl);
emit_function(ctx, overload->impl);
if (ctx->error)
return;
}
}
 
/* from NIR perspective, we actually have inputs. But most of the "inputs"
* for a fragment shader are just bary.f instructions. The *actual* inputs
* from the hw perspective are the frag_pos and optionally frag_coord and
* frag_face.
*/
static void
fixup_frag_inputs(struct ir3_compile *ctx)
{
struct ir3_shader_variant *so = ctx->so;
struct ir3_block *block = ctx->block;
struct ir3_instruction **inputs;
struct ir3_instruction *instr;
int n, regid = 0;
 
block->ninputs = 0;
 
n = 4; /* always have frag_pos */
n += COND(so->frag_face, 4);
n += COND(so->frag_coord, 4);
 
inputs = ir3_alloc(ctx->ir, n * (sizeof(struct ir3_instruction *)));
 
if (so->frag_face) {
/* this ultimately gets assigned to hr0.x so doesn't conflict
* with frag_coord/frag_pos..
*/
inputs[block->ninputs++] = ctx->frag_face;
ctx->frag_face->regs[0]->num = 0;
 
/* remaining channels not used, but let's avoid confusing
* other parts that expect inputs to come in groups of vec4
*/
inputs[block->ninputs++] = NULL;
inputs[block->ninputs++] = NULL;
inputs[block->ninputs++] = NULL;
}
 
/* since we don't know where to set the regid for frag_coord,
* we have to use r0.x for it. But we don't want to *always*
* use r1.x for frag_pos as that could increase the register
* footprint on simple shaders:
*/
if (so->frag_coord) {
ctx->frag_coord[0]->regs[0]->num = regid++;
ctx->frag_coord[1]->regs[0]->num = regid++;
ctx->frag_coord[2]->regs[0]->num = regid++;
ctx->frag_coord[3]->regs[0]->num = regid++;
 
inputs[block->ninputs++] = ctx->frag_coord[0];
inputs[block->ninputs++] = ctx->frag_coord[1];
inputs[block->ninputs++] = ctx->frag_coord[2];
inputs[block->ninputs++] = ctx->frag_coord[3];
}
 
/* we always have frag_pos: */
so->pos_regid = regid;
 
/* r0.x */
instr = create_input(block, NULL, block->ninputs);
instr->regs[0]->num = regid++;
inputs[block->ninputs++] = instr;
ctx->frag_pos->regs[1]->instr = instr;
 
/* r0.y */
instr = create_input(block, NULL, block->ninputs);
instr->regs[0]->num = regid++;
inputs[block->ninputs++] = instr;
ctx->frag_pos->regs[2]->instr = instr;
 
block->inputs = inputs;
}
 
static void
compile_dump(struct ir3_compile *ctx)
{
const char *name = (ctx->so->type == SHADER_VERTEX) ? "vert" : "frag";
static unsigned n = 0;
char fname[16];
FILE *f;
snprintf(fname, sizeof(fname), "%s-%04u.dot", name, n++);
f = fopen(fname, "w");
if (!f)
return;
ir3_block_depth(ctx->block);
ir3_dump(ctx->ir, name, ctx->block, f);
fclose(f);
}
 
int
ir3_compile_shader_nir(struct ir3_shader_variant *so,
const struct tgsi_token *tokens, struct ir3_shader_key key)
{
struct ir3_compile *ctx;
struct ir3_block *block;
struct ir3_instruction **inputs;
unsigned i, j, actual_in;
int ret = 0, max_bary;
 
assert(!so->ir);
 
so->ir = ir3_create();
 
assert(so->ir);
 
ctx = compile_init(so, tokens);
if (!ctx) {
DBG("INIT failed!");
ret = -1;
goto out;
}
 
emit_instructions(ctx);
 
if (ctx->error) {
DBG("EMIT failed!");
ret = -1;
goto out;
}
 
block = ctx->block;
so->ir->block = block;
 
/* keep track of the inputs from TGSI perspective.. */
inputs = block->inputs;
 
/* but fixup actual inputs for frag shader: */
if (so->type == SHADER_FRAGMENT)
fixup_frag_inputs(ctx);
 
/* at this point, for binning pass, throw away unneeded outputs: */
if (key.binning_pass) {
for (i = 0, j = 0; i < so->outputs_count; i++) {
unsigned name = sem2name(so->outputs[i].semantic);
unsigned idx = sem2idx(so->outputs[i].semantic);
 
/* throw away everything but first position/psize */
if ((idx == 0) && ((name == TGSI_SEMANTIC_POSITION) ||
(name == TGSI_SEMANTIC_PSIZE))) {
if (i != j) {
so->outputs[j] = so->outputs[i];
block->outputs[(j*4)+0] = block->outputs[(i*4)+0];
block->outputs[(j*4)+1] = block->outputs[(i*4)+1];
block->outputs[(j*4)+2] = block->outputs[(i*4)+2];
block->outputs[(j*4)+3] = block->outputs[(i*4)+3];
}
j++;
}
}
so->outputs_count = j;
block->noutputs = j * 4;
}
 
/* if we want half-precision outputs, mark the output registers
* as half:
*/
if (key.half_precision) {
for (i = 0; i < block->noutputs; i++) {
if (!block->outputs[i])
continue;
block->outputs[i]->regs[0]->flags |= IR3_REG_HALF;
}
}
 
/* at this point, we want the kill's in the outputs array too,
* so that they get scheduled (since they have no dst).. we've
* already ensured that the array is big enough in push_block():
*/
if (so->type == SHADER_FRAGMENT) {
for (i = 0; i < ctx->kill_count; i++)
block->outputs[block->noutputs++] = ctx->kill[i];
}
 
if (fd_mesa_debug & FD_DBG_OPTDUMP)
compile_dump(ctx);
 
if (fd_mesa_debug & FD_DBG_OPTMSGS) {
printf("BEFORE CP:\n");
ir3_dump_instr_list(block->head);
}
 
ir3_block_depth(block);
 
ir3_block_cp(block);
 
if (fd_mesa_debug & FD_DBG_OPTMSGS) {
printf("BEFORE GROUPING:\n");
ir3_dump_instr_list(block->head);
}
 
/* Group left/right neighbors, inserting mov's where needed to
* solve conflicts:
*/
ir3_block_group(block);
 
if (fd_mesa_debug & FD_DBG_OPTDUMP)
compile_dump(ctx);
 
ir3_block_depth(block);
 
if (fd_mesa_debug & FD_DBG_OPTMSGS) {
printf("AFTER DEPTH:\n");
ir3_dump_instr_list(block->head);
}
 
ret = ir3_block_sched(block);
if (ret) {
DBG("SCHED failed!");
goto out;
}
 
if (fd_mesa_debug & FD_DBG_OPTMSGS) {
printf("AFTER SCHED:\n");
ir3_dump_instr_list(block->head);
}
 
ret = ir3_block_ra(block, so->type, so->frag_coord, so->frag_face);
if (ret) {
DBG("RA failed!");
goto out;
}
 
if (fd_mesa_debug & FD_DBG_OPTMSGS) {
printf("AFTER RA:\n");
ir3_dump_instr_list(block->head);
}
 
ir3_block_legalize(block, &so->has_samp, &max_bary);
 
/* fixup input/outputs: */
for (i = 0; i < so->outputs_count; i++) {
so->outputs[i].regid = block->outputs[i*4]->regs[0]->num;
/* preserve hack for depth output.. tgsi writes depth to .z,
* but what we give the hw is the scalar register:
*/
if ((so->type == SHADER_FRAGMENT) &&
(sem2name(so->outputs[i].semantic) == TGSI_SEMANTIC_POSITION))
so->outputs[i].regid += 2;
}
 
/* Note that some or all channels of an input may be unused: */
actual_in = 0;
for (i = 0; i < so->inputs_count; i++) {
unsigned j, regid = ~0, compmask = 0;
so->inputs[i].ncomp = 0;
for (j = 0; j < 4; j++) {
struct ir3_instruction *in = inputs[(i*4) + j];
if (in) {
compmask |= (1 << j);
regid = in->regs[0]->num - j;
actual_in++;
so->inputs[i].ncomp++;
}
}
so->inputs[i].regid = regid;
so->inputs[i].compmask = compmask;
}
 
/* fragment shader always gets full vec4's even if it doesn't
* fetch all components, but vertex shader we need to update
* with the actual number of components fetch, otherwise thing
* will hang due to mismaptch between VFD_DECODE's and
* TOTALATTRTOVS
*/
if (so->type == SHADER_VERTEX)
so->total_in = actual_in;
else
so->total_in = align(max_bary + 1, 4);
 
out:
if (ret) {
ir3_destroy(so->ir);
so->ir = NULL;
}
compile_free(ctx);
 
return ret;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/ir3/ir3_cp.c
0,0 → 1,415
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "freedreno_util.h"
 
#include "ir3.h"
 
/*
* Copy Propagate:
*/
 
/* is it a type preserving mov, with ok flags? */
static bool is_eligible_mov(struct ir3_instruction *instr, bool allow_flags)
{
if (is_same_type_mov(instr)) {
struct ir3_register *dst = instr->regs[0];
struct ir3_register *src = instr->regs[1];
struct ir3_instruction *src_instr = ssa(src);
if (dst->flags & (IR3_REG_ADDR | IR3_REG_RELATIV))
return false;
if (src->flags & IR3_REG_RELATIV)
return false;
if (!allow_flags)
if (src->flags & (IR3_REG_FABS | IR3_REG_FNEG |
IR3_REG_SABS | IR3_REG_SNEG | IR3_REG_BNOT))
return false;
if (!src_instr)
return false;
/* TODO: remove this hack: */
if (is_meta(src_instr) && (src_instr->opc == OPC_META_FO))
return false;
return true;
}
return false;
}
 
static unsigned cp_flags(unsigned flags)
{
/* only considering these flags (at least for now): */
flags &= (IR3_REG_CONST | IR3_REG_IMMED |
IR3_REG_FNEG | IR3_REG_FABS |
IR3_REG_SNEG | IR3_REG_SABS |
IR3_REG_BNOT | IR3_REG_RELATIV);
return flags;
}
 
static bool valid_flags(struct ir3_instruction *instr, unsigned n,
unsigned flags)
{
unsigned valid_flags;
flags = cp_flags(flags);
 
/* clear flags that are 'ok' */
switch (instr->category) {
case 1:
valid_flags = IR3_REG_IMMED | IR3_REG_RELATIV;
if (flags & ~valid_flags)
return false;
break;
case 5:
/* no flags allowed */
if (flags)
return false;
break;
case 6:
valid_flags = IR3_REG_IMMED;
if (flags & ~valid_flags)
return false;
break;
case 2:
valid_flags = ir3_cat2_absneg(instr->opc) |
IR3_REG_CONST | IR3_REG_RELATIV;
 
if (ir3_cat2_int(instr->opc))
valid_flags |= IR3_REG_IMMED;
 
if (flags & ~valid_flags)
return false;
 
if (flags & (IR3_REG_CONST | IR3_REG_IMMED)) {
unsigned m = (n ^ 1) + 1;
/* cannot deal w/ const in both srcs:
* (note that some cat2 actually only have a single src)
*/
if (m < instr->regs_count) {
struct ir3_register *reg = instr->regs[m];
if ((flags & IR3_REG_CONST) && (reg->flags & IR3_REG_CONST))
return false;
if ((flags & IR3_REG_IMMED) && (reg->flags & IR3_REG_IMMED))
return false;
}
/* cannot be const + ABS|NEG: */
if (flags & (IR3_REG_FABS | IR3_REG_FNEG |
IR3_REG_SABS | IR3_REG_SNEG | IR3_REG_BNOT))
return false;
}
break;
case 3:
valid_flags = ir3_cat3_absneg(instr->opc) |
IR3_REG_CONST | IR3_REG_RELATIV;
 
if (flags & ~valid_flags)
return false;
 
if (flags & (IR3_REG_CONST | IR3_REG_RELATIV)) {
/* cannot deal w/ const/relativ in 2nd src: */
if (n == 1)
return false;
}
 
if (flags & IR3_REG_CONST) {
/* cannot be const + ABS|NEG: */
if (flags & (IR3_REG_FABS | IR3_REG_FNEG |
IR3_REG_SABS | IR3_REG_SNEG | IR3_REG_BNOT))
return false;
}
break;
case 4:
/* seems like blob compiler avoids const as src.. */
/* TODO double check if this is still the case on a4xx */
if (flags & IR3_REG_CONST)
return false;
if (flags & (IR3_REG_SABS | IR3_REG_SNEG))
return false;
break;
}
 
return true;
}
 
/* propagate register flags from src to dst.. negates need special
* handling to cancel each other out.
*/
static void combine_flags(unsigned *dstflags, unsigned srcflags)
{
/* if what we are combining into already has (abs) flags,
* we can drop (neg) from src:
*/
if (*dstflags & IR3_REG_FABS)
srcflags &= ~IR3_REG_FNEG;
if (*dstflags & IR3_REG_SABS)
srcflags &= ~IR3_REG_SNEG;
 
if (srcflags & IR3_REG_FABS)
*dstflags |= IR3_REG_FABS;
if (srcflags & IR3_REG_SABS)
*dstflags |= IR3_REG_SABS;
if (srcflags & IR3_REG_FNEG)
*dstflags ^= IR3_REG_FNEG;
if (srcflags & IR3_REG_SNEG)
*dstflags ^= IR3_REG_SNEG;
if (srcflags & IR3_REG_BNOT)
*dstflags ^= IR3_REG_BNOT;
}
 
static struct ir3_instruction * instr_cp(struct ir3_instruction *instr, unsigned *flags);
 
/* the "plain" MAD's (ie. the ones that don't shift first src prior to
* multiply) can swap their first two srcs if src[0] is !CONST and
* src[1] is CONST:
*/
static bool is_valid_mad(struct ir3_instruction *instr)
{
return (instr->category == 3) && is_mad(instr->opc);
}
 
/**
* Handle cp for a given src register. This additionally handles
* the cases of collapsing immedate/const (which replace the src
* register with a non-ssa src) or collapsing mov's from relative
* src (which needs to also fixup the address src reference by the
* instruction).
*/
static void
reg_cp(struct ir3_instruction *instr, struct ir3_register *reg, unsigned n)
{
unsigned src_flags = 0, new_flags;
struct ir3_instruction *src_instr;
 
if (is_meta(instr)) {
/* meta instructions cannot fold up register
* flags.. they are usually src for texture
* fetch, etc, where we cannot specify abs/neg
*/
reg->instr = instr_cp(reg->instr, NULL);
return;
}
 
src_instr = instr_cp(reg->instr, &src_flags);
 
new_flags = reg->flags;
combine_flags(&new_flags, src_flags);
 
reg->flags = new_flags;
reg->instr = src_instr;
 
if (!valid_flags(instr, n, reg->flags)) {
/* insert an absneg.f */
if (reg->flags & (IR3_REG_SNEG | IR3_REG_SABS | IR3_REG_BNOT)) {
debug_assert(!(reg->flags & (IR3_REG_FNEG | IR3_REG_FABS)));
reg->instr = ir3_ABSNEG_S(instr->block,
reg->instr, cp_flags(src_flags));
} else {
debug_assert(!(reg->flags & (IR3_REG_SNEG | IR3_REG_SABS | IR3_REG_BNOT)));
reg->instr = ir3_ABSNEG_F(instr->block,
reg->instr, cp_flags(src_flags));
}
reg->flags &= ~cp_flags(src_flags);
debug_assert(valid_flags(instr, n, reg->flags));
/* send it through instr_cp() again since
* the absneg src might be a mov from const
* that could be cleaned up:
*/
reg->instr = instr_cp(reg->instr, NULL);
return;
}
 
if (is_same_type_mov(reg->instr)) {
struct ir3_register *src_reg = reg->instr->regs[1];
unsigned new_flags = src_reg->flags;
 
combine_flags(&new_flags, reg->flags);
 
if (!valid_flags(instr, n, new_flags)) {
/* special case for "normal" mad instructions, we can
* try swapping the first two args if that fits better.
*/
if ((n == 1) && is_valid_mad(instr) &&
!(instr->regs[0 + 1]->flags & (IR3_REG_CONST | IR3_REG_RELATIV)) &&
valid_flags(instr, 0, new_flags)) {
/* swap src[0] and src[1]: */
struct ir3_register *tmp;
tmp = instr->regs[0 + 1];
instr->regs[0 + 1] = instr->regs[1 + 1];
instr->regs[1 + 1] = tmp;
n = 0;
} else {
return;
}
}
 
/* Here we handle the special case of mov from
* CONST and/or RELATIV. These need to be handled
* specially, because in the case of move from CONST
* there is no src ir3_instruction so we need to
* replace the ir3_register. And in the case of
* RELATIV we need to handle the address register
* dependency.
*/
if (src_reg->flags & IR3_REG_CONST) {
/* an instruction cannot reference two different
* address registers:
*/
if ((src_reg->flags & IR3_REG_RELATIV) &&
conflicts(instr->address, reg->instr->address))
return;
 
src_reg->flags = new_flags;
instr->regs[n+1] = src_reg;
 
if (src_reg->flags & IR3_REG_RELATIV)
instr->address = reg->instr->address;
 
return;
}
 
if ((src_reg->flags & IR3_REG_RELATIV) &&
!conflicts(instr->address, reg->instr->address)) {
src_reg->flags = new_flags;
instr->regs[n+1] = src_reg;
instr->address = reg->instr->address;
 
return;
}
 
/* NOTE: seems we can only do immed integers, so don't
* need to care about float. But we do need to handle
* abs/neg *before* checking that the immediate requires
* few enough bits to encode:
*
* TODO: do we need to do something to avoid accidentally
* catching a float immed?
*/
if (src_reg->flags & IR3_REG_IMMED) {
int32_t iim_val = src_reg->iim_val;
 
debug_assert((instr->category == 1) ||
(instr->category == 6) ||
((instr->category == 2) &&
ir3_cat2_int(instr->opc)));
 
if (new_flags & IR3_REG_SABS)
iim_val = abs(iim_val);
 
if (new_flags & IR3_REG_SNEG)
iim_val = -iim_val;
 
if (new_flags & IR3_REG_BNOT)
iim_val = ~iim_val;
 
if (!(iim_val & ~0x3ff)) {
new_flags &= ~(IR3_REG_SABS | IR3_REG_SNEG | IR3_REG_BNOT);
src_reg->flags = new_flags;
src_reg->iim_val = iim_val;
instr->regs[n+1] = src_reg;
}
 
return;
}
}
}
 
/**
* Given an SSA src (instruction), return the one with extraneous
* mov's removed, ie, for (to copy NIR syntax):
*
* vec1 ssa1 = fadd <something>, <somethingelse>
* vec1 ssa2 = fabs ssa1
* vec1 ssa3 = fneg ssa1
*
* then calling instr_cp(ssa3, &flags) would return ssa1 with
* (IR3_REG_ABS | IR3_REG_NEGATE) in flags. If flags is NULL,
* then disallow eliminating copies which would require flag
* propagation (for example, we cannot propagate abs/neg into
* an output).
*/
static struct ir3_instruction *
instr_cp(struct ir3_instruction *instr, unsigned *flags)
{
struct ir3_register *reg;
 
/* stay within the block.. don't try to operate across
* basic block boundaries or we'll have problems when
* dealing with multiple basic blocks:
*/
if (is_meta(instr) && (instr->opc == OPC_META_INPUT))
return instr;
 
if (is_eligible_mov(instr, !!flags)) {
struct ir3_register *reg = instr->regs[1];
struct ir3_instruction *src_instr = ssa(reg);
if (flags)
combine_flags(flags, reg->flags);
return instr_cp(src_instr, flags);
}
 
/* Check termination condition before walking children (rather
* than before checking eligible-mov). A mov instruction may
* appear as ssa-src for multiple other instructions, and we
* want to consider it for removal for each, rather than just
* the first one. (But regardless of how many places it shows
* up as a src, we only need to recursively walk the children
* once.)
*/
if (ir3_instr_check_mark(instr))
return instr;
 
/* walk down the graph from each src: */
foreach_src_n(reg, n, instr) {
if (!(reg->flags & IR3_REG_SSA))
continue;
 
reg_cp(instr, reg, n);
}
 
if (instr->address)
instr->address = instr_cp(instr->address, NULL);
 
return instr;
}
 
static void block_cp(struct ir3_block *block)
{
unsigned i;
 
for (i = 0; i < block->noutputs; i++) {
if (block->outputs[i]) {
struct ir3_instruction *out =
instr_cp(block->outputs[i], NULL);
 
block->outputs[i] = out;
}
}
}
 
void ir3_block_cp(struct ir3_block *block)
{
ir3_clear_mark(block->shader);
block_cp(block);
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/ir3/ir3_depth.c
0,0 → 1,169
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "util/u_math.h"
 
#include "ir3.h"
 
/*
* Instruction Depth:
*
* Calculates weighted instruction depth, ie. the sum of # of needed
* instructions plus delay slots back to original input (ie INPUT or
* CONST). That is to say, an instructions depth is:
*
* depth(instr) {
* d = 0;
* // for each src register:
* foreach (src in instr->regs[1..n])
* d = max(d, delayslots(src->instr, n) + depth(src->instr));
* return d + 1;
* }
*
* After an instruction's depth is calculated, it is inserted into the
* blocks depth sorted list, which is used by the scheduling pass.
*/
 
/* calculate required # of delay slots between the instruction that
* assigns a value and the one that consumes
*/
int ir3_delayslots(struct ir3_instruction *assigner,
struct ir3_instruction *consumer, unsigned n)
{
/* worst case is cat1-3 (alu) -> cat4/5 needing 6 cycles, normal
* alu -> alu needs 3 cycles, cat4 -> alu and texture fetch
* handled with sync bits
*/
 
if (is_meta(assigner))
return 0;
 
if (writes_addr(assigner))
return 6;
 
/* handled via sync flags: */
if (is_sfu(assigner) || is_tex(assigner) || is_mem(assigner))
return 0;
 
/* assigner must be alu: */
if (is_flow(consumer) || is_sfu(consumer) || is_tex(consumer) ||
is_mem(consumer)) {
return 6;
} else if ((consumer->category == 3) &&
(is_mad(consumer->opc) || is_madsh(consumer->opc)) &&
(n == 2)) {
/* special case, 3rd src to cat3 not required on first cycle */
return 1;
} else {
return 3;
}
}
 
static void insert_by_depth(struct ir3_instruction *instr)
{
struct ir3_block *block = instr->block;
struct ir3_instruction *n = block->head;
struct ir3_instruction *p = NULL;
 
while (n && (n != instr) && (n->depth > instr->depth)) {
p = n;
n = n->next;
}
 
instr->next = n;
if (p)
p->next = instr;
else
block->head = instr;
}
 
static void ir3_instr_depth(struct ir3_instruction *instr)
{
struct ir3_instruction *src;
 
/* if we've already visited this instruction, bail now: */
if (ir3_instr_check_mark(instr))
return;
 
instr->depth = 0;
 
foreach_ssa_src_n(src, i, instr) {
unsigned sd;
 
/* visit child to compute it's depth: */
ir3_instr_depth(src);
 
sd = ir3_delayslots(src, instr, i) + src->depth;
 
instr->depth = MAX2(instr->depth, sd);
}
 
/* meta-instructions don't add cycles, other than PHI.. which
* might translate to a real instruction..
*
* well, not entirely true, fan-in/out, etc might need to need
* to generate some extra mov's in edge cases, etc.. probably
* we might want to do depth calculation considering the worst
* case for these??
*/
if (!is_meta(instr))
instr->depth++;
 
insert_by_depth(instr);
}
 
void ir3_block_depth(struct ir3_block *block)
{
unsigned i;
 
block->head = NULL;
 
ir3_clear_mark(block->shader);
for (i = 0; i < block->noutputs; i++)
if (block->outputs[i])
ir3_instr_depth(block->outputs[i]);
 
/* mark un-used instructions: */
for (i = 0; i < block->shader->instrs_count; i++) {
struct ir3_instruction *instr = block->shader->instrs[i];
 
/* just consider instructions within this block: */
if (instr->block != block)
continue;
 
if (!ir3_instr_check_mark(instr))
instr->depth = DEPTH_UNUSED;
}
 
/* cleanup unused inputs: */
for (i = 0; i < block->ninputs; i++) {
struct ir3_instruction *in = block->inputs[i];
if (in && (in->depth == DEPTH_UNUSED))
block->inputs[i] = NULL;
}
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/ir3/ir3_dump.c
0,0 → 1,456
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include <stdarg.h>
 
#include "ir3.h"
 
#define PTRID(x) ((unsigned long)(x))
 
struct ir3_dump_ctx {
FILE *f;
bool verbose;
};
 
static void dump_instr_name(struct ir3_dump_ctx *ctx,
struct ir3_instruction *instr)
{
/* for debugging: */
if (ctx->verbose) {
#ifdef DEBUG
fprintf(ctx->f, "%04u:", instr->serialno);
#endif
fprintf(ctx->f, "%03u: ", instr->depth);
}
 
if (instr->flags & IR3_INSTR_SY)
fprintf(ctx->f, "(sy)");
if (instr->flags & IR3_INSTR_SS)
fprintf(ctx->f, "(ss)");
 
if (is_meta(instr)) {
switch(instr->opc) {
case OPC_META_PHI:
fprintf(ctx->f, "&#934;");
break;
default:
/* shouldn't hit here.. just for debugging: */
switch (instr->opc) {
case OPC_META_INPUT: fprintf(ctx->f, "_meta:in"); break;
case OPC_META_OUTPUT: fprintf(ctx->f, "_meta:out"); break;
case OPC_META_FO: fprintf(ctx->f, "_meta:fo"); break;
case OPC_META_FI: fprintf(ctx->f, "_meta:fi"); break;
case OPC_META_FLOW: fprintf(ctx->f, "_meta:flow"); break;
 
default: fprintf(ctx->f, "_meta:%d", instr->opc); break;
}
break;
}
} else if (instr->category == 1) {
static const char *type[] = {
[TYPE_F16] = "f16",
[TYPE_F32] = "f32",
[TYPE_U16] = "u16",
[TYPE_U32] = "u32",
[TYPE_S16] = "s16",
[TYPE_S32] = "s32",
[TYPE_U8] = "u8",
[TYPE_S8] = "s8",
};
if (instr->cat1.src_type == instr->cat1.dst_type)
fprintf(ctx->f, "mov");
else
fprintf(ctx->f, "cov");
fprintf(ctx->f, ".%s%s", type[instr->cat1.src_type], type[instr->cat1.dst_type]);
} else {
fprintf(ctx->f, "%s", ir3_instr_name(instr));
if (instr->flags & IR3_INSTR_3D)
fprintf(ctx->f, ".3d");
if (instr->flags & IR3_INSTR_A)
fprintf(ctx->f, ".a");
if (instr->flags & IR3_INSTR_O)
fprintf(ctx->f, ".o");
if (instr->flags & IR3_INSTR_P)
fprintf(ctx->f, ".p");
if (instr->flags & IR3_INSTR_S)
fprintf(ctx->f, ".s");
if (instr->flags & IR3_INSTR_S2EN)
fprintf(ctx->f, ".s2en");
}
}
 
static void dump_reg_name(struct ir3_dump_ctx *ctx,
struct ir3_register *reg, bool followssa)
{
if ((reg->flags & (IR3_REG_FABS | IR3_REG_SABS)) &&
(reg->flags & (IR3_REG_FNEG | IR3_REG_SNEG | IR3_REG_BNOT)))
fprintf(ctx->f, "(absneg)");
else if (reg->flags & (IR3_REG_FNEG | IR3_REG_SNEG | IR3_REG_BNOT))
fprintf(ctx->f, "(neg)");
else if (reg->flags & (IR3_REG_FABS | IR3_REG_SABS))
fprintf(ctx->f, "(abs)");
 
if (reg->flags & IR3_REG_IMMED) {
fprintf(ctx->f, "imm[%f,%d,0x%x]", reg->fim_val, reg->iim_val, reg->iim_val);
} else if (reg->flags & IR3_REG_SSA) {
if (ctx->verbose) {
fprintf(ctx->f, "_");
if (followssa) {
fprintf(ctx->f, "[");
dump_instr_name(ctx, reg->instr);
fprintf(ctx->f, "]");
}
}
} else if (reg->flags & IR3_REG_RELATIV) {
if (reg->flags & IR3_REG_HALF)
fprintf(ctx->f, "h");
if (reg->flags & IR3_REG_CONST)
fprintf(ctx->f, "c<a0.x + %u>", reg->num);
else
fprintf(ctx->f, "\x1b[0;31mr<a0.x + %u>\x1b[0m (%u)", reg->num, reg->size);
} else {
if (reg->flags & IR3_REG_HALF)
fprintf(ctx->f, "h");
if (reg->flags & IR3_REG_CONST)
fprintf(ctx->f, "c%u.%c", reg_num(reg), "xyzw"[reg_comp(reg)]);
else
fprintf(ctx->f, "\x1b[0;31mr%u.%c\x1b[0m", reg_num(reg), "xyzw"[reg_comp(reg)]);
}
}
 
static void ir3_instr_dump(struct ir3_dump_ctx *ctx,
struct ir3_instruction *instr);
static void ir3_block_dump(struct ir3_dump_ctx *ctx,
struct ir3_block *block, const char *name);
 
static void dump_instr(struct ir3_dump_ctx *ctx,
struct ir3_instruction *instr)
{
/* if we've already visited this instruction, bail now: */
if (ir3_instr_check_mark(instr))
return;
 
/* some meta-instructions need to be handled specially: */
if (is_meta(instr)) {
if ((instr->opc == OPC_META_FO) ||
(instr->opc == OPC_META_FI)) {
struct ir3_instruction *src;
foreach_ssa_src(src, instr)
dump_instr(ctx, src);
} else if (instr->opc == OPC_META_FLOW) {
struct ir3_register *reg = instr->regs[1];
ir3_block_dump(ctx, instr->flow.if_block, "if");
if (instr->flow.else_block)
ir3_block_dump(ctx, instr->flow.else_block, "else");
if (reg->flags & IR3_REG_SSA)
dump_instr(ctx, reg->instr);
} else if (instr->opc == OPC_META_PHI) {
/* treat like a normal instruction: */
ir3_instr_dump(ctx, instr);
}
} else {
ir3_instr_dump(ctx, instr);
}
}
 
/* arrarraggh! if link is to something outside of the current block, we
* need to defer emitting the link until the end of the block, since the
* edge triggers pre-creation of the node it links to inside the cluster,
* even though it is meant to be outside..
*/
static struct {
char buf[40960];
unsigned n;
} edge_buf;
 
/* helper to print or defer: */
static void printdef(struct ir3_dump_ctx *ctx,
bool defer, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
if (defer) {
unsigned n = edge_buf.n;
n += vsnprintf(&edge_buf.buf[n], sizeof(edge_buf.buf) - n,
fmt, ap);
edge_buf.n = n;
} else {
vfprintf(ctx->f, fmt, ap);
}
va_end(ap);
}
 
static void dump_link2(struct ir3_dump_ctx *ctx,
struct ir3_instruction *instr, const char *target, bool defer)
{
/* some meta-instructions need to be handled specially: */
if (is_meta(instr)) {
if (instr->opc == OPC_META_INPUT) {
printdef(ctx, defer, "input%lx:<in%u>:w -> %s",
PTRID(instr->inout.block),
instr->regs[0]->num, target);
} else if (instr->opc == OPC_META_FO) {
struct ir3_register *reg = instr->regs[1];
dump_link2(ctx, reg->instr, target, defer);
printdef(ctx, defer, "[label=\".%c\"]",
"xyzw"[instr->fo.off & 0x3]);
} else if (instr->opc == OPC_META_FI) {
struct ir3_instruction *src;
 
foreach_ssa_src_n(src, i, instr) {
dump_link2(ctx, src, target, defer);
printdef(ctx, defer, "[label=\".%c\"]",
"xyzw"[i & 0x3]);
}
} else if (instr->opc == OPC_META_OUTPUT) {
printdef(ctx, defer, "output%lx:<out%u>:w -> %s",
PTRID(instr->inout.block),
instr->regs[0]->num, target);
} else if (instr->opc == OPC_META_PHI) {
/* treat like a normal instruction: */
printdef(ctx, defer, "instr%lx:<dst0> -> %s", PTRID(instr), target);
}
} else {
printdef(ctx, defer, "instr%lx:<dst0> -> %s", PTRID(instr), target);
}
}
 
static void dump_link(struct ir3_dump_ctx *ctx,
struct ir3_instruction *instr,
struct ir3_block *block, const char *target)
{
bool defer = instr->block != block;
dump_link2(ctx, instr, target, defer);
printdef(ctx, defer, "\n");
}
 
static struct ir3_register *follow_flow(struct ir3_register *reg)
{
if (reg->flags & IR3_REG_SSA) {
struct ir3_instruction *instr = reg->instr;
/* go with the flow.. */
if (is_meta(instr) && (instr->opc == OPC_META_FLOW))
return instr->regs[1];
}
return reg;
}
 
static void ir3_instr_dump(struct ir3_dump_ctx *ctx,
struct ir3_instruction *instr)
{
struct ir3_register *src;
 
fprintf(ctx->f, "instr%lx [shape=record,style=filled,fillcolor=lightgrey,label=\"{",
PTRID(instr));
dump_instr_name(ctx, instr);
 
/* destination register: */
fprintf(ctx->f, "|<dst0>");
 
/* source register(s): */
foreach_src_n(src, i, instr) {
struct ir3_register *reg = follow_flow(src);
 
fprintf(ctx->f, "|");
 
if (reg->flags & IR3_REG_SSA)
fprintf(ctx->f, "<src%u> ", i);
 
dump_reg_name(ctx, reg, true);
}
 
fprintf(ctx->f, "}\"];\n");
 
/* and recursively dump dependent instructions: */
foreach_src_n(src, i, instr) {
struct ir3_register *reg = follow_flow(src);
char target[32]; /* link target */
 
if (!(reg->flags & IR3_REG_SSA))
continue;
 
snprintf(target, sizeof(target), "instr%lx:<src%u>",
PTRID(instr), i);
 
dump_instr(ctx, reg->instr);
dump_link(ctx, reg->instr, instr->block, target);
}
}
 
static void ir3_block_dump(struct ir3_dump_ctx *ctx,
struct ir3_block *block, const char *name)
{
unsigned i, n;
 
n = edge_buf.n;
 
fprintf(ctx->f, "subgraph cluster%lx {\n", PTRID(block));
fprintf(ctx->f, "label=\"%s\";\n", name);
 
/* draw inputs: */
fprintf(ctx->f, "input%lx [shape=record,label=\"inputs", PTRID(block));
for (i = 0; i < block->ninputs; i++)
if (block->inputs[i])
fprintf(ctx->f, "|<in%u> i%u.%c", i, (i >> 2), "xyzw"[i & 0x3]);
fprintf(ctx->f, "\"];\n");
 
/* draw instruction graph: */
for (i = 0; i < block->noutputs; i++)
if (block->outputs[i])
dump_instr(ctx, block->outputs[i]);
 
/* draw outputs: */
fprintf(ctx->f, "output%lx [shape=record,label=\"outputs", PTRID(block));
for (i = 0; i < block->noutputs; i++)
fprintf(ctx->f, "|<out%u> o%u.%c", i, (i >> 2), "xyzw"[i & 0x3]);
fprintf(ctx->f, "\"];\n");
 
/* and links to outputs: */
for (i = 0; i < block->noutputs; i++) {
char target[32]; /* link target */
 
/* NOTE: there could be outputs that are never assigned,
* so skip them
*/
if (!block->outputs[i])
continue;
 
snprintf(target, sizeof(target), "output%lx:<out%u>:e",
PTRID(block), i);
 
dump_link(ctx, block->outputs[i], block, target);
}
 
fprintf(ctx->f, "}\n");
 
/* and links to inputs: */
if (block->parent) {
for (i = 0; i < block->ninputs; i++) {
char target[32]; /* link target */
 
if (!block->inputs[i])
continue;
 
dump_instr(ctx, block->inputs[i]);
 
snprintf(target, sizeof(target), "input%lx:<in%u>:e",
PTRID(block), i);
 
dump_link(ctx, block->inputs[i], block, target);
}
}
 
/* dump deferred edges: */
if (edge_buf.n > n) {
fprintf(ctx->f, "%*s", edge_buf.n - n, &edge_buf.buf[n]);
edge_buf.n = n;
}
}
 
void ir3_dump(struct ir3 *shader, const char *name,
struct ir3_block *block /* XXX maybe 'block' ptr should move to ir3? */,
FILE *f)
{
struct ir3_dump_ctx ctx = {
.f = f,
};
ir3_clear_mark(shader);
fprintf(ctx.f, "digraph G {\n");
fprintf(ctx.f, "rankdir=RL;\n");
fprintf(ctx.f, "nodesep=0.25;\n");
fprintf(ctx.f, "ranksep=1.5;\n");
ir3_block_dump(&ctx, block, name);
fprintf(ctx.f, "}\n");
}
 
/*
* For Debugging:
*/
 
void
ir3_dump_instr_single(struct ir3_instruction *instr)
{
struct ir3_dump_ctx ctx = {
.f = stdout,
.verbose = true,
};
unsigned i;
 
dump_instr_name(&ctx, instr);
for (i = 0; i < instr->regs_count; i++) {
struct ir3_register *reg = instr->regs[i];
printf(i ? ", " : " ");
dump_reg_name(&ctx, reg, !!i);
}
 
if (instr->address) {
fprintf(ctx.f, ", address=_");
fprintf(ctx.f, "[");
dump_instr_name(&ctx, instr->address);
fprintf(ctx.f, "]");
}
 
if (instr->fanin) {
fprintf(ctx.f, ", fanin=_");
fprintf(ctx.f, "[");
dump_instr_name(&ctx, instr->fanin);
fprintf(ctx.f, "]");
}
 
if (is_meta(instr)) {
if (instr->opc == OPC_META_FO) {
printf(", off=%d", instr->fo.off);
} else if ((instr->opc == OPC_META_FI) && instr->fi.aid) {
printf(", aid=%d", instr->fi.aid);
}
}
 
printf("\n");
}
 
void
ir3_dump_instr_list(struct ir3_instruction *instr)
{
struct ir3_block *block = instr->block;
unsigned n = 0;
 
while (instr) {
ir3_dump_instr_single(instr);
if (!is_meta(instr))
n++;
instr = instr->next;
}
printf("%u instructions\n", n);
 
for (n = 0; n < block->noutputs; n++) {
if (!block->outputs[n])
continue;
printf("out%d: ", n);
ir3_dump_instr_single(block->outputs[n]);
}
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/ir3/ir3_flatten.c
0,0 → 1,152
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include <stdarg.h>
 
#include "ir3.h"
 
/*
* Flatten: flatten out legs of if/else, etc
*
* TODO probably should use some heuristic to decide to not flatten
* if one side of the other is too large / deeply nested / whatever?
*/
 
struct ir3_flatten_ctx {
struct ir3_block *block;
unsigned cnt;
};
 
static struct ir3_register *unwrap(struct ir3_register *reg)
{
 
if (reg->flags & IR3_REG_SSA) {
struct ir3_instruction *instr = reg->instr;
if (is_meta(instr)) {
switch (instr->opc) {
case OPC_META_OUTPUT:
case OPC_META_FLOW:
if (instr->regs_count > 1)
return instr->regs[1];
return NULL;
default:
break;
}
}
}
return reg;
}
 
static void ir3_instr_flatten(struct ir3_flatten_ctx *ctx,
struct ir3_instruction *instr)
{
struct ir3_instruction *src;
 
/* if we've already visited this instruction, bail now: */
if (ir3_instr_check_mark(instr))
return;
 
instr->block = ctx->block;
 
/* TODO: maybe some threshold to decide whether to
* flatten or not??
*/
if (is_meta(instr)) {
if (instr->opc == OPC_META_PHI) {
struct ir3_register *cond, *t, *f;
 
cond = unwrap(instr->regs[1]);
t = unwrap(instr->regs[2]); /* true val */
f = unwrap(instr->regs[3]); /* false val */
 
/* must have cond, but t or f may be null if only written
* one one side of the if/else (in which case we can just
* convert the PHI to a simple move).
*/
assert(cond);
assert(t || f);
 
if (t && f) {
/* convert the PHI instruction to sel.{b16,b32} */
instr->category = 3;
 
/* instruction type based on dst size: */
if (instr->regs[0]->flags & IR3_REG_HALF)
instr->opc = OPC_SEL_B16;
else
instr->opc = OPC_SEL_B32;
 
instr->regs[1] = t;
instr->regs[2] = cond;
instr->regs[3] = f;
} else {
/* convert to simple mov: */
instr->category = 1;
instr->cat1.dst_type = TYPE_F32;
instr->cat1.src_type = TYPE_F32;
instr->regs_count = 2;
instr->regs[1] = t ? t : f;
}
 
ctx->cnt++;
} else if ((instr->opc == OPC_META_INPUT) &&
(instr->regs_count == 2)) {
type_t ftype;
 
if (instr->regs[0]->flags & IR3_REG_HALF)
ftype = TYPE_F16;
else
ftype = TYPE_F32;
 
/* convert meta:input to mov: */
instr->category = 1;
instr->cat1.src_type = ftype;
instr->cat1.dst_type = ftype;
}
}
 
/* recursively visit children: */
foreach_ssa_src(src, instr)
ir3_instr_flatten(ctx, src);
}
 
/* return >= 0 is # of phi's flattened, < 0 is error */
int ir3_block_flatten(struct ir3_block *block)
{
struct ir3_flatten_ctx ctx = {
.block = block,
};
unsigned i;
 
ir3_clear_mark(block->shader);
for(i = 0; i < block->noutputs; i++)
if (block->outputs[i])
ir3_instr_flatten(&ctx, block->outputs[i]);
 
return ctx.cnt;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/ir3/ir3_group.c
0,0 → 1,266
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "freedreno_util.h"
 
#include "ir3.h"
 
/*
* Find/group instruction neighbors:
*/
 
/* stop condition for iteration: */
static bool check_stop(struct ir3_instruction *instr)
{
if (ir3_instr_check_mark(instr))
return true;
 
/* stay within the block.. don't try to operate across
* basic block boundaries or we'll have problems when
* dealing with multiple basic blocks:
*/
if (is_meta(instr) && (instr->opc == OPC_META_INPUT))
return true;
 
return false;
}
 
static struct ir3_instruction * create_mov(struct ir3_instruction *instr)
{
struct ir3_instruction *mov;
 
mov = ir3_instr_create(instr->block, 1, 0);
mov->cat1.src_type = TYPE_F32;
mov->cat1.dst_type = TYPE_F32;
ir3_reg_create(mov, 0, 0); /* dst */
ir3_reg_create(mov, 0, IR3_REG_SSA)->instr = instr;
 
return mov;
}
 
/* bleh.. we need to do the same group_n() thing for both inputs/outputs
* (where we have a simple instr[] array), and fanin nodes (where we have
* an extra indirection via reg->instr).
*/
struct group_ops {
struct ir3_instruction *(*get)(void *arr, int idx);
void (*insert_mov)(void *arr, int idx, struct ir3_instruction *instr);
};
 
static struct ir3_instruction *arr_get(void *arr, int idx)
{
return ((struct ir3_instruction **)arr)[idx];
}
static void arr_insert_mov_out(void *arr, int idx, struct ir3_instruction *instr)
{
((struct ir3_instruction **)arr)[idx] = create_mov(instr);
}
static void arr_insert_mov_in(void *arr, int idx, struct ir3_instruction *instr)
{
/* so, we can't insert a mov in front of a meta:in.. and the downstream
* instruction already has a pointer to 'instr'. So we cheat a bit and
* morph the meta:in instruction into a mov and insert a new meta:in
* in front.
*/
struct ir3_instruction *in;
 
debug_assert(instr->regs_count == 1);
 
in = ir3_instr_create(instr->block, -1, OPC_META_INPUT);
in->inout.block = instr->block;
ir3_reg_create(in, instr->regs[0]->num, 0);
 
/* create src reg for meta:in and fixup to now be a mov: */
ir3_reg_create(instr, 0, IR3_REG_SSA)->instr = in;
instr->category = 1;
instr->opc = 0;
instr->cat1.src_type = TYPE_F32;
instr->cat1.dst_type = TYPE_F32;
 
((struct ir3_instruction **)arr)[idx] = in;
}
static struct group_ops arr_ops_out = { arr_get, arr_insert_mov_out };
static struct group_ops arr_ops_in = { arr_get, arr_insert_mov_in };
 
static struct ir3_instruction *instr_get(void *arr, int idx)
{
return ssa(((struct ir3_instruction *)arr)->regs[idx+1]);
}
static void instr_insert_mov(void *arr, int idx, struct ir3_instruction *instr)
{
((struct ir3_instruction *)arr)->regs[idx+1]->instr = create_mov(instr);
}
static struct group_ops instr_ops = { instr_get, instr_insert_mov };
 
 
static void group_n(struct group_ops *ops, void *arr, unsigned n)
{
unsigned i, j;
 
/* first pass, figure out what has conflicts and needs a mov
* inserted. Do this up front, before starting to setup
* left/right neighbor pointers. Trying to do it in a single
* pass could result in a situation where we can't even setup
* the mov's right neighbor ptr if the next instr also needs
* a mov.
*/
restart:
for (i = 0; i < n; i++) {
struct ir3_instruction *instr = ops->get(arr, i);
if (instr) {
struct ir3_instruction *left = (i > 0) ? ops->get(arr, i - 1) : NULL;
struct ir3_instruction *right = (i < (n-1)) ? ops->get(arr, i + 1) : NULL;
bool conflict;
 
/* check for left/right neighbor conflicts: */
conflict = conflicts(instr->cp.left, left) ||
conflicts(instr->cp.right, right);
 
/* we also can't have an instr twice in the group: */
for (j = i + 1; (j < n) && !conflict; j++)
if (ops->get(arr, j) == instr)
conflict = true;
 
if (conflict) {
ops->insert_mov(arr, i, instr);
/* inserting the mov may have caused a conflict
* against the previous:
*/
goto restart;
}
}
}
 
/* second pass, now that we've inserted mov's, fixup left/right
* neighbors. This is guaranteed to succeed, since by definition
* the newly inserted mov's cannot conflict with anything.
*/
for (i = 0; i < n; i++) {
struct ir3_instruction *instr = ops->get(arr, i);
if (instr) {
struct ir3_instruction *left = (i > 0) ? ops->get(arr, i - 1) : NULL;
struct ir3_instruction *right = (i < (n-1)) ? ops->get(arr, i + 1) : NULL;
 
debug_assert(!conflicts(instr->cp.left, left));
if (left) {
instr->cp.left_cnt++;
instr->cp.left = left;
}
 
debug_assert(!conflicts(instr->cp.right, right));
if (right) {
instr->cp.right_cnt++;
instr->cp.right = right;
}
}
}
}
 
static void instr_find_neighbors(struct ir3_instruction *instr)
{
struct ir3_instruction *src;
 
if (check_stop(instr))
return;
 
if (is_meta(instr) && (instr->opc == OPC_META_FI))
group_n(&instr_ops, instr, instr->regs_count - 1);
 
foreach_ssa_src(src, instr)
instr_find_neighbors(src);
}
 
/* a bit of sadness.. we can't have "holes" in inputs from PoV of
* register assignment, they still need to be grouped together. So
* we need to insert dummy/padding instruction for grouping, and
* then take it back out again before anyone notices.
*/
static void pad_and_group_input(struct ir3_instruction **input, unsigned n)
{
int i, mask = 0;
struct ir3_block *block = NULL;
 
for (i = n - 1; i >= 0; i--) {
struct ir3_instruction *instr = input[i];
if (instr) {
block = instr->block;
} else if (block) {
instr = ir3_instr_create(block, 0, OPC_NOP);
ir3_reg_create(instr, 0, IR3_REG_SSA); /* dst */
input[i] = instr;
mask |= (1 << i);
}
}
 
group_n(&arr_ops_in, input, n);
 
for (i = 0; i < n; i++) {
if (mask & (1 << i))
input[i] = NULL;
}
}
 
static void block_find_neighbors(struct ir3_block *block)
{
unsigned i;
 
for (i = 0; i < block->noutputs; i++) {
if (block->outputs[i]) {
struct ir3_instruction *instr = block->outputs[i];
instr_find_neighbors(instr);
}
}
 
/* shader inputs/outputs themselves must be contiguous as well:
*/
if (!block->parent) {
/* NOTE: group inputs first, since we only insert mov's
* *before* the conflicted instr (and that would go badly
* for inputs). By doing inputs first, we should never
* have a conflict on inputs.. pushing any conflict to
* resolve to the outputs, for stuff like:
*
* MOV OUT[n], IN[m].wzyx
*
* NOTE: we assume here inputs/outputs are grouped in vec4.
* This logic won't quite cut it if we don't align smaller
* on vec4 boundaries
*/
for (i = 0; i < block->ninputs; i += 4)
pad_and_group_input(&block->inputs[i], 4);
for (i = 0; i < block->noutputs; i += 4)
group_n(&arr_ops_out, &block->outputs[i], 4);
 
}
}
 
void ir3_block_group(struct ir3_block *block)
{
ir3_clear_mark(block->shader);
block_find_neighbors(block);
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/ir3/ir3_legalize.c
0,0 → 1,248
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "pipe/p_shader_tokens.h"
#include "util/u_math.h"
 
#include "freedreno_util.h"
 
#include "ir3.h"
 
/*
* Legalize:
*
* We currently require that scheduling ensures that we have enough nop's
* in all the right places. The legalize step mostly handles fixing up
* instruction flags ((ss)/(sy)/(ei)), and collapses sequences of nop's
* into fewer nop's w/ rpt flag.
*/
 
struct ir3_legalize_ctx {
struct ir3_block *block;
bool has_samp;
int max_bary;
};
 
static void legalize(struct ir3_legalize_ctx *ctx)
{
struct ir3_block *block = ctx->block;
struct ir3_instruction *n;
struct ir3 *shader = block->shader;
struct ir3_instruction *end =
ir3_instr_create(block, 0, OPC_END);
struct ir3_instruction *last_input = NULL;
struct ir3_instruction *last_rel = NULL;
regmask_t needs_ss_war; /* write after read */
regmask_t needs_ss;
regmask_t needs_sy;
 
regmask_init(&needs_ss_war);
regmask_init(&needs_ss);
regmask_init(&needs_sy);
 
shader->instrs_count = 0;
 
for (n = block->head; n; n = n->next) {
struct ir3_register *reg;
unsigned i;
 
if (is_meta(n))
continue;
 
if (is_input(n)) {
struct ir3_register *inloc = n->regs[1];
assert(inloc->flags & IR3_REG_IMMED);
ctx->max_bary = MAX2(ctx->max_bary, inloc->iim_val);
}
 
/* NOTE: consider dst register too.. it could happen that
* texture sample instruction (for example) writes some
* components which are unused. A subsequent instruction
* that writes the same register can race w/ the sam instr
* resulting in undefined results:
*/
for (i = 0; i < n->regs_count; i++) {
reg = n->regs[i];
 
if (reg_gpr(reg)) {
 
/* TODO: we probably only need (ss) for alu
* instr consuming sfu result.. need to make
* some tests for both this and (sy)..
*/
if (regmask_get(&needs_ss, reg)) {
n->flags |= IR3_INSTR_SS;
regmask_init(&needs_ss);
}
 
if (regmask_get(&needs_sy, reg)) {
n->flags |= IR3_INSTR_SY;
regmask_init(&needs_sy);
}
}
 
/* TODO: is it valid to have address reg loaded from a
* relative src (ie. mova a0, c<a0.x+4>)? If so, the
* last_rel check below should be moved ahead of this:
*/
if (reg->flags & IR3_REG_RELATIV)
last_rel = n;
}
 
if (n->regs_count > 0) {
reg = n->regs[0];
if (regmask_get(&needs_ss_war, reg)) {
n->flags |= IR3_INSTR_SS;
regmask_init(&needs_ss_war); // ??? I assume?
}
 
if (last_rel && (reg->num == regid(REG_A0, 0))) {
last_rel->flags |= IR3_INSTR_UL;
last_rel = NULL;
}
}
 
/* cat5+ does not have an (ss) bit, if needed we need to
* insert a nop to carry the sync flag. Would be kinda
* clever if we were aware of this during scheduling, but
* this should be a pretty rare case:
*/
if ((n->flags & IR3_INSTR_SS) && (n->category >= 5)) {
struct ir3_instruction *nop;
nop = ir3_instr_create(block, 0, OPC_NOP);
nop->flags |= IR3_INSTR_SS;
n->flags &= ~IR3_INSTR_SS;
}
 
/* need to be able to set (ss) on first instruction: */
if ((shader->instrs_count == 0) && (n->category >= 5))
ir3_instr_create(block, 0, OPC_NOP);
 
if (is_nop(n) && shader->instrs_count) {
struct ir3_instruction *last =
shader->instrs[shader->instrs_count-1];
if (is_nop(last) && (last->repeat < 5)) {
last->repeat++;
last->flags |= n->flags;
continue;
}
}
 
shader->instrs[shader->instrs_count++] = n;
 
if (is_sfu(n))
regmask_set(&needs_ss, n->regs[0]);
 
if (is_tex(n)) {
/* this ends up being the # of samp instructions.. but that
* is ok, everything else only cares whether it is zero or
* not. We do this here, rather than when we encounter a
* SAMP decl, because (especially in binning pass shader)
* the samp instruction(s) could get eliminated if the
* result is not used.
*/
ctx->has_samp = true;
regmask_set(&needs_sy, n->regs[0]);
} else if (is_mem(n)) {
regmask_set(&needs_sy, n->regs[0]);
}
 
/* both tex/sfu appear to not always immediately consume
* their src register(s):
*/
if (is_tex(n) || is_sfu(n) || is_mem(n)) {
foreach_src(reg, n) {
if (reg_gpr(reg))
regmask_set(&needs_ss_war, reg);
}
}
 
if (is_input(n))
last_input = n;
}
 
if (last_input) {
/* special hack.. if using ldlv to bypass interpolation,
* we need to insert a dummy bary.f on which we can set
* the (ei) flag:
*/
if (is_mem(last_input) && (last_input->opc == OPC_LDLV)) {
int i, cnt;
 
/* note that ir3_instr_create() inserts into
* shader->instrs[] and increments the count..
* so we need to bump up the cnt initially (to
* avoid it clobbering the last real instr) and
* restore it after.
*/
cnt = ++shader->instrs_count;
 
/* inserting instructions would be a bit nicer if list.. */
for (i = cnt - 2; i >= 0; i--) {
if (shader->instrs[i] == last_input) {
 
/* (ss)bary.f (ei)r63.x, 0, r0.x */
last_input = ir3_instr_create(block, 2, OPC_BARY_F);
last_input->flags |= IR3_INSTR_SS;
ir3_reg_create(last_input, regid(63, 0), 0);
ir3_reg_create(last_input, 0, IR3_REG_IMMED)->iim_val = 0;
ir3_reg_create(last_input, regid(0, 0), 0);
 
shader->instrs[i + 1] = last_input;
 
break;
}
shader->instrs[i + 1] = shader->instrs[i];
}
 
shader->instrs_count = cnt;
}
last_input->regs[0]->flags |= IR3_REG_EI;
}
 
if (last_rel)
last_rel->flags |= IR3_INSTR_UL;
 
shader->instrs[shader->instrs_count++] = end;
 
shader->instrs[0]->flags |= IR3_INSTR_SS | IR3_INSTR_SY;
}
 
void ir3_block_legalize(struct ir3_block *block,
bool *has_samp, int *max_bary)
{
struct ir3_legalize_ctx ctx = {
.block = block,
.max_bary = -1,
};
 
legalize(&ctx);
 
*has_samp = ctx.has_samp;
*max_bary = ctx.max_bary;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/ir3/ir3_nir.h
0,0 → 1,36
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2015 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef IR3_NIR_H_
#define IR3_NIR_H_
 
#include "glsl/nir/nir.h"
 
bool ir3_nir_lower_if_else(nir_shader *shader);
 
#endif /* IR3_NIR_H_ */
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/ir3/ir3_nir_lower_if_else.c
0,0 → 1,337
/*
* Copyright © 2014 Intel Corporation
* Copyright © 2015 Red Hat
*
* 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.
*
* Authors:
* Jason Ekstrand (jason@jlekstrand.net)
* Rob Clark (robclark@freedesktop.org)
*
*/
 
#include "ir3_nir.h"
#include "glsl/nir/nir_builder.h"
 
/* Based on nir_opt_peephole_select, and hacked up to more aggressively
* flatten anything that can be flattened
*
* This *might* be something that other drivers could use. On the other
* hand, I think most other hw has predicated instructions or similar
* to select which side of if/else writes back result (and therefore
* not having to assign unique registers to both sides of the if/else.
* (And hopefully those drivers don't also have crazy scheduling reqs
* and can more easily do this in their backend.)
*
* TODO eventually when we have proper flow control in the backend:
*
* + Probably weight differently normal ALUs vs SFUs (cos/rcp/exp)
* since executing extra SFUs for the branch-not-taken path will
* generally be much more expensive.
*
* Possibly what constitutes an ALU vs SFU differs between hw
* backends.. but that seems doubtful.
*
* + Account for texture fetch and memory accesses (incl UBOs)
* since these will be more expensive..
*
* + When if-condition is const (or uniform) or we have some way
* to know that all threads in the warp take the same branch
* then we should prefer to not flatten the if/else..
*/
 
struct lower_state {
nir_builder b;
void *mem_ctx;
bool progress;
};
 
static bool
valid_dest(nir_block *block, nir_dest *dest)
{
/* It must be SSA */
if (!dest->is_ssa)
return false;
 
/* We only lower blocks that do not contain other blocks
* (so this is run iteratively in a loop). Therefore if
* we get this far, it should not have any if_uses:
*/
assert(list_empty(&dest->ssa.if_uses));
 
/* The only uses of this definition must be phi's in the
* successor or in the current block
*/
nir_foreach_use(&dest->ssa, use) {
nir_instr *dest_instr = use->parent_instr;
if (dest_instr->block == block)
continue;
if ((dest_instr->type == nir_instr_type_phi) &&
(dest_instr->block == block->successors[0]))
continue;
return false;
}
 
return true;
}
 
static bool
block_check_for_allowed_instrs(nir_block *block)
{
nir_foreach_instr(block, instr) {
switch (instr->type) {
case nir_instr_type_intrinsic: {
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
const nir_intrinsic_info *info =
&nir_intrinsic_infos[intr->intrinsic];
 
switch (intr->intrinsic) {
case nir_intrinsic_discard_if:
/* to simplify things, we want discard_if src in ssa: */
if (!intr->src[0].is_ssa)
return false;
/* fallthrough */
case nir_intrinsic_discard:
/* discard/discard_if can be reordered, but only
* with some special care
*/
break;
case nir_intrinsic_store_output:
/* TODO technically, if both if and else store
* the same output, we can hoist that out to
* the end of the block w/ a phi..
* In practice, the tgsi shaders we already get
* do this for us, so I think we don't need to
*/
default:
if (!(info->flags & NIR_INTRINSIC_CAN_REORDER))
return false;
}
 
break;
}
 
case nir_instr_type_tex: {
nir_tex_instr *tex = nir_instr_as_tex(instr);
if (!valid_dest(block, &tex->dest))
return false;
break;
}
case nir_instr_type_phi: {
nir_phi_instr *phi = nir_instr_as_phi(instr);
if (!valid_dest(block, &phi->dest))
return false;
break;
}
case nir_instr_type_alu: {
nir_alu_instr *alu = nir_instr_as_alu(instr);
if (!valid_dest(block, &alu->dest.dest))
return false;
break;
}
 
case nir_instr_type_load_const:
case nir_instr_type_ssa_undef:
break; /* always ssa dest */
 
default:
return false;
}
}
 
return true;
}
 
/* flatten an then or else block: */
static void
flatten_block(nir_builder *bld, nir_block *if_block, nir_block *prev_block,
nir_ssa_def *condition, bool invert)
{
nir_foreach_instr_safe(if_block, instr) {
if (instr->type == nir_instr_type_intrinsic) {
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
if ((intr->intrinsic == nir_intrinsic_discard) ||
(intr->intrinsic == nir_intrinsic_discard_if)) {
nir_ssa_def *discard_cond;
 
nir_builder_insert_after_instr(bld,
nir_block_last_instr(prev_block));
 
if (invert) {
condition = nir_inot(bld, condition);
invert = false;
}
 
if (intr->intrinsic == nir_intrinsic_discard) {
discard_cond = condition;
} else {
assert(intr->src[0].is_ssa);
/* discard_if gets re-written w/ src and'd: */
discard_cond = nir_iand(bld, condition, intr->src[0].ssa);
}
 
nir_intrinsic_instr *discard_if =
nir_intrinsic_instr_create(bld->shader,
nir_intrinsic_discard_if);
discard_if->src[0] = nir_src_for_ssa(discard_cond);
 
nir_instr_insert_after(nir_block_last_instr(prev_block),
&discard_if->instr);
nir_instr_remove(instr);
instr = NULL;
}
}
/* if not an handled specially, just move to prev block: */
if (instr) {
/* NOTE: exec_node_remove() is safe here (vs nir_instr_remove()
* since we are re-adding the instructin back in to the prev
* block (so no dangling SSA uses)
*/
exec_node_remove(&instr->node);
instr->block = prev_block;
exec_list_push_tail(&prev_block->instr_list, &instr->node);
}
}
}
 
static bool
lower_if_else_block(nir_block *block, void *void_state)
{
struct lower_state *state = void_state;
 
/* If the block is empty, then it certainly doesn't have any phi nodes,
* so we can skip it. This also ensures that we do an early skip on the
* end block of the function which isn't actually attached to the CFG.
*/
if (exec_list_is_empty(&block->instr_list))
return true;
 
if (nir_cf_node_is_first(&block->cf_node))
return true;
 
nir_cf_node *prev_node = nir_cf_node_prev(&block->cf_node);
if (prev_node->type != nir_cf_node_if)
return true;
 
nir_if *if_stmt = nir_cf_node_as_if(prev_node);
nir_cf_node *then_node = nir_if_first_then_node(if_stmt);
nir_cf_node *else_node = nir_if_first_else_node(if_stmt);
 
/* We can only have one block in each side ... */
if (nir_if_last_then_node(if_stmt) != then_node ||
nir_if_last_else_node(if_stmt) != else_node)
return true;
 
nir_block *then_block = nir_cf_node_as_block(then_node);
nir_block *else_block = nir_cf_node_as_block(else_node);
 
/* ... and those blocks must only contain "allowed" instructions. */
if (!block_check_for_allowed_instrs(then_block) ||
!block_check_for_allowed_instrs(else_block))
return true;
 
/* condition should be ssa too, which simplifies flatten_block: */
if (!if_stmt->condition.is_ssa)
return true;
 
/* At this point, we know that the previous CFG node is an if-then
* statement containing only moves to phi nodes in this block. We can
* just remove that entire CF node and replace all of the phi nodes with
* selects.
*/
 
nir_block *prev_block = nir_cf_node_as_block(nir_cf_node_prev(prev_node));
assert(prev_block->cf_node.type == nir_cf_node_block);
 
/* First, we move the remaining instructions from the blocks to the
* block before. There are a few things that need handling specially
* like discard/discard_if.
*/
flatten_block(&state->b, then_block, prev_block,
if_stmt->condition.ssa, false);
flatten_block(&state->b, else_block, prev_block,
if_stmt->condition.ssa, true);
 
nir_foreach_instr_safe(block, instr) {
if (instr->type != nir_instr_type_phi)
break;
 
nir_phi_instr *phi = nir_instr_as_phi(instr);
nir_alu_instr *sel = nir_alu_instr_create(state->mem_ctx, nir_op_bcsel);
nir_src_copy(&sel->src[0].src, &if_stmt->condition, state->mem_ctx);
/* Splat the condition to all channels */
memset(sel->src[0].swizzle, 0, sizeof sel->src[0].swizzle);
 
assert(exec_list_length(&phi->srcs) == 2);
nir_foreach_phi_src(phi, src) {
assert(src->pred == then_block || src->pred == else_block);
assert(src->src.is_ssa);
 
unsigned idx = src->pred == then_block ? 1 : 2;
nir_src_copy(&sel->src[idx].src, &src->src, state->mem_ctx);
}
 
nir_ssa_dest_init(&sel->instr, &sel->dest.dest,
phi->dest.ssa.num_components, phi->dest.ssa.name);
sel->dest.write_mask = (1 << phi->dest.ssa.num_components) - 1;
 
nir_ssa_def_rewrite_uses(&phi->dest.ssa,
nir_src_for_ssa(&sel->dest.dest.ssa),
state->mem_ctx);
 
nir_instr_insert_before(&phi->instr, &sel->instr);
nir_instr_remove(&phi->instr);
}
 
nir_cf_node_remove(&if_stmt->cf_node);
state->progress = true;
 
return true;
}
 
static bool
lower_if_else_impl(nir_function_impl *impl)
{
struct lower_state state;
 
state.mem_ctx = ralloc_parent(impl);
state.progress = false;
nir_builder_init(&state.b, impl);
 
nir_foreach_block(impl, lower_if_else_block, &state);
 
if (state.progress)
nir_metadata_preserve(impl, nir_metadata_none);
 
return state.progress;
}
 
bool
ir3_nir_lower_if_else(nir_shader *shader)
{
bool progress = false;
 
nir_foreach_overload(shader, overload) {
if (overload->impl)
progress |= lower_if_else_impl(overload->impl);
}
 
return progress;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/ir3/ir3_ra.c
0,0 → 1,659
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "pipe/p_shader_tokens.h"
#include "util/u_math.h"
 
#include "ir3.h"
 
/*
* Register Assignment:
*
* NOTE: currently only works on a single basic block.. need to think
* about how multiple basic blocks are going to get scheduled. But
* I think I want to re-arrange how blocks work, ie. get rid of the
* block nesting thing..
*
* NOTE: we could do register coalescing (eliminate moves) as part of
* the RA step.. OTOH I think we need to do scheduling before register
* assignment. And if we remove a mov that effects scheduling (unless
* we leave a placeholder nop, which seems lame), so I'm not really
* sure how practical this is to do both in a single stage. But OTOH
* I'm not really sure a sane way for the CP stage to realize when it
* cannot remove a mov due to multi-register constraints..
*
* NOTE: http://scopesconf.org/scopes-01/paper/session1_2.ps.gz has
* some ideas to handle array allocation with a more conventional
* graph coloring algorithm for register assignment, which might be
* a good alternative to the current algo. However afaict it cannot
* handle overlapping arrays, which is a scenario that we have to
* deal with
*/
 
struct ir3_ra_ctx {
struct ir3_block *block;
enum shader_t type;
bool frag_coord;
bool frag_face;
int cnt;
bool error;
struct {
unsigned base;
unsigned size;
} arrays[MAX_ARRAYS];
};
 
#ifdef DEBUG
# include "freedreno_util.h"
# define ra_debug (fd_mesa_debug & FD_DBG_OPTMSGS)
#else
# define ra_debug 0
#endif
 
#define ra_dump_list(msg, n) do { \
if (ra_debug) { \
debug_printf("-- " msg); \
ir3_dump_instr_list(n); \
} \
} while (0)
 
#define ra_dump_instr(msg, n) do { \
if (ra_debug) { \
debug_printf(">> " msg); \
ir3_dump_instr_single(n); \
} \
} while (0)
 
#define ra_assert(ctx, x) do { \
debug_assert(x); \
if (!(x)) { \
debug_printf("RA: failed assert: %s\n", #x); \
(ctx)->error = true; \
}; \
} while (0)
 
 
/* sorta ugly way to retrofit half-precision support.. rather than
* passing extra param around, just OR in a high bit. All the low
* value arithmetic (ie. +/- offset within a contiguous vec4, etc)
* will continue to work as long as you don't underflow (and that
* would go badly anyways).
*/
#define REG_HALF 0x8000
 
#define REG(n, wm, f) (struct ir3_register){ \
.flags = (f), \
.num = (n), \
.wrmask = TGSI_WRITEMASK_ ## wm, \
}
 
/* check that the register exists, is a GPR and is not special (a0/p0) */
static struct ir3_register * reg_check(struct ir3_instruction *instr, unsigned n)
{
if ((n < instr->regs_count) && reg_gpr(instr->regs[n]) &&
!(instr->regs[n]->flags & IR3_REG_SSA))
return instr->regs[n];
return NULL;
}
 
/* figure out if an unassigned src register points back to the instr we
* are assigning:
*/
static bool instr_used_by(struct ir3_instruction *instr,
struct ir3_register *src)
{
struct ir3_instruction *src_instr = ssa(src);
unsigned i;
if (instr == src_instr)
return true;
if (src_instr && is_meta(src_instr))
for (i = 1; i < src_instr->regs_count; i++)
if (instr_used_by(instr, src_instr->regs[i]))
return true;
 
return false;
}
 
static bool instr_is_output(struct ir3_instruction *instr)
{
struct ir3_block *block = instr->block;
unsigned i;
 
for (i = 0; i < block->noutputs; i++)
if (instr == block->outputs[i])
return true;
 
return false;
}
 
static void mark_sources(struct ir3_instruction *instr,
struct ir3_instruction *n, regmask_t *liveregs, regmask_t *written)
{
unsigned i;
 
for (i = 1; i < n->regs_count; i++) {
struct ir3_register *r = reg_check(n, i);
if (r)
regmask_set_if_not(liveregs, r, written);
 
/* if any src points back to the instruction(s) in
* the block of neighbors that we are assigning then
* mark any written (clobbered) registers as live:
*/
if (instr_used_by(instr, n->regs[i]))
regmask_or(liveregs, liveregs, written);
}
 
}
 
/* live means read before written */
static void compute_liveregs(struct ir3_ra_ctx *ctx,
struct ir3_instruction *instr, regmask_t *liveregs)
{
struct ir3_block *block = instr->block;
struct ir3_instruction *n;
regmask_t written;
unsigned i;
 
regmask_init(&written);
 
for (n = instr->next; n; n = n->next) {
struct ir3_register *r;
 
if (is_meta(n))
continue;
 
/* check first src's read: */
mark_sources(instr, n, liveregs, &written);
 
/* for instructions that write to an array, we need to
* capture the dependency on the array elements:
*/
if (n->fanin)
mark_sources(instr, n->fanin, liveregs, &written);
 
/* meta-instructions don't actually get scheduled,
* so don't let it's write confuse us.. what we
* really care about is when the src to the meta
* instr was written:
*/
if (is_meta(n))
continue;
 
/* then dst written (if assigned already): */
r = reg_check(n, 0);
if (r) {
/* if an instruction *is* an output, then it is live */
if (!instr_is_output(n))
regmask_set(&written, r);
}
 
}
 
/* be sure to account for output registers too: */
for (i = 0; i < block->noutputs; i++) {
struct ir3_register *r;
if (!block->outputs[i])
continue;
r = reg_check(block->outputs[i], 0);
if (r)
regmask_set_if_not(liveregs, r, &written);
}
 
/* if instruction is output, we need a reg that isn't written
* before the end.. equiv to the instr_used_by() check above
* in the loop body
* TODO maybe should follow fanin/fanout?
*/
if (instr_is_output(instr))
regmask_or(liveregs, liveregs, &written);
}
 
static int find_available(regmask_t *liveregs, int size, bool half)
{
unsigned i;
unsigned f = half ? IR3_REG_HALF : 0;
for (i = 0; i < MAX_REG - size; i++) {
if (!regmask_get(liveregs, &REG(i, X, f))) {
unsigned start = i++;
for (; (i < MAX_REG) && ((i - start) < size); i++)
if (regmask_get(liveregs, &REG(i, X, f)))
break;
if ((i - start) >= size)
return start;
}
}
assert(0);
return -1;
}
 
static int alloc_block(struct ir3_ra_ctx *ctx,
struct ir3_instruction *instr, int size)
{
struct ir3_register *dst = instr->regs[0];
struct ir3_instruction *n;
regmask_t liveregs;
unsigned name;
 
/* should only ever be called w/ head of neighbor list: */
debug_assert(!instr->cp.left);
 
regmask_init(&liveregs);
 
for (n = instr; n; n = n->cp.right)
compute_liveregs(ctx, n, &liveregs);
 
/* because we do assignment on fanout nodes for wrmask!=0x1, we
* need to handle this special case, where the fanout nodes all
* appear after one or more of the consumers of the src node:
*
* 0098:009: sam _, r2.x
* 0028:010: mul.f r3.z, r4.x, c13.x
* ; we start assigning here for '0098:009: sam'.. but
* ; would miss the usage at '0028:010: mul.f'
* 0101:009: _meta:fo _, _[0098:009: sam], off=2
*/
if (is_meta(instr) && (instr->opc == OPC_META_FO))
compute_liveregs(ctx, instr->regs[1]->instr, &liveregs);
 
name = find_available(&liveregs, size,
!!(dst->flags & IR3_REG_HALF));
 
if (dst->flags & IR3_REG_HALF)
name |= REG_HALF;
 
return name;
}
 
static type_t half_type(type_t type)
{
switch (type) {
case TYPE_F32: return TYPE_F16;
case TYPE_U32: return TYPE_U16;
case TYPE_S32: return TYPE_S16;
/* instructions may already be fixed up: */
case TYPE_F16:
case TYPE_U16:
case TYPE_S16:
return type;
default:
assert(0);
return ~0;
}
}
 
/* some instructions need fix-up if dst register is half precision: */
static void fixup_half_instr_dst(struct ir3_instruction *instr)
{
switch (instr->category) {
case 1: /* move instructions */
instr->cat1.dst_type = half_type(instr->cat1.dst_type);
break;
case 3:
switch (instr->opc) {
case OPC_MAD_F32:
instr->opc = OPC_MAD_F16;
break;
case OPC_SEL_B32:
instr->opc = OPC_SEL_B16;
break;
case OPC_SEL_S32:
instr->opc = OPC_SEL_S16;
break;
case OPC_SEL_F32:
instr->opc = OPC_SEL_F16;
break;
case OPC_SAD_S32:
instr->opc = OPC_SAD_S16;
break;
/* instructions may already be fixed up: */
case OPC_MAD_F16:
case OPC_SEL_B16:
case OPC_SEL_S16:
case OPC_SEL_F16:
case OPC_SAD_S16:
break;
default:
assert(0);
break;
}
break;
case 5:
instr->cat5.type = half_type(instr->cat5.type);
break;
}
}
/* some instructions need fix-up if src register is half precision: */
static void fixup_half_instr_src(struct ir3_instruction *instr)
{
switch (instr->category) {
case 1: /* move instructions */
instr->cat1.src_type = half_type(instr->cat1.src_type);
break;
}
}
 
static void reg_assign(struct ir3_instruction *instr,
unsigned r, unsigned name)
{
struct ir3_register *reg = instr->regs[r];
 
reg->flags &= ~IR3_REG_SSA;
reg->num = name & ~REG_HALF;
 
if (name & REG_HALF) {
reg->flags |= IR3_REG_HALF;
/* if dst reg being assigned, patch up the instr: */
if (reg == instr->regs[0])
fixup_half_instr_dst(instr);
else
fixup_half_instr_src(instr);
}
}
 
static void instr_assign(struct ir3_ra_ctx *ctx,
struct ir3_instruction *instr, unsigned name);
 
static void instr_assign_src(struct ir3_ra_ctx *ctx,
struct ir3_instruction *instr, unsigned r, unsigned name)
{
struct ir3_register *reg = instr->regs[r];
 
if (reg->flags & IR3_REG_RELATIV)
name += reg->offset;
 
reg_assign(instr, r, name);
 
if (is_meta(instr)) {
switch (instr->opc) {
case OPC_META_INPUT:
/* shader-input does not have a src, only block input: */
debug_assert(instr->regs_count == 2);
instr_assign(ctx, instr, name);
return;
case OPC_META_FO:
instr_assign(ctx, instr, name + instr->fo.off);
return;
case OPC_META_FI:
instr_assign(ctx, instr, name - (r - 1));
return;
default:
break;
}
}
}
 
static void instr_assign_srcs(struct ir3_ra_ctx *ctx,
struct ir3_instruction *instr, unsigned name)
{
struct ir3_instruction *n, *src;
 
for (n = instr->next; n && !ctx->error; n = n->next) {
foreach_ssa_src_n(src, i, n) {
unsigned r = i + 1;
 
/* skip address / etc (non real sources): */
if (r >= n->regs_count)
continue;
 
if (src == instr)
instr_assign_src(ctx, n, r, name);
}
}
}
 
static void instr_assign(struct ir3_ra_ctx *ctx,
struct ir3_instruction *instr, unsigned name)
{
struct ir3_register *reg = instr->regs[0];
 
if (reg->flags & IR3_REG_RELATIV)
return;
 
/* check if already assigned: */
if (!(reg->flags & IR3_REG_SSA)) {
/* ... and if so, sanity check: */
ra_assert(ctx, reg->num == (name & ~REG_HALF));
return;
}
 
/* rename this instructions dst register: */
reg_assign(instr, 0, name);
 
/* and rename any subsequent use of result of this instr: */
instr_assign_srcs(ctx, instr, name);
 
/* To simplify the neighbor logic, and to "avoid" dealing with
* instructions which write more than one output, we actually
* do register assignment for instructions that produce multiple
* outputs on the fanout nodes and propagate up the assignment
* to the actual instruction:
*/
if (is_meta(instr) && (instr->opc == OPC_META_FO)) {
struct ir3_instruction *src;
 
debug_assert(name >= instr->fo.off);
 
foreach_ssa_src(src, instr)
instr_assign(ctx, src, name - instr->fo.off);
}
}
 
/* check neighbor list to see if it is already partially (or completely)
* assigned, in which case register block is already allocated and we
* just need to complete the assignment:
*/
static int check_partial_assignment(struct ir3_ra_ctx *ctx,
struct ir3_instruction *instr)
{
struct ir3_instruction *n;
int off = 0;
 
debug_assert(!instr->cp.left);
 
for (n = instr; n; n = n->cp.right) {
struct ir3_register *dst = n->regs[0];
if ((n->depth != DEPTH_UNUSED) &&
!(dst->flags & IR3_REG_SSA)) {
int name = dst->num - off;
debug_assert(name >= 0);
return name;
}
off++;
}
 
return -1;
}
 
/* allocate register name(s) for a list of neighboring instructions;
* instr should point to leftmost neighbor (head of list)
*/
static void instr_alloc_and_assign(struct ir3_ra_ctx *ctx,
struct ir3_instruction *instr)
{
struct ir3_instruction *n;
struct ir3_register *dst;
int name;
 
debug_assert(!instr->cp.left);
 
if (instr->regs_count == 0)
return;
 
dst = instr->regs[0];
 
/* For indirect dst, take the register assignment from the
* fanin and propagate it forward.
*/
if (dst->flags & IR3_REG_RELATIV) {
/* NOTE can be grouped, if for example outputs:
* for now disable cp if indirect writes
*/
instr_alloc_and_assign(ctx, instr->fanin);
 
dst->num += instr->fanin->regs[0]->num;
dst->flags &= ~IR3_REG_SSA;
 
instr_assign_srcs(ctx, instr, instr->fanin->regs[0]->num);
 
return;
}
 
/* for instructions w/ fanouts, do the actual register assignment
* on the group of fanout neighbor nodes and propagate the reg
* name back up to the texture instruction.
*/
if (dst->wrmask != 0x1)
return;
 
name = check_partial_assignment(ctx, instr);
 
/* allocate register(s): */
if (name >= 0) {
/* already partially assigned, just finish the job */
} else if (reg_gpr(dst)) {
int size;
/* number of consecutive registers to assign: */
size = ir3_neighbor_count(instr);
if (dst->wrmask != 0x1)
size = MAX2(size, ffs(~dst->wrmask) - 1);
name = alloc_block(ctx, instr, size);
} else if (dst->flags & IR3_REG_ADDR) {
debug_assert(!instr->cp.right);
dst->flags &= ~IR3_REG_ADDR;
name = regid(REG_A0, 0) | REG_HALF;
} else {
debug_assert(!instr->cp.right);
/* predicate register (p0).. etc */
name = regid(REG_P0, 0);
debug_assert(dst->num == name);
}
 
ra_assert(ctx, name >= 0);
 
for (n = instr; n && !ctx->error; n = n->cp.right) {
instr_assign(ctx, n, name);
name++;
}
}
 
static void instr_assign_array(struct ir3_ra_ctx *ctx,
struct ir3_instruction *instr)
{
struct ir3_instruction *src;
int name, aid = instr->fi.aid;
 
if (ctx->arrays[aid].base == ~0) {
int size = instr->regs_count - 1;
ctx->arrays[aid].base = alloc_block(ctx, instr, size);
ctx->arrays[aid].size = size;
}
 
name = ctx->arrays[aid].base;
 
foreach_ssa_src_n(src, i, instr) {
unsigned r = i + 1;
 
/* skip address / etc (non real sources): */
if (r >= instr->regs_count)
break;
 
instr_assign(ctx, src, name);
name++;
}
 
}
 
static int block_ra(struct ir3_ra_ctx *ctx, struct ir3_block *block)
{
struct ir3_instruction *n;
 
/* frag shader inputs get pre-assigned, since we have some
* constraints/unknowns about setup for some of these regs:
*/
if ((ctx->type == SHADER_FRAGMENT) && !block->parent) {
unsigned i = 0, j;
if (ctx->frag_face && (i < block->ninputs) && block->inputs[i]) {
/* if we have frag_face, it gets hr0.x */
instr_assign(ctx, block->inputs[i], REG_HALF | 0);
i += 4;
}
for (j = 0; i < block->ninputs; i++, j++)
if (block->inputs[i])
instr_assign(ctx, block->inputs[i], j);
}
 
ra_dump_list("-------\n", block->head);
 
/* first pass, assign arrays: */
for (n = block->head; n && !ctx->error; n = n->next) {
if (is_meta(n) && (n->opc == OPC_META_FI) && n->fi.aid) {
debug_assert(!n->cp.left); /* don't think this should happen */
ra_dump_instr("ASSIGN ARRAY: ", n);
instr_assign_array(ctx, n);
ra_dump_list("-------\n", block->head);
}
}
 
for (n = block->head; n && !ctx->error; n = n->next) {
ra_dump_instr("ASSIGN: ", n);
instr_alloc_and_assign(ctx, ir3_neighbor_first(n));
ra_dump_list("-------\n", block->head);
}
 
return ctx->error ? -1 : 0;
}
 
int ir3_block_ra(struct ir3_block *block, enum shader_t type,
bool frag_coord, bool frag_face)
{
struct ir3_instruction *n;
struct ir3_ra_ctx ctx = {
.block = block,
.type = type,
.frag_coord = frag_coord,
.frag_face = frag_face,
};
int ret;
 
memset(&ctx.arrays, ~0, sizeof(ctx.arrays));
 
/* mark dst registers w/ SSA flag so we can see which
* have been assigned so far:
* NOTE: we really should set SSA flag consistently on
* every dst register in the frontend.
*/
for (n = block->head; n; n = n->next)
if (n->regs_count > 0)
n->regs[0]->flags |= IR3_REG_SSA;
 
ir3_clear_mark(block->shader);
ret = block_ra(&ctx, block);
 
return ret;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/ir3/ir3_sched.c
0,0 → 1,471
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
 
#include "util/u_math.h"
 
#include "ir3.h"
 
enum {
SCHEDULED = -1,
DELAYED = -2,
};
 
/*
* Instruction Scheduling:
*
* Using the depth sorted list from depth pass, attempt to recursively
* schedule deepest unscheduled path. The first instruction that cannot
* be scheduled, returns the required delay slots it needs, at which
* point we return back up to the top and attempt to schedule by next
* highest depth. After a sufficient number of instructions have been
* scheduled, return back to beginning of list and start again. If you
* reach the end of depth sorted list without being able to insert any
* instruction, insert nop's. Repeat until no more unscheduled
* instructions.
*
* There are a few special cases that need to be handled, since sched
* is currently independent of register allocation. Usages of address
* register (a0.x) or predicate register (p0.x) must be serialized. Ie.
* if you have two pairs of instructions that write the same special
* register and then read it, then those pairs cannot be interleaved.
* To solve this, when we are in such a scheduling "critical section",
* and we encounter a conflicting write to a special register, we try
* to schedule any remaining instructions that use that value first.
*/
 
struct ir3_sched_ctx {
struct ir3_instruction *scheduled; /* last scheduled instr */
struct ir3_instruction *addr; /* current a0.x user, if any */
struct ir3_instruction *pred; /* current p0.x user, if any */
unsigned cnt;
bool error;
};
 
static struct ir3_instruction *
deepest(struct ir3_instruction **srcs, unsigned nsrcs)
{
struct ir3_instruction *d = NULL;
unsigned i = 0, id = 0;
 
while ((i < nsrcs) && !(d = srcs[id = i]))
i++;
 
if (!d)
return NULL;
 
for (; i < nsrcs; i++)
if (srcs[i] && (srcs[i]->depth > d->depth))
d = srcs[id = i];
 
srcs[id] = NULL;
 
return d;
}
 
static unsigned distance(struct ir3_sched_ctx *ctx,
struct ir3_instruction *instr, unsigned maxd)
{
struct ir3_instruction *n = ctx->scheduled;
unsigned d = 0;
while (n && (n != instr) && (d < maxd)) {
if (is_alu(n) || is_flow(n))
d++;
n = n->next;
}
return d;
}
 
/* TODO maybe we want double linked list? */
static struct ir3_instruction * prev(struct ir3_instruction *instr)
{
struct ir3_instruction *p = instr->block->head;
while (p && (p->next != instr))
p = p->next;
return p;
}
 
static bool is_sfu_or_mem(struct ir3_instruction *instr)
{
return is_sfu(instr) || is_mem(instr);
}
 
static void schedule(struct ir3_sched_ctx *ctx,
struct ir3_instruction *instr, bool remove)
{
struct ir3_block *block = instr->block;
 
/* maybe there is a better way to handle this than just stuffing
* a nop.. ideally we'd know about this constraint in the
* scheduling and depth calculation..
*/
if (ctx->scheduled && is_sfu_or_mem(ctx->scheduled) && is_sfu_or_mem(instr))
schedule(ctx, ir3_instr_create(block, 0, OPC_NOP), false);
 
/* remove from depth list:
*/
if (remove) {
struct ir3_instruction *p = prev(instr);
 
/* NOTE: this can happen for inputs which are not
* read.. in that case there is no need to schedule
* the input, so just bail:
*/
if (instr != (p ? p->next : block->head))
return;
 
if (p)
p->next = instr->next;
else
block->head = instr->next;
}
 
if (writes_addr(instr)) {
assert(ctx->addr == NULL);
ctx->addr = instr;
}
 
if (writes_pred(instr)) {
assert(ctx->pred == NULL);
ctx->pred = instr;
}
 
instr->flags |= IR3_INSTR_MARK;
 
instr->next = ctx->scheduled;
ctx->scheduled = instr;
 
ctx->cnt++;
}
 
/*
* Delay-slot calculation. Follows fanin/fanout.
*/
 
/* calculate delay for specified src: */
static unsigned delay_calc_srcn(struct ir3_sched_ctx *ctx,
struct ir3_instruction *assigner,
struct ir3_instruction *consumer, unsigned srcn)
{
unsigned delay = 0;
 
if (is_meta(assigner)) {
struct ir3_instruction *src;
foreach_ssa_src(src, assigner) {
unsigned d = delay_calc_srcn(ctx, src, consumer, srcn);
delay = MAX2(delay, d);
}
} else {
delay = ir3_delayslots(assigner, consumer, srcn);
delay -= distance(ctx, assigner, delay);
}
 
return delay;
}
 
/* calculate delay for instruction (maximum of delay for all srcs): */
static unsigned delay_calc(struct ir3_sched_ctx *ctx,
struct ir3_instruction *instr)
{
unsigned delay = 0;
struct ir3_instruction *src;
 
foreach_ssa_src_n(src, i, instr) {
unsigned d = delay_calc_srcn(ctx, src, instr, i);
delay = MAX2(delay, d);
}
 
return delay;
}
 
/* A negative return value signals that an instruction has been newly
* SCHEDULED (or DELAYED due to address or predicate register already
* in use), return back up to the top of the stack (to block_sched())
*/
static int trysched(struct ir3_sched_ctx *ctx,
struct ir3_instruction *instr)
{
struct ir3_instruction *srcs[64];
struct ir3_instruction *src;
unsigned delay, nsrcs = 0;
 
/* if already scheduled: */
if (instr->flags & IR3_INSTR_MARK)
return 0;
 
/* figure out our src's, copy 'em out into an array for sorting: */
foreach_ssa_src(src, instr) {
debug_assert(nsrcs < ARRAY_SIZE(srcs));
srcs[nsrcs++] = src;
}
 
/* for each src register in sorted order:
*/
delay = 0;
while ((src = deepest(srcs, nsrcs))) {
delay = trysched(ctx, src);
if (delay)
return delay;
}
 
/* all our dependents are scheduled, figure out if
* we have enough delay slots to schedule ourself:
*/
delay = delay_calc(ctx, instr);
if (delay)
return delay;
 
/* if the instruction is a kill, we need to ensure *every*
* bary.f is scheduled. The hw seems unhappy if the thread
* gets killed before the end-input (ei) flag is hit.
*
* We could do this by adding each bary.f instruction as
* virtual ssa src for the kill instruction. But we have
* fixed length instr->regs[].
*
* TODO this wouldn't be quite right if we had multiple
* basic blocks, if any block was conditional. We'd need
* to schedule the bary.f's outside of any block which
* was conditional that contained a kill.. I think..
*/
if (is_kill(instr)) {
struct ir3 *ir = instr->block->shader;
unsigned i;
 
for (i = 0; i < ir->baryfs_count; i++) {
struct ir3_instruction *baryf = ir->baryfs[i];
if (baryf->depth == DEPTH_UNUSED)
continue;
delay = trysched(ctx, baryf);
if (delay)
return delay;
}
}
 
/* if this is a write to address/predicate register, and that
* register is currently in use, we need to defer until it is
* free:
*/
if (writes_addr(instr) && ctx->addr) {
assert(ctx->addr != instr);
return DELAYED;
}
if (writes_pred(instr) && ctx->pred) {
assert(ctx->pred != instr);
return DELAYED;
}
 
schedule(ctx, instr, true);
return SCHEDULED;
}
 
static struct ir3_instruction * reverse(struct ir3_instruction *instr)
{
struct ir3_instruction *reversed = NULL;
while (instr) {
struct ir3_instruction *next = instr->next;
instr->next = reversed;
reversed = instr;
instr = next;
}
return reversed;
}
 
static bool uses_current_addr(struct ir3_sched_ctx *ctx,
struct ir3_instruction *instr)
{
return instr->address && (ctx->addr == instr->address);
}
 
static bool uses_current_pred(struct ir3_sched_ctx *ctx,
struct ir3_instruction *instr)
{
struct ir3_instruction *src;
foreach_ssa_src(src, instr)
if (ctx->pred == src)
return true;
return false;
}
 
/* when we encounter an instruction that writes to the address register
* when it is in use, we delay that instruction and try to schedule all
* other instructions using the current address register:
*/
static int block_sched_undelayed(struct ir3_sched_ctx *ctx,
struct ir3_block *block)
{
struct ir3_instruction *instr = block->head;
bool addr_in_use = false;
bool pred_in_use = false;
bool all_delayed = true;
unsigned cnt = ~0, attempted = 0;
 
while (instr) {
struct ir3_instruction *next = instr->next;
bool addr = uses_current_addr(ctx, instr);
bool pred = uses_current_pred(ctx, instr);
 
if (addr || pred) {
int ret = trysched(ctx, instr);
 
if (ret != DELAYED)
all_delayed = false;
 
if (ret == SCHEDULED)
cnt = 0;
else if (ret > 0)
cnt = MIN2(cnt, ret);
if (addr)
addr_in_use = true;
if (pred)
pred_in_use = true;
 
attempted++;
}
 
instr = next;
}
 
if (!addr_in_use)
ctx->addr = NULL;
 
if (!pred_in_use)
ctx->pred = NULL;
 
/* detect if we've gotten ourselves into an impossible situation
* and bail if needed
*/
if (all_delayed && (attempted > 0)) {
if (pred_in_use) {
/* TODO we probably need to keep a list of instructions
* that reference predicate, similar to indirects
*/
ctx->error = true;
return DELAYED;
}
if (addr_in_use) {
struct ir3 *ir = ctx->addr->block->shader;
struct ir3_instruction *new_addr =
ir3_instr_clone(ctx->addr);
unsigned i;
 
/* original addr is scheduled, but new one isn't: */
new_addr->flags &= ~IR3_INSTR_MARK;
 
for (i = 0; i < ir->indirects_count; i++) {
struct ir3_instruction *indirect = ir->indirects[i];
 
/* skip instructions already scheduled: */
if (indirect->flags & IR3_INSTR_MARK)
continue;
 
/* remap remaining instructions using current addr
* to new addr:
*/
if (indirect->address == ctx->addr)
indirect->address = new_addr;
}
 
/* all remaining indirects remapped to new addr: */
ctx->addr = NULL;
 
/* not really, but this will trigger us to go back to
* main trysched() loop now that we've resolved the
* conflict by duplicating the instr that writes to
* the address register.
*/
return SCHEDULED;
}
}
 
return cnt;
}
 
static void block_sched(struct ir3_sched_ctx *ctx, struct ir3_block *block)
{
struct ir3_instruction *instr;
 
/* schedule all the shader input's (meta-instr) first so that
* the RA step sees that the input registers contain a value
* from the start of the shader:
*/
if (!block->parent) {
unsigned i;
for (i = 0; i < block->ninputs; i++) {
struct ir3_instruction *in = block->inputs[i];
if (in)
schedule(ctx, in, true);
}
}
 
while ((instr = block->head) && !ctx->error) {
/* NOTE: always grab next *before* trysched(), in case the
* instruction is actually scheduled (and therefore moved
* from depth list into scheduled list)
*/
struct ir3_instruction *next = instr->next;
int cnt = trysched(ctx, instr);
 
if (cnt == DELAYED)
cnt = block_sched_undelayed(ctx, block);
 
/* -1 is signal to return up stack, but to us means same as 0: */
cnt = MAX2(0, cnt);
cnt += ctx->cnt;
instr = next;
 
/* if deepest remaining instruction cannot be scheduled, try
* the increasingly more shallow instructions until needed
* number of delay slots is filled:
*/
while (instr && (cnt > ctx->cnt)) {
next = instr->next;
trysched(ctx, instr);
instr = next;
}
 
/* and if we run out of instructions that can be scheduled,
* then it is time for nop's:
*/
while (cnt > ctx->cnt)
schedule(ctx, ir3_instr_create(block, 0, OPC_NOP), false);
}
 
/* at this point, scheduled list is in reverse order, so fix that: */
block->head = reverse(ctx->scheduled);
}
 
int ir3_block_sched(struct ir3_block *block)
{
struct ir3_sched_ctx ctx = {0};
ir3_clear_mark(block->shader);
block_sched(&ctx, block);
if (ctx.error)
return -1;
return 0;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/ir3/ir3_shader.c
0,0 → 1,293
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#include "pipe/p_state.h"
#include "util/u_string.h"
#include "util/u_memory.h"
#include "util/u_inlines.h"
#include "util/u_format.h"
#include "tgsi/tgsi_dump.h"
#include "tgsi/tgsi_parse.h"
 
#include "freedreno_context.h"
#include "freedreno_util.h"
 
#include "ir3_shader.h"
#include "ir3_compiler.h"
 
 
static void
delete_variant(struct ir3_shader_variant *v)
{
if (v->ir)
ir3_destroy(v->ir);
fd_bo_del(v->bo);
free(v);
}
 
/* for vertex shader, the inputs are loaded into registers before the shader
* is executed, so max_regs from the shader instructions might not properly
* reflect the # of registers actually used, especially in case passthrough
* varyings.
*
* Likewise, for fragment shader, we can have some regs which are passed
* input values but never touched by the resulting shader (ie. as result
* of dead code elimination or simply because we don't know how to turn
* the reg off.
*/
static void
fixup_regfootprint(struct ir3_shader_variant *v)
{
if (v->type == SHADER_VERTEX) {
unsigned i;
for (i = 0; i < v->inputs_count; i++) {
/* skip frag inputs fetch via bary.f since their reg's are
* not written by gpu before shader starts (and in fact the
* regid's might not even be valid)
*/
if (v->inputs[i].bary)
continue;
 
if (v->inputs[i].compmask) {
int32_t regid = (v->inputs[i].regid + 3) >> 2;
v->info.max_reg = MAX2(v->info.max_reg, regid);
}
}
for (i = 0; i < v->outputs_count; i++) {
int32_t regid = (v->outputs[i].regid + 3) >> 2;
v->info.max_reg = MAX2(v->info.max_reg, regid);
}
} else if (v->type == SHADER_FRAGMENT) {
/* NOTE: not sure how to turn pos_regid off.. but this could
* be, for example, r1.x while max reg used by the shader is
* r0.*, in which case we need to fixup the reg footprint:
*/
v->info.max_reg = MAX2(v->info.max_reg, v->pos_regid >> 2);
if (v->frag_coord)
debug_assert(v->info.max_reg >= 0); /* hard coded r0.x */
if (v->frag_face)
debug_assert(v->info.max_half_reg >= 0); /* hr0.x */
}
}
 
/* wrapper for ir3_assemble() which does some info fixup based on
* shader state. Non-static since used by ir3_cmdline too.
*/
void * ir3_shader_assemble(struct ir3_shader_variant *v, uint32_t gpu_id)
{
void *bin;
 
bin = ir3_assemble(v->ir, &v->info, gpu_id);
if (!bin)
return NULL;
 
if (gpu_id >= 400) {
v->instrlen = v->info.sizedwords / (2 * 16);
} else {
v->instrlen = v->info.sizedwords / (2 * 4);
}
 
/* NOTE: if relative addressing is used, we set constlen in
* the compiler (to worst-case value) since we don't know in
* the assembler what the max addr reg value can be:
*/
v->constlen = MIN2(255, MAX2(v->constlen, v->info.max_const + 1));
 
fixup_regfootprint(v);
 
return bin;
}
 
static void
assemble_variant(struct ir3_shader_variant *v)
{
struct fd_context *ctx = fd_context(v->shader->pctx);
uint32_t gpu_id = ir3_shader_gpuid(v->shader);
uint32_t sz, *bin;
 
bin = ir3_shader_assemble(v, gpu_id);
sz = v->info.sizedwords * 4;
 
v->bo = fd_bo_new(ctx->dev, sz,
DRM_FREEDRENO_GEM_CACHE_WCOMBINE |
DRM_FREEDRENO_GEM_TYPE_KMEM);
 
memcpy(fd_bo_map(v->bo), bin, sz);
 
free(bin);
 
/* no need to keep the ir around beyond this point: */
ir3_destroy(v->ir);
v->ir = NULL;
}
 
/* reset before attempting to compile again.. */
static void reset_variant(struct ir3_shader_variant *v, const char *msg)
{
debug_error(msg);
v->inputs_count = 0;
v->outputs_count = 0;
v->total_in = 0;
v->has_samp = false;
v->immediates_count = 0;
}
 
static struct ir3_shader_variant *
create_variant(struct ir3_shader *shader, struct ir3_shader_key key)
{
struct ir3_shader_variant *v = CALLOC_STRUCT(ir3_shader_variant);
const struct tgsi_token *tokens = shader->tokens;
int ret;
 
if (!v)
return NULL;
 
v->shader = shader;
v->key = key;
v->type = shader->type;
 
if (fd_mesa_debug & FD_DBG_DISASM) {
DBG("dump tgsi: type=%d, k={bp=%u,cts=%u,hp=%u}", shader->type,
key.binning_pass, key.color_two_side, key.half_precision);
tgsi_dump(tokens, 0);
}
 
if (fd_mesa_debug & FD_DBG_NIR) {
ret = ir3_compile_shader_nir(v, tokens, key);
if (ret)
reset_variant(v, "NIR compiler failed, fallback to TGSI!");
} else {
ret = -1;
}
 
if (ret) {
ret = ir3_compile_shader(v, tokens, key, true);
if (ret) {
reset_variant(v, "new compiler failed, trying without copy propagation!");
ret = ir3_compile_shader(v, tokens, key, false);
}
}
 
if (ret) {
debug_error("compile failed!");
goto fail;
}
 
assemble_variant(v);
if (!v->bo) {
debug_error("assemble failed!");
goto fail;
}
 
if (fd_mesa_debug & FD_DBG_DISASM) {
DBG("disassemble: type=%d, k={bp=%u,cts=%u,hp=%u}", v->type,
key.binning_pass, key.color_two_side, key.half_precision);
disasm_a3xx(fd_bo_map(v->bo), v->info.sizedwords, 0, v->type);
}
 
return v;
 
fail:
delete_variant(v);
return NULL;
}
 
uint32_t
ir3_shader_gpuid(struct ir3_shader *shader)
{
struct fd_context *ctx = fd_context(shader->pctx);
return ctx->screen->gpu_id;
}
 
struct ir3_shader_variant *
ir3_shader_variant(struct ir3_shader *shader, struct ir3_shader_key key)
{
struct ir3_shader_variant *v;
 
/* some shader key values only apply to vertex or frag shader,
* so normalize the key to avoid constructing multiple identical
* variants:
*/
switch (shader->type) {
case SHADER_FRAGMENT:
case SHADER_COMPUTE:
key.binning_pass = false;
if (key.has_per_samp) {
key.vsaturate_s = 0;
key.vsaturate_t = 0;
key.vsaturate_r = 0;
}
break;
case SHADER_VERTEX:
key.color_two_side = false;
key.half_precision = false;
key.rasterflat = false;
if (key.has_per_samp) {
key.fsaturate_s = 0;
key.fsaturate_t = 0;
key.fsaturate_r = 0;
}
break;
}
 
for (v = shader->variants; v; v = v->next)
if (ir3_shader_key_equal(&key, &v->key))
return v;
 
/* compile new variant if it doesn't exist already: */
v = create_variant(shader, key);
v->next = shader->variants;
shader->variants = v;
 
return v;
}
 
 
void
ir3_shader_destroy(struct ir3_shader *shader)
{
struct ir3_shader_variant *v, *t;
for (v = shader->variants; v; ) {
t = v;
v = v->next;
delete_variant(t);
}
free((void *)shader->tokens);
free(shader);
}
 
struct ir3_shader *
ir3_shader_create(struct pipe_context *pctx, const struct tgsi_token *tokens,
enum shader_t type)
{
struct ir3_shader *shader = CALLOC_STRUCT(ir3_shader);
shader->pctx = pctx;
shader->type = type;
shader->tokens = tgsi_dup_tokens(tokens);
return shader;
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/drivers/freedreno/ir3/ir3_shader.h
0,0 → 1,277
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
 
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* 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.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
 
#ifndef IR3_SHADER_H_
#define IR3_SHADER_H_
 
#include "ir3.h"
#include "disasm.h"
 
typedef uint16_t ir3_semantic; /* semantic name + index */
static inline ir3_semantic
ir3_semantic_name(uint8_t name, uint16_t index)
{
return (name << 8) | (index & 0xff);
}
 
static inline uint8_t sem2name(ir3_semantic sem)
{
return sem >> 8;
}
 
static inline uint16_t sem2idx(ir3_semantic sem)
{
return sem & 0xff;
}
 
/* Configuration key used to identify a shader variant.. different
* shader variants can be used to implement features not supported
* in hw (two sided color), binning-pass vertex shader, etc.
*/
struct ir3_shader_key {
union {
struct {
/* do we need to check {v,f}saturate_{s,t,r}? */
unsigned has_per_samp : 1;
 
/*
* Vertex shader variant parameters:
*/
unsigned binning_pass : 1;
 
/*
* Fragment shader variant parameters:
*/
unsigned color_two_side : 1;
unsigned half_precision : 1;
/* used when shader needs to handle flat varyings (a4xx),
* for TGSI_INTERPOLATE_COLOR:
*/
unsigned rasterflat : 1;
};
uint32_t global;
};
 
/* bitmask of sampler which needs coords clamped for vertex
* shader:
*/
uint16_t vsaturate_s, vsaturate_t, vsaturate_r;
 
/* bitmask of sampler which needs coords clamped for frag
* shader:
*/
uint16_t fsaturate_s, fsaturate_t, fsaturate_r;
 
/* bitmask of sampler which produces integer outputs:
*/
uint16_t vinteger_s, finteger_s;
};
 
static inline bool
ir3_shader_key_equal(struct ir3_shader_key *a, struct ir3_shader_key *b)
{
/* slow-path if we need to check {v,f}saturate_{s,t,r} */
if (a->has_per_samp || b->has_per_samp)
return memcmp(a, b, sizeof(struct ir3_shader_key)) == 0;
return a->global == b->global;
}
 
struct ir3_shader_variant {
struct fd_bo *bo;
 
struct ir3_shader_key key;
 
struct ir3_info info;
struct ir3 *ir;
 
/* the instructions length is in units of instruction groups
* (4 instructions for a3xx, 16 instructions for a4xx.. each
* instruction is 2 dwords):
*/
unsigned instrlen;
 
/* the constants length is in units of vec4's, and is the sum of
* the uniforms and the built-in compiler constants
*/
unsigned constlen;
 
/* About Linkage:
* + Let the frag shader determine the position/compmask for the
* varyings, since it is the place where we know if the varying
* is actually used, and if so, which components are used. So
* what the hw calls "outloc" is taken from the "inloc" of the
* frag shader.
* + From the vert shader, we only need the output regid
*/
 
/* for frag shader, pos_regid holds the frag_pos, ie. what is passed
* to bary.f instructions
*/
uint8_t pos_regid;
bool frag_coord, frag_face, color0_mrt;
 
/* varyings/outputs: */
unsigned outputs_count;
struct {
ir3_semantic semantic;
uint8_t regid;
} outputs[16 + 2]; /* +POSITION +PSIZE */
bool writes_pos, writes_psize;
 
/* vertices/inputs: */
unsigned inputs_count;
struct {
ir3_semantic semantic;
uint8_t regid;
uint8_t compmask;
uint8_t ncomp;
/* In theory inloc of fs should match outloc of vs. Or
* rather the outloc of the vs is 8 plus the offset passed
* to bary.f. Presumably that +8 is to account for
* gl_Position/gl_PointSize?
*
* NOTE inloc is currently aligned to 4 (we don't try
* to pack varyings). Changing this would likely break
* assumptions in few places (like setting up of flat
* shading in fd3_program) so be sure to check all the
* spots where inloc is used.
*/
uint8_t inloc;
uint8_t bary;
uint8_t interpolate;
} inputs[16 + 2]; /* +POSITION +FACE */
 
unsigned total_in; /* sum of inputs (scalar) */
 
/* do we have one or more texture sample instructions: */
bool has_samp;
 
/* do we have kill instructions: */
bool has_kill;
 
/* const reg # of first immediate, ie. 1 == c1
* (not regid, because TGSI thinks in terms of vec4 registers,
* not scalar registers)
*/
unsigned first_driver_param;
unsigned first_immediate;
unsigned immediates_count;
struct {
uint32_t val[4];
} immediates[64];
 
/* shader variants form a linked list: */
struct ir3_shader_variant *next;
 
/* replicated here to avoid passing extra ptrs everywhere: */
enum shader_t type;
struct ir3_shader *shader;
};
 
struct ir3_shader {
enum shader_t type;
 
struct pipe_context *pctx;
const struct tgsi_token *tokens;
 
struct ir3_shader_variant *variants;
 
/* so far, only used for blit_prog shader.. values for
* VPC_VARYING_PS_REPL[i].MODE
*/
uint32_t vpsrepl[8];
};
 
void * ir3_shader_assemble(struct ir3_shader_variant *v, uint32_t gpu_id);
 
struct ir3_shader * ir3_shader_create(struct pipe_context *pctx,
const struct tgsi_token *tokens, enum shader_t type);
void ir3_shader_destroy(struct ir3_shader *shader);
uint32_t ir3_shader_gpuid(struct ir3_shader *shader);
struct ir3_shader_variant * ir3_shader_variant(struct ir3_shader *shader,
struct ir3_shader_key key);
 
/*
* Helper/util:
*/
 
static inline int
ir3_find_output(const struct ir3_shader_variant *so, ir3_semantic semantic)
{
int j;
 
for (j = 0; j < so->outputs_count; j++)
if (so->outputs[j].semantic == semantic)
return j;
 
/* it seems optional to have a OUT.BCOLOR[n] for each OUT.COLOR[n]
* in the vertex shader.. but the fragment shader doesn't know this
* so it will always have both IN.COLOR[n] and IN.BCOLOR[n]. So
* at link time if there is no matching OUT.BCOLOR[n], we must map
* OUT.COLOR[n] to IN.BCOLOR[n]. And visa versa if there is only
* a OUT.BCOLOR[n] but no matching OUT.COLOR[n]
*/
if (sem2name(semantic) == TGSI_SEMANTIC_BCOLOR) {
unsigned idx = sem2idx(semantic);
semantic = ir3_semantic_name(TGSI_SEMANTIC_COLOR, idx);
} else if (sem2name(semantic) == TGSI_SEMANTIC_COLOR) {
unsigned idx = sem2idx(semantic);
semantic = ir3_semantic_name(TGSI_SEMANTIC_BCOLOR, idx);
} else {
return 0;
}
 
for (j = 0; j < so->outputs_count; j++)
if (so->outputs[j].semantic == semantic)
return j;
 
debug_assert(0);
 
return 0;
}
 
static inline int
ir3_next_varying(const struct ir3_shader_variant *so, int i)
{
while (++i < so->inputs_count)
if (so->inputs[i].compmask && so->inputs[i].bary)
break;
return i;
}
 
static inline uint32_t
ir3_find_output_regid(const struct ir3_shader_variant *so, ir3_semantic semantic)
{
int j;
for (j = 0; j < so->outputs_count; j++)
if (so->outputs[j].semantic == semantic)
return so->outputs[j].regid;
return regid(63, 0);
}
 
#endif /* IR3_SHADER_H_ */