diff options
682 files changed, 25754 insertions, 18583 deletions
@@ -232,6 +232,7 @@ MAIN_FILES = \ $(DIRECTORY)/src/glsl/README \ $(DIRECTORY)/src/glsl/glcpp/*.[chly] \ $(DIRECTORY)/src/glsl/glcpp/README \ + $(DIRECTORY)/src/glsl/builtins \ $(DIRECTORY)/src/Makefile \ $(DIRECTORY)/src/mesa/Makefile* \ $(DIRECTORY)/src/mesa/sources.mak \ @@ -283,8 +284,7 @@ MAIN_FILES = \ $(DIRECTORY)/src/mesa/x86/*.S \ $(DIRECTORY)/src/mesa/x86/rtasm/*.[ch] \ $(DIRECTORY)/src/mesa/x86-64/*.[chS] \ - $(DIRECTORY)/src/mesa/x86-64/Makefile \ - $(DIRECTORY)/windows/VC8/ + $(DIRECTORY)/src/mesa/x86-64/Makefile MAPI_FILES = \ $(DIRECTORY)/include/GLES/*.h \ diff --git a/SConstruct b/SConstruct index 368ad83edf3..8607d2cd8e0 100644 --- a/SConstruct +++ b/SConstruct @@ -56,6 +56,12 @@ else: Help(opts.GenerateHelpText(env)) +# fail early for a common error on windows +if env['gles']: + try: + import libxml2 + except ImportError: + raise SCons.Errors.UserError, "GLES requires libxml2-python to build" ####################################################################### # Environment setup @@ -115,8 +121,6 @@ if env['platform'] in ('posix', 'linux', 'freebsd', 'darwin'): # for debugging #print env.Dump() -Export('env') - ####################################################################### # Invoke host SConscripts @@ -126,7 +130,7 @@ Export('env') # # Create host environent -if env['platform'] != common.host_platform: +if env['crosscompile'] and env['platform'] != 'embedded': host_env = Environment( options = opts, # no tool used @@ -143,13 +147,25 @@ if env['platform'] != common.host_platform: host_env.Tool('gallium') + host_env['hostonly'] = True + assert host_env['crosscompile'] == False + + if host_env['msvc']: + host_env.Append(CPPPATH = ['#include/c99']) + + target_env = env + env = host_env + Export('env') + SConscript( - 'src/glsl/SConscript', + 'src/SConscript', variant_dir = host_env['build_dir'], duplicate = 0, # http://www.scons.org/doc/0.97/HTML/scons-user/x2261.html - exports={'env':host_env}, ) + env = target_env + +Export('env') ####################################################################### # Invoke SConscripts diff --git a/common.py b/common.py index 76184d577a3..b44f20e8216 100644 --- a/common.py +++ b/common.py @@ -14,13 +14,7 @@ import SCons.Script.SConscript ####################################################################### # Defaults -_platform_map = { - 'linux2': 'linux', - 'win32': 'windows', -} - -host_platform = sys.platform -host_platform = _platform_map.get(host_platform, host_platform) +host_platform = _platform.system().lower() # Search sys.argv[] for a "platform=foo" argument since we don't have # an 'env' variable at this point. @@ -29,8 +23,6 @@ if 'platform' in SCons.Script.ARGUMENTS: else: target_platform = host_platform -cross_compiling = target_platform != host_platform - _machine_map = { 'x86': 'x86', 'i386': 'x86', @@ -38,6 +30,7 @@ _machine_map = { 'i586': 'x86', 'i686': 'x86', 'ppc' : 'ppc', + 'AMD64': 'x86_64', 'x86_64': 'x86_64', } @@ -52,7 +45,7 @@ host_machine = _machine_map.get(host_machine, 'generic') default_machine = host_machine default_toolchain = 'default' -if target_platform == 'windows' and cross_compiling: +if target_platform == 'windows' and host_platform != 'windows': default_machine = 'x86' default_toolchain = 'crossmingw' @@ -88,8 +81,9 @@ def AddOptions(opts): opts.Add(EnumOption('machine', 'use machine-specific assembly code', default_machine, allowed_values=('generic', 'ppc', 'x86', 'x86_64'))) opts.Add(EnumOption('platform', 'target platform', host_platform, - allowed_values=('linux', 'cell', 'windows', 'winddk', 'wince', 'darwin', 'embedded', 'cygwin', 'sunos5', 'freebsd8'))) + allowed_values=('linux', 'cell', 'windows', 'winddk', 'wince', 'darwin', 'embedded', 'cygwin_nt-5.1', 'cygwin_nt-6.1', 'sunos5', 'freebsd8'))) opts.Add('toolchain', 'compiler toolchain', default_toolchain) + opts.Add(BoolOption('gles', 'EXPERIMENTAL: enable OpenGL ES support', 'no')) opts.Add(BoolOption('llvm', 'use LLVM', default_llvm)) opts.Add(BoolOption('debug', 'DEPRECATED: debug build', 'yes')) opts.Add(BoolOption('profile', 'DEPRECATED: profile build', 'no')) diff --git a/configs/autoconf.in b/configs/autoconf.in index dc8f8622416..9defba21afb 100644 --- a/configs/autoconf.in +++ b/configs/autoconf.in @@ -16,10 +16,12 @@ PIC_FLAGS = @PIC_FLAGS@ DEFINES = @DEFINES@ API_DEFINES = @API_DEFINES@ SHARED_GLAPI = @SHARED_GLAPI@ -CFLAGS = @CPPFLAGS@ @CFLAGS@ \ +CFLAGS_NOVISIBILITY = @CPPFLAGS@ @CFLAGS@ \ $(OPT_FLAGS) $(PIC_FLAGS) $(ARCH_FLAGS) $(ASM_FLAGS) $(DEFINES) -CXXFLAGS = @CPPFLAGS@ @CXXFLAGS@ \ +CXXFLAGS_NOVISIBILITY = @CPPFLAGS@ @CXXFLAGS@ \ $(OPT_FLAGS) $(PIC_FLAGS) $(ARCH_FLAGS) $(DEFINES) +CFLAGS = $(CFLAGS_NOVISIBILITY) @VISIBILITY_CFLAGS@ +CXXFLAGS = $(CXXFLAGS_NOVISIBILITY) @VISIBILITY_CXXFLAGS@ LDFLAGS = @LDFLAGS@ EXTRA_LIB_PATH = @EXTRA_LIB_PATH@ RADEON_CFLAGS = @RADEON_CFLAGS@ @@ -34,9 +36,8 @@ LLVM_LIBS = @LLVM_LIBS@ GLW_CFLAGS = @GLW_CFLAGS@ GLUT_CFLAGS = @GLUT_CFLAGS@ GLX_TLS = @GLX_TLS@ - -TALLOC_LIBS = @TALLOC_LIBS@ -TALLOC_CFLAGS = @TALLOC_CFLAGS@ +DRI_CFLAGS = @DRI_CFLAGS@ +DRI_CXXFLAGS = @DRI_CXXFLAGS@ # dlopen DLOPEN_LIBS = @DLOPEN_LIBS@ @@ -67,6 +68,7 @@ GLESv1_CM_LIB = GLESv1_CM GLESv2_LIB = GLESv2 VG_LIB = OpenVG GLAPI_LIB = glapi +WAYLAND_EGL_LIB = wayland-egl # Library names (actual file names) GL_LIB_NAME = @GL_LIB_NAME@ @@ -79,6 +81,7 @@ GLESv1_CM_LIB_NAME = @GLESv1_CM_LIB_NAME@ GLESv2_LIB_NAME = @GLESv2_LIB_NAME@ VG_LIB_NAME = @VG_LIB_NAME@ GLAPI_LIB_NAME = @GLAPI_LIB_NAME@ +WAYLAND_EGL_LIB_NAME = @WAYLAND_EGL_LIB_NAME@ # Globs used to install the lib and all symlinks GL_LIB_GLOB = @GL_LIB_GLOB@ @@ -91,6 +94,7 @@ GLESv1_CM_LIB_GLOB = @GLESv1_CM_LIB_GLOB@ GLESv2_LIB_GLOB = @GLESv2_LIB_GLOB@ VG_LIB_GLOB = @VG_LIB_GLOB@ GLAPI_LIB_GLOB = @GLAPI_LIB_GLOB@ +WAYLAND_EGL_LIB_GLOB = @WAYLAND_EGL_LIB_GLOB@ # Directories to build LIB_DIR = @LIB_DIR@ @@ -107,7 +111,10 @@ GALLIUM_AUXILIARIES = $(TOP)/src/gallium/auxiliary/libgallium.a GALLIUM_DRIVERS = $(foreach DIR,$(GALLIUM_DRIVERS_DIRS),$(TOP)/src/gallium/drivers/$(DIR)/lib$(DIR).a) # Driver specific build vars -DRI_DIRS = @DRI_DIRS@ +DRI_DIRS = @DRI_DIRS@ +DRICORE_GLSL_LIBS = @DRICORE_GLSL_LIBS@ +DRICORE_LIBS = @DRICORE_LIBS@ +DRICORE_LIB_DEPS = @DRICORE_LIB_DEPS@ EGL_PLATFORMS = @EGL_PLATFORMS@ EGL_CLIENT_APIS = @EGL_CLIENT_APIS@ @@ -134,8 +141,10 @@ GLESv1_CM_LIB_DEPS = $(EXTRA_LIB_PATH) @GLESv1_CM_LIB_DEPS@ GLESv2_LIB_DEPS = $(EXTRA_LIB_PATH) @GLESv2_LIB_DEPS@ VG_LIB_DEPS = $(EXTRA_LIB_PATH) @VG_LIB_DEPS@ GLAPI_LIB_DEPS = $(EXTRA_LIB_PATH) @GLAPI_LIB_DEPS@ +WAYLAND_EGL_LIB_DEPS = $(EXTRA_LIBPATH) @WAYLAND_EGL_LIB_DEPS@ # DRI dependencies +MESA_MODULES = @MESA_MODULES@ DRI_LIB_DEPS = $(EXTRA_LIB_PATH) @DRI_LIB_DEPS@ LIBDRM_CFLAGS = @LIBDRM_CFLAGS@ LIBDRM_LIB = @LIBDRM_LIBS@ @@ -193,11 +202,16 @@ GLESv2_PC_LIB_PRIV = @GLESv2_PC_LIB_PRIV@ EGL_PC_REQ_PRIV = @GL_PC_REQ_PRIV@ EGL_PC_LIB_PRIV = @GL_PC_LIB_PRIV@ EGL_PC_CFLAGS = @GL_PC_CFLAGS@ +WAYLAND_EGL_PC_REQ_PRIV = @WAYLAND_EGL_PC_REQ_PRIV@ +WAYLAND_EGL_PC_LIB_PRIV = @WAYLAND_EGL_PC_LIB_PRIV@ +WAYLAND_EGL_PC_CFLAGS = @WAYLAND_EGL_PC_CFLAGS@ XCB_DRI2_CFLAGS = @XCB_DRI2_CFLAGS@ XCB_DRI2_LIBS = @XCB_DRI2_LIBS@ LIBUDEV_CFLAGS = @LIBUDEV_CFLAGS@ LIBUDEV_LIBS = @LIBUDEV_LIBS@ +WAYLAND_CFLAGS = @WAYLAND_CFLAGS@ +WAYLAND_LIBS = @WAYLAND_LIBS@ MESA_LLVM = @MESA_LLVM@ diff --git a/configs/default b/configs/default index 9030cf5b9df..0582a0210af 100644 --- a/configs/default +++ b/configs/default @@ -60,6 +60,7 @@ GLESv1_CM_LIB = GLESv1_CM GLESv2_LIB = GLESv2 VG_LIB = OpenVG GLAPI_LIB = glapi +WAYLAND_EGL_LIB = wayland-egl # Library names (actual file names) @@ -73,6 +74,7 @@ GLESv1_CM_LIB_NAME = lib$(GLESv1_CM_LIB).so GLESv2_LIB_NAME = lib$(GLESv2_LIB).so VG_LIB_NAME = lib$(VG_LIB).so GLAPI_LIB_NAME = lib$(GLAPI_LIB).so +WAYLAND_EGL_LIB_NAME = lib$(WAYLAND_EGL_LIB).so # globs used to install the lib and all symlinks GL_LIB_GLOB = $(GL_LIB_NAME)* @@ -85,9 +87,10 @@ GLESv1_CM_LIB_GLOB = $(GLESv1_CM_LIB_NAME)* GLESv2_LIB_GLOB = $(GLESv2_LIB_NAME)* VG_LIB_GLOB = $(VG_LIB_NAME)* GLAPI_LIB_GLOB = $(GLAPI_LIB_NAME)* +WAYLAND_EGL_LIB_GLOB = $(WAYLAND_EGL_LIB_NAME)* -TALLOC_LIBS = `pkg-config --libs talloc` -TALLOC_CFLAGS = `pkg-config --cflags talloc` +DRI_CFLAGS = $(CFLAGS) +DRI_CXXFLAGS = $(CXXFLAGS) # Optional assembly language optimization files for libGL MESA_ASM_SOURCES = @@ -123,7 +126,7 @@ EGL_CLIENT_APIS = $(GL_LIB) # Library dependencies #EXTRA_LIB_PATH ?= -GL_LIB_DEPS = $(EXTRA_LIB_PATH) -lX11 -lXext -lm -lpthread $(TALLOC_LIBS) +GL_LIB_DEPS = $(EXTRA_LIB_PATH) -lX11 -lXext -lm -lpthread EGL_LIB_DEPS = $(EXTRA_LIB_PATH) -ldl -lpthread OSMESA_LIB_DEPS = $(EXTRA_LIB_PATH) -L$(TOP)/$(LIB_DIR) -l$(GL_LIB) GLU_LIB_DEPS = $(EXTRA_LIB_PATH) -L$(TOP)/$(LIB_DIR) -l$(GL_LIB) -lm @@ -134,6 +137,7 @@ GLESv1_CM_LIB_DEPS = $(EXTRA_LIB_PATH) -lpthread GLESv2_LIB_DEPS = $(EXTRA_LIB_PATH) -lpthread VG_LIB_DEPS = $(EXTRA_LIB_PATH) -lpthread GLAPI_LIB_DEPS = $(EXTRA_LIB_PATH) -lpthread +WAYLAND_EGL_LIB_DEPS = $(EXTRA_LIB_PATH) -lwayland-client -ldrm # Program dependencies - specific GL/glut libraries added in Makefiles APP_LIB_DEPS = -lm @@ -182,3 +186,6 @@ GLESv2_PC_CFLAGS = VG_PC_REQ_PRIV = VG_PC_LIB_PRIV = VG_PC_CFLAGS = +WAYLAND_EGL_PC_REQ_PRIV = +WAYLAND_EGL_PC_LIB_PRIV = +WAYLAND_EGL_PC_CFLAGS = diff --git a/configs/freebsd-dri b/configs/freebsd-dri index a4aa82e96df..23cf58a3bf5 100644 --- a/configs/freebsd-dri +++ b/configs/freebsd-dri @@ -30,9 +30,11 @@ ASM_SOURCES = MESA_ASM_SOURCES = # Library/program dependencies +MESA_MODULES = $(TOP)/src/mesa/libmesa.a + LIBDRM_CFLAGS = `pkg-config --cflags libdrm` LIBDRM_LIB = `pkg-config --libs libdrm` -DRI_LIB_DEPS = -L/usr/local/lib -lm -pthread -lexpat $(LIBDRM_LIB) +DRI_LIB_DEPS = $(MESA_MODULES) -L/usr/local/lib -lm -pthread -lexpat $(LIBDRM_LIB) GL_LIB_DEPS = -L/usr/local/lib -lX11 -lXext -lXxf86vm -lXdamage -lXfixes \ -lm -pthread $(LIBDRM_LIB) diff --git a/configs/linux-dri b/configs/linux-dri index 9a0253f919b..ce2da8317d7 100644 --- a/configs/linux-dri +++ b/configs/linux-dri @@ -43,9 +43,11 @@ MESA_ASM_SOURCES = # Library/program dependencies EXTRA_LIB_PATH=-L/usr/X11R6/lib +MESA_MODULES = $(TOP)/src/mesa/libmesa.a + LIBDRM_CFLAGS = $(shell pkg-config --cflags libdrm) LIBDRM_LIB = $(shell pkg-config --libs libdrm) -DRI_LIB_DEPS = $(EXTRA_LIB_PATH) -lm -lpthread -lexpat -ldl -ltalloc $(LIBDRM_LIB) +DRI_LIB_DEPS = $(MESA_MODULES) $(EXTRA_LIB_PATH) -lm -lpthread -lexpat -ldl $(LIBDRM_LIB) GL_LIB_DEPS = $(EXTRA_LIB_PATH) -lX11 -lXext -lXxf86vm -lXdamage -lXfixes \ -lm -lpthread -ldl $(LIBDRM_LIB) diff --git a/configs/linux-dri-xcb b/configs/linux-dri-xcb index 8092a048d7c..7518080703b 100644 --- a/configs/linux-dri-xcb +++ b/configs/linux-dri-xcb @@ -41,9 +41,11 @@ MESA_ASM_SOURCES = # Library/program dependencies EXTRA_LIB_PATH=$(shell pkg-config --libs-only-L x11) +MESA_MODULES = $(TOP)/src/mesa/libmesa.a + LIBDRM_CFLAGS = $(shell pkg-config --cflags libdrm) LIBDRM_LIB = $(shell pkg-config --libs libdrm) -DRI_LIB_DEPS = $(EXTRA_LIB_PATH) -lm -lpthread -lexpat -ldl $(LIBDRM_LIB) +DRI_LIB_DEPS = $(MESA_MODULES) $(EXTRA_LIB_PATH) -lm -lpthread -lexpat -ldl $(LIBDRM_LIB) GL_LIB_DEPS = $(EXTRA_LIB_PATH) -lX11 -lXext -lXxf86vm -lm -lpthread -ldl \ $(LIBDRM_LIB) $(shell pkg-config --libs xcb) $(shell pkg-config --libs x11-xcb) $(shell pkg-config --libs xcb-glx) diff --git a/configs/linux-egl b/configs/linux-egl index 6393e942c79..216bcbab321 100644 --- a/configs/linux-egl +++ b/configs/linux-egl @@ -38,9 +38,11 @@ MESA_ASM_SOURCES = # Library/program dependencies EXTRA_LIB_PATH=-L/usr/X11R6/lib +MESA_MODULES = $(TOP)/src/mesa/libmesa.a + LIBDRM_CFLAGS = $(shell pkg-config --cflags libdrm) LIBDRM_LIB = $(shell pkg-config --libs libdrm) -DRI_LIB_DEPS = $(EXTRA_LIB_PATH) -lm -lpthread -lexpat -ldl $(LIBDRM_LIB) +DRI_LIB_DEPS = $(MESA_MODULES) $(EXTRA_LIB_PATH) -lm -lpthread -lexpat -ldl $(LIBDRM_LIB) GL_LIB_DEPS = $(EXTRA_LIB_PATH) -lX11 -lXext -lXxf86vm -lXdamage -lXfixes \ -lm -lpthread -ldl \ $(LIBDRM_LIB) diff --git a/configs/linux-indirect b/configs/linux-indirect index 272d34e8407..507382adced 100644 --- a/configs/linux-indirect +++ b/configs/linux-indirect @@ -42,7 +42,8 @@ MESA_ASM_SOURCES = # Library/program dependencies EXTRA_LIB_PATH=-L/usr/X11R6/lib -DRI_LIB_DEPS = $(EXTRA_LIB_PATH) -lm -lpthread -lexpat -ldl +MESA_MODULES = $(TOP)/src/mesa/libmesa.a +DRI_LIB_DEPS = $(MESA_MODULES) $(EXTRA_LIB_PATH) -lm -lpthread -lexpat -ldl GL_LIB_DEPS = $(EXTRA_LIB_PATH) -lX11 -lXext -lXxf86vm -lm -lpthread -ldl diff --git a/configs/linux-llvm b/configs/linux-llvm index 22de0662ee1..e6999539a17 100644 --- a/configs/linux-llvm +++ b/configs/linux-llvm @@ -41,4 +41,4 @@ else endif LD = g++ -GL_LIB_DEPS = $(LLVM_LDFLAGS) $(LLVM_LIBS) $(EXTRA_LIB_PATH) -lX11 -lXext -lm -lpthread -ltalloc -lstdc++ -ludis86 +GL_LIB_DEPS = $(LLVM_LDFLAGS) $(LLVM_LIBS) $(EXTRA_LIB_PATH) -lX11 -lXext -lm -lpthread -lstdc++ -ludis86 diff --git a/configure.ac b/configure.ac index 2f1e94a7912..19455eed186 100644 --- a/configure.ac +++ b/configure.ac @@ -20,6 +20,7 @@ AC_CANONICAL_HOST dnl Versions for external dependencies LIBDRM_REQUIRED=2.4.23 LIBDRM_RADEON_REQUIRED=2.4.23 +LIBDRM_INTEL_REQUIRED=2.4.23 DRI2PROTO_REQUIRED=2.1 GLPROTO_REQUIRED=1.4.11 LIBDRM_XORG_REQUIRED=2.4.23 @@ -150,9 +151,13 @@ if test "x$GCC" = xyes; then # Enable -fvisibility=hidden if using a gcc that supports it save_CFLAGS="$CFLAGS" AC_MSG_CHECKING([whether $CC supports -fvisibility=hidden]) - CFLAGS="$CFLAGS -fvisibility=hidden" + VISIBILITY_CFLAGS="-fvisibility=hidden" + CFLAGS="$CFLAGS $VISIBILITY_CFLAGS" AC_LINK_IFELSE([AC_LANG_PROGRAM()], AC_MSG_RESULT([yes]), - [CFLAGS="$save_CFLAGS" ; AC_MSG_RESULT([no])]); + [VISIBILITY_CFLAGS=""; AC_MSG_RESULT([no])]); + + # Restore CFLAGS; VISIBILITY_CFLAGS are added to it where needed. + CFLAGS=$save_CFLAGS # Work around aliasing bugs - developers should comment this out CFLAGS="$CFLAGS -fno-strict-aliasing" @@ -163,14 +168,21 @@ if test "x$GXX" = xyes; then # Enable -fvisibility=hidden if using a gcc that supports it save_CXXFLAGS="$CXXFLAGS" AC_MSG_CHECKING([whether $CXX supports -fvisibility=hidden]) - CXXFLAGS="$CXXFLAGS -fvisibility=hidden" + VISIBILITY_CXXFLAGS="-fvisibility=hidden" + CXXFLAGS="$CXXFLAGS $VISIBILITY_CXXFLAGS" AC_LINK_IFELSE([AC_LANG_PROGRAM()], AC_MSG_RESULT([yes]), - [CXXFLAGS="$save_CXXFLAGS" ; AC_MSG_RESULT([no])]); + [VISIBILITY_CXXFLAGS="" ; AC_MSG_RESULT([no])]); + + # Restore CXXFLAGS; VISIBILITY_CXXFLAGS are added to it where needed. + CXXFLAGS=$save_CXXFLAGS # Work around aliasing bugs - developers should comment this out CXXFLAGS="$CXXFLAGS -fno-strict-aliasing" fi +AC_SUBST([VISIBILITY_CFLAGS]) +AC_SUBST([VISIBILITY_CXXFLAGS]) + dnl These should be unnecessary, but let the user set them if they want AC_ARG_VAR([OPT_FLAGS], [Additional optimization flags for the compiler. Default is to use CFLAGS.]) @@ -317,6 +329,7 @@ GLESv1_CM_LIB_NAME='lib$(GLESv1_CM_LIB).'${LIB_EXTENSION} GLESv2_LIB_NAME='lib$(GLESv2_LIB).'${LIB_EXTENSION} VG_LIB_NAME='lib$(VG_LIB).'${LIB_EXTENSION} GLAPI_LIB_NAME='lib$(GLAPI_LIB).'${LIB_EXTENSION} +WAYLAND_EGL_LIB_NAME='lib$(WAYLAND_EGL_LIB).'${LIB_EXTENSION} GL_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GL_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*' GLU_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GLU_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*' @@ -329,6 +342,7 @@ GLESv1_CM_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GLESv1_CM_LIB)'${LIB_VERSION_SEPARATOR}' GLESv2_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GLESv2_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*' VG_LIB_GLOB=${LIB_PREFIX_GLOB}'$(VG_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*' GLAPI_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GLAPI_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*' +WAYLAND_EGL_LIB_GLOB=${LIB_PREFIX_GLOB}'$(WAYLAND_EGL_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*' AC_SUBST([GL_LIB_NAME]) AC_SUBST([GLU_LIB_NAME]) @@ -340,6 +354,7 @@ AC_SUBST([GLESv1_CM_LIB_NAME]) AC_SUBST([GLESv2_LIB_NAME]) AC_SUBST([VG_LIB_NAME]) AC_SUBST([GLAPI_LIB_NAME]) +AC_SUBST([WAYLAND_EGL_LIB_NAME]) AC_SUBST([GL_LIB_GLOB]) AC_SUBST([GLU_LIB_GLOB]) @@ -351,6 +366,7 @@ AC_SUBST([GLESv1_CM_LIB_GLOB]) AC_SUBST([GLESv2_LIB_GLOB]) AC_SUBST([VG_LIB_GLOB]) AC_SUBST([GLAPI_LIB_GLOB]) +AC_SUBST([WAYLAND_EGL_LIB_GLOB]) dnl dnl Arch/platform-specific settings @@ -582,10 +598,6 @@ xno) ;; esac -PKG_CHECK_MODULES([TALLOC], [talloc]) -AC_SUBST([TALLOC_LIBS]) -AC_SUBST([TALLOC_CFLAGS]) - dnl dnl Driver specific build directories dnl @@ -602,7 +614,7 @@ GALLIUM_DRIVERS_DIRS="softpipe failover galahad trace rbug noop identity" GALLIUM_STATE_TRACKERS_DIRS="" # build shared-glapi if enabled for OpenGL or if OpenGL ES is enabled -case "x$enabled_shared_glapi$enable_gles1$enable_gles2" in +case "x$enable_shared_glapi$enable_gles1$enable_gles2" in x*yes*) CORE_DIRS="$CORE_DIRS mapi/shared-glapi" ;; @@ -734,8 +746,8 @@ xlib) GL_PC_LIB_PRIV="$GL_LIB_DEPS" GL_PC_CFLAGS="$X11_INCLUDES" fi - GL_LIB_DEPS="$GL_LIB_DEPS $SELINUX_LIBS -lm -lpthread $TALLOC_LIBS" - GL_PC_LIB_PRIV="$GL_PC_LIB_PRIV $SELINUX_LIBS -lm -lpthread $TALLOC_LIBS" + GL_LIB_DEPS="$GL_LIB_DEPS $SELINUX_LIBS -lm -lpthread" + GL_PC_LIB_PRIV="$GL_PC_LIB_PRIV $SELINUX_LIBS -lm -lpthread" # if static, move the external libraries to the programs # and empty the libraries for libGL @@ -818,10 +830,45 @@ AC_SUBST([GLESv2_PC_LIB_PRIV]) GLAPI_LIB_DEPS="-lpthread" AC_SUBST([GLAPI_LIB_DEPS]) + +dnl Setup default DRI CFLAGS +DRI_CFLAGS='$(CFLAGS)' +DRI_CXXFLAGS='$(CXXFLAGS)' +DRI_LIB_DEPS='$(TOP)/src/mesa/libmesa.a' +MESA_MODULES='$(TOP)/src/mesa/libmesa.a' + +AC_ARG_ENABLE([shared-dricore], + [AS_HELP_STRING([--enable-shared-dricore], + [link DRI modules with shared core DRI routines @<:@default=disabled@:>@])], + [enable_dricore="$enableval"], + [enable_dricore=no]) +if test "$mesa_driver" = dri ; then + if test "$enable_dricore" = yes ; then + if test "$GCC$GXX" != yesyes ; then + AC_MSG_WARN([Shared dricore requires GCC-compatible rpath handling. Disabling shared dricore]) + enable_dricore=no + else + DRICORE_GLSL_LIBS='$(TOP)/$(LIB_DIR)/libglsl.so' + DRICORE_LIBS='$(TOP)/$(LIB_DIR)/libdricore.so' + DRICORE_LIB_DEPS='-L$(TOP)/$(LIB_DIR) -Wl,-R$(DRI_DRIVER_INSTALL_DIR) -lglsl' + DRI_LIB_DEPS='-L$(TOP)/$(LIB_DIR) -Wl,-R$(DRI_DRIVER_INSTALL_DIR) -ldricore -lglsl' + DRI_CFLAGS='$(CFLAGS_NOVISIBILITY) -DUSE_DRICORE' + DRI_CXXFLAGS='$(CXXFLAGS_NOVISIBILITY) -DUSE_DRICORE' + MESA_MODULES='$(DRICORE_LIBS) $(DRICORE_GLSL_LIBS)' + fi + fi +fi +AC_SUBST([DRICORE_LIBS]) +AC_SUBST([DRICORE_GLSL_LIBS]) +AC_SUBST([DRICORE_LIB_DEPS]) +AC_SUBST([DRI_CXXFLAGS]) +AC_SUBST([DRI_CFLAGS]) +AC_SUBST([MESA_MODULES]) + AC_SUBST([HAVE_XF86VIDMODE]) PKG_CHECK_MODULES([LIBDRM_RADEON], - [libdrm_radeon libdrm >= $LIBDRM_RADEON_REQUIRED], + [libdrm_radeon >= $LIBDRM_RADEON_REQUIRED], HAVE_LIBDRM_RADEON=yes, HAVE_LIBDRM_RADEON=no) @@ -843,6 +890,9 @@ AC_ARG_ENABLE([glx-tls], [GLX_USE_TLS=no]) AC_SUBST(GLX_TLS, ${GLX_USE_TLS}) +AS_IF([test "x$GLX_USE_TLS" = xyes], + [DEFINES="${DEFINES} -DGLX_USE_TLS -DPTHREADS"]) + dnl dnl More DRI setup dnl @@ -898,11 +948,6 @@ esac dnl Set DRI_DIRS, DEFINES and LIB_DEPS if test "$mesa_driver" = dri -o "$mesa_driver" = no; then - # Use TLS in GLX? - if test "x$GLX_USE_TLS" = xyes; then - DEFINES="$DEFINES -DGLX_USE_TLS -DPTHREADS" - fi - # Platform specific settings and drivers to build case "$host_os" in linux*) @@ -988,8 +1033,8 @@ if test "$mesa_driver" = dri -o "$mesa_driver" = no; then [AC_MSG_ERROR([Expat required for DRI.])]) fi - # put all the necessary libs together - DRI_LIB_DEPS="$SELINUX_LIBS $LIBDRM_LIBS $EXPAT_LIB -lm -lpthread $DLOPEN_LIBS $TALLOC_LIBS" + # put all the necessary libs together, including possibly libdricore + DRI_LIB_DEPS="$DRI_LIB_DEPS $SELINUX_LIBS $LIBDRM_LIBS $EXPAT_LIB -lm -lpthread $DLOPEN_LIBS" fi AC_SUBST([DRI_DIRS]) AC_SUBST([EXPAT_INCLUDES]) @@ -997,7 +1042,7 @@ AC_SUBST([DRI_LIB_DEPS]) case $DRI_DIRS in *i915*|*i965*) - PKG_CHECK_MODULES([INTEL], [libdrm_intel >= 2.4.23]) + PKG_CHECK_MODULES([INTEL], [libdrm_intel >= $LIBDRM_INTEL_REQUIRED]) ;; esac @@ -1065,12 +1110,12 @@ case "$DRIVER_DIRS" in *osmesa*) # only link libraries with osmesa if shared if test "$enable_static" = no; then - OSMESA_LIB_DEPS="-lm -lpthread $SELINUX_LIBS $DLOPEN_LIBS $TALLOC_LIBS" + OSMESA_LIB_DEPS="-lm -lpthread $SELINUX_LIBS $DLOPEN_LIBS" else OSMESA_LIB_DEPS="" fi OSMESA_MESA_DEPS="" - OSMESA_PC_LIB_PRIV="-lm -lpthread $SELINUX_LIBS $DLOPEN_LIBS $TALLOC_LIBS" + OSMESA_PC_LIB_PRIV="-lm -lpthread $SELINUX_LIBS $DLOPEN_LIBS" ;; esac AC_SUBST([OSMESA_LIB_DEPS]) @@ -1539,6 +1584,8 @@ AC_ARG_WITH([egl-displays], [with_egl_platforms="$withval"]) EGL_PLATFORMS="" +WAYLAND_EGL_LIB_DEPS="" + case "$with_egl_platforms" in yes) if test "x$enable_egl" = xyes && test "x$mesa_driver" != xosmesa; then @@ -1556,16 +1603,31 @@ yes) egl_platforms=`IFS=', '; echo $with_egl_platforms` for plat in $egl_platforms; do test -d "$srcdir/src/gallium/state_trackers/egl/$plat" || \ - AC_MSG_ERROR([EGL platform '$plat' does't exist]) + AC_MSG_ERROR([EGL platform '$plat' doesn't exist]) if test "$plat" = "fbdev"; then GALLIUM_WINSYS_DIRS="$GALLIUM_WINSYS_DIRS sw/fbdev" fi + if test "$plat" = "wayland"; then + PKG_CHECK_MODULES([WAYLAND], [wayland-client],, \ + [AC_MSG_ERROR([cannot find libwayland-client])]) + WAYLAND_EGL_LIB_DEPS="$WAYLAND_LIBS $LIBDRM_LIBS" + fi done EGL_PLATFORMS="$egl_platforms" ;; esac AC_SUBST([EGL_PLATFORMS]) +AC_SUBST([WAYLAND_EGL_LIB_DEPS]) +WAYLAND_EGL_PC_REQ_PRIV="wayland-client libdrm" +WAYLAND_EGL_PC_LIB_PRIV= +WAYLAND_EGL_PC_CFLAGS= + +AC_SUBST([WAYLAND_EGL_PC_REQ_PRIV]) +AC_SUBST([WAYLAND_EGL_PC_LIB_PRIV]) +AC_SUBST([WAYLAND_EGL_PC_CFLAGS]) + + AC_ARG_WITH([egl-driver-dir], [AS_HELP_STRING([--with-egl-driver-dir=DIR], [directory for EGL drivers [[default=${libdir}/egl]]])], @@ -1705,20 +1767,12 @@ AC_ARG_ENABLE([gallium-radeon], [enable_gallium_radeon="$enableval"], [enable_gallium_radeon=auto]) if test "x$enable_gallium_radeon" = xauto; then - if test "x$HAVE_LIBDRM_RADEON" = xyes; then - GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS r300" - gallium_check_st "radeon/drm" "dri-r300" - else - AC_MSG_WARN([libdrm_radeon is missing, not building gallium-radeon (r300)]) - fi + GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS r300" + gallium_check_st "radeon/drm" "dri-r300" fi if test "x$enable_gallium_radeon" = xyes; then - if test "x$HAVE_LIBDRM_RADEON" = xyes; then - GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS r300" - gallium_check_st "radeon/drm" "dri-r300" "xorg-radeon" - else - AC_MSG_ERROR([libdrm_radeon is missing, cannot build gallium-radeon (r300)]) - fi + GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS r300" + gallium_check_st "radeon/drm" "dri-r300" "xorg-radeon" fi dnl @@ -1730,12 +1784,8 @@ AC_ARG_ENABLE([gallium-r600], [enable_gallium_r600="$enableval"], [enable_gallium_r600=auto]) if test "x$enable_gallium_r600" = xyes; then - if test "x$HAVE_LIBDRM_RADEON" = xyes; then - GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS r600" - gallium_check_st "r600/drm" "dri-r600" "xvmc-r600" "va-r600" - else - AC_MSG_ERROR([libdrm_radeon is missing, cannot build gallium-r600]) - fi + GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS r600" + gallium_check_st "r600/drm" "dri-r600" "xvmc-r600" fi dnl @@ -1860,6 +1910,7 @@ if test "$mesa_driver" != no; then fi echo " DRI driver dir: $DRI_DRIVER_INSTALL_DIR" echo " Use XCB: $enable_xcb" + echo " Shared dricore: $enable_dricore" fi fi echo "" diff --git a/docs/GL3.txt b/docs/GL3.txt index 93bd56d2c4c..9ff25a95297 100644 --- a/docs/GL3.txt +++ b/docs/GL3.txt @@ -15,10 +15,13 @@ GL 3.0: GLSL changes (GL_EXT_gpu_shader4, etc) not started Conditional rendering (GL_NV_conditional_render) DONE (swrast & softpipe) Map buffer subranges (GL_ARB_map_buffer_range) DONE -Float textures, renderbuffers some infrastructure done - (incl. GL_EXT_packed_float, GL_EXT_shared_exponent) +Clamping controls (GL_ARB_color_buffer_float) BRANCH ~mareko/mesa floating2 +Float textures, renderbuffers (GL_ARB_texture_float) BRANCH ~mareko/mesa floating2 +GL_EXT_packed_float not started +GL_EXT_texture_shared_exponent not started +Float depth buffers (GL_ARB_depth_buffer_float) not started Framebuffer objects (GL_EXT_framebuffer_object) DONE -Half-float some infrastructure done +Half-float DONE Multisample blit DONE Non-normalized Integer texture/framebuffer formats ~50% done 1D/2D Texture arrays core Mesa, swrast done @@ -30,7 +33,7 @@ Transform feedback (GL_EXT_transform_feedback) ~50% done glBindFragDataLocation, glGetFragDataLocation, glBindBufferRange, glBindBufferBase commands Vertex array objects (GL_APPLE_vertex_array_object) DONE -sRGB framebuffer format (GL_EXT_framebuffer_sRGB) not started +sRGB framebuffer format (GL_EXT_framebuffer_sRGB) core GL done (i965, gallium), GLX todo glClearBuffer commands DONE glGetStringi command DONE glTexParameterI, glGetTexParameterI commands DONE @@ -48,7 +51,7 @@ Primitive restart (GL_NV_primitive_restart) DONE (gallium) Texture buffer objs (GL_ARB_texture_buffer_object) not started Rectangular textures (GL_ARB_texture_rectangle) DONE Uniform buffer objs (GL_ARB_uniform_buffer_object) not started -Signed normalized texture formats ~50% done +Signed normalized textures (GL_EXT_texture_snorm) ~50% done GL 3.2: diff --git a/docs/envvars.html b/docs/envvars.html index fd1700a02f1..c8be8437176 100644 --- a/docs/envvars.html +++ b/docs/envvars.html @@ -9,17 +9,38 @@ <H1>Environment Variables</H1> <p> -Mesa supports the following environment variables: +Normally, no environment variables need to be set. Most of the environment +variables used by Mesa/Gallium are for debugging purposes, but they can +sometimes be useful for debugging end-user issues. </p> + + +<H2>LibGL environment variables</H2> + +<ul> +<li>LIBGL_DEBUG - If defined debug information will be printed to stderr. + If set to 'verbose' additional information will be printed. +<li>LIBGL_DRIVERS_PATH - colon-separated list of paths to search for DRI drivers +<li>LIBGL_ALWAYS_INDIRECT - forces an indirect rendering context/connection. +<li>LIBGL_ALWAYS_SOFTWARE - if set, always use software rendering +<li>LIBGL_NO_DRAWARRAYS - if set do not use DrawArrays GLX protocol (for debugging) +</ul> + + + +<H2>Core Mesa environment variables</H2> + <ul> <li>MESA_NO_ASM - if set, disables all assembly language optimizations <li>MESA_NO_MMX - if set, disables Intel MMX optimizations <li>MESA_NO_3DNOW - if set, disables AMD 3DNow! optimizations <li>MESA_NO_SSE - if set, disables Intel SSE optimizations -<li>MESA_DEBUG - if set, error messages are printed to stderr. -If the value of MESA_DEBUG is "FP" floating point arithmetic errors will -generate exceptions. -<li>MESA_NO_DITHER - if set, disables dithering, overriding glEnable(GL_DITHER) +<li>MESA_DEBUG - if set, error messages are printed to stderr. For example, + if the application generates a GL_INVALID_ENUM error, a corresponding error + message indicating where the error occured, and possibly why, will be + printed to stderr.<br> + If the value of MESA_DEBUG is 'FP' floating point arithmetic errors will + generate exceptions. <li>MESA_TEX_PROG - if set, implement conventional texture env modes with fragment programs (intended for developers only) <li>MESA_TNL_PROG - if set, implement conventional vertex transformation @@ -28,11 +49,14 @@ Setting this variable automatically sets the MESA_TEX_PROG variable as well. <li>MESA_EXTENSION_OVERRIDE - can be used to enable/disable extensions. A value such as "GL_EXT_foo -GL_EXT_bar" will enable the GL_EXT_foo extension and disable the GL_EXT_bar extension. -<li>MESA_GLSL - <a href="shading.html#envvars">shading language options</a> +<li>MESA_GLSL - <a href="shading.html#envvars">shading language compiler options</a> </ul> + +<H2>Mesa Xlib driver environment variables</H2> + <p> -The following are only applicable to the Xlib software driver. +The following are only applicable to the Mesa Xlib software driver. See the <A HREF="xlibdriver.html">Xlib software driver page</A> for details. </p> <ul> @@ -51,9 +75,8 @@ See the <A HREF="xlibdriver.html">Xlib software driver page</A> for details. </ul> -<p> -These environment variables are for the Intel i945/i965 drivers: -</p> +<h2>i945/i965 driver environment variables (non-Gallium)</h2> + <ul> <li>INTEL_STRICT_CONFORMANCE - if set to 1, enable sw fallbacks to improve OpenGL conformance. If set to 2, always use software rendering. @@ -62,17 +85,71 @@ These environment variables are for the Intel i945/i965 drivers: </ul> -<p> -These environment variables are for the Radeon R300 driver: -</p> +<h2>Radeon R300 driver environment variables (non-Gallium)</h2> + <ul> <li>R300_NO_TCL - if set, disable hardware-accelerated Transform/Clip/Lighting. </ul> + +<h2>EGL environment variables</h2> + <p> Mesa EGL supports different sets of environment variables. See the <a href="egl.html">Mesa EGL</a> page for the details. </p> + +<h2>Gallium environment variables</h2> + +<ul> +<li>GALLIUM_PRINT_OPTIONS - if non-zero, print all the Gallium environment + variables which are used, and their current values. +<li>GALLIUM_NOSSE - if non-zero, do not use SSE runtime code generation for + shader execution +<li>GALLIUM_NOPPC - if non-zero, do not use PPC runtime code generation for + shader execution +<li>GALLIUM_DUMP_CPU - if non-zero, print information about the CPU on start-up +<li>TGSI_PRINT_SANITY - if set, do extra sanity checking on TGSI shaders and + print any errors to stderr. +<LI>DRAW_FSE - ??? +<LI>DRAW_NO_FSE - ??? +<li>DRAW_USE_LLVM - if set to zero, the draw module will not use LLVM to execute + shaders, vertex fetch, etc. +</ul> + +<h3>Softpipe driver environment variables</h3> +<ul> +<li>SOFTPIPE_DUMP_FS - if set, the softpipe driver will print fragment shaders + to stderr +<li>SOFTPIPE_DUMP_GS - if set, the softpipe driver will print geometry shaders + to stderr +<li>SOFTPIPE_NO_RAST - if set, rasterization is no-op'd. For profiling purposes. +</ul> + + +<h3>LLVMpipe driver environment variables</h3> +<ul> +<li>LP_NO_RAST - if set LLVMpipe will no-op rasterization +<li>LP_DEBUG - a comma-separated list of debug options is acceptec. See the + source code for details. +<li>LP_PERF - a comma-separated list of options to selectively no-op various + parts of the driver. See the source code for details. +<li>LP_NUM_THREADS - an integer indicating how many threads to use for rendering. + Zero turns of threading completely. The default value is the number of CPU + cores present. +</ul> + + +<p> +Other Gallium drivers have their own environment variables. These may change +frequently so the source code should be consulted for details. +</p> + + +<br> +<br> + + </BODY> </HTML> diff --git a/docs/relnotes-7.11.html b/docs/relnotes-7.11.html index b0350a22f38..6c6622ed3f4 100644 --- a/docs/relnotes-7.11.html +++ b/docs/relnotes-7.11.html @@ -49,8 +49,10 @@ tbd <h2>Changes</h2> - -<p>tbd</p> +<ul> +<li>The Windows MSVC project files have been removed. They haven't been maintained +in quite a while. Building with SCons is an alterantive. +</ul> </body> diff --git a/docs/shading.html b/docs/shading.html index c41d4a9be2b..aba39597429 100644 --- a/docs/shading.html +++ b/docs/shading.html @@ -167,7 +167,7 @@ Here's an example of using the compiler to compile a vertex shader and emit GL_ARB_vertex_program-style instructions: </p> <pre> - src/glsl/glslcompiler --dump-ast myshader.vert + src/glsl/glsl_compiler --dump-ast myshader.vert </pre> Options include diff --git a/docs/sourcetree.html b/docs/sourcetree.html index 00dc4e7c9f4..08a9a50e9ec 100644 --- a/docs/sourcetree.html +++ b/docs/sourcetree.html @@ -23,6 +23,7 @@ each directory. <ul> <li><b>docs</b> - EGL documentation <li><b>drivers</b> - EGL drivers + <li><b>glsl</b> - the GLSL compiler <li><b>main</b> - main EGL library implementation. This is where all the EGL API functions are implemented, like eglCreateContext(). </ul> diff --git a/include/EGL/eglplatform.h b/include/EGL/eglplatform.h index 33a3e5f8891..005b2944404 100644 --- a/include/EGL/eglplatform.h +++ b/include/EGL/eglplatform.h @@ -78,6 +78,12 @@ typedef int EGLNativeDisplayType; typedef void *EGLNativeWindowType; typedef void *EGLNativePixmapType; +#elif defined(WL_EGL_PLATFORM) + +typedef struct wl_egl_display *EGLNativeDisplayType; +typedef struct wl_egl_pixmap *EGLNativePixmapType; +typedef struct wl_egl_window *EGLNativeWindowType; + #elif defined(__unix__) || defined(__unix) #ifdef MESA_EGL_NO_X11_HEADERS diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h index 39aa68bc8ca..2fb729afcdf 100644 --- a/include/GL/internal/dri_interface.h +++ b/include/GL/internal/dri_interface.h @@ -499,6 +499,7 @@ struct __DRIuseInvalidateExtensionRec { #define __DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE 45 #define __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS 46 #define __DRI_ATTRIB_YINVERTED 47 +#define __DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE 48 /* __DRI_ATTRIB_RENDER_TYPE */ #define __DRI_ATTRIB_RGBA_BIT 0x01 @@ -656,7 +657,7 @@ struct __DRIlegacyExtensionRec { * conjunction with the core extension. */ #define __DRI_SWRAST "DRI_SWRast" -#define __DRI_SWRAST_VERSION 1 +#define __DRI_SWRAST_VERSION 2 struct __DRIswrastExtensionRec { __DRIextension base; @@ -669,6 +670,13 @@ struct __DRIswrastExtensionRec { __DRIdrawable *(*createNewDrawable)(__DRIscreen *screen, const __DRIconfig *config, void *loaderPrivate); + + /* Since version 2 */ + __DRIcontext *(*createNewContextForAPI)(__DRIscreen *screen, + int api, + const __DRIconfig *config, + __DRIcontext *shared, + void *data); }; /** @@ -778,6 +786,14 @@ struct __DRIdri2ExtensionRec { const __DRIconfig *config, __DRIcontext *shared, void *data); + + __DRIbuffer *(*allocateBuffer)(__DRIscreen *screen, + unsigned int attachment, + unsigned int format, + int width, + int height); + void (*releaseBuffer)(__DRIscreen *screen, + __DRIbuffer *buffer); }; diff --git a/scons/crossmingw.py b/scons/crossmingw.py index 8af0d93f01a..cc046229e2c 100644 --- a/scons/crossmingw.py +++ b/scons/crossmingw.py @@ -194,5 +194,8 @@ def generate(env): env.AppendUnique(SHLINKFLAGS = ['-Wl,--enable-stdcall-fixup']) #env.AppendUnique(SHLINKFLAGS = ['-Wl,--kill-at']) + # Avoid depending on gcc runtime DLLs + env.AppendUnique(LINKFLAGS = ['-static-libgcc']) + def exists(env): return find(env) diff --git a/scons/gallium.py b/scons/gallium.py index 75e9b9e7fc3..9118257ac05 100644..100755 --- a/scons/gallium.py +++ b/scons/gallium.py @@ -35,6 +35,7 @@ import os import os.path import re import subprocess +import platform as _platform import SCons.Action import SCons.Builder @@ -141,6 +142,10 @@ def pkg_config_modules(env, name, modules): def generate(env): """Common environment generation code""" + # Tell tools which machine to compile for + env['TARGET_ARCH'] = env['machine'] + env['MSVS_ARCH'] = env['machine'] + # Toolchain platform = env['platform'] if env['toolchain'] == 'default': @@ -175,6 +180,10 @@ def generate(env): env['gcc'] = 'gcc' in os.path.basename(env['CC']).split('-') env['msvc'] = env['CC'] == 'cl' + if env['msvc'] and env['toolchain'] == 'default' and env['machine'] == 'x86_64': + # MSVC x64 support is broken in earlier versions of scons + env.EnsurePythonVersion(2, 0) + # shortcuts machine = env['machine'] platform = env['platform'] @@ -183,6 +192,25 @@ def generate(env): gcc = env['gcc'] msvc = env['msvc'] + # Determine whether we are cross compiling; in particular, whether we need + # to compile code generators with a different compiler as the target code. + host_platform = _platform.system().lower() + host_machine = os.environ.get('PROCESSOR_ARCHITEW6432', os.environ.get('PROCESSOR_ARCHITECTURE', _platform.machine())) + host_machine = { + 'x86': 'x86', + 'i386': 'x86', + 'i486': 'x86', + 'i586': 'x86', + 'i686': 'x86', + 'ppc' : 'ppc', + 'AMD64': 'x86_64', + 'x86_64': 'x86_64', + }.get(host_machine, 'generic') + env['crosscompile'] = platform != host_platform + if machine == 'x86_64' and host_machine != 'x86_64': + env['crosscompile'] = True + env['hostonly'] = False + # Backwards compatability with the debug= profile= options if env['build'] == 'debug': if not env['debug']: @@ -349,12 +377,15 @@ def generate(env): '-m32', #'-march=pentium4', ] - if distutils.version.LooseVersion(ccversion) >= distutils.version.LooseVersion('4.2'): + if distutils.version.LooseVersion(ccversion) >= distutils.version.LooseVersion('4.2') \ + and (platform != 'windows' or env['build'] == 'debug' or True): # NOTE: We need to ensure stack is realigned given that we # produce shared objects, and have no control over the stack # alignment policy of the application. Therefore we need # -mstackrealign ore -mincoming-stack-boundary=2. # + # XXX: -O and -mstackrealign causes stack corruption on MinGW + # # XXX: We could have SSE without -mstackrealign if we always used # __attribute__((force_align_arg_pointer)), but that's not # always the case. @@ -402,13 +433,19 @@ def generate(env): '/Od', # disable optimizations '/Oi', # enable intrinsic functions '/Oy-', # disable frame pointer omission - '/GL-', # disable whole program optimization ] else: ccflags += [ '/O2', # optimize for speed + ] + if env['build'] == 'release': + ccflags += [ '/GL', # enable whole program optimization ] + else: + ccflags += [ + '/GL-', # disable whole program optimization + ] ccflags += [ '/fp:fast', # fast floating point '/W3', # warning level @@ -498,7 +535,7 @@ def generate(env): else: env['_LIBFLAGS'] = '-Wl,--start-group ' + env['_LIBFLAGS'] + ' -Wl,--end-group' if msvc: - if env['build'] != 'debug': + if env['build'] == 'release': # enable Link-time Code Generation linkflags += ['/LTCG'] env.Append(ARFLAGS = ['/LTCG']) @@ -551,6 +588,10 @@ def generate(env): env.Append(LINKFLAGS = linkflags) env.Append(SHLINKFLAGS = shlinkflags) + # We have C++ in several libraries, so always link with the C++ compiler + if env['gcc']: + env['LINK'] = env['CXX'] + # Default libs env.Append(LIBS = []) diff --git a/scons/llvm.py b/scons/llvm.py index 1b033acb1b3..3fef9e0900d 100644 --- a/scons/llvm.py +++ b/scons/llvm.py @@ -147,8 +147,6 @@ def generate(env): except OSError: print 'scons: llvm-config version %s failed' % llvm_version return - else: - env['LINK'] = env['CXX'] assert llvm_version is not None env['llvm'] = True diff --git a/src/SConscript b/src/SConscript index 201812c5ac3..f11894f2990 100644 --- a/src/SConscript +++ b/src/SConscript @@ -1,13 +1,21 @@ Import('*') + if env['platform'] == 'windows': SConscript('getopt/SConscript') - SConscript('talloc/SConscript') -else: - talloc = 'talloc' - Export('talloc') SConscript('glsl/SConscript') + +if env['hostonly']: + # We are just compiling the things necessary on the host for cross + # compilation + Return() + + +# When env['gles'] is set, the targets defined in mapi/glapi/SConscript are not +# used. libgl-xlib and libgl-gdi adapt themselves to use the targets defined +# in mapi/glapi-shared/SConscript. mesa/SConscript also adapts itself to +# enable OpenGL ES support. SConscript('mapi/glapi/SConscript') SConscript('mesa/SConscript') @@ -17,5 +25,8 @@ if env['platform'] != 'embedded': SConscript('egl/main/SConscript') SConscript('glut/glx/SConscript') + if env['gles']: + SConscript('mapi/shared-glapi/SConscript') + SConscript('gallium/SConscript') diff --git a/src/egl/Makefile b/src/egl/Makefile index 50f227f07da..52daf2efa7e 100644 --- a/src/egl/Makefile +++ b/src/egl/Makefile @@ -5,6 +5,10 @@ include $(TOP)/configs/current SUBDIRS = drivers main +ifneq ($(findstring wayland, $(EGL_PLATFORMS)),) +SUBDIRS += wayland +endif + default: subdirs diff --git a/src/egl/drivers/dri2/Makefile b/src/egl/drivers/dri2/Makefile index 553ee8771f8..89e9dd7970a 100644 --- a/src/egl/drivers/dri2/Makefile +++ b/src/egl/drivers/dri2/Makefile @@ -4,7 +4,7 @@ TOP = ../../../.. include $(TOP)/configs/current EGL_DRIVER = egl_dri2 -EGL_SOURCES = egl_dri2.c +EGL_SOURCES = egl_dri2.c platform_x11.c platform_drm.c EGL_INCLUDES = \ -I$(TOP)/include \ @@ -20,4 +20,15 @@ EGL_LIBS = $(XCB_DRI2_LIBS) $(LIBUDEV_LIBS) $(DLOPEN_LIBS) $(LIBDRM_LIB) EGL_CFLAGS = -D_EGL_MAIN=_eglBuiltInDriverDRI2 EGL_BUILTIN = true +ifeq ($(SHARED_GLAPI),1) +EGL_CFLAGS += -DHAVE_SHARED_GLAPI +endif + +ifneq ($(findstring wayland, $(EGL_PLATFORMS)),) +EGL_SOURCES += platform_wayland.c +EGL_INCLUDES += -DHAVE_WAYLAND_PLATFORM $(WAYLAND_CFLAGS) \ + -I$(TOP)/src/egl/wayland +EGL_LIBS += $(WAYLAND_LIBS) +endif + include ../Makefile.template diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c index 6fc1e49e773..99f87f076c1 100644 --- a/src/egl/drivers/dri2/egl_dri2.c +++ b/src/egl/drivers/dri2/egl_dri2.c @@ -36,93 +36,12 @@ #include <xf86drm.h> #include <GL/gl.h> #include <GL/internal/dri_interface.h> -#include <xcb/xcb.h> -#include <xcb/dri2.h> -#include <xcb/xfixes.h> -#include <X11/Xlib-xcb.h> #include <sys/types.h> #include <sys/stat.h> -#ifdef HAVE_LIBUDEV -#include <libudev.h> -#endif - -#include "eglconfig.h" -#include "eglcontext.h" -#include "egldisplay.h" -#include "egldriver.h" -#include "eglcurrent.h" -#include "egllog.h" -#include "eglsurface.h" -#include "eglimage.h" - -#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) - -struct dri2_egl_driver -{ - _EGLDriver base; - - _EGLProc (*get_proc_address)(const char *procname); - void (*glFlush)(void); -}; - -struct dri2_egl_display -{ - xcb_connection_t *conn; - int dri2_major; - int dri2_minor; - __DRIscreen *dri_screen; - const __DRIconfig **driver_configs; - void *driver; - __DRIcoreExtension *core; - __DRIdri2Extension *dri2; - __DRI2flushExtension *flush; - __DRItexBufferExtension *tex_buffer; - __DRIimageExtension *image; - int fd; - - char *device_name; - char *driver_name; - - __DRIdri2LoaderExtension loader_extension; - const __DRIextension *extensions[3]; -}; - -struct dri2_egl_context -{ - _EGLContext base; - __DRIcontext *dri_context; -}; - -struct dri2_egl_surface -{ - _EGLSurface base; - __DRIdrawable *dri_drawable; - xcb_drawable_t drawable; - __DRIbuffer buffers[5]; - int buffer_count; - xcb_xfixes_region_t region; - int have_fake_front; - int swap_interval; -}; - -struct dri2_egl_config -{ - _EGLConfig base; - const __DRIconfig *dri_config; -}; - -struct dri2_egl_image -{ - _EGLImage base; - __DRIimage *dri_image; -}; - -/* standard typecasts */ -_EGL_DRIVER_STANDARD_TYPECASTS(dri2_egl) -_EGL_DRIVER_TYPECAST(dri2_egl_image, _EGLImage, obj) +#include "egl_dri2.h" -static const __DRIuseInvalidateExtension use_invalidate = { +const __DRIuseInvalidateExtension use_invalidate = { { __DRI_USE_INVALIDATE, 1 } }; @@ -177,15 +96,18 @@ EGLint dri2_to_egl_attribute_map[] = { EGL_Y_INVERTED_NOK, /* __DRI_ATTRIB_YINVERTED */ }; -static struct dri2_egl_config * +struct dri2_egl_config * dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id, - int depth, EGLint surface_type) + int depth, EGLint surface_type, const EGLint *attr_list) { struct dri2_egl_config *conf; struct dri2_egl_display *dri2_dpy; _EGLConfig base; unsigned int attrib, value, double_buffer; EGLint key, bind_to_texture_rgb, bind_to_texture_rgba; + _EGLConfig *matching_config; + EGLint num_configs = 0; + EGLint config_id; int i; dri2_dpy = disp->DriverData; @@ -238,15 +160,9 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id, } } - /* In EGL, double buffer or not isn't a config attribute. Pixmaps - * surfaces are always single buffered, pbuffer surfaces are always - * back buffers and windows can be either, selected by passing an - * attribute at window surface construction time. To support this - * we ignore all double buffer configs and manipulate the buffer we - * return in the getBuffer callback to get the behaviour we want. */ - - if (double_buffer) - return NULL; + if (attr_list) + for (i = 0; attr_list[i] != EGL_NONE; i += 2) + _eglSetConfigKey(&base, attr_list[i], attr_list[i+1]); if (depth > 0 && depth != base.BufferSize) return NULL; @@ -254,7 +170,8 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id, base.NativeRenderable = EGL_TRUE; base.SurfaceType = surface_type; - if (surface_type & (EGL_PIXMAP_BIT | EGL_PBUFFER_BIT)) { + if (surface_type & (EGL_PBUFFER_BIT | + (disp->Extensions.NOK_texture_from_pixmap ? EGL_PIXMAP_BIT : 0))) { base.BindToTextureRGB = bind_to_texture_rgb; if (base.AlphaSize > 0) base.BindToTextureRGBA = bind_to_texture_rgba; @@ -268,110 +185,49 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id, return NULL; } - conf = malloc(sizeof *conf); - if (conf != NULL) { - memcpy(&conf->base, &base, sizeof base); - conf->dri_config = dri_config; - _eglLinkConfig(&conf->base); - } + config_id = base.ConfigID; + base.ConfigID = EGL_DONT_CARE; + base.SurfaceType = EGL_DONT_CARE; + num_configs = _eglFilterArray(disp->Configs, (void **) &matching_config, 1, + (_EGLArrayForEach) _eglMatchConfig, &base); - return conf; -} + if (num_configs == 1) { + conf = (struct dri2_egl_config *) matching_config; -/** - * Process list of buffer received from the server - * - * Processes the list of buffers received in a reply from the server to either - * \c DRI2GetBuffers or \c DRI2GetBuffersWithFormat. - */ -static void -dri2_process_buffers(struct dri2_egl_surface *dri2_surf, - xcb_dri2_dri2_buffer_t *buffers, unsigned count) -{ - struct dri2_egl_display *dri2_dpy = - dri2_egl_display(dri2_surf->base.Resource.Display); - xcb_rectangle_t rectangle; - unsigned i; - - dri2_surf->buffer_count = count; - dri2_surf->have_fake_front = 0; - - /* This assumes the DRI2 buffer attachment tokens matches the - * __DRIbuffer tokens. */ - for (i = 0; i < count; i++) { - dri2_surf->buffers[i].attachment = buffers[i].attachment; - dri2_surf->buffers[i].name = buffers[i].name; - dri2_surf->buffers[i].pitch = buffers[i].pitch; - dri2_surf->buffers[i].cpp = buffers[i].cpp; - dri2_surf->buffers[i].flags = buffers[i].flags; - - /* We only use the DRI drivers single buffer configs. This - * means that if we try to render to a window, DRI2 will give us - * the fake front buffer, which we'll use as a back buffer. - * Note that EGL doesn't require that several clients rendering - * to the same window must see the same aux buffers. */ - if (dri2_surf->buffers[i].attachment == __DRI_BUFFER_FAKE_FRONT_LEFT) - dri2_surf->have_fake_front = 1; + if (double_buffer && !conf->dri_double_config) + conf->dri_double_config = dri_config; + else if (!double_buffer && !conf->dri_single_config) + conf->dri_single_config = dri_config; + else + /* a similar config type is already added + * => attach it as new config + */ + num_configs = 0; } - if (dri2_surf->region != XCB_NONE) - xcb_xfixes_destroy_region(dri2_dpy->conn, dri2_surf->region); + if (num_configs == 0) { + conf = malloc(sizeof *conf); + if (conf == NULL) + return NULL; - rectangle.x = 0; - rectangle.y = 0; - rectangle.width = dri2_surf->base.Width; - rectangle.height = dri2_surf->base.Height; - dri2_surf->region = xcb_generate_id(dri2_dpy->conn); - xcb_xfixes_create_region(dri2_dpy->conn, dri2_surf->region, 1, &rectangle); -} - -static __DRIbuffer * -dri2_get_buffers(__DRIdrawable * driDrawable, - int *width, int *height, - unsigned int *attachments, int count, - int *out_count, void *loaderPrivate) -{ - struct dri2_egl_surface *dri2_surf = loaderPrivate; - struct dri2_egl_display *dri2_dpy = - dri2_egl_display(dri2_surf->base.Resource.Display); - xcb_dri2_dri2_buffer_t *buffers; - xcb_dri2_get_buffers_reply_t *reply; - xcb_dri2_get_buffers_cookie_t cookie; - - (void) driDrawable; - - cookie = xcb_dri2_get_buffers_unchecked (dri2_dpy->conn, - dri2_surf->drawable, - count, count, attachments); - reply = xcb_dri2_get_buffers_reply (dri2_dpy->conn, cookie, NULL); - buffers = xcb_dri2_get_buffers_buffers (reply); - if (buffers == NULL) - return NULL; - - *out_count = reply->count; - dri2_surf->base.Width = *width = reply->width; - dri2_surf->base.Height = *height = reply->height; - dri2_process_buffers(dri2_surf, buffers, *out_count); - - free(reply); - - return dri2_surf->buffers; -} - -static void -dri2_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate) -{ - (void) driDrawable; + memcpy(&conf->base, &base, sizeof base); + if (double_buffer) { + conf->dri_double_config = dri_config; + conf->dri_single_config = NULL; + } else { + conf->dri_single_config = dri_config; + conf->dri_double_config = NULL; + } + conf->base.SurfaceType = 0; + conf->base.ConfigID = config_id; - /* FIXME: Does EGL support front buffer rendering at all? */ + _eglLinkConfig(&conf->base); + } -#if 0 - struct dri2_egl_surface *dri2_surf = loaderPrivate; + conf->base.SurfaceType |= surface_type & (!double_buffer ? EGL_PIXMAP_BIT: + (EGL_WINDOW_BIT | EGL_PBUFFER_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT)); - dri2WaitGL(dri2_surf); -#else - (void) loaderPrivate; -#endif + return conf; } static __DRIimage * @@ -394,49 +250,11 @@ dri2_lookup_egl_image(__DRIscreen *screen, void *image, void *data) return dri2_img->dri_image; } -static const __DRIimageLookupExtension image_lookup_extension = { +const __DRIimageLookupExtension image_lookup_extension = { { __DRI_IMAGE_LOOKUP, 1 }, dri2_lookup_egl_image }; -static __DRIbuffer * -dri2_get_buffers_with_format(__DRIdrawable * driDrawable, - int *width, int *height, - unsigned int *attachments, int count, - int *out_count, void *loaderPrivate) -{ - struct dri2_egl_surface *dri2_surf = loaderPrivate; - struct dri2_egl_display *dri2_dpy = - dri2_egl_display(dri2_surf->base.Resource.Display); - xcb_dri2_dri2_buffer_t *buffers; - xcb_dri2_get_buffers_with_format_reply_t *reply; - xcb_dri2_get_buffers_with_format_cookie_t cookie; - xcb_dri2_attach_format_t *format_attachments; - - (void) driDrawable; - - format_attachments = (xcb_dri2_attach_format_t *) attachments; - cookie = xcb_dri2_get_buffers_with_format_unchecked (dri2_dpy->conn, - dri2_surf->drawable, - count, count, - format_attachments); - - reply = xcb_dri2_get_buffers_with_format_reply (dri2_dpy->conn, - cookie, NULL); - if (reply == NULL) - return NULL; - - buffers = xcb_dri2_get_buffers_with_format_buffers (reply); - dri2_surf->base.Width = *width = reply->width; - dri2_surf->base.Height = *height = reply->height; - *out_count = reply->count; - dri2_process_buffers(dri2_surf, buffers, *out_count); - - free(reply); - - return dri2_surf->buffers; -} - static const char dri_driver_path[] = DEFAULT_DRIVER_DIR; struct dri2_extension_match { @@ -458,6 +276,17 @@ static struct dri2_extension_match dri2_core_extensions[] = { { NULL, 0, 0 } }; +static struct dri2_extension_match swrast_driver_extensions[] = { + { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) }, + { __DRI_SWRAST, 2, offsetof(struct dri2_egl_display, swrast) }, + { NULL } +}; + +static struct dri2_extension_match swrast_core_extensions[] = { + { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) }, + { NULL } +}; + static EGLBoolean dri2_bind_extensions(struct dri2_egl_display *dri2_dpy, struct dri2_extension_match *matches, @@ -491,180 +320,7 @@ dri2_bind_extensions(struct dri2_egl_display *dri2_dpy, return ret; } -static char * -dri2_strndup(const char *s, int length) -{ - char *d; - - d = malloc(length + 1); - if (d == NULL) - return NULL; - - memcpy(d, s, length); - d[length] = '\0'; - - return d; -} - -static EGLBoolean -dri2_connect(struct dri2_egl_display *dri2_dpy) -{ - xcb_xfixes_query_version_reply_t *xfixes_query; - xcb_xfixes_query_version_cookie_t xfixes_query_cookie; - xcb_dri2_query_version_reply_t *dri2_query; - xcb_dri2_query_version_cookie_t dri2_query_cookie; - xcb_dri2_connect_reply_t *connect; - xcb_dri2_connect_cookie_t connect_cookie; - xcb_generic_error_t *error; - xcb_screen_iterator_t s; - - xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_xfixes_id); - xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_dri2_id); - - xfixes_query_cookie = xcb_xfixes_query_version(dri2_dpy->conn, - XCB_XFIXES_MAJOR_VERSION, - XCB_XFIXES_MINOR_VERSION); - - dri2_query_cookie = xcb_dri2_query_version (dri2_dpy->conn, - XCB_DRI2_MAJOR_VERSION, - XCB_DRI2_MINOR_VERSION); - - s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn)); - connect_cookie = xcb_dri2_connect_unchecked (dri2_dpy->conn, - s.data->root, - XCB_DRI2_DRIVER_TYPE_DRI); - - xfixes_query = - xcb_xfixes_query_version_reply (dri2_dpy->conn, - xfixes_query_cookie, &error); - if (xfixes_query == NULL || - error != NULL || xfixes_query->major_version < 2) { - _eglLog(_EGL_FATAL, "DRI2: failed to query xfixes version"); - free(error); - return EGL_FALSE; - } - free(xfixes_query); - - dri2_query = - xcb_dri2_query_version_reply (dri2_dpy->conn, dri2_query_cookie, &error); - if (dri2_query == NULL || error != NULL) { - _eglLog(_EGL_FATAL, "DRI2: failed to query version"); - free(error); - return EGL_FALSE; - } - dri2_dpy->dri2_major = dri2_query->major_version; - dri2_dpy->dri2_minor = dri2_query->minor_version; - free(dri2_query); - - connect = xcb_dri2_connect_reply (dri2_dpy->conn, connect_cookie, NULL); - if (connect == NULL || - connect->driver_name_length + connect->device_name_length == 0) { - _eglLog(_EGL_FATAL, "DRI2: failed to authenticate"); - return EGL_FALSE; - } - - dri2_dpy->device_name = - dri2_strndup(xcb_dri2_connect_device_name (connect), - xcb_dri2_connect_device_name_length (connect)); - - dri2_dpy->driver_name = - dri2_strndup(xcb_dri2_connect_driver_name (connect), - xcb_dri2_connect_driver_name_length (connect)); - - if (dri2_dpy->device_name == NULL || dri2_dpy->driver_name == NULL) { - free(dri2_dpy->device_name); - free(dri2_dpy->driver_name); - free(connect); - return EGL_FALSE; - } - free(connect); - - return EGL_TRUE; -} - -static EGLBoolean -dri2_authenticate(struct dri2_egl_display *dri2_dpy) -{ - xcb_dri2_authenticate_reply_t *authenticate; - xcb_dri2_authenticate_cookie_t authenticate_cookie; - xcb_screen_iterator_t s; - drm_magic_t magic; - - if (drmGetMagic(dri2_dpy->fd, &magic)) { - _eglLog(_EGL_FATAL, "DRI2: failed to get drm magic"); - return EGL_FALSE; - } - - s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn)); - authenticate_cookie = - xcb_dri2_authenticate_unchecked(dri2_dpy->conn, s.data->root, magic); - authenticate = - xcb_dri2_authenticate_reply(dri2_dpy->conn, authenticate_cookie, NULL); - if (authenticate == NULL || !authenticate->authenticated) { - _eglLog(_EGL_FATAL, "DRI2: failed to authenticate"); - free(authenticate); - return EGL_FALSE; - } - - free(authenticate); - - return EGL_TRUE; -} - -static EGLBoolean -dri2_add_configs_for_visuals(struct dri2_egl_display *dri2_dpy, - _EGLDisplay *disp) -{ - xcb_screen_iterator_t s; - xcb_depth_iterator_t d; - xcb_visualtype_t *visuals; - int i, j, id; - struct dri2_egl_config *conf; - EGLint surface_type; - - s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn)); - d = xcb_screen_allowed_depths_iterator(s.data); - id = 1; - - surface_type = - EGL_WINDOW_BIT | - EGL_PIXMAP_BIT | - EGL_PBUFFER_BIT | - EGL_SWAP_BEHAVIOR_PRESERVED_BIT; - - while (d.rem > 0) { - EGLBoolean class_added[6] = { 0, }; - - visuals = xcb_depth_visuals(d.data); - for (i = 0; i < xcb_depth_visuals_length(d.data); i++) { - if (class_added[visuals[i]._class]) - continue; - - class_added[visuals[i]._class] = EGL_TRUE; - for (j = 0; dri2_dpy->driver_configs[j]; j++) { - conf = dri2_add_config(disp, dri2_dpy->driver_configs[j], - id++, d.data->depth, surface_type); - if (conf == NULL) - continue; - _eglSetConfigKey(&conf->base, - EGL_NATIVE_VISUAL_ID, visuals[i].visual_id); - _eglSetConfigKey(&conf->base, - EGL_NATIVE_VISUAL_TYPE, visuals[i]._class); - } - } - - xcb_depth_next(&d); - } - - if (!_eglGetArraySize(disp->Configs)) { - _eglLog(_EGL_WARNING, "DRI2: failed to create any config"); - return EGL_FALSE; - } - - return EGL_TRUE; -} - -static EGLBoolean +EGLBoolean dri2_load_driver(_EGLDisplay *disp) { struct dri2_egl_display *dri2_dpy = disp->DriverData; @@ -718,15 +374,22 @@ dri2_load_driver(_EGLDisplay *disp) return EGL_FALSE; } - if (!dri2_bind_extensions(dri2_dpy, dri2_driver_extensions, extensions)) { - dlclose(dri2_dpy->driver); - return EGL_FALSE; - } + if (strcmp(dri2_dpy->driver_name, "swrast") == 0) { + if (!dri2_bind_extensions(dri2_dpy, swrast_driver_extensions, extensions)) { + dlclose(dri2_dpy->driver); + return EGL_FALSE; + } + } else { + if (!dri2_bind_extensions(dri2_dpy, dri2_driver_extensions, extensions)) { + dlclose(dri2_dpy->driver); + return EGL_FALSE; + } + } return EGL_TRUE; } -static EGLBoolean +EGLBoolean dri2_create_screen(_EGLDisplay *disp) { const __DRIextension **extensions; @@ -734,9 +397,17 @@ dri2_create_screen(_EGLDisplay *disp) unsigned int api_mask; dri2_dpy = disp->DriverData; - dri2_dpy->dri_screen = - dri2_dpy->dri2->createNewScreen(0, dri2_dpy->fd, dri2_dpy->extensions, - &dri2_dpy->driver_configs, disp); + + if (dri2_dpy->dri2) { + dri2_dpy->dri_screen = + dri2_dpy->dri2->createNewScreen(0, dri2_dpy->fd, dri2_dpy->extensions, + &dri2_dpy->driver_configs, disp); + } else { + assert(dri2_dpy->swrast); + dri2_dpy->dri_screen = + dri2_dpy->swrast->createNewScreen(0, dri2_dpy->extensions, + &dri2_dpy->driver_configs, disp); + } if (dri2_dpy->dri_screen == NULL) { _eglLog(_EGL_WARNING, "DRI2: failed to create dri screen"); @@ -744,13 +415,28 @@ dri2_create_screen(_EGLDisplay *disp) } extensions = dri2_dpy->core->getExtensions(dri2_dpy->dri_screen); - if (!dri2_bind_extensions(dri2_dpy, dri2_core_extensions, extensions)) - goto cleanup_dri_screen; + + if (dri2_dpy->dri2) { + if (!dri2_bind_extensions(dri2_dpy, dri2_core_extensions, extensions)) + goto cleanup_dri_screen; + } else { + assert(dri2_dpy->swrast); + if (!dri2_bind_extensions(dri2_dpy, swrast_core_extensions, extensions)) + goto cleanup_dri_screen; + } - if (dri2_dpy->dri2->base.version >= 2) - api_mask = dri2_dpy->dri2->getAPIMask(dri2_dpy->dri_screen); - else - api_mask = 1 << __DRI_API_OPENGL; + if (dri2_dpy->dri2) { + if (dri2_dpy->dri2->base.version >= 2) + api_mask = dri2_dpy->dri2->getAPIMask(dri2_dpy->dri_screen); + else + api_mask = 1 << __DRI_API_OPENGL; + } else { + assert(dri2_dpy->swrast); + if (dri2_dpy->swrast->base.version >= 2) + api_mask = 1 << __DRI_API_OPENGL | 1 << __DRI_API_GLES | 1 << __DRI_API_GLES2; + else + api_mask = 1 << __DRI_API_OPENGL; + } disp->ClientAPIs = 0; if (api_mask & (1 <<__DRI_API_OPENGL)) @@ -760,710 +446,29 @@ dri2_create_screen(_EGLDisplay *disp) if (api_mask & (1 << __DRI_API_GLES2)) disp->ClientAPIs |= EGL_OPENGL_ES2_BIT; - if (dri2_dpy->dri2->base.version >= 2) { - disp->Extensions.KHR_surfaceless_gles1 = EGL_TRUE; - disp->Extensions.KHR_surfaceless_gles2 = EGL_TRUE; - disp->Extensions.KHR_surfaceless_opengl = EGL_TRUE; - } - - return EGL_TRUE; - - cleanup_dri_screen: - dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen); - - return EGL_FALSE; -} - -static EGLBoolean -dri2_initialize_x11(_EGLDriver *drv, _EGLDisplay *disp) -{ - struct dri2_egl_display *dri2_dpy; - - (void) drv; - - dri2_dpy = malloc(sizeof *dri2_dpy); - if (!dri2_dpy) - return _eglError(EGL_BAD_ALLOC, "eglInitialize"); - - disp->DriverData = (void *) dri2_dpy; - if (disp->PlatformDisplay == NULL) { - dri2_dpy->conn = xcb_connect(0, 0); - } else { - dri2_dpy->conn = XGetXCBConnection((Display *) disp->PlatformDisplay); - } - - if (xcb_connection_has_error(dri2_dpy->conn)) { - _eglLog(_EGL_WARNING, "DRI2: xcb_connect failed"); - goto cleanup_dpy; - } - - if (dri2_dpy->conn) { - if (!dri2_connect(dri2_dpy)) - goto cleanup_conn; - } - - if (!dri2_load_driver(disp)) - goto cleanup_conn; - - dri2_dpy->fd = open(dri2_dpy->device_name, O_RDWR); - if (dri2_dpy->fd == -1) { - _eglLog(_EGL_WARNING, - "DRI2: could not open %s (%s)", dri2_dpy->device_name, - strerror(errno)); - goto cleanup_driver; - } - - if (dri2_dpy->conn) { - if (!dri2_authenticate(dri2_dpy)) - goto cleanup_fd; - } - - if (dri2_dpy->dri2_minor >= 1) { - dri2_dpy->loader_extension.base.name = __DRI_DRI2_LOADER; - dri2_dpy->loader_extension.base.version = 3; - dri2_dpy->loader_extension.getBuffers = dri2_get_buffers; - dri2_dpy->loader_extension.flushFrontBuffer = dri2_flush_front_buffer; - dri2_dpy->loader_extension.getBuffersWithFormat = - dri2_get_buffers_with_format; + if (dri2_dpy->dri2) { + if (dri2_dpy->dri2->base.version >= 2) { + disp->Extensions.KHR_surfaceless_gles1 = EGL_TRUE; + disp->Extensions.KHR_surfaceless_gles2 = EGL_TRUE; + disp->Extensions.KHR_surfaceless_opengl = EGL_TRUE; + } } else { - dri2_dpy->loader_extension.base.name = __DRI_DRI2_LOADER; - dri2_dpy->loader_extension.base.version = 2; - dri2_dpy->loader_extension.getBuffers = dri2_get_buffers; - dri2_dpy->loader_extension.flushFrontBuffer = dri2_flush_front_buffer; - dri2_dpy->loader_extension.getBuffersWithFormat = NULL; - } - - dri2_dpy->extensions[0] = &dri2_dpy->loader_extension.base; - dri2_dpy->extensions[1] = &image_lookup_extension.base; - dri2_dpy->extensions[2] = NULL; - - if (!dri2_create_screen(disp)) - goto cleanup_fd; - - if (dri2_dpy->conn) { - if (!dri2_add_configs_for_visuals(dri2_dpy, disp)) - goto cleanup_configs; + assert(dri2_dpy->swrast); + if (dri2_dpy->swrast->base.version >= 2) { + disp->Extensions.KHR_surfaceless_gles1 = EGL_TRUE; + disp->Extensions.KHR_surfaceless_gles2 = EGL_TRUE; + disp->Extensions.KHR_surfaceless_opengl = EGL_TRUE; + } } - disp->Extensions.MESA_drm_image = EGL_TRUE; - disp->Extensions.KHR_image_base = EGL_TRUE; - disp->Extensions.KHR_image_pixmap = EGL_TRUE; - disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE; - disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE; - disp->Extensions.NOK_swap_region = EGL_TRUE; - disp->Extensions.NOK_texture_from_pixmap = EGL_TRUE; - - /* we're supporting EGL 1.4 */ - disp->VersionMajor = 1; - disp->VersionMinor = 4; - return EGL_TRUE; - cleanup_configs: - _eglCleanupDisplay(disp); + cleanup_dri_screen: dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen); - cleanup_fd: - close(dri2_dpy->fd); - cleanup_driver: - dlclose(dri2_dpy->driver); - cleanup_conn: - if (disp->PlatformDisplay == NULL) - xcb_disconnect(dri2_dpy->conn); - cleanup_dpy: - free(dri2_dpy); - - return EGL_FALSE; -} - -#ifdef HAVE_LIBUDEV - -struct dri2_driver_map { - int vendor_id; - const char *driver; - const int *chip_ids; - int num_chips_ids; -}; - -const int i915_chip_ids[] = { - 0x3577, /* PCI_CHIP_I830_M */ - 0x2562, /* PCI_CHIP_845_G */ - 0x3582, /* PCI_CHIP_I855_GM */ - 0x2572, /* PCI_CHIP_I865_G */ - 0x2582, /* PCI_CHIP_I915_G */ - 0x258a, /* PCI_CHIP_E7221_G */ - 0x2592, /* PCI_CHIP_I915_GM */ - 0x2772, /* PCI_CHIP_I945_G */ - 0x27a2, /* PCI_CHIP_I945_GM */ - 0x27ae, /* PCI_CHIP_I945_GME */ - 0x29b2, /* PCI_CHIP_Q35_G */ - 0x29c2, /* PCI_CHIP_G33_G */ - 0x29d2, /* PCI_CHIP_Q33_G */ - 0xa001, /* PCI_CHIP_IGD_G */ - 0xa011, /* Pineview */ -}; - -const int i965_chip_ids[] = { - 0x0042, /* PCI_CHIP_ILD_G */ - 0x0046, /* PCI_CHIP_ILM_G */ - 0x0102, /* PCI_CHIP_SANDYBRIDGE_GT1 */ - 0x0106, /* PCI_CHIP_SANDYBRIDGE_M_GT1 */ - 0x010a, /* PCI_CHIP_SANDYBRIDGE_S */ - 0x0112, /* PCI_CHIP_SANDYBRIDGE_GT2 */ - 0x0116, /* PCI_CHIP_SANDYBRIDGE_M_GT2 */ - 0x0122, /* PCI_CHIP_SANDYBRIDGE_GT2_PLUS */ - 0x0126, /* PCI_CHIP_SANDYBRIDGE_M_GT2_PLUS */ - 0x29a2, /* PCI_CHIP_I965_G */ - 0x2992, /* PCI_CHIP_I965_Q */ - 0x2982, /* PCI_CHIP_I965_G_1 */ - 0x2972, /* PCI_CHIP_I946_GZ */ - 0x2a02, /* PCI_CHIP_I965_GM */ - 0x2a12, /* PCI_CHIP_I965_GME */ - 0x2a42, /* PCI_CHIP_GM45_GM */ - 0x2e02, /* PCI_CHIP_IGD_E_G */ - 0x2e12, /* PCI_CHIP_Q45_G */ - 0x2e22, /* PCI_CHIP_G45_G */ - 0x2e32, /* PCI_CHIP_G41_G */ - 0x2e42, /* PCI_CHIP_B43_G */ - 0x2e92, /* PCI_CHIP_B43_G1 */ -}; - -const int r100_chip_ids[] = { - 0x4C57, /* PCI_CHIP_RADEON_LW */ - 0x4C58, /* PCI_CHIP_RADEON_LX */ - 0x4C59, /* PCI_CHIP_RADEON_LY */ - 0x4C5A, /* PCI_CHIP_RADEON_LZ */ - 0x5144, /* PCI_CHIP_RADEON_QD */ - 0x5145, /* PCI_CHIP_RADEON_QE */ - 0x5146, /* PCI_CHIP_RADEON_QF */ - 0x5147, /* PCI_CHIP_RADEON_QG */ - 0x5159, /* PCI_CHIP_RADEON_QY */ - 0x515A, /* PCI_CHIP_RADEON_QZ */ - 0x5157, /* PCI_CHIP_RV200_QW */ - 0x5158, /* PCI_CHIP_RV200_QX */ - 0x515E, /* PCI_CHIP_RN50_515E */ - 0x5969, /* PCI_CHIP_RN50_5969 */ - 0x4136, /* PCI_CHIP_RS100_4136 */ - 0x4336, /* PCI_CHIP_RS100_4336 */ - 0x4137, /* PCI_CHIP_RS200_4137 */ - 0x4337, /* PCI_CHIP_RS200_4337 */ - 0x4237, /* PCI_CHIP_RS250_4237 */ - 0x4437, /* PCI_CHIP_RS250_4437 */ -}; - -const int r200_chip_ids[] = { - 0x5148, /* PCI_CHIP_R200_QH */ - 0x514C, /* PCI_CHIP_R200_QL */ - 0x514D, /* PCI_CHIP_R200_QM */ - 0x4242, /* PCI_CHIP_R200_BB */ - 0x4243, /* PCI_CHIP_R200_BC */ - 0x4966, /* PCI_CHIP_RV250_If */ - 0x4967, /* PCI_CHIP_RV250_Ig */ - 0x4C64, /* PCI_CHIP_RV250_Ld */ - 0x4C66, /* PCI_CHIP_RV250_Lf */ - 0x4C67, /* PCI_CHIP_RV250_Lg */ - 0x5960, /* PCI_CHIP_RV280_5960 */ - 0x5961, /* PCI_CHIP_RV280_5961 */ - 0x5962, /* PCI_CHIP_RV280_5962 */ - 0x5964, /* PCI_CHIP_RV280_5964 */ - 0x5965, /* PCI_CHIP_RV280_5965 */ - 0x5C61, /* PCI_CHIP_RV280_5C61 */ - 0x5C63, /* PCI_CHIP_RV280_5C63 */ - 0x5834, /* PCI_CHIP_RS300_5834 */ - 0x5835, /* PCI_CHIP_RS300_5835 */ - 0x7834, /* PCI_CHIP_RS350_7834 */ - 0x7835, /* PCI_CHIP_RS350_7835 */ -}; - -const int r300_chip_ids[] = { - 0x4144, /* PCI_CHIP_R300_AD */ - 0x4145, /* PCI_CHIP_R300_AE */ - 0x4146, /* PCI_CHIP_R300_AF */ - 0x4147, /* PCI_CHIP_R300_AG */ - 0x4E44, /* PCI_CHIP_R300_ND */ - 0x4E45, /* PCI_CHIP_R300_NE */ - 0x4E46, /* PCI_CHIP_R300_NF */ - 0x4E47, /* PCI_CHIP_R300_NG */ - 0x4E48, /* PCI_CHIP_R350_NH */ - 0x4E49, /* PCI_CHIP_R350_NI */ - 0x4E4B, /* PCI_CHIP_R350_NK */ - 0x4148, /* PCI_CHIP_R350_AH */ - 0x4149, /* PCI_CHIP_R350_AI */ - 0x414A, /* PCI_CHIP_R350_AJ */ - 0x414B, /* PCI_CHIP_R350_AK */ - 0x4E4A, /* PCI_CHIP_R360_NJ */ - 0x4150, /* PCI_CHIP_RV350_AP */ - 0x4151, /* PCI_CHIP_RV350_AQ */ - 0x4152, /* PCI_CHIP_RV350_AR */ - 0x4153, /* PCI_CHIP_RV350_AS */ - 0x4154, /* PCI_CHIP_RV350_AT */ - 0x4155, /* PCI_CHIP_RV350_AU */ - 0x4156, /* PCI_CHIP_RV350_AV */ - 0x4E50, /* PCI_CHIP_RV350_NP */ - 0x4E51, /* PCI_CHIP_RV350_NQ */ - 0x4E52, /* PCI_CHIP_RV350_NR */ - 0x4E53, /* PCI_CHIP_RV350_NS */ - 0x4E54, /* PCI_CHIP_RV350_NT */ - 0x4E56, /* PCI_CHIP_RV350_NV */ - 0x5460, /* PCI_CHIP_RV370_5460 */ - 0x5462, /* PCI_CHIP_RV370_5462 */ - 0x5464, /* PCI_CHIP_RV370_5464 */ - 0x5B60, /* PCI_CHIP_RV370_5B60 */ - 0x5B62, /* PCI_CHIP_RV370_5B62 */ - 0x5B63, /* PCI_CHIP_RV370_5B63 */ - 0x5B64, /* PCI_CHIP_RV370_5B64 */ - 0x5B65, /* PCI_CHIP_RV370_5B65 */ - 0x3150, /* PCI_CHIP_RV380_3150 */ - 0x3152, /* PCI_CHIP_RV380_3152 */ - 0x3154, /* PCI_CHIP_RV380_3154 */ - 0x3155, /* PCI_CHIP_RV380_3155 */ - 0x3E50, /* PCI_CHIP_RV380_3E50 */ - 0x3E54, /* PCI_CHIP_RV380_3E54 */ - 0x4A48, /* PCI_CHIP_R420_JH */ - 0x4A49, /* PCI_CHIP_R420_JI */ - 0x4A4A, /* PCI_CHIP_R420_JJ */ - 0x4A4B, /* PCI_CHIP_R420_JK */ - 0x4A4C, /* PCI_CHIP_R420_JL */ - 0x4A4D, /* PCI_CHIP_R420_JM */ - 0x4A4E, /* PCI_CHIP_R420_JN */ - 0x4A4F, /* PCI_CHIP_R420_JO */ - 0x4A50, /* PCI_CHIP_R420_JP */ - 0x4A54, /* PCI_CHIP_R420_JT */ - 0x5548, /* PCI_CHIP_R423_UH */ - 0x5549, /* PCI_CHIP_R423_UI */ - 0x554A, /* PCI_CHIP_R423_UJ */ - 0x554B, /* PCI_CHIP_R423_UK */ - 0x5550, /* PCI_CHIP_R423_5550 */ - 0x5551, /* PCI_CHIP_R423_UQ */ - 0x5552, /* PCI_CHIP_R423_UR */ - 0x5554, /* PCI_CHIP_R423_UT */ - 0x5D57, /* PCI_CHIP_R423_5D57 */ - 0x554C, /* PCI_CHIP_R430_554C */ - 0x554D, /* PCI_CHIP_R430_554D */ - 0x554E, /* PCI_CHIP_R430_554E */ - 0x554F, /* PCI_CHIP_R430_554F */ - 0x5D48, /* PCI_CHIP_R430_5D48 */ - 0x5D49, /* PCI_CHIP_R430_5D49 */ - 0x5D4A, /* PCI_CHIP_R430_5D4A */ - 0x5D4C, /* PCI_CHIP_R480_5D4C */ - 0x5D4D, /* PCI_CHIP_R480_5D4D */ - 0x5D4E, /* PCI_CHIP_R480_5D4E */ - 0x5D4F, /* PCI_CHIP_R480_5D4F */ - 0x5D50, /* PCI_CHIP_R480_5D50 */ - 0x5D52, /* PCI_CHIP_R480_5D52 */ - 0x4B49, /* PCI_CHIP_R481_4B49 */ - 0x4B4A, /* PCI_CHIP_R481_4B4A */ - 0x4B4B, /* PCI_CHIP_R481_4B4B */ - 0x4B4C, /* PCI_CHIP_R481_4B4C */ - 0x564A, /* PCI_CHIP_RV410_564A */ - 0x564B, /* PCI_CHIP_RV410_564B */ - 0x564F, /* PCI_CHIP_RV410_564F */ - 0x5652, /* PCI_CHIP_RV410_5652 */ - 0x5653, /* PCI_CHIP_RV410_5653 */ - 0x5657, /* PCI_CHIP_RV410_5657 */ - 0x5E48, /* PCI_CHIP_RV410_5E48 */ - 0x5E4A, /* PCI_CHIP_RV410_5E4A */ - 0x5E4B, /* PCI_CHIP_RV410_5E4B */ - 0x5E4C, /* PCI_CHIP_RV410_5E4C */ - 0x5E4D, /* PCI_CHIP_RV410_5E4D */ - 0x5E4F, /* PCI_CHIP_RV410_5E4F */ - 0x5A41, /* PCI_CHIP_RS400_5A41 */ - 0x5A42, /* PCI_CHIP_RS400_5A42 */ - 0x5A61, /* PCI_CHIP_RC410_5A61 */ - 0x5A62, /* PCI_CHIP_RC410_5A62 */ - 0x5954, /* PCI_CHIP_RS480_5954 */ - 0x5955, /* PCI_CHIP_RS480_5955 */ - 0x5974, /* PCI_CHIP_RS482_5974 */ - 0x5975, /* PCI_CHIP_RS482_5975 */ - 0x7100, /* PCI_CHIP_R520_7100 */ - 0x7101, /* PCI_CHIP_R520_7101 */ - 0x7102, /* PCI_CHIP_R520_7102 */ - 0x7103, /* PCI_CHIP_R520_7103 */ - 0x7104, /* PCI_CHIP_R520_7104 */ - 0x7105, /* PCI_CHIP_R520_7105 */ - 0x7106, /* PCI_CHIP_R520_7106 */ - 0x7108, /* PCI_CHIP_R520_7108 */ - 0x7109, /* PCI_CHIP_R520_7109 */ - 0x710A, /* PCI_CHIP_R520_710A */ - 0x710B, /* PCI_CHIP_R520_710B */ - 0x710C, /* PCI_CHIP_R520_710C */ - 0x710E, /* PCI_CHIP_R520_710E */ - 0x710F, /* PCI_CHIP_R520_710F */ - 0x7140, /* PCI_CHIP_RV515_7140 */ - 0x7141, /* PCI_CHIP_RV515_7141 */ - 0x7142, /* PCI_CHIP_RV515_7142 */ - 0x7143, /* PCI_CHIP_RV515_7143 */ - 0x7144, /* PCI_CHIP_RV515_7144 */ - 0x7145, /* PCI_CHIP_RV515_7145 */ - 0x7146, /* PCI_CHIP_RV515_7146 */ - 0x7147, /* PCI_CHIP_RV515_7147 */ - 0x7149, /* PCI_CHIP_RV515_7149 */ - 0x714A, /* PCI_CHIP_RV515_714A */ - 0x714B, /* PCI_CHIP_RV515_714B */ - 0x714C, /* PCI_CHIP_RV515_714C */ - 0x714D, /* PCI_CHIP_RV515_714D */ - 0x714E, /* PCI_CHIP_RV515_714E */ - 0x714F, /* PCI_CHIP_RV515_714F */ - 0x7151, /* PCI_CHIP_RV515_7151 */ - 0x7152, /* PCI_CHIP_RV515_7152 */ - 0x7153, /* PCI_CHIP_RV515_7153 */ - 0x715E, /* PCI_CHIP_RV515_715E */ - 0x715F, /* PCI_CHIP_RV515_715F */ - 0x7180, /* PCI_CHIP_RV515_7180 */ - 0x7181, /* PCI_CHIP_RV515_7181 */ - 0x7183, /* PCI_CHIP_RV515_7183 */ - 0x7186, /* PCI_CHIP_RV515_7186 */ - 0x7187, /* PCI_CHIP_RV515_7187 */ - 0x7188, /* PCI_CHIP_RV515_7188 */ - 0x718A, /* PCI_CHIP_RV515_718A */ - 0x718B, /* PCI_CHIP_RV515_718B */ - 0x718C, /* PCI_CHIP_RV515_718C */ - 0x718D, /* PCI_CHIP_RV515_718D */ - 0x718F, /* PCI_CHIP_RV515_718F */ - 0x7193, /* PCI_CHIP_RV515_7193 */ - 0x7196, /* PCI_CHIP_RV515_7196 */ - 0x719B, /* PCI_CHIP_RV515_719B */ - 0x719F, /* PCI_CHIP_RV515_719F */ - 0x7200, /* PCI_CHIP_RV515_7200 */ - 0x7210, /* PCI_CHIP_RV515_7210 */ - 0x7211, /* PCI_CHIP_RV515_7211 */ - 0x71C0, /* PCI_CHIP_RV530_71C0 */ - 0x71C1, /* PCI_CHIP_RV530_71C1 */ - 0x71C2, /* PCI_CHIP_RV530_71C2 */ - 0x71C3, /* PCI_CHIP_RV530_71C3 */ - 0x71C4, /* PCI_CHIP_RV530_71C4 */ - 0x71C5, /* PCI_CHIP_RV530_71C5 */ - 0x71C6, /* PCI_CHIP_RV530_71C6 */ - 0x71C7, /* PCI_CHIP_RV530_71C7 */ - 0x71CD, /* PCI_CHIP_RV530_71CD */ - 0x71CE, /* PCI_CHIP_RV530_71CE */ - 0x71D2, /* PCI_CHIP_RV530_71D2 */ - 0x71D4, /* PCI_CHIP_RV530_71D4 */ - 0x71D5, /* PCI_CHIP_RV530_71D5 */ - 0x71D6, /* PCI_CHIP_RV530_71D6 */ - 0x71DA, /* PCI_CHIP_RV530_71DA */ - 0x71DE, /* PCI_CHIP_RV530_71DE */ - 0x7281, /* PCI_CHIP_RV560_7281 */ - 0x7283, /* PCI_CHIP_RV560_7283 */ - 0x7287, /* PCI_CHIP_RV560_7287 */ - 0x7290, /* PCI_CHIP_RV560_7290 */ - 0x7291, /* PCI_CHIP_RV560_7291 */ - 0x7293, /* PCI_CHIP_RV560_7293 */ - 0x7297, /* PCI_CHIP_RV560_7297 */ - 0x7280, /* PCI_CHIP_RV570_7280 */ - 0x7288, /* PCI_CHIP_RV570_7288 */ - 0x7289, /* PCI_CHIP_RV570_7289 */ - 0x728B, /* PCI_CHIP_RV570_728B */ - 0x728C, /* PCI_CHIP_RV570_728C */ - 0x7240, /* PCI_CHIP_R580_7240 */ - 0x7243, /* PCI_CHIP_R580_7243 */ - 0x7244, /* PCI_CHIP_R580_7244 */ - 0x7245, /* PCI_CHIP_R580_7245 */ - 0x7246, /* PCI_CHIP_R580_7246 */ - 0x7247, /* PCI_CHIP_R580_7247 */ - 0x7248, /* PCI_CHIP_R580_7248 */ - 0x7249, /* PCI_CHIP_R580_7249 */ - 0x724A, /* PCI_CHIP_R580_724A */ - 0x724B, /* PCI_CHIP_R580_724B */ - 0x724C, /* PCI_CHIP_R580_724C */ - 0x724D, /* PCI_CHIP_R580_724D */ - 0x724E, /* PCI_CHIP_R580_724E */ - 0x724F, /* PCI_CHIP_R580_724F */ - 0x7284, /* PCI_CHIP_R580_7284 */ - 0x793F, /* PCI_CHIP_RS600_793F */ - 0x7941, /* PCI_CHIP_RS600_7941 */ - 0x7942, /* PCI_CHIP_RS600_7942 */ - 0x791E, /* PCI_CHIP_RS690_791E */ - 0x791F, /* PCI_CHIP_RS690_791F */ - 0x796C, /* PCI_CHIP_RS740_796C */ - 0x796D, /* PCI_CHIP_RS740_796D */ - 0x796E, /* PCI_CHIP_RS740_796E */ - 0x796F, /* PCI_CHIP_RS740_796F */ -}; - -const int r600_chip_ids[] = { - 0x9400, /* PCI_CHIP_R600_9400 */ - 0x9401, /* PCI_CHIP_R600_9401 */ - 0x9402, /* PCI_CHIP_R600_9402 */ - 0x9403, /* PCI_CHIP_R600_9403 */ - 0x9405, /* PCI_CHIP_R600_9405 */ - 0x940A, /* PCI_CHIP_R600_940A */ - 0x940B, /* PCI_CHIP_R600_940B */ - 0x940F, /* PCI_CHIP_R600_940F */ - 0x94C0, /* PCI_CHIP_RV610_94C0 */ - 0x94C1, /* PCI_CHIP_RV610_94C1 */ - 0x94C3, /* PCI_CHIP_RV610_94C3 */ - 0x94C4, /* PCI_CHIP_RV610_94C4 */ - 0x94C5, /* PCI_CHIP_RV610_94C5 */ - 0x94C6, /* PCI_CHIP_RV610_94C6 */ - 0x94C7, /* PCI_CHIP_RV610_94C7 */ - 0x94C8, /* PCI_CHIP_RV610_94C8 */ - 0x94C9, /* PCI_CHIP_RV610_94C9 */ - 0x94CB, /* PCI_CHIP_RV610_94CB */ - 0x94CC, /* PCI_CHIP_RV610_94CC */ - 0x94CD, /* PCI_CHIP_RV610_94CD */ - 0x9580, /* PCI_CHIP_RV630_9580 */ - 0x9581, /* PCI_CHIP_RV630_9581 */ - 0x9583, /* PCI_CHIP_RV630_9583 */ - 0x9586, /* PCI_CHIP_RV630_9586 */ - 0x9587, /* PCI_CHIP_RV630_9587 */ - 0x9588, /* PCI_CHIP_RV630_9588 */ - 0x9589, /* PCI_CHIP_RV630_9589 */ - 0x958A, /* PCI_CHIP_RV630_958A */ - 0x958B, /* PCI_CHIP_RV630_958B */ - 0x958C, /* PCI_CHIP_RV630_958C */ - 0x958D, /* PCI_CHIP_RV630_958D */ - 0x958E, /* PCI_CHIP_RV630_958E */ - 0x958F, /* PCI_CHIP_RV630_958F */ - 0x9500, /* PCI_CHIP_RV670_9500 */ - 0x9501, /* PCI_CHIP_RV670_9501 */ - 0x9504, /* PCI_CHIP_RV670_9504 */ - 0x9505, /* PCI_CHIP_RV670_9505 */ - 0x9506, /* PCI_CHIP_RV670_9506 */ - 0x9507, /* PCI_CHIP_RV670_9507 */ - 0x9508, /* PCI_CHIP_RV670_9508 */ - 0x9509, /* PCI_CHIP_RV670_9509 */ - 0x950F, /* PCI_CHIP_RV670_950F */ - 0x9511, /* PCI_CHIP_RV670_9511 */ - 0x9515, /* PCI_CHIP_RV670_9515 */ - 0x9517, /* PCI_CHIP_RV670_9517 */ - 0x9519, /* PCI_CHIP_RV670_9519 */ - 0x95C0, /* PCI_CHIP_RV620_95C0 */ - 0x95C2, /* PCI_CHIP_RV620_95C2 */ - 0x95C4, /* PCI_CHIP_RV620_95C4 */ - 0x95C5, /* PCI_CHIP_RV620_95C5 */ - 0x95C6, /* PCI_CHIP_RV620_95C6 */ - 0x95C7, /* PCI_CHIP_RV620_95C7 */ - 0x95C9, /* PCI_CHIP_RV620_95C9 */ - 0x95CC, /* PCI_CHIP_RV620_95CC */ - 0x95CD, /* PCI_CHIP_RV620_95CD */ - 0x95CE, /* PCI_CHIP_RV620_95CE */ - 0x95CF, /* PCI_CHIP_RV620_95CF */ - 0x9590, /* PCI_CHIP_RV635_9590 */ - 0x9591, /* PCI_CHIP_RV635_9591 */ - 0x9593, /* PCI_CHIP_RV635_9593 */ - 0x9595, /* PCI_CHIP_RV635_9595 */ - 0x9596, /* PCI_CHIP_RV635_9596 */ - 0x9597, /* PCI_CHIP_RV635_9597 */ - 0x9598, /* PCI_CHIP_RV635_9598 */ - 0x9599, /* PCI_CHIP_RV635_9599 */ - 0x959B, /* PCI_CHIP_RV635_959B */ - 0x9610, /* PCI_CHIP_RS780_9610 */ - 0x9611, /* PCI_CHIP_RS780_9611 */ - 0x9612, /* PCI_CHIP_RS780_9612 */ - 0x9613, /* PCI_CHIP_RS780_9613 */ - 0x9614, /* PCI_CHIP_RS780_9614 */ - 0x9615, /* PCI_CHIP_RS780_9615 */ - 0x9616, /* PCI_CHIP_RS780_9616 */ - 0x9710, /* PCI_CHIP_RS880_9710 */ - 0x9711, /* PCI_CHIP_RS880_9711 */ - 0x9712, /* PCI_CHIP_RS880_9712 */ - 0x9713, /* PCI_CHIP_RS880_9713 */ - 0x9714, /* PCI_CHIP_RS880_9714 */ - 0x9715, /* PCI_CHIP_RS880_9715 */ - 0x9440, /* PCI_CHIP_RV770_9440 */ - 0x9441, /* PCI_CHIP_RV770_9441 */ - 0x9442, /* PCI_CHIP_RV770_9442 */ - 0x9443, /* PCI_CHIP_RV770_9443 */ - 0x9444, /* PCI_CHIP_RV770_9444 */ - 0x9446, /* PCI_CHIP_RV770_9446 */ - 0x944A, /* PCI_CHIP_RV770_944A */ - 0x944B, /* PCI_CHIP_RV770_944B */ - 0x944C, /* PCI_CHIP_RV770_944C */ - 0x944E, /* PCI_CHIP_RV770_944E */ - 0x9450, /* PCI_CHIP_RV770_9450 */ - 0x9452, /* PCI_CHIP_RV770_9452 */ - 0x9456, /* PCI_CHIP_RV770_9456 */ - 0x945A, /* PCI_CHIP_RV770_945A */ - 0x945B, /* PCI_CHIP_RV770_945B */ - 0x945E, /* PCI_CHIP_RV770_945E */ - 0x9460, /* PCI_CHIP_RV790_9460 */ - 0x9462, /* PCI_CHIP_RV790_9462 */ - 0x946A, /* PCI_CHIP_RV770_946A */ - 0x946B, /* PCI_CHIP_RV770_946B */ - 0x947A, /* PCI_CHIP_RV770_947A */ - 0x947B, /* PCI_CHIP_RV770_947B */ - 0x9480, /* PCI_CHIP_RV730_9480 */ - 0x9487, /* PCI_CHIP_RV730_9487 */ - 0x9488, /* PCI_CHIP_RV730_9488 */ - 0x9489, /* PCI_CHIP_RV730_9489 */ - 0x948A, /* PCI_CHIP_RV730_948A */ - 0x948F, /* PCI_CHIP_RV730_948F */ - 0x9490, /* PCI_CHIP_RV730_9490 */ - 0x9491, /* PCI_CHIP_RV730_9491 */ - 0x9495, /* PCI_CHIP_RV730_9495 */ - 0x9498, /* PCI_CHIP_RV730_9498 */ - 0x949C, /* PCI_CHIP_RV730_949C */ - 0x949E, /* PCI_CHIP_RV730_949E */ - 0x949F, /* PCI_CHIP_RV730_949F */ - 0x9540, /* PCI_CHIP_RV710_9540 */ - 0x9541, /* PCI_CHIP_RV710_9541 */ - 0x9542, /* PCI_CHIP_RV710_9542 */ - 0x954E, /* PCI_CHIP_RV710_954E */ - 0x954F, /* PCI_CHIP_RV710_954F */ - 0x9552, /* PCI_CHIP_RV710_9552 */ - 0x9553, /* PCI_CHIP_RV710_9553 */ - 0x9555, /* PCI_CHIP_RV710_9555 */ - 0x9557, /* PCI_CHIP_RV710_9557 */ - 0x955F, /* PCI_CHIP_RV710_955F */ - 0x94A0, /* PCI_CHIP_RV740_94A0 */ - 0x94A1, /* PCI_CHIP_RV740_94A1 */ - 0x94A3, /* PCI_CHIP_RV740_94A3 */ - 0x94B1, /* PCI_CHIP_RV740_94B1 */ - 0x94B3, /* PCI_CHIP_RV740_94B3 */ - 0x94B4, /* PCI_CHIP_RV740_94B4 */ - 0x94B5, /* PCI_CHIP_RV740_94B5 */ - 0x94B9, /* PCI_CHIP_RV740_94B9 */ - 0x68E0, /* PCI_CHIP_CEDAR_68E0 */ - 0x68E1, /* PCI_CHIP_CEDAR_68E1 */ - 0x68E4, /* PCI_CHIP_CEDAR_68E4 */ - 0x68E5, /* PCI_CHIP_CEDAR_68E5 */ - 0x68E8, /* PCI_CHIP_CEDAR_68E8 */ - 0x68E9, /* PCI_CHIP_CEDAR_68E9 */ - 0x68F1, /* PCI_CHIP_CEDAR_68F1 */ - 0x68F8, /* PCI_CHIP_CEDAR_68F8 */ - 0x68F9, /* PCI_CHIP_CEDAR_68F9 */ - 0x68FE, /* PCI_CHIP_CEDAR_68FE */ - 0x68C0, /* PCI_CHIP_REDWOOD_68C0 */ - 0x68C1, /* PCI_CHIP_REDWOOD_68C1 */ - 0x68C8, /* PCI_CHIP_REDWOOD_68C8 */ - 0x68C9, /* PCI_CHIP_REDWOOD_68C9 */ - 0x68D8, /* PCI_CHIP_REDWOOD_68D8 */ - 0x68D9, /* PCI_CHIP_REDWOOD_68D9 */ - 0x68DA, /* PCI_CHIP_REDWOOD_68DA */ - 0x68DE, /* PCI_CHIP_REDWOOD_68DE */ - 0x68A0, /* PCI_CHIP_JUNIPER_68A0 */ - 0x68A1, /* PCI_CHIP_JUNIPER_68A1 */ - 0x68A8, /* PCI_CHIP_JUNIPER_68A8 */ - 0x68A9, /* PCI_CHIP_JUNIPER_68A9 */ - 0x68B0, /* PCI_CHIP_JUNIPER_68B0 */ - 0x68B8, /* PCI_CHIP_JUNIPER_68B8 */ - 0x68B9, /* PCI_CHIP_JUNIPER_68B9 */ - 0x68BE, /* PCI_CHIP_JUNIPER_68BE */ - 0x6880, /* PCI_CHIP_CYPRESS_6880 */ - 0x6888, /* PCI_CHIP_CYPRESS_6888 */ - 0x6889, /* PCI_CHIP_CYPRESS_6889 */ - 0x688A, /* PCI_CHIP_CYPRESS_688A */ - 0x6898, /* PCI_CHIP_CYPRESS_6898 */ - 0x6899, /* PCI_CHIP_CYPRESS_6899 */ - 0x689E, /* PCI_CHIP_CYPRESS_689E */ - 0x689C, /* PCI_CHIP_HEMLOCK_689C */ - 0x689D, /* PCI_CHIP_HEMLOCK_689D */ -}; - -const struct dri2_driver_map driver_map[] = { - { 0x8086, "i915", i915_chip_ids, ARRAY_SIZE(i915_chip_ids) }, - { 0x8086, "i965", i965_chip_ids, ARRAY_SIZE(i965_chip_ids) }, - { 0x1002, "radeon", r100_chip_ids, ARRAY_SIZE(r100_chip_ids) }, - { 0x1002, "r200", r200_chip_ids, ARRAY_SIZE(r200_chip_ids) }, - { 0x1002, "r300", r300_chip_ids, ARRAY_SIZE(r300_chip_ids) }, - { 0x1002, "r600", r600_chip_ids, ARRAY_SIZE(r600_chip_ids) }, -}; - -static char * -dri2_get_driver_for_fd(int fd) -{ - struct udev *udev; - struct udev_device *device, *parent; - struct stat buf; - const char *pci_id; - char *driver = NULL; - int vendor_id, chip_id, i, j; - - udev = udev_new(); - if (fstat(fd, &buf) < 0) { - _eglLog(_EGL_WARNING, "EGL-DRI2: failed to stat fd %d", fd); - goto out; - } - - device = udev_device_new_from_devnum(udev, 'c', buf.st_rdev); - if (device == NULL) { - _eglLog(_EGL_WARNING, - "EGL-DRI2: could not create udev device for fd %d", fd); - goto out; - } - - parent = udev_device_get_parent(device); - if (parent == NULL) { - _eglLog(_EGL_WARNING, "DRI2: could not get parent device"); - goto out; - } - - pci_id = udev_device_get_property_value(parent, "PCI_ID"); - if (pci_id == NULL || sscanf(pci_id, "%x:%x", &vendor_id, &chip_id) != 2) { - _eglLog(_EGL_WARNING, "EGL-DRI2: malformed or no PCI ID"); - goto out; - } - - for (i = 0; i < ARRAY_SIZE(driver_map); i++) { - if (vendor_id != driver_map[i].vendor_id) - continue; - for (j = 0; j < driver_map[i].num_chips_ids; j++) - if (driver_map[i].chip_ids[j] == chip_id) { - driver = strdup(driver_map[i].driver); - _eglLog(_EGL_DEBUG, "pci id for %d: %04x:%04x, driver %s", - fd, vendor_id, chip_id, driver); - goto out; - } - } - - out: - udev_device_unref(device); - udev_unref(udev); - - return driver; -} - -static EGLBoolean -dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp) -{ - struct dri2_egl_display *dri2_dpy; - int i; - - dri2_dpy = malloc(sizeof *dri2_dpy); - if (!dri2_dpy) - return _eglError(EGL_BAD_ALLOC, "eglInitialize"); - - disp->DriverData = (void *) dri2_dpy; - dri2_dpy->fd = (int) disp->PlatformDisplay; - - dri2_dpy->driver_name = dri2_get_driver_for_fd(dri2_dpy->fd); - if (dri2_dpy->driver_name == NULL) - return _eglError(EGL_BAD_ALLOC, "DRI2: failed to get driver name"); - - if (!dri2_load_driver(disp)) - goto cleanup_driver_name; - - dri2_dpy->extensions[0] = &image_lookup_extension.base; - dri2_dpy->extensions[1] = &use_invalidate.base; - dri2_dpy->extensions[2] = NULL; - - if (!dri2_create_screen(disp)) - goto cleanup_driver; - - for (i = 0; dri2_dpy->driver_configs[i]; i++) - dri2_add_config(disp, dri2_dpy->driver_configs[i], i + 1, 0, 0); - - disp->Extensions.MESA_drm_image = EGL_TRUE; - disp->Extensions.KHR_image_base = EGL_TRUE; - disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE; - disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE; - - /* we're supporting EGL 1.4 */ - disp->VersionMajor = 1; - disp->VersionMinor = 4; - - return EGL_TRUE; - - cleanup_driver: - dlclose(dri2_dpy->driver); - cleanup_driver_name: - free(dri2_dpy->driver_name); return EGL_FALSE; } -#endif - /** * Called via eglInitialize(), GLX_drv->API.Initialize(). */ @@ -1485,6 +490,12 @@ dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp) if (disp->Options.TestOnly) return EGL_TRUE; return dri2_initialize_drm(drv, disp); +#ifdef HAVE_WAYLAND_PLATFORM + case _EGL_PLATFORM_WAYLAND: + if (disp->Options.TestOnly) + return EGL_TRUE; + return dri2_initialize_wayland(drv, disp); +#endif #endif default: @@ -1504,7 +515,8 @@ dri2_terminate(_EGLDriver *drv, _EGLDisplay *disp) _eglCleanupDisplay(disp); dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen); - close(dri2_dpy->fd); + if (dri2_dpy->fd) + close(dri2_dpy->fd); dlclose(dri2_dpy->driver); if (disp->PlatformDisplay == NULL) xcb_disconnect(dri2_dpy->conn); @@ -1562,28 +574,61 @@ dri2_create_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf, return NULL; } - if (conf != NULL) - dri_config = dri2_config->dri_config; + if (conf != NULL) { + /* The config chosen here isn't necessarily + * used for surfaces later. + * A pixmap surface will use the single config. + * This opportunity depends on disabling the + * doubleBufferMode check in + * src/mesa/main/context.c:check_compatible() + */ + if (dri2_config->dri_double_config) + dri_config = dri2_config->dri_double_config; + else + dri_config = dri2_config->dri_single_config; + } else dri_config = NULL; - if (dri2_dpy->dri2->base.version >= 2) { - dri2_ctx->dri_context = - dri2_dpy->dri2->createNewContextForAPI(dri2_dpy->dri_screen, - api, - dri_config, - dri2_ctx_shared ? - dri2_ctx_shared->dri_context : NULL, - dri2_ctx); - } else if (api == __DRI_API_OPENGL) { - dri2_ctx->dri_context = - dri2_dpy->dri2->createNewContext(dri2_dpy->dri_screen, - dri2_config->dri_config, - dri2_ctx_shared ? - dri2_ctx_shared->dri_context : NULL, - dri2_ctx); + if (dri2_dpy->dri2) { + if (dri2_dpy->dri2->base.version >= 2) { + dri2_ctx->dri_context = + dri2_dpy->dri2->createNewContextForAPI(dri2_dpy->dri_screen, + api, + dri_config, + dri2_ctx_shared ? + dri2_ctx_shared->dri_context : NULL, + dri2_ctx); + } else if (api == __DRI_API_OPENGL) { + dri2_ctx->dri_context = + dri2_dpy->dri2->createNewContext(dri2_dpy->dri_screen, + dri_config, + dri2_ctx_shared ? + dri2_ctx_shared->dri_context : NULL, + dri2_ctx); + } else { + /* fail */ + } } else { - /* fail */ + assert(dri2_dpy->swrast); + if (dri2_dpy->swrast->base.version >= 2) { + dri2_ctx->dri_context = + dri2_dpy->swrast->createNewContextForAPI(dri2_dpy->dri_screen, + api, + dri_config, + dri2_ctx_shared ? + dri2_ctx_shared->dri_context : NULL, + dri2_ctx); + } else if (api == __DRI_API_OPENGL) { + dri2_ctx->dri_context = + dri2_dpy->core->createNewContext(dri2_dpy->dri_screen, + dri_config, + dri2_ctx_shared ? + dri2_ctx_shared->dri_context : NULL, + dri2_ctx); + } else { + /* fail */ + } } if (!dri2_ctx->dri_context) @@ -1596,29 +641,6 @@ dri2_create_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf, return NULL; } -static EGLBoolean -dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf) -{ - struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); - struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); - - (void) drv; - - if (!_eglPutSurface(surf)) - return EGL_TRUE; - - (*dri2_dpy->core->destroyDrawable)(dri2_surf->dri_drawable); - - xcb_dri2_destroy_drawable (dri2_dpy->conn, dri2_surf->drawable); - - if (surf->Type == EGL_PBUFFER_BIT) - xcb_free_pixmap (dri2_dpy->conn, dri2_surf->drawable); - - free(surf); - - return EGL_TRUE; -} - /** * Called via eglMakeCurrent(), drv->API.MakeCurrent(). */ @@ -1648,19 +670,20 @@ dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf, rdraw = (dri2_rsurf) ? dri2_rsurf->dri_drawable : NULL; cctx = (dri2_ctx) ? dri2_ctx->dri_context : NULL; + if (old_ctx) { + __DRIcontext *old_cctx = dri2_egl_context(old_ctx)->dri_context; + dri2_dpy->core->unbindContext(old_cctx); + } + if ((cctx == NULL && ddraw == NULL && rdraw == NULL) || dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) { - dri2_destroy_surface(drv, disp, old_dsurf); - dri2_destroy_surface(drv, disp, old_rsurf); - if (old_ctx) { - /* unbind the old context only when there is no new context bound */ - if (!ctx) { - __DRIcontext *old_cctx = dri2_egl_context(old_ctx)->dri_context; - dri2_dpy->core->unbindContext(old_cctx); - } - /* no destroy? */ + if (old_dsurf) + drv->API.DestroySurface(drv, disp, old_dsurf); + if (old_rsurf) + drv->API.DestroySurface(drv, disp, old_rsurf); + /* no destroy? */ + if (old_ctx) _eglPutContext(old_ctx); - } return EGL_TRUE; } else { @@ -1682,190 +705,6 @@ dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf, } } -/** - * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface(). - */ -static _EGLSurface * -dri2_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type, - _EGLConfig *conf, EGLNativeWindowType window, - const EGLint *attrib_list) -{ - struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); - struct dri2_egl_config *dri2_conf = dri2_egl_config(conf); - struct dri2_egl_surface *dri2_surf; - xcb_get_geometry_cookie_t cookie; - xcb_get_geometry_reply_t *reply; - xcb_screen_iterator_t s; - xcb_generic_error_t *error; - - (void) drv; - - dri2_surf = malloc(sizeof *dri2_surf); - if (!dri2_surf) { - _eglError(EGL_BAD_ALLOC, "dri2_create_surface"); - return NULL; - } - - if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list)) - goto cleanup_surf; - - dri2_surf->region = XCB_NONE; - if (type == EGL_PBUFFER_BIT) { - dri2_surf->drawable = xcb_generate_id(dri2_dpy->conn); - s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn)); - xcb_create_pixmap(dri2_dpy->conn, conf->BufferSize, - dri2_surf->drawable, s.data->root, - dri2_surf->base.Width, dri2_surf->base.Height); - } else { - dri2_surf->drawable = window; - } - - dri2_surf->dri_drawable = - (*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen, - dri2_conf->dri_config, dri2_surf); - if (dri2_surf->dri_drawable == NULL) { - _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable"); - goto cleanup_pixmap; - } - - xcb_dri2_create_drawable (dri2_dpy->conn, dri2_surf->drawable); - - if (type != EGL_PBUFFER_BIT) { - cookie = xcb_get_geometry (dri2_dpy->conn, dri2_surf->drawable); - reply = xcb_get_geometry_reply (dri2_dpy->conn, cookie, &error); - if (reply == NULL || error != NULL) { - _eglError(EGL_BAD_ALLOC, "xcb_get_geometry"); - free(error); - goto cleanup_dri_drawable; - } - - dri2_surf->base.Width = reply->width; - dri2_surf->base.Height = reply->height; - free(reply); - } - - return &dri2_surf->base; - - cleanup_dri_drawable: - dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable); - cleanup_pixmap: - if (type == EGL_PBUFFER_BIT) - xcb_free_pixmap(dri2_dpy->conn, dri2_surf->drawable); - cleanup_surf: - free(dri2_surf); - - return NULL; -} - -/** - * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface(). - */ -static _EGLSurface * -dri2_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp, - _EGLConfig *conf, EGLNativeWindowType window, - const EGLint *attrib_list) -{ - return dri2_create_surface(drv, disp, EGL_WINDOW_BIT, conf, - window, attrib_list); -} - -static _EGLSurface * -dri2_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp, - _EGLConfig *conf, EGLNativePixmapType pixmap, - const EGLint *attrib_list) -{ - return dri2_create_surface(drv, disp, EGL_PIXMAP_BIT, conf, - pixmap, attrib_list); -} - -static _EGLSurface * -dri2_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp, - _EGLConfig *conf, const EGLint *attrib_list) -{ - return dri2_create_surface(drv, disp, EGL_PBUFFER_BIT, conf, - XCB_WINDOW_NONE, attrib_list); -} - -static EGLBoolean -dri2_copy_region(_EGLDriver *drv, _EGLDisplay *disp, - _EGLSurface *draw, xcb_xfixes_region_t region) -{ - struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); - struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); - struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); - _EGLContext *ctx; - xcb_dri2_copy_region_cookie_t cookie; - - if (dri2_drv->glFlush) { - ctx = _eglGetCurrentContext(); - if (ctx && ctx->DrawSurface == &dri2_surf->base) - dri2_drv->glFlush(); - } - - (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable); - -#if 0 - /* FIXME: Add support for dri swapbuffers, that'll give us swap - * interval and page flipping (at least for fullscreen windows) as - * well as the page flip event. Unless surface->SwapBehavior is - * EGL_BUFFER_PRESERVED. */ -#if __DRI2_FLUSH_VERSION >= 2 - if (pdraw->psc->f) - (*pdraw->psc->f->flushInvalidate)(pdraw->driDrawable); -#endif -#endif - - if (!dri2_surf->have_fake_front) - return EGL_TRUE; - - cookie = xcb_dri2_copy_region_unchecked(dri2_dpy->conn, - dri2_surf->drawable, - region, - XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT, - XCB_DRI2_ATTACHMENT_BUFFER_FAKE_FRONT_LEFT); - free(xcb_dri2_copy_region_reply(dri2_dpy->conn, cookie, NULL)); - - return EGL_TRUE; -} - -static EGLBoolean -dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw) -{ - struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); - - return dri2_copy_region(drv, disp, draw, dri2_surf->region); -} - -static EGLBoolean -dri2_swap_buffers_region(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw, - EGLint numRects, const EGLint *rects) -{ - struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); - struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); - EGLBoolean ret; - xcb_xfixes_region_t region; - xcb_rectangle_t rectangles[16]; - int i; - - if (numRects > (int)ARRAY_SIZE(rectangles)) - return dri2_copy_region(drv, disp, draw, dri2_surf->region); - - /* FIXME: Invert y here? */ - for (i = 0; i < numRects; i++) { - rectangles[i].x = rects[i * 4]; - rectangles[i].y = rects[i * 4 + 1]; - rectangles[i].width = rects[i * 4 + 2]; - rectangles[i].height = rects[i * 4 + 3]; - } - - region = xcb_generate_id(dri2_dpy->conn); - xcb_xfixes_create_region(dri2_dpy->conn, region, numRects, rectangles); - ret = dri2_copy_region(drv, disp, draw, region); - xcb_xfixes_destroy_region(dri2_dpy->conn, region); - - return ret; -} - /* * Called from eglGetProcAddress() via drv->API.GetProcAddress(). */ @@ -1907,33 +746,6 @@ dri2_wait_native(_EGLDriver *drv, _EGLDisplay *disp, EGLint engine) } static EGLBoolean -dri2_copy_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, - EGLNativePixmapType target) -{ - struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); - struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); - xcb_gcontext_t gc; - - (void) drv; - - (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable); - - gc = xcb_generate_id(dri2_dpy->conn); - xcb_create_gc(dri2_dpy->conn, gc, target, 0, NULL); - xcb_copy_area(dri2_dpy->conn, - dri2_surf->drawable, - target, - gc, - 0, 0, - 0, 0, - dri2_surf->base.Width, - dri2_surf->base.Height); - xcb_free_gc(dri2_dpy->conn, gc); - - return EGL_TRUE; -} - -static EGLBoolean dri2_bind_tex_image(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer) { @@ -2009,94 +821,6 @@ dri2_release_tex_image(_EGLDriver *drv, } static _EGLImage * -dri2_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx, - EGLClientBuffer buffer, const EGLint *attr_list) -{ - struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); - struct dri2_egl_image *dri2_img; - unsigned int attachments[1]; - xcb_drawable_t drawable; - xcb_dri2_get_buffers_cookie_t buffers_cookie; - xcb_dri2_get_buffers_reply_t *buffers_reply; - xcb_dri2_dri2_buffer_t *buffers; - xcb_get_geometry_cookie_t geometry_cookie; - xcb_get_geometry_reply_t *geometry_reply; - xcb_generic_error_t *error; - int stride, format; - - (void) ctx; - - drawable = (xcb_drawable_t) buffer; - xcb_dri2_create_drawable (dri2_dpy->conn, drawable); - attachments[0] = XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT; - buffers_cookie = - xcb_dri2_get_buffers_unchecked (dri2_dpy->conn, - drawable, 1, 1, attachments); - geometry_cookie = xcb_get_geometry (dri2_dpy->conn, drawable); - buffers_reply = xcb_dri2_get_buffers_reply (dri2_dpy->conn, - buffers_cookie, NULL); - buffers = xcb_dri2_get_buffers_buffers (buffers_reply); - if (buffers == NULL) { - return NULL; - } - - geometry_reply = xcb_get_geometry_reply (dri2_dpy->conn, - geometry_cookie, &error); - if (geometry_reply == NULL || error != NULL) { - _eglError(EGL_BAD_ALLOC, "xcb_get_geometry"); - free(error); - free(buffers_reply); - } - - switch (geometry_reply->depth) { - case 16: - format = __DRI_IMAGE_FORMAT_RGB565; - break; - case 24: - format = __DRI_IMAGE_FORMAT_XRGB8888; - break; - case 32: - format = __DRI_IMAGE_FORMAT_ARGB8888; - break; - default: - _eglError(EGL_BAD_PARAMETER, - "dri2_create_image_khr: unsupported pixmap depth"); - free(buffers_reply); - free(geometry_reply); - return NULL; - } - - dri2_img = malloc(sizeof *dri2_img); - if (!dri2_img) { - free(buffers_reply); - free(geometry_reply); - _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr"); - return EGL_NO_IMAGE_KHR; - } - - if (!_eglInitImage(&dri2_img->base, disp)) { - free(buffers_reply); - free(geometry_reply); - return EGL_NO_IMAGE_KHR; - } - - stride = buffers[0].pitch / buffers[0].cpp; - dri2_img->dri_image = - dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen, - buffers_reply->width, - buffers_reply->height, - format, - buffers[0].name, - stride, - dri2_img); - - free(buffers_reply); - free(geometry_reply); - - return &dri2_img->base; -} - -static _EGLImage * dri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx, EGLClientBuffer buffer, const EGLint *attr_list) @@ -2191,7 +915,7 @@ dri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx, return &dri2_img->base; } -static _EGLImage * +_EGLImage * dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attr_list) @@ -2199,8 +923,6 @@ dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp, (void) drv; switch (target) { - case EGL_NATIVE_PIXMAP_KHR: - return dri2_create_image_khr_pixmap(disp, ctx, buffer, attr_list); case EGL_GL_RENDERBUFFER_KHR: return dri2_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list); case EGL_DRM_BUFFER_MESA: @@ -2337,6 +1059,9 @@ static void dri2_unload(_EGLDriver *drv) { struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); + + if (dri2_drv->handle) + dlclose(dri2_drv->handle); free(dri2_drv); } @@ -2344,23 +1069,30 @@ static EGLBoolean dri2_load(_EGLDriver *drv) { struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); +#ifdef HAVE_SHARED_GLAPI + const char *libname = "libglapi.so.0"; +#else + /* + * Both libGL.so and libglapi.so are glapi providers. There is no way to + * tell which one to load. + */ + const char *libname = NULL; +#endif void *handle; - handle = dlopen(NULL, RTLD_LAZY | RTLD_GLOBAL); + /* RTLD_GLOBAL to make sure glapi symbols are visible to DRI drivers */ + handle = dlopen(libname, RTLD_LAZY | RTLD_GLOBAL); if (handle) { dri2_drv->get_proc_address = (_EGLProc (*)(const char *)) dlsym(handle, "_glapi_get_proc_address"); - /* no need to keep a reference */ - dlclose(handle); + if (!dri2_drv->get_proc_address || !libname) { + /* no need to keep a reference */ + dlclose(handle); + handle = NULL; + } } - /* - * If glapi is not available, loading DRI drivers will fail. Ideally, we - * should load one of libGL, libGLESv1_CM, or libGLESv2 and go on. But if - * the app has loaded another one of them with RTLD_LOCAL, there may be - * unexpected behaviors later because there will be two copies of glapi - * (with global variables of the same names!) in the memory. - */ + /* if glapi is not available, loading DRI drivers will fail */ if (!dri2_drv->get_proc_address) { _eglLog(_EGL_WARNING, "DRI2: failed to find _glapi_get_proc_address"); return EGL_FALSE; @@ -2369,6 +1101,8 @@ dri2_load(_EGLDriver *drv) dri2_drv->glFlush = (void (*)(void)) dri2_drv->get_proc_address("glFlush"); + dri2_drv->handle = handle; + return EGL_TRUE; } @@ -2397,20 +1131,13 @@ _EGL_MAIN(const char *args) dri2_drv->base.API.Terminate = dri2_terminate; dri2_drv->base.API.CreateContext = dri2_create_context; dri2_drv->base.API.MakeCurrent = dri2_make_current; - dri2_drv->base.API.CreateWindowSurface = dri2_create_window_surface; - dri2_drv->base.API.CreatePixmapSurface = dri2_create_pixmap_surface; - dri2_drv->base.API.CreatePbufferSurface = dri2_create_pbuffer_surface; - dri2_drv->base.API.DestroySurface = dri2_destroy_surface; - dri2_drv->base.API.SwapBuffers = dri2_swap_buffers; dri2_drv->base.API.GetProcAddress = dri2_get_proc_address; dri2_drv->base.API.WaitClient = dri2_wait_client; dri2_drv->base.API.WaitNative = dri2_wait_native; - dri2_drv->base.API.CopyBuffers = dri2_copy_buffers; dri2_drv->base.API.BindTexImage = dri2_bind_tex_image; dri2_drv->base.API.ReleaseTexImage = dri2_release_tex_image; dri2_drv->base.API.CreateImageKHR = dri2_create_image_khr; dri2_drv->base.API.DestroyImageKHR = dri2_destroy_image_khr; - dri2_drv->base.API.SwapBuffersRegionNOK = dri2_swap_buffers_region; dri2_drv->base.API.CreateDRMImageMESA = dri2_create_drm_image_mesa; dri2_drv->base.API.ExportDRMImageMESA = dri2_export_drm_image_mesa; diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h new file mode 100644 index 00000000000..235e30df3d8 --- /dev/null +++ b/src/egl/drivers/dri2/egl_dri2.h @@ -0,0 +1,195 @@ +/* + * Copyright © 2011 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Kristian Høgsberg <[email protected]> + */ + +#ifndef EGL_DRI2_INCLUDED +#define EGL_DRI2_INCLUDED + +#include <xcb/xcb.h> +#include <xcb/dri2.h> +#include <xcb/xfixes.h> +#include <X11/Xlib-xcb.h> + +#ifdef HAVE_WAYLAND_PLATFORM +#include <wayland-client.h> +#include "wayland-egl-priv.h" +#endif + +#include <GL/gl.h> +#include <GL/internal/dri_interface.h> + +#include "eglconfig.h" +#include "eglcontext.h" +#include "egldisplay.h" +#include "egldriver.h" +#include "eglcurrent.h" +#include "egllog.h" +#include "eglsurface.h" +#include "eglimage.h" + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + +struct dri2_egl_driver +{ + _EGLDriver base; + + void *handle; + _EGLProc (*get_proc_address)(const char *procname); + void (*glFlush)(void); +}; + +struct dri2_egl_display +{ + xcb_connection_t *conn; + int dri2_major; + int dri2_minor; + __DRIscreen *dri_screen; + const __DRIconfig **driver_configs; + void *driver; + __DRIcoreExtension *core; + __DRIdri2Extension *dri2; + __DRIswrastExtension *swrast; + __DRI2flushExtension *flush; + __DRItexBufferExtension *tex_buffer; + __DRIimageExtension *image; + int fd; + + char *device_name; + char *driver_name; + + __DRIdri2LoaderExtension dri2_loader_extension; + __DRIswrastLoaderExtension swrast_loader_extension; + const __DRIextension *extensions[3]; +#ifdef HAVE_WAYLAND_PLATFORM + struct wl_egl_display *wl_dpy; +#endif +}; + +struct dri2_egl_context +{ + _EGLContext base; + __DRIcontext *dri_context; +}; + +#ifdef HAVE_WAYLAND_PLATFORM +enum wayland_buffer_type { + WL_BUFFER_FRONT, + WL_BUFFER_BACK, + WL_BUFFER_COUNT +}; + +#define __DRI_BUFFER_COUNT 10 +#endif + +enum dri2_surface_type { + DRI2_WINDOW_SURFACE, + DRI2_PIXMAP_SURFACE, + DRI2_PBUFFER_SURFACE +}; + +struct dri2_egl_surface +{ + _EGLSurface base; + __DRIdrawable *dri_drawable; + xcb_drawable_t drawable; + __DRIbuffer buffers[5]; + int buffer_count; + xcb_xfixes_region_t region; + int have_fake_front; + int swap_interval; + + int depth; + int bytes_per_pixel; + xcb_gcontext_t gc; + xcb_gcontext_t swapgc; + + enum dri2_surface_type type; +#ifdef HAVE_WAYLAND_PLATFORM + struct wl_egl_window *wl_win; + struct wl_egl_pixmap *wl_pix; + struct wl_buffer *wl_drm_buffer[WL_BUFFER_COUNT]; + int dx; + int dy; + __DRIbuffer *dri_buffers[__DRI_BUFFER_COUNT]; + __DRIbuffer *pending_buffer; + EGLBoolean block_swap_buffers; +#endif +}; + +struct dri2_egl_buffer { + __DRIbuffer *dri_buffer; + struct dri2_egl_display *dri2_dpy; +}; + + +struct dri2_egl_config +{ + _EGLConfig base; + const __DRIconfig *dri_single_config; + const __DRIconfig *dri_double_config; +}; + +struct dri2_egl_image +{ + _EGLImage base; + __DRIimage *dri_image; +}; + +/* standard typecasts */ +_EGL_DRIVER_STANDARD_TYPECASTS(dri2_egl) +_EGL_DRIVER_TYPECAST(dri2_egl_image, _EGLImage, obj) + +extern const __DRIimageLookupExtension image_lookup_extension; +extern const __DRIuseInvalidateExtension use_invalidate; + +EGLBoolean +dri2_load_driver(_EGLDisplay *disp); + +EGLBoolean +dri2_create_screen(_EGLDisplay *disp); + +struct dri2_egl_config * +dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id, + int depth, EGLint surface_type, const EGLint *attr_list); + +_EGLImage * +dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp, + _EGLContext *ctx, EGLenum target, + EGLClientBuffer buffer, const EGLint *attr_list); + +EGLBoolean +dri2_initialize_x11(_EGLDriver *drv, _EGLDisplay *disp); + +EGLBoolean +dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp); + +EGLBoolean +dri2_initialize_wayland(_EGLDriver *drv, _EGLDisplay *disp); + +char * +dri2_get_driver_for_fd(int fd); + +#endif /* EGL_DRI2_INCLUDED */ diff --git a/src/egl/drivers/dri2/platform_drm.c b/src/egl/drivers/dri2/platform_drm.c new file mode 100644 index 00000000000..3dab899decb --- /dev/null +++ b/src/egl/drivers/dri2/platform_drm.c @@ -0,0 +1,683 @@ +/* + * Copyright © 2011 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Kristian Høgsberg <[email protected]> + */ + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <limits.h> +#include <dlfcn.h> +#include <fcntl.h> +#include <errno.h> +#include <unistd.h> +#include <xf86drm.h> +#include <sys/types.h> +#include <sys/stat.h> + +#ifdef HAVE_LIBUDEV +#include <libudev.h> +#endif + +#include "egl_dri2.h" + + +#ifdef HAVE_LIBUDEV + +struct dri2_driver_map { + int vendor_id; + const char *driver; + const int *chip_ids; + int num_chips_ids; +}; + +const int i915_chip_ids[] = { + 0x3577, /* PCI_CHIP_I830_M */ + 0x2562, /* PCI_CHIP_845_G */ + 0x3582, /* PCI_CHIP_I855_GM */ + 0x2572, /* PCI_CHIP_I865_G */ + 0x2582, /* PCI_CHIP_I915_G */ + 0x258a, /* PCI_CHIP_E7221_G */ + 0x2592, /* PCI_CHIP_I915_GM */ + 0x2772, /* PCI_CHIP_I945_G */ + 0x27a2, /* PCI_CHIP_I945_GM */ + 0x27ae, /* PCI_CHIP_I945_GME */ + 0x29b2, /* PCI_CHIP_Q35_G */ + 0x29c2, /* PCI_CHIP_G33_G */ + 0x29d2, /* PCI_CHIP_Q33_G */ + 0xa001, /* PCI_CHIP_IGD_G */ + 0xa011, /* Pineview */ +}; + +const int i965_chip_ids[] = { + 0x0042, /* PCI_CHIP_ILD_G */ + 0x0046, /* PCI_CHIP_ILM_G */ + 0x0102, /* PCI_CHIP_SANDYBRIDGE_GT1 */ + 0x0106, /* PCI_CHIP_SANDYBRIDGE_M_GT1 */ + 0x010a, /* PCI_CHIP_SANDYBRIDGE_S */ + 0x0112, /* PCI_CHIP_SANDYBRIDGE_GT2 */ + 0x0116, /* PCI_CHIP_SANDYBRIDGE_M_GT2 */ + 0x0122, /* PCI_CHIP_SANDYBRIDGE_GT2_PLUS */ + 0x0126, /* PCI_CHIP_SANDYBRIDGE_M_GT2_PLUS */ + 0x29a2, /* PCI_CHIP_I965_G */ + 0x2992, /* PCI_CHIP_I965_Q */ + 0x2982, /* PCI_CHIP_I965_G_1 */ + 0x2972, /* PCI_CHIP_I946_GZ */ + 0x2a02, /* PCI_CHIP_I965_GM */ + 0x2a12, /* PCI_CHIP_I965_GME */ + 0x2a42, /* PCI_CHIP_GM45_GM */ + 0x2e02, /* PCI_CHIP_IGD_E_G */ + 0x2e12, /* PCI_CHIP_Q45_G */ + 0x2e22, /* PCI_CHIP_G45_G */ + 0x2e32, /* PCI_CHIP_G41_G */ + 0x2e42, /* PCI_CHIP_B43_G */ + 0x2e92, /* PCI_CHIP_B43_G1 */ +}; + +const int r100_chip_ids[] = { + 0x4C57, /* PCI_CHIP_RADEON_LW */ + 0x4C58, /* PCI_CHIP_RADEON_LX */ + 0x4C59, /* PCI_CHIP_RADEON_LY */ + 0x4C5A, /* PCI_CHIP_RADEON_LZ */ + 0x5144, /* PCI_CHIP_RADEON_QD */ + 0x5145, /* PCI_CHIP_RADEON_QE */ + 0x5146, /* PCI_CHIP_RADEON_QF */ + 0x5147, /* PCI_CHIP_RADEON_QG */ + 0x5159, /* PCI_CHIP_RADEON_QY */ + 0x515A, /* PCI_CHIP_RADEON_QZ */ + 0x5157, /* PCI_CHIP_RV200_QW */ + 0x5158, /* PCI_CHIP_RV200_QX */ + 0x515E, /* PCI_CHIP_RN50_515E */ + 0x5969, /* PCI_CHIP_RN50_5969 */ + 0x4136, /* PCI_CHIP_RS100_4136 */ + 0x4336, /* PCI_CHIP_RS100_4336 */ + 0x4137, /* PCI_CHIP_RS200_4137 */ + 0x4337, /* PCI_CHIP_RS200_4337 */ + 0x4237, /* PCI_CHIP_RS250_4237 */ + 0x4437, /* PCI_CHIP_RS250_4437 */ +}; + +const int r200_chip_ids[] = { + 0x5148, /* PCI_CHIP_R200_QH */ + 0x514C, /* PCI_CHIP_R200_QL */ + 0x514D, /* PCI_CHIP_R200_QM */ + 0x4242, /* PCI_CHIP_R200_BB */ + 0x4966, /* PCI_CHIP_RV250_If */ + 0x4967, /* PCI_CHIP_RV250_Ig */ + 0x4C64, /* PCI_CHIP_RV250_Ld */ + 0x4C66, /* PCI_CHIP_RV250_Lf */ + 0x4C67, /* PCI_CHIP_RV250_Lg */ + 0x5960, /* PCI_CHIP_RV280_5960 */ + 0x5961, /* PCI_CHIP_RV280_5961 */ + 0x5962, /* PCI_CHIP_RV280_5962 */ + 0x5964, /* PCI_CHIP_RV280_5964 */ + 0x5965, /* PCI_CHIP_RV280_5965 */ + 0x5C61, /* PCI_CHIP_RV280_5C61 */ + 0x5C63, /* PCI_CHIP_RV280_5C63 */ + 0x5834, /* PCI_CHIP_RS300_5834 */ + 0x5835, /* PCI_CHIP_RS300_5835 */ + 0x7834, /* PCI_CHIP_RS350_7834 */ + 0x7835, /* PCI_CHIP_RS350_7835 */ +}; + +const int r300_chip_ids[] = { + 0x4144, /* PCI_CHIP_R300_AD */ + 0x4145, /* PCI_CHIP_R300_AE */ + 0x4146, /* PCI_CHIP_R300_AF */ + 0x4147, /* PCI_CHIP_R300_AG */ + 0x4E44, /* PCI_CHIP_R300_ND */ + 0x4E45, /* PCI_CHIP_R300_NE */ + 0x4E46, /* PCI_CHIP_R300_NF */ + 0x4E47, /* PCI_CHIP_R300_NG */ + 0x4E48, /* PCI_CHIP_R350_NH */ + 0x4E49, /* PCI_CHIP_R350_NI */ + 0x4E4B, /* PCI_CHIP_R350_NK */ + 0x4148, /* PCI_CHIP_R350_AH */ + 0x4149, /* PCI_CHIP_R350_AI */ + 0x414A, /* PCI_CHIP_R350_AJ */ + 0x414B, /* PCI_CHIP_R350_AK */ + 0x4E4A, /* PCI_CHIP_R360_NJ */ + 0x4150, /* PCI_CHIP_RV350_AP */ + 0x4151, /* PCI_CHIP_RV350_AQ */ + 0x4152, /* PCI_CHIP_RV350_AR */ + 0x4153, /* PCI_CHIP_RV350_AS */ + 0x4154, /* PCI_CHIP_RV350_AT */ + 0x4155, /* PCI_CHIP_RV350_AU */ + 0x4156, /* PCI_CHIP_RV350_AV */ + 0x4E50, /* PCI_CHIP_RV350_NP */ + 0x4E51, /* PCI_CHIP_RV350_NQ */ + 0x4E52, /* PCI_CHIP_RV350_NR */ + 0x4E53, /* PCI_CHIP_RV350_NS */ + 0x4E54, /* PCI_CHIP_RV350_NT */ + 0x4E56, /* PCI_CHIP_RV350_NV */ + 0x5460, /* PCI_CHIP_RV370_5460 */ + 0x5462, /* PCI_CHIP_RV370_5462 */ + 0x5464, /* PCI_CHIP_RV370_5464 */ + 0x5B60, /* PCI_CHIP_RV370_5B60 */ + 0x5B62, /* PCI_CHIP_RV370_5B62 */ + 0x5B63, /* PCI_CHIP_RV370_5B63 */ + 0x5B64, /* PCI_CHIP_RV370_5B64 */ + 0x5B65, /* PCI_CHIP_RV370_5B65 */ + 0x3150, /* PCI_CHIP_RV380_3150 */ + 0x3152, /* PCI_CHIP_RV380_3152 */ + 0x3154, /* PCI_CHIP_RV380_3154 */ + 0x3155, /* PCI_CHIP_RV380_3155 */ + 0x3E50, /* PCI_CHIP_RV380_3E50 */ + 0x3E54, /* PCI_CHIP_RV380_3E54 */ + 0x4A48, /* PCI_CHIP_R420_JH */ + 0x4A49, /* PCI_CHIP_R420_JI */ + 0x4A4A, /* PCI_CHIP_R420_JJ */ + 0x4A4B, /* PCI_CHIP_R420_JK */ + 0x4A4C, /* PCI_CHIP_R420_JL */ + 0x4A4D, /* PCI_CHIP_R420_JM */ + 0x4A4E, /* PCI_CHIP_R420_JN */ + 0x4A4F, /* PCI_CHIP_R420_JO */ + 0x4A50, /* PCI_CHIP_R420_JP */ + 0x4A54, /* PCI_CHIP_R420_JT */ + 0x5548, /* PCI_CHIP_R423_UH */ + 0x5549, /* PCI_CHIP_R423_UI */ + 0x554A, /* PCI_CHIP_R423_UJ */ + 0x554B, /* PCI_CHIP_R423_UK */ + 0x5550, /* PCI_CHIP_R423_5550 */ + 0x5551, /* PCI_CHIP_R423_UQ */ + 0x5552, /* PCI_CHIP_R423_UR */ + 0x5554, /* PCI_CHIP_R423_UT */ + 0x5D57, /* PCI_CHIP_R423_5D57 */ + 0x554C, /* PCI_CHIP_R430_554C */ + 0x554D, /* PCI_CHIP_R430_554D */ + 0x554E, /* PCI_CHIP_R430_554E */ + 0x554F, /* PCI_CHIP_R430_554F */ + 0x5D48, /* PCI_CHIP_R430_5D48 */ + 0x5D49, /* PCI_CHIP_R430_5D49 */ + 0x5D4A, /* PCI_CHIP_R430_5D4A */ + 0x5D4C, /* PCI_CHIP_R480_5D4C */ + 0x5D4D, /* PCI_CHIP_R480_5D4D */ + 0x5D4E, /* PCI_CHIP_R480_5D4E */ + 0x5D4F, /* PCI_CHIP_R480_5D4F */ + 0x5D50, /* PCI_CHIP_R480_5D50 */ + 0x5D52, /* PCI_CHIP_R480_5D52 */ + 0x4B49, /* PCI_CHIP_R481_4B49 */ + 0x4B4A, /* PCI_CHIP_R481_4B4A */ + 0x4B4B, /* PCI_CHIP_R481_4B4B */ + 0x4B4C, /* PCI_CHIP_R481_4B4C */ + 0x564A, /* PCI_CHIP_RV410_564A */ + 0x564B, /* PCI_CHIP_RV410_564B */ + 0x564F, /* PCI_CHIP_RV410_564F */ + 0x5652, /* PCI_CHIP_RV410_5652 */ + 0x5653, /* PCI_CHIP_RV410_5653 */ + 0x5657, /* PCI_CHIP_RV410_5657 */ + 0x5E48, /* PCI_CHIP_RV410_5E48 */ + 0x5E4A, /* PCI_CHIP_RV410_5E4A */ + 0x5E4B, /* PCI_CHIP_RV410_5E4B */ + 0x5E4C, /* PCI_CHIP_RV410_5E4C */ + 0x5E4D, /* PCI_CHIP_RV410_5E4D */ + 0x5E4F, /* PCI_CHIP_RV410_5E4F */ + 0x5A41, /* PCI_CHIP_RS400_5A41 */ + 0x5A42, /* PCI_CHIP_RS400_5A42 */ + 0x5A61, /* PCI_CHIP_RC410_5A61 */ + 0x5A62, /* PCI_CHIP_RC410_5A62 */ + 0x5954, /* PCI_CHIP_RS480_5954 */ + 0x5955, /* PCI_CHIP_RS480_5955 */ + 0x5974, /* PCI_CHIP_RS482_5974 */ + 0x5975, /* PCI_CHIP_RS482_5975 */ + 0x7100, /* PCI_CHIP_R520_7100 */ + 0x7101, /* PCI_CHIP_R520_7101 */ + 0x7102, /* PCI_CHIP_R520_7102 */ + 0x7103, /* PCI_CHIP_R520_7103 */ + 0x7104, /* PCI_CHIP_R520_7104 */ + 0x7105, /* PCI_CHIP_R520_7105 */ + 0x7106, /* PCI_CHIP_R520_7106 */ + 0x7108, /* PCI_CHIP_R520_7108 */ + 0x7109, /* PCI_CHIP_R520_7109 */ + 0x710A, /* PCI_CHIP_R520_710A */ + 0x710B, /* PCI_CHIP_R520_710B */ + 0x710C, /* PCI_CHIP_R520_710C */ + 0x710E, /* PCI_CHIP_R520_710E */ + 0x710F, /* PCI_CHIP_R520_710F */ + 0x7140, /* PCI_CHIP_RV515_7140 */ + 0x7141, /* PCI_CHIP_RV515_7141 */ + 0x7142, /* PCI_CHIP_RV515_7142 */ + 0x7143, /* PCI_CHIP_RV515_7143 */ + 0x7144, /* PCI_CHIP_RV515_7144 */ + 0x7145, /* PCI_CHIP_RV515_7145 */ + 0x7146, /* PCI_CHIP_RV515_7146 */ + 0x7147, /* PCI_CHIP_RV515_7147 */ + 0x7149, /* PCI_CHIP_RV515_7149 */ + 0x714A, /* PCI_CHIP_RV515_714A */ + 0x714B, /* PCI_CHIP_RV515_714B */ + 0x714C, /* PCI_CHIP_RV515_714C */ + 0x714D, /* PCI_CHIP_RV515_714D */ + 0x714E, /* PCI_CHIP_RV515_714E */ + 0x714F, /* PCI_CHIP_RV515_714F */ + 0x7151, /* PCI_CHIP_RV515_7151 */ + 0x7152, /* PCI_CHIP_RV515_7152 */ + 0x7153, /* PCI_CHIP_RV515_7153 */ + 0x715E, /* PCI_CHIP_RV515_715E */ + 0x715F, /* PCI_CHIP_RV515_715F */ + 0x7180, /* PCI_CHIP_RV515_7180 */ + 0x7181, /* PCI_CHIP_RV515_7181 */ + 0x7183, /* PCI_CHIP_RV515_7183 */ + 0x7186, /* PCI_CHIP_RV515_7186 */ + 0x7187, /* PCI_CHIP_RV515_7187 */ + 0x7188, /* PCI_CHIP_RV515_7188 */ + 0x718A, /* PCI_CHIP_RV515_718A */ + 0x718B, /* PCI_CHIP_RV515_718B */ + 0x718C, /* PCI_CHIP_RV515_718C */ + 0x718D, /* PCI_CHIP_RV515_718D */ + 0x718F, /* PCI_CHIP_RV515_718F */ + 0x7193, /* PCI_CHIP_RV515_7193 */ + 0x7196, /* PCI_CHIP_RV515_7196 */ + 0x719B, /* PCI_CHIP_RV515_719B */ + 0x719F, /* PCI_CHIP_RV515_719F */ + 0x7200, /* PCI_CHIP_RV515_7200 */ + 0x7210, /* PCI_CHIP_RV515_7210 */ + 0x7211, /* PCI_CHIP_RV515_7211 */ + 0x71C0, /* PCI_CHIP_RV530_71C0 */ + 0x71C1, /* PCI_CHIP_RV530_71C1 */ + 0x71C2, /* PCI_CHIP_RV530_71C2 */ + 0x71C3, /* PCI_CHIP_RV530_71C3 */ + 0x71C4, /* PCI_CHIP_RV530_71C4 */ + 0x71C5, /* PCI_CHIP_RV530_71C5 */ + 0x71C6, /* PCI_CHIP_RV530_71C6 */ + 0x71C7, /* PCI_CHIP_RV530_71C7 */ + 0x71CD, /* PCI_CHIP_RV530_71CD */ + 0x71CE, /* PCI_CHIP_RV530_71CE */ + 0x71D2, /* PCI_CHIP_RV530_71D2 */ + 0x71D4, /* PCI_CHIP_RV530_71D4 */ + 0x71D5, /* PCI_CHIP_RV530_71D5 */ + 0x71D6, /* PCI_CHIP_RV530_71D6 */ + 0x71DA, /* PCI_CHIP_RV530_71DA */ + 0x71DE, /* PCI_CHIP_RV530_71DE */ + 0x7281, /* PCI_CHIP_RV560_7281 */ + 0x7283, /* PCI_CHIP_RV560_7283 */ + 0x7287, /* PCI_CHIP_RV560_7287 */ + 0x7290, /* PCI_CHIP_RV560_7290 */ + 0x7291, /* PCI_CHIP_RV560_7291 */ + 0x7293, /* PCI_CHIP_RV560_7293 */ + 0x7297, /* PCI_CHIP_RV560_7297 */ + 0x7280, /* PCI_CHIP_RV570_7280 */ + 0x7288, /* PCI_CHIP_RV570_7288 */ + 0x7289, /* PCI_CHIP_RV570_7289 */ + 0x728B, /* PCI_CHIP_RV570_728B */ + 0x728C, /* PCI_CHIP_RV570_728C */ + 0x7240, /* PCI_CHIP_R580_7240 */ + 0x7243, /* PCI_CHIP_R580_7243 */ + 0x7244, /* PCI_CHIP_R580_7244 */ + 0x7245, /* PCI_CHIP_R580_7245 */ + 0x7246, /* PCI_CHIP_R580_7246 */ + 0x7247, /* PCI_CHIP_R580_7247 */ + 0x7248, /* PCI_CHIP_R580_7248 */ + 0x7249, /* PCI_CHIP_R580_7249 */ + 0x724A, /* PCI_CHIP_R580_724A */ + 0x724B, /* PCI_CHIP_R580_724B */ + 0x724C, /* PCI_CHIP_R580_724C */ + 0x724D, /* PCI_CHIP_R580_724D */ + 0x724E, /* PCI_CHIP_R580_724E */ + 0x724F, /* PCI_CHIP_R580_724F */ + 0x7284, /* PCI_CHIP_R580_7284 */ + 0x793F, /* PCI_CHIP_RS600_793F */ + 0x7941, /* PCI_CHIP_RS600_7941 */ + 0x7942, /* PCI_CHIP_RS600_7942 */ + 0x791E, /* PCI_CHIP_RS690_791E */ + 0x791F, /* PCI_CHIP_RS690_791F */ + 0x796C, /* PCI_CHIP_RS740_796C */ + 0x796D, /* PCI_CHIP_RS740_796D */ + 0x796E, /* PCI_CHIP_RS740_796E */ + 0x796F, /* PCI_CHIP_RS740_796F */ +}; + +const int r600_chip_ids[] = { + 0x9400, /* PCI_CHIP_R600_9400 */ + 0x9401, /* PCI_CHIP_R600_9401 */ + 0x9402, /* PCI_CHIP_R600_9402 */ + 0x9403, /* PCI_CHIP_R600_9403 */ + 0x9405, /* PCI_CHIP_R600_9405 */ + 0x940A, /* PCI_CHIP_R600_940A */ + 0x940B, /* PCI_CHIP_R600_940B */ + 0x940F, /* PCI_CHIP_R600_940F */ + 0x94C0, /* PCI_CHIP_RV610_94C0 */ + 0x94C1, /* PCI_CHIP_RV610_94C1 */ + 0x94C3, /* PCI_CHIP_RV610_94C3 */ + 0x94C4, /* PCI_CHIP_RV610_94C4 */ + 0x94C5, /* PCI_CHIP_RV610_94C5 */ + 0x94C6, /* PCI_CHIP_RV610_94C6 */ + 0x94C7, /* PCI_CHIP_RV610_94C7 */ + 0x94C8, /* PCI_CHIP_RV610_94C8 */ + 0x94C9, /* PCI_CHIP_RV610_94C9 */ + 0x94CB, /* PCI_CHIP_RV610_94CB */ + 0x94CC, /* PCI_CHIP_RV610_94CC */ + 0x94CD, /* PCI_CHIP_RV610_94CD */ + 0x9580, /* PCI_CHIP_RV630_9580 */ + 0x9581, /* PCI_CHIP_RV630_9581 */ + 0x9583, /* PCI_CHIP_RV630_9583 */ + 0x9586, /* PCI_CHIP_RV630_9586 */ + 0x9587, /* PCI_CHIP_RV630_9587 */ + 0x9588, /* PCI_CHIP_RV630_9588 */ + 0x9589, /* PCI_CHIP_RV630_9589 */ + 0x958A, /* PCI_CHIP_RV630_958A */ + 0x958B, /* PCI_CHIP_RV630_958B */ + 0x958C, /* PCI_CHIP_RV630_958C */ + 0x958D, /* PCI_CHIP_RV630_958D */ + 0x958E, /* PCI_CHIP_RV630_958E */ + 0x958F, /* PCI_CHIP_RV630_958F */ + 0x9500, /* PCI_CHIP_RV670_9500 */ + 0x9501, /* PCI_CHIP_RV670_9501 */ + 0x9504, /* PCI_CHIP_RV670_9504 */ + 0x9505, /* PCI_CHIP_RV670_9505 */ + 0x9506, /* PCI_CHIP_RV670_9506 */ + 0x9507, /* PCI_CHIP_RV670_9507 */ + 0x9508, /* PCI_CHIP_RV670_9508 */ + 0x9509, /* PCI_CHIP_RV670_9509 */ + 0x950F, /* PCI_CHIP_RV670_950F */ + 0x9511, /* PCI_CHIP_RV670_9511 */ + 0x9515, /* PCI_CHIP_RV670_9515 */ + 0x9517, /* PCI_CHIP_RV670_9517 */ + 0x9519, /* PCI_CHIP_RV670_9519 */ + 0x95C0, /* PCI_CHIP_RV620_95C0 */ + 0x95C2, /* PCI_CHIP_RV620_95C2 */ + 0x95C4, /* PCI_CHIP_RV620_95C4 */ + 0x95C5, /* PCI_CHIP_RV620_95C5 */ + 0x95C6, /* PCI_CHIP_RV620_95C6 */ + 0x95C7, /* PCI_CHIP_RV620_95C7 */ + 0x95C9, /* PCI_CHIP_RV620_95C9 */ + 0x95CC, /* PCI_CHIP_RV620_95CC */ + 0x95CD, /* PCI_CHIP_RV620_95CD */ + 0x95CE, /* PCI_CHIP_RV620_95CE */ + 0x95CF, /* PCI_CHIP_RV620_95CF */ + 0x9590, /* PCI_CHIP_RV635_9590 */ + 0x9591, /* PCI_CHIP_RV635_9591 */ + 0x9593, /* PCI_CHIP_RV635_9593 */ + 0x9595, /* PCI_CHIP_RV635_9595 */ + 0x9596, /* PCI_CHIP_RV635_9596 */ + 0x9597, /* PCI_CHIP_RV635_9597 */ + 0x9598, /* PCI_CHIP_RV635_9598 */ + 0x9599, /* PCI_CHIP_RV635_9599 */ + 0x959B, /* PCI_CHIP_RV635_959B */ + 0x9610, /* PCI_CHIP_RS780_9610 */ + 0x9611, /* PCI_CHIP_RS780_9611 */ + 0x9612, /* PCI_CHIP_RS780_9612 */ + 0x9613, /* PCI_CHIP_RS780_9613 */ + 0x9614, /* PCI_CHIP_RS780_9614 */ + 0x9615, /* PCI_CHIP_RS780_9615 */ + 0x9616, /* PCI_CHIP_RS780_9616 */ + 0x9710, /* PCI_CHIP_RS880_9710 */ + 0x9711, /* PCI_CHIP_RS880_9711 */ + 0x9712, /* PCI_CHIP_RS880_9712 */ + 0x9713, /* PCI_CHIP_RS880_9713 */ + 0x9714, /* PCI_CHIP_RS880_9714 */ + 0x9715, /* PCI_CHIP_RS880_9715 */ + 0x9440, /* PCI_CHIP_RV770_9440 */ + 0x9441, /* PCI_CHIP_RV770_9441 */ + 0x9442, /* PCI_CHIP_RV770_9442 */ + 0x9443, /* PCI_CHIP_RV770_9443 */ + 0x9444, /* PCI_CHIP_RV770_9444 */ + 0x9446, /* PCI_CHIP_RV770_9446 */ + 0x944A, /* PCI_CHIP_RV770_944A */ + 0x944B, /* PCI_CHIP_RV770_944B */ + 0x944C, /* PCI_CHIP_RV770_944C */ + 0x944E, /* PCI_CHIP_RV770_944E */ + 0x9450, /* PCI_CHIP_RV770_9450 */ + 0x9452, /* PCI_CHIP_RV770_9452 */ + 0x9456, /* PCI_CHIP_RV770_9456 */ + 0x945A, /* PCI_CHIP_RV770_945A */ + 0x945B, /* PCI_CHIP_RV770_945B */ + 0x945E, /* PCI_CHIP_RV770_945E */ + 0x9460, /* PCI_CHIP_RV790_9460 */ + 0x9462, /* PCI_CHIP_RV790_9462 */ + 0x946A, /* PCI_CHIP_RV770_946A */ + 0x946B, /* PCI_CHIP_RV770_946B */ + 0x947A, /* PCI_CHIP_RV770_947A */ + 0x947B, /* PCI_CHIP_RV770_947B */ + 0x9480, /* PCI_CHIP_RV730_9480 */ + 0x9487, /* PCI_CHIP_RV730_9487 */ + 0x9488, /* PCI_CHIP_RV730_9488 */ + 0x9489, /* PCI_CHIP_RV730_9489 */ + 0x948A, /* PCI_CHIP_RV730_948A */ + 0x948F, /* PCI_CHIP_RV730_948F */ + 0x9490, /* PCI_CHIP_RV730_9490 */ + 0x9491, /* PCI_CHIP_RV730_9491 */ + 0x9495, /* PCI_CHIP_RV730_9495 */ + 0x9498, /* PCI_CHIP_RV730_9498 */ + 0x949C, /* PCI_CHIP_RV730_949C */ + 0x949E, /* PCI_CHIP_RV730_949E */ + 0x949F, /* PCI_CHIP_RV730_949F */ + 0x9540, /* PCI_CHIP_RV710_9540 */ + 0x9541, /* PCI_CHIP_RV710_9541 */ + 0x9542, /* PCI_CHIP_RV710_9542 */ + 0x954E, /* PCI_CHIP_RV710_954E */ + 0x954F, /* PCI_CHIP_RV710_954F */ + 0x9552, /* PCI_CHIP_RV710_9552 */ + 0x9553, /* PCI_CHIP_RV710_9553 */ + 0x9555, /* PCI_CHIP_RV710_9555 */ + 0x9557, /* PCI_CHIP_RV710_9557 */ + 0x955F, /* PCI_CHIP_RV710_955F */ + 0x94A0, /* PCI_CHIP_RV740_94A0 */ + 0x94A1, /* PCI_CHIP_RV740_94A1 */ + 0x94A3, /* PCI_CHIP_RV740_94A3 */ + 0x94B1, /* PCI_CHIP_RV740_94B1 */ + 0x94B3, /* PCI_CHIP_RV740_94B3 */ + 0x94B4, /* PCI_CHIP_RV740_94B4 */ + 0x94B5, /* PCI_CHIP_RV740_94B5 */ + 0x94B9, /* PCI_CHIP_RV740_94B9 */ + 0x68E0, /* PCI_CHIP_CEDAR_68E0 */ + 0x68E1, /* PCI_CHIP_CEDAR_68E1 */ + 0x68E4, /* PCI_CHIP_CEDAR_68E4 */ + 0x68E5, /* PCI_CHIP_CEDAR_68E5 */ + 0x68E8, /* PCI_CHIP_CEDAR_68E8 */ + 0x68E9, /* PCI_CHIP_CEDAR_68E9 */ + 0x68F1, /* PCI_CHIP_CEDAR_68F1 */ + 0x68F8, /* PCI_CHIP_CEDAR_68F8 */ + 0x68F9, /* PCI_CHIP_CEDAR_68F9 */ + 0x68FE, /* PCI_CHIP_CEDAR_68FE */ + 0x68C0, /* PCI_CHIP_REDWOOD_68C0 */ + 0x68C1, /* PCI_CHIP_REDWOOD_68C1 */ + 0x68C8, /* PCI_CHIP_REDWOOD_68C8 */ + 0x68C9, /* PCI_CHIP_REDWOOD_68C9 */ + 0x68D8, /* PCI_CHIP_REDWOOD_68D8 */ + 0x68D9, /* PCI_CHIP_REDWOOD_68D9 */ + 0x68DA, /* PCI_CHIP_REDWOOD_68DA */ + 0x68DE, /* PCI_CHIP_REDWOOD_68DE */ + 0x68A0, /* PCI_CHIP_JUNIPER_68A0 */ + 0x68A1, /* PCI_CHIP_JUNIPER_68A1 */ + 0x68A8, /* PCI_CHIP_JUNIPER_68A8 */ + 0x68A9, /* PCI_CHIP_JUNIPER_68A9 */ + 0x68B0, /* PCI_CHIP_JUNIPER_68B0 */ + 0x68B8, /* PCI_CHIP_JUNIPER_68B8 */ + 0x68B9, /* PCI_CHIP_JUNIPER_68B9 */ + 0x68BE, /* PCI_CHIP_JUNIPER_68BE */ + 0x6880, /* PCI_CHIP_CYPRESS_6880 */ + 0x6888, /* PCI_CHIP_CYPRESS_6888 */ + 0x6889, /* PCI_CHIP_CYPRESS_6889 */ + 0x688A, /* PCI_CHIP_CYPRESS_688A */ + 0x6898, /* PCI_CHIP_CYPRESS_6898 */ + 0x6899, /* PCI_CHIP_CYPRESS_6899 */ + 0x689E, /* PCI_CHIP_CYPRESS_689E */ + 0x689C, /* PCI_CHIP_HEMLOCK_689C */ + 0x689D, /* PCI_CHIP_HEMLOCK_689D */ + 0x9802, /* PCI_CHIP_PALM_9802 */ + 0x9803, /* PCI_CHIP_PALM_9803 */ + 0x9804, /* PCI_CHIP_PALM_9804 */ + 0x9805, /* PCI_CHIP_PALM_9805 */ + 0x6720, /* PCI_CHIP_BARTS_6720 */ + 0x6721, /* PCI_CHIP_BARTS_6721 */ + 0x6722, /* PCI_CHIP_BARTS_6722 */ + 0x6723, /* PCI_CHIP_BARTS_6723 */ + 0x6724, /* PCI_CHIP_BARTS_6724 */ + 0x6725, /* PCI_CHIP_BARTS_6725 */ + 0x6726, /* PCI_CHIP_BARTS_6726 */ + 0x6727, /* PCI_CHIP_BARTS_6727 */ + 0x6728, /* PCI_CHIP_BARTS_6728 */ + 0x6729, /* PCI_CHIP_BARTS_6729 */ + 0x6738, /* PCI_CHIP_BARTS_6738 */ + 0x6739, /* PCI_CHIP_BARTS_6738 */ + 0x6740, /* PCI_CHIP_TURKS_6740 */ + 0x6741, /* PCI_CHIP_TURKS_6741 */ + 0x6742, /* PCI_CHIP_TURKS_6742 */ + 0x6743, /* PCI_CHIP_TURKS_6743 */ + 0x6744, /* PCI_CHIP_TURKS_6744 */ + 0x6745, /* PCI_CHIP_TURKS_6745 */ + 0x6746, /* PCI_CHIP_TURKS_6746 */ + 0x6747, /* PCI_CHIP_TURKS_6747 */ + 0x6748, /* PCI_CHIP_TURKS_6748 */ + 0x6749, /* PCI_CHIP_TURKS_6749 */ + 0x6750, /* PCI_CHIP_TURKS_6750 */ + 0x6758, /* PCI_CHIP_TURKS_6758 */ + 0x6759, /* PCI_CHIP_TURKS_6759 */ + 0x6760, /* PCI_CHIP_CAICOS_6760 */ + 0x6761, /* PCI_CHIP_CAICOS_6761 */ + 0x6762, /* PCI_CHIP_CAICOS_6762 */ + 0x6763, /* PCI_CHIP_CAICOS_6763 */ + 0x6764, /* PCI_CHIP_CAICOS_6764 */ + 0x6765, /* PCI_CHIP_CAICOS_6765 */ + 0x6766, /* PCI_CHIP_CAICOS_6766 */ + 0x6767, /* PCI_CHIP_CAICOS_6767 */ + 0x6768, /* PCI_CHIP_CAICOS_6768 */ + 0x6770, /* PCI_CHIP_CAICOS_6770 */ + 0x6779, /* PCI_CHIP_CAICOS_6779 */ +}; + +const struct dri2_driver_map driver_map[] = { + { 0x8086, "i915", i915_chip_ids, ARRAY_SIZE(i915_chip_ids) }, + { 0x8086, "i965", i965_chip_ids, ARRAY_SIZE(i965_chip_ids) }, + { 0x1002, "radeon", r100_chip_ids, ARRAY_SIZE(r100_chip_ids) }, + { 0x1002, "r200", r200_chip_ids, ARRAY_SIZE(r200_chip_ids) }, + { 0x1002, "r300", r300_chip_ids, ARRAY_SIZE(r300_chip_ids) }, + { 0x1002, "r600", r600_chip_ids, ARRAY_SIZE(r600_chip_ids) }, + { 0x10de, "nouveau", NULL, -1 }, +}; + +char * +dri2_get_driver_for_fd(int fd) +{ + struct udev *udev; + struct udev_device *device, *parent; + struct stat buf; + const char *pci_id; + char *driver = NULL; + int vendor_id, chip_id, i, j; + + udev = udev_new(); + if (fstat(fd, &buf) < 0) { + _eglLog(_EGL_WARNING, "EGL-DRI2: failed to stat fd %d", fd); + goto out; + } + + device = udev_device_new_from_devnum(udev, 'c', buf.st_rdev); + if (device == NULL) { + _eglLog(_EGL_WARNING, + "EGL-DRI2: could not create udev device for fd %d", fd); + goto out; + } + + parent = udev_device_get_parent(device); + if (parent == NULL) { + _eglLog(_EGL_WARNING, "DRI2: could not get parent device"); + goto out; + } + + pci_id = udev_device_get_property_value(parent, "PCI_ID"); + if (pci_id == NULL || sscanf(pci_id, "%x:%x", &vendor_id, &chip_id) != 2) { + _eglLog(_EGL_WARNING, "EGL-DRI2: malformed or no PCI ID"); + goto out; + } + + for (i = 0; i < ARRAY_SIZE(driver_map); i++) { + if (vendor_id != driver_map[i].vendor_id) + continue; + if (driver_map[i].num_chips_ids == -1) { + driver = strdup(driver_map[i].driver); + _eglLog(_EGL_DEBUG, "pci id for %d: %04x:%04x, driver %s", + fd, vendor_id, chip_id, driver); + goto out; + } + + for (j = 0; j < driver_map[i].num_chips_ids; j++) + if (driver_map[i].chip_ids[j] == chip_id) { + driver = strdup(driver_map[i].driver); + _eglLog(_EGL_DEBUG, "pci id for %d: %04x:%04x, driver %s", + fd, vendor_id, chip_id, driver); + goto out; + } + } + + out: + udev_device_unref(device); + udev_unref(udev); + + return driver; +} + +EGLBoolean +dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp) +{ + struct dri2_egl_display *dri2_dpy; + int i; + + dri2_dpy = malloc(sizeof *dri2_dpy); + if (!dri2_dpy) + return _eglError(EGL_BAD_ALLOC, "eglInitialize"); + + memset(dri2_dpy, 0, sizeof *dri2_dpy); + + disp->DriverData = (void *) dri2_dpy; + dri2_dpy->fd = (int) disp->PlatformDisplay; + + dri2_dpy->driver_name = dri2_get_driver_for_fd(dri2_dpy->fd); + if (dri2_dpy->driver_name == NULL) + return _eglError(EGL_BAD_ALLOC, "DRI2: failed to get driver name"); + + if (!dri2_load_driver(disp)) + goto cleanup_driver_name; + + dri2_dpy->extensions[0] = &image_lookup_extension.base; + dri2_dpy->extensions[1] = &use_invalidate.base; + dri2_dpy->extensions[2] = NULL; + + if (!dri2_create_screen(disp)) + goto cleanup_driver; + + for (i = 0; dri2_dpy->driver_configs[i]; i++) + dri2_add_config(disp, dri2_dpy->driver_configs[i], i + 1, 0, 0, NULL); + + disp->Extensions.MESA_drm_image = EGL_TRUE; + disp->Extensions.KHR_image_base = EGL_TRUE; + disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE; + disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE; + + /* we're supporting EGL 1.4 */ + disp->VersionMajor = 1; + disp->VersionMinor = 4; + + return EGL_TRUE; + + cleanup_driver: + dlclose(dri2_dpy->driver); + cleanup_driver_name: + free(dri2_dpy->driver_name); + + return EGL_FALSE; +} + +#endif diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c new file mode 100644 index 00000000000..21b440624ff --- /dev/null +++ b/src/egl/drivers/dri2/platform_wayland.c @@ -0,0 +1,673 @@ +/* + * Copyright © 2011 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Kristian Høgsberg <[email protected]> + * Benjamin Franzke <[email protected]> + */ + +#include <stdlib.h> +#include <string.h> +#include <limits.h> +#include <dlfcn.h> +#include <errno.h> +#include <unistd.h> + +#include "egl_dri2.h" + +static void +sync_callback(void *data) +{ + int *done = data; + + *done = 1; +} + +static void +force_roundtrip(struct wl_display *display) +{ + int done = 0; + + wl_display_sync_callback(display, sync_callback, &done); + wl_display_iterate(display, WL_DISPLAY_WRITABLE); + while (!done) + wl_display_iterate(display, WL_DISPLAY_READABLE); +} + + +/** + * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface(). + */ +static _EGLSurface * +dri2_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type, + _EGLConfig *conf, EGLNativeWindowType window, + const EGLint *attrib_list) +{ + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + struct dri2_egl_config *dri2_conf = dri2_egl_config(conf); + struct dri2_egl_surface *dri2_surf; + struct dri2_egl_buffer *dri2_buf; + int i; + + (void) drv; + + dri2_surf = malloc(sizeof *dri2_surf); + if (!dri2_surf) { + _eglError(EGL_BAD_ALLOC, "dri2_create_surface"); + return NULL; + } + + if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list)) + goto cleanup_surf; + + for (i = 0; i < WL_BUFFER_COUNT; ++i) + dri2_surf->wl_drm_buffer[i] = NULL; + + for (i = 0; i < __DRI_BUFFER_COUNT; ++i) + dri2_surf->dri_buffers[i] = NULL; + + dri2_surf->pending_buffer = NULL; + dri2_surf->block_swap_buffers = EGL_FALSE; + + switch (type) { + case EGL_WINDOW_BIT: + dri2_surf->wl_win = (struct wl_egl_window *) window; + dri2_surf->type = DRI2_WINDOW_SURFACE; + + dri2_surf->base.Width = -1; + dri2_surf->base.Height = -1; + break; + case EGL_PIXMAP_BIT: + dri2_surf->wl_pix = (struct wl_egl_pixmap *) window; + dri2_surf->type = DRI2_PIXMAP_SURFACE; + + dri2_surf->base.Width = dri2_surf->wl_pix->width; + dri2_surf->base.Height = dri2_surf->wl_pix->height; + + if (dri2_surf->wl_pix->name > 0) { + dri2_buf = dri2_surf->wl_pix->driver_private; + dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT] = dri2_buf->dri_buffer; + } + break; + default: + goto cleanup_surf; + } + + dri2_surf->dri_drawable = + (*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen, + type == EGL_WINDOW_BIT ? + dri2_conf->dri_double_config : + dri2_conf->dri_single_config, + dri2_surf); + if (dri2_surf->dri_drawable == NULL) { + _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable"); + goto cleanup_dri_drawable; + } + + return &dri2_surf->base; + + cleanup_dri_drawable: + dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable); + cleanup_surf: + free(dri2_surf); + + return NULL; +} + +/** + * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface(). + */ +static _EGLSurface * +dri2_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp, + _EGLConfig *conf, EGLNativeWindowType window, + const EGLint *attrib_list) +{ + return dri2_create_surface(drv, disp, EGL_WINDOW_BIT, conf, + window, attrib_list); +} + +static _EGLSurface * +dri2_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp, + _EGLConfig *conf, EGLNativePixmapType pixmap, + const EGLint *attrib_list) +{ + return dri2_create_surface(drv, disp, EGL_PIXMAP_BIT, conf, + pixmap, attrib_list); +} + +/** + * Called via eglDestroySurface(), drv->API.DestroySurface(). + */ +static EGLBoolean +dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf) +{ + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); + int i; + + (void) drv; + + if (!_eglPutSurface(surf)) + return EGL_TRUE; + + (*dri2_dpy->core->destroyDrawable)(dri2_surf->dri_drawable); + + for (i = 0; i < WL_BUFFER_COUNT; ++i) + if (dri2_surf->wl_drm_buffer[i]) + wl_buffer_destroy(dri2_surf->wl_drm_buffer[i]); + + for (i = 0; i < __DRI_BUFFER_COUNT; ++i) + if (dri2_surf->dri_buffers[i] && !(i == __DRI_BUFFER_FRONT_LEFT && + dri2_surf->type == DRI2_PIXMAP_SURFACE)) + dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen, + dri2_surf->dri_buffers[i]); + + free(surf); + + return EGL_TRUE; +} + +static void +dri2_wl_egl_pixmap_destroy(struct wl_egl_pixmap *egl_pixmap) +{ + struct dri2_egl_buffer *dri2_buf = egl_pixmap->driver_private; + + assert(dri2_buf); + + dri2_buf->dri2_dpy->dri2->releaseBuffer(dri2_buf->dri2_dpy->dri_screen, + dri2_buf->dri_buffer); + + free(dri2_buf); + + egl_pixmap->driver_private = NULL; + egl_pixmap->destroy = NULL; + egl_pixmap->name = 0; +} + +static void +dri2_process_back_buffer(struct dri2_egl_surface *dri2_surf, unsigned format) +{ + struct dri2_egl_display *dri2_dpy = + dri2_egl_display(dri2_surf->base.Resource.Display); + + (void) format; + + switch (dri2_surf->type) { + case DRI2_WINDOW_SURFACE: + /* allocate a front buffer for our double-buffered window*/ + dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT] = + dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen, + __DRI_BUFFER_FRONT_LEFT, format, + dri2_surf->base.Width, dri2_surf->base.Height); + break; + default: + break; + } +} + +static void +dri2_process_front_buffer(struct dri2_egl_surface *dri2_surf, unsigned format) +{ + struct dri2_egl_display *dri2_dpy = + dri2_egl_display(dri2_surf->base.Resource.Display); + struct dri2_egl_buffer *dri2_buf; + + switch (dri2_surf->type) { + case DRI2_PIXMAP_SURFACE: + dri2_buf = malloc(sizeof *dri2_buf); + if (!dri2_buf) + return; + + dri2_buf->dri_buffer = dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT]; + dri2_buf->dri2_dpy = dri2_dpy; + + dri2_surf->wl_pix->name = dri2_buf->dri_buffer->name; + dri2_surf->wl_pix->stride = dri2_buf->dri_buffer->pitch; + dri2_surf->wl_pix->driver_private = dri2_buf; + dri2_surf->wl_pix->destroy = dri2_wl_egl_pixmap_destroy; + break; + default: + break; + } +} + +static void +dri2_release_pending_buffer(void *data) +{ + struct dri2_egl_surface *dri2_surf = data; + struct dri2_egl_display *dri2_dpy = + dri2_egl_display(dri2_surf->base.Resource.Display); + + /* FIXME: print internal error */ + if (!dri2_surf->pending_buffer) + return; + + dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen, + dri2_surf->pending_buffer); + dri2_surf->pending_buffer = NULL; +} + +static void +dri2_release_buffers(struct dri2_egl_surface *dri2_surf) +{ + struct dri2_egl_display *dri2_dpy = + dri2_egl_display(dri2_surf->base.Resource.Display); + int i; + + for (i = 0; i < __DRI_BUFFER_COUNT; ++i) { + if (dri2_surf->dri_buffers[i]) { + switch (i) { + case __DRI_BUFFER_FRONT_LEFT: + if (dri2_surf->pending_buffer) + force_roundtrip(dri2_dpy->wl_dpy->display); + dri2_surf->pending_buffer = dri2_surf->dri_buffers[i]; + wl_display_sync_callback(dri2_dpy->wl_dpy->display, + dri2_release_pending_buffer, dri2_surf); + break; + default: + dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen, + dri2_surf->dri_buffers[i]); + break; + } + dri2_surf->dri_buffers[i] = NULL; + } + } +} + +static __DRIbuffer * +dri2_get_buffers_with_format(__DRIdrawable * driDrawable, + int *width, int *height, + unsigned int *attachments, int count, + int *out_count, void *loaderPrivate) +{ + struct dri2_egl_surface *dri2_surf = loaderPrivate; + struct dri2_egl_display *dri2_dpy = + dri2_egl_display(dri2_surf->base.Resource.Display); + int i; + + if (dri2_surf->type == DRI2_WINDOW_SURFACE && + (dri2_surf->base.Width != dri2_surf->wl_win->width || + dri2_surf->base.Height != dri2_surf->wl_win->height)) { + + dri2_release_buffers(dri2_surf); + + dri2_surf->base.Width = dri2_surf->wl_win->width; + dri2_surf->base.Height = dri2_surf->wl_win->height; + dri2_surf->dx = dri2_surf->wl_win->dx; + dri2_surf->dy = dri2_surf->wl_win->dy; + + for (i = 0; i < WL_BUFFER_COUNT; ++i) { + if (dri2_surf->wl_drm_buffer[i]) + wl_buffer_destroy(dri2_surf->wl_drm_buffer[i]); + dri2_surf->wl_drm_buffer[i] = NULL; + } + } + + dri2_surf->buffer_count = 0; + for (i = 0; i < 2*count; i+=2) { + assert(attachments[i] < __DRI_BUFFER_COUNT); + assert(dri2_surf->buffer_count < 5); + + if (dri2_surf->dri_buffers[attachments[i]] == NULL) { + + dri2_surf->dri_buffers[attachments[i]] = + dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen, + attachments[i], attachments[i+1], + dri2_surf->base.Width, dri2_surf->base.Height); + + if (!dri2_surf->dri_buffers[attachments[i]]) + continue; + + if (attachments[i] == __DRI_BUFFER_FRONT_LEFT) + dri2_process_front_buffer(dri2_surf, attachments[i+1]); + else if (attachments[i] == __DRI_BUFFER_BACK_LEFT) + dri2_process_back_buffer(dri2_surf, attachments[i+1]); + } + + memcpy(&dri2_surf->buffers[dri2_surf->buffer_count], + dri2_surf->dri_buffers[attachments[i]], + sizeof(__DRIbuffer)); + + dri2_surf->buffer_count++; + } + + assert(dri2_surf->type == DRI2_PIXMAP_SURFACE || + dri2_surf->dri_buffers[__DRI_BUFFER_BACK_LEFT]); + + *out_count = dri2_surf->buffer_count; + if (dri2_surf->buffer_count == 0) + return NULL; + + *width = dri2_surf->base.Width; + *height = dri2_surf->base.Height; + + return dri2_surf->buffers; +} + +static __DRIbuffer * +dri2_get_buffers(__DRIdrawable * driDrawable, + int *width, int *height, + unsigned int *attachments, int count, + int *out_count, void *loaderPrivate) +{ + unsigned int *attachments_with_format; + __DRIbuffer *buffer; + const unsigned int format = 32; + int i; + + attachments_with_format = calloc(count * 2, sizeof(unsigned int)); + if (!attachments_with_format) { + *out_count = 0; + return NULL; + } + + for (i = 0; i < count; ++i) { + attachments_with_format[2*i] = attachments[i]; + attachments_with_format[2*i + 1] = format; + } + + buffer = + dri2_get_buffers_with_format(driDrawable, + width, height, + attachments_with_format, count, + out_count, loaderPrivate); + + free(attachments_with_format); + + return buffer; +} + + +static void +dri2_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate) +{ + (void) driDrawable; + + /* FIXME: Does EGL support front buffer rendering at all? */ + +#if 0 + struct dri2_egl_surface *dri2_surf = loaderPrivate; + + dri2WaitGL(dri2_surf); +#else + (void) loaderPrivate; +#endif +} + +static struct wl_buffer * +wayland_create_buffer(struct dri2_egl_surface *dri2_surf, __DRIbuffer *buffer) +{ + struct dri2_egl_display *dri2_dpy = + dri2_egl_display(dri2_surf->base.Resource.Display); + + return wl_drm_create_buffer(dri2_dpy->wl_dpy->drm, buffer->name, + dri2_surf->base.Width, dri2_surf->base.Height, + buffer->pitch, dri2_surf->wl_win->visual); +} + +static void +wayland_frame_callback(void *data, uint32_t time) +{ + struct dri2_egl_surface *dri2_surf = data; + + dri2_surf->block_swap_buffers = EGL_FALSE; +} + +static inline void +pointer_swap(const void **p1, const void **p2) +{ + const void *tmp = *p1; + *p1 = *p2; + *p2 = tmp; +} + +/** + * Called via eglSwapBuffers(), drv->API.SwapBuffers(). + */ +static EGLBoolean +dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw) +{ + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); + struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); + + while (dri2_surf->block_swap_buffers) + wl_display_iterate(dri2_dpy->wl_dpy->display, WL_DISPLAY_READABLE); + + dri2_surf->block_swap_buffers = EGL_TRUE; + wl_display_frame_callback(dri2_dpy->wl_dpy->display, + wayland_frame_callback, dri2_surf); + + if (dri2_surf->type == DRI2_WINDOW_SURFACE) { + pointer_swap( + (const void **) &dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT], + (const void **) &dri2_surf->dri_buffers[__DRI_BUFFER_BACK_LEFT]); + + dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT]->attachment = + __DRI_BUFFER_FRONT_LEFT; + dri2_surf->dri_buffers[__DRI_BUFFER_BACK_LEFT]->attachment = + __DRI_BUFFER_BACK_LEFT; + + pointer_swap((const void **) &dri2_surf->wl_drm_buffer[WL_BUFFER_FRONT], + (const void **) &dri2_surf->wl_drm_buffer[WL_BUFFER_BACK]); + + if (!dri2_surf->wl_drm_buffer[WL_BUFFER_FRONT]) + dri2_surf->wl_drm_buffer[WL_BUFFER_FRONT] = + wayland_create_buffer(dri2_surf, + dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT]); + + wl_surface_attach(dri2_surf->wl_win->surface, + dri2_surf->wl_drm_buffer[WL_BUFFER_FRONT], + dri2_surf->dx, dri2_surf->dy); + + dri2_surf->wl_win->attached_width = dri2_surf->base.Width; + dri2_surf->wl_win->attached_height = dri2_surf->base.Height; + /* reset resize growing parameters */ + dri2_surf->dx = 0; + dri2_surf->dy = 0; + + wl_surface_damage(dri2_surf->wl_win->surface, 0, 0, + dri2_surf->base.Width, dri2_surf->base.Height); + } + + _EGLContext *ctx; + if (dri2_drv->glFlush) { + ctx = _eglGetCurrentContext(); + if (ctx && ctx->DrawSurface == &dri2_surf->base) + dri2_drv->glFlush(); + } + + (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable); + (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable); + + return EGL_TRUE; +} + +/** + * Called via eglCreateImageKHR(), drv->API.CreateImageKHR(). + */ +static _EGLImage * +dri2_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx, + EGLClientBuffer buffer, const EGLint *attr_list) +{ + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + struct wl_egl_pixmap *wl_egl_pixmap = (struct wl_egl_pixmap *) buffer; + struct dri2_egl_buffer *dri2_buf; + EGLint wl_attr_list[] = { + EGL_WIDTH, 0, + EGL_HEIGHT, 0, + EGL_DRM_BUFFER_STRIDE_MESA, 0, + EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, + EGL_NONE + }; + + dri2_buf = malloc(sizeof *dri2_buf); + if (!dri2_buf) + return NULL; + + dri2_buf->dri2_dpy = dri2_dpy; + dri2_buf->dri_buffer = + dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen, + __DRI_BUFFER_FRONT_LEFT, 32, + wl_egl_pixmap->width, + wl_egl_pixmap->height); + + wl_egl_pixmap->name = dri2_buf->dri_buffer->name; + wl_egl_pixmap->stride = dri2_buf->dri_buffer->pitch; + wl_egl_pixmap->destroy = dri2_wl_egl_pixmap_destroy; + wl_egl_pixmap->driver_private = dri2_buf; + + wl_attr_list[1] = wl_egl_pixmap->width; + wl_attr_list[3] = wl_egl_pixmap->height; + wl_attr_list[5] = wl_egl_pixmap->stride / 4; + + + return dri2_create_image_khr(disp->Driver, disp, ctx, EGL_DRM_BUFFER_MESA, + (EGLClientBuffer)(intptr_t) wl_egl_pixmap->name, wl_attr_list); +} + +static _EGLImage * +dri2_wayland_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp, + _EGLContext *ctx, EGLenum target, + EGLClientBuffer buffer, const EGLint *attr_list) +{ + (void) drv; + + switch (target) { + case EGL_NATIVE_PIXMAP_KHR: + return dri2_create_image_khr_pixmap(disp, ctx, buffer, attr_list); + default: + return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list); + } +} + +/** + * Called via eglTerminate(), drv->API.Terminate(). + */ +static EGLBoolean +dri2_terminate(_EGLDriver *drv, _EGLDisplay *disp) +{ + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + + _eglReleaseDisplayResources(drv, disp); + _eglCleanupDisplay(disp); + + dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen); + close(dri2_dpy->fd); + dlclose(dri2_dpy->driver); + free(dri2_dpy->driver_name); + free(dri2_dpy); + disp->DriverData = NULL; + + return EGL_TRUE; +} + +EGLBoolean +dri2_initialize_wayland(_EGLDriver *drv, _EGLDisplay *disp) +{ + struct dri2_egl_display *dri2_dpy; + int i; + + drv->API.CreateWindowSurface = dri2_create_window_surface; + drv->API.CreatePixmapSurface = dri2_create_pixmap_surface; + drv->API.DestroySurface = dri2_destroy_surface; + drv->API.SwapBuffers = dri2_swap_buffers; + drv->API.CreateImageKHR = dri2_wayland_create_image_khr; + drv->API.Terminate = dri2_terminate; + + dri2_dpy = malloc(sizeof *dri2_dpy); + if (!dri2_dpy) + return _eglError(EGL_BAD_ALLOC, "eglInitialize"); + + memset(dri2_dpy, 0, sizeof *dri2_dpy); + + disp->DriverData = (void *) dri2_dpy; + dri2_dpy->wl_dpy = disp->PlatformDisplay; + + if (dri2_dpy->wl_dpy->fd == -1) + force_roundtrip(dri2_dpy->wl_dpy->display); + if (dri2_dpy->wl_dpy->fd == -1) + goto cleanup_dpy; + + dri2_dpy->fd = dup(dri2_dpy->wl_dpy->fd); + if (dri2_dpy->fd < 0) { + _eglError(EGL_BAD_ALLOC, "DRI2: failed to dup fd"); + goto cleanup_dpy; + } + + if (!dri2_dpy->wl_dpy->authenticated) + force_roundtrip(dri2_dpy->wl_dpy->display); + if (!dri2_dpy->wl_dpy->authenticated) + goto cleanup_dpy; + + dri2_dpy->driver_name = dri2_get_driver_for_fd(dri2_dpy->fd); + if (dri2_dpy->driver_name == NULL) { + _eglError(EGL_BAD_ALLOC, "DRI2: failed to get driver name"); + goto cleanup_fd; + } + + if (!dri2_load_driver(disp)) + goto cleanup_driver_name; + + dri2_dpy->dri2_loader_extension.base.name = __DRI_DRI2_LOADER; + dri2_dpy->dri2_loader_extension.base.version = 3; + dri2_dpy->dri2_loader_extension.getBuffers = dri2_get_buffers; + dri2_dpy->dri2_loader_extension.flushFrontBuffer = dri2_flush_front_buffer; + dri2_dpy->dri2_loader_extension.getBuffersWithFormat = + dri2_get_buffers_with_format; + + dri2_dpy->extensions[0] = &dri2_dpy->dri2_loader_extension.base; + dri2_dpy->extensions[1] = &image_lookup_extension.base; + dri2_dpy->extensions[2] = NULL; + + if (!dri2_create_screen(disp)) + goto cleanup_driver; + + for (i = 0; dri2_dpy->driver_configs[i]; i++) + dri2_add_config(disp, dri2_dpy->driver_configs[i], i + 1, 0, + EGL_WINDOW_BIT | EGL_PIXMAP_BIT, NULL); + + + disp->Extensions.MESA_drm_image = EGL_TRUE; + disp->Extensions.KHR_image_base = EGL_TRUE; + disp->Extensions.KHR_image_pixmap = EGL_TRUE; + disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE; + disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE; + + /* we're supporting EGL 1.4 */ + disp->VersionMajor = 1; + disp->VersionMinor = 4; + + return EGL_TRUE; + + cleanup_driver: + dlclose(dri2_dpy->driver); + cleanup_driver_name: + free(dri2_dpy->driver_name); + cleanup_fd: + close(dri2_dpy->fd); + cleanup_dpy: + free(dri2_dpy); + + return EGL_FALSE; +} diff --git a/src/egl/drivers/dri2/platform_x11.c b/src/egl/drivers/dri2/platform_x11.c new file mode 100644 index 00000000000..50310eec5a9 --- /dev/null +++ b/src/egl/drivers/dri2/platform_x11.c @@ -0,0 +1,1058 @@ +/* + * Copyright © 2011 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Kristian Høgsberg <[email protected]> + */ + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <limits.h> +#include <dlfcn.h> +#include <fcntl.h> +#include <errno.h> +#include <unistd.h> +#include <xf86drm.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include "egl_dri2.h" + +static void +swrastCreateDrawable(struct dri2_egl_display * dri2_dpy, + struct dri2_egl_surface * dri2_surf, + int depth) +{ + uint32_t mask; + const uint32_t function = GXcopy; + uint32_t valgc[2]; + + /* create GC's */ + dri2_surf->gc = xcb_generate_id(dri2_dpy->conn); + mask = XCB_GC_FUNCTION; + xcb_create_gc(dri2_dpy->conn, dri2_surf->gc, dri2_surf->drawable, mask, &function); + + dri2_surf->swapgc = xcb_generate_id(dri2_dpy->conn); + mask = XCB_GC_FUNCTION | XCB_GC_GRAPHICS_EXPOSURES; + valgc[0] = function; + valgc[1] = False; + xcb_create_gc(dri2_dpy->conn, dri2_surf->swapgc, dri2_surf->drawable, mask, valgc); + dri2_surf->depth = depth; + switch (depth) { + case 32: + case 24: + dri2_surf->bytes_per_pixel = 4; + break; + case 16: + dri2_surf->bytes_per_pixel = 2; + break; + case 8: + dri2_surf->bytes_per_pixel = 1; + break; + case 0: + dri2_surf->bytes_per_pixel = 0; + break; + default: + _eglLog(_EGL_WARNING, "unsupported depth %d", depth); + } +} + +static void +swrastDestroyDrawable(struct dri2_egl_display * dri2_dpy, + struct dri2_egl_surface * dri2_surf) +{ + xcb_free_gc(dri2_dpy->conn, dri2_surf->gc); + xcb_free_gc(dri2_dpy->conn, dri2_surf->swapgc); +} + +static void +swrastGetDrawableInfo(__DRIdrawable * draw, + int *x, int *y, int *w, int *h, + void *loaderPrivate) +{ + struct dri2_egl_surface *dri2_surf = loaderPrivate; + struct dri2_egl_display *dri2_dpy = dri2_egl_display(dri2_surf->base.Resource.Display); + + xcb_get_geometry_cookie_t cookie; + xcb_get_geometry_reply_t *reply; + xcb_generic_error_t *error; + + *w = *h = 0; + cookie = xcb_get_geometry (dri2_dpy->conn, dri2_surf->drawable); + reply = xcb_get_geometry_reply (dri2_dpy->conn, cookie, &error); + if (reply == NULL) + return; + + if (error != NULL) { + _eglLog(_EGL_WARNING, "error in xcb_get_geometry"); + free(error); + } else { + *w = reply->width; + *h = reply->height; + } + free(reply); +} + +static void +swrastPutImage(__DRIdrawable * draw, int op, + int x, int y, int w, int h, + char *data, void *loaderPrivate) +{ + struct dri2_egl_surface *dri2_surf = loaderPrivate; + struct dri2_egl_display *dri2_dpy = dri2_egl_display(dri2_surf->base.Resource.Display); + + xcb_gcontext_t gc; + + switch (op) { + case __DRI_SWRAST_IMAGE_OP_DRAW: + gc = dri2_surf->gc; + break; + case __DRI_SWRAST_IMAGE_OP_SWAP: + gc = dri2_surf->swapgc; + break; + default: + return; + } + + xcb_put_image(dri2_dpy->conn, XCB_IMAGE_FORMAT_Z_PIXMAP, dri2_surf->drawable, + gc, w, h, x, y, 0, dri2_surf->depth, + w*h*dri2_surf->bytes_per_pixel, (const uint8_t *)data); +} + +static void +swrastGetImage(__DRIdrawable * read, + int x, int y, int w, int h, + char *data, void *loaderPrivate) +{ + struct dri2_egl_surface *dri2_surf = loaderPrivate; + struct dri2_egl_display *dri2_dpy = dri2_egl_display(dri2_surf->base.Resource.Display); + + xcb_get_image_cookie_t cookie; + xcb_get_image_reply_t *reply; + xcb_generic_error_t *error; + + cookie = xcb_get_image (dri2_dpy->conn, XCB_IMAGE_FORMAT_Z_PIXMAP, + dri2_surf->drawable, x, y, w, h, ~0); + reply = xcb_get_image_reply (dri2_dpy->conn, cookie, &error); + if (reply == NULL) + return; + + if (error != NULL) { + _eglLog(_EGL_WARNING, "error in xcb_get_image"); + free(error); + } else { + uint32_t bytes = xcb_get_image_data_length(reply); + uint8_t *idata = xcb_get_image_data(reply); + memcpy(data, idata, bytes); + } + free(reply); +} + + +/** + * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface(). + */ +static _EGLSurface * +dri2_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type, + _EGLConfig *conf, EGLNativeWindowType window, + const EGLint *attrib_list) +{ + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + struct dri2_egl_config *dri2_conf = dri2_egl_config(conf); + struct dri2_egl_surface *dri2_surf; + xcb_get_geometry_cookie_t cookie; + xcb_get_geometry_reply_t *reply; + xcb_screen_iterator_t s; + xcb_generic_error_t *error; + + (void) drv; + + dri2_surf = malloc(sizeof *dri2_surf); + if (!dri2_surf) { + _eglError(EGL_BAD_ALLOC, "dri2_create_surface"); + return NULL; + } + + if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list)) + goto cleanup_surf; + + dri2_surf->region = XCB_NONE; + if (type == EGL_PBUFFER_BIT) { + dri2_surf->drawable = xcb_generate_id(dri2_dpy->conn); + s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn)); + xcb_create_pixmap(dri2_dpy->conn, conf->BufferSize, + dri2_surf->drawable, s.data->root, + dri2_surf->base.Width, dri2_surf->base.Height); + } else { + dri2_surf->drawable = window; + } + + if (dri2_dpy->dri2) { + dri2_surf->dri_drawable = + (*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen, + type == EGL_WINDOW_BIT ? + dri2_conf->dri_double_config : + dri2_conf->dri_single_config, + dri2_surf); + } else { + assert(dri2_dpy->swrast); + dri2_surf->dri_drawable = + (*dri2_dpy->swrast->createNewDrawable) (dri2_dpy->dri_screen, + dri2_conf->dri_double_config, + dri2_surf); + } + + if (dri2_surf->dri_drawable == NULL) { + _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable"); + goto cleanup_pixmap; + } + + if (dri2_dpy->dri2) { + xcb_dri2_create_drawable (dri2_dpy->conn, dri2_surf->drawable); + } else { + swrastCreateDrawable(dri2_dpy, dri2_surf, _eglGetConfigKey(conf, EGL_DEPTH_SIZE)); + } + + if (type != EGL_PBUFFER_BIT) { + cookie = xcb_get_geometry (dri2_dpy->conn, dri2_surf->drawable); + reply = xcb_get_geometry_reply (dri2_dpy->conn, cookie, &error); + if (reply == NULL || error != NULL) { + _eglError(EGL_BAD_ALLOC, "xcb_get_geometry"); + free(error); + goto cleanup_dri_drawable; + } + + dri2_surf->base.Width = reply->width; + dri2_surf->base.Height = reply->height; + free(reply); + } + + return &dri2_surf->base; + + cleanup_dri_drawable: + dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable); + cleanup_pixmap: + if (type == EGL_PBUFFER_BIT) + xcb_free_pixmap(dri2_dpy->conn, dri2_surf->drawable); + cleanup_surf: + free(dri2_surf); + + return NULL; +} + +/** + * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface(). + */ +static _EGLSurface * +dri2_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp, + _EGLConfig *conf, EGLNativeWindowType window, + const EGLint *attrib_list) +{ + return dri2_create_surface(drv, disp, EGL_WINDOW_BIT, conf, + window, attrib_list); +} + +static _EGLSurface * +dri2_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp, + _EGLConfig *conf, EGLNativePixmapType pixmap, + const EGLint *attrib_list) +{ + return dri2_create_surface(drv, disp, EGL_PIXMAP_BIT, conf, + pixmap, attrib_list); +} + +static _EGLSurface * +dri2_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp, + _EGLConfig *conf, const EGLint *attrib_list) +{ + return dri2_create_surface(drv, disp, EGL_PBUFFER_BIT, conf, + XCB_WINDOW_NONE, attrib_list); +} + +static EGLBoolean +dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf) +{ + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); + + (void) drv; + + if (!_eglPutSurface(surf)) + return EGL_TRUE; + + (*dri2_dpy->core->destroyDrawable)(dri2_surf->dri_drawable); + + if (dri2_dpy->dri2) { + xcb_dri2_destroy_drawable (dri2_dpy->conn, dri2_surf->drawable); + } else { + assert(dri2_dpy->swrast); + swrastDestroyDrawable(dri2_dpy, dri2_surf); + } + + if (surf->Type == EGL_PBUFFER_BIT) + xcb_free_pixmap (dri2_dpy->conn, dri2_surf->drawable); + + free(surf); + + return EGL_TRUE; +} + +/** + * Process list of buffer received from the server + * + * Processes the list of buffers received in a reply from the server to either + * \c DRI2GetBuffers or \c DRI2GetBuffersWithFormat. + */ +static void +dri2_process_buffers(struct dri2_egl_surface *dri2_surf, + xcb_dri2_dri2_buffer_t *buffers, unsigned count) +{ + struct dri2_egl_display *dri2_dpy = + dri2_egl_display(dri2_surf->base.Resource.Display); + xcb_rectangle_t rectangle; + unsigned i; + + dri2_surf->buffer_count = count; + dri2_surf->have_fake_front = 0; + + /* This assumes the DRI2 buffer attachment tokens matches the + * __DRIbuffer tokens. */ + for (i = 0; i < count; i++) { + dri2_surf->buffers[i].attachment = buffers[i].attachment; + dri2_surf->buffers[i].name = buffers[i].name; + dri2_surf->buffers[i].pitch = buffers[i].pitch; + dri2_surf->buffers[i].cpp = buffers[i].cpp; + dri2_surf->buffers[i].flags = buffers[i].flags; + + /* We only use the DRI drivers single buffer configs. This + * means that if we try to render to a window, DRI2 will give us + * the fake front buffer, which we'll use as a back buffer. + * Note that EGL doesn't require that several clients rendering + * to the same window must see the same aux buffers. */ + if (dri2_surf->buffers[i].attachment == __DRI_BUFFER_FAKE_FRONT_LEFT) + dri2_surf->have_fake_front = 1; + } + + if (dri2_surf->region != XCB_NONE) + xcb_xfixes_destroy_region(dri2_dpy->conn, dri2_surf->region); + + rectangle.x = 0; + rectangle.y = 0; + rectangle.width = dri2_surf->base.Width; + rectangle.height = dri2_surf->base.Height; + dri2_surf->region = xcb_generate_id(dri2_dpy->conn); + xcb_xfixes_create_region(dri2_dpy->conn, dri2_surf->region, 1, &rectangle); +} + +static __DRIbuffer * +dri2_get_buffers(__DRIdrawable * driDrawable, + int *width, int *height, + unsigned int *attachments, int count, + int *out_count, void *loaderPrivate) +{ + struct dri2_egl_surface *dri2_surf = loaderPrivate; + struct dri2_egl_display *dri2_dpy = + dri2_egl_display(dri2_surf->base.Resource.Display); + xcb_dri2_dri2_buffer_t *buffers; + xcb_dri2_get_buffers_reply_t *reply; + xcb_dri2_get_buffers_cookie_t cookie; + + (void) driDrawable; + + cookie = xcb_dri2_get_buffers_unchecked (dri2_dpy->conn, + dri2_surf->drawable, + count, count, attachments); + reply = xcb_dri2_get_buffers_reply (dri2_dpy->conn, cookie, NULL); + buffers = xcb_dri2_get_buffers_buffers (reply); + if (buffers == NULL) + return NULL; + + *out_count = reply->count; + dri2_surf->base.Width = *width = reply->width; + dri2_surf->base.Height = *height = reply->height; + dri2_process_buffers(dri2_surf, buffers, *out_count); + + free(reply); + + return dri2_surf->buffers; +} + +static __DRIbuffer * +dri2_get_buffers_with_format(__DRIdrawable * driDrawable, + int *width, int *height, + unsigned int *attachments, int count, + int *out_count, void *loaderPrivate) +{ + struct dri2_egl_surface *dri2_surf = loaderPrivate; + struct dri2_egl_display *dri2_dpy = + dri2_egl_display(dri2_surf->base.Resource.Display); + xcb_dri2_dri2_buffer_t *buffers; + xcb_dri2_get_buffers_with_format_reply_t *reply; + xcb_dri2_get_buffers_with_format_cookie_t cookie; + xcb_dri2_attach_format_t *format_attachments; + + (void) driDrawable; + + format_attachments = (xcb_dri2_attach_format_t *) attachments; + cookie = xcb_dri2_get_buffers_with_format_unchecked (dri2_dpy->conn, + dri2_surf->drawable, + count, count, + format_attachments); + + reply = xcb_dri2_get_buffers_with_format_reply (dri2_dpy->conn, + cookie, NULL); + if (reply == NULL) + return NULL; + + buffers = xcb_dri2_get_buffers_with_format_buffers (reply); + dri2_surf->base.Width = *width = reply->width; + dri2_surf->base.Height = *height = reply->height; + *out_count = reply->count; + dri2_process_buffers(dri2_surf, buffers, *out_count); + + free(reply); + + return dri2_surf->buffers; +} + +static void +dri2_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate) +{ + (void) driDrawable; + + /* FIXME: Does EGL support front buffer rendering at all? */ + +#if 0 + struct dri2_egl_surface *dri2_surf = loaderPrivate; + + dri2WaitGL(dri2_surf); +#else + (void) loaderPrivate; +#endif +} + +static char * +dri2_strndup(const char *s, int length) +{ + char *d; + + d = malloc(length + 1); + if (d == NULL) + return NULL; + + memcpy(d, s, length); + d[length] = '\0'; + + return d; +} + +static EGLBoolean +dri2_connect(struct dri2_egl_display *dri2_dpy) +{ + xcb_xfixes_query_version_reply_t *xfixes_query; + xcb_xfixes_query_version_cookie_t xfixes_query_cookie; + xcb_dri2_query_version_reply_t *dri2_query; + xcb_dri2_query_version_cookie_t dri2_query_cookie; + xcb_dri2_connect_reply_t *connect; + xcb_dri2_connect_cookie_t connect_cookie; + xcb_generic_error_t *error; + xcb_screen_iterator_t s; + + xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_xfixes_id); + xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_dri2_id); + + xfixes_query_cookie = xcb_xfixes_query_version(dri2_dpy->conn, + XCB_XFIXES_MAJOR_VERSION, + XCB_XFIXES_MINOR_VERSION); + + dri2_query_cookie = xcb_dri2_query_version (dri2_dpy->conn, + XCB_DRI2_MAJOR_VERSION, + XCB_DRI2_MINOR_VERSION); + + s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn)); + connect_cookie = xcb_dri2_connect_unchecked (dri2_dpy->conn, + s.data->root, + XCB_DRI2_DRIVER_TYPE_DRI); + + xfixes_query = + xcb_xfixes_query_version_reply (dri2_dpy->conn, + xfixes_query_cookie, &error); + if (xfixes_query == NULL || + error != NULL || xfixes_query->major_version < 2) { + _eglLog(_EGL_WARNING, "DRI2: failed to query xfixes version"); + free(error); + return EGL_FALSE; + } + free(xfixes_query); + + dri2_query = + xcb_dri2_query_version_reply (dri2_dpy->conn, dri2_query_cookie, &error); + if (dri2_query == NULL || error != NULL) { + _eglLog(_EGL_WARNING, "DRI2: failed to query version"); + free(error); + return EGL_FALSE; + } + dri2_dpy->dri2_major = dri2_query->major_version; + dri2_dpy->dri2_minor = dri2_query->minor_version; + free(dri2_query); + + connect = xcb_dri2_connect_reply (dri2_dpy->conn, connect_cookie, NULL); + if (connect == NULL || + connect->driver_name_length + connect->device_name_length == 0) { + _eglLog(_EGL_WARNING, "DRI2: failed to authenticate"); + return EGL_FALSE; + } + + dri2_dpy->device_name = + dri2_strndup(xcb_dri2_connect_device_name (connect), + xcb_dri2_connect_device_name_length (connect)); + + dri2_dpy->driver_name = + dri2_strndup(xcb_dri2_connect_driver_name (connect), + xcb_dri2_connect_driver_name_length (connect)); + + if (dri2_dpy->device_name == NULL || dri2_dpy->driver_name == NULL) { + free(dri2_dpy->device_name); + free(dri2_dpy->driver_name); + free(connect); + return EGL_FALSE; + } + free(connect); + + return EGL_TRUE; +} + +static EGLBoolean +dri2_authenticate(struct dri2_egl_display *dri2_dpy) +{ + xcb_dri2_authenticate_reply_t *authenticate; + xcb_dri2_authenticate_cookie_t authenticate_cookie; + xcb_screen_iterator_t s; + drm_magic_t magic; + + if (drmGetMagic(dri2_dpy->fd, &magic)) { + _eglLog(_EGL_WARNING, "DRI2: failed to get drm magic"); + return EGL_FALSE; + } + + s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn)); + authenticate_cookie = + xcb_dri2_authenticate_unchecked(dri2_dpy->conn, s.data->root, magic); + authenticate = + xcb_dri2_authenticate_reply(dri2_dpy->conn, authenticate_cookie, NULL); + if (authenticate == NULL || !authenticate->authenticated) { + _eglLog(_EGL_WARNING, "DRI2: failed to authenticate"); + free(authenticate); + return EGL_FALSE; + } + + free(authenticate); + + return EGL_TRUE; +} + +static EGLBoolean +dri2_add_configs_for_visuals(struct dri2_egl_display *dri2_dpy, + _EGLDisplay *disp) +{ + xcb_screen_iterator_t s; + xcb_depth_iterator_t d; + xcb_visualtype_t *visuals; + int i, j, id; + EGLint surface_type; + EGLint config_attrs[] = { + EGL_NATIVE_VISUAL_ID, 0, + EGL_NATIVE_VISUAL_TYPE, 0, + EGL_NONE + }; + + s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn)); + d = xcb_screen_allowed_depths_iterator(s.data); + id = 1; + + surface_type = + EGL_WINDOW_BIT | + EGL_PIXMAP_BIT | + EGL_PBUFFER_BIT | + EGL_SWAP_BEHAVIOR_PRESERVED_BIT; + + while (d.rem > 0) { + EGLBoolean class_added[6] = { 0, }; + + visuals = xcb_depth_visuals(d.data); + for (i = 0; i < xcb_depth_visuals_length(d.data); i++) { + if (class_added[visuals[i]._class]) + continue; + + class_added[visuals[i]._class] = EGL_TRUE; + for (j = 0; dri2_dpy->driver_configs[j]; j++) { + config_attrs[1] = visuals[i].visual_id; + config_attrs[3] = visuals[i]._class; + + dri2_add_config(disp, dri2_dpy->driver_configs[j], id++, + d.data->depth, surface_type, config_attrs); + } + } + + xcb_depth_next(&d); + } + + if (!_eglGetArraySize(disp->Configs)) { + _eglLog(_EGL_WARNING, "DRI2: failed to create any config"); + return EGL_FALSE; + } + + return EGL_TRUE; +} + +static EGLBoolean +dri2_copy_region(_EGLDriver *drv, _EGLDisplay *disp, + _EGLSurface *draw, xcb_xfixes_region_t region) +{ + struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); + _EGLContext *ctx; + enum xcb_dri2_attachment_t render_attachment; + xcb_dri2_copy_region_cookie_t cookie; + + if (dri2_drv->glFlush) { + ctx = _eglGetCurrentContext(); + if (ctx && ctx->DrawSurface == &dri2_surf->base) + dri2_drv->glFlush(); + } + + (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable); + +#if 0 + /* FIXME: Add support for dri swapbuffers, that'll give us swap + * interval and page flipping (at least for fullscreen windows) as + * well as the page flip event. Unless surface->SwapBehavior is + * EGL_BUFFER_PRESERVED. */ +#if __DRI2_FLUSH_VERSION >= 2 + if (pdraw->psc->f) + (*pdraw->psc->f->flushInvalidate)(pdraw->driDrawable); +#endif +#endif + + if (dri2_surf->have_fake_front) + render_attachment = XCB_DRI2_ATTACHMENT_BUFFER_FAKE_FRONT_LEFT; + else + render_attachment = XCB_DRI2_ATTACHMENT_BUFFER_BACK_LEFT; + + cookie = xcb_dri2_copy_region_unchecked(dri2_dpy->conn, + dri2_surf->drawable, + region, + XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT, + render_attachment); + free(xcb_dri2_copy_region_reply(dri2_dpy->conn, cookie, NULL)); + + return EGL_TRUE; +} + +static EGLBoolean +dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw) +{ + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); + + if (dri2_dpy->dri2) { + return dri2_copy_region(drv, disp, draw, dri2_surf->region); + } else { + assert(dri2_dpy->swrast); + + dri2_dpy->core->swapBuffers(dri2_surf->dri_drawable); + return EGL_TRUE; + } +} + +static EGLBoolean +dri2_swap_buffers_region(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw, + EGLint numRects, const EGLint *rects) +{ + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); + EGLBoolean ret; + xcb_xfixes_region_t region; + xcb_rectangle_t rectangles[16]; + int i; + + if (numRects > (int)ARRAY_SIZE(rectangles)) + return dri2_copy_region(drv, disp, draw, dri2_surf->region); + + /* FIXME: Invert y here? */ + for (i = 0; i < numRects; i++) { + rectangles[i].x = rects[i * 4]; + rectangles[i].y = rects[i * 4 + 1]; + rectangles[i].width = rects[i * 4 + 2]; + rectangles[i].height = rects[i * 4 + 3]; + } + + region = xcb_generate_id(dri2_dpy->conn); + xcb_xfixes_create_region(dri2_dpy->conn, region, numRects, rectangles); + ret = dri2_copy_region(drv, disp, draw, region); + xcb_xfixes_destroy_region(dri2_dpy->conn, region); + + return ret; +} + +static EGLBoolean +dri2_copy_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, + EGLNativePixmapType target) +{ + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); + xcb_gcontext_t gc; + + (void) drv; + + (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable); + + gc = xcb_generate_id(dri2_dpy->conn); + xcb_create_gc(dri2_dpy->conn, gc, target, 0, NULL); + xcb_copy_area(dri2_dpy->conn, + dri2_surf->drawable, + target, + gc, + 0, 0, + 0, 0, + dri2_surf->base.Width, + dri2_surf->base.Height); + xcb_free_gc(dri2_dpy->conn, gc); + + return EGL_TRUE; +} + +static _EGLImage * +dri2_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx, + EGLClientBuffer buffer, const EGLint *attr_list) +{ + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + struct dri2_egl_image *dri2_img; + unsigned int attachments[1]; + xcb_drawable_t drawable; + xcb_dri2_get_buffers_cookie_t buffers_cookie; + xcb_dri2_get_buffers_reply_t *buffers_reply; + xcb_dri2_dri2_buffer_t *buffers; + xcb_get_geometry_cookie_t geometry_cookie; + xcb_get_geometry_reply_t *geometry_reply; + xcb_generic_error_t *error; + int stride, format; + + (void) ctx; + + drawable = (xcb_drawable_t) buffer; + xcb_dri2_create_drawable (dri2_dpy->conn, drawable); + attachments[0] = XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT; + buffers_cookie = + xcb_dri2_get_buffers_unchecked (dri2_dpy->conn, + drawable, 1, 1, attachments); + geometry_cookie = xcb_get_geometry (dri2_dpy->conn, drawable); + buffers_reply = xcb_dri2_get_buffers_reply (dri2_dpy->conn, + buffers_cookie, NULL); + buffers = xcb_dri2_get_buffers_buffers (buffers_reply); + if (buffers == NULL) { + return NULL; + } + + geometry_reply = xcb_get_geometry_reply (dri2_dpy->conn, + geometry_cookie, &error); + if (geometry_reply == NULL || error != NULL) { + _eglError(EGL_BAD_ALLOC, "xcb_get_geometry"); + free(error); + free(buffers_reply); + return NULL; + } + + switch (geometry_reply->depth) { + case 16: + format = __DRI_IMAGE_FORMAT_RGB565; + break; + case 24: + format = __DRI_IMAGE_FORMAT_XRGB8888; + break; + case 32: + format = __DRI_IMAGE_FORMAT_ARGB8888; + break; + default: + _eglError(EGL_BAD_PARAMETER, + "dri2_create_image_khr: unsupported pixmap depth"); + free(buffers_reply); + free(geometry_reply); + return NULL; + } + + dri2_img = malloc(sizeof *dri2_img); + if (!dri2_img) { + free(buffers_reply); + free(geometry_reply); + _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr"); + return EGL_NO_IMAGE_KHR; + } + + if (!_eglInitImage(&dri2_img->base, disp)) { + free(buffers_reply); + free(geometry_reply); + return EGL_NO_IMAGE_KHR; + } + + stride = buffers[0].pitch / buffers[0].cpp; + dri2_img->dri_image = + dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen, + buffers_reply->width, + buffers_reply->height, + format, + buffers[0].name, + stride, + dri2_img); + + free(buffers_reply); + free(geometry_reply); + + return &dri2_img->base; +} + +static _EGLImage * +dri2_x11_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp, + _EGLContext *ctx, EGLenum target, + EGLClientBuffer buffer, const EGLint *attr_list) +{ + (void) drv; + + switch (target) { + case EGL_NATIVE_PIXMAP_KHR: + return dri2_create_image_khr_pixmap(disp, ctx, buffer, attr_list); + default: + return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list); + } +} + +static EGLBoolean +dri2_initialize_x11_swrast(_EGLDriver *drv, _EGLDisplay *disp) +{ + struct dri2_egl_display *dri2_dpy; + + drv->API.CreateWindowSurface = dri2_create_window_surface; + drv->API.CreatePixmapSurface = dri2_create_pixmap_surface; + drv->API.CreatePbufferSurface = dri2_create_pbuffer_surface; + drv->API.DestroySurface = dri2_destroy_surface; + drv->API.SwapBuffers = dri2_swap_buffers; + drv->API.CopyBuffers = dri2_copy_buffers; + + drv->API.SwapBuffersRegionNOK = NULL; + drv->API.CreateImageKHR = NULL; + drv->API.DestroyImageKHR = NULL; + drv->API.CreateDRMImageMESA = NULL; + drv->API.ExportDRMImageMESA = NULL; + + dri2_dpy = malloc(sizeof *dri2_dpy); + if (!dri2_dpy) + return _eglError(EGL_BAD_ALLOC, "eglInitialize"); + + memset(dri2_dpy, 0, sizeof *dri2_dpy); + + disp->DriverData = (void *) dri2_dpy; + if (disp->PlatformDisplay == NULL) { + dri2_dpy->conn = xcb_connect(0, 0); + } else { + dri2_dpy->conn = XGetXCBConnection((Display *) disp->PlatformDisplay); + } + + if (xcb_connection_has_error(dri2_dpy->conn)) { + _eglLog(_EGL_WARNING, "DRI2: xcb_connect failed"); + goto cleanup_dpy; + } + + dri2_dpy->driver_name = dri2_strndup("swrast", strlen("swrast")); + + if (!dri2_load_driver(disp)) + goto cleanup_conn; + + dri2_dpy->swrast_loader_extension.base.name = __DRI_SWRAST_LOADER; + dri2_dpy->swrast_loader_extension.base.version = __DRI_SWRAST_LOADER_VERSION; + dri2_dpy->swrast_loader_extension.getDrawableInfo = swrastGetDrawableInfo; + dri2_dpy->swrast_loader_extension.putImage = swrastPutImage; + dri2_dpy->swrast_loader_extension.getImage = swrastGetImage; + + dri2_dpy->extensions[0] = &dri2_dpy->swrast_loader_extension.base; + dri2_dpy->extensions[1] = NULL; + dri2_dpy->extensions[2] = NULL; + + if (!dri2_create_screen(disp)) + goto cleanup_driver; + + if (dri2_dpy->conn) { + if (!dri2_add_configs_for_visuals(dri2_dpy, disp)) + goto cleanup_configs; + } + + /* we're supporting EGL 1.4 */ + disp->VersionMajor = 1; + disp->VersionMinor = 4; + + return EGL_TRUE; + + cleanup_configs: + _eglCleanupDisplay(disp); + dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen); + cleanup_driver: + dlclose(dri2_dpy->driver); + cleanup_conn: + if (disp->PlatformDisplay == NULL) + xcb_disconnect(dri2_dpy->conn); + cleanup_dpy: + free(dri2_dpy); + + return EGL_FALSE; +} + + +static EGLBoolean +dri2_initialize_x11_dri2(_EGLDriver *drv, _EGLDisplay *disp) +{ + struct dri2_egl_display *dri2_dpy; + + drv->API.CreateWindowSurface = dri2_create_window_surface; + drv->API.CreatePixmapSurface = dri2_create_pixmap_surface; + drv->API.CreatePbufferSurface = dri2_create_pbuffer_surface; + drv->API.DestroySurface = dri2_destroy_surface; + drv->API.SwapBuffers = dri2_swap_buffers; + drv->API.CopyBuffers = dri2_copy_buffers; + drv->API.CreateImageKHR = dri2_x11_create_image_khr; + drv->API.SwapBuffersRegionNOK = dri2_swap_buffers_region; + + dri2_dpy = malloc(sizeof *dri2_dpy); + if (!dri2_dpy) + return _eglError(EGL_BAD_ALLOC, "eglInitialize"); + + memset(dri2_dpy, 0, sizeof *dri2_dpy); + + disp->DriverData = (void *) dri2_dpy; + if (disp->PlatformDisplay == NULL) { + dri2_dpy->conn = xcb_connect(0, 0); + } else { + dri2_dpy->conn = XGetXCBConnection((Display *) disp->PlatformDisplay); + } + + if (xcb_connection_has_error(dri2_dpy->conn)) { + _eglLog(_EGL_WARNING, "DRI2: xcb_connect failed"); + goto cleanup_dpy; + } + + if (dri2_dpy->conn) { + if (!dri2_connect(dri2_dpy)) + goto cleanup_conn; + } + + if (!dri2_load_driver(disp)) + goto cleanup_conn; + + dri2_dpy->fd = open(dri2_dpy->device_name, O_RDWR); + if (dri2_dpy->fd == -1) { + _eglLog(_EGL_WARNING, + "DRI2: could not open %s (%s)", dri2_dpy->device_name, + strerror(errno)); + goto cleanup_driver; + } + + if (dri2_dpy->conn) { + if (!dri2_authenticate(dri2_dpy)) + goto cleanup_fd; + } + + if (dri2_dpy->dri2_minor >= 1) { + dri2_dpy->dri2_loader_extension.base.name = __DRI_DRI2_LOADER; + dri2_dpy->dri2_loader_extension.base.version = 3; + dri2_dpy->dri2_loader_extension.getBuffers = dri2_get_buffers; + dri2_dpy->dri2_loader_extension.flushFrontBuffer = dri2_flush_front_buffer; + dri2_dpy->dri2_loader_extension.getBuffersWithFormat = + dri2_get_buffers_with_format; + } else { + dri2_dpy->dri2_loader_extension.base.name = __DRI_DRI2_LOADER; + dri2_dpy->dri2_loader_extension.base.version = 2; + dri2_dpy->dri2_loader_extension.getBuffers = dri2_get_buffers; + dri2_dpy->dri2_loader_extension.flushFrontBuffer = dri2_flush_front_buffer; + dri2_dpy->dri2_loader_extension.getBuffersWithFormat = NULL; + } + + dri2_dpy->extensions[0] = &dri2_dpy->dri2_loader_extension.base; + dri2_dpy->extensions[1] = &image_lookup_extension.base; + dri2_dpy->extensions[2] = NULL; + + if (!dri2_create_screen(disp)) + goto cleanup_fd; + + if (dri2_dpy->conn) { + if (!dri2_add_configs_for_visuals(dri2_dpy, disp)) + goto cleanup_configs; + } + + disp->Extensions.MESA_drm_image = EGL_TRUE; + disp->Extensions.KHR_image_base = EGL_TRUE; + disp->Extensions.KHR_image_pixmap = EGL_TRUE; + disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE; + disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE; + disp->Extensions.NOK_swap_region = EGL_TRUE; + disp->Extensions.NOK_texture_from_pixmap = EGL_TRUE; + + /* we're supporting EGL 1.4 */ + disp->VersionMajor = 1; + disp->VersionMinor = 4; + + return EGL_TRUE; + + cleanup_configs: + _eglCleanupDisplay(disp); + dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen); + cleanup_fd: + close(dri2_dpy->fd); + cleanup_driver: + dlclose(dri2_dpy->driver); + cleanup_conn: + if (disp->PlatformDisplay == NULL) + xcb_disconnect(dri2_dpy->conn); + cleanup_dpy: + free(dri2_dpy); + + return EGL_FALSE; +} + +EGLBoolean +dri2_initialize_x11(_EGLDriver *drv, _EGLDisplay *disp) +{ + EGLBoolean initialized = EGL_TRUE; + + int x11_dri2_accel = (getenv("LIBGL_ALWAYS_SOFTWARE") == NULL); + + if (x11_dri2_accel) { + if (!dri2_initialize_x11_dri2(drv, disp)) { + initialized = dri2_initialize_x11_swrast(drv, disp); + } + } else { + initialized = dri2_initialize_x11_swrast(drv, disp); + } + + return initialized; +} + diff --git a/src/egl/main/Makefile b/src/egl/main/Makefile index c710631688c..a5b92995020 100644 --- a/src/egl/main/Makefile +++ b/src/egl/main/Makefile @@ -58,7 +58,7 @@ LOCAL_LIBS = ifeq ($(filter dri2, $(EGL_DRIVERS_DIRS)),dri2) LOCAL_CFLAGS += -D_EGL_BUILT_IN_DRIVER_DRI2 LOCAL_LIBS += $(TOP)/src/egl/drivers/dri2/libegl_dri2.a -EGL_LIB_DEPS += $(XCB_DRI2_LIBS) $(LIBUDEV_LIBS) $(DLOPEN_LIBS) $(LIBDRM_LIB) +EGL_LIB_DEPS += $(XCB_DRI2_LIBS) $(LIBUDEV_LIBS) $(DLOPEN_LIBS) $(LIBDRM_LIB) $(WAYLAND_LIBS) endif ifeq ($(filter glx, $(EGL_DRIVERS_DIRS)),glx) LOCAL_CFLAGS += -D_EGL_BUILT_IN_DRIVER_GLX @@ -71,6 +71,9 @@ EGL_NATIVE_PLATFORM=_EGL_INVALID_PLATFORM ifeq ($(firstword $(EGL_PLATFORMS)),x11) EGL_NATIVE_PLATFORM=_EGL_PLATFORM_X11 endif +ifeq ($(firstword $(EGL_PLATFORMS)),wayland) +EGL_NATIVE_PLATFORM=_EGL_PLATFORM_WAYLAND +endif ifeq ($(firstword $(EGL_PLATFORMS)),drm) EGL_NATIVE_PLATFORM=_EGL_PLATFORM_DRM endif diff --git a/src/egl/main/egldisplay.c b/src/egl/main/egldisplay.c index 565e44d2d23..30592947297 100644 --- a/src/egl/main/egldisplay.c +++ b/src/egl/main/egldisplay.c @@ -27,6 +27,7 @@ _eglGetNativePlatformFromEnv(void) } egl_platforms[_EGL_NUM_PLATFORMS] = { { _EGL_PLATFORM_WINDOWS, "gdi" }, { _EGL_PLATFORM_X11, "x11" }, + { _EGL_PLATFORM_WAYLAND, "wayland" }, { _EGL_PLATFORM_DRM, "drm" }, { _EGL_PLATFORM_FBDEV, "fbdev" } }; diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h index dbc5d32d910..ce035eb2ef1 100644 --- a/src/egl/main/egldisplay.h +++ b/src/egl/main/egldisplay.h @@ -11,6 +11,7 @@ enum _egl_platform_type { _EGL_PLATFORM_WINDOWS, _EGL_PLATFORM_X11, + _EGL_PLATFORM_WAYLAND, _EGL_PLATFORM_DRM, _EGL_PLATFORM_FBDEV, diff --git a/src/egl/main/egldriver.c b/src/egl/main/egldriver.c index e133c220f5c..b75e8b6a2cb 100644 --- a/src/egl/main/egldriver.c +++ b/src/egl/main/egldriver.c @@ -437,6 +437,7 @@ _eglAddUserDriver(void) { const char *search_path = _eglGetSearchPath(); char *env; + size_t name_len = 0; env = getenv("EGL_DRIVER"); #if defined(_EGL_OS_UNIX) @@ -448,21 +449,39 @@ _eglAddUserDriver(void) env = NULL; } } + else if (env) { + char *suffix = strchr(env, '.'); + name_len = (suffix) ? suffix - env : strlen(env); + } +#else + if (env) + name_len = strlen(env); #endif /* _EGL_OS_UNIX */ - if (env) { + + /* + * Try built-in drivers first if we know the driver name. This makes sure + * we do not load the outdated external driver that is still on the + * filesystem. + */ + if (name_len) { _EGLModule *mod; EGLint i; - /* env can be a path */ - _eglPreloadForEach(search_path, _eglLoaderFile, (void *) env); - /* or the name of a built-in driver */ for (i = 0; _eglBuiltInDrivers[i].name; i++) { - if (!strcmp(_eglBuiltInDrivers[i].name, env)) { + if (strlen(_eglBuiltInDrivers[i].name) == name_len && + !strncmp(_eglBuiltInDrivers[i].name, env, name_len)) { mod = _eglAddModule(env); if (mod) mod->BuiltIn = _eglBuiltInDrivers[i].main; + + return EGL_TRUE; } } + } + + /* otherwise, treat env as a path */ + if (env) { + _eglPreloadForEach(search_path, _eglLoaderFile, (void *) env); return EGL_TRUE; } diff --git a/src/egl/wayland/Makefile b/src/egl/wayland/Makefile new file mode 100644 index 00000000000..4cd036519db --- /dev/null +++ b/src/egl/wayland/Makefile @@ -0,0 +1,67 @@ +# src/egl/main/Makefile + +TOP = ../../.. +include $(TOP)/configs/current + +INCLUDE_DIRS = -I$(TOP)/include + +HEADERS = wayland-egl-priv.h +SOURCES = wayland-egl.c + +OBJECTS = $(SOURCES:.c=.o) + +LOCAL_CFLAGS = -I$(TOP)/include/EGL $(LIBDRM_CFLAGS) $(WAYLAND_CFLAGS) +LOCAL_LIBS = + +.c.o: + $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $(LOCAL_CFLAGS) $< -o $@ + + +default: depend library + +# wayland-egl Library +library: $(TOP)/$(LIB_DIR)/$(WAYLAND_EGL_LIB_NAME) + +$(TOP)/$(LIB_DIR)/$(WAYLAND_EGL_LIB_NAME): $(OBJECTS) $(LOCAL_LIBS) + $(MKLIB) -o $(WAYLAND_EGL_LIB) -linker '$(CC)' -ldflags '$(LDFLAGS)' \ + -install $(TOP)/$(LIB_DIR) $(MKLIB_OPTIONS) \ + -L$(TOP)/$(LIB_DIR) $(WAYLAND_EGL_LIB_DEPS) \ + $(OBJECTS) $(LOCAL_LIBS) + +PKG_CONFIG_DIR = $(INSTALL_LIB_DIR)/pkgconfig + +gl_pcedit = sed \ + -e 's,@INSTALL_DIR@,$(INSTALL_DIR),' \ + -e 's,@INSTALL_LIB_DIR@,$(INSTALL_LIB_DIR),' \ + -e 's,@INSTALL_INC_DIR@,$(INSTALL_INC_DIR),' \ + -e 's,@VERSION@,$(MESA_MAJOR).$(MESA_MINOR).$(MESA_TINY),' \ + -e 's,@WAYLAND_EGL_PC_REQ_PRIV@,$(WAYLAND_EGL_PC_REQ_PRIV),' \ + -e 's,@WAYLAND_EGL_PC_LIB_PRIV@,$(WAYLAND_EGL_PC_LIB_PRIV),' \ + -e 's,@WAYLAND_EGL_PC_CFLAGS@,$(WAYLAND_EGL_PC_CFLAGS),' \ + -e 's,@WAYLAND_EGL_LIB@,$(WAYLAND_EGL_LIB),' + +wayland-egl.pc: wayland-egl.pc.in + $(gl_pcedit) $< > $@ + +install: default wayland-egl.pc + $(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR) + $(MINSTALL) $(TOP)/$(LIB_DIR)/$(WAYLAND_EGL_LIB_GLOB) \ + $(DESTDIR)$(INSTALL_LIB_DIR) + $(INSTALL) -d $(DESTDIR)$(PKG_CONFIG_DIR) + $(INSTALL) -m 644 wayland-egl.pc $(DESTDIR)$(PKG_CONFIG_DIR) + +clean: + -rm -f *.o + -rm -f depend depend.bak + + +depend: $(SOURCES) $(HEADERS) + @ echo "running $(MKDEP)" + @ rm -f depend + @ touch depend + $(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDE_DIRS) \ + $(SOURCES) $(HEADERS) > /dev/null 2>/dev/null + + +-include depend +# DO NOT DELETE diff --git a/src/egl/wayland/wayland-egl-priv.h b/src/egl/wayland/wayland-egl-priv.h new file mode 100644 index 00000000000..38b21c25be2 --- /dev/null +++ b/src/egl/wayland/wayland-egl-priv.h @@ -0,0 +1,60 @@ +#ifndef _WAYLAND_EGL_PRIV_H +#define _WAYLAND_EGL_PRIV_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* GCC visibility */ +#if defined(__GNUC__) && __GNUC__ >= 4 +#define WL_EGL_EXPORT __attribute__ ((visibility("default"))) +#else +#define WL_EGL_EXPORT +#endif + +#include <stdbool.h> +#include <wayland-client.h> + +struct wl_egl_display { + struct wl_display *display; + + struct wl_drm *drm; + int fd; + char *device_name; + bool authenticated; + + void (*glFlush)(void); +}; + +struct wl_egl_window { + struct wl_surface *surface; + struct wl_visual *visual; + + int width; + int height; + int dx; + int dy; + + int attached_width; + int attached_height; +}; + +struct wl_egl_pixmap { + struct wl_egl_display *display; + struct wl_visual *visual; + + int name; + int width; + int height; + int stride; + + void (*destroy) (struct wl_egl_pixmap *egl_pixmap); + + void *driver_private; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/egl/wayland/wayland-egl.c b/src/egl/wayland/wayland-egl.c new file mode 100644 index 00000000000..12fbdfa29c1 --- /dev/null +++ b/src/egl/wayland/wayland-egl.c @@ -0,0 +1,226 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdbool.h> +#include <errno.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> + +#include <dlfcn.h> + +#include <wayland-client.h> +#include <xf86drm.h> + +#include "wayland-egl.h" +#include "wayland-egl-priv.h" + +static void +drm_handle_device(void *data, struct wl_drm *drm, const char *device) +{ + struct wl_egl_display *egl_display = data; + drm_magic_t magic; + + egl_display->device_name = strdup(device); + + egl_display->fd = open(egl_display->device_name, O_RDWR); + + if (egl_display->fd == -1) { + fprintf(stderr, "wayland-egl: could not open %s (%s)", + egl_display->device_name, strerror(errno)); + return; + } + drmGetMagic(egl_display->fd, &magic); + wl_drm_authenticate(egl_display->drm, magic); +} + +static void +drm_handle_authenticated(void *data, struct wl_drm *drm) +{ + struct wl_egl_display *egl_display = data; + + egl_display->authenticated = true; +} + +static const struct wl_drm_listener drm_listener = { + drm_handle_device, + drm_handle_authenticated +}; + +static void +wl_display_handle_global(struct wl_display *display, uint32_t id, + const char *interface, uint32_t version, void *data) +{ + struct wl_egl_display *egl_display = data; + + if (strcmp(interface, "drm") == 0) { + egl_display->drm = wl_drm_create(display, id); + wl_drm_add_listener(egl_display->drm, &drm_listener, + egl_display); + } +} + +/* stolen from egl_dri2:dri2_load() */ +static void * +get_flush_address() { + void *handle; + void *(*get_proc_address)(const char *procname); + + handle = dlopen(NULL, RTLD_LAZY | RTLD_GLOBAL); + if (handle) { + get_proc_address = (void* (*)(const char *)) + dlsym(handle, "_glapi_get_proc_address"); + /* no need to keep a reference */ + dlclose(handle); + } + + /* + * If glapi is not available, loading DRI drivers will fail. Ideally, we + * should load one of libGL, libGLESv1_CM, or libGLESv2 and go on. But if + * the app has loaded another one of them with RTLD_LOCAL, there may be + * unexpected behaviors later because there will be two copies of glapi + * (with global variables of the same names!) in the memory. + */ + if (!get_proc_address) { + fprintf(stderr, "failed to find _glapi_get_proc_address"); + return NULL; + } + + return get_proc_address("glFlush"); +} + +WL_EGL_EXPORT struct wl_egl_display * +wl_egl_display_create(struct wl_display *display) +{ + struct wl_egl_display *egl_display; + + egl_display = malloc(sizeof *egl_display); + if (!egl_display) + return NULL; + + egl_display->display = display; + egl_display->drm = NULL; + egl_display->fd = -1; + egl_display->device_name = NULL; + egl_display->authenticated = false; + + egl_display->glFlush = (void (*)(void)) get_flush_address(); + + wl_display_add_global_listener(display, wl_display_handle_global, + egl_display); + + return egl_display; +} + +WL_EGL_EXPORT void +wl_egl_display_destroy(struct wl_egl_display *egl_display) +{ + + free(egl_display->device_name); + close(egl_display->fd); + + wl_drm_destroy(egl_display->drm); + + free(egl_display); +} + +WL_EGL_EXPORT void +wl_egl_window_resize(struct wl_egl_window *egl_window, + int width, int height, + int dx, int dy) +{ + egl_window->width = width; + egl_window->height = height; + egl_window->dx = dx; + egl_window->dy = dy; +} + +WL_EGL_EXPORT struct wl_egl_window * +wl_egl_window_create(struct wl_egl_display *egl_display, + struct wl_surface *surface, + int width, int height, + struct wl_visual *visual) +{ + struct wl_egl_window *egl_window; + + egl_window = malloc(sizeof *egl_window); + if (!egl_window) + return NULL; + + egl_window->surface = surface; + egl_window->visual = visual; + wl_egl_window_resize(egl_window, width, height, 0, 0); + egl_window->attached_width = 0; + egl_window->attached_height = 0; + + return egl_window; +} + +WL_EGL_EXPORT void +wl_egl_window_destroy(struct wl_egl_window *egl_window) +{ + free(egl_window); +} + +WL_EGL_EXPORT void +wl_egl_window_get_attached_size(struct wl_egl_window *egl_window, + int *width, int *height) +{ + if (width) + *width = egl_window->attached_width; + if (height) + *height = egl_window->attached_height; +} + +WL_EGL_EXPORT struct wl_egl_pixmap * +wl_egl_pixmap_create(struct wl_egl_display *egl_display, + int width, int height, + struct wl_visual *visual, uint32_t flags) +{ + struct wl_egl_pixmap *egl_pixmap; + + egl_pixmap = malloc(sizeof *egl_pixmap); + if (egl_pixmap == NULL) + return NULL; + + egl_pixmap->display = egl_display; + egl_pixmap->width = width; + egl_pixmap->height = height; + egl_pixmap->visual = visual; + egl_pixmap->name = 0; + egl_pixmap->stride = 0; + + egl_pixmap->destroy = NULL; + + return egl_pixmap; +} + +WL_EGL_EXPORT void +wl_egl_pixmap_destroy(struct wl_egl_pixmap *egl_pixmap) +{ + if (egl_pixmap->destroy) + egl_pixmap->destroy(egl_pixmap); + free(egl_pixmap); +} + +WL_EGL_EXPORT struct wl_buffer * +wl_egl_pixmap_create_buffer(struct wl_egl_display *egl_display, + struct wl_egl_pixmap *egl_pixmap) +{ + if (egl_pixmap->name == 0) + return NULL; + + return wl_drm_create_buffer(egl_display->drm, egl_pixmap->name, + egl_pixmap->width, egl_pixmap->height, + egl_pixmap->stride, egl_pixmap->visual); +} + +WL_EGL_EXPORT void +wl_egl_pixmap_flush(struct wl_egl_display *egl_display, + struct wl_egl_pixmap *egl_pixmap) +{ + if (egl_display->glFlush) + egl_display->glFlush(); +} diff --git a/src/egl/wayland/wayland-egl.pc.in b/src/egl/wayland/wayland-egl.pc.in new file mode 100644 index 00000000000..3c2067c2a77 --- /dev/null +++ b/src/egl/wayland/wayland-egl.pc.in @@ -0,0 +1,12 @@ +prefix=@INSTALL_DIR@ +exec_prefix=${prefix} +libdir=@INSTALL_LIB_DIR@ +includedir=@INSTALL_INC_DIR@ + +Name: wayland-egl +Description: Mesa wayland-egl library +Requires.private: @WAYLAND_EGL_PC_REQ_PRIV@ +Version: @VERSION@ +Libs: -L${libdir} -l@WAYLAND_EGL_LIB@ +Libs.private: @WAYLAND_EGL_PC_LIB_PRIV@ +Cflags: -I${includedir} @WAYLAND_EGL_PC_CFLAGS@ diff --git a/src/gallium/SConscript b/src/gallium/SConscript index 2265f1de46c..31580556f03 100644 --- a/src/gallium/SConscript +++ b/src/gallium/SConscript @@ -42,6 +42,7 @@ if env['drm']: # SConscript([ # 'drivers/nouveau/SConscript', # 'drivers/nv50/SConscript', + # 'drivers/nvc0/SConscript', # 'drivers/nvfx/SConscript', # ]) diff --git a/src/gallium/auxiliary/Makefile b/src/gallium/auxiliary/Makefile index 6cf1ddd43fe..e40f546929d 100644 --- a/src/gallium/auxiliary/Makefile +++ b/src/gallium/auxiliary/Makefile @@ -143,6 +143,7 @@ C_SOURCES = \ util/u_transfer.c \ util/u_resource.c \ util/u_upload_mgr.c \ + util/u_vbuf_mgr.c \ vl/vl_bitstream_parser.c \ vl/vl_mpeg12_mc_renderer.c \ vl/vl_compositor.c \ diff --git a/src/gallium/auxiliary/SConscript b/src/gallium/auxiliary/SConscript index e6806d9a723..11024d41923 100644 --- a/src/gallium/auxiliary/SConscript +++ b/src/gallium/auxiliary/SConscript @@ -190,11 +190,11 @@ source = [ 'util/u_tile.c', 'util/u_transfer.c', 'util/u_upload_mgr.c', + 'util/u_vbuf_mgr.c', 'vl/vl_bitstream_parser.c', 'vl/vl_mpeg12_mc_renderer.c', 'vl/vl_compositor.c', 'vl/vl_csc.c', - 'target-helpers/wrap_screen.c', ] if env['llvm']: diff --git a/src/gallium/auxiliary/cso_cache/cso_context.c b/src/gallium/auxiliary/cso_cache/cso_context.c index 58b022d531d..fdd40fca126 100644 --- a/src/gallium/auxiliary/cso_cache/cso_context.c +++ b/src/gallium/auxiliary/cso_cache/cso_context.c @@ -47,41 +47,45 @@ #include "cso_cache/cso_hash.h" #include "cso_context.h" -struct cso_context { - struct pipe_context *pipe; - struct cso_cache *cache; +/** + * Info related to samplers and sampler views. + * We have one of these for fragment samplers and another for vertex samplers. + */ +struct sampler_info +{ struct { void *samplers[PIPE_MAX_SAMPLERS]; unsigned nr_samplers; - - void *vertex_samplers[PIPE_MAX_VERTEX_SAMPLERS]; - unsigned nr_vertex_samplers; } hw; void *samplers[PIPE_MAX_SAMPLERS]; unsigned nr_samplers; - void *vertex_samplers[PIPE_MAX_VERTEX_SAMPLERS]; - unsigned nr_vertex_samplers; - - unsigned nr_samplers_saved; void *samplers_saved[PIPE_MAX_SAMPLERS]; + unsigned nr_samplers_saved; + + struct pipe_sampler_view *views[PIPE_MAX_SAMPLERS]; + unsigned nr_views; + + struct pipe_sampler_view *views_saved[PIPE_MAX_SAMPLERS]; + unsigned nr_views_saved; +}; + - unsigned nr_vertex_samplers_saved; - void *vertex_samplers_saved[PIPE_MAX_VERTEX_SAMPLERS]; - uint nr_fragment_sampler_views; - struct pipe_sampler_view *fragment_sampler_views[PIPE_MAX_SAMPLERS]; +struct cso_context { + struct pipe_context *pipe; + struct cso_cache *cache; - uint nr_vertex_sampler_views; - struct pipe_sampler_view *vertex_sampler_views[PIPE_MAX_VERTEX_SAMPLERS]; + struct sampler_info fragment_samplers; + struct sampler_info vertex_samplers; - uint nr_fragment_sampler_views_saved; - struct pipe_sampler_view *fragment_sampler_views_saved[PIPE_MAX_SAMPLERS]; + uint nr_vertex_buffers; + struct pipe_vertex_buffer vertex_buffers[PIPE_MAX_ATTRIBS]; - uint nr_vertex_sampler_views_saved; - struct pipe_sampler_view *vertex_sampler_views_saved[PIPE_MAX_VERTEX_SAMPLERS]; + uint nr_vertex_buffers_saved; + struct pipe_vertex_buffer vertex_buffers_saved[PIPE_MAX_ATTRIBS]; /** Current and saved state. * The saved state is used as a 1-deep stack. @@ -252,6 +256,8 @@ struct cso_context *cso_create_context( struct pipe_context *pipe ) if (ctx == NULL) goto out; + assert(PIPE_MAX_SAMPLERS == PIPE_MAX_VERTEX_SAMPLERS); + ctx->cache = cso_cache_create(); if (ctx->cache == NULL) goto out; @@ -278,7 +284,8 @@ out: void cso_release_all( struct cso_context *ctx ) { unsigned i; - + struct sampler_info *info; + if (ctx->pipe) { ctx->pipe->bind_blend_state( ctx->pipe, NULL ); ctx->pipe->bind_rasterizer_state( ctx->pipe, NULL ); @@ -294,19 +301,30 @@ void cso_release_all( struct cso_context *ctx ) ctx->pipe->set_vertex_sampler_views(ctx->pipe, 0, NULL); } + /* free fragment samplers, views */ + info = &ctx->fragment_samplers; for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { - pipe_sampler_view_reference(&ctx->fragment_sampler_views[i], NULL); - pipe_sampler_view_reference(&ctx->fragment_sampler_views_saved[i], NULL); + pipe_sampler_view_reference(&info->views[i], NULL); + pipe_sampler_view_reference(&info->views_saved[i], NULL); } - for (i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; i++) { - pipe_sampler_view_reference(&ctx->vertex_sampler_views[i], NULL); - pipe_sampler_view_reference(&ctx->vertex_sampler_views_saved[i], NULL); + /* free vertex samplers, views */ + info = &ctx->vertex_samplers; + for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { + pipe_sampler_view_reference(&info->views[i], NULL); + pipe_sampler_view_reference(&info->views_saved[i], NULL); } util_unreference_framebuffer_state(&ctx->fb); util_unreference_framebuffer_state(&ctx->fb_saved); + util_copy_vertex_buffers(ctx->vertex_buffers, + &ctx->nr_vertex_buffers, + NULL, 0); + util_copy_vertex_buffers(ctx->vertex_buffers_saved, + &ctx->nr_vertex_buffers_saved, + NULL, 0); + if (ctx->cache) { cso_cache_delete( ctx->cache ); ctx->cache = NULL; @@ -395,233 +413,6 @@ void cso_restore_blend(struct cso_context *ctx) -enum pipe_error cso_single_sampler(struct cso_context *ctx, - unsigned idx, - const struct pipe_sampler_state *templ) -{ - void *handle = NULL; - - if (templ != NULL) { - unsigned key_size = sizeof(struct pipe_sampler_state); - unsigned hash_key = cso_construct_key((void*)templ, key_size); - struct cso_hash_iter iter = cso_find_state_template(ctx->cache, - hash_key, CSO_SAMPLER, - (void*)templ, key_size); - - if (cso_hash_iter_is_null(iter)) { - struct cso_sampler *cso = MALLOC(sizeof(struct cso_sampler)); - if (!cso) - return PIPE_ERROR_OUT_OF_MEMORY; - - memcpy(&cso->state, templ, sizeof(*templ)); - cso->data = ctx->pipe->create_sampler_state(ctx->pipe, &cso->state); - cso->delete_state = (cso_state_callback)ctx->pipe->delete_sampler_state; - cso->context = ctx->pipe; - - iter = cso_insert_state(ctx->cache, hash_key, CSO_SAMPLER, cso); - if (cso_hash_iter_is_null(iter)) { - FREE(cso); - return PIPE_ERROR_OUT_OF_MEMORY; - } - - handle = cso->data; - } - else { - handle = ((struct cso_sampler *)cso_hash_iter_data(iter))->data; - } - } - - ctx->samplers[idx] = handle; - return PIPE_OK; -} - -enum pipe_error -cso_single_vertex_sampler(struct cso_context *ctx, - unsigned idx, - const struct pipe_sampler_state *templ) -{ - void *handle = NULL; - - if (templ != NULL) { - unsigned key_size = sizeof(struct pipe_sampler_state); - unsigned hash_key = cso_construct_key((void*)templ, key_size); - struct cso_hash_iter iter = cso_find_state_template(ctx->cache, - hash_key, CSO_SAMPLER, - (void*)templ, key_size); - - if (cso_hash_iter_is_null(iter)) { - struct cso_sampler *cso = MALLOC(sizeof(struct cso_sampler)); - if (!cso) - return PIPE_ERROR_OUT_OF_MEMORY; - - memcpy(&cso->state, templ, sizeof(*templ)); - cso->data = ctx->pipe->create_sampler_state(ctx->pipe, &cso->state); - cso->delete_state = (cso_state_callback)ctx->pipe->delete_sampler_state; - cso->context = ctx->pipe; - - iter = cso_insert_state(ctx->cache, hash_key, CSO_SAMPLER, cso); - if (cso_hash_iter_is_null(iter)) { - FREE(cso); - return PIPE_ERROR_OUT_OF_MEMORY; - } - - handle = cso->data; - } - else { - handle = ((struct cso_sampler *)cso_hash_iter_data(iter))->data; - } - } - - ctx->vertex_samplers[idx] = handle; - return PIPE_OK; -} - -void cso_single_sampler_done( struct cso_context *ctx ) -{ - unsigned i; - - /* find highest non-null sampler */ - for (i = PIPE_MAX_SAMPLERS; i > 0; i--) { - if (ctx->samplers[i - 1] != NULL) - break; - } - - ctx->nr_samplers = i; - - if (ctx->hw.nr_samplers != ctx->nr_samplers || - memcmp(ctx->hw.samplers, - ctx->samplers, - ctx->nr_samplers * sizeof(void *)) != 0) - { - memcpy(ctx->hw.samplers, ctx->samplers, ctx->nr_samplers * sizeof(void *)); - ctx->hw.nr_samplers = ctx->nr_samplers; - - ctx->pipe->bind_fragment_sampler_states(ctx->pipe, ctx->nr_samplers, ctx->samplers); - } -} - -void -cso_single_vertex_sampler_done(struct cso_context *ctx) -{ - unsigned i; - - /* find highest non-null sampler */ - for (i = PIPE_MAX_VERTEX_SAMPLERS; i > 0; i--) { - if (ctx->vertex_samplers[i - 1] != NULL) - break; - } - - ctx->nr_vertex_samplers = i; - - if (ctx->hw.nr_vertex_samplers != ctx->nr_vertex_samplers || - memcmp(ctx->hw.vertex_samplers, - ctx->vertex_samplers, - ctx->nr_vertex_samplers * sizeof(void *)) != 0) - { - memcpy(ctx->hw.vertex_samplers, - ctx->vertex_samplers, - ctx->nr_vertex_samplers * sizeof(void *)); - ctx->hw.nr_vertex_samplers = ctx->nr_vertex_samplers; - - ctx->pipe->bind_vertex_sampler_states(ctx->pipe, - ctx->nr_vertex_samplers, - ctx->vertex_samplers); - } -} - -/* - * If the function encouters any errors it will return the - * last one. Done to always try to set as many samplers - * as possible. - */ -enum pipe_error cso_set_samplers( struct cso_context *ctx, - unsigned nr, - const struct pipe_sampler_state **templates ) -{ - unsigned i; - enum pipe_error temp, error = PIPE_OK; - - /* TODO: fastpath - */ - - for (i = 0; i < nr; i++) { - temp = cso_single_sampler( ctx, i, templates[i] ); - if (temp != PIPE_OK) - error = temp; - } - - for ( ; i < ctx->nr_samplers; i++) { - temp = cso_single_sampler( ctx, i, NULL ); - if (temp != PIPE_OK) - error = temp; - } - - cso_single_sampler_done( ctx ); - - return error; -} - -void cso_save_samplers(struct cso_context *ctx) -{ - ctx->nr_samplers_saved = ctx->nr_samplers; - memcpy(ctx->samplers_saved, ctx->samplers, sizeof(ctx->samplers)); -} - -void cso_restore_samplers(struct cso_context *ctx) -{ - ctx->nr_samplers = ctx->nr_samplers_saved; - memcpy(ctx->samplers, ctx->samplers_saved, sizeof(ctx->samplers)); - cso_single_sampler_done( ctx ); -} - -/* - * If the function encouters any errors it will return the - * last one. Done to always try to set as many samplers - * as possible. - */ -enum pipe_error cso_set_vertex_samplers(struct cso_context *ctx, - unsigned nr, - const struct pipe_sampler_state **templates) -{ - unsigned i; - enum pipe_error temp, error = PIPE_OK; - - /* TODO: fastpath - */ - - for (i = 0; i < nr; i++) { - temp = cso_single_vertex_sampler( ctx, i, templates[i] ); - if (temp != PIPE_OK) - error = temp; - } - - for ( ; i < ctx->nr_samplers; i++) { - temp = cso_single_vertex_sampler( ctx, i, NULL ); - if (temp != PIPE_OK) - error = temp; - } - - cso_single_vertex_sampler_done( ctx ); - - return error; -} - -void -cso_save_vertex_samplers(struct cso_context *ctx) -{ - ctx->nr_vertex_samplers_saved = ctx->nr_vertex_samplers; - memcpy(ctx->vertex_samplers_saved, ctx->vertex_samplers, sizeof(ctx->vertex_samplers)); -} - -void -cso_restore_vertex_samplers(struct cso_context *ctx) -{ - ctx->nr_vertex_samplers = ctx->nr_vertex_samplers_saved; - memcpy(ctx->vertex_samplers, ctx->vertex_samplers_saved, sizeof(ctx->vertex_samplers)); - cso_single_vertex_sampler_done(ctx); -} - - enum pipe_error cso_set_depth_stencil_alpha(struct cso_context *ctx, const struct pipe_depth_stencil_alpha_state *templ) { @@ -1143,121 +934,361 @@ void cso_restore_vertex_elements(struct cso_context *ctx) ctx->velements_saved = NULL; } -/* fragment sampler view state */ +/* vertex buffers */ -void -cso_set_fragment_sampler_views(struct cso_context *cso, - uint count, - struct pipe_sampler_view **views) +void cso_set_vertex_buffers(struct cso_context *ctx, + unsigned count, + const struct pipe_vertex_buffer *buffers) { - uint i; - - for (i = 0; i < count; i++) { - pipe_sampler_view_reference(&cso->fragment_sampler_views[i], views[i]); + if (count != ctx->nr_vertex_buffers || + memcmp(buffers, ctx->vertex_buffers, + sizeof(struct pipe_vertex_buffer) * count) != 0) { + util_copy_vertex_buffers(ctx->vertex_buffers, &ctx->nr_vertex_buffers, + buffers, count); + ctx->pipe->set_vertex_buffers(ctx->pipe, count, buffers); } - for (; i < cso->nr_fragment_sampler_views; i++) { - pipe_sampler_view_reference(&cso->fragment_sampler_views[i], NULL); +} + +void cso_save_vertex_buffers(struct cso_context *ctx) +{ + util_copy_vertex_buffers(ctx->vertex_buffers_saved, + &ctx->nr_vertex_buffers_saved, + ctx->vertex_buffers, + ctx->nr_vertex_buffers); +} + +void cso_restore_vertex_buffers(struct cso_context *ctx) +{ + util_copy_vertex_buffers(ctx->vertex_buffers, + &ctx->nr_vertex_buffers, + ctx->vertex_buffers_saved, + ctx->nr_vertex_buffers_saved); + ctx->pipe->set_vertex_buffers(ctx->pipe, ctx->nr_vertex_buffers, + ctx->vertex_buffers); +} + + +/**************** fragment/vertex sampler view state *************************/ + +static enum pipe_error +single_sampler(struct cso_context *ctx, + struct sampler_info *info, + unsigned idx, + const struct pipe_sampler_state *templ) +{ + void *handle = NULL; + + if (templ != NULL) { + unsigned key_size = sizeof(struct pipe_sampler_state); + unsigned hash_key = cso_construct_key((void*)templ, key_size); + struct cso_hash_iter iter = + cso_find_state_template(ctx->cache, + hash_key, CSO_SAMPLER, + (void *) templ, key_size); + + if (cso_hash_iter_is_null(iter)) { + struct cso_sampler *cso = MALLOC(sizeof(struct cso_sampler)); + if (!cso) + return PIPE_ERROR_OUT_OF_MEMORY; + + memcpy(&cso->state, templ, sizeof(*templ)); + cso->data = ctx->pipe->create_sampler_state(ctx->pipe, &cso->state); + cso->delete_state = (cso_state_callback)ctx->pipe->delete_sampler_state; + cso->context = ctx->pipe; + + iter = cso_insert_state(ctx->cache, hash_key, CSO_SAMPLER, cso); + if (cso_hash_iter_is_null(iter)) { + FREE(cso); + return PIPE_ERROR_OUT_OF_MEMORY; + } + + handle = cso->data; + } + else { + handle = ((struct cso_sampler *)cso_hash_iter_data(iter))->data; + } } - cso->pipe->set_fragment_sampler_views(cso->pipe, - MAX2(count, cso->nr_fragment_sampler_views), - cso->fragment_sampler_views); + info->samplers[idx] = handle; - cso->nr_fragment_sampler_views = count; + return PIPE_OK; } -void -cso_save_fragment_sampler_views(struct cso_context *cso) +enum pipe_error +cso_single_sampler(struct cso_context *ctx, + unsigned idx, + const struct pipe_sampler_state *templ) { - uint i; + return single_sampler(ctx, &ctx->fragment_samplers, idx, templ); +} + +enum pipe_error +cso_single_vertex_sampler(struct cso_context *ctx, + unsigned idx, + const struct pipe_sampler_state *templ) +{ + return single_sampler(ctx, &ctx->vertex_samplers, idx, templ); +} + - cso->nr_fragment_sampler_views_saved = cso->nr_fragment_sampler_views; - for (i = 0; i < cso->nr_fragment_sampler_views; i++) { - assert(!cso->fragment_sampler_views_saved[i]); +static void +single_sampler_done(struct cso_context *ctx, + struct sampler_info *info) +{ + unsigned i; - pipe_sampler_view_reference(&cso->fragment_sampler_views_saved[i], - cso->fragment_sampler_views[i]); + /* find highest non-null sampler */ + for (i = PIPE_MAX_SAMPLERS; i > 0; i--) { + if (info->samplers[i - 1] != NULL) + break; + } + + info->nr_samplers = i; + + if (info->hw.nr_samplers != info->nr_samplers || + memcmp(info->hw.samplers, + info->samplers, + info->nr_samplers * sizeof(void *)) != 0) + { + memcpy(info->hw.samplers, + info->samplers, + info->nr_samplers * sizeof(void *)); + info->hw.nr_samplers = info->nr_samplers; + + if (info == &ctx->fragment_samplers) { + ctx->pipe->bind_fragment_sampler_states(ctx->pipe, + info->nr_samplers, + info->samplers); + } + else if (info == &ctx->vertex_samplers) { + ctx->pipe->bind_vertex_sampler_states(ctx->pipe, + info->nr_samplers, + info->samplers); + } + else { + assert(0); + } } } void -cso_restore_fragment_sampler_views(struct cso_context *cso) +cso_single_sampler_done( struct cso_context *ctx ) { - uint i; + single_sampler_done(ctx, &ctx->fragment_samplers); +} + +void +cso_single_vertex_sampler_done(struct cso_context *ctx) +{ + single_sampler_done(ctx, &ctx->vertex_samplers); +} - for (i = 0; i < cso->nr_fragment_sampler_views_saved; i++) { - pipe_sampler_view_reference(&cso->fragment_sampler_views[i], cso->fragment_sampler_views_saved[i]); - pipe_sampler_view_reference(&cso->fragment_sampler_views_saved[i], NULL); + +/* + * If the function encouters any errors it will return the + * last one. Done to always try to set as many samplers + * as possible. + */ +static enum pipe_error +set_samplers(struct cso_context *ctx, + struct sampler_info *info, + unsigned nr, + const struct pipe_sampler_state **templates) +{ + unsigned i; + enum pipe_error temp, error = PIPE_OK; + + /* TODO: fastpath + */ + + for (i = 0; i < nr; i++) { + temp = single_sampler(ctx, info, i, templates[i]); + if (temp != PIPE_OK) + error = temp; } - for (; i < cso->nr_fragment_sampler_views; i++) { - pipe_sampler_view_reference(&cso->fragment_sampler_views[i], NULL); + + for ( ; i < info->nr_samplers; i++) { + temp = single_sampler(ctx, info, i, NULL); + if (temp != PIPE_OK) + error = temp; } - cso->pipe->set_fragment_sampler_views(cso->pipe, - MAX2(cso->nr_fragment_sampler_views, cso->nr_fragment_sampler_views_saved), - cso->fragment_sampler_views); + single_sampler_done(ctx, info); + + return error; +} + +enum pipe_error +cso_set_samplers(struct cso_context *ctx, + unsigned nr, + const struct pipe_sampler_state **templates) +{ + return set_samplers(ctx, &ctx->fragment_samplers, nr, templates); +} - cso->nr_fragment_sampler_views = cso->nr_fragment_sampler_views_saved; - cso->nr_fragment_sampler_views_saved = 0; +enum pipe_error +cso_set_vertex_samplers(struct cso_context *ctx, + unsigned nr, + const struct pipe_sampler_state **templates) +{ + return set_samplers(ctx, &ctx->vertex_samplers, nr, templates); } -/* vertex sampler view state */ + +static void +save_samplers(struct cso_context *ctx, struct sampler_info *info) +{ + info->nr_samplers_saved = info->nr_samplers; + memcpy(info->samplers_saved, info->samplers, sizeof(info->samplers)); +} void -cso_set_vertex_sampler_views(struct cso_context *cso, - uint count, - struct pipe_sampler_view **views) +cso_save_samplers(struct cso_context *ctx) +{ + save_samplers(ctx, &ctx->fragment_samplers); +} + +void +cso_save_vertex_samplers(struct cso_context *ctx) +{ + save_samplers(ctx, &ctx->vertex_samplers); +} + + + +static void +restore_samplers(struct cso_context *ctx, struct sampler_info *info) +{ + info->nr_samplers = info->nr_samplers_saved; + memcpy(info->samplers, info->samplers_saved, sizeof(info->samplers)); + single_sampler_done(ctx, info); +} + +void +cso_restore_samplers(struct cso_context *ctx) +{ + restore_samplers(ctx, &ctx->fragment_samplers); +} + +void +cso_restore_vertex_samplers(struct cso_context *ctx) +{ + restore_samplers(ctx, &ctx->vertex_samplers); +} + + + +static void +set_sampler_views(struct cso_context *ctx, + struct sampler_info *info, + void (*set_views)(struct pipe_context *, + unsigned num_views, + struct pipe_sampler_view **), + uint count, + struct pipe_sampler_view **views) { uint i; + /* reference new views */ for (i = 0; i < count; i++) { - pipe_sampler_view_reference(&cso->vertex_sampler_views[i], views[i]); + pipe_sampler_view_reference(&info->views[i], views[i]); } - for (; i < cso->nr_vertex_sampler_views; i++) { - pipe_sampler_view_reference(&cso->vertex_sampler_views[i], NULL); + /* unref extra old views, if any */ + for (; i < info->nr_views; i++) { + pipe_sampler_view_reference(&info->views[i], NULL); } - cso->pipe->set_vertex_sampler_views(cso->pipe, - MAX2(count, cso->nr_vertex_sampler_views), - cso->vertex_sampler_views); + info->nr_views = count; - cso->nr_vertex_sampler_views = count; + /* bind the new sampler views */ + set_views(ctx->pipe, count, info->views); } void -cso_save_vertex_sampler_views(struct cso_context *cso) +cso_set_fragment_sampler_views(struct cso_context *ctx, + uint count, + struct pipe_sampler_view **views) { - uint i; + set_sampler_views(ctx, &ctx->fragment_samplers, + ctx->pipe->set_fragment_sampler_views, + count, views); +} - cso->nr_vertex_sampler_views_saved = cso->nr_vertex_sampler_views; +void +cso_set_vertex_sampler_views(struct cso_context *ctx, + uint count, + struct pipe_sampler_view **views) +{ + set_sampler_views(ctx, &ctx->vertex_samplers, + ctx->pipe->set_vertex_sampler_views, + count, views); +} - for (i = 0; i < cso->nr_vertex_sampler_views; i++) { - assert(!cso->vertex_sampler_views_saved[i]); - pipe_sampler_view_reference(&cso->vertex_sampler_views_saved[i], - cso->vertex_sampler_views[i]); + +static void +save_sampler_views(struct cso_context *ctx, + struct sampler_info *info) +{ + uint i; + + info->nr_views_saved = info->nr_views; + + for (i = 0; i < info->nr_views; i++) { + assert(!info->views_saved[i]); + pipe_sampler_view_reference(&info->views_saved[i], info->views[i]); } } void -cso_restore_vertex_sampler_views(struct cso_context *cso) +cso_save_fragment_sampler_views(struct cso_context *ctx) +{ + save_sampler_views(ctx, &ctx->fragment_samplers); +} + +void +cso_save_vertex_sampler_views(struct cso_context *ctx) +{ + save_sampler_views(ctx, &ctx->vertex_samplers); +} + + +static void +restore_sampler_views(struct cso_context *ctx, + struct sampler_info *info, + void (*set_views)(struct pipe_context *, + unsigned num_views, + struct pipe_sampler_view **)) { uint i; - for (i = 0; i < cso->nr_vertex_sampler_views_saved; i++) { - pipe_sampler_view_reference(&cso->vertex_sampler_views[i], cso->vertex_sampler_views_saved[i]); - pipe_sampler_view_reference(&cso->vertex_sampler_views_saved[i], NULL); + for (i = 0; i < info->nr_views_saved; i++) { + pipe_sampler_view_reference(&info->views[i], info->views_saved[i]); + pipe_sampler_view_reference(&info->views_saved[i], NULL); } - for (; i < cso->nr_vertex_sampler_views; i++) { - pipe_sampler_view_reference(&cso->vertex_sampler_views[i], NULL); + for (; i < info->nr_views; i++) { + pipe_sampler_view_reference(&info->views[i], NULL); } - cso->pipe->set_vertex_sampler_views(cso->pipe, - MAX2(cso->nr_vertex_sampler_views, cso->nr_vertex_sampler_views_saved), - cso->vertex_sampler_views); + /* bind the old/saved sampler views */ + set_views(ctx->pipe, info->nr_views_saved, info->views); + + info->nr_views = info->nr_views_saved; + info->nr_views_saved = 0; +} + +void +cso_restore_fragment_sampler_views(struct cso_context *ctx) +{ + restore_sampler_views(ctx, &ctx->fragment_samplers, + ctx->pipe->set_fragment_sampler_views); +} - cso->nr_vertex_sampler_views = cso->nr_vertex_sampler_views_saved; - cso->nr_vertex_sampler_views_saved = 0; +void +cso_restore_vertex_sampler_views(struct cso_context *ctx) +{ + restore_sampler_views(ctx, &ctx->vertex_samplers, + ctx->pipe->set_vertex_sampler_views); } diff --git a/src/gallium/auxiliary/cso_cache/cso_context.h b/src/gallium/auxiliary/cso_cache/cso_context.h index f0b07f73765..00edc9f8dd4 100644 --- a/src/gallium/auxiliary/cso_cache/cso_context.h +++ b/src/gallium/auxiliary/cso_cache/cso_context.h @@ -110,6 +110,13 @@ void cso_save_vertex_elements(struct cso_context *ctx); void cso_restore_vertex_elements(struct cso_context *ctx); +void cso_set_vertex_buffers(struct cso_context *ctx, + unsigned count, + const struct pipe_vertex_buffer *buffers); +void cso_save_vertex_buffers(struct cso_context *ctx); +void cso_restore_vertex_buffers(struct cso_context *ctx); + + /* These aren't really sensible -- most of the time the api provides * object semantics for shaders anyway, and the cases where it doesn't * (eg mesa's internall-generated texenv programs), it will be up to diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c index e045313b94f..95d96719873 100644 --- a/src/gallium/auxiliary/draw/draw_context.c +++ b/src/gallium/auxiliary/draw/draw_context.c @@ -88,8 +88,14 @@ draw_create_gallivm(struct pipe_context *pipe, struct gallivm_state *gallivm) goto fail; #if HAVE_LLVM - if (draw_get_option_use_llvm() && gallivm) { - draw->llvm = draw_llvm_create(draw, gallivm); + if (draw_get_option_use_llvm()) { + if (!gallivm) { + gallivm = gallivm_create(); + draw->own_gallivm = gallivm; + } + + if (gallivm) + draw->llvm = draw_llvm_create(draw, gallivm); } #endif @@ -180,8 +186,11 @@ void draw_destroy( struct draw_context *draw ) draw_vs_destroy( draw ); draw_gs_destroy( draw ); #ifdef HAVE_LLVM - if(draw->llvm) + if (draw->llvm) draw_llvm_destroy( draw->llvm ); + + if (draw->own_gallivm) + gallivm_destroy(draw->own_gallivm); #endif FREE( draw ); @@ -401,7 +410,7 @@ void draw_wide_line_threshold(struct draw_context *draw, float threshold) { draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); - draw->pipeline.wide_line_threshold = threshold; + draw->pipeline.wide_line_threshold = roundf(threshold); } diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c index 0c51aa85b37..a5217c1d4ec 100644 --- a/src/gallium/auxiliary/draw/draw_llvm.c +++ b/src/gallium/auxiliary/draw/draw_llvm.c @@ -214,13 +214,12 @@ static LLVMTypeRef create_jit_vertex_buffer_type(struct gallivm_state *gallivm) { LLVMTargetDataRef target = gallivm->target; - LLVMTypeRef elem_types[4]; + LLVMTypeRef elem_types[3]; LLVMTypeRef vb_type; elem_types[0] = - elem_types[1] = - elem_types[2] = LLVMInt32TypeInContext(gallivm->context); - elem_types[3] = LLVMPointerType(LLVMOpaqueTypeInContext(gallivm->context), 0); /* vs_constants */ + elem_types[1] = LLVMInt32TypeInContext(gallivm->context); + elem_types[2] = LLVMPointerType(LLVMInt8TypeInContext(gallivm->context), 0); /* vs_constants */ vb_type = LLVMStructTypeInContext(gallivm->context, elem_types, Elements(elem_types), 0); @@ -229,10 +228,8 @@ create_jit_vertex_buffer_type(struct gallivm_state *gallivm) LP_CHECK_MEMBER_OFFSET(struct pipe_vertex_buffer, stride, target, vb_type, 0); - LP_CHECK_MEMBER_OFFSET(struct pipe_vertex_buffer, max_index, - target, vb_type, 1); LP_CHECK_MEMBER_OFFSET(struct pipe_vertex_buffer, buffer_offset, - target, vb_type, 2); + target, vb_type, 1); LP_CHECK_STRUCT_SIZE(struct pipe_vertex_buffer, target, vb_type); @@ -513,9 +510,7 @@ generate_fetch(struct gallivm_state *gallivm, LLVMValueRef vbuffer_ptr = LLVMBuildGEP(builder, vbuffers_ptr, &indices, 1, ""); LLVMValueRef vb_stride = draw_jit_vbuffer_stride(gallivm, vbuf); - LLVMValueRef vb_max_index = draw_jit_vbuffer_max_index(gallivm, vbuf); LLVMValueRef vb_buffer_offset = draw_jit_vbuffer_offset(gallivm, vbuf); - LLVMValueRef cond; LLVMValueRef stride; if (velem->instance_divisor) { @@ -525,10 +520,6 @@ generate_fetch(struct gallivm_state *gallivm, "instance_divisor"); } - /* limit index to min(index, vb_max_index) */ - cond = LLVMBuildICmp(builder, LLVMIntULE, index, vb_max_index, ""); - index = LLVMBuildSelect(builder, cond, index, vb_max_index, ""); - stride = LLVMBuildMul(builder, vb_stride, index, ""); vbuffer_ptr = LLVMBuildLoad(builder, vbuffer_ptr, "vbuffer"); diff --git a/src/gallium/auxiliary/draw/draw_llvm.h b/src/gallium/auxiliary/draw/draw_llvm.h index 9f038f1f04d..e8623e7bcdc 100644 --- a/src/gallium/auxiliary/draw/draw_llvm.h +++ b/src/gallium/auxiliary/draw/draw_llvm.h @@ -133,11 +133,8 @@ struct draw_jit_context #define draw_jit_vbuffer_stride(_gallivm, _ptr) \ lp_build_struct_get(_gallivm, _ptr, 0, "stride") -#define draw_jit_vbuffer_max_index(_gallivm, _ptr) \ - lp_build_struct_get(_gallivm, _ptr, 1, "max_index") - #define draw_jit_vbuffer_offset(_gallivm, _ptr) \ - lp_build_struct_get(_gallivm, _ptr, 2, "buffer_offset") + lp_build_struct_get(_gallivm, _ptr, 1, "buffer_offset") typedef int diff --git a/src/gallium/auxiliary/draw/draw_pipe.c b/src/gallium/auxiliary/draw/draw_pipe.c index 6206197dae9..f1b0171f520 100644 --- a/src/gallium/auxiliary/draw/draw_pipe.c +++ b/src/gallium/auxiliary/draw/draw_pipe.c @@ -64,8 +64,8 @@ boolean draw_pipeline_init( struct draw_context *draw ) return FALSE; /* these defaults are oriented toward the needs of softpipe */ - draw->pipeline.wide_point_threshold = 1000000.0; /* infinity */ - draw->pipeline.wide_line_threshold = 1.0; + draw->pipeline.wide_point_threshold = 1000000.0f; /* infinity */ + draw->pipeline.wide_line_threshold = 1.0f; draw->pipeline.wide_point_sprites = FALSE; draw->pipeline.line_stipple = TRUE; draw->pipeline.point_sprite = TRUE; diff --git a/src/gallium/auxiliary/draw/draw_pipe_aaline.c b/src/gallium/auxiliary/draw/draw_pipe_aaline.c index 0851b9acc0d..32af29ae144 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_aaline.c +++ b/src/gallium/auxiliary/draw/draw_pipe_aaline.c @@ -55,9 +55,16 @@ /** + * Size for the alpha texture used for antialiasing + */ +#define TEXTURE_SIZE_LOG2 5 /* 32 x 32 */ + +/** * Max texture level for the alpha texture used for antialiasing + * + * Don't use the 1x1 and 2x2 mipmap levels. */ -#define MAX_TEXTURE_LEVEL 5 /* 32 x 32 */ +#define MAX_TEXTURE_LEVEL (TEXTURE_SIZE_LOG2 - 2) /** @@ -403,8 +410,8 @@ aaline_create_texture(struct aaline_stage *aaline) texTemp.target = PIPE_TEXTURE_2D; texTemp.format = PIPE_FORMAT_A8_UNORM; /* XXX verify supported by driver! */ texTemp.last_level = MAX_TEXTURE_LEVEL; - texTemp.width0 = 1 << MAX_TEXTURE_LEVEL; - texTemp.height0 = 1 << MAX_TEXTURE_LEVEL; + texTemp.width0 = 1 << TEXTURE_SIZE_LOG2; + texTemp.height0 = 1 << TEXTURE_SIZE_LOG2; texTemp.depth0 = 1; texTemp.array_size = 1; texTemp.bind = PIPE_BIND_SAMPLER_VIEW; @@ -461,7 +468,7 @@ aaline_create_texture(struct aaline_stage *aaline) d = 200; /* tuneable */ } else if (i == 0 || j == 0 || i == size - 1 || j == size - 1) { - d = 0; + d = 35; /* edge texel */ } else { d = 255; @@ -498,8 +505,7 @@ aaline_create_sampler(struct aaline_stage *aaline) sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR; sampler.normalized_coords = 1; sampler.min_lod = 0.0f; - /* avoid using the 1x1 and 2x2 mipmap levels */ - sampler.max_lod = MAX_TEXTURE_LEVEL - 2; + sampler.max_lod = MAX_TEXTURE_LEVEL; aaline->sampler_cso = pipe->create_sampler_state(pipe, &sampler); if (aaline->sampler_cso == NULL) diff --git a/src/gallium/auxiliary/draw/draw_pipe_pstipple.c b/src/gallium/auxiliary/draw/draw_pipe_pstipple.c index f5515c1df76..ea62c9739fd 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_pstipple.c +++ b/src/gallium/auxiliary/draw/draw_pipe_pstipple.c @@ -27,8 +27,9 @@ /** * Polygon stipple stage: implement polygon stipple with texture map and - * fragment program. The fragment program samples the texture and does - * a fragment kill for the stipple-failing fragments. + * fragment program. The fragment program samples the texture using the + * fragment window coordinate register and does a fragment kill for the + * stipple-failing fragments. * * Authors: Brian Paul */ @@ -114,7 +115,8 @@ struct pstip_stage /** * Subclass of tgsi_transform_context, used for transforming the - * user's fragment shader to add the special AA instructions. + * user's fragment shader to add the extra texture sample and fragment kill + * instructions. */ struct pstip_transform_context { struct tgsi_transform_context base; @@ -658,16 +660,16 @@ pstip_create_fs_state(struct pipe_context *pipe, const struct pipe_shader_state *fs) { struct pstip_stage *pstip = pstip_stage_from_pipe(pipe); - struct pstip_fragment_shader *aafs = CALLOC_STRUCT(pstip_fragment_shader); + struct pstip_fragment_shader *pstipfs = CALLOC_STRUCT(pstip_fragment_shader); - if (aafs) { - aafs->state = *fs; + if (pstipfs) { + pstipfs->state = *fs; /* pass-through */ - aafs->driver_fs = pstip->driver_create_fs_state(pstip->pipe, fs); + pstipfs->driver_fs = pstip->driver_create_fs_state(pstip->pipe, fs); } - return aafs; + return pstipfs; } @@ -675,12 +677,12 @@ static void pstip_bind_fs_state(struct pipe_context *pipe, void *fs) { struct pstip_stage *pstip = pstip_stage_from_pipe(pipe); - struct pstip_fragment_shader *aafs = (struct pstip_fragment_shader *) fs; + struct pstip_fragment_shader *pstipfs = (struct pstip_fragment_shader *) fs; /* save current */ - pstip->fs = aafs; + pstip->fs = pstipfs; /* pass-through */ pstip->driver_bind_fs_state(pstip->pipe, - (aafs ? aafs->driver_fs : NULL)); + (pstipfs ? pstipfs->driver_fs : NULL)); } @@ -688,14 +690,14 @@ static void pstip_delete_fs_state(struct pipe_context *pipe, void *fs) { struct pstip_stage *pstip = pstip_stage_from_pipe(pipe); - struct pstip_fragment_shader *aafs = (struct pstip_fragment_shader *) fs; + struct pstip_fragment_shader *pstipfs = (struct pstip_fragment_shader *) fs; /* pass-through */ - pstip->driver_delete_fs_state(pstip->pipe, aafs->driver_fs); + pstip->driver_delete_fs_state(pstip->pipe, pstipfs->driver_fs); - if (aafs->pstip_fs) - pstip->driver_delete_fs_state(pstip->pipe, aafs->pstip_fs); + if (pstipfs->pstip_fs) + pstip->driver_delete_fs_state(pstip->pipe, pstipfs->pstip_fs); - FREE(aafs); + FREE(pstipfs); } diff --git a/src/gallium/auxiliary/draw/draw_pipe_validate.c b/src/gallium/auxiliary/draw/draw_pipe_validate.c index c575a8ac7ca..27afba5af3d 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_validate.c +++ b/src/gallium/auxiliary/draw/draw_pipe_validate.c @@ -29,6 +29,7 @@ */ #include "util/u_memory.h" +#include "util/u_math.h" #include "pipe/p_defines.h" #include "draw_private.h" #include "draw_pipe.h" @@ -86,7 +87,7 @@ draw_need_pipeline(const struct draw_context *draw, return TRUE; /* wide lines */ - if (rasterizer->line_width > draw->pipeline.wide_line_threshold) + if (roundf(rasterizer->line_width) > draw->pipeline.wide_line_threshold) return TRUE; /* AA lines */ @@ -169,7 +170,7 @@ static struct draw_stage *validate_pipeline( struct draw_stage *stage ) stage->next = next; /* drawing wide lines? */ - wide_lines = (rast->line_width > draw->pipeline.wide_line_threshold + wide_lines = (roundf(rast->line_width) > draw->pipeline.wide_line_threshold && !rast->line_smooth); /* drawing large/sprite points (but not AA points)? */ diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h index 06ed4d60ef2..db2e3c5410d 100644 --- a/src/gallium/auxiliary/draw/draw_private.h +++ b/src/gallium/auxiliary/draw/draw_private.h @@ -286,6 +286,7 @@ struct draw_context #ifdef HAVE_LLVM struct draw_llvm *llvm; + struct gallivm_state *own_gallivm; #endif struct pipe_sampler_view *sampler_views[PIPE_MAX_VERTEX_SAMPLERS]; diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c index 4078b2a07d0..c3d7e871f7a 100644 --- a/src/gallium/auxiliary/draw/draw_pt.c +++ b/src/gallium/auxiliary/draw/draw_pt.c @@ -459,10 +459,9 @@ draw_vbo(struct draw_context *draw, } debug_printf("Buffers:\n"); for (i = 0; i < draw->pt.nr_vertex_buffers; i++) { - debug_printf(" %u: stride=%u maxindex=%u offset=%u ptr=%p\n", + debug_printf(" %u: stride=%u offset=%u ptr=%p\n", i, draw->pt.vertex_buffer[i].stride, - draw->pt.vertex_buffer[i].max_index, draw->pt.vertex_buffer[i].buffer_offset, draw->pt.user.vbuffer[i]); } diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch.c b/src/gallium/auxiliary/draw/draw_pt_fetch.c index ae12ee24bdc..4fa3b265e10 100644 --- a/src/gallium/auxiliary/draw/draw_pt_fetch.c +++ b/src/gallium/auxiliary/draw/draw_pt_fetch.c @@ -139,7 +139,7 @@ void draw_pt_fetch_run( struct pt_fetch *fetch, ((char *)draw->pt.user.vbuffer[i] + draw->pt.vertex_buffer[i].buffer_offset), draw->pt.vertex_buffer[i].stride, - draw->pt.vertex_buffer[i].max_index); + draw->pt.user.max_index); } translate->run_elts( translate, @@ -166,7 +166,7 @@ void draw_pt_fetch_run_linear( struct pt_fetch *fetch, ((char *)draw->pt.user.vbuffer[i] + draw->pt.vertex_buffer[i].buffer_offset), draw->pt.vertex_buffer[i].stride, - draw->pt.vertex_buffer[i].max_index); + draw->pt.user.max_index); } translate->run( translate, diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c index e706b7796f8..51043102a61 100644 --- a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c +++ b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c @@ -186,7 +186,7 @@ static void fetch_emit_prepare( struct draw_pt_middle_end *middle, ((char *)draw->pt.user.vbuffer[i] + draw->pt.vertex_buffer[i].buffer_offset), draw->pt.vertex_buffer[i].stride, - draw->pt.vertex_buffer[i].max_index); + draw->pt.user.max_index); } *max_vertices = (draw->render->max_vertex_buffer_bytes / diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c index c98fb3d5205..1e926fb028e 100644 --- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c +++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c @@ -169,7 +169,7 @@ static void fse_prepare( struct draw_pt_middle_end *middle, ((const ubyte *) draw->pt.user.vbuffer[i] + draw->pt.vertex_buffer[i].buffer_offset), draw->pt.vertex_buffer[i].stride, - draw->pt.vertex_buffer[i].max_index ); + draw->pt.user.max_index ); } *max_vertices = (draw->render->max_vertex_buffer_bytes / diff --git a/src/gallium/auxiliary/gallivm/lp_bld_conv.c b/src/gallium/auxiliary/gallivm/lp_bld_conv.c index c43ee8ac638..c261d761161 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_conv.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_conv.c @@ -231,44 +231,53 @@ lp_build_unsigned_norm_to_float(struct gallivm_state *gallivm, assert(dst_type.floating); - /* Special-case int8->float, though most cases could be handled - * this way: - */ - if (src_width == 8) { - scale = 1.0/255.0; + mantissa = lp_mantissa(dst_type); + + if (src_width <= (mantissa + 1)) { + /* + * The source width matches fits what can be represented in floating + * point (i.e., mantissa + 1 bits). So do a straight multiplication + * followed by casting. No further rounding is necessary. + */ + + scale = 1.0/(double)((1ULL << src_width) - 1); res = LLVMBuildSIToFP(builder, src, vec_type, ""); res = LLVMBuildFMul(builder, res, lp_build_const_vec(gallivm, dst_type, scale), ""); return res; } + else { + /* + * The source width exceeds what can be represented in floating + * point. So truncate the incoming values. + */ - mantissa = lp_mantissa(dst_type); - - n = MIN2(mantissa, src_width); + n = MIN2(mantissa, src_width); - ubound = ((unsigned long long)1 << n); - mask = ubound - 1; - scale = (double)ubound/mask; - bias = (double)((unsigned long long)1 << (mantissa - n)); + ubound = ((unsigned long long)1 << n); + mask = ubound - 1; + scale = (double)ubound/mask; + bias = (double)((unsigned long long)1 << (mantissa - n)); - res = src; + res = src; - if(src_width > mantissa) { - int shift = src_width - mantissa; - res = LLVMBuildLShr(builder, res, - lp_build_const_int_vec(gallivm, dst_type, shift), ""); - } + if (src_width > mantissa) { + int shift = src_width - mantissa; + res = LLVMBuildLShr(builder, res, + lp_build_const_int_vec(gallivm, dst_type, shift), ""); + } - bias_ = lp_build_const_vec(gallivm, dst_type, bias); + bias_ = lp_build_const_vec(gallivm, dst_type, bias); - res = LLVMBuildOr(builder, - res, - LLVMBuildBitCast(builder, bias_, int_vec_type, ""), ""); + res = LLVMBuildOr(builder, + res, + LLVMBuildBitCast(builder, bias_, int_vec_type, ""), ""); - res = LLVMBuildBitCast(builder, res, vec_type, ""); + res = LLVMBuildBitCast(builder, res, vec_type, ""); - res = LLVMBuildFSub(builder, res, bias_, ""); - res = LLVMBuildFMul(builder, res, lp_build_const_vec(gallivm, dst_type, scale), ""); + res = LLVMBuildFSub(builder, res, bias_, ""); + res = LLVMBuildFMul(builder, res, lp_build_const_vec(gallivm, dst_type, scale), ""); + } return res; } diff --git a/src/gallium/auxiliary/gallivm/lp_bld_init.c b/src/gallium/auxiliary/gallivm/lp_bld_init.c index 7504cb5cf2f..45addee8fab 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_init.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_init.c @@ -222,11 +222,12 @@ free_gallivm_state(struct gallivm_state *gallivm) static boolean init_gallivm_state(struct gallivm_state *gallivm) { - assert(gallivm_initialized); assert(!gallivm->context); assert(!gallivm->module); assert(!gallivm->provider); + lp_build_init(); + gallivm->context = LLVMContextCreate(); if (!gallivm->context) goto fail; @@ -387,6 +388,9 @@ gallivm_garbage_collect(struct gallivm_state *gallivm) void lp_build_init(void) { + if (gallivm_initialized) + return; + #ifdef DEBUG gallivm_debug = debug_get_option_gallivm_debug(); #endif diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h b/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h index 2ef02160f23..960068c494d 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h @@ -82,6 +82,10 @@ struct pb_manager */ void (*flush)( struct pb_manager *mgr ); + + boolean + (*is_buffer_busy)( struct pb_manager *mgr, + struct pb_buffer *buf ); }; diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c index a6eb4039621..25accefa8d6 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c @@ -227,8 +227,6 @@ pb_cache_is_buffer_compat(struct pb_cache_buffer *buf, pb_size size, const struct pb_desc *desc) { - void *map; - if(buf->base.base.size < size) return 0; @@ -242,13 +240,18 @@ pb_cache_is_buffer_compat(struct pb_cache_buffer *buf, if(!pb_check_usage(desc->usage, buf->base.base.usage)) return 0; - map = pb_map(buf->buffer, PB_USAGE_DONTBLOCK, NULL); - if (!map) { - return -1; + if (buf->mgr->provider->is_buffer_busy) { + if (buf->mgr->provider->is_buffer_busy(buf->mgr->provider, buf->buffer)) + return -1; + } else { + void *ptr = pb_map(buf->buffer, PB_USAGE_DONTBLOCK, NULL); + + if (!ptr) + return -1; + + pb_unmap(buf->buffer); } - pb_unmap(buf->buffer); - return 1; } diff --git a/src/gallium/auxiliary/rtasm/rtasm_x86sse.c b/src/gallium/auxiliary/rtasm/rtasm_x86sse.c index 75b0f6a68ea..b03dd3a0cf8 100644 --- a/src/gallium/auxiliary/rtasm/rtasm_x86sse.c +++ b/src/gallium/auxiliary/rtasm/rtasm_x86sse.c @@ -2132,7 +2132,8 @@ struct x86_reg x86_fn_arg( struct x86_function *p, return x86_make_disp(x86_make_reg(file_REG32, reg_SP), p->stack_offset + arg * 4); /* ??? */ default: - abort(); + assert(0 && "Unexpected x86 target ABI in x86_fn_arg"); + return x86_make_reg(file_REG32, reg_CX); /* not used / silence warning */ } } diff --git a/src/gallium/auxiliary/tgsi/tgsi_build.c b/src/gallium/auxiliary/tgsi/tgsi_build.c index 16a205f2068..d2cb98e84af 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_build.c +++ b/src/gallium/auxiliary/tgsi/tgsi_build.c @@ -26,6 +26,7 @@ **************************************************************************/ #include "util/u_debug.h" +#include "pipe/p_format.h" #include "pipe/p_shader_tokens.h" #include "tgsi_build.h" #include "tgsi_parse.h" @@ -226,6 +227,45 @@ tgsi_build_declaration_semantic( return ds; } + +static struct tgsi_declaration_resource +tgsi_default_declaration_resource(void) +{ + struct tgsi_declaration_resource declaration_resource; + + declaration_resource.Resource = TGSI_TEXTURE_UNKNOWN; + declaration_resource.ReturnTypeX = PIPE_TYPE_UNORM; + declaration_resource.ReturnTypeY = PIPE_TYPE_UNORM; + declaration_resource.ReturnTypeZ = PIPE_TYPE_UNORM; + declaration_resource.ReturnTypeW = PIPE_TYPE_UNORM; + + return declaration_resource; +} + +static struct tgsi_declaration_resource +tgsi_build_declaration_resource(unsigned texture, + unsigned return_type_x, + unsigned return_type_y, + unsigned return_type_z, + unsigned return_type_w, + struct tgsi_declaration *declaration, + struct tgsi_header *header) +{ + struct tgsi_declaration_resource declaration_resource; + + declaration_resource = tgsi_default_declaration_resource(); + declaration_resource.Resource = texture; + declaration_resource.ReturnTypeX = return_type_x; + declaration_resource.ReturnTypeY = return_type_y; + declaration_resource.ReturnTypeZ = return_type_z; + declaration_resource.ReturnTypeW = return_type_w; + + declaration_grow(declaration, header); + + return declaration_resource; +} + + struct tgsi_full_declaration tgsi_default_full_declaration( void ) { @@ -235,6 +275,7 @@ tgsi_default_full_declaration( void ) full_declaration.Range = tgsi_default_declaration_range(); full_declaration.Semantic = tgsi_default_declaration_semantic(); full_declaration.ImmediateData.u = NULL; + full_declaration.Resource = tgsi_default_declaration_resource(); return full_declaration; } @@ -324,6 +365,24 @@ tgsi_build_full_declaration( } } + if (full_decl->Declaration.File == TGSI_FILE_RESOURCE) { + struct tgsi_declaration_resource *dr; + + if (maxsize <= size) { + return 0; + } + dr = (struct tgsi_declaration_resource *)&tokens[size]; + size++; + + *dr = tgsi_build_declaration_resource(full_decl->Resource.Resource, + full_decl->Resource.ReturnTypeX, + full_decl->Resource.ReturnTypeY, + full_decl->Resource.ReturnTypeZ, + full_decl->Resource.ReturnTypeW, + declaration, + header); + } + return size; } diff --git a/src/gallium/auxiliary/tgsi/tgsi_dump.c b/src/gallium/auxiliary/tgsi/tgsi_dump.c index 82cd8eaa969..c12662076b1 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_dump.c +++ b/src/gallium/auxiliary/tgsi/tgsi_dump.c @@ -104,7 +104,8 @@ tgsi_file_names[TGSI_FILE_COUNT] = "PRED", "SV", "IMMX", - "TEMPX" + "TEMPX", + "RES" }; static const char *interpolate_names[] = @@ -157,7 +158,9 @@ tgsi_texture_names[TGSI_TEXTURE_COUNT] = "RECT", "SHADOW1D", "SHADOW2D", - "SHADOWRECT" + "SHADOWRECT", + "1DARRAY", + "2DARRAY" }; const char *tgsi_property_names[TGSI_PROPERTY_COUNT] = @@ -170,6 +173,15 @@ const char *tgsi_property_names[TGSI_PROPERTY_COUNT] = "FS_COLOR0_WRITES_ALL_CBUFS", }; +static const char *tgsi_type_names[] = +{ + "UNORM", + "SNORM", + "SINT", + "UINT", + "FLOAT" +}; + const char *tgsi_primitive_names[PIPE_PRIM_MAX] = { "POINTS", @@ -393,6 +405,26 @@ iter_declaration( } } + if (decl->Declaration.File == TGSI_FILE_RESOURCE) { + TXT(", "); + ENM(decl->Resource.Resource, tgsi_texture_names); + TXT(", "); + if ((decl->Resource.ReturnTypeX == decl->Resource.ReturnTypeY) && + (decl->Resource.ReturnTypeX == decl->Resource.ReturnTypeZ) && + (decl->Resource.ReturnTypeX == decl->Resource.ReturnTypeW)) { + ENM(decl->Resource.ReturnTypeX, tgsi_type_names); + } else { + ENM(decl->Resource.ReturnTypeX, tgsi_type_names); + TXT(", "); + ENM(decl->Resource.ReturnTypeY, tgsi_type_names); + TXT(", "); + ENM(decl->Resource.ReturnTypeZ, tgsi_type_names); + TXT(", "); + ENM(decl->Resource.ReturnTypeW, tgsi_type_names); + } + + } + if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT && decl->Declaration.File == TGSI_FILE_INPUT) { diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.c b/src/gallium/auxiliary/tgsi/tgsi_exec.c index 35b27423513..cbb090b2803 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_exec.c +++ b/src/gallium/auxiliary/tgsi/tgsi_exec.c @@ -1750,6 +1750,36 @@ exec_tex(struct tgsi_exec_machine *mach, &r[0], &r[1], &r[2], &r[3]); /* outputs */ break; + case TGSI_TEXTURE_1D_ARRAY: + FETCH(&r[0], 0, CHAN_X); + FETCH(&r[1], 0, CHAN_Y); + + if (modifier == TEX_MODIFIER_PROJECTED) { + micro_div(&r[0], &r[0], &r[3]); + } + + fetch_texel(mach->Samplers[unit], + &r[0], &r[1], &r[2], lod, /* S, T, P, LOD */ + control, + &r[0], &r[1], &r[2], &r[3]); /* outputs */ + break; + + case TGSI_TEXTURE_2D_ARRAY: + FETCH(&r[0], 0, CHAN_X); + FETCH(&r[1], 0, CHAN_Y); + FETCH(&r[2], 0, CHAN_Z); + + if (modifier == TEX_MODIFIER_PROJECTED) { + micro_div(&r[0], &r[0], &r[3]); + micro_div(&r[1], &r[1], &r[3]); + } + + fetch_texel(mach->Samplers[unit], + &r[0], &r[1], &r[2], lod, /* S, T, P, LOD */ + control, + &r[0], &r[1], &r[2], &r[3]); /* outputs */ + break; + case TGSI_TEXTURE_3D: case TGSI_TEXTURE_CUBE: FETCH(&r[0], 0, CHAN_X); @@ -1843,6 +1873,164 @@ exec_txd(struct tgsi_exec_machine *mach, } + +static void +exec_sample(struct tgsi_exec_machine *mach, + const struct tgsi_full_instruction *inst, + uint modifier) +{ + const uint resource_unit = inst->Src[1].Register.Index; + const uint sampler_unit = inst->Src[2].Register.Index; + union tgsi_exec_channel r[4]; + const union tgsi_exec_channel *lod = &ZeroVec; + enum tgsi_sampler_control control; + uint chan; + + if (modifier != TEX_MODIFIER_NONE) { + if (modifier == TEX_MODIFIER_LOD_BIAS) + FETCH(&r[3], 3, CHAN_X); + else /*TEX_MODIFIER_LOD*/ + FETCH(&r[3], 0, CHAN_W); + + if (modifier != TEX_MODIFIER_PROJECTED) { + lod = &r[3]; + } + } + + if (modifier == TEX_MODIFIER_EXPLICIT_LOD) { + control = tgsi_sampler_lod_explicit; + } else { + control = tgsi_sampler_lod_bias; + } + + switch (mach->Resources[resource_unit].Resource) { + case TGSI_TEXTURE_1D: + case TGSI_TEXTURE_SHADOW1D: + FETCH(&r[0], 0, CHAN_X); + + if (modifier == TEX_MODIFIER_PROJECTED) { + micro_div(&r[0], &r[0], &r[3]); + } + + fetch_texel(mach->Samplers[sampler_unit], + &r[0], &ZeroVec, &ZeroVec, lod, /* S, T, P, LOD */ + control, + &r[0], &r[1], &r[2], &r[3]); /* R, G, B, A */ + break; + + case TGSI_TEXTURE_2D: + case TGSI_TEXTURE_RECT: + case TGSI_TEXTURE_SHADOW2D: + case TGSI_TEXTURE_SHADOWRECT: + FETCH(&r[0], 0, CHAN_X); + FETCH(&r[1], 0, CHAN_Y); + FETCH(&r[2], 0, CHAN_Z); + + if (modifier == TEX_MODIFIER_PROJECTED) { + micro_div(&r[0], &r[0], &r[3]); + micro_div(&r[1], &r[1], &r[3]); + micro_div(&r[2], &r[2], &r[3]); + } + + fetch_texel(mach->Samplers[sampler_unit], + &r[0], &r[1], &r[2], lod, /* S, T, P, LOD */ + control, + &r[0], &r[1], &r[2], &r[3]); /* outputs */ + break; + + case TGSI_TEXTURE_3D: + case TGSI_TEXTURE_CUBE: + FETCH(&r[0], 0, CHAN_X); + FETCH(&r[1], 0, CHAN_Y); + FETCH(&r[2], 0, CHAN_Z); + + if (modifier == TEX_MODIFIER_PROJECTED) { + micro_div(&r[0], &r[0], &r[3]); + micro_div(&r[1], &r[1], &r[3]); + micro_div(&r[2], &r[2], &r[3]); + } + + fetch_texel(mach->Samplers[sampler_unit], + &r[0], &r[1], &r[2], lod, + control, + &r[0], &r[1], &r[2], &r[3]); + break; + + default: + assert(0); + } + + for (chan = 0; chan < NUM_CHANNELS; chan++) { + if (inst->Dst[0].Register.WriteMask & (1 << chan)) { + store_dest(mach, &r[chan], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT); + } + } +} + +static void +exec_sample_d(struct tgsi_exec_machine *mach, + const struct tgsi_full_instruction *inst) +{ + const uint resource_unit = inst->Src[1].Register.Index; + const uint sampler_unit = inst->Src[2].Register.Index; + union tgsi_exec_channel r[4]; + uint chan; + /* + * XXX: This is fake SAMPLE_D -- the derivatives are not taken into account, yet. + */ + + switch (mach->Resources[resource_unit].Resource) { + case TGSI_TEXTURE_1D: + case TGSI_TEXTURE_SHADOW1D: + + FETCH(&r[0], 0, CHAN_X); + + fetch_texel(mach->Samplers[sampler_unit], + &r[0], &ZeroVec, &ZeroVec, &ZeroVec, /* S, T, P, BIAS */ + tgsi_sampler_lod_bias, + &r[0], &r[1], &r[2], &r[3]); /* R, G, B, A */ + break; + + case TGSI_TEXTURE_2D: + case TGSI_TEXTURE_RECT: + case TGSI_TEXTURE_SHADOW2D: + case TGSI_TEXTURE_SHADOWRECT: + + FETCH(&r[0], 0, CHAN_X); + FETCH(&r[1], 0, CHAN_Y); + FETCH(&r[2], 0, CHAN_Z); + + fetch_texel(mach->Samplers[sampler_unit], + &r[0], &r[1], &r[2], &ZeroVec, /* inputs */ + tgsi_sampler_lod_bias, + &r[0], &r[1], &r[2], &r[3]); /* outputs */ + break; + + case TGSI_TEXTURE_3D: + case TGSI_TEXTURE_CUBE: + + FETCH(&r[0], 0, CHAN_X); + FETCH(&r[1], 0, CHAN_Y); + FETCH(&r[2], 0, CHAN_Z); + + fetch_texel(mach->Samplers[sampler_unit], + &r[0], &r[1], &r[2], &ZeroVec, + tgsi_sampler_lod_bias, + &r[0], &r[1], &r[2], &r[3]); + break; + + default: + assert(0); + } + + for (chan = 0; chan < NUM_CHANNELS; chan++) { + if (inst->Dst[0].Register.WriteMask & (1 << chan)) { + store_dest(mach, &r[chan], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT); + } + } +} + + /** * Evaluate a constant-valued coefficient at the position of the * current quad. @@ -1914,6 +2102,11 @@ static void exec_declaration(struct tgsi_exec_machine *mach, const struct tgsi_full_declaration *decl) { + if (decl->Declaration.File == TGSI_FILE_RESOURCE) { + mach->Resources[decl->Range.First] = decl->Resource; + return; + } + if (mach->Processor == TGSI_PROCESSOR_FRAGMENT) { if (decl->Declaration.File == TGSI_FILE_INPUT) { uint first, last, mask; @@ -3688,6 +3881,54 @@ exec_instruction( exec_endswitch(mach); break; + case TGSI_OPCODE_LOAD: + assert(0); + break; + + case TGSI_OPCODE_LOAD_MS: + assert(0); + break; + + case TGSI_OPCODE_SAMPLE: + exec_sample(mach, inst, TEX_MODIFIER_NONE); + break; + + case TGSI_OPCODE_SAMPLE_B: + exec_sample(mach, inst, TEX_MODIFIER_LOD_BIAS); + break; + + case TGSI_OPCODE_SAMPLE_C: + exec_sample(mach, inst, TEX_MODIFIER_NONE); + break; + + case TGSI_OPCODE_SAMPLE_C_LZ: + exec_sample(mach, inst, TEX_MODIFIER_LOD_BIAS); + break; + + case TGSI_OPCODE_SAMPLE_D: + exec_sample_d(mach, inst); + break; + + case TGSI_OPCODE_SAMPLE_L: + exec_sample(mach, inst, TEX_MODIFIER_EXPLICIT_LOD); + break; + + case TGSI_OPCODE_GATHER4: + assert(0); + break; + + case TGSI_OPCODE_RESINFO: + assert(0); + break; + + case TGSI_OPCODE_SAMPLE_POS: + assert(0); + break; + + case TGSI_OPCODE_SAMPLE_INFO: + assert(0); + break; + default: assert( 0 ); } diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.h b/src/gallium/auxiliary/tgsi/tgsi_exec.h index 6c204c73714..4a423b5bb4e 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_exec.h +++ b/src/gallium/auxiliary/tgsi/tgsi_exec.h @@ -308,6 +308,7 @@ struct tgsi_exec_machine struct tgsi_full_declaration *Declarations; uint NumDeclarations; + struct tgsi_declaration_resource Resources[PIPE_MAX_SHADER_RESOURCES]; }; struct tgsi_exec_machine * diff --git a/src/gallium/auxiliary/tgsi/tgsi_info.c b/src/gallium/auxiliary/tgsi/tgsi_info.c index e59e964ffa7..14ed56a1f6a 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_info.c +++ b/src/gallium/auxiliary/tgsi/tgsi_info.c @@ -175,7 +175,20 @@ static const struct tgsi_opcode_info opcode_info[TGSI_OPCODE_LAST] = { 0, 1, 0, 0, 0, 0, "SWITCH", TGSI_OPCODE_SWITCH }, { 0, 1, 0, 0, 0, 0, "CASE", TGSI_OPCODE_CASE }, { 0, 0, 0, 0, 0, 0, "DEFAULT", TGSI_OPCODE_DEFAULT }, - { 0, 0, 0, 0, 0, 0, "ENDSWITCH", TGSI_OPCODE_ENDSWITCH } + { 0, 0, 0, 0, 0, 0, "ENDSWITCH", TGSI_OPCODE_ENDSWITCH }, + + { 1, 2, 0, 0, 0, 0, "LOAD", TGSI_OPCODE_LOAD }, + { 1, 2, 0, 0, 0, 0, "LOAD_MS", TGSI_OPCODE_LOAD_MS }, + { 1, 3, 0, 0, 0, 0, "SAMPLE", TGSI_OPCODE_SAMPLE }, + { 1, 4, 0, 0, 0, 0, "SAMPLE_B", TGSI_OPCODE_SAMPLE_B }, + { 1, 4, 0, 0, 0, 0, "SAMPLE_C", TGSI_OPCODE_SAMPLE_C }, + { 1, 4, 0, 0, 0, 0, "SAMPLE_C_LZ", TGSI_OPCODE_SAMPLE_C_LZ }, + { 1, 5, 0, 0, 0, 0, "SAMPLE_D", TGSI_OPCODE_SAMPLE_D }, + { 1, 3, 0, 0, 0, 0, "SAMPLE_L", TGSI_OPCODE_SAMPLE_L }, + { 1, 3, 0, 0, 0, 0, "GATHER4", TGSI_OPCODE_GATHER4 }, + { 1, 2, 0, 0, 0, 0, "RESINFO", TGSI_OPCODE_RESINFO }, + { 1, 2, 0, 0, 0, 0, "SAMPLE_POS", TGSI_OPCODE_SAMPLE_POS }, + { 1, 2, 0, 0, 0, 0, "SAMPLE_INFO", TGSI_OPCODE_SAMPLE_INFO }, }; const struct tgsi_opcode_info * diff --git a/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h b/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h index b3123ed016d..b5d4504425b 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h +++ b/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h @@ -168,6 +168,19 @@ OP01(CASE) OP00(DEFAULT) OP00(ENDSWITCH) +OP12(LOAD) +OP12(LOAD_MS) +OP13(SAMPLE) +OP14(SAMPLE_B) +OP14(SAMPLE_C) +OP14(SAMPLE_C_LZ) +OP15(SAMPLE_D) +OP13(SAMPLE_L) +OP13(GATHER4) +OP12(RESINFO) +OP13(SAMPLE_POS) +OP12(SAMPLE_INFO) + #undef OP00 #undef OP01 @@ -180,6 +193,10 @@ OP00(ENDSWITCH) #undef OP14 #endif +#ifdef OP15 +#undef OP15 +#endif + #undef OP00_LBL #undef OP01_LBL diff --git a/src/gallium/auxiliary/tgsi/tgsi_parse.c b/src/gallium/auxiliary/tgsi/tgsi_parse.c index 1891203abe1..fb36f9de32d 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_parse.c +++ b/src/gallium/auxiliary/tgsi/tgsi_parse.c @@ -128,6 +128,10 @@ tgsi_parse_token( } } + if (decl->Declaration.File == TGSI_FILE_RESOURCE) { + next_token(ctx, &decl->Resource); + } + break; } diff --git a/src/gallium/auxiliary/tgsi/tgsi_parse.h b/src/gallium/auxiliary/tgsi/tgsi_parse.h index 2aafa2a6e83..b7a3c9bc0e6 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_parse.h +++ b/src/gallium/auxiliary/tgsi/tgsi_parse.h @@ -69,6 +69,7 @@ struct tgsi_full_declaration struct tgsi_declaration_dimension Dim; struct tgsi_declaration_semantic Semantic; struct tgsi_immediate_array_data ImmediateData; + struct tgsi_declaration_resource Resource; }; struct tgsi_full_immediate @@ -84,7 +85,7 @@ struct tgsi_full_property }; #define TGSI_FULL_MAX_DST_REGISTERS 2 -#define TGSI_FULL_MAX_SRC_REGISTERS 4 /* TXD has 4 */ +#define TGSI_FULL_MAX_SRC_REGISTERS 5 /* SAMPLE_D has 5 */ struct tgsi_full_instruction { diff --git a/src/gallium/auxiliary/tgsi/tgsi_sanity.c b/src/gallium/auxiliary/tgsi/tgsi_sanity.c index acbff103efe..509c5346837 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_sanity.c +++ b/src/gallium/auxiliary/tgsi/tgsi_sanity.c @@ -258,7 +258,8 @@ static const char *file_names[TGSI_FILE_COUNT] = "PRED", "SV", "IMMX", - "TEMPX" + "TEMPX", + "RES" }; static boolean diff --git a/src/gallium/auxiliary/tgsi/tgsi_sse2.c b/src/gallium/auxiliary/tgsi/tgsi_sse2.c index 3f2cda860e0..92ba8b8f033 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_sse2.c +++ b/src/gallium/auxiliary/tgsi/tgsi_sse2.c @@ -1514,6 +1514,7 @@ emit_tex( struct x86_function *func, break; case TGSI_TEXTURE_2D: case TGSI_TEXTURE_RECT: + case TGSI_TEXTURE_1D_ARRAY: count = 2; break; case TGSI_TEXTURE_SHADOW1D: @@ -1521,6 +1522,7 @@ emit_tex( struct x86_function *func, case TGSI_TEXTURE_SHADOWRECT: case TGSI_TEXTURE_3D: case TGSI_TEXTURE_CUBE: + case TGSI_TEXTURE_2D_ARRAY: count = 3; break; default: diff --git a/src/gallium/auxiliary/tgsi/tgsi_text.c b/src/gallium/auxiliary/tgsi/tgsi_text.c index 819b0725a1f..1eac762e6e5 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_text.c +++ b/src/gallium/auxiliary/tgsi/tgsi_text.c @@ -283,7 +283,8 @@ static const char *file_names[TGSI_FILE_COUNT] = "PRED", "SV", "IMMX", - "TEMPX" + "TEMPX", + "RES" }; static boolean @@ -828,6 +829,15 @@ static const char *texture_names[TGSI_TEXTURE_COUNT] = "SHADOWRECT" }; +static const char *type_names[] = +{ + "UNORM", + "SNORM", + "SINT", + "UINT", + "FLOAT" +}; + static boolean match_inst_mnemonic(const char **pcur, const struct tgsi_opcode_info *info) @@ -1104,42 +1114,113 @@ static boolean parse_declaration( struct translate_ctx *ctx ) cur = ctx->cur; eat_opt_white( &cur ); if (*cur == ',' && !is_vs_input) { - uint i; + uint i, j; cur++; eat_opt_white( &cur ); - for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) { - if (str_match_no_case( &cur, semantic_names[i] )) { - const char *cur2 = cur; - uint index; - - if (is_digit_alpha_underscore( cur )) - continue; - eat_opt_white( &cur2 ); - if (*cur2 == '[') { - cur2++; - eat_opt_white( &cur2 ); - if (!parse_uint( &cur2, &index )) { - report_error( ctx, "Expected literal integer" ); + if (file == TGSI_FILE_RESOURCE) { + for (i = 0; i < TGSI_TEXTURE_COUNT; i++) { + if (str_match_no_case(&cur, texture_names[i])) { + if (!is_digit_alpha_underscore(cur)) { + decl.Resource.Resource = i; + break; + } + } + } + if (i == TGSI_TEXTURE_COUNT) { + report_error(ctx, "Expected texture target"); + return FALSE; + } + eat_opt_white( &cur ); + if (*cur != ',') { + report_error( ctx, "Expected `,'" ); + return FALSE; + } + ++cur; + eat_opt_white( &cur ); + for (j = 0; j < 4; ++j) { + for (i = 0; i < PIPE_TYPE_COUNT; ++i) { + if (str_match_no_case(&cur, type_names[i])) { + if (!is_digit_alpha_underscore(cur)) { + switch (j) { + case 0: + decl.Resource.ReturnTypeX = i; + break; + case 1: + decl.Resource.ReturnTypeY = i; + break; + case 2: + decl.Resource.ReturnTypeZ = i; + break; + case 3: + decl.Resource.ReturnTypeW = i; + break; + default: + assert(0); + } + break; + } + } + } + if (i == PIPE_TYPE_COUNT) { + if (j == 0 || j > 2) { + report_error(ctx, "Expected type name"); return FALSE; } + break; + } else { + const char *cur2 = cur; eat_opt_white( &cur2 ); - if (*cur2 != ']') { - report_error( ctx, "Expected `]'" ); - return FALSE; + if (*cur2 == ',') { + cur2++; + eat_opt_white( &cur2 ); + cur = cur2; + continue; + } else + break; + } + } + if (j < 4) { + decl.Resource.ReturnTypeY = + decl.Resource.ReturnTypeZ = + decl.Resource.ReturnTypeW = + decl.Resource.ReturnTypeX; + } + ctx->cur = cur; + } else { + for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) { + if (str_match_no_case( &cur, semantic_names[i] )) { + const char *cur2 = cur; + uint index; + + if (is_digit_alpha_underscore( cur )) + continue; + eat_opt_white( &cur2 ); + if (*cur2 == '[') { + cur2++; + eat_opt_white( &cur2 ); + if (!parse_uint( &cur2, &index )) { + report_error( ctx, "Expected literal integer" ); + return FALSE; + } + eat_opt_white( &cur2 ); + if (*cur2 != ']') { + report_error( ctx, "Expected `]'" ); + return FALSE; + } + cur2++; + + decl.Semantic.Index = index; + + cur = cur2; } - cur2++; - decl.Semantic.Index = index; + decl.Declaration.Semantic = 1; + decl.Semantic.Name = i; - cur = cur2; + ctx->cur = cur; + break; } - - decl.Declaration.Semantic = 1; - decl.Semantic.Name = i; - - ctx->cur = cur; - break; } } } else if (is_imm_array) { diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.c b/src/gallium/auxiliary/tgsi/tgsi_ureg.c index 02de12d77d5..4564ab81f99 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_ureg.c +++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.c @@ -1,6 +1,6 @@ /************************************************************************** * - * Copyright 2009 VMware, Inc. + * Copyright 2009-2010 VMware, Inc. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -47,6 +47,7 @@ union tgsi_any_token { struct tgsi_declaration_range decl_range; struct tgsi_declaration_dimension decl_dim; struct tgsi_declaration_semantic decl_semantic; + struct tgsi_declaration_resource decl_resource; struct tgsi_immediate imm; union tgsi_immediate_data imm_data; struct tgsi_instruction insn; @@ -137,6 +138,16 @@ struct ureg_program struct ureg_src sampler[PIPE_MAX_SAMPLERS]; unsigned nr_samplers; + struct { + unsigned index; + unsigned target; + unsigned return_type_x; + unsigned return_type_y; + unsigned return_type_z; + unsigned return_type_w; + } resource[PIPE_MAX_SHADER_RESOURCES]; + unsigned nr_resources; + unsigned temps_active[UREG_MAX_TEMP / 32]; unsigned nr_temps; @@ -578,6 +589,41 @@ struct ureg_src ureg_DECL_sampler( struct ureg_program *ureg, return ureg->sampler[0]; } +/* + * Allocate a new shader resource. + */ +struct ureg_src +ureg_DECL_resource(struct ureg_program *ureg, + unsigned index, + unsigned target, + unsigned return_type_x, + unsigned return_type_y, + unsigned return_type_z, + unsigned return_type_w) +{ + struct ureg_src reg = ureg_src_register(TGSI_FILE_RESOURCE, index); + uint i; + + for (i = 0; i < ureg->nr_resources; i++) { + if (ureg->resource[i].index == index) { + return reg; + } + } + + if (i < PIPE_MAX_SHADER_RESOURCES) { + ureg->resource[i].index = index; + ureg->resource[i].target = target; + ureg->resource[i].return_type_x = return_type_x; + ureg->resource[i].return_type_y = return_type_y; + ureg->resource[i].return_type_z = return_type_z; + ureg->resource[i].return_type_w = return_type_w; + ureg->nr_resources++; + return reg; + } + + assert(0); + return reg; +} static int match_or_expand_immediate( const unsigned *v, @@ -821,9 +867,10 @@ ureg_emit_dst( struct ureg_program *ureg, assert(dst.File != TGSI_FILE_CONSTANT); assert(dst.File != TGSI_FILE_INPUT); assert(dst.File != TGSI_FILE_SAMPLER); + assert(dst.File != TGSI_FILE_RESOURCE); assert(dst.File != TGSI_FILE_IMMEDIATE); assert(dst.File < TGSI_FILE_COUNT); - + out[n].value = 0; out[n].dst.File = dst.File; out[n].dst.WriteMask = dst.WriteMask; @@ -1206,6 +1253,36 @@ emit_decl_range2D(struct ureg_program *ureg, } static void +emit_decl_resource(struct ureg_program *ureg, + unsigned index, + unsigned target, + unsigned return_type_x, + unsigned return_type_y, + unsigned return_type_z, + unsigned return_type_w ) +{ + union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 3); + + out[0].value = 0; + out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION; + out[0].decl.NrTokens = 3; + out[0].decl.File = TGSI_FILE_RESOURCE; + out[0].decl.UsageMask = 0xf; + out[0].decl.Interpolate = TGSI_INTERPOLATE_CONSTANT; + + out[1].value = 0; + out[1].decl_range.First = index; + out[1].decl_range.Last = index; + + out[2].value = 0; + out[2].decl_resource.Resource = target; + out[2].decl_resource.ReturnTypeX = return_type_x; + out[2].decl_resource.ReturnTypeY = return_type_y; + out[2].decl_resource.ReturnTypeZ = return_type_z; + out[2].decl_resource.ReturnTypeW = return_type_w; +} + +static void emit_immediate( struct ureg_program *ureg, const unsigned *v, unsigned type ) @@ -1341,6 +1418,16 @@ static void emit_decls( struct ureg_program *ureg ) ureg->sampler[i].Index, 1 ); } + for (i = 0; i < ureg->nr_resources; i++) { + emit_decl_resource(ureg, + ureg->resource[i].index, + ureg->resource[i].target, + ureg->resource[i].return_type_x, + ureg->resource[i].return_type_y, + ureg->resource[i].return_type_z, + ureg->resource[i].return_type_w); + } + if (ureg->const_decls.nr_constant_ranges) { for (i = 0; i < ureg->const_decls.nr_constant_ranges; i++) { emit_decl_range(ureg, diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.h b/src/gallium/auxiliary/tgsi/tgsi_ureg.h index 807128a5e52..b8d193f3f89 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_ureg.h +++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.h @@ -270,6 +270,15 @@ struct ureg_src ureg_DECL_sampler( struct ureg_program *, unsigned index ); +struct ureg_src +ureg_DECL_resource(struct ureg_program *, + unsigned index, + unsigned target, + unsigned return_type_x, + unsigned return_type_y, + unsigned return_type_z, + unsigned return_type_w ); + static INLINE struct ureg_src ureg_imm4f( struct ureg_program *ureg, @@ -733,6 +742,66 @@ static INLINE void ureg_##op( struct ureg_program *ureg, \ } +#define OP14( op ) \ +static INLINE void ureg_##op( struct ureg_program *ureg, \ + struct ureg_dst dst, \ + struct ureg_src src0, \ + struct ureg_src src1, \ + struct ureg_src src2, \ + struct ureg_src src3 ) \ +{ \ + unsigned opcode = TGSI_OPCODE_##op; \ + unsigned insn = ureg_emit_insn(ureg, \ + opcode, \ + dst.Saturate, \ + dst.Predicate, \ + dst.PredNegate, \ + dst.PredSwizzleX, \ + dst.PredSwizzleY, \ + dst.PredSwizzleZ, \ + dst.PredSwizzleW, \ + 1, \ + 4).insn_token; \ + ureg_emit_dst( ureg, dst ); \ + ureg_emit_src( ureg, src0 ); \ + ureg_emit_src( ureg, src1 ); \ + ureg_emit_src( ureg, src2 ); \ + ureg_emit_src( ureg, src3 ); \ + ureg_fixup_insn_size( ureg, insn ); \ +} + + +#define OP15( op ) \ +static INLINE void ureg_##op( struct ureg_program *ureg, \ + struct ureg_dst dst, \ + struct ureg_src src0, \ + struct ureg_src src1, \ + struct ureg_src src2, \ + struct ureg_src src3, \ + struct ureg_src src4 ) \ +{ \ + unsigned opcode = TGSI_OPCODE_##op; \ + unsigned insn = ureg_emit_insn(ureg, \ + opcode, \ + dst.Saturate, \ + dst.Predicate, \ + dst.PredNegate, \ + dst.PredSwizzleX, \ + dst.PredSwizzleY, \ + dst.PredSwizzleZ, \ + dst.PredSwizzleW, \ + 1, \ + 5).insn_token; \ + ureg_emit_dst( ureg, dst ); \ + ureg_emit_src( ureg, src0 ); \ + ureg_emit_src( ureg, src1 ); \ + ureg_emit_src( ureg, src2 ); \ + ureg_emit_src( ureg, src3 ); \ + ureg_emit_src( ureg, src4 ); \ + ureg_fixup_insn_size( ureg, insn ); \ +} + + /* Use a template include to generate a correctly-typed ureg_OP() * function for each TGSI opcode: */ diff --git a/src/gallium/auxiliary/tgsi/tgsi_util.c b/src/gallium/auxiliary/tgsi/tgsi_util.c index 08e7e89bd67..aa9a886d4a9 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_util.c +++ b/src/gallium/auxiliary/tgsi/tgsi_util.c @@ -280,7 +280,12 @@ tgsi_util_get_inst_usage_mask(const struct tgsi_full_instruction *inst, case TGSI_TEXTURE_CUBE: read_mask = TGSI_WRITEMASK_XYZ; break; - + case TGSI_TEXTURE_1D_ARRAY: + read_mask = TGSI_WRITEMASK_XY; + break; + case TGSI_TEXTURE_2D_ARRAY: + read_mask = TGSI_WRITEMASK_XYZ; + break; default: assert(0); read_mask = 0; diff --git a/src/gallium/auxiliary/translate/translate_cache.c b/src/gallium/auxiliary/translate/translate_cache.c index d8069a149cf..3f1ecb630f2 100644 --- a/src/gallium/auxiliary/translate/translate_cache.c +++ b/src/gallium/auxiliary/translate/translate_cache.c @@ -40,6 +40,10 @@ struct translate_cache { struct translate_cache * translate_cache_create( void ) { struct translate_cache *cache = MALLOC_STRUCT(translate_cache); + if (cache == NULL) { + return NULL; + } + cache->hash = cso_hash_create(); return cache; } diff --git a/src/gallium/auxiliary/util/dbghelp.h b/src/gallium/auxiliary/util/dbghelp.h new file mode 100644 index 00000000000..bc7c53cf9f2 --- /dev/null +++ b/src/gallium/auxiliary/util/dbghelp.h @@ -0,0 +1,1265 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the w64 mingw-runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#ifndef _DBGHELP_ +#define _DBGHELP_ + +#ifdef _WIN64 +#ifndef _IMAGEHLP64 +#define _IMAGEHLP64 +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define IMAGEAPI DECLSPEC_IMPORT WINAPI +#define DBHLP_DEPRECIATED __declspec(deprecated) + +#define DBHLPAPI IMAGEAPI + +#define IMAGE_SEPARATION (64*1024) + + typedef struct _LOADED_IMAGE { + PSTR ModuleName; + HANDLE hFile; + PUCHAR MappedAddress; +#ifdef _IMAGEHLP64 + PIMAGE_NT_HEADERS64 FileHeader; +#else + PIMAGE_NT_HEADERS32 FileHeader; +#endif + PIMAGE_SECTION_HEADER LastRvaSection; + ULONG NumberOfSections; + PIMAGE_SECTION_HEADER Sections; + ULONG Characteristics; + BOOLEAN fSystemImage; + BOOLEAN fDOSImage; + LIST_ENTRY Links; + ULONG SizeOfImage; + } LOADED_IMAGE,*PLOADED_IMAGE; + +#define MAX_SYM_NAME 2000 + + typedef BOOL (CALLBACK *PFIND_DEBUG_FILE_CALLBACK)(HANDLE FileHandle,PSTR FileName,PVOID CallerData); + typedef BOOL (CALLBACK *PFINDFILEINPATHCALLBACK)(PSTR filename,PVOID context); + typedef BOOL (CALLBACK *PFIND_EXE_FILE_CALLBACK)(HANDLE FileHandle,PSTR FileName,PVOID CallerData); + + typedef BOOL (WINAPI *PSYMBOLSERVERPROC)(LPCSTR,LPCSTR,PVOID,DWORD,DWORD,LPSTR); + typedef BOOL (WINAPI *PSYMBOLSERVEROPENPROC)(VOID); + typedef BOOL (WINAPI *PSYMBOLSERVERCLOSEPROC)(VOID); + typedef BOOL (WINAPI *PSYMBOLSERVERSETOPTIONSPROC)(UINT_PTR,ULONG64); + typedef BOOL (CALLBACK WINAPI *PSYMBOLSERVERCALLBACKPROC)(UINT_PTR action,ULONG64 data,ULONG64 context); + typedef UINT_PTR (WINAPI *PSYMBOLSERVERGETOPTIONSPROC)(); + typedef BOOL (WINAPI *PSYMBOLSERVERPINGPROC)(LPCSTR); + + HANDLE IMAGEAPI FindDebugInfoFile(PSTR FileName,PSTR SymbolPath,PSTR DebugFilePath); + HANDLE IMAGEAPI FindDebugInfoFileEx(PSTR FileName,PSTR SymbolPath,PSTR DebugFilePath,PFIND_DEBUG_FILE_CALLBACK Callback,PVOID CallerData); + BOOL IMAGEAPI SymFindFileInPath(HANDLE hprocess,LPSTR SearchPath,LPSTR FileName,PVOID id,DWORD two,DWORD three,DWORD flags,LPSTR FoundFile,PFINDFILEINPATHCALLBACK callback,PVOID context); + HANDLE IMAGEAPI FindExecutableImage(PSTR FileName,PSTR SymbolPath,PSTR ImageFilePath); + HANDLE IMAGEAPI FindExecutableImageEx(PSTR FileName,PSTR SymbolPath,PSTR ImageFilePath,PFIND_EXE_FILE_CALLBACK Callback,PVOID CallerData); + PIMAGE_NT_HEADERS IMAGEAPI ImageNtHeader(PVOID Base); + PVOID IMAGEAPI ImageDirectoryEntryToDataEx(PVOID Base,BOOLEAN MappedAsImage,USHORT DirectoryEntry,PULONG Size,PIMAGE_SECTION_HEADER *FoundHeader); + PVOID IMAGEAPI ImageDirectoryEntryToData(PVOID Base,BOOLEAN MappedAsImage,USHORT DirectoryEntry,PULONG Size); + PIMAGE_SECTION_HEADER IMAGEAPI ImageRvaToSection(PIMAGE_NT_HEADERS NtHeaders,PVOID Base,ULONG Rva); + PVOID IMAGEAPI ImageRvaToVa(PIMAGE_NT_HEADERS NtHeaders,PVOID Base,ULONG Rva,PIMAGE_SECTION_HEADER *LastRvaSection); + +#define SSRVOPT_CALLBACK 0x0001 +#define SSRVOPT_DWORD 0x0002 +#define SSRVOPT_DWORDPTR 0x0004 +#define SSRVOPT_GUIDPTR 0x0008 +#define SSRVOPT_OLDGUIDPTR 0x0010 +#define SSRVOPT_UNATTENDED 0x0020 +#define SSRVOPT_NOCOPY 0x0040 +#define SSRVOPT_PARENTWIN 0x0080 +#define SSRVOPT_PARAMTYPE 0x0100 +#define SSRVOPT_SECURE 0x0200 +#define SSRVOPT_TRACE 0x0400 +#define SSRVOPT_SETCONTEXT 0x0800 +#define SSRVOPT_PROXY 0x1000 +#define SSRVOPT_DOWNSTREAM_STORE 0x2000 +#define SSRVOPT_RESET ((ULONG_PTR)-1) + +#define SSRVACTION_TRACE 1 +#define SSRVACTION_QUERYCANCEL 2 +#define SSRVACTION_EVENT 3 + +#ifndef _WIN64 + + typedef struct _IMAGE_DEBUG_INFORMATION { + LIST_ENTRY List; + DWORD ReservedSize; + PVOID ReservedMappedBase; + USHORT ReservedMachine; + USHORT ReservedCharacteristics; + DWORD ReservedCheckSum; + DWORD ImageBase; + DWORD SizeOfImage; + DWORD ReservedNumberOfSections; + PIMAGE_SECTION_HEADER ReservedSections; + DWORD ReservedExportedNamesSize; + PSTR ReservedExportedNames; + DWORD ReservedNumberOfFunctionTableEntries; + PIMAGE_FUNCTION_ENTRY ReservedFunctionTableEntries; + DWORD ReservedLowestFunctionStartingAddress; + DWORD ReservedHighestFunctionEndingAddress; + DWORD ReservedNumberOfFpoTableEntries; + PFPO_DATA ReservedFpoTableEntries; + DWORD SizeOfCoffSymbols; + PIMAGE_COFF_SYMBOLS_HEADER CoffSymbols; + DWORD ReservedSizeOfCodeViewSymbols; + PVOID ReservedCodeViewSymbols; + PSTR ImageFilePath; + PSTR ImageFileName; + PSTR ReservedDebugFilePath; + DWORD ReservedTimeDateStamp; + BOOL ReservedRomImage; + PIMAGE_DEBUG_DIRECTORY ReservedDebugDirectory; + DWORD ReservedNumberOfDebugDirectories; + DWORD ReservedOriginalFunctionTableBaseAddress; + DWORD Reserved[2 ]; + } IMAGE_DEBUG_INFORMATION,*PIMAGE_DEBUG_INFORMATION; + + PIMAGE_DEBUG_INFORMATION IMAGEAPI MapDebugInformation(HANDLE FileHandle,PSTR FileName,PSTR SymbolPath,DWORD ImageBase); + BOOL IMAGEAPI UnmapDebugInformation(PIMAGE_DEBUG_INFORMATION DebugInfo); +#endif + + typedef BOOL (CALLBACK *PENUMDIRTREE_CALLBACK)(LPCSTR FilePath,PVOID CallerData); + + BOOL IMAGEAPI SearchTreeForFile(PSTR RootPath,PSTR InputPathName,PSTR OutputPathBuffer); + BOOL IMAGEAPI EnumDirTree(HANDLE hProcess,PSTR RootPath,PSTR InputPathName,PSTR OutputPathBuffer,PENUMDIRTREE_CALLBACK Callback,PVOID CallbackData); + BOOL IMAGEAPI MakeSureDirectoryPathExists(PCSTR DirPath); + +#define UNDNAME_COMPLETE (0x0000) +#define UNDNAME_NO_LEADING_UNDERSCORES (0x0001) +#define UNDNAME_NO_MS_KEYWORDS (0x0002) +#define UNDNAME_NO_FUNCTION_RETURNS (0x0004) +#define UNDNAME_NO_ALLOCATION_MODEL (0x0008) +#define UNDNAME_NO_ALLOCATION_LANGUAGE (0x0010) +#define UNDNAME_NO_MS_THISTYPE (0x0020) +#define UNDNAME_NO_CV_THISTYPE (0x0040) +#define UNDNAME_NO_THISTYPE (0x0060) +#define UNDNAME_NO_ACCESS_SPECIFIERS (0x0080) +#define UNDNAME_NO_THROW_SIGNATURES (0x0100) +#define UNDNAME_NO_MEMBER_TYPE (0x0200) +#define UNDNAME_NO_RETURN_UDT_MODEL (0x0400) +#define UNDNAME_32_BIT_DECODE (0x0800) +#define UNDNAME_NAME_ONLY (0x1000) +#define UNDNAME_NO_ARGUMENTS (0x2000) +#define UNDNAME_NO_SPECIAL_SYMS (0x4000) + + DWORD IMAGEAPI WINAPI UnDecorateSymbolName(PCSTR DecoratedName,PSTR UnDecoratedName,DWORD UndecoratedLength,DWORD Flags); + +#define DBHHEADER_DEBUGDIRS 0x1 + + typedef struct _MODLOAD_DATA { + DWORD ssize; + DWORD ssig; + PVOID data; + DWORD size; + DWORD flags; + } MODLOAD_DATA,*PMODLOAD_DATA; + + typedef enum { + AddrMode1616,AddrMode1632,AddrModeReal,AddrModeFlat + } ADDRESS_MODE; + + typedef struct _tagADDRESS64 { + DWORD64 Offset; + WORD Segment; + ADDRESS_MODE Mode; + } ADDRESS64,*LPADDRESS64; + +#ifdef _IMAGEHLP64 +#define ADDRESS ADDRESS64 +#define LPADDRESS LPADDRESS64 +#else + typedef struct _tagADDRESS { + DWORD Offset; + WORD Segment; + ADDRESS_MODE Mode; + } ADDRESS,*LPADDRESS; + + static __inline void Address32To64(LPADDRESS a32,LPADDRESS64 a64) { + a64->Offset = (ULONG64)(LONG64)(LONG)a32->Offset; + a64->Segment = a32->Segment; + a64->Mode = a32->Mode; + } + + static __inline void Address64To32(LPADDRESS64 a64,LPADDRESS a32) { + a32->Offset = (ULONG)a64->Offset; + a32->Segment = a64->Segment; + a32->Mode = a64->Mode; + } +#endif + + typedef struct _KDHELP64 { + DWORD64 Thread; + DWORD ThCallbackStack; + DWORD ThCallbackBStore; + DWORD NextCallback; + DWORD FramePointer; + DWORD64 KiCallUserMode; + DWORD64 KeUserCallbackDispatcher; + DWORD64 SystemRangeStart; + DWORD64 Reserved[8]; + } KDHELP64,*PKDHELP64; + +#ifdef _IMAGEHLP64 +#define KDHELP KDHELP64 +#define PKDHELP PKDHELP64 +#else + typedef struct _KDHELP { + DWORD Thread; + DWORD ThCallbackStack; + DWORD NextCallback; + DWORD FramePointer; + DWORD KiCallUserMode; + DWORD KeUserCallbackDispatcher; + DWORD SystemRangeStart; + DWORD ThCallbackBStore; + DWORD Reserved[8]; + } KDHELP,*PKDHELP; + + static __inline void KdHelp32To64(PKDHELP p32,PKDHELP64 p64) { + p64->Thread = p32->Thread; + p64->ThCallbackStack = p32->ThCallbackStack; + p64->NextCallback = p32->NextCallback; + p64->FramePointer = p32->FramePointer; + p64->KiCallUserMode = p32->KiCallUserMode; + p64->KeUserCallbackDispatcher = p32->KeUserCallbackDispatcher; + p64->SystemRangeStart = p32->SystemRangeStart; + } +#endif + + typedef struct _tagSTACKFRAME64 { + ADDRESS64 AddrPC; + ADDRESS64 AddrReturn; + ADDRESS64 AddrFrame; + ADDRESS64 AddrStack; + ADDRESS64 AddrBStore; + PVOID FuncTableEntry; + DWORD64 Params[4]; + BOOL Far; + BOOL Virtual; + DWORD64 Reserved[3]; + KDHELP64 KdHelp; + } STACKFRAME64,*LPSTACKFRAME64; + +#ifdef _IMAGEHLP64 +#define STACKFRAME STACKFRAME64 +#define LPSTACKFRAME LPSTACKFRAME64 +#else + typedef struct _tagSTACKFRAME { + ADDRESS AddrPC; + ADDRESS AddrReturn; + ADDRESS AddrFrame; + ADDRESS AddrStack; + PVOID FuncTableEntry; + DWORD Params[4]; + BOOL Far; + BOOL Virtual; + DWORD Reserved[3]; + KDHELP KdHelp; + ADDRESS AddrBStore; + } STACKFRAME,*LPSTACKFRAME; +#endif + + typedef BOOL (WINAPI *PREAD_PROCESS_MEMORY_ROUTINE64)(HANDLE hProcess,DWORD64 qwBaseAddress,PVOID lpBuffer,DWORD nSize,LPDWORD lpNumberOfBytesRead); + typedef PVOID (WINAPI *PFUNCTION_TABLE_ACCESS_ROUTINE64)(HANDLE hProcess,DWORD64 AddrBase); + typedef DWORD64 (WINAPI *PGET_MODULE_BASE_ROUTINE64)(HANDLE hProcess,DWORD64 Address); + typedef DWORD64 (WINAPI *PTRANSLATE_ADDRESS_ROUTINE64)(HANDLE hProcess,HANDLE hThread,LPADDRESS64 lpaddr); + + BOOL IMAGEAPI StackWalk64(DWORD MachineType,HANDLE hProcess,HANDLE hThread,LPSTACKFRAME64 StackFrame,PVOID ContextRecord,PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress); + +#ifdef _IMAGEHLP64 +#define PREAD_PROCESS_MEMORY_ROUTINE PREAD_PROCESS_MEMORY_ROUTINE64 +#define PFUNCTION_TABLE_ACCESS_ROUTINE PFUNCTION_TABLE_ACCESS_ROUTINE64 +#define PGET_MODULE_BASE_ROUTINE PGET_MODULE_BASE_ROUTINE64 +#define PTRANSLATE_ADDRESS_ROUTINE PTRANSLATE_ADDRESS_ROUTINE64 +#define StackWalk StackWalk64 +#else + typedef BOOL (WINAPI *PREAD_PROCESS_MEMORY_ROUTINE)(HANDLE hProcess,DWORD lpBaseAddress,PVOID lpBuffer,DWORD nSize,PDWORD lpNumberOfBytesRead); + typedef PVOID (WINAPI *PFUNCTION_TABLE_ACCESS_ROUTINE)(HANDLE hProcess,DWORD AddrBase); + typedef DWORD (WINAPI *PGET_MODULE_BASE_ROUTINE)(HANDLE hProcess,DWORD Address); + typedef DWORD (WINAPI *PTRANSLATE_ADDRESS_ROUTINE)(HANDLE hProcess,HANDLE hThread,LPADDRESS lpaddr); + + BOOL IMAGEAPI StackWalk(DWORD MachineType,HANDLE hProcess,HANDLE hThread,LPSTACKFRAME StackFrame,PVOID ContextRecord,PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,PTRANSLATE_ADDRESS_ROUTINE TranslateAddress); +#endif + +#define API_VERSION_NUMBER 9 + + typedef struct API_VERSION { + USHORT MajorVersion; + USHORT MinorVersion; + USHORT Revision; + USHORT Reserved; + } API_VERSION,*LPAPI_VERSION; + + LPAPI_VERSION IMAGEAPI ImagehlpApiVersion(VOID); + LPAPI_VERSION IMAGEAPI ImagehlpApiVersionEx(LPAPI_VERSION AppVersion); + DWORD IMAGEAPI GetTimestampForLoadedLibrary(HMODULE Module); + + typedef BOOL (CALLBACK *PSYM_ENUMMODULES_CALLBACK64)(PSTR ModuleName,DWORD64 BaseOfDll,PVOID UserContext); + typedef BOOL (CALLBACK *PSYM_ENUMSYMBOLS_CALLBACK64)(PSTR SymbolName,DWORD64 SymbolAddress,ULONG SymbolSize,PVOID UserContext); + typedef BOOL (CALLBACK *PSYM_ENUMSYMBOLS_CALLBACK64W)(PWSTR SymbolName,DWORD64 SymbolAddress,ULONG SymbolSize,PVOID UserContext); + typedef BOOL (CALLBACK *PENUMLOADED_MODULES_CALLBACK64)(PSTR ModuleName,DWORD64 ModuleBase,ULONG ModuleSize,PVOID UserContext); + typedef BOOL (CALLBACK *PSYMBOL_REGISTERED_CALLBACK64)(HANDLE hProcess,ULONG ActionCode,ULONG64 CallbackData,ULONG64 UserContext); + typedef PVOID (CALLBACK *PSYMBOL_FUNCENTRY_CALLBACK)(HANDLE hProcess,DWORD AddrBase,PVOID UserContext); + typedef PVOID (CALLBACK *PSYMBOL_FUNCENTRY_CALLBACK64)(HANDLE hProcess,ULONG64 AddrBase,ULONG64 UserContext); + +#ifdef _IMAGEHLP64 +#define PSYM_ENUMMODULES_CALLBACK PSYM_ENUMMODULES_CALLBACK64 +#define PSYM_ENUMSYMBOLS_CALLBACK PSYM_ENUMSYMBOLS_CALLBACK64 +#define PSYM_ENUMSYMBOLS_CALLBACKW PSYM_ENUMSYMBOLS_CALLBACK64W +#define PENUMLOADED_MODULES_CALLBACK PENUMLOADED_MODULES_CALLBACK64 +#define PSYMBOL_REGISTERED_CALLBACK PSYMBOL_REGISTERED_CALLBACK64 +#define PSYMBOL_FUNCENTRY_CALLBACK PSYMBOL_FUNCENTRY_CALLBACK64 +#else + typedef BOOL (CALLBACK *PSYM_ENUMMODULES_CALLBACK)(PSTR ModuleName,ULONG BaseOfDll,PVOID UserContext); + typedef BOOL (CALLBACK *PSYM_ENUMSYMBOLS_CALLBACK)(PSTR SymbolName,ULONG SymbolAddress,ULONG SymbolSize,PVOID UserContext); + typedef BOOL (CALLBACK *PSYM_ENUMSYMBOLS_CALLBACKW)(PWSTR SymbolName,ULONG SymbolAddress,ULONG SymbolSize,PVOID UserContext); + typedef BOOL (CALLBACK *PENUMLOADED_MODULES_CALLBACK)(PSTR ModuleName,ULONG ModuleBase,ULONG ModuleSize,PVOID UserContext); + typedef BOOL (CALLBACK *PSYMBOL_REGISTERED_CALLBACK)(HANDLE hProcess,ULONG ActionCode,PVOID CallbackData,PVOID UserContext); +#endif + +#define SYMFLAG_VALUEPRESENT 0x00000001 +#define SYMFLAG_REGISTER 0x00000008 +#define SYMFLAG_REGREL 0x00000010 +#define SYMFLAG_FRAMEREL 0x00000020 +#define SYMFLAG_PARAMETER 0x00000040 +#define SYMFLAG_LOCAL 0x00000080 +#define SYMFLAG_CONSTANT 0x00000100 +#define SYMFLAG_EXPORT 0x00000200 +#define SYMFLAG_FORWARDER 0x00000400 +#define SYMFLAG_FUNCTION 0x00000800 +#define SYMFLAG_VIRTUAL 0x00001000 +#define SYMFLAG_THUNK 0x00002000 +#define SYMFLAG_TLSREL 0x00004000 + + typedef enum { + SymNone = 0,SymCoff,SymCv,SymPdb,SymExport,SymDeferred,SymSym,SymDia,SymVirtual,NumSymTypes + } SYM_TYPE; + + typedef struct _IMAGEHLP_SYMBOL64 { + DWORD SizeOfStruct; + DWORD64 Address; + DWORD Size; + DWORD Flags; + DWORD MaxNameLength; + CHAR Name[1]; + } IMAGEHLP_SYMBOL64,*PIMAGEHLP_SYMBOL64; + + typedef struct _IMAGEHLP_SYMBOL64_PACKAGE { + IMAGEHLP_SYMBOL64 sym; + CHAR name[MAX_SYM_NAME + 1]; + } IMAGEHLP_SYMBOL64_PACKAGE,*PIMAGEHLP_SYMBOL64_PACKAGE; + +#ifdef _IMAGEHLP64 + +#define IMAGEHLP_SYMBOL IMAGEHLP_SYMBOL64 +#define PIMAGEHLP_SYMBOL PIMAGEHLP_SYMBOL64 +#define IMAGEHLP_SYMBOL_PACKAGE IMAGEHLP_SYMBOL64_PACKAGE +#define PIMAGEHLP_SYMBOL_PACKAGE PIMAGEHLP_SYMBOL64_PACKAGE +#else + + typedef struct _IMAGEHLP_SYMBOL { + DWORD SizeOfStruct; + DWORD Address; + DWORD Size; + DWORD Flags; + DWORD MaxNameLength; + CHAR Name[1]; + } IMAGEHLP_SYMBOL,*PIMAGEHLP_SYMBOL; + + typedef struct _IMAGEHLP_SYMBOL_PACKAGE { + IMAGEHLP_SYMBOL sym; + CHAR name[MAX_SYM_NAME + 1]; + } IMAGEHLP_SYMBOL_PACKAGE,*PIMAGEHLP_SYMBOL_PACKAGE; +#endif + + typedef struct _IMAGEHLP_MODULE64 { + DWORD SizeOfStruct; + DWORD64 BaseOfImage; + DWORD ImageSize; + DWORD TimeDateStamp; + DWORD CheckSum; + DWORD NumSyms; + SYM_TYPE SymType; + CHAR ModuleName[32]; + CHAR ImageName[256]; + CHAR LoadedImageName[256]; + CHAR LoadedPdbName[256]; + DWORD CVSig; + CHAR CVData[MAX_PATH*3]; + DWORD PdbSig; + GUID PdbSig70; + DWORD PdbAge; + BOOL PdbUnmatched; + BOOL DbgUnmatched; + BOOL LineNumbers; + BOOL GlobalSymbols; + BOOL TypeInfo; + } IMAGEHLP_MODULE64,*PIMAGEHLP_MODULE64; + + typedef struct _IMAGEHLP_MODULE64W { + DWORD SizeOfStruct; + DWORD64 BaseOfImage; + DWORD ImageSize; + DWORD TimeDateStamp; + DWORD CheckSum; + DWORD NumSyms; + SYM_TYPE SymType; + WCHAR ModuleName[32]; + WCHAR ImageName[256]; + WCHAR LoadedImageName[256]; + WCHAR LoadedPdbName[256]; + DWORD CVSig; + WCHAR CVData[MAX_PATH*3]; + DWORD PdbSig; + GUID PdbSig70; + DWORD PdbAge; + BOOL PdbUnmatched; + BOOL DbgUnmatched; + BOOL LineNumbers; + BOOL GlobalSymbols; + BOOL TypeInfo; + } IMAGEHLP_MODULEW64,*PIMAGEHLP_MODULEW64; + +#ifdef _IMAGEHLP64 +#define IMAGEHLP_MODULE IMAGEHLP_MODULE64 +#define PIMAGEHLP_MODULE PIMAGEHLP_MODULE64 +#define IMAGEHLP_MODULEW IMAGEHLP_MODULEW64 +#define PIMAGEHLP_MODULEW PIMAGEHLP_MODULEW64 +#else + typedef struct _IMAGEHLP_MODULE { + DWORD SizeOfStruct; + DWORD BaseOfImage; + DWORD ImageSize; + DWORD TimeDateStamp; + DWORD CheckSum; + DWORD NumSyms; + SYM_TYPE SymType; + CHAR ModuleName[32]; + CHAR ImageName[256]; + CHAR LoadedImageName[256]; + } IMAGEHLP_MODULE,*PIMAGEHLP_MODULE; + + typedef struct _IMAGEHLP_MODULEW { + DWORD SizeOfStruct; + DWORD BaseOfImage; + DWORD ImageSize; + DWORD TimeDateStamp; + DWORD CheckSum; + DWORD NumSyms; + SYM_TYPE SymType; + WCHAR ModuleName[32]; + WCHAR ImageName[256]; + WCHAR LoadedImageName[256]; + } IMAGEHLP_MODULEW,*PIMAGEHLP_MODULEW; +#endif + + typedef struct _IMAGEHLP_LINE64 { + DWORD SizeOfStruct; + PVOID Key; + DWORD LineNumber; + PCHAR FileName; + DWORD64 Address; + } IMAGEHLP_LINE64,*PIMAGEHLP_LINE64; + +#ifdef _IMAGEHLP64 +#define IMAGEHLP_LINE IMAGEHLP_LINE64 +#define PIMAGEHLP_LINE PIMAGEHLP_LINE64 +#else + typedef struct _IMAGEHLP_LINE { + DWORD SizeOfStruct; + PVOID Key; + DWORD LineNumber; + PCHAR FileName; + DWORD Address; + } IMAGEHLP_LINE,*PIMAGEHLP_LINE; +#endif + + typedef struct _SOURCEFILE { + DWORD64 ModBase; + PCHAR FileName; + } SOURCEFILE,*PSOURCEFILE; + +#define CBA_DEFERRED_SYMBOL_LOAD_START 0x00000001 +#define CBA_DEFERRED_SYMBOL_LOAD_COMPLETE 0x00000002 +#define CBA_DEFERRED_SYMBOL_LOAD_FAILURE 0x00000003 +#define CBA_SYMBOLS_UNLOADED 0x00000004 +#define CBA_DUPLICATE_SYMBOL 0x00000005 +#define CBA_READ_MEMORY 0x00000006 +#define CBA_DEFERRED_SYMBOL_LOAD_CANCEL 0x00000007 +#define CBA_SET_OPTIONS 0x00000008 +#define CBA_EVENT 0x00000010 +#define CBA_DEFERRED_SYMBOL_LOAD_PARTIAL 0x00000020 +#define CBA_DEBUG_INFO 0x10000000 + + typedef struct _IMAGEHLP_CBA_READ_MEMORY { + DWORD64 addr; + PVOID buf; + DWORD bytes; + DWORD *bytesread; + } IMAGEHLP_CBA_READ_MEMORY,*PIMAGEHLP_CBA_READ_MEMORY; + + enum { + sevInfo = 0,sevProblem,sevAttn,sevFatal,sevMax + }; + + typedef struct _IMAGEHLP_CBA_EVENT { + DWORD severity; + DWORD code; + PCHAR desc; + PVOID object; + } IMAGEHLP_CBA_EVENT,*PIMAGEHLP_CBA_EVENT; + + typedef struct _IMAGEHLP_DEFERRED_SYMBOL_LOAD64 { + DWORD SizeOfStruct; + DWORD64 BaseOfImage; + DWORD CheckSum; + DWORD TimeDateStamp; + CHAR FileName[MAX_PATH]; + BOOLEAN Reparse; + HANDLE hFile; + DWORD Flags; + } IMAGEHLP_DEFERRED_SYMBOL_LOAD64,*PIMAGEHLP_DEFERRED_SYMBOL_LOAD64; + +#define DSLFLAG_MISMATCHED_PDB 0x1 +#define DSLFLAG_MISMATCHED_DBG 0x2 + +#ifdef _IMAGEHLP64 +#define IMAGEHLP_DEFERRED_SYMBOL_LOAD IMAGEHLP_DEFERRED_SYMBOL_LOAD64 +#define PIMAGEHLP_DEFERRED_SYMBOL_LOAD PIMAGEHLP_DEFERRED_SYMBOL_LOAD64 +#else + typedef struct _IMAGEHLP_DEFERRED_SYMBOL_LOAD { + DWORD SizeOfStruct; + DWORD BaseOfImage; + DWORD CheckSum; + DWORD TimeDateStamp; + CHAR FileName[MAX_PATH]; + BOOLEAN Reparse; + HANDLE hFile; + } IMAGEHLP_DEFERRED_SYMBOL_LOAD,*PIMAGEHLP_DEFERRED_SYMBOL_LOAD; +#endif + + typedef struct _IMAGEHLP_DUPLICATE_SYMBOL64 { + DWORD SizeOfStruct; + DWORD NumberOfDups; + PIMAGEHLP_SYMBOL64 Symbol; + DWORD SelectedSymbol; + } IMAGEHLP_DUPLICATE_SYMBOL64,*PIMAGEHLP_DUPLICATE_SYMBOL64; + +#ifdef _IMAGEHLP64 +#define IMAGEHLP_DUPLICATE_SYMBOL IMAGEHLP_DUPLICATE_SYMBOL64 +#define PIMAGEHLP_DUPLICATE_SYMBOL PIMAGEHLP_DUPLICATE_SYMBOL64 +#else + typedef struct _IMAGEHLP_DUPLICATE_SYMBOL { + DWORD SizeOfStruct; + DWORD NumberOfDups; + PIMAGEHLP_SYMBOL Symbol; + DWORD SelectedSymbol; + } IMAGEHLP_DUPLICATE_SYMBOL,*PIMAGEHLP_DUPLICATE_SYMBOL; +#endif + + BOOL IMAGEAPI SymSetParentWindow(HWND hwnd); + PCHAR IMAGEAPI SymSetHomeDirectory(PCSTR dir); + PCHAR IMAGEAPI SymGetHomeDirectory(DWORD type,PSTR dir,size_t size); + + enum { + hdBase = 0,hdSym,hdSrc,hdMax + }; + +#define SYMOPT_CASE_INSENSITIVE 0x00000001 +#define SYMOPT_UNDNAME 0x00000002 +#define SYMOPT_DEFERRED_LOADS 0x00000004 +#define SYMOPT_NO_CPP 0x00000008 +#define SYMOPT_LOAD_LINES 0x00000010 +#define SYMOPT_OMAP_FIND_NEAREST 0x00000020 +#define SYMOPT_LOAD_ANYTHING 0x00000040 +#define SYMOPT_IGNORE_CVREC 0x00000080 +#define SYMOPT_NO_UNQUALIFIED_LOADS 0x00000100 +#define SYMOPT_FAIL_CRITICAL_ERRORS 0x00000200 +#define SYMOPT_EXACT_SYMBOLS 0x00000400 +#define SYMOPT_ALLOW_ABSOLUTE_SYMBOLS 0x00000800 +#define SYMOPT_IGNORE_NT_SYMPATH 0x00001000 +#define SYMOPT_INCLUDE_32BIT_MODULES 0x00002000 +#define SYMOPT_PUBLICS_ONLY 0x00004000 +#define SYMOPT_NO_PUBLICS 0x00008000 +#define SYMOPT_AUTO_PUBLICS 0x00010000 +#define SYMOPT_NO_IMAGE_SEARCH 0x00020000 +#define SYMOPT_SECURE 0x00040000 +#define SYMOPT_NO_PROMPTS 0x00080000 + +#define SYMOPT_DEBUG 0x80000000 + + DWORD IMAGEAPI SymSetOptions(DWORD SymOptions); + DWORD IMAGEAPI SymGetOptions(VOID); + BOOL IMAGEAPI SymCleanup(HANDLE hProcess); + BOOL IMAGEAPI SymMatchString(LPSTR string,LPSTR expression,BOOL fCase); + + typedef BOOL (CALLBACK *PSYM_ENUMSOURCFILES_CALLBACK)(PSOURCEFILE pSourceFile,PVOID UserContext); + + BOOL IMAGEAPI SymEnumSourceFiles(HANDLE hProcess,ULONG64 ModBase,LPSTR Mask,PSYM_ENUMSOURCFILES_CALLBACK cbSrcFiles,PVOID UserContext); + BOOL IMAGEAPI SymEnumerateModules64(HANDLE hProcess,PSYM_ENUMMODULES_CALLBACK64 EnumModulesCallback,PVOID UserContext); + +#ifdef _IMAGEHLP64 +#define SymEnumerateModules SymEnumerateModules64 +#else + BOOL IMAGEAPI SymEnumerateModules(HANDLE hProcess,PSYM_ENUMMODULES_CALLBACK EnumModulesCallback,PVOID UserContext); +#endif + + BOOL IMAGEAPI SymEnumerateSymbols64(HANDLE hProcess,DWORD64 BaseOfDll,PSYM_ENUMSYMBOLS_CALLBACK64 EnumSymbolsCallback,PVOID UserContext); + BOOL IMAGEAPI SymEnumerateSymbolsW64(HANDLE hProcess,DWORD64 BaseOfDll,PSYM_ENUMSYMBOLS_CALLBACK64W EnumSymbolsCallback,PVOID UserContext); + +#ifdef _IMAGEHLP64 +#define SymEnumerateSymbols SymEnumerateSymbols64 +#define SymEnumerateSymbolsW SymEnumerateSymbolsW64 +#else + BOOL IMAGEAPI SymEnumerateSymbols(HANDLE hProcess,DWORD BaseOfDll,PSYM_ENUMSYMBOLS_CALLBACK EnumSymbolsCallback,PVOID UserContext); + BOOL IMAGEAPI SymEnumerateSymbolsW(HANDLE hProcess,DWORD BaseOfDll,PSYM_ENUMSYMBOLS_CALLBACKW EnumSymbolsCallback,PVOID UserContext); +#endif + + BOOL IMAGEAPI EnumerateLoadedModules64(HANDLE hProcess,PENUMLOADED_MODULES_CALLBACK64 EnumLoadedModulesCallback,PVOID UserContext); +#ifdef _IMAGEHLP64 +#define EnumerateLoadedModules EnumerateLoadedModules64 +#else + BOOL IMAGEAPI EnumerateLoadedModules(HANDLE hProcess,PENUMLOADED_MODULES_CALLBACK EnumLoadedModulesCallback,PVOID UserContext); +#endif + + PVOID IMAGEAPI SymFunctionTableAccess64(HANDLE hProcess,DWORD64 AddrBase); + +#ifdef _IMAGEHLP64 +#define SymFunctionTableAccess SymFunctionTableAccess64 +#else + PVOID IMAGEAPI SymFunctionTableAccess(HANDLE hProcess,DWORD AddrBase); +#endif + + BOOL IMAGEAPI SymGetModuleInfo64(HANDLE hProcess,DWORD64 qwAddr,PIMAGEHLP_MODULE64 ModuleInfo); + BOOL IMAGEAPI SymGetModuleInfoW64(HANDLE hProcess,DWORD64 qwAddr,PIMAGEHLP_MODULEW64 ModuleInfo); + +#ifdef _IMAGEHLP64 +#define SymGetModuleInfo SymGetModuleInfo64 +#define SymGetModuleInfoW SymGetModuleInfoW64 +#else + BOOL IMAGEAPI SymGetModuleInfo(HANDLE hProcess,DWORD dwAddr,PIMAGEHLP_MODULE ModuleInfo); + BOOL IMAGEAPI SymGetModuleInfoW(HANDLE hProcess,DWORD dwAddr,PIMAGEHLP_MODULEW ModuleInfo); +#endif + + DWORD64 IMAGEAPI SymGetModuleBase64(HANDLE hProcess,DWORD64 qwAddr); + +#ifdef _IMAGEHLP64 +#define SymGetModuleBase SymGetModuleBase64 +#else + DWORD IMAGEAPI SymGetModuleBase(HANDLE hProcess,DWORD dwAddr); +#endif + + BOOL IMAGEAPI SymGetSymNext64(HANDLE hProcess,PIMAGEHLP_SYMBOL64 Symbol); + +#ifdef _IMAGEHLP64 +#define SymGetSymNext SymGetSymNext64 +#else + BOOL IMAGEAPI SymGetSymNext(HANDLE hProcess,PIMAGEHLP_SYMBOL Symbol); +#endif + + BOOL IMAGEAPI SymGetSymPrev64(HANDLE hProcess,PIMAGEHLP_SYMBOL64 Symbol); + +#ifdef _IMAGEHLP64 +#define SymGetSymPrev SymGetSymPrev64 +#else + BOOL IMAGEAPI SymGetSymPrev(HANDLE hProcess,PIMAGEHLP_SYMBOL Symbol); +#endif + + typedef struct _SRCCODEINFO { + DWORD SizeOfStruct; + PVOID Key; + DWORD64 ModBase; + CHAR Obj[MAX_PATH + 1]; + CHAR FileName[MAX_PATH + 1]; + DWORD LineNumber; + DWORD64 Address; + } SRCCODEINFO,*PSRCCODEINFO; + + typedef BOOL (CALLBACK *PSYM_ENUMLINES_CALLBACK)(PSRCCODEINFO LineInfo,PVOID UserContext); + + BOOL IMAGEAPI SymEnumLines(HANDLE hProcess,ULONG64 Base,PCSTR Obj,PCSTR File,PSYM_ENUMLINES_CALLBACK EnumLinesCallback,PVOID UserContext); + BOOL IMAGEAPI SymGetLineFromAddr64(HANDLE hProcess,DWORD64 qwAddr,PDWORD pdwDisplacement,PIMAGEHLP_LINE64 Line64); + +#ifdef _IMAGEHLP64 +#define SymGetLineFromAddr SymGetLineFromAddr64 +#else + BOOL IMAGEAPI SymGetLineFromAddr(HANDLE hProcess,DWORD dwAddr,PDWORD pdwDisplacement,PIMAGEHLP_LINE Line); +#endif + + BOOL IMAGEAPI SymGetLineFromName64(HANDLE hProcess,PSTR ModuleName,PSTR FileName,DWORD dwLineNumber,PLONG plDisplacement,PIMAGEHLP_LINE64 Line); + +#ifdef _IMAGEHLP64 +#define SymGetLineFromName SymGetLineFromName64 +#else + BOOL IMAGEAPI SymGetLineFromName(HANDLE hProcess,PSTR ModuleName,PSTR FileName,DWORD dwLineNumber,PLONG plDisplacement,PIMAGEHLP_LINE Line); +#endif + + BOOL IMAGEAPI SymGetLineNext64(HANDLE hProcess,PIMAGEHLP_LINE64 Line); + +#ifdef _IMAGEHLP64 +#define SymGetLineNext SymGetLineNext64 +#else + BOOL IMAGEAPI SymGetLineNext(HANDLE hProcess,PIMAGEHLP_LINE Line); +#endif + + BOOL IMAGEAPI SymGetLinePrev64(HANDLE hProcess,PIMAGEHLP_LINE64 Line); + +#ifdef _IMAGEHLP64 +#define SymGetLinePrev SymGetLinePrev64 +#else + BOOL IMAGEAPI SymGetLinePrev(HANDLE hProcess,PIMAGEHLP_LINE Line); +#endif + + BOOL IMAGEAPI SymMatchFileName(PSTR FileName,PSTR Match,PSTR *FileNameStop,PSTR *MatchStop); + BOOL IMAGEAPI SymInitialize(HANDLE hProcess,PSTR UserSearchPath,BOOL fInvadeProcess); + BOOL IMAGEAPI SymGetSearchPath(HANDLE hProcess,PSTR SearchPath,DWORD SearchPathLength); + BOOL IMAGEAPI SymSetSearchPath(HANDLE hProcess,PSTR SearchPath); + DWORD64 IMAGEAPI SymLoadModule64(HANDLE hProcess,HANDLE hFile,PSTR ImageName,PSTR ModuleName,DWORD64 BaseOfDll,DWORD SizeOfDll); + +#define SLMFLAG_VIRTUAL 0x1 + + DWORD64 IMAGEAPI SymLoadModuleEx(HANDLE hProcess,HANDLE hFile,PSTR ImageName,PSTR ModuleName,DWORD64 BaseOfDll,DWORD DllSize,PMODLOAD_DATA Data,DWORD Flags); + +#ifdef _IMAGEHLP64 +#define SymLoadModule SymLoadModule64 +#else + DWORD IMAGEAPI SymLoadModule(HANDLE hProcess,HANDLE hFile,PSTR ImageName,PSTR ModuleName,DWORD BaseOfDll,DWORD SizeOfDll); +#endif + + BOOL IMAGEAPI SymUnloadModule64(HANDLE hProcess,DWORD64 BaseOfDll); + +#ifdef _IMAGEHLP64 +#define SymUnloadModule SymUnloadModule64 +#else + BOOL IMAGEAPI SymUnloadModule(HANDLE hProcess,DWORD BaseOfDll); +#endif + + BOOL IMAGEAPI SymUnDName64(PIMAGEHLP_SYMBOL64 sym,PSTR UnDecName,DWORD UnDecNameLength); + +#ifdef _IMAGEHLP64 +#define SymUnDName SymUnDName64 +#else + BOOL IMAGEAPI SymUnDName(PIMAGEHLP_SYMBOL sym,PSTR UnDecName,DWORD UnDecNameLength); +#endif + + BOOL IMAGEAPI SymRegisterCallback64(HANDLE hProcess,PSYMBOL_REGISTERED_CALLBACK64 CallbackFunction,ULONG64 UserContext); + + BOOL IMAGEAPI SymRegisterFunctionEntryCallback64(HANDLE hProcess,PSYMBOL_FUNCENTRY_CALLBACK64 CallbackFunction,ULONG64 UserContext); + +#ifdef _IMAGEHLP64 +#define SymRegisterCallback SymRegisterCallback64 +#define SymRegisterFunctionEntryCallback SymRegisterFunctionEntryCallback64 +#else + BOOL IMAGEAPI SymRegisterCallback(HANDLE hProcess,PSYMBOL_REGISTERED_CALLBACK CallbackFunction,PVOID UserContext); + BOOL IMAGEAPI SymRegisterFunctionEntryCallback(HANDLE hProcess,PSYMBOL_FUNCENTRY_CALLBACK CallbackFunction,PVOID UserContext); +#endif + + typedef struct _IMAGEHLP_SYMBOL_SRC { + DWORD sizeofstruct; + DWORD type; + char file[MAX_PATH]; + } IMAGEHLP_SYMBOL_SRC,*PIMAGEHLP_SYMBOL_SRC; + + typedef struct _MODULE_TYPE_INFO { + USHORT dataLength; + USHORT leaf; + BYTE data[1]; + } MODULE_TYPE_INFO,*PMODULE_TYPE_INFO; + + typedef struct _SYMBOL_INFO { + ULONG SizeOfStruct; + ULONG TypeIndex; + ULONG64 Reserved[2]; + ULONG info; + ULONG Size; + ULONG64 ModBase; + ULONG Flags; + ULONG64 Value; + ULONG64 Address; + ULONG Register; + ULONG Scope; + ULONG Tag; + ULONG NameLen; + ULONG MaxNameLen; + CHAR Name[1]; + } SYMBOL_INFO,*PSYMBOL_INFO; + + typedef struct _SYMBOL_INFO_PACKAGE { + SYMBOL_INFO si; + CHAR name[MAX_SYM_NAME + 1]; + } SYMBOL_INFO_PACKAGE,*PSYMBOL_INFO_PACKAGE; + + typedef struct _IMAGEHLP_STACK_FRAME + { + ULONG64 InstructionOffset; + ULONG64 ReturnOffset; + ULONG64 FrameOffset; + ULONG64 StackOffset; + ULONG64 BackingStoreOffset; + ULONG64 FuncTableEntry; + ULONG64 Params[4]; + ULONG64 Reserved[5]; + BOOL Virtual; + ULONG Reserved2; + } IMAGEHLP_STACK_FRAME,*PIMAGEHLP_STACK_FRAME; + + typedef VOID IMAGEHLP_CONTEXT,*PIMAGEHLP_CONTEXT; + + BOOL IMAGEAPI SymSetContext(HANDLE hProcess,PIMAGEHLP_STACK_FRAME StackFrame,PIMAGEHLP_CONTEXT Context); + BOOL IMAGEAPI SymFromAddr(HANDLE hProcess,DWORD64 Address,PDWORD64 Displacement,PSYMBOL_INFO Symbol); + BOOL IMAGEAPI SymFromToken(HANDLE hProcess,DWORD64 Base,DWORD Token,PSYMBOL_INFO Symbol); + BOOL IMAGEAPI SymFromName(HANDLE hProcess,LPSTR Name,PSYMBOL_INFO Symbol); + + typedef BOOL (CALLBACK *PSYM_ENUMERATESYMBOLS_CALLBACK)(PSYMBOL_INFO pSymInfo,ULONG SymbolSize,PVOID UserContext); + + BOOL IMAGEAPI SymEnumSymbols(HANDLE hProcess,ULONG64 BaseOfDll,PCSTR Mask,PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,PVOID UserContext); + BOOL IMAGEAPI SymEnumSymbolsForAddr(HANDLE hProcess,DWORD64 Address,PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,PVOID UserContext); + +#define SYMENUMFLAG_FULLSRCH 1 +#define SYMENUMFLAG_SPEEDSRCH 2 + + typedef enum _IMAGEHLP_SYMBOL_TYPE_INFO { + TI_GET_SYMTAG,TI_GET_SYMNAME,TI_GET_LENGTH,TI_GET_TYPE,TI_GET_TYPEID,TI_GET_BASETYPE,TI_GET_ARRAYINDEXTYPEID,TI_FINDCHILDREN, + TI_GET_DATAKIND,TI_GET_ADDRESSOFFSET,TI_GET_OFFSET,TI_GET_VALUE,TI_GET_COUNT,TI_GET_CHILDRENCOUNT,TI_GET_BITPOSITION,TI_GET_VIRTUALBASECLASS, + TI_GET_VIRTUALTABLESHAPEID,TI_GET_VIRTUALBASEPOINTEROFFSET,TI_GET_CLASSPARENTID,TI_GET_NESTED,TI_GET_SYMINDEX,TI_GET_LEXICALPARENT, + TI_GET_ADDRESS,TI_GET_THISADJUST,TI_GET_UDTKIND,TI_IS_EQUIV_TO,TI_GET_CALLING_CONVENTION + } IMAGEHLP_SYMBOL_TYPE_INFO; + + typedef struct _TI_FINDCHILDREN_PARAMS { + ULONG Count; + ULONG Start; + ULONG ChildId[1]; + } TI_FINDCHILDREN_PARAMS; + + BOOL IMAGEAPI SymGetTypeInfo(HANDLE hProcess,DWORD64 ModBase,ULONG TypeId,IMAGEHLP_SYMBOL_TYPE_INFO GetType,PVOID pInfo); + BOOL IMAGEAPI SymEnumTypes(HANDLE hProcess,ULONG64 BaseOfDll,PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,PVOID UserContext); + BOOL IMAGEAPI SymGetTypeFromName(HANDLE hProcess,ULONG64 BaseOfDll,LPSTR Name,PSYMBOL_INFO Symbol); + BOOL IMAGEAPI SymAddSymbol(HANDLE hProcess,ULONG64 BaseOfDll,PCSTR Name,DWORD64 Address,DWORD Size,DWORD Flags); + BOOL IMAGEAPI SymDeleteSymbol(HANDLE hProcess,ULONG64 BaseOfDll,PCSTR Name,DWORD64 Address,DWORD Flags); + + typedef BOOL (WINAPI *PDBGHELP_CREATE_USER_DUMP_CALLBACK)(DWORD DataType,PVOID *Data,LPDWORD DataLength,PVOID UserData); + + BOOL WINAPI DbgHelpCreateUserDump(LPSTR FileName,PDBGHELP_CREATE_USER_DUMP_CALLBACK Callback,PVOID UserData); + BOOL WINAPI DbgHelpCreateUserDumpW(LPWSTR FileName,PDBGHELP_CREATE_USER_DUMP_CALLBACK Callback,PVOID UserData); + BOOL IMAGEAPI SymGetSymFromAddr64(HANDLE hProcess,DWORD64 qwAddr,PDWORD64 pdwDisplacement,PIMAGEHLP_SYMBOL64 Symbol); + +#ifdef _IMAGEHLP64 +#define SymGetSymFromAddr SymGetSymFromAddr64 +#else + BOOL IMAGEAPI SymGetSymFromAddr(HANDLE hProcess,DWORD dwAddr,PDWORD pdwDisplacement,PIMAGEHLP_SYMBOL Symbol); +#endif + + BOOL IMAGEAPI SymGetSymFromName64(HANDLE hProcess,PSTR Name,PIMAGEHLP_SYMBOL64 Symbol); + +#ifdef _IMAGEHLP64 +#define SymGetSymFromName SymGetSymFromName64 +#else + BOOL IMAGEAPI SymGetSymFromName(HANDLE hProcess,PSTR Name,PIMAGEHLP_SYMBOL Symbol); +#endif + + DBHLP_DEPRECIATED BOOL IMAGEAPI FindFileInPath(HANDLE hprocess,LPSTR SearchPath,LPSTR FileName,PVOID id,DWORD two,DWORD three,DWORD flags,LPSTR FilePath); + DBHLP_DEPRECIATED BOOL IMAGEAPI FindFileInSearchPath(HANDLE hprocess,LPSTR SearchPath,LPSTR FileName,DWORD one,DWORD two,DWORD three,LPSTR FilePath); + DBHLP_DEPRECIATED BOOL IMAGEAPI SymEnumSym(HANDLE hProcess,ULONG64 BaseOfDll,PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,PVOID UserContext); + +#define SYMF_OMAP_GENERATED 0x00000001 +#define SYMF_OMAP_MODIFIED 0x00000002 +#define SYMF_REGISTER 0x00000008 +#define SYMF_REGREL 0x00000010 +#define SYMF_FRAMEREL 0x00000020 +#define SYMF_PARAMETER 0x00000040 +#define SYMF_LOCAL 0x00000080 +#define SYMF_CONSTANT 0x00000100 +#define SYMF_EXPORT 0x00000200 +#define SYMF_FORWARDER 0x00000400 +#define SYMF_FUNCTION 0x00000800 +#define SYMF_VIRTUAL 0x00001000 +#define SYMF_THUNK 0x00002000 +#define SYMF_TLSREL 0x00004000 + +#define IMAGEHLP_SYMBOL_INFO_VALUEPRESENT 1 +#define IMAGEHLP_SYMBOL_INFO_REGISTER SYMF_REGISTER +#define IMAGEHLP_SYMBOL_INFO_REGRELATIVE SYMF_REGREL +#define IMAGEHLP_SYMBOL_INFO_FRAMERELATIVE SYMF_FRAMEREL +#define IMAGEHLP_SYMBOL_INFO_PARAMETER SYMF_PARAMETER +#define IMAGEHLP_SYMBOL_INFO_LOCAL SYMF_LOCAL +#define IMAGEHLP_SYMBOL_INFO_CONSTANT SYMF_CONSTANT +#define IMAGEHLP_SYMBOL_FUNCTION SYMF_FUNCTION +#define IMAGEHLP_SYMBOL_VIRTUAL SYMF_VIRTUAL +#define IMAGEHLP_SYMBOL_THUNK SYMF_THUNK +#define IMAGEHLP_SYMBOL_INFO_TLSRELATIVE SYMF_TLSREL + +#include <pshpack4.h> + +#define MINIDUMP_SIGNATURE ('PMDM') +#define MINIDUMP_VERSION (42899) + typedef DWORD RVA; + typedef ULONG64 RVA64; + + typedef struct _MINIDUMP_LOCATION_DESCRIPTOR { + ULONG32 DataSize; + RVA Rva; + } MINIDUMP_LOCATION_DESCRIPTOR; + + typedef struct _MINIDUMP_LOCATION_DESCRIPTOR64 { + ULONG64 DataSize; + RVA64 Rva; + } MINIDUMP_LOCATION_DESCRIPTOR64; + + typedef struct _MINIDUMP_MEMORY_DESCRIPTOR { + ULONG64 StartOfMemoryRange; + MINIDUMP_LOCATION_DESCRIPTOR Memory; + } MINIDUMP_MEMORY_DESCRIPTOR,*PMINIDUMP_MEMORY_DESCRIPTOR; + + typedef struct _MINIDUMP_MEMORY_DESCRIPTOR64 { + ULONG64 StartOfMemoryRange; + ULONG64 DataSize; + } MINIDUMP_MEMORY_DESCRIPTOR64,*PMINIDUMP_MEMORY_DESCRIPTOR64; + + typedef struct _MINIDUMP_HEADER { + ULONG32 Signature; + ULONG32 Version; + ULONG32 NumberOfStreams; + RVA StreamDirectoryRva; + ULONG32 CheckSum; + union { + ULONG32 Reserved; + ULONG32 TimeDateStamp; + } DUMMYUNIONNAME; + ULONG64 Flags; + } MINIDUMP_HEADER,*PMINIDUMP_HEADER; + + typedef struct _MINIDUMP_DIRECTORY { + ULONG32 StreamType; + MINIDUMP_LOCATION_DESCRIPTOR Location; + } MINIDUMP_DIRECTORY,*PMINIDUMP_DIRECTORY; + + typedef struct _MINIDUMP_STRING { + ULONG32 Length; + WCHAR Buffer [0]; + } MINIDUMP_STRING,*PMINIDUMP_STRING; + + typedef enum _MINIDUMP_STREAM_TYPE { + UnusedStream = 0,ReservedStream0 = 1,ReservedStream1 = 2,ThreadListStream = 3,ModuleListStream = 4,MemoryListStream = 5, + ExceptionStream = 6,SystemInfoStream = 7,ThreadExListStream = 8,Memory64ListStream = 9,CommentStreamA = 10,CommentStreamW = 11, + HandleDataStream = 12,FunctionTableStream = 13,UnloadedModuleListStream = 14,MiscInfoStream = 15,LastReservedStream = 0xffff + } MINIDUMP_STREAM_TYPE; + + typedef union _CPU_INFORMATION { + struct { + ULONG32 VendorId [3 ]; + ULONG32 VersionInformation; + ULONG32 FeatureInformation; + ULONG32 AMDExtendedCpuFeatures; + } X86CpuInfo; + struct { + ULONG64 ProcessorFeatures [2 ]; + } OtherCpuInfo; + } CPU_INFORMATION,*PCPU_INFORMATION; + + typedef struct _MINIDUMP_SYSTEM_INFO { + USHORT ProcessorArchitecture; + USHORT ProcessorLevel; + USHORT ProcessorRevision; + union { + USHORT Reserved0; + struct { + UCHAR NumberOfProcessors; + UCHAR ProductType; + } DUMMYSTRUCTNAME; + } DUMMYUNIONNAME; + ULONG32 MajorVersion; + ULONG32 MinorVersion; + ULONG32 BuildNumber; + ULONG32 PlatformId; + RVA CSDVersionRva; + union { + ULONG32 Reserved1; + struct { + USHORT SuiteMask; + USHORT Reserved2; + } DUMMYSTRUCTNAME; + } DUMMYUNIONNAME1; + CPU_INFORMATION Cpu; + } MINIDUMP_SYSTEM_INFO,*PMINIDUMP_SYSTEM_INFO; + + C_ASSERT (sizeof (((PPROCESS_INFORMATION)0)->dwThreadId)==4); + + typedef struct _MINIDUMP_THREAD { + ULONG32 ThreadId; + ULONG32 SuspendCount; + ULONG32 PriorityClass; + ULONG32 Priority; + ULONG64 Teb; + MINIDUMP_MEMORY_DESCRIPTOR Stack; + MINIDUMP_LOCATION_DESCRIPTOR ThreadContext; + } MINIDUMP_THREAD,*PMINIDUMP_THREAD; + + typedef struct _MINIDUMP_THREAD_LIST { + ULONG32 NumberOfThreads; + MINIDUMP_THREAD Threads [0]; + } MINIDUMP_THREAD_LIST,*PMINIDUMP_THREAD_LIST; + + typedef struct _MINIDUMP_THREAD_EX { + ULONG32 ThreadId; + ULONG32 SuspendCount; + ULONG32 PriorityClass; + ULONG32 Priority; + ULONG64 Teb; + MINIDUMP_MEMORY_DESCRIPTOR Stack; + MINIDUMP_LOCATION_DESCRIPTOR ThreadContext; + MINIDUMP_MEMORY_DESCRIPTOR BackingStore; + } MINIDUMP_THREAD_EX,*PMINIDUMP_THREAD_EX; + + typedef struct _MINIDUMP_THREAD_EX_LIST { + ULONG32 NumberOfThreads; + MINIDUMP_THREAD_EX Threads [0]; + } MINIDUMP_THREAD_EX_LIST,*PMINIDUMP_THREAD_EX_LIST; + + typedef struct _MINIDUMP_EXCEPTION { + ULONG32 ExceptionCode; + ULONG32 ExceptionFlags; + ULONG64 ExceptionRecord; + ULONG64 ExceptionAddress; + ULONG32 NumberParameters; + ULONG32 __unusedAlignment; + ULONG64 ExceptionInformation [EXCEPTION_MAXIMUM_PARAMETERS ]; + } MINIDUMP_EXCEPTION,*PMINIDUMP_EXCEPTION; + + typedef struct MINIDUMP_EXCEPTION_STREAM { + ULONG32 ThreadId; + ULONG32 __alignment; + MINIDUMP_EXCEPTION ExceptionRecord; + MINIDUMP_LOCATION_DESCRIPTOR ThreadContext; + } MINIDUMP_EXCEPTION_STREAM,*PMINIDUMP_EXCEPTION_STREAM; + + typedef struct _MINIDUMP_MODULE { + ULONG64 BaseOfImage; + ULONG32 SizeOfImage; + ULONG32 CheckSum; + ULONG32 TimeDateStamp; + RVA ModuleNameRva; + VS_FIXEDFILEINFO VersionInfo; + MINIDUMP_LOCATION_DESCRIPTOR CvRecord; + MINIDUMP_LOCATION_DESCRIPTOR MiscRecord; + ULONG64 Reserved0; + ULONG64 Reserved1; + } MINIDUMP_MODULE,*PMINIDUMP_MODULE; + + typedef struct _MINIDUMP_MODULE_LIST { + ULONG32 NumberOfModules; + MINIDUMP_MODULE Modules [0 ]; + } MINIDUMP_MODULE_LIST,*PMINIDUMP_MODULE_LIST; + + typedef struct _MINIDUMP_MEMORY_LIST { + ULONG32 NumberOfMemoryRanges; + MINIDUMP_MEMORY_DESCRIPTOR MemoryRanges [0]; + } MINIDUMP_MEMORY_LIST,*PMINIDUMP_MEMORY_LIST; + + typedef struct _MINIDUMP_MEMORY64_LIST { + ULONG64 NumberOfMemoryRanges; + RVA64 BaseRva; + MINIDUMP_MEMORY_DESCRIPTOR64 MemoryRanges [0]; + } MINIDUMP_MEMORY64_LIST,*PMINIDUMP_MEMORY64_LIST; + + typedef struct _MINIDUMP_EXCEPTION_INFORMATION { + DWORD ThreadId; + PEXCEPTION_POINTERS ExceptionPointers; + BOOL ClientPointers; + } MINIDUMP_EXCEPTION_INFORMATION,*PMINIDUMP_EXCEPTION_INFORMATION; + + typedef struct _MINIDUMP_EXCEPTION_INFORMATION64 { + DWORD ThreadId; + ULONG64 ExceptionRecord; + ULONG64 ContextRecord; + BOOL ClientPointers; + } MINIDUMP_EXCEPTION_INFORMATION64,*PMINIDUMP_EXCEPTION_INFORMATION64; + + typedef struct _MINIDUMP_HANDLE_DESCRIPTOR { + ULONG64 Handle; + RVA TypeNameRva; + RVA ObjectNameRva; + ULONG32 Attributes; + ULONG32 GrantedAccess; + ULONG32 HandleCount; + ULONG32 PointerCount; + } MINIDUMP_HANDLE_DESCRIPTOR,*PMINIDUMP_HANDLE_DESCRIPTOR; + + typedef struct _MINIDUMP_HANDLE_DATA_STREAM { + ULONG32 SizeOfHeader; + ULONG32 SizeOfDescriptor; + ULONG32 NumberOfDescriptors; + ULONG32 Reserved; + } MINIDUMP_HANDLE_DATA_STREAM,*PMINIDUMP_HANDLE_DATA_STREAM; + + typedef struct _MINIDUMP_FUNCTION_TABLE_DESCRIPTOR { + ULONG64 MinimumAddress; + ULONG64 MaximumAddress; + ULONG64 BaseAddress; + ULONG32 EntryCount; + ULONG32 SizeOfAlignPad; + } MINIDUMP_FUNCTION_TABLE_DESCRIPTOR,*PMINIDUMP_FUNCTION_TABLE_DESCRIPTOR; + + typedef struct _MINIDUMP_FUNCTION_TABLE_STREAM { + ULONG32 SizeOfHeader; + ULONG32 SizeOfDescriptor; + ULONG32 SizeOfNativeDescriptor; + ULONG32 SizeOfFunctionEntry; + ULONG32 NumberOfDescriptors; + ULONG32 SizeOfAlignPad; + } MINIDUMP_FUNCTION_TABLE_STREAM,*PMINIDUMP_FUNCTION_TABLE_STREAM; + + typedef struct _MINIDUMP_UNLOADED_MODULE { + ULONG64 BaseOfImage; + ULONG32 SizeOfImage; + ULONG32 CheckSum; + ULONG32 TimeDateStamp; + RVA ModuleNameRva; + } MINIDUMP_UNLOADED_MODULE,*PMINIDUMP_UNLOADED_MODULE; + + typedef struct _MINIDUMP_UNLOADED_MODULE_LIST { + ULONG32 SizeOfHeader; + ULONG32 SizeOfEntry; + ULONG32 NumberOfEntries; + } MINIDUMP_UNLOADED_MODULE_LIST,*PMINIDUMP_UNLOADED_MODULE_LIST; + +#define MINIDUMP_MISC1_PROCESS_ID 0x00000001 +#define MINIDUMP_MISC1_PROCESS_TIMES 0x00000002 + + typedef struct _MINIDUMP_MISC_INFO { + ULONG32 SizeOfInfo; + ULONG32 Flags1; + ULONG32 ProcessId; + ULONG32 ProcessCreateTime; + ULONG32 ProcessUserTime; + ULONG32 ProcessKernelTime; + } MINIDUMP_MISC_INFO,*PMINIDUMP_MISC_INFO; + + typedef struct _MINIDUMP_USER_RECORD { + ULONG32 Type; + MINIDUMP_LOCATION_DESCRIPTOR Memory; + } MINIDUMP_USER_RECORD,*PMINIDUMP_USER_RECORD; + + typedef struct _MINIDUMP_USER_STREAM { + ULONG32 Type; + ULONG BufferSize; + PVOID Buffer; + } MINIDUMP_USER_STREAM,*PMINIDUMP_USER_STREAM; + + typedef struct _MINIDUMP_USER_STREAM_INFORMATION { + ULONG UserStreamCount; + PMINIDUMP_USER_STREAM UserStreamArray; + } MINIDUMP_USER_STREAM_INFORMATION,*PMINIDUMP_USER_STREAM_INFORMATION; + + typedef enum _MINIDUMP_CALLBACK_TYPE { + ModuleCallback,ThreadCallback,ThreadExCallback,IncludeThreadCallback,IncludeModuleCallback,MemoryCallback + } MINIDUMP_CALLBACK_TYPE; + + typedef struct _MINIDUMP_THREAD_CALLBACK { + ULONG ThreadId; + HANDLE ThreadHandle; + CONTEXT Context; + ULONG SizeOfContext; + ULONG64 StackBase; + ULONG64 StackEnd; + } MINIDUMP_THREAD_CALLBACK,*PMINIDUMP_THREAD_CALLBACK; + + typedef struct _MINIDUMP_THREAD_EX_CALLBACK { + ULONG ThreadId; + HANDLE ThreadHandle; + CONTEXT Context; + ULONG SizeOfContext; + ULONG64 StackBase; + ULONG64 StackEnd; + ULONG64 BackingStoreBase; + ULONG64 BackingStoreEnd; + } MINIDUMP_THREAD_EX_CALLBACK,*PMINIDUMP_THREAD_EX_CALLBACK; + + typedef struct _MINIDUMP_INCLUDE_THREAD_CALLBACK { + ULONG ThreadId; + } MINIDUMP_INCLUDE_THREAD_CALLBACK,*PMINIDUMP_INCLUDE_THREAD_CALLBACK; + + typedef enum _THREAD_WRITE_FLAGS { + ThreadWriteThread = 0x0001,ThreadWriteStack = 0x0002,ThreadWriteContext = 0x0004,ThreadWriteBackingStore = 0x0008, + ThreadWriteInstructionWindow = 0x0010,ThreadWriteThreadData = 0x0020 + } THREAD_WRITE_FLAGS; + + typedef struct _MINIDUMP_MODULE_CALLBACK { + PWCHAR FullPath; + ULONG64 BaseOfImage; + ULONG SizeOfImage; + ULONG CheckSum; + ULONG TimeDateStamp; + VS_FIXEDFILEINFO VersionInfo; + PVOID CvRecord; + ULONG SizeOfCvRecord; + PVOID MiscRecord; + ULONG SizeOfMiscRecord; + } MINIDUMP_MODULE_CALLBACK,*PMINIDUMP_MODULE_CALLBACK; + + typedef struct _MINIDUMP_INCLUDE_MODULE_CALLBACK { + ULONG64 BaseOfImage; + } MINIDUMP_INCLUDE_MODULE_CALLBACK,*PMINIDUMP_INCLUDE_MODULE_CALLBACK; + + typedef enum _MODULE_WRITE_FLAGS { + ModuleWriteModule = 0x0001,ModuleWriteDataSeg = 0x0002,ModuleWriteMiscRecord = 0x0004,ModuleWriteCvRecord = 0x0008, + ModuleReferencedByMemory = 0x0010 + } MODULE_WRITE_FLAGS; + + typedef struct _MINIDUMP_CALLBACK_INPUT { + ULONG ProcessId; + HANDLE ProcessHandle; + ULONG CallbackType; + union { + MINIDUMP_THREAD_CALLBACK Thread; + MINIDUMP_THREAD_EX_CALLBACK ThreadEx; + MINIDUMP_MODULE_CALLBACK Module; + MINIDUMP_INCLUDE_THREAD_CALLBACK IncludeThread; + MINIDUMP_INCLUDE_MODULE_CALLBACK IncludeModule; + } DUMMYUNIONNAME; + } MINIDUMP_CALLBACK_INPUT,*PMINIDUMP_CALLBACK_INPUT; + + typedef struct _MINIDUMP_CALLBACK_OUTPUT { + union { + ULONG ModuleWriteFlags; + ULONG ThreadWriteFlags; + struct { + ULONG64 MemoryBase; + ULONG MemorySize; + } DUMMYSTRUCTNAME; + } DUMMYUNIONNAME; + } MINIDUMP_CALLBACK_OUTPUT,*PMINIDUMP_CALLBACK_OUTPUT; + + typedef enum _MINIDUMP_TYPE { + MiniDumpNormal = 0x0000,MiniDumpWithDataSegs = 0x0001,MiniDumpWithFullMemory = 0x0002,MiniDumpWithHandleData = 0x0004, + MiniDumpFilterMemory = 0x0008,MiniDumpScanMemory = 0x0010,MiniDumpWithUnloadedModules = 0x0020,MiniDumpWithIndirectlyReferencedMemory = 0x0040, + MiniDumpFilterModulePaths = 0x0080,MiniDumpWithProcessThreadData = 0x0100,MiniDumpWithPrivateReadWriteMemory = 0x0200, + MiniDumpWithoutOptionalData = 0x0400 + } MINIDUMP_TYPE; + + typedef BOOL (WINAPI *MINIDUMP_CALLBACK_ROUTINE)(PVOID CallbackParam,CONST PMINIDUMP_CALLBACK_INPUT CallbackInput,PMINIDUMP_CALLBACK_OUTPUT CallbackOutput); + + typedef struct _MINIDUMP_CALLBACK_INFORMATION { + MINIDUMP_CALLBACK_ROUTINE CallbackRoutine; + PVOID CallbackParam; + } MINIDUMP_CALLBACK_INFORMATION,*PMINIDUMP_CALLBACK_INFORMATION; + +#define RVA_TO_ADDR(Mapping,Rva) ((PVOID)(((ULONG_PTR) (Mapping)) + (Rva))) + + BOOL WINAPI MiniDumpWriteDump(HANDLE hProcess,DWORD ProcessId,HANDLE hFile,MINIDUMP_TYPE DumpType,CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam); + BOOL WINAPI MiniDumpReadDumpStream(PVOID BaseOfDump,ULONG StreamNumber,PMINIDUMP_DIRECTORY *Dir,PVOID *StreamPointer,ULONG *StreamSize); + +#include <poppack.h> + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/gallium/auxiliary/util/u_blit.c b/src/gallium/auxiliary/util/u_blit.c index c11f7d383db..76bd7ace526 100644 --- a/src/gallium/auxiliary/util/u_blit.c +++ b/src/gallium/auxiliary/util/u_blit.c @@ -199,6 +199,7 @@ get_next_slot( struct blit_state *ctx ) if (!ctx->vbuf) { ctx->vbuf = pipe_buffer_create(ctx->pipe->screen, PIPE_BIND_VERTEX_BUFFER, + PIPE_USAGE_STREAM, max_slots * sizeof ctx->vertices); } @@ -480,6 +481,7 @@ util_blit_pixels_writemask(struct blit_state *ctx, cso_save_vertex_shader(ctx->cso); cso_save_clip(ctx->cso); cso_save_vertex_elements(ctx->cso); + cso_save_vertex_buffers(ctx->cso); /* set misc state we care about */ cso_set_blend(ctx->cso, &ctx->blend); @@ -554,7 +556,7 @@ util_blit_pixels_writemask(struct blit_state *ctx, s1, t1, z); - util_draw_vertex_buffer(ctx->pipe, ctx->vbuf, offset, + util_draw_vertex_buffer(ctx->pipe, ctx->cso, ctx->vbuf, offset, PIPE_PRIM_TRIANGLE_FAN, 4, /* verts */ 2); /* attribs/vert */ @@ -571,6 +573,7 @@ util_blit_pixels_writemask(struct blit_state *ctx, cso_restore_vertex_shader(ctx->cso); cso_restore_clip(ctx->cso); cso_restore_vertex_elements(ctx->cso); + cso_restore_vertex_buffers(ctx->cso); pipe_sampler_view_reference(&sampler_view, NULL); } @@ -672,6 +675,7 @@ util_blit_pixels_tex(struct blit_state *ctx, cso_save_vertex_shader(ctx->cso); cso_save_clip(ctx->cso); cso_save_vertex_elements(ctx->cso); + cso_save_vertex_buffers(ctx->cso); /* set misc state we care about */ cso_set_blend(ctx->cso, &ctx->blend); @@ -722,7 +726,7 @@ util_blit_pixels_tex(struct blit_state *ctx, s0, t0, s1, t1, z); - util_draw_vertex_buffer(ctx->pipe, + util_draw_vertex_buffer(ctx->pipe, ctx->cso, ctx->vbuf, offset, PIPE_PRIM_TRIANGLE_FAN, 4, /* verts */ @@ -740,4 +744,5 @@ util_blit_pixels_tex(struct blit_state *ctx, cso_restore_vertex_shader(ctx->cso); cso_restore_clip(ctx->cso); cso_restore_vertex_elements(ctx->cso); + cso_restore_vertex_buffers(ctx->cso); } diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c index 545021d2642..fd1c2b72d04 100644 --- a/src/gallium/auxiliary/util/u_blitter.c +++ b/src/gallium/auxiliary/util/u_blitter.c @@ -86,7 +86,6 @@ struct blitter_context_priv void *dsa_write_depth_keep_stencil; void *dsa_keep_depth_stencil; void *dsa_keep_depth_write_stencil; - void *dsa_flush_depth_stencil; void *velem_state; @@ -156,10 +155,6 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe) ctx->dsa_keep_depth_stencil = pipe->create_depth_stencil_alpha_state(pipe, &dsa); - dsa.depth.writemask = 1; - ctx->dsa_flush_depth_stencil = - pipe->create_depth_stencil_alpha_state(pipe, &dsa); - dsa.depth.enabled = 1; dsa.depth.writemask = 1; dsa.depth.func = PIPE_FUNC_ALWAYS; @@ -225,9 +220,10 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe) ctx->vertices[i][0][3] = 1; /*v.w*/ /* create the vertex buffer */ - ctx->vbuf = pipe_buffer_create(ctx->base.pipe->screen, - PIPE_BIND_VERTEX_BUFFER, - sizeof(ctx->vertices)); + ctx->vbuf = pipe_user_buffer_create(ctx->base.pipe->screen, + ctx->vertices, + sizeof(ctx->vertices), + PIPE_BIND_VERTEX_BUFFER); return &ctx->base; } @@ -245,7 +241,6 @@ void util_blitter_destroy(struct blitter_context *blitter) ctx->dsa_write_depth_keep_stencil); pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil); pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil); - pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_flush_depth_stencil); pipe->delete_rasterizer_state(pipe, ctx->rs_state); pipe->delete_vs_state(pipe, ctx->vs); @@ -272,6 +267,12 @@ void util_blitter_destroy(struct blitter_context *blitter) static void blitter_check_saved_CSOs(struct blitter_context_priv *ctx) { + if (ctx->base.running) { + _debug_printf("u_blitter: Caught recursion on save. " + "This is a driver bug.\n"); + } + ctx->base.running = TRUE; + /* make sure these CSOs have been saved */ assert(ctx->base.saved_blend_state != INVALID_PTR && ctx->base.saved_dsa_state != INVALID_PTR && @@ -302,7 +303,6 @@ static void blitter_restore_CSOs(struct blitter_context_priv *ctx) ctx->base.saved_velem_state = INVALID_PTR; pipe->set_stencil_ref(pipe, &ctx->base.saved_stencil_ref); - pipe->set_viewport_state(pipe, &ctx->base.saved_viewport); pipe->set_clip_state(pipe, &ctx->base.saved_clip); @@ -346,6 +346,12 @@ static void blitter_restore_CSOs(struct blitter_context_priv *ctx) } ctx->base.saved_num_vertex_buffers = ~0; } + + if (!ctx->base.running) { + _debug_printf("u_blitter: Caught recursion on restore. " + "This is a driver bug.\n"); + } + ctx->base.running = FALSE; } static void blitter_set_rectangle(struct blitter_context_priv *ctx, @@ -509,22 +515,6 @@ static void blitter_set_dst_dimensions(struct blitter_context_priv *ctx, ctx->dst_height = height; } -static void blitter_draw_quad(struct blitter_context_priv *ctx) -{ - struct pipe_context *pipe = ctx->base.pipe; - struct pipe_box box; - - /* write vertices and draw them */ - u_box_1d(0, sizeof(ctx->vertices), &box); - pipe->transfer_inline_write(pipe, ctx->vbuf, 0, - PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD, - &box, ctx->vertices, sizeof(ctx->vertices), 0); - - util_draw_vertex_buffer(pipe, ctx->vbuf, 0, PIPE_PRIM_TRIANGLE_FAN, - 4, /* verts */ - 2); /* attribs/vert */ -} - static INLINE void **blitter_get_sampler_state(struct blitter_context_priv *ctx, int miplevel, boolean normalized) @@ -649,15 +639,19 @@ static void blitter_draw_rectangle(struct blitter_context *blitter, } blitter_set_rectangle(ctx, x1, y1, x2, y2, depth); - blitter_draw_quad(ctx); + ctx->base.pipe->redefine_user_buffer(ctx->base.pipe, ctx->vbuf, + 0, ctx->vbuf->width0); + util_draw_vertex_buffer(ctx->base.pipe, NULL, ctx->vbuf, 0, + PIPE_PRIM_TRIANGLE_FAN, 4, 2); } -void util_blitter_clear(struct blitter_context *blitter, - unsigned width, unsigned height, - unsigned num_cbufs, - unsigned clear_buffers, - const float *rgba, - double depth, unsigned stencil) +static void util_blitter_clear_custom(struct blitter_context *blitter, + unsigned width, unsigned height, + unsigned num_cbufs, + unsigned clear_buffers, + const float *rgba, + double depth, unsigned stencil, + void *custom_blend, void *custom_dsa) { struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; struct pipe_context *pipe = ctx->base.pipe; @@ -668,26 +662,28 @@ void util_blitter_clear(struct blitter_context *blitter, blitter_check_saved_CSOs(ctx); /* bind CSOs */ - if (clear_buffers & PIPE_CLEAR_COLOR) + if (custom_blend) { + pipe->bind_blend_state(pipe, custom_blend); + } else if (clear_buffers & PIPE_CLEAR_COLOR) { pipe->bind_blend_state(pipe, ctx->blend_write_color); - else + } else { pipe->bind_blend_state(pipe, ctx->blend_keep_color); + } - if ((clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) { - sr.ref_value[0] = stencil & 0xff; + if (custom_dsa) { + pipe->bind_depth_stencil_alpha_state(pipe, custom_dsa); + } else if ((clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) { pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil); - pipe->set_stencil_ref(pipe, &sr); - } - else if (clear_buffers & PIPE_CLEAR_DEPTH) { + } else if (clear_buffers & PIPE_CLEAR_DEPTH) { pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil); - } - else if (clear_buffers & PIPE_CLEAR_STENCIL) { - sr.ref_value[0] = stencil & 0xff; + } else if (clear_buffers & PIPE_CLEAR_STENCIL) { pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil); - pipe->set_stencil_ref(pipe, &sr); - } - else + } else { pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); + } + + sr.ref_value[0] = stencil & 0xff; + pipe->set_stencil_ref(pipe, &sr); pipe->bind_rasterizer_state(pipe, ctx->rs_state); pipe->bind_vertex_elements_state(pipe, ctx->velem_state); @@ -700,6 +696,27 @@ void util_blitter_clear(struct blitter_context *blitter, blitter_restore_CSOs(ctx); } +void util_blitter_clear(struct blitter_context *blitter, + unsigned width, unsigned height, + unsigned num_cbufs, + unsigned clear_buffers, + const float *rgba, + double depth, unsigned stencil) +{ + util_blitter_clear_custom(blitter, width, height, num_cbufs, + clear_buffers, rgba, depth, stencil, + NULL, NULL); +} + +void util_blitter_clear_depth_custom(struct blitter_context *blitter, + unsigned width, unsigned height, + double depth, void *custom_dsa) +{ + const float rgba[4] = {0, 0, 0, 0}; + util_blitter_clear_custom(blitter, width, height, 0, + 0, rgba, depth, 0, NULL, custom_dsa); +} + static boolean is_overlap(unsigned sx1, unsigned sx2, unsigned sy1, unsigned sy2, unsigned dx1, unsigned dx2, unsigned dy1, unsigned dy2) @@ -737,9 +754,6 @@ void util_blitter_copy_region(struct blitter_context *blitter, if (dst == src) { assert(!is_overlap(srcbox->x, srcbox->x + width, srcbox->y, srcbox->y + height, dstx, dstx + width, dsty, dsty + height)); - } else { - assert(util_is_format_compatible(util_format_description(src->format), - util_format_description(dst->format))); } assert(src->target < PIPE_MAX_TEXTURE_TYPES); /* XXX should handle 3d regions */ @@ -761,8 +775,10 @@ void util_blitter_copy_region(struct blitter_context *blitter, dst->nr_samples, bind, 0) || !screen->is_format_supported(screen, src->format, src->target, src->nr_samples, PIPE_BIND_SAMPLER_VIEW, 0)) { + ctx->base.running = TRUE; util_resource_copy_region(pipe, dst, dstlevel, dstx, dsty, dstz, src, srclevel, srcbox); + ctx->base.running = FALSE; return; } @@ -853,7 +869,10 @@ void util_blitter_copy_region(struct blitter_context *blitter, /* Draw. */ blitter_set_rectangle(ctx, dstx, dsty, dstx+width, dsty+height, 0); - blitter_draw_quad(ctx); + ctx->base.pipe->redefine_user_buffer(ctx->base.pipe, ctx->vbuf, + 0, ctx->vbuf->width0); + util_draw_vertex_buffer(ctx->base.pipe, NULL, ctx->vbuf, 0, + PIPE_PRIM_TRIANGLE_FAN, 4, 2); break; default: @@ -1014,12 +1033,3 @@ void util_blitter_custom_depth_stencil(struct blitter_context *blitter, UTIL_BLITTER_ATTRIB_NONE, NULL); blitter_restore_CSOs(ctx); } - -/* flush a region of a depth stencil surface for r300g */ -void util_blitter_flush_depth_stencil(struct blitter_context *blitter, - struct pipe_surface *dstsurf) -{ - struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; - util_blitter_custom_depth_stencil(blitter, dstsurf, NULL, - ctx->dsa_flush_depth_stencil, 0.0f); -} diff --git a/src/gallium/auxiliary/util/u_blitter.h b/src/gallium/auxiliary/util/u_blitter.h index 922a8580ac1..41470d92bba 100644 --- a/src/gallium/auxiliary/util/u_blitter.h +++ b/src/gallium/auxiliary/util/u_blitter.h @@ -55,13 +55,13 @@ struct blitter_context * \param y1 A Y coordinate of the top-left corner. * \param x2 An X coordinate of the bottom-right corner. * \param y2 A Y coordinate of the bottom-right corner. - * \param depth A depth which the rectangle is rendered at. + * \param depth A depth which the rectangle is rendered at. * * \param type Semantics of the attributes "attrib". * If type is UTIL_BLITTER_ATTRIB_NONE, ignore them. * If type is UTIL_BLITTER_ATTRIB_COLOR, the attributes - * make up a constant RGBA color, and should go to the COLOR0 - * varying slot of a fragment shader. + * make up a constant RGBA color, and should go + * to the GENERIC0 varying slot of a fragment shader. * If type is UTIL_BLITTER_ATTRIB_TEXCOORD, {a1, a2} and * {a3, a4} specify top-left and bottom-right texture * coordinates of the rectangle, respectively, and should go @@ -79,6 +79,9 @@ struct blitter_context enum blitter_attrib_type type, const float attrib[4]); + /* Whether the blitter is running. */ + boolean running; + /* Private members, really. */ struct pipe_context *pipe; /**< pipe context */ @@ -141,6 +144,10 @@ void util_blitter_clear(struct blitter_context *blitter, const float *rgba, double depth, unsigned stencil); +void util_blitter_clear_depth_custom(struct blitter_context *blitter, + unsigned width, unsigned height, + double depth, void *custom_dsa); + /** * Copy a block of pixels from one surface to another. * @@ -200,9 +207,6 @@ void util_blitter_clear_depth_stencil(struct blitter_context *blitter, unsigned dstx, unsigned dsty, unsigned width, unsigned height); -void util_blitter_flush_depth_stencil(struct blitter_context *blitter, - struct pipe_surface *dstsurf); - void util_blitter_custom_depth_stencil(struct blitter_context *blitter, struct pipe_surface *zsurf, struct pipe_surface *cbsurf, diff --git a/src/gallium/auxiliary/util/u_debug.c b/src/gallium/auxiliary/util/u_debug.c index f4ad545bee7..36ce4b57713 100644 --- a/src/gallium/auxiliary/util/u_debug.c +++ b/src/gallium/auxiliary/util/u_debug.c @@ -44,6 +44,7 @@ #include "util/u_surface.h" #include <limits.h> /* CHAR_BIT */ +#include <ctype.h> /* isalnum */ void _debug_vprintf(const char *format, va_list ap) { @@ -180,6 +181,48 @@ debug_get_num_option(const char *name, long dfault) return result; } +static boolean str_has_option(const char *str, const char *name) +{ + /* Empty string. */ + if (!*str) { + return FALSE; + } + + /* OPTION=all */ + if (!util_strcmp(str, "all")) { + return TRUE; + } + + /* Find 'name' in 'str' surrounded by non-alphanumeric characters. */ + { + const char *start = str; + unsigned name_len = strlen(name); + + /* 'start' is the beginning of the currently-parsed word, + * we increment 'str' each iteration. + * if we find either the end of string or a non-alphanumeric character, + * we compare 'start' up to 'str-1' with 'name'. */ + + while (1) { + if (!*str || !isalnum(*str)) { + if (str-start == name_len && + !memcmp(start, name, name_len)) { + return TRUE; + } + + if (!*str) { + return FALSE; + } + + start = str+1; + } + + str++; + } + } + + return FALSE; +} unsigned long debug_get_flags_option(const char *name, @@ -207,7 +250,7 @@ debug_get_flags_option(const char *name, else { result = 0; while( flags->name ) { - if (!util_strcmp(str, "all") || util_strstr(str, flags->name )) + if (str_has_option(str, flags->name)) result |= flags->value; ++flags; } @@ -359,6 +402,41 @@ const char *u_prim_name( unsigned prim ) +#ifdef DEBUG +int fl_indent = 0; +const char* fl_function[1024]; + +int debug_funclog_enter(const char* f, const int line, const char* file) +{ + int i; + + for (i = 0; i < fl_indent; i++) + debug_printf(" "); + debug_printf("%s\n", f); + + assert(fl_indent < 1023); + fl_function[fl_indent++] = f; + + return 0; +} + +void debug_funclog_exit(const char* f, const int line, const char* file) +{ + --fl_indent; + assert(fl_indent >= 0); + assert(fl_function[fl_indent] == f); +} + +void debug_funclog_enter_exit(const char* f, const int line, const char* file) +{ + int i; + for (i = 0; i < fl_indent; i++) + debug_printf(" "); + debug_printf("%s\n", f); +} +#endif + + #ifdef DEBUG /** diff --git a/src/gallium/auxiliary/util/u_debug.h b/src/gallium/auxiliary/util/u_debug.h index 1c9624ea3ed..c47c13c64cf 100644 --- a/src/gallium/auxiliary/util/u_debug.h +++ b/src/gallium/auxiliary/util/u_debug.h @@ -280,6 +280,43 @@ debug_dump_flags(const struct debug_named_value *names, /** + * Function enter exit loggers + */ +#ifdef DEBUG +int debug_funclog_enter(const char* f, const int line, const char* file); +void debug_funclog_exit(const char* f, const int line, const char* file); +void debug_funclog_enter_exit(const char* f, const int line, const char* file); + +#define DEBUG_FUNCLOG_ENTER() \ + int __debug_decleration_work_around = \ + debug_funclog_enter(__FUNCTION__, __LINE__, __FILE__) +#define DEBUG_FUNCLOG_EXIT() \ + do { \ + (void)__debug_decleration_work_around; \ + debug_funclog_exit(__FUNCTION__, __LINE__, __FILE__); \ + return; \ + } while(0) +#define DEBUG_FUNCLOG_EXIT_RET(ret) \ + do { \ + (void)__debug_decleration_work_around; \ + debug_funclog_exit(__FUNCTION__, __LINE__, __FILE__); \ + return ret; \ + } while(0) +#define DEBUG_FUNCLOG_ENTER_EXIT() \ + debug_funclog_enter_exit(__FUNCTION__, __LINE__, __FILE__) + +#else +#define DEBUG_FUNCLOG_ENTER() \ + int __debug_decleration_work_around +#define DEBUG_FUNCLOG_EXIT() \ + do { (void)__debug_decleration_work_around; return; } while(0) +#define DEBUG_FUNCLOG_EXIT_RET(ret) \ + do { (void)__debug_decleration_work_around; return ret; } while(0) +#define DEBUG_FUNCLOG_ENTER_EXIT() +#endif + + +/** * Get option. * * It is an alias for getenv on Linux. diff --git a/src/gallium/auxiliary/util/u_debug_refcnt.c b/src/gallium/auxiliary/util/u_debug_refcnt.c index 40a26c9c697..6f706a35fda 100644 --- a/src/gallium/auxiliary/util/u_debug_refcnt.c +++ b/src/gallium/auxiliary/util/u_debug_refcnt.c @@ -43,7 +43,8 @@ int debug_refcnt_state; struct os_stream* stream; /* TODO: maybe move this serial machinery to a stand-alone module and expose it? */ -static pipe_mutex serials_mutex; +pipe_static_mutex(serials_mutex); + static struct util_hash_table* serials_hash; static unsigned serials_last; @@ -66,6 +67,15 @@ static boolean debug_serial(void* p, unsigned* pserial) { unsigned serial; boolean found = TRUE; +#ifdef PIPE_SUBSYSTEM_WINDOWS_USER + static boolean first = TRUE; + + if (first) { + pipe_mutex_init(serials_mutex); + first = FALSE; + } +#endif + pipe_mutex_lock(serials_mutex); if(!serials_hash) serials_hash = util_hash_table_create(hash_ptr, compare_ptr); diff --git a/src/gallium/auxiliary/util/u_debug_symbol.c b/src/gallium/auxiliary/util/u_debug_symbol.c index 44d437747a1..bae9be87a26 100644 --- a/src/gallium/auxiliary/util/u_debug_symbol.c +++ b/src/gallium/auxiliary/util/u_debug_symbol.c @@ -40,20 +40,43 @@ #include "u_debug_symbol.h" #include "u_hash_table.h" -#if defined(PIPE_CC_MSVC) && defined(PIPE_ARCH_X86) +#if defined(PIPE_OS_WINDOWS) && defined(PIPE_ARCH_X86) #include <windows.h> #include <stddef.h> -#include <imagehlp.h> -/* - * TODO: Cleanup code. - * TODO: Support x86_64 - */ +#include "dbghelp.h" + static BOOL bSymInitialized = FALSE; -static HMODULE hModule_Imagehlp = NULL; +static HMODULE hModule_Dbghelp = NULL; + + +static +FARPROC WINAPI __GetProcAddress(LPCSTR lpProcName) +{ +#ifdef PIPE_CC_GCC + if (!hModule_Dbghelp) { + /* + * bfdhelp.dll is a dbghelp.dll look-alike replacement, which is able to + * understand MinGW symbols using BFD library. It is available from + * http://people.freedesktop.org/~jrfonseca/bfdhelp/ for now. + */ + hModule_Dbghelp = LoadLibraryA("bfdhelp.dll"); + } +#endif + + if (!hModule_Dbghelp) { + hModule_Dbghelp = LoadLibraryA("dbghelp.dll"); + if (!hModule_Dbghelp) { + return NULL; + } + } + + return GetProcAddress(hModule_Dbghelp, lpProcName); +} + typedef BOOL (WINAPI *PFNSYMINITIALIZE)(HANDLE, LPSTR, BOOL); static PFNSYMINITIALIZE pfnSymInitialize = NULL; @@ -62,8 +85,7 @@ static BOOL WINAPI j_SymInitialize(HANDLE hProcess, PSTR UserSearchPath, BOOL fInvadeProcess) { if( - (hModule_Imagehlp || (hModule_Imagehlp = LoadLibraryA("IMAGEHLP.DLL"))) && - (pfnSymInitialize || (pfnSymInitialize = (PFNSYMINITIALIZE) GetProcAddress(hModule_Imagehlp, "SymInitialize"))) + (pfnSymInitialize || (pfnSymInitialize = (PFNSYMINITIALIZE) __GetProcAddress("SymInitialize"))) ) return pfnSymInitialize(hProcess, UserSearchPath, fInvadeProcess); else @@ -77,57 +99,41 @@ static DWORD WINAPI j_SymSetOptions(DWORD SymOptions) { if( - (hModule_Imagehlp || (hModule_Imagehlp = LoadLibraryA("IMAGEHLP.DLL"))) && - (pfnSymSetOptions || (pfnSymSetOptions = (PFNSYMSETOPTIONS) GetProcAddress(hModule_Imagehlp, "SymSetOptions"))) + (pfnSymSetOptions || (pfnSymSetOptions = (PFNSYMSETOPTIONS) __GetProcAddress("SymSetOptions"))) ) return pfnSymSetOptions(SymOptions); else return FALSE; } -typedef PGET_MODULE_BASE_ROUTINE PFNSYMGETMODULEBASE; -static PFNSYMGETMODULEBASE pfnSymGetModuleBase = NULL; +typedef BOOL (WINAPI *PFNSYMGETSYMFROMADDR)(HANDLE, DWORD64, PDWORD64, PSYMBOL_INFO); +static PFNSYMGETSYMFROMADDR pfnSymFromAddr = NULL; static -DWORD WINAPI j_SymGetModuleBase(HANDLE hProcess, DWORD dwAddr) +BOOL WINAPI j_SymFromAddr(HANDLE hProcess, DWORD64 Address, PDWORD64 Displacement, PSYMBOL_INFO Symbol) { if( - (hModule_Imagehlp || (hModule_Imagehlp = LoadLibraryA("IMAGEHLP.DLL"))) && - (pfnSymGetModuleBase || (pfnSymGetModuleBase = (PFNSYMGETMODULEBASE) GetProcAddress(hModule_Imagehlp, "SymGetModuleBase"))) + (pfnSymFromAddr || (pfnSymFromAddr = (PFNSYMGETSYMFROMADDR) __GetProcAddress("SymFromAddr"))) ) - return pfnSymGetModuleBase(hProcess, dwAddr); - else - return 0; -} - -typedef BOOL (WINAPI *PFNSYMGETSYMFROMADDR)(HANDLE, DWORD, LPDWORD, PIMAGEHLP_SYMBOL); -static PFNSYMGETSYMFROMADDR pfnSymGetSymFromAddr = NULL; - -static -BOOL WINAPI j_SymGetSymFromAddr(HANDLE hProcess, DWORD Address, PDWORD Displacement, PIMAGEHLP_SYMBOL Symbol) -{ - if( - (hModule_Imagehlp || (hModule_Imagehlp = LoadLibraryA("IMAGEHLP.DLL"))) && - (pfnSymGetSymFromAddr || (pfnSymGetSymFromAddr = (PFNSYMGETSYMFROMADDR) GetProcAddress(hModule_Imagehlp, "SymGetSymFromAddr"))) - ) - return pfnSymGetSymFromAddr(hProcess, Address, Displacement, Symbol); + return pfnSymFromAddr(hProcess, Address, Displacement, Symbol); else return FALSE; } static INLINE void -debug_symbol_name_imagehlp(const void *addr, char* buf, unsigned size) +debug_symbol_name_dbghelp(const void *addr, char* buf, unsigned size) { HANDLE hProcess; BYTE symbolBuffer[1024]; - PIMAGEHLP_SYMBOL pSymbol = (PIMAGEHLP_SYMBOL) symbolBuffer; - DWORD dwDisplacement = 0; /* Displacement of the input address, relative to the start of the symbol */ + PSYMBOL_INFO pSymbol = (PSYMBOL_INFO) symbolBuffer; + DWORD64 dwDisplacement = 0; /* Displacement of the input address, relative to the start of the symbol */ hProcess = GetCurrentProcess(); + memset(pSymbol, 0, sizeof *pSymbol); pSymbol->SizeOfStruct = sizeof(symbolBuffer); - pSymbol->MaxNameLength = sizeof(symbolBuffer) - offsetof(IMAGEHLP_SYMBOL, Name); + pSymbol->MaxNameLen = sizeof(symbolBuffer) - offsetof(SYMBOL_INFO, Name); if(!bSymInitialized) { j_SymSetOptions(/* SYMOPT_UNDNAME | */ SYMOPT_LOAD_LINES); @@ -135,7 +141,7 @@ debug_symbol_name_imagehlp(const void *addr, char* buf, unsigned size) bSymInitialized = TRUE; } - if(!j_SymGetSymFromAddr(hProcess, (DWORD)addr, &dwDisplacement, pSymbol)) + if(!j_SymFromAddr(hProcess, (DWORD64)(uintptr_t)addr, &dwDisplacement, pSymbol)) buf[0] = 0; else { @@ -165,8 +171,8 @@ debug_symbol_name_glibc(const void *addr, char* buf, unsigned size) void debug_symbol_name(const void *addr, char* buf, unsigned size) { -#if defined(PIPE_CC_MSVC) && defined(PIPE_ARCH_X86) - debug_symbol_name_imagehlp(addr, buf, size); +#if defined(PIPE_OS_WINDOWS) && defined(PIPE_ARCH_X86) + debug_symbol_name_dbghelp(addr, buf, size); if(buf[0]) return; #endif @@ -190,7 +196,7 @@ debug_symbol_print(const void *addr) } struct util_hash_table* symbols_hash; -pipe_mutex symbols_mutex; +pipe_static_mutex(symbols_mutex); static unsigned hash_ptr(void* p) { @@ -211,6 +217,15 @@ const char* debug_symbol_name_cached(const void *addr) { const char* name; +#ifdef PIPE_SUBSYSTEM_WINDOWS_USER + static boolean first = TRUE; + + if (first) { + pipe_mutex_init(symbols_mutex); + first = FALSE; + } +#endif + pipe_mutex_lock(symbols_mutex); if(!symbols_hash) symbols_hash = util_hash_table_create(hash_ptr, compare_ptr); diff --git a/src/gallium/auxiliary/util/u_draw_quad.c b/src/gallium/auxiliary/util/u_draw_quad.c index 0b6dc5880f3..0defd919974 100644 --- a/src/gallium/auxiliary/util/u_draw_quad.c +++ b/src/gallium/auxiliary/util/u_draw_quad.c @@ -31,6 +31,7 @@ #include "util/u_inlines.h" #include "util/u_draw_quad.h" #include "util/u_memory.h" +#include "cso_cache/cso_context.h" /** @@ -39,6 +40,7 @@ */ void util_draw_vertex_buffer(struct pipe_context *pipe, + struct cso_context *cso, struct pipe_resource *vbuf, uint offset, uint prim_type, @@ -54,8 +56,12 @@ util_draw_vertex_buffer(struct pipe_context *pipe, vbuffer.buffer = vbuf; vbuffer.stride = num_attribs * 4 * sizeof(float); /* vertex size */ vbuffer.buffer_offset = offset; - vbuffer.max_index = num_verts - 1; - pipe->set_vertex_buffers(pipe, 1, &vbuffer); + + if (cso) { + cso_set_vertex_buffers(cso, 1, &vbuffer); + } else { + pipe->set_vertex_buffers(pipe, 1, &vbuffer); + } /* note: vertex elements already set by caller */ @@ -70,7 +76,7 @@ util_draw_vertex_buffer(struct pipe_context *pipe, * Note: this isn't especially efficient. */ void -util_draw_texquad(struct pipe_context *pipe, +util_draw_texquad(struct pipe_context *pipe, struct cso_context *cso, float x0, float y0, float x1, float y1, float z) { uint numAttribs = 2, i, j; @@ -118,7 +124,7 @@ util_draw_texquad(struct pipe_context *pipe, if (!vbuf) goto out; - util_draw_vertex_buffer(pipe, vbuf, 0, PIPE_PRIM_TRIANGLE_FAN, 4, 2); + util_draw_vertex_buffer(pipe, cso, vbuf, 0, PIPE_PRIM_TRIANGLE_FAN, 4, 2); out: if (vbuf) diff --git a/src/gallium/auxiliary/util/u_draw_quad.h b/src/gallium/auxiliary/util/u_draw_quad.h index 52994fe05c3..f1167786f0e 100644 --- a/src/gallium/auxiliary/util/u_draw_quad.h +++ b/src/gallium/auxiliary/util/u_draw_quad.h @@ -38,17 +38,18 @@ extern "C" { #endif struct pipe_resource; +struct cso_context; #include "util/u_draw.h" extern void -util_draw_vertex_buffer(struct pipe_context *pipe, +util_draw_vertex_buffer(struct pipe_context *pipe, struct cso_context *cso, struct pipe_resource *vbuf, uint offset, uint num_attribs, uint num_verts, uint prim_type); extern void -util_draw_texquad(struct pipe_context *pipe, +util_draw_texquad(struct pipe_context *pipe, struct cso_context *cso, float x0, float y0, float x1, float y1, float z); diff --git a/src/gallium/auxiliary/util/u_dump_state.c b/src/gallium/auxiliary/util/u_dump_state.c index b471d59eebf..5ecf8cbb067 100644 --- a/src/gallium/auxiliary/util/u_dump_state.c +++ b/src/gallium/auxiliary/util/u_dump_state.c @@ -681,7 +681,6 @@ util_dump_vertex_buffer(struct os_stream *stream, const struct pipe_vertex_buffe util_dump_struct_begin(stream, "pipe_vertex_buffer"); util_dump_member(stream, uint, state, stride); - util_dump_member(stream, uint, state, max_index); util_dump_member(stream, uint, state, buffer_offset); util_dump_member(stream, ptr, state, buffer); diff --git a/src/gallium/auxiliary/util/u_format.h b/src/gallium/auxiliary/util/u_format.h index 03b73c0e98f..7659a802a41 100644 --- a/src/gallium/auxiliary/util/u_format.h +++ b/src/gallium/auxiliary/util/u_format.h @@ -673,7 +673,8 @@ util_format_has_alpha(enum pipe_format format) } /** - * Return the matching SRGB format, or PIPE_FORMAT_NONE if none. + * Given a linear RGB colorspace format, return the corresponding SRGB + * format, or PIPE_FORMAT_NONE if none. */ static INLINE enum pipe_format util_format_srgb(enum pipe_format format) @@ -711,6 +712,45 @@ util_format_srgb(enum pipe_format format) } /** + * Given an sRGB format, return the corresponding linear colorspace format. + * For non sRGB formats, return the format unchanged. + */ +static INLINE enum pipe_format +util_format_linear(enum pipe_format format) +{ + switch (format) { + case PIPE_FORMAT_L8_SRGB: + return PIPE_FORMAT_L8_UNORM; + case PIPE_FORMAT_L8A8_SRGB: + return PIPE_FORMAT_L8A8_UNORM; + case PIPE_FORMAT_R8G8B8_SRGB: + return PIPE_FORMAT_R8G8B8_UNORM; + case PIPE_FORMAT_A8B8G8R8_SRGB: + return PIPE_FORMAT_A8B8G8R8_UNORM; + case PIPE_FORMAT_X8B8G8R8_SRGB: + return PIPE_FORMAT_X8B8G8R8_UNORM; + case PIPE_FORMAT_B8G8R8A8_SRGB: + return PIPE_FORMAT_B8G8R8A8_UNORM; + case PIPE_FORMAT_B8G8R8X8_SRGB: + return PIPE_FORMAT_B8G8R8X8_UNORM; + case PIPE_FORMAT_A8R8G8B8_SRGB: + return PIPE_FORMAT_A8R8G8B8_UNORM; + case PIPE_FORMAT_X8R8G8B8_SRGB: + return PIPE_FORMAT_X8R8G8B8_UNORM; + case PIPE_FORMAT_DXT1_SRGB: + return PIPE_FORMAT_DXT1_RGB; + case PIPE_FORMAT_DXT1_SRGBA: + return PIPE_FORMAT_DXT1_RGBA; + case PIPE_FORMAT_DXT3_SRGBA: + return PIPE_FORMAT_DXT3_RGBA; + case PIPE_FORMAT_DXT5_SRGBA: + return PIPE_FORMAT_DXT5_RGBA; + default: + return format; + } +} + +/** * Return the number of components stored. * Formats with block size != 1x1 will always have 1 component (the block). */ diff --git a/src/gallium/auxiliary/util/u_gen_mipmap.c b/src/gallium/auxiliary/util/u_gen_mipmap.c index d22ae8b375b..3b6342ad8d1 100644 --- a/src/gallium/auxiliary/util/u_gen_mipmap.c +++ b/src/gallium/auxiliary/util/u_gen_mipmap.c @@ -1350,6 +1350,7 @@ get_next_slot(struct gen_mipmap_state *ctx) if (!ctx->vbuf) { ctx->vbuf = pipe_buffer_create(ctx->pipe->screen, PIPE_BIND_VERTEX_BUFFER, + PIPE_USAGE_STREAM, max_slots * sizeof ctx->vertices); } @@ -1616,7 +1617,8 @@ util_gen_mipmap(struct gen_mipmap_state *ctx, face, rcoord); - util_draw_vertex_buffer(ctx->pipe, + util_draw_vertex_buffer(ctx->pipe, + ctx->cso, ctx->vbuf, offset, PIPE_PRIM_TRIANGLE_FAN, diff --git a/src/gallium/auxiliary/util/u_index_modify.c b/src/gallium/auxiliary/util/u_index_modify.c index f2c9db3caf1..d0a28b5fdfa 100644 --- a/src/gallium/auxiliary/util/u_index_modify.c +++ b/src/gallium/auxiliary/util/u_index_modify.c @@ -38,7 +38,10 @@ void util_shorten_ubyte_elts_to_userptr(struct pipe_context *context, unsigned short *out_map = out; unsigned i; - in_map = pipe_buffer_map(context, elts, PIPE_TRANSFER_READ, &src_transfer); + in_map = pipe_buffer_map(context, elts, + PIPE_TRANSFER_READ | + PIPE_TRANSFER_UNSYNCHRONIZED, + &src_transfer); in_map += start; for (i = 0; i < count; i++) { @@ -62,6 +65,7 @@ void util_shorten_ubyte_elts(struct pipe_context *context, new_elts = pipe_buffer_create(context->screen, PIPE_BIND_INDEX_BUFFER, + PIPE_USAGE_STATIC, 2 * count); out_map = pipe_buffer_map(context, new_elts, PIPE_TRANSFER_WRITE, @@ -87,7 +91,10 @@ void util_rebuild_ushort_elts_to_userptr(struct pipe_context *context, unsigned short *out_map = out; unsigned i; - in_map = pipe_buffer_map(context, elts, PIPE_TRANSFER_READ, &in_transfer); + in_map = pipe_buffer_map(context, elts, + PIPE_TRANSFER_READ | + PIPE_TRANSFER_UNSYNCHRONIZED, + &in_transfer); in_map += start; for (i = 0; i < count; i++) { @@ -110,6 +117,7 @@ void util_rebuild_ushort_elts(struct pipe_context *context, new_elts = pipe_buffer_create(context->screen, PIPE_BIND_INDEX_BUFFER, + PIPE_USAGE_STATIC, 2 * count); out_map = pipe_buffer_map(context, new_elts, @@ -135,7 +143,10 @@ void util_rebuild_uint_elts_to_userptr(struct pipe_context *context, unsigned int *out_map = out; unsigned i; - in_map = pipe_buffer_map(context, elts, PIPE_TRANSFER_READ, &in_transfer); + in_map = pipe_buffer_map(context, elts, + PIPE_TRANSFER_READ | + PIPE_TRANSFER_UNSYNCHRONIZED, + &in_transfer); in_map += start; for (i = 0; i < count; i++) { @@ -158,6 +169,7 @@ void util_rebuild_uint_elts(struct pipe_context *context, new_elts = pipe_buffer_create(context->screen, PIPE_BIND_INDEX_BUFFER, + PIPE_USAGE_STATIC, 2 * count); out_map = pipe_buffer_map(context, new_elts, diff --git a/src/gallium/auxiliary/util/u_inlines.h b/src/gallium/auxiliary/util/u_inlines.h index b4870bce981..98889fb70ac 100644 --- a/src/gallium/auxiliary/util/u_inlines.h +++ b/src/gallium/auxiliary/util/u_inlines.h @@ -160,6 +160,21 @@ pipe_surface_init(struct pipe_context *ctx, struct pipe_surface* ps, pipe_surface_reset(ctx, ps, pt, level, layer, flags); } +/* Return true if the surfaces are equal. */ +static INLINE boolean +pipe_surface_equal(struct pipe_surface *s1, struct pipe_surface *s2) +{ + return s1->texture == s2->texture && + s1->format == s2->format && + (s1->texture->target != PIPE_BUFFER || + (s1->u.buf.first_element == s2->u.buf.first_element && + s1->u.buf.last_element == s2->u.buf.last_element)) && + (s1->texture->target == PIPE_BUFFER || + (s1->u.tex.level == s2->u.tex.level && + s1->u.tex.first_layer == s2->u.tex.first_layer && + s1->u.tex.last_layer == s2->u.tex.last_layer)); +} + /* * Convenience wrappers for screen buffer functions. */ @@ -167,6 +182,7 @@ pipe_surface_init(struct pipe_context *ctx, struct pipe_surface* ps, static INLINE struct pipe_resource * pipe_buffer_create( struct pipe_screen *screen, unsigned bind, + unsigned usage, unsigned size ) { struct pipe_resource buffer; @@ -174,7 +190,7 @@ pipe_buffer_create( struct pipe_screen *screen, buffer.target = PIPE_BUFFER; buffer.format = PIPE_FORMAT_R8_UNORM; /* want TYPELESS or similar */ buffer.bind = bind; - buffer.usage = PIPE_USAGE_DEFAULT; + buffer.usage = usage; buffer.flags = 0; buffer.width0 = size; buffer.height0 = 1; @@ -220,6 +236,7 @@ pipe_buffer_map_range(struct pipe_context *pipe, map = pipe->transfer_map( pipe, *transfer ); if (map == NULL) { pipe->transfer_destroy( pipe, *transfer ); + *transfer = NULL; return NULL; } diff --git a/src/gallium/auxiliary/util/u_math.h b/src/gallium/auxiliary/util/u_math.h index 37294b7203f..30555f92a6d 100644 --- a/src/gallium/auxiliary/util/u_math.h +++ b/src/gallium/auxiliary/util/u_math.h @@ -176,7 +176,7 @@ static INLINE float logf( float f ) #define isfinite(x) _finite((double)(x)) #define isnan(x) _isnan((double)(x)) -#endif +#endif /* _MSC_VER < 1400 && !defined(__cplusplus) */ static INLINE double log2( double x ) { @@ -184,6 +184,18 @@ static INLINE double log2( double x ) return log( x ) * invln2; } +static INLINE double +round(double x) +{ + return x >= 0.0 ? floor(x + 0.5) : ceil(x - 0.5); +} + +static INLINE float +roundf(float x) +{ + return x >= 0.0f ? floorf(x + 0.5f) : ceilf(x - 0.5f); +} + #endif /* _MSC_VER */ diff --git a/src/gallium/auxiliary/util/u_resource.c b/src/gallium/auxiliary/util/u_resource.c index 443c9f8067e..ea6896b430f 100644 --- a/src/gallium/auxiliary/util/u_resource.c +++ b/src/gallium/auxiliary/util/u_resource.c @@ -35,7 +35,7 @@ unsigned u_is_resource_referenced_vtbl( struct pipe_context *pipe, struct pipe_transfer *u_get_transfer_vtbl(struct pipe_context *context, struct pipe_resource *resource, unsigned level, - enum pipe_transfer_usage usage, + unsigned usage, const struct pipe_box *box) { struct u_resource *ur = u_resource(resource); diff --git a/src/gallium/auxiliary/util/u_tile.c b/src/gallium/auxiliary/util/u_tile.c index 44cadbfcdd0..e3c7085ba92 100644 --- a/src/gallium/auxiliary/util/u_tile.c +++ b/src/gallium/auxiliary/util/u_tile.c @@ -367,47 +367,19 @@ pipe_get_tile_rgba(struct pipe_context *pipe, uint x, uint y, uint w, uint h, float *p) { - unsigned dst_stride = w * 4; - void *packed; - enum pipe_format format = pt->resource->format; - - if (u_clip_tile(x, y, &w, &h, &pt->box)) - return; - - packed = MALLOC(util_format_get_nblocks(format, w, h) * util_format_get_blocksize(format)); - - if (!packed) - return; - - if(format == PIPE_FORMAT_UYVY || format == PIPE_FORMAT_YUYV) - assert((x & 1) == 0); - - pipe_get_tile_raw(pipe, pt, x, y, w, h, packed, 0); - - pipe_tile_raw_to_rgba(format, packed, w, h, p, dst_stride); - - FREE(packed); + pipe_get_tile_rgba_format(pipe, pt, x, y, w, h, pt->resource->format, p); } void -pipe_get_tile_swizzle(struct pipe_context *pipe, - struct pipe_transfer *pt, - uint x, - uint y, - uint w, - uint h, - uint swizzle_r, - uint swizzle_g, - uint swizzle_b, - uint swizzle_a, - enum pipe_format format, - float *p) +pipe_get_tile_rgba_format(struct pipe_context *pipe, + struct pipe_transfer *pt, + uint x, uint y, uint w, uint h, + enum pipe_format format, + float *p) { unsigned dst_stride = w * 4; void *packed; - uint iy; - float rgba01[6]; if (u_clip_tile(x, y, &w, &h, &pt->box)) { return; @@ -427,35 +399,6 @@ pipe_get_tile_swizzle(struct pipe_context *pipe, pipe_tile_raw_to_rgba(format, packed, w, h, p, dst_stride); FREE(packed); - - if (swizzle_r == PIPE_SWIZZLE_RED && - swizzle_g == PIPE_SWIZZLE_GREEN && - swizzle_b == PIPE_SWIZZLE_BLUE && - swizzle_a == PIPE_SWIZZLE_ALPHA) { - /* no-op, skip */ - return; - } - - rgba01[PIPE_SWIZZLE_ZERO] = 0.0f; - rgba01[PIPE_SWIZZLE_ONE] = 1.0f; - - for (iy = 0; iy < h; iy++) { - float *row = p; - uint ix; - - for (ix = 0; ix < w; ix++) { - rgba01[PIPE_SWIZZLE_RED] = row[0]; - rgba01[PIPE_SWIZZLE_GREEN] = row[1]; - rgba01[PIPE_SWIZZLE_BLUE] = row[2]; - rgba01[PIPE_SWIZZLE_ALPHA] = row[3]; - - *row++ = rgba01[swizzle_r]; - *row++ = rgba01[swizzle_g]; - *row++ = rgba01[swizzle_b]; - *row++ = rgba01[swizzle_a]; - } - p += dst_stride; - } } @@ -465,9 +408,19 @@ pipe_put_tile_rgba(struct pipe_context *pipe, uint x, uint y, uint w, uint h, const float *p) { + pipe_put_tile_rgba_format(pipe, pt, x, y, w, h, pt->resource->format, p); +} + + +void +pipe_put_tile_rgba_format(struct pipe_context *pipe, + struct pipe_transfer *pt, + uint x, uint y, uint w, uint h, + enum pipe_format format, + const float *p) +{ unsigned src_stride = w * 4; void *packed; - enum pipe_format format = pt->resource->format; if (u_clip_tile(x, y, &w, &h, &pt->box)) return; diff --git a/src/gallium/auxiliary/util/u_tile.h b/src/gallium/auxiliary/util/u_tile.h index 558351d0ce5..0ba274308fe 100644 --- a/src/gallium/auxiliary/util/u_tile.h +++ b/src/gallium/auxiliary/util/u_tile.h @@ -80,18 +80,11 @@ pipe_get_tile_rgba(struct pipe_context *pipe, float *p); void -pipe_get_tile_swizzle(struct pipe_context *pipe, - struct pipe_transfer *pt, - uint x, - uint y, - uint w, - uint h, - uint swizzle_r, - uint swizzle_g, - uint swizzle_b, - uint swizzle_a, - enum pipe_format format, - float *p); +pipe_get_tile_rgba_format(struct pipe_context *pipe, + struct pipe_transfer *pt, + uint x, uint y, uint w, uint h, + enum pipe_format format, + float *p); void pipe_put_tile_rgba(struct pipe_context *pipe, @@ -99,6 +92,13 @@ pipe_put_tile_rgba(struct pipe_context *pipe, uint x, uint y, uint w, uint h, const float *p); +void +pipe_put_tile_rgba_format(struct pipe_context *pipe, + struct pipe_transfer *pt, + uint x, uint y, uint w, uint h, + enum pipe_format format, + const float *p); + void pipe_get_tile_z(struct pipe_context *pipe, diff --git a/src/gallium/auxiliary/util/u_transfer.c b/src/gallium/auxiliary/util/u_transfer.c index e2828cfd99e..b6c63d9642f 100644 --- a/src/gallium/auxiliary/util/u_transfer.c +++ b/src/gallium/auxiliary/util/u_transfer.c @@ -112,3 +112,10 @@ void u_default_transfer_destroy(struct pipe_context *pipe, FREE(transfer); } +void u_default_redefine_user_buffer(struct pipe_context *ctx, + struct pipe_resource *resource, + unsigned offset, + unsigned size) +{ + resource->width0 = MAX2(resource->width0, offset + size); +} diff --git a/src/gallium/auxiliary/util/u_transfer.h b/src/gallium/auxiliary/util/u_transfer.h index 3412e13c3cc..8cf9c418b04 100644 --- a/src/gallium/auxiliary/util/u_transfer.h +++ b/src/gallium/auxiliary/util/u_transfer.h @@ -93,7 +93,7 @@ struct u_resource_vtbl { struct u_resource { struct pipe_resource b; - struct u_resource_vtbl *vtbl; + const struct u_resource_vtbl *vtbl; }; @@ -136,11 +136,9 @@ void u_transfer_inline_write_vtbl( struct pipe_context *rm_ctx, unsigned stride, unsigned layer_stride); - - - - - - +void u_default_redefine_user_buffer(struct pipe_context *ctx, + struct pipe_resource *resource, + unsigned offset, + unsigned size); #endif diff --git a/src/gallium/auxiliary/util/u_upload_mgr.c b/src/gallium/auxiliary/util/u_upload_mgr.c index 3b3d5b418fe..dcf800a1e8e 100644 --- a/src/gallium/auxiliary/util/u_upload_mgr.c +++ b/src/gallium/auxiliary/util/u_upload_mgr.c @@ -85,7 +85,12 @@ void u_upload_flush( struct u_upload_mgr *upload ) { /* Unmap and unreference the upload buffer. */ if (upload->transfer) { + if (upload->size) { + pipe_buffer_flush_mapped_range(upload->pipe, upload->transfer, + 0, upload->size); + } pipe_transfer_unmap(upload->pipe, upload->transfer); + pipe_transfer_destroy(upload->pipe, upload->transfer); upload->transfer = NULL; } pipe_resource_reference( &upload->buffer, NULL ); @@ -116,13 +121,17 @@ u_upload_alloc_buffer( struct u_upload_mgr *upload, upload->buffer = pipe_buffer_create( upload->pipe->screen, upload->bind, + PIPE_USAGE_STREAM, size ); if (upload->buffer == NULL) goto fail; /* Map the new buffer. */ - upload->map = pipe_buffer_map(upload->pipe, upload->buffer, - PIPE_TRANSFER_WRITE, &upload->transfer); + upload->map = pipe_buffer_map_range(upload->pipe, upload->buffer, + 0, size, + PIPE_TRANSFER_WRITE | + PIPE_TRANSFER_FLUSH_EXPLICIT, + &upload->transfer); upload->size = size; diff --git a/src/gallium/auxiliary/util/u_vbuf_mgr.c b/src/gallium/auxiliary/util/u_vbuf_mgr.c new file mode 100644 index 00000000000..dec8dd717e8 --- /dev/null +++ b/src/gallium/auxiliary/util/u_vbuf_mgr.c @@ -0,0 +1,601 @@ +/************************************************************************** + * + * Copyright 2011 Marek Olšák <[email protected]> + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL AUTHORS 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. + * + **************************************************************************/ + +#include "util/u_vbuf_mgr.h" + +#include "util/u_format.h" +#include "util/u_inlines.h" +#include "util/u_memory.h" +#include "util/u_upload_mgr.h" +#include "translate/translate.h" +#include "translate/translate_cache.h" + +/* Hardware vertex fetcher limitations can be described by this structure. */ +struct u_vbuf_caps { + /* Vertex format CAPs. */ + /* TRUE if hardware supports it. */ + unsigned format_fixed32:1; /* PIPE_FORMAT_*32*_FIXED */ + unsigned format_float16:1; /* PIPE_FORMAT_*16*_FLOAT */ + unsigned format_float64:1; /* PIPE_FORMAT_*64*_FLOAT */ + unsigned format_norm32:1; /* PIPE_FORMAT_*32*NORM */ + unsigned format_scaled32:1; /* PIPE_FORMAT_*32*SCALED */ + + /* Whether vertex fetches don't have to be dword-aligned. */ + /* TRUE if hardware supports it. */ + unsigned fetch_dword_unaligned:1; +}; + +struct u_vbuf_mgr_elements { + unsigned count; + struct pipe_vertex_element ve[PIPE_MAX_ATTRIBS]; + + /* If (velem[i].src_format != real_format[i]), the vertex buffer + * referenced by the vertex element cannot be used for rendering and + * its vertex data must be translated to real_format[i]. */ + enum pipe_format native_format[PIPE_MAX_ATTRIBS]; + unsigned native_format_size[PIPE_MAX_ATTRIBS]; + + /* This might mean two things: + * - src_format != native_format, as discussed above. + * - src_offset % 4 != 0 (if the caps don't allow such an offset). */ + boolean incompatible_layout; +}; + +struct u_vbuf_mgr_priv { + struct u_vbuf_mgr b; + struct u_vbuf_caps caps; + struct pipe_context *pipe; + + struct translate_cache *translate_cache; + unsigned translate_vb_slot; + + struct u_vbuf_mgr_elements *ve; + void *saved_ve, *fallback_ve; + boolean ve_binding_lock; + + boolean any_user_vbs; + boolean incompatible_vb_layout; +}; + +static void u_vbuf_mgr_init_format_caps(struct u_vbuf_mgr_priv *mgr) +{ + struct pipe_screen *screen = mgr->pipe->screen; + + mgr->caps.format_fixed32 = + screen->is_format_supported(screen, PIPE_FORMAT_R32_FIXED, PIPE_BUFFER, + 0, PIPE_BIND_VERTEX_BUFFER, 0); + + mgr->caps.format_float16 = + screen->is_format_supported(screen, PIPE_FORMAT_R16_FLOAT, PIPE_BUFFER, + 0, PIPE_BIND_VERTEX_BUFFER, 0); + + mgr->caps.format_float64 = + screen->is_format_supported(screen, PIPE_FORMAT_R64_FLOAT, PIPE_BUFFER, + 0, PIPE_BIND_VERTEX_BUFFER, 0); + + mgr->caps.format_norm32 = + screen->is_format_supported(screen, PIPE_FORMAT_R32_UNORM, PIPE_BUFFER, + 0, PIPE_BIND_VERTEX_BUFFER, 0) && + screen->is_format_supported(screen, PIPE_FORMAT_R32_SNORM, PIPE_BUFFER, + 0, PIPE_BIND_VERTEX_BUFFER, 0); + + mgr->caps.format_scaled32 = + screen->is_format_supported(screen, PIPE_FORMAT_R32_USCALED, PIPE_BUFFER, + 0, PIPE_BIND_VERTEX_BUFFER, 0) && + screen->is_format_supported(screen, PIPE_FORMAT_R32_SSCALED, PIPE_BUFFER, + 0, PIPE_BIND_VERTEX_BUFFER, 0); +} + +struct u_vbuf_mgr * +u_vbuf_mgr_create(struct pipe_context *pipe, + unsigned upload_buffer_size, + unsigned upload_buffer_alignment, + unsigned upload_buffer_bind, + enum u_fetch_alignment fetch_alignment) +{ + struct u_vbuf_mgr_priv *mgr = CALLOC_STRUCT(u_vbuf_mgr_priv); + + mgr->pipe = pipe; + mgr->translate_cache = translate_cache_create(); + + mgr->b.uploader = u_upload_create(pipe, upload_buffer_size, + upload_buffer_alignment, + upload_buffer_bind); + + mgr->caps.fetch_dword_unaligned = + fetch_alignment == U_VERTEX_FETCH_BYTE_ALIGNED; + + u_vbuf_mgr_init_format_caps(mgr); + + return &mgr->b; +} + +void u_vbuf_mgr_destroy(struct u_vbuf_mgr *mgrb) +{ + struct u_vbuf_mgr_priv *mgr = (struct u_vbuf_mgr_priv*)mgrb; + unsigned i; + + for (i = 0; i < mgr->b.nr_real_vertex_buffers; i++) { + pipe_resource_reference(&mgr->b.vertex_buffer[i].buffer, NULL); + pipe_resource_reference(&mgr->b.real_vertex_buffer[i], NULL); + } + + translate_cache_destroy(mgr->translate_cache); + u_upload_destroy(mgr->b.uploader); + FREE(mgr); +} + + +static void u_vbuf_translate_begin(struct u_vbuf_mgr_priv *mgr, + int min_index, int max_index, + boolean *upload_flushed) +{ + struct translate_key key; + struct translate_element *te; + unsigned tr_elem_index[PIPE_MAX_ATTRIBS]; + struct translate *tr; + boolean vb_translated[PIPE_MAX_ATTRIBS] = {0}; + uint8_t *vb_map[PIPE_MAX_ATTRIBS] = {0}, *out_map; + struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS] = {0}; + struct pipe_resource *out_buffer = NULL; + unsigned i, num_verts, out_offset; + struct pipe_vertex_element new_velems[PIPE_MAX_ATTRIBS]; + + memset(&key, 0, sizeof(key)); + memset(tr_elem_index, 0xff, sizeof(tr_elem_index)); + + /* Initialize the translate key, i.e. the recipe how vertices should be + * translated. */ + for (i = 0; i < mgr->ve->count; i++) { + struct pipe_vertex_buffer *vb = + &mgr->b.vertex_buffer[mgr->ve->ve[i].vertex_buffer_index]; + enum pipe_format output_format = mgr->ve->native_format[i]; + unsigned output_format_size = mgr->ve->native_format_size[i]; + + /* Check for support. */ + if (mgr->ve->ve[i].src_format == mgr->ve->native_format[i] && + (mgr->caps.fetch_dword_unaligned || + (vb->buffer_offset % 4 == 0 && + vb->stride % 4 == 0 && + mgr->ve->ve[i].src_offset % 4 == 0))) { + continue; + } + + /* Workaround for translate: output floats instead of halfs. */ + switch (output_format) { + case PIPE_FORMAT_R16_FLOAT: + output_format = PIPE_FORMAT_R32_FLOAT; + output_format_size = 4; + break; + case PIPE_FORMAT_R16G16_FLOAT: + output_format = PIPE_FORMAT_R32G32_FLOAT; + output_format_size = 8; + break; + case PIPE_FORMAT_R16G16B16_FLOAT: + output_format = PIPE_FORMAT_R32G32B32_FLOAT; + output_format_size = 12; + break; + case PIPE_FORMAT_R16G16B16A16_FLOAT: + output_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + output_format_size = 16; + break; + default:; + } + + /* Add this vertex element. */ + te = &key.element[key.nr_elements]; + /*te->type; + te->instance_divisor;*/ + te->input_buffer = mgr->ve->ve[i].vertex_buffer_index; + te->input_format = mgr->ve->ve[i].src_format; + te->input_offset = mgr->ve->ve[i].src_offset; + te->output_format = output_format; + te->output_offset = key.output_stride; + + key.output_stride += output_format_size; + vb_translated[mgr->ve->ve[i].vertex_buffer_index] = TRUE; + tr_elem_index[i] = key.nr_elements; + key.nr_elements++; + } + + /* Get a translate object. */ + tr = translate_cache_find(mgr->translate_cache, &key); + + /* Map buffers we want to translate. */ + for (i = 0; i < mgr->b.nr_vertex_buffers; i++) { + if (vb_translated[i]) { + struct pipe_vertex_buffer *vb = &mgr->b.vertex_buffer[i]; + + vb_map[i] = pipe_buffer_map(mgr->pipe, vb->buffer, + PIPE_TRANSFER_READ, &vb_transfer[i]); + + tr->set_buffer(tr, i, + vb_map[i] + vb->buffer_offset + vb->stride * min_index, + vb->stride, ~0); + } + } + + /* Create and map the output buffer. */ + num_verts = max_index + 1 - min_index; + + u_upload_alloc(mgr->b.uploader, + key.output_stride * min_index, + key.output_stride * num_verts, + &out_offset, &out_buffer, upload_flushed, + (void**)&out_map); + + out_offset -= key.output_stride * min_index; + + /* Translate. */ + tr->run(tr, 0, num_verts, 0, out_map); + + /* Unmap all buffers. */ + for (i = 0; i < mgr->b.nr_vertex_buffers; i++) { + if (vb_translated[i]) { + pipe_buffer_unmap(mgr->pipe, vb_transfer[i]); + } + } + + /* Setup the new vertex buffer in the first free slot. */ + mgr->translate_vb_slot = ~0; + for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { + if (!mgr->b.vertex_buffer[i].buffer) { + mgr->translate_vb_slot = i; + + if (i >= mgr->b.nr_vertex_buffers) { + mgr->b.nr_real_vertex_buffers = i+1; + } + break; + } + } + + if (mgr->translate_vb_slot != ~0) { + /* Setup the new vertex buffer. */ + pipe_resource_reference( + &mgr->b.real_vertex_buffer[mgr->translate_vb_slot], out_buffer); + mgr->b.vertex_buffer[mgr->translate_vb_slot].buffer_offset = out_offset; + mgr->b.vertex_buffer[mgr->translate_vb_slot].stride = key.output_stride; + + /* Setup new vertex elements. */ + for (i = 0; i < mgr->ve->count; i++) { + if (tr_elem_index[i] < key.nr_elements) { + te = &key.element[tr_elem_index[i]]; + new_velems[i].instance_divisor = mgr->ve->ve[i].instance_divisor; + new_velems[i].src_format = te->output_format; + new_velems[i].src_offset = te->output_offset; + new_velems[i].vertex_buffer_index = mgr->translate_vb_slot; + } else { + memcpy(&new_velems[i], &mgr->ve->ve[i], + sizeof(struct pipe_vertex_element)); + } + } + + mgr->fallback_ve = + mgr->pipe->create_vertex_elements_state(mgr->pipe, mgr->ve->count, + new_velems); + + /* Preserve saved_ve. */ + mgr->ve_binding_lock = TRUE; + mgr->pipe->bind_vertex_elements_state(mgr->pipe, mgr->fallback_ve); + mgr->ve_binding_lock = FALSE; + } + + pipe_resource_reference(&out_buffer, NULL); +} + +static void u_vbuf_translate_end(struct u_vbuf_mgr_priv *mgr) +{ + if (mgr->fallback_ve == NULL) { + return; + } + + /* Restore vertex elements. */ + /* Note that saved_ve will be overwritten in bind_vertex_elements_state. */ + mgr->pipe->bind_vertex_elements_state(mgr->pipe, mgr->saved_ve); + mgr->pipe->delete_vertex_elements_state(mgr->pipe, mgr->fallback_ve); + mgr->fallback_ve = NULL; + + /* Delete the now-unused VBO. */ + pipe_resource_reference(&mgr->b.real_vertex_buffer[mgr->translate_vb_slot], + NULL); + mgr->b.nr_real_vertex_buffers = mgr->b.nr_vertex_buffers; +} + +#define FORMAT_REPLACE(what, withwhat) \ + case PIPE_FORMAT_##what: format = PIPE_FORMAT_##withwhat; break + +struct u_vbuf_mgr_elements * +u_vbuf_mgr_create_vertex_elements(struct u_vbuf_mgr *mgrb, + unsigned count, + const struct pipe_vertex_element *attribs, + struct pipe_vertex_element *native_attribs) +{ + struct u_vbuf_mgr_priv *mgr = (struct u_vbuf_mgr_priv*)mgrb; + unsigned i; + struct u_vbuf_mgr_elements *ve = CALLOC_STRUCT(u_vbuf_mgr_elements); + + ve->count = count; + + if (!count) { + return ve; + } + + memcpy(ve->ve, attribs, sizeof(struct pipe_vertex_element) * count); + memcpy(native_attribs, attribs, sizeof(struct pipe_vertex_element) * count); + + /* Set the best native format in case the original format is not + * supported. */ + for (i = 0; i < count; i++) { + enum pipe_format format = ve->ve[i].src_format; + + /* Choose a native format. + * For now we don't care about the alignment, that's going to + * be sorted out later. */ + if (!mgr->caps.format_fixed32) { + switch (format) { + FORMAT_REPLACE(R32_FIXED, R32_FLOAT); + FORMAT_REPLACE(R32G32_FIXED, R32G32_FLOAT); + FORMAT_REPLACE(R32G32B32_FIXED, R32G32B32_FLOAT); + FORMAT_REPLACE(R32G32B32A32_FIXED, R32G32B32A32_FLOAT); + default:; + } + } + if (!mgr->caps.format_float16) { + switch (format) { + FORMAT_REPLACE(R16_FLOAT, R32_FLOAT); + FORMAT_REPLACE(R16G16_FLOAT, R32G32_FLOAT); + FORMAT_REPLACE(R16G16B16_FLOAT, R32G32B32_FLOAT); + FORMAT_REPLACE(R16G16B16A16_FLOAT, R32G32B32A32_FLOAT); + default:; + } + } + if (!mgr->caps.format_float64) { + switch (format) { + FORMAT_REPLACE(R64_FLOAT, R32_FLOAT); + FORMAT_REPLACE(R64G64_FLOAT, R32G32_FLOAT); + FORMAT_REPLACE(R64G64B64_FLOAT, R32G32B32_FLOAT); + FORMAT_REPLACE(R64G64B64A64_FLOAT, R32G32B32A32_FLOAT); + default:; + } + } + if (!mgr->caps.format_norm32) { + switch (format) { + FORMAT_REPLACE(R32_UNORM, R32_FLOAT); + FORMAT_REPLACE(R32G32_UNORM, R32G32_FLOAT); + FORMAT_REPLACE(R32G32B32_UNORM, R32G32B32_FLOAT); + FORMAT_REPLACE(R32G32B32A32_UNORM, R32G32B32A32_FLOAT); + FORMAT_REPLACE(R32_SNORM, R32_FLOAT); + FORMAT_REPLACE(R32G32_SNORM, R32G32_FLOAT); + FORMAT_REPLACE(R32G32B32_SNORM, R32G32B32_FLOAT); + FORMAT_REPLACE(R32G32B32A32_SNORM, R32G32B32A32_FLOAT); + default:; + } + } + if (!mgr->caps.format_scaled32) { + switch (format) { + FORMAT_REPLACE(R32_USCALED, R32_FLOAT); + FORMAT_REPLACE(R32G32_USCALED, R32G32_FLOAT); + FORMAT_REPLACE(R32G32B32_USCALED, R32G32B32_FLOAT); + FORMAT_REPLACE(R32G32B32A32_USCALED,R32G32B32A32_FLOAT); + FORMAT_REPLACE(R32_SSCALED, R32_FLOAT); + FORMAT_REPLACE(R32G32_SSCALED, R32G32_FLOAT); + FORMAT_REPLACE(R32G32B32_SSCALED, R32G32B32_FLOAT); + FORMAT_REPLACE(R32G32B32A32_SSCALED,R32G32B32A32_FLOAT); + default:; + } + } + + native_attribs[i].src_format = format; + ve->native_format[i] = format; + ve->native_format_size[i] = + util_format_get_blocksize(ve->native_format[i]); + + ve->incompatible_layout = + ve->incompatible_layout || + ve->ve[i].src_format != ve->native_format[i] || + (!mgr->caps.fetch_dword_unaligned && ve->ve[i].src_offset % 4 != 0); + } + + /* Align the formats to the size of DWORD if needed. */ + if (!mgr->caps.fetch_dword_unaligned) { + for (i = 0; i < count; i++) { + ve->native_format_size[i] = align(ve->native_format_size[i], 4); + } + } + + return ve; +} + +void u_vbuf_mgr_bind_vertex_elements(struct u_vbuf_mgr *mgrb, + void *cso, + struct u_vbuf_mgr_elements *ve) +{ + struct u_vbuf_mgr_priv *mgr = (struct u_vbuf_mgr_priv*)mgrb; + + if (!cso) { + return; + } + + if (!mgr->ve_binding_lock) { + mgr->saved_ve = cso; + mgr->ve = ve; + } +} + +void u_vbuf_mgr_destroy_vertex_elements(struct u_vbuf_mgr *mgr, + struct u_vbuf_mgr_elements *ve) +{ + FREE(ve); +} + +void u_vbuf_mgr_set_vertex_buffers(struct u_vbuf_mgr *mgrb, + unsigned count, + const struct pipe_vertex_buffer *bufs) +{ + struct u_vbuf_mgr_priv *mgr = (struct u_vbuf_mgr_priv*)mgrb; + unsigned i; + + mgr->b.max_index = ~0; + mgr->any_user_vbs = FALSE; + mgr->incompatible_vb_layout = FALSE; + + if (!mgr->caps.fetch_dword_unaligned) { + /* Check if the strides and offsets are aligned to the size of DWORD. */ + for (i = 0; i < count; i++) { + if (bufs[i].buffer) { + if (bufs[i].stride % 4 != 0 || + bufs[i].buffer_offset % 4 != 0) { + mgr->incompatible_vb_layout = TRUE; + break; + } + } + } + } + + for (i = 0; i < count; i++) { + const struct pipe_vertex_buffer *vb = &bufs[i]; + + pipe_resource_reference(&mgr->b.vertex_buffer[i].buffer, vb->buffer); + pipe_resource_reference(&mgr->b.real_vertex_buffer[i], NULL); + + if (u_vbuf_resource(vb->buffer)->user_ptr) { + mgr->any_user_vbs = TRUE; + continue; + } + + pipe_resource_reference(&mgr->b.real_vertex_buffer[i], vb->buffer); + + /* The stride of zero means we will be fetching only the first + * vertex, so don't care about max_index. */ + if (!vb->stride) { + continue; + } + + /* Update the maximum index. */ + mgr->b.max_index = + MIN2(mgr->b.max_index, + (vb->buffer->width0 - vb->buffer_offset) / vb->stride); + } + + for (; i < mgr->b.nr_real_vertex_buffers; i++) { + pipe_resource_reference(&mgr->b.vertex_buffer[i].buffer, NULL); + pipe_resource_reference(&mgr->b.real_vertex_buffer[i], NULL); + } + + memcpy(mgr->b.vertex_buffer, bufs, + sizeof(struct pipe_vertex_buffer) * count); + + mgr->b.nr_vertex_buffers = count; + mgr->b.nr_real_vertex_buffers = count; +} + +static void u_vbuf_upload_buffers(struct u_vbuf_mgr_priv *mgr, + int min_index, int max_index, + boolean *upload_flushed) +{ + int i, nr = mgr->ve->count; + unsigned count = max_index + 1 - min_index; + boolean uploaded[PIPE_MAX_ATTRIBS] = {0}; + + for (i = 0; i < nr; i++) { + unsigned index = mgr->ve->ve[i].vertex_buffer_index; + struct pipe_vertex_buffer *vb = &mgr->b.vertex_buffer[index]; + + if (vb->buffer && + u_vbuf_resource(vb->buffer)->user_ptr && + !uploaded[index]) { + unsigned first, size; + boolean flushed; + + if (vb->stride) { + first = vb->stride * min_index; + size = vb->stride * count; + } else { + first = 0; + size = mgr->ve->native_format_size[i]; + } + + u_upload_data(mgr->b.uploader, first, size, + u_vbuf_resource(vb->buffer)->user_ptr + first, + &vb->buffer_offset, + &mgr->b.real_vertex_buffer[index], + &flushed); + + vb->buffer_offset -= first; + + uploaded[index] = TRUE; + *upload_flushed = *upload_flushed || flushed; + } else { + assert(mgr->b.real_vertex_buffer[index]); + } + } +} + +void u_vbuf_mgr_draw_begin(struct u_vbuf_mgr *mgrb, + const struct pipe_draw_info *info, + boolean *buffers_updated, + boolean *uploader_flushed) +{ + struct u_vbuf_mgr_priv *mgr = (struct u_vbuf_mgr_priv*)mgrb; + boolean bufs_updated = FALSE, upload_flushed = FALSE; + int min_index, max_index; + + min_index = info->min_index - info->index_bias; + max_index = info->max_index - info->index_bias; + + /* Translate vertices with non-native layouts or formats. */ + if (mgr->incompatible_vb_layout || mgr->ve->incompatible_layout) { + u_vbuf_translate_begin(mgr, min_index, max_index, &upload_flushed); + + if (mgr->fallback_ve) { + bufs_updated = TRUE; + } + } + + /* Upload user buffers. */ + if (mgr->any_user_vbs) { + u_vbuf_upload_buffers(mgr, min_index, max_index, &upload_flushed); + bufs_updated = TRUE; + } + + /* Set the return values. */ + if (buffers_updated) { + *buffers_updated = bufs_updated; + } + if (uploader_flushed) { + *uploader_flushed = upload_flushed; + } +} + +void u_vbuf_mgr_draw_end(struct u_vbuf_mgr *mgrb) +{ + struct u_vbuf_mgr_priv *mgr = (struct u_vbuf_mgr_priv*)mgrb; + + if (mgr->fallback_ve) { + u_vbuf_translate_end(mgr); + } +} diff --git a/src/gallium/auxiliary/util/u_vbuf_mgr.h b/src/gallium/auxiliary/util/u_vbuf_mgr.h new file mode 100644 index 00000000000..8b241854c83 --- /dev/null +++ b/src/gallium/auxiliary/util/u_vbuf_mgr.h @@ -0,0 +1,121 @@ +/************************************************************************** + * + * Copyright 2011 Marek Olšák <[email protected]> + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL AUTHORS 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. + * + **************************************************************************/ + +#ifndef U_VBUF_MGR_H +#define U_VBUF_MGR_H + +/* This module builds upon u_upload_mgr and translate_cache and takes care of + * user buffer uploads and vertex format fallbacks. It's designed + * for the drivers which don't always use the Draw module. (e.g. for HWTCL) + */ + +#include "pipe/p_context.h" +#include "pipe/p_state.h" +#include "util/u_transfer.h" + +/* The manager. + * This structure should also be used to access vertex buffers + * from a driver. */ +struct u_vbuf_mgr { + /* This is what was set in set_vertex_buffers. + * May contain user buffers. */ + struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; + unsigned nr_vertex_buffers; + + /* Contains only real vertex buffers. + * Hardware drivers should use real_vertex_buffers[i] + * instead of vertex_buffers[i].buffer. */ + struct pipe_resource *real_vertex_buffer[PIPE_MAX_ATTRIBS]; + int nr_real_vertex_buffers; + + /* Precomputed max_index for hardware vertex buffers. */ + int max_index; + + /* This uploader can optionally be used by the driver. + * + * Allowed functions: + * - u_upload_alloc + * - u_upload_data + * - u_upload_buffer + * - u_upload_flush */ + struct u_upload_mgr *uploader; +}; + +struct u_vbuf_resource { + struct u_resource b; + uint8_t *user_ptr; +}; + +/* Opaque type containing information about vertex elements for the manager. */ +struct u_vbuf_mgr_elements; + +enum u_fetch_alignment { + U_VERTEX_FETCH_BYTE_ALIGNED, + U_VERTEX_FETCH_DWORD_ALIGNED +}; + + +struct u_vbuf_mgr * +u_vbuf_mgr_create(struct pipe_context *pipe, + unsigned upload_buffer_size, + unsigned upload_buffer_alignment, + unsigned upload_buffer_bind, + enum u_fetch_alignment fetch_alignment); + +void u_vbuf_mgr_destroy(struct u_vbuf_mgr *mgr); + +struct u_vbuf_mgr_elements * +u_vbuf_mgr_create_vertex_elements(struct u_vbuf_mgr *mgr, + unsigned count, + const struct pipe_vertex_element *attrs, + struct pipe_vertex_element *native_attrs); + +void u_vbuf_mgr_bind_vertex_elements(struct u_vbuf_mgr *mgr, + void *cso, + struct u_vbuf_mgr_elements *ve); + +void u_vbuf_mgr_destroy_vertex_elements(struct u_vbuf_mgr *mgr, + struct u_vbuf_mgr_elements *ve); + +void u_vbuf_mgr_set_vertex_buffers(struct u_vbuf_mgr *mgr, + unsigned count, + const struct pipe_vertex_buffer *bufs); + +void u_vbuf_mgr_draw_begin(struct u_vbuf_mgr *mgr, + const struct pipe_draw_info *info, + boolean *buffers_updated, + boolean *uploader_flushed); + +void u_vbuf_mgr_draw_end(struct u_vbuf_mgr *mgr); + + +static INLINE struct u_vbuf_resource *u_vbuf_resource(struct pipe_resource *r) +{ + return (struct u_vbuf_resource*)r; +} + +#endif diff --git a/src/gallium/auxiliary/vl/vl_compositor.c b/src/gallium/auxiliary/vl/vl_compositor.c index d7b29497ace..d1ba5faf788 100644 --- a/src/gallium/auxiliary/vl/vl_compositor.c +++ b/src/gallium/auxiliary/vl/vl_compositor.c @@ -247,13 +247,13 @@ init_buffers(struct vl_compositor *c) * Create our vertex buffer and vertex buffer elements */ c->vertex_buf.stride = sizeof(struct vertex4f); - c->vertex_buf.max_index = (VL_COMPOSITOR_MAX_LAYERS + 2) * 6 - 1; c->vertex_buf.buffer_offset = 0; /* XXX: Create with DYNAMIC or STREAM */ c->vertex_buf.buffer = pipe_buffer_create ( c->pipe->screen, PIPE_BIND_VERTEX_BUFFER, + PIPE_USAGE_STATIC, sizeof(struct vertex4f) * (VL_COMPOSITOR_MAX_LAYERS + 2) * 6 ); @@ -276,6 +276,7 @@ init_buffers(struct vl_compositor *c) ( c->pipe->screen, PIPE_BIND_CONSTANT_BUFFER, + PIPE_USAGE_STATIC, sizeof(struct fragment_shader_consts) ); diff --git a/src/gallium/auxiliary/vl/vl_idct.c b/src/gallium/auxiliary/vl/vl_idct.c index 5d472f93481..89463a5c75c 100644 --- a/src/gallium/auxiliary/vl/vl_idct.c +++ b/src/gallium/auxiliary/vl/vl_idct.c @@ -428,7 +428,6 @@ init_textures(struct vl_idct *idct, struct vl_idct_buffer *buffer) /* create textures */ memset(&template, 0, sizeof(struct pipe_resource)); template.last_level = 0; - template.depth0 = 1; template.bind = PIPE_BIND_SAMPLER_VIEW; template.flags = 0; @@ -437,6 +436,7 @@ init_textures(struct vl_idct *idct, struct vl_idct_buffer *buffer) template.width0 = idct->buffer_width / 4; template.height0 = idct->buffer_height; template.depth0 = 1; + template.array_size = 1; template.usage = PIPE_USAGE_STREAM; buffer->textures.individual.source = idct->pipe->screen->resource_create(idct->pipe->screen, &template); @@ -478,7 +478,6 @@ init_vertex_buffers(struct vl_idct *idct, struct vl_idct_buffer *buffer) assert(idct && buffer); buffer->vertex_bufs.individual.quad.stride = idct->quad.stride; - buffer->vertex_bufs.individual.quad.max_index = idct->quad.max_index; buffer->vertex_bufs.individual.quad.buffer_offset = idct->quad.buffer_offset; pipe_resource_reference(&buffer->vertex_bufs.individual.quad.buffer, idct->quad.buffer); @@ -526,6 +525,7 @@ vl_idct_upload_matrix(struct pipe_context *pipe) template.width0 = 2; template.height0 = 8; template.depth0 = 1; + template.array_size = 1; template.usage = PIPE_USAGE_IMMUTABLE; template.bind = PIPE_BIND_SAMPLER_VIEW; template.flags = 0; diff --git a/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.c b/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.c index de83b6a5338..484e781f0cb 100644 --- a/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.c +++ b/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.c @@ -888,6 +888,7 @@ vl_mpeg12_mc_init_buffer(struct vl_mpeg12_mc_renderer *renderer, struct vl_mpeg1 template.width0 = renderer->buffer_width; template.height0 = renderer->buffer_height; template.depth0 = 1; + template.array_size = 1; template.usage = PIPE_USAGE_STATIC; template.bind = PIPE_BIND_SAMPLER_VIEW; template.flags = 0; @@ -928,7 +929,6 @@ vl_mpeg12_mc_init_buffer(struct vl_mpeg12_mc_renderer *renderer, struct vl_mpeg1 } buffer->vertex_bufs.individual.quad.stride = renderer->quad.stride; - buffer->vertex_bufs.individual.quad.max_index = renderer->quad.max_index; buffer->vertex_bufs.individual.quad.buffer_offset = renderer->quad.buffer_offset; pipe_resource_reference(&buffer->vertex_bufs.individual.quad.buffer, renderer->quad.buffer); diff --git a/src/gallium/auxiliary/vl/vl_vertex_buffers.c b/src/gallium/auxiliary/vl/vl_vertex_buffers.c index 8599ed3533d..552a0451fef 100644 --- a/src/gallium/auxiliary/vl/vl_vertex_buffers.c +++ b/src/gallium/auxiliary/vl/vl_vertex_buffers.c @@ -53,12 +53,12 @@ vl_vb_upload_quads(struct pipe_context *pipe, unsigned max_blocks) /* create buffer */ quad.stride = sizeof(struct vertex2f); - quad.max_index = 4 * max_blocks - 1; quad.buffer_offset = 0; quad.buffer = pipe_buffer_create ( pipe->screen, PIPE_BIND_VERTEX_BUFFER, + PIPE_USAGE_STATIC, sizeof(struct vertex2f) * 4 * max_blocks ); @@ -100,7 +100,7 @@ unsigned vl_vb_element_helper(struct pipe_vertex_element* elements, unsigned num_elements, unsigned vertex_buffer_index) { - unsigned i, size, offset = 0; + unsigned i, offset = 0; assert(elements && num_elements); @@ -126,12 +126,12 @@ vl_vb_init(struct vl_vertex_buffer *buffer, struct pipe_context *pipe, buffer->stride = stride; buf.stride = stride; - buf.max_index = 4 * max_blocks - 1; buf.buffer_offset = 0; buf.buffer = pipe_buffer_create ( pipe->screen, PIPE_BIND_VERTEX_BUFFER, + PIPE_USAGE_STREAM, stride * 4 * max_blocks ); diff --git a/src/gallium/docs/d3d11ddi.txt b/src/gallium/docs/d3d11ddi.txt index 11e77190895..0a9e7e50f1d 100644 --- a/src/gallium/docs/d3d11ddi.txt +++ b/src/gallium/docs/d3d11ddi.txt @@ -337,7 +337,6 @@ IaSetTopology + Gallium supports line loops, triangle fans, quads, quad strips and polygons IaSetVertexBuffers -> set_vertex_buffers - + Gallium allows to specify a max_index here - Gallium only allows setting all vertex buffers at once, while D3D11 supports setting a subset OpenResource -> texture_from_handle diff --git a/src/gallium/docs/source/context.rst b/src/gallium/docs/source/context.rst index 6760e7be4b9..c6812cd309e 100644 --- a/src/gallium/docs/source/context.rst +++ b/src/gallium/docs/source/context.rst @@ -3,8 +3,12 @@ Context ======= -The context object represents the purest, most directly accessible, abilities -of the device's 3D rendering pipeline. +A Gallium rendering context encapsulates the state which effects 3D +rendering such as blend state, depth/stencil state, texture samplers, +etc. + +Note that resource/texture allocation is not per-context but per-screen. + Methods ------- @@ -12,20 +16,23 @@ Methods CSO State ^^^^^^^^^ -All CSO state is created, bound, and destroyed, with triplets of methods that -all follow a specific naming scheme. For example, ``create_blend_state``, -``bind_blend_state``, and ``destroy_blend_state``. +All Constant State Object (CSO) state is created, bound, and destroyed, +with triplets of methods that all follow a specific naming scheme. +For example, ``create_blend_state``, ``bind_blend_state``, and +``destroy_blend_state``. CSO objects handled by the context object: * :ref:`Blend`: ``*_blend_state`` -* :ref:`Sampler`: These are special; they can be bound to either vertex or - fragment samplers, and they are bound in groups. - ``bind_fragment_sampler_states``, ``bind_vertex_sampler_states`` +* :ref:`Sampler`: Texture sampler states are bound separately for fragment, + vertex and geometry samplers. Note that sampler states are set en masse. + If M is the max number of sampler units supported by the driver and N + samplers are bound with ``bind_fragment_sampler_states`` then sampler + units N..M-1 are considered disabled/NULL. * :ref:`Rasterizer`: ``*_rasterizer_state`` * :ref:`Depth, Stencil, & Alpha`: ``*_depth_stencil_alpha_state`` -* :ref:`Shader`: These have two sets of methods. ``*_fs_state`` is for - fragment shaders, and ``*_vs_state`` is for vertex shaders. +* :ref:`Shader`: These are create, bind and destroy methods for vertex, + fragment and geometry shaders. * :ref:`Vertex Elements`: ``*_vertex_elements_state`` @@ -47,6 +54,9 @@ buffers, surfaces) are bound to the driver. * ``set_index_buffer`` +* ``set_stream_output_buffers`` + + Non-CSO State ^^^^^^^^^^^^^ @@ -96,7 +106,9 @@ to the array index which is used for sampling. * ``set_fragment_sampler_views`` binds an array of sampler views to fragment shader stage. Every binding point acquires a reference to a respective sampler view and releases a reference to the previous - sampler view. + sampler view. If M is the maximum number of sampler units and N units + is passed to set_fragment_sampler_views, the driver should unbind the + sampler views for units N..M-1. * ``set_vertex_sampler_views`` binds an array of sampler views to vertex shader stage. Every binding point acquires a reference to a respective @@ -233,6 +245,11 @@ The most common type of query is the occlusion query, are written to the framebuffer without being culled by :ref:`Depth, Stencil, & Alpha` testing or shader KILL instructions. The result is an unsigned 64-bit integer. +In cases where a boolean result of an occlusion query is enough, +``PIPE_QUERY_OCCLUSION_PREDICATE`` should be used. It is just like +``PIPE_QUERY_OCCLUSION_COUNTER`` except that the result is a boolean +value of FALSE for cases where COUNTER would result in 0 and TRUE +for all other cases. Another type of query, ``PIPE_QUERY_TIME_ELAPSED``, returns the amount of time, in nanoseconds, the context takes to perform operations. @@ -349,6 +366,22 @@ Any pointers into the map should be considered invalid and discarded. Basically get_transfer, transfer_map, data write, transfer_unmap, and transfer_destroy all in one. + +The box parameter to some of these functions defines a 1D, 2D or 3D +region of pixels. This is self-explanatory for 1D, 2D and 3D texture +targets. + +For PIPE_TEXTURE_1D_ARRAY, the box::y and box::height fields refer to the +array dimension of the texture. + +For PIPE_TEXTURE_2D_ARRAY, the box::z and box::depth fields refer to the +array dimension of the texture. + +For PIPE_TEXTURE_CUBE, the box:z and box::depth fields refer to the +faces of the cube map (z + depth <= 6). + + + .. _transfer_flush_region: transfer_flush_region @@ -359,6 +392,22 @@ be flushed on write or unmap. Flushes must be requested with ``transfer_flush_region``. Flush ranges are relative to the mapped range, not the beginning of the resource. + + +.. _redefine_user_buffer: + +redefine_user_buffer +%%%%%%%%%%%%%%%%%%%% + +This function notifies a driver that the user buffer content has been changed. +The updated region starts at ``offset`` and is ``size`` bytes large. +The ``offset`` is relative to the pointer specified in ``user_buffer_create``. +While uploading the user buffer, the driver is allowed not to upload +the memory outside of this region. +The width0 is redefined to ``MAX2(width0, offset+size)``. + + + .. _pipe_transfer: PIPE_TRANSFER @@ -366,16 +415,32 @@ PIPE_TRANSFER These flags control the behavior of a transfer object. -* ``READ``: resource contents are read at transfer create time. -* ``WRITE``: resource contents will be written back at transfer destroy time. -* ``MAP_DIRECTLY``: a transfer should directly map the resource. May return - NULL if not supported. -* ``DISCARD``: The memory within the mapped region is discarded. - Cannot be used with ``READ``. -* ``DONTBLOCK``: Fail if the resource cannot be mapped immediately. -* ``UNSYNCHRONIZED``: Do not synchronize pending operations on the resource - when mapping. The interaction of any writes to the map and any - operations pending on the resource are undefined. Cannot be used with - ``READ``. -* ``FLUSH_EXPLICIT``: Written ranges will be notified later with - :ref:`transfer_flush_region`. Cannot be used with ``READ``. +``PIPE_TRANSFER_READ`` + Resource contents read back (or accessed directly) at transfer create time. + +``PIPE_TRANSFER_WRITE`` + Resource contents will be written back at transfer_destroy time (or modified + as a result of being accessed directly). + +``PIPE_TRANSFER_MAP_DIRECTLY`` + a transfer should directly map the resource. May return NULL if not supported. + +``PIPE_TRANSFER_DISCARD_RANGE`` + The memory within the mapped region is discarded. Cannot be used with + ``PIPE_TRANSFER_READ``. + +``PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE`` + Discards all memory backing the resource. It should not be used with + ``PIPE_TRANSFER_READ``. + +``PIPE_TRANSFER_DONTBLOCK`` + Fail if the resource cannot be mapped immediately. + +``PIPE_TRANSFER_UNSYNCHRONIZED`` + Do not synchronize pending operations on the resource when mapping. The + interaction of any writes to the map and any operations pending on the + resource are undefined. Cannot be used with ``PIPE_TRANSFER_READ``. + +``PIPE_TRANSFER_FLUSH_EXPLICIT`` + Written ranges will be notified later with :ref:`transfer_flush_region`. + Cannot be used with ``PIPE_TRANSFER_READ``. diff --git a/src/gallium/docs/source/screen.rst b/src/gallium/docs/source/screen.rst index ab90097add6..976e75bed04 100644 --- a/src/gallium/docs/source/screen.rst +++ b/src/gallium/docs/source/screen.rst @@ -273,7 +273,7 @@ Modern APIs allow using buffers as shader resources. **depth0** the depth of the base mip level of the texture (1 for everything else). -**array_size the array size for 1D and 2D array textures. +**array_size** the array size for 1D and 2D array textures. For cube maps this must be 6, for other textures 1. **last_level** the last mip map level present. diff --git a/src/gallium/docs/source/tgsi.rst b/src/gallium/docs/source/tgsi.rst index d986e6601e6..4debcc6ecc4 100644 --- a/src/gallium/docs/source/tgsi.rst +++ b/src/gallium/docs/source/tgsi.rst @@ -1250,6 +1250,157 @@ This opcode is the inverse of :opcode:`DFRACEXP`. dst.zw = \sqrt{src.zw} +.. _resourceopcodes: + +Resource Access Opcodes +^^^^^^^^^^^^^^^^^^^^^^^^ + +Those opcodes follow very closely semantics of the respective Direct3D +instructions. If in doubt double check Direct3D documentation. + +.. opcode:: LOAD - Simplified alternative to the "SAMPLE" instruction. + Using the provided integer address, LOAD fetches data + from the specified buffer/texture without any filtering. + The source data may come from any resource type other + than CUBE. + LOAD dst, address, resource + e.g. + LOAD TEMP[0], TEMP[1], RES[0] + The 'address' is specified as unsigned integers. If the + 'address' is out of range [0...(# texels - 1)] the + result of the fetch is always 0 in all components. + As such the instruction doesn't honor address wrap + modes, in cases where that behavior is desirable + 'sample' instruction should be used. + address.w always provides an unsigned integer mipmap + level. If the value is out of the range then the + instruction always returns 0 in all components. + address.yz are ignored for buffers and 1d textures. + address.z is ignored for 1d texture arrays and 2d + textures. + For 1D texture arrays address.y provides the array + index (also as unsigned integer). If the value is + out of the range of available array indices + [0... (array size - 1)] then the opcode always returns + 0 in all components. + For 2D texture arrays address.z provides the array + index, otherwise it exhibits the same behavior as in + the case for 1D texture arrays. + The exeact semantics of the source address are presented + in the table below: + resource type X Y Z W + ------------- ------------------------ + PIPE_BUFFER x ignored + PIPE_TEXTURE_1D x mpl + PIPE_TEXTURE_2D x y mpl + PIPE_TEXTURE_3D x y z mpl + PIPE_TEXTURE_RECT x y mpl + PIPE_TEXTURE_CUBE not allowed as source + PIPE_TEXTURE_1D_ARRAY x idx mpl + PIPE_TEXTURE_2D_ARRAY x y idx mpl + + Where 'mpl' is a mipmap level and 'idx' is the + array index. + + +.. opcode:: LOAD_MS - Just like LOAD but allows fetch data from + multi-sampled surfaces. + +.. opcode:: SAMPLE - Using provided address, sample data from the + specified texture using the filtering mode identified + by the gven sampler. The source data may come from + any resource type other than buffers. + SAMPLE dst, address, resource, sampler + e.g. + SAMPLE TEMP[0], TEMP[1], RES[0], SAMP[0] + +.. opcode:: SAMPLE_B - Just like the SAMPLE instruction with the + exception that an additiona bias is applied to the + level of detail computed as part of the instruction + execution. + SAMPLE_B dst, address, resource, sampler, lod_bias + e.g. + SAMPLE_B TEMP[0], TEMP[1], RES[0], SAMP[0], TEMP[2].x + +.. opcode:: SAMPLE_C - Similar to the SAMPLE instruction but it + performs a comparison filter. The operands to SAMPLE_C + are identical to SAMPLE, except that tere is an additional + float32 operand, reference value, which must be a register + with single-component, or a scalar literal. + SAMPLE_C makes the hardware use the current samplers + compare_func (in pipe_sampler_state) to compare + reference value against the red component value for the + surce resource at each texel that the currently configured + texture filter covers based on the provided coordinates. + SAMPLE_C dst, address, resource.r, sampler, ref_value + e.g. + SAMPLE_C TEMP[0], TEMP[1], RES[0].r, SAMP[0], TEMP[2].x + +.. opcode:: SAMPLE_C_LZ - Same as SAMPLE_C, but LOD is 0 and derivatives + are ignored. The LZ stands for level-zero. + SAMPLE_C_LZ dst, address, resource.r, sampler, ref_value + e.g. + SAMPLE_C_LZ TEMP[0], TEMP[1], RES[0].r, SAMP[0], TEMP[2].x + + +.. opcode:: SAMPLE_D - SAMPLE_D is identical to the SAMPLE opcode except + that the derivatives for the source address in the x + direction and the y direction are provided by extra + parameters. + SAMPLE_D dst, address, resource, sampler, der_x, der_y + e.g. + SAMPLE_D TEMP[0], TEMP[1], RES[0], SAMP[0], TEMP[2], TEMP[3] + +.. opcode:: SAMPLE_L - SAMPLE_L is identical to the SAMPLE opcode except + that the LOD is provided directly as a scalar value, + representing no anisotropy. Source addresses A channel + is used as the LOD. + SAMPLE_L dst, address, resource, sampler + e.g. + SAMPLE_L TEMP[0], TEMP[1], RES[0], SAMP[0] + + +.. opcode:: GATHER4 - Gathers the four texels to be used in a bi-linear + filtering operation and packs them into a single register. + Only woth with 2D, 2D array, cubemaps, and cubemaps arrays. + For 2D textures, only the addressing modes of the sampler and + the top level of any mip pyramid are used. Set W to zero. + It behaves like the SAMPLE instruction, but a filtered + sample is not generated. The four samples that contribute + to filtering are places into xyzw in cunter-clockwise order, + starting with the (u,v) texture coordinate delta at the + following locations (-, +), (+, +), (+, -), (-, -), where + the magnitude of the deltas are half a texel. + + +.. opcode:: RESINFO - query the dimensions of a given input buffer. + dst receives width, height, depth or array size and + number of mipmap levels. The dst can have a writemask + which will specify what info is the caller interested + in. + RESINFO dst, src_mip_level, resource + e.g. + RESINFO TEMP[0], TEMP[1].x, RES[0] + src_mip_level is an unsigned integer scalar. If it's + out of range then returns 0 for width, height and + depth/array size but the total number of mipmap is + still returned correctly for the given resource. + The returned width, height and depth values are for + the mipmap level selected by the src_mip_level and + are in the number of texels. + For 1d texture array width is in dst.x, array size + is in dst.y and dst.zw are always 0. + +.. opcode:: SAMPLE_POS - query the position of a given sample. + dst receives float4 (x, y, 0, 0) indicated where the + sample is located. If the resource is not a multi-sample + resource and not a render target, the result is 0. + +.. opcode:: SAMPLE_INFO - dst receives number of samples in x. + If the resource is not a multi-sample resource and + not a render target, the result is 0. + + Explanation of symbols used ------------------------------ @@ -1332,6 +1483,8 @@ wrapping when interpolating by the rasteriser. If TGSI_CYLINDRICAL_WRAP_X is set to 1, the X component should be interpolated according to cylindrical wrapping rules. +If file is TGSI_FILE_RESOURCE, a Declaration Resource token follows. + Declaration Semantic ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1475,6 +1628,23 @@ is a writable stencil reference value. Only the Y component is writable. This allows the fragment shader to change the fragments stencilref value. +Declaration Resource +^^^^^^^^^^^^^^^^^^^^^^^^ + + Follows Declaration token if file is TGSI_FILE_RESOURCE. + + DCL RES[#], resource, type(s) + + Declares a shader input resource and assigns it to a RES[#] + register. + + resource can be one of BUFFER, 1D, 2D, 3D, CUBE, 1DArray and + 2DArray. + + type must be 1 or 4 entries (if specifying on a per-component + level) out of UNORM, SNORM, SINT, UINT and FLOAT. + + Properties ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/gallium/drivers/cell/ppu/cell_state_vertex.c b/src/gallium/drivers/cell/ppu/cell_state_vertex.c index eb22a09a913..7f65b82619e 100644 --- a/src/gallium/drivers/cell/ppu/cell_state_vertex.c +++ b/src/gallium/drivers/cell/ppu/cell_state_vertex.c @@ -33,6 +33,7 @@ #include "cell_state.h" #include "util/u_memory.h" +#include "util/u_transfer.h" #include "draw/draw_context.h" @@ -115,4 +116,5 @@ cell_init_vertex_functions(struct cell_context *cell) cell->pipe.create_vertex_elements_state = cell_create_vertex_elements_state; cell->pipe.bind_vertex_elements_state = cell_bind_vertex_elements_state; cell->pipe.delete_vertex_elements_state = cell_delete_vertex_elements_state; + cell->pipe.redefine_user_buffer = u_default_redefine_user_buffer; } diff --git a/src/gallium/drivers/failover/fo_state.c b/src/gallium/drivers/failover/fo_state.c index af1fd953aaf..b4da1b8b901 100644 --- a/src/gallium/drivers/failover/fo_state.c +++ b/src/gallium/drivers/failover/fo_state.c @@ -30,6 +30,7 @@ #include "util/u_inlines.h" #include "util/u_memory.h" +#include "util/u_transfer.h" #include "fo_context.h" @@ -656,4 +657,5 @@ failover_init_state_functions( struct failover_context *failover ) failover->pipe.set_constant_buffer = failover_set_constant_buffer; failover->pipe.create_sampler_view = failover_create_sampler_view; failover->pipe.sampler_view_destroy = failover_sampler_view_destroy; + failover->pipe.redefine_user_buffer = u_default_redefine_user_buffer; } diff --git a/src/gallium/drivers/galahad/glhd_context.c b/src/gallium/drivers/galahad/glhd_context.c index 8cbf0b1de4a..75e4c253dd9 100644 --- a/src/gallium/drivers/galahad/glhd_context.c +++ b/src/gallium/drivers/galahad/glhd_context.c @@ -962,6 +962,19 @@ galahad_context_transfer_inline_write(struct pipe_context *_context, } +static void galahad_redefine_user_buffer(struct pipe_context *_context, + struct pipe_resource *_resource, + unsigned offset, unsigned size) +{ + struct galahad_context *glhd_context = galahad_context(_context); + struct galahad_resource *glhd_resource = galahad_resource(_resource); + struct pipe_context *context = glhd_context->pipe; + struct pipe_resource *resource = glhd_resource->resource; + + context->redefine_user_buffer(context, resource, offset, size); +} + + struct pipe_context * galahad_context_create(struct pipe_screen *_screen, struct pipe_context *pipe) { @@ -1036,6 +1049,7 @@ galahad_context_create(struct pipe_screen *_screen, struct pipe_context *pipe) glhd_pipe->base.transfer_unmap = galahad_context_transfer_unmap; glhd_pipe->base.transfer_flush_region = galahad_context_transfer_flush_region; glhd_pipe->base.transfer_inline_write = galahad_context_transfer_inline_write; + glhd_pipe->base.redefine_user_buffer = galahad_redefine_user_buffer; glhd_pipe->pipe = pipe; diff --git a/src/gallium/drivers/i915/TODO b/src/gallium/drivers/i915/TODO index 94c428bebf8..f4e1423fa59 100644 --- a/src/gallium/drivers/i915/TODO +++ b/src/gallium/drivers/i915/TODO @@ -1,5 +1,13 @@ Random list of problems with i915g: +- Check if PIPE_CAP_BLEND_EQUATION_SEPARATE work, the code is there. + If not fix it! A simple task, good for beginners. + +- Add support for PIPE_CAP_POINT_SPRITE either via the draw module or directly + via the hardware, look at the classic driver, more advanced. + +- What does this button do? Figure out LIS7 with regards to depth offset. + - Dies with BadDrawable on GLXFBconfig changes/destruction. Makes piglit totally unusable :( Upgrading xserver helped here, it doesn't crash anymore. Still broken, it doesn't update the viewport/get new buffers. diff --git a/src/gallium/drivers/i915/i915_context.c b/src/gallium/drivers/i915/i915_context.c index ea3c10b5e78..707b2e9f956 100644 --- a/src/gallium/drivers/i915/i915_context.c +++ b/src/gallium/drivers/i915/i915_context.c @@ -39,6 +39,9 @@ #include "pipe/p_screen.h" +DEBUG_GET_ONCE_BOOL_OPTION(i915_no_vbuf, "I915_NO_VBUF", FALSE); + + /* * Draw functions */ @@ -50,7 +53,6 @@ i915_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info) struct i915_context *i915 = i915_context(pipe); struct draw_context *draw = i915->draw; void *mapped_indices = NULL; - unsigned i; unsigned cbuf_dirty; @@ -64,14 +66,6 @@ i915_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info) i915_update_derived(i915); /* - * Map vertex buffers - */ - for (i = 0; i < i915->num_vertex_buffers; i++) { - void *buf = i915_buffer(i915->vertex_buffer[i].buffer)->data; - draw_set_mapped_vertex_buffer(draw, i, buf); - } - - /* * Map index buffer, if present */ if (info->indexed && i915->index_buffer.buffer) @@ -90,13 +84,6 @@ i915_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info) */ draw_vbo(i915->draw, info); - /* - * unmap vertex/index buffers - */ - for (i = 0; i < i915->num_vertex_buffers; i++) { - draw_set_mapped_vertex_buffer(draw, i, NULL); - } - if (mapped_indices) draw_set_mapped_index_buffer(draw, NULL); } @@ -117,10 +104,6 @@ static void i915_destroy(struct pipe_context *pipe) if(i915->batch) i915->iws->batchbuffer_destroy(i915->batch); - for (i = 0; i < i915->num_vertex_buffers; i++) { - pipe_resource_reference(&i915->vertex_buffer[i].buffer, NULL); - } - /* unbind framebuffer */ for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { pipe_surface_reference(&i915->framebuffer.cbufs[i], NULL); @@ -164,7 +147,7 @@ i915_create_context(struct pipe_screen *screen, void *priv) */ i915->draw = draw_create(&i915->base); assert(i915->draw); - if (!debug_get_bool_option("I915_NO_VBUF", FALSE)) { + if (!debug_get_option_i915_no_vbuf()) { draw_set_rasterize_stage(i915->draw, i915_draw_vbuf_stage(i915)); } else { draw_set_rasterize_stage(i915->draw, i915_draw_render_stage(i915)); @@ -180,6 +163,8 @@ i915_create_context(struct pipe_screen *screen, void *priv) i915->dirty = ~0; i915->hardware_dirty = ~0; + i915->immediate_dirty = ~0; + i915->dynamic_dirty = ~0; /* Batch stream debugging is a bit hacked up at the moment: */ diff --git a/src/gallium/drivers/i915/i915_context.h b/src/gallium/drivers/i915/i915_context.h index b7f1fb22221..2cf53424f06 100644 --- a/src/gallium/drivers/i915/i915_context.h +++ b/src/gallium/drivers/i915/i915_context.h @@ -219,14 +219,12 @@ struct i915_context { struct pipe_scissor_state scissor; struct pipe_sampler_view *fragment_sampler_views[PIPE_MAX_SAMPLERS]; struct pipe_viewport_state viewport; - struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; struct pipe_index_buffer index_buffer; unsigned dirty; unsigned num_samplers; unsigned num_fragment_sampler_views; - unsigned num_vertex_buffers; struct i915_winsys_batchbuffer *batch; @@ -237,6 +235,8 @@ struct i915_context { struct i915_state current; unsigned hardware_dirty; + unsigned immediate_dirty; + unsigned dynamic_dirty; struct util_slab_mempool transfer_pool; }; diff --git a/src/gallium/drivers/i915/i915_debug.c b/src/gallium/drivers/i915/i915_debug.c index 845e92cf5c6..1713bf131f2 100644 --- a/src/gallium/drivers/i915/i915_debug.c +++ b/src/gallium/drivers/i915/i915_debug.c @@ -48,10 +48,15 @@ static const struct debug_named_value debug_options[] = { unsigned i915_debug = 0; boolean i915_tiling = TRUE; -void i915_debug_init(struct i915_screen *screen) +DEBUG_GET_ONCE_FLAGS_OPTION(i915_debug, "I915_DEBUG", debug_options, 0) +DEBUG_GET_ONCE_BOOL_OPTION(i915_no_tiling, "I915_NO_TILING", FALSE) +DEBUG_GET_ONCE_BOOL_OPTION(i915_lie, "I915_LIE", FALSE) + +void i915_debug_init(struct i915_screen *is) { - i915_debug = debug_get_flags_option("I915_DEBUG", debug_options, 0); - i915_tiling = !debug_get_bool_option("I915_NO_TILING", FALSE); + i915_debug = debug_get_option_i915_debug(); + is->debug.tiling = !debug_get_option_i915_no_tiling(); + is->debug.lie = debug_get_option_i915_lie(); } diff --git a/src/gallium/drivers/i915/i915_debug.h b/src/gallium/drivers/i915/i915_debug.h index 11af7662f0a..fa60799d0c5 100644 --- a/src/gallium/drivers/i915/i915_debug.h +++ b/src/gallium/drivers/i915/i915_debug.h @@ -46,7 +46,6 @@ struct i915_winsys_batchbuffer; #define DBG_CONSTANTS 0x20 extern unsigned i915_debug; -extern boolean i915_tiling; #ifdef DEBUG static INLINE boolean diff --git a/src/gallium/drivers/i915/i915_flush.c b/src/gallium/drivers/i915/i915_flush.c index a2c70b11991..911c051d1f2 100644 --- a/src/gallium/drivers/i915/i915_flush.c +++ b/src/gallium/drivers/i915/i915_flush.c @@ -74,7 +74,6 @@ static void i915_flush_pipe( struct pipe_context *pipe, /* If there are no flags, just flush pending commands to hardware: */ FLUSH_BATCH(fence); - i915->vbo_flushed = 1; I915_DBG(DBG_FLUSH, "%s: #####\n", __FUNCTION__); } @@ -93,5 +92,8 @@ void i915_flush(struct i915_context *i915, struct pipe_fence_handle **fence) struct i915_winsys_batchbuffer *batch = i915->batch; batch->iws->batchbuffer_flush(batch, fence); + i915->vbo_flushed = 1; i915->hardware_dirty = ~0; + i915->immediate_dirty = ~0; + i915->dynamic_dirty = ~0; } diff --git a/src/gallium/drivers/i915/i915_resource_texture.c b/src/gallium/drivers/i915/i915_resource_texture.c index e793d126ade..aad5235a6ad 100644 --- a/src/gallium/drivers/i915/i915_resource_texture.c +++ b/src/gallium/drivers/i915/i915_resource_texture.c @@ -172,15 +172,15 @@ i915_texture_set_image_offset(struct i915_texture *tex, } static enum i915_winsys_buffer_tile -i915_texture_tiling(struct pipe_resource *pt) +i915_texture_tiling(struct i915_screen *is, struct i915_texture *tex) { - if (!i915_tiling) + if (!is->debug.tiling) return I915_TILE_NONE; - if (pt->target == PIPE_TEXTURE_1D) + if (tex->b.b.target == PIPE_TEXTURE_1D) return I915_TILE_NONE; - if (util_format_is_s3tc(pt->format)) + if (util_format_is_s3tc(tex->b.b.format)) /* XXX X-tiling might make sense */ return I915_TILE_NONE; @@ -401,11 +401,7 @@ i915_texture_layout_3d(struct i915_texture *tex) static boolean i915_texture_layout(struct i915_texture * tex) { - struct pipe_resource *pt = &tex->b.b; - - tex->tiling = i915_texture_tiling(pt); - - switch (pt->target) { + switch (tex->b.b.target) { case PIPE_TEXTURE_1D: case PIPE_TEXTURE_2D: case PIPE_TEXTURE_RECT: @@ -649,11 +645,7 @@ i945_texture_layout_cube(struct i915_texture *tex) static boolean i945_texture_layout(struct i915_texture * tex) { - struct pipe_resource *pt = &tex->b.b; - - tex->tiling = i915_texture_tiling(pt); - - switch (pt->target) { + switch (tex->b.b.target) { case PIPE_TEXTURE_1D: case PIPE_TEXTURE_2D: case PIPE_TEXTURE_RECT: @@ -664,7 +656,7 @@ i945_texture_layout(struct i915_texture * tex) i945_texture_layout_3d(tex); break; case PIPE_TEXTURE_CUBE: - if (!util_format_is_s3tc(pt->format)) + if (!util_format_is_s3tc(tex->b.b.format)) i9x5_texture_layout_cube(tex); else i945_texture_layout_cube(tex); @@ -818,6 +810,8 @@ i915_texture_create(struct pipe_screen *screen, pipe_reference_init(&tex->b.b.reference, 1); tex->b.b.screen = screen; + tex->tiling = i915_texture_tiling(is, tex); + if (is->is_i945) { if (!i945_texture_layout(tex)) goto fail; diff --git a/src/gallium/drivers/i915/i915_screen.c b/src/gallium/drivers/i915/i915_screen.c index bdbc08e8086..77febbf5012 100644 --- a/src/gallium/drivers/i915/i915_screen.c +++ b/src/gallium/drivers/i915/i915_screen.c @@ -98,59 +98,81 @@ i915_get_name(struct pipe_screen *screen) } static int -i915_get_param(struct pipe_screen *screen, enum pipe_cap param) +i915_get_param(struct pipe_screen *screen, enum pipe_cap cap) { - switch (param) { - case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS: - return 8; - case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS: - return 0; - case PIPE_CAP_MAX_COMBINED_SAMPLERS: - return 8; + struct i915_screen *is = i915_screen(screen); + + switch (cap) { + /* Supported features (boolean caps). */ + case PIPE_CAP_ANISOTROPIC_FILTER: case PIPE_CAP_NPOT_TEXTURES: - return 1; + case PIPE_CAP_PRIMITIVE_RESTART: /* draw module */ + case PIPE_CAP_TEXTURE_MIRROR_REPEAT: + case PIPE_CAP_TEXTURE_SHADOW_MAP: case PIPE_CAP_TWO_SIDED_STENCIL: return 1; - case PIPE_CAP_GLSL: - return 0; - case PIPE_CAP_ANISOTROPIC_FILTER: + + /* Features that should be supported (boolean caps). */ + /* XXX: Just test the code */ + case PIPE_CAP_BLEND_EQUATION_SEPARATE: return 0; + + /* Unsupported features (boolean caps). */ + case PIPE_CAP_ARRAY_TEXTURES: + case PIPE_CAP_DEPTH_CLAMP: + case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE: /* disable for now */ + case PIPE_CAP_GLSL: + case PIPE_CAP_INDEP_BLEND_ENABLE: + case PIPE_CAP_INDEP_BLEND_FUNC: + case PIPE_CAP_INSTANCED_DRAWING: /* draw module? */ case PIPE_CAP_POINT_SPRITE: + case PIPE_CAP_SHADER_STENCIL_EXPORT: + case PIPE_CAP_TEXTURE_MIRROR_CLAMP: + case PIPE_CAP_TEXTURE_SWIZZLE: + case PIPE_CAP_TIMER_QUERY: return 0; - case PIPE_CAP_MAX_RENDER_TARGETS: - return 1; + + /* Features we can lie about (boolean caps). */ case PIPE_CAP_OCCLUSION_QUERY: + return is->debug.lie ? 1 : 0; + + /* Texturing. */ + case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS: + case PIPE_CAP_MAX_COMBINED_SAMPLERS: + return 8; + case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS: return 0; - case PIPE_CAP_TIMER_QUERY: - return 0; - case PIPE_CAP_TEXTURE_SHADOW_MAP: - return 1; case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: return I915_MAX_TEXTURE_2D_LEVELS; case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: return I915_MAX_TEXTURE_3D_LEVELS; case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: return I915_MAX_TEXTURE_2D_LEVELS; + + /* Render targets. */ + case PIPE_CAP_MAX_RENDER_TARGETS: + return 1; + + /* Fragment coordinate conventions. */ case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: return 1; case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: return 0; - case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE: - /* disable for now */ - return 0; + default: + debug_printf("%s: Unkown cap %u.\n", __FUNCTION__, cap); return 0; } } static int -i915_get_shader_param(struct pipe_screen *screen, unsigned shader, enum pipe_shader_cap param) +i915_get_shader_param(struct pipe_screen *screen, unsigned shader, enum pipe_shader_cap cap) { switch(shader) { case PIPE_SHADER_VERTEX: - return draw_get_shader_param(shader, param); + return draw_get_shader_param(shader, cap); case PIPE_SHADER_FRAGMENT: break; default: @@ -158,7 +180,7 @@ i915_get_shader_param(struct pipe_screen *screen, unsigned shader, enum pipe_sha } /* XXX: these are just shader model 2.0 values, fix this! */ - switch(param) { + switch(cap) { case PIPE_SHADER_CAP_MAX_INSTRUCTIONS: return 96; case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS: @@ -191,15 +213,15 @@ i915_get_shader_param(struct pipe_screen *screen, unsigned shader, enum pipe_sha case PIPE_SHADER_CAP_SUBROUTINES: return 0; default: - assert(0); + debug_printf("%s: Unkown cap %u.\n", __FUNCTION__, cap); return 0; } } static float -i915_get_paramf(struct pipe_screen *screen, enum pipe_cap param) +i915_get_paramf(struct pipe_screen *screen, enum pipe_cap cap) { - switch (param) { + switch(cap) { case PIPE_CAP_MAX_LINE_WIDTH: /* fall-through */ case PIPE_CAP_MAX_LINE_WIDTH_AA: @@ -217,6 +239,7 @@ i915_get_paramf(struct pipe_screen *screen, enum pipe_cap param) return 16.0; default: + debug_printf("%s: Unkown cap %u.\n", __FUNCTION__, cap); return 0; } } @@ -321,6 +344,20 @@ i915_fence_finish(struct pipe_screen *screen, static void +i915_flush_frontbuffer(struct pipe_screen *screen, + struct pipe_resource *resource, + unsigned level, unsigned layer, + void *winsys_drawable_handle) +{ + /* XXX: Dummy right now. */ + (void)screen; + (void)resource; + (void)level; + (void)layer; + (void)winsys_drawable_handle; +} + +static void i915_destroy_screen(struct pipe_screen *screen) { struct i915_screen *is = i915_screen(screen); @@ -371,6 +408,7 @@ i915_screen_create(struct i915_winsys *iws) is->base.winsys = NULL; is->base.destroy = i915_destroy_screen; + is->base.flush_frontbuffer = i915_flush_frontbuffer; is->base.get_name = i915_get_name; is->base.get_vendor = i915_get_vendor; diff --git a/src/gallium/drivers/i915/i915_screen.h b/src/gallium/drivers/i915/i915_screen.h index bb4d255a3b3..60f0e2971e0 100644 --- a/src/gallium/drivers/i915/i915_screen.h +++ b/src/gallium/drivers/i915/i915_screen.h @@ -45,6 +45,11 @@ struct i915_screen struct i915_winsys *iws; boolean is_i945; + + struct { + boolean tiling; + boolean lie; + } debug; }; diff --git a/src/gallium/drivers/i915/i915_state.c b/src/gallium/drivers/i915/i915_state.c index 4a1a4a04f6d..58bbbd1de2c 100644 --- a/src/gallium/drivers/i915/i915_state.c +++ b/src/gallium/drivers/i915/i915_state.c @@ -33,6 +33,7 @@ #include "util/u_inlines.h" #include "util/u_math.h" #include "util/u_memory.h" +#include "util/u_transfer.h" #include "tgsi/tgsi_parse.h" #include "i915_context.h" @@ -57,10 +58,8 @@ translate_wrap_mode(unsigned wrap) return TEXCOORDMODE_CLAMP_EDGE; case PIPE_TEX_WRAP_CLAMP_TO_BORDER: return TEXCOORDMODE_CLAMP_BORDER; - /* - case PIPE_TEX_WRAP_MIRRORED_REPEAT: + case PIPE_TEX_WRAP_MIRROR_REPEAT: return TEXCOORDMODE_MIRROR; - */ default: return TEXCOORDMODE_WRAP; } @@ -535,21 +534,31 @@ static void i915_set_constant_buffer(struct pipe_context *pipe, /* if we have a new buffer compare it with the old one */ if (buf) { - struct i915_buffer *ir = i915_buffer(buf); + struct i915_buffer *ibuf = i915_buffer(buf); struct pipe_resource *old_buf = i915->constants[shader]; struct i915_buffer *old = old_buf ? i915_buffer(old_buf) : NULL; - - new_num = ir->b.b.width0 / 4 * sizeof(float); - - if (old && new_num != i915->current.num_user_constants[shader]) - diff = memcmp(old->data, ir->data, ir->b.b.width0); + unsigned old_num = i915->current.num_user_constants[shader]; + + new_num = ibuf->b.b.width0 / 4 * sizeof(float); + + if (old_num == new_num) { + if (old_num == 0) + diff = FALSE; +#if 0 + /* XXX no point in running this code since st/mesa only uses user buffers */ + /* Can't compare the buffer data since they are userbuffers */ + else if (old && old->free_on_destroy) + diff = memcmp(old->data, ibuf->data, ibuf->b.b.width0); +#else + (void)old; +#endif + } } else { diff = i915->current.num_user_constants[shader] != 0; } /* * flush before updateing the state. - * XXX: looks like its okay to skip the flush for vertex cbufs */ if (diff && shader == PIPE_SHADER_FRAGMENT) draw_flush(i915->draw); @@ -766,17 +775,25 @@ static void i915_set_vertex_buffers(struct pipe_context *pipe, const struct pipe_vertex_buffer *buffers) { struct i915_context *i915 = i915_context(pipe); - /* Because we change state before the draw_set_vertex_buffers call - * we need a flush here, just to be sure. - */ - draw_flush(i915->draw); + struct draw_context *draw = i915->draw; + int i; - util_copy_vertex_buffers(i915->vertex_buffer, - &i915->num_vertex_buffers, - buffers, count); +#if 0 + /* XXX doesn't look like this is needed */ + /* unmap old */ + for (i = 0; i < i915->num_vertex_buffers; i++) { + draw_set_mapped_vertex_buffer(draw, i, NULL); + } +#endif /* pass-through to draw module */ - draw_set_vertex_buffers(i915->draw, count, buffers); + draw_set_vertex_buffers(draw, count, buffers); + + /* map new */ + for (i = 0; i < count; i++) { + void *buf = i915_buffer(buffers[i].buffer)->data; + draw_set_mapped_vertex_buffer(draw, i, buf); + } } static void * @@ -801,11 +818,6 @@ i915_bind_vertex_elements_state(struct pipe_context *pipe, struct i915_context *i915 = i915_context(pipe); struct i915_velems_state *i915_velems = (struct i915_velems_state *) velems; - /* Because we change state before the draw_set_vertex_buffers call - * we need a flush here, just to be sure. - */ - draw_flush(i915->draw); - /* pass-through to draw module */ if (i915_velems) { draw_set_vertex_elements(i915->draw, @@ -882,4 +894,5 @@ i915_init_state_functions( struct i915_context *i915 ) i915->base.set_viewport_state = i915_set_viewport_state; i915->base.set_vertex_buffers = i915_set_vertex_buffers; i915->base.set_index_buffer = i915_set_index_buffer; + i915->base.redefine_user_buffer = u_default_redefine_user_buffer; } diff --git a/src/gallium/drivers/i915/i915_state_dynamic.c b/src/gallium/drivers/i915/i915_state_dynamic.c index d61a8c3407f..204cee6fe9e 100644 --- a/src/gallium/drivers/i915/i915_state_dynamic.c +++ b/src/gallium/drivers/i915/i915_state_dynamic.c @@ -46,18 +46,34 @@ * (active) state every time a 4kb boundary is crossed. */ -static INLINE void set_dynamic_indirect(struct i915_context *i915, - unsigned offset, - const unsigned *src, - unsigned dwords) +static INLINE void set_dynamic(struct i915_context *i915, + unsigned offset, + const unsigned state) +{ + if (i915->current.dynamic[offset] == state) + return; + + i915->current.dynamic[offset] = state; + i915->dynamic_dirty |= 1 << offset; + i915->hardware_dirty |= I915_HW_DYNAMIC; +} + + + +static INLINE void set_dynamic_array(struct i915_context *i915, + unsigned offset, + const unsigned *src, + unsigned dwords) { unsigned i; if (!memcmp(src, &i915->current.dynamic[offset], dwords * 4)) return; - for (i = 0; i < dwords; i++) + for (i = 0; i < dwords; i++) { i915->current.dynamic[offset + i] = src[i]; + i915->dynamic_dirty |= 1 << (offset + i); + } i915->hardware_dirty |= I915_HW_DYNAMIC; } @@ -79,12 +95,7 @@ static void upload_MODES4(struct i915_context *i915) */ modes4 |= i915->blend->modes4; - /* Always, so that we know when state is in-active: - */ - set_dynamic_indirect(i915, - I915_DYNAMIC_MODES4, - &modes4, - 1); + set_dynamic(i915, I915_DYNAMIC_MODES4, modes4); } const struct i915_tracked_state i915_upload_MODES4 = { @@ -107,10 +118,7 @@ static void upload_BFO(struct i915_context *i915) bfo[0] |= i915->stencil_ref.ref_value[1] << BFO_STENCIL_REF_SHIFT; } - set_dynamic_indirect(i915, - I915_DYNAMIC_BFO_0, - &(bfo[0]), - 2); + set_dynamic_array(i915, I915_DYNAMIC_BFO_0, bfo, 2); } const struct i915_tracked_state i915_upload_BFO = { @@ -141,10 +149,7 @@ static void upload_BLENDCOLOR(struct i915_context *i915) color[3]); } - set_dynamic_indirect(i915, - I915_DYNAMIC_BC_0, - bc, - 2); + set_dynamic_array(i915, I915_DYNAMIC_BC_0, bc, 2); } const struct i915_tracked_state i915_upload_BLENDCOLOR = { @@ -161,10 +166,7 @@ static void upload_IAB(struct i915_context *i915) { unsigned iab = i915->blend->iab; - set_dynamic_indirect(i915, - I915_DYNAMIC_IAB, - &iab, - 1); + set_dynamic(i915, I915_DYNAMIC_IAB, iab); } const struct i915_tracked_state i915_upload_IAB = { @@ -179,10 +181,8 @@ const struct i915_tracked_state i915_upload_IAB = { */ static void upload_DEPTHSCALE(struct i915_context *i915) { - set_dynamic_indirect(i915, - I915_DYNAMIC_DEPTHSCALE_0, - &(i915->rasterizer->ds[0].u), - 2); + set_dynamic_array(i915, I915_DYNAMIC_DEPTHSCALE_0, + &i915->rasterizer->ds[0].u, 2); } const struct i915_tracked_state i915_upload_DEPTHSCALE = { @@ -234,10 +234,7 @@ static void upload_STIPPLE(struct i915_context *i915) (p[3] << 12)); } - set_dynamic_indirect(i915, - I915_DYNAMIC_STP_0, - &st[0], - 2); + set_dynamic_array(i915, I915_DYNAMIC_STP_0, st, 2); } const struct i915_tracked_state i915_upload_STIPPLE = { @@ -253,10 +250,7 @@ const struct i915_tracked_state i915_upload_STIPPLE = { */ static void upload_SCISSOR_ENABLE( struct i915_context *i915 ) { - set_dynamic_indirect(i915, - I915_DYNAMIC_SC_ENA_0, - &(i915->rasterizer->sc[0]), - 1); + set_dynamic(i915, I915_DYNAMIC_SC_ENA_0, i915->rasterizer->sc[0]); } const struct i915_tracked_state i915_upload_SCISSOR_ENABLE = { @@ -282,10 +276,7 @@ static void upload_SCISSOR_RECT(struct i915_context *i915) sc[1] = (y1 << 16) | (x1 & 0xffff); sc[2] = (y2 << 16) | (x2 & 0xffff); - set_dynamic_indirect(i915, - I915_DYNAMIC_SC_RECT_0, - &sc[0], - 3); + set_dynamic_array(i915, I915_DYNAMIC_SC_RECT_0, sc, 3); } const struct i915_tracked_state i915_upload_SCISSOR_RECT = { diff --git a/src/gallium/drivers/i915/i915_state_emit.c b/src/gallium/drivers/i915/i915_state_emit.c index 5a89977c26c..509d487b498 100644 --- a/src/gallium/drivers/i915/i915_state_emit.c +++ b/src/gallium/drivers/i915/i915_state_emit.c @@ -35,6 +35,8 @@ #include "pipe/p_context.h" #include "pipe/p_defines.h" +#include "util/u_math.h" + static unsigned translate_format( enum pipe_format format ) { switch (format) { @@ -178,11 +180,6 @@ i915_emit_hardware_state(struct i915_context *i915 ) ENABLE_TEXKILL_3D_4D | TEXKILL_4D); - /* Need to initialize this to zero. - */ - OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(3) | (0)); - OUT_BATCH(0); - OUT_BATCH(_3DSTATE_DEPTH_SUBRECT_DISABLE); /* disable indirect state for now @@ -194,27 +191,30 @@ i915_emit_hardware_state(struct i915_context *i915 ) /* 7 dwords, 1 relocs */ if (i915->hardware_dirty & I915_HW_IMMEDIATE) { - OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | - I1_LOAD_S(0) | - I1_LOAD_S(1) | - I1_LOAD_S(2) | - I1_LOAD_S(4) | - I1_LOAD_S(5) | - I1_LOAD_S(6) | - (5)); - - if(i915->vbo) - OUT_RELOC(i915->vbo, - I915_USAGE_VERTEX, - i915->current.immediate[I915_IMMEDIATE_S0]); - else - /* FIXME: we should not do this */ - OUT_BATCH(0); - OUT_BATCH(i915->current.immediate[I915_IMMEDIATE_S1]); - OUT_BATCH(i915->current.immediate[I915_IMMEDIATE_S2]); - OUT_BATCH(i915->current.immediate[I915_IMMEDIATE_S4]); - OUT_BATCH(i915->current.immediate[I915_IMMEDIATE_S5]); - OUT_BATCH(i915->current.immediate[I915_IMMEDIATE_S6]); + /* remove unwatned bits and S7 */ + unsigned dirty = (1 << I915_IMMEDIATE_S0 | 1 << I915_IMMEDIATE_S1 | + 1 << I915_IMMEDIATE_S2 | 1 << I915_IMMEDIATE_S3 | + 1 << I915_IMMEDIATE_S3 | 1 << I915_IMMEDIATE_S4 | + 1 << I915_IMMEDIATE_S5 | 1 << I915_IMMEDIATE_S6) & + i915->immediate_dirty; + int i, num = util_bitcount(dirty); + assert(num && num <= I915_MAX_IMMEDIATE); + + OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | + dirty << 4 | (num - 1)); + + if (i915->immediate_dirty & (1 << I915_IMMEDIATE_S0)) { + if (i915->vbo) + OUT_RELOC(i915->vbo, I915_USAGE_VERTEX, + i915->current.immediate[I915_IMMEDIATE_S0]); + else + OUT_BATCH(0); + } + + for (i = 1; i < I915_MAX_IMMEDIATE; i++) { + if (dirty & (1 << i)) + OUT_BATCH(i915->current.immediate[i]); + } } #if 01 @@ -223,7 +223,8 @@ i915_emit_hardware_state(struct i915_context *i915 ) { int i; for (i = 0; i < I915_MAX_DYNAMIC; i++) { - OUT_BATCH(i915->current.dynamic[i]); + if (i915->dynamic_dirty & (1 << i)); + OUT_BATCH(i915->current.dynamic[i]); } } #endif @@ -443,4 +444,6 @@ i915_emit_hardware_state(struct i915_context *i915 ) i915->batch->relocs - save_relocs); i915->hardware_dirty = 0; + i915->immediate_dirty = 0; + i915->dynamic_dirty = 0; } diff --git a/src/gallium/drivers/i915/i915_state_immediate.c b/src/gallium/drivers/i915/i915_state_immediate.c index f9ade7077f2..81348647399 100644 --- a/src/gallium/drivers/i915/i915_state_immediate.c +++ b/src/gallium/drivers/i915/i915_state_immediate.c @@ -36,12 +36,20 @@ #include "util/u_memory.h" -/* All state expressable with the LOAD_STATE_IMMEDIATE_1 packet. - * Would like to opportunistically recombine all these fragments into - * a single packet containing only what has changed, but for now emit - * as multiple packets. +/* Convinience function to check immediate state. */ +static INLINE void set_immediate(struct i915_context *i915, + unsigned offset, + const unsigned state) +{ + if (i915->current.immediate[offset] == state) + return; + + i915->current.immediate[offset] = state; + i915->immediate_dirty |= 1 << offset; + i915->hardware_dirty |= I915_HW_IMMEDIATE; +} @@ -56,9 +64,14 @@ static void upload_S0S1(struct i915_context *i915) */ LIS0 = i915->vbo_offset; + /* Need to force this */ + if (i915->dirty & I915_NEW_VBO) { + i915->immediate_dirty |= 1 << I915_IMMEDIATE_S0; + i915->hardware_dirty |= I915_HW_IMMEDIATE; + } + /* I915_NEW_VERTEX_SIZE */ - /* XXX do this where the vertex size is calculated! */ { unsigned vertex_size = i915->current.vertex_info.size; @@ -66,16 +79,8 @@ static void upload_S0S1(struct i915_context *i915) (vertex_size << 16)); } - /* I915_NEW_VBO - */ - if (1 || - i915->current.immediate[I915_IMMEDIATE_S0] != LIS0 || - i915->current.immediate[I915_IMMEDIATE_S1] != LIS1) - { - i915->current.immediate[I915_IMMEDIATE_S0] = LIS0; - i915->current.immediate[I915_IMMEDIATE_S1] = LIS1; - i915->hardware_dirty |= I915_HW_IMMEDIATE; - } + set_immediate(i915, I915_IMMEDIATE_S0, LIS0); + set_immediate(i915, I915_IMMEDIATE_S1, LIS1); } const struct i915_tracked_state i915_upload_S0S1 = { @@ -98,21 +103,13 @@ static void upload_S2S4(struct i915_context *i915) { LIS2 = i915->current.vertex_info.hwfmt[1]; LIS4 = i915->current.vertex_info.hwfmt[0]; - /* - debug_printf("LIS2: 0x%x LIS4: 0x%x\n", LIS2, LIS4); - */ assert(LIS4); /* should never be zero? */ } LIS4 |= i915->rasterizer->LIS4; - if (LIS2 != i915->current.immediate[I915_IMMEDIATE_S2] || - LIS4 != i915->current.immediate[I915_IMMEDIATE_S4]) { - - i915->current.immediate[I915_IMMEDIATE_S2] = LIS2; - i915->current.immediate[I915_IMMEDIATE_S4] = LIS4; - i915->hardware_dirty |= I915_HW_IMMEDIATE; - } + set_immediate(i915, I915_IMMEDIATE_S2, LIS2); + set_immediate(i915, I915_IMMEDIATE_S4, LIS4); } const struct i915_tracked_state i915_upload_S2S4 = { @@ -142,15 +139,12 @@ static void upload_S5(struct i915_context *i915) #if 0 /* I915_NEW_RASTERIZER */ - if (i915->state.Polygon->OffsetFill) { + if (i915->rasterizer->LIS7) { LIS5 |= S5_GLOBAL_DEPTH_OFFSET_ENABLE; } #endif - if (LIS5 != i915->current.immediate[I915_IMMEDIATE_S5]) { - i915->current.immediate[I915_IMMEDIATE_S5] = LIS5; - i915->hardware_dirty |= I915_HW_IMMEDIATE; - } + set_immediate(i915, I915_IMMEDIATE_S5, LIS5); } const struct i915_tracked_state i915_upload_S5 = { @@ -180,14 +174,11 @@ static void upload_S6(struct i915_context *i915) */ LIS6 |= i915->depth_stencil->depth_LIS6; - if (LIS6 != i915->current.immediate[I915_IMMEDIATE_S6]) { - i915->current.immediate[I915_IMMEDIATE_S6] = LIS6; - i915->hardware_dirty |= I915_HW_IMMEDIATE; - } + set_immediate(i915, I915_IMMEDIATE_S6, LIS6); } const struct i915_tracked_state i915_upload_S6 = { - "imm s6", + "imm S6", upload_S6, I915_NEW_BLEND | I915_NEW_DEPTH_STENCIL | I915_NEW_FRAMEBUFFER }; @@ -204,10 +195,9 @@ static void upload_S7(struct i915_context *i915) */ LIS7 = i915->rasterizer->LIS7; - if (LIS7 != i915->current.immediate[I915_IMMEDIATE_S7]) { - i915->current.immediate[I915_IMMEDIATE_S7] = LIS7; - i915->hardware_dirty |= I915_HW_IMMEDIATE; - } +#if 0 + set_immediate(i915, I915_IMMEDIATE_S7, LIS7); +#endif } const struct i915_tracked_state i915_upload_S7 = { diff --git a/src/gallium/drivers/i915/i915_winsys.h b/src/gallium/drivers/i915/i915_winsys.h index 24ea416f015..e915a886c9b 100644 --- a/src/gallium/drivers/i915/i915_winsys.h +++ b/src/gallium/drivers/i915/i915_winsys.h @@ -103,11 +103,12 @@ struct i915_winsys { * @usage how is the hardware going to use the buffer. * @offset add this to the reloc buffers address * @target buffer where to write the address, null for batchbuffer. + * @fenced relocation needs a fence. */ int (*batchbuffer_reloc)(struct i915_winsys_batchbuffer *batch, struct i915_winsys_buffer *reloc, enum i915_winsys_buffer_usage usage, - unsigned offset, bool fenced); + unsigned offset, boolean fenced); /** * Flush a bufferbatch. diff --git a/src/gallium/drivers/i965/brw_pipe_vertex.c b/src/gallium/drivers/i965/brw_pipe_vertex.c index b23454b5808..570ea23ff45 100644 --- a/src/gallium/drivers/i965/brw_pipe_vertex.c +++ b/src/gallium/drivers/i965/brw_pipe_vertex.c @@ -4,6 +4,7 @@ #include "util/u_memory.h" #include "util/u_format.h" +#include "util/u_transfer.h" static unsigned brw_translate_surface_format( unsigned id ) @@ -302,6 +303,7 @@ brw_pipe_vertex_init( struct brw_context *brw ) brw->base.create_vertex_elements_state = brw_create_vertex_elements_state; brw->base.bind_vertex_elements_state = brw_bind_vertex_elements_state; brw->base.delete_vertex_elements_state = brw_delete_vertex_elements_state; + brw->base.redefine_user_buffer = u_default_redefine_user_buffer; } diff --git a/src/gallium/drivers/identity/id_context.c b/src/gallium/drivers/identity/id_context.c index 3efbd6a246d..b533abe24c6 100644 --- a/src/gallium/drivers/identity/id_context.c +++ b/src/gallium/drivers/identity/id_context.c @@ -855,6 +855,19 @@ identity_context_transfer_inline_write(struct pipe_context *_context, } +static void identity_redefine_user_buffer(struct pipe_context *_context, + struct pipe_resource *_resource, + unsigned offset, unsigned size) +{ + struct identity_context *id_context = identity_context(_context); + struct identity_resource *id_resource = identity_resource(_resource); + struct pipe_context *context = id_context->pipe; + struct pipe_resource *resource = id_resource->resource; + + context->redefine_user_buffer(context, resource, offset, size); +} + + struct pipe_context * identity_context_create(struct pipe_screen *_screen, struct pipe_context *pipe) { @@ -929,6 +942,7 @@ identity_context_create(struct pipe_screen *_screen, struct pipe_context *pipe) id_pipe->base.transfer_unmap = identity_context_transfer_unmap; id_pipe->base.transfer_flush_region = identity_context_transfer_flush_region; id_pipe->base.transfer_inline_write = identity_context_transfer_inline_write; + id_pipe->base.redefine_user_buffer = identity_redefine_user_buffer; id_pipe->pipe = pipe; diff --git a/src/gallium/drivers/llvmpipe/SConscript b/src/gallium/drivers/llvmpipe/SConscript index 26b258b9569..c10a8cbc12c 100644 --- a/src/gallium/drivers/llvmpipe/SConscript +++ b/src/gallium/drivers/llvmpipe/SConscript @@ -96,10 +96,15 @@ if env['platform'] != 'embedded': tests.append('round') for test in tests: + testname = 'lp_test_' + test target = env.Program( - target = 'lp_test_' + test, - source = ['lp_test_' + test + '.c', 'lp_test_main.c'], + target = testname, + source = [testname + '.c', 'lp_test_main.c'], ) env.InstallProgram(target) + + # http://www.scons.org/wiki/UnitTests + alias = env.Alias(testname, [target], target[0].abspath) + AlwaysBuild(alias) Export('llvmpipe') diff --git a/src/gallium/drivers/llvmpipe/lp_flush.c b/src/gallium/drivers/llvmpipe/lp_flush.c index 85e3cdec82c..849db06acdf 100644 --- a/src/gallium/drivers/llvmpipe/lp_flush.c +++ b/src/gallium/drivers/llvmpipe/lp_flush.c @@ -72,7 +72,7 @@ llvmpipe_flush( struct pipe_context *pipe, for (i = 0; i < llvmpipe->framebuffer.nr_cbufs; i++) { util_snprintf(filename, sizeof(filename), "cbuf%u_%u", i, frame_no); - debug_dump_surface_bmp(&llvmpipe->pipe, filename, llvmpipe->framebuffer.cbufs[0]); + debug_dump_surface_bmp(&llvmpipe->pipe, filename, llvmpipe->framebuffer.cbufs[i]); } if (0) { diff --git a/src/gallium/drivers/llvmpipe/lp_state_vertex.c b/src/gallium/drivers/llvmpipe/lp_state_vertex.c index fffdeb6ccde..be86f66de91 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_vertex.c +++ b/src/gallium/drivers/llvmpipe/lp_state_vertex.c @@ -34,6 +34,7 @@ #include "draw/draw_context.h" #include "util/u_inlines.h" +#include "util/u_transfer.h" static void * @@ -114,4 +115,6 @@ llvmpipe_init_vertex_funcs(struct llvmpipe_context *llvmpipe) llvmpipe->pipe.set_vertex_buffers = llvmpipe_set_vertex_buffers; llvmpipe->pipe.set_index_buffer = llvmpipe_set_index_buffer; + + llvmpipe->pipe.redefine_user_buffer = u_default_redefine_user_buffer; } diff --git a/src/gallium/drivers/llvmpipe/lp_test_main.c b/src/gallium/drivers/llvmpipe/lp_test_main.c index 149ee6f1256..d229c620310 100644 --- a/src/gallium/drivers/llvmpipe/lp_test_main.c +++ b/src/gallium/drivers/llvmpipe/lp_test_main.c @@ -35,24 +35,13 @@ #include "util/u_cpu_detect.h" +#include "util/u_math.h" #include "gallivm/lp_bld_const.h" #include "gallivm/lp_bld_init.h" #include "lp_test.h" -#ifdef PIPE_CC_MSVC -static INLINE double -round(double x) -{ - if (x >= 0.0) - return floor(x + 0.5); - else - return ceil(x - 0.5); -} -#endif - - void dump_type(FILE *fp, struct lp_type type) diff --git a/src/gallium/drivers/noop/noop_state.c b/src/gallium/drivers/noop/noop_state.c index ad324774c03..00a4c1eb01e 100644 --- a/src/gallium/drivers/noop/noop_state.c +++ b/src/gallium/drivers/noop/noop_state.c @@ -28,6 +28,7 @@ #include <pipe/p_screen.h> #include <util/u_memory.h> #include <util/u_inlines.h> +#include "util/u_transfer.h" static void noop_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info) { @@ -287,4 +288,5 @@ void noop_init_state_functions(struct pipe_context *ctx) ctx->sampler_view_destroy = noop_sampler_view_destroy; ctx->surface_destroy = noop_surface_destroy; ctx->draw_vbo = noop_draw_vbo; + ctx->redefine_user_buffer = u_default_redefine_user_buffer; } diff --git a/src/gallium/drivers/nv50/nv50_pc_optimize.c b/src/gallium/drivers/nv50/nv50_pc_optimize.c index 27eb3817bf1..679e5ea1485 100644 --- a/src/gallium/drivers/nv50/nv50_pc_optimize.c +++ b/src/gallium/drivers/nv50/nv50_pc_optimize.c @@ -299,7 +299,7 @@ check_swap_src_0_1(struct nv_instruction *nvi) } if (nvi->opcode == NV_OP_SET && nvi->src[0] != src0) - nvi->set_cond = cc_swapped[nvi->set_cond]; + nvi->set_cond = (nvi->set_cond & ~7) | cc_swapped[nvi->set_cond & 7]; } static int diff --git a/src/gallium/drivers/nv50/nv50_query.c b/src/gallium/drivers/nv50/nv50_query.c index 53f94820ce0..f3418df8381 100644 --- a/src/gallium/drivers/nv50/nv50_query.c +++ b/src/gallium/drivers/nv50/nv50_query.c @@ -45,7 +45,7 @@ nv50_query_create(struct pipe_context *pipe, unsigned type) struct nv50_query *q = CALLOC_STRUCT(nv50_query); int ret; - assert (q->type == PIPE_QUERY_OCCLUSION_COUNTER); + assert (type == PIPE_QUERY_OCCLUSION_COUNTER); q->type = type; ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 256, diff --git a/src/gallium/drivers/nv50/nv50_state.c b/src/gallium/drivers/nv50/nv50_state.c index b4eda0f617d..ba2c3e8c281 100644 --- a/src/gallium/drivers/nv50/nv50_state.c +++ b/src/gallium/drivers/nv50/nv50_state.c @@ -23,6 +23,7 @@ #include "pipe/p_state.h" #include "pipe/p_defines.h" #include "util/u_inlines.h" +#include "util/u_transfer.h" #include "tgsi/tgsi_parse.h" @@ -886,5 +887,6 @@ nv50_init_state_functions(struct nv50_context *nv50) nv50->pipe.set_vertex_buffers = nv50_set_vertex_buffers; nv50->pipe.set_index_buffer = nv50_set_index_buffer; + nv50->pipe.redefine_user_buffer = u_default_redefine_user_buffer; } diff --git a/src/gallium/drivers/nv50/nv50_tgsi_to_nc.c b/src/gallium/drivers/nv50/nv50_tgsi_to_nc.c index d6b80c3ea79..ce9300ad8fd 100644 --- a/src/gallium/drivers/nv50/nv50_tgsi_to_nc.c +++ b/src/gallium/drivers/nv50/nv50_tgsi_to_nc.c @@ -1130,7 +1130,7 @@ emit_fetch(struct bld_context *bld, const struct tgsi_full_instruction *insn, case TGSI_FILE_INPUT: res = bld_saved_input(bld, idx, swz); if (res && (insn->Instruction.Opcode != TGSI_OPCODE_TXP)) - return res; + break; res = new_value(bld->pc, bld->ti->input_file, type); res->reg.id = bld->ti->input_map[idx][swz]; diff --git a/src/gallium/drivers/nvc0/nvc0_3d.xml.h b/src/gallium/drivers/nvc0/nvc0_3d.xml.h index 61932ff2b6a..73a605f94e1 100644 --- a/src/gallium/drivers/nvc0/nvc0_3d.xml.h +++ b/src/gallium/drivers/nvc0/nvc0_3d.xml.h @@ -84,6 +84,14 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define NVC0_3D_EARLY_FRAGMENT_TESTS 0x00000210 +#define NVC0_3D_MEM_BARRIER 0x0000021c +#define NVC0_3D_MEM_BARRIER_UNK0 0x00000001 +#define NVC0_3D_MEM_BARRIER_UNK1 0x00000002 +#define NVC0_3D_MEM_BARRIER_UNK2 0x00000004 +#define NVC0_3D_MEM_BARRIER_UNK4 0x00000010 +#define NVC0_3D_MEM_BARRIER_UNK8 0x00000100 +#define NVC0_3D_MEM_BARRIER_UNK12 0x00001000 + #define NVC0_3D_TESS_MODE 0x00000320 #define NVC0_3D_TESS_MODE_PRIM__MASK 0x0000000f #define NVC0_3D_TESS_MODE_PRIM__SHIFT 0 @@ -122,11 +130,17 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define NVC0_3D_TFB_PRIMITIVE_ID(i0) (0x00000390 + 0x20*(i0)) -#define NVC0_3D_TFB_UNK0700(i0) (0x00000700 + 0x10*(i0)) +#define NVC0_3D_TFB_UNK07X0(i0) (0x00000700 + 0x10*(i0)) +#define NVC0_3D_TFB_UNK07X0__ESIZE 0x00000010 +#define NVC0_3D_TFB_UNK07X0__LEN 0x00000004 #define NVC0_3D_TFB_VARYING_COUNT(i0) (0x00000704 + 0x10*(i0)) +#define NVC0_3D_TFB_VARYING_COUNT__ESIZE 0x00000010 +#define NVC0_3D_TFB_VARYING_COUNT__LEN 0x00000004 #define NVC0_3D_TFB_BUFFER_STRIDE(i0) (0x00000708 + 0x10*(i0)) +#define NVC0_3D_TFB_BUFFER_STRIDE__ESIZE 0x00000010 +#define NVC0_3D_TFB_BUFFER_STRIDE__LEN 0x00000004 #define NVC0_3D_TFB_ENABLE 0x00000744 @@ -144,29 +158,29 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define NVC0_3D_RT__ESIZE 0x00000020 #define NVC0_3D_RT__LEN 0x00000008 -#define NVC0_3D_RT_ADDRESS_HIGH(i0) (0x00000800 + 0x20*(i0)) +#define NVC0_3D_RT_ADDRESS_HIGH(i0) (0x00000800 + 0x40*(i0)) -#define NVC0_3D_RT_ADDRESS_LOW(i0) (0x00000804 + 0x20*(i0)) +#define NVC0_3D_RT_ADDRESS_LOW(i0) (0x00000804 + 0x40*(i0)) -#define NVC0_3D_RT_HORIZ(i0) (0x00000808 + 0x20*(i0)) +#define NVC0_3D_RT_HORIZ(i0) (0x00000808 + 0x40*(i0)) -#define NVC0_3D_RT_VERT(i0) (0x0000080c + 0x20*(i0)) +#define NVC0_3D_RT_VERT(i0) (0x0000080c + 0x40*(i0)) -#define NVC0_3D_RT_FORMAT(i0) (0x00000810 + 0x20*(i0)) +#define NVC0_3D_RT_FORMAT(i0) (0x00000810 + 0x40*(i0)) -#define NVC0_3D_RT_TILE_MODE(i0) (0x00000814 + 0x20*(i0)) +#define NVC0_3D_RT_TILE_MODE(i0) (0x00000814 + 0x40*(i0)) #define NVC0_3D_RT_TILE_MODE_UNK0 0x00000001 #define NVC0_3D_RT_TILE_MODE_Y__MASK 0x00000070 #define NVC0_3D_RT_TILE_MODE_Y__SHIFT 4 #define NVC0_3D_RT_TILE_MODE_Z__MASK 0x00000700 #define NVC0_3D_RT_TILE_MODE_Z__SHIFT 8 -#define NVC0_3D_RT_ARRAY_MODE(i0) (0x00000818 + 0x20*(i0)) +#define NVC0_3D_RT_ARRAY_MODE(i0) (0x00000818 + 0x40*(i0)) #define NVC0_3D_RT_ARRAY_MODE_LAYERS__MASK 0x0000ffff #define NVC0_3D_RT_ARRAY_MODE_LAYERS__SHIFT 0 #define NVC0_3D_RT_ARRAY_MODE_VOLUME 0x00010000 -#define NVC0_3D_RT_LAYER_STRIDE(i0) (0x0000081c + 0x20*(i0)) +#define NVC0_3D_RT_LAYER_STRIDE(i0) (0x0000081c + 0x40*(i0)) #define NVC0_3D_VIEWPORT_SCALE_X(i0) (0x00000a00 + 0x20*(i0)) #define NVC0_3D_VIEWPORT_SCALE_X__ESIZE 0x00000020 @@ -216,21 +230,21 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define NVC0_3D_DEPTH_RANGE_FAR__ESIZE 0x00000010 #define NVC0_3D_DEPTH_RANGE_FAR__LEN 0x00000010 -#define NVC0_3D_VIEWPORT_CLIP_HORIZ(i0) (0x00000d00 + 0x8*(i0)) -#define NVC0_3D_VIEWPORT_CLIP_HORIZ__ESIZE 0x00000008 -#define NVC0_3D_VIEWPORT_CLIP_HORIZ__LEN 0x00000008 -#define NVC0_3D_VIEWPORT_CLIP_HORIZ_MIN__MASK 0x0000ffff -#define NVC0_3D_VIEWPORT_CLIP_HORIZ_MIN__SHIFT 0 -#define NVC0_3D_VIEWPORT_CLIP_HORIZ_MAX__MASK 0xffff0000 -#define NVC0_3D_VIEWPORT_CLIP_HORIZ_MAX__SHIFT 16 - -#define NVC0_3D_VIEWPORT_CLIP_VERT(i0) (0x00000d04 + 0x8*(i0)) -#define NVC0_3D_VIEWPORT_CLIP_VERT__ESIZE 0x00000008 -#define NVC0_3D_VIEWPORT_CLIP_VERT__LEN 0x00000008 -#define NVC0_3D_VIEWPORT_CLIP_VERT_MIN__MASK 0x0000ffff -#define NVC0_3D_VIEWPORT_CLIP_VERT_MIN__SHIFT 0 -#define NVC0_3D_VIEWPORT_CLIP_VERT_MAX__MASK 0xffff0000 -#define NVC0_3D_VIEWPORT_CLIP_VERT_MAX__SHIFT 16 +#define NVC0_3D_CLIP_RECT_HORIZ(i0) (0x00000d00 + 0x8*(i0)) +#define NVC0_3D_CLIP_RECT_HORIZ__ESIZE 0x00000008 +#define NVC0_3D_CLIP_RECT_HORIZ__LEN 0x00000008 +#define NVC0_3D_CLIP_RECT_HORIZ_MIN__MASK 0x0000ffff +#define NVC0_3D_CLIP_RECT_HORIZ_MIN__SHIFT 0 +#define NVC0_3D_CLIP_RECT_HORIZ_MAX__MASK 0xffff0000 +#define NVC0_3D_CLIP_RECT_HORIZ_MAX__SHIFT 16 + +#define NVC0_3D_CLIP_RECT_VERT(i0) (0x00000d04 + 0x8*(i0)) +#define NVC0_3D_CLIP_RECT_VERT__ESIZE 0x00000008 +#define NVC0_3D_CLIP_RECT_VERT__LEN 0x00000008 +#define NVC0_3D_CLIP_RECT_VERT_MIN__MASK 0x0000ffff +#define NVC0_3D_CLIP_RECT_VERT_MIN__SHIFT 0 +#define NVC0_3D_CLIP_RECT_VERT_MAX__MASK 0xffff0000 +#define NVC0_3D_CLIP_RECT_VERT_MAX__SHIFT 16 #define NVC0_3D_CLIPID_REGION_HORIZ(i0) (0x00000d40 + 0x8*(i0)) #define NVC0_3D_CLIPID_REGION_HORIZ__ESIZE 0x00000008 @@ -356,6 +370,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define NVC0_3D_SCREEN_SCISSOR_VERT_Y__MASK 0x0000ffff #define NVC0_3D_SCREEN_SCISSOR_VERT_Y__SHIFT 0 +#define NVC0_3D_CLEAR_FLAGS 0x000010f8 +#define NVC0_3D_CLEAR_FLAGS_STENCIL_MASK 0x00000001 +#define NVC0_3D_CLEAR_FLAGS_UNK4 0x00000010 +#define NVC0_3D_CLEAR_FLAGS_SCISSOR 0x00000100 +#define NVC0_3D_CLEAR_FLAGS_VIEWPORT 0x00001000 + #define NVC0_3D_VERTEX_ID 0x00001118 #define NVC0_3D_VTX_ATTR_DEFINE 0x0000114c @@ -561,7 +581,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define NVC0_3D_BLEND_ENABLE__ESIZE 0x00000004 #define NVC0_3D_BLEND_ENABLE__LEN 0x00000008 -#define NVC0_3D_STENCIL_FRONT_ENABLE 0x00001380 +#define NVC0_3D_STENCIL_ENABLE 0x00001380 #define NVC0_3D_STENCIL_FRONT_OP_FAIL 0x00001384 #define NVC0_3D_STENCIL_FRONT_OP_FAIL_ZERO 0x00000000 @@ -605,9 +625,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define NVC0_3D_STENCIL_FRONT_FUNC_REF 0x00001394 -#define NVC0_3D_STENCIL_FRONT_MASK 0x00001398 +#define NVC0_3D_STENCIL_FRONT_FUNC_MASK 0x00001398 -#define NVC0_3D_STENCIL_FRONT_FUNC_MASK 0x0000139c +#define NVC0_3D_STENCIL_FRONT_MASK 0x0000139c #define NVC0_3D_DRAW_TFB_BASE 0x000013a4 @@ -642,6 +662,18 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define NVC0_3D_CLIPID_HEIGHT 0x00001504 #define NVC0_3D_CLIPID_HEIGHT__MAX 0x00002000 +#define NVC0_3D_CLIPID_FILL_RECT_HORIZ 0x00001508 +#define NVC0_3D_CLIPID_FILL_RECT_HORIZ_LOW__MASK 0x0000ffff +#define NVC0_3D_CLIPID_FILL_RECT_HORIZ_LOW__SHIFT 0 +#define NVC0_3D_CLIPID_FILL_RECT_HORIZ_HIGH__MASK 0xffff0000 +#define NVC0_3D_CLIPID_FILL_RECT_HORIZ_HIGH__SHIFT 16 + +#define NVC0_3D_CLIPID_FILL_RECT_VERT 0x0000150c +#define NVC0_3D_CLIPID_FILL_RECT_VERT_LOW__MASK 0x0000ffff +#define NVC0_3D_CLIPID_FILL_RECT_VERT_LOW__SHIFT 0 +#define NVC0_3D_CLIPID_FILL_RECT_VERT_HIGH__MASK 0xffff0000 +#define NVC0_3D_CLIPID_FILL_RECT_VERT_HIGH__SHIFT 16 + #define NVC0_3D_VP_CLIP_DISTANCE_ENABLE 0x00001510 #define NVC0_3D_VP_CLIP_DISTANCE_ENABLE_0 0x00000001 #define NVC0_3D_VP_CLIP_DISTANCE_ENABLE_1 0x00000002 @@ -814,8 +846,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define NVC0_3D_VERTEX_BASE_LOW 0x000015f8 #define NVC0_3D_POINT_COORD_REPLACE 0x00001604 -#define NVC0_3D_POINT_COORD_REPLACE_BITS__MASK 0x00001fff -#define NVC0_3D_POINT_COORD_REPLACE_BITS__SHIFT 0 +#define NVC0_3D_POINT_COORD_REPLACE_COORD_ORIGIN__MASK 0x00000004 +#define NVC0_3D_POINT_COORD_REPLACE_COORD_ORIGIN__SHIFT 2 +#define NVC0_3D_POINT_COORD_REPLACE_COORD_ORIGIN_LOWER_LEFT 0x00000000 +#define NVC0_3D_POINT_COORD_REPLACE_COORD_ORIGIN_UPPER_LEFT 0x00000004 +#define NVC0_3D_POINT_COORD_REPLACE_ENABLE__MASK 0x000007f8 +#define NVC0_3D_POINT_COORD_REPLACE_ENABLE__SHIFT 3 #define NVC0_3D_CODE_ADDRESS_HIGH 0x00001608 @@ -864,8 +900,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define NVC0_3D_POINT_RASTER_RULES_OGL 0x00000000 #define NVC0_3D_POINT_RASTER_RULES_D3D 0x00000001 -#define NVC0_3D_POINT_SPRITE_CTRL 0x00001660 - #define NVC0_3D_TEX_MISC 0x00001664 #define NVC0_3D_TEX_MISC_SEAMLESS_CUBE_MAP 0x00000004 @@ -928,22 +962,28 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define NVC0_3D_VIEW_VOLUME_CLIP_CTRL 0x0000193c #define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK0 0x00000001 -#define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK1 0x00000002 -#define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK2 0x00000004 -#define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK3 0x00000008 -#define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK4 0x00000010 +#define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK1__MASK 0x00000006 +#define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK1__SHIFT 1 +#define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK1_UNK0 0x00000000 +#define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK1_UNK1 0x00000002 +#define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK1_UNK2 0x00000004 +#define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_DEPTH_CLAMP_NEAR 0x00000008 +#define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_DEPTH_CLAMP_FAR 0x00000010 #define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK7 0x00000080 #define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK10 0x00000400 #define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK11 0x00000800 -#define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK12 0x00001000 -#define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK13 0x00002000 +#define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK12__MASK 0x00003000 +#define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK12__SHIFT 12 +#define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK12_UNK0 0x00000000 +#define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK12_UNK1 0x00001000 +#define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK12_UNK2 0x00002000 -#define NVC0_3D_VIEWPORT_CLIP_RECTS_EN 0x0000194c +#define NVC0_3D_CLIP_RECTS_EN 0x0000194c -#define NVC0_3D_VIEWPORT_CLIP_MODE 0x00001950 -#define NVC0_3D_VIEWPORT_CLIP_MODE_INSIDE_ANY 0x00000000 -#define NVC0_3D_VIEWPORT_CLIP_MODE_OUTSIDE_ALL 0x00000001 -#define NVC0_3D_VIEWPORT_CLIP_MODE_NEVER 0x00000002 +#define NVC0_3D_CLIP_RECTS_MODE 0x00001950 +#define NVC0_3D_CLIP_RECTS_MODE_INSIDE_ANY 0x00000000 +#define NVC0_3D_CLIP_RECTS_MODE_OUTSIDE_ALL 0x00000001 +#define NVC0_3D_CLIP_RECTS_MODE_NEVER 0x00000002 #define NVC0_3D_FP_ZORDER_CTRL 0x0000196c #define NVC0_3D_FP_ZORDER_CTRL_0 0x00000001 @@ -996,6 +1036,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define NVC0_3D_CLEAR_BUFFERS_LAYER__MASK 0x001ffc00 #define NVC0_3D_CLEAR_BUFFERS_LAYER__SHIFT 10 +#define NVC0_3D_CLIPID_FILL 0x000019d4 + #define NVC0_3D_COLOR_MASK(i0) (0x00001a00 + 0x4*(i0)) #define NVC0_3D_COLOR_MASK__ESIZE 0x00000004 #define NVC0_3D_COLOR_MASK__LEN 0x00000008 @@ -1155,9 +1197,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define NVC0_3D_VERT_COLOR_CLAMP_EN 0x00002600 -#define NVC0_3D_TFB_VARYING_LOCS(i0) (0x00002800 + 0x4*(i0)) +#define NVC0_3D_TFB_VARYING_LOCS(i0, i1) (0x00002800 + 0x80*(i0) + 0x4*(i1)) #define NVC0_3D_TFB_VARYING_LOCS__ESIZE 0x00000004 -#define NVC0_3D_TFB_VARYING_LOCS__LEN 0x00000080 +#define NVC0_3D_TFB_VARYING_LOCS__LEN 0x00000020 #define NVC0_3D_COLOR_MASK_BROADCAST 0x00003808 diff --git a/src/gallium/drivers/nvc0/nvc0_buffer.c b/src/gallium/drivers/nvc0/nvc0_buffer.c index ea3e642a448..aa949bdfa36 100644 --- a/src/gallium/drivers/nvc0/nvc0_buffer.c +++ b/src/gallium/drivers/nvc0/nvc0_buffer.c @@ -59,15 +59,23 @@ release_allocation(struct nvc0_mm_allocation **mm, struct nvc0_fence *fence) (*mm) = NULL; } -static INLINE boolean -nvc0_buffer_reallocate(struct nvc0_screen *screen, struct nvc0_resource *buf, - unsigned domain) +INLINE void +nvc0_buffer_release_gpu_storage(struct nvc0_resource *buf) { nouveau_bo_ref(NULL, &buf->bo); if (buf->mm) release_allocation(&buf->mm, buf->fence); + buf->domain = 0; +} + +static INLINE boolean +nvc0_buffer_reallocate(struct nvc0_screen *screen, struct nvc0_resource *buf, + unsigned domain) +{ + nvc0_buffer_release_gpu_storage(buf); + return nvc0_buffer_allocate(screen, buf, domain); } @@ -77,10 +85,7 @@ nvc0_buffer_destroy(struct pipe_screen *pscreen, { struct nvc0_resource *res = nvc0_resource(presource); - nouveau_bo_ref(NULL, &res->bo); - - if (res->mm) - release_allocation(&res->mm, res->fence); + nvc0_buffer_release_gpu_storage(res); if (res->data && !(res->status & NVC0_BUFFER_STATUS_USER_MEMORY)) FREE(res->data); @@ -112,7 +117,7 @@ nvc0_buffer_download(struct nvc0_context *nvc0, struct nvc0_resource *buf, memcpy(buf->data + start, bounce->map, size); nouveau_bo_unmap(bounce); - buf->status &= ~NVC0_BUFFER_STATUS_DIRTY; + buf->status &= ~NVC0_BUFFER_STATUS_GPU_WRITING; nouveau_bo_ref(NULL, &bounce); if (mm) @@ -151,7 +156,7 @@ nvc0_buffer_upload(struct nvc0_context *nvc0, struct nvc0_resource *buf, release_allocation(&mm, nvc0->screen->fence.current); if (start == 0 && size == buf->base.width0) - buf->status &= ~NVC0_BUFFER_STATUS_DIRTY; + buf->status &= ~NVC0_BUFFER_STATUS_GPU_WRITING; return TRUE; } @@ -174,7 +179,7 @@ nvc0_buffer_transfer_get(struct pipe_context *pipe, if (buf->domain == NOUVEAU_BO_VRAM) { if (usage & PIPE_TRANSFER_READ) { - if (buf->status & NVC0_BUFFER_STATUS_DIRTY) + if (buf->status & NVC0_BUFFER_STATUS_GPU_WRITING) nvc0_buffer_download(nvc0_context(pipe), buf, 0, buf->base.width0); } } diff --git a/src/gallium/drivers/nvc0/nvc0_context.c b/src/gallium/drivers/nvc0/nvc0_context.c index 2118abb5d5d..f02de4d044a 100644 --- a/src/gallium/drivers/nvc0/nvc0_context.c +++ b/src/gallium/drivers/nvc0/nvc0_context.c @@ -41,17 +41,18 @@ nvc0_flush(struct pipe_context *pipe, unsigned flags, OUT_RING (chan, 0); BEGIN_RING(chan, RING_3D(TEX_CACHE_CTL), 1); OUT_RING (chan, 0x00); + } else + if ((flags & PIPE_FLUSH_RENDER_CACHE) && !(flags & PIPE_FLUSH_FRAME)) { + BEGIN_RING(chan, RING_3D(SERIALIZE), 1); + OUT_RING (chan, 0); } - if (fence) { - nvc0_screen_fence_new(nvc0->screen, (struct nvc0_fence **)fence, TRUE); - } + if (fence) + nvc0_fence_reference((struct nvc0_fence **)fence, + nvc0->screen->fence.current); - if (flags & (PIPE_FLUSH_SWAPBUFFERS | PIPE_FLUSH_FRAME)) { + if (flags & (PIPE_FLUSH_SWAPBUFFERS | PIPE_FLUSH_FRAME)) FIRE_RING(chan); - - nvc0_screen_fence_next(nvc0->screen); - } } static void @@ -67,6 +68,16 @@ nvc0_destroy(struct pipe_context *pipe) FREE(nvc0); } +void +nvc0_default_flush_notify(struct nouveau_channel *chan) +{ + struct nvc0_context *nvc0 = chan->user_private; + + nvc0_screen_fence_update(nvc0->screen, TRUE); + + nvc0_screen_fence_next(nvc0->screen); +} + struct pipe_context * nvc0_create(struct pipe_screen *pscreen, void *priv) { @@ -91,6 +102,7 @@ nvc0_create(struct pipe_screen *pscreen, void *priv) nvc0->pipe.flush = nvc0_flush; screen->base.channel->user_private = nvc0; + screen->base.channel->flush_notify = nvc0_default_flush_notify; nvc0_init_query_functions(nvc0); nvc0_init_surface_functions(nvc0); @@ -148,12 +160,14 @@ nvc0_bufctx_emit_relocs(struct nvc0_context *nvc0) { struct resident *rsd; struct util_dynarray *array; - unsigned ctx, i; + unsigned ctx, i, n; for (ctx = 0; ctx < NVC0_BUFCTX_COUNT; ++ctx) { array = &nvc0->residents[ctx]; - for (i = 0; i < array->size / sizeof(struct resident); ++i) { + n = array->size / sizeof(struct resident); + MARK_RING(nvc0->screen->base.channel, n, n); + for (i = 0; i < n; ++i) { rsd = util_dynarray_element(array, struct resident, i); nvc0_resource_validate(rsd->res, rsd->flags); diff --git a/src/gallium/drivers/nvc0/nvc0_context.h b/src/gallium/drivers/nvc0/nvc0_context.h index 94117988e50..1ce5554f7b7 100644 --- a/src/gallium/drivers/nvc0/nvc0_context.h +++ b/src/gallium/drivers/nvc0/nvc0_context.h @@ -54,6 +54,8 @@ #define NVC0_NEW_CONSTBUF (1 << 18) #define NVC0_NEW_TEXTURES (1 << 19) #define NVC0_NEW_SAMPLERS (1 << 20) +#define NVC0_NEW_TFB (1 << 21) +#define NVC0_NEW_TFB_BUFFERS (1 << 22) #define NVC0_BUFCTX_CONSTANT 0 #define NVC0_BUFCTX_FRAME 1 @@ -79,6 +81,7 @@ struct nvc0_context { uint8_t num_vtxelts; uint8_t num_textures[5]; uint8_t num_samplers[5]; + uint8_t tls_required; /* bitmask of shader types using l[] */ uint16_t scissor; uint32_t uniform_buffer_bound[5]; } state; @@ -123,6 +126,11 @@ struct nvc0_context { boolean vbo_dirty; boolean vbo_push_hint; + struct nvc0_transform_feedback_state *tfb; + struct pipe_resource *tfbbuf[4]; + unsigned num_tfbbufs; + unsigned tfb_offset[4]; + struct draw_context *draw; }; @@ -149,6 +157,8 @@ nvc0_surface(struct pipe_surface *ps) /* nvc0_context.c */ struct pipe_context *nvc0_create(struct pipe_screen *, void *); +void nvc0_default_flush_notify(struct nouveau_channel *); + void nvc0_bufctx_emit_relocs(struct nvc0_context *); void nvc0_bufctx_add_resident(struct nvc0_context *, int ctx, struct nvc0_resource *, uint32_t flags); @@ -177,6 +187,8 @@ void nvc0_tevlprog_validate(struct nvc0_context *); void nvc0_gmtyprog_validate(struct nvc0_context *); void nvc0_fragprog_validate(struct nvc0_context *); +void nvc0_tfb_validate(struct nvc0_context *); + /* nvc0_state.c */ extern void nvc0_init_state_functions(struct nvc0_context *); diff --git a/src/gallium/drivers/nvc0/nvc0_fence.c b/src/gallium/drivers/nvc0/nvc0_fence.c index 9d2c48cf14d..f2d4b1451bf 100644 --- a/src/gallium/drivers/nvc0/nvc0_fence.c +++ b/src/gallium/drivers/nvc0/nvc0_fence.c @@ -55,6 +55,7 @@ nvc0_fence_emit(struct nvc0_fence *fence) assert(fence->state == NVC0_FENCE_STATE_AVAILABLE); + MARK_RING (chan, 5, 2); BEGIN_RING(chan, RING_3D(QUERY_ADDRESS_HIGH), 4); OUT_RELOCh(chan, screen->fence.bo, 0, NOUVEAU_BO_WR); OUT_RELOCl(chan, screen->fence.bo, 0, NOUVEAU_BO_WR); @@ -83,7 +84,8 @@ nvc0_fence_del(struct nvc0_fence *fence) struct nvc0_fence *it; struct nvc0_screen *screen = fence->screen; - if (fence->state == NVC0_FENCE_STATE_EMITTED) { + if (fence->state == NVC0_FENCE_STATE_EMITTED || + fence->state == NVC0_FENCE_STATE_FLUSHED) { if (fence == screen->fence.head) { screen->fence.head = fence->next; if (!screen->fence.head) @@ -118,8 +120,8 @@ nvc0_fence_trigger_release_buffers(struct nvc0_fence *fence) fence->buffers = NULL; } -static void -nvc0_screen_fence_update(struct nvc0_screen *screen) +void +nvc0_screen_fence_update(struct nvc0_screen *screen, boolean flushed) { struct nvc0_fence *fence; struct nvc0_fence *next = NULL; @@ -146,38 +148,43 @@ nvc0_screen_fence_update(struct nvc0_screen *screen) screen->fence.head = next; if (!next) screen->fence.tail = NULL; -} -#define NVC0_FENCE_MAX_SPINS (1 << 17) + if (flushed) { + for (fence = next; fence; fence = fence->next) + fence->state = NVC0_FENCE_STATE_FLUSHED; + } +} boolean nvc0_fence_signalled(struct nvc0_fence *fence) { struct nvc0_screen *screen = fence->screen; - if (fence->state == NVC0_FENCE_STATE_EMITTED) - nvc0_screen_fence_update(screen); + if (fence->state >= NVC0_FENCE_STATE_EMITTED) + nvc0_screen_fence_update(screen, FALSE); return fence->state == NVC0_FENCE_STATE_SIGNALLED; } +#define NVC0_FENCE_MAX_SPINS (1 << 31) + boolean nvc0_fence_wait(struct nvc0_fence *fence) { struct nvc0_screen *screen = fence->screen; - int spins = 0; + uint32_t spins = 0; - if (fence->state == NVC0_FENCE_STATE_AVAILABLE) { + if (fence->state < NVC0_FENCE_STATE_EMITTED) { nvc0_fence_emit(fence); - FIRE_RING(screen->base.channel); - if (fence == screen->fence.current) nvc0_screen_fence_new(screen, &screen->fence.current, FALSE); } + if (fence->state < NVC0_FENCE_STATE_FLUSHED) + FIRE_RING(screen->base.channel); do { - nvc0_screen_fence_update(screen); + nvc0_screen_fence_update(screen, FALSE); if (fence->state == NVC0_FENCE_STATE_SIGNALLED) return TRUE; @@ -188,8 +195,9 @@ nvc0_fence_wait(struct nvc0_fence *fence) #endif } while (spins < NVC0_FENCE_MAX_SPINS); - if (spins > 9000) - NOUVEAU_ERR("fence %x: been spinning too long\n", fence->sequence); + debug_printf("Wait on fence %u (ack = %u, next = %u) timed out !\n", + fence->sequence, + screen->fence.sequence_ack, screen->fence.sequence); return FALSE; } @@ -199,5 +207,4 @@ nvc0_screen_fence_next(struct nvc0_screen *screen) { nvc0_fence_emit(screen->fence.current); nvc0_screen_fence_new(screen, &screen->fence.current, FALSE); - nvc0_screen_fence_update(screen); } diff --git a/src/gallium/drivers/nvc0/nvc0_fence.h b/src/gallium/drivers/nvc0/nvc0_fence.h index e63c164bda4..3d8c3f8ba60 100644 --- a/src/gallium/drivers/nvc0/nvc0_fence.h +++ b/src/gallium/drivers/nvc0/nvc0_fence.h @@ -7,7 +7,8 @@ #define NVC0_FENCE_STATE_AVAILABLE 0 #define NVC0_FENCE_STATE_EMITTED 1 -#define NVC0_FENCE_STATE_SIGNALLED 2 +#define NVC0_FENCE_STATE_FLUSHED 2 +#define NVC0_FENCE_STATE_SIGNALLED 3 struct nvc0_mm_allocation; diff --git a/src/gallium/drivers/nvc0/nvc0_miptree.c b/src/gallium/drivers/nvc0/nvc0_miptree.c index 7c7e134146e..ea3ed9e0225 100644 --- a/src/gallium/drivers/nvc0/nvc0_miptree.c +++ b/src/gallium/drivers/nvc0/nvc0_miptree.c @@ -143,8 +143,7 @@ nvc0_miptree_create(struct pipe_screen *pscreen, switch (pt->format) { case PIPE_FORMAT_Z16_UNORM: tile_flags = 0x0700; /* COMPRESSED */ - tile_flags = 0x0200; /* NORMAL ? */ - tile_flags = 0x0100; /* NORMAL ? */ + tile_flags = 0x0100; /* NORMAL */ break; case PIPE_FORMAT_S8_USCALED_Z24_UNORM: tile_flags = 0x5300; /* MSAA 4, COMPRESSED */ @@ -170,6 +169,7 @@ nvc0_miptree_create(struct pipe_screen *pscreen, break; case PIPE_FORMAT_R16G16B16A16_UNORM: tile_flags = 0xe900; /* COMPRESSED */ + tile_flags = 0xfe00; /* NORMAL */ break; default: tile_flags = 0xe000; /* MSAA 4, COMPRESSED 32 BIT */ @@ -283,7 +283,7 @@ nvc0_miptree_surface_new(struct pipe_context *pipe, pipe_reference_init(&ps->reference, 1); pipe_resource_reference(&ps->texture, pt); ps->context = pipe; - ps->format = pt->format; + ps->format = templ->format; ps->usage = templ->usage; ps->u.tex.level = templ->u.tex.level; ps->u.tex.first_layer = templ->u.tex.first_layer; diff --git a/src/gallium/drivers/nvc0/nvc0_mm.c b/src/gallium/drivers/nvc0/nvc0_mm.c index 0629dad19c9..516d2e31b55 100644 --- a/src/gallium/drivers/nvc0/nvc0_mm.c +++ b/src/gallium/drivers/nvc0/nvc0_mm.c @@ -96,13 +96,13 @@ mm_bucket_by_size(struct nvc0_mman *cache, unsigned size) static INLINE uint32_t mm_default_slab_size(unsigned chunk_order) { - assert(chunk_order <= MM_MAX_ORDER && chunk_order >= MM_MIN_ORDER); - static const int8_t slab_order[MM_MAX_ORDER - MM_MIN_ORDER + 1] = { 12, 12, 13, 14, 14, 17, 17, 17, 17, 19, 19, 20, 21, 22 }; + assert(chunk_order <= MM_MAX_ORDER && chunk_order >= MM_MIN_ORDER); + return 1 << slab_order[chunk_order - MM_MIN_ORDER]; } diff --git a/src/gallium/drivers/nvc0/nvc0_pc.c b/src/gallium/drivers/nvc0/nvc0_pc.c index 304a1919768..f51d289e8cd 100644 --- a/src/gallium/drivers/nvc0/nvc0_pc.c +++ b/src/gallium/drivers/nvc0/nvc0_pc.c @@ -44,6 +44,11 @@ nvc0_insn_can_load(struct nv_instruction *nvi, int s, if (ld->indirect >= 0) return FALSE; + /* a few ops can use g[] sources directly, but we don't support g[] yet */ + if (ld->src[0]->value->reg.file == NV_FILE_MEM_L || + ld->src[0]->value->reg.file == NV_FILE_MEM_G) + return FALSE; + for (i = 0; i < 3 && nvi->src[i]; ++i) if (nvi->src[i]->value->reg.file == NV_FILE_IMM) return FALSE; @@ -55,15 +60,11 @@ nvc0_insn_can_load(struct nv_instruction *nvi, int s, boolean nvc0_insn_is_predicateable(struct nv_instruction *nvi) { - int s; - - if (!nv_op_predicateable(nvi->opcode)) + if (nvi->predicate >= 0) /* already predicated */ return FALSE; - if (nvi->predicate >= 0) + if (!nvc0_op_info_table[nvi->opcode].predicate && + !nvc0_op_info_table[nvi->opcode].pseudo) return FALSE; - for (s = 0; s < 4 && nvi->src[s]; ++s) - if (nvi->src[s]->value->reg.file == NV_FILE_IMM) - return FALSE; return TRUE; } @@ -103,6 +104,12 @@ nvc0_pc_replace_value(struct nv_pc *pc, return n; } +static INLINE boolean +is_gpr63(struct nv_value *val) +{ + return (val->reg.file == NV_FILE_GPR && val->reg.id == 63); +} + struct nv_value * nvc0_pc_find_constant(struct nv_ref *ref) { @@ -116,7 +123,7 @@ nvc0_pc_find_constant(struct nv_ref *ref) assert(!src->insn->src[0]->mod); src = src->insn->src[0]->value; } - if ((src->reg.file == NV_FILE_IMM) || + if ((src->reg.file == NV_FILE_IMM) || is_gpr63(src) || (src->insn && src->insn->opcode == NV_OP_LD && src->insn->src[0]->value->reg.file >= NV_FILE_MEM_C(0) && @@ -130,7 +137,7 @@ nvc0_pc_find_immediate(struct nv_ref *ref) { struct nv_value *src = nvc0_pc_find_constant(ref); - return (src && src->reg.file == NV_FILE_IMM) ? src : NULL; + return (src && (src->reg.file == NV_FILE_IMM || is_gpr63(src))) ? src : NULL; } static void @@ -187,7 +194,10 @@ nvc0_pc_pass_in_order(struct nv_basic_block *root, nv_pc_pass_func f, bb[p++] = b->out[j]; break; case CFG_EDGE_LOOP_LEAVE: - bbb[pp++] = b->out[j]; + if (!b->out[j]->priv) { + bbb[pp++] = b->out[j]; + b->out[j]->priv = 1; + } break; default: assert(0); @@ -499,6 +509,9 @@ nvc0_insn_append(struct nv_basic_block *b, struct nv_instruction *i) i->bb = b; b->num_instructions++; + + if (i->prev && i->prev->terminator) + nvc0_insns_permute(i->prev, i); } void @@ -512,6 +525,8 @@ nvc0_insn_insert_after(struct nv_instruction *at, struct nv_instruction *ni) ni->prev = at; ni->next->prev = ni; ni->prev->next = ni; + ni->bb = at->bb; + ni->bb->num_instructions++; } void diff --git a/src/gallium/drivers/nvc0/nvc0_pc.h b/src/gallium/drivers/nvc0/nvc0_pc.h index 969cc68c596..efa073a9201 100644 --- a/src/gallium/drivers/nvc0/nvc0_pc.h +++ b/src/gallium/drivers/nvc0/nvc0_pc.h @@ -53,7 +53,8 @@ /** * BIND forces source operand i into the same register as destination operand i, - * and the operands will be assigned consecutive registers (needed for TEX) + * and the operands will be assigned consecutive registers (needed for TEX). + * Beware conflicts ! * SELECT forces its multiple source operands and its destination operand into * one and the same register. */ @@ -204,6 +205,10 @@ #define NV_CC_C 0x11 #define NV_CC_A 0x12 #define NV_CC_S 0x13 +#define NV_CC_INVERSE(cc) ((cc) ^ 0x7) +/* for 1 bit predicates: */ +#define NV_CC_P 0 +#define NV_CC_NOT_P 1 #define NV_PC_MAX_INSTRUCTIONS 2048 #define NV_PC_MAX_VALUES (NV_PC_MAX_INSTRUCTIONS * 4) @@ -259,12 +264,6 @@ nv_op_supported_src_mods(uint opcode) return nvc0_op_info_table[opcode].mods; } -static INLINE boolean -nv_op_predicateable(uint opcode) -{ - return nvc0_op_info_table[opcode].predicate ? TRUE : FALSE; -} - static INLINE uint nv_type_order(ubyte type) { @@ -310,7 +309,7 @@ struct nv_reg { int32_t s32; int64_t s64; uint64_t u64; - uint32_t u32; + uint32_t u32; /* expected to be 0 for $r63 */ float f32; double f64; } imm; @@ -344,6 +343,8 @@ struct nv_ref { uint8_t flags; }; +#define NV_REF_FLAG_REGALLOC_PRIV (1 << 0) + struct nv_basic_block; struct nv_instruction { @@ -485,7 +486,7 @@ nv_alloc_instruction(struct nv_pc *pc, uint opcode) assert(pc->num_instructions < NV_PC_MAX_INSTRUCTIONS); insn->opcode = opcode; - insn->cc = 0; + insn->cc = NV_CC_P; insn->indirect = -1; insn->predicate = -1; diff --git a/src/gallium/drivers/nvc0/nvc0_pc_emit.c b/src/gallium/drivers/nvc0/nvc0_pc_emit.c index db8055d91cd..c10f920e6f1 100644 --- a/src/gallium/drivers/nvc0/nvc0_pc_emit.c +++ b/src/gallium/drivers/nvc0/nvc0_pc_emit.c @@ -236,7 +236,7 @@ emit_flow(struct nv_pc *pc, struct nv_instruction *i, uint8_t op) */ pc->emit[0] |= (pcrel & 0x3f) << 26; - pc->emit[1] |= (pcrel >> 6) & 0x1ffff; + pc->emit[1] |= (pcrel >> 6) & 0x3ffff; } } @@ -393,6 +393,8 @@ emit_tex(struct nv_pc *pc, struct nv_instruction *i) { int src1 = i->tex_array + i->tex_dim + i->tex_cube; + assert(src1 < 6); + pc->emit[0] = 0x00000086; pc->emit[1] = 0x80000000; @@ -446,7 +448,7 @@ emit_flop(struct nv_pc *pc, struct nv_instruction *i, ubyte op) pc->emit[0] |= op << 26; - if (op >= 4) { + if (op >= 3) { if (i->src[0]->mod & NV_MOD_NEG) pc->emit[0] |= 1 << 9; if (i->src[0]->mod & NV_MOD_ABS) pc->emit[0] |= 1 << 7; } else { @@ -477,6 +479,7 @@ emit_ddx(struct nv_pc *pc, struct nv_instruction *i) { i->quadop = 0x99; i->lanes = 4; + i->src[1] = i->src[0]; emit_quadop(pc, i); } @@ -485,6 +488,7 @@ emit_ddy(struct nv_pc *pc, struct nv_instruction *i) { i->quadop = 0xa5; i->lanes = 5; + i->src[1] = i->src[0]; emit_quadop(pc, i); } @@ -629,25 +633,28 @@ emit_slct(struct nv_pc *pc, struct nv_instruction *i) static void emit_cvt(struct nv_pc *pc, struct nv_instruction *i) { + uint32_t rint; + pc->emit[0] = 0x00000004; pc->emit[1] = 0x10000000; - if (i->opcode != NV_OP_CVT) + /* if no type conversion specified, get type from opcode */ + if (i->opcode != NV_OP_CVT && i->ext.cvt.d == i->ext.cvt.s) i->ext.cvt.d = i->ext.cvt.s = NV_OPTYPE(i->opcode); switch (i->ext.cvt.d) { case NV_TYPE_F32: switch (i->ext.cvt.s) { case NV_TYPE_F32: pc->emit[1] = 0x10000000; break; - case NV_TYPE_S32: pc->emit[0] |= 0x200; + case NV_TYPE_S32: pc->emit[0] |= 0x200; /* fall through */ case NV_TYPE_U32: pc->emit[1] = 0x18000000; break; } break; - case NV_TYPE_S32: pc->emit[0] |= 0x80; + case NV_TYPE_S32: pc->emit[0] |= 0x80; /* fall through */ case NV_TYPE_U32: switch (i->ext.cvt.s) { case NV_TYPE_F32: pc->emit[1] = 0x14000000; break; - case NV_TYPE_S32: pc->emit[0] |= 0x200; + case NV_TYPE_S32: pc->emit[0] |= 0x200; /* fall through */ case NV_TYPE_U32: pc->emit[1] = 0x1c000000; break; } break; @@ -656,14 +663,20 @@ emit_cvt(struct nv_pc *pc, struct nv_instruction *i) break; } - if (i->opcode == NV_OP_FLOOR) - pc->emit[1] |= 0x00020000; - else - if (i->opcode == NV_OP_CEIL) - pc->emit[1] |= 0x00040000; - else - if (i->opcode == NV_OP_TRUNC) - pc->emit[1] |= 0x00060000; + rint = (i->ext.cvt.d == NV_TYPE_F32) ? 1 << 7 : 0; + + if (i->opcode == NV_OP_FLOOR) { + pc->emit[0] |= rint; + pc->emit[1] |= 2 << 16; + } else + if (i->opcode == NV_OP_CEIL) { + pc->emit[0] |= rint; + pc->emit[1] |= 4 << 16; + } else + if (i->opcode == NV_OP_TRUNC) { + pc->emit[0] |= rint; + pc->emit[1] |= 6 << 16; + } if (i->saturate || i->opcode == NV_OP_SAT) pc->emit[0] |= 0x20; @@ -793,11 +806,8 @@ emit_ldst_size(struct nv_pc *pc, struct nv_instruction *i) } static void -emit_ld_const(struct nv_pc *pc, struct nv_instruction *i) +emit_ld_common(struct nv_pc *pc, struct nv_instruction *i) { - pc->emit[0] = 0x00000006; - pc->emit[1] = 0x14000000 | (const_space_index(i, 0) << 10); - emit_ldst_size(pc, i); set_pred(pc, i); @@ -808,6 +818,15 @@ emit_ld_const(struct nv_pc *pc, struct nv_instruction *i) } static void +emit_ld_const(struct nv_pc *pc, struct nv_instruction *i) +{ + pc->emit[0] = 0x00000006; + pc->emit[1] = 0x14000000 | (const_space_index(i, 0) << 10); + + emit_ld_common(pc, i); +} + +static void emit_ld(struct nv_pc *pc, struct nv_instruction *i) { if (SFILE(i, 0) >= NV_FILE_MEM_C(0) && @@ -818,6 +837,12 @@ emit_ld(struct nv_pc *pc, struct nv_instruction *i) } else { emit_ld_const(pc, i); } + } else + if (SFILE(i, 0) == NV_FILE_MEM_L) { + pc->emit[0] = 0x00000005; + pc->emit[1] = 0xc0000000; + + emit_ld_common(pc, i); } else { NOUVEAU_ERR("emit_ld(%u): not handled yet\n", SFILE(i, 0)); abort(); @@ -827,8 +852,19 @@ emit_ld(struct nv_pc *pc, struct nv_instruction *i) static void emit_st(struct nv_pc *pc, struct nv_instruction *i) { - NOUVEAU_ERR("emit_st: not handled yet\n"); - abort(); + if (SFILE(i, 0) != NV_FILE_MEM_L) + NOUVEAU_ERR("emit_st(%u): file not handled yet\n", SFILE(i, 0)); + + pc->emit[0] = 0x00000005 | (0 << 8); /* write-back caching */ + pc->emit[1] = 0xc8000000; + + emit_ldst_size(pc, i); + + set_pred(pc, i); + set_address_16(pc, i->src[0]); + + SID(pc, (i->indirect >= 0) ? i->src[i->indirect] : NULL, 20); + DID(pc, i->src[1]->value, 14); } void diff --git a/src/gallium/drivers/nvc0/nvc0_pc_optimize.c b/src/gallium/drivers/nvc0/nvc0_pc_optimize.c index acc72bff14c..c5a7367a5fd 100644 --- a/src/gallium/drivers/nvc0/nvc0_pc_optimize.c +++ b/src/gallium/drivers/nvc0/nvc0_pc_optimize.c @@ -99,6 +99,7 @@ inst_removable(struct nv_instruction *nvi) nvc0_insn_refcount(nvi))); } +/* Check if we do not actually have to emit this instruction. */ static INLINE boolean inst_is_noop(struct nv_instruction *nvi) { @@ -141,9 +142,10 @@ nv_pc_pass_pre_emission(void *priv, struct nv_basic_block *b) struct nv_instruction *nvi, *next; int j; + /* find first non-empty block emitted before b */ for (j = pc->num_blocks - 1; j >= 0 && !pc->bb_list[j]->emit_size; --j); - if (j >= 0) { + for (; j >= 0; --j) { in = pc->bb_list[j]; /* check for no-op branches (BRA $PC+8) */ @@ -157,6 +159,9 @@ nv_pc_pass_pre_emission(void *priv, struct nv_basic_block *b) nvc0_insn_delete(in->exit); } b->emit_pos = in->emit_pos + in->emit_size; + + if (in->emit_size) /* no more no-op branches to b */ + break; } pc->bb_list[pc->num_blocks++] = b; @@ -240,10 +245,15 @@ check_swap_src_0_1(struct nv_instruction *nvi) struct nv_ref *src0 = nvi->src[0]; struct nv_ref *src1 = nvi->src[1]; - if (!nv_op_commutative(nvi->opcode)) + if (!nv_op_commutative(nvi->opcode) && + NV_BASEOP(nvi->opcode) != NV_OP_SET && + NV_BASEOP(nvi->opcode) != NV_OP_SLCT) return; assert(src0 && src1 && src0->value && src1->value); + if (src1->value->reg.file != NV_FILE_GPR) + return; + if (is_cspace_load(src0->value->insn)) { if (!is_cspace_load(src1->value->insn)) { nvi->src[0] = src1; @@ -258,8 +268,13 @@ check_swap_src_0_1(struct nv_instruction *nvi) } } - if (nvi->src[0] != src0 && nvi->opcode == NV_OP_SET) - nvi->set_cond = cc_swapped[nvi->set_cond]; + if (nvi->src[0] != src0) { + if (NV_BASEOP(nvi->opcode) == NV_OP_SET) + nvi->set_cond = (nvi->set_cond & ~7) | cc_swapped[nvi->set_cond & 7]; + else + if (NV_BASEOP(nvi->opcode) == NV_OP_SLCT) + nvi->set_cond = NV_CC_INVERSE(nvi->set_cond); + } } static void @@ -543,6 +558,7 @@ constant_operand(struct nv_pc *pc, nv_reference(pc, nvi, s, nvi->src[t]->value); nvi->src[s]->mod = nvi->src[t]->mod; } + break; case NV_OP_ADD_F32: if (u.u32 == 0) { switch (nvi->src[t]->mod) { @@ -562,6 +578,7 @@ constant_operand(struct nv_pc *pc, if (nvi->opcode != NV_OP_CVT) nvi->src[0]->mod = 0; } + break; case NV_OP_ADD_B32: if (u.u32 == 0) { assert(nvi->src[t]->mod == 0); @@ -582,7 +599,7 @@ constant_operand(struct nv_pc *pc, } else if (u.s32 > 0 && u.s32 == (1 << shift)) { nvi->opcode = NV_OP_SHL; - (val = new_value(pc, NV_FILE_IMM, NV_TYPE_U32))->reg.imm.s32 = shift; + (val = new_value(pc, NV_FILE_IMM, 4))->reg.imm.s32 = shift; nv_reference(pc, nvi, 0, nvi->src[t]->value); nv_reference(pc, nvi, 1, val); break; @@ -590,14 +607,14 @@ constant_operand(struct nv_pc *pc, break; case NV_OP_RCP: u.f32 = 1.0f / u.f32; - (val = new_value(pc, NV_FILE_IMM, NV_TYPE_F32))->reg.imm.f32 = u.f32; + (val = new_value(pc, NV_FILE_IMM, 4))->reg.imm.f32 = u.f32; nvi->opcode = NV_OP_MOV; assert(s == 0); nv_reference(pc, nvi, 0, val); break; case NV_OP_RSQ: u.f32 = 1.0f / sqrtf(u.f32); - (val = new_value(pc, NV_FILE_IMM, NV_TYPE_F32))->reg.imm.f32 = u.f32; + (val = new_value(pc, NV_FILE_IMM, 4))->reg.imm.f32 = u.f32; nvi->opcode = NV_OP_MOV; assert(s == 0); nv_reference(pc, nvi, 0, val); @@ -607,25 +624,83 @@ constant_operand(struct nv_pc *pc, } } +static void +handle_min_max(struct nv_pass *ctx, struct nv_instruction *nvi) +{ + struct nv_value *src0 = nvi->src[0]->value; + struct nv_value *src1 = nvi->src[1]->value; + + if (src0 != src1 || (nvi->src[0]->mod | nvi->src[1]->mod)) + return; + if (src0->reg.file != NV_FILE_GPR) + return; + nvc0_pc_replace_value(ctx->pc, nvi->def[0], src0); + nvc0_insn_delete(nvi); +} + +/* check if we can MUL + ADD -> MAD/FMA */ +static void +handle_add_mul(struct nv_pass *ctx, struct nv_instruction *nvi) +{ + struct nv_value *src0 = nvi->src[0]->value; + struct nv_value *src1 = nvi->src[1]->value; + struct nv_value *src; + int s; + uint8_t mod[4]; + + if (SRC_IS_MUL(src0) && src0->refc == 1) s = 0; + else + if (SRC_IS_MUL(src1) && src1->refc == 1) s = 1; + else + return; + + if ((src0->insn && src0->insn->bb != nvi->bb) || + (src1->insn && src1->insn->bb != nvi->bb)) + return; + + /* check for immediates from prior constant folding */ + if (src0->reg.file != NV_FILE_GPR || src1->reg.file != NV_FILE_GPR) + return; + src = nvi->src[s]->value; + + mod[0] = nvi->src[0]->mod; + mod[1] = nvi->src[1]->mod; + mod[2] = src->insn->src[0]->mod; + mod[3] = src->insn->src[1]->mod; + + if ((mod[0] | mod[1] | mod[2] | mod[3]) & ~NV_MOD_NEG) + return; + + nvi->opcode = NV_OP_MAD_F32; + + nv_reference(ctx->pc, nvi, s, NULL); + nvi->src[2] = nvi->src[!s]; + nvi->src[!s] = NULL; + + nv_reference(ctx->pc, nvi, 0, src->insn->src[0]->value); + nvi->src[0]->mod = mod[2] ^ mod[s]; + nv_reference(ctx->pc, nvi, 1, src->insn->src[1]->value); + nvi->src[1]->mod = mod[3]; +} + static int -nv_pass_lower_arith(struct nv_pass *ctx, struct nv_basic_block *b) +nv_pass_algebraic_opt(struct nv_pass *ctx, struct nv_basic_block *b) { struct nv_instruction *nvi, *next; int j; for (nvi = b->entry; nvi; nvi = next) { - struct nv_value *src0, *src1, *src; - int s; - uint8_t mod[4]; + struct nv_value *src0, *src1; + uint baseop = NV_BASEOP(nvi->opcode); next = nvi->next; src0 = nvc0_pc_find_immediate(nvi->src[0]); src1 = nvc0_pc_find_immediate(nvi->src[1]); - if (src0 && src1) + if (src0 && src1) { constant_expression(ctx->pc, nvi, src0, src1); - else { + } else { if (src0) constant_operand(ctx->pc, nvi, src0, 0); else @@ -633,44 +708,13 @@ nv_pass_lower_arith(struct nv_pass *ctx, struct nv_basic_block *b) constant_operand(ctx->pc, nvi, src1, 1); } - /* check if we can MUL + ADD -> MAD/FMA */ - if (nvi->opcode != NV_OP_ADD) - continue; - - src0 = nvi->src[0]->value; - src1 = nvi->src[1]->value; - - if (SRC_IS_MUL(src0) && src0->refc == 1) - src = src0; + if (baseop == NV_OP_MIN || baseop == NV_OP_MAX) + handle_min_max(ctx, nvi); else - if (SRC_IS_MUL(src1) && src1->refc == 1) - src = src1; - else - continue; - - /* could have an immediate from above constant_* */ - if (src0->reg.file != NV_FILE_GPR || src1->reg.file != NV_FILE_GPR) - continue; - s = (src == src0) ? 0 : 1; - - mod[0] = nvi->src[0]->mod; - mod[1] = nvi->src[1]->mod; - mod[2] = src->insn->src[0]->mod; - mod[3] = src->insn->src[0]->mod; - - if ((mod[0] | mod[1] | mod[2] | mod[3]) & ~NV_MOD_NEG) - continue; - - nvi->opcode = NV_OP_MAD; - nv_reference(ctx->pc, nvi, s, NULL); - nvi->src[2] = nvi->src[!s]; - - nvi->src[0] = new_ref(ctx->pc, src->insn->src[0]->value); - nvi->src[1] = new_ref(ctx->pc, src->insn->src[1]->value); - nvi->src[0]->mod = mod[2] ^ mod[s]; - nvi->src[1]->mod = mod[3]; + if (nvi->opcode == NV_OP_ADD_F32) + handle_add_mul(ctx, nvi); } - DESCEND_ARBITRARY(j, nv_pass_lower_arith); + DESCEND_ARBITRARY(j, nv_pass_algebraic_opt); return 0; } @@ -700,8 +744,12 @@ struct pass_reld_elim { int alloc; }; +/* Extend the load operation in @rec to also cover the data loaded by @ld. + * The two loads may not overlap but reference adjacent memory locations. + */ static void -combine_load(struct mem_record *rec, struct nv_instruction *ld) +combine_load(struct nv_pc *pc, struct mem_record *rec, + struct nv_instruction *ld) { struct nv_instruction *fv = rec->insn; struct nv_value *mem = ld->src[0]->value; @@ -716,7 +764,7 @@ combine_load(struct mem_record *rec, struct nv_instruction *ld) return; rec->ofst = mem->reg.address; for (j = 0; j < d; ++j) - fv->def[d + j] = fv->def[j]; + fv->def[mem->reg.size / 4 + j] = fv->def[j]; d = 0; } else if ((size == 8 && rec->ofst & 3) || @@ -729,6 +777,9 @@ combine_load(struct mem_record *rec, struct nv_instruction *ld) fv->def[d++]->insn = fv; } + if (fv->src[0]->value->refc > 1) + nv_reference(pc, fv, 0, new_value_like(pc, fv->src[0]->value)); + fv->src[0]->value->reg.address = rec->ofst; fv->src[0]->value->reg.size = rec->size = size; nvc0_insn_delete(ld); @@ -793,6 +844,7 @@ nv_pass_mem_opt(struct pass_reld_elim *ctx, struct nv_basic_block *b) ((it->ofst >> 4) == (ofst >> 4)) && ((it->ofst + it->size == ofst) || (it->ofst - mem->reg.size == ofst))) { + /* only NV_OP_VFETCH can load exactly 12 bytes */ if (ld->opcode == NV_OP_LD && it->size + mem->reg.size == 12) continue; if (it->ofst < ofst) { @@ -808,7 +860,7 @@ nv_pass_mem_opt(struct pass_reld_elim *ctx, struct nv_basic_block *b) switch (ld->opcode) { case NV_OP_EXPORT: combine_export(it, ld); break; default: - combine_load(it, ld); + combine_load(ctx->pc, it, ld); break; } } else @@ -817,6 +869,11 @@ nv_pass_mem_opt(struct pass_reld_elim *ctx, struct nv_basic_block *b) } } + ctx->alloc = 0; + ctx->mem_a = ctx->mem_v = ctx->mem_l = NULL; + for (s = 0; s < 16; ++s) + ctx->mem_c[s] = NULL; + DESCEND_ARBITRARY(s, nv_pass_mem_opt); return 0; } @@ -1006,7 +1063,6 @@ nv_pass_dce(struct nv_pass_dce *ctx, struct nv_basic_block *b) return 0; } -#if 0 /* Register allocation inserted ELSE blocks for all IF/ENDIF without ELSE. * Returns TRUE if @bb initiates an IF/ELSE/ENDIF clause, or is an IF with * BREAK and dummy ELSE block. @@ -1027,61 +1083,187 @@ bb_is_if_else_endif(struct nv_basic_block *bb) } } -/* predicate instructions and remove branch at the end */ +/* Predicate instructions and delete any branch at the end if it is + * not a break from a loop. + */ static void predicate_instructions(struct nv_pc *pc, struct nv_basic_block *b, - struct nv_value *p, ubyte cc) + struct nv_value *pred, uint8_t cc) { + struct nv_instruction *nvi, *prev; + int s; + if (!b->entry) + return; + for (nvi = b->entry; nvi; nvi = nvi->next) { + prev = nvi; + if (inst_is_noop(nvi)) + continue; + for (s = 0; nvi->src[s]; ++s); + assert(s < 6); + nvi->predicate = s; + nvi->cc = cc; + nv_reference(pc, nvi, nvi->predicate, pred); + } + if (prev->opcode == NV_OP_BRA && + b->out_kind[0] != CFG_EDGE_LOOP_LEAVE && + b->out_kind[1] != CFG_EDGE_LOOP_LEAVE) + nvc0_insn_delete(prev); } -#endif -/* NOTE: Run this after register allocation, we can just cut out the cflow - * instructions and hook the predicates to the conditional OPs if they are - * not using immediates; better than inserting SELECT to join definitions. - * - * NOTE: Should adapt prior optimization to make this possible more often. +static INLINE boolean +may_predicate_insn(struct nv_instruction *nvi, struct nv_value *pred) +{ + if (nvi->def[0] && values_equal(nvi->def[0], pred)) + return FALSE; + return nvc0_insn_is_predicateable(nvi); +} + +/* Transform IF/ELSE/ENDIF constructs into predicated instructions + * where feasible. */ static int nv_pass_flatten(struct nv_pass *ctx, struct nv_basic_block *b) { + struct nv_instruction *nvi; + struct nv_value *pred; + int k; + int n0, n1; /* instruction counts of outgoing blocks */ + + if (bb_is_if_else_endif(b)) { + assert(b->exit && b->exit->opcode == NV_OP_BRA); + + assert(b->exit->predicate >= 0); + pred = b->exit->src[b->exit->predicate]->value; + + n1 = n0 = 0; + for (nvi = b->out[0]->entry; nvi; nvi = nvi->next, ++n0) + if (!may_predicate_insn(nvi, pred)) + break; + if (!nvi) { + /* we're after register allocation, so there always is an ELSE block */ + for (nvi = b->out[1]->entry; nvi; nvi = nvi->next, ++n1) + if (!may_predicate_insn(nvi, pred)) + break; + } + + /* 12 is an arbitrary limit */ + if (!nvi && n0 < 12 && n1 < 12) { + predicate_instructions(ctx->pc, b->out[0], pred, !b->exit->cc); + predicate_instructions(ctx->pc, b->out[1], pred, b->exit->cc); + + nvc0_insn_delete(b->exit); /* delete the branch */ + + /* and a potential joinat before it */ + if (b->exit && b->exit->opcode == NV_OP_JOINAT) + nvc0_insn_delete(b->exit); + + /* remove join operations at the end of the conditional */ + k = (b->out[0]->out_kind[0] == CFG_EDGE_LOOP_LEAVE) ? 1 : 0; + if ((nvi = b->out[0]->out[k]->entry)) { + nvi->join = 0; + if (nvi->opcode == NV_OP_JOIN) + nvc0_insn_delete(nvi); + } + } + } + DESCEND_ARBITRARY(k, nv_pass_flatten); + return 0; } +/* Tests instructions for equality, but independently of sources. */ +static boolean +is_operation_equal(struct nv_instruction *a, struct nv_instruction *b) +{ + if (a->opcode != b->opcode) + return FALSE; + if (nv_is_texture_op(a->opcode)) { + if (a->ext.tex.t != b->ext.tex.t || + a->ext.tex.s != b->ext.tex.s) + return FALSE; + if (a->tex_dim != b->tex_dim || + a->tex_array != b->tex_array || + a->tex_cube != b->tex_cube || + a->tex_shadow != b->tex_shadow || + a->tex_live != b->tex_live) + return FALSE; + } else + if (a->opcode == NV_OP_CVT) { + if (a->ext.cvt.s != b->ext.cvt.s || + a->ext.cvt.d != b->ext.cvt.d) + return FALSE; + } else + if (NV_BASEOP(a->opcode) == NV_OP_SET || + NV_BASEOP(a->opcode) == NV_OP_SLCT) { + if (a->set_cond != b->set_cond) + return FALSE; + } else + if (a->opcode == NV_OP_LINTERP || + a->opcode == NV_OP_PINTERP) { + if (a->centroid != b->centroid || + a->flat != b->flat) + return FALSE; + } + if (a->cc != b->cc) + return FALSE; + if (a->lanes != b->lanes || + a->patch != b->patch || + a->saturate != b->saturate) + return FALSE; + if (a->opcode == NV_OP_QUADOP) /* beware quadon ! */ + return FALSE; + return TRUE; +} + /* local common subexpression elimination, stupid O(n^2) implementation */ static int nv_pass_cse(struct nv_pass *ctx, struct nv_basic_block *b) { struct nv_instruction *ir, *ik, *next; struct nv_instruction *entry = b->phi ? b->phi : b->entry; - int s; + int s, d; unsigned int reps; do { reps = 0; for (ir = entry; ir; ir = next) { next = ir->next; + if (ir->fixed) + continue; for (ik = entry; ik != ir; ik = ik->next) { - if (ir->opcode != ik->opcode || ir->fixed) + if (!is_operation_equal(ir, ik)) continue; - - if (!ir->def[0] || !ik->def[0] || ir->def[1] || ik->def[1]) + if (!ir->def[0] || !ik->def[0]) continue; if (ik->indirect != ir->indirect || ik->predicate != ir->predicate) continue; - if (!values_equal(ik->def[0], ir->def[0])) + for (d = 0; d < 4; ++d) { + if ((ir->def[d] ? 1 : 0) != (ik->def[d] ? 1 : 0)) + break; + if (ir->def[d]) { + if (!values_equal(ik->def[0], ir->def[0])) + break; + } else { + d = 4; + break; + } + } + if (d != 4) continue; - for (s = 0; s < 3; ++s) { + for (s = 0; s < 5; ++s) { struct nv_value *a, *b; - if (!ik->src[s]) { - if (ir->src[s]) - break; - continue; + if ((ir->src[s] ? 1 : 0) != (ik->src[s] ? 1 : 0)) + break; + if (!ir->src[s]) { + s = 5; + break; } + if (ik->src[s]->mod != ir->src[s]->mod) break; a = ik->src[s]->value; @@ -1089,14 +1271,15 @@ nv_pass_cse(struct nv_pass *ctx, struct nv_basic_block *b) if (a == b) continue; if (a->reg.file != b->reg.file || - a->reg.id < 0 || + a->reg.id < 0 || /* this excludes memory loads/stores */ a->reg.id != b->reg.id) break; } - if (s == 3) { + if (s == 5) { nvc0_insn_delete(ir); + for (d = 0; d < 4 && ir->def[d]; ++d) + nvc0_pc_replace_value(ctx->pc, ir->def[d], ik->def[d]); ++reps; - nvc0_pc_replace_value(ctx->pc, ir->def[0], ik->def[0]); break; } } @@ -1110,13 +1293,15 @@ nv_pass_cse(struct nv_pass *ctx, struct nv_basic_block *b) /* Make sure all sources of an NV_OP_BIND are distinct, they need to occupy * neighbouring registers. CSE might have messed this up. + * Just generate a MOV for each source to avoid conflicts if they're used in + * multiple NV_OP_BIND at different positions. */ static int nv_pass_fix_bind(struct nv_pass *ctx, struct nv_basic_block *b) { struct nv_value *val; struct nv_instruction *bnd, *nvi, *next; - int s, t; + int s; for (bnd = b->entry; bnd; bnd = next) { next = bnd->next; @@ -1124,20 +1309,17 @@ nv_pass_fix_bind(struct nv_pass *ctx, struct nv_basic_block *b) continue; for (s = 0; s < 4 && bnd->src[s]; ++s) { val = bnd->src[s]->value; - for (t = s + 1; t < 4 && bnd->src[t]; ++t) { - if (bnd->src[t]->value != val) - continue; - nvi = nv_alloc_instruction(ctx->pc, NV_OP_MOV); - nvi->def[0] = new_value_like(ctx->pc, val); - nvi->def[0]->insn = nvi; - nv_reference(ctx->pc, nvi, 0, val); - nvc0_insn_insert_before(bnd, nvi); - nv_reference(ctx->pc, bnd, t, nvi->def[0]); - } + nvi = nv_alloc_instruction(ctx->pc, NV_OP_MOV); + nvi->def[0] = new_value_like(ctx->pc, val); + nvi->def[0]->insn = nvi; + nv_reference(ctx->pc, nvi, 0, val); + nv_reference(ctx->pc, bnd, s, nvi->def[0]); + + nvc0_insn_insert_before(bnd, nvi); } } - DESCEND_ARBITRARY(t, nv_pass_fix_bind); + DESCEND_ARBITRARY(s, nv_pass_fix_bind); return 0; } @@ -1153,11 +1335,17 @@ nv_pc_pass0(struct nv_pc *pc, struct nv_basic_block *root) pass.n = 0; pass.pc = pc; + /* Do CSE so we can just compare values by pointer in subsequent passes. */ + pc->pass_seq++; + ret = nv_pass_cse(&pass, root); + if (ret) + return ret; + /* Do this first, so we don't have to pay attention * to whether sources are supported memory loads. */ pc->pass_seq++; - ret = nv_pass_lower_arith(&pass, root); + ret = nv_pass_algebraic_opt(&pass, root); if (ret) return ret; @@ -1185,11 +1373,9 @@ nv_pc_pass0(struct nv_pc *pc, struct nv_basic_block *root) reldelim->pc = pc; } - pc->pass_seq++; - ret = nv_pass_cse(&pass, root); - if (ret) - return ret; - + /* May run DCE before load-combining since that pass will clean up + * after itself. + */ dce.pc = pc; do { dce.removed = 0; diff --git a/src/gallium/drivers/nvc0/nvc0_pc_print.c b/src/gallium/drivers/nvc0/nvc0_pc_print.c index b03826484e4..90c669cc4b8 100644 --- a/src/gallium/drivers/nvc0/nvc0_pc_print.c +++ b/src/gallium/drivers/nvc0/nvc0_pc_print.c @@ -225,7 +225,7 @@ nvc0_print_instruction(struct nv_instruction *i) PRINT("%s", gree); if (NV_BASEOP(i->opcode) == NV_OP_SET) - PRINT("set %s", nv_cond_name(i->set_cond)); + PRINT("%s %s", nvc0_opcode_name(i->opcode), nv_cond_name(i->set_cond)); else if (i->saturate) PRINT("sat %s", nvc0_opcode_name(i->opcode)); @@ -278,10 +278,10 @@ struct nv_op_info nvc0_op_info_table[NV_OP_COUNT + 1] = { NV_OP_MERGE, "merge", NV_TYPE_ANY, 0, /* fcvpoi */ 0, 0, 1, 0, 1, 0, 0 }, { NV_OP_PHI, "phi", NV_TYPE_ANY, 0, /* fcvpoi */ 0, 0, 0, 0, 1, 0, 0 }, { NV_OP_SELECT, "select", NV_TYPE_ANY, 0, /* fcvpoi */ 0, 0, 0, 0, 1, 0, 0 }, - { NV_OP_NOP, "nop", NV_TYPE_ANY, 0, /* fcvpoi */ 0, 0, 0, 0, 0, 0, 0 }, + { NV_OP_NOP, "nop", NV_TYPE_ANY, 0, /* fcvpoi */ 0, 0, 0, 1, 0, 0, 0 }, - { NV_OP_LD, "ld", NV_TYPE_ANY, 0, 0, 0, 0, 0, 0, 0, 0 }, - { NV_OP_ST, "st", NV_TYPE_ANY, 0, 0, 0, 0, 0, 0, 0, 0 }, + { NV_OP_LD, "ld", NV_TYPE_ANY, 0, 0, 0, 0, 1, 0, 0, 0 }, + { NV_OP_ST, "st", NV_TYPE_ANY, 0, 0, 0, 0, 1, 0, 0, 0 }, { NV_OP_MOV, "mov", NV_TYPE_ANY, 0, 0, 0, 0, 1, 0, 1, 0 }, { NV_OP_AND, "and", NV_TYPE_U32, NV_MOD_NOT, 0, 1, 0, 1, 0, 6, 0 }, { NV_OP_OR, "or", NV_TYPE_U32, NV_MOD_NOT, 0, 1, 0, 1, 0, 6, 0 }, @@ -302,7 +302,7 @@ struct nv_op_info nvc0_op_info_table[NV_OP_COUNT + 1] = { NV_OP_CEIL, "ceil", NV_TYPE_F32, NV_MOD_SGN, 0, 0, 0, 1, 0, 0, 0 }, { NV_OP_FLOOR, "floor", NV_TYPE_F32, NV_MOD_SGN, 0, 0, 0, 1, 0, 0, 0 }, - { NV_OP_TRUNC, "floor", NV_TYPE_F32, NV_MOD_SGN, 0, 0, 0, 1, 0, 0, 0 }, + { NV_OP_TRUNC, "trunc", NV_TYPE_F32, NV_MOD_SGN, 0, 0, 0, 1, 0, 0, 0 }, { NV_OP_SAD, "sad", NV_TYPE_S32, 0, 0, 1, 0, 1, 0, 0, 0 }, @@ -343,18 +343,18 @@ struct nv_op_info nvc0_op_info_table[NV_OP_COUNT + 1] = { NV_OP_MIN, "max", NV_TYPE_U32, 0, 0, 1, 0, 1, 0, 0, 0 }, { NV_OP_MAX, "min", NV_TYPE_S32, 0, 0, 1, 0, 1, 0, 0, 0 }, { NV_OP_MIN, "min", NV_TYPE_U32, 0, 0, 1, 0, 1, 0, 0, 0 }, - { NV_OP_SET, "set", NV_TYPE_F32, NV_MOD_SGN, 0, 0, 0, 1, 0, 0, 2 }, - { NV_OP_SET, "set", NV_TYPE_S32, 0, 0, 0, 0, 1, 0, 0, 0 }, - { NV_OP_SET, "set", NV_TYPE_U32, 0, 0, 0, 0, 1, 0, 0, 0 }, + { NV_OP_SET, "set", NV_TYPE_F32, NV_MOD_SGN, 0, 0, 0, 1, 0, 2, 2 }, + { NV_OP_SET, "set", NV_TYPE_S32, 0, 0, 0, 0, 1, 0, 2, 2 }, + { NV_OP_SET, "set", NV_TYPE_U32, 0, 0, 0, 0, 1, 0, 2, 2 }, { NV_OP_SHR, "sar", NV_TYPE_S32, 0, 0, 0, 0, 1, 0, 1, 0 }, - { NV_OP_RCP, "rcp", NV_TYPE_F32, NV_MOD_SGN, 0, 0, 0, 0, 0, 0, 0 }, - { NV_OP_RSQ, "rsqrt", NV_TYPE_F32, NV_MOD_SGN, 0, 0, 0, 0, 0, 0, 0 }, - { NV_OP_LG2, "lg2", NV_TYPE_F32, NV_MOD_SGN, 0, 0, 0, 0, 0, 0, 0 }, - { NV_OP_SIN, "sin", NV_TYPE_F32, 0, 0, 0, 0, 0, 0, 0, 0 }, - { NV_OP_COS, "cos", NV_TYPE_F32, 0, 0, 0, 0, 0, 0, 0, 0 }, - { NV_OP_EX2, "ex2", NV_TYPE_F32, 0, 0, 0, 0, 0, 0, 0, 0 }, - { NV_OP_PRESIN, "presin", NV_TYPE_F32, NV_MOD_SGN, 0, 0, 0, 0, 0, 0, 0 }, - { NV_OP_PREEX2, "preex2", NV_TYPE_F32, NV_MOD_SGN, 0, 0, 0, 0, 0, 0, 0 }, + { NV_OP_RCP, "rcp", NV_TYPE_F32, NV_MOD_SGN, 0, 0, 0, 1, 0, 0, 0 }, + { NV_OP_RSQ, "rsqrt", NV_TYPE_F32, NV_MOD_SGN, 0, 0, 0, 1, 0, 0, 0 }, + { NV_OP_LG2, "lg2", NV_TYPE_F32, NV_MOD_SGN, 0, 0, 0, 1, 0, 0, 0 }, + { NV_OP_SIN, "sin", NV_TYPE_F32, 0, 0, 0, 0, 1, 0, 0, 0 }, + { NV_OP_COS, "cos", NV_TYPE_F32, 0, 0, 0, 0, 1, 0, 0, 0 }, + { NV_OP_EX2, "ex2", NV_TYPE_F32, 0, 0, 0, 0, 1, 0, 0, 0 }, + { NV_OP_PRESIN, "presin", NV_TYPE_F32, NV_MOD_SGN, 0, 0, 0, 1, 0, 0, 1 }, + { NV_OP_PREEX2, "preex2", NV_TYPE_F32, NV_MOD_SGN, 0, 0, 0, 1, 0, 0, 1 }, { NV_OP_SAT, "sat", NV_TYPE_F32, 0, 0, 0, 0, 1, 0, 0, 0 }, { NV_OP_SET_F32_AND, "and set", NV_TYPE_F32, 0, 0, 0, 0, 1, 0, 0, 0 }, @@ -363,13 +363,13 @@ struct nv_op_info nvc0_op_info_table[NV_OP_COUNT + 1] = { NV_OP_SELP, "selp", NV_TYPE_U32, 0, 0, 0, 0, 1, 0, 0, 0 }, - { NV_OP_SLCT_F32, "slct", NV_TYPE_F32, 0, 0, 0, 0, 1, 0, 0, 0 }, - { NV_OP_SLCT_F32, "slct", NV_TYPE_S32, 0, 0, 0, 0, 1, 0, 0, 0 }, - { NV_OP_SLCT_F32, "slct", NV_TYPE_U32, 0, 0, 0, 0, 1, 0, 0, 0 }, + { NV_OP_SLCT, "slct", NV_TYPE_F32, 0, 0, 0, 0, 1, 0, 2, 2 }, + { NV_OP_SLCT, "slct", NV_TYPE_S32, 0, 0, 0, 0, 1, 0, 2, 2 }, + { NV_OP_SLCT, "slct", NV_TYPE_U32, 0, 0, 0, 0, 1, 0, 2, 2 }, { NV_OP_ADD, "sub", NV_TYPE_F32, 0, 0, 0, 0, 1, 0, 1, 0 }, - { NV_OP_FSET_F32, "fset", NV_TYPE_F32, NV_MOD_SGN, 0, 0, 0, 1, 0, 0, 2 }, + { NV_OP_SET, "fset", NV_TYPE_F32, NV_MOD_SGN, 0, 0, 0, 1, 0, 2, 2 }, { NV_OP_TXG, "texgrad", NV_TYPE_F32, 0, 0, 0, 1, 1, 0, 0, 0 }, diff --git a/src/gallium/drivers/nvc0/nvc0_pc_regalloc.c b/src/gallium/drivers/nvc0/nvc0_pc_regalloc.c index d24f09a1507..f4afe083e2d 100644 --- a/src/gallium/drivers/nvc0/nvc0_pc_regalloc.c +++ b/src/gallium/drivers/nvc0/nvc0_pc_regalloc.c @@ -39,6 +39,30 @@ struct register_set { struct nv_pc *pc; }; +/* aliasing is allowed */ +static void +intersect_register_sets(struct register_set *dst, + struct register_set *src1, struct register_set *src2) +{ + int i; + + for (i = 0; i < NVC0_NUM_REGISTER_FILES; ++i) { + dst->bits[i][0] = src1->bits[i][0] | src2->bits[i][0]; + dst->bits[i][1] = src1->bits[i][1] | src2->bits[i][1]; + } +} + +static void +mask_register_set(struct register_set *set, uint32_t mask, uint32_t umask) +{ + int i; + + for (i = 0; i < NVC0_NUM_REGISTER_FILES; ++i) { + set->bits[i][0] = (set->bits[i][0] | mask) & umask; + set->bits[i][1] = (set->bits[i][1] | mask) & umask; + } +} + struct nv_pc_pass { struct nv_pc *pc; struct nv_instruction **insns; @@ -63,6 +87,9 @@ add_range_ex(struct nv_value *val, int bgn, int end, struct nv_range *new_range) { struct nv_range *range, **nextp = &val->livei; + if (bgn == end) /* [a, a) is invalid / empty */ + return TRUE; + for (range = val->livei; range; range = range->next) { if (end < range->bgn) break; /* insert before */ @@ -327,14 +354,14 @@ do_join_values(struct nv_pc_pass *ctx, struct nv_value *a, struct nv_value *b) assert(b->join == a->join); } -static INLINE void +static INLINE boolean try_join_values(struct nv_pc_pass *ctx, struct nv_value *a, struct nv_value *b) { if (!join_allowed(ctx, a, b)) { #ifdef NVC0_RA_DEBUG_JOIN debug_printf("cannot join %i to %i: not allowed\n", b->n, a->n); #endif - return; + return FALSE; } if (livei_have_overlap(a->join, b->join)) { #ifdef NVC0_RA_DEBUG_JOIN @@ -342,10 +369,27 @@ try_join_values(struct nv_pc_pass *ctx, struct nv_value *a, struct nv_value *b) livei_print(a); livei_print(b); #endif - return; + return FALSE; } do_join_values(ctx, a, b); + + return TRUE; +} + +static void +join_values_nofail(struct nv_pc_pass *ctx, + struct nv_value *a, struct nv_value *b, boolean type_only) +{ + if (type_only) { + assert(join_allowed(ctx, a, b)); + do_join_values(ctx, a, b); + } else { + boolean ok = try_join_values(ctx, a, b); + if (!ok) { + NOUVEAU_ERR("failed to coalesce values\n"); + } + } } static INLINE boolean @@ -360,20 +404,32 @@ need_new_else_block(struct nv_basic_block *b, struct nv_basic_block *p) return (b->num_in > 1) && (n == 2); } +/* Look for the @phi's operand whose definition reaches @b. */ static int phi_opnd_for_bb(struct nv_instruction *phi, struct nv_basic_block *b, struct nv_basic_block *tb) { + struct nv_ref *srci, *srcj; int i, j; for (j = -1, i = 0; i < 6 && phi->src[i]; ++i) { - if (!nvc0_bblock_reachable_by(b, phi->src[i]->value->insn->bb, tb)) + srci = phi->src[i]; + /* if already replaced, check with original source first */ + if (srci->flags & NV_REF_FLAG_REGALLOC_PRIV) + srci = srci->value->insn->src[0]; + if (!nvc0_bblock_reachable_by(b, srci->value->insn->bb, NULL)) continue; /* NOTE: back-edges are ignored by the reachable-by check */ - if (j < 0 || !nvc0_bblock_reachable_by(phi->src[j]->value->insn->bb, - phi->src[i]->value->insn->bb, tb)) + if (j < 0 || !nvc0_bblock_reachable_by(srcj->value->insn->bb, + srci->value->insn->bb, NULL)) { j = i; + srcj = srci; + } } + if (j >= 0 && nvc0_bblock_reachable_by(b, phi->def[0]->insn->bb, NULL)) + if (!nvc0_bblock_reachable_by(srcj->value->insn->bb, + phi->def[0]->insn->bb, NULL)) + j = -1; return j; } @@ -420,21 +476,23 @@ pass_generate_phi_movs(struct nv_pc_pass *ctx, struct nv_basic_block *b) ctx->pc->current_block = pn; for (i = b->phi; i && i->opcode == NV_OP_PHI; i = i->next) { - if ((j = phi_opnd_for_bb(i, p, b)) < 0) - continue; - val = i->src[j]->value; - - if (i->src[j]->flags) { - /* value already encountered from a different in-block */ - val = val->insn->src[0]->value; - while (j < 6 && i->src[j]) - ++j; - assert(j < 6); + j = phi_opnd_for_bb(i, p, b); + + if (j < 0) { + val = i->def[0]; + } else { + val = i->src[j]->value; + if (i->src[j]->flags & NV_REF_FLAG_REGALLOC_PRIV) { + j = -1; + /* use original value, we already encountered & replaced it */ + val = val->insn->src[0]->value; + } } + if (j < 0) /* need an additional source ? */ + for (j = 0; j < 6 && i->src[j] && i->src[j]->value != val; ++j); + assert(j < 6); /* XXX: really ugly shaders */ ni = new_instruction(ctx->pc, NV_OP_MOV); - - /* TODO: insert instruction at correct position in the first place */ if (ni->prev && ni->prev->target) nvc0_insns_permute(ni->prev, ni); @@ -442,7 +500,7 @@ pass_generate_phi_movs(struct nv_pc_pass *ctx, struct nv_basic_block *b) ni->def[0]->insn = ni; nv_reference(ctx->pc, ni, 0, val); nv_reference(ctx->pc, i, j, ni->def[0]); /* new phi source = MOV def */ - i->src[j]->flags = 1; + i->src[j]->flags |= NV_REF_FLAG_REGALLOC_PRIV; } if (pn != p && pn->exit) { @@ -460,8 +518,13 @@ pass_generate_phi_movs(struct nv_pc_pass *ctx, struct nv_basic_block *b) return 0; } +#define JOIN_MASK_PHI (1 << 0) +#define JOIN_MASK_SELECT (1 << 1) +#define JOIN_MASK_MOV (1 << 2) +#define JOIN_MASK_BIND (1 << 3) + static int -pass_join_values(struct nv_pc_pass *ctx, int iter) +pass_join_values(struct nv_pc_pass *ctx, unsigned mask) { int c, n; @@ -470,36 +533,33 @@ pass_join_values(struct nv_pc_pass *ctx, int iter) switch (i->opcode) { case NV_OP_PHI: - if (iter != 2) + if (!(mask & JOIN_MASK_PHI)) break; for (c = 0; c < 6 && i->src[c]; ++c) - try_join_values(ctx, i->def[0], i->src[c]->value); + join_values_nofail(ctx, i->def[0], i->src[c]->value, FALSE); break; case NV_OP_MOV: - if ((iter == 2) && i->src[0]->value->insn && - !nv_is_texture_op(i->src[0]->value->join->insn->opcode)) + if (!(mask & JOIN_MASK_MOV)) + break; + if (i->src[0]->value->insn && !i->src[0]->value->insn->def[1]) try_join_values(ctx, i->def[0], i->src[0]->value); break; case NV_OP_SELECT: - if (iter != 1) + if (!(mask & JOIN_MASK_SELECT)) break; - for (c = 0; c < 6 && i->src[c]; ++c) { - assert(join_allowed(ctx, i->def[0], i->src[c]->value)); - do_join_values(ctx, i->def[0], i->src[c]->value); - } - break; - case NV_OP_TEX: - case NV_OP_TXB: - case NV_OP_TXL: - case NV_OP_TXQ: - /* on nvc0, TEX src and dst can differ */ + for (c = 0; c < 6 && i->src[c]; ++c) + join_values_nofail(ctx, i->def[0], i->src[c]->value, TRUE); break; case NV_OP_BIND: - if (iter) + if (!(mask & JOIN_MASK_BIND)) break; - for (c = 0; c < 6 && i->src[c]; ++c) - do_join_values(ctx, i->def[c], i->src[c]->value); + for (c = 0; c < 4 && i->src[c]; ++c) + join_values_nofail(ctx, i->def[c], i->src[c]->value, TRUE); break; + case NV_OP_TEX: + case NV_OP_TXB: + case NV_OP_TXL: + case NV_OP_TXQ: /* on nvc0, TEX src and dst can differ */ default: break; } @@ -621,15 +681,16 @@ static void collect_live_values(struct nv_basic_block *b, const int n) { int i; - if (b->out[0]) { - if (b->out[1]) { /* what to do about back-edges ? */ + /* XXX: what to do about back/fake-edges (used to include both here) ? */ + if (b->out[0] && b->out_kind[0] != CFG_EDGE_FAKE) { + if (b->out[1] && b->out_kind[1] != CFG_EDGE_FAKE) { for (i = 0; i < n; ++i) b->live_set[i] = b->out[0]->live_set[i] | b->out[1]->live_set[i]; } else { memcpy(b->live_set, b->out[0]->live_set, n * sizeof(uint32_t)); } } else - if (b->out[1]) { + if (b->out[1] && b->out_kind[1] != CFG_EDGE_FAKE) { memcpy(b->live_set, b->out[1]->live_set, n * sizeof(uint32_t)); } else { memset(b->live_set, 0, n * sizeof(uint32_t)); @@ -746,42 +807,46 @@ insert_ordered_tail(struct nv_value *list, struct nv_value *nval) elem->next = nval; } -static int -pass_linear_scan(struct nv_pc_pass *ctx, int iter) +static void +collect_register_values(struct nv_pc_pass *ctx, struct nv_value *head, + boolean assigned_only) { - struct nv_instruction *i; - struct register_set f, free; + struct nv_value *val; int k, n; - struct nv_value *cur, *val, *tmp[2]; - struct nv_value active, inactive, handled, unhandled; - make_empty_list(&active); - make_empty_list(&inactive); - make_empty_list(&handled); - make_empty_list(&unhandled); + make_empty_list(head); - nvc0_ctor_register_set(ctx->pc, &free); - - /* joined values should have range = NULL and thus not be added; - * also, fixed memory values won't be added because they're not - * def'd, just used - */ for (n = 0; n < ctx->num_insns; ++n) { - i = ctx->insns[n]; + struct nv_instruction *i = ctx->insns[n]; + /* for joined values, only the representative will have livei != NULL */ for (k = 0; k < 5; ++k) { if (i->def[k] && i->def[k]->livei) - insert_ordered_tail(&unhandled, i->def[k]); - else - if (0 && i->def[k]) - debug_printf("skipping def'd value %i: no livei\n", i->def[k]->n); + if (!assigned_only || i->def[k]->reg.id >= 0) + insert_ordered_tail(head, i->def[k]); } } - for (val = unhandled.next; val != unhandled.prev; val = val->next) { + for (val = head->next; val != head->prev; val = val->next) { assert(val->join == val); assert(val->livei->bgn <= val->next->livei->bgn); } +} + +static int +pass_linear_scan(struct nv_pc_pass *ctx) +{ + struct register_set f, free; + struct nv_value *cur, *val, *tmp[2]; + struct nv_value active, inactive, handled, unhandled; + + make_empty_list(&active); + make_empty_list(&inactive); + make_empty_list(&handled); + + nvc0_ctor_register_set(ctx->pc, &free); + + collect_register_values(ctx, &unhandled, FALSE); foreach_s(cur, tmp[0], &unhandled) { remove_from_list(cur); @@ -818,14 +883,7 @@ pass_linear_scan(struct nv_pc_pass *ctx, int iter) reg_occupy(&f, val); if (cur->reg.id < 0) { - boolean mem = FALSE; - int v = nvi_vector_size(cur->insn); - - if (v > 1) - mem = !reg_assign(&f, &cur->insn->def[0], v); - else - if (iter) - mem = !reg_assign(&f, &cur, 1); + boolean mem = !reg_assign(&f, &cur, 1); if (mem) { NOUVEAU_ERR("out of registers\n"); @@ -839,6 +897,68 @@ pass_linear_scan(struct nv_pc_pass *ctx, int iter) return 0; } +/* Allocate values defined by instructions such as TEX, which have to be + * assigned to consecutive registers. + * Linear scan doesn't really work here since the values can have different + * live intervals. + */ +static int +pass_allocate_constrained_values(struct nv_pc_pass *ctx) +{ + struct nv_value regvals, *val; + struct nv_instruction *i; + struct nv_value *defs[4]; + struct register_set regs[4]; + int n, vsize, c; + uint32_t mask; + boolean mem; + + collect_register_values(ctx, ®vals, TRUE); + + for (n = 0; n < ctx->num_insns; ++n) { + i = ctx->insns[n]; + vsize = nvi_vector_size(i); + if (!(vsize > 1)) + continue; + assert(vsize <= 4); + + for (c = 0; c < vsize; ++c) + defs[c] = i->def[c]->join; + + if (defs[0]->reg.id >= 0) { + for (c = 1; c < vsize; ++c) + assert(defs[c]->reg.id >= 0); + continue; + } + + for (c = 0; c < vsize; ++c) { + nvc0_ctor_register_set(ctx->pc, ®s[c]); + + foreach(val, ®vals) { + if (val->reg.id >= 0 && livei_have_overlap(val, defs[c])) + reg_occupy(®s[c], val); + } + mask = 0x11111111; + if (vsize == 2) /* granularity is 2 and not 4 */ + mask |= 0x11111111 << 2; + mask_register_set(®s[c], 0, mask << c); + + if (defs[c]->livei) + insert_ordered_tail(®vals, defs[c]); + } + for (c = 1; c < vsize; ++c) + intersect_register_sets(®s[0], ®s[0], ®s[c]); + + mem = !reg_assign(®s[0], &defs[0], vsize); + + if (mem) { + NOUVEAU_ERR("out of registers\n"); + abort(); + } + } + return 0; +} + static int nv_pc_pass1(struct nv_pc *pc, struct nv_basic_block *root) { @@ -862,6 +982,10 @@ nv_pc_pass1(struct nv_pc *pc, struct nv_basic_block *root) ret = pass_generate_phi_movs(ctx, root); assert(!ret); +#ifdef NVC0_RA_DEBUG_LIVEI + nvc0_print_function(root); +#endif + for (i = 0; i < pc->loop_nesting_bound; ++i) { pc->pass_seq++; ret = pass_build_live_sets(ctx, root); @@ -888,19 +1012,19 @@ nv_pc_pass1(struct nv_pc *pc, struct nv_basic_block *root) livei_print(&pc->values[i]); #endif - ret = pass_join_values(ctx, 0); + ret = pass_join_values(ctx, JOIN_MASK_PHI); if (ret) goto out; - ret = pass_linear_scan(ctx, 0); + ret = pass_join_values(ctx, JOIN_MASK_SELECT | JOIN_MASK_BIND); if (ret) goto out; - ret = pass_join_values(ctx, 1); + ret = pass_join_values(ctx, JOIN_MASK_MOV); if (ret) goto out; - ret = pass_join_values(ctx, 2); + ret = pass_allocate_constrained_values(ctx); if (ret) goto out; - ret = pass_linear_scan(ctx, 1); + ret = pass_linear_scan(ctx); if (ret) goto out; diff --git a/src/gallium/drivers/nvc0/nvc0_program.c b/src/gallium/drivers/nvc0/nvc0_program.c index aefaf7b98ad..899fe147c6a 100644 --- a/src/gallium/drivers/nvc0/nvc0_program.c +++ b/src/gallium/drivers/nvc0/nvc0_program.c @@ -185,8 +185,17 @@ nvc0_varying_location(unsigned sn, unsigned si) return 0x2e0; */ case TGSI_SEMANTIC_GENERIC: + /* We'd really like to distinguish between TEXCOORD and GENERIC here, + * since only 0x300 to 0x37c can be replaced by sprite coordinates. + * Also, gl_PointCoord should be a system value and must be assigned to + * address 0x2e0. For now, let's cheat: + */ assert(si < 31); - return 0x80 + (si * 16); + if (si <= 7) + return 0x300 + si * 16; + if (si == 9) + return 0x2e0; + return 0x80 + ((si - 8) * 16); case TGSI_SEMANTIC_NORMAL: return 0x360; case TGSI_SEMANTIC_PRIMID: @@ -256,12 +265,14 @@ prog_decl(struct nvc0_translation_info *ti, case TGSI_FILE_INPUT: for (i = first; i <= last; ++i) { if (ti->prog->type == PIPE_SHADER_VERTEX) { - sn = TGSI_SEMANTIC_GENERIC; - si = i; + for (c = 0; c < 4; ++c) + ti->input_loc[i][c] = 0x80 + i * 16 + c * 4; + } else { + for (c = 0; c < 4; ++c) + ti->input_loc[i][c] = nvc0_varying_location(sn, si) + c * 4; + /* for sprite coordinates: */ + ti->prog->fp.in_pos[i] = ti->input_loc[i][0] / 4; } - for (c = 0; c < 4; ++c) - ti->input_loc[i][c] = nvc0_varying_location(sn, si) + c * 4; - if (ti->prog->type == PIPE_SHADER_FRAGMENT) ti->interp_mode[i] = nvc0_interp_mode(decl); } @@ -281,6 +292,8 @@ prog_decl(struct nvc0_translation_info *ti, } else { for (c = 0; c < 4; ++c) ti->output_loc[i][c] = nvc0_varying_location(sn, si) + c * 4; + /* for TFB_VARYING_LOCS: */ + ti->prog->vp.out_pos[i] = ti->output_loc[i][0] / 4; } } break; @@ -288,9 +301,11 @@ prog_decl(struct nvc0_translation_info *ti, ti->sysval_loc[i] = nvc0_system_value_location(sn, si, &ti->sysval_in[i]); assert(first == last); break; + case TGSI_FILE_TEMPORARY: + ti->temp128_nr = MAX2(ti->temp128_nr, last + 1); + break; case TGSI_FILE_NULL: case TGSI_FILE_CONSTANT: - case TGSI_FILE_TEMPORARY: case TGSI_FILE_SAMPLER: case TGSI_FILE_ADDRESS: case TGSI_FILE_IMMEDIATE: @@ -518,8 +533,13 @@ nvc0_fp_gen_header(struct nvc0_program *fp, struct nvc0_translation_info *ti) if (!ti->input_access[i][c]) continue; a = ti->input_loc[i][c] / 2; - if ((a & ~7) == 0x70/2) - fp->hdr[5] |= 1 << (28 + (a & 7) / 2); /* FRAG_COORD_UMASK */ + if (ti->input_loc[i][c] >= 0x2c0) + a -= 32; + if (ti->input_loc[i][0] == 0x70) + fp->hdr[5] |= 1 << (28 + c); /* FRAG_COORD_UMASK */ + else + if (ti->input_loc[i][0] == 0x2e0) + fp->hdr[14] |= 1 << (24 + c); /* POINT_COORD */ else fp->hdr[4 + a / 32] |= m << (a % 32); } @@ -618,7 +638,7 @@ nvc0_prog_scan(struct nvc0_translation_info *ti) if (ti->scan.writes_z) prog->flags[0] = 0x11; /* ? */ else - if (!ti->global_stores) + if (!ti->scan.uses_kill && !ti->global_stores) prog->fp.early_z = 1; ret = nvc0_fp_gen_header(prog, ti); @@ -629,6 +649,11 @@ nvc0_prog_scan(struct nvc0_translation_info *ti) break; } + if (ti->require_stores) { + prog->hdr[0] |= 1 << 26; + prog->hdr[1] |= ti->temp128_nr * 16; /* l[] size */ + } + assert(!ret); return ret; } diff --git a/src/gallium/drivers/nvc0/nvc0_program.h b/src/gallium/drivers/nvc0/nvc0_program.h index e6b210d1355..f6fea29780b 100644 --- a/src/gallium/drivers/nvc0/nvc0_program.h +++ b/src/gallium/drivers/nvc0/nvc0_program.h @@ -21,16 +21,18 @@ struct nvc0_program { unsigned code_size; unsigned parm_size; - uint32_t hdr[20]; + uint32_t hdr[20]; /* TODO: move this into code to save space */ uint32_t flags[2]; struct { uint8_t edgeflag; uint8_t num_ucps; + uint8_t out_pos[PIPE_MAX_SHADER_OUTPUTS]; } vp; struct { uint8_t early_z; + uint8_t in_pos[PIPE_MAX_SHADER_INPUTS]; } fp; void *relocs; @@ -74,6 +76,7 @@ struct nvc0_translation_info { uint32_t *immd32; ubyte *immd32_ty; unsigned immd32_nr; + unsigned temp128_nr; ubyte edgeflag_out; struct nvc0_subroutine *subr; unsigned num_subrs; diff --git a/src/gallium/drivers/nvc0/nvc0_push.c b/src/gallium/drivers/nvc0/nvc0_push.c index 74c3451c19a..fcbb7da41a3 100644 --- a/src/gallium/drivers/nvc0/nvc0_push.c +++ b/src/gallium/drivers/nvc0/nvc0_push.c @@ -217,6 +217,7 @@ nvc0_push_vbo(struct nvc0_context *nvc0, const struct pipe_draw_info *info) struct push_context ctx; unsigned i, index_size; unsigned inst = info->instance_count; + boolean apply_bias = info->indexed && info->index_bias; ctx.chan = nvc0->screen->base.channel; ctx.translate = nvc0->vertex->translate; @@ -230,7 +231,8 @@ nvc0_push_vbo(struct nvc0_context *nvc0, const struct pipe_draw_info *info) data = nvc0_resource_map_offset(nvc0, res, vb->buffer_offset, NOUVEAU_BO_RD); - if (info->indexed) + + if (apply_bias && likely(!(nvc0->vertex->instance_bufs & (1 << i)))) data += info->index_bias * vb->stride; ctx.translate->set_buffer(ctx.translate, i, data, vb->stride, ~0); diff --git a/src/gallium/drivers/nvc0/nvc0_query.c b/src/gallium/drivers/nvc0/nvc0_query.c index cc83fbe771c..e5e43c0e7a5 100644 --- a/src/gallium/drivers/nvc0/nvc0_query.c +++ b/src/gallium/drivers/nvc0/nvc0_query.c @@ -312,6 +312,7 @@ nvc0_render_condition(struct pipe_context *pipe, if (mode == PIPE_RENDER_COND_WAIT || mode == PIPE_RENDER_COND_BY_REGION_WAIT) { + MARK_RING (chan, 5, 2); BEGIN_RING(chan, RING_3D_(NV84_SUBCHAN_QUERY_ADDRESS_HIGH), 4); OUT_RELOCh(chan, q->bo, q->offset, NOUVEAU_BO_GART | NOUVEAU_BO_RD); OUT_RELOCl(chan, q->bo, q->offset, NOUVEAU_BO_GART | NOUVEAU_BO_RD); @@ -319,6 +320,7 @@ nvc0_render_condition(struct pipe_context *pipe, OUT_RING (chan, 0x00001001); } + MARK_RING (chan, 4, 2); BEGIN_RING(chan, RING_3D(COND_ADDRESS_HIGH), 3); OUT_RELOCh(chan, q->bo, q->offset, NOUVEAU_BO_GART | NOUVEAU_BO_RD); OUT_RELOCl(chan, q->bo, q->offset, NOUVEAU_BO_GART | NOUVEAU_BO_RD); diff --git a/src/gallium/drivers/nvc0/nvc0_resource.h b/src/gallium/drivers/nvc0/nvc0_resource.h index 17e79642a6d..599823c0dc9 100644 --- a/src/gallium/drivers/nvc0/nvc0_resource.h +++ b/src/gallium/drivers/nvc0/nvc0_resource.h @@ -24,7 +24,8 @@ struct nvc0_context; * USER_MEMORY: resource->data is a pointer to client memory and may change * between GL calls */ -#define NVC0_BUFFER_STATUS_DIRTY (1 << 0) +#define NVC0_BUFFER_STATUS_GPU_READING (1 << 0) +#define NVC0_BUFFER_STATUS_GPU_WRITING (1 << 1) #define NVC0_BUFFER_STATUS_USER_MEMORY (1 << 7) /* Resources, if mapped into the GPU's address space, are guaranteed to @@ -51,6 +52,9 @@ struct nvc0_resource { struct nvc0_mm_allocation *mm; }; +void +nvc0_buffer_release_gpu_storage(struct nvc0_resource *); + boolean nvc0_buffer_download(struct nvc0_context *, struct nvc0_resource *, unsigned start, unsigned size); @@ -87,7 +91,7 @@ nvc0_resource_map_offset(struct nvc0_context *nvc0, nvc0_buffer_adjust_score(nvc0, res, -250); if ((res->domain == NOUVEAU_BO_VRAM) && - (res->status & NVC0_BUFFER_STATUS_DIRTY)) + (res->status & NVC0_BUFFER_STATUS_GPU_WRITING)) nvc0_buffer_download(nvc0, res, 0, res->base.width0); if ((res->domain != NOUVEAU_BO_GART) || diff --git a/src/gallium/drivers/nvc0/nvc0_screen.c b/src/gallium/drivers/nvc0/nvc0_screen.c index f608b32e1cb..f7f1fd09a12 100644 --- a/src/gallium/drivers/nvc0/nvc0_screen.c +++ b/src/gallium/drivers/nvc0/nvc0_screen.c @@ -75,6 +75,8 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) return 10; case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: return 13; + case PIPE_CAP_ARRAY_TEXTURES: + return 1; case PIPE_CAP_TEXTURE_MIRROR_CLAMP: case PIPE_CAP_TEXTURE_MIRROR_REPEAT: case PIPE_CAP_TEXTURE_SWIZZLE: @@ -281,9 +283,6 @@ nvc0_magic_3d_init(struct nouveau_channel *chan) BEGIN_RING(chan, RING_3D_(0x074c), 1); OUT_RING (chan, 0x3f); - BEGIN_RING(chan, RING_3D_(0x10f8), 1); - OUT_RING (chan, 0x0101); - BEGIN_RING(chan, RING_3D_(0x16a8), 1); OUT_RING (chan, (3 << 16) | 3); BEGIN_RING(chan, RING_3D_(0x1794), 1); @@ -476,7 +475,7 @@ nvc0_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) OUT_RING (chan, (15 << 4) | 1); } - screen->tls_size = 4 * 4 * 32 * 128 * 4; + screen->tls_size = (16 * 32) * (NVC0_CAP_MAX_PROGRAM_TEMPS * 16); ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 1 << 17, screen->tls_size, &screen->tls); if (ret) @@ -490,6 +489,8 @@ nvc0_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) OUT_RELOCl(chan, screen->tls, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); OUT_RING (chan, screen->tls_size >> 32); OUT_RING (chan, screen->tls_size); + BEGIN_RING(chan, RING_3D_(0x07a0), 1); + OUT_RING (chan, 0); BEGIN_RING(chan, RING_3D(LOCAL_BASE), 1); OUT_RING (chan, 0); @@ -532,16 +533,27 @@ nvc0_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) BEGIN_RING(chan, RING_3D_(0x1590), 1); /* deactivate ZCULL */ OUT_RING (chan, 0x3f); - BEGIN_RING(chan, RING_3D(VIEWPORT_CLIP_RECTS_EN), 1); + BEGIN_RING(chan, RING_3D(CLIP_RECTS_MODE), 1); + OUT_RING (chan, NVC0_3D_CLIP_RECTS_MODE_INSIDE_ANY); + BEGIN_RING(chan, RING_3D(CLIP_RECT_HORIZ(0)), 8 * 2); + for (i = 0; i < 8 * 2; ++i) + OUT_RING(chan, 0); + BEGIN_RING(chan, RING_3D(CLIP_RECTS_EN), 1); OUT_RING (chan, 0); BEGIN_RING(chan, RING_3D(CLIPID_ENABLE), 1); OUT_RING (chan, 0); + /* neither scissors, viewport nor stencil mask should affect clears */ + BEGIN_RING(chan, RING_3D(CLEAR_FLAGS), 1); + OUT_RING (chan, 0); + BEGIN_RING(chan, RING_3D(VIEWPORT_TRANSFORM_EN), 1); OUT_RING (chan, 1); BEGIN_RING(chan, RING_3D(DEPTH_RANGE_NEAR(0)), 2); OUT_RINGf (chan, 0.0f); OUT_RINGf (chan, 1.0f); + BEGIN_RING(chan, RING_3D(VIEW_VOLUME_CLIP_CTRL), 1); + OUT_RING (chan, NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK1_UNK1); /* We use scissors instead of exact view volume clipping, * so they're always enabled. @@ -628,11 +640,14 @@ nvc0_screen_make_buffers_resident(struct nvc0_screen *screen) const unsigned flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD; + MARK_RING(chan, 5, 5); nouveau_bo_validate(chan, screen->text, flags); nouveau_bo_validate(chan, screen->uniforms, flags); nouveau_bo_validate(chan, screen->txc, flags); - nouveau_bo_validate(chan, screen->tls, flags); nouveau_bo_validate(chan, screen->mp_stack_bo, flags); + + if (screen->cur_ctx && screen->cur_ctx->state.tls_required) + nouveau_bo_validate(chan, screen->tls, flags); } int diff --git a/src/gallium/drivers/nvc0/nvc0_screen.h b/src/gallium/drivers/nvc0/nvc0_screen.h index 1fac142e2be..d952ff1f9b1 100644 --- a/src/gallium/drivers/nvc0/nvc0_screen.h +++ b/src/gallium/drivers/nvc0/nvc0_screen.h @@ -128,17 +128,25 @@ nvc0_resource_validate(struct nvc0_resource *res, uint32_t flags) { struct nvc0_screen *screen = nvc0_screen(res->base.screen); - nouveau_bo_validate(screen->base.channel, res->bo, flags); + if (likely(res->bo)) { + nouveau_bo_validate(screen->base.channel, res->bo, flags); - nvc0_resource_fence(res, flags); + if (flags & NOUVEAU_BO_WR) + res->status |= NVC0_BUFFER_STATUS_GPU_WRITING; + if (flags & NOUVEAU_BO_RD) + res->status |= NVC0_BUFFER_STATUS_GPU_READING; + + nvc0_resource_fence(res, flags); + } } boolean nvc0_screen_fence_new(struct nvc0_screen *, struct nvc0_fence **, boolean emit); - void nvc0_screen_fence_next(struct nvc0_screen *); +void +nvc0_screen_fence_update(struct nvc0_screen *, boolean flushed); static INLINE boolean nvc0_screen_fence_emit(struct nvc0_screen *screen) diff --git a/src/gallium/drivers/nvc0/nvc0_shader_state.c b/src/gallium/drivers/nvc0/nvc0_shader_state.c index 981b5488d08..357f8b80deb 100644 --- a/src/gallium/drivers/nvc0/nvc0_shader_state.c +++ b/src/gallium/drivers/nvc0/nvc0_shader_state.c @@ -27,6 +27,16 @@ #include "nvc0_context.h" +static INLINE void +nvc0_program_update_context_state(struct nvc0_context *nvc0, + struct nvc0_program *prog, int stage) +{ + if (prog->hdr[1]) + nvc0->state.tls_required |= 1 << stage; + else + nvc0->state.tls_required &= ~(1 << stage); +} + static boolean nvc0_program_validate(struct nvc0_context *nvc0, struct nvc0_program *prog) { @@ -55,7 +65,7 @@ nvc0_program_validate(struct nvc0_context *nvc0, struct nvc0_program *prog) prog->code_base + NVC0_SHADER_HEADER_SIZE, prog->code_size, prog->code); - BEGIN_RING(nvc0->screen->base.channel, RING_3D_(0x021c), 1); + BEGIN_RING(nvc0->screen->base.channel, RING_3D(MEM_BARRIER), 1); OUT_RING (nvc0->screen->base.channel, 0x1111); return TRUE; @@ -77,6 +87,7 @@ nvc0_vertprog_validate(struct nvc0_context *nvc0) if (!nvc0_program_validate(nvc0, vp)) return; + nvc0_program_update_context_state(nvc0, vp, 0); BEGIN_RING(chan, RING_3D(SP_SELECT(1)), 2); OUT_RING (chan, 0x11); @@ -98,6 +109,7 @@ nvc0_fragprog_validate(struct nvc0_context *nvc0) if (!nvc0_program_validate(nvc0, fp)) return; + nvc0_program_update_context_state(nvc0, fp, 4); BEGIN_RING(chan, RING_3D(EARLY_FRAGMENT_TESTS), 1); OUT_RING (chan, fp->fp.early_z); @@ -127,6 +139,7 @@ nvc0_tctlprog_validate(struct nvc0_context *nvc0) } if (!nvc0_program_validate(nvc0, tp)) return; + nvc0_program_update_context_state(nvc0, tp, 1); BEGIN_RING(chan, RING_3D(SP_SELECT(2)), 2); OUT_RING (chan, 0x21); @@ -148,6 +161,7 @@ nvc0_tevlprog_validate(struct nvc0_context *nvc0) } if (!nvc0_program_validate(nvc0, tp)) return; + nvc0_program_update_context_state(nvc0, tp, 2); BEGIN_RING(chan, RING_3D(TEP_SELECT), 1); OUT_RING (chan, 0x31); @@ -170,6 +184,7 @@ nvc0_gmtyprog_validate(struct nvc0_context *nvc0) } if (!nvc0_program_validate(nvc0, gp)) return; + nvc0_program_update_context_state(nvc0, gp, 3); BEGIN_RING(chan, RING_3D(GP_SELECT), 1); OUT_RING (chan, 0x41); @@ -178,3 +193,59 @@ nvc0_gmtyprog_validate(struct nvc0_context *nvc0) BEGIN_RING(chan, RING_3D(SP_GPR_ALLOC(4)), 1); OUT_RING (chan, gp->max_gpr); } + +/* It's *is* kind of shader related. We need to inspect the program + * to get the output locations right. + */ +void +nvc0_tfb_validate(struct nvc0_context *nvc0) +{ + struct nouveau_channel *chan = nvc0->screen->base.channel; + struct nvc0_program *vp; + struct nvc0_transform_feedback_state *tfb = nvc0->tfb; + int b; + + BEGIN_RING(chan, RING_3D(TFB_ENABLE), 1); + if (!tfb) { + OUT_RING(chan, 0); + return; + } + OUT_RING(chan, 1); + + vp = nvc0->vertprog ? nvc0->vertprog : nvc0->gmtyprog; + + for (b = 0; b < nvc0->num_tfbbufs; ++b) { + uint8_t idx, var[128]; + int i, n; + struct nvc0_resource *buf = nvc0_resource(nvc0->tfbbuf[b]); + + BEGIN_RING(chan, RING_3D(TFB_BUFFER_ENABLE(b)), 5); + OUT_RING (chan, 1); + OUT_RESRCh(chan, buf, nvc0->tfb_offset[b], NOUVEAU_BO_WR); + OUT_RESRCl(chan, buf, nvc0->tfb_offset[b], NOUVEAU_BO_WR); + OUT_RING (chan, buf->base.width0 - nvc0->tfb_offset[b]); + OUT_RING (chan, 0); /* TFB_PRIMITIVE_ID <- offset ? */ + + if (!(nvc0->dirty & NVC0_NEW_TFB)) + continue; + + BEGIN_RING(chan, RING_3D(TFB_UNK07X0(b)), 3); + OUT_RING (chan, 0); + OUT_RING (chan, tfb->varying_count[b]); + OUT_RING (chan, tfb->stride[b]); + + n = b ? tfb->varying_count[b - 1] : 0; + i = 0; + for (; i < tfb->varying_count[b]; ++i) { + idx = tfb->varying_index[n + i]; + var[i] = vp->vp.out_pos[idx >> 2] + (idx & 3); + } + for (; i & 3; ++i) + var[i] = 0; + + BEGIN_RING(chan, RING_3D(TFB_VARYING_LOCS(b, 0)), i / 4); + OUT_RINGp (chan, var, i / 4); + } + for (; b < 4; ++b) + IMMED_RING(chan, RING_3D(TFB_BUFFER_ENABLE(b)), 0); +} diff --git a/src/gallium/drivers/nvc0/nvc0_state.c b/src/gallium/drivers/nvc0/nvc0_state.c index c08f3693f5e..aa437195764 100644 --- a/src/gallium/drivers/nvc0/nvc0_state.c +++ b/src/gallium/drivers/nvc0/nvc0_state.c @@ -22,6 +22,7 @@ #include "pipe/p_defines.h" #include "util/u_inlines.h" +#include "util/u_transfer.h" #include "tgsi/tgsi_parse.h" @@ -50,40 +51,35 @@ nvc0_colormask(unsigned mask) return ret; } +#define NVC0_BLEND_FACTOR_CASE(a, b) \ + case PIPE_BLENDFACTOR_##a: return NV50_3D_BLEND_FACTOR_##b + static INLINE uint32_t nvc0_blend_fac(unsigned factor) { - static const uint16_t bf[] = { - NV50_3D_BLEND_FACTOR_ZERO, /* 0x00 */ - NV50_3D_BLEND_FACTOR_ONE, - NV50_3D_BLEND_FACTOR_SRC_COLOR, - NV50_3D_BLEND_FACTOR_SRC_ALPHA, - NV50_3D_BLEND_FACTOR_DST_ALPHA, - NV50_3D_BLEND_FACTOR_DST_COLOR, - NV50_3D_BLEND_FACTOR_SRC_ALPHA_SATURATE, - NV50_3D_BLEND_FACTOR_CONSTANT_COLOR, - NV50_3D_BLEND_FACTOR_CONSTANT_ALPHA, - NV50_3D_BLEND_FACTOR_SRC1_COLOR, - NV50_3D_BLEND_FACTOR_SRC1_ALPHA, - NV50_3D_BLEND_FACTOR_ZERO, /* 0x0b */ - NV50_3D_BLEND_FACTOR_ZERO, /* 0x0c */ - NV50_3D_BLEND_FACTOR_ZERO, /* 0x0d */ - NV50_3D_BLEND_FACTOR_ZERO, /* 0x0e */ - NV50_3D_BLEND_FACTOR_ZERO, /* 0x0f */ - NV50_3D_BLEND_FACTOR_ZERO, /* 0x10 */ - NV50_3D_BLEND_FACTOR_ZERO, /* 0x11 */ - NV50_3D_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, - NV50_3D_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, - NV50_3D_BLEND_FACTOR_ONE_MINUS_DST_ALPHA, - NV50_3D_BLEND_FACTOR_ONE_MINUS_DST_COLOR, - NV50_3D_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR, - NV50_3D_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA, - NV50_3D_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR, - NV50_3D_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA - }; - - assert(factor < (sizeof(bf) / sizeof(bf[0]))); - return bf[factor]; + switch (factor) { + NVC0_BLEND_FACTOR_CASE(ONE, ONE); + NVC0_BLEND_FACTOR_CASE(SRC_COLOR, SRC_COLOR); + NVC0_BLEND_FACTOR_CASE(SRC_ALPHA, SRC_ALPHA); + NVC0_BLEND_FACTOR_CASE(DST_ALPHA, DST_ALPHA); + NVC0_BLEND_FACTOR_CASE(DST_COLOR, DST_COLOR); + NVC0_BLEND_FACTOR_CASE(SRC_ALPHA_SATURATE, SRC_ALPHA_SATURATE); + NVC0_BLEND_FACTOR_CASE(CONST_COLOR, CONSTANT_COLOR); + NVC0_BLEND_FACTOR_CASE(CONST_ALPHA, CONSTANT_ALPHA); + NVC0_BLEND_FACTOR_CASE(SRC1_COLOR, SRC1_COLOR); + NVC0_BLEND_FACTOR_CASE(SRC1_ALPHA, SRC1_ALPHA); + NVC0_BLEND_FACTOR_CASE(ZERO, ZERO); + NVC0_BLEND_FACTOR_CASE(INV_SRC_COLOR, ONE_MINUS_SRC_COLOR); + NVC0_BLEND_FACTOR_CASE(INV_SRC_ALPHA, ONE_MINUS_SRC_ALPHA); + NVC0_BLEND_FACTOR_CASE(INV_DST_ALPHA, ONE_MINUS_DST_ALPHA); + NVC0_BLEND_FACTOR_CASE(INV_DST_COLOR, ONE_MINUS_DST_COLOR); + NVC0_BLEND_FACTOR_CASE(INV_CONST_COLOR, ONE_MINUS_CONSTANT_COLOR); + NVC0_BLEND_FACTOR_CASE(INV_CONST_ALPHA, ONE_MINUS_CONSTANT_ALPHA); + NVC0_BLEND_FACTOR_CASE(INV_SRC1_COLOR, ONE_MINUS_SRC1_COLOR); + NVC0_BLEND_FACTOR_CASE(INV_SRC1_ALPHA, ONE_MINUS_SRC1_ALPHA); + default: + return NV50_3D_BLEND_FACTOR_ZERO; + } } static void * @@ -176,9 +172,9 @@ nvc0_rasterizer_state_create(struct pipe_context *pipe, return NULL; so->pipe = *cso; -#ifndef NVC0_SCISSORS_CLIPPING - SB_IMMED_3D(so, SCISSOR_ENABLE(0), cso->scissor); -#endif + /* Scissor enables are handled in scissor state, we will not want to + * always emit 16 commands, one for each scissor rectangle, here. + */ SB_BEGIN_3D(so, SHADE_MODEL, 1); SB_DATA (so, cso->flatshade ? NVC0_3D_SHADE_MODEL_FLAT : @@ -242,7 +238,7 @@ nvc0_rasterizer_state_create(struct pipe_context *pipe, SB_BEGIN_3D(so, POLYGON_OFFSET_FACTOR, 1); SB_DATA (so, fui(cso->offset_scale)); SB_BEGIN_3D(so, POLYGON_OFFSET_UNITS, 1); - SB_DATA (so, fui(cso->offset_units)); /* XXX: multiply by 2 ? */ + SB_DATA (so, fui(cso->offset_units * 2.0f)); } assert(so->size < (sizeof(so->state) / sizeof(so->state[0]))); @@ -283,20 +279,21 @@ nvc0_zsa_state_create(struct pipe_context *pipe, } if (cso->stencil[0].enabled) { - SB_BEGIN_3D(so, STENCIL_FRONT_ENABLE, 5); + SB_BEGIN_3D(so, STENCIL_ENABLE, 5); SB_DATA (so, 1); SB_DATA (so, nvgl_stencil_op(cso->stencil[0].fail_op)); SB_DATA (so, nvgl_stencil_op(cso->stencil[0].zfail_op)); SB_DATA (so, nvgl_stencil_op(cso->stencil[0].zpass_op)); SB_DATA (so, nvgl_comparison_op(cso->stencil[0].func)); - SB_BEGIN_3D(so, STENCIL_FRONT_MASK, 2); - SB_DATA (so, cso->stencil[0].writemask); + SB_BEGIN_3D(so, STENCIL_FRONT_FUNC_MASK, 2); SB_DATA (so, cso->stencil[0].valuemask); + SB_DATA (so, cso->stencil[0].writemask); } else { - SB_IMMED_3D(so, STENCIL_FRONT_ENABLE, 0); + SB_IMMED_3D(so, STENCIL_ENABLE, 0); } if (cso->stencil[1].enabled) { + assert(cso->stencil[0].enabled); SB_BEGIN_3D(so, STENCIL_TWO_SIDE_ENABLE, 5); SB_DATA (so, 1); SB_DATA (so, nvgl_stencil_op(cso->stencil[1].fail_op)); @@ -306,7 +303,8 @@ nvc0_zsa_state_create(struct pipe_context *pipe, SB_BEGIN_3D(so, STENCIL_BACK_MASK, 2); SB_DATA (so, cso->stencil[1].writemask); SB_DATA (so, cso->stencil[1].valuemask); - } else { + } else + if (cso->stencil[0].enabled) { SB_IMMED_3D(so, STENCIL_TWO_SIDE_ENABLE, 0); } @@ -808,6 +806,74 @@ nvc0_vertex_state_bind(struct pipe_context *pipe, void *hwcso) nvc0->dirty |= NVC0_NEW_VERTEX; } +static void * +nvc0_tfb_state_create(struct pipe_context *pipe, + const struct pipe_stream_output_state *pso) +{ + struct nvc0_transform_feedback_state *so; + int n = 0; + int i, c, b; + + so = MALLOC(sizeof(*so) + pso->num_outputs * 4 * sizeof(uint8_t)); + if (!so) + return NULL; + + for (b = 0; b < 4; ++b) { + for (i = 0; i < pso->num_outputs; ++i) { + if (pso->output_buffer[i] != b) + continue; + for (c = 0; c < 4; ++c) { + if (!(pso->register_mask[i] & (1 << c))) + continue; + so->varying_count[b]++; + so->varying_index[n++] = (pso->register_index[i] << 2) | c; + } + } + so->stride[b] = so->varying_count[b] * 4; + } + if (pso->stride) + so->stride[0] = pso->stride; + + return so; +} + +static void +nvc0_tfb_state_delete(struct pipe_context *pipe, void *hwcso) +{ + FREE(hwcso); +} + +static void +nvc0_tfb_state_bind(struct pipe_context *pipe, void *hwcso) +{ + nvc0_context(pipe)->tfb = hwcso; + nvc0_context(pipe)->dirty |= NVC0_NEW_TFB; +} + +static void +nvc0_set_transform_feedback_buffers(struct pipe_context *pipe, + struct pipe_resource **buffers, + int *offsets, + int num_buffers) +{ + struct nvc0_context *nvc0 = nvc0_context(pipe); + int i; + + assert(num_buffers >= 0 && num_buffers <= 4); /* why signed ? */ + + for (i = 0; i < num_buffers; ++i) { + assert(offsets[i] >= 0); + nvc0->tfb_offset[i] = offsets[i]; + pipe_resource_reference(&nvc0->tfbbuf[i], buffers[i]); + } + for (; i < nvc0->num_tfbbufs; ++i) + pipe_resource_reference(&nvc0->tfbbuf[i], NULL); + + nvc0->num_tfbbufs = num_buffers; + + nvc0->dirty |= NVC0_NEW_TFB_BUFFERS; +} + void nvc0_init_state_functions(struct nvc0_context *nvc0) { @@ -861,5 +927,12 @@ nvc0_init_state_functions(struct nvc0_context *nvc0) nvc0->pipe.set_vertex_buffers = nvc0_set_vertex_buffers; nvc0->pipe.set_index_buffer = nvc0_set_index_buffer; + + nvc0->pipe.create_stream_output_state = nvc0_tfb_state_create; + nvc0->pipe.delete_stream_output_state = nvc0_tfb_state_delete; + nvc0->pipe.bind_stream_output_state = nvc0_tfb_state_bind; + nvc0->pipe.set_stream_output_buffers = nvc0_set_transform_feedback_buffers; + + nvc0->pipe.redefine_user_buffer = u_default_redefine_user_buffer; } diff --git a/src/gallium/drivers/nvc0/nvc0_state_validate.c b/src/gallium/drivers/nvc0/nvc0_state_validate.c index 25aec0244db..70c418fad9b 100644 --- a/src/gallium/drivers/nvc0/nvc0_state_validate.c +++ b/src/gallium/drivers/nvc0/nvc0_state_validate.c @@ -25,6 +25,7 @@ nvc0_validate_zcull(struct nvc0_context *nvc0) else width = fb->width; + MARK_RING (chan, 23, 4); BEGIN_RING(chan, RING_3D_(0x1590), 1); /* ZCULL_REGION_INDEX (bits 0x3f) */ OUT_RING (chan, 0); BEGIN_RING(chan, RING_3D_(0x07e8), 2); /* ZCULL_ADDRESS_A_HIGH */ @@ -57,6 +58,7 @@ nvc0_validate_fb(struct nvc0_context *nvc0) struct nouveau_channel *chan = nvc0->screen->base.channel; struct pipe_framebuffer_state *fb = &nvc0->framebuffer; unsigned i; + boolean serialize = FALSE; nvc0_bufctx_reset(nvc0, NVC0_BUFCTX_FRAME); @@ -66,12 +68,14 @@ nvc0_validate_fb(struct nvc0_context *nvc0) OUT_RING (chan, fb->width << 16); OUT_RING (chan, fb->height << 16); + MARK_RING(chan, 9 * fb->nr_cbufs, 2 * fb->nr_cbufs); + for (i = 0; i < fb->nr_cbufs; ++i) { struct nvc0_miptree *mt = nvc0_miptree(fb->cbufs[i]->texture); struct nvc0_surface *sf = nvc0_surface(fb->cbufs[i]); struct nouveau_bo *bo = mt->base.bo; uint32_t offset = sf->offset; - + BEGIN_RING(chan, RING_3D(RT_ADDRESS_HIGH(i)), 8); OUT_RELOCh(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); OUT_RELOCl(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); @@ -83,6 +87,11 @@ nvc0_validate_fb(struct nvc0_context *nvc0) OUT_RING (chan, sf->depth); OUT_RING (chan, mt->layer_stride >> 2); + if (mt->base.status & NVC0_BUFFER_STATUS_GPU_READING) + serialize = TRUE; + mt->base.status |= NVC0_BUFFER_STATUS_GPU_WRITING; + mt->base.status &= ~NVC0_BUFFER_STATUS_GPU_READING; + nvc0_bufctx_add_resident(nvc0, NVC0_BUFCTX_FRAME, &mt->base, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); } @@ -93,7 +102,8 @@ nvc0_validate_fb(struct nvc0_context *nvc0) struct nouveau_bo *bo = mt->base.bo; int unk = mt->base.base.target == PIPE_TEXTURE_2D; uint32_t offset = sf->offset; - + + MARK_RING (chan, 12, 2); BEGIN_RING(chan, RING_3D(ZETA_ADDRESS_HIGH), 5); OUT_RELOCh(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); OUT_RELOCl(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); @@ -107,6 +117,11 @@ nvc0_validate_fb(struct nvc0_context *nvc0) OUT_RING (chan, sf->height); OUT_RING (chan, (unk << 16) | sf->depth); + if (mt->base.status & NVC0_BUFFER_STATUS_GPU_READING) + serialize = TRUE; + mt->base.status |= NVC0_BUFFER_STATUS_GPU_WRITING; + mt->base.status &= ~NVC0_BUFFER_STATUS_GPU_READING; + nvc0_bufctx_add_resident(nvc0, NVC0_BUFCTX_FRAME, &mt->base, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); } else { @@ -114,11 +129,10 @@ nvc0_validate_fb(struct nvc0_context *nvc0) OUT_RING (chan, 0); } -#ifndef NVC0_SCISSORS_CLIPPING - BEGIN_RING(chan, RING_3D(VIEWPORT_HORIZ(0)), 2); - OUT_RING (chan, fb->width << 16); - OUT_RING (chan, fb->height << 16); -#endif + if (serialize) { + BEGIN_RING(chan, RING_3D(SERIALIZE), 1); + OUT_RING (chan, 0); + } } static void @@ -160,65 +174,54 @@ nvc0_validate_scissor(struct nvc0_context *nvc0) { struct nouveau_channel *chan = nvc0->screen->base.channel; struct pipe_scissor_state *s = &nvc0->scissor; -#ifdef NVC0_SCISSORS_CLIPPING - struct pipe_viewport_state *vp = &nvc0->viewport; - int minx, maxx, miny, maxy; - if (!(nvc0->dirty & - (NVC0_NEW_SCISSOR | NVC0_NEW_VIEWPORT | NVC0_NEW_FRAMEBUFFER)) && - nvc0->state.scissor == nvc0->rast->pipe.scissor) + if (!(nvc0->dirty & NVC0_NEW_SCISSOR) && + nvc0->rast->pipe.scissor == nvc0->state.scissor) return; nvc0->state.scissor = nvc0->rast->pipe.scissor; - if (nvc0->state.scissor) { - minx = s->minx; - maxx = s->maxx; - miny = s->miny; - maxy = s->maxy; + BEGIN_RING(chan, RING_3D(SCISSOR_HORIZ(0)), 2); + if (nvc0->rast->pipe.scissor) { + OUT_RING(chan, (s->maxx << 16) | s->minx); + OUT_RING(chan, (s->maxy << 16) | s->miny); } else { - minx = 0; - maxx = nvc0->framebuffer.width; - miny = 0; - maxy = nvc0->framebuffer.height; + OUT_RING(chan, (0xffff << 16) | 0); + OUT_RING(chan, (0xffff << 16) | 0); } - - minx = MAX2(minx, (int)(vp->translate[0] - fabsf(vp->scale[0]))); - maxx = MIN2(maxx, (int)(vp->translate[0] + fabsf(vp->scale[0]))); - miny = MAX2(miny, (int)(vp->translate[1] - fabsf(vp->scale[1]))); - maxy = MIN2(maxy, (int)(vp->translate[1] + fabsf(vp->scale[1]))); - - BEGIN_RING(chan, RING_3D(SCISSOR_HORIZ(0)), 2); - OUT_RING (chan, (maxx << 16) | minx); - OUT_RING (chan, (maxy << 16) | miny); - BEGIN_RING(chan, RING_3D(VIEWPORT_HORIZ(0)), 2); - OUT_RING (chan, ((maxx - minx) << 16) | minx); - OUT_RING (chan, ((maxy - miny) << 16) | miny); -#else - BEGIN_RING(chan, RING_3D(SCISSOR_HORIZ(0)), 2); - OUT_RING (chan, (s->maxx << 16) | s->minx); - OUT_RING (chan, (s->maxy << 16) | s->miny); -#endif } static void nvc0_validate_viewport(struct nvc0_context *nvc0) { struct nouveau_channel *chan = nvc0->screen->base.channel; + struct pipe_viewport_state *vp = &nvc0->viewport; + int x, y, w, h; + float zmin, zmax; BEGIN_RING(chan, RING_3D(VIEWPORT_TRANSLATE_X(0)), 3); - OUT_RINGf (chan, nvc0->viewport.translate[0]); - OUT_RINGf (chan, nvc0->viewport.translate[1]); - OUT_RINGf (chan, nvc0->viewport.translate[2]); + OUT_RINGf (chan, vp->translate[0]); + OUT_RINGf (chan, vp->translate[1]); + OUT_RINGf (chan, vp->translate[2]); BEGIN_RING(chan, RING_3D(VIEWPORT_SCALE_X(0)), 3); - OUT_RINGf (chan, nvc0->viewport.scale[0]); - OUT_RINGf (chan, nvc0->viewport.scale[1]); - OUT_RINGf (chan, nvc0->viewport.scale[2]); + OUT_RINGf (chan, vp->scale[0]); + OUT_RINGf (chan, vp->scale[1]); + OUT_RINGf (chan, vp->scale[2]); -#ifdef NVC0_SCISSORS_CLIPPING + /* now set the viewport rectangle to viewport dimensions for clipping */ + + x = (int)(vp->translate[0] - fabsf(vp->scale[0])); + y = (int)(vp->translate[1] - fabsf(vp->scale[1])); + w = (int)fabsf(2.0f * vp->scale[0]); + h = (int)fabsf(2.0f * vp->scale[1]); + zmin = vp->translate[2] - fabsf(vp->scale[2]); + zmax = vp->translate[2] + fabsf(vp->scale[2]); + + BEGIN_RING(chan, RING_3D(VIEWPORT_HORIZ(0)), 2); + OUT_RING (chan, (w << 16) | x); + OUT_RING (chan, (h << 16) | y); BEGIN_RING(chan, RING_3D(DEPTH_RANGE_NEAR(0)), 2); - OUT_RINGf (chan, nvc0->viewport.translate[2] - nvc0->viewport.scale[2]); - OUT_RINGf (chan, nvc0->viewport.translate[2] + nvc0->viewport.scale[2]); -#endif + OUT_RINGf (chan, zmin); + OUT_RINGf (chan, zmax); } static void @@ -227,10 +230,15 @@ nvc0_validate_clip(struct nvc0_context *nvc0) struct nouveau_channel *chan = nvc0->screen->base.channel; uint32_t clip; - clip = nvc0->clip.depth_clamp ? 0x201a : 0x0002; -#ifndef NVC0_SCISSORS_CLIPPING - clip |= 0x1080; -#endif + if (nvc0->clip.depth_clamp) { + clip = + NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK1_UNK1 | + NVC0_3D_VIEW_VOLUME_CLIP_CTRL_DEPTH_CLAMP_NEAR | + NVC0_3D_VIEW_VOLUME_CLIP_CTRL_DEPTH_CLAMP_FAR | + NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK12_UNK2; + } else { + clip = NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK1_UNK1; + } BEGIN_RING(chan, RING_3D(VIEW_VOLUME_CLIP_CTRL), 1); OUT_RING (chan, clip); @@ -238,6 +246,7 @@ nvc0_validate_clip(struct nvc0_context *nvc0) if (nvc0->clip.nr) { struct nouveau_bo *bo = nvc0->screen->uniforms; + MARK_RING (chan, 6 + nvc0->clip.nr * 4, 2); BEGIN_RING(chan, RING_3D(CB_SIZE), 3); OUT_RING (chan, 256); OUT_RELOCh(chan, bo, 5 << 16, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); @@ -281,6 +290,32 @@ nvc0_validate_rasterizer(struct nvc0_context *nvc0) } static void +nvc0_validate_sprite_coords(struct nvc0_context *nvc0) +{ + struct nouveau_channel *chan = nvc0->screen->base.channel; + uint32_t reg; + + if (nvc0->rast->pipe.sprite_coord_mode == PIPE_SPRITE_COORD_UPPER_LEFT) + reg = NVC0_3D_POINT_COORD_REPLACE_COORD_ORIGIN_UPPER_LEFT; + else + reg = NVC0_3D_POINT_COORD_REPLACE_COORD_ORIGIN_LOWER_LEFT; + + if (nvc0->rast->pipe.point_quad_rasterization) { + uint32_t en = nvc0->rast->pipe.sprite_coord_enable; + + while (en) { + int i = ffs(en) - 1; + en &= ~(1 << i); + if (i >= 0 && i < 8) + reg |= 8 << i; + } + } + + BEGIN_RING(chan, RING_3D(POINT_COORD_REPLACE), 1); + OUT_RING (chan, reg); +} + +static void nvc0_constbufs_validate(struct nvc0_context *nvc0) { struct nouveau_channel *chan = nvc0->screen->base.channel; @@ -340,6 +375,7 @@ nvc0_constbufs_validate(struct nvc0_context *nvc0) NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); if (rebind) { + MARK_RING (chan, 4, 2); BEGIN_RING(chan, RING_3D(CB_SIZE), 3); OUT_RING (chan, align(res->base.width0, 0x100)); OUT_RELOCh(chan, bo, base, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); @@ -357,6 +393,7 @@ nvc0_constbufs_validate(struct nvc0_context *nvc0) } nr = MIN2(MIN2(nr - 6, words), NV04_PFIFO_MAX_PACKET_LEN - 1); + MARK_RING (chan, nr + 5, 2); BEGIN_RING(chan, RING_3D(CB_SIZE), 3); OUT_RING (chan, align(res->base.width0, 0x100)); OUT_RELOCh(chan, bo, base, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); @@ -383,13 +420,7 @@ static struct state_validate { { nvc0_validate_blend_colour, NVC0_NEW_BLEND_COLOUR }, { nvc0_validate_stencil_ref, NVC0_NEW_STENCIL_REF }, { nvc0_validate_stipple, NVC0_NEW_STIPPLE }, -#ifdef NVC0_SCISSORS_CLIPPING - { nvc0_validate_scissor, NVC0_NEW_SCISSOR | NVC0_NEW_VIEWPORT | - NVC0_NEW_RASTERIZER | - NVC0_NEW_FRAMEBUFFER }, -#else - { nvc0_validate_scissor, NVC0_NEW_SCISSOR }, -#endif + { nvc0_validate_scissor, NVC0_NEW_SCISSOR | NVC0_NEW_RASTERIZER }, { nvc0_validate_viewport, NVC0_NEW_VIEWPORT }, { nvc0_validate_clip, NVC0_NEW_CLIP }, { nvc0_vertprog_validate, NVC0_NEW_VERTPROG }, @@ -397,10 +428,12 @@ static struct state_validate { { nvc0_tevlprog_validate, NVC0_NEW_TEVLPROG }, { nvc0_gmtyprog_validate, NVC0_NEW_GMTYPROG }, { nvc0_fragprog_validate, NVC0_NEW_FRAGPROG }, + { nvc0_validate_sprite_coords, NVC0_NEW_RASTERIZER | NVC0_NEW_FRAGPROG }, { nvc0_constbufs_validate, NVC0_NEW_CONSTBUF }, { nvc0_validate_textures, NVC0_NEW_TEXTURES }, { nvc0_validate_samplers, NVC0_NEW_SAMPLERS }, - { nvc0_vertex_arrays_validate, NVC0_NEW_VERTEX | NVC0_NEW_ARRAYS } + { nvc0_vertex_arrays_validate, NVC0_NEW_VERTEX | NVC0_NEW_ARRAYS }, + { nvc0_tfb_validate, NVC0_NEW_TFB | NVC0_NEW_TFB_BUFFERS } }; #define validate_list_len (sizeof(validate_list) / sizeof(validate_list[0])) diff --git a/src/gallium/drivers/nvc0/nvc0_stateobj.h b/src/gallium/drivers/nvc0/nvc0_stateobj.h index 6c8028aba13..57566128ab5 100644 --- a/src/gallium/drivers/nvc0/nvc0_stateobj.h +++ b/src/gallium/drivers/nvc0/nvc0_stateobj.h @@ -4,8 +4,6 @@ #include "pipe/p_state.h" -#define NVC0_SCISSORS_CLIPPING - #define SB_BEGIN_3D(so, m, s) \ (so)->state[(so)->size++] = \ (0x2 << 28) | ((s) << 16) | (NVC0_SUBCH_3D << 13) | ((NVC0_3D_##m) >> 2) @@ -67,16 +65,17 @@ struct nvc0_vertex_stateobj { unsigned num_elements; uint32_t instance_elts; uint32_t instance_bufs; + boolean need_conversion; /* e.g. VFETCH cannot convert f64 to f32 */ unsigned vtx_size; unsigned vtx_per_packet_max; - struct nvc0_vertex_element element[1]; + struct nvc0_vertex_element element[0]; }; /* will have to lookup index -> location qualifier from nvc0_program */ -struct nvc0_tfb_state { - uint8_t varying_count[4]; +struct nvc0_transform_feedback_state { uint32_t stride[4]; - uint8_t varying_indices[1]; + uint8_t varying_count[4]; + uint8_t varying_index[0]; }; #endif diff --git a/src/gallium/drivers/nvc0/nvc0_surface.c b/src/gallium/drivers/nvc0/nvc0_surface.c index cc0a65687dc..8898bc733a3 100644 --- a/src/gallium/drivers/nvc0/nvc0_surface.c +++ b/src/gallium/drivers/nvc0/nvc0_surface.c @@ -33,25 +33,15 @@ #include "nv50_defs.xml.h" +#define NVC0_ENG2D_SUPPORTED_FORMATS 0xff9ccfe1cce3ccc9ULL + /* return TRUE for formats that can be converted among each other by NVC0_2D */ static INLINE boolean nvc0_2d_format_faithful(enum pipe_format format) { - switch (format) { - case PIPE_FORMAT_B8G8R8A8_UNORM: - case PIPE_FORMAT_B8G8R8X8_UNORM: - case PIPE_FORMAT_B8G8R8A8_SRGB: - case PIPE_FORMAT_B8G8R8X8_SRGB: - case PIPE_FORMAT_B5G6R5_UNORM: - case PIPE_FORMAT_B5G5R5A1_UNORM: - case PIPE_FORMAT_B10G10R10A2_UNORM: - case PIPE_FORMAT_R8_UNORM: - case PIPE_FORMAT_R32G32B32A32_FLOAT: - case PIPE_FORMAT_R32G32B32_FLOAT: - return TRUE; - default: - return FALSE; - } + uint8_t id = nvc0_format_table[format].rt; + + return (id >= 0xc0) && (NVC0_ENG2D_SUPPORTED_FORMATS & (1ULL << (id - 0xc0))); } static INLINE uint8_t @@ -62,7 +52,7 @@ nvc0_2d_format(enum pipe_format format) /* Hardware values for color formats range from 0xc0 to 0xff, * but the 2D engine doesn't support all of them. */ - if ((id >= 0xc0) && (0xff0843e080608409ULL & (1ULL << (id - 0xc0)))) + if (nvc0_2d_format_faithful(format)) return id; switch (util_format_get_blocksize(format)) { @@ -72,6 +62,10 @@ nvc0_2d_format(enum pipe_format format) return NV50_SURFACE_FORMAT_R16_UNORM; case 4: return NV50_SURFACE_FORMAT_A8R8G8B8_UNORM; + case 8: + return NV50_SURFACE_FORMAT_R16G16B16A16_UNORM; + case 16: + return NV50_SURFACE_FORMAT_R32G32B32A32_FLOAT; default: return 0; } @@ -249,15 +243,16 @@ nvc0_clear_render_target(struct pipe_context *pipe, OUT_RING (chan, 1); OUT_RING (chan, 0); - /* NOTE: only works with D3D clear flag (5097/0x143c bit 4) */ - - BEGIN_RING(chan, RING_3D(VIEWPORT_HORIZ(0)), 2); - OUT_RING (chan, (width << 16) | dstx); - OUT_RING (chan, (height << 16) | dsty); + BEGIN_RING(chan, RING_3D(CLIP_RECT_HORIZ(0)), 2); + OUT_RING (chan, ((dstx + width) << 16) | dstx); + OUT_RING (chan, ((dsty + height) << 16) | dsty); + IMMED_RING(chan, RING_3D(CLIP_RECTS_EN), 1); BEGIN_RING(chan, RING_3D(CLEAR_BUFFERS), 1); OUT_RING (chan, 0x3c); + IMMED_RING(chan, RING_3D(CLIP_RECTS_EN), 0); + nv50->dirty |= NVC0_NEW_FRAMEBUFFER; } @@ -306,13 +301,16 @@ nvc0_clear_depth_stencil(struct pipe_context *pipe, OUT_RING (chan, sf->height); OUT_RING (chan, (1 << 16) | 1); - BEGIN_RING(chan, RING_3D(VIEWPORT_HORIZ(0)), 2); - OUT_RING (chan, (width << 16) | dstx); - OUT_RING (chan, (height << 16) | dsty); + BEGIN_RING(chan, RING_3D(CLIP_RECT_HORIZ(0)), 2); + OUT_RING (chan, ((dstx + width) << 16) | dstx); + OUT_RING (chan, ((dsty + height) << 16) | dsty); + IMMED_RING(chan, RING_3D(CLIP_RECTS_EN), 1); BEGIN_RING(chan, RING_3D(CLEAR_BUFFERS), 1); OUT_RING (chan, mode); + IMMED_RING(chan, RING_3D(CLIP_RECTS_EN), 0); + nv50->dirty |= NVC0_NEW_FRAMEBUFFER; } diff --git a/src/gallium/drivers/nvc0/nvc0_tex.c b/src/gallium/drivers/nvc0/nvc0_tex.c index b219f82c903..968558a5869 100644 --- a/src/gallium/drivers/nvc0/nvc0_tex.c +++ b/src/gallium/drivers/nvc0/nvc0_tex.c @@ -196,9 +196,16 @@ nvc0_validate_tic(struct nvc0_context *nvc0, int s) OUT_RINGp (chan, &tic->tic[3], 5); need_flush = TRUE; + } else + if (res->status & NVC0_BUFFER_STATUS_GPU_WRITING) { + BEGIN_RING(chan, RING_3D(TEX_CACHE_CTL), 1); + OUT_RING (chan, (tic->id << 4) | 1); } nvc0->screen->tic.lock[tic->id / 32] |= 1 << (tic->id % 32); + res->status &= ~NVC0_BUFFER_STATUS_GPU_WRITING; + res->status |= NVC0_BUFFER_STATUS_GPU_READING; + nvc0_bufctx_add_resident(nvc0, NVC0_BUFCTX_TEXTURES, res, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); diff --git a/src/gallium/drivers/nvc0/nvc0_tgsi_to_nc.c b/src/gallium/drivers/nvc0/nvc0_tgsi_to_nc.c index 950bee2eda4..a44d330c731 100644 --- a/src/gallium/drivers/nvc0/nvc0_tgsi_to_nc.c +++ b/src/gallium/drivers/nvc0/nvc0_tgsi_to_nc.c @@ -63,7 +63,13 @@ bld_register_access(struct bld_register *reg, unsigned i) static INLINE void bld_register_add_val(struct bld_register *reg, struct nv_value *val) { - util_dynarray_append(®->vals, struct nv_value *, val); + struct nv_basic_block *bb = val->insn->bb; + + if (reg->vals.size && + (util_dynarray_top(®->vals, struct nv_value *))->insn->bb == bb) + *(util_dynarray_top_ptr(®->vals, struct nv_value *)) = val; + else + util_dynarray_append(®->vals, struct nv_value *, val); } static INLINE boolean @@ -127,13 +133,10 @@ struct bld_context { static INLINE ubyte bld_register_file(struct bld_context *bld, struct bld_register *reg) { - if (reg < &bld->avs[0][0]) return NV_FILE_GPR; - else - if (reg < &bld->pvs[0][0]) return NV_FILE_GPR; - else - if (reg < &bld->ovs[0][0]) return NV_FILE_PRED; - else - return NV_FILE_MEM_V; + if (reg >= &bld->pvs[0][0] && + reg < &bld->ovs[0][0]) + return NV_FILE_PRED; + return NV_FILE_GPR; } static INLINE struct nv_value * @@ -361,6 +364,9 @@ bld_loop_phi(struct bld_context *bld, struct bld_register *reg, struct nv_basic_block *bb = bld->pc->current_block; struct nv_value *val = NULL; + if (bld->ti->require_stores) /* XXX: actually only for INDEXABLE_TEMP */ + return NULL; + if (bld->loop_lvl > 1) { --bld->loop_lvl; if (!((reg->loop_def | reg->loop_use) & (1 << bld->loop_lvl))) @@ -459,6 +465,7 @@ bld_loop_end(struct bld_context *bld, struct nv_basic_block *bb) reg = (struct bld_register *)phi->target; phi->target = NULL; + /* start with s == 1, src[0] is from outside the loop */ for (s = 1, n = 0; n < bb->num_in; ++n) { if (bb->in_kind[n] != CFG_EDGE_BACK) continue; @@ -470,8 +477,11 @@ bld_loop_end(struct bld_context *bld, struct nv_basic_block *bb) for (i = 0; i < 4; ++i) if (phi->src[i] && phi->src[i]->value == val) break; - if (i == 4) + if (i == 4) { + /* skip values we do not want to replace */ + for (; phi->src[s] && phi->src[s]->value != phi->def[0]; ++s); nv_reference(bld->pc, phi, s++, val); + } } bld->pc->current_block = save; @@ -563,11 +573,12 @@ bld_lmem_store(struct bld_context *bld, struct nv_value *ptr, int ofst, loc = new_value(bld->pc, NV_FILE_MEM_L, nv_type_sizeof(NV_TYPE_U32)); - loc->reg.id = ofst * 4; + loc->reg.address = ofst * 4; nv_reference(bld->pc, insn, 0, loc); - nv_reference(bld->pc, insn, 1, ptr); - nv_reference(bld->pc, insn, 2, val); + nv_reference(bld->pc, insn, 1, val); + if (ptr) + bld_src_pointer(bld, insn, 2, ptr); } static struct nv_value * @@ -579,7 +590,9 @@ bld_lmem_load(struct bld_context *bld, struct nv_value *ptr, int ofst) loc->reg.address = ofst * 4; - val = bld_insn_2(bld, NV_OP_LD, loc, ptr); + val = bld_insn_1(bld, NV_OP_LD, loc); + if (ptr) + bld_src_pointer(bld, val->insn, 1, ptr); return val; } @@ -650,7 +663,7 @@ bld_kil(struct bld_context *bld, struct nv_value *src) static void bld_flow(struct bld_context *bld, uint opcode, - struct nv_value *src, struct nv_basic_block *target, + struct nv_value *pred, uint8_t cc, struct nv_basic_block *target, boolean reconverge) { struct nv_instruction *nvi; @@ -661,8 +674,10 @@ bld_flow(struct bld_context *bld, uint opcode, nvi = new_instruction(bld->pc, opcode); nvi->target = target; nvi->terminator = 1; - if (src) - bld_src_predicate(bld, nvi, 0, src); + if (pred) { + nvi->cc = cc; + bld_src_predicate(bld, nvi, 0, pred); + } } static ubyte @@ -878,11 +893,10 @@ emit_store(struct bld_context *bld, const struct tgsi_full_instruction *inst, break; case TGSI_FILE_TEMPORARY: assert(idx < BLD_MAX_TEMPS); - if (!res->insn) + if (!res->insn || res->insn->bb != bld->pc->current_block) res = bld_insn_1(bld, NV_OP_MOV, res); assert(res->reg.file == NV_FILE_GPR); - assert(res->insn->bb = bld->pc->current_block); if (bld->ti->require_stores) bld_lmem_store(bld, ptr, idx * 4 + chan, res); @@ -979,14 +993,6 @@ bld_new_block(struct bld_context *bld, struct nv_basic_block *b) } static struct nv_value * -bld_get_saved_input(struct bld_context *bld, unsigned i, unsigned c) -{ - if (bld->saved_inputs[i][c]) - return bld->saved_inputs[i][c]; - return NULL; -} - -static struct nv_value * bld_interp(struct bld_context *bld, unsigned mode, struct nv_value *val) { unsigned cent = mode & NVC0_INTERP_CENTROID; @@ -1053,9 +1059,9 @@ emit_fetch(struct bld_context *bld, const struct tgsi_full_instruction *insn, case TGSI_FILE_INPUT: assert(!src->Register.Dimension); if (!ptr) { - res = bld_get_saved_input(bld, idx, swz); + res = bld->saved_inputs[idx][swz]; if (res) - return res; + break; } res = new_value(bld->pc, bld->ti->input_file, 4); if (ptr) @@ -1173,7 +1179,7 @@ static INLINE void describe_texture_target(unsigned target, int *dim, int *array, int *cube, int *shadow) { - *array = *cube = *shadow = 0; + *dim = *array = *cube = *shadow = 0; switch (target) { case TGSI_TEXTURE_1D: @@ -1199,11 +1205,6 @@ describe_texture_target(unsigned target, int *dim, *dim = 2; *cube = 1; break; - /* - case TGSI_TEXTURE_CUBE_ARRAY: - *dim = 2; - *cube = *array = 1; - break; case TGSI_TEXTURE_1D_ARRAY: *dim = *array = 1; break; @@ -1211,6 +1212,7 @@ describe_texture_target(unsigned target, int *dim, *dim = 2; *array = 1; break; + /* case TGSI_TEXTURE_SHADOW1D_ARRAY: *dim = *array = *shadow = 1; break; @@ -1220,7 +1222,7 @@ describe_texture_target(unsigned target, int *dim, break; case TGSI_TEXTURE_CUBE_ARRAY: *dim = 2; - *array = *cube = 1; + *cube = *array = 1; break; */ default: @@ -1338,10 +1340,6 @@ emit_tex(struct bld_context *bld, uint opcode, int tic, int tsc, if (array) arg[dim] = bld_cvt(bld, NV_TYPE_U32, NV_TYPE_F32, arg[dim]); - /* ensure that all inputs reside in a GPR */ - for (c = 0; c < dim + array + cube + shadow; ++c) - (src[c] = bld_insn_1(bld, NV_OP_MOV, arg[c]))->insn->fixed = 1; - /* bind { layer x y z } and { lod/bias shadow } to adjacent regs */ bnd = new_instruction(bld->pc, NV_OP_BIND); @@ -1383,21 +1381,12 @@ emit_tex(struct bld_context *bld, uint opcode, int tic, int tsc, nvi->tex_dim = dim; nvi->tex_cube = cube; nvi->tex_shadow = shadow; + nvi->tex_array = array; nvi->tex_live = 0; return nvi; } -/* -static boolean -bld_is_constant(struct nv_value *val) -{ - if (val->reg.file == NV_FILE_IMM) - return TRUE; - return val->insn && nvCG_find_constant(val->insn->src[0]); -} -*/ - static void bld_tex(struct bld_context *bld, struct nv_value *dst0[4], const struct tgsi_full_instruction *insn) @@ -1413,7 +1402,7 @@ bld_tex(struct bld_context *bld, struct nv_value *dst0[4], assert(dim + array + shadow + lodbias <= 5); - if (!cube && insn->Instruction.Opcode == TGSI_OPCODE_TXP) + if (!cube && !array && insn->Instruction.Opcode == TGSI_OPCODE_TXP) load_proj_tex_coords(bld, t, dim, shadow, insn); else { for (c = 0; c < dim + cube + array; ++c) @@ -1504,10 +1493,10 @@ bld_instruction(struct bld_context *bld, case TGSI_OPCODE_CMP: FOR_EACH_DST0_ENABLED_CHANNEL(c, insn) { src0 = emit_fetch(bld, insn, 0, c); - src0 = bld_setp(bld, NV_OP_SET_F32, NV_CC_LT, src0, bld->zero); src1 = emit_fetch(bld, insn, 1, c); src2 = emit_fetch(bld, insn, 2, c); - dst0[c] = bld_insn_3(bld, NV_OP_SELP, src1, src2, src0); + dst0[c] = bld_insn_3(bld, NV_OP_SLCT_F32, src1, src2, src0); + dst0[c]->insn->set_cond = NV_CC_LT; } break; case TGSI_OPCODE_COS: @@ -1601,6 +1590,7 @@ bld_instruction(struct bld_context *bld, case TGSI_OPCODE_IF: { struct nv_basic_block *b = new_basic_block(bld->pc); + struct nv_value *pred = emit_fetch(bld, insn, 0, 0); assert(bld->cond_lvl < BLD_MAX_COND_NESTING); @@ -1609,10 +1599,19 @@ bld_instruction(struct bld_context *bld, bld->join_bb[bld->cond_lvl] = bld->pc->current_block; bld->cond_bb[bld->cond_lvl] = bld->pc->current_block; - src1 = bld_setp(bld, NV_OP_SET_U32, NV_CC_EQ, - emit_fetch(bld, insn, 0, 0), bld->zero); + if (pred->insn && NV_BASEOP(pred->insn->opcode) == NV_OP_SET) { + pred = bld_clone(bld, pred->insn); + pred->reg.size = 1; + pred->reg.file = NV_FILE_PRED; + if (pred->insn->opcode == NV_OP_FSET_F32) + pred->insn->opcode = NV_OP_SET_F32; + } else { + pred = bld_setp(bld, NV_OP_SET_U32, NV_CC_NE | NV_CC_U, + pred, bld->zero); + } + assert(!mask); - bld_flow(bld, NV_OP_BRA, src1, NULL, (bld->cond_lvl == 0)); + bld_flow(bld, NV_OP_BRA, pred, NV_CC_NOT_P, NULL, (bld->cond_lvl == 0)); ++bld->cond_lvl; bld_new_block(bld, b); @@ -1638,6 +1637,10 @@ bld_instruction(struct bld_context *bld, { struct nv_basic_block *b = new_basic_block(bld->pc); + if (bld->pc->current_block->exit && + !bld->pc->current_block->exit->terminator) + bld_flow(bld, NV_OP_BRA, NULL, NV_CC_P, b, FALSE); + --bld->cond_lvl; nvc0_bblock_attach(bld->pc->current_block, b, bld->out_kind); nvc0_bblock_attach(bld->cond_bb[bld->cond_lvl], b, CFG_EDGE_FORWARD); @@ -1678,7 +1681,7 @@ bld_instruction(struct bld_context *bld, { struct nv_basic_block *bb = bld->brkt_bb[bld->loop_lvl - 1]; - bld_flow(bld, NV_OP_BRA, NULL, bb, FALSE); + bld_flow(bld, NV_OP_BRA, NULL, NV_CC_P, bb, FALSE); if (bld->out_kind == CFG_EDGE_FORWARD) /* else we already had BRK/CONT */ nvc0_bblock_attach(bld->pc->current_block, bb, CFG_EDGE_LOOP_LEAVE); @@ -1690,7 +1693,7 @@ bld_instruction(struct bld_context *bld, { struct nv_basic_block *bb = bld->loop_bb[bld->loop_lvl - 1]; - bld_flow(bld, NV_OP_BRA, NULL, bb, FALSE); + bld_flow(bld, NV_OP_BRA, NULL, NV_CC_P, bb, FALSE); nvc0_bblock_attach(bld->pc->current_block, bb, CFG_EDGE_BACK); @@ -1705,9 +1708,11 @@ bld_instruction(struct bld_context *bld, { struct nv_basic_block *bb = bld->loop_bb[bld->loop_lvl - 1]; - bld_flow(bld, NV_OP_BRA, NULL, bb, FALSE); + if (bld->out_kind != CFG_EDGE_FAKE) { /* else we already had BRK/CONT */ + bld_flow(bld, NV_OP_BRA, NULL, NV_CC_P, bb, FALSE); - nvc0_bblock_attach(bld->pc->current_block, bb, CFG_EDGE_BACK); + nvc0_bblock_attach(bld->pc->current_block, bb, CFG_EDGE_BACK); + } bld_loop_end(bld, bb); /* replace loop-side operand of the phis */ @@ -1824,11 +1829,11 @@ bld_instruction(struct bld_context *bld, case TGSI_OPCODE_SSG: FOR_EACH_DST0_ENABLED_CHANNEL(c, insn) { /* XXX: set lt, set gt, sub */ src0 = emit_fetch(bld, insn, 0, c); - src1 = bld_setp(bld, NV_OP_SET_F32, NV_CC_EQ, src0, bld->zero); - temp = bld_insn_2(bld, NV_OP_AND, src0, bld_imm_u32(bld, 0x80000000)); - temp = bld_insn_2(bld, NV_OP_OR, temp, bld_imm_f32(bld, 1.0f)); - dst0[c] = bld_insn_1(bld, NV_OP_MOV, temp); - bld_src_predicate(bld, dst0[c]->insn, 1, src1); + src1 = bld_insn_2(bld, NV_OP_FSET_F32, src0, bld->zero); + src2 = bld_insn_2(bld, NV_OP_FSET_F32, src0, bld->zero); + src1->insn->set_cond = NV_CC_GT; + src2->insn->set_cond = NV_CC_LT; + dst0[c] = bld_insn_2(bld, NV_OP_SUB_F32, src1, src2); } break; case TGSI_OPCODE_SUB: @@ -1892,10 +1897,10 @@ bld_instruction(struct bld_context *bld, } for (c = 0; c < 4; ++c) - if ((mask & (1 << c)) && - ((dst0[c]->reg.file == NV_FILE_IMM) || - (dst0[c]->reg.id == 63 && dst0[c]->reg.file == NV_FILE_GPR))) - dst0[c] = bld_insn_1(bld, NV_OP_MOV, dst0[c]); + if (mask & (1 << c)) + if ((dst0[c]->reg.file == NV_FILE_IMM) || + (dst0[c]->reg.file == NV_FILE_GPR && dst0[c]->reg.id == 63)) + dst0[c] = bld_insn_1(bld, NV_OP_MOV, dst0[c]); c = 0; if ((mask & 0x3) == 0x3) { diff --git a/src/gallium/drivers/nvc0/nvc0_transfer.c b/src/gallium/drivers/nvc0/nvc0_transfer.c index 286b382f58e..b279bdc6e7d 100644 --- a/src/gallium/drivers/nvc0/nvc0_transfer.c +++ b/src/gallium/drivers/nvc0/nvc0_transfer.c @@ -10,7 +10,8 @@ struct nvc0_transfer { struct pipe_transfer base; struct nvc0_m2mf_rect rect[2]; uint32_t nblocksx; - uint32_t nblocksy; + uint16_t nblocksy; + uint16_t nlayers; }; static void @@ -242,23 +243,36 @@ nvc0_miptree_transfer_new(struct pipe_context *pctx, struct nvc0_miptree_level *lvl = &mt->level[level]; struct nvc0_transfer *tx; uint32_t size; - uint32_t w, h, d, z, layer; + uint32_t w, h, d, z, layer, box_h, box_y; int ret; + tx = CALLOC_STRUCT(nvc0_transfer); + if (!tx) + return NULL; + + box_y = box->y; + box_h = box->height; + if (mt->layout_3d) { z = box->z; d = u_minify(res->depth0, level); layer = 0; + tx->nlayers = box->depth; } else { z = 0; d = 1; - layer = box->z; + if (res->target == PIPE_TEXTURE_1D || + res->target == PIPE_TEXTURE_1D_ARRAY) { + box_y = 0; + box_h = 1; + layer = box->y; + tx->nlayers = box->height; + } else { + layer = box->z; + tx->nlayers = box->depth; + } } - tx = CALLOC_STRUCT(nvc0_transfer); - if (!tx) - return NULL; - pipe_resource_reference(&tx->base.resource, res); tx->base.level = level; @@ -266,7 +280,7 @@ nvc0_miptree_transfer_new(struct pipe_context *pctx, tx->base.box = *box; tx->nblocksx = util_format_get_nblocksx(res->format, box->width); - tx->nblocksy = util_format_get_nblocksy(res->format, box->height); + tx->nblocksy = util_format_get_nblocksy(res->format, box_h); tx->base.stride = tx->nblocksx * util_format_get_blocksize(res->format); tx->base.layer_stride = tx->nblocksy * tx->base.stride; @@ -280,7 +294,7 @@ nvc0_miptree_transfer_new(struct pipe_context *pctx, tx->rect[0].base = lvl->offset + layer * mt->layer_stride; tx->rect[0].tile_mode = lvl->tile_mode; tx->rect[0].x = util_format_get_nblocksx(res->format, box->x); - tx->rect[0].y = util_format_get_nblocksy(res->format, box->y); + tx->rect[0].y = util_format_get_nblocksy(res->format, box_y); tx->rect[0].z = z; tx->rect[0].width = util_format_get_nblocksx(res->format, w); tx->rect[0].height = util_format_get_nblocksy(res->format, h); @@ -291,7 +305,7 @@ nvc0_miptree_transfer_new(struct pipe_context *pctx, size = tx->base.layer_stride; ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0, - size * tx->base.box.depth, &tx->rect[1].bo); + size * tx->nlayers, &tx->rect[1].bo); if (ret) { FREE(tx); return NULL; @@ -304,8 +318,9 @@ nvc0_miptree_transfer_new(struct pipe_context *pctx, tx->rect[1].domain = NOUVEAU_BO_GART; if (usage & PIPE_TRANSFER_READ) { + unsigned base = tx->rect[0].base; unsigned i; - for (i = 0; i < box->depth; ++i) { + for (i = 0; i < tx->nlayers; ++i) { nvc0_m2mf_transfer_rect(pscreen, &tx->rect[1], &tx->rect[0], tx->nblocksx, tx->nblocksy); if (mt->layout_3d) @@ -314,9 +329,10 @@ nvc0_miptree_transfer_new(struct pipe_context *pctx, tx->rect[0].base += mt->layer_stride; tx->rect[1].base += size; } + tx->rect[0].z = z; + tx->rect[0].base = base; + tx->rect[1].base = 0; } - tx->rect[0].z = z; - tx->rect[1].base = 0; return &tx->base; } @@ -331,7 +347,7 @@ nvc0_miptree_transfer_del(struct pipe_context *pctx, unsigned i; if (tx->base.usage & PIPE_TRANSFER_WRITE) { - for (i = 0; i < tx->base.box.depth; ++i) { + for (i = 0; i < tx->nlayers; ++i) { nvc0_m2mf_transfer_rect(pscreen, &tx->rect[0], &tx->rect[1], tx->nblocksx, tx->nblocksy); if (mt->layout_3d) diff --git a/src/gallium/drivers/nvc0/nvc0_vbo.c b/src/gallium/drivers/nvc0/nvc0_vbo.c index a51a887ed89..2db43d8704b 100644 --- a/src/gallium/drivers/nvc0/nvc0_vbo.c +++ b/src/gallium/drivers/nvc0/nvc0_vbo.c @@ -54,12 +54,13 @@ nvc0_vertex_state_create(struct pipe_context *pipe, assert(num_elements); so = MALLOC(sizeof(*so) + - (num_elements - 1) * sizeof(struct nvc0_vertex_element)); + num_elements * sizeof(struct nvc0_vertex_element)); if (!so) return NULL; so->num_elements = num_elements; so->instance_elts = 0; so->instance_bufs = 0; + so->need_conversion = FALSE; transkey.nr_elements = 0; transkey.output_stride = 0; @@ -83,6 +84,7 @@ nvc0_vertex_state_create(struct pipe_context *pipe, return NULL; } so->element[i].state = nvc0_format_table[fmt].vtx; + so->need_conversion = TRUE; } so->element[i].state |= i; @@ -152,7 +154,7 @@ nvc0_vbuf_range(struct nvc0_context *nvc0, int vbi, if (unlikely(nvc0->vertex->instance_bufs & (1 << vbi))) { /* TODO: use min and max instance divisor to get a proper range */ *base = 0; - *size = (nvc0->vtxbuf[vbi].max_index + 1) * nvc0->vtxbuf[vbi].stride; + *size = nvc0->vtxbuf[vbi].buffer->width0; } else { assert(nvc0->vbo_max_index != ~0); *base = nvc0->vbo_min_index * nvc0->vtxbuf[vbi].stride; @@ -171,12 +173,15 @@ nvc0_prevalidate_vbufs(struct nvc0_context *nvc0) nvc0->vbo_fifo = nvc0->vbo_user = 0; + nvc0_bufctx_reset(nvc0, NVC0_BUFCTX_VERTEX); + for (i = 0; i < nvc0->num_vtxbufs; ++i) { vb = &nvc0->vtxbuf[i]; if (!vb->stride) continue; buf = nvc0_resource(vb->buffer); + /* NOTE: user buffers with temporary storage count as mapped by GPU */ if (!nvc0_resource_mapped_by_gpu(vb->buffer)) { if (nvc0->vbo_push_hint) { nvc0->vbo_fifo = ~0; @@ -227,16 +232,30 @@ nvc0_update_user_vbufs(struct nvc0_context *nvc0) } offset = vb->buffer_offset + ve->src_offset; + MARK_RING (chan, 6, 4); BEGIN_RING_1I(chan, RING_3D(VERTEX_ARRAY_SELECT), 5); OUT_RING (chan, i); - OUT_RESRCh(chan, buf, size - 1, NOUVEAU_BO_RD); - OUT_RESRCl(chan, buf, size - 1, NOUVEAU_BO_RD); + OUT_RESRCh(chan, buf, base + size - 1, NOUVEAU_BO_RD); + OUT_RESRCl(chan, buf, base + size - 1, NOUVEAU_BO_RD); OUT_RESRCh(chan, buf, offset, NOUVEAU_BO_RD); OUT_RESRCl(chan, buf, offset, NOUVEAU_BO_RD); } nvc0->vbo_dirty = TRUE; } +static INLINE void +nvc0_release_user_vbufs(struct nvc0_context *nvc0) +{ + uint32_t vbo_user = nvc0->vbo_user; + + while (vbo_user) { + int i = ffs(vbo_user) - 1; + vbo_user &= ~(1 << i); + + nvc0_buffer_release_gpu_storage(nvc0_resource(nvc0->vtxbuf[i].buffer)); + } +} + void nvc0_vertex_arrays_validate(struct nvc0_context *nvc0) { @@ -246,7 +265,12 @@ nvc0_vertex_arrays_validate(struct nvc0_context *nvc0) struct nvc0_vertex_element *ve; unsigned i; - nvc0_prevalidate_vbufs(nvc0); + if (unlikely(vertex->need_conversion)) { + nvc0->vbo_fifo = ~0; + nvc0->vbo_user = 0; + } else { + nvc0_prevalidate_vbufs(nvc0); + } BEGIN_RING(chan, RING_3D(VERTEX_ATTRIB_FORMAT(0)), vertex->num_elements); for (i = 0; i < vertex->num_elements; ++i) { @@ -292,6 +316,7 @@ nvc0_vertex_arrays_validate(struct nvc0_context *nvc0) size = vb->buffer->width0; offset = ve->pipe.src_offset + vb->buffer_offset; + MARK_RING (chan, 8, 4); BEGIN_RING(chan, RING_3D(VERTEX_ARRAY_FETCH(i)), 1); OUT_RING (chan, (1 << 12) | vb->stride); BEGIN_RING_1I(chan, RING_3D(VERTEX_ARRAY_SELECT), 5); @@ -346,57 +371,10 @@ nvc0_draw_vbo_flush_notify(struct nouveau_channel *chan) { struct nvc0_context *nvc0 = chan->user_private; - nvc0_bufctx_emit_relocs(nvc0); -} + nvc0_screen_fence_update(nvc0->screen, TRUE); -#if 0 -static struct nouveau_bo * -nvc0_tfb_setup(struct nvc0_context *nvc0) -{ - struct nouveau_channel *chan = nvc0->screen->base.channel; - struct nouveau_bo *tfb = NULL; - int ret, i; - - ret = nouveau_bo_new(nvc0->screen->base.device, - NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0, 4096, &tfb); - if (ret) - return NULL; - - ret = nouveau_bo_map(tfb, NOUVEAU_BO_WR); - if (ret) - return NULL; - memset(tfb->map, 0xee, 8 * 4 * 3); - nouveau_bo_unmap(tfb); - - BEGIN_RING(chan, RING_3D(TFB_ENABLE), 1); - OUT_RING (chan, 1); - BEGIN_RING(chan, RING_3D(TFB_BUFFER_ENABLE(0)), 5); - OUT_RING (chan, 1); - OUT_RELOCh(chan, tfb, 0, NOUVEAU_BO_GART | NOUVEAU_BO_WR); - OUT_RELOCl(chan, tfb, 0, NOUVEAU_BO_GART | NOUVEAU_BO_WR); - OUT_RING (chan, tfb->size); - OUT_RING (chan, 0); /* TFB_PRIMITIVE_ID(0) */ - BEGIN_RING(chan, RING_3D(TFB_UNK0700(0)), 3); - OUT_RING (chan, 0); - OUT_RING (chan, 8); /* TFB_VARYING_COUNT(0) */ - OUT_RING (chan, 32); /* TFB_BUFFER_STRIDE(0) */ - BEGIN_RING(chan, RING_3D(TFB_VARYING_LOCS(0)), 2); - OUT_RING (chan, 0x1f1e1d1c); - OUT_RING (chan, 0xa3a2a1a0); - for (i = 1; i < 4; ++i) { - BEGIN_RING(chan, RING_3D(TFB_BUFFER_ENABLE(i)), 1); - OUT_RING (chan, 0); - } - BEGIN_RING(chan, RING_3D(TFB_ENABLE), 1); - OUT_RING (chan, 1); - BEGIN_RING(chan, RING_3D_(0x135c), 1); - OUT_RING (chan, 1); - BEGIN_RING(chan, RING_3D_(0x135c), 1); - OUT_RING (chan, 0); - - return tfb; + nvc0_bufctx_emit_relocs(nvc0); } -#endif static void nvc0_draw_arrays(struct nvc0_context *nvc0, @@ -422,7 +400,7 @@ nvc0_draw_arrays(struct nvc0_context *nvc0, prim |= NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT; } - chan->flush_notify = NULL; + chan->flush_notify = nvc0_default_flush_notify; } static void @@ -592,7 +570,7 @@ nvc0_draw_elements(struct nvc0_context *nvc0, boolean shorten, } } - chan->flush_notify = NULL; + chan->flush_notify = nvc0_default_flush_notify; } void @@ -611,6 +589,9 @@ nvc0_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info) nvc0->vbo_min_index = info->min_index; nvc0->vbo_max_index = info->max_index; + if (nvc0->vbo_push_hint != !!nvc0->vbo_fifo) + nvc0->dirty |= NVC0_NEW_ARRAYS; + if (nvc0->vbo_user && !(nvc0->dirty & (NVC0_NEW_VERTEX | NVC0_NEW_ARRAYS))) nvc0_update_user_vbufs(nvc0); @@ -668,4 +649,6 @@ nvc0_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info) info->mode, info->start, info->count, info->instance_count, info->index_bias); } + + nvc0_release_user_vbufs(nvc0); } diff --git a/src/gallium/drivers/nvc0/nvc0_winsys.h b/src/gallium/drivers/nvc0/nvc0_winsys.h index 1544fb7a1de..45f71967eff 100644 --- a/src/gallium/drivers/nvc0/nvc0_winsys.h +++ b/src/gallium/drivers/nvc0/nvc0_winsys.h @@ -95,7 +95,7 @@ OUT_RESRCl(struct nouveau_channel *chan, struct nvc0_resource *res, unsigned delta, unsigned flags) { if (flags & NOUVEAU_BO_WR) - res->status |= NVC0_BUFFER_STATUS_DIRTY; + res->status |= NVC0_BUFFER_STATUS_GPU_WRITING; return OUT_RELOCl(chan, res->bo, res->offset + delta, res->domain | flags); } diff --git a/src/gallium/drivers/nvfx/nvfx_vbo.c b/src/gallium/drivers/nvfx/nvfx_vbo.c index 01dacb43dad..b72379d6536 100644 --- a/src/gallium/drivers/nvfx/nvfx_vbo.c +++ b/src/gallium/drivers/nvfx/nvfx_vbo.c @@ -2,6 +2,7 @@ #include "pipe/p_state.h" #include "util/u_inlines.h" #include "util/u_format.h" +#include "util/u_transfer.h" #include "translate/translate.h" #include "nvfx_context.h" @@ -631,4 +632,6 @@ nvfx_init_vbo_functions(struct nvfx_context *nvfx) nvfx->pipe.create_vertex_elements_state = nvfx_vtxelts_state_create; nvfx->pipe.delete_vertex_elements_state = nvfx_vtxelts_state_delete; nvfx->pipe.bind_vertex_elements_state = nvfx_vtxelts_state_bind; + + nvfx->pipe.redefine_user_buffer = u_default_redefine_user_buffer; } diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c index a43e83c0d36..4f86db39926 100644 --- a/src/gallium/drivers/r300/r300_blit.c +++ b/src/gallium/drivers/r300/r300_blit.c @@ -55,11 +55,12 @@ static void r300_blitter_begin(struct r300_context* r300, enum r300_blitter_op o util_blitter_save_viewport(r300->blitter, &r300->viewport); util_blitter_save_clip(r300->blitter, (struct pipe_clip_state*)r300->clip_state.state); util_blitter_save_vertex_elements(r300->blitter, r300->velems); - util_blitter_save_vertex_buffers(r300->blitter, r300->vertex_buffer_count, - r300->vertex_buffer); + util_blitter_save_vertex_buffers(r300->blitter, r300->vbuf_mgr->nr_vertex_buffers, + r300->vbuf_mgr->vertex_buffer); - if (op & (R300_CLEAR_SURFACE | R300_COPY)) + if (op & (R300_CLEAR_SURFACE | R300_COPY)) { util_blitter_save_framebuffer(r300->blitter, r300->fb_state.state); + } if (op & R300_COPY) { struct r300_textures_state* state = @@ -108,6 +109,14 @@ static boolean r300_cbzb_clear_allowed(struct r300_context *r300, return r300_surface(fb->cbufs[0])->cbzb_allowed; } +static boolean r300_fast_zclear_allowed(struct r300_context *r300) +{ + struct pipe_framebuffer_state *fb = + (struct pipe_framebuffer_state*)r300->fb_state.state; + + return r300_resource(fb->zsbuf->texture)->tex.zmask_dwords[fb->zsbuf->u.tex.level]; +} + static uint32_t r300_depth_clear_value(enum pipe_format format, double depth, unsigned stencil) { @@ -132,37 +141,46 @@ static void r300_clear(struct pipe_context* pipe, double depth, unsigned stencil) { - /* My notes about fastfill: + /* My notes about Zbuffer compression: * - * 1) Only the zbuffer is cleared. + * 1) The zbuffer must be micro-tiled and whole microtiles must be + * written if compression is enabled. If microtiling is disabled, + * it locks up. * - * 2) The zbuffer must be micro-tiled and whole microtiles must be - * written. If microtiling is disabled, it locks up. + * 2) There is ZMASK RAM which contains a compressed zbuffer. + * Each dword of the Z Mask contains compression information + * for 16 4x4 pixel tiles, that is 2 bits for each tile. + * On chips with 2 Z pipes, every other dword maps to a different + * pipe. On newer chipsets, there is a new compression mode + * with 8x8 pixel tiles per 2 bits. * - * 3) There is Z Mask RAM which contains a compressed zbuffer and - * it interacts with fastfill. We should figure out how to use it - * to get more performance. - * This is what we know about the Z Mask: + * 3) The FASTFILL bit has nothing to do with filling. It only tells hw + * it should look in the ZMASK RAM first before fetching from a real + * zbuffer. * - * Each dword of the Z Mask contains compression information - * for 16 4x4 pixel blocks, that is 2 bits for each block. - * On chips with 2 Z pipes, every other dword maps to a different - * pipe. + * 4) If a pixel is in a cleared state, ZB_DEPTHCLEARVALUE is returned + * during zbuffer reads instead of the value that is actually stored + * in the zbuffer memory. A pixel is in a cleared state when its ZMASK + * is equal to 0. Therefore, if you clear ZMASK with zeros, you may + * leave the zbuffer memory uninitialized, but then you must enable + * compression, so that the ZMASK RAM is actually used. * - * 4) ZB_DEPTHCLEARVALUE is used to clear the zbuffer and the Z Mask must - * be equal to 0. (clear the Z Mask RAM with zeros) + * 5) Each 4x4 (or 8x8) tile is automatically decompressed and recompressed + * during zbuffer updates. A special decompressing operation should be + * used to fully decompress a zbuffer, which basically just stores all + * compressed tiles in ZMASK to the zbuffer memory. * - * 5) For 16-bit zbuffer, compression causes a hung with one or + * 6) For a 16-bit zbuffer, compression causes a hung with one or * two samples and should not be used. * - * 6) FORCE_COMPRESSED_STENCIL_VALUE should be enabled for stencil clears + * 7) FORCE_COMPRESSED_STENCIL_VALUE should be enabled for stencil clears * to avoid needless decompression. * - * 7) Fastfill must not be used if reading of compressed Z data is disabled + * 8) Fastfill must not be used if reading of compressed Z data is disabled * and writing of compressed Z data is enabled (RD/WR_COMP_ENABLE), * i.e. it cannot be used to compress the zbuffer. * - * 8) ZB_CB_CLEAR does not interact with fastfill in any way. + * 9) ZB_CB_CLEAR does not interact with zbuffer compression in any way. * * - Marek */ @@ -172,32 +190,30 @@ static void r300_clear(struct pipe_context* pipe, (struct pipe_framebuffer_state*)r300->fb_state.state; struct r300_hyperz_state *hyperz = (struct r300_hyperz_state*)r300->hyperz_state.state; - struct r300_texture *zstex = - fb->zsbuf ? r300_texture(fb->zsbuf->texture) : NULL; + struct r300_resource *zstex = + fb->zsbuf ? r300_resource(fb->zsbuf->texture) : NULL; uint32_t width = fb->width; uint32_t height = fb->height; boolean can_hyperz = r300->rws->get_value(r300->rws, R300_CAN_HYPERZ); uint32_t hyperz_dcv = hyperz->zb_depthclearvalue; - /* Decompress zbuffers that are bound as textures. If we didn't flush here, - * it would happen inside the blitter when updating derived state, - * causing a blitter operation to be called from inside the blitter, - * which would overwrite saved states and they would never get restored. */ - r300_flush_depth_textures(r300); - /* Enable fast Z clear. * The zbuffer must be in micro-tiled mode, otherwise it locks up. */ if ((buffers & PIPE_CLEAR_DEPTHSTENCIL) && can_hyperz) { hyperz_dcv = hyperz->zb_depthclearvalue = r300_depth_clear_value(fb->zsbuf->format, depth, stencil); - r300_mark_fb_state_dirty(r300, R300_CHANGED_ZCLEAR_FLAG); - if (zstex->zmask_mem[fb->zsbuf->u.tex.level]) { + if (r300_fast_zclear_allowed(r300)) { r300_mark_atom_dirty(r300, &r300->zmask_clear); buffers &= ~PIPE_CLEAR_DEPTHSTENCIL; } + if (zstex->hiz_mem[fb->zsbuf->u.tex.level]) r300_mark_atom_dirty(r300, &r300->hiz_clear); + + /* XXX Change this to r300_mark_atom_dirty(r300, &r300->hyperz_state); + * once hiz offset is constant. */ + r300_mark_fb_state_dirty(r300, R300_CHANGED_HYPERZ_FLAG); } /* Enable CBZB clear. */ @@ -211,7 +227,7 @@ static void r300_clear(struct pipe_context* pipe, height = surf->cbzb_height; r300->cbzb_clear = TRUE; - r300_mark_fb_state_dirty(r300, R300_CHANGED_CBZB_FLAG); + r300_mark_fb_state_dirty(r300, R300_CHANGED_HYPERZ_FLAG); } /* Clear. */ @@ -225,7 +241,7 @@ static void r300_clear(struct pipe_context* pipe, buffers, rgba, depth, stencil); r300_blitter_end(r300); } else if (r300->zmask_clear.dirty) { - /* Just clear zmask and hiz now, this does not use a standard draw + /* Just clear zmask and hiz now, this does not use the standard draw * procedure. */ unsigned dwords; @@ -257,16 +273,15 @@ static void r300_clear(struct pipe_context* pipe, if (r300->cbzb_clear) { r300->cbzb_clear = FALSE; hyperz->zb_depthclearvalue = hyperz_dcv; - r300_mark_fb_state_dirty(r300, R300_CHANGED_CBZB_FLAG); + r300_mark_fb_state_dirty(r300, R300_CHANGED_HYPERZ_FLAG); } /* Enable fastfill and/or hiz. * * If we cleared zmask/hiz, it's in use now. The Hyper-Z state update * looks if zmask/hiz is in use and enables fastfill accordingly. */ - if (zstex && - (zstex->zmask_in_use[fb->zsbuf->u.tex.level] || - zstex->hiz_in_use[fb->zsbuf->u.tex.level])) { + if (r300->zmask_in_use || + (zstex && zstex->hiz_in_use[fb->zsbuf->u.tex.level])) { r300_mark_atom_dirty(r300, &r300->hyperz_state); } } @@ -280,16 +295,16 @@ static void r300_clear_render_target(struct pipe_context *pipe, { struct r300_context *r300 = r300_context(pipe); - /* Decompress zbuffers that are bound as textures. If we didn't flush here, - * it would happen inside the blitter when updating derived state, - * causing a blitter operation to be called from inside the blitter, - * which would overwrite saved states and they would never get restored. */ - r300_flush_depth_textures(r300); + r300->zmask_locked = TRUE; + r300_mark_atom_dirty(r300, &r300->hyperz_state); r300_blitter_begin(r300, R300_CLEAR_SURFACE); util_blitter_clear_render_target(r300->blitter, dst, rgba, dstx, dsty, width, height); r300_blitter_end(r300); + + r300->zmask_locked = FALSE; + r300_mark_atom_dirty(r300, &r300->hyperz_state); } /* Clear a region of a depth stencil surface. */ @@ -302,83 +317,70 @@ static void r300_clear_depth_stencil(struct pipe_context *pipe, unsigned width, unsigned height) { struct r300_context *r300 = r300_context(pipe); + struct pipe_framebuffer_state *fb = + (struct pipe_framebuffer_state*)r300->fb_state.state; - /* Decompress zbuffers that are bound as textures. If we didn't flush here, - * it would happen inside the blitter when updating derived state, - * causing a blitter operation to be called from inside the blitter, - * which would overwrite saved states and they would never get restored. */ - r300_flush_depth_textures(r300); + if (r300->zmask_in_use && !r300->zmask_locked) { + if (fb->zsbuf->texture == dst->texture) { + r300_decompress_zmask(r300); + } else { + r300->zmask_locked = TRUE; + r300_mark_atom_dirty(r300, &r300->hyperz_state); + } + } r300_blitter_begin(r300, R300_CLEAR_SURFACE); util_blitter_clear_depth_stencil(r300->blitter, dst, clear_flags, depth, stencil, dstx, dsty, width, height); r300_blitter_end(r300); + + if (r300->zmask_locked) { + r300->zmask_locked = FALSE; + r300_mark_atom_dirty(r300, &r300->hyperz_state); + } } -/* Flush a depth stencil buffer. */ -static void r300_flush_depth_stencil(struct pipe_context *pipe, - struct pipe_resource *dst, - unsigned level, - unsigned layer) +void r300_decompress_zmask(struct r300_context *r300) { - struct r300_context *r300 = r300_context(pipe); - struct pipe_surface *dstsurf, surf_tmpl; - struct r300_texture *tex = r300_texture(dst); + struct pipe_framebuffer_state *fb = + (struct pipe_framebuffer_state*)r300->fb_state.state; - if (!tex->zmask_mem[level]) - return; - if (!tex->zmask_in_use[level]) + if (!r300->zmask_in_use || r300->zmask_locked) return; - surf_tmpl.format = dst->format; - surf_tmpl.usage = PIPE_BIND_DEPTH_STENCIL; - surf_tmpl.u.tex.level = level; - surf_tmpl.u.tex.first_layer = layer; - surf_tmpl.u.tex.last_layer = layer; - dstsurf = pipe->create_surface(pipe, dst, &surf_tmpl); + r300->zmask_decompress = TRUE; + r300_mark_atom_dirty(r300, &r300->hyperz_state); - r300->z_decomp_rd = TRUE; - - r300_blitter_begin(r300, R300_CLEAR_SURFACE); - util_blitter_flush_depth_stencil(r300->blitter, dstsurf); + r300_blitter_begin(r300, R300_CLEAR); + util_blitter_clear_depth_custom(r300->blitter, fb->width, fb->height, 0, + r300->dsa_decompress_zmask); r300_blitter_end(r300); - r300->z_decomp_rd = FALSE; - tex->zmask_in_use[level] = FALSE; - pipe_surface_reference(&dstsurf, NULL); + r300->zmask_decompress = FALSE; + r300->zmask_in_use = FALSE; + r300_mark_atom_dirty(r300, &r300->hyperz_state); } -/* We can't use compressed zbuffers as samplers. */ -void r300_flush_depth_textures(struct r300_context *r300) +void r300_decompress_zmask_locked_unsafe(struct r300_context *r300) { - struct r300_textures_state *state = - (struct r300_textures_state*)r300->textures_state.state; - unsigned i, level; - unsigned count = MIN2(state->sampler_view_count, - state->sampler_state_count); - - if (r300->z_decomp_rd) - return; - - for (i = 0; i < count; i++) - if (state->sampler_views[i] && state->sampler_states[i]) { - struct pipe_resource *tex = state->sampler_views[i]->base.texture; - - if (tex->target == PIPE_TEXTURE_3D || - tex->target == PIPE_TEXTURE_CUBE) - continue; + struct pipe_framebuffer_state fb = {0}; + fb.width = r300->locked_zbuffer->width; + fb.height = r300->locked_zbuffer->height; + fb.nr_cbufs = 0; + fb.zsbuf = r300->locked_zbuffer; + + r300->context.set_framebuffer_state(&r300->context, &fb); + r300_decompress_zmask(r300); +} - /* Ignore non-depth textures. - * Also ignore reinterpreted depth textures, e.g. resource_copy. */ - if (!util_format_is_depth_or_stencil(tex->format)) - continue; +void r300_decompress_zmask_locked(struct r300_context *r300) +{ + struct pipe_framebuffer_state saved_fb = {0}; - for (level = 0; level <= tex->last_level; level++) - if (r300_texture(tex)->zmask_in_use[level]) { - /* We don't handle 3D textures and cubemaps yet. */ - r300_flush_depth_stencil(&r300->context, tex, level, 0); - } - } + util_copy_framebuffer_state(&saved_fb, r300->fb_state.state); + r300_decompress_zmask_locked_unsafe(r300); + r300->context.set_framebuffer_state(&r300->context, &saved_fb); + util_unreference_framebuffer_state(&saved_fb); } /* Copy a block of pixels from one surface to another using HW. */ @@ -393,8 +395,6 @@ static void r300_hw_copy_region(struct pipe_context* pipe, struct r300_context* r300 = r300_context(pipe); r300_blitter_begin(r300, R300_COPY); - - /* Do a copy */ util_blitter_copy_region(r300->blitter, dst, dst_level, dstx, dsty, dstz, src, src_level, src_box, TRUE); r300_blitter_end(r300); @@ -409,56 +409,102 @@ static void r300_resource_copy_region(struct pipe_context *pipe, unsigned src_level, const struct pipe_box *src_box) { - enum pipe_format old_format = dst->format; - enum pipe_format new_format = old_format; - boolean is_depth; - - if (!pipe->screen->is_format_supported(pipe->screen, - old_format, src->target, - src->nr_samples, - PIPE_BIND_RENDER_TARGET | - PIPE_BIND_SAMPLER_VIEW, 0) && - util_format_is_plain(old_format)) { - switch (util_format_get_blocksize(old_format)) { + struct r300_context *r300 = r300_context(pipe); + struct pipe_framebuffer_state *fb = + (struct pipe_framebuffer_state*)r300->fb_state.state; + struct pipe_resource old_src = *src; + struct pipe_resource old_dst = *dst; + struct pipe_resource new_src = old_src; + struct pipe_resource new_dst = old_dst; + const struct util_format_description *desc = + util_format_description(dst->format); + struct pipe_box box; + + if (r300->zmask_in_use && !r300->zmask_locked) { + if (fb->zsbuf->texture == src || + fb->zsbuf->texture == dst) { + r300_decompress_zmask(r300); + } else { + r300->zmask_locked = TRUE; + r300_mark_atom_dirty(r300, &r300->hyperz_state); + } + } + + /* Handle non-renderable plain formats. */ + if (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN && + (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB || + !pipe->screen->is_format_supported(pipe->screen, + src->format, src->target, + src->nr_samples, + PIPE_BIND_SAMPLER_VIEW, 0) || + !pipe->screen->is_format_supported(pipe->screen, + dst->format, dst->target, + dst->nr_samples, + PIPE_BIND_RENDER_TARGET, 0))) { + switch (util_format_get_blocksize(old_dst.format)) { case 1: - new_format = PIPE_FORMAT_I8_UNORM; + new_dst.format = PIPE_FORMAT_I8_UNORM; break; case 2: - new_format = PIPE_FORMAT_B4G4R4A4_UNORM; + new_dst.format = PIPE_FORMAT_B4G4R4A4_UNORM; break; case 4: - new_format = PIPE_FORMAT_B8G8R8A8_UNORM; + new_dst.format = PIPE_FORMAT_B8G8R8A8_UNORM; break; case 8: - new_format = PIPE_FORMAT_R16G16B16A16_UNORM; + new_dst.format = PIPE_FORMAT_R16G16B16A16_UNORM; break; default: debug_printf("r300: surface_copy: Unhandled format: %s. Falling back to software.\n" "r300: surface_copy: Software fallback doesn't work for tiled textures.\n", - util_format_short_name(old_format)); + util_format_short_name(dst->format)); } + new_src.format = new_dst.format; } - is_depth = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 0) != 0; - if (is_depth) { - r300_flush_depth_stencil(pipe, src, src_level, src_box->z); - } + /* Handle compressed formats. */ + if (desc->layout == UTIL_FORMAT_LAYOUT_S3TC) { + switch (util_format_get_blocksize(old_dst.format)) { + case 8: + /* 1 pixel = 4 bits, + * we set 1 pixel = 2 bytes ===> 4 times larger pixels. */ + new_dst.format = PIPE_FORMAT_B4G4R4A4_UNORM; + break; + case 16: + /* 1 pixel = 8 bits, + * we set 1 pixel = 4 bytes ===> 4 times larger pixels. */ + new_dst.format = PIPE_FORMAT_B8G8R8A8_UNORM; + break; + } - if (old_format != new_format) { - r300_texture_reinterpret_format(pipe->screen, - dst, new_format); - r300_texture_reinterpret_format(pipe->screen, - src, new_format); + /* Since the pixels are 4 times larger, we must decrease + * the image size and the coordinates 4 times. */ + new_src.format = new_dst.format; + new_dst.height0 = (new_dst.height0 + 3) / 4; + new_src.height0 = (new_src.height0 + 3) / 4; + dsty /= 4; + box = *src_box; + box.y /= 4; + box.height = (box.height + 3) / 4; + src_box = &box; } + if (old_src.format != new_src.format) + r300_resource_set_properties(pipe->screen, src, 0, &new_src); + if (old_dst.format != new_dst.format) + r300_resource_set_properties(pipe->screen, dst, 0, &new_dst); + r300_hw_copy_region(pipe, dst, dst_level, dstx, dsty, dstz, src, src_level, src_box); - if (old_format != new_format) { - r300_texture_reinterpret_format(pipe->screen, - dst, old_format); - r300_texture_reinterpret_format(pipe->screen, - src, old_format); + if (old_src.format != new_src.format) + r300_resource_set_properties(pipe->screen, src, 0, &old_src); + if (old_dst.format != new_dst.format) + r300_resource_set_properties(pipe->screen, dst, 0, &old_dst); + + if (r300->zmask_locked) { + r300->zmask_locked = FALSE; + r300_mark_atom_dirty(r300, &r300->hyperz_state); } } diff --git a/src/gallium/drivers/r300/r300_cb.h b/src/gallium/drivers/r300/r300_cb.h index 9d3d4fc1b19..b373937a1f9 100644 --- a/src/gallium/drivers/r300/r300_cb.h +++ b/src/gallium/drivers/r300/r300_cb.h @@ -61,40 +61,52 @@ * that they neatly hide away, and don't have the cost of function setup, so * we're going to use them. */ -#ifdef DEBUG -#define CB_DEBUG(x) x -#else -#define CB_DEBUG(x) -#endif - - /** * Command buffer setup. */ +#ifdef DEBUG + #define CB_LOCALS \ - CB_DEBUG(int cs_count = 0;) \ + int cs_count = 0; \ uint32_t *cs_ptr = NULL; \ - CB_DEBUG((void) cs_count;) (void) cs_ptr; + (void) cs_count; (void) cs_ptr -#define NEW_CB(ptr, size) do { \ - assert(sizeof(*ptr) == sizeof(uint32_t)); \ - cs_ptr = (ptr) = (uint32_t*)malloc((size) * sizeof(uint32_t)); \ - CB_DEBUG(cs_count = size;) \ +#define BEGIN_CB(ptr, size) do { \ + assert(sizeof(*(ptr)) == sizeof(uint32_t)); \ + cs_count = (size); \ + cs_ptr = (ptr); \ } while (0) -#define BEGIN_CB(ptr, size) do { \ - assert(sizeof(*ptr) == sizeof(uint32_t)); \ - cs_ptr = ptr; \ - CB_DEBUG(cs_count = size;) \ +#define NEW_CB(ptr, size) \ + do { \ + assert(sizeof(*(ptr)) == sizeof(uint32_t)); \ + cs_count = (size); \ + cs_ptr = (ptr) = (uint32_t*)malloc((size) * sizeof(uint32_t)); \ } while (0) #define END_CB do { \ - CB_DEBUG(if (cs_count != 0) \ + if (cs_count != 0) \ debug_printf("r300: Warning: cs_count off by %d at (%s, %s:%i)\n", \ - cs_count, __FUNCTION__, __FILE__, __LINE__);) \ + cs_count, __FUNCTION__, __FILE__, __LINE__); \ } while (0) +#define CB_USED_DW(x) cs_count -= x + +#else + +#define CB_LOCALS \ + uint32_t *cs_ptr = NULL; (void) cs_ptr + +#define NEW_CB(ptr, size) \ + cs_ptr = (ptr) = (uint32_t*)malloc((size) * sizeof(uint32_t)) + +#define BEGIN_CB(ptr, size) cs_ptr = (ptr) +#define END_CB +#define CB_USED_DW(x) + +#endif + /** * Storing pure DWORDs. @@ -103,13 +115,13 @@ #define OUT_CB(value) do { \ *cs_ptr = (value); \ cs_ptr++; \ - CB_DEBUG(cs_count--;) \ + CB_USED_DW(1); \ } while (0) #define OUT_CB_TABLE(values, count) do { \ memcpy(cs_ptr, values, count * sizeof(uint32_t)); \ cs_ptr += count; \ - CB_DEBUG(cs_count -= count;) \ + CB_USED_DW(count); \ } while (0) #define OUT_CB_32F(value) \ diff --git a/src/gallium/drivers/r300/r300_chipset.c b/src/gallium/drivers/r300/r300_chipset.c index 2b183f62c56..1968d0feb35 100644 --- a/src/gallium/drivers/r300/r300_chipset.c +++ b/src/gallium/drivers/r300/r300_chipset.c @@ -241,7 +241,6 @@ void r300_parse_chipset(struct r300_capabilities* caps) case 0x5A42: caps->family = CHIP_FAMILY_RS400; caps->has_tcl = FALSE; - caps->zmask_ram = RV3xx_ZMASK_SIZE; break; case 0x5A61: @@ -424,5 +423,6 @@ void r300_parse_chipset(struct r300_capabilities* caps) } caps->is_rv350 = caps->family >= CHIP_FAMILY_RV350; + caps->z_compress = caps->is_rv350 ? R300_ZCOMP_8X8 : R300_ZCOMP_4X4; caps->dxtc_swizzle = caps->is_r400 || caps->is_r500; } diff --git a/src/gallium/drivers/r300/r300_chipset.h b/src/gallium/drivers/r300/r300_chipset.h index f2035d20092..0be161fa07a 100644 --- a/src/gallium/drivers/r300/r300_chipset.h +++ b/src/gallium/drivers/r300/r300_chipset.h @@ -33,6 +33,13 @@ #define PIPE_ZMASK_SIZE 4096 #define RV3xx_ZMASK_SIZE 5120 +/* The size of a compressed tile. Each compressed tile takes 2 bits + * in the ZMASK RAM, so there is always 16 tiles per one dword. */ +enum r300_zmask_compression { + R300_ZCOMP_4X4 = 4, + R300_ZCOMP_8X8 = 8 +}; + /* Structure containing all the possible information about a specific Radeon * in the R3xx, R4xx, and R5xx families. */ struct r300_capabilities { @@ -50,10 +57,12 @@ struct r300_capabilities { unsigned num_tex_units; /* Whether or not TCL is physically present */ boolean has_tcl; - /* Some chipsets do not have HiZ RAM - other have varying amounts . */ + /* Some chipsets do not have HiZ RAM - other have varying amounts. */ int hiz_ram; - /* some chipsets have zmask ram per pipe some don't */ + /* Some chipsets have zmask ram per pipe some don't. */ int zmask_ram; + /* Compression mode for ZMASK. */ + enum r300_zmask_compression z_compress; /* Whether or not this is RV350 or newer, including all r400 and r500 * chipsets. The differences compared to the oldest r300 chips are: * - Blend LTE/GTE thresholds diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c index 91263ad7bcd..9f85bd4ce5f 100644 --- a/src/gallium/drivers/r300/r300_context.c +++ b/src/gallium/drivers/r300/r300_context.c @@ -35,26 +35,24 @@ #include "r300_screen_buffer.h" #include "r300_winsys.h" -#ifdef HAVE_LLVM -#include "gallivm/lp_bld_init.h" -#endif - static void r300_update_num_contexts(struct r300_screen *r300screen, int diff) { + pipe_mutex_lock(r300screen->num_contexts_mutex); if (diff > 0) { - p_atomic_inc(&r300screen->num_contexts); + r300screen->num_contexts++; if (r300screen->num_contexts > 1) util_slab_set_thread_safety(&r300screen->pool_buffers, UTIL_SLAB_MULTITHREADED); } else { - p_atomic_dec(&r300screen->num_contexts); + r300screen->num_contexts--; if (r300screen->num_contexts <= 1) util_slab_set_thread_safety(&r300screen->pool_buffers, UTIL_SLAB_SINGLETHREADED); } + pipe_mutex_unlock(r300screen->num_contexts_mutex); } static void r300_release_referenced_objects(struct r300_context *r300) @@ -87,17 +85,14 @@ static void r300_release_referenced_objects(struct r300_context *r300) /* The SWTCL VBO. */ pipe_resource_reference(&r300->vbo, NULL); - /* Vertex buffers. */ - for (i = 0; i < r300->vertex_buffer_count; i++) { - pipe_resource_reference(&r300->vertex_buffer[i].buffer, NULL); - pipe_resource_reference(&r300->valid_vertex_buffer[i], NULL); - } - /* If there are any queries pending or not destroyed, remove them now. */ foreach_s(query, temp, &r300->query_list) { remove_from_list(query); FREE(query); } + + r300->context.delete_depth_stencil_alpha_state(&r300->context, + r300->dsa_decompress_zmask); } static void r300_destroy_context(struct pipe_context* context) @@ -106,28 +101,15 @@ static void r300_destroy_context(struct pipe_context* context) if (r300->blitter) util_blitter_destroy(r300->blitter); - if (r300->draw) { + if (r300->draw) draw_destroy(r300->draw); -#ifdef HAVE_LLVM - gallivm_destroy(r300->gallivm); -#endif - } - - if (r300->upload_vb) - u_upload_destroy(r300->upload_vb); - if (r300->upload_ib) - u_upload_destroy(r300->upload_ib); - - if (r300->tran.translate_cache) - translate_cache_destroy(r300->tran.translate_cache); + if (r300->vbuf_mgr) + u_vbuf_mgr_destroy(r300->vbuf_mgr); /* XXX: This function assumes r300->query_list was initialized */ r300_release_referenced_objects(r300); - if (r300->zmask_mm) - r300_hyperz_destroy_mm(r300); - if (r300->cs) r300->rws->cs_destroy(r300->cs); @@ -247,7 +229,7 @@ static boolean r300_setup_atoms(struct r300_context* r300) if (has_hiz_ram) R300_INIT_ATOM(hiz_clear, 0); /* zmask clear */ - R300_INIT_ATOM(zmask_clear, 0); + R300_INIT_ATOM(zmask_clear, 4); } /* ZB (unpipelined), SU. */ R300_INIT_ATOM(query_start, 4); @@ -432,12 +414,7 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, if (!r300screen->caps.has_tcl) { /* Create a Draw. This is used for SW TCL. */ -#ifdef HAVE_LLVM - r300->gallivm = gallivm_create(); - r300->draw = draw_create_gallivm(&r300->context, r300->gallivm); -#else r300->draw = draw_create(&r300->context); -#endif if (r300->draw == NULL) goto fail; /* Enable our renderer. */ @@ -456,6 +433,13 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, r300_init_state_functions(r300); r300_init_resource_functions(r300); + r300->vbuf_mgr = u_vbuf_mgr_create(&r300->context, 1024 * 1024, 16, + PIPE_BIND_VERTEX_BUFFER | + PIPE_BIND_INDEX_BUFFER, + U_VERTEX_FETCH_DWORD_ALIGNED); + if (!r300->vbuf_mgr) + goto fail; + r300->blitter = util_blitter_create(&r300->context); if (r300->blitter == NULL) goto fail; @@ -470,23 +454,6 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, if (!r300_hyperz_init_mm(r300)) goto fail; - r300->upload_ib = u_upload_create(&r300->context, - 64 * 1024, 16, - PIPE_BIND_INDEX_BUFFER); - - if (r300->upload_ib == NULL) - goto fail; - - r300->upload_vb = u_upload_create(&r300->context, - 1024 * 1024, 16, - PIPE_BIND_VERTEX_BUFFER); - if (r300->upload_vb == NULL) - goto fail; - - r300->tran.translate_cache = translate_cache_create(); - if (r300->tran.translate_cache == NULL) - goto fail; - r300_init_states(&r300->context); /* The KIL opcode needs the first texture unit to be enabled @@ -515,7 +482,8 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, } { - struct pipe_resource vb = {}; + struct pipe_resource vb; + memset(&vb, 0, sizeof(vb)); vb.target = PIPE_BUFFER; vb.format = PIPE_FORMAT_R8_UNORM; vb.bind = PIPE_BIND_VERTEX_BUFFER; @@ -527,36 +495,44 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, r300->dummy_vb = screen->resource_create(screen, &vb); } + { + struct pipe_depth_stencil_alpha_state dsa; + memset(&dsa, 0, sizeof(dsa)); + dsa.depth.writemask = 1; + + r300->dsa_decompress_zmask = + r300->context.create_depth_stencil_alpha_state(&r300->context, + &dsa); + } + + /* Print driver info. */ +#ifdef NDEBUG + if (DBG_ON(r300, DBG_INFO)) { +#else + { +#endif + fprintf(stderr, + "r300: DRM version: %d.%d.%d, Name: %s, ID: 0x%04x, GB: %d, Z: %d\n" + "r300: GART size: %d MB, VRAM size: %d MB\n" + "r300: AA compression: %s, Z compression: %s, HiZ: %s\n", + rws->get_value(rws, R300_VID_DRM_MAJOR), + rws->get_value(rws, R300_VID_DRM_MINOR), + rws->get_value(rws, R300_VID_DRM_PATCHLEVEL), + screen->get_name(screen), + rws->get_value(rws, R300_VID_PCI_ID), + rws->get_value(rws, R300_VID_GB_PIPES), + rws->get_value(rws, R300_VID_Z_PIPES), + rws->get_value(rws, R300_VID_GART_SIZE) >> 20, + rws->get_value(rws, R300_VID_VRAM_SIZE) >> 20, + rws->get_value(rws, R300_CAN_AACOMPRESS) ? "YES" : "NO", + rws->get_value(rws, R300_CAN_HYPERZ) ? "YES" : "NO", + rws->get_value(rws, R300_CAN_HYPERZ) && + r300->screen->caps.hiz_ram ? "YES" : "NO"); + } + return &r300->context; - fail: +fail: r300_destroy_context(&r300->context); return NULL; } - -void r300_finish(struct r300_context *r300) -{ - struct pipe_framebuffer_state *fb; - unsigned i; - - /* This is a preliminary implementation of glFinish. - * - * The ideal implementation should use something like EmitIrqLocked and - * WaitIrq, or better, real fences. - */ - if (r300->fb_state.state) { - fb = r300->fb_state.state; - - for (i = 0; i < fb->nr_cbufs; i++) { - if (fb->cbufs[i]->texture) { - r300->rws->buffer_wait(r300->rws, - r300_texture(fb->cbufs[i]->texture)->buffer); - return; - } - } - if (fb->zsbuf && fb->zsbuf->texture) { - r300->rws->buffer_wait(r300->rws, - r300_texture(fb->zsbuf->texture)->buffer); - } - } -} diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index e09cf87f733..30073759476 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -30,11 +30,11 @@ #include "pipe/p_context.h" #include "util/u_inlines.h" #include "util/u_transfer.h" - -#include "translate/translate_cache.h" +#include "util/u_vbuf_mgr.h" #include "r300_defines.h" #include "r300_screen.h" +#include "r300_winsys.h" struct u_upload_mgr; struct r300_context; @@ -189,11 +189,6 @@ struct r300_sampler_view { uint32_t texcache_region; }; -struct r300_texture_fb_state { - uint32_t pitch[R300_MAX_TEXTURE_LEVELS]; /* COLORPITCH or DEPTHPITCH. */ - uint32_t format; /* US_OUT_FMT or R300_ZB_FORMAT */ -}; - struct r300_texture_sampler_state { struct r300_texture_format_state format; uint32_t filter0; /* R300_TX_FILTER0: 0x4400 */ @@ -273,14 +268,12 @@ struct r300_query { /* How many results have been written, in dwords. It's incremented * after end_query and flush. */ unsigned num_results; - /* if we've flushed the query */ - boolean flushed; /* if begin has been emitted */ boolean begin_emitted; /* The buffer where query results are stored. */ - struct r300_winsys_buffer *buffer; - struct r300_winsys_cs_buffer *cs_buffer; + struct r300_winsys_bo *buf; + struct r300_winsys_cs_handle *cs_buf; /* The size of the buffer. */ unsigned buffer_size; /* The domain of the buffer. */ @@ -291,28 +284,12 @@ struct r300_query { struct r300_query* next; }; -/* Fence object. - * - * This is a fake fence. Instead of syncing with the fence, we sync - * with the context, which is inefficient but compliant. - * - * This is not a subclass of pipe_fence_handle because pipe_fence_handle is - * never actually fully defined. So, rather than have it as a member, and do - * subclass-style casting, we treat pipe_fence_handle as an opaque, and just - * trust that our state tracker does not ever mess up fence objects. - */ -struct r300_fence { - struct pipe_reference reference; - struct r300_context *ctx; - boolean signalled; -}; - struct r300_surface { struct pipe_surface base; /* Winsys buffer backing the texture. */ - struct r300_winsys_buffer *buffer; - struct r300_winsys_cs_buffer *cs_buffer; + struct r300_winsys_bo *buf; + struct r300_winsys_cs_handle *cs_buf; enum r300_buffer_domain domain; @@ -329,13 +306,9 @@ struct r300_surface { /* Whether the CBZB clear is allowed on the surface. */ boolean cbzb_allowed; - }; struct r300_texture_desc { - /* Parent class. */ - struct u_resource b; - /* Width, height, and depth. * Most of the time, these are equal to pipe_texture::width0, height0, * and depth0. However, NPOT 3D textures must have dimensions aligned @@ -387,27 +360,38 @@ struct r300_texture_desc { /* Whether CBZB fast color clear is allowed on the miplevel. */ boolean cbzb_allowed[R300_MAX_TEXTURE_LEVELS]; + + /* Zbuffer compression info for each miplevel. */ + boolean zcomp8x8[R300_MAX_TEXTURE_LEVELS]; + /* If zero, then disable compression. */ + unsigned zmask_dwords[R300_MAX_TEXTURE_LEVELS]; }; -struct r300_texture { - struct r300_texture_desc desc; +struct r300_resource +{ + struct u_vbuf_resource b; + /* Winsys buffer backing this resource. */ + struct r300_winsys_bo *buf; + struct r300_winsys_cs_handle *cs_buf; enum r300_buffer_domain domain; + unsigned buf_size; + + /* Constant buffers are in user memory. */ + uint8_t *constant_buffer; - /* Pipe buffer backing this texture. */ - struct r300_winsys_buffer *buffer; - struct r300_winsys_cs_buffer *cs_buffer; + /* Texture description (addressing, layout, special features). */ + struct r300_texture_desc tex; /* Registers carrying texture format data. */ /* Only format-independent bits should be filled in. */ struct r300_texture_format_state tx_format; - /* All bits should be filled in. */ - struct r300_texture_fb_state fb_state; - /* hyper-z memory allocs */ + /* Where the texture starts in the buffer. */ + unsigned tex_offset; + + /* HiZ memory allocations. */ struct mem_block *hiz_mem[R300_MAX_TEXTURE_LEVELS]; - struct mem_block *zmask_mem[R300_MAX_TEXTURE_LEVELS]; - boolean zmask_in_use[R300_MAX_TEXTURE_LEVELS]; boolean hiz_in_use[R300_MAX_TEXTURE_LEVELS]; /* This is the level tiling flags were last time set for. @@ -418,32 +402,16 @@ struct r300_texture { struct r300_vertex_element_state { unsigned count; struct pipe_vertex_element velem[PIPE_MAX_ATTRIBS]; + unsigned format_size[PIPE_MAX_ATTRIBS]; - /* If (velem[i].src_format != hw_format[i]), the vertex buffer - * referenced by this vertex element cannot be used for rendering and - * its vertex data must be translated to hw_format[i]. */ - enum pipe_format hw_format[PIPE_MAX_ATTRIBS]; - unsigned hw_format_size[PIPE_MAX_ATTRIBS]; + struct u_vbuf_mgr_elements *vmgr_elements; /* The size of the vertex, in dwords. */ unsigned vertex_size_dwords; - /* This might mean two things: - * - src_format != hw_format, as discussed above. - * - src_offset % 4 != 0. */ - boolean incompatible_layout; - struct r300_vertex_stream_state vertex_stream; }; -struct r300_translate_context { - /* Translate cache for incompatible vertex offset/stride/format fallback. */ - struct translate_cache *translate_cache; - - /* Saved and new vertex element state. */ - void *saved_velems, *new_velems; -}; - struct r300_context { /* Parent class */ struct pipe_context context; @@ -456,7 +424,6 @@ struct r300_context { struct r300_screen *screen; /* Draw module. Used mostly for SW TCL. */ - struct gallivm_state *gallivm; struct draw_context* draw; /* Vertex buffer for SW TCL. */ struct pipe_resource* vbo; @@ -471,8 +438,6 @@ struct r300_context { struct blitter_context* blitter; /* Stencil two-sided reference value fallback. */ struct r300_stencilref_context *stencilref_fallback; - /* For translating vertex buffers having incompatible vertex layout. */ - struct r300_translate_context tran; /* The KIL opcode needs the first texture unit to be enabled * on r3xx-r4xx. In order to calm down the CS checker, we bind this @@ -554,14 +519,6 @@ struct r300_context { /* The pointers to the first and the last atom. */ struct r300_atom *first_dirty, *last_dirty; - /* Vertex buffers for Gallium. */ - /* May contain user buffers. */ - struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; - /* Contains only non-user buffers. */ - struct pipe_resource *valid_vertex_buffer[PIPE_MAX_ATTRIBS]; - int vertex_buffer_count; - int vertex_buffer_max_index; - boolean any_user_vbs; /* Vertex elements for Gallium. */ struct r300_vertex_element_state *velems; @@ -588,21 +545,23 @@ struct r300_context { int sprite_coord_enable; /* Whether two-sided color selection is enabled (AKA light_twoside). */ boolean two_sided_color; - /* Incompatible vertex buffer layout? (misaligned stride or buffer_offset) */ - boolean incompatible_vb_layout; -#define R300_Z_COMPRESS_44 1 -#define RV350_Z_COMPRESS_88 2 - int z_compression; + boolean cbzb_clear; - boolean z_decomp_rd; + /* Whether ZMASK is enabled. */ + boolean zmask_in_use; + /* Whether ZMASK is being decompressed. */ + boolean zmask_decompress; + /* Whether ZMASK is locked, i.e. should be disabled and cannot be taken over. */ + boolean zmask_locked; + /* The zbuffer the ZMASK of which is locked. */ + struct pipe_surface *locked_zbuffer; + + void *dsa_decompress_zmask; /* two mem block managers for hiz/zmask ram space */ struct mem_block *hiz_mm; - struct mem_block *zmask_mm; - /* upload managers */ - struct u_upload_mgr *upload_vb; - struct u_upload_mgr *upload_ib; + struct u_vbuf_mgr *vbuf_mgr; struct util_slab_mempool pool_transfers; @@ -612,16 +571,10 @@ struct r300_context { /* const tracking for VS */ int vs_const_base; - /* AOS (PACKET3_3D_LOAD_VBPNTR) command buffer for the case offset=0. */ - uint32_t vertex_arrays_cb[(16 * 3 + 1) / 2]; + /* Vertex array state info */ boolean vertex_arrays_dirty; - - /* Whether any buffer (FB, textures, VBOs) has been set, but buffers - * haven't been validated yet. */ - boolean validate_buffers; - /* Whether user buffers have been validated. */ - boolean upload_vb_validated; - boolean upload_ib_validated; + boolean vertex_arrays_indexed; + int vertex_arrays_offset; }; #define foreach_atom(r300, atom) \ @@ -641,9 +594,9 @@ static INLINE struct r300_surface* r300_surface(struct pipe_surface* surf) return (struct r300_surface*)surf; } -static INLINE struct r300_texture* r300_texture(struct pipe_resource* tex) +static INLINE struct r300_resource* r300_resource(struct pipe_resource* tex) { - return (struct r300_texture*)tex; + return (struct r300_resource*)tex; } static INLINE struct r300_context* r300_context(struct pipe_context* context) @@ -675,7 +628,6 @@ static INLINE void r300_mark_atom_dirty(struct r300_context *r300, struct pipe_context* r300_create_context(struct pipe_screen* screen, void *priv); -void r300_finish(struct r300_context *r300); void r300_flush_cb(void *data); /* Context initialization. */ @@ -688,7 +640,9 @@ void r300_init_state_functions(struct r300_context* r300); void r300_init_resource_functions(struct r300_context* r300); /* r300_blit.c */ -void r300_flush_depth_textures(struct r300_context *r300); +void r300_decompress_zmask(struct r300_context *r300); +void r300_decompress_zmask_locked_unsafe(struct r300_context *r300); +void r300_decompress_zmask_locked(struct r300_context *r300); /* r300_query.c */ void r300_resume_query(struct r300_context *r300, @@ -696,9 +650,6 @@ void r300_resume_query(struct r300_context *r300, void r300_stop_query(struct r300_context *r300); /* r300_render_translate.c */ -void r300_begin_vertex_translate(struct r300_context *r300, - int min_index, int max_index); -void r300_end_vertex_translate(struct r300_context *r300); void r300_translate_index_buffer(struct r300_context *r300, struct pipe_resource **index_buffer, unsigned *index_size, unsigned index_offset, @@ -714,8 +665,7 @@ void r500_emit_index_bias(struct r300_context *r300, int index_bias); /* r300_state.c */ enum r300_fb_state_change { R300_CHANGED_FB_STATE = 0, - R300_CHANGED_CBZB_FLAG, - R300_CHANGED_ZCLEAR_FLAG, + R300_CHANGED_HYPERZ_FLAG, R300_CHANGED_MULTIWRITE }; diff --git a/src/gallium/drivers/r300/r300_cs.h b/src/gallium/drivers/r300/r300_cs.h index 6726f100e1b..2e52dfa43c6 100644 --- a/src/gallium/drivers/r300/r300_cs.h +++ b/src/gallium/drivers/r300/r300_cs.h @@ -35,12 +35,6 @@ * that they neatly hide away, and don't have the cost of function setup,so * we're going to use them. */ -#ifdef DEBUG -#define CS_DEBUG(x) x -#else -#define CS_DEBUG(x) -#endif - /** * Command submission setup. */ @@ -50,22 +44,29 @@ struct r300_winsys_screen *cs_winsys = (context)->rws; \ int cs_count = 0; (void) cs_count; (void) cs_winsys; +#ifdef DEBUG + #define BEGIN_CS(size) do { \ assert(size <= (R300_MAX_CMDBUF_DWORDS - cs_copy->cdw)); \ - CS_DEBUG(cs_count = size;) \ + cs_count = size; \ } while (0) -#ifdef DEBUG #define END_CS do { \ if (cs_count != 0) \ debug_printf("r300: Warning: cs_count off by %d at (%s, %s:%i)\n", \ cs_count, __FUNCTION__, __FILE__, __LINE__); \ cs_count = 0; \ } while (0) + +#define CS_USED_DW(x) cs_count -= (x) + #else + +#define BEGIN_CS(size) #define END_CS -#endif +#define CS_USED_DW(x) +#endif /** * Writing pure DWORDs. @@ -73,7 +74,7 @@ #define OUT_CS(value) do { \ cs_copy->buf[cs_copy->cdw++] = (value); \ - CS_DEBUG(cs_count--;) \ + CS_USED_DW(1); \ } while (0) #define OUT_CS_32F(value) \ @@ -98,7 +99,7 @@ #define OUT_CS_TABLE(values, count) do { \ memcpy(cs_copy->buf + cs_copy->cdw, values, count * 4); \ cs_copy->cdw += count; \ - CS_DEBUG(cs_count -= count;) \ + CS_USED_DW(count); \ } while (0) @@ -106,27 +107,11 @@ * Writing relocations. */ -#define OUT_CS_RELOC(bo, offset) do { \ - assert(bo); \ - OUT_CS(offset); \ - cs_winsys->cs_write_reloc(cs_copy, bo); \ - CS_DEBUG(cs_count -= 2;) \ -} while (0) - -#define OUT_CS_BUF_RELOC(bo, offset) do { \ - assert(bo); \ - OUT_CS_RELOC(r300_buffer(bo)->cs_buf, offset); \ -} while (0) - -#define OUT_CS_TEX_RELOC(tex, offset) do { \ - assert(tex); \ - OUT_CS_RELOC(tex->cs_buffer, offset); \ -} while (0) - -#define OUT_CS_BUF_RELOC_NO_OFFSET(bo) do { \ - assert(bo); \ - cs_winsys->cs_write_reloc(cs_copy, r300_buffer(bo)->cs_buf); \ - CS_DEBUG(cs_count -= 2;) \ +#define OUT_CS_RELOC(r) do { \ + assert((r)); \ + assert((r)->cs_buf); \ + cs_winsys->cs_write_reloc(cs_copy, (r)->cs_buf); \ + CS_USED_DW(2); \ } while (0) @@ -135,7 +120,7 @@ */ #define WRITE_CS_TABLE(values, count) do { \ - CS_DEBUG(assert(cs_count == 0);) \ + assert(cs_count == 0); \ memcpy(cs_copy->buf + cs_copy->cdw, (values), (count) * 4); \ cs_copy->cdw += (count); \ } while (0) diff --git a/src/gallium/drivers/r300/r300_debug.c b/src/gallium/drivers/r300/r300_debug.c index d6aa90bd053..b60cfd1f248 100644 --- a/src/gallium/drivers/r300/r300_debug.c +++ b/src/gallium/drivers/r300/r300_debug.c @@ -27,6 +27,7 @@ #include <stdio.h> static const struct debug_named_value debug_options[] = { + { "info", DBG_INFO, "Print hardware info"}, { "fp", DBG_FP, "Log fragment program compilation" }, { "vp", DBG_VP, "Log vertex program compilation" }, { "pstat", DBG_P_STAT, "Log vertex/fragment program stats" }, @@ -49,6 +50,8 @@ static const struct debug_named_value debug_options[] = { { "noimmd", DBG_NO_IMMD, "Disable immediate mode" }, { "noopt", DBG_NO_OPT, "Disable shader optimizations" }, { "nocbzb", DBG_NO_CBZB, "Disable fast color clear" }, + { "nozmask", DBG_NO_ZMASK, "Disable zbuffer compression" }, + { "nohiz", DBG_NO_HIZ, "Disable hierarchical zbuffer" }, /* must be last */ DEBUG_NAMED_VALUE_END diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c index d14cdcbbaf0..e2e4719ec82 100644 --- a/src/gallium/drivers/r300/r300_emit.c +++ b/src/gallium/drivers/r300/r300_emit.c @@ -89,7 +89,7 @@ static void get_rc_constant_state( struct rc_constant * constant) { struct r300_textures_state* texstate = r300->textures_state.state; - struct r300_texture *tex; + struct r300_resource *tex; assert(constant->Type == RC_CONSTANT_STATE); @@ -101,19 +101,19 @@ static void get_rc_constant_state( /* Factor for converting rectangle coords to * normalized coords. Should only show up on non-r500. */ case RC_STATE_R300_TEXRECT_FACTOR: - tex = r300_texture(texstate->sampler_views[constant->u.State[1]]->base.texture); - vec[0] = 1.0 / tex->desc.width0; - vec[1] = 1.0 / tex->desc.height0; + tex = r300_resource(texstate->sampler_views[constant->u.State[1]]->base.texture); + vec[0] = 1.0 / tex->tex.width0; + vec[1] = 1.0 / tex->tex.height0; vec[2] = 0; vec[3] = 1; break; case RC_STATE_R300_TEXSCALE_FACTOR: - tex = r300_texture(texstate->sampler_views[constant->u.State[1]]->base.texture); + tex = r300_resource(texstate->sampler_views[constant->u.State[1]]->base.texture); /* Add a small number to the texture size to work around rounding errors in hw. */ - vec[0] = tex->desc.b.b.width0 / (tex->desc.width0 + 0.001f); - vec[1] = tex->desc.b.b.height0 / (tex->desc.height0 + 0.001f); - vec[2] = tex->desc.b.b.depth0 / (tex->desc.depth0 + 0.001f); + vec[0] = tex->b.b.b.width0 / (tex->tex.width0 + 0.001f); + vec[1] = tex->b.b.b.height0 / (tex->tex.height0 + 0.001f); + vec[2] = tex->b.b.b.depth0 / (tex->tex.depth0 + 0.001f); vec[3] = 1; break; @@ -352,11 +352,9 @@ void r300_emit_aa_state(struct r300_context *r300, unsigned size, void *state) OUT_CS_REG(R300_GB_AA_CONFIG, aa->aa_config); if (aa->dest) { - OUT_CS_REG_SEQ(R300_RB3D_AARESOLVE_OFFSET, 1); - OUT_CS_RELOC(aa->dest->cs_buffer, aa->dest->offset); - - OUT_CS_REG_SEQ(R300_RB3D_AARESOLVE_PITCH, 1); - OUT_CS_RELOC(aa->dest->cs_buffer, aa->dest->pitch); + OUT_CS_REG(R300_RB3D_AARESOLVE_OFFSET, aa->dest->offset); + OUT_CS_RELOC(aa->dest); + OUT_CS_REG(R300_RB3D_AARESOLVE_PITCH, aa->dest->pitch); } OUT_CS_REG(R300_RB3D_AARESOLVE_CTL, aa->aaresolve_ctl); @@ -391,11 +389,11 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state) for (i = 0; i < fb->nr_cbufs; i++) { surf = r300_surface(fb->cbufs[i]); - OUT_CS_REG_SEQ(R300_RB3D_COLOROFFSET0 + (4 * i), 1); - OUT_CS_RELOC(surf->cs_buffer, surf->offset); + OUT_CS_REG(R300_RB3D_COLOROFFSET0 + (4 * i), surf->offset); + OUT_CS_RELOC(surf); - OUT_CS_REG_SEQ(R300_RB3D_COLORPITCH0 + (4 * i), 1); - OUT_CS_RELOC(surf->cs_buffer, surf->pitch); + OUT_CS_REG(R300_RB3D_COLORPITCH0 + (4 * i), surf->pitch); + OUT_CS_RELOC(surf); } /* Set up the ZB part of the CBZB clear. */ @@ -404,11 +402,11 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state) OUT_CS_REG(R300_ZB_FORMAT, surf->cbzb_format); - OUT_CS_REG_SEQ(R300_ZB_DEPTHOFFSET, 1); - OUT_CS_RELOC(surf->cs_buffer, surf->cbzb_midpoint_offset); + OUT_CS_REG(R300_ZB_DEPTHOFFSET, surf->cbzb_midpoint_offset); + OUT_CS_RELOC(surf); - OUT_CS_REG_SEQ(R300_ZB_DEPTHPITCH, 1); - OUT_CS_RELOC(surf->cs_buffer, surf->cbzb_pitch); + OUT_CS_REG(R300_ZB_DEPTHPITCH, surf->cbzb_pitch); + OUT_CS_RELOC(surf); DBG(r300, DBG_CBZB, "CBZB clearing cbuf %08x %08x\n", surf->cbzb_format, @@ -420,19 +418,20 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state) OUT_CS_REG(R300_ZB_FORMAT, surf->format); - OUT_CS_REG_SEQ(R300_ZB_DEPTHOFFSET, 1); - OUT_CS_RELOC(surf->cs_buffer, surf->offset); + OUT_CS_REG(R300_ZB_DEPTHOFFSET, surf->offset); + OUT_CS_RELOC(surf); - OUT_CS_REG_SEQ(R300_ZB_DEPTHPITCH, 1); - OUT_CS_RELOC(surf->cs_buffer, surf->pitch); + OUT_CS_REG(R300_ZB_DEPTHPITCH, surf->pitch); + OUT_CS_RELOC(surf); if (can_hyperz) { uint32_t surf_pitch; - struct r300_texture *tex; + struct r300_resource *tex; int level = surf->base.u.tex.level; - tex = r300_texture(surf->base.texture); + tex = r300_resource(surf->base.texture); surf_pitch = surf->pitch & R300_DEPTHPITCH_MASK; + /* HiZ RAM. */ if (r300->screen->caps.hiz_ram) { if (tex->hiz_mem[level]) { @@ -443,14 +442,10 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state) OUT_CS_REG(R300_ZB_HIZ_PITCH, 0); } } + /* Z Mask RAM. (compressed zbuffer) */ - if (tex->zmask_mem[level]) { - OUT_CS_REG(R300_ZB_ZMASK_OFFSET, tex->zmask_mem[level]->ofs << 2); - OUT_CS_REG(R300_ZB_ZMASK_PITCH, surf_pitch); - } else { - OUT_CS_REG(R300_ZB_ZMASK_OFFSET, 0); - OUT_CS_REG(R300_ZB_ZMASK_PITCH, 0); - } + OUT_CS_REG(R300_ZB_ZMASK_OFFSET, 0); + OUT_CS_REG(R300_ZB_ZMASK_PITCH, surf_pitch); } } @@ -462,6 +457,7 @@ void r300_emit_hyperz_state(struct r300_context *r300, { struct r300_hyperz_state *z = state; CS_LOCALS(r300); + if (z->flush) WRITE_CS_TABLE(&z->cb_flush_begin, size); else @@ -563,14 +559,12 @@ void r300_emit_query_start(struct r300_context *r300, unsigned size, void*state) OUT_CS_REG(R300_ZB_ZPASS_DATA, 0); END_CS; query->begin_emitted = TRUE; - query->flushed = FALSE; } static void r300_emit_query_end_frag_pipes(struct r300_context *r300, struct r300_query *query) { struct r300_capabilities* caps = &r300->screen->caps; - struct r300_winsys_cs_buffer *buf = r300->query_current->cs_buffer; CS_LOCALS(r300); assert(caps->num_frag_pipes); @@ -588,25 +582,25 @@ static void r300_emit_query_end_frag_pipes(struct r300_context *r300, case 4: /* pipe 3 only */ OUT_CS_REG(R300_SU_REG_DEST, 1 << 3); - OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_CS_RELOC(buf, (query->num_results + 3) * 4); + OUT_CS_REG(R300_ZB_ZPASS_ADDR, (query->num_results + 3) * 4); + OUT_CS_RELOC(r300->query_current); case 3: /* pipe 2 only */ OUT_CS_REG(R300_SU_REG_DEST, 1 << 2); - OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_CS_RELOC(buf, (query->num_results + 2) * 4); + OUT_CS_REG(R300_ZB_ZPASS_ADDR, (query->num_results + 2) * 4); + OUT_CS_RELOC(r300->query_current); case 2: /* pipe 1 only */ /* As mentioned above, accomodate RV380 and older. */ OUT_CS_REG(R300_SU_REG_DEST, 1 << (caps->high_second_pipe ? 3 : 1)); - OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_CS_RELOC(buf, (query->num_results + 1) * 4); + OUT_CS_REG(R300_ZB_ZPASS_ADDR, (query->num_results + 1) * 4); + OUT_CS_RELOC(r300->query_current); case 1: /* pipe 0 only */ OUT_CS_REG(R300_SU_REG_DEST, 1 << 0); - OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_CS_RELOC(buf, (query->num_results + 0) * 4); + OUT_CS_REG(R300_ZB_ZPASS_ADDR, (query->num_results + 0) * 4); + OUT_CS_RELOC(r300->query_current); break; default: fprintf(stderr, "r300: Implementation error: Chipset reports %d" @@ -622,13 +616,12 @@ static void r300_emit_query_end_frag_pipes(struct r300_context *r300, static void rv530_emit_query_end_single_z(struct r300_context *r300, struct r300_query *query) { - struct r300_winsys_cs_buffer *buf = r300->query_current->cs_buffer; CS_LOCALS(r300); BEGIN_CS(8); OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_0); - OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_CS_RELOC(buf, query->num_results * 4); + OUT_CS_REG(R300_ZB_ZPASS_ADDR, query->num_results * 4); + OUT_CS_RELOC(r300->query_current); OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL); END_CS; } @@ -636,16 +629,15 @@ static void rv530_emit_query_end_single_z(struct r300_context *r300, static void rv530_emit_query_end_double_z(struct r300_context *r300, struct r300_query *query) { - struct r300_winsys_cs_buffer *buf = r300->query_current->cs_buffer; CS_LOCALS(r300); BEGIN_CS(14); OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_0); - OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_CS_RELOC(buf, (query->num_results + 0) * 4); + OUT_CS_REG(R300_ZB_ZPASS_ADDR, (query->num_results + 0) * 4); + OUT_CS_RELOC(r300->query_current); OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_1); - OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_CS_RELOC(buf, (query->num_results + 1) * 4); + OUT_CS_REG(R300_ZB_ZPASS_ADDR, (query->num_results + 1) * 4); + OUT_CS_RELOC(r300->query_current); OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL); END_CS; } @@ -784,7 +776,7 @@ void r300_emit_textures_state(struct r300_context *r300, { struct r300_textures_state *allstate = (struct r300_textures_state*)state; struct r300_texture_sampler_state *texstate; - struct r300_texture *tex; + struct r300_resource *tex; unsigned i; CS_LOCALS(r300); @@ -794,7 +786,7 @@ void r300_emit_textures_state(struct r300_context *r300, for (i = 0; i < allstate->count; i++) { if ((1 << i) & allstate->tx_enable) { texstate = &allstate->regs[i]; - tex = r300_texture(allstate->sampler_views[i]->base.texture); + tex = r300_resource(allstate->sampler_views[i]->base.texture); OUT_CS_REG(R300_TX_FILTER0_0 + (i * 4), texstate->filter0); OUT_CS_REG(R300_TX_FILTER1_0 + (i * 4), texstate->filter1); @@ -805,96 +797,56 @@ void r300_emit_textures_state(struct r300_context *r300, OUT_CS_REG(R300_TX_FORMAT1_0 + (i * 4), texstate->format.format1); OUT_CS_REG(R300_TX_FORMAT2_0 + (i * 4), texstate->format.format2); - OUT_CS_REG_SEQ(R300_TX_OFFSET_0 + (i * 4), 1); - OUT_CS_TEX_RELOC(tex, texstate->format.tile_config); + OUT_CS_REG(R300_TX_OFFSET_0 + (i * 4), texstate->format.tile_config); + OUT_CS_RELOC(tex); } } END_CS; } -static void r300_update_vertex_arrays_cb(struct r300_context *r300, unsigned packet_size) +void r300_emit_vertex_arrays(struct r300_context* r300, int offset, boolean indexed) { - struct pipe_vertex_buffer *vb1, *vb2, *vbuf = r300->vertex_buffer; + struct pipe_vertex_buffer *vbuf = r300->vbuf_mgr->vertex_buffer; + struct pipe_resource **valid_vbuf = r300->vbuf_mgr->real_vertex_buffer; struct pipe_vertex_element *velem = r300->velems->velem; - unsigned *hw_format_size = r300->velems->hw_format_size; - unsigned size1, size2, vertex_array_count = r300->velems->count; + struct r300_resource *buf; int i; - CB_LOCALS; + unsigned vertex_array_count = r300->velems->count; + unsigned packet_size = (vertex_array_count * 3 + 1) / 2; + struct pipe_vertex_buffer *vb1, *vb2; + unsigned *hw_format_size; + unsigned size1, size2; + CS_LOCALS(r300); + + BEGIN_CS(2 + packet_size + vertex_array_count * 2); + OUT_CS_PKT3(R300_PACKET3_3D_LOAD_VBPNTR, packet_size); + OUT_CS(vertex_array_count | (!indexed ? R300_VC_FORCE_PREFETCH : 0)); + + hw_format_size = r300->velems->format_size; - BEGIN_CB(r300->vertex_arrays_cb, packet_size); for (i = 0; i < vertex_array_count - 1; i += 2) { vb1 = &vbuf[velem[i].vertex_buffer_index]; vb2 = &vbuf[velem[i+1].vertex_buffer_index]; size1 = hw_format_size[i]; size2 = hw_format_size[i+1]; - OUT_CB(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride) | + OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride) | R300_VBPNTR_SIZE1(size2) | R300_VBPNTR_STRIDE1(vb2->stride)); - OUT_CB(vb1->buffer_offset + velem[i].src_offset); - OUT_CB(vb2->buffer_offset + velem[i+1].src_offset); + OUT_CS(vb1->buffer_offset + velem[i].src_offset + offset * vb1->stride); + OUT_CS(vb2->buffer_offset + velem[i+1].src_offset + offset * vb2->stride); } if (vertex_array_count & 1) { vb1 = &vbuf[velem[i].vertex_buffer_index]; size1 = hw_format_size[i]; - OUT_CB(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride)); - OUT_CB(vb1->buffer_offset + velem[i].src_offset); - } - END_CB; - - r300->vertex_arrays_dirty = FALSE; -} - -void r300_emit_vertex_arrays(struct r300_context* r300, int offset, boolean indexed) -{ - struct pipe_vertex_buffer *vbuf = r300->vertex_buffer; - struct pipe_resource **valid_vbuf = r300->valid_vertex_buffer; - struct pipe_vertex_element *velem = r300->velems->velem; - struct r300_buffer *buf; - int i; - unsigned vertex_array_count = r300->velems->count; - unsigned packet_size = (vertex_array_count * 3 + 1) / 2; - CS_LOCALS(r300); - - BEGIN_CS(2 + packet_size + vertex_array_count * 2); - OUT_CS_PKT3(R300_PACKET3_3D_LOAD_VBPNTR, packet_size); - OUT_CS(vertex_array_count | (!indexed ? R300_VC_FORCE_PREFETCH : 0)); - - if (!offset) { - if (r300->vertex_arrays_dirty) { - r300_update_vertex_arrays_cb(r300, packet_size); - } - OUT_CS_TABLE(r300->vertex_arrays_cb, packet_size); - } else { - struct pipe_vertex_buffer *vb1, *vb2; - unsigned *hw_format_size = r300->velems->hw_format_size; - unsigned size1, size2; - - for (i = 0; i < vertex_array_count - 1; i += 2) { - vb1 = &vbuf[velem[i].vertex_buffer_index]; - vb2 = &vbuf[velem[i+1].vertex_buffer_index]; - size1 = hw_format_size[i]; - size2 = hw_format_size[i+1]; - - OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride) | - R300_VBPNTR_SIZE1(size2) | R300_VBPNTR_STRIDE1(vb2->stride)); - OUT_CS(vb1->buffer_offset + velem[i].src_offset + offset * vb1->stride); - OUT_CS(vb2->buffer_offset + velem[i+1].src_offset + offset * vb2->stride); - } - - if (vertex_array_count & 1) { - vb1 = &vbuf[velem[i].vertex_buffer_index]; - size1 = hw_format_size[i]; - - OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride)); - OUT_CS(vb1->buffer_offset + velem[i].src_offset + offset * vb1->stride); - } + OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride)); + OUT_CS(vb1->buffer_offset + velem[i].src_offset + offset * vb1->stride); } for (i = 0; i < vertex_array_count; i++) { - buf = r300_buffer(valid_vbuf[velem[i].vertex_buffer_index]); - OUT_CS_BUF_RELOC_NO_OFFSET(&buf->b.b); + buf = r300_resource(valid_vbuf[velem[i].vertex_buffer_index]); + OUT_CS_RELOC(buf); } END_CS; } @@ -919,7 +871,8 @@ void r300_emit_vertex_arrays_swtcl(struct r300_context *r300, boolean indexed) OUT_CS(r300->vertex_info.size | (r300->vertex_info.size << 8)); OUT_CS(r300->draw_vbo_offset); - OUT_CS_BUF_RELOC(r300->vbo, 0); + OUT_CS(0); + OUT_CS_RELOC(r300_resource(r300->vbo)); END_CS; } @@ -1097,17 +1050,6 @@ static void r300_emit_hiz_line_clear(struct r300_context *r300, int start, uint1 END_CS; } -static void r300_emit_zmask_line_clear(struct r300_context *r300, int start, uint16_t count, uint32_t val) -{ - CS_LOCALS(r300); - BEGIN_CS(4); - OUT_CS_PKT3(R300_PACKET3_3D_CLEAR_ZMASK, 2); - OUT_CS(start); - OUT_CS(count); - OUT_CS(val); - END_CS; -} - #define ALIGN_DIVUP(x, y) (((x) + (y) - 1) / (y)) void r300_emit_hiz_clear(struct r300_context *r300, unsigned size, void *state) @@ -1118,13 +1060,13 @@ void r300_emit_hiz_clear(struct r300_context *r300, unsigned size, void *state) (struct r300_hyperz_state*)r300->hyperz_state.state; struct r300_screen* r300screen = r300->screen; uint32_t stride, offset = 0, height, offset_shift; - struct r300_texture* tex; + struct r300_resource* tex; int i; - tex = r300_texture(fb->zsbuf->texture); + tex = r300_resource(fb->zsbuf->texture); offset = tex->hiz_mem[fb->zsbuf->u.tex.level]->ofs; - stride = tex->desc.stride_in_pixels[fb->zsbuf->u.tex.level]; + stride = tex->tex.stride_in_pixels[fb->zsbuf->u.tex.level]; /* convert from pixels to 4x4 blocks */ stride = ALIGN_DIVUP(stride, 4); @@ -1153,42 +1095,21 @@ void r300_emit_zmask_clear(struct r300_context *r300, unsigned size, void *state { struct pipe_framebuffer_state *fb = (struct pipe_framebuffer_state*)r300->fb_state.state; - struct r300_screen* r300screen = r300->screen; - uint32_t stride, offset = 0; - struct r300_texture* tex; - uint32_t i, height; - int mult, offset_shift; - - tex = r300_texture(fb->zsbuf->texture); - stride = tex->desc.stride_in_pixels[fb->zsbuf->u.tex.level]; - - offset = tex->zmask_mem[fb->zsbuf->u.tex.level]->ofs; - - if (r300->z_compression == RV350_Z_COMPRESS_88) - mult = 8; - else - mult = 4; - - height = ALIGN_DIVUP(fb->zsbuf->height, mult); - - offset_shift = 4; - offset_shift += (r300screen->caps.num_frag_pipes / 2); - stride = ALIGN_DIVUP(stride, r300screen->caps.num_frag_pipes); + struct r300_resource *tex; + CS_LOCALS(r300); - /* okay have width in pixels - divide by block width */ - stride = ALIGN_DIVUP(stride, mult); - /* have width in blocks - divide by number of fragment pipes screen width */ - /* 16 blocks per dword */ - stride = ALIGN_DIVUP(stride, 16); + tex = r300_resource(fb->zsbuf->texture); - for (i = 0; i < height; i++) { - offset = i * stride; - offset <<= offset_shift; - r300_emit_zmask_line_clear(r300, offset, stride, 0x0);//0xffffffff); - } + BEGIN_CS(size); + OUT_CS_PKT3(R300_PACKET3_3D_CLEAR_ZMASK, 2); + OUT_CS(0); + OUT_CS(tex->tex.zmask_dwords[fb->zsbuf->u.tex.level]); + OUT_CS(0); + END_CS; /* Mark the current zbuffer's zmask as in use. */ - tex->zmask_in_use[fb->zsbuf->u.tex.level] = TRUE; + r300->zmask_in_use = TRUE; + r300_mark_atom_dirty(r300, &r300->hyperz_state); } void r300_emit_ztop_state(struct r300_context* r300, @@ -1219,7 +1140,7 @@ boolean r300_emit_buffer_validate(struct r300_context *r300, (struct pipe_framebuffer_state*)r300->fb_state.state; struct r300_textures_state *texstate = (struct r300_textures_state*)r300->textures_state.state; - struct r300_texture *tex; + struct r300_resource *tex; unsigned i; boolean flushed = FALSE; @@ -1227,16 +1148,16 @@ validate: if (r300->fb_state.dirty) { /* Color buffers... */ for (i = 0; i < fb->nr_cbufs; i++) { - tex = r300_texture(fb->cbufs[i]->texture); - assert(tex && tex->buffer && "cbuf is marked, but NULL!"); - r300->rws->cs_add_reloc(r300->cs, tex->cs_buffer, 0, + tex = r300_resource(fb->cbufs[i]->texture); + assert(tex && tex->buf && "cbuf is marked, but NULL!"); + r300->rws->cs_add_reloc(r300->cs, tex->cs_buf, 0, r300_surface(fb->cbufs[i])->domain); } /* ...depth buffer... */ if (fb->zsbuf) { - tex = r300_texture(fb->zsbuf->texture); - assert(tex && tex->buffer && "zsbuf is marked, but NULL!"); - r300->rws->cs_add_reloc(r300->cs, tex->cs_buffer, 0, + tex = r300_resource(fb->zsbuf->texture); + assert(tex && tex->buf && "zsbuf is marked, but NULL!"); + r300->rws->cs_add_reloc(r300->cs, tex->cs_buf, 0, r300_surface(fb->zsbuf)->domain); } } @@ -1247,35 +1168,35 @@ validate: continue; } - tex = r300_texture(texstate->sampler_views[i]->base.texture); - r300->rws->cs_add_reloc(r300->cs, tex->cs_buffer, tex->domain, 0); + tex = r300_resource(texstate->sampler_views[i]->base.texture); + r300->rws->cs_add_reloc(r300->cs, tex->cs_buf, tex->domain, 0); } } /* ...occlusion query buffer... */ if (r300->query_current) - r300->rws->cs_add_reloc(r300->cs, r300->query_current->cs_buffer, + r300->rws->cs_add_reloc(r300->cs, r300->query_current->cs_buf, 0, r300->query_current->domain); /* ...vertex buffer for SWTCL path... */ if (r300->vbo) - r300->rws->cs_add_reloc(r300->cs, r300_buffer(r300->vbo)->cs_buf, - r300_buffer(r300->vbo)->domain, 0); + r300->rws->cs_add_reloc(r300->cs, r300_resource(r300->vbo)->cs_buf, + r300_resource(r300->vbo)->domain, 0); /* ...vertex buffers for HWTCL path... */ - if (do_validate_vertex_buffers) { - struct pipe_resource **buf = r300->valid_vertex_buffer; - struct pipe_resource **last = r300->valid_vertex_buffer + - r300->vertex_buffer_count; + if (do_validate_vertex_buffers && r300->vertex_arrays_dirty) { + struct pipe_resource **buf = r300->vbuf_mgr->real_vertex_buffer; + struct pipe_resource **last = r300->vbuf_mgr->real_vertex_buffer + + r300->vbuf_mgr->nr_real_vertex_buffers; for (; buf != last; buf++) { if (!*buf) continue; - r300->rws->cs_add_reloc(r300->cs, r300_buffer(*buf)->cs_buf, - r300_buffer(*buf)->domain, 0); + r300->rws->cs_add_reloc(r300->cs, r300_resource(*buf)->cs_buf, + r300_resource(*buf)->domain, 0); } } /* ...and index buffer for HWTCL path. */ if (index_buffer) - r300->rws->cs_add_reloc(r300->cs, r300_buffer(index_buffer)->cs_buf, - r300_buffer(index_buffer)->domain, 0); + r300->rws->cs_add_reloc(r300->cs, r300_resource(index_buffer)->cs_buf, + r300_resource(index_buffer)->domain, 0); /* Now do the validation. */ if (!r300->rws->cs_validate(r300->cs)) { diff --git a/src/gallium/drivers/r300/r300_flush.c b/src/gallium/drivers/r300/r300_flush.c index b250532ba92..c77cc08539d 100644 --- a/src/gallium/drivers/r300/r300_flush.c +++ b/src/gallium/drivers/r300/r300_flush.c @@ -36,16 +36,24 @@ static void r300_flush(struct pipe_context* pipe, struct pipe_fence_handle** fence) { struct r300_context *r300 = r300_context(pipe); - struct r300_query *query; struct r300_atom *atom; - struct r300_fence **rfence = (struct r300_fence**)fence; - - u_upload_flush(r300->upload_vb); - u_upload_flush(r300->upload_ib); + struct r300_winsys_bo **rfence = (struct r300_winsys_bo**)fence; if (r300->draw && !r300->draw_vbo_locked) r300_draw_flush_vbuf(r300); + if (rfence) { + /* Create a fence, which is a dummy BO. */ + *rfence = r300->rws->buffer_create(r300->rws, 1, 1, + PIPE_BIND_VERTEX_BUFFER, + PIPE_USAGE_STATIC, + R300_DOMAIN_GTT); + /* Add the fence as a dummy relocation. */ + r300->rws->cs_add_reloc(r300->cs, + r300->rws->buffer_get_cs_handle(*rfence), + R300_DOMAIN_GTT, R300_DOMAIN_GTT); + } + if (r300->dirty_hw) { r300_emit_hyperz_end(r300); r300_emit_query_end(r300); @@ -62,32 +70,29 @@ static void r300_flush(struct pipe_context* pipe, r300_mark_atom_dirty(r300, atom); } } + r300->vertex_arrays_dirty = TRUE; /* Unmark HWTCL state for SWTCL. */ if (!r300->screen->caps.has_tcl) { r300->vs_state.dirty = FALSE; r300->vs_constants.dirty = FALSE; } - - r300->validate_buffers = TRUE; - r300->upload_vb_validated = FALSE; - r300->upload_ib_validated = FALSE; } else { - /* Even if hw is not dirty, we should at least reset the CS in case - * the space checking failed for the first draw operation. */ - r300->rws->cs_flush(r300->cs); - } - - /* reset flushed query */ - foreach(query, &r300->query_list) { - query->flushed = TRUE; + if (rfence) { + /* We have to create a fence object, but the command stream is empty + * and we cannot emit an empty CS. We must write some regs then. */ + CS_LOCALS(r300); + OUT_CS_REG(RB3D_COLOR_CHANNEL_MASK, 0); + r300->rws->cs_flush(r300->cs); + } else { + /* Even if hw is not dirty, we should at least reset the CS in case + * the space checking failed for the first draw operation. */ + r300->rws->cs_flush(r300->cs); + } } - /* Create a new fence. */ - if (rfence) { - *rfence = CALLOC_STRUCT(r300_fence); - pipe_reference_init(&(*rfence)->reference, 1); - (*rfence)->ctx = r300; + if (flags & PIPE_FLUSH_FRAME) { + r300->rws->cs_sync_flush(r300->cs); } } diff --git a/src/gallium/drivers/r300/r300_fs.c b/src/gallium/drivers/r300/r300_fs.c index 6d4091dc87d..cec7473009a 100644 --- a/src/gallium/drivers/r300/r300_fs.c +++ b/src/gallium/drivers/r300/r300_fs.c @@ -152,13 +152,13 @@ static void get_external_state( for (i = 0; i < texstate->sampler_state_count; i++) { struct r300_sampler_state *s = texstate->sampler_states[i]; struct r300_sampler_view *v = texstate->sampler_views[i]; - struct r300_texture *t; + struct r300_resource *t; if (!s || !v) { continue; } - t = r300_texture(texstate->sampler_views[i]->base.texture); + t = r300_resource(texstate->sampler_views[i]->base.texture); if (s->state.compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { state->unit[i].compare_mode_enabled = 1; @@ -181,7 +181,7 @@ static void get_external_state( state->unit[i].non_normalized_coords = !s->state.normalized_coords; /* XXX this should probably take into account STR, not just S. */ - if (t->desc.is_npot) { + if (t->tex.is_npot) { switch (s->state.wrap_s) { case PIPE_TEX_WRAP_REPEAT: state->unit[i].wrap_mode = RC_WRAP_REPEAT; @@ -201,7 +201,7 @@ static void get_external_state( state->unit[i].wrap_mode = RC_WRAP_NONE; } - if (t->desc.b.b.target == PIPE_TEXTURE_3D) + if (t->b.b.b.target == PIPE_TEXTURE_3D) state->unit[i].clamp_and_scale_before_fetch = TRUE; } } @@ -298,44 +298,98 @@ static void r300_emit_fs_code_to_buffer( } } else { /* r300 */ struct r300_fragment_program_code *code = &generic_code->code.r300; - - shader->cb_code_size = 19 + - (r300->screen->caps.is_r400 ? 2 : 0) + - code->alu.length * 4 + - (code->tex.length ? (1 + code->tex.length) : 0) + - imm_count * 5; + unsigned int alu_length = code->alu.length; + unsigned int alu_iterations = ((alu_length - 1) / 64) + 1; + unsigned int tex_length = code->tex.length; + unsigned int tex_iterations = + tex_length > 0 ? ((tex_length - 1) / 32) + 1 : 0; + unsigned int iterations = + alu_iterations > tex_iterations ? alu_iterations : tex_iterations; + unsigned int bank = 0; + + shader->cb_code_size = 15 + + /* R400_US_CODE_BANK */ + (r300->screen->caps.is_r400 ? 2 * (iterations + 1): 0) + + /* R400_US_CODE_EXT */ + (r300->screen->caps.is_r400 ? 2 : 0) + + /* R300_US_ALU_{RGB,ALPHA}_{INST,ADDR}_0, R400_US_ALU_EXT_ADDR_0 */ + (code->r390_mode ? (5 * alu_iterations) : 4) + + /* R400_US_ALU_EXT_ADDR_[0-63] */ + (code->r390_mode ? (code->alu.length) : 0) + + /* R300_US_ALU_{RGB,ALPHA}_{INST,ADDR}_0 */ + code->alu.length * 4 + + /* R300_US_TEX_INST_0, R300_US_TEX_INST_[0-31] */ + (code->tex.length > 0 ? code->tex.length + tex_iterations : 0) + + imm_count * 5; NEW_CB(shader->cb_code, shader->cb_code_size); - if (r300->screen->caps.is_r400) - OUT_CB_REG(R400_US_CODE_BANK, 0); - OUT_CB_REG(R300_US_CONFIG, code->config); OUT_CB_REG(R300_US_PIXSIZE, code->pixsize); OUT_CB_REG(R300_US_CODE_OFFSET, code->code_offset); + if (code->r390_mode) { + OUT_CB_REG(R400_US_CODE_EXT, code->r400_code_offset_ext); + } else if (r300->screen->caps.is_r400) { + /* This register appears to affect shaders even if r390_mode is + * disabled, so it needs to be set to 0 for shaders that + * don't use r390_mode. */ + OUT_CB_REG(R400_US_CODE_EXT, 0); + } + OUT_CB_REG_SEQ(R300_US_CODE_ADDR_0, 4); OUT_CB_TABLE(code->code_addr, 4); - OUT_CB_REG_SEQ(R300_US_ALU_RGB_INST_0, code->alu.length); - for (i = 0; i < code->alu.length; i++) - OUT_CB(code->alu.inst[i].rgb_inst); + do { + unsigned int bank_alu_length = (alu_length < 64 ? alu_length : 64); + unsigned int bank_alu_offset = bank * 64; + unsigned int bank_tex_length = (tex_length < 32 ? tex_length : 32); + unsigned int bank_tex_offset = bank * 32; + + if (r300->screen->caps.is_r400) { + OUT_CB_REG(R400_US_CODE_BANK, code->r390_mode ? + (bank << R400_BANK_SHIFT) | R400_R390_MODE_ENABLE : 0);//2 + } + + if (bank_alu_length > 0) { + OUT_CB_REG_SEQ(R300_US_ALU_RGB_INST_0, bank_alu_length); + for (i = 0; i < bank_alu_length; i++) + OUT_CB(code->alu.inst[i + bank_alu_offset].rgb_inst); + + OUT_CB_REG_SEQ(R300_US_ALU_RGB_ADDR_0, bank_alu_length); + for (i = 0; i < bank_alu_length; i++) + OUT_CB(code->alu.inst[i + bank_alu_offset].rgb_addr); - OUT_CB_REG_SEQ(R300_US_ALU_RGB_ADDR_0, code->alu.length); - for (i = 0; i < code->alu.length; i++) - OUT_CB(code->alu.inst[i].rgb_addr); + OUT_CB_REG_SEQ(R300_US_ALU_ALPHA_INST_0, bank_alu_length); + for (i = 0; i < bank_alu_length; i++) + OUT_CB(code->alu.inst[i + bank_alu_offset].alpha_inst); - OUT_CB_REG_SEQ(R300_US_ALU_ALPHA_INST_0, code->alu.length); - for (i = 0; i < code->alu.length; i++) - OUT_CB(code->alu.inst[i].alpha_inst); + OUT_CB_REG_SEQ(R300_US_ALU_ALPHA_ADDR_0, bank_alu_length); + for (i = 0; i < bank_alu_length; i++) + OUT_CB(code->alu.inst[i + bank_alu_offset].alpha_addr); - OUT_CB_REG_SEQ(R300_US_ALU_ALPHA_ADDR_0, code->alu.length); - for (i = 0; i < code->alu.length; i++) - OUT_CB(code->alu.inst[i].alpha_addr); + if (code->r390_mode) { + OUT_CB_REG_SEQ(R400_US_ALU_EXT_ADDR_0, bank_alu_length); + for (i = 0; i < bank_alu_length; i++) + OUT_CB(code->alu.inst[i + bank_alu_offset].r400_ext_addr); + } + } + + if (bank_tex_length > 0) { + OUT_CB_REG_SEQ(R300_US_TEX_INST_0, bank_tex_length); + OUT_CB_TABLE(code->tex.inst + bank_tex_offset, bank_tex_length); + } + + alu_length -= bank_alu_length; + tex_length -= bank_tex_length; + bank++; + } while(code->r390_mode && (alu_length > 0 || tex_length > 0)); - if (code->tex.length) { - OUT_CB_REG_SEQ(R300_US_TEX_INST_0, code->tex.length); - OUT_CB_TABLE(code->tex.inst, code->tex.length); + /* R400_US_CODE_BANK needs to be reset to 0, otherwise some shaders + * will be rendered incorrectly. */ + if (r300->screen->caps.is_r400) { + OUT_CB_REG(R400_US_CODE_BANK, + code->r390_mode ? R400_R390_MODE_ENABLE : 0); } /* Emit immediates. */ @@ -384,12 +438,17 @@ static void r300_translate_fragment_shader( compiler.code = &shader->code; compiler.state = shader->compare_state; compiler.Base.is_r500 = r300->screen->caps.is_r500; + compiler.Base.is_r400 = r300->screen->caps.is_r400; compiler.Base.disable_optimizations = DBG_ON(r300, DBG_NO_OPT); compiler.Base.has_half_swizzles = TRUE; compiler.Base.has_presub = TRUE; - compiler.Base.max_temp_regs = compiler.Base.is_r500 ? 128 : 32; + compiler.Base.max_temp_regs = + compiler.Base.is_r500 ? 128 : (compiler.Base.is_r400 ? 64 : 32); compiler.Base.max_constants = compiler.Base.is_r500 ? 256 : 32; - compiler.Base.max_alu_insts = compiler.Base.is_r500 ? 512 : 64; + compiler.Base.max_alu_insts = + (compiler.Base.is_r500 || compiler.Base.is_r400) ? 512 : 64; + compiler.Base.max_tex_insts = + (compiler.Base.is_r500 || compiler.Base.is_r400) ? 512 : 32; compiler.AllocateHwInputs = &allocate_hardware_inputs; compiler.UserData = &shader->inputs; @@ -414,6 +473,13 @@ static void r300_translate_fragment_shader( r300_tgsi_to_rc(&ttr, tokens); + if (ttr.error) { + fprintf(stderr, "r300 FP: Cannot translate a shader. " + "Using a dummy shader instead.\n"); + r300_dummy_fragment_shader(r300, shader); + return; + } + if (!r300->screen->caps.is_r500 || compiler.Base.Program.Constants.Count > 200) { compiler.Base.remove_unused_constants = TRUE; diff --git a/src/gallium/drivers/r300/r300_hyperz.c b/src/gallium/drivers/r300/r300_hyperz.c index c22e307c679..873e0209d42 100644 --- a/src/gallium/drivers/r300/r300_hyperz.c +++ b/src/gallium/drivers/r300/r300_hyperz.c @@ -127,7 +127,7 @@ static boolean r300_can_hiz(struct r300_context *r300) z->current_func, dsa_state->z_stencil_control); return FALSE; } - } + } return TRUE; } @@ -137,9 +137,8 @@ static void r300_update_hyperz(struct r300_context* r300) (struct r300_hyperz_state*)r300->hyperz_state.state; struct pipe_framebuffer_state *fb = (struct pipe_framebuffer_state*)r300->fb_state.state; - struct r300_texture *zstex = - fb->zsbuf ? r300_texture(fb->zsbuf->texture) : NULL; - boolean zmask_in_use = FALSE; + struct r300_resource *zstex = + fb->zsbuf ? r300_resource(fb->zsbuf->texture) : NULL; boolean hiz_in_use = FALSE; z->gb_z_peq_config = 0; @@ -158,42 +157,40 @@ static void r300_update_hyperz(struct r300_context* r300) if (!r300->rws->get_value(r300->rws, R300_CAN_HYPERZ)) return; - zmask_in_use = zstex->zmask_in_use[fb->zsbuf->u.tex.level]; hiz_in_use = zstex->hiz_in_use[fb->zsbuf->u.tex.level]; - /* Z fastfill. */ - if (zmask_in_use) { - z->zb_bw_cntl |= R300_FAST_FILL_ENABLE; /* | R300_FORCE_COMPRESSED_STENCIL_VALUE_ENABLE;*/ - } - /* Zbuffer compression. */ - if (zmask_in_use && r300->z_compression) { - z->zb_bw_cntl |= R300_RD_COMP_ENABLE; - if (r300->z_decomp_rd == false) + if (r300->zmask_in_use && !r300->zmask_locked) { + z->zb_bw_cntl |= R300_FAST_FILL_ENABLE | + /*R300_FORCE_COMPRESSED_STENCIL_VALUE_ENABLE |*/ + R300_RD_COMP_ENABLE; + + if (!r300->zmask_decompress) { z->zb_bw_cntl |= R300_WR_COMP_ENABLE; + } } - /* RV350 and up optimizations. */ - /* The section 10.4.9 in the docs is a lie. */ - if (r300->z_compression == RV350_Z_COMPRESS_88) + + if (zstex->tex.zcomp8x8[fb->zsbuf->u.tex.level]) { z->gb_z_peq_config |= R300_GB_Z_PEQ_CONFIG_Z_PEQ_SIZE_8_8; + } + + if (hiz_in_use && r300_can_hiz(r300)) { + z->zb_bw_cntl |= R300_HIZ_ENABLE | + r300_get_hiz_min(r300); - if (hiz_in_use) { - bool can_hiz = r300_can_hiz(r300); - if (can_hiz) { - z->zb_bw_cntl |= R300_HIZ_ENABLE; - z->sc_hyperz |= R300_SC_HYPERZ_ENABLE; - z->sc_hyperz |= r300_get_sc_hz_max(r300); - z->zb_bw_cntl |= r300_get_hiz_min(r300); + z->sc_hyperz |= R300_SC_HYPERZ_ENABLE | + r300_get_sc_hz_max(r300); + + if (r300->screen->caps.is_r500) { + z->zb_bw_cntl |= R500_HIZ_FP_EXP_BITS_3 | + R500_HIZ_EQUAL_REJECT_ENABLE; } } /* R500-specific features and optimizations. */ if (r300->screen->caps.is_r500) { - z->zb_bw_cntl |= R500_HIZ_FP_EXP_BITS_3; - z->zb_bw_cntl |= - R500_HIZ_EQUAL_REJECT_ENABLE | - R500_PEQ_PACKING_ENABLE | - R500_COVERED_PTR_MASKING_ENABLE; + z->zb_bw_cntl |= R500_PEQ_PACKING_ENABLE | + R500_COVERED_PTR_MASKING_ENABLE; } } @@ -297,26 +294,10 @@ static void r300_update_hiz_clear(struct r300_context *r300) r300->hiz_clear.size = height * 4; } -static void r300_update_zmask_clear(struct r300_context *r300) -{ - struct pipe_framebuffer_state *fb = - (struct pipe_framebuffer_state*)r300->fb_state.state; - uint32_t height; - int mult; - - if (r300->z_compression == RV350_Z_COMPRESS_88) - mult = 8; - else - mult = 4; - - height = ALIGN_DIVUP(fb->zsbuf->height, mult); - - r300->zmask_clear.size = height * 4; -} - void r300_update_hyperz_state(struct r300_context* r300) { r300_update_ztop(r300); + if (r300->hyperz_state.dirty) { r300_update_hyperz(r300); } @@ -324,64 +305,24 @@ void r300_update_hyperz_state(struct r300_context* r300) if (r300->hiz_clear.dirty) { r300_update_hiz_clear(r300); } - if (r300->zmask_clear.dirty) { - r300_update_zmask_clear(r300); - } } void r300_hiz_alloc_block(struct r300_context *r300, struct r300_surface *surf) { - struct r300_texture *tex; + struct r300_resource *tex; uint32_t zsize, ndw; int level = surf->base.u.tex.level; - tex = r300_texture(surf->base.texture); + tex = r300_resource(surf->base.texture); if (tex->hiz_mem[level]) return; - zsize = tex->desc.layer_size_in_bytes[level]; - zsize /= util_format_get_blocksize(tex->desc.b.b.format); + zsize = tex->tex.layer_size_in_bytes[level]; + zsize /= util_format_get_blocksize(tex->b.b.b.format); ndw = ALIGN_DIVUP(zsize, 64); tex->hiz_mem[level] = u_mmAllocMem(r300->hiz_mm, ndw, 0, 0); - return; -} - -void r300_zmask_alloc_block(struct r300_context *r300, struct r300_surface *surf, int compress) -{ - int bsize = 256; - uint32_t zsize, ndw; - int level = surf->base.u.tex.level; - struct r300_texture *tex; - - tex = r300_texture(surf->base.texture); - - /* We currently don't handle decompression for 3D textures and cubemaps - * correctly. */ - if (tex->desc.b.b.target != PIPE_TEXTURE_1D && - tex->desc.b.b.target != PIPE_TEXTURE_2D && - tex->desc.b.b.target != PIPE_TEXTURE_RECT) - return; - - /* Cannot flush zmask of 16-bit zbuffers. */ - if (util_format_get_blocksizebits(tex->desc.b.b.format) == 16) - return; - - if (tex->zmask_mem[level]) - return; - - zsize = tex->desc.layer_size_in_bytes[level]; - zsize /= util_format_get_blocksize(tex->desc.b.b.format); - - /* each zmask dword represents 16 4x4 blocks - which is 256 pixels - or 16 8x8 depending on the gb peq flag = 1024 pixels */ - if (compress == RV350_Z_COMPRESS_88) - bsize = 1024; - - ndw = ALIGN_DIVUP(zsize, bsize); - tex->zmask_mem[level] = u_mmAllocMem(r300->zmask_mm, ndw, 0, 0); - return; } boolean r300_hyperz_init_mm(struct r300_context *r300) @@ -389,15 +330,9 @@ boolean r300_hyperz_init_mm(struct r300_context *r300) struct r300_screen* r300screen = r300->screen; int frag_pipes = r300screen->caps.num_frag_pipes; - r300->zmask_mm = u_mmInit(0, r300screen->caps.zmask_ram * frag_pipes); - if (!r300->zmask_mm) - return FALSE; - if (r300screen->caps.hiz_ram) { r300->hiz_mm = u_mmInit(0, r300screen->caps.hiz_ram * frag_pipes); if (!r300->hiz_mm) { - u_mmDestroy(r300->zmask_mm); - r300->zmask_mm = NULL; return FALSE; } } @@ -413,7 +348,4 @@ void r300_hyperz_destroy_mm(struct r300_context *r300) u_mmDestroy(r300->hiz_mm); r300->hiz_mm = NULL; } - - u_mmDestroy(r300->zmask_mm); - r300->zmask_mm = NULL; } diff --git a/src/gallium/drivers/r300/r300_hyperz.h b/src/gallium/drivers/r300/r300_hyperz.h index 30a23ec6493..d4c8e7c60a9 100644 --- a/src/gallium/drivers/r300/r300_hyperz.h +++ b/src/gallium/drivers/r300/r300_hyperz.h @@ -28,8 +28,8 @@ struct r300_context; void r300_update_hyperz_state(struct r300_context* r300); void r300_hiz_alloc_block(struct r300_context *r300, struct r300_surface *surf); -void r300_zmask_alloc_block(struct r300_context *r300, struct r300_surface *surf, int compress); boolean r300_hyperz_init_mm(struct r300_context *r300); void r300_hyperz_destroy_mm(struct r300_context *r300); + #endif diff --git a/src/gallium/drivers/r300/r300_query.c b/src/gallium/drivers/r300/r300_query.c index 6223e043210..717485f43cb 100644 --- a/src/gallium/drivers/r300/r300_query.c +++ b/src/gallium/drivers/r300/r300_query.c @@ -57,10 +57,10 @@ static struct pipe_query *r300_create_query(struct pipe_context *pipe, insert_at_tail(&r300->query_list, q); /* Open up the occlusion query buffer. */ - q->buffer = r300->rws->buffer_create(r300->rws, q->buffer_size, 4096, + q->buf = r300->rws->buffer_create(r300->rws, q->buffer_size, 4096, PIPE_BIND_CUSTOM, PIPE_USAGE_STREAM, q->domain); - q->cs_buffer = r300->rws->buffer_get_cs_handle(r300->rws, q->buffer); + q->cs_buf = r300->rws->buffer_get_cs_handle(q->buf); return (struct pipe_query*)q; } @@ -68,10 +68,9 @@ static struct pipe_query *r300_create_query(struct pipe_context *pipe, static void r300_destroy_query(struct pipe_context* pipe, struct pipe_query* query) { - struct r300_context *r300 = r300_context(pipe); struct r300_query* q = r300_query(query); - r300->rws->buffer_reference(r300->rws, &q->buffer, NULL); + r300_winsys_bo_reference(&q->buf, NULL); remove_from_list(q); FREE(query); } @@ -128,16 +127,12 @@ static boolean r300_get_query_result(struct pipe_context* pipe, { struct r300_context* r300 = r300_context(pipe); struct r300_query *q = r300_query(query); - unsigned flags, i; + unsigned i; uint32_t temp, *map; - uint64_t *result = (uint64_t*)vresult; - - if (!q->flushed) - pipe->flush(pipe, 0, NULL); - - flags = PIPE_TRANSFER_READ | (!wait ? PIPE_TRANSFER_DONTBLOCK : 0); - map = r300->rws->buffer_map(r300->rws, q->buffer, r300->cs, flags); + map = r300->rws->buffer_map(q->buf, r300->cs, + PIPE_TRANSFER_READ | + (!wait ? PIPE_TRANSFER_DONTBLOCK : 0)); if (!map) return FALSE; @@ -148,9 +143,9 @@ static boolean r300_get_query_result(struct pipe_context* pipe, map++; } - r300->rws->buffer_unmap(r300->rws, q->buffer); + r300->rws->buffer_unmap(q->buf); - *result = temp; + *((uint64_t*)vresult) = temp; return TRUE; } diff --git a/src/gallium/drivers/r300/r300_reg.h b/src/gallium/drivers/r300/r300_reg.h index d1154dee40a..1d93dab2ca2 100644 --- a/src/gallium/drivers/r300/r300_reg.h +++ b/src/gallium/drivers/r300/r300_reg.h @@ -2162,14 +2162,11 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. /* R4xx extended fragment shader registers. */ #define R400_US_ALU_EXT_ADDR_0 0x4ac0 /* up to 63 (0x4bbc) */ -# define R400_ADDR0_EXT_RGB_MSB_BIT 0x01 -# define R400_ADDR1_EXT_RGB_MSB_BIT 0x02 -# define R400_ADDR2_EXT_RGB_MSB_BIT 0x04 +# define R400_ADDR_EXT_RGB_MSB_BIT(x) (1 << (x)) # define R400_ADDRD_EXT_RGB_MSB_BIT 0x08 -# define R400_ADDR0_EXT_A_MSB_BIT 0x10 -# define R400_ADDR1_EXT_A_MSB_BIT 0x20 -# define R400_ADDR2_EXT_A_MSB_BIT 0x40 +# define R400_ADDR_EXT_A_MSB_BIT(x) (1 << ((x) + 4)) # define R400_ADDRD_EXT_A_MSB_BIT 0x80 + #define R400_US_CODE_BANK 0x46b8 # define R400_BANK_SHIFT 0 # define R400_BANK_MASK 0xf diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c index b35822c82f8..2ead8667bda 100644 --- a/src/gallium/drivers/r300/r300_render.c +++ b/src/gallium/drivers/r300/r300_render.c @@ -127,6 +127,20 @@ void r500_emit_index_bias(struct r300_context *r300, int index_bias) END_CS; } +static void r300_emit_draw_init(struct r300_context *r300, unsigned mode, + unsigned min_index, unsigned max_index) +{ + CS_LOCALS(r300); + + BEGIN_CS(5); + OUT_CS_REG(R300_GA_COLOR_CONTROL, + r300_provoking_vertex_fixes(r300, mode)); + OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2); + OUT_CS(max_index); + OUT_CS(min_index); + END_CS; +} + /* This function splits the index bias value into two parts: * - buffer_offset: the value that can be safely added to buffer offsets * in r300_emit_vertex_arrays (it must yield a positive offset when added to @@ -136,7 +150,7 @@ void r500_emit_index_bias(struct r300_context *r300, int index_bias) static void r300_split_index_bias(struct r300_context *r300, int index_bias, int *buffer_offset, int *index_offset) { - struct pipe_vertex_buffer *vb, *vbufs = r300->vertex_buffer; + struct pipe_vertex_buffer *vb, *vbufs = r300->vbuf_mgr->vertex_buffer; struct pipe_vertex_element *velem = r300->velems->velem; unsigned i, size; int max_neg_bias; @@ -235,24 +249,11 @@ static boolean r300_emit_states(struct r300_context *r300, /* Validate buffers and emit dirty state if needed. */ if (first_draw) { - if (r300->validate_buffers) { - if (!r300_emit_buffer_validate(r300, validate_vbos, - index_buffer)) { - fprintf(stderr, "r300: CS space validation failed. " - "(not enough memory?) Skipping rendering.\n"); - return FALSE; - } - - /* Consider the validation done only if everything was validated. */ - if (validate_vbos) { - r300->validate_buffers = FALSE; - if (r300->any_user_vbs) - r300->upload_vb_validated = TRUE; - if (r300->index_buffer.buffer && - r300_is_user_buffer(r300->index_buffer.buffer)) { - r300->upload_ib_validated = TRUE; - } - } + if (!r300_emit_buffer_validate(r300, validate_vbos, + index_buffer)) { + fprintf(stderr, "r300: CS space validation failed. " + "(not enough memory?) Skipping rendering.\n"); + return FALSE; } r300_emit_dirty_state(r300); @@ -263,9 +264,17 @@ static boolean r300_emit_states(struct r300_context *r300, r500_emit_index_bias(r300, 0); } - if (emit_vertex_arrays) + if (emit_vertex_arrays && + (r300->vertex_arrays_dirty || + r300->vertex_arrays_indexed != indexed || + r300->vertex_arrays_offset != buffer_offset)) { r300_emit_vertex_arrays(r300, buffer_offset, indexed); + r300->vertex_arrays_dirty = FALSE; + r300->vertex_arrays_indexed = indexed; + r300->vertex_arrays_offset = buffer_offset; + } + if (emit_vertex_arrays_swtcl) r300_emit_vertex_arrays_swtcl(r300, indexed); } @@ -294,7 +303,8 @@ static boolean r300_prepare_for_rendering(struct r300_context *r300, if (r300_reserve_cs_dwords(r300, flags, cs_dwords)) flags |= PREP_FIRST_DRAW; - return r300_emit_states(r300, flags, index_buffer, buffer_offset, index_bias); + return r300_emit_states(r300, flags, index_buffer, buffer_offset, + index_bias); } static boolean immd_is_good_idea(struct r300_context *r300, @@ -325,17 +335,12 @@ static boolean immd_is_good_idea(struct r300_context *r300, vbi = velem->vertex_buffer_index; if (!checked[vbi]) { - buf = r300->valid_vertex_buffer[vbi]; + buf = r300->vbuf_mgr->real_vertex_buffer[vbi]; - if (!(r300_buffer(buf)->domain & R300_DOMAIN_GTT)) { + if ((r300_resource(buf)->domain != R300_DOMAIN_GTT)) { return FALSE; } - if (r300_buffer_is_referenced(&r300->context, buf, - R300_REF_CS | R300_REF_HW)) { - /* It's a very bad idea to map it... */ - return FALSE; - } checked[vbi] = TRUE; } } @@ -346,10 +351,9 @@ static boolean immd_is_good_idea(struct r300_context *r300, * The HWTCL draw functions. * ****************************************************************************/ -static void r300_emit_draw_arrays_immediate(struct r300_context *r300, - unsigned mode, - unsigned start, - unsigned count) +static void r300_draw_arrays_immediate(struct r300_context *r300, + unsigned mode, unsigned start, + unsigned count) { struct pipe_vertex_element* velem; struct pipe_vertex_buffer* vbuf; @@ -360,7 +364,7 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300, unsigned vertex_size = r300->velems->vertex_size_dwords; /* The number of dwords for this draw operation. */ - unsigned dwords = 9 + count * vertex_size; + unsigned dwords = 4 + count * vertex_size; /* Size of the vertex element, in dwords. */ unsigned size[PIPE_MAX_ATTRIBS]; @@ -370,9 +374,8 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300, unsigned stride[PIPE_MAX_ATTRIBS]; /* Mapped vertex buffers. */ - uint32_t* map[PIPE_MAX_ATTRIBS]; + uint32_t* map[PIPE_MAX_ATTRIBS] = {0}; uint32_t* mapelem[PIPE_MAX_ATTRIBS]; - struct pipe_transfer* transfer[PIPE_MAX_ATTRIBS] = {0}; CS_LOCALS(r300); @@ -382,29 +385,25 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300, /* Calculate the vertex size, offsets, strides etc. and map the buffers. */ for (i = 0; i < vertex_element_count; i++) { velem = &r300->velems->velem[i]; - size[i] = r300->velems->hw_format_size[i] / 4; + size[i] = r300->velems->format_size[i] / 4; vbi = velem->vertex_buffer_index; - vbuf = &r300->vertex_buffer[vbi]; + vbuf = &r300->vbuf_mgr->vertex_buffer[vbi]; stride[i] = vbuf->stride / 4; /* Map the buffer. */ - if (!transfer[vbi]) { - map[vbi] = (uint32_t*)pipe_buffer_map(&r300->context, - r300->valid_vertex_buffer[vbi], - PIPE_TRANSFER_READ, - &transfer[vbi]); + if (!map[vbi]) { + map[vbi] = (uint32_t*)r300->rws->buffer_map( + r300_resource(r300->vbuf_mgr->real_vertex_buffer[vbi])->buf, + r300->cs, PIPE_TRANSFER_READ | PIPE_TRANSFER_UNSYNCHRONIZED); map[vbi] += (vbuf->buffer_offset / 4) + stride[i] * start; } mapelem[i] = map[vbi] + (velem->src_offset / 4); } + r300_emit_draw_init(r300, mode, 0, count-1); + BEGIN_CS(dwords); - OUT_CS_REG(R300_GA_COLOR_CONTROL, - r300_provoking_vertex_fixes(r300, mode)); OUT_CS_REG(R300_VAP_VTX_SIZE, vertex_size); - OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2); - OUT_CS(count - 1); - OUT_CS(0); OUT_CS_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, count * vertex_size); OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (count << 16) | r300_translate_primitive(mode)); @@ -421,9 +420,9 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300, for (i = 0; i < vertex_element_count; i++) { vbi = r300->velems->velem[i].vertex_buffer_index; - if (transfer[vbi]) { - pipe_buffer_unmap(&r300->context, transfer[vbi]); - transfer[vbi] = NULL; + if (map[vbi]) { + r300->rws->buffer_unmap(r300_resource(r300->vbuf_mgr->real_vertex_buffer[vbi])->buf); + map[vbi] = NULL; } } } @@ -441,15 +440,12 @@ static void r300_emit_draw_arrays(struct r300_context *r300, return; } - BEGIN_CS(7 + (alt_num_verts ? 2 : 0)); + r300_emit_draw_init(r300, mode, 0, count-1); + + BEGIN_CS(2 + (alt_num_verts ? 2 : 0)); if (alt_num_verts) { OUT_CS_REG(R500_VAP_ALT_NUM_VERTICES, count); } - OUT_CS_REG(R300_GA_COLOR_CONTROL, - r300_provoking_vertex_fixes(r300, mode)); - OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2); - OUT_CS(count - 1); - OUT_CS(0); OUT_CS_PKT3(R300_PACKET3_3D_DRAW_VBUF_2, 0); OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (count << 16) | r300_translate_primitive(mode) | @@ -471,22 +467,16 @@ static void r300_emit_draw_elements(struct r300_context *r300, boolean alt_num_verts = count > 65535; CS_LOCALS(r300); - if (count >= (1 << 24)) { + if (count >= (1 << 24) || maxIndex >= (1 << 24)) { fprintf(stderr, "r300: Got a huge number of vertices: %i, " - "refusing to render.\n", count); + "refusing to render (maxIndex: %i).\n", count, maxIndex); return; } DBG(r300, DBG_DRAW, "r300: Indexbuf of %u indices, min %u max %u\n", count, minIndex, maxIndex); - BEGIN_CS(5); - OUT_CS_REG(R300_GA_COLOR_CONTROL, - r300_provoking_vertex_fixes(r300, mode)); - OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2); - OUT_CS(maxIndex); - OUT_CS(minIndex); - END_CS; + r300_emit_draw_init(r300, mode, minIndex, maxIndex); /* If start is odd, render the first triangle with indices embedded * in the command stream. This will increase start by 3 and make it @@ -527,30 +517,105 @@ static void r300_emit_draw_elements(struct r300_context *r300, (alt_num_verts ? R500_VAP_VF_CNTL__USE_ALT_NUM_VERTS : 0)); } - /* INDX_BUFFER is a truly special packet3. - * Unlike most other packet3, where the offset is after the count, - * the order is reversed, so the relocation ends up carrying the - * size of the indexbuf instead of the offset. - */ OUT_CS_PKT3(R300_PACKET3_INDX_BUFFER, 2); OUT_CS(R300_INDX_BUFFER_ONE_REG_WR | (R300_VAP_PORT_IDX0 >> 2) | (0 << R300_INDX_BUFFER_SKIP_SHIFT)); OUT_CS(offset_dwords << 2); - OUT_CS_BUF_RELOC(indexBuffer, count_dwords); + OUT_CS(count_dwords); + OUT_CS_RELOC(r300_resource(indexBuffer)); + END_CS; +} + +static void r300_draw_elements_immediate(struct r300_context *r300, + int indexBias, unsigned minIndex, + unsigned maxIndex, unsigned mode, + unsigned start, unsigned count) +{ + uint8_t *ptr1; + uint16_t *ptr2; + uint32_t *ptr4; + unsigned index_size = r300->index_buffer.index_size; + unsigned i, count_dwords = index_size == 4 ? count : (count + 1) / 2; + CS_LOCALS(r300); + + /* 19 dwords for r300_draw_elements_immediate. Give up if the function fails. */ + if (!r300_prepare_for_rendering(r300, + PREP_FIRST_DRAW | PREP_VALIDATE_VBOS | PREP_EMIT_AOS | + PREP_INDEXED, NULL, 2+count_dwords, 0, indexBias)) + return; + r300_emit_draw_init(r300, mode, minIndex, maxIndex); + + BEGIN_CS(2 + count_dwords); + OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, count_dwords); + + switch (index_size) { + case 1: + ptr1 = r300_resource(r300->index_buffer.buffer)->b.user_ptr; + ptr1 += start; + + OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) | + r300_translate_primitive(mode)); + + if (indexBias && !r300->screen->caps.index_bias_supported) { + for (i = 0; i < count-1; i += 2) + OUT_CS(((ptr1[i+1] + indexBias) << 16) | + (ptr1[i] + indexBias)); + + if (count & 1) + OUT_CS(ptr1[i] + indexBias); + } else { + for (i = 0; i < count-1; i += 2) + OUT_CS(((ptr1[i+1]) << 16) | + (ptr1[i] )); + + if (count & 1) + OUT_CS(ptr1[i]); + } + break; + + case 2: + ptr2 = (uint16_t*)r300_resource(r300->index_buffer.buffer)->b.user_ptr; + ptr2 += start; + + OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) | + r300_translate_primitive(mode)); + + if (indexBias && !r300->screen->caps.index_bias_supported) { + for (i = 0; i < count-1; i += 2) + OUT_CS(((ptr2[i+1] + indexBias) << 16) | + (ptr2[i] + indexBias)); + + if (count & 1) + OUT_CS(ptr2[i] + indexBias); + } else { + OUT_CS_TABLE(ptr2, count_dwords); + } + break; + + case 4: + ptr4 = (uint32_t*)r300_resource(r300->index_buffer.buffer)->b.user_ptr; + ptr4 += start; + + OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) | + R300_VAP_VF_CNTL__INDEX_SIZE_32bit | + r300_translate_primitive(mode)); + + if (indexBias && !r300->screen->caps.index_bias_supported) { + for (i = 0; i < count; i++) + OUT_CS(ptr4[i] + indexBias); + } else { + OUT_CS_TABLE(ptr4, count_dwords); + } + break; + } END_CS; } -/* This is the fast-path drawing & emission for HW TCL. */ -static void r300_draw_range_elements(struct pipe_context* pipe, - int indexBias, - unsigned minIndex, - unsigned maxIndex, - unsigned mode, - unsigned start, - unsigned count) +static void r300_draw_elements(struct r300_context *r300, int indexBias, + unsigned minIndex, unsigned maxIndex, + unsigned mode, unsigned start, unsigned count) { - struct r300_context* r300 = r300_context(pipe); struct pipe_resource *indexBuffer = r300->index_buffer.buffer; unsigned indexSize = r300->index_buffer.index_size; struct pipe_resource* orgIndexBuffer = indexBuffer; @@ -570,30 +635,28 @@ static void r300_draw_range_elements(struct pipe_context* pipe, /* Fallback for misaligned ushort indices. */ if (indexSize == 2 && (start & 1) && - !r300_is_user_buffer(indexBuffer)) { - struct pipe_transfer *transfer; - struct pipe_resource *userbuf; - - uint16_t *ptr = pipe_buffer_map(pipe, indexBuffer, - PIPE_TRANSFER_READ, &transfer); + !r300_resource(indexBuffer)->b.user_ptr) { + /* If we got here, then orgIndexBuffer == indexBuffer. */ + uint16_t *ptr = r300->rws->buffer_map(r300_resource(orgIndexBuffer)->buf, + r300->cs, + PIPE_TRANSFER_READ | + PIPE_TRANSFER_UNSYNCHRONIZED); if (mode == PIPE_PRIM_TRIANGLES) { memcpy(indices3, ptr + start, 6); } else { /* Copy the mapped index buffer directly to the upload buffer. * The start index will be aligned simply from the fact that - * every sub-buffer in u_upload_mgr is aligned. */ - userbuf = pipe->screen->user_buffer_create(pipe->screen, - ptr, 0, - PIPE_BIND_INDEX_BUFFER); - indexBuffer = userbuf; - r300_upload_index_buffer(r300, &indexBuffer, indexSize, &start, count); - pipe_resource_reference(&userbuf, NULL); + * every sub-buffer in the upload buffer is aligned. */ + r300_upload_index_buffer(r300, &indexBuffer, indexSize, &start, + count, (uint8_t*)ptr); } - pipe_buffer_unmap(pipe, transfer); + r300->rws->buffer_unmap(r300_resource(orgIndexBuffer)->buf); } else { - if (r300_is_user_buffer(indexBuffer)) - r300_upload_index_buffer(r300, &indexBuffer, indexSize, &start, count); + if (r300_resource(indexBuffer)->b.user_ptr) + r300_upload_index_buffer(r300, &indexBuffer, indexSize, + &start, count, + r300_resource(indexBuffer)->b.user_ptr); } /* 19 dwords for emit_draw_elements. Give up if the function fails. */ @@ -607,7 +670,11 @@ static void r300_draw_range_elements(struct pipe_context* pipe, minIndex, maxIndex, mode, start, count, indices3); } else { do { - short_count = MIN2(count, 65534); + if (indexSize == 2 && (start & 1)) + short_count = MIN2(count, 65535); + else + short_count = MIN2(count, 65534); + r300_emit_draw_elements(r300, indexBuffer, indexSize, minIndex, maxIndex, mode, start, short_count, indices3); @@ -631,43 +698,38 @@ done: } } -static void r300_draw_arrays(struct pipe_context* pipe, unsigned mode, +static void r300_draw_arrays(struct r300_context *r300, unsigned mode, unsigned start, unsigned count) { - struct r300_context* r300 = r300_context(pipe); boolean alt_num_verts = r300->screen->caps.is_r500 && count > 65536 && r300->rws->get_value(r300->rws, R300_VID_DRM_2_3_0); unsigned short_count; - if (immd_is_good_idea(r300, count)) { - r300_emit_draw_arrays_immediate(r300, mode, start, count); + /* 9 spare dwords for emit_draw_arrays. Give up if the function fails. */ + if (!r300_prepare_for_rendering(r300, + PREP_FIRST_DRAW | PREP_VALIDATE_VBOS | PREP_EMIT_AOS, + NULL, 9, start, 0)) + return; + + if (alt_num_verts || count <= 65535) { + r300_emit_draw_arrays(r300, mode, count); } else { - /* 9 spare dwords for emit_draw_arrays. Give up if the function fails. */ - if (!r300_prepare_for_rendering(r300, - PREP_FIRST_DRAW | PREP_VALIDATE_VBOS | PREP_EMIT_AOS, - NULL, 9, start, 0)) - return; + do { + short_count = MIN2(count, 65535); + r300_emit_draw_arrays(r300, mode, short_count); - if (alt_num_verts || count <= 65535) { - r300_emit_draw_arrays(r300, mode, count); - } else { - do { - short_count = MIN2(count, 65535); - r300_emit_draw_arrays(r300, mode, short_count); - - start += short_count; - count -= short_count; - - /* 9 spare dwords for emit_draw_arrays. Give up if the function fails. */ - if (count) { - if (!r300_prepare_for_rendering(r300, - PREP_VALIDATE_VBOS | PREP_EMIT_AOS, NULL, 9, - start, 0)) - return; - } - } while (count); - } + start += short_count; + count -= short_count; + + /* 9 spare dwords for emit_draw_arrays. Give up if the function fails. */ + if (count) { + if (!r300_prepare_for_rendering(r300, + PREP_VALIDATE_VBOS | PREP_EMIT_AOS, NULL, 9, + start, 0)) + return; + } + } while (count); } } @@ -676,83 +738,45 @@ static void r300_draw_vbo(struct pipe_context* pipe, { struct r300_context* r300 = r300_context(pipe); unsigned count = info->count; - boolean translate = FALSE; + boolean buffers_updated, uploader_flushed; boolean indexed = info->indexed && r300->index_buffer.buffer; - unsigned min_index = 0; - unsigned max_index = r300->vertex_buffer_max_index; + unsigned start_indexed = info->start + r300->index_buffer.offset; + int max_index = MIN2(r300->vbuf_mgr->max_index, info->max_index); - if (r300->skip_rendering) { + if (r300->skip_rendering || + !u_trim_pipe_prim(info->mode, &count)) { return; } - if (!u_trim_pipe_prim(info->mode, &count)) { - return; + /* Start the vbuf manager and update buffers if needed. */ + u_vbuf_mgr_draw_begin(r300->vbuf_mgr, info, + &buffers_updated, &uploader_flushed); + if (buffers_updated) { + r300->vertex_arrays_dirty = TRUE; } - if (indexed) { - int real_min_index, real_max_index; - /* Compute the start for draw_elements, taking the offset into account. */ - unsigned start_indexed = - info->start + - (r300->index_buffer.offset / r300->index_buffer.index_size); - - assert(r300->index_buffer.offset % r300->index_buffer.index_size == 0); - - /* Index buffer range checking. */ - if ((start_indexed + count) * r300->index_buffer.index_size > - r300->index_buffer.buffer->width0) { - fprintf(stderr, "r300: Invalid index buffer range. Skipping rendering.\n"); - return; - } - - min_index = MAX2(min_index, info->min_index); - max_index = MIN2(max_index, info->max_index); - real_min_index = (int)min_index - info->index_bias; - real_max_index = (int)max_index - info->index_bias; - - if (max_index >= (1 << 24) - 1) { - fprintf(stderr, "r300: Invalid max_index: %i. Skipping rendering...\n", max_index); - return; - } - - r300_update_derived_state(r300); - - /* Set up the fallback for an incompatible vertex layout if needed. */ - if (r300->incompatible_vb_layout || r300->velems->incompatible_layout) { - r300_begin_vertex_translate(r300, real_min_index, real_max_index); - translate = TRUE; - } + /* Draw. */ + r300_update_derived_state(r300); - /* Upload vertex buffers. */ - if (r300->any_user_vbs) { - r300_upload_user_buffers(r300, real_min_index, real_max_index); + if (indexed) { + if (count <= 8 && + r300_resource(r300->index_buffer.buffer)->b.user_ptr) { + r300_draw_elements_immediate(r300, info->index_bias, + info->min_index, max_index, + info->mode, start_indexed, count); + } else { + r300_draw_elements(r300, info->index_bias, info->min_index, + max_index, info->mode, start_indexed, count); } - - r300_draw_range_elements(pipe, info->index_bias, min_index, max_index, - info->mode, start_indexed, count); } else { - min_index = MAX2(min_index, info->start); - max_index = MIN2(max_index, info->start + count - 1); - - r300_update_derived_state(r300); - - /* Set up the fallback for an incompatible vertex layout if needed. */ - if (r300->incompatible_vb_layout || r300->velems->incompatible_layout) { - r300_begin_vertex_translate(r300, min_index, max_index); - translate = TRUE; - } - - /* Upload vertex buffers. */ - if (r300->any_user_vbs) { - r300_upload_user_buffers(r300, min_index, max_index); + if (immd_is_good_idea(r300, count)) { + r300_draw_arrays_immediate(r300, info->mode, info->start, count); + } else { + r300_draw_arrays(r300, info->mode, info->start, count); } - - r300_draw_arrays(pipe, info->mode, info->start, count); } - if (translate) { - r300_end_vertex_translate(r300); - } + u_vbuf_mgr_draw_end(r300->vbuf_mgr); } /**************************************************************************** @@ -787,11 +811,12 @@ static void r300_swtcl_draw_vbo(struct pipe_context* pipe, (indexed ? PREP_INDEXED : 0), indexed ? 256 : 6); - for (i = 0; i < r300->vertex_buffer_count; i++) { - if (r300->vertex_buffer[i].buffer) { + for (i = 0; i < r300->vbuf_mgr->nr_vertex_buffers; i++) { + if (r300->vbuf_mgr->vertex_buffer[i].buffer) { void *buf = pipe_buffer_map(pipe, - r300->vertex_buffer[i].buffer, - PIPE_TRANSFER_READ, + r300->vbuf_mgr->vertex_buffer[i].buffer, + PIPE_TRANSFER_READ | + PIPE_TRANSFER_UNSYNCHRONIZED, &vb_transfer[i]); draw_set_mapped_vertex_buffer(r300->draw, i, buf); } @@ -799,7 +824,8 @@ static void r300_swtcl_draw_vbo(struct pipe_context* pipe, if (indexed) { indices = pipe_buffer_map(pipe, r300->index_buffer.buffer, - PIPE_TRANSFER_READ, &ib_transfer); + PIPE_TRANSFER_READ | + PIPE_TRANSFER_UNSYNCHRONIZED, &ib_transfer); } draw_set_mapped_index_buffer(r300->draw, indices); @@ -810,8 +836,8 @@ static void r300_swtcl_draw_vbo(struct pipe_context* pipe, draw_flush(r300->draw); r300->draw_vbo_locked = FALSE; - for (i = 0; i < r300->vertex_buffer_count; i++) { - if (r300->vertex_buffer[i].buffer) { + for (i = 0; i < r300->vbuf_mgr->nr_vertex_buffers; i++) { + if (r300->vbuf_mgr->vertex_buffer[i].buffer) { pipe_buffer_unmap(pipe, vb_transfer[i]); draw_set_mapped_vertex_buffer(r300->draw, i, NULL); } @@ -874,10 +900,10 @@ static boolean r300_render_allocate_vertices(struct vbuf_render* render, pipe_resource_reference(&r300->vbo, NULL); r300->vbo = pipe_buffer_create(screen, PIPE_BIND_VERTEX_BUFFER, + PIPE_USAGE_STREAM, R300_MAX_DRAW_VBO_SIZE); r300->draw_vbo_offset = 0; r300->draw_vbo_size = R300_MAX_DRAW_VBO_SIZE; - r300->validate_buffers = TRUE; } r300render->vertex_size = vertex_size; @@ -896,7 +922,8 @@ static void* r300_render_map_vertices(struct vbuf_render* render) r300render->vbo_ptr = pipe_buffer_map(&r300render->r300->context, r300->vbo, - PIPE_TRANSFER_WRITE, + PIPE_TRANSFER_WRITE | + PIPE_TRANSFER_UNSYNCHRONIZED, &r300render->vbo_transfer); assert(r300render->vbo_ptr); @@ -963,7 +990,7 @@ static void r300_render_draw_arrays(struct vbuf_render* render, if (r300->draw_first_emitted) { if (!r300_prepare_for_rendering(r300, PREP_FIRST_DRAW | PREP_EMIT_AOS_SWTCL, - NULL, 6, 0, 0)) + NULL, dwords, 0, 0)) return; } else { if (!r300_emit_states(r300, @@ -972,23 +999,6 @@ static void r300_render_draw_arrays(struct vbuf_render* render, return; } - /* Uncomment to dump all VBOs rendered through this interface. - * Slow and noisy! - ptr = pipe_buffer_map(&r300render->r300->context, - r300render->vbo, PIPE_TRANSFER_READ, - &r300render->vbo_transfer); - - for (i = 0; i < count; i++) { - printf("r300: Vertex %d\n", i); - draw_dump_emitted_vertex(&r300->vertex_info, ptr); - ptr += r300->vertex_info.size * 4; - printf("\n"); - } - - pipe_buffer_unmap(&r300render->r300->context, r300render->vbo, - r300render->vbo_transfer); - */ - BEGIN_CS(dwords); OUT_CS_REG(R300_GA_COLOR_CONTROL, r300_provoking_vertex_fixes(r300, r300render->prim)); @@ -1250,7 +1260,7 @@ static void r300_resource_resolve(struct pipe_context* pipe, aa->aaresolve_ctl = R300_RB3D_AARESOLVE_CTL_AARESOLVE_MODE_RESOLVE | R300_RB3D_AARESOLVE_CTL_AARESOLVE_ALPHA_AVERAGE; - r300->aa_state.size = 12; + r300->aa_state.size = 10; r300_mark_atom_dirty(r300, &r300->aa_state); /* Resolve the surface. */ diff --git a/src/gallium/drivers/r300/r300_render_translate.c b/src/gallium/drivers/r300/r300_render_translate.c index c48062c8084..f8c7558f4b4 100644 --- a/src/gallium/drivers/r300/r300_render_translate.c +++ b/src/gallium/drivers/r300/r300_render_translate.c @@ -20,207 +20,64 @@ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/** - * The functions below translate vertex and index buffers to the layout - * compatible with the hardware, so that all vertex and index fetches are - * DWORD-aligned and all used vertex and index formats are supported. - * For indices, an optional index offset is added to each index. - */ - #include "r300_context.h" -#include "translate/translate.h" #include "util/u_index_modify.h" +#include "util/u_upload_mgr.h" -/* XXX Optimization: use min_index and translate only that range. */ -/* XXX Use the uploader. */ -void r300_begin_vertex_translate(struct r300_context *r300, - int min_index, int max_index) -{ - struct pipe_context *pipe = &r300->context; - struct translate_key key = {0}; - struct translate_element *te; - unsigned tr_elem_index[PIPE_MAX_ATTRIBS] = {0}; - struct translate *tr; - struct r300_vertex_element_state *ve = r300->velems; - boolean vb_translated[PIPE_MAX_ATTRIBS] = {0}; - void *vb_map[PIPE_MAX_ATTRIBS] = {0}, *out_map; - struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS] = {0}, *out_transfer; - struct pipe_resource *out_buffer; - unsigned i, num_verts; - unsigned slot; - - /* Initialize the translate key, i.e. the recipe how vertices should be - * translated. */ - for (i = 0; i < ve->count; i++) { - struct pipe_vertex_buffer *vb = - &r300->vertex_buffer[ve->velem[i].vertex_buffer_index]; - enum pipe_format output_format = ve->hw_format[i]; - unsigned output_format_size = ve->hw_format_size[i]; - - /* Check for support. */ - if (ve->velem[i].src_format == ve->hw_format[i] && - (vb->buffer_offset + ve->velem[i].src_offset) % 4 == 0 && - vb->stride % 4 == 0) { - continue; - } - - /* Workaround for translate: output floats instead of halfs. */ - switch (output_format) { - case PIPE_FORMAT_R16_FLOAT: - output_format = PIPE_FORMAT_R32_FLOAT; - output_format_size = 4; - break; - case PIPE_FORMAT_R16G16_FLOAT: - output_format = PIPE_FORMAT_R32G32_FLOAT; - output_format_size = 8; - break; - case PIPE_FORMAT_R16G16B16_FLOAT: - output_format = PIPE_FORMAT_R32G32B32_FLOAT; - output_format_size = 12; - break; - case PIPE_FORMAT_R16G16B16A16_FLOAT: - output_format = PIPE_FORMAT_R32G32B32A32_FLOAT; - output_format_size = 16; - break; - default:; - } - - /* Add this vertex element. */ - te = &key.element[key.nr_elements]; - /*te->type; - te->instance_divisor;*/ - te->input_buffer = ve->velem[i].vertex_buffer_index; - te->input_format = ve->velem[i].src_format; - te->input_offset = vb->buffer_offset + ve->velem[i].src_offset; - te->output_format = output_format; - te->output_offset = key.output_stride; - - key.output_stride += output_format_size; - vb_translated[ve->velem[i].vertex_buffer_index] = TRUE; - tr_elem_index[i] = key.nr_elements; - key.nr_elements++; - } - - /* Get a translate object. */ - tr = translate_cache_find(r300->tran.translate_cache, &key); - - /* Map buffers we want to translate. */ - for (i = 0; i < r300->vertex_buffer_count; i++) { - if (vb_translated[i]) { - struct pipe_vertex_buffer *vb = &r300->vertex_buffer[i]; - - vb_map[i] = pipe_buffer_map(pipe, vb->buffer, - PIPE_TRANSFER_READ, &vb_transfer[i]); - - tr->set_buffer(tr, i, vb_map[i], vb->stride, max_index); - } - } - - /* Create and map the output buffer. */ - num_verts = max_index + 1; - - out_buffer = pipe_buffer_create(&r300->screen->screen, - PIPE_BIND_VERTEX_BUFFER, - key.output_stride * num_verts); - - out_map = pipe_buffer_map(pipe, out_buffer, PIPE_TRANSFER_WRITE, - &out_transfer); - - /* Translate. */ - tr->run(tr, 0, num_verts, 0, out_map); - - /* Unmap all buffers. */ - for (i = 0; i < r300->vertex_buffer_count; i++) { - if (vb_translated[i]) { - pipe_buffer_unmap(pipe, vb_transfer[i]); - } - } - - pipe_buffer_unmap(pipe, out_transfer); - - /* Setup the new vertex buffer in the first free slot. */ - slot = ~0; - for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { - struct pipe_vertex_buffer *vb = &r300->vertex_buffer[i]; - - if (!vb->buffer) { - pipe_resource_reference(&r300->valid_vertex_buffer[i], out_buffer); - vb->buffer_offset = 0; - vb->stride = key.output_stride; - slot = i; - /* XXX probably need to preserve the real count for u_blitter_save_*. */ - r300->vertex_buffer_count = MAX2(r300->vertex_buffer_count, i+1); - r300->validate_buffers = TRUE; - break; - } - } - /* XXX This may fail. */ - assert(slot != ~0); - - /* Save and replace vertex elements. */ - { - struct pipe_vertex_element new_velems[PIPE_MAX_ATTRIBS]; - - r300->tran.saved_velems = r300->velems; - - for (i = 0; i < ve->count; i++) { - if (vb_translated[ve->velem[i].vertex_buffer_index]) { - te = &key.element[tr_elem_index[i]]; - new_velems[i].instance_divisor = ve->velem[i].instance_divisor; - new_velems[i].src_format = te->output_format; - new_velems[i].src_offset = te->output_offset; - new_velems[i].vertex_buffer_index = slot; - } else { - memcpy(&new_velems[i], &ve->velem[i], - sizeof(struct pipe_vertex_element)); - } - } - - r300->tran.new_velems = - pipe->create_vertex_elements_state(pipe, ve->count, new_velems); - pipe->bind_vertex_elements_state(pipe, r300->tran.new_velems); - } - - pipe_resource_reference(&out_buffer, NULL); -} -void r300_end_vertex_translate(struct r300_context *r300) -{ - struct pipe_context *pipe = &r300->context; - - /* Restore vertex elements. */ - pipe->bind_vertex_elements_state(pipe, r300->tran.saved_velems); - pipe->delete_vertex_elements_state(pipe, r300->tran.new_velems); -} - -/* XXX Use the uploader. */ void r300_translate_index_buffer(struct r300_context *r300, struct pipe_resource **index_buffer, unsigned *index_size, unsigned index_offset, unsigned *start, unsigned count) { + struct pipe_resource *out_buffer = NULL; + unsigned out_offset; + void *ptr; + boolean flushed; + switch (*index_size) { - case 1: - util_shorten_ubyte_elts(&r300->context, index_buffer, index_offset, *start, count); - *index_size = 2; - *start = 0; - r300->validate_buffers = TRUE; - break; + case 1: + u_upload_alloc(r300->vbuf_mgr->uploader, 0, count * 2, + &out_offset, &out_buffer, &flushed, &ptr); + + util_shorten_ubyte_elts_to_userptr( + &r300->context, *index_buffer, index_offset, + *start, count, ptr); + + *index_buffer = NULL; + pipe_resource_reference(index_buffer, out_buffer); + *index_size = 2; + *start = out_offset / 2; + break; + + case 2: + if (index_offset) { + u_upload_alloc(r300->vbuf_mgr->uploader, 0, count * 2, + &out_offset, &out_buffer, &flushed, &ptr); + + util_rebuild_ushort_elts_to_userptr(&r300->context, *index_buffer, + index_offset, *start, + count, ptr); + + *index_buffer = NULL; + pipe_resource_reference(index_buffer, out_buffer); + *start = out_offset / 2; + } + break; - case 2: - if (index_offset) { - util_rebuild_ushort_elts(&r300->context, index_buffer, index_offset, *start, count); - *start = 0; - r300->validate_buffers = TRUE; - } - break; + case 4: + if (index_offset) { + u_upload_alloc(r300->vbuf_mgr->uploader, 0, count * 4, + &out_offset, &out_buffer, &flushed, &ptr); - case 4: - if (index_offset) { - util_rebuild_uint_elts(&r300->context, index_buffer, index_offset, *start, count); - *start = 0; - r300->validate_buffers = TRUE; - } - break; + util_rebuild_uint_elts_to_userptr(&r300->context, *index_buffer, + index_offset, *start, + count, ptr); + + *index_buffer = NULL; + pipe_resource_reference(index_buffer, out_buffer); + *start = out_offset / 4; + } + break; } } diff --git a/src/gallium/drivers/r300/r300_resource.c b/src/gallium/drivers/r300/r300_resource.c index dd1df970594..f3d8c5b889f 100644 --- a/src/gallium/drivers/r300/r300_resource.c +++ b/src/gallium/drivers/r300/r300_resource.c @@ -38,26 +38,22 @@ r300_resource_create(struct pipe_screen *screen, } -static struct pipe_resource * -r300_resource_from_handle(struct pipe_screen * screen, - const struct pipe_resource *templ, - struct winsys_handle *whandle) +static unsigned r300_resource_is_referenced_by_cs(struct pipe_context *context, + struct pipe_resource *buf, + unsigned level, int layer) { - if (templ->target == PIPE_BUFFER) - return NULL; - else - return r300_texture_from_handle(screen, templ, whandle); + return r300_buffer_is_referenced(context, buf); } void r300_init_resource_functions(struct r300_context *r300) { r300->context.get_transfer = u_get_transfer_vtbl; r300->context.transfer_map = u_transfer_map_vtbl; - r300->context.transfer_flush_region = u_transfer_flush_region_vtbl; + r300->context.transfer_flush_region = u_default_transfer_flush_region; r300->context.transfer_unmap = u_transfer_unmap_vtbl; r300->context.transfer_destroy = u_transfer_destroy_vtbl; r300->context.transfer_inline_write = u_transfer_inline_write_vtbl; - r300->context.is_resource_referenced = u_is_resource_referenced_vtbl; + r300->context.is_resource_referenced = r300_resource_is_referenced_by_cs; r300->context.create_surface = r300_create_surface; r300->context.surface_destroy = r300_surface_destroy; } @@ -65,8 +61,8 @@ void r300_init_resource_functions(struct r300_context *r300) void r300_init_screen_resource_functions(struct r300_screen *r300screen) { r300screen->screen.resource_create = r300_resource_create; - r300screen->screen.resource_from_handle = r300_resource_from_handle; - r300screen->screen.resource_get_handle = u_resource_get_handle_vtbl; + r300screen->screen.resource_from_handle = r300_texture_from_handle; + r300screen->screen.resource_get_handle = r300_resource_get_handle; r300screen->screen.resource_destroy = u_resource_destroy_vtbl; r300screen->screen.user_buffer_create = r300_user_buffer_create; } diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c index c75aeaa10a7..77a9c6ad86f 100644 --- a/src/gallium/drivers/r300/r300_screen.c +++ b/src/gallium/drivers/r300/r300_screen.c @@ -34,10 +34,6 @@ #include "draw/draw_context.h" -#ifdef HAVE_LLVM -#include "gallivm/lp_bld_init.h" -#endif - /* Return the identifier behind whom the brave coders responsible for this * amalgamation of code, sweat, and duct tape, routinely obscure their names. * @@ -87,12 +83,8 @@ static const char* r300_get_name(struct pipe_screen* pscreen) static int r300_get_param(struct pipe_screen* pscreen, enum pipe_cap param) { struct r300_screen* r300screen = r300_screen(pscreen); - boolean is_r400 = r300screen->caps.is_r400; boolean is_r500 = r300screen->caps.is_r500; - /* XXX extended shader capabilities of r400 unimplemented */ - is_r400 = FALSE; - switch (param) { /* Supported features (boolean caps). */ case PIPE_CAP_NPOT_TEXTURES: @@ -129,11 +121,13 @@ static int r300_get_param(struct pipe_screen* pscreen, enum pipe_cap param) case PIPE_CAP_DUAL_SOURCE_BLEND: case PIPE_CAP_INDEP_BLEND_ENABLE: case PIPE_CAP_INDEP_BLEND_FUNC: - case PIPE_CAP_DEPTH_CLAMP: /* XXX implemented, but breaks Regnum Online */ + case PIPE_CAP_DEPTH_CLAMP: case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE: case PIPE_CAP_SHADER_STENCIL_EXPORT: case PIPE_CAP_STREAM_OUTPUT: case PIPE_CAP_PRIMITIVE_RESTART: + case PIPE_CAP_INSTANCED_DRAWING: + case PIPE_CAP_ARRAY_TEXTURES: return 0; /* Texturing. */ @@ -175,9 +169,6 @@ static int r300_get_shader_param(struct pipe_screen *pscreen, unsigned shader, e boolean is_r400 = r300screen->caps.is_r400; boolean is_r500 = r300screen->caps.is_r500; - /* XXX extended shader capabilities of r400 unimplemented */ - is_r400 = FALSE; - switch (shader) { case PIPE_SHADER_FRAGMENT: @@ -407,6 +398,7 @@ static void r300_destroy_screen(struct pipe_screen* pscreen) struct r300_winsys_screen *rws = r300_winsys_screen(pscreen); util_slab_destroy(&r300screen->pool_buffers); + pipe_mutex_destroy(r300screen->num_contexts_mutex); if (rws) rws->destroy(rws); @@ -418,32 +410,28 @@ static void r300_fence_reference(struct pipe_screen *screen, struct pipe_fence_handle **ptr, struct pipe_fence_handle *fence) { - struct r300_fence **oldf = (struct r300_fence**)ptr; - struct r300_fence *newf = (struct r300_fence*)fence; - - if (pipe_reference(&(*oldf)->reference, &newf->reference)) - FREE(*oldf); - - *ptr = fence; + r300_winsys_bo_reference((struct r300_winsys_bo**)ptr, + (struct r300_winsys_bo*)fence); } static int r300_fence_signalled(struct pipe_screen *screen, struct pipe_fence_handle *fence, unsigned flags) { - struct r300_fence *rfence = (struct r300_fence*)fence; + struct r300_winsys_screen *rws = r300_screen(screen)->rws; + struct r300_winsys_bo *rfence = (struct r300_winsys_bo*)fence; - return rfence->signalled ? 0 : 1; /* 0 == success */ + return !rws->buffer_is_busy(rfence) ? 0 : 1; /* 0 == success */ } static int r300_fence_finish(struct pipe_screen *screen, struct pipe_fence_handle *fence, unsigned flags) { - struct r300_fence *rfence = (struct r300_fence*)fence; + struct r300_winsys_screen *rws = r300_screen(screen)->rws; + struct r300_winsys_bo *rfence = (struct r300_winsys_bo*)fence; - r300_finish(rfence->ctx); - rfence->signalled = TRUE; + rws->buffer_wait(rfence); return 0; /* 0 == success */ } @@ -463,12 +451,19 @@ struct pipe_screen* r300_screen_create(struct r300_winsys_screen *rws) r300_init_debug(r300screen); r300_parse_chipset(&r300screen->caps); + if (SCREEN_DBG_ON(r300screen, DBG_NO_ZMASK)) + r300screen->caps.zmask_ram = 0; + if (SCREEN_DBG_ON(r300screen, DBG_NO_HIZ)) + r300screen->caps.hiz_ram = 0; + r300screen->caps.index_bias_supported = r300screen->caps.is_r500 && rws->get_value(rws, R300_VID_DRM_2_3_0); + pipe_mutex_init(r300screen->num_contexts_mutex); + util_slab_create(&r300screen->pool_buffers, - sizeof(struct r300_buffer), 64, + sizeof(struct r300_resource), 64, UTIL_SLAB_SINGLETHREADED); r300screen->rws = rws; @@ -490,9 +485,5 @@ struct pipe_screen* r300_screen_create(struct r300_winsys_screen *rws) util_format_s3tc_init(); -#ifdef HAVE_LLVM - lp_build_init(); -#endif - return &r300screen->screen; } diff --git a/src/gallium/drivers/r300/r300_screen.h b/src/gallium/drivers/r300/r300_screen.h index 752f53b7579..576f9c1f4a9 100644 --- a/src/gallium/drivers/r300/r300_screen.h +++ b/src/gallium/drivers/r300/r300_screen.h @@ -52,6 +52,7 @@ struct r300_screen { /* The number of created contexts to know whether we have multiple * contexts or not. */ int num_contexts; + pipe_mutex num_contexts_mutex; }; @@ -94,6 +95,7 @@ r300_winsys_screen(struct pipe_screen *screen) { #define DBG_HYPERZ (1 << 12) #define DBG_SCISSOR (1 << 13) #define DBG_UPLOAD (1 << 14) +#define DBG_INFO (1 << 15) /* Features. */ #define DBG_ANISOHQ (1 << 16) #define DBG_NO_TILING (1 << 17) @@ -101,6 +103,8 @@ r300_winsys_screen(struct pipe_screen *screen) { #define DBG_FAKE_OCC (1 << 19) #define DBG_NO_OPT (1 << 20) #define DBG_NO_CBZB (1 << 21) +#define DBG_NO_ZMASK (1 << 22) +#define DBG_NO_HIZ (1 << 23) /* Statistics. */ #define DBG_P_STAT (1 << 25) /*@}*/ diff --git a/src/gallium/drivers/r300/r300_screen_buffer.c b/src/gallium/drivers/r300/r300_screen_buffer.c index cc3c1d7687e..1045911f3ae 100644 --- a/src/gallium/drivers/r300/r300_screen_buffer.c +++ b/src/gallium/drivers/r300/r300_screen_buffer.c @@ -34,117 +34,50 @@ #include "r300_winsys.h" unsigned r300_buffer_is_referenced(struct pipe_context *context, - struct pipe_resource *buf, - enum r300_reference_domain domain) + struct pipe_resource *buf) { struct r300_context *r300 = r300_context(context); - struct r300_buffer *rbuf = r300_buffer(buf); + struct r300_resource *rbuf = r300_resource(buf); - if (r300_is_user_buffer(buf)) + if (rbuf->b.user_ptr || rbuf->constant_buffer) return PIPE_UNREFERENCED; - if (r300->rws->cs_is_buffer_referenced(r300->cs, rbuf->cs_buf, domain)) + if (r300->rws->cs_is_buffer_referenced(r300->cs, rbuf->cs_buf)) return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; return PIPE_UNREFERENCED; } -static unsigned r300_buffer_is_referenced_by_cs(struct pipe_context *context, - struct pipe_resource *buf, - unsigned level, int layer) -{ - return r300_buffer_is_referenced(context, buf, R300_REF_CS); -} - void r300_upload_index_buffer(struct r300_context *r300, struct pipe_resource **index_buffer, unsigned index_size, unsigned *start, - unsigned count) + unsigned count, uint8_t *ptr) { unsigned index_offset; - uint8_t *ptr = r300_buffer(*index_buffer)->user_buffer; boolean flushed; *index_buffer = NULL; - u_upload_data(r300->upload_ib, + u_upload_data(r300->vbuf_mgr->uploader, 0, count * index_size, ptr + (*start * index_size), &index_offset, index_buffer, &flushed); *start = index_offset / index_size; - - if (flushed || !r300->upload_ib_validated) { - r300->upload_ib_validated = FALSE; - r300->validate_buffers = TRUE; - } -} - -void r300_upload_user_buffers(struct r300_context *r300, - int min_index, int max_index) -{ - int i, nr = r300->velems->count; - unsigned count = max_index + 1 - min_index; - boolean flushed; - boolean uploaded[16] = {0}; - - for (i = 0; i < nr; i++) { - unsigned index = r300->velems->velem[i].vertex_buffer_index; - struct pipe_vertex_buffer *vb = &r300->vertex_buffer[index]; - struct r300_buffer *userbuf = r300_buffer(vb->buffer); - - if (userbuf && userbuf->user_buffer && !uploaded[index]) { - unsigned first, size; - - if (vb->stride) { - first = vb->stride * min_index; - size = vb->stride * count; - } else { - first = 0; - size = r300->velems->hw_format_size[i]; - } - - DBG(r300, DBG_UPLOAD, - "Uploading %i bytes, index: %i, buffer: %p, userptr: %p " - "offset: %i, stride: %i.\n", - size, index, userbuf, userbuf->user_buffer, - vb->buffer_offset, vb->stride); - - u_upload_data(r300->upload_vb, first, size, - userbuf->user_buffer + first, - &vb->buffer_offset, - &r300->valid_vertex_buffer[index], - &flushed); - - vb->buffer_offset -= first; - - r300->vertex_arrays_dirty = TRUE; - - if (flushed || !r300->upload_vb_validated) { - r300->upload_vb_validated = FALSE; - r300->validate_buffers = TRUE; - } - uploaded[index] = TRUE; - } else { - assert(r300->valid_vertex_buffer[index]); - } - } - DBG(r300, DBG_UPLOAD, "-------\n"); } static void r300_buffer_destroy(struct pipe_screen *screen, struct pipe_resource *buf) { struct r300_screen *r300screen = r300_screen(screen); - struct r300_buffer *rbuf = r300_buffer(buf); - struct r300_winsys_screen *rws = r300screen->rws; + struct r300_resource *rbuf = r300_resource(buf); if (rbuf->constant_buffer) FREE(rbuf->constant_buffer); if (rbuf->buf) - rws->buffer_reference(rws, &rbuf->buf, NULL); + r300_winsys_bo_reference(&rbuf->buf, NULL); util_slab_free(&r300screen->pool_buffers, rbuf); } @@ -188,15 +121,15 @@ r300_buffer_transfer_map( struct pipe_context *pipe, struct r300_context *r300 = r300_context(pipe); struct r300_screen *r300screen = r300_screen(pipe->screen); struct r300_winsys_screen *rws = r300screen->rws; - struct r300_buffer *rbuf = r300_buffer(transfer->resource); + struct r300_resource *rbuf = r300_resource(transfer->resource); uint8_t *map; - if (rbuf->user_buffer) - return (uint8_t *) rbuf->user_buffer + transfer->box.x; + if (rbuf->b.user_ptr) + return (uint8_t *) rbuf->b.user_ptr + transfer->box.x; if (rbuf->constant_buffer) return (uint8_t *) rbuf->constant_buffer + transfer->box.x; - map = rws->buffer_map(rws, rbuf->buf, r300->cs, transfer->usage); + map = rws->buffer_map(rbuf->buf, r300->cs, transfer->usage); if (map == NULL) return NULL; @@ -204,22 +137,15 @@ r300_buffer_transfer_map( struct pipe_context *pipe, return map + transfer->box.x; } -static void r300_buffer_transfer_flush_region( struct pipe_context *pipe, - struct pipe_transfer *transfer, - const struct pipe_box *box) -{ - /* no-op */ -} - static void r300_buffer_transfer_unmap( struct pipe_context *pipe, struct pipe_transfer *transfer ) { struct r300_screen *r300screen = r300_screen(pipe->screen); struct r300_winsys_screen *rws = r300screen->rws; - struct r300_buffer *rbuf = r300_buffer(transfer->resource); + struct r300_resource *rbuf = r300_resource(transfer->resource); if (rbuf->buf) { - rws->buffer_unmap(rws, rbuf->buf); + rws->buffer_unmap(rbuf->buf); } } @@ -234,32 +160,32 @@ static void r300_buffer_transfer_inline_write(struct pipe_context *pipe, { struct r300_context *r300 = r300_context(pipe); struct r300_winsys_screen *rws = r300->screen->rws; - struct r300_buffer *rbuf = r300_buffer(resource); + struct r300_resource *rbuf = r300_resource(resource); uint8_t *map = NULL; if (rbuf->constant_buffer) { memcpy(rbuf->constant_buffer + box->x, data, box->width); return; } - assert(rbuf->user_buffer == NULL); + assert(rbuf->b.user_ptr == NULL); - map = rws->buffer_map(rws, rbuf->buf, r300->cs, + map = rws->buffer_map(rbuf->buf, r300->cs, PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD | usage); memcpy(map + box->x, data, box->width); - rws->buffer_unmap(rws, rbuf->buf); + rws->buffer_unmap(rbuf->buf); } -struct u_resource_vtbl r300_buffer_vtbl = +static const struct u_resource_vtbl r300_buffer_vtbl = { - u_default_resource_get_handle, /* get_handle */ + NULL, /* get_handle */ r300_buffer_destroy, /* resource_destroy */ - r300_buffer_is_referenced_by_cs, /* is_buffer_referenced */ + NULL, /* is_buffer_referenced */ r300_buffer_get_transfer, /* get_transfer */ r300_buffer_transfer_destroy, /* transfer_destroy */ r300_buffer_transfer_map, /* transfer_map */ - r300_buffer_transfer_flush_region, /* transfer_flush_region */ + NULL, /* transfer_flush_region */ r300_buffer_transfer_unmap, /* transfer_unmap */ r300_buffer_transfer_inline_write /* transfer_inline_write */ }; @@ -268,42 +194,41 @@ struct pipe_resource *r300_buffer_create(struct pipe_screen *screen, const struct pipe_resource *templ) { struct r300_screen *r300screen = r300_screen(screen); - struct r300_buffer *rbuf; + struct r300_resource *rbuf; unsigned alignment = 16; rbuf = util_slab_alloc(&r300screen->pool_buffers); - rbuf->magic = R300_BUFFER_MAGIC; - - rbuf->b.b = *templ; - rbuf->b.vtbl = &r300_buffer_vtbl; - pipe_reference_init(&rbuf->b.b.reference, 1); - rbuf->b.b.screen = screen; + rbuf->b.b.b = *templ; + rbuf->b.b.vtbl = &r300_buffer_vtbl; + pipe_reference_init(&rbuf->b.b.b.reference, 1); + rbuf->b.b.b.screen = screen; + rbuf->b.user_ptr = NULL; rbuf->domain = R300_DOMAIN_GTT; rbuf->buf = NULL; + rbuf->buf_size = templ->width0; rbuf->constant_buffer = NULL; - rbuf->user_buffer = NULL; /* Alloc constant buffers in RAM. */ if (templ->bind & PIPE_BIND_CONSTANT_BUFFER) { rbuf->constant_buffer = MALLOC(templ->width0); - return &rbuf->b.b; + return &rbuf->b.b.b; } rbuf->buf = r300screen->rws->buffer_create(r300screen->rws, - rbuf->b.b.width0, alignment, - rbuf->b.b.bind, rbuf->b.b.usage, + rbuf->b.b.b.width0, alignment, + rbuf->b.b.b.bind, rbuf->b.b.b.usage, rbuf->domain); - rbuf->cs_buf = - r300screen->rws->buffer_get_cs_handle(r300screen->rws, rbuf->buf); - if (!rbuf->buf) { util_slab_free(&r300screen->pool_buffers, rbuf); return NULL; } - return &rbuf->b.b; + rbuf->cs_buf = + r300screen->rws->buffer_get_cs_handle(rbuf->buf); + + return &rbuf->b.b.b; } struct pipe_resource *r300_user_buffer_create(struct pipe_screen *screen, @@ -311,27 +236,26 @@ struct pipe_resource *r300_user_buffer_create(struct pipe_screen *screen, unsigned bind) { struct r300_screen *r300screen = r300_screen(screen); - struct r300_buffer *rbuf; + struct r300_resource *rbuf; rbuf = util_slab_alloc(&r300screen->pool_buffers); - rbuf->magic = R300_BUFFER_MAGIC; - - pipe_reference_init(&rbuf->b.b.reference, 1); - rbuf->b.vtbl = &r300_buffer_vtbl; - rbuf->b.b.screen = screen; - rbuf->b.b.target = PIPE_BUFFER; - rbuf->b.b.format = PIPE_FORMAT_R8_UNORM; - rbuf->b.b.usage = PIPE_USAGE_IMMUTABLE; - rbuf->b.b.bind = bind; - rbuf->b.b.width0 = ~0; - rbuf->b.b.height0 = 1; - rbuf->b.b.depth0 = 1; - rbuf->b.b.array_size = 1; - rbuf->b.b.flags = 0; + pipe_reference_init(&rbuf->b.b.b.reference, 1); + rbuf->b.b.b.screen = screen; + rbuf->b.b.b.target = PIPE_BUFFER; + rbuf->b.b.b.format = PIPE_FORMAT_R8_UNORM; + rbuf->b.b.b.usage = PIPE_USAGE_IMMUTABLE; + rbuf->b.b.b.bind = bind; + rbuf->b.b.b.width0 = ~0; + rbuf->b.b.b.height0 = 1; + rbuf->b.b.b.depth0 = 1; + rbuf->b.b.b.array_size = 1; + rbuf->b.b.b.flags = 0; + rbuf->b.b.vtbl = &r300_buffer_vtbl; + rbuf->b.user_ptr = ptr; rbuf->domain = R300_DOMAIN_GTT; rbuf->buf = NULL; + rbuf->buf_size = size; rbuf->constant_buffer = NULL; - rbuf->user_buffer = ptr; - return &rbuf->b.b; + return &rbuf->b.b.b; } diff --git a/src/gallium/drivers/r300/r300_screen_buffer.h b/src/gallium/drivers/r300/r300_screen_buffer.h index 58dec8539b6..14bee460d5b 100644 --- a/src/gallium/drivers/r300/r300_screen_buffer.h +++ b/src/gallium/drivers/r300/r300_screen_buffer.h @@ -35,39 +35,12 @@ #include "r300_winsys.h" #include "r300_context.h" -#define R300_BUFFER_MAGIC 0xabcd1234 -#define R300_BUFFER_MAX_RANGES 32 - -struct r300_buffer_range { - uint32_t start; - uint32_t end; -}; - -/* Vertex buffer. */ -struct r300_buffer -{ - struct u_resource b; - - uint32_t magic; - - struct r300_winsys_buffer *buf; - struct r300_winsys_cs_buffer *cs_buf; - - enum r300_buffer_domain domain; - - uint8_t *user_buffer; - uint8_t *constant_buffer; -}; - /* Functions. */ -void r300_upload_user_buffers(struct r300_context *r300, - int min_index, int max_index); - void r300_upload_index_buffer(struct r300_context *r300, struct pipe_resource **index_buffer, unsigned index_size, unsigned *start, - unsigned count); + unsigned count, uint8_t *ptr); struct pipe_resource *r300_buffer_create(struct pipe_screen *screen, const struct pipe_resource *templ); @@ -77,8 +50,7 @@ struct pipe_resource *r300_user_buffer_create(struct pipe_screen *screen, unsigned bind); unsigned r300_buffer_is_referenced(struct pipe_context *context, - struct pipe_resource *buf, - enum r300_reference_domain domain); + struct pipe_resource *buf); /* Inline functions. */ @@ -87,9 +59,4 @@ static INLINE struct r300_buffer *r300_buffer(struct pipe_resource *buffer) return (struct r300_buffer *)buffer; } -static INLINE boolean r300_is_user_buffer(struct pipe_resource *buffer) -{ - return r300_buffer(buffer)->user_buffer ? true : false; -} - #endif diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index 3a97b76a4c8..09f18b3e624 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -28,6 +28,7 @@ #include "util/u_mm.h" #include "util/u_memory.h" #include "util/u_pack_color.h" +#include "util/u_transfer.h" #include "tgsi/tgsi_parse.h" @@ -442,8 +443,7 @@ static void r300_set_clip_state(struct pipe_context* pipe, OUT_CB_TABLE(state->ucp, state->nr * 4); } OUT_CB_REG(R300_VAP_CLIP_CNTL, ((1 << state->nr) - 1) | - R300_PS_UCP_MODE_CLIP_AS_TRIFAN | - (state->depth_clamp ? R300_CLIP_DISABLE : 0)); + R300_PS_UCP_MODE_CLIP_AS_TRIFAN); END_CB; r300_mark_atom_dirty(r300, &r300->clip_state); @@ -617,21 +617,16 @@ static void r300_set_stencil_ref(struct pipe_context* pipe, } static void r300_tex_set_tiling_flags(struct r300_context *r300, - struct r300_texture *tex, unsigned level) + struct r300_resource *tex, + unsigned level) { /* Check if the macrotile flag needs to be changed. * Skip changing the flags otherwise. */ - if (tex->desc.macrotile[tex->surface_level] != - tex->desc.macrotile[level]) { - /* Tiling determines how DRM treats the buffer data. - * We must flush CS when changing it if the buffer is referenced. */ - if (r300->rws->cs_is_buffer_referenced(r300->cs, - tex->cs_buffer, R300_REF_CS)) - r300->context.flush(&r300->context, 0, NULL); - - r300->rws->buffer_set_tiling(r300->rws, tex->buffer, - tex->desc.microtile, tex->desc.macrotile[level], - tex->desc.stride_in_bytes[0]); + if (tex->tex.macrotile[tex->surface_level] != + tex->tex.macrotile[level]) { + r300->rws->buffer_set_tiling(tex->buf, r300->cs, + tex->tex.microtile, tex->tex.macrotile[level], + tex->tex.stride_in_bytes[0]); tex->surface_level = level; } @@ -646,12 +641,12 @@ static void r300_fb_set_tiling_flags(struct r300_context *r300, /* Set tiling flags for new surfaces. */ for (i = 0; i < state->nr_cbufs; i++) { r300_tex_set_tiling_flags(r300, - r300_texture(state->cbufs[i]->texture), + r300_resource(state->cbufs[i]->texture), state->cbufs[i]->u.tex.level); } if (state->zsbuf) { r300_tex_set_tiling_flags(r300, - r300_texture(state->zsbuf->texture), + r300_resource(state->zsbuf->texture), state->zsbuf->u.tex.level); } } @@ -660,7 +655,7 @@ static void r300_print_fb_surf_info(struct pipe_surface *surf, unsigned index, const char *binding) { struct pipe_resource *tex = surf->texture; - struct r300_texture *rtex = r300_texture(tex); + struct r300_resource *rtex = r300_resource(tex); fprintf(stderr, "r300: %s[%i] Dim: %ix%i, Firstlayer: %i, " @@ -673,9 +668,9 @@ static void r300_print_fb_surf_info(struct pipe_surface *surf, unsigned index, surf->u.tex.first_layer, surf->u.tex.last_layer, surf->u.tex.level, util_format_short_name(surf->format), - rtex->desc.macrotile[0] ? "YES" : " NO", - rtex->desc.microtile ? "YES" : " NO", - rtex->desc.stride_in_pixels[0], + rtex->tex.macrotile[0] ? "YES" : " NO", + rtex->tex.microtile ? "YES" : " NO", + rtex->tex.stride_in_pixels[0], tex->width0, tex->height0, tex->depth0, tex->last_level, util_format_short_name(tex->format)); } @@ -695,8 +690,7 @@ void r300_mark_fb_state_dirty(struct r300_context *r300, } if (change == R300_CHANGED_FB_STATE || - change == R300_CHANGED_CBZB_FLAG || - change == R300_CHANGED_ZCLEAR_FLAG) { + change == R300_CHANGED_HYPERZ_FLAG) { r300_mark_atom_dirty(r300, &r300->hyperz_state); } @@ -720,8 +714,8 @@ void r300_mark_fb_state_dirty(struct r300_context *r300, } static void - r300_set_framebuffer_state(struct pipe_context* pipe, - const struct pipe_framebuffer_state* state) +r300_set_framebuffer_state(struct pipe_context* pipe, + const struct pipe_framebuffer_state* state) { struct r300_context* r300 = r300_context(pipe); struct r300_aa_state *aa = (struct r300_aa_state*)r300->aa_state.state; @@ -729,7 +723,6 @@ static void boolean can_hyperz = r300->rws->get_value(r300->rws, R300_CAN_HYPERZ); unsigned max_width, max_height, i; uint32_t zbuffer_bpp = 0; - int blocksize; if (r300->screen->caps.is_r500) { max_width = max_height = 4096; @@ -745,6 +738,32 @@ static void return; } + if (old_state->zsbuf && r300->zmask_in_use && !r300->zmask_locked) { + /* There is a zmask in use, what are we gonna do? */ + if (state->zsbuf) { + if (!pipe_surface_equal(old_state->zsbuf, state->zsbuf)) { + /* Decompress the currently bound zbuffer before we bind another one. */ + r300_decompress_zmask(r300); + } + } else { + /* We don't bind another zbuffer, so lock the current one. */ + r300->zmask_locked = TRUE; + pipe_surface_reference(&r300->locked_zbuffer, old_state->zsbuf); + } + } else if (r300->zmask_locked && r300->locked_zbuffer) { + /* We have a locked zbuffer now, what are we gonna do? */ + if (state->zsbuf) { + if (!pipe_surface_equal(r300->locked_zbuffer, state->zsbuf)) { + /* We are binding some other zbuffer, so decompress the locked one, + * it gets unlocked automatically. */ + r300_decompress_zmask_locked_unsafe(r300); + } else { + /* We are binding the locked zbuffer again, so unlock it. */ + r300->zmask_locked = FALSE; + } + } + } + /* If nr_cbufs is changed from zero to non-zero or vice versa... */ if (!!old_state->nr_cbufs != !!state->nr_cbufs) { r300_mark_atom_dirty(r300, &r300->blend_state); @@ -759,14 +778,14 @@ static void util_copy_framebuffer_state(r300->fb_state.state, state); + if (!r300->zmask_locked) { + pipe_surface_reference(&r300->locked_zbuffer, NULL); + } + r300_mark_fb_state_dirty(r300, R300_CHANGED_FB_STATE); - r300->validate_buffers = TRUE; - r300->z_compression = false; - if (state->zsbuf) { - blocksize = util_format_get_blocksize(state->zsbuf->texture->format); - switch (blocksize) { + switch (util_format_get_blocksize(state->zsbuf->texture->format)) { case 2: zbuffer_bpp = 16; break; @@ -774,30 +793,19 @@ static void zbuffer_bpp = 24; break; } + + /* Setup Hyper-Z. */ if (can_hyperz) { struct r300_surface *zs_surf = r300_surface(state->zsbuf); - struct r300_texture *tex; - int compress = r300->screen->caps.is_rv350 ? RV350_Z_COMPRESS_88 : R300_Z_COMPRESS_44; + struct r300_resource *tex = r300_resource(zs_surf->base.texture); int level = zs_surf->base.u.tex.level; - tex = r300_texture(zs_surf->base.texture); - /* work out whether we can support hiz on this buffer */ r300_hiz_alloc_block(r300, zs_surf); - - /* work out whether we can support zmask features on this buffer */ - r300_zmask_alloc_block(r300, zs_surf, compress); - - if (tex->zmask_mem[level]) { - /* compression causes hangs on 16-bit */ - if (zbuffer_bpp == 24) - r300->z_compression = compress; - } + DBG(r300, DBG_HYPERZ, - "hyper-z features: hiz: %d @ %08x z-compression: %d z-fastfill: %d @ %08x\n", tex->hiz_mem[level] ? 1 : 0, - tex->hiz_mem[level] ? tex->hiz_mem[level]->ofs : 0xdeadbeef, - r300->z_compression, tex->zmask_mem[level] ? 1 : 0, - tex->zmask_mem[level] ? tex->zmask_mem[level]->ofs : 0xdeadbeef); + "hyper-z features: hiz: %d @ %08x\n", tex->hiz_mem[level] ? 1 : 0, + tex->hiz_mem[level] ? tex->hiz_mem[level]->ofs : 0xdeadbeef); } /* Polygon offset depends on the zbuffer bit depth. */ @@ -1300,7 +1308,7 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe, struct r300_context* r300 = r300_context(pipe); struct r300_textures_state* state = (struct r300_textures_state*)r300->textures_state.state; - struct r300_texture *texture; + struct r300_resource *texture; unsigned i, real_num_views = 0, view_index = 0; unsigned tex_units = r300->screen->caps.num_tex_units; boolean dirty_tex = FALSE; @@ -1329,8 +1337,8 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe, /* Set the texrect factor in the fragment shader. * Needed for RECT and NPOT fallback. */ - texture = r300_texture(views[i]->texture); - if (texture->desc.is_npot) { + texture = r300_resource(views[i]->texture); + if (texture->tex.is_npot) { r300_mark_atom_dirty(r300, &r300->fs_rc_constant_state); } @@ -1350,7 +1358,6 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe, state->sampler_view_count = count; r300_mark_atom_dirty(r300, &r300->textures_state); - r300->validate_buffers = TRUE; if (dirty_tex) { r300_mark_atom_dirty(r300, &r300->texture_cache_inval); @@ -1363,7 +1370,7 @@ r300_create_sampler_view(struct pipe_context *pipe, const struct pipe_sampler_view *templ) { struct r300_sampler_view *view = CALLOC_STRUCT(r300_sampler_view); - struct r300_texture *tex = r300_texture(texture); + struct r300_resource *tex = r300_resource(texture); boolean is_r500 = r300_screen(pipe->screen)->caps.is_r500; boolean dxtc_swizzle = r300_screen(pipe->screen)->caps.dxtc_swizzle; @@ -1465,10 +1472,7 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe, const struct pipe_vertex_buffer* buffers) { struct r300_context* r300 = r300_context(pipe); - const struct pipe_vertex_buffer *vbo; - unsigned i, max_index = (1 << 24) - 1; - boolean any_user_buffer = FALSE; - boolean any_nonuser_buffer = FALSE; + unsigned i; struct pipe_vertex_buffer dummy_vb = {0}; /* There must be at least one vertex buffer set, otherwise it locks up. */ @@ -1478,90 +1482,20 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe, count = 1; } - if (count == r300->vertex_buffer_count && - memcmp(r300->vertex_buffer, buffers, - sizeof(struct pipe_vertex_buffer) * count) == 0) { - return; - } + u_vbuf_mgr_set_vertex_buffers(r300->vbuf_mgr, count, buffers); if (r300->screen->caps.has_tcl) { /* HW TCL. */ - r300->incompatible_vb_layout = FALSE; - - /* Check if the strides and offsets are aligned to the size of DWORD. */ - for (i = 0; i < count; i++) { - if (buffers[i].buffer) { - if (buffers[i].stride % 4 != 0 || - buffers[i].buffer_offset % 4 != 0) { - r300->incompatible_vb_layout = TRUE; - break; - } - } - } - for (i = 0; i < count; i++) { - vbo = &buffers[i]; - - /* Skip NULL buffers */ - if (!vbo->buffer) { - continue; - } - - /* User buffers have no info about maximum index, - * we will have to compute it in draw_vbo. */ - if (r300_is_user_buffer(vbo->buffer)) { - any_user_buffer = TRUE; - continue; - } - any_nonuser_buffer = TRUE; - - /* The stride of zero means we will be fetching only the first - * vertex, so don't care about max_index. */ - if (!vbo->stride) - continue; - - /* Update the maximum index. */ - { - unsigned vbo_max_index = - (vbo->buffer->width0 - vbo->buffer_offset) / vbo->stride; - max_index = MIN2(max_index, vbo_max_index); + if (buffers[i].buffer && + !r300_resource(buffers[i].buffer)->b.user_ptr) { } } - - r300->any_user_vbs = any_user_buffer; - r300->vertex_buffer_max_index = max_index; r300->vertex_arrays_dirty = TRUE; - if (any_nonuser_buffer) - r300->validate_buffers = TRUE; - if (!any_user_buffer) - r300->upload_vb_validated = FALSE; } else { /* SW TCL. */ draw_set_vertex_buffers(r300->draw, count, buffers); } - - /* Common code. */ - for (i = 0; i < count; i++) { - vbo = &buffers[i]; - - /* Reference our buffer. */ - pipe_resource_reference(&r300->vertex_buffer[i].buffer, vbo->buffer); - if (vbo->buffer && r300_is_user_buffer(vbo->buffer)) { - pipe_resource_reference(&r300->valid_vertex_buffer[i], NULL); - } else { - pipe_resource_reference(&r300->valid_vertex_buffer[i], vbo->buffer); - } - } - for (; i < r300->vertex_buffer_count; i++) { - /* Dereference any old buffers. */ - pipe_resource_reference(&r300->vertex_buffer[i].buffer, NULL); - pipe_resource_reference(&r300->valid_vertex_buffer[i], NULL); - } - - memcpy(r300->vertex_buffer, buffers, - sizeof(struct pipe_vertex_buffer) * count); - - r300->vertex_buffer_count = count; } static void r300_set_index_buffer(struct pipe_context* pipe, @@ -1570,14 +1504,11 @@ static void r300_set_index_buffer(struct pipe_context* pipe, struct r300_context* r300 = r300_context(pipe); if (ib && ib->buffer) { + assert(ib->offset % ib->index_size == 0); + pipe_resource_reference(&r300->index_buffer.buffer, ib->buffer); memcpy(&r300->index_buffer, ib, sizeof(r300->index_buffer)); - - if (r300->screen->caps.has_tcl && - !r300_is_user_buffer(ib->buffer)) { - r300->validate_buffers = TRUE; - r300->upload_ib_validated = FALSE; - } + r300->index_buffer.offset /= r300->index_buffer.index_size; } else { pipe_resource_reference(&r300->index_buffer.buffer, NULL); @@ -1607,7 +1538,7 @@ static void r300_vertex_psc(struct r300_vertex_element_state *velems) * so PSC should just route stuff based on the vertex elements, * and not on attrib information. */ for (i = 0; i < velems->count; i++) { - format = velems->hw_format[i]; + format = velems->velem[i].src_format; type = r300_translate_vertex_data_type(format); if (type == R300_INVALID_FORMAT) { @@ -1639,16 +1570,13 @@ static void r300_vertex_psc(struct r300_vertex_element_state *velems) vstream->count = (i >> 1) + 1; } -#define FORMAT_REPLACE(what, withwhat) \ - case PIPE_FORMAT_##what: *format = PIPE_FORMAT_##withwhat; break - static void* r300_create_vertex_elements_state(struct pipe_context* pipe, unsigned count, const struct pipe_vertex_element* attribs) { + struct r300_context *r300 = r300_context(pipe); struct r300_vertex_element_state *velems; unsigned i; - enum pipe_format *format; struct pipe_vertex_element dummy_attrib = {0}; /* R300 Programmable Stream Control (PSC) doesn't support 0 vertex elements. */ @@ -1660,77 +1588,26 @@ static void* r300_create_vertex_elements_state(struct pipe_context* pipe, assert(count <= PIPE_MAX_ATTRIBS); velems = CALLOC_STRUCT(r300_vertex_element_state); - if (velems != NULL) { - velems->count = count; - memcpy(velems->velem, attribs, sizeof(struct pipe_vertex_element) * count); - - if (r300_screen(pipe->screen)->caps.has_tcl) { - /* Set the best hw format in case the original format is not - * supported by hw. */ - for (i = 0; i < count; i++) { - velems->hw_format[i] = velems->velem[i].src_format; - format = &velems->hw_format[i]; - - /* This is basically the list of unsupported formats. - * For now we don't care about the alignment, that's going to - * be sorted out after the PSC setup. */ - switch (*format) { - FORMAT_REPLACE(R64_FLOAT, R32_FLOAT); - FORMAT_REPLACE(R64G64_FLOAT, R32G32_FLOAT); - FORMAT_REPLACE(R64G64B64_FLOAT, R32G32B32_FLOAT); - FORMAT_REPLACE(R64G64B64A64_FLOAT, R32G32B32A32_FLOAT); - - FORMAT_REPLACE(R32_UNORM, R32_FLOAT); - FORMAT_REPLACE(R32G32_UNORM, R32G32_FLOAT); - FORMAT_REPLACE(R32G32B32_UNORM, R32G32B32_FLOAT); - FORMAT_REPLACE(R32G32B32A32_UNORM, R32G32B32A32_FLOAT); - - FORMAT_REPLACE(R32_USCALED, R32_FLOAT); - FORMAT_REPLACE(R32G32_USCALED, R32G32_FLOAT); - FORMAT_REPLACE(R32G32B32_USCALED, R32G32B32_FLOAT); - FORMAT_REPLACE(R32G32B32A32_USCALED,R32G32B32A32_FLOAT); - - FORMAT_REPLACE(R32_SNORM, R32_FLOAT); - FORMAT_REPLACE(R32G32_SNORM, R32G32_FLOAT); - FORMAT_REPLACE(R32G32B32_SNORM, R32G32B32_FLOAT); - FORMAT_REPLACE(R32G32B32A32_SNORM, R32G32B32A32_FLOAT); - - FORMAT_REPLACE(R32_SSCALED, R32_FLOAT); - FORMAT_REPLACE(R32G32_SSCALED, R32G32_FLOAT); - FORMAT_REPLACE(R32G32B32_SSCALED, R32G32B32_FLOAT); - FORMAT_REPLACE(R32G32B32A32_SSCALED,R32G32B32A32_FLOAT); - - FORMAT_REPLACE(R32_FIXED, R32_FLOAT); - FORMAT_REPLACE(R32G32_FIXED, R32G32_FLOAT); - FORMAT_REPLACE(R32G32B32_FIXED, R32G32B32_FLOAT); - FORMAT_REPLACE(R32G32B32A32_FIXED, R32G32B32A32_FLOAT); - - default:; - } + if (!velems) + return NULL; - velems->incompatible_layout = - velems->incompatible_layout || - velems->velem[i].src_format != velems->hw_format[i] || - velems->velem[i].src_offset % 4 != 0; - } + velems->count = count; + velems->vmgr_elements = + u_vbuf_mgr_create_vertex_elements(r300->vbuf_mgr, count, attribs, + velems->velem); - /* Now setup PSC. - * The unused components will be replaced by (..., 0, 1). */ - r300_vertex_psc(velems); - - /* Align the formats to the size of DWORD. - * We only care about the blocksizes of the formats since - * swizzles are already set up. - * Also compute the vertex size. */ - for (i = 0; i < count; i++) { - /* This is OK because we check for aligned strides too - * elsewhere. */ - velems->hw_format_size[i] = - align(util_format_get_blocksize(velems->hw_format[i]), 4); - velems->vertex_size_dwords += velems->hw_format_size[i] / 4; - } + if (r300_screen(pipe->screen)->caps.has_tcl) { + /* Setup PSC. + * The unused components will be replaced by (..., 0, 1). */ + r300_vertex_psc(velems); + + for (i = 0; i < count; i++) { + velems->format_size[i] = + align(util_format_get_blocksize(velems->velem[i].src_format), 4); + velems->vertex_size_dwords += velems->format_size[i] / 4; } } + return velems; } @@ -1746,6 +1623,8 @@ static void r300_bind_vertex_elements_state(struct pipe_context *pipe, r300->velems = velems; + u_vbuf_mgr_bind_vertex_elements(r300->vbuf_mgr, state, velems->vmgr_elements); + if (r300->draw) { draw_set_vertex_elements(r300->draw, velems->count, velems->velem); return; @@ -1758,7 +1637,11 @@ static void r300_bind_vertex_elements_state(struct pipe_context *pipe, static void r300_delete_vertex_elements_state(struct pipe_context *pipe, void *state) { - FREE(state); + struct r300_context *r300 = r300_context(pipe); + struct r300_vertex_element_state *velems = state; + + u_vbuf_mgr_destroy_vertex_elements(r300->vbuf_mgr, velems->vmgr_elements); + FREE(state); } static void* r300_create_vs_state(struct pipe_context* pipe, @@ -1845,7 +1728,7 @@ static void r300_set_constant_buffer(struct pipe_context *pipe, { struct r300_context* r300 = r300_context(pipe); struct r300_constant_buffer *cbuf; - struct r300_buffer *rbuf = r300_buffer(buf); + struct r300_resource *rbuf = r300_resource(buf); uint32_t *mapped; switch (shader) { @@ -1862,8 +1745,8 @@ static void r300_set_constant_buffer(struct pipe_context *pipe, if (buf == NULL || buf->width0 == 0) return; - if (rbuf->user_buffer) - mapped = (uint32_t*)rbuf->user_buffer; + if (rbuf->b.user_ptr) + mapped = (uint32_t*)rbuf->b.user_ptr; else if (rbuf->constant_buffer) mapped = (uint32_t*)rbuf->constant_buffer; else @@ -1947,6 +1830,7 @@ void r300_init_state_functions(struct r300_context* r300) r300->context.set_vertex_buffers = r300_set_vertex_buffers; r300->context.set_index_buffer = r300_set_index_buffer; + r300->context.redefine_user_buffer = u_default_redefine_user_buffer; r300->context.create_vertex_elements_state = r300_create_vertex_elements_state; r300->context.bind_vertex_elements_state = r300_bind_vertex_elements_state; diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c index 95be7849f8f..003fe9a58cd 100644 --- a/src/gallium/drivers/r300/r300_state_derived.c +++ b/src/gallium/drivers/r300/r300_state_derived.c @@ -489,7 +489,8 @@ static void r300_update_rs_block(struct r300_context *r300) for (; i < ATTR_GENERIC_COUNT; i++) { if (fs_inputs->generic[i] != ATTR_UNUSED) { fprintf(stderr, "r300: ERROR: FS input generic %i unassigned, " - "not enough hardware slots.\n", i); + "not enough hardware slots (it's not a bug, do not " + "report it).\n", i); } } @@ -524,7 +525,8 @@ static void r300_update_rs_block(struct r300_context *r300) DBG(r300, DBG_RS, "r300: FS input fog unassigned.\n"); } else { fprintf(stderr, "r300: ERROR: FS input fog unassigned, " - "not enough hardware slots.\n"); + "not enough hardware slots. (it's not a bug, " + "do not report it)\n"); } } } @@ -551,7 +553,8 @@ static void r300_update_rs_block(struct r300_context *r300) } else { if (fs_inputs->wpos != ATTR_UNUSED && tex_count >= 8) { fprintf(stderr, "r300: ERROR: FS input WPOS unassigned, " - "not enough hardware slots.\n"); + "not enough hardware slots. (it's not a bug, do not " + "report it)\n"); } } @@ -674,7 +677,20 @@ static uint32_t r300_get_border_color(enum pipe_format format, case 16: if (desc->nr_channels <= 2) { border_swizzled[0] = border_swizzled[2]; - util_pack_color(border_swizzled, PIPE_FORMAT_R16G16_UNORM, &uc); + if (desc->channel[0].type == UTIL_FORMAT_TYPE_FLOAT) { + util_pack_color(border_swizzled, PIPE_FORMAT_R16G16_FLOAT, &uc); + } else { + util_pack_color(border_swizzled, PIPE_FORMAT_R16G16_UNORM, &uc); + } + } else { + util_pack_color(border_swizzled, PIPE_FORMAT_B8G8R8A8_UNORM, &uc); + } + break; + + case 32: + if (desc->nr_channels == 1) { + border_swizzled[0] = border_swizzled[2]; + util_pack_color(border_swizzled, PIPE_FORMAT_R32_FLOAT, &uc); } else { util_pack_color(border_swizzled, PIPE_FORMAT_B8G8R8A8_UNORM, &uc); } @@ -684,6 +700,25 @@ static uint32_t r300_get_border_color(enum pipe_format format, return uc.ui; } +static boolean util_format_is_float(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + unsigned i; + + if (!format) + return FALSE; + + /* Find the first non-void channel. */ + for (i = 0; i < 4; i++) + if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID) + break; + + if (i == 4) + return FALSE; + + return desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT ? TRUE : FALSE; +} + static void r300_merge_textures_and_samplers(struct r300_context* r300) { struct r300_textures_state *state = @@ -691,7 +726,7 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) struct r300_texture_sampler_state *texstate; struct r300_sampler_state *sampler; struct r300_sampler_view *view; - struct r300_texture *tex; + struct r300_resource *tex; unsigned min_level, max_level, i, j, size; unsigned count = MIN2(state->sampler_view_count, state->sampler_state_count); @@ -709,7 +744,7 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) state->tx_enable |= 1 << i; view = state->sampler_views[i]; - tex = r300_texture(view->base.texture); + tex = r300_resource(view->base.texture); sampler = state->sampler_states[i]; texstate = &state->regs[i]; @@ -725,32 +760,37 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) /* determine min/max levels */ max_level = MIN3(sampler->max_lod + view->base.u.tex.first_level, - tex->desc.b.b.last_level, view->base.u.tex.last_level); + tex->b.b.b.last_level, view->base.u.tex.last_level); min_level = MIN2(sampler->min_lod + view->base.u.tex.first_level, max_level); - if (tex->desc.is_npot && min_level > 0) { + if (tex->tex.is_npot && min_level > 0) { /* Even though we do not implement mipmapping for NPOT * textures, we should at least honor the minimum level * which is allowed to be displayed. We do this by setting up - * an i-th mipmap level as the zero level. */ - r300_texture_setup_format_state(r300->screen, &tex->desc, + * the i-th mipmap level as the zero level. */ + unsigned offset = tex->tex_offset + + tex->tex.offset_in_bytes[min_level]; + + r300_texture_setup_format_state(r300->screen, tex, min_level, &texstate->format); - texstate->format.tile_config |= - tex->desc.offset_in_bytes[min_level] & 0xffffffe0; - assert((tex->desc.offset_in_bytes[min_level] & 0x1f) == 0); + texstate->format.tile_config |= offset & 0xffffffe0; + assert((offset & 0x1f) == 0); + } else { + texstate->format.tile_config |= tex->tex_offset & 0xffffffe0; + assert((tex->tex_offset & 0x1f) == 0); } /* Assign a texture cache region. */ texstate->format.format1 |= view->texcache_region; /* Depth textures are kinda special. */ - if (util_format_is_depth_or_stencil(tex->desc.b.b.format)) { + if (util_format_is_depth_or_stencil(tex->b.b.b.format)) { unsigned char depth_swizzle[4]; if (!r300->screen->caps.is_r500 && - util_format_get_blocksizebits(tex->desc.b.b.format) == 32) { + util_format_get_blocksizebits(tex->b.b.b.format) == 32) { /* X24x8 is sampled as Y16X16 on r3xx-r4xx. * The depth here is at the Y component. */ for (j = 0; j < 4; j++) @@ -775,17 +815,17 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) } if (r300->screen->caps.dxtc_swizzle && - util_format_is_compressed(tex->desc.b.b.format)) { + util_format_is_compressed(tex->b.b.b.format)) { texstate->filter1 |= R400_DXTC_SWIZZLE_ENABLE; } /* to emulate 1D textures through 2D ones correctly */ - if (tex->desc.b.b.target == PIPE_TEXTURE_1D) { + if (tex->b.b.b.target == PIPE_TEXTURE_1D) { texstate->filter0 &= ~R300_TX_WRAP_T_MASK; texstate->filter0 |= R300_TX_WRAP_T(R300_TX_CLAMP_TO_EDGE); } - if (tex->desc.is_npot) { + if (tex->tex.is_npot) { /* NPOT textures don't support mip filter, unfortunately. * This prevents incorrect rendering. */ texstate->filter0 &= ~R300_TX_MIN_FILTER_MIP_MASK; @@ -814,6 +854,32 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) texstate->filter0 |= R300_TX_MAX_MIP_LEVEL(min_level); } + /* Float textures only support nearest and mip-nearest filtering. */ + if (util_format_is_float(tex->b.b.b.format)) { + /* No MAG linear filtering. */ + if ((texstate->filter0 & R300_TX_MAG_FILTER_MASK) == + R300_TX_MAG_FILTER_LINEAR) { + texstate->filter0 &= ~R300_TX_MAG_FILTER_MASK; + texstate->filter0 |= R300_TX_MAG_FILTER_NEAREST; + } + /* No MIN linear filtering. */ + if ((texstate->filter0 & R300_TX_MIN_FILTER_MASK) == + R300_TX_MIN_FILTER_LINEAR) { + texstate->filter0 &= ~R300_TX_MIN_FILTER_MASK; + texstate->filter0 |= R300_TX_MIN_FILTER_NEAREST; + } + /* No mipmap linear filtering. */ + if ((texstate->filter0 & R300_TX_MIN_FILTER_MIP_MASK) == + R300_TX_MIN_FILTER_MIP_LINEAR) { + texstate->filter0 &= ~R300_TX_MIN_FILTER_MIP_MASK; + texstate->filter0 |= R300_TX_MIN_FILTER_MIP_NEAREST; + } + /* No anisotropic filtering. */ + texstate->filter0 &= ~R300_TX_MAX_ANISO_MASK; + texstate->filter1 &= ~R500_TX_MAX_ANISO_MASK; + texstate->filter1 &= ~R500_TX_ANISO_HIGH_QUALITY; + } + texstate->filter0 |= i << 28; size += 16; @@ -862,11 +928,35 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) } } -void r300_update_derived_state(struct r300_context* r300) +static void r300_decompress_depth_textures(struct r300_context *r300) { - r300_flush_depth_textures(r300); + struct r300_textures_state *state = + (struct r300_textures_state*)r300->textures_state.state; + struct pipe_resource *tex; + unsigned count = MIN2(state->sampler_view_count, + state->sampler_state_count); + unsigned i; + + if (!r300->zmask_locked || !r300->locked_zbuffer) { + return; + } + for (i = 0; i < count; i++) { + if (state->sampler_views[i] && state->sampler_states[i]) { + tex = state->sampler_views[i]->base.texture; + + if (tex == r300->locked_zbuffer->texture) { + r300_decompress_zmask_locked(r300); + return; + } + } + } +} + +void r300_update_derived_state(struct r300_context* r300) +{ if (r300->textures_state.dirty) { + r300_decompress_depth_textures(r300); r300_merge_textures_and_samplers(r300); } diff --git a/src/gallium/drivers/r300/r300_state_inlines.h b/src/gallium/drivers/r300/r300_state_inlines.h index 7e501221b1f..06da04c7ad7 100644 --- a/src/gallium/drivers/r300/r300_state_inlines.h +++ b/src/gallium/drivers/r300/r300_state_inlines.h @@ -25,13 +25,9 @@ #define R300_STATE_INLINES_H #include "draw/draw_vertex.h" - #include "pipe/p_format.h" - #include "util/u_format.h" - #include "r300_reg.h" - #include <stdio.h> /* Some maths. These should probably find their way to u_math, if needed. */ @@ -341,24 +337,6 @@ static INLINE uint32_t r500_anisotropy(unsigned max_aniso) R500_TX_ANISO_HIGH_QUALITY; } -/* Non-CSO state. (For now.) */ - -static INLINE uint32_t r300_translate_gb_pipes(int pipe_count) -{ - switch (pipe_count) { - case 1: - return R300_GB_TILE_PIPE_COUNT_RV300; - case 2: - return R300_GB_TILE_PIPE_COUNT_R300; - case 3: - return R300_GB_TILE_PIPE_COUNT_R420_3P; - case 4: - return R300_GB_TILE_PIPE_COUNT_R420; - } - return 0; -} - - /* Translate pipe_formats into PSC vertex types. */ static INLINE uint16_t r300_translate_vertex_data_type(enum pipe_format format) { diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c index 6fdc504ed54..354144cac79 100644 --- a/src/gallium/drivers/r300/r300_texture.c +++ b/src/gallium/drivers/r300/r300_texture.c @@ -370,14 +370,18 @@ static uint32_t r300_translate_colorformat(enum pipe_format format) switch (format) { /* 8-bit buffers. */ case PIPE_FORMAT_A8_UNORM: + /*case PIPE_FORMAT_A8_SNORM:*/ case PIPE_FORMAT_I8_UNORM: + /*case PIPE_FORMAT_I8_SNORM:*/ case PIPE_FORMAT_L8_UNORM: + /*case PIPE_FORMAT_L8_SNORM:*/ case PIPE_FORMAT_R8_UNORM: case PIPE_FORMAT_R8_SNORM: return R300_COLOR_FORMAT_I8; /* 16-bit buffers. */ case PIPE_FORMAT_L8A8_UNORM: + /*case PIPE_FORMAT_L8A8_SNORM:*/ case PIPE_FORMAT_R8G8_UNORM: case PIPE_FORMAT_R8G8_SNORM: return R300_COLOR_FORMAT_UV88; @@ -395,13 +399,21 @@ static uint32_t r300_translate_colorformat(enum pipe_format format) /* 32-bit buffers. */ case PIPE_FORMAT_B8G8R8A8_UNORM: + /*case PIPE_FORMAT_B8G8R8A8_SNORM:*/ case PIPE_FORMAT_B8G8R8X8_UNORM: + /*case PIPE_FORMAT_B8G8R8X8_SNORM:*/ case PIPE_FORMAT_A8R8G8B8_UNORM: + /*case PIPE_FORMAT_A8R8G8B8_SNORM:*/ case PIPE_FORMAT_X8R8G8B8_UNORM: + /*case PIPE_FORMAT_X8R8G8B8_SNORM:*/ case PIPE_FORMAT_A8B8G8R8_UNORM: + /*case PIPE_FORMAT_A8B8G8R8_SNORM:*/ + case PIPE_FORMAT_R8G8B8A8_UNORM: case PIPE_FORMAT_R8G8B8A8_SNORM: case PIPE_FORMAT_X8B8G8R8_UNORM: + /*case PIPE_FORMAT_X8B8G8R8_SNORM:*/ case PIPE_FORMAT_R8G8B8X8_UNORM: + /*case PIPE_FORMAT_R8G8B8X8_SNORM:*/ case PIPE_FORMAT_R8SG8SB8UX8U_NORM: return R300_COLOR_FORMAT_ARGB8888; @@ -506,9 +518,12 @@ static uint32_t r300_translate_out_fmt(enum pipe_format format) /* 8-bit outputs, one channel. * COLORFORMAT_I8 stores the C2 component. */ case PIPE_FORMAT_A8_UNORM: + /*case PIPE_FORMAT_A8_SNORM:*/ return modifier | R300_C2_SEL_A; case PIPE_FORMAT_I8_UNORM: + /*case PIPE_FORMAT_I8_SNORM:*/ case PIPE_FORMAT_L8_UNORM: + /*case PIPE_FORMAT_L8_SNORM:*/ case PIPE_FORMAT_R8_UNORM: case PIPE_FORMAT_R8_SNORM: return modifier | R300_C2_SEL_R; @@ -516,6 +531,7 @@ static uint32_t r300_translate_out_fmt(enum pipe_format format) /* 16-bit outputs, two channels. * COLORFORMAT_UV88 stores C2 and C0. */ case PIPE_FORMAT_L8A8_UNORM: + /*case PIPE_FORMAT_L8A8_SNORM:*/ return modifier | R300_C0_SEL_A | R300_C2_SEL_R; case PIPE_FORMAT_R8G8_UNORM: case PIPE_FORMAT_R8G8_SNORM: @@ -528,7 +544,9 @@ static uint32_t r300_translate_out_fmt(enum pipe_format format) case PIPE_FORMAT_B4G4R4A4_UNORM: case PIPE_FORMAT_B4G4R4X4_UNORM: case PIPE_FORMAT_B8G8R8A8_UNORM: + /*case PIPE_FORMAT_B8G8R8A8_SNORM:*/ case PIPE_FORMAT_B8G8R8X8_UNORM: + /*case PIPE_FORMAT_B8G8R8X8_SNORM:*/ case PIPE_FORMAT_B10G10R10A2_UNORM: return modifier | R300_C0_SEL_B | R300_C1_SEL_G | @@ -536,20 +554,26 @@ static uint32_t r300_translate_out_fmt(enum pipe_format format) /* ARGB outputs. */ case PIPE_FORMAT_A8R8G8B8_UNORM: + /*case PIPE_FORMAT_A8R8G8B8_SNORM:*/ case PIPE_FORMAT_X8R8G8B8_UNORM: + /*case PIPE_FORMAT_X8R8G8B8_SNORM:*/ return modifier | R300_C0_SEL_A | R300_C1_SEL_R | R300_C2_SEL_G | R300_C3_SEL_B; /* ABGR outputs. */ case PIPE_FORMAT_A8B8G8R8_UNORM: + /*case PIPE_FORMAT_A8B8G8R8_SNORM:*/ case PIPE_FORMAT_X8B8G8R8_UNORM: + /*case PIPE_FORMAT_X8B8G8R8_SNORM:*/ return modifier | R300_C0_SEL_A | R300_C1_SEL_B | R300_C2_SEL_G | R300_C3_SEL_R; /* RGBA outputs. */ case PIPE_FORMAT_R8G8B8X8_UNORM: + /*case PIPE_FORMAT_R8G8B8X8_SNORM:*/ + case PIPE_FORMAT_R8G8B8A8_UNORM: case PIPE_FORMAT_R8G8B8A8_SNORM: case PIPE_FORMAT_R8SG8SB8UX8U_NORM: case PIPE_FORMAT_R10G10B10A2_UNORM: @@ -585,11 +609,12 @@ boolean r300_is_sampler_format_supported(enum pipe_format format) } void r300_texture_setup_format_state(struct r300_screen *screen, - struct r300_texture_desc *desc, + struct r300_resource *tex, unsigned level, struct r300_texture_format_state *out) { - struct pipe_resource *pt = &desc->b.b; + struct pipe_resource *pt = &tex->b.b.b; + struct r300_texture_desc *desc = &tex->tex; boolean is_r500 = screen->caps.is_r500; /* Mask out all the fields we change. */ @@ -632,163 +657,152 @@ void r300_texture_setup_format_state(struct r300_screen *screen, R300_TXO_MICRO_TILE(desc->microtile); } -static void r300_texture_setup_fb_state(struct r300_screen* screen, - struct r300_texture* tex) +static void r300_texture_setup_fb_state(struct r300_surface *surf) { - unsigned i; + struct r300_resource *tex = r300_resource(surf->base.texture); + unsigned level = surf->base.u.tex.level; /* Set framebuffer state. */ - if (util_format_is_depth_or_stencil(tex->desc.b.b.format)) { - for (i = 0; i <= tex->desc.b.b.last_level; i++) { - tex->fb_state.pitch[i] = - tex->desc.stride_in_pixels[i] | - R300_DEPTHMACROTILE(tex->desc.macrotile[i]) | - R300_DEPTHMICROTILE(tex->desc.microtile); - } - tex->fb_state.format = r300_translate_zsformat(tex->desc.b.b.format); + if (util_format_is_depth_or_stencil(surf->base.format)) { + surf->pitch = + tex->tex.stride_in_pixels[level] | + R300_DEPTHMACROTILE(tex->tex.macrotile[level]) | + R300_DEPTHMICROTILE(tex->tex.microtile); + surf->format = r300_translate_zsformat(surf->base.format); } else { - for (i = 0; i <= tex->desc.b.b.last_level; i++) { - tex->fb_state.pitch[i] = - tex->desc.stride_in_pixels[i] | - r300_translate_colorformat(tex->desc.b.b.format) | - R300_COLOR_TILE(tex->desc.macrotile[i]) | - R300_COLOR_MICROTILE(tex->desc.microtile); - } - tex->fb_state.format = r300_translate_out_fmt(tex->desc.b.b.format); + surf->pitch = + tex->tex.stride_in_pixels[level] | + r300_translate_colorformat(surf->base.format) | + R300_COLOR_TILE(tex->tex.macrotile[level]) | + R300_COLOR_MICROTILE(tex->tex.microtile); + surf->format = r300_translate_out_fmt(surf->base.format); } } -void r300_texture_reinterpret_format(struct pipe_screen *screen, +boolean r300_resource_set_properties(struct pipe_screen *screen, struct pipe_resource *tex, - enum pipe_format new_format) + unsigned offset, + const struct pipe_resource *new_properties) { - struct r300_screen *r300screen = r300_screen(screen); + struct r300_screen *rscreen = r300_screen(screen); + struct r300_resource *res = r300_resource(tex); - SCREEN_DBG(r300screen, DBG_TEX, - "r300: texture_reinterpret_format: %s -> %s\n", + SCREEN_DBG(rscreen, DBG_TEX, + "r300: texture_set_properties: %s -> %s\n", util_format_short_name(tex->format), - util_format_short_name(new_format)); - - tex->format = new_format; + util_format_short_name(new_properties->format)); - r300_texture_setup_fb_state(r300_screen(screen), r300_texture(tex)); -} - -static unsigned r300_texture_is_referenced(struct pipe_context *context, - struct pipe_resource *texture, - unsigned level, int layer) -{ - struct r300_context *r300 = r300_context(context); - struct r300_texture *rtex = (struct r300_texture *)texture; - - if (r300->rws->cs_is_buffer_referenced(r300->cs, - rtex->cs_buffer, R300_REF_CS)) - return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; + if (!r300_texture_desc_init(rscreen, res, new_properties)) { + fprintf(stderr, "r300: ERROR: Cannot set texture properties.\n"); + return FALSE; + } + res->tex_offset = offset; + r300_texture_setup_format_state(rscreen, res, 0, &res->tx_format); - return PIPE_UNREFERENCED; + return TRUE; } static void r300_texture_destroy(struct pipe_screen *screen, struct pipe_resource* texture) { - struct r300_texture* tex = (struct r300_texture*)texture; - struct r300_winsys_screen *rws = (struct r300_winsys_screen *)texture->screen->winsys; + struct r300_resource* tex = (struct r300_resource*)texture; int i; - rws->buffer_reference(rws, &tex->buffer, NULL); + r300_winsys_bo_reference(&tex->buf, NULL); for (i = 0; i < R300_MAX_TEXTURE_LEVELS; i++) { if (tex->hiz_mem[i]) u_mmFreeMem(tex->hiz_mem[i]); - if (tex->zmask_mem[i]) - u_mmFreeMem(tex->zmask_mem[i]); } FREE(tex); } -static boolean r300_texture_get_handle(struct pipe_screen* screen, - struct pipe_resource *texture, - struct winsys_handle *whandle) +boolean r300_resource_get_handle(struct pipe_screen* screen, + struct pipe_resource *texture, + struct winsys_handle *whandle) { struct r300_winsys_screen *rws = (struct r300_winsys_screen *)screen->winsys; - struct r300_texture* tex = (struct r300_texture*)texture; + struct r300_resource* tex = (struct r300_resource*)texture; if (!tex) { return FALSE; } - return rws->buffer_get_handle(rws, tex->buffer, - tex->desc.stride_in_bytes[0], whandle); + return rws->buffer_get_handle(tex->buf, + tex->tex.stride_in_bytes[0], whandle); } -struct u_resource_vtbl r300_texture_vtbl = +static const struct u_resource_vtbl r300_texture_vtbl = { - r300_texture_get_handle, /* get_handle */ - r300_texture_destroy, /* resource_destroy */ - r300_texture_is_referenced, /* is_resource_referenced */ - r300_texture_get_transfer, /* get_transfer */ - r300_texture_transfer_destroy, /* transfer_destroy */ - r300_texture_transfer_map, /* transfer_map */ - u_default_transfer_flush_region, /* transfer_flush_region */ - r300_texture_transfer_unmap, /* transfer_unmap */ - u_default_transfer_inline_write /* transfer_inline_write */ + NULL, /* get_handle */ + r300_texture_destroy, /* resource_destroy */ + NULL, /* is_resource_referenced */ + r300_texture_get_transfer, /* get_transfer */ + r300_texture_transfer_destroy, /* transfer_destroy */ + r300_texture_transfer_map, /* transfer_map */ + NULL, /* transfer_flush_region */ + r300_texture_transfer_unmap, /* transfer_unmap */ + u_default_transfer_inline_write /* transfer_inline_write */ }; /* The common texture constructor. */ -static struct r300_texture* +static struct r300_resource* r300_texture_create_object(struct r300_screen *rscreen, const struct pipe_resource *base, enum r300_buffer_tiling microtile, enum r300_buffer_tiling macrotile, unsigned stride_in_bytes_override, unsigned max_buffer_size, - struct r300_winsys_buffer *buffer) + struct r300_winsys_bo *buffer) { struct r300_winsys_screen *rws = rscreen->rws; - struct r300_texture *tex = CALLOC_STRUCT(r300_texture); + struct r300_resource *tex = CALLOC_STRUCT(r300_resource); if (!tex) { if (buffer) - rws->buffer_reference(rws, &buffer, NULL); + r300_winsys_bo_reference(&buffer, NULL); return NULL; } - /* Initialize the descriptor. */ - if (!r300_texture_desc_init(rscreen, &tex->desc, base, - microtile, macrotile, - stride_in_bytes_override, - max_buffer_size)) { + pipe_reference_init(&tex->b.b.b.reference, 1); + tex->b.b.b.screen = &rscreen->screen; + tex->b.b.b.usage = base->usage; + tex->b.b.b.bind = base->bind; + tex->b.b.b.flags = base->flags; + tex->b.b.vtbl = &r300_texture_vtbl; + tex->tex.microtile = microtile; + tex->tex.macrotile[0] = macrotile; + tex->tex.stride_in_bytes_override = stride_in_bytes_override; + tex->domain = base->flags & R300_RESOURCE_FLAG_TRANSFER ? + R300_DOMAIN_GTT : + R300_DOMAIN_VRAM | R300_DOMAIN_GTT; + tex->buf_size = max_buffer_size; + + if (!r300_resource_set_properties(&rscreen->screen, &tex->b.b.b, 0, base)) { if (buffer) - rws->buffer_reference(rws, &buffer, NULL); + r300_winsys_bo_reference(&buffer, NULL); FREE(tex); return NULL; } - /* Initialize the hardware state. */ - r300_texture_setup_format_state(rscreen, &tex->desc, 0, &tex->tx_format); - r300_texture_setup_fb_state(rscreen, tex); - - tex->desc.b.vtbl = &r300_texture_vtbl; - pipe_reference_init(&tex->desc.b.b.reference, 1); - tex->domain = base->flags & R300_RESOURCE_FLAG_TRANSFER ? - R300_DOMAIN_GTT : - R300_DOMAIN_VRAM | R300_DOMAIN_GTT; - tex->buffer = buffer; /* Create the backing buffer if needed. */ - if (!tex->buffer) { - tex->buffer = rws->buffer_create(rws, tex->desc.size_in_bytes, 2048, + if (!buffer) { + tex->buf_size = tex->tex.size_in_bytes; + tex->buf = rws->buffer_create(rws, tex->tex.size_in_bytes, 2048, base->bind, base->usage, tex->domain); - if (!tex->buffer) { + if (!tex->buf) { FREE(tex); return NULL; } + } else { + tex->buf = buffer; } - tex->cs_buffer = rws->buffer_get_cs_handle(rws, tex->buffer); + tex->cs_buf = rws->buffer_get_cs_handle(tex->buf); - rws->buffer_set_tiling(rws, tex->buffer, - tex->desc.microtile, tex->desc.macrotile[0], - tex->desc.stride_in_bytes[0]); + rws->buffer_set_tiling(tex->buf, NULL, + tex->tex.microtile, tex->tex.macrotile[0], + tex->tex.stride_in_bytes[0]); return tex; } @@ -820,7 +834,7 @@ struct pipe_resource *r300_texture_from_handle(struct pipe_screen *screen, { struct r300_winsys_screen *rws = (struct r300_winsys_screen*)screen->winsys; struct r300_screen *rscreen = r300_screen(screen); - struct r300_winsys_buffer *buffer; + struct r300_winsys_bo *buffer; enum r300_buffer_tiling microtile, macrotile; unsigned stride, size; @@ -836,7 +850,7 @@ struct pipe_resource *r300_texture_from_handle(struct pipe_screen *screen, if (!buffer) return NULL; - rws->buffer_get_tiling(rws, buffer, µtile, ¯otile); + rws->buffer_get_tiling(buffer, µtile, ¯otile); /* Enforce a microtiled zbuffer. */ if (util_format_is_depth_or_stencil(base->format) && @@ -847,7 +861,7 @@ struct pipe_resource *r300_texture_from_handle(struct pipe_screen *screen, break; case 2: - if (rws->get_value(rws, R300_VID_SQUARE_TILING_SUPPORT)) + if (rws->get_value(rws, R300_VID_DRM_2_1_0)) microtile = R300_BUFFER_SQUARETILED; break; } @@ -864,7 +878,7 @@ struct pipe_surface* r300_create_surface(struct pipe_context * ctx, struct pipe_resource* texture, const struct pipe_surface *surf_tmpl) { - struct r300_texture* tex = r300_texture(texture); + struct r300_resource* tex = r300_resource(texture); struct r300_surface* surface = CALLOC_STRUCT(r300_surface); unsigned level = surf_tmpl->u.tex.level; @@ -884,28 +898,27 @@ struct pipe_surface* r300_create_surface(struct pipe_context * ctx, surface->base.u.tex.first_layer = surf_tmpl->u.tex.first_layer; surface->base.u.tex.last_layer = surf_tmpl->u.tex.last_layer; - surface->buffer = tex->buffer; - surface->cs_buffer = tex->cs_buffer; + surface->buf = tex->buf; + surface->cs_buf = tex->cs_buf; /* Prefer VRAM if there are multiple domains to choose from. */ surface->domain = tex->domain; if (surface->domain & R300_DOMAIN_VRAM) surface->domain &= ~R300_DOMAIN_GTT; - surface->offset = r300_texture_get_offset(&tex->desc, level, + surface->offset = r300_texture_get_offset(tex, level, surf_tmpl->u.tex.first_layer); - surface->pitch = tex->fb_state.pitch[level]; - surface->format = tex->fb_state.format; + r300_texture_setup_fb_state(surface); /* Parameters for the CBZB clear. */ - surface->cbzb_allowed = tex->desc.cbzb_allowed[level]; + surface->cbzb_allowed = tex->tex.cbzb_allowed[level]; surface->cbzb_width = align(surface->base.width, 64); /* Height must be aligned to the size of a tile. */ - tile_height = r300_get_pixel_alignment(tex->desc.b.b.format, - tex->desc.b.b.nr_samples, - tex->desc.microtile, - tex->desc.macrotile[level], + tile_height = r300_get_pixel_alignment(tex->b.b.b.format, + tex->b.b.b.nr_samples, + tex->tex.microtile, + tex->tex.macrotile[level], DIM_HEIGHT, 0); surface->cbzb_height = align((surface->base.height + 1) / 2, @@ -914,7 +927,7 @@ struct pipe_surface* r300_create_surface(struct pipe_context * ctx, /* Offset must be aligned to 2K and must point at the beginning * of a scanline. */ offset = surface->offset + - tex->desc.stride_in_bytes[level] * surface->cbzb_height; + tex->tex.stride_in_bytes[level] * surface->cbzb_height; surface->cbzb_midpoint_offset = offset & ~2047; surface->cbzb_pitch = surface->pitch & 0x1ffffc; @@ -929,8 +942,8 @@ struct pipe_surface* r300_create_surface(struct pipe_context * ctx, surface->cbzb_allowed ? "YES" : " NO", surface->cbzb_width, surface->cbzb_height, offset & 2047, - tex->desc.microtile ? "YES" : " NO", - tex->desc.macrotile[level] ? "YES" : " NO"); + tex->tex.microtile ? "YES" : " NO", + tex->tex.macrotile[level] ? "YES" : " NO"); } return &surface->base; diff --git a/src/gallium/drivers/r300/r300_texture.h b/src/gallium/drivers/r300/r300_texture.h index 0ab22f747e4..158a387478f 100644 --- a/src/gallium/drivers/r300/r300_texture.h +++ b/src/gallium/drivers/r300/r300_texture.h @@ -32,7 +32,7 @@ struct pipe_resource; struct winsys_handle; struct r300_texture_format_state; struct r300_texture_desc; -struct r300_texture; +struct r300_resource; struct r300_screen; unsigned r300_get_swizzle_combined(const unsigned char *swizzle_format, @@ -46,9 +46,10 @@ uint32_t r300_translate_texformat(enum pipe_format format, uint32_t r500_tx_format_msb_bit(enum pipe_format format); -void r300_texture_reinterpret_format(struct pipe_screen *screen, +boolean r300_resource_set_properties(struct pipe_screen *screen, struct pipe_resource *tex, - enum pipe_format new_format); + unsigned offset, + const struct pipe_resource *new_properties); boolean r300_is_colorbuffer_format_supported(enum pipe_format format); @@ -57,10 +58,14 @@ boolean r300_is_zs_format_supported(enum pipe_format format); boolean r300_is_sampler_format_supported(enum pipe_format format); void r300_texture_setup_format_state(struct r300_screen *screen, - struct r300_texture_desc *desc, + struct r300_resource *tex, unsigned level, struct r300_texture_format_state *out); +boolean r300_resource_get_handle(struct pipe_screen* screen, + struct pipe_resource *texture, + struct winsys_handle *whandle); + struct pipe_resource* r300_texture_from_handle(struct pipe_screen* screen, const struct pipe_resource* base, diff --git a/src/gallium/drivers/r300/r300_texture_desc.c b/src/gallium/drivers/r300/r300_texture_desc.c index 7b1739142d4..2cfeec7d751 100644 --- a/src/gallium/drivers/r300/r300_texture_desc.c +++ b/src/gallium/drivers/r300/r300_texture_desc.c @@ -90,19 +90,19 @@ unsigned r300_get_pixel_alignment(enum pipe_format format, } /* Return true if macrotiling should be enabled on the miplevel. */ -static boolean r300_texture_macro_switch(struct r300_texture_desc *desc, +static boolean r300_texture_macro_switch(struct r300_resource *tex, unsigned level, boolean rv350_mode, enum r300_dim dim) { unsigned tile, texdim; - tile = r300_get_pixel_alignment(desc->b.b.format, desc->b.b.nr_samples, - desc->microtile, R300_BUFFER_TILED, dim, 0); + tile = r300_get_pixel_alignment(tex->b.b.b.format, tex->b.b.b.nr_samples, + tex->tex.microtile, R300_BUFFER_TILED, dim, 0); if (dim == DIM_WIDTH) { - texdim = u_minify(desc->width0, level); + texdim = u_minify(tex->tex.width0, level); } else { - texdim = u_minify(desc->height0, level); + texdim = u_minify(tex->tex.height0, level); } /* See TX_FILTER1_n.MACRO_SWITCH. */ @@ -118,7 +118,7 @@ static boolean r300_texture_macro_switch(struct r300_texture_desc *desc, * at the given level. */ static unsigned r300_texture_get_stride(struct r300_screen *screen, - struct r300_texture_desc *desc, + struct r300_resource *tex, unsigned level) { unsigned tile_width, width, stride; @@ -126,62 +126,62 @@ static unsigned r300_texture_get_stride(struct r300_screen *screen, screen->caps.family == CHIP_FAMILY_RS690 || screen->caps.family == CHIP_FAMILY_RS740); - if (desc->stride_in_bytes_override) - return desc->stride_in_bytes_override; + if (tex->tex.stride_in_bytes_override) + return tex->tex.stride_in_bytes_override; /* Check the level. */ - if (level > desc->b.b.last_level) { + if (level > tex->b.b.b.last_level) { SCREEN_DBG(screen, DBG_TEX, "%s: level (%u) > last_level (%u)\n", - __FUNCTION__, level, desc->b.b.last_level); + __FUNCTION__, level, tex->b.b.b.last_level); return 0; } - width = u_minify(desc->width0, level); + width = u_minify(tex->tex.width0, level); - if (util_format_is_plain(desc->b.b.format)) { - tile_width = r300_get_pixel_alignment(desc->b.b.format, - desc->b.b.nr_samples, - desc->microtile, - desc->macrotile[level], + if (util_format_is_plain(tex->b.b.b.format)) { + tile_width = r300_get_pixel_alignment(tex->b.b.b.format, + tex->b.b.b.nr_samples, + tex->tex.microtile, + tex->tex.macrotile[level], DIM_WIDTH, is_rs690); width = align(width, tile_width); - stride = util_format_get_stride(desc->b.b.format, width); + stride = util_format_get_stride(tex->b.b.b.format, width); /* The alignment to 32 bytes is sort of implied by the layout... */ return stride; } else { - return align(util_format_get_stride(desc->b.b.format, width), is_rs690 ? 64 : 32); + return align(util_format_get_stride(tex->b.b.b.format, width), is_rs690 ? 64 : 32); } } -static unsigned r300_texture_get_nblocksy(struct r300_texture_desc *desc, +static unsigned r300_texture_get_nblocksy(struct r300_resource *tex, unsigned level, boolean *out_aligned_for_cbzb) { unsigned height, tile_height; - height = u_minify(desc->height0, level); + height = u_minify(tex->tex.height0, level); - if (util_format_is_plain(desc->b.b.format)) { - tile_height = r300_get_pixel_alignment(desc->b.b.format, - desc->b.b.nr_samples, - desc->microtile, - desc->macrotile[level], + /* Mipmapped and 3D textures must have their height aligned to POT. */ + if ((tex->b.b.b.target != PIPE_TEXTURE_1D && + tex->b.b.b.target != PIPE_TEXTURE_2D && + tex->b.b.b.target != PIPE_TEXTURE_RECT) || + tex->b.b.b.last_level != 0) { + height = util_next_power_of_two(height); + } + + if (util_format_is_plain(tex->b.b.b.format)) { + tile_height = r300_get_pixel_alignment(tex->b.b.b.format, + tex->b.b.b.nr_samples, + tex->tex.microtile, + tex->tex.macrotile[level], DIM_HEIGHT, 0); height = align(height, tile_height); - /* This is needed for the kernel checker, unfortunately. */ - if ((desc->b.b.target != PIPE_TEXTURE_1D && - desc->b.b.target != PIPE_TEXTURE_2D && - desc->b.b.target != PIPE_TEXTURE_RECT) || - desc->b.b.last_level != 0) { - height = util_next_power_of_two(height); - } - /* See if the CBZB clear can be used on the buffer, * taking the texture size into account. */ if (out_aligned_for_cbzb) { - if (desc->macrotile[level]) { + if (tex->tex.macrotile[level]) { /* When clearing, the layer (width*height) is horizontally split * into two, and the upper and lower halves are cleared by the CB * and ZB units, respectively. Therefore, the number of macrotiles @@ -189,10 +189,10 @@ static unsigned r300_texture_get_nblocksy(struct r300_texture_desc *desc, /* Align the height so that there is an even number of macrotiles. * Do so for 3 or more macrotiles in the Y direction. */ - if (level == 0 && desc->b.b.last_level == 0 && - (desc->b.b.target == PIPE_TEXTURE_1D || - desc->b.b.target == PIPE_TEXTURE_2D || - desc->b.b.target == PIPE_TEXTURE_RECT) && + if (level == 0 && tex->b.b.b.last_level == 0 && + (tex->b.b.b.target == PIPE_TEXTURE_1D || + tex->b.b.b.target == PIPE_TEXTURE_2D || + tex->b.b.b.target == PIPE_TEXTURE_RECT) && height >= tile_height * 3) { height = align(height, tile_height * 2); } @@ -204,11 +204,11 @@ static unsigned r300_texture_get_nblocksy(struct r300_texture_desc *desc, } } - return util_format_get_nblocksy(desc->b.b.format, height); + return util_format_get_nblocksy(tex->b.b.b.format, height); } static void r300_texture_3d_fix_mipmapping(struct r300_screen *screen, - struct r300_texture_desc *desc) + struct r300_resource *tex) { /* The kernels <= 2.6.34-rc4 compute the size of mipmapped 3D textures * incorrectly. This is a workaround to prevent CS from being rejected. */ @@ -216,17 +216,17 @@ static void r300_texture_3d_fix_mipmapping(struct r300_screen *screen, unsigned i, size; if (!screen->rws->get_value(screen->rws, R300_VID_DRM_2_3_0) && - desc->b.b.target == PIPE_TEXTURE_3D && - desc->b.b.last_level > 0) { + tex->b.b.b.target == PIPE_TEXTURE_3D && + tex->b.b.b.last_level > 0) { size = 0; - for (i = 0; i <= desc->b.b.last_level; i++) { - size += desc->stride_in_bytes[i] * - r300_texture_get_nblocksy(desc, i, FALSE); + for (i = 0; i <= tex->b.b.b.last_level; i++) { + size += tex->tex.stride_in_bytes[i] * + r300_texture_get_nblocksy(tex, i, FALSE); } - size *= desc->depth0; - desc->size_in_bytes = size; + size *= tex->tex.depth0; + tex->tex.size_in_bytes = size; } } @@ -239,15 +239,15 @@ static unsigned stride_to_width(enum pipe_format format, } static void r300_setup_miptree(struct r300_screen *screen, - struct r300_texture_desc *desc, + struct r300_resource *tex, boolean align_for_cbzb) { - struct pipe_resource *base = &desc->b.b; + struct pipe_resource *base = &tex->b.b.b; unsigned stride, size, layer_size, nblocksy, i; boolean rv350_mode = screen->caps.family >= CHIP_FAMILY_R350; boolean aligned_for_cbzb; - desc->size_in_bytes = 0; + tex->tex.size_in_bytes = 0; SCREEN_DBG(screen, DBG_TEXALLOC, "r300: Making miptree for texture, format %s\n", @@ -255,21 +255,21 @@ static void r300_setup_miptree(struct r300_screen *screen, for (i = 0; i <= base->last_level; i++) { /* Let's see if this miplevel can be macrotiled. */ - desc->macrotile[i] = - (desc->macrotile[0] == R300_BUFFER_TILED && - r300_texture_macro_switch(desc, i, rv350_mode, DIM_WIDTH) && - r300_texture_macro_switch(desc, i, rv350_mode, DIM_HEIGHT)) ? + tex->tex.macrotile[i] = + (tex->tex.macrotile[0] == R300_BUFFER_TILED && + r300_texture_macro_switch(tex, i, rv350_mode, DIM_WIDTH) && + r300_texture_macro_switch(tex, i, rv350_mode, DIM_HEIGHT)) ? R300_BUFFER_TILED : R300_BUFFER_LINEAR; - stride = r300_texture_get_stride(screen, desc, i); + stride = r300_texture_get_stride(screen, tex, i); /* Compute the number of blocks in Y, see if the CBZB clear can be * used on the texture. */ aligned_for_cbzb = FALSE; - if (align_for_cbzb && desc->cbzb_allowed[i]) - nblocksy = r300_texture_get_nblocksy(desc, i, &aligned_for_cbzb); + if (align_for_cbzb && tex->tex.cbzb_allowed[i]) + nblocksy = r300_texture_get_nblocksy(tex, i, &aligned_for_cbzb); else - nblocksy = r300_texture_get_nblocksy(desc, i, NULL); + nblocksy = r300_texture_get_nblocksy(tex, i, NULL); layer_size = stride * nblocksy; @@ -280,75 +280,136 @@ static void r300_setup_miptree(struct r300_screen *screen, if (base->target == PIPE_TEXTURE_CUBE) size = layer_size * 6; else - size = layer_size * u_minify(desc->depth0, i); + size = layer_size * u_minify(tex->tex.depth0, i); - desc->offset_in_bytes[i] = desc->size_in_bytes; - desc->size_in_bytes = desc->offset_in_bytes[i] + size; - desc->layer_size_in_bytes[i] = layer_size; - desc->stride_in_bytes[i] = stride; - desc->stride_in_pixels[i] = stride_to_width(desc->b.b.format, stride); - desc->cbzb_allowed[i] = desc->cbzb_allowed[i] && aligned_for_cbzb; + tex->tex.offset_in_bytes[i] = tex->tex.size_in_bytes; + tex->tex.size_in_bytes = tex->tex.offset_in_bytes[i] + size; + tex->tex.layer_size_in_bytes[i] = layer_size; + tex->tex.stride_in_bytes[i] = stride; + tex->tex.stride_in_pixels[i] = stride_to_width(tex->b.b.b.format, stride); + tex->tex.cbzb_allowed[i] = tex->tex.cbzb_allowed[i] && aligned_for_cbzb; SCREEN_DBG(screen, DBG_TEXALLOC, "r300: Texture miptree: Level %d " "(%dx%dx%d px, pitch %d bytes) %d bytes total, macrotiled %s\n", - i, u_minify(desc->width0, i), u_minify(desc->height0, i), - u_minify(desc->depth0, i), stride, desc->size_in_bytes, - desc->macrotile[i] ? "TRUE" : "FALSE"); + i, u_minify(tex->tex.width0, i), u_minify(tex->tex.height0, i), + u_minify(tex->tex.depth0, i), stride, tex->tex.size_in_bytes, + tex->tex.macrotile[i] ? "TRUE" : "FALSE"); } } -static void r300_setup_flags(struct r300_texture_desc *desc) +static void r300_setup_flags(struct r300_resource *tex) { - desc->uses_stride_addressing = - !util_is_power_of_two(desc->b.b.width0) || - (desc->stride_in_bytes_override && - stride_to_width(desc->b.b.format, - desc->stride_in_bytes_override) != desc->b.b.width0); - - desc->is_npot = - desc->uses_stride_addressing || - !util_is_power_of_two(desc->b.b.height0) || - !util_is_power_of_two(desc->b.b.depth0); + tex->tex.uses_stride_addressing = + !util_is_power_of_two(tex->b.b.b.width0) || + (tex->tex.stride_in_bytes_override && + stride_to_width(tex->b.b.b.format, + tex->tex.stride_in_bytes_override) != tex->b.b.b.width0); + + tex->tex.is_npot = + tex->tex.uses_stride_addressing || + !util_is_power_of_two(tex->b.b.b.height0) || + !util_is_power_of_two(tex->b.b.b.depth0); } static void r300_setup_cbzb_flags(struct r300_screen *rscreen, - struct r300_texture_desc *desc) + struct r300_resource *tex) { unsigned i, bpp; boolean first_level_valid; - bpp = util_format_get_blocksizebits(desc->b.b.format); + bpp = util_format_get_blocksizebits(tex->b.b.b.format); /* 1) The texture must be point-sampled, * 2) The depth must be 16 or 32 bits. * 3) If the midpoint ZB offset is not aligned to 2048, it returns garbage * with certain texture sizes. Macrotiling ensures the alignment. */ - first_level_valid = desc->b.b.nr_samples <= 1 && + first_level_valid = tex->b.b.b.nr_samples <= 1 && (bpp == 16 || bpp == 32) && - desc->macrotile[0]; + tex->tex.macrotile[0]; if (SCREEN_DBG_ON(rscreen, DBG_NO_CBZB)) first_level_valid = FALSE; - for (i = 0; i <= desc->b.b.last_level; i++) - desc->cbzb_allowed[i] = first_level_valid && desc->macrotile[i]; + for (i = 0; i <= tex->b.b.b.last_level; i++) + tex->tex.cbzb_allowed[i] = first_level_valid && tex->tex.macrotile[i]; +} + +#define ALIGN_DIVUP(x, y) (((x) + (y) - 1) / (y)) + +static void r300_setup_zmask_flags(struct r300_screen *screen, + struct r300_resource *tex) +{ + /* The tile size of 1 DWORD is: + * + * GPU Pipes 4x4 mode 8x8 mode + * ------------------------------------------ + * R580 4P/1Z 32x32 64x64 + * RV570 3P/1Z 48x16 96x32 + * RV530 1P/2Z 32x16 64x32 + * 1P/1Z 16x16 32x32 + */ + static unsigned num_blocks_x_per_dw[4] = {4, 8, 12, 8}; + static unsigned num_blocks_y_per_dw[4] = {4, 4, 4, 8}; + + if (util_format_is_depth_or_stencil(tex->b.b.b.format) && + util_format_get_blocksizebits(tex->b.b.b.format) == 32 && + tex->tex.microtile) { + unsigned i, pipes; + + if (screen->caps.family == CHIP_FAMILY_RV530) { + pipes = screen->caps.num_z_pipes; + } else { + pipes = screen->caps.num_frag_pipes; + } + + for (i = 0; i <= tex->b.b.b.last_level; i++) { + unsigned numdw, compsize; + + /* The 8x8 compression mode needs macrotiling. */ + compsize = screen->caps.z_compress == R300_ZCOMP_8X8 && + tex->tex.macrotile[i] && + tex->b.b.b.nr_samples <= 1 ? 8 : 4; + + /* Get the zbuffer size (with the aligned width and height). */ + numdw = align(tex->tex.stride_in_pixels[i], + num_blocks_x_per_dw[pipes-1] * compsize) * + align(u_minify(tex->b.b.b.height0, i), + num_blocks_y_per_dw[pipes-1] * compsize); + + /* Convert pixels -> dwords. */ + numdw = ALIGN_DIVUP(numdw, num_blocks_x_per_dw[pipes-1] * compsize * + num_blocks_y_per_dw[pipes-1] * compsize); + + /* Check that we have enough ZMASK memory. */ + if (numdw <= screen->caps.zmask_ram * pipes) { + tex->tex.zmask_dwords[i] = numdw; + tex->tex.zcomp8x8[i] = compsize == 8; + } else { + tex->tex.zmask_dwords[i] = 0; + tex->tex.zcomp8x8[i] = FALSE; + } + } + } } static void r300_setup_tiling(struct r300_screen *screen, - struct r300_texture_desc *desc) + struct r300_resource *tex) { struct r300_winsys_screen *rws = screen->rws; - enum pipe_format format = desc->b.b.format; + enum pipe_format format = tex->b.b.b.format; boolean rv350_mode = screen->caps.family >= CHIP_FAMILY_R350; boolean is_zb = util_format_is_depth_or_stencil(format); boolean dbg_no_tiling = SCREEN_DBG_ON(screen, DBG_NO_TILING); + tex->tex.microtile = R300_BUFFER_LINEAR; + tex->tex.macrotile[0] = R300_BUFFER_LINEAR; + if (!util_format_is_plain(format)) { return; } /* If height == 1, disable microtiling except for zbuffer. */ - if (!is_zb && (desc->b.b.height0 == 1 || dbg_no_tiling)) { + if (!is_zb && (tex->b.b.b.height0 == 1 || dbg_no_tiling)) { return; } @@ -357,12 +418,12 @@ static void r300_setup_tiling(struct r300_screen *screen, case 1: case 4: case 8: - desc->microtile = R300_BUFFER_TILED; + tex->tex.microtile = R300_BUFFER_TILED; break; case 2: - if (rws->get_value(rws, R300_VID_SQUARE_TILING_SUPPORT)) { - desc->microtile = R300_BUFFER_SQUARETILED; + if (rws->get_value(rws, R300_VID_DRM_2_1_0)) { + tex->tex.microtile = R300_BUFFER_SQUARETILED; } break; } @@ -372,104 +433,100 @@ static void r300_setup_tiling(struct r300_screen *screen, } /* Set macrotiling. */ - if (r300_texture_macro_switch(desc, 0, rv350_mode, DIM_WIDTH) && - r300_texture_macro_switch(desc, 0, rv350_mode, DIM_HEIGHT)) { - desc->macrotile[0] = R300_BUFFER_TILED; + if (r300_texture_macro_switch(tex, 0, rv350_mode, DIM_WIDTH) && + r300_texture_macro_switch(tex, 0, rv350_mode, DIM_HEIGHT)) { + tex->tex.macrotile[0] = R300_BUFFER_TILED; } } -static void r300_tex_print_info(struct r300_screen *rscreen, - struct r300_texture_desc *desc, +static void r300_tex_print_info(struct r300_resource *tex, const char *func) { fprintf(stderr, "r300: %s: Macro: %s, Micro: %s, Pitch: %i, Dim: %ix%ix%i, " "LastLevel: %i, Size: %i, Format: %s\n", func, - desc->macrotile[0] ? "YES" : " NO", - desc->microtile ? "YES" : " NO", - desc->stride_in_pixels[0], - desc->b.b.width0, desc->b.b.height0, desc->b.b.depth0, - desc->b.b.last_level, desc->size_in_bytes, - util_format_short_name(desc->b.b.format)); + tex->tex.macrotile[0] ? "YES" : " NO", + tex->tex.microtile ? "YES" : " NO", + tex->tex.stride_in_pixels[0], + tex->b.b.b.width0, tex->b.b.b.height0, tex->b.b.b.depth0, + tex->b.b.b.last_level, tex->tex.size_in_bytes, + util_format_short_name(tex->b.b.b.format)); } boolean r300_texture_desc_init(struct r300_screen *rscreen, - struct r300_texture_desc *desc, - const struct pipe_resource *base, - enum r300_buffer_tiling microtile, - enum r300_buffer_tiling macrotile, - unsigned stride_in_bytes_override, - unsigned max_buffer_size) + struct r300_resource *tex, + const struct pipe_resource *base) { - desc->b.b = *base; - desc->b.b.screen = &rscreen->screen; - desc->stride_in_bytes_override = stride_in_bytes_override; - desc->width0 = base->width0; - desc->height0 = base->height0; - desc->depth0 = base->depth0; - - r300_setup_flags(desc); + tex->b.b.b.target = base->target; + tex->b.b.b.format = base->format; + tex->b.b.b.width0 = base->width0; + tex->b.b.b.height0 = base->height0; + tex->b.b.b.depth0 = base->depth0; + tex->b.b.b.array_size = base->array_size; + tex->b.b.b.last_level = base->last_level; + tex->b.b.b.nr_samples = base->nr_samples; + tex->tex.width0 = base->width0; + tex->tex.height0 = base->height0; + tex->tex.depth0 = base->depth0; + + r300_setup_flags(tex); /* Align a 3D NPOT texture to POT. */ - if (base->target == PIPE_TEXTURE_3D && desc->is_npot) { - desc->width0 = util_next_power_of_two(desc->width0); - desc->height0 = util_next_power_of_two(desc->height0); - desc->depth0 = util_next_power_of_two(desc->depth0); + if (base->target == PIPE_TEXTURE_3D && tex->tex.is_npot) { + tex->tex.width0 = util_next_power_of_two(tex->tex.width0); + tex->tex.height0 = util_next_power_of_two(tex->tex.height0); + tex->tex.depth0 = util_next_power_of_two(tex->tex.depth0); } /* Setup tiling. */ - if (microtile == R300_BUFFER_SELECT_LAYOUT || - macrotile == R300_BUFFER_SELECT_LAYOUT) { - r300_setup_tiling(rscreen, desc); - } else { - desc->microtile = microtile; - desc->macrotile[0] = macrotile; - assert(desc->b.b.last_level == 0); + if (tex->tex.microtile == R300_BUFFER_SELECT_LAYOUT) { + r300_setup_tiling(rscreen, tex); } - r300_setup_cbzb_flags(rscreen, desc); + r300_setup_cbzb_flags(rscreen, tex); /* Setup the miptree description. */ - r300_setup_miptree(rscreen, desc, TRUE); + r300_setup_miptree(rscreen, tex, TRUE); /* If the required buffer size is larger the given max size, * try again without the alignment for the CBZB clear. */ - if (max_buffer_size && desc->size_in_bytes > max_buffer_size) { - r300_setup_miptree(rscreen, desc, FALSE); + if (tex->buf_size && tex->tex.size_in_bytes > tex->buf_size) { + r300_setup_miptree(rscreen, tex, FALSE); } - r300_texture_3d_fix_mipmapping(rscreen, desc); + r300_texture_3d_fix_mipmapping(rscreen, tex); + r300_setup_zmask_flags(rscreen, tex); - if (max_buffer_size) { + if (tex->buf_size) { /* Make sure the buffer we got is large enough. */ - if (desc->size_in_bytes > max_buffer_size) { + if (tex->tex.size_in_bytes > tex->buf_size) { fprintf(stderr, "r300: texture_desc_init: The buffer is not " "large enough. Got: %i, Need: %i, Info:\n", - max_buffer_size, desc->size_in_bytes); - r300_tex_print_info(rscreen, desc, "texture_desc_init"); + tex->buf_size, tex->tex.size_in_bytes); + r300_tex_print_info(tex, "texture_desc_init"); return FALSE; } - desc->buffer_size_in_bytes = max_buffer_size; + tex->tex.buffer_size_in_bytes = tex->buf_size; } else { - desc->buffer_size_in_bytes = desc->size_in_bytes; + tex->tex.buffer_size_in_bytes = tex->tex.size_in_bytes; } if (SCREEN_DBG_ON(rscreen, DBG_TEX)) - r300_tex_print_info(rscreen, desc, "texture_desc_init"); + r300_tex_print_info(tex, "texture_desc_init"); return TRUE; } -unsigned r300_texture_get_offset(struct r300_texture_desc *desc, +unsigned r300_texture_get_offset(struct r300_resource *tex, unsigned level, unsigned layer) { - unsigned offset = desc->offset_in_bytes[level]; + unsigned offset = tex->tex.offset_in_bytes[level]; - switch (desc->b.b.target) { + switch (tex->b.b.b.target) { case PIPE_TEXTURE_3D: case PIPE_TEXTURE_CUBE: - return offset + layer * desc->layer_size_in_bytes[level]; + return offset + layer * tex->tex.layer_size_in_bytes[level]; default: assert(layer == 0); diff --git a/src/gallium/drivers/r300/r300_texture_desc.h b/src/gallium/drivers/r300/r300_texture_desc.h index 121d215b4cb..ce6e9643ec6 100644 --- a/src/gallium/drivers/r300/r300_texture_desc.h +++ b/src/gallium/drivers/r300/r300_texture_desc.h @@ -30,7 +30,7 @@ struct pipe_resource; struct r300_screen; struct r300_texture_desc; -struct r300_texture; +struct r300_resource; enum r300_dim { DIM_WIDTH = 0, @@ -44,14 +44,10 @@ unsigned r300_get_pixel_alignment(enum pipe_format format, enum r300_dim dim, boolean is_rs690); boolean r300_texture_desc_init(struct r300_screen *rscreen, - struct r300_texture_desc *desc, - const struct pipe_resource *base, - enum r300_buffer_tiling microtile, - enum r300_buffer_tiling macrotile, - unsigned stride_in_bytes_override, - unsigned max_buffer_size); - -unsigned r300_texture_get_offset(struct r300_texture_desc *desc, + struct r300_resource *tex, + const struct pipe_resource *base); + +unsigned r300_texture_get_offset(struct r300_resource *tex, unsigned level, unsigned layer); #endif diff --git a/src/gallium/drivers/r300/r300_tgsi_to_rc.c b/src/gallium/drivers/r300/r300_tgsi_to_rc.c index 15a323989b2..97ec0a1a1f2 100644 --- a/src/gallium/drivers/r300/r300_tgsi_to_rc.c +++ b/src/gallium/drivers/r300/r300_tgsi_to_rc.c @@ -191,7 +191,12 @@ static void transform_dstreg( dst->File = translate_register_file(src->Register.File); dst->Index = translate_register_index(ttr, src->Register.File, src->Register.Index); dst->WriteMask = src->Register.WriteMask; - dst->RelAddr = src->Register.Indirect; + + if (src->Register.Indirect) { + ttr->error = TRUE; + fprintf(stderr, "r300: Relative addressing of destination operands " + "is unsupported.\n"); + } } static void transform_srcreg( @@ -332,6 +337,8 @@ void r300_tgsi_to_rc(struct tgsi_to_rc * ttr, unsigned imm_index = 0; int i; + ttr->error = FALSE; + /* Allocate constants placeholders. * * Note: What if declared constants are not contiguous? */ diff --git a/src/gallium/drivers/r300/r300_tgsi_to_rc.h b/src/gallium/drivers/r300/r300_tgsi_to_rc.h index 97641a954b9..adb044cfe56 100644 --- a/src/gallium/drivers/r300/r300_tgsi_to_rc.h +++ b/src/gallium/drivers/r300/r300_tgsi_to_rc.h @@ -47,6 +47,9 @@ struct tgsi_to_rc { /* Vertex shaders have no half swizzles, and no way to handle them, so * until rc grows proper support, indicate if they're safe to use. */ boolean use_half_swizzles; + + /* If an error occured. */ + boolean error; }; void r300_tgsi_to_rc(struct tgsi_to_rc * ttr, const struct tgsi_token * tokens); diff --git a/src/gallium/drivers/r300/r300_transfer.c b/src/gallium/drivers/r300/r300_transfer.c index ae93fab554e..30de9ec1e32 100644 --- a/src/gallium/drivers/r300/r300_transfer.c +++ b/src/gallium/drivers/r300/r300_transfer.c @@ -37,7 +37,7 @@ struct r300_transfer { unsigned offset; /* Linear texture. */ - struct r300_texture *linear_texture; + struct r300_resource *linear_texture; }; /* Convenience cast wrapper. */ @@ -54,7 +54,7 @@ static void r300_copy_from_tiled_texture(struct pipe_context *ctx, struct pipe_transfer *transfer = (struct pipe_transfer*)r300transfer; struct pipe_resource *tex = transfer->resource; - ctx->resource_copy_region(ctx, &r300transfer->linear_texture->desc.b.b, 0, + ctx->resource_copy_region(ctx, &r300transfer->linear_texture->b.b.b, 0, 0, 0, 0, tex, transfer->level, &transfer->box); } @@ -70,7 +70,7 @@ static void r300_copy_into_tiled_texture(struct pipe_context *ctx, ctx->resource_copy_region(ctx, tex, transfer->level, transfer->box.x, transfer->box.y, transfer->box.z, - &r300transfer->linear_texture->desc.b.b, 0, &src_box); + &r300transfer->linear_texture->b.b.b, 0, &src_box); ctx->flush(ctx, 0, NULL); } @@ -83,25 +83,24 @@ r300_texture_get_transfer(struct pipe_context *ctx, const struct pipe_box *box) { struct r300_context *r300 = r300_context(ctx); - struct r300_texture *tex = r300_texture(texture); + struct r300_resource *tex = r300_resource(texture); struct r300_transfer *trans; struct pipe_resource base; boolean referenced_cs, referenced_hw, blittable; + const struct util_format_description *desc = + util_format_description(texture->format); referenced_cs = - r300->rws->cs_is_buffer_referenced(r300->cs, - tex->cs_buffer, R300_REF_CS); + r300->rws->cs_is_buffer_referenced(r300->cs, tex->cs_buf); if (referenced_cs) { referenced_hw = TRUE; } else { referenced_hw = - r300->rws->cs_is_buffer_referenced(r300->cs, - tex->cs_buffer, R300_REF_HW); + r300->rws->buffer_is_busy(tex->buf); } - blittable = ctx->screen->is_format_supported( - ctx->screen, texture->format, texture->target, 0, - PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET, 0); + blittable = desc->layout == UTIL_FORMAT_LAYOUT_PLAIN || + desc->layout == UTIL_FORMAT_LAYOUT_S3TC; trans = CALLOC_STRUCT(r300_transfer); if (trans) { @@ -114,8 +113,13 @@ r300_texture_get_transfer(struct pipe_context *ctx, /* If the texture is tiled, we must create a temporary detiled texture * for this transfer. * Also make write transfers pipelined. */ - if (tex->desc.microtile || tex->desc.macrotile[level] || - ((referenced_hw & !(usage & PIPE_TRANSFER_READ)) && blittable)) { + if (tex->tex.microtile || tex->tex.macrotile[level] || + (referenced_hw && blittable && !(usage & PIPE_TRANSFER_READ))) { + if (r300->blitter->running) { + fprintf(stderr, "r300: ERROR: Blitter recursion in texture_get_transfer.\n"); + os_break(); + } + base.target = PIPE_TEXTURE_2D; base.format = texture->format; base.width0 = box->width; @@ -140,7 +144,7 @@ r300_texture_get_transfer(struct pipe_context *ctx, } /* Create the temporary texture. */ - trans->linear_texture = r300_texture( + trans->linear_texture = r300_resource( ctx->screen->resource_create(ctx->screen, &base)); @@ -149,14 +153,14 @@ r300_texture_get_transfer(struct pipe_context *ctx, * Let's flush and try again. */ ctx->flush(ctx, 0, NULL); - trans->linear_texture = r300_texture( + trans->linear_texture = r300_resource( ctx->screen->resource_create(ctx->screen, &base)); if (!trans->linear_texture) { /* For linear textures, it's safe to fallback to * an unpipelined transfer. */ - if (!tex->desc.microtile && !tex->desc.macrotile[level]) { + if (!tex->tex.microtile && !tex->tex.macrotile[level]) { goto unpipelined; } @@ -168,8 +172,8 @@ r300_texture_get_transfer(struct pipe_context *ctx, } } - assert(!trans->linear_texture->desc.microtile && - !trans->linear_texture->desc.macrotile[0]); + assert(!trans->linear_texture->tex.microtile && + !trans->linear_texture->tex.macrotile[0]); /* Set the stride. * @@ -179,7 +183,7 @@ r300_texture_get_transfer(struct pipe_context *ctx, * right thing internally. */ trans->transfer.stride = - trans->linear_texture->desc.stride_in_bytes[0]; + trans->linear_texture->tex.stride_in_bytes[0]; if (usage & PIPE_TRANSFER_READ) { /* We cannot map a tiled texture directly because the data is @@ -194,8 +198,8 @@ r300_texture_get_transfer(struct pipe_context *ctx, unpipelined: /* Unpipelined transfer. */ - trans->transfer.stride = tex->desc.stride_in_bytes[level]; - trans->offset = r300_texture_get_offset(&tex->desc, level, box->z); + trans->transfer.stride = tex->tex.stride_in_bytes[level]; + trans->offset = r300_texture_get_offset(tex, level, box->z); if (referenced_cs) ctx->flush(ctx, PIPE_FLUSH_RENDER_CACHE, NULL); @@ -227,20 +231,19 @@ void* r300_texture_transfer_map(struct pipe_context *ctx, struct r300_context *r300 = r300_context(ctx); struct r300_winsys_screen *rws = (struct r300_winsys_screen *)ctx->winsys; struct r300_transfer *r300transfer = r300_transfer(transfer); - struct r300_texture *tex = r300_texture(transfer->resource); + struct r300_resource *tex = r300_resource(transfer->resource); char *map; - enum pipe_format format = tex->desc.b.b.format; + enum pipe_format format = tex->b.b.b.format; if (r300transfer->linear_texture) { /* The detiled texture is of the same size as the region being mapped * (no offset needed). */ - return rws->buffer_map(rws, - r300transfer->linear_texture->buffer, + return rws->buffer_map(r300transfer->linear_texture->buf, r300->cs, transfer->usage); } else { /* Tiling is disabled. */ - map = rws->buffer_map(rws, tex->buffer, r300->cs, + map = rws->buffer_map(tex->buf, r300->cs, transfer->usage); if (!map) { @@ -258,11 +261,11 @@ void r300_texture_transfer_unmap(struct pipe_context *ctx, { struct r300_winsys_screen *rws = (struct r300_winsys_screen *)ctx->winsys; struct r300_transfer *r300transfer = r300_transfer(transfer); - struct r300_texture *tex = r300_texture(transfer->resource); + struct r300_resource *tex = r300_resource(transfer->resource); if (r300transfer->linear_texture) { - rws->buffer_unmap(rws, r300transfer->linear_texture->buffer); + rws->buffer_unmap(r300transfer->linear_texture->buf); } else { - rws->buffer_unmap(rws, tex->buffer); + rws->buffer_unmap(tex->buf); } } diff --git a/src/gallium/drivers/r300/r300_vs.c b/src/gallium/drivers/r300/r300_vs.c index 78021e2c5d4..b319890157f 100644 --- a/src/gallium/drivers/r300/r300_vs.c +++ b/src/gallium/drivers/r300/r300_vs.c @@ -226,6 +226,13 @@ void r300_translate_vertex_shader(struct r300_context *r300, r300_tgsi_to_rc(&ttr, vs->state.tokens); + if (ttr.error) { + fprintf(stderr, "r300 VP: Cannot translate a shader. " + "Using a dummy shader instead.\n"); + r300_dummy_vertex_shader(r300, vs); + return; + } + if (compiler.Base.Program.Constants.Count > 200) { compiler.Base.remove_unused_constants = TRUE; } diff --git a/src/gallium/drivers/r300/r300_winsys.h b/src/gallium/drivers/r300/r300_winsys.h index 460da77a4fb..d5c73585c81 100644 --- a/src/gallium/drivers/r300/r300_winsys.h +++ b/src/gallium/drivers/r300/r300_winsys.h @@ -28,38 +28,45 @@ * Any winsys hosting this pipe needs to implement r300_winsys_screen and then * call r300_screen_create to start things. */ +#include "r300_defines.h" + +#include "pipebuffer/pb_bufmgr.h" #include "pipe/p_defines.h" #include "pipe/p_state.h" -#include "r300_defines.h" - #define R300_MAX_CMDBUF_DWORDS (16 * 1024) struct winsys_handle; struct r300_winsys_screen; -struct r300_winsys_buffer; /* for map/unmap etc. */ -struct r300_winsys_cs_buffer; /* for write_reloc etc. */ +#define r300_winsys_bo pb_buffer +#define r300_winsys_bo_reference(pdst, src) pb_reference(pdst, src) + +struct r300_winsys_cs_handle; /* for write_reloc etc. */ struct r300_winsys_cs { - unsigned cdw; /* Number of used dwords. */ - uint32_t buf[R300_MAX_CMDBUF_DWORDS]; /* The command buffer. */ + unsigned cdw; /* Number of used dwords. */ + uint32_t *buf; /* The command buffer. */ }; enum r300_value_id { R300_VID_PCI_ID, R300_VID_GB_PIPES, R300_VID_Z_PIPES, - R300_VID_SQUARE_TILING_SUPPORT, - R300_VID_DRM_2_3_0, /* R500 VAP regs, MSPOS regs, fixed tex3D size checking */ - R300_VID_DRM_2_6_0, /* Hyper-Z, GB_Z_PEQ_CONFIG on rv350->r4xx, R500 FG_ALPHA_VALUE */ - R300_VID_DRM_2_8_0, /* R500 US_FORMAT regs, R500 ARGB2101010 colorbuffer */ - R300_CAN_HYPERZ, -}; - -enum r300_reference_domain { /* bitfield */ - R300_REF_CS = 1, - R300_REF_HW = 2 + R300_VID_GART_SIZE, + R300_VID_VRAM_SIZE, + R300_VID_DRM_MAJOR, + R300_VID_DRM_MINOR, + R300_VID_DRM_PATCHLEVEL, + + /* These should probably go away: */ + R300_VID_DRM_2_1_0, /* Square tiling. */ + R300_VID_DRM_2_3_0, /* R500 VAP regs, MSPOS regs, fixed tex3D size checking */ + R300_VID_DRM_2_6_0, /* Hyper-Z, GB_Z_PEQ_CONFIG on rv350->r4xx, R500 FG_ALPHA_VALUE */ + R300_VID_DRM_2_8_0, /* R500 US_FORMAT regs, R500 ARGB2101010 colorbuffer, CMask */ + + R300_CAN_HYPERZ, /* ZMask + HiZ */ + R300_CAN_AACOMPRESS, /* CMask */ }; struct r300_winsys_screen { @@ -98,91 +105,78 @@ struct r300_winsys_screen { * \param domain A bitmask of the R300_DOMAIN_* flags. * \return The created buffer object. */ - struct r300_winsys_buffer *(*buffer_create)(struct r300_winsys_screen *ws, + struct r300_winsys_bo *(*buffer_create)(struct r300_winsys_screen *ws, unsigned size, unsigned alignment, unsigned bind, unsigned usage, enum r300_buffer_domain domain); - struct r300_winsys_cs_buffer *(*buffer_get_cs_handle)( - struct r300_winsys_screen *ws, - struct r300_winsys_buffer *buf); - - /** - * Reference a buffer object (assign with reference counting). - * - * \param ws The winsys this function is called from. - * \param pdst A destination pointer to set the source buffer to. - * \param src A source buffer object. - */ - void (*buffer_reference)(struct r300_winsys_screen *ws, - struct r300_winsys_buffer **pdst, - struct r300_winsys_buffer *src); + struct r300_winsys_cs_handle *(*buffer_get_cs_handle)( + struct r300_winsys_bo *buf); /** * Map the entire data store of a buffer object into the client's address * space. * - * \param ws The winsys this function is called from. * \param buf A winsys buffer object to map. * \param cs A command stream to flush if the buffer is referenced by it. * \param usage A bitmask of the PIPE_TRANSFER_* flags. * \return The pointer at the beginning of the buffer. */ - void *(*buffer_map)(struct r300_winsys_screen *ws, - struct r300_winsys_buffer *buf, + void *(*buffer_map)(struct r300_winsys_bo *buf, struct r300_winsys_cs *cs, enum pipe_transfer_usage usage); /** * Unmap a buffer object from the client's address space. * - * \param ws The winsys this function is called from. * \param buf A winsys buffer object to unmap. */ - void (*buffer_unmap)(struct r300_winsys_screen *ws, - struct r300_winsys_buffer *buf); + void (*buffer_unmap)(struct r300_winsys_bo *buf); + + /** + * Return TRUE if a buffer object is being used by the GPU. + * + * \param buf A winsys buffer object. + */ + boolean (*buffer_is_busy)(struct r300_winsys_bo *buf); /** * Wait for a buffer object until it is not used by a GPU. This is * equivalent to a fence placed after the last command using the buffer, * and synchronizing to the fence. * - * \param ws The winsys this function is called from. * \param buf A winsys buffer object to wait for. */ - void (*buffer_wait)(struct r300_winsys_screen *ws, - struct r300_winsys_buffer *buf); + void (*buffer_wait)(struct r300_winsys_bo *buf); /** * Return tiling flags describing a memory layout of a buffer object. * - * \param ws The winsys this function is called from. * \param buf A winsys buffer object to get the flags from. * \param macrotile A pointer to the return value of the microtile flag. * \param microtile A pointer to the return value of the macrotile flag. * * \note microtile and macrotile are not bitmasks! */ - void (*buffer_get_tiling)(struct r300_winsys_screen *ws, - struct r300_winsys_buffer *buf, + void (*buffer_get_tiling)(struct r300_winsys_bo *buf, enum r300_buffer_tiling *microtile, enum r300_buffer_tiling *macrotile); /** * Set tiling flags describing a memory layout of a buffer object. * - * \param ws The winsys this function is called from. * \param buf A winsys buffer object to set the flags for. + * \param cs A command stream to flush if the buffer is referenced by it. * \param macrotile A macrotile flag. * \param microtile A microtile flag. * \param stride A stride of the buffer in bytes, for texturing. * * \note microtile and macrotile are not bitmasks! */ - void (*buffer_set_tiling)(struct r300_winsys_screen *ws, - struct r300_winsys_buffer *buf, + void (*buffer_set_tiling)(struct r300_winsys_bo *buf, + struct r300_winsys_cs *cs, enum r300_buffer_tiling microtile, enum r300_buffer_tiling macrotile, unsigned stride); @@ -197,7 +191,7 @@ struct r300_winsys_screen { * \param stride The returned buffer stride in bytes. * \param size The returned buffer size. */ - struct r300_winsys_buffer *(*buffer_from_handle)(struct r300_winsys_screen *ws, + struct r300_winsys_bo *(*buffer_from_handle)(struct r300_winsys_screen *ws, struct winsys_handle *whandle, unsigned *stride, unsigned *size); @@ -206,14 +200,12 @@ struct r300_winsys_screen { * Get a winsys handle from a winsys buffer. The internal structure * of the handle is platform-specific and only a winsys should access it. * - * \param ws The winsys this function is called from. * \param buf A winsys buffer object to get the handle from. * \param whandle A winsys handle pointer. * \param stride A stride of the buffer in bytes, for texturing. * \return TRUE on success. */ - boolean (*buffer_get_handle)(struct r300_winsys_screen *ws, - struct r300_winsys_buffer *buf, + boolean (*buffer_get_handle)(struct r300_winsys_bo *buf, unsigned stride, struct winsys_handle *whandle); @@ -248,7 +240,7 @@ struct r300_winsys_screen { * \param wd A write domain containing a bitmask of the R300_DOMAIN_* flags. */ void (*cs_add_reloc)(struct r300_winsys_cs *cs, - struct r300_winsys_cs_buffer *buf, + struct r300_winsys_cs_handle *buf, enum r300_buffer_domain rd, enum r300_buffer_domain wd); @@ -269,7 +261,7 @@ struct r300_winsys_screen { * \param wd A write domain containing a bitmask of the R300_DOMAIN_* flags. */ void (*cs_write_reloc)(struct r300_winsys_cs *cs, - struct r300_winsys_cs_buffer *buf); + struct r300_winsys_cs_handle *buf); /** * Flush a command stream. @@ -279,6 +271,13 @@ struct r300_winsys_screen { void (*cs_flush)(struct r300_winsys_cs *cs); /** + * Wait until the last flush is completed. + * + * \param cs A command stream. + */ + void (*cs_sync_flush)(struct r300_winsys_cs *cs); + + /** * Set a flush callback which is called from winsys when flush is * required. * @@ -291,16 +290,13 @@ struct r300_winsys_screen { void *user); /** - * Return TRUE if a buffer is referenced by a command stream or by hardware - * (i.e. is busy), based on the domain parameter. + * Return TRUE if a buffer is referenced by a command stream. * * \param cs A command stream. * \param buf A winsys buffer. - * \param domain A bitmask of the R300_REF_* enums. */ boolean (*cs_is_buffer_referenced)(struct r300_winsys_cs *cs, - struct r300_winsys_cs_buffer *buf, - enum r300_reference_domain domain); + struct r300_winsys_cs_handle *buf); }; #endif /* R300_WINSYS_H */ diff --git a/src/gallium/drivers/r600/Makefile b/src/gallium/drivers/r600/Makefile index a690b671e49..436de9c4dbd 100644 --- a/src/gallium/drivers/r600/Makefile +++ b/src/gallium/drivers/r600/Makefile @@ -22,7 +22,6 @@ C_SOURCES = \ evergreen_state.c \ eg_asm.c \ r600_translate.c \ - r600_state_common.c \ - r600_upload.c + r600_state_common.c include ../../Makefile.template diff --git a/src/gallium/drivers/r600/SConscript b/src/gallium/drivers/r600/SConscript index e51f50c5df5..5a5fa6d65fd 100644 --- a/src/gallium/drivers/r600/SConscript +++ b/src/gallium/drivers/r600/SConscript @@ -28,7 +28,6 @@ r600 = env.ConvenienceLibrary( 'r600_state_common.c', 'r600_texture.c', 'r600_translate.c', - 'r600_upload.c', 'r700_asm.c', 'evergreen_state.c', 'eg_asm.c', diff --git a/src/gallium/drivers/r600/eg_state_inlines.h b/src/gallium/drivers/r600/eg_state_inlines.h index 5a39d7cdeec..b5fcc7106fe 100644 --- a/src/gallium/drivers/r600/eg_state_inlines.h +++ b/src/gallium/drivers/r600/eg_state_inlines.h @@ -253,9 +253,13 @@ static inline unsigned r600_tex_dim(unsigned dim) default: case PIPE_TEXTURE_1D: return V_030000_SQ_TEX_DIM_1D; + case PIPE_TEXTURE_1D_ARRAY: + return V_030000_SQ_TEX_DIM_1D_ARRAY; case PIPE_TEXTURE_2D: case PIPE_TEXTURE_RECT: return V_030000_SQ_TEX_DIM_2D; + case PIPE_TEXTURE_2D_ARRAY: + return V_030000_SQ_TEX_DIM_2D_ARRAY; case PIPE_TEXTURE_3D: return V_030000_SQ_TEX_DIM_3D; case PIPE_TEXTURE_CUBE: @@ -289,10 +293,14 @@ static inline uint32_t r600_translate_colorswap(enum pipe_format format) { switch (format) { /* 8-bit buffers. */ + case PIPE_FORMAT_L4A4_UNORM: + return V_028C70_SWAP_ALT; + case PIPE_FORMAT_A8_UNORM: return V_028C70_SWAP_ALT_REV; case PIPE_FORMAT_I8_UNORM: case PIPE_FORMAT_L8_UNORM: + case PIPE_FORMAT_L8_SRGB: case PIPE_FORMAT_R8_UNORM: case PIPE_FORMAT_R8_SNORM: return V_028C70_SWAP_STD; @@ -313,6 +321,7 @@ static inline uint32_t r600_translate_colorswap(enum pipe_format format) return V_028C70_SWAP_STD; case PIPE_FORMAT_L8A8_UNORM: + case PIPE_FORMAT_L8A8_SRGB: return V_028C70_SWAP_ALT; case PIPE_FORMAT_R8G8_UNORM: return V_028C70_SWAP_STD; @@ -352,9 +361,11 @@ static inline uint32_t r600_translate_colorswap(enum pipe_format format) case PIPE_FORMAT_R10G10B10A2_UNORM: case PIPE_FORMAT_R10G10B10X2_SNORM: - case PIPE_FORMAT_B10G10R10A2_UNORM: case PIPE_FORMAT_R10SG10SB10SA2U_NORM: - return V_028C70_SWAP_STD_REV; + return V_028C70_SWAP_STD; + + case PIPE_FORMAT_B10G10R10A2_UNORM: + return V_028C70_SWAP_ALT; case PIPE_FORMAT_R16G16_UNORM: return V_028C70_SWAP_STD; @@ -362,14 +373,13 @@ static inline uint32_t r600_translate_colorswap(enum pipe_format format) /* 64-bit buffers. */ case PIPE_FORMAT_R16G16B16A16_UNORM: case PIPE_FORMAT_R16G16B16A16_SNORM: - // return V_028C70_COLOR_16_16_16_16; case PIPE_FORMAT_R16G16B16A16_FLOAT: - // return V_028C70_COLOR_16_16_16_16_FLOAT; /* 128-bit buffers. */ case PIPE_FORMAT_R32G32B32A32_FLOAT: - // return V_028C70_COLOR_32_32_32_32_FLOAT; - return 0; + case PIPE_FORMAT_R32G32B32A32_SNORM: + case PIPE_FORMAT_R32G32B32A32_UNORM: + return V_028C70_SWAP_STD; default: R600_ERR("unsupported colorswap format %d\n", format); return ~0; @@ -381,9 +391,13 @@ static INLINE uint32_t r600_translate_colorformat(enum pipe_format format) { switch (format) { /* 8-bit buffers. */ + case PIPE_FORMAT_L4A4_UNORM: + return V_028C70_COLOR_4_4; + case PIPE_FORMAT_A8_UNORM: case PIPE_FORMAT_I8_UNORM: case PIPE_FORMAT_L8_UNORM: + case PIPE_FORMAT_L8_SRGB: case PIPE_FORMAT_R8_UNORM: case PIPE_FORMAT_R8_SNORM: return V_028C70_COLOR_8; @@ -404,6 +418,7 @@ static INLINE uint32_t r600_translate_colorformat(enum pipe_format format) return V_028C70_COLOR_16; case PIPE_FORMAT_L8A8_UNORM: + case PIPE_FORMAT_L8A8_SRGB: case PIPE_FORMAT_R8G8_UNORM: return V_028C70_COLOR_8_8; @@ -430,7 +445,7 @@ static INLINE uint32_t r600_translate_colorformat(enum pipe_format format) case PIPE_FORMAT_R10G10B10X2_SNORM: case PIPE_FORMAT_B10G10R10A2_UNORM: case PIPE_FORMAT_R10SG10SB10SA2U_NORM: - return V_028C70_COLOR_10_10_10_2; + return V_028C70_COLOR_2_10_10_10; case PIPE_FORMAT_Z24X8_UNORM: case PIPE_FORMAT_Z24_UNORM_S8_USCALED: @@ -471,6 +486,9 @@ static INLINE uint32_t r600_translate_colorformat(enum pipe_format format) return V_028C70_COLOR_32_32; /* 128-bit buffers. */ + case PIPE_FORMAT_R32G32B32A32_SNORM: + case PIPE_FORMAT_R32G32B32A32_UNORM: + return V_028C70_COLOR_32_32_32_32; case PIPE_FORMAT_R32G32B32_FLOAT: return V_028C70_COLOR_32_32_32_FLOAT; case PIPE_FORMAT_R32G32B32A32_FLOAT: @@ -501,9 +519,4 @@ static INLINE boolean r600_is_zs_format_supported(enum pipe_format format) return r600_translate_dbformat(format) != ~0; } -static INLINE boolean r600_is_vertex_format_supported(enum pipe_format format) -{ - return r600_translate_colorformat(format) != ~0; -} - #endif diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c index 306ca03234f..3efdbaba0c3 100644 --- a/src/gallium/drivers/r600/evergreen_state.c +++ b/src/gallium/drivers/r600/evergreen_state.c @@ -103,7 +103,7 @@ static void *evergreen_create_blend_state(struct pipe_context *ctx, } blend->cb_target_mask = target_mask; r600_pipe_state_add_reg(rstate, R_028808_CB_COLOR_CONTROL, - color_control, 0xFFFFFFFF, NULL); + color_control, 0xFFFFFFFD, NULL); r600_pipe_state_add_reg(rstate, R_028C3C_PA_SC_AA_MASK, 0xFFFFFFFF, 0xFFFFFFFF, NULL); for (int i = 0; i < 8; i++) { @@ -351,7 +351,7 @@ static struct pipe_sampler_view *evergreen_create_sampler_view(struct pipe_conte struct r600_resource *rbuffer; unsigned format; uint32_t word4 = 0, yuv_format = 0, pitch = 0; - unsigned char swizzle[4]; + unsigned char swizzle[4], array_mode = 0, tile_type = 0; struct r600_bo *bo[2]; if (resource == NULL) @@ -380,35 +380,42 @@ static struct pipe_sampler_view *evergreen_create_sampler_view(struct pipe_conte if (desc == NULL) { R600_ERR("unknow format %d\n", state->format); } - tmp = (struct r600_resource_texture*)texture; + tmp = (struct r600_resource_texture *)texture; + if (tmp->depth && !tmp->is_flushing_texture) { + r600_texture_depth_flush(ctx, texture, TRUE); + tmp = tmp->flushed_depth_texture; + } + + if (tmp->force_int_type) { + word4 &= C_030010_NUM_FORMAT_ALL; + word4 |= S_030010_NUM_FORMAT_ALL(V_030010_SQ_NUM_FORMAT_INT); + } + rbuffer = &tmp->resource; bo[0] = rbuffer->bo; bo[1] = rbuffer->bo; - /* FIXME depth texture decompression */ - if (tmp->depth) { - r600_texture_depth_flush(ctx, texture); - tmp = (struct r600_resource_texture*)texture; - rbuffer = &tmp->flushed_depth_texture->resource; - bo[0] = rbuffer->bo; - bo[1] = rbuffer->bo; - } - pitch = align(tmp->pitch_in_pixels[0], 8); + + pitch = align(tmp->pitch_in_blocks[0] * util_format_get_blockwidth(state->format), 8); + array_mode = tmp->array_mode[0]; + tile_type = tmp->tile_type; /* FIXME properly handle first level != 0 */ r600_pipe_state_add_reg(rstate, R_030000_RESOURCE0_WORD0, S_030000_DIM(r600_tex_dim(texture->target)) | S_030000_PITCH((pitch / 8) - 1) | + S_030000_NON_DISP_TILING_ORDER(tile_type) | S_030000_TEX_WIDTH(texture->width0 - 1), 0xFFFFFFFF, NULL); r600_pipe_state_add_reg(rstate, R_030004_RESOURCE0_WORD1, S_030004_TEX_HEIGHT(texture->height0 - 1) | - S_030004_TEX_DEPTH(texture->depth0 - 1), + S_030004_TEX_DEPTH(texture->depth0 - 1) | + S_030004_ARRAY_MODE(array_mode), 0xFFFFFFFF, NULL); r600_pipe_state_add_reg(rstate, R_030008_RESOURCE0_WORD2, (tmp->offset[0] + r600_bo_offset(bo[0])) >> 8, 0xFFFFFFFF, bo[0]); r600_pipe_state_add_reg(rstate, R_03000C_RESOURCE0_WORD3, (tmp->offset[1] + r600_bo_offset(bo[1])) >> 8, 0xFFFFFFFF, bo[1]); r600_pipe_state_add_reg(rstate, R_030010_RESOURCE0_WORD4, - word4 | S_030010_NUM_FORMAT_ALL(V_030010_SQ_NUM_FORMAT_NORM) | + word4 | S_030010_SRF_MODE_ALL(V_030010_SRF_MODE_NO_ZERO) | S_030010_BASE_LEVEL(state->u.tex.first_level), 0xFFFFFFFF, NULL); r600_pipe_state_add_reg(rstate, R_030014_RESOURCE0_WORD5, @@ -431,7 +438,8 @@ static void evergreen_set_vs_sampler_view(struct pipe_context *ctx, unsigned cou for (int i = 0; i < count; i++) { if (resource[i]) { - evergreen_context_pipe_state_set_vs_resource(&rctx->ctx, &resource[i]->state, i); + evergreen_context_pipe_state_set_vs_resource(&rctx->ctx, &resource[i]->state, + i + R600_MAX_CONST_BUFFERS); } } } @@ -446,9 +454,11 @@ static void evergreen_set_ps_sampler_view(struct pipe_context *ctx, unsigned cou for (i = 0; i < count; i++) { if (&rctx->ps_samplers.views[i]->base != views[i]) { if (resource[i]) - evergreen_context_pipe_state_set_ps_resource(&rctx->ctx, &resource[i]->state, i); + evergreen_context_pipe_state_set_ps_resource(&rctx->ctx, &resource[i]->state, + i + R600_MAX_CONST_BUFFERS); else - evergreen_context_pipe_state_set_ps_resource(&rctx->ctx, NULL, i); + evergreen_context_pipe_state_set_ps_resource(&rctx->ctx, NULL, + i + R600_MAX_CONST_BUFFERS); pipe_sampler_view_reference( (struct pipe_sampler_view **)&rctx->ps_samplers.views[i], @@ -457,7 +467,8 @@ static void evergreen_set_ps_sampler_view(struct pipe_context *ctx, unsigned cou } for (i = count; i < NUM_TEX_UNITS; i++) { if (rctx->ps_samplers.views[i]) { - evergreen_context_pipe_state_set_ps_resource(&rctx->ctx, NULL, i); + evergreen_context_pipe_state_set_ps_resource(&rctx->ctx, NULL, + i + R600_MAX_CONST_BUFFERS); pipe_sampler_view_reference((struct pipe_sampler_view **)&rctx->ps_samplers.views[i], NULL); } } @@ -638,11 +649,19 @@ static void evergreen_cb(struct r600_pipe_context *rctx, struct r600_pipe_state unsigned color_info; unsigned format, swap, ntype; unsigned offset; + unsigned tile_type; const struct util_format_description *desc; struct r600_bo *bo[3]; + int i; surf = (struct r600_surface *)state->cbufs[cb]; rtex = (struct r600_resource_texture*)state->cbufs[cb]->texture; + + if (rtex->depth && !rtex->is_flushing_texture) { + r600_texture_depth_flush(&rctx->context, state->cbufs[cb]->texture, TRUE); + rtex = rtex->flushed_depth_texture; + } + rbuffer = &rtex->resource; bo[0] = rbuffer->bo; bo[1] = rbuffer->bo; @@ -651,21 +670,43 @@ static void evergreen_cb(struct r600_pipe_context *rctx, struct r600_pipe_state /* XXX quite sure for dx10+ hw don't need any offset hacks */ offset = r600_texture_get_offset((struct r600_resource_texture *)state->cbufs[cb]->texture, level, state->cbufs[cb]->u.tex.first_layer); - pitch = rtex->pitch_in_pixels[level] / 8 - 1; - slice = rtex->pitch_in_pixels[level] * surf->aligned_height / 64 - 1; + pitch = rtex->pitch_in_blocks[level] / 8 - 1; + slice = rtex->pitch_in_blocks[level] * surf->aligned_height / 64 - 1; ntype = 0; - desc = util_format_description(rtex->resource.base.b.format); + desc = util_format_description(surf->base.format); if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) ntype = V_028C70_NUMBER_SRGB; - format = r600_translate_colorformat(rtex->resource.base.b.format); - swap = r600_translate_colorswap(rtex->resource.base.b.format); + format = r600_translate_colorformat(surf->base.format); + swap = r600_translate_colorswap(surf->base.format); + + /* disable when gallium grows int textures */ + if ((format == FMT_32_32_32_32 || format == FMT_16_16_16_16) && rtex->force_int_type) + ntype = 4; + color_info = S_028C70_FORMAT(format) | S_028C70_COMP_SWAP(swap) | + S_028C70_ARRAY_MODE(rtex->array_mode[level]) | S_028C70_BLEND_CLAMP(1) | S_028C70_NUMBER_TYPE(ntype); - if (desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS) - color_info |= S_028C70_SOURCE_FORMAT(1); + + for (i = 0; i < 4; i++) { + if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID) { + break; + } + } + + /* we can only set the export size if any thing is snorm/unorm component is > 11 bits, + if we aren't a float, sint or uint */ + if (desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS && + desc->channel[i].size < 12 && desc->channel[i].type != UTIL_FORMAT_TYPE_FLOAT && + ntype != 4 && ntype != 5) + color_info |= S_028C70_SOURCE_FORMAT(V_028C70_EXPORT_4C_16BPC); + + if (rtex->array_mode[level] > V_028C70_ARRAY_LINEAR_ALIGNED) { + tile_type = rtex->tile_type; + } else /* workaround for linear buffers */ + tile_type = 1; /* FIXME handle enabling of CB beyond BASE8 which has different offset */ r600_pipe_state_add_reg(rstate, @@ -690,7 +731,7 @@ static void evergreen_cb(struct r600_pipe_context *rctx, struct r600_pipe_state 0x00000000, 0xFFFFFFFF, NULL); r600_pipe_state_add_reg(rstate, R_028C74_CB_COLOR0_ATTRIB + cb * 0x3C, - S_028C74_NON_DISP_TILING_ORDER(1), + S_028C74_NON_DISP_TILING_ORDER(tile_type), 0xFFFFFFFF, bo[0]); } @@ -711,17 +752,14 @@ static void evergreen_db(struct r600_pipe_context *rctx, struct r600_pipe_state surf = (struct r600_surface *)state->zsbuf; rtex = (struct r600_resource_texture*)state->zsbuf->texture; - rtex->tiled = 1; - rtex->array_mode[level] = 2; - rtex->tile_type = 1; - rtex->depth = 1; + rbuffer = &rtex->resource; /* XXX quite sure for dx10+ hw don't need any offset hacks */ offset = r600_texture_get_offset((struct r600_resource_texture *)state->zsbuf->texture, level, state->zsbuf->u.tex.first_layer); - pitch = rtex->pitch_in_pixels[level] / 8 - 1; - slice = rtex->pitch_in_pixels[level] * surf->aligned_height / 64 - 1; + pitch = rtex->pitch_in_blocks[level] / 8 - 1; + slice = rtex->pitch_in_blocks[level] * surf->aligned_height / 64 - 1; format = r600_translate_dbformat(state->zsbuf->texture->format); stencil_format = r600_translate_stencilformat(state->zsbuf->texture->format); @@ -837,51 +875,6 @@ static void evergreen_set_framebuffer_state(struct pipe_context *ctx, } } -static void evergreen_set_constant_buffer(struct pipe_context *ctx, uint shader, uint index, - struct pipe_resource *buffer) -{ - struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; - struct r600_resource *rbuffer = (struct r600_resource*)buffer; - uint32_t offset; - - /* Note that the state tracker can unbind constant buffers by - * passing NULL here. - */ - if (buffer == NULL) { - return; - } - - r600_upload_const_buffer(rctx, buffer, &offset); - - switch (shader) { - case PIPE_SHADER_VERTEX: - rctx->vs_const_buffer.nregs = 0; - r600_pipe_state_add_reg(&rctx->vs_const_buffer, - R_028180_ALU_CONST_BUFFER_SIZE_VS_0, - ALIGN_DIVUP(buffer->width0 >> 4, 16), - 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(&rctx->vs_const_buffer, - R_028980_ALU_CONST_CACHE_VS_0, - (r600_bo_offset(rbuffer->bo) + offset) >> 8, 0xFFFFFFFF, rbuffer->bo); - r600_context_pipe_state_set(&rctx->ctx, &rctx->vs_const_buffer); - break; - case PIPE_SHADER_FRAGMENT: - rctx->ps_const_buffer.nregs = 0; - r600_pipe_state_add_reg(&rctx->ps_const_buffer, - R_028140_ALU_CONST_BUFFER_SIZE_PS_0, - ALIGN_DIVUP(buffer->width0 >> 4, 16), - 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(&rctx->ps_const_buffer, - R_028940_ALU_CONST_CACHE_PS_0, - (r600_bo_offset(rbuffer->bo) + offset) >> 8, 0xFFFFFFFF, rbuffer->bo); - r600_context_pipe_state_set(&rctx->ctx, &rctx->ps_const_buffer); - break; - default: - R600_ERR("unsupported %d\n", shader); - return; - } -} - void evergreen_init_state_functions(struct r600_pipe_context *rctx) { rctx->context.create_blend_state = evergreen_create_blend_state; @@ -909,7 +902,7 @@ void evergreen_init_state_functions(struct r600_pipe_context *rctx) rctx->context.delete_vs_state = r600_delete_vs_shader; rctx->context.set_blend_color = evergreen_set_blend_color; rctx->context.set_clip_state = evergreen_set_clip_state; - rctx->context.set_constant_buffer = evergreen_set_constant_buffer; + rctx->context.set_constant_buffer = r600_set_constant_buffer; rctx->context.set_fragment_sampler_views = evergreen_set_ps_sampler_view; rctx->context.set_framebuffer_state = evergreen_set_framebuffer_state; rctx->context.set_polygon_stipple = evergreen_set_polygon_stipple; @@ -921,6 +914,7 @@ void evergreen_init_state_functions(struct r600_pipe_context *rctx) rctx->context.set_vertex_sampler_views = evergreen_set_vs_sampler_view; rctx->context.set_viewport_state = evergreen_set_viewport_state; rctx->context.sampler_view_destroy = r600_sampler_view_destroy; + rctx->context.redefine_user_buffer = u_default_redefine_user_buffer; } void evergreen_init_config(struct r600_pipe_context *rctx) @@ -1325,216 +1319,6 @@ void evergreen_polygon_offset_update(struct r600_pipe_context *rctx) } } -static void evergreen_spi_update(struct r600_pipe_context *rctx) -{ - struct r600_pipe_shader *shader = rctx->ps_shader; - struct r600_pipe_state rstate; - struct r600_shader *rshader = &shader->shader; - unsigned i, tmp; - - rstate.nregs = 0; - for (i = 0; i < rshader->ninput; i++) { - tmp = S_028644_SEMANTIC(r600_find_vs_semantic_index(&rctx->vs_shader->shader, rshader, i)); - if (rshader->input[i].name == TGSI_SEMANTIC_COLOR || - rshader->input[i].name == TGSI_SEMANTIC_BCOLOR || - rshader->input[i].name == TGSI_SEMANTIC_POSITION) { - tmp |= S_028644_FLAT_SHADE(rctx->flatshade); - } - if (rshader->input[i].name == TGSI_SEMANTIC_GENERIC && - rctx->sprite_coord_enable & (1 << rshader->input[i].sid)) { - tmp |= S_028644_PT_SPRITE_TEX(1); - } - r600_pipe_state_add_reg(&rstate, R_028644_SPI_PS_INPUT_CNTL_0 + i * 4, tmp, 0xFFFFFFFF, NULL); - } - r600_context_pipe_state_set(&rctx->ctx, &rstate); -} - -void evergreen_vertex_buffer_update(struct r600_pipe_context *rctx) -{ - struct r600_pipe_state *rstate; - struct r600_resource *rbuffer; - struct pipe_vertex_buffer *vertex_buffer; - unsigned i, offset; - - /* we don't update until we know vertex elements */ - if (rctx->vertex_elements == NULL || !rctx->nvertex_buffer) - return; - - if (rctx->vertex_elements->incompatible_layout) { - /* translate rebind new vertex elements so - * return once translated - */ - r600_begin_vertex_translate(rctx); - return; - } - - if (rctx->any_user_vbs) { - r600_upload_user_buffers(rctx); - rctx->any_user_vbs = FALSE; - } - - if (rctx->vertex_elements->vbuffer_need_offset) { - /* one resource per vertex elements */ - rctx->nvs_resource = rctx->vertex_elements->count; - } else { - /* bind vertex buffer once */ - rctx->nvs_resource = rctx->nvertex_buffer; - } - - for (i = 0 ; i < rctx->nvs_resource; i++) { - rstate = &rctx->vs_resource[i]; - rstate->id = R600_PIPE_STATE_RESOURCE; - rstate->nregs = 0; - - if (rctx->vertex_elements->vbuffer_need_offset) { - /* one resource per vertex elements */ - unsigned vbuffer_index; - vbuffer_index = rctx->vertex_elements->elements[i].vertex_buffer_index; - vertex_buffer = &rctx->vertex_buffer[vbuffer_index]; - rbuffer = (struct r600_resource*)vertex_buffer->buffer; - offset = rctx->vertex_elements->vbuffer_offset[i]; - } else { - /* bind vertex buffer once */ - vertex_buffer = &rctx->vertex_buffer[i]; - rbuffer = (struct r600_resource*)vertex_buffer->buffer; - offset = 0; - } - if (vertex_buffer == NULL || rbuffer == NULL) - continue; - offset += vertex_buffer->buffer_offset + r600_bo_offset(rbuffer->bo); - - r600_pipe_state_add_reg(rstate, R_030000_RESOURCE0_WORD0, - offset, 0xFFFFFFFF, rbuffer->bo); - r600_pipe_state_add_reg(rstate, R_030004_RESOURCE0_WORD1, - rbuffer->bo_size - offset - 1, 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(rstate, R_030008_RESOURCE0_WORD2, - S_030008_STRIDE(vertex_buffer->stride), - 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(rstate, R_03000C_RESOURCE0_WORD3, - S_03000C_DST_SEL_X(V_03000C_SQ_SEL_X) | - S_03000C_DST_SEL_Y(V_03000C_SQ_SEL_Y) | - S_03000C_DST_SEL_Z(V_03000C_SQ_SEL_Z) | - S_03000C_DST_SEL_W(V_03000C_SQ_SEL_W), - 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(rstate, R_030010_RESOURCE0_WORD4, - 0x00000000, 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(rstate, R_030014_RESOURCE0_WORD5, - 0x00000000, 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(rstate, R_030018_RESOURCE0_WORD6, - 0x00000000, 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(rstate, R_03001C_RESOURCE0_WORD7, - 0xC0000000, 0xFFFFFFFF, NULL); - evergreen_context_pipe_state_set_fs_resource(&rctx->ctx, rstate, i); - } -} - -int r600_conv_pipe_prim(unsigned pprim, unsigned *prim); -void evergreen_draw(struct pipe_context *ctx, const struct pipe_draw_info *info) -{ - struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; - struct r600_resource *rbuffer; - u32 vgt_dma_index_type, vgt_draw_initiator, mask; - struct r600_draw rdraw; - struct r600_pipe_state vgt; - struct r600_drawl draw; - unsigned prim; - - memset(&draw, 0, sizeof(struct r600_drawl)); - draw.ctx = ctx; - draw.mode = info->mode; - draw.start = info->start; - draw.count = info->count; - if (info->indexed && rctx->index_buffer.buffer) { - draw.start += rctx->index_buffer.offset / rctx->index_buffer.index_size; - draw.min_index = info->min_index; - draw.max_index = info->max_index; - draw.index_bias = info->index_bias; - - r600_translate_index_buffer(rctx, &rctx->index_buffer.buffer, - &rctx->index_buffer.index_size, - &draw.start, - info->count); - - draw.index_size = rctx->index_buffer.index_size; - pipe_resource_reference(&draw.index_buffer, rctx->index_buffer.buffer); - draw.index_buffer_offset = draw.start * draw.index_size; - draw.start = 0; - r600_upload_index_buffer(rctx, &draw); - } else { - draw.index_size = 0; - draw.index_buffer = NULL; - draw.min_index = info->min_index; - draw.max_index = info->max_index; - draw.index_bias = info->start; - } - - switch (draw.index_size) { - case 2: - vgt_draw_initiator = 0; - vgt_dma_index_type = 0; - break; - case 4: - vgt_draw_initiator = 0; - vgt_dma_index_type = 1; - break; - case 0: - vgt_draw_initiator = 2; - vgt_dma_index_type = 0; - break; - default: - R600_ERR("unsupported index size %d\n", draw.index_size); - return; - } - if (r600_conv_pipe_prim(draw.mode, &prim)) - return; - if (unlikely(rctx->ps_shader == NULL)) { - R600_ERR("missing vertex shader\n"); - return; - } - if (unlikely(rctx->vs_shader == NULL)) { - R600_ERR("missing vertex shader\n"); - return; - } - /* there should be enough input */ - if (rctx->vertex_elements->count < rctx->vs_shader->shader.bc.nresource) { - R600_ERR("%d resources provided, expecting %d\n", - rctx->vertex_elements->count, rctx->vs_shader->shader.bc.nresource); - return; - } - - evergreen_spi_update(rctx); - - mask = 0; - for (int i = 0; i < rctx->framebuffer.nr_cbufs; i++) { - mask |= (0xF << (i * 4)); - } - - vgt.id = R600_PIPE_STATE_VGT; - vgt.nregs = 0; - r600_pipe_state_add_reg(&vgt, R_008958_VGT_PRIMITIVE_TYPE, prim, 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(&vgt, R_028408_VGT_INDX_OFFSET, draw.index_bias, 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(&vgt, R_028238_CB_TARGET_MASK, rctx->cb_target_mask & mask, 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(&vgt, R_028400_VGT_MAX_VTX_INDX, draw.max_index, 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(&vgt, R_028404_VGT_MIN_VTX_INDX, draw.min_index, 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(&vgt, R_03CFF0_SQ_VTX_BASE_VTX_LOC, 0, 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(&vgt, R_03CFF4_SQ_VTX_START_INST_LOC, 0, 0xFFFFFFFF, NULL); - r600_context_pipe_state_set(&rctx->ctx, &vgt); - - rdraw.vgt_num_indices = draw.count; - rdraw.vgt_num_instances = 1; - rdraw.vgt_index_type = vgt_dma_index_type; - rdraw.vgt_draw_initiator = vgt_draw_initiator; - rdraw.indices = NULL; - if (draw.index_buffer) { - rbuffer = (struct r600_resource*)draw.index_buffer; - rdraw.indices = rbuffer->bo; - rdraw.indices_bo_offset = draw.index_buffer_offset; - } - evergreen_context_draw(&rctx->ctx, &rdraw); - - pipe_resource_reference(&draw.index_buffer, NULL); -} - void evergreen_pipe_shader_ps(struct pipe_context *ctx, struct r600_pipe_shader *shader) { struct r600_pipe_state *rstate = &shader->rstate; @@ -1733,3 +1517,31 @@ void *evergreen_create_db_flush_dsa(struct r600_pipe_context *rctx) S_028000_COPY_CENTROID(1), NULL); return rstate; } + +void evergreen_pipe_set_buffer_resource(struct r600_pipe_context *rctx, + struct r600_pipe_state *rstate, + struct r600_resource *rbuffer, + unsigned offset, unsigned stride) +{ + r600_pipe_state_add_reg(rstate, R_030000_RESOURCE0_WORD0, + offset, 0xFFFFFFFF, rbuffer->bo); + r600_pipe_state_add_reg(rstate, R_030004_RESOURCE0_WORD1, + rbuffer->bo_size - offset - 1, 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(rstate, R_030008_RESOURCE0_WORD2, + S_030008_STRIDE(stride), + 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(rstate, R_03000C_RESOURCE0_WORD3, + S_03000C_DST_SEL_X(V_03000C_SQ_SEL_X) | + S_03000C_DST_SEL_Y(V_03000C_SQ_SEL_Y) | + S_03000C_DST_SEL_Z(V_03000C_SQ_SEL_Z) | + S_03000C_DST_SEL_W(V_03000C_SQ_SEL_W), + 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(rstate, R_030010_RESOURCE0_WORD4, + 0x00000000, 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(rstate, R_030014_RESOURCE0_WORD5, + 0x00000000, 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(rstate, R_030018_RESOURCE0_WORD6, + 0x00000000, 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(rstate, R_03001C_RESOURCE0_WORD7, + 0xC0000000, 0xFFFFFFFF, NULL); +} diff --git a/src/gallium/drivers/r600/evergreend.h b/src/gallium/drivers/r600/evergreend.h index e09e02ca000..f0a1ee0cd02 100644 --- a/src/gallium/drivers/r600/evergreend.h +++ b/src/gallium/drivers/r600/evergreend.h @@ -327,6 +327,9 @@ #define S_028C70_SOURCE_FORMAT(x) (((x) & 0x3) << 24) #define G_028C70_SOURCE_FORMAT(x) (((x) >> 24) & 0x3) #define C_028C70_SOURCE_FORMAT 0xFCFFFFFF +#define V_028C70_EXPORT_4C_32BPC 0x0 +#define V_028C70_EXPORT_4C_16BPC 0x1 +#define V_028C70_EXPORT_2C_32BPC 0x2 /* Do not use */ #define S_028C70_RAT(x) (((x) & 0x1) << 26) #define G_028C70_RAT(x) (((x) >> 26) & 0x1) #define C_028C70_RAT 0xFBFFFFFF @@ -427,15 +430,6 @@ #define C_028800_STENCILZFAIL_BF 0x1FFFFFFF #define R_028808_CB_COLOR_CONTROL 0x028808 -#define S_028808_FOG_ENABLE(x) (((x) & 0x1) << 0) -#define G_028808_FOG_ENABLE(x) (((x) >> 0) & 0x1) -#define C_028808_FOG_ENABLE 0xFFFFFFFE -#define S_028808_MULTIWRITE_ENABLE(x) (((x) & 0x1) << 1) -#define G_028808_MULTIWRITE_ENABLE(x) (((x) >> 1) & 0x1) -#define C_028808_MULTIWRITE_ENABLE 0xFFFFFFFD -#define S_028808_DITHER_ENABLE(x) (((x) & 0x1) << 2) -#define G_028808_DITHER_ENABLE(x) (((x) >> 2) & 0x1) -#define C_028808_DITHER_ENABLE 0xFFFFFFFB #define S_028808_DEGAMMA_ENABLE(x) (((x) & 0x1) << 3) #define G_028808_DEGAMMA_ENABLE(x) (((x) >> 3) & 0x1) #define C_028808_DEGAMMA_ENABLE 0xFFFFFFF7 @@ -939,6 +933,9 @@ #define V_030000_SQ_TEX_DIM_2D_ARRAY 0x00000005 #define V_030000_SQ_TEX_DIM_2D_MSAA 0x00000006 #define V_030000_SQ_TEX_DIM_2D_ARRAY_MSAA 0x00000007 +#define S_030000_NON_DISP_TILING_ORDER(x) (((x) & 0x1) << 5) +#define G_030000_NON_DISP_TILING_ORDER(x) (((x) >> 5) & 0x1) +#define C_030000_NON_DISP_TILING_ORDER 0xFFFFFFDF #define S_030000_PITCH(x) (((x) & 0xFFF) << 6) #define G_030000_PITCH(x) (((x) >> 6) & 0xFFF) #define C_030000_PITCH 0xFFFC003F diff --git a/src/gallium/drivers/r600/r600.h b/src/gallium/drivers/r600/r600.h index a852bef6156..64c52bca795 100644 --- a/src/gallium/drivers/r600/r600.h +++ b/src/gallium/drivers/r600/r600.h @@ -113,6 +113,7 @@ struct r600_tiling_info { enum radeon_family r600_get_family(struct radeon *rw); enum chip_class r600_get_family_class(struct radeon *radeon); struct r600_tiling_info *r600_get_tiling_info(struct radeon *radeon); +unsigned r600_get_clock_crystal_freq(struct radeon *radeon); /* r600_bo.c */ struct r600_bo; @@ -249,6 +250,7 @@ struct r600_context { struct list_head query_list; unsigned num_query_running; struct list_head fenced_bo; + unsigned max_db; /* for OQ */ }; struct r600_draw { diff --git a/src/gallium/drivers/r600/r600_asm.c b/src/gallium/drivers/r600/r600_asm.c index f4ff2fc3d43..1393df88757 100644 --- a/src/gallium/drivers/r600/r600_asm.c +++ b/src/gallium/drivers/r600/r600_asm.c @@ -50,6 +50,7 @@ static inline unsigned int r600_bc_get_num_operands(struct r600_bc *bc, struct r case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP: return 0; case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_ADD: + case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_ADD_INT: case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLE: case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLGT: case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLGE: @@ -97,6 +98,7 @@ static inline unsigned int r600_bc_get_num_operands(struct r600_bc *bc, struct r case EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP: return 0; case EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_ADD: + case EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_ADD_INT: case EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLE: case EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLGT: case EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLGE: @@ -288,6 +290,31 @@ int r600_bc_add_output(struct r600_bc *bc, const struct r600_bc_output *output) { int r; + if (bc->cf_last && bc->cf_last->inst == BC_INST(bc, V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT) && + output->type == bc->cf_last->output.type && + output->elem_size == bc->cf_last->output.elem_size && + output->swizzle_x == bc->cf_last->output.swizzle_x && + output->swizzle_y == bc->cf_last->output.swizzle_y && + output->swizzle_z == bc->cf_last->output.swizzle_z && + output->swizzle_w == bc->cf_last->output.swizzle_w && + (output->burst_count + bc->cf_last->output.burst_count) <= 16) { + + if ((output->gpr + output->burst_count) == bc->cf_last->output.gpr && + (output->array_base + output->burst_count) == bc->cf_last->output.array_base) { + + bc->cf_last->output.gpr = output->gpr; + bc->cf_last->output.array_base = output->array_base; + bc->cf_last->output.burst_count += output->burst_count; + return 0; + + } else if (output->gpr == (bc->cf_last->output.gpr + bc->cf_last->output.burst_count) && + output->array_base == (bc->cf_last->output.array_base + bc->cf_last->output.burst_count)) { + + bc->cf_last->output.burst_count += output->burst_count; + return 0; + } + } + r = r600_bc_add_cf(bc); if (r) return r; @@ -418,6 +445,20 @@ static int is_alu_reduction_inst(struct r600_bc *bc, struct r600_bc_alu *alu) } } +static int is_alu_cube_inst(struct r600_bc *bc, struct r600_bc_alu *alu) +{ + switch (bc->chiprev) { + case CHIPREV_R600: + case CHIPREV_R700: + return !alu->is_op3 && + alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_CUBE; + case CHIPREV_EVERGREEN: + default: + return !alu->is_op3 && + alu->inst == EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_CUBE; + } +} + static int is_alu_mova_inst(struct r600_bc *bc, struct r600_bc_alu *alu) { switch (bc->chiprev) { @@ -480,9 +521,9 @@ static int is_alu_trans_unit_inst(struct r600_bc *bc, struct r600_bc_alu *alu) case CHIPREV_EVERGREEN: default: if (!alu->is_op3) + /* Note that FLT_TO_INT* instructions are vector instructions + * on Evergreen, despite what the documentation says. */ return alu->inst == EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_ASHR_INT || - alu->inst == EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FLT_TO_INT || - alu->inst == EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FLT_TO_INT_FLOOR || alu->inst == EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_INT_TO_FLT || alu->inst == EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_LSHL_INT || alu->inst == EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_LSHR_INT || @@ -563,7 +604,7 @@ struct alu_bank_swizzle { int hw_cfile_elem[4]; }; -const unsigned cycle_for_bank_swizzle_vec[][3] = { +static const unsigned cycle_for_bank_swizzle_vec[][3] = { [SQ_ALU_VEC_012] = { 0, 1, 2 }, [SQ_ALU_VEC_021] = { 0, 2, 1 }, [SQ_ALU_VEC_120] = { 1, 2, 0 }, @@ -572,7 +613,7 @@ const unsigned cycle_for_bank_swizzle_vec[][3] = { [SQ_ALU_VEC_210] = { 2, 1, 0 } }; -const unsigned cycle_for_bank_swizzle_scl[][3] = { +static const unsigned cycle_for_bank_swizzle_scl[][3] = { [SQ_ALU_SCL_210] = { 2, 1, 0 }, [SQ_ALU_SCL_122] = { 1, 2, 2 }, [SQ_ALU_SCL_212] = { 2, 1, 2 }, @@ -785,7 +826,8 @@ static int replace_gpr_with_pv_ps(struct r600_bc *bc, for (i = 0; i < 5; ++i) { if(prev[i] && prev[i]->dst.write && !prev[i]->dst.rel) { gpr[i] = prev[i]->dst.sel; - if (is_alu_reduction_inst(bc, prev[i])) + /* cube writes more than PV.X */ + if (!is_alu_cube_inst(bc, prev[i]) && is_alu_reduction_inst(bc, prev[i])) chan[i] = 0; else chan[i] = prev[i]->dst.chan; @@ -865,7 +907,7 @@ static int r600_bc_alu_nliterals(struct r600_bc *bc, struct r600_bc_alu *alu, for (i = 0; i < num_src; ++i) { if (alu->src[i].sel == V_SQ_ALU_SRC_LITERAL) { - uint32_t value = alu->src[i].value[alu->src[i].chan]; + uint32_t value = alu->src[i].value; unsigned found = 0; for (j = 0; j < *nliteral; ++j) { if (literal[j] == value) { @@ -892,7 +934,7 @@ static void r600_bc_alu_adjust_literals(struct r600_bc *bc, for (i = 0; i < num_src; ++i) { if (alu->src[i].sel == V_SQ_ALU_SRC_LITERAL) { - uint32_t value = alu->src[i].value[alu->src[i].chan]; + uint32_t value = alu->src[i].value; for (j = 0; j < nliteral; ++j) { if (literal[j] == value) { alu->src[i].chan = j; @@ -1195,8 +1237,7 @@ int r600_bc_add_alu_type(struct r600_bc *bc, const struct r600_bc_alu *alu, int bc->ngpr = nalu->src[i].sel + 1; } if (nalu->src[i].sel == V_SQ_ALU_SRC_LITERAL) - r600_bc_special_constants( - nalu->src[i].value[nalu->src[i].chan], + r600_bc_special_constants(nalu->src[i].value, &nalu->src[i].sel, &nalu->src[i].neg); } if (nalu->dst.sel >= bc->ngpr) { @@ -1308,6 +1349,18 @@ int r600_bc_add_tex(struct r600_bc *bc, const struct r600_bc_tex *tex) return -ENOMEM; memcpy(ntex, tex, sizeof(struct r600_bc_tex)); + /* we can't fetch data und use it as texture lookup address in the same TEX clause */ + if (bc->cf_last != NULL && + bc->cf_last->inst == V_SQ_CF_WORD1_SQ_CF_INST_TEX) { + struct r600_bc_tex *ttex; + LIST_FOR_EACH_ENTRY(ttex, &bc->cf_last->tex, list) { + if (ttex->dst_gpr == ntex->src_gpr) { + bc->force_add_cf = 1; + break; + } + } + } + /* cf can contains only alu or only vtx or only tex */ if (bc->cf_last == NULL || bc->cf_last->inst != V_SQ_CF_WORD1_SQ_CF_INST_TEX || @@ -1374,6 +1427,7 @@ static int r600_bc_vtx_build(struct r600_bc *bc, struct r600_bc_vtx *vtx, unsign } } bc->bytecode[id++] = S_SQ_VTX_WORD0_BUFFER_ID(vtx->buffer_id + fetch_resource_start) | + S_SQ_VTX_WORD0_FETCH_TYPE(vtx->fetch_type) | S_SQ_VTX_WORD0_SRC_GPR(vtx->src_gpr) | S_SQ_VTX_WORD0_SRC_SEL_X(vtx->src_sel_x) | S_SQ_VTX_WORD0_MEGA_FETCH_COUNT(vtx->mega_fetch_count); @@ -2674,18 +2728,73 @@ void r600_bc_dump(struct r600_bc *bc) } LIST_FOR_EACH_ENTRY(tex, &cf->tex, list) { - //TODO + fprintf(stderr, "%04d %08X ", id, bc->bytecode[id]); + fprintf(stderr, "INST:%d ", tex->inst); + fprintf(stderr, "RESOURCE_ID:%d ", tex->resource_id); + fprintf(stderr, "SRC(GPR:%d ", tex->src_gpr); + fprintf(stderr, "REL:%d)\n", tex->src_rel); + id++; + fprintf(stderr, "%04d %08X ", id, bc->bytecode[id]); + fprintf(stderr, "DST(GPR:%d ", tex->dst_gpr); + fprintf(stderr, "REL:%d ", tex->dst_rel); + fprintf(stderr, "SEL_X:%d ", tex->dst_sel_x); + fprintf(stderr, "SEL_Y:%d ", tex->dst_sel_y); + fprintf(stderr, "SEL_Z:%d ", tex->dst_sel_z); + fprintf(stderr, "SEL_W:%d) ", tex->dst_sel_w); + fprintf(stderr, "LOD_BIAS:%d ", tex->lod_bias); + fprintf(stderr, "COORD_TYPE_X:%d ", tex->coord_type_x); + fprintf(stderr, "COORD_TYPE_Y:%d ", tex->coord_type_y); + fprintf(stderr, "COORD_TYPE_Z:%d ", tex->coord_type_z); + fprintf(stderr, "COORD_TYPE_W:%d\n", tex->coord_type_w); + id++; + fprintf(stderr, "%04d %08X ", id, bc->bytecode[id]); + fprintf(stderr, "OFFSET_X:%d ", tex->offset_x); + fprintf(stderr, "OFFSET_Y:%d ", tex->offset_y); + fprintf(stderr, "OFFSET_Z:%d ", tex->offset_z); + fprintf(stderr, "SAMPLER_ID:%d ", tex->sampler_id); + fprintf(stderr, "SRC(SEL_X:%d ", tex->src_sel_x); + fprintf(stderr, "SEL_Y:%d ", tex->src_sel_y); + fprintf(stderr, "SEL_Z:%d ", tex->src_sel_z); + fprintf(stderr, "SEL_W:%d)\n", tex->src_sel_w); + id++; + fprintf(stderr, "%04d %08X \n", id, bc->bytecode[id]); + id++; } LIST_FOR_EACH_ENTRY(vtx, &cf->vtx, list) { + fprintf(stderr, "%04d %08X ", id, bc->bytecode[id]); + fprintf(stderr, "INST:%d ", vtx->inst); + fprintf(stderr, "FETCH_TYPE:%d ", vtx->fetch_type); + fprintf(stderr, "BUFFER_ID:%d\n", vtx->buffer_id); + id++; + /* This assumes that no semantic fetches exist */ + fprintf(stderr, "%04d %08X ", id, bc->bytecode[id]); + fprintf(stderr, "SRC(GPR:%d ", vtx->src_gpr); + fprintf(stderr, "SEL_X:%d) ", vtx->src_sel_x); + fprintf(stderr, "MEGA_FETCH_COUNT:%d ", vtx->mega_fetch_count); + fprintf(stderr, "DST(GPR:%d ", vtx->dst_gpr); + fprintf(stderr, "SEL_X:%d ", vtx->dst_sel_x); + fprintf(stderr, "SEL_Y:%d ", vtx->dst_sel_y); + fprintf(stderr, "SEL_Z:%d ", vtx->dst_sel_z); + fprintf(stderr, "SEL_W:%d) ", vtx->dst_sel_w); + fprintf(stderr, "USE_CONST_FIELDS:%d ", vtx->use_const_fields); + fprintf(stderr, "DATA_FORMAT:%d ", vtx->data_format); + fprintf(stderr, "NUM_FORMAT_ALL:%d ", vtx->num_format_all); + fprintf(stderr, "FORMAT_COMP_ALL:%d ", vtx->format_comp_all); + fprintf(stderr, "SRF_MODE_ALL:%d\n", vtx->srf_mode_all); + id++; + fprintf(stderr, "%04d %08X \n", id, bc->bytecode[id]); //TODO + id++; + fprintf(stderr, "%04d %08X \n", id, bc->bytecode[id]); + id++; } } fprintf(stderr, "--------------------------------------\n"); } -void r600_cf_vtx(struct r600_vertex_element *ve, u32 *bytecode, unsigned count) +static void r600_cf_vtx(struct r600_vertex_element *ve, u32 *bytecode, unsigned count) { struct r600_pipe_state *rstate; unsigned i = 0; @@ -2721,42 +2830,6 @@ void r600_cf_vtx(struct r600_vertex_element *ve, u32 *bytecode, unsigned count) 0xFFFFFFFF, ve->fetch_shader); } -void r600_cf_vtx_tc(struct r600_vertex_element *ve, u32 *bytecode, unsigned count) -{ - struct r600_pipe_state *rstate; - unsigned i = 0; - - if (count > 8) { - bytecode[i++] = S_SQ_CF_WORD0_ADDR(8 >> 1); - bytecode[i++] = S_SQ_CF_WORD1_CF_INST(V_SQ_CF_WORD1_SQ_CF_INST_VTX_TC) | - S_SQ_CF_WORD1_BARRIER(1) | - S_SQ_CF_WORD1_COUNT(8 - 1); - bytecode[i++] = S_SQ_CF_WORD0_ADDR(40 >> 1); - bytecode[i++] = S_SQ_CF_WORD1_CF_INST(V_SQ_CF_WORD1_SQ_CF_INST_VTX_TC) | - S_SQ_CF_WORD1_BARRIER(1) | - S_SQ_CF_WORD1_COUNT((count - 8) - 1); - } else { - bytecode[i++] = S_SQ_CF_WORD0_ADDR(8 >> 1); - bytecode[i++] = S_SQ_CF_WORD1_CF_INST(V_SQ_CF_WORD1_SQ_CF_INST_VTX_TC) | - S_SQ_CF_WORD1_BARRIER(1) | - S_SQ_CF_WORD1_COUNT(count - 1); - } - bytecode[i++] = S_SQ_CF_WORD0_ADDR(0); - bytecode[i++] = S_SQ_CF_WORD1_CF_INST(V_SQ_CF_WORD1_SQ_CF_INST_RETURN) | - S_SQ_CF_WORD1_BARRIER(1); - - rstate = &ve->rstate; - rstate->id = R600_PIPE_STATE_FETCH_SHADER; - rstate->nregs = 0; - r600_pipe_state_add_reg(rstate, R_0288A4_SQ_PGM_RESOURCES_FS, - 0x00000000, 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(rstate, R_0288DC_SQ_PGM_CF_OFFSET_FS, - 0x00000000, 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(rstate, R_028894_SQ_PGM_START_FS, - r600_bo_offset(ve->fetch_shader) >> 8, - 0xFFFFFFFF, ve->fetch_shader); -} - static void r600_vertex_data_type(enum pipe_format pformat, unsigned *format, unsigned *num_format, unsigned *format_comp) { @@ -2780,7 +2853,7 @@ static void r600_vertex_data_type(enum pipe_format pformat, unsigned *format, } switch (desc->channel[i].type) { - /* Half-floats, floats, doubles */ + /* Half-floats, floats, ints */ case UTIL_FORMAT_TYPE_FLOAT: switch (desc->channel[i].size) { case 16: @@ -2792,8 +2865,6 @@ static void r600_vertex_data_type(enum pipe_format pformat, unsigned *format, *format = FMT_16_16_FLOAT; break; case 3: - *format = FMT_16_16_16_FLOAT; - break; case 4: *format = FMT_16_16_16_16_FLOAT; break; @@ -2833,8 +2904,6 @@ static void r600_vertex_data_type(enum pipe_format pformat, unsigned *format, *format = FMT_8_8; break; case 3: - // *format = FMT_8_8_8; /* fails piglit draw-vertices test */ - // break; case 4: *format = FMT_8_8_8_8; break; @@ -2849,8 +2918,6 @@ static void r600_vertex_data_type(enum pipe_format pformat, unsigned *format, *format = FMT_16_16; break; case 3: - // *format = FMT_16_16_16; /* fails piglit draw-vertices test */ - // break; case 4: *format = FMT_16_16_16_16; break; @@ -2938,10 +3005,10 @@ int r600_vertex_elements_build_fetch_shader(struct r600_pipe_context *rctx, stru for (i = 0; i < ve->count; i++) { unsigned vbuffer_index; - r600_vertex_data_type(ve->hw_format[i], &format, &num_format, &format_comp); - desc = util_format_description(ve->hw_format[i]); + r600_vertex_data_type(ve->elements[i].src_format, &format, &num_format, &format_comp); + desc = util_format_description(ve->elements[i].src_format); if (desc == NULL) { - R600_ERR("unknown format %d\n", ve->hw_format[i]); + R600_ERR("unknown format %d\n", ve->elements[i].src_format); r600_bo_reference(rctx->radeon, &ve->fetch_shader, NULL); return -EINVAL; } diff --git a/src/gallium/drivers/r600/r600_asm.h b/src/gallium/drivers/r600/r600_asm.h index 519245f3af2..453c29790c1 100644 --- a/src/gallium/drivers/r600/r600_asm.h +++ b/src/gallium/drivers/r600/r600_asm.h @@ -34,7 +34,7 @@ struct r600_bc_alu_src { unsigned neg; unsigned abs; unsigned rel; - u32 *value; + uint32_t value; }; struct r600_bc_alu_dst { @@ -201,8 +201,6 @@ int r600_bc_add_cfinst(struct r600_bc *bc, int inst); int r600_bc_add_alu_type(struct r600_bc *bc, const struct r600_bc_alu *alu, int type); void r600_bc_special_constants(u32 value, unsigned *sel, unsigned *neg); void r600_bc_dump(struct r600_bc *bc); -void r600_cf_vtx(struct r600_vertex_element *ve, u32 *bytecode, unsigned count); -void r600_cf_vtx_tc(struct r600_vertex_element *ve, u32 *bytecode, unsigned count); int r600_vertex_elements_build_fetch_shader(struct r600_pipe_context *rctx, struct r600_vertex_element *ve); diff --git a/src/gallium/drivers/r600/r600_blit.c b/src/gallium/drivers/r600/r600_blit.c index b9ec9592e35..9865ea17ae5 100644 --- a/src/gallium/drivers/r600/r600_blit.c +++ b/src/gallium/drivers/r600/r600_blit.c @@ -36,6 +36,7 @@ static void r600_blitter_begin(struct pipe_context *ctx, enum r600_blitter_op op { struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; + rctx->blit = true; r600_context_queries_suspend(&rctx->ctx); util_blitter_save_blend(rctx->blitter, rctx->states[R600_PIPE_STATE_BLEND]); @@ -53,9 +54,9 @@ static void r600_blitter_begin(struct pipe_context *ctx, enum r600_blitter_op op if (rctx->states[R600_PIPE_STATE_CLIP]) { util_blitter_save_clip(rctx->blitter, &rctx->clip); } - util_blitter_save_vertex_buffers(rctx->blitter, rctx->nvertex_buffer, rctx->vertex_buffer); - - rctx->vertex_elements = NULL; + util_blitter_save_vertex_buffers(rctx->blitter, + rctx->vbuf_mgr->nr_vertex_buffers, + rctx->vbuf_mgr->vertex_buffer); if (op & (R600_CLEAR_SURFACE | R600_COPY)) util_blitter_save_framebuffer(rctx->blitter, &rctx->framebuffer); @@ -76,6 +77,7 @@ static void r600_blitter_end(struct pipe_context *ctx) { struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; r600_context_queries_resume(&rctx->ctx); + rctx->blit = false; } void r600_blit_uncompress_depth(struct pipe_context *ctx, struct r600_resource_texture *texture) @@ -84,13 +86,17 @@ void r600_blit_uncompress_depth(struct pipe_context *ctx, struct r600_resource_t struct pipe_surface *zsurf, *cbsurf, surf_tmpl; int level = 0; float depth = 1.0f; - surf_tmpl.format = texture->resource.base.b.format; + + if (!texture->dirty_db) + return; + + surf_tmpl.format = texture->resource.b.b.b.format; surf_tmpl.u.tex.level = level; surf_tmpl.u.tex.first_layer = 0; surf_tmpl.u.tex.last_layer = 0; surf_tmpl.usage = PIPE_BIND_DEPTH_STENCIL; - zsurf = ctx->create_surface(ctx, &texture->resource.base.b, &surf_tmpl); + zsurf = ctx->create_surface(ctx, &texture->resource.b.b.b, &surf_tmpl); surf_tmpl.format = ((struct pipe_resource*)texture->flushed_depth_texture)->format; surf_tmpl.usage = PIPE_BIND_RENDER_TARGET; @@ -107,6 +113,48 @@ void r600_blit_uncompress_depth(struct pipe_context *ctx, struct r600_resource_t pipe_surface_reference(&zsurf, NULL); pipe_surface_reference(&cbsurf, NULL); + + texture->dirty_db = FALSE; +} + +void r600_flush_depth_textures(struct r600_pipe_context *rctx) +{ + unsigned int i; + + if (rctx->blit) return; + + /* FIXME: This handles fragment shader textures only. */ + + for (i = 0; i < rctx->ps_samplers.n_views; ++i) { + struct r600_pipe_sampler_view *view; + struct r600_resource_texture *tex; + + view = rctx->ps_samplers.views[i]; + if (!view) continue; + + tex = (struct r600_resource_texture *)view->base.texture; + if (!tex->depth) + continue; + + if (tex->is_flushing_texture) + continue; + + r600_blit_uncompress_depth(&rctx->context, tex); + } + + /* also check CB here */ + for (i = 0; i < rctx->framebuffer.nr_cbufs; i++) { + struct r600_resource_texture *tex; + tex = (struct r600_resource_texture *)rctx->framebuffer.cbufs[i]->texture; + + if (!tex->depth) + continue; + + if (tex->is_flushing_texture) + continue; + + r600_blit_uncompress_depth(&rctx->context, tex); + } } static void r600_clear(struct pipe_context *ctx, unsigned buffers, @@ -171,6 +219,52 @@ static void r600_hw_copy_region(struct pipe_context *ctx, r600_blitter_end(ctx); } +struct texture_orig_info { + unsigned format; + unsigned width0; + unsigned height0; +}; + +static void r600_s3tc_to_blittable(struct pipe_resource *tex, + unsigned level, + struct texture_orig_info *orig) +{ + struct r600_resource_texture *rtex = (struct r600_resource_texture*)tex; + unsigned pixsize = util_format_get_blocksize(tex->format); + int new_format; + int new_height, new_width; + + orig->format = tex->format; + orig->width0 = tex->width0; + orig->height0 = tex->height0; + + if (pixsize == 8) + new_format = PIPE_FORMAT_R16G16B16A16_UNORM; /* 64-bit block */ + else + new_format = PIPE_FORMAT_R32G32B32A32_UNORM; /* 128-bit block */ + + new_width = util_format_get_nblocksx(tex->format, orig->width0); + new_height = util_format_get_nblocksy(tex->format, orig->height0); + + rtex->force_int_type = true; + tex->width0 = new_width; + tex->height0 = new_height; + tex->format = new_format; + +} + +static void r600_reset_blittable_to_s3tc(struct pipe_resource *tex, + unsigned level, + struct texture_orig_info *orig) +{ + struct r600_resource_texture *rtex = (struct r600_resource_texture*)tex; + rtex->force_int_type = false; + + tex->format = orig->format; + tex->width0 = orig->width0; + tex->height0 = orig->height0; +} + static void r600_resource_copy_region(struct pipe_context *ctx, struct pipe_resource *dst, unsigned dst_level, @@ -179,15 +273,36 @@ static void r600_resource_copy_region(struct pipe_context *ctx, unsigned src_level, const struct pipe_box *src_box) { - boolean is_depth; - /* there is something wrong with depth resource copies at the moment so avoid them for now */ - is_depth = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 0) != 0; - if (is_depth) - util_resource_copy_region(ctx, dst, dst_level, dstx, dsty, dstz, - src, src_level, src_box); - else - r600_hw_copy_region(ctx, dst, dst_level, dstx, dsty, dstz, - src, src_level, src_box); + struct r600_resource_texture *rsrc = (struct r600_resource_texture*)src; + struct texture_orig_info orig_info[2]; + boolean restore_orig[2]; + + if (rsrc->depth && !rsrc->is_flushing_texture) + r600_texture_depth_flush(ctx, src, FALSE); + + restore_orig[0] = restore_orig[1] = FALSE; + + if (util_format_is_s3tc(src->format)) { + r600_s3tc_to_blittable(src, src_level, &orig_info[0]); + restore_orig[0] = TRUE; + } + + if (util_format_is_s3tc(dst->format)) { + r600_s3tc_to_blittable(dst, dst_level, &orig_info[1]); + restore_orig[1] = TRUE; + /* translate the dst box as well */ + dstx = util_format_get_nblocksx(orig_info[1].format, dstx); + dsty = util_format_get_nblocksy(orig_info[1].format, dsty); + } + + r600_hw_copy_region(ctx, dst, dst_level, dstx, dsty, dstz, + src, src_level, src_box); + + if (restore_orig[0]) + r600_reset_blittable_to_s3tc(src, src_level, &orig_info[0]); + + if (restore_orig[1]) + r600_reset_blittable_to_s3tc(dst, dst_level, &orig_info[1]); } void r600_init_blit_functions(struct r600_pipe_context *rctx) @@ -197,3 +312,19 @@ void r600_init_blit_functions(struct r600_pipe_context *rctx) rctx->context.clear_depth_stencil = r600_clear_depth_stencil; rctx->context.resource_copy_region = r600_resource_copy_region; } + +void r600_blit_push_depth(struct pipe_context *ctx, struct r600_resource_texture *texture) +{ + struct pipe_box sbox; + + sbox.x = sbox.y = sbox.z = 0; + sbox.width = texture->resource.b.b.b.width0; + sbox.height = texture->resource.b.b.b.height0; + /* XXX that might be wrong */ + sbox.depth = 1; + + r600_hw_copy_region(ctx, (struct pipe_resource *)texture, 0, + 0, 0, 0, + (struct pipe_resource *)texture->flushed_depth_texture, 0, + &sbox); +} diff --git a/src/gallium/drivers/r600/r600_buffer.c b/src/gallium/drivers/r600/r600_buffer.c index 469c8195fe9..0c5d7133c7a 100644 --- a/src/gallium/drivers/r600/r600_buffer.c +++ b/src/gallium/drivers/r600/r600_buffer.c @@ -29,85 +29,58 @@ #include <util/u_math.h> #include <util/u_inlines.h> #include <util/u_memory.h> +#include "util/u_upload_mgr.h" + #include "state_tracker/drm_driver.h" + #include <xf86drm.h> #include "radeon_drm.h" + #include "r600.h" #include "r600_pipe.h" -extern struct u_resource_vtbl r600_buffer_vtbl; - - -struct pipe_resource *r600_buffer_create(struct pipe_screen *screen, - const struct pipe_resource *templ) -{ - struct r600_resource_buffer *rbuffer; - struct r600_bo *bo; - /* XXX We probably want a different alignment for buffers and textures. */ - unsigned alignment = 4096; - - rbuffer = CALLOC_STRUCT(r600_resource_buffer); - if (rbuffer == NULL) - return NULL; - - rbuffer->magic = R600_BUFFER_MAGIC; - rbuffer->user_buffer = NULL; - rbuffer->r.base.b = *templ; - pipe_reference_init(&rbuffer->r.base.b.reference, 1); - rbuffer->r.base.b.screen = screen; - rbuffer->r.base.vtbl = &r600_buffer_vtbl; - rbuffer->r.size = rbuffer->r.base.b.width0; - rbuffer->r.bo_size = rbuffer->r.size; - rbuffer->uploaded = FALSE; - bo = r600_bo((struct radeon*)screen->winsys, rbuffer->r.base.b.width0, alignment, rbuffer->r.base.b.bind, rbuffer->r.base.b.usage); - if (bo == NULL) { - FREE(rbuffer); - return NULL; - } - rbuffer->r.bo = bo; - return &rbuffer->r.base.b; -} - -struct pipe_resource *r600_user_buffer_create(struct pipe_screen *screen, - void *ptr, unsigned bytes, - unsigned bind) -{ - struct r600_resource_buffer *rbuffer; - - rbuffer = CALLOC_STRUCT(r600_resource_buffer); - if (rbuffer == NULL) - return NULL; - - rbuffer->magic = R600_BUFFER_MAGIC; - pipe_reference_init(&rbuffer->r.base.b.reference, 1); - rbuffer->r.base.vtbl = &r600_buffer_vtbl; - rbuffer->r.base.b.screen = screen; - rbuffer->r.base.b.target = PIPE_BUFFER; - rbuffer->r.base.b.format = PIPE_FORMAT_R8_UNORM; - rbuffer->r.base.b.usage = PIPE_USAGE_IMMUTABLE; - rbuffer->r.base.b.bind = bind; - rbuffer->r.base.b.width0 = bytes; - rbuffer->r.base.b.height0 = 1; - rbuffer->r.base.b.depth0 = 1; - rbuffer->r.base.b.array_size = 1; - rbuffer->r.base.b.flags = 0; - rbuffer->r.bo = NULL; - rbuffer->r.bo_size = 0; - rbuffer->user_buffer = ptr; - rbuffer->uploaded = FALSE; - return &rbuffer->r.base.b; -} - static void r600_buffer_destroy(struct pipe_screen *screen, struct pipe_resource *buf) { + struct r600_screen *rscreen = (struct r600_screen*)screen; struct r600_resource_buffer *rbuffer = r600_buffer(buf); if (rbuffer->r.bo) { r600_bo_reference((struct radeon*)screen->winsys, &rbuffer->r.bo, NULL); } rbuffer->r.bo = NULL; - FREE(rbuffer); + util_slab_free(&rscreen->pool_buffers, rbuffer); +} + +static unsigned r600_buffer_is_referenced_by_cs(struct pipe_context *context, + struct pipe_resource *buf, + unsigned level, int layer) +{ + /* FIXME */ + return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; +} + +static struct pipe_transfer *r600_get_transfer(struct pipe_context *ctx, + struct pipe_resource *resource, + unsigned level, + unsigned usage, + const struct pipe_box *box) +{ + struct r600_pipe_context *rctx = (struct r600_pipe_context*)ctx; + struct pipe_transfer *transfer = util_slab_alloc(&rctx->pool_transfers); + + transfer->resource = resource; + transfer->level = level; + transfer->usage = usage; + transfer->box = *box; + transfer->stride = 0; + transfer->layer_stride = 0; + transfer->data = NULL; + + /* Note strides are zero, this is ok for buffers, but not for + * textures 2d & higher at least. + */ + return transfer; } static void *r600_buffer_transfer_map(struct pipe_context *pipe, @@ -117,8 +90,8 @@ static void *r600_buffer_transfer_map(struct pipe_context *pipe, int write = 0; uint8_t *data; - if (rbuffer->user_buffer) - return (uint8_t*)rbuffer->user_buffer + transfer->box.x; + if (rbuffer->r.b.user_ptr) + return (uint8_t*)rbuffer->r.b.user_ptr + transfer->box.x; if (transfer->usage & PIPE_TRANSFER_DONTBLOCK) { /* FIXME */ @@ -138,7 +111,7 @@ static void r600_buffer_transfer_unmap(struct pipe_context *pipe, { struct r600_resource_buffer *rbuffer = r600_buffer(transfer->resource); - if (rbuffer->user_buffer) + if (rbuffer->r.b.user_ptr) return; if (rbuffer->r.bo) @@ -151,128 +124,163 @@ static void r600_buffer_transfer_flush_region(struct pipe_context *pipe, { } -unsigned r600_buffer_is_referenced_by_cs(struct pipe_context *context, - struct pipe_resource *buf, - unsigned level, int layer) +static void r600_transfer_destroy(struct pipe_context *ctx, + struct pipe_transfer *transfer) { - /* FIXME */ - return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; + struct r600_pipe_context *rctx = (struct r600_pipe_context*)ctx; + util_slab_free(&rctx->pool_transfers, transfer); } -struct pipe_resource *r600_buffer_from_handle(struct pipe_screen *screen, - struct winsys_handle *whandle) +static void r600_buffer_transfer_inline_write(struct pipe_context *pipe, + struct pipe_resource *resource, + unsigned level, + unsigned usage, + const struct pipe_box *box, + const void *data, + unsigned stride, + unsigned layer_stride) { - struct radeon *rw = (struct radeon*)screen->winsys; - struct r600_resource *rbuffer; - struct r600_bo *bo = NULL; + struct radeon *ws = (struct radeon*)pipe->winsys; + struct r600_resource_buffer *rbuffer = r600_buffer(resource); + uint8_t *map = NULL; - bo = r600_bo_handle(rw, whandle->handle, NULL); - if (bo == NULL) { - return NULL; - } + assert(rbuffer->r.b.user_ptr == NULL); - rbuffer = CALLOC_STRUCT(r600_resource); - if (rbuffer == NULL) { - r600_bo_reference(rw, &bo, NULL); - return NULL; - } + map = r600_bo_map(ws, rbuffer->r.bo, + PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD | usage, + pipe); - pipe_reference_init(&rbuffer->base.b.reference, 1); - rbuffer->base.b.target = PIPE_BUFFER; - rbuffer->base.b.screen = screen; - rbuffer->base.vtbl = &r600_buffer_vtbl; - rbuffer->bo = bo; - return &rbuffer->base.b; + memcpy(map + box->x, data, box->width); + + if (rbuffer->r.bo) + r600_bo_unmap(ws, rbuffer->r.bo); } -struct u_resource_vtbl r600_buffer_vtbl = +static const struct u_resource_vtbl r600_buffer_vtbl = { u_default_resource_get_handle, /* get_handle */ r600_buffer_destroy, /* resource_destroy */ r600_buffer_is_referenced_by_cs, /* is_buffer_referenced */ - u_default_get_transfer, /* get_transfer */ - u_default_transfer_destroy, /* transfer_destroy */ + r600_get_transfer, /* get_transfer */ + r600_transfer_destroy, /* transfer_destroy */ r600_buffer_transfer_map, /* transfer_map */ r600_buffer_transfer_flush_region, /* transfer_flush_region */ r600_buffer_transfer_unmap, /* transfer_unmap */ - u_default_transfer_inline_write /* transfer_inline_write */ + r600_buffer_transfer_inline_write /* transfer_inline_write */ }; -int r600_upload_index_buffer(struct r600_pipe_context *rctx, struct r600_drawl *draw) +struct pipe_resource *r600_buffer_create(struct pipe_screen *screen, + const struct pipe_resource *templ) { - if (r600_buffer_is_user_buffer(draw->index_buffer)) { - struct r600_resource_buffer *rbuffer = r600_buffer(draw->index_buffer); - unsigned upload_offset; - int ret = 0; - - ret = r600_upload_buffer(rctx->rupload_vb, - draw->index_buffer_offset, - draw->count * draw->index_size, - rbuffer, - &upload_offset, - &rbuffer->r.bo_size, - &rbuffer->r.bo); - if (ret) - return ret; - rbuffer->uploaded = TRUE; - draw->index_buffer_offset = upload_offset; + struct r600_screen *rscreen = (struct r600_screen*)screen; + struct r600_resource_buffer *rbuffer; + struct r600_bo *bo; + /* XXX We probably want a different alignment for buffers and textures. */ + unsigned alignment = 4096; + + rbuffer = util_slab_alloc(&rscreen->pool_buffers); + + rbuffer->magic = R600_BUFFER_MAGIC; + rbuffer->r.b.b.b = *templ; + pipe_reference_init(&rbuffer->r.b.b.b.reference, 1); + rbuffer->r.b.b.b.screen = screen; + rbuffer->r.b.b.vtbl = &r600_buffer_vtbl; + rbuffer->r.b.user_ptr = NULL; + rbuffer->r.size = rbuffer->r.b.b.b.width0; + rbuffer->r.bo_size = rbuffer->r.size; + + bo = r600_bo((struct radeon*)screen->winsys, + rbuffer->r.b.b.b.width0, + alignment, rbuffer->r.b.b.b.bind, + rbuffer->r.b.b.b.usage); + + if (bo == NULL) { + FREE(rbuffer); + return NULL; } + rbuffer->r.bo = bo; + return &rbuffer->r.b.b.b; +} + +struct pipe_resource *r600_user_buffer_create(struct pipe_screen *screen, + void *ptr, unsigned bytes, + unsigned bind) +{ + struct r600_screen *rscreen = (struct r600_screen*)screen; + struct r600_resource_buffer *rbuffer; - return 0; + rbuffer = util_slab_alloc(&rscreen->pool_buffers); + + rbuffer->magic = R600_BUFFER_MAGIC; + pipe_reference_init(&rbuffer->r.b.b.b.reference, 1); + rbuffer->r.b.b.vtbl = &r600_buffer_vtbl; + rbuffer->r.b.b.b.screen = screen; + rbuffer->r.b.b.b.target = PIPE_BUFFER; + rbuffer->r.b.b.b.format = PIPE_FORMAT_R8_UNORM; + rbuffer->r.b.b.b.usage = PIPE_USAGE_IMMUTABLE; + rbuffer->r.b.b.b.bind = bind; + rbuffer->r.b.b.b.width0 = bytes; + rbuffer->r.b.b.b.height0 = 1; + rbuffer->r.b.b.b.depth0 = 1; + rbuffer->r.b.b.b.array_size = 1; + rbuffer->r.b.b.b.flags = 0; + rbuffer->r.b.user_ptr = ptr; + rbuffer->r.bo = NULL; + rbuffer->r.bo_size = 0; + return &rbuffer->r.b.b.b; } -int r600_upload_user_buffers(struct r600_pipe_context *rctx) +struct pipe_resource *r600_buffer_from_handle(struct pipe_screen *screen, + struct winsys_handle *whandle) { - enum pipe_error ret = PIPE_OK; - int i, nr; - - nr = rctx->vertex_elements->count; - nr = rctx->nvertex_buffer; - - for (i = 0; i < nr; i++) { - struct pipe_vertex_buffer *vb = &rctx->vertex_buffer[i]; - - if (r600_buffer_is_user_buffer(vb->buffer)) { - struct r600_resource_buffer *rbuffer = r600_buffer(vb->buffer); - unsigned upload_offset; - - ret = r600_upload_buffer(rctx->rupload_vb, - 0, vb->buffer->width0, - rbuffer, - &upload_offset, - &rbuffer->r.bo_size, - &rbuffer->r.bo); - if (ret) - return ret; - rbuffer->uploaded = TRUE; - vb->buffer_offset = upload_offset; - } + struct radeon *rw = (struct radeon*)screen->winsys; + struct r600_resource *rbuffer; + struct r600_bo *bo = NULL; + + bo = r600_bo_handle(rw, whandle->handle, NULL); + if (bo == NULL) { + return NULL; + } + + rbuffer = CALLOC_STRUCT(r600_resource); + if (rbuffer == NULL) { + r600_bo_reference(rw, &bo, NULL); + return NULL; } - return ret; + + pipe_reference_init(&rbuffer->b.b.b.reference, 1); + rbuffer->b.b.b.target = PIPE_BUFFER; + rbuffer->b.b.b.screen = screen; + rbuffer->b.b.vtbl = &r600_buffer_vtbl; + rbuffer->bo = bo; + return &rbuffer->b.b.b; } +void r600_upload_index_buffer(struct r600_pipe_context *rctx, struct r600_drawl *draw) +{ + struct r600_resource_buffer *rbuffer = r600_buffer(draw->index_buffer); + boolean flushed; + + u_upload_data(rctx->vbuf_mgr->uploader, 0, + draw->info.count * draw->index_size, + rbuffer->r.b.user_ptr, + &draw->index_buffer_offset, + &draw->index_buffer, &flushed); +} -int r600_upload_const_buffer(struct r600_pipe_context *rctx, struct pipe_resource *cbuffer, +void r600_upload_const_buffer(struct r600_pipe_context *rctx, struct r600_resource_buffer **rbuffer, uint32_t *const_offset) { - if (r600_buffer_is_user_buffer(cbuffer)) { - struct r600_resource_buffer *rbuffer = r600_buffer(cbuffer); - unsigned upload_offset; - int ret = 0; - - ret = r600_upload_buffer(rctx->rupload_const, - 0, cbuffer->width0, - rbuffer, - &upload_offset, - &rbuffer->r.bo_size, - &rbuffer->r.bo); - if (ret) - return ret; - rbuffer->uploaded = TRUE; - *const_offset = upload_offset; - return 0; - } + if ((*rbuffer)->r.b.user_ptr) { + uint8_t *ptr = (*rbuffer)->r.b.user_ptr; + unsigned size = (*rbuffer)->r.b.b.b.width0; + boolean flushed; + + *rbuffer = NULL; - *const_offset = 0; - return 0; + u_upload_data(rctx->vbuf_mgr->uploader, 0, size, ptr, const_offset, + (struct pipe_resource**)rbuffer, &flushed); + } else { + *const_offset = 0; + } } diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c index 68b625cc3b4..34094001b75 100644 --- a/src/gallium/drivers/r600/r600_pipe.c +++ b/src/gallium/drivers/r600/r600_pipe.c @@ -30,11 +30,13 @@ #include <tgsi/tgsi_util.h> #include <util/u_blitter.h> #include <util/u_double_list.h> +#include <util/u_format_s3tc.h> #include <util/u_transfer.h> #include <util/u_surface.h> #include <util/u_pack_color.h> #include <util/u_memory.h> #include <util/u_inlines.h> +#include "util/u_upload_mgr.h" #include <pipebuffer/pb_buffer.h> #include "r600.h" #include "r600d.h" @@ -69,8 +71,30 @@ static void r600_flush(struct pipe_context *ctx, unsigned flags, #endif r600_context_flush(&rctx->ctx); - r600_upload_flush(rctx->rupload_vb); - r600_upload_flush(rctx->rupload_const); + /* XXX This shouldn't be really necessary, but removing it breaks some tests. + * Needless buffer reallocations may significantly increase memory consumption, + * so getting rid of this call is important. */ + u_upload_flush(rctx->vbuf_mgr->uploader); +} + +static void r600_update_num_contexts(struct r600_screen *rscreen, + int diff) +{ + pipe_mutex_lock(rscreen->mutex_num_contexts); + if (diff > 0) { + rscreen->num_contexts++; + + if (rscreen->num_contexts > 1) + util_slab_set_thread_safety(&rscreen->pool_buffers, + UTIL_SLAB_MULTITHREADED); + } else { + rscreen->num_contexts--; + + if (rscreen->num_contexts <= 1) + util_slab_set_thread_safety(&rscreen->pool_buffers, + UTIL_SLAB_SINGLETHREADED); + } + pipe_mutex_unlock(rscreen->mutex_num_contexts); } static void r600_destroy_context(struct pipe_context *context) @@ -79,8 +103,6 @@ static void r600_destroy_context(struct pipe_context *context) rctx->context.delete_depth_stencil_alpha_state(&rctx->context, rctx->custom_dsa_flush); - r600_end_vertex_translate(rctx); - r600_context_fini(&rctx->ctx); util_blitter_destroy(rctx->blitter); @@ -89,14 +111,11 @@ static void r600_destroy_context(struct pipe_context *context) free(rctx->states[i]); } - r600_upload_destroy(rctx->rupload_vb); - r600_upload_destroy(rctx->rupload_const); + u_vbuf_mgr_destroy(rctx->vbuf_mgr); + util_slab_destroy(&rctx->pool_transfers); - if (rctx->tran.translate_cache) - translate_cache_destroy(rctx->tran.translate_cache); + r600_update_num_contexts(rctx->screen, -1); - FREE(rctx->ps_resource); - FREE(rctx->vs_resource); FREE(rctx); } @@ -108,6 +127,9 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void if (rctx == NULL) return NULL; + + r600_update_num_contexts(rscreen, 1); + rctx->context.winsys = rscreen->screen.winsys; rctx->context.screen = screen; rctx->context.priv = priv; @@ -123,6 +145,7 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void r600_init_query_functions(rctx); r600_init_context_resource_functions(rctx); r600_init_surface_functions(rctx); + rctx->context.draw_vbo = r600_draw_vbo; switch (r600_get_family(rctx->radeon)) { case CHIP_R600: @@ -137,7 +160,6 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void case CHIP_RV730: case CHIP_RV710: case CHIP_RV740: - rctx->context.draw_vbo = r600_draw_vbo; r600_init_state_functions(rctx); if (r600_context_init(&rctx->ctx, rctx->radeon)) { r600_destroy_context(&rctx->context); @@ -154,7 +176,6 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void case CHIP_BARTS: case CHIP_TURKS: case CHIP_CAICOS: - rctx->context.draw_vbo = evergreen_draw; evergreen_init_state_functions(rctx); if (evergreen_context_init(&rctx->ctx, rctx->radeon)) { r600_destroy_context(&rctx->context); @@ -168,39 +189,23 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void return NULL; } - rctx->rupload_vb = r600_upload_create(rctx, 128 * 1024, 16); - if (rctx->rupload_vb == NULL) { - r600_destroy_context(&rctx->context); - return NULL; - } + util_slab_create(&rctx->pool_transfers, + sizeof(struct pipe_transfer), 64, + UTIL_SLAB_SINGLETHREADED); - rctx->rupload_const = r600_upload_create(rctx, 128 * 1024, 256); - if (rctx->rupload_const == NULL) { + rctx->vbuf_mgr = u_vbuf_mgr_create(&rctx->context, 1024 * 1024, 256, + PIPE_BIND_VERTEX_BUFFER | + PIPE_BIND_INDEX_BUFFER | + PIPE_BIND_CONSTANT_BUFFER, + U_VERTEX_FETCH_DWORD_ALIGNED); + if (!rctx->vbuf_mgr) { r600_destroy_context(&rctx->context); return NULL; } rctx->blitter = util_blitter_create(&rctx->context); if (rctx->blitter == NULL) { - FREE(rctx); - return NULL; - } - - rctx->tran.translate_cache = translate_cache_create(); - if (rctx->tran.translate_cache == NULL) { - FREE(rctx); - return NULL; - } - - rctx->vs_resource = CALLOC(R600_RESOURCE_ARRAY_SIZE, sizeof(struct r600_pipe_state)); - if (!rctx->vs_resource) { - FREE(rctx); - return NULL; - } - - rctx->ps_resource = CALLOC(R600_RESOURCE_ARRAY_SIZE, sizeof(struct r600_pipe_state)); - if (!rctx->ps_resource) { - FREE(rctx); + r600_destroy_context(&rctx->context); return NULL; } @@ -284,13 +289,16 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param) return 1; /* Unsupported features (boolean caps). */ - case PIPE_CAP_TIMER_QUERY: case PIPE_CAP_STREAM_OUTPUT: case PIPE_CAP_PRIMITIVE_RESTART: case PIPE_CAP_INDEP_BLEND_FUNC: /* FIXME allow this */ case PIPE_CAP_INSTANCED_DRAWING: return 0; + case PIPE_CAP_ARRAY_TEXTURES: + /* fix once the CS checker upstream is fixed */ + return debug_get_bool_option("R600_ARRAY_TEXTURE", FALSE); + /* Texturing. */ case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: @@ -319,6 +327,10 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param) case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: return 0; + /* Timer queries, present when the clock frequency is non zero. */ + case PIPE_CAP_TIMER_QUERY: + return r600_get_clock_crystal_freq(rscreen->radeon) != 0; + default: R600_ERR("r600: unknown param %d\n", param); return 0; @@ -385,7 +397,7 @@ static int r600_get_shader_param(struct pipe_screen* pscreen, unsigned shader, e case PIPE_SHADER_CAP_MAX_CONSTS: return 256; //max native parameters case PIPE_SHADER_CAP_MAX_CONST_BUFFERS: - return 1; + return R600_MAX_CONST_BUFFERS; case PIPE_SHADER_CAP_MAX_PREDS: return 0; /* FIXME */ case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED: @@ -441,9 +453,14 @@ static boolean r600_is_format_supported(struct pipe_screen* screen, retval |= PIPE_BIND_DEPTH_STENCIL; } - if ((usage & PIPE_BIND_VERTEX_BUFFER) && - r600_is_vertex_format_supported(format)) - retval |= PIPE_BIND_VERTEX_BUFFER; + if (usage & PIPE_BIND_VERTEX_BUFFER) { + struct r600_screen *rscreen = (struct r600_screen *)screen; + enum radeon_family family = r600_get_family(rscreen->radeon); + + if (r600_is_vertex_format_supported(format, family)) { + retval |= PIPE_BIND_VERTEX_BUFFER; + } + } if (usage & PIPE_BIND_TRANSFER_READ) retval |= PIPE_BIND_TRANSFER_READ; @@ -462,6 +479,8 @@ static void r600_destroy_screen(struct pipe_screen* pscreen) radeon_decref(rscreen->radeon); + util_slab_destroy(&rscreen->pool_buffers); + pipe_mutex_destroy(rscreen->mutex_num_contexts); FREE(rscreen); } @@ -489,6 +508,13 @@ struct pipe_screen *r600_screen_create(struct radeon *radeon) r600_init_screen_resource_functions(&rscreen->screen); rscreen->tiling_info = r600_get_tiling_info(radeon); + util_format_s3tc_init(); + + util_slab_create(&rscreen->pool_buffers, + sizeof(struct r600_resource_buffer), 64, + UTIL_SLAB_SINGLETHREADED); + + pipe_mutex_init(rscreen->mutex_num_contexts); return &rscreen->screen; } diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h index 7f74fda0daf..8dc1f4ad5c3 100644 --- a/src/gallium/drivers/r600/r600_pipe.h +++ b/src/gallium/drivers/r600/r600_pipe.h @@ -30,12 +30,15 @@ #include <pipe/p_screen.h> #include <pipe/p_context.h> #include <util/u_math.h> -#include "translate/translate_cache.h" +#include "util/u_slab.h" +#include "util/u_vbuf_mgr.h" #include "r600.h" #include "r600_public.h" #include "r600_shader.h" #include "r600_resource.h" +#define R600_MAX_CONST_BUFFERS 1 + enum r600_pipe_state_id { R600_PIPE_STATE_BLEND = 0, R600_PIPE_STATE_BLEND_COLOR, @@ -62,6 +65,11 @@ struct r600_screen { struct pipe_screen screen; struct radeon *radeon; struct r600_tiling_info *tiling_info; + struct util_slab_mempool pool_buffers; + unsigned num_contexts; + + /* for thread-safe write accessing to num_contexts */ + pipe_mutex mutex_num_contexts; }; struct r600_pipe_sampler_view { @@ -86,9 +94,7 @@ struct r600_vertex_element { unsigned count; struct pipe_vertex_element elements[PIPE_MAX_ATTRIBS]; - enum pipe_format hw_format[PIPE_MAX_ATTRIBS]; - unsigned hw_format_size[PIPE_MAX_ATTRIBS]; - boolean incompatible_layout; + struct u_vbuf_mgr_elements *vmgr_elements; struct r600_bo *fetch_shader; unsigned fs_size; struct r600_pipe_state rstate; @@ -117,22 +123,9 @@ struct r600_textures_info { unsigned n_samplers; }; -/* vertex buffer translation context, used to translate vertex input that - * hw doesn't natively support, so far only FLOAT64 is unsupported. - */ -struct r600_translate_context { - /* Translate cache for incompatible vertex offset/stride/format fallback. */ - struct translate_cache *translate_cache; - /* The vertex buffer slot containing the translated buffer. */ - unsigned vb_slot; - void *new_velems; -}; - #define R600_CONSTANT_ARRAY_SIZE 256 #define R600_RESOURCE_ARRAY_SIZE 160 -struct r600_upload; - struct r600_pipe_context { struct pipe_context context; struct blitter_context *blitter; @@ -143,43 +136,35 @@ struct r600_pipe_context { struct r600_pipe_state *states[R600_PIPE_NSTATES]; struct r600_context ctx; struct r600_vertex_element *vertex_elements; + struct r600_pipe_state fs_resource[PIPE_MAX_ATTRIBS]; struct pipe_framebuffer_state framebuffer; struct pipe_index_buffer index_buffer; - struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; - unsigned nvertex_buffer; unsigned cb_target_mask; /* for saving when using blitter */ struct pipe_stencil_ref stencil_ref; struct pipe_viewport_state viewport; struct pipe_clip_state clip; - unsigned nvs_resource; - struct r600_pipe_state *vs_resource; - struct r600_pipe_state *ps_resource; struct r600_pipe_state config; struct r600_pipe_shader *ps_shader; struct r600_pipe_shader *vs_shader; struct r600_pipe_state vs_const_buffer; + struct r600_pipe_state vs_const_buffer_resource[R600_MAX_CONST_BUFFERS]; struct r600_pipe_state ps_const_buffer; + struct r600_pipe_state ps_const_buffer_resource[R600_MAX_CONST_BUFFERS]; struct r600_pipe_rasterizer *rasterizer; /* shader information */ unsigned sprite_coord_enable; bool flatshade; - struct r600_upload *rupload_vb; - unsigned any_user_vbs; struct r600_textures_info ps_samplers; - unsigned vb_max_index; - struct r600_translate_context tran; - struct r600_upload *rupload_const; + + struct u_vbuf_mgr *vbuf_mgr; + struct util_slab_mempool pool_transfers; + bool blit; }; struct r600_drawl { + struct pipe_draw_info info; struct pipe_context *ctx; - unsigned mode; - unsigned min_index; - unsigned max_index; - unsigned index_bias; - unsigned start; - unsigned count; unsigned index_size; unsigned index_buffer_offset; struct pipe_resource *index_buffer; @@ -188,16 +173,20 @@ struct r600_drawl { /* evergreen_state.c */ void evergreen_init_state_functions(struct r600_pipe_context *rctx); void evergreen_init_config(struct r600_pipe_context *rctx); -void evergreen_draw(struct pipe_context *ctx, const struct pipe_draw_info *info); void evergreen_pipe_shader_ps(struct pipe_context *ctx, struct r600_pipe_shader *shader); void evergreen_pipe_shader_vs(struct pipe_context *ctx, struct r600_pipe_shader *shader); void *evergreen_create_db_flush_dsa(struct r600_pipe_context *rctx); void evergreen_polygon_offset_update(struct r600_pipe_context *rctx); -void evergreen_vertex_buffer_update(struct r600_pipe_context *rctx); +void evergreen_pipe_set_buffer_resource(struct r600_pipe_context *rctx, + struct r600_pipe_state *rstate, + struct r600_resource *rbuffer, + unsigned offset, unsigned stride); /* r600_blit.c */ void r600_init_blit_functions(struct r600_pipe_context *rctx); void r600_blit_uncompress_depth(struct pipe_context *ctx, struct r600_resource_texture *texture); +void r600_blit_push_depth(struct pipe_context *ctx, struct r600_resource_texture *texture); +void r600_flush_depth_textures(struct r600_pipe_context *rctx); /* r600_buffer.c */ struct pipe_resource *r600_buffer_create(struct pipe_screen *screen, @@ -205,13 +194,9 @@ struct pipe_resource *r600_buffer_create(struct pipe_screen *screen, struct pipe_resource *r600_user_buffer_create(struct pipe_screen *screen, void *ptr, unsigned bytes, unsigned bind); -unsigned r600_buffer_is_referenced_by_cs(struct pipe_context *context, - struct pipe_resource *buf, - unsigned level, int layer); struct pipe_resource *r600_buffer_from_handle(struct pipe_screen *screen, struct winsys_handle *whandle); -int r600_upload_index_buffer(struct r600_pipe_context *rctx, struct r600_drawl *draw); -int r600_upload_user_buffers(struct r600_pipe_context *rctx); +void r600_upload_index_buffer(struct r600_pipe_context *rctx, struct r600_drawl *draw); /* r600_query.c */ void r600_init_query_functions(struct r600_pipe_context *rctx); @@ -220,7 +205,6 @@ void r600_init_query_functions(struct r600_pipe_context *rctx); void r600_init_context_resource_functions(struct r600_pipe_context *r600); /* r600_shader.c */ -int r600_pipe_shader(struct pipe_context *ctx, struct r600_pipe_shader *shader); int r600_pipe_shader_create(struct pipe_context *ctx, struct r600_pipe_shader *shader, const struct tgsi_token *tokens); void r600_pipe_shader_destroy(struct pipe_context *ctx, struct r600_pipe_shader *shader); int r600_find_vs_semantic_index(struct r600_shader *vs, @@ -228,11 +212,14 @@ int r600_find_vs_semantic_index(struct r600_shader *vs, /* r600_state.c */ void r600_init_state_functions(struct r600_pipe_context *rctx); -void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info); +void r600_spi_update(struct r600_pipe_context *rctx); void r600_init_config(struct r600_pipe_context *rctx); void *r600_create_db_flush_dsa(struct r600_pipe_context *rctx); void r600_polygon_offset_update(struct r600_pipe_context *rctx); -void r600_vertex_buffer_update(struct r600_pipe_context *rctx); +void r600_pipe_set_buffer_resource(struct r600_pipe_context *rctx, + struct r600_pipe_state *rstate, + struct r600_resource *rbuffer, + unsigned offset, unsigned stride); /* r600_helper.h */ int r600_conv_pipe_prim(unsigned pprim, unsigned *prim); @@ -247,8 +234,6 @@ unsigned r600_texture_get_offset(struct r600_resource_texture *rtex, unsigned level, unsigned layer); /* r600_translate.c */ -void r600_begin_vertex_translate(struct r600_pipe_context *rctx); -void r600_end_vertex_translate(struct r600_pipe_context *rctx); void r600_translate_index_buffer(struct r600_pipe_context *r600, struct pipe_resource **index_buffer, unsigned *index_size, @@ -277,6 +262,9 @@ void r600_bind_ps_shader(struct pipe_context *ctx, void *state); void r600_bind_vs_shader(struct pipe_context *ctx, void *state); void r600_delete_ps_shader(struct pipe_context *ctx, void *state); void r600_delete_vs_shader(struct pipe_context *ctx, void *state); +void r600_set_constant_buffer(struct pipe_context *ctx, uint shader, uint index, + struct pipe_resource *buffer); +void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info); /* * common helpers diff --git a/src/gallium/drivers/r600/r600_resource.h b/src/gallium/drivers/r600/r600_resource.h index 28b3e1e5e40..836e7491f1f 100644 --- a/src/gallium/drivers/r600/r600_resource.h +++ b/src/gallium/drivers/r600/r600_resource.h @@ -24,6 +24,7 @@ #define R600_RESOURCE_H #include "util/u_transfer.h" +#include "util/u_vbuf_mgr.h" /* flag to indicate a resource is to be used as a transfer so should not be tiled */ #define R600_RESOURCE_FLAG_TRANSFER PIPE_RESOURCE_FLAG_DRV_PRIV @@ -43,7 +44,7 @@ struct r600_transfer { * underlying implementations. */ struct r600_resource { - struct u_resource base; + struct u_vbuf_resource b; struct r600_bo *bo; u32 size; unsigned bo_size; @@ -52,26 +53,31 @@ struct r600_resource { struct r600_resource_texture { struct r600_resource resource; unsigned offset[PIPE_MAX_TEXTURE_LEVELS]; - unsigned pitch_in_bytes[PIPE_MAX_TEXTURE_LEVELS]; - unsigned pitch_in_pixels[PIPE_MAX_TEXTURE_LEVELS]; + unsigned pitch_in_bytes[PIPE_MAX_TEXTURE_LEVELS]; /* transfer */ + unsigned pitch_in_blocks[PIPE_MAX_TEXTURE_LEVELS]; /* texture resource */ unsigned layer_size[PIPE_MAX_TEXTURE_LEVELS]; unsigned array_mode[PIPE_MAX_TEXTURE_LEVELS]; unsigned pitch_override; unsigned size; - unsigned tiled; unsigned tile_type; unsigned depth; - unsigned dirty; + unsigned dirty_db; struct r600_resource_texture *flushed_depth_texture; + boolean is_flushing_texture; + + /* on some cards we have to use integer 64/128-bit types + for s3tc blits, do this until gallium grows int formats */ + boolean force_int_type; }; +#define R600_TEX_IS_TILED(tex, level) ((tex)->array_mode[level] != V_038000_ARRAY_LINEAR_GENERAL && (tex)->array_mode[level] != V_038000_ARRAY_LINEAR_ALIGNED) + #define R600_BUFFER_MAGIC 0xabcd1600 +/* XXX this could be removed */ struct r600_resource_buffer { struct r600_resource r; uint32_t magic; - void *user_buffer; - bool uploaded; }; struct r600_surface { @@ -98,14 +104,7 @@ static INLINE struct r600_resource_buffer *r600_buffer(struct pipe_resource *buf return NULL; } -static INLINE boolean r600_buffer_is_user_buffer(struct pipe_resource *buffer) -{ - if (r600_buffer(buffer)->uploaded) - return FALSE; - return r600_buffer(buffer)->user_buffer ? TRUE : FALSE; -} - -int r600_texture_depth_flush(struct pipe_context *ctx, struct pipe_resource *texture); +int r600_texture_depth_flush(struct pipe_context *ctx, struct pipe_resource *texture, boolean just_create); /* r600_texture.c texture transfer functions. */ struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx, @@ -121,15 +120,7 @@ void r600_texture_transfer_unmap(struct pipe_context *ctx, struct pipe_transfer* transfer); struct r600_pipe_context; -struct r600_upload *r600_upload_create(struct r600_pipe_context *rctx, - unsigned default_size, - unsigned alignment); -void r600_upload_flush(struct r600_upload *upload); -void r600_upload_destroy(struct r600_upload *upload); -int r600_upload_buffer(struct r600_upload *upload, unsigned offset, - unsigned size, struct r600_resource_buffer *in_buffer, - unsigned *out_offset, unsigned *out_size, - struct r600_bo **out_buffer); - -int r600_upload_const_buffer(struct r600_pipe_context *rctx, struct pipe_resource *cbuffer, uint32_t *offset); + +void r600_upload_const_buffer(struct r600_pipe_context *rctx, struct r600_resource_buffer **rbuffer, uint32_t *offset); + #endif diff --git a/src/gallium/drivers/r600/r600_shader.c b/src/gallium/drivers/r600/r600_shader.c index c982471a04f..240c8f1ffd0 100644 --- a/src/gallium/drivers/r600/r600_shader.c +++ b/src/gallium/drivers/r600/r600_shader.c @@ -28,6 +28,7 @@ #include "r600_pipe.h" #include "r600_asm.h" #include "r600_sq.h" +#include "r600_formats.h" #include "r600_opcodes.h" #include "r600d.h" #include <stdio.h> @@ -175,6 +176,13 @@ static void r600_pipe_shader_ps(struct pipe_context *ctx, struct r600_pipe_shade R_0288CC_SQ_PGM_CF_OFFSET_PS, 0x00000000, 0xFFFFFFFF, NULL); + if (rshader->fs_write_all) { + r600_pipe_state_add_reg(rstate, R_028808_CB_COLOR_CONTROL, + S_028808_MULTIWRITE_ENABLE(1), + S_028808_MULTIWRITE_ENABLE(1), + NULL); + } + if (rshader->uses_kill) { /* only set some bits here, the other bits are set in the dsa state */ r600_pipe_state_add_reg(rstate, @@ -187,7 +195,7 @@ static void r600_pipe_shader_ps(struct pipe_context *ctx, struct r600_pipe_shade 0xFFFFFFFF, NULL); } -int r600_pipe_shader(struct pipe_context *ctx, struct r600_pipe_shader *shader) +static int r600_pipe_shader(struct pipe_context *ctx, struct r600_pipe_shader *shader) { struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; struct r600_shader *rshader = &shader->shader; @@ -225,12 +233,12 @@ int r600_pipe_shader(struct pipe_context *ctx, struct r600_pipe_shader *shader) return 0; } -int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *shader, u32 **literals); +static int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *shader); + int r600_pipe_shader_create(struct pipe_context *ctx, struct r600_pipe_shader *shader, const struct tgsi_token *tokens) { static int dump_shaders = -1; struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; - u32 *literals; int r; /* Would like some magic "get_bool_option_once" routine. @@ -243,13 +251,12 @@ int r600_pipe_shader_create(struct pipe_context *ctx, struct r600_pipe_shader *s tgsi_dump(tokens, 0); } shader->shader.family = r600_get_family(rctx->radeon); - r = r600_shader_from_tgsi(tokens, &shader->shader, &literals); + r = r600_shader_from_tgsi(tokens, &shader->shader); if (r) { R600_ERR("translation from TGSI failed !\n"); return r; } r = r600_bc_build(&shader->shader.bc); - free(literals); if (r) { R600_ERR("building bytecode failed !\n"); return r; @@ -274,6 +281,15 @@ void r600_pipe_shader_destroy(struct pipe_context *ctx, struct r600_pipe_shader */ struct r600_shader_tgsi_instruction; +struct r600_shader_src { + unsigned sel; + unsigned swizzle[4]; + unsigned neg; + unsigned abs; + unsigned rel; + uint32_t value[4]; +}; + struct r600_shader_ctx { struct tgsi_shader_info info; struct tgsi_parse_context parse; @@ -281,9 +297,11 @@ struct r600_shader_ctx { unsigned type; unsigned file_offset[TGSI_FILE_COUNT]; unsigned temp_reg; + unsigned ar_reg; struct r600_shader_tgsi_instruction *inst_info; struct r600_bc *bc; struct r600_shader *shader; + struct r600_shader_src src[3]; u32 *literals; u32 nliterals; u32 max_driver_temp_used; @@ -492,9 +510,179 @@ static int evergreen_gpr_count(struct r600_shader_ctx *ctx) return ctx->num_interp_gpr; } -int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *shader, u32 **literals) +static void tgsi_src(struct r600_shader_ctx *ctx, + const struct tgsi_full_src_register *tgsi_src, + struct r600_shader_src *r600_src) +{ + memset(r600_src, 0, sizeof(*r600_src)); + r600_src->swizzle[0] = tgsi_src->Register.SwizzleX; + r600_src->swizzle[1] = tgsi_src->Register.SwizzleY; + r600_src->swizzle[2] = tgsi_src->Register.SwizzleZ; + r600_src->swizzle[3] = tgsi_src->Register.SwizzleW; + r600_src->neg = tgsi_src->Register.Negate; + r600_src->abs = tgsi_src->Register.Absolute; + if (tgsi_src->Register.File == TGSI_FILE_IMMEDIATE) { + int index; + if ((tgsi_src->Register.SwizzleX == tgsi_src->Register.SwizzleY) && + (tgsi_src->Register.SwizzleX == tgsi_src->Register.SwizzleZ) && + (tgsi_src->Register.SwizzleX == tgsi_src->Register.SwizzleW)) { + + index = tgsi_src->Register.Index * 4 + tgsi_src->Register.SwizzleX; + r600_bc_special_constants(ctx->literals[index], &r600_src->sel, &r600_src->neg); + if (r600_src->sel != V_SQ_ALU_SRC_LITERAL) + return; + } + index = tgsi_src->Register.Index; + r600_src->sel = V_SQ_ALU_SRC_LITERAL; + memcpy(r600_src->value, ctx->literals + index * 4, sizeof(r600_src->value)); + } else { + if (tgsi_src->Register.Indirect) + r600_src->rel = V_SQ_REL_RELATIVE; + r600_src->sel = tgsi_src->Register.Index; + r600_src->sel += ctx->file_offset[tgsi_src->Register.File]; + } +} + +static int tgsi_fetch_rel_const(struct r600_shader_ctx *ctx, unsigned int offset, unsigned int dst_reg) +{ + struct r600_bc_vtx vtx; + unsigned int ar_reg; + int r; + + if (offset) { + struct r600_bc_alu alu; + + memset(&alu, 0, sizeof(alu)); + + alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_ADD_INT); + alu.src[0].sel = ctx->ar_reg; + + alu.src[1].sel = V_SQ_ALU_SRC_LITERAL; + alu.src[1].value = offset; + + alu.dst.sel = dst_reg; + alu.dst.write = 1; + alu.last = 1; + + if ((r = r600_bc_add_alu(ctx->bc, &alu))) + return r; + + ar_reg = dst_reg; + } else { + ar_reg = ctx->ar_reg; + } + + memset(&vtx, 0, sizeof(vtx)); + vtx.fetch_type = 2; /* VTX_FETCH_NO_INDEX_OFFSET */ + vtx.src_gpr = ar_reg; + vtx.mega_fetch_count = 16; + vtx.dst_gpr = dst_reg; + vtx.dst_sel_x = 0; /* SEL_X */ + vtx.dst_sel_y = 1; /* SEL_Y */ + vtx.dst_sel_z = 2; /* SEL_Z */ + vtx.dst_sel_w = 3; /* SEL_W */ + vtx.data_format = FMT_32_32_32_32_FLOAT; + vtx.num_format_all = 2; /* NUM_FORMAT_SCALED */ + vtx.format_comp_all = 1; /* FORMAT_COMP_SIGNED */ + vtx.srf_mode_all = 1; /* SRF_MODE_NO_ZERO */ + + if ((r = r600_bc_add_vtx(ctx->bc, &vtx))) + return r; + + return 0; +} + +static int tgsi_split_constant(struct r600_shader_ctx *ctx) +{ + struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction; + struct r600_bc_alu alu; + int i, j, k, nconst, r; + + for (i = 0, nconst = 0; i < inst->Instruction.NumSrcRegs; i++) { + if (inst->Src[i].Register.File == TGSI_FILE_CONSTANT) { + nconst++; + } + tgsi_src(ctx, &inst->Src[i], &ctx->src[i]); + } + for (i = 0, j = nconst - 1; i < inst->Instruction.NumSrcRegs; i++) { + if (inst->Src[i].Register.File != TGSI_FILE_CONSTANT) { + continue; + } + + if (ctx->src[i].rel) { + int treg = r600_get_temp(ctx); + if ((r = tgsi_fetch_rel_const(ctx, ctx->src[i].sel - 512, treg))) + return r; + + ctx->src[i].sel = treg; + ctx->src[i].rel = 0; + j--; + } else if (j > 0) { + int treg = r600_get_temp(ctx); + for (k = 0; k < 4; k++) { + memset(&alu, 0, sizeof(struct r600_bc_alu)); + alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV); + alu.src[0].sel = ctx->src[i].sel; + alu.src[0].chan = k; + alu.src[0].rel = ctx->src[i].rel; + alu.dst.sel = treg; + alu.dst.chan = k; + alu.dst.write = 1; + if (k == 3) + alu.last = 1; + r = r600_bc_add_alu(ctx->bc, &alu); + if (r) + return r; + } + ctx->src[i].sel = treg; + ctx->src[i].rel =0; + j--; + } + } + return 0; +} + +/* need to move any immediate into a temp - for trig functions which use literal for PI stuff */ +static int tgsi_split_literal_constant(struct r600_shader_ctx *ctx) +{ + struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction; + struct r600_bc_alu alu; + int i, j, k, nliteral, r; + + for (i = 0, nliteral = 0; i < inst->Instruction.NumSrcRegs; i++) { + if (ctx->src[i].sel == V_SQ_ALU_SRC_LITERAL) { + nliteral++; + } + } + for (i = 0, j = nliteral - 1; i < inst->Instruction.NumSrcRegs; i++) { + if (j > 0 && ctx->src[i].sel == V_SQ_ALU_SRC_LITERAL) { + int treg = r600_get_temp(ctx); + for (k = 0; k < 4; k++) { + memset(&alu, 0, sizeof(struct r600_bc_alu)); + alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV); + alu.src[0].sel = ctx->src[i].sel; + alu.src[0].chan = k; + alu.src[0].value = ctx->src[i].value[k]; + alu.dst.sel = treg; + alu.dst.chan = k; + alu.dst.write = 1; + if (k == 3) + alu.last = 1; + r = r600_bc_add_alu(ctx->bc, &alu); + if (r) + return r; + } + ctx->src[i].sel = treg; + j--; + } + } + return 0; +} + +static int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *shader) { struct tgsi_full_immediate *immediate; + struct tgsi_full_property *property; struct r600_shader_ctx ctx; struct r600_bc_output output[32]; unsigned noutput; @@ -558,12 +746,13 @@ int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *s ctx.file_offset[TGSI_FILE_CONSTANT] = 512; ctx.file_offset[TGSI_FILE_IMMEDIATE] = V_SQ_ALU_SRC_LITERAL; - ctx.temp_reg = ctx.file_offset[TGSI_FILE_TEMPORARY] + + ctx.ar_reg = ctx.file_offset[TGSI_FILE_TEMPORARY] + ctx.info.file_count[TGSI_FILE_TEMPORARY]; + ctx.temp_reg = ctx.ar_reg + 1; ctx.nliterals = 0; ctx.literals = NULL; - + shader->fs_write_all = FALSE; while (!tgsi_parse_end_of_tokens(&ctx.parse)) { tgsi_parse_token(&ctx.parse); switch (ctx.parse.FullToken.Token.Type) { @@ -592,7 +781,12 @@ int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *s ctx.max_driver_temp_used = 0; /* reserve first tmp for everyone */ r600_get_temp(&ctx); + opcode = ctx.parse.FullToken.FullInstruction.Instruction.Opcode; + if ((r = tgsi_split_constant(&ctx))) + goto out_err; + if ((r = tgsi_split_literal_constant(&ctx))) + goto out_err; if (ctx.bc->chiprev == CHIPREV_EVERGREEN) ctx.inst_info = &eg_shader_tgsi_instruction[opcode]; else @@ -602,6 +796,11 @@ int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *s goto out_err; break; case TGSI_TOKEN_TYPE_PROPERTY: + property = &ctx.parse.FullToken.FullProperty; + if (property->Property.PropertyName == TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS) { + if (property->u[0].Data == 1) + shader->fs_write_all = TRUE; + } break; default: R600_ERR("unsupported token type %d\n", ctx.parse.FullToken.Token.Type); @@ -619,6 +818,7 @@ int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *s output[i].swizzle_y = 1; output[i].swizzle_z = 2; output[i].swizzle_w = 3; + output[i].burst_count = 1; output[i].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PARAM; output[i].array_base = i - pos0; switch (ctx.type) { @@ -680,6 +880,7 @@ int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *s output[i].swizzle_y = 1; output[i].swizzle_z = 2; output[i].swizzle_w = 3; + output[i].burst_count = 1; output[i].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PARAM; output[i].array_base = 0; noutput++; @@ -694,6 +895,7 @@ int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *s output[0].swizzle_y = 7; output[0].swizzle_z = 7; output[0].swizzle_w = 7; + output[0].burst_count = 1; output[0].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PIXEL; output[0].array_base = 0; noutput++; @@ -704,7 +906,7 @@ int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *s if (r) goto out_err; } - *literals = ctx.literals; + free(ctx.literals); tgsi_parse_free(&ctx.parse); return 0; out_err: @@ -724,40 +926,22 @@ static int tgsi_end(struct r600_shader_ctx *ctx) return 0; } -static int tgsi_src(struct r600_shader_ctx *ctx, - const struct tgsi_full_src_register *tgsi_src, - struct r600_bc_alu_src *r600_src) +static void r600_bc_src(struct r600_bc_alu_src *bc_src, + const struct r600_shader_src *shader_src, + unsigned chan) { - memset(r600_src, 0, sizeof(struct r600_bc_alu_src)); - r600_src->neg = tgsi_src->Register.Negate; - r600_src->abs = tgsi_src->Register.Absolute; - if (tgsi_src->Register.File == TGSI_FILE_IMMEDIATE) { - int index; - if((tgsi_src->Register.SwizzleX == tgsi_src->Register.SwizzleY) && - (tgsi_src->Register.SwizzleX == tgsi_src->Register.SwizzleZ) && - (tgsi_src->Register.SwizzleX == tgsi_src->Register.SwizzleW)) { - - index = tgsi_src->Register.Index * 4 + tgsi_src->Register.SwizzleX; - r600_bc_special_constants(ctx->literals[index], &r600_src->sel, &r600_src->neg); - if (r600_src->sel != V_SQ_ALU_SRC_LITERAL) - return 0; - } - index = tgsi_src->Register.Index; - r600_src->sel = V_SQ_ALU_SRC_LITERAL; - r600_src->value = ctx->literals + index * 4; - } else { - if (tgsi_src->Register.Indirect) - r600_src->rel = V_SQ_REL_RELATIVE; - r600_src->sel = tgsi_src->Register.Index; - r600_src->sel += ctx->file_offset[tgsi_src->Register.File]; - } - return 0; + bc_src->sel = shader_src->sel; + bc_src->chan = shader_src->swizzle[chan]; + bc_src->neg = shader_src->neg; + bc_src->abs = shader_src->abs; + bc_src->rel = shader_src->rel; + bc_src->value = shader_src->value[bc_src->chan]; } -static int tgsi_dst(struct r600_shader_ctx *ctx, - const struct tgsi_full_dst_register *tgsi_dst, - unsigned swizzle, - struct r600_bc_alu_dst *r600_dst) +static void tgsi_dst(struct r600_shader_ctx *ctx, + const struct tgsi_full_dst_register *tgsi_dst, + unsigned swizzle, + struct r600_bc_alu_dst *r600_dst) { struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction; @@ -770,101 +954,6 @@ static int tgsi_dst(struct r600_shader_ctx *ctx, if (inst->Instruction.Saturate) { r600_dst->clamp = 1; } - return 0; -} - -static unsigned tgsi_chan(const struct tgsi_full_src_register *tgsi_src, unsigned swizzle) -{ - switch (swizzle) { - case 0: - return tgsi_src->Register.SwizzleX; - case 1: - return tgsi_src->Register.SwizzleY; - case 2: - return tgsi_src->Register.SwizzleZ; - case 3: - return tgsi_src->Register.SwizzleW; - default: - return 0; - } -} - -static int tgsi_split_constant(struct r600_shader_ctx *ctx, struct r600_bc_alu_src r600_src[3]) -{ - struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction; - struct r600_bc_alu alu; - int i, j, k, nconst, r; - - for (i = 0, nconst = 0; i < inst->Instruction.NumSrcRegs; i++) { - if (inst->Src[i].Register.File == TGSI_FILE_CONSTANT) { - nconst++; - } - r = tgsi_src(ctx, &inst->Src[i], &r600_src[i]); - if (r) { - return r; - } - } - for (i = 0, j = nconst - 1; i < inst->Instruction.NumSrcRegs; i++) { - if (j > 0 && inst->Src[i].Register.File == TGSI_FILE_CONSTANT) { - int treg = r600_get_temp(ctx); - for (k = 0; k < 4; k++) { - memset(&alu, 0, sizeof(struct r600_bc_alu)); - alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV); - alu.src[0].sel = r600_src[i].sel; - alu.src[0].chan = k; - alu.src[0].rel = r600_src[i].rel; - alu.dst.sel = treg; - alu.dst.chan = k; - alu.dst.write = 1; - if (k == 3) - alu.last = 1; - r = r600_bc_add_alu(ctx->bc, &alu); - if (r) - return r; - } - r600_src[i].sel = treg; - r600_src[i].rel =0; - j--; - } - } - return 0; -} - -/* need to move any immediate into a temp - for trig functions which use literal for PI stuff */ -static int tgsi_split_literal_constant(struct r600_shader_ctx *ctx, struct r600_bc_alu_src r600_src[3]) -{ - struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction; - struct r600_bc_alu alu; - int i, j, k, nliteral, r; - - for (i = 0, nliteral = 0; i < inst->Instruction.NumSrcRegs; i++) { - if (r600_src[i].sel == V_SQ_ALU_SRC_LITERAL) { - nliteral++; - } - } - for (i = 0, j = nliteral - 1; i < inst->Instruction.NumSrcRegs; i++) { - if (j > 0 && r600_src[i].sel == V_SQ_ALU_SRC_LITERAL) { - int treg = r600_get_temp(ctx); - for (k = 0; k < 4; k++) { - memset(&alu, 0, sizeof(struct r600_bc_alu)); - alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV); - alu.src[0].sel = r600_src[i].sel; - alu.src[0].chan = k; - alu.src[0].value = r600_src[i].value; - alu.dst.sel = treg; - alu.dst.chan = k; - alu.dst.write = 1; - if (k == 3) - alu.last = 1; - r = r600_bc_add_alu(ctx->bc, &alu); - if (r) - return r; - } - r600_src[i].sel = treg; - j--; - } - } - return 0; } static int tgsi_last_instruction(unsigned writemask) @@ -882,38 +971,25 @@ static int tgsi_last_instruction(unsigned writemask) static int tgsi_op2_s(struct r600_shader_ctx *ctx, int swap) { struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction; - struct r600_bc_alu_src r600_src[3]; struct r600_bc_alu alu; int i, j, r; int lasti = tgsi_last_instruction(inst->Dst[0].Register.WriteMask); - r = tgsi_split_constant(ctx, r600_src); - if (r) - return r; - r = tgsi_split_literal_constant(ctx, r600_src); - if (r) - return r; for (i = 0; i < lasti + 1; i++) { if (!(inst->Dst[0].Register.WriteMask & (1 << i))) continue; memset(&alu, 0, sizeof(struct r600_bc_alu)); - r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst); - if (r) - return r; + tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst); alu.inst = ctx->inst_info->r600_opcode; if (!swap) { for (j = 0; j < inst->Instruction.NumSrcRegs; j++) { - alu.src[j] = r600_src[j]; - alu.src[j].chan = tgsi_chan(&inst->Src[j], i); + r600_bc_src(&alu.src[j], &ctx->src[j], i); } } else { - alu.src[0] = r600_src[1]; - alu.src[0].chan = tgsi_chan(&inst->Src[1], i); - - alu.src[1] = r600_src[0]; - alu.src[1].chan = tgsi_chan(&inst->Src[0], i); + r600_bc_src(&alu.src[0], &ctx->src[1], i); + r600_bc_src(&alu.src[1], &ctx->src[0], i); } /* handle some special cases */ switch (ctx->inst_info->tgsi_opcode) { @@ -951,24 +1027,15 @@ static int tgsi_op2_swap(struct r600_shader_ctx *ctx) * r700 - normalize by dividing by 2PI * see fdo bug 27901 */ -static int tgsi_setup_trig(struct r600_shader_ctx *ctx, - struct r600_bc_alu_src r600_src[3]) +static int tgsi_setup_trig(struct r600_shader_ctx *ctx) { static float half_inv_pi = 1.0 /(3.1415926535 * 2); static float double_pi = 3.1415926535 * 2; static float neg_pi = -3.1415926535; - struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction; int r; struct r600_bc_alu alu; - r = tgsi_split_constant(ctx, r600_src); - if (r) - return r; - r = tgsi_split_literal_constant(ctx, r600_src); - if (r) - return r; - memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MULADD); alu.is_op3 = 1; @@ -977,12 +1044,11 @@ static int tgsi_setup_trig(struct r600_shader_ctx *ctx, alu.dst.sel = ctx->temp_reg; alu.dst.write = 1; - alu.src[0] = r600_src[0]; - alu.src[0].chan = tgsi_chan(&inst->Src[0], 0); + r600_bc_src(&alu.src[0], &ctx->src[0], 0); alu.src[1].sel = V_SQ_ALU_SRC_LITERAL; alu.src[1].chan = 0; - alu.src[1].value = (uint32_t *)&half_inv_pi; + alu.src[1].value = *(uint32_t *)&half_inv_pi; alu.src[2].sel = V_SQ_ALU_SRC_0_5; alu.src[2].chan = 0; alu.last = 1; @@ -1021,8 +1087,8 @@ static int tgsi_setup_trig(struct r600_shader_ctx *ctx, alu.src[2].chan = 0; if (ctx->bc->chiprev == CHIPREV_R600) { - alu.src[1].value = (uint32_t *)&double_pi; - alu.src[2].value = (uint32_t *)&neg_pi; + alu.src[1].value = *(uint32_t *)&double_pi; + alu.src[2].value = *(uint32_t *)&neg_pi; } else { alu.src[1].sel = V_SQ_ALU_SRC_1; alu.src[2].sel = V_SQ_ALU_SRC_0_5; @@ -1039,12 +1105,11 @@ static int tgsi_setup_trig(struct r600_shader_ctx *ctx, static int tgsi_trig(struct r600_shader_ctx *ctx) { struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction; - struct r600_bc_alu_src r600_src[3]; struct r600_bc_alu alu; int i, r; int lasti = tgsi_last_instruction(inst->Dst[0].Register.WriteMask); - r = tgsi_setup_trig(ctx, r600_src); + r = tgsi_setup_trig(ctx); if (r) return r; @@ -1070,9 +1135,7 @@ static int tgsi_trig(struct r600_shader_ctx *ctx) alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV); alu.src[0].sel = ctx->temp_reg; - r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst); - if (r) - return r; + tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst); if (i == lasti) alu.last = 1; r = r600_bc_add_alu(ctx->bc, &alu); @@ -1085,7 +1148,6 @@ static int tgsi_trig(struct r600_shader_ctx *ctx) static int tgsi_scs(struct r600_shader_ctx *ctx) { struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction; - struct r600_bc_alu_src r600_src[3]; struct r600_bc_alu alu; int r; @@ -1093,7 +1155,7 @@ static int tgsi_scs(struct r600_shader_ctx *ctx) * X or Y components of the destination vector. */ if (likely(inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_XY)) { - r = tgsi_setup_trig(ctx, r600_src); + r = tgsi_setup_trig(ctx); if (r) return r; } @@ -1102,9 +1164,7 @@ static int tgsi_scs(struct r600_shader_ctx *ctx) if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_X) { memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_COS); - r = tgsi_dst(ctx, &inst->Dst[0], 0, &alu.dst); - if (r) - return r; + tgsi_dst(ctx, &inst->Dst[0], 0, &alu.dst); alu.src[0].sel = ctx->temp_reg; alu.src[0].chan = 0; @@ -1118,9 +1178,7 @@ static int tgsi_scs(struct r600_shader_ctx *ctx) if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Y) { memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SIN); - r = tgsi_dst(ctx, &inst->Dst[0], 1, &alu.dst); - if (r) - return r; + tgsi_dst(ctx, &inst->Dst[0], 1, &alu.dst); alu.src[0].sel = ctx->temp_reg; alu.src[0].chan = 0; @@ -1136,9 +1194,7 @@ static int tgsi_scs(struct r600_shader_ctx *ctx) alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV); - r = tgsi_dst(ctx, &inst->Dst[0], 2, &alu.dst); - if (r) - return r; + tgsi_dst(ctx, &inst->Dst[0], 2, &alu.dst); alu.src[0].sel = V_SQ_ALU_SRC_0; alu.src[0].chan = 0; @@ -1156,9 +1212,7 @@ static int tgsi_scs(struct r600_shader_ctx *ctx) alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV); - r = tgsi_dst(ctx, &inst->Dst[0], 3, &alu.dst); - if (r) - return r; + tgsi_dst(ctx, &inst->Dst[0], 3, &alu.dst); alu.src[0].sel = V_SQ_ALU_SRC_1; alu.src[0].chan = 0; @@ -1175,7 +1229,6 @@ static int tgsi_scs(struct r600_shader_ctx *ctx) static int tgsi_kill(struct r600_shader_ctx *ctx) { - struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction; struct r600_bc_alu alu; int i, r; @@ -1191,10 +1244,7 @@ static int tgsi_kill(struct r600_shader_ctx *ctx) alu.src[1].sel = V_SQ_ALU_SRC_1; alu.src[1].neg = 1; } else { - r = tgsi_src(ctx, &inst->Src[0], &alu.src[1]); - if (r) - return r; - alu.src[1].chan = tgsi_chan(&inst->Src[0], i); + r600_bc_src(&alu.src[1], &ctx->src[0], i); } if (i == 3) { alu.last = 1; @@ -1214,24 +1264,14 @@ static int tgsi_lit(struct r600_shader_ctx *ctx) { struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction; struct r600_bc_alu alu; - struct r600_bc_alu_src r600_src[3]; int r; - r = tgsi_split_constant(ctx, r600_src); - if (r) - return r; - r = tgsi_split_literal_constant(ctx, r600_src); - if (r) - return r; - /* dst.x, <- 1.0 */ memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV); alu.src[0].sel = V_SQ_ALU_SRC_1; /*1.0*/ alu.src[0].chan = 0; - r = tgsi_dst(ctx, &inst->Dst[0], 0, &alu.dst); - if (r) - return r; + tgsi_dst(ctx, &inst->Dst[0], 0, &alu.dst); alu.dst.write = (inst->Dst[0].Register.WriteMask >> 0) & 1; r = r600_bc_add_alu(ctx->bc, &alu); if (r) @@ -1240,12 +1280,10 @@ static int tgsi_lit(struct r600_shader_ctx *ctx) /* dst.y = max(src.x, 0.0) */ memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MAX); - alu.src[0] = r600_src[0]; + r600_bc_src(&alu.src[0], &ctx->src[0], 0); alu.src[1].sel = V_SQ_ALU_SRC_0; /*0.0*/ alu.src[1].chan = 0; - r = tgsi_dst(ctx, &inst->Dst[0], 1, &alu.dst); - if (r) - return r; + tgsi_dst(ctx, &inst->Dst[0], 1, &alu.dst); alu.dst.write = (inst->Dst[0].Register.WriteMask >> 1) & 1; r = r600_bc_add_alu(ctx->bc, &alu); if (r) @@ -1256,9 +1294,7 @@ static int tgsi_lit(struct r600_shader_ctx *ctx) alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV); alu.src[0].sel = V_SQ_ALU_SRC_1; alu.src[0].chan = 0; - r = tgsi_dst(ctx, &inst->Dst[0], 3, &alu.dst); - if (r) - return r; + tgsi_dst(ctx, &inst->Dst[0], 3, &alu.dst); alu.dst.write = (inst->Dst[0].Register.WriteMask >> 3) & 1; alu.last = 1; r = r600_bc_add_alu(ctx->bc, &alu); @@ -1273,11 +1309,8 @@ static int tgsi_lit(struct r600_shader_ctx *ctx) /* dst.z = log(src.y) */ memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_LOG_CLAMPED); - alu.src[0] = r600_src[0]; - alu.src[0].chan = tgsi_chan(&inst->Src[0], 1); - r = tgsi_dst(ctx, &inst->Dst[0], 2, &alu.dst); - if (r) - return r; + r600_bc_src(&alu.src[0], &ctx->src[0], 1); + tgsi_dst(ctx, &inst->Dst[0], 2, &alu.dst); alu.last = 1; r = r600_bc_add_alu(ctx->bc, &alu); if (r) @@ -1289,13 +1322,11 @@ static int tgsi_lit(struct r600_shader_ctx *ctx) /* tmp.x = amd MUL_LIT(src.w, dst.z, src.x ) */ memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MUL_LIT); - alu.src[0] = r600_src[0]; - alu.src[0].chan = tgsi_chan(&inst->Src[0], 3); + r600_bc_src(&alu.src[0], &ctx->src[0], 3); alu.src[1].sel = sel; alu.src[1].chan = chan; - alu.src[2] = r600_src[0]; - alu.src[2].chan = tgsi_chan(&inst->Src[0], 0); + r600_bc_src(&alu.src[2], &ctx->src[0], 0); alu.dst.sel = ctx->temp_reg; alu.dst.chan = 0; alu.dst.write = 1; @@ -1310,9 +1341,7 @@ static int tgsi_lit(struct r600_shader_ctx *ctx) alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_EXP_IEEE); alu.src[0].sel = ctx->temp_reg; alu.src[0].chan = 0; - r = tgsi_dst(ctx, &inst->Dst[0], 2, &alu.dst); - if (r) - return r; + tgsi_dst(ctx, &inst->Dst[0], 2, &alu.dst); alu.last = 1; r = r600_bc_add_alu(ctx->bc, &alu); if (r) @@ -1336,10 +1365,7 @@ static int tgsi_rsq(struct r600_shader_ctx *ctx) alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIPSQRT_CLAMPED); for (i = 0; i < inst->Instruction.NumSrcRegs; i++) { - r = tgsi_src(ctx, &inst->Src[i], &alu.src[i]); - if (r) - return r; - alu.src[i].chan = tgsi_chan(&inst->Src[i], 0); + r600_bc_src(&alu.src[i], &ctx->src[i], 0); alu.src[i].abs = 1; } alu.dst.sel = ctx->temp_reg; @@ -1363,9 +1389,7 @@ static int tgsi_helper_tempx_replicate(struct r600_shader_ctx *ctx) alu.src[0].sel = ctx->temp_reg; alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV); alu.dst.chan = i; - r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst); - if (r) - return r; + tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst); alu.dst.write = (inst->Dst[0].Register.WriteMask >> i) & 1; if (i == 3) alu.last = 1; @@ -1385,10 +1409,7 @@ static int tgsi_trans_srcx_replicate(struct r600_shader_ctx *ctx) memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = ctx->inst_info->r600_opcode; for (i = 0; i < inst->Instruction.NumSrcRegs; i++) { - r = tgsi_src(ctx, &inst->Src[i], &alu.src[i]); - if (r) - return r; - alu.src[i].chan = tgsi_chan(&inst->Src[i], 0); + r600_bc_src(&alu.src[i], &ctx->src[i], 0); } alu.dst.sel = ctx->temp_reg; alu.dst.write = 1; @@ -1402,17 +1423,13 @@ static int tgsi_trans_srcx_replicate(struct r600_shader_ctx *ctx) static int tgsi_pow(struct r600_shader_ctx *ctx) { - struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction; struct r600_bc_alu alu; int r; /* LOG2(a) */ memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_LOG_IEEE); - r = tgsi_src(ctx, &inst->Src[0], &alu.src[0]); - if (r) - return r; - alu.src[0].chan = tgsi_chan(&inst->Src[0], 0); + r600_bc_src(&alu.src[0], &ctx->src[0], 0); alu.dst.sel = ctx->temp_reg; alu.dst.write = 1; alu.last = 1; @@ -1422,10 +1439,7 @@ static int tgsi_pow(struct r600_shader_ctx *ctx) /* b * LOG2(a) */ memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MUL); - r = tgsi_src(ctx, &inst->Src[1], &alu.src[0]); - if (r) - return r; - alu.src[0].chan = tgsi_chan(&inst->Src[1], 0); + r600_bc_src(&alu.src[0], &ctx->src[1], 0); alu.src[1].sel = ctx->temp_reg; alu.dst.sel = ctx->temp_reg; alu.dst.write = 1; @@ -1450,16 +1464,8 @@ static int tgsi_ssg(struct r600_shader_ctx *ctx) { struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction; struct r600_bc_alu alu; - struct r600_bc_alu_src r600_src[3]; int i, r; - r = tgsi_split_constant(ctx, r600_src); - if (r) - return r; - r = tgsi_split_literal_constant(ctx, r600_src); - if (r) - return r; - /* tmp = (src > 0 ? 1 : src) */ for (i = 0; i < 4; i++) { memset(&alu, 0, sizeof(struct r600_bc_alu)); @@ -1469,13 +1475,10 @@ static int tgsi_ssg(struct r600_shader_ctx *ctx) alu.dst.sel = ctx->temp_reg; alu.dst.chan = i; - alu.src[0] = r600_src[0]; - alu.src[0].chan = tgsi_chan(&inst->Src[0], i); - + r600_bc_src(&alu.src[0], &ctx->src[0], i); alu.src[1].sel = V_SQ_ALU_SRC_1; + r600_bc_src(&alu.src[2], &ctx->src[0], i); - alu.src[2] = r600_src[0]; - alu.src[2].chan = tgsi_chan(&inst->Src[0], i); if (i == 3) alu.last = 1; r = r600_bc_add_alu(ctx->bc, &alu); @@ -1488,9 +1491,7 @@ static int tgsi_ssg(struct r600_shader_ctx *ctx) memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_CNDGT); alu.is_op3 = 1; - r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst); - if (r) - return r; + tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst); alu.src[0].sel = ctx->temp_reg; alu.src[0].chan = i; @@ -1523,9 +1524,7 @@ static int tgsi_helper_copy(struct r600_shader_ctx *ctx, struct tgsi_full_instru alu.dst.chan = i; } else { alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV); - r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst); - if (r) - return r; + tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst); alu.src[0].sel = ctx->temp_reg; alu.src[0].chan = i; } @@ -1542,17 +1541,10 @@ static int tgsi_helper_copy(struct r600_shader_ctx *ctx, struct tgsi_full_instru static int tgsi_op3(struct r600_shader_ctx *ctx) { struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction; - struct r600_bc_alu_src r600_src[3]; struct r600_bc_alu alu; int i, j, r; int lasti = tgsi_last_instruction(inst->Dst[0].Register.WriteMask); - r = tgsi_split_constant(ctx, r600_src); - if (r) - return r; - r = tgsi_split_literal_constant(ctx, r600_src); - if (r) - return r; for (i = 0; i < lasti + 1; i++) { if (!(inst->Dst[0].Register.WriteMask & (1 << i))) continue; @@ -1560,14 +1552,10 @@ static int tgsi_op3(struct r600_shader_ctx *ctx) memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = ctx->inst_info->r600_opcode; for (j = 0; j < inst->Instruction.NumSrcRegs; j++) { - alu.src[j] = r600_src[j]; - alu.src[j].chan = tgsi_chan(&inst->Src[j], i); + r600_bc_src(&alu.src[j], &ctx->src[j], i); } - r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst); - if (r) - return r; - + tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst); alu.dst.chan = i; alu.dst.write = 1; alu.is_op3 = 1; @@ -1584,28 +1572,17 @@ static int tgsi_op3(struct r600_shader_ctx *ctx) static int tgsi_dp(struct r600_shader_ctx *ctx) { struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction; - struct r600_bc_alu_src r600_src[3]; struct r600_bc_alu alu; int i, j, r; - r = tgsi_split_constant(ctx, r600_src); - if (r) - return r; - r = tgsi_split_literal_constant(ctx, r600_src); - if (r) - return r; for (i = 0; i < 4; i++) { memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = ctx->inst_info->r600_opcode; for (j = 0; j < inst->Instruction.NumSrcRegs; j++) { - alu.src[j] = r600_src[j]; - alu.src[j].chan = tgsi_chan(&inst->Src[j], i); + r600_bc_src(&alu.src[j], &ctx->src[j], i); } - r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst); - if (r) - return r; - + tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst); alu.dst.chan = i; alu.dst.write = (inst->Dst[0].Register.WriteMask >> i) & 1; /* handle some special cases */ @@ -1661,11 +1638,8 @@ static int tgsi_tex(struct r600_shader_ctx *ctx) /* Add perspective divide */ memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIP_IEEE); - r = tgsi_src(ctx, &inst->Src[0], &alu.src[0]); - if (r) - return r; + r600_bc_src(&alu.src[0], &ctx->src[0], 3); - alu.src[0].chan = tgsi_chan(&inst->Src[0], 3); alu.dst.sel = ctx->temp_reg; alu.dst.chan = 3; alu.last = 1; @@ -1679,10 +1653,7 @@ static int tgsi_tex(struct r600_shader_ctx *ctx) alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MUL); alu.src[0].sel = ctx->temp_reg; alu.src[0].chan = 3; - r = tgsi_src(ctx, &inst->Src[0], &alu.src[1]); - if (r) - return r; - alu.src[1].chan = tgsi_chan(&inst->Src[0], i); + r600_bc_src(&alu.src[1], &ctx->src[0], i); alu.dst.sel = ctx->temp_reg; alu.dst.chan = i; alu.dst.write = 1; @@ -1735,14 +1706,8 @@ static int tgsi_tex(struct r600_shader_ctx *ctx) src2_chan = 0; break; } - r = tgsi_src(ctx, &inst->Src[0], &alu.src[0]); - if (r) - return r; - alu.src[0].chan = tgsi_chan(&inst->Src[0], src_chan); - r = tgsi_src(ctx, &inst->Src[0], &alu.src[1]); - if (r) - return r; - alu.src[1].chan = tgsi_chan(&inst->Src[0], src2_chan); + r600_bc_src(&alu.src[0], &ctx->src[0], src_chan); + r600_bc_src(&alu.src[1], &ctx->src[0], src2_chan); alu.dst.sel = ctx->temp_reg; alu.dst.chan = i; if (i == 3) @@ -1782,7 +1747,7 @@ static int tgsi_tex(struct r600_shader_ctx *ctx) alu.src[2].sel = V_SQ_ALU_SRC_LITERAL; alu.src[2].chan = 0; - alu.src[2].value = (u32*)&one_point_five; + alu.src[2].value = *(uint32_t *)&one_point_five; alu.dst.sel = ctx->temp_reg; alu.dst.chan = 0; @@ -1803,7 +1768,7 @@ static int tgsi_tex(struct r600_shader_ctx *ctx) alu.src[2].sel = V_SQ_ALU_SRC_LITERAL; alu.src[2].chan = 0; - alu.src[2].value = (u32*)&one_point_five; + alu.src[2].value = *(uint32_t *)&one_point_five; alu.dst.sel = ctx->temp_reg; alu.dst.chan = 1; @@ -1822,10 +1787,7 @@ static int tgsi_tex(struct r600_shader_ctx *ctx) for (i = 0; i < 4; i++) { memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV); - r = tgsi_src(ctx, &inst->Src[0], &alu.src[0]); - if (r) - return r; - alu.src[0].chan = tgsi_chan(&inst->Src[0], i); + r600_bc_src(&alu.src[0], &ctx->src[0], i); alu.dst.sel = ctx->temp_reg; alu.dst.chan = i; if (i == 3) @@ -1846,7 +1808,7 @@ static int tgsi_tex(struct r600_shader_ctx *ctx) memset(&tex, 0, sizeof(struct r600_bc_tex)); tex.inst = opcode; tex.sampler_id = ctx->file_offset[inst->Src[1].Register.File] + inst->Src[1].Register.Index; - tex.resource_id = tex.sampler_id; + tex.resource_id = tex.sampler_id + R600_MAX_CONST_BUFFERS; tex.src_gpr = src_gpr; tex.dst_gpr = ctx->file_offset[inst->Dst[0].Register.File] + inst->Dst[0].Register.Index; tex.dst_sel_x = (inst->Dst[0].Register.WriteMask & 1) ? 0 : 7; @@ -1872,6 +1834,12 @@ static int tgsi_tex(struct r600_shader_ctx *ctx) tex.coord_type_w = 1; } + if (inst->Texture.Texture == TGSI_TEXTURE_1D_ARRAY) { + tex.coord_type_z = 0; + tex.src_sel_z = 1; + } else if (inst->Texture.Texture == TGSI_TEXTURE_2D_ARRAY) + tex.coord_type_z = 0; + if (inst->Texture.Texture == TGSI_TEXTURE_SHADOW1D || inst->Texture.Texture == TGSI_TEXTURE_SHADOW2D) tex.src_sel_w = 2; @@ -1886,36 +1854,23 @@ static int tgsi_tex(struct r600_shader_ctx *ctx) static int tgsi_lrp(struct r600_shader_ctx *ctx) { struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction; - struct r600_bc_alu_src r600_src[3]; struct r600_bc_alu alu; int lasti = tgsi_last_instruction(inst->Dst[0].Register.WriteMask); unsigned i; int r; - r = tgsi_split_constant(ctx, r600_src); - if (r) - return r; - r = tgsi_split_literal_constant(ctx, r600_src); - if (r) - return r; - /* optimize if it's just an equal balance */ - if(r600_src[0].sel == V_SQ_ALU_SRC_0_5) { + if (ctx->src[0].sel == V_SQ_ALU_SRC_0_5) { for (i = 0; i < lasti + 1; i++) { if (!(inst->Dst[0].Register.WriteMask & (1 << i))) continue; memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_ADD); - alu.src[0] = r600_src[1]; - alu.src[0].chan = tgsi_chan(&inst->Src[1], i); - alu.src[1] = r600_src[2]; - alu.src[1].chan = tgsi_chan(&inst->Src[2], i); + r600_bc_src(&alu.src[0], &ctx->src[1], i); + r600_bc_src(&alu.src[1], &ctx->src[2], i); alu.omod = 3; - r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst); - if (r) - return r; - + tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst); alu.dst.chan = i; if (i == lasti) { alu.last = 1; @@ -1936,8 +1891,7 @@ static int tgsi_lrp(struct r600_shader_ctx *ctx) alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_ADD); alu.src[0].sel = V_SQ_ALU_SRC_1; alu.src[0].chan = 0; - alu.src[1] = r600_src[0]; - alu.src[1].chan = tgsi_chan(&inst->Src[0], i); + r600_bc_src(&alu.src[1], &ctx->src[0], i); alu.src[1].neg = 1; alu.dst.sel = ctx->temp_reg; alu.dst.chan = i; @@ -1959,8 +1913,7 @@ static int tgsi_lrp(struct r600_shader_ctx *ctx) alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MUL); alu.src[0].sel = ctx->temp_reg; alu.src[0].chan = i; - alu.src[1] = r600_src[2]; - alu.src[1].chan = tgsi_chan(&inst->Src[2], i); + r600_bc_src(&alu.src[1], &ctx->src[2], i); alu.dst.sel = ctx->temp_reg; alu.dst.chan = i; if (i == lasti) { @@ -1980,17 +1933,12 @@ static int tgsi_lrp(struct r600_shader_ctx *ctx) memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MULADD); alu.is_op3 = 1; - alu.src[0] = r600_src[0]; - alu.src[0].chan = tgsi_chan(&inst->Src[0], i); - alu.src[1] = r600_src[1]; - alu.src[1].chan = tgsi_chan(&inst->Src[1], i); + r600_bc_src(&alu.src[0], &ctx->src[0], i); + r600_bc_src(&alu.src[1], &ctx->src[1], i); alu.src[2].sel = ctx->temp_reg; alu.src[2].chan = i; - r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst); - if (r) - return r; - + tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst); alu.dst.chan = i; if (i == lasti) { alu.last = 1; @@ -2005,37 +1953,20 @@ static int tgsi_lrp(struct r600_shader_ctx *ctx) static int tgsi_cmp(struct r600_shader_ctx *ctx) { struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction; - struct r600_bc_alu_src r600_src[3]; struct r600_bc_alu alu; int i, r; int lasti = tgsi_last_instruction(inst->Dst[0].Register.WriteMask); - r = tgsi_split_constant(ctx, r600_src); - if (r) - return r; - r = tgsi_split_literal_constant(ctx, r600_src); - if (r) - return r; - for (i = 0; i < lasti + 1; i++) { if (!(inst->Dst[0].Register.WriteMask & (1 << i))) continue; memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_CNDGE); - alu.src[0] = r600_src[0]; - alu.src[0].chan = tgsi_chan(&inst->Src[0], i); - - alu.src[1] = r600_src[2]; - alu.src[1].chan = tgsi_chan(&inst->Src[2], i); - - alu.src[2] = r600_src[1]; - alu.src[2].chan = tgsi_chan(&inst->Src[1], i); - - r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst); - if (r) - return r; - + r600_bc_src(&alu.src[0], &ctx->src[0], i); + r600_bc_src(&alu.src[1], &ctx->src[2], i); + r600_bc_src(&alu.src[2], &ctx->src[1], i); + tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst); alu.dst.chan = i; alu.dst.write = 1; alu.is_op3 = 1; @@ -2051,7 +1982,6 @@ static int tgsi_cmp(struct r600_shader_ctx *ctx) static int tgsi_xpd(struct r600_shader_ctx *ctx) { struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction; - struct r600_bc_alu_src r600_src[3]; struct r600_bc_alu alu; uint32_t use_temp = 0; int i, r; @@ -2059,43 +1989,34 @@ static int tgsi_xpd(struct r600_shader_ctx *ctx) if (inst->Dst[0].Register.WriteMask != 0xf) use_temp = 1; - r = tgsi_split_constant(ctx, r600_src); - if (r) - return r; - r = tgsi_split_literal_constant(ctx, r600_src); - if (r) - return r; - for (i = 0; i < 4; i++) { memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MUL); - alu.src[0] = r600_src[0]; switch (i) { case 0: - alu.src[0].chan = tgsi_chan(&inst->Src[0], 2); + r600_bc_src(&alu.src[0], &ctx->src[0], 2); break; case 1: - alu.src[0].chan = tgsi_chan(&inst->Src[0], 0); + r600_bc_src(&alu.src[0], &ctx->src[0], 0); break; case 2: - alu.src[0].chan = tgsi_chan(&inst->Src[0], 1); + r600_bc_src(&alu.src[0], &ctx->src[0], 1); break; case 3: alu.src[0].sel = V_SQ_ALU_SRC_0; alu.src[0].chan = i; } - alu.src[1] = r600_src[1]; switch (i) { case 0: - alu.src[1].chan = tgsi_chan(&inst->Src[1], 1); + r600_bc_src(&alu.src[1], &ctx->src[1], 1); break; case 1: - alu.src[1].chan = tgsi_chan(&inst->Src[1], 2); + r600_bc_src(&alu.src[1], &ctx->src[1], 2); break; case 2: - alu.src[1].chan = tgsi_chan(&inst->Src[1], 0); + r600_bc_src(&alu.src[1], &ctx->src[1], 0); break; case 3: alu.src[1].sel = V_SQ_ALU_SRC_0; @@ -2117,32 +2038,30 @@ static int tgsi_xpd(struct r600_shader_ctx *ctx) memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MULADD); - alu.src[0] = r600_src[0]; switch (i) { case 0: - alu.src[0].chan = tgsi_chan(&inst->Src[0], 1); + r600_bc_src(&alu.src[0], &ctx->src[0], 1); break; case 1: - alu.src[0].chan = tgsi_chan(&inst->Src[0], 2); + r600_bc_src(&alu.src[0], &ctx->src[0], 2); break; case 2: - alu.src[0].chan = tgsi_chan(&inst->Src[0], 0); + r600_bc_src(&alu.src[0], &ctx->src[0], 0); break; case 3: alu.src[0].sel = V_SQ_ALU_SRC_0; alu.src[0].chan = i; } - alu.src[1] = r600_src[1]; switch (i) { case 0: - alu.src[1].chan = tgsi_chan(&inst->Src[1], 2); + r600_bc_src(&alu.src[1], &ctx->src[1], 2); break; case 1: - alu.src[1].chan = tgsi_chan(&inst->Src[1], 0); + r600_bc_src(&alu.src[1], &ctx->src[1], 0); break; case 2: - alu.src[1].chan = tgsi_chan(&inst->Src[1], 1); + r600_bc_src(&alu.src[1], &ctx->src[1], 1); break; case 3: alu.src[1].sel = V_SQ_ALU_SRC_0; @@ -2155,11 +2074,8 @@ static int tgsi_xpd(struct r600_shader_ctx *ctx) if (use_temp) alu.dst.sel = ctx->temp_reg; - else { - r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst); - if (r) - return r; - } + else + tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst); alu.dst.chan = i; alu.dst.write = 1; alu.is_op3 = 1; @@ -2177,7 +2093,6 @@ static int tgsi_xpd(struct r600_shader_ctx *ctx) static int tgsi_exp(struct r600_shader_ctx *ctx) { struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction; - struct r600_bc_alu_src r600_src[3] = { { 0 } }; struct r600_bc_alu alu; int r; @@ -2186,11 +2101,7 @@ static int tgsi_exp(struct r600_shader_ctx *ctx) memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FLOOR); - r = tgsi_src(ctx, &inst->Src[0], &alu.src[0]); - if (r) - return r; - - alu.src[0].chan = tgsi_chan(&inst->Src[0], 0); + r600_bc_src(&alu.src[0], &ctx->src[0], 0); alu.dst.sel = ctx->temp_reg; alu.dst.chan = 0; @@ -2218,11 +2129,7 @@ static int tgsi_exp(struct r600_shader_ctx *ctx) memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FRACT); - alu.src[0] = r600_src[0]; - r = tgsi_src(ctx, &inst->Src[0], &alu.src[0]); - if (r) - return r; - alu.src[0].chan = tgsi_chan(&inst->Src[0], 0); + r600_bc_src(&alu.src[0], &ctx->src[0], 0); alu.dst.sel = ctx->temp_reg; // r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst); @@ -2242,10 +2149,7 @@ static int tgsi_exp(struct r600_shader_ctx *ctx) if ((inst->Dst[0].Register.WriteMask >> 2) & 0x1) { memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_EXP_IEEE); - r = tgsi_src(ctx, &inst->Src[0], &alu.src[0]); - if (r) - return r; - alu.src[0].chan = tgsi_chan(&inst->Src[0], 0); + r600_bc_src(&alu.src[0], &ctx->src[0], 0); alu.dst.sel = ctx->temp_reg; alu.dst.write = 1; @@ -2288,11 +2192,7 @@ static int tgsi_log(struct r600_shader_ctx *ctx) memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_LOG_IEEE); - r = tgsi_src(ctx, &inst->Src[0], &alu.src[0]); - if (r) - return r; - - alu.src[0].chan = tgsi_chan(&inst->Src[0], 0); + r600_bc_src(&alu.src[0], &ctx->src[0], 0); alu.dst.sel = ctx->temp_reg; alu.dst.chan = 0; @@ -2321,11 +2221,7 @@ static int tgsi_log(struct r600_shader_ctx *ctx) memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_LOG_IEEE); - r = tgsi_src(ctx, &inst->Src[0], &alu.src[0]); - if (r) - return r; - - alu.src[0].chan = tgsi_chan(&inst->Src[0], 0); + r600_bc_src(&alu.src[0], &ctx->src[0], 0); alu.dst.sel = ctx->temp_reg; alu.dst.chan = 1; @@ -2385,11 +2281,7 @@ static int tgsi_log(struct r600_shader_ctx *ctx) alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MUL); - r = tgsi_src(ctx, &inst->Src[0], &alu.src[0]); - if (r) - return r; - - alu.src[0].chan = tgsi_chan(&inst->Src[0], 0); + r600_bc_src(&alu.src[0], &ctx->src[0], 0); alu.src[1].sel = ctx->temp_reg; alu.src[1].chan = 1; @@ -2409,11 +2301,7 @@ static int tgsi_log(struct r600_shader_ctx *ctx) memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_LOG_IEEE); - r = tgsi_src(ctx, &inst->Src[0], &alu.src[0]); - if (r) - return r; - - alu.src[0].chan = tgsi_chan(&inst->Src[0], 0); + r600_bc_src(&alu.src[0], &ctx->src[0], 0); alu.dst.sel = ctx->temp_reg; alu.dst.write = 1; @@ -2451,6 +2339,7 @@ static int tgsi_eg_arl(struct r600_shader_ctx *ctx) struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction; struct r600_bc_alu alu; int r; + memset(&alu, 0, sizeof(struct r600_bc_alu)); switch (inst->Instruction.Opcode) { @@ -2465,23 +2354,23 @@ static int tgsi_eg_arl(struct r600_shader_ctx *ctx) return -1; } - r = tgsi_src(ctx, &inst->Src[0], &alu.src[0]); - if (r) - return r; - alu.src[0].chan = tgsi_chan(&inst->Src[0], 0); + r600_bc_src(&alu.src[0], &ctx->src[0], 0); alu.last = 1; - alu.dst.chan = 0; - alu.dst.sel = ctx->temp_reg; + alu.dst.sel = ctx->ar_reg; alu.dst.write = 1; r = r600_bc_add_alu(ctx->bc, &alu); if (r) return r; + + /* TODO: Note that the MOVA can be avoided if we never use AR for + * indexing non-CB registers in the current ALU clause. Similarly, we + * need to load AR from ar_reg again if we started a new clause + * between ARL and AR usage. The easy way to do that is to remove + * the MOVA here, and load it for the first AR access after ar_reg + * has been modified in each clause. */ memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOVA_INT; - r = tgsi_src(ctx, &inst->Src[0], &alu.src[0]); - if (r) - return r; - alu.src[0].sel = ctx->temp_reg; + alu.src[0].sel = ctx->ar_reg; alu.src[0].chan = 0; alu.last = 1; r = r600_bc_add_alu(ctx->bc, &alu); @@ -2495,26 +2384,48 @@ static int tgsi_r600_arl(struct r600_shader_ctx *ctx) struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction; struct r600_bc_alu alu; int r; - memset(&alu, 0, sizeof(struct r600_bc_alu)); switch (inst->Instruction.Opcode) { case TGSI_OPCODE_ARL: - alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOVA_FLOOR; + memset(&alu, 0, sizeof(alu)); + alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FLOOR; + r600_bc_src(&alu.src[0], &ctx->src[0], 0); + alu.dst.sel = ctx->ar_reg; + alu.dst.write = 1; + alu.last = 1; + + if ((r = r600_bc_add_alu(ctx->bc, &alu))) + return r; + + memset(&alu, 0, sizeof(alu)); + alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FLT_TO_INT; + alu.src[0].sel = ctx->ar_reg; + alu.dst.sel = ctx->ar_reg; + alu.dst.write = 1; + alu.last = 1; + + if ((r = r600_bc_add_alu(ctx->bc, &alu))) + return r; break; case TGSI_OPCODE_ARR: - alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOVA; + memset(&alu, 0, sizeof(alu)); + alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FLT_TO_INT; + r600_bc_src(&alu.src[0], &ctx->src[0], 0); + alu.dst.sel = ctx->ar_reg; + alu.dst.write = 1; + alu.last = 1; + + if ((r = r600_bc_add_alu(ctx->bc, &alu))) + return r; break; default: assert(0); return -1; } - - r = tgsi_src(ctx, &inst->Src[0], &alu.src[0]); - if (r) - return r; - alu.src[0].chan = tgsi_chan(&inst->Src[0], 0); - + memset(&alu, 0, sizeof(alu)); + alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOVA_INT; + alu.src[0].sel = ctx->ar_reg; alu.last = 1; r = r600_bc_add_alu(ctx->bc, &alu); @@ -2534,26 +2445,18 @@ static int tgsi_opdst(struct r600_shader_ctx *ctx) memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MUL); - r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst); - if (r) - return r; + tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst); if (i == 0 || i == 3) { alu.src[0].sel = V_SQ_ALU_SRC_1; } else { - r = tgsi_src(ctx, &inst->Src[0], &alu.src[0]); - if (r) - return r; - alu.src[0].chan = tgsi_chan(&inst->Src[0], i); + r600_bc_src(&alu.src[0], &ctx->src[0], i); } - if (i == 0 || i == 2) { + if (i == 0 || i == 2) { alu.src[1].sel = V_SQ_ALU_SRC_1; } else { - r = tgsi_src(ctx, &inst->Src[1], &alu.src[1]); - if (r) - return r; - alu.src[1].chan = tgsi_chan(&inst->Src[1], i); + r600_bc_src(&alu.src[1], &ctx->src[1], i); } if (i == 3) alu.last = 1; @@ -2566,7 +2469,6 @@ static int tgsi_opdst(struct r600_shader_ctx *ctx) static int emit_logic_pred(struct r600_shader_ctx *ctx, int opcode) { - struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction; struct r600_bc_alu alu; int r; @@ -2578,10 +2480,7 @@ static int emit_logic_pred(struct r600_shader_ctx *ctx, int opcode) alu.dst.write = 1; alu.dst.chan = 0; - r = tgsi_src(ctx, &inst->Src[0], &alu.src[0]); - if (r) - return r; - alu.src[0].chan = tgsi_chan(&inst->Src[0], 0); + r600_bc_src(&alu.src[0], &ctx->src[0], 0); alu.src[1].sel = V_SQ_ALU_SRC_0; alu.src[1].chan = 0; diff --git a/src/gallium/drivers/r600/r600_shader.h b/src/gallium/drivers/r600/r600_shader.h index 935dd6fe3ab..8f96ce5085c 100644 --- a/src/gallium/drivers/r600/r600_shader.h +++ b/src/gallium/drivers/r600/r600_shader.h @@ -45,8 +45,7 @@ struct r600_shader { struct r600_shader_io output[32]; enum radeon_family family; boolean uses_kill; + boolean fs_write_all; }; -int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *shader, u32 **literals); - #endif diff --git a/src/gallium/drivers/r600/r600_state.c b/src/gallium/drivers/r600/r600_state.c index de2668cee16..576067ae81e 100644 --- a/src/gallium/drivers/r600/r600_state.c +++ b/src/gallium/drivers/r600/r600_state.c @@ -37,6 +37,7 @@ #include <util/u_memory.h> #include <util/u_inlines.h> #include <util/u_framebuffer.h> +#include "util/u_transfer.h" #include <pipebuffer/pb_buffer.h> #include "r600.h" #include "r600d.h" @@ -94,221 +95,6 @@ void r600_polygon_offset_update(struct r600_pipe_context *rctx) } } -/* FIXME optimize away spi update when it's not needed */ -static void r600_spi_update(struct r600_pipe_context *rctx) -{ - struct r600_pipe_shader *shader = rctx->ps_shader; - struct r600_pipe_state rstate; - struct r600_shader *rshader = &shader->shader; - unsigned i, tmp; - - rstate.nregs = 0; - for (i = 0; i < rshader->ninput; i++) { - tmp = S_028644_SEMANTIC(r600_find_vs_semantic_index(&rctx->vs_shader->shader, rshader, i)); - if (rshader->input[i].centroid) - tmp |= S_028644_SEL_CENTROID(1); - if (rshader->input[i].interpolate == TGSI_INTERPOLATE_LINEAR) - tmp |= S_028644_SEL_LINEAR(1); - - if (rshader->input[i].name == TGSI_SEMANTIC_COLOR || - rshader->input[i].name == TGSI_SEMANTIC_BCOLOR || - rshader->input[i].name == TGSI_SEMANTIC_POSITION) { - tmp |= S_028644_FLAT_SHADE(rctx->flatshade); - } - if (rshader->input[i].name == TGSI_SEMANTIC_GENERIC && - rctx->sprite_coord_enable & (1 << rshader->input[i].sid)) { - tmp |= S_028644_PT_SPRITE_TEX(1); - } - r600_pipe_state_add_reg(&rstate, R_028644_SPI_PS_INPUT_CNTL_0 + i * 4, tmp, 0xFFFFFFFF, NULL); - } - r600_context_pipe_state_set(&rctx->ctx, &rstate); -} - -void r600_vertex_buffer_update(struct r600_pipe_context *rctx) -{ - struct r600_pipe_state *rstate; - struct r600_resource *rbuffer; - struct pipe_vertex_buffer *vertex_buffer; - unsigned i, offset; - - /* we don't update until we know vertex elements */ - if (rctx->vertex_elements == NULL || !rctx->nvertex_buffer) - return; - - if (rctx->vertex_elements->incompatible_layout) { - /* translate rebind new vertex elements so - * return once translated - */ - r600_begin_vertex_translate(rctx); - return; - } - - if (rctx->any_user_vbs) { - r600_upload_user_buffers(rctx); - rctx->any_user_vbs = FALSE; - } - - if (rctx->vertex_elements->vbuffer_need_offset) { - /* one resource per vertex elements */ - rctx->nvs_resource = rctx->vertex_elements->count; - } else { - /* bind vertex buffer once */ - rctx->nvs_resource = rctx->nvertex_buffer; - } - - for (i = 0 ; i < rctx->nvs_resource; i++) { - rstate = &rctx->vs_resource[i]; - rstate->id = R600_PIPE_STATE_RESOURCE; - rstate->nregs = 0; - - if (rctx->vertex_elements->vbuffer_need_offset) { - /* one resource per vertex elements */ - unsigned vbuffer_index; - vbuffer_index = rctx->vertex_elements->elements[i].vertex_buffer_index; - vertex_buffer = &rctx->vertex_buffer[vbuffer_index]; - rbuffer = (struct r600_resource*)vertex_buffer->buffer; - offset = rctx->vertex_elements->vbuffer_offset[i]; - } else { - /* bind vertex buffer once */ - vertex_buffer = &rctx->vertex_buffer[i]; - rbuffer = (struct r600_resource*)vertex_buffer->buffer; - offset = 0; - } - if (vertex_buffer == NULL || rbuffer == NULL) - continue; - offset += vertex_buffer->buffer_offset + r600_bo_offset(rbuffer->bo); - - r600_pipe_state_add_reg(rstate, R_038000_RESOURCE0_WORD0, - offset, 0xFFFFFFFF, rbuffer->bo); - r600_pipe_state_add_reg(rstate, R_038004_RESOURCE0_WORD1, - rbuffer->bo_size - offset - 1, 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(rstate, R_038008_RESOURCE0_WORD2, - S_038008_STRIDE(vertex_buffer->stride), - 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(rstate, R_03800C_RESOURCE0_WORD3, - 0x00000000, 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(rstate, R_038010_RESOURCE0_WORD4, - 0x00000000, 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(rstate, R_038014_RESOURCE0_WORD5, - 0x00000000, 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(rstate, R_038018_RESOURCE0_WORD6, - 0xC0000000, 0xFFFFFFFF, NULL); - r600_context_pipe_state_set_fs_resource(&rctx->ctx, rstate, i); - } -} - -static void r600_draw_common(struct r600_drawl *draw) -{ - struct r600_pipe_context *rctx = (struct r600_pipe_context *)draw->ctx; - struct r600_resource *rbuffer; - unsigned prim; - u32 vgt_dma_index_type, vgt_draw_initiator, mask; - struct r600_draw rdraw; - struct r600_pipe_state vgt; - - switch (draw->index_size) { - case 2: - vgt_draw_initiator = 0; - vgt_dma_index_type = 0; - break; - case 4: - vgt_draw_initiator = 0; - vgt_dma_index_type = 1; - break; - case 0: - vgt_draw_initiator = 2; - vgt_dma_index_type = 0; - break; - default: - R600_ERR("unsupported index size %d\n", draw->index_size); - return; - } - if (r600_conv_pipe_prim(draw->mode, &prim)) - return; - if (unlikely(rctx->ps_shader == NULL)) { - R600_ERR("missing vertex shader\n"); - return; - } - if (unlikely(rctx->vs_shader == NULL)) { - R600_ERR("missing vertex shader\n"); - return; - } - /* there should be enough input */ - if (rctx->vertex_elements->count < rctx->vs_shader->shader.bc.nresource) { - R600_ERR("%d resources provided, expecting %d\n", - rctx->vertex_elements->count, rctx->vs_shader->shader.bc.nresource); - return; - } - - r600_spi_update(rctx); - - mask = 0; - for (int i = 0; i < rctx->framebuffer.nr_cbufs; i++) { - mask |= (0xF << (i * 4)); - } - - vgt.id = R600_PIPE_STATE_VGT; - vgt.nregs = 0; - r600_pipe_state_add_reg(&vgt, R_008958_VGT_PRIMITIVE_TYPE, prim, 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(&vgt, R_028408_VGT_INDX_OFFSET, draw->index_bias, 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(&vgt, R_028400_VGT_MAX_VTX_INDX, draw->max_index, 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(&vgt, R_028404_VGT_MIN_VTX_INDX, draw->min_index, 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(&vgt, R_028238_CB_TARGET_MASK, rctx->cb_target_mask & mask, 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(&vgt, R_03CFF0_SQ_VTX_BASE_VTX_LOC, 0, 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(&vgt, R_03CFF4_SQ_VTX_START_INST_LOC, 0, 0xFFFFFFFF, NULL); - r600_context_pipe_state_set(&rctx->ctx, &vgt); - - rdraw.vgt_num_indices = draw->count; - rdraw.vgt_num_instances = 1; - rdraw.vgt_index_type = vgt_dma_index_type; - rdraw.vgt_draw_initiator = vgt_draw_initiator; - rdraw.indices = NULL; - if (draw->index_buffer) { - rbuffer = (struct r600_resource*)draw->index_buffer; - rdraw.indices = rbuffer->bo; - rdraw.indices_bo_offset = draw->index_buffer_offset; - } - r600_context_draw(&rctx->ctx, &rdraw); -} - -void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info) -{ - struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; - struct r600_drawl draw; - - memset(&draw, 0, sizeof(struct r600_drawl)); - draw.ctx = ctx; - draw.mode = info->mode; - draw.start = info->start; - draw.count = info->count; - if (info->indexed && rctx->index_buffer.buffer) { - draw.start += rctx->index_buffer.offset / rctx->index_buffer.index_size; - draw.min_index = info->min_index; - draw.max_index = info->max_index; - draw.index_bias = info->index_bias; - - r600_translate_index_buffer(rctx, &rctx->index_buffer.buffer, - &rctx->index_buffer.index_size, - &draw.start, - info->count); - - draw.index_size = rctx->index_buffer.index_size; - pipe_resource_reference(&draw.index_buffer, rctx->index_buffer.buffer); - draw.index_buffer_offset = draw.start * draw.index_size; - draw.start = 0; - r600_upload_index_buffer(rctx, &draw); - } else { - draw.index_size = 0; - draw.index_buffer = NULL; - draw.min_index = info->min_index; - draw.max_index = info->max_index; - draw.index_bias = info->start; - } - r600_draw_common(&draw); - - pipe_resource_reference(&draw.index_buffer, NULL); -} - static void r600_set_blend_color(struct pipe_context *ctx, const struct pipe_blend_color *state) { @@ -616,6 +402,7 @@ static struct pipe_sampler_view *r600_create_sampler_view(struct pipe_context *c uint32_t word4 = 0, yuv_format = 0, pitch = 0; unsigned char swizzle[4], array_mode = 0, tile_type = 0; struct r600_bo *bo[2]; + unsigned height, depth; if (resource == NULL) return NULL; @@ -643,22 +430,30 @@ static struct pipe_sampler_view *r600_create_sampler_view(struct pipe_context *c if (desc == NULL) { R600_ERR("unknow format %d\n", state->format); } - tmp = (struct r600_resource_texture*)texture; + tmp = (struct r600_resource_texture *)texture; + if (tmp->depth && !tmp->is_flushing_texture) { + r600_texture_depth_flush(ctx, texture, TRUE); + tmp = tmp->flushed_depth_texture; + } + + if (tmp->force_int_type) { + word4 &= C_038010_NUM_FORMAT_ALL; + word4 |= S_038010_NUM_FORMAT_ALL(V_038010_SQ_NUM_FORMAT_INT); + } rbuffer = &tmp->resource; bo[0] = rbuffer->bo; bo[1] = rbuffer->bo; - /* FIXME depth texture decompression */ - if (tmp->depth) { - r600_texture_depth_flush(ctx, texture); - tmp = (struct r600_resource_texture*)texture; - rbuffer = &tmp->flushed_depth_texture->resource; - bo[0] = rbuffer->bo; - bo[1] = rbuffer->bo; - } - pitch = align(tmp->pitch_in_pixels[0], 8); - if (tmp->tiled) { - array_mode = tmp->array_mode[0]; - tile_type = tmp->tile_type; + pitch = align(tmp->pitch_in_blocks[0] * util_format_get_blockwidth(state->format), 8); + array_mode = tmp->array_mode[0]; + tile_type = tmp->tile_type; + + height = texture->height0; + depth = texture->depth0; + if (texture->target == PIPE_TEXTURE_1D_ARRAY) { + height = 1; + depth = texture->array_size; + } else if (texture->target == PIPE_TEXTURE_2D_ARRAY) { + depth = texture->array_size; } /* FIXME properly handle first level != 0 */ @@ -669,22 +464,22 @@ static struct pipe_sampler_view *r600_create_sampler_view(struct pipe_context *c S_038000_PITCH((pitch / 8) - 1) | S_038000_TEX_WIDTH(texture->width0 - 1), 0xFFFFFFFF, NULL); r600_pipe_state_add_reg(rstate, R_038004_RESOURCE0_WORD1, - S_038004_TEX_HEIGHT(texture->height0 - 1) | - S_038004_TEX_DEPTH(texture->depth0 - 1) | + S_038004_TEX_HEIGHT(height - 1) | + S_038004_TEX_DEPTH(depth - 1) | S_038004_DATA_FORMAT(format), 0xFFFFFFFF, NULL); r600_pipe_state_add_reg(rstate, R_038008_RESOURCE0_WORD2, (tmp->offset[0] + r600_bo_offset(bo[0])) >> 8, 0xFFFFFFFF, bo[0]); r600_pipe_state_add_reg(rstate, R_03800C_RESOURCE0_WORD3, (tmp->offset[1] + r600_bo_offset(bo[1])) >> 8, 0xFFFFFFFF, bo[1]); r600_pipe_state_add_reg(rstate, R_038010_RESOURCE0_WORD4, - word4 | S_038010_NUM_FORMAT_ALL(V_038010_SQ_NUM_FORMAT_NORM) | + word4 | S_038010_SRF_MODE_ALL(V_038010_SRF_MODE_NO_ZERO) | S_038010_REQUEST_SIZE(1) | S_038010_BASE_LEVEL(state->u.tex.first_level), 0xFFFFFFFF, NULL); r600_pipe_state_add_reg(rstate, R_038014_RESOURCE0_WORD5, S_038014_LAST_LEVEL(state->u.tex.last_level) | - S_038014_BASE_ARRAY(0) | - S_038014_LAST_ARRAY(0), 0xFFFFFFFF, NULL); + S_038014_BASE_ARRAY(state->u.tex.first_layer) | + S_038014_LAST_ARRAY(state->u.tex.last_layer), 0xFFFFFFFF, NULL); r600_pipe_state_add_reg(rstate, R_038018_RESOURCE0_WORD6, S_038018_TYPE(V_038010_SQ_TEX_VTX_VALID_TEXTURE), 0xFFFFFFFF, NULL); @@ -714,9 +509,11 @@ static void r600_set_ps_sampler_view(struct pipe_context *ctx, unsigned count, for (i = 0; i < count; i++) { if (&rctx->ps_samplers.views[i]->base != views[i]) { if (resource[i]) - r600_context_pipe_state_set_ps_resource(&rctx->ctx, &resource[i]->state, i); + r600_context_pipe_state_set_ps_resource(&rctx->ctx, &resource[i]->state, + i + R600_MAX_CONST_BUFFERS); else - r600_context_pipe_state_set_ps_resource(&rctx->ctx, NULL, i); + r600_context_pipe_state_set_ps_resource(&rctx->ctx, NULL, + i + R600_MAX_CONST_BUFFERS); pipe_sampler_view_reference( (struct pipe_sampler_view **)&rctx->ps_samplers.views[i], @@ -726,7 +523,8 @@ static void r600_set_ps_sampler_view(struct pipe_context *ctx, unsigned count, } for (i = count; i < NUM_TEX_UNITS; i++) { if (rctx->ps_samplers.views[i]) { - r600_context_pipe_state_set_ps_resource(&rctx->ctx, NULL, i); + r600_context_pipe_state_set_ps_resource(&rctx->ctx, NULL, + i + R600_MAX_CONST_BUFFERS); pipe_sampler_view_reference((struct pipe_sampler_view **)&rctx->ps_samplers.views[i], NULL); } } @@ -908,21 +706,28 @@ static void r600_cb(struct r600_pipe_context *rctx, struct r600_pipe_state *rsta unsigned offset; const struct util_format_description *desc; struct r600_bo *bo[3]; + int i; surf = (struct r600_surface *)state->cbufs[cb]; rtex = (struct r600_resource_texture*)state->cbufs[cb]->texture; + + if (rtex->depth && !rtex->is_flushing_texture) { + r600_texture_depth_flush(&rctx->context, state->cbufs[cb]->texture, TRUE); + rtex = rtex->flushed_depth_texture; + } + rbuffer = &rtex->resource; bo[0] = rbuffer->bo; bo[1] = rbuffer->bo; bo[2] = rbuffer->bo; /* XXX quite sure for dx10+ hw don't need any offset hacks */ - offset = r600_texture_get_offset((struct r600_resource_texture *)state->cbufs[cb]->texture, + offset = r600_texture_get_offset(rtex, level, state->cbufs[cb]->u.tex.first_layer); - pitch = rtex->pitch_in_pixels[level] / 8 - 1; - slice = rtex->pitch_in_pixels[level] * surf->aligned_height / 64 - 1; + pitch = rtex->pitch_in_blocks[level] / 8 - 1; + slice = rtex->pitch_in_blocks[level] * surf->aligned_height / 64 - 1; ntype = 0; - desc = util_format_description(rtex->resource.base.b.format); + desc = util_format_description(surf->base.format); if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) ntype = V_0280A0_NUMBER_SRGB; else if (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN) { @@ -937,15 +742,30 @@ static void r600_cb(struct r600_pipe_context *rctx, struct r600_pipe_state *rsta } } - format = r600_translate_colorformat(rtex->resource.base.b.format); - swap = r600_translate_colorswap(rtex->resource.base.b.format); + for (i = 0; i < 4; i++) { + if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID) { + break; + } + } + + format = r600_translate_colorformat(surf->base.format); + swap = r600_translate_colorswap(surf->base.format); + + /* disable when gallium grows int textures */ + if ((format == FMT_32_32_32_32 || format == FMT_16_16_16_16) && rtex->force_int_type) + ntype = 4; + color_info = S_0280A0_FORMAT(format) | S_0280A0_COMP_SWAP(swap) | S_0280A0_ARRAY_MODE(rtex->array_mode[level]) | S_0280A0_BLEND_CLAMP(1) | S_0280A0_NUMBER_TYPE(ntype); - if (desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS) - color_info |= S_0280A0_SOURCE_FORMAT(1); + + /* on R600 this can't be set if BLEND_CLAMP isn't set, + if BLEND_FLOAT32 is set of > 11 bits in a UNORM or SNORM */ + if (desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS && + desc->channel[i].size < 12) + color_info |= S_0280A0_SOURCE_FORMAT(V_0280A0_EXPORT_NORM); r600_pipe_state_add_reg(rstate, R_028040_CB_COLOR0_BASE + cb * 4, @@ -989,17 +809,14 @@ static void r600_db(struct r600_pipe_context *rctx, struct r600_pipe_state *rsta surf = (struct r600_surface *)state->zsbuf; rtex = (struct r600_resource_texture*)state->zsbuf->texture; - rtex->tiled = 1; - rtex->array_mode[level] = 2; - rtex->tile_type = 1; - rtex->depth = 1; + rbuffer = &rtex->resource; /* XXX quite sure for dx10+ hw don't need any offset hacks */ offset = r600_texture_get_offset((struct r600_resource_texture *)state->zsbuf->texture, level, state->zsbuf->u.tex.first_layer); - pitch = rtex->pitch_in_pixels[level] / 8 - 1; - slice = rtex->pitch_in_pixels[level] * surf->aligned_height / 64 - 1; + pitch = rtex->pitch_in_blocks[level] / 8 - 1; + slice = rtex->pitch_in_blocks[level] * surf->aligned_height / 64 - 1; format = r600_translate_dbformat(state->zsbuf->texture->format); r600_pipe_state_add_reg(rstate, R_02800C_DB_DEPTH_BASE, @@ -1115,51 +932,6 @@ static void r600_set_framebuffer_state(struct pipe_context *ctx, } } -static void r600_set_constant_buffer(struct pipe_context *ctx, uint shader, uint index, - struct pipe_resource *buffer) -{ - struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; - struct r600_resource *rbuffer = (struct r600_resource*)buffer; - uint32_t offset; - - /* Note that the state tracker can unbind constant buffers by - * passing NULL here. - */ - if (buffer == NULL) { - return; - } - - r600_upload_const_buffer(rctx, buffer, &offset); - - switch (shader) { - case PIPE_SHADER_VERTEX: - rctx->vs_const_buffer.nregs = 0; - r600_pipe_state_add_reg(&rctx->vs_const_buffer, - R_028180_ALU_CONST_BUFFER_SIZE_VS_0, - ALIGN_DIVUP(buffer->width0 >> 4, 16), - 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(&rctx->vs_const_buffer, - R_028980_ALU_CONST_CACHE_VS_0, - (r600_bo_offset(rbuffer->bo) + offset) >> 8, 0xFFFFFFFF, rbuffer->bo); - r600_context_pipe_state_set(&rctx->ctx, &rctx->vs_const_buffer); - break; - case PIPE_SHADER_FRAGMENT: - rctx->ps_const_buffer.nregs = 0; - r600_pipe_state_add_reg(&rctx->ps_const_buffer, - R_028140_ALU_CONST_BUFFER_SIZE_PS_0, - ALIGN_DIVUP(buffer->width0 >> 4, 16), - 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(&rctx->ps_const_buffer, - R_028940_ALU_CONST_CACHE_PS_0, - (r600_bo_offset(rbuffer->bo) + offset) >> 8, 0xFFFFFFFF, rbuffer->bo); - r600_context_pipe_state_set(&rctx->ctx, &rctx->ps_const_buffer); - break; - default: - R600_ERR("unsupported %d\n", shader); - return; - } -} - void r600_init_state_functions(struct r600_pipe_context *rctx) { rctx->context.create_blend_state = r600_create_blend_state; @@ -1199,6 +971,7 @@ void r600_init_state_functions(struct r600_pipe_context *rctx) rctx->context.set_vertex_sampler_views = r600_set_vs_sampler_view; rctx->context.set_viewport_state = r600_set_viewport_state; rctx->context.sampler_view_destroy = r600_sampler_view_destroy; + rctx->context.redefine_user_buffer = u_default_redefine_user_buffer; } void r600_init_config(struct r600_pipe_context *rctx) @@ -1489,3 +1262,25 @@ void *r600_create_db_flush_dsa(struct r600_pipe_context *rctx) S_028D0C_COPY_CENTROID(1), NULL); return rstate; } + +void r600_pipe_set_buffer_resource(struct r600_pipe_context *rctx, + struct r600_pipe_state *rstate, + struct r600_resource *rbuffer, + unsigned offset, unsigned stride) +{ + r600_pipe_state_add_reg(rstate, R_038000_RESOURCE0_WORD0, + offset, 0xFFFFFFFF, rbuffer->bo); + r600_pipe_state_add_reg(rstate, R_038004_RESOURCE0_WORD1, + rbuffer->bo_size - offset - 1, 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(rstate, R_038008_RESOURCE0_WORD2, + S_038008_STRIDE(stride), + 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(rstate, R_03800C_RESOURCE0_WORD3, + 0x00000000, 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(rstate, R_038010_RESOURCE0_WORD4, + 0x00000000, 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(rstate, R_038014_RESOURCE0_WORD5, + 0x00000000, 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(rstate, R_038018_RESOURCE0_WORD6, + 0xC0000000, 0xFFFFFFFF, NULL); +} diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c index 3603376f738..72707fbd8b8 100644 --- a/src/gallium/drivers/r600/r600_state_common.c +++ b/src/gallium/drivers/r600/r600_state_common.c @@ -27,7 +27,9 @@ #include <util/u_memory.h> #include <util/u_format.h> #include <pipebuffer/pb_buffer.h> +#include "pipe/p_shader_tokens.h" #include "r600_pipe.h" +#include "r600d.h" /* common state between evergreen and r600 */ void r600_bind_blend_state(struct pipe_context *ctx, void *state) @@ -119,24 +121,13 @@ void r600_bind_vertex_elements(struct pipe_context *ctx, void *state) struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; struct r600_vertex_element *v = (struct r600_vertex_element*)state; - /* delete previous translated vertex elements */ - if (rctx->tran.new_velems) { - r600_end_vertex_translate(rctx); - } - rctx->vertex_elements = v; if (v) { + u_vbuf_mgr_bind_vertex_elements(rctx->vbuf_mgr, state, + v->vmgr_elements); + rctx->states[v->rstate.id] = &v->rstate; r600_context_pipe_state_set(&rctx->ctx, &v->rstate); - if (rctx->family >= CHIP_CEDAR) { - evergreen_vertex_buffer_update(rctx); - } else { - r600_vertex_buffer_update(rctx); - } - } - - if (v) { -// rctx->vs_rebuild = TRUE; } } @@ -152,6 +143,7 @@ void r600_delete_vertex_element(struct pipe_context *ctx, void *state) rctx->vertex_elements = NULL; r600_bo_reference(rctx->radeon, &v->fetch_shader, NULL); + u_vbuf_mgr_destroy_vertex_elements(rctx->vbuf_mgr, v->vmgr_elements); FREE(state); } @@ -176,88 +168,44 @@ void r600_set_vertex_buffers(struct pipe_context *ctx, unsigned count, const struct pipe_vertex_buffer *buffers) { struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; - struct pipe_vertex_buffer *vbo; - unsigned max_index = (unsigned)-1; + int i; - if (rctx->family >= CHIP_CEDAR) { - for (int i = 0; i < rctx->nvertex_buffer; i++) { - pipe_resource_reference(&rctx->vertex_buffer[i].buffer, NULL); - evergreen_context_pipe_state_set_fs_resource(&rctx->ctx, NULL, i); + /* Zero states. */ + for (i = 0; i < count; i++) { + if (!buffers[i].buffer) { + if (rctx->family >= CHIP_CEDAR) { + evergreen_context_pipe_state_set_fs_resource(&rctx->ctx, NULL, i); + } else { + r600_context_pipe_state_set_fs_resource(&rctx->ctx, NULL, i); + } } - } else { - for (int i = 0; i < rctx->nvertex_buffer; i++) { - pipe_resource_reference(&rctx->vertex_buffer[i].buffer, NULL); + } + for (; i < rctx->vbuf_mgr->nr_real_vertex_buffers; i++) { + if (rctx->family >= CHIP_CEDAR) { + evergreen_context_pipe_state_set_fs_resource(&rctx->ctx, NULL, i); + } else { r600_context_pipe_state_set_fs_resource(&rctx->ctx, NULL, i); } } - memcpy(rctx->vertex_buffer, buffers, sizeof(struct pipe_vertex_buffer) * count); - - for (int i = 0; i < count; i++) { - vbo = (struct pipe_vertex_buffer*)&buffers[i]; - - rctx->vertex_buffer[i].buffer = NULL; - if (buffers[i].buffer == NULL) - continue; - if (r600_buffer_is_user_buffer(buffers[i].buffer)) - rctx->any_user_vbs = TRUE; - pipe_resource_reference(&rctx->vertex_buffer[i].buffer, buffers[i].buffer); - /* The stride of zero means we will be fetching only the first - * vertex, so don't care about max_index. */ - if (!vbo->stride) - continue; - - if (vbo->max_index == ~0) { - vbo->max_index = (vbo->buffer->width0 - vbo->buffer_offset) / vbo->stride; - } - max_index = MIN2(vbo->max_index, max_index); - } - rctx->nvertex_buffer = count; - rctx->vb_max_index = max_index; - if (rctx->family >= CHIP_CEDAR) { - evergreen_vertex_buffer_update(rctx); - } else { - r600_vertex_buffer_update(rctx); - } + u_vbuf_mgr_set_vertex_buffers(rctx->vbuf_mgr, count, buffers); } - -#define FORMAT_REPLACE(what, withwhat) \ - case PIPE_FORMAT_##what: *format = PIPE_FORMAT_##withwhat; break - void *r600_create_vertex_elements(struct pipe_context *ctx, unsigned count, const struct pipe_vertex_element *elements) { struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; struct r600_vertex_element *v = CALLOC_STRUCT(r600_vertex_element); - enum pipe_format *format; - int i; assert(count < 32); if (!v) return NULL; v->count = count; - memcpy(v->elements, elements, count * sizeof(struct pipe_vertex_element)); - - for (i = 0; i < count; i++) { - v->hw_format[i] = v->elements[i].src_format; - format = &v->hw_format[i]; - - switch (*format) { - FORMAT_REPLACE(R64_FLOAT, R32_FLOAT); - FORMAT_REPLACE(R64G64_FLOAT, R32G32_FLOAT); - FORMAT_REPLACE(R64G64B64_FLOAT, R32G32B32_FLOAT); - FORMAT_REPLACE(R64G64B64A64_FLOAT, R32G32B32A32_FLOAT); - default:; - } - v->incompatible_layout = - v->incompatible_layout || - v->elements[i].src_format != v->hw_format[i]; - - v->hw_format_size[i] = align(util_format_get_blocksize(v->hw_format[i]), 4); - } + v->vmgr_elements = + u_vbuf_mgr_create_vertex_elements(rctx->vbuf_mgr, count, + elements, v->elements); if (r600_vertex_elements_build_fetch_shader(rctx, v)) { FREE(v); @@ -327,3 +275,274 @@ void r600_delete_vs_shader(struct pipe_context *ctx, void *state) r600_pipe_shader_destroy(ctx, shader); free(shader); } + +/* FIXME optimize away spi update when it's not needed */ +void r600_spi_update(struct r600_pipe_context *rctx) +{ + struct r600_pipe_shader *shader = rctx->ps_shader; + struct r600_pipe_state rstate; + struct r600_shader *rshader = &shader->shader; + unsigned i, tmp; + + rstate.nregs = 0; + for (i = 0; i < rshader->ninput; i++) { + tmp = S_028644_SEMANTIC(r600_find_vs_semantic_index(&rctx->vs_shader->shader, rshader, i)); + + if (rshader->input[i].name == TGSI_SEMANTIC_COLOR || + rshader->input[i].name == TGSI_SEMANTIC_BCOLOR || + rshader->input[i].name == TGSI_SEMANTIC_POSITION) { + tmp |= S_028644_FLAT_SHADE(rctx->flatshade); + } + + if (rshader->input[i].name == TGSI_SEMANTIC_GENERIC && + rctx->sprite_coord_enable & (1 << rshader->input[i].sid)) { + tmp |= S_028644_PT_SPRITE_TEX(1); + } + + if (rctx->family < CHIP_CEDAR) { + if (rshader->input[i].centroid) + tmp |= S_028644_SEL_CENTROID(1); + + if (rshader->input[i].interpolate == TGSI_INTERPOLATE_LINEAR) + tmp |= S_028644_SEL_LINEAR(1); + } + + r600_pipe_state_add_reg(&rstate, R_028644_SPI_PS_INPUT_CNTL_0 + i * 4, tmp, 0xFFFFFFFF, NULL); + } + r600_context_pipe_state_set(&rctx->ctx, &rstate); +} + +void r600_set_constant_buffer(struct pipe_context *ctx, uint shader, uint index, + struct pipe_resource *buffer) +{ + struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; + struct r600_resource_buffer *rbuffer = r600_buffer(buffer); + struct r600_pipe_state *rstate; + uint32_t offset; + + /* Note that the state tracker can unbind constant buffers by + * passing NULL here. + */ + if (buffer == NULL) { + return; + } + + r600_upload_const_buffer(rctx, &rbuffer, &offset); + offset += r600_bo_offset(rbuffer->r.bo); + + switch (shader) { + case PIPE_SHADER_VERTEX: + rctx->vs_const_buffer.nregs = 0; + r600_pipe_state_add_reg(&rctx->vs_const_buffer, + R_028180_ALU_CONST_BUFFER_SIZE_VS_0, + ALIGN_DIVUP(buffer->width0 >> 4, 16), + 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(&rctx->vs_const_buffer, + R_028980_ALU_CONST_CACHE_VS_0, + offset >> 8, 0xFFFFFFFF, rbuffer->r.bo); + r600_context_pipe_state_set(&rctx->ctx, &rctx->vs_const_buffer); + + rstate = &rctx->vs_const_buffer_resource[index]; + rstate->id = R600_PIPE_STATE_RESOURCE; + rstate->nregs = 0; + if (rctx->family >= CHIP_CEDAR) { + evergreen_pipe_set_buffer_resource(rctx, rstate, &rbuffer->r, offset, 16); + evergreen_context_pipe_state_set_vs_resource(&rctx->ctx, rstate, index); + } else { + r600_pipe_set_buffer_resource(rctx, rstate, &rbuffer->r, offset, 16); + r600_context_pipe_state_set_vs_resource(&rctx->ctx, rstate, index); + } + break; + case PIPE_SHADER_FRAGMENT: + rctx->ps_const_buffer.nregs = 0; + r600_pipe_state_add_reg(&rctx->ps_const_buffer, + R_028140_ALU_CONST_BUFFER_SIZE_PS_0, + ALIGN_DIVUP(buffer->width0 >> 4, 16), + 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(&rctx->ps_const_buffer, + R_028940_ALU_CONST_CACHE_PS_0, + offset >> 8, 0xFFFFFFFF, rbuffer->r.bo); + r600_context_pipe_state_set(&rctx->ctx, &rctx->ps_const_buffer); + + rstate = &rctx->ps_const_buffer_resource[index]; + rstate->id = R600_PIPE_STATE_RESOURCE; + rstate->nregs = 0; + if (rctx->family >= CHIP_CEDAR) { + evergreen_pipe_set_buffer_resource(rctx, rstate, &rbuffer->r, offset, 16); + evergreen_context_pipe_state_set_ps_resource(&rctx->ctx, rstate, index); + } else { + r600_pipe_set_buffer_resource(rctx, rstate, &rbuffer->r, offset, 16); + r600_context_pipe_state_set_ps_resource(&rctx->ctx, rstate, index); + } + break; + default: + R600_ERR("unsupported %d\n", shader); + return; + } + + if (buffer != &rbuffer->r.b.b.b) + pipe_resource_reference((struct pipe_resource**)&rbuffer, NULL); +} + +static void r600_vertex_buffer_update(struct r600_pipe_context *rctx) +{ + struct r600_pipe_state *rstate; + struct r600_resource *rbuffer; + struct pipe_vertex_buffer *vertex_buffer; + unsigned i, count, offset; + + if (rctx->vertex_elements->vbuffer_need_offset) { + /* one resource per vertex elements */ + count = rctx->vertex_elements->count; + } else { + /* bind vertex buffer once */ + count = rctx->vbuf_mgr->nr_real_vertex_buffers; + } + + for (i = 0 ; i < count; i++) { + rstate = &rctx->fs_resource[i]; + rstate->id = R600_PIPE_STATE_RESOURCE; + rstate->nregs = 0; + + if (rctx->vertex_elements->vbuffer_need_offset) { + /* one resource per vertex elements */ + unsigned vbuffer_index; + vbuffer_index = rctx->vertex_elements->elements[i].vertex_buffer_index; + vertex_buffer = &rctx->vbuf_mgr->vertex_buffer[vbuffer_index]; + rbuffer = (struct r600_resource*)rctx->vbuf_mgr->real_vertex_buffer[vbuffer_index]; + offset = rctx->vertex_elements->vbuffer_offset[i]; + } else { + /* bind vertex buffer once */ + vertex_buffer = &rctx->vbuf_mgr->vertex_buffer[i]; + rbuffer = (struct r600_resource*)rctx->vbuf_mgr->real_vertex_buffer[i]; + offset = 0; + } + if (vertex_buffer == NULL || rbuffer == NULL) + continue; + offset += vertex_buffer->buffer_offset + r600_bo_offset(rbuffer->bo); + + if (rctx->family >= CHIP_CEDAR) { + evergreen_pipe_set_buffer_resource(rctx, rstate, rbuffer, offset, vertex_buffer->stride); + evergreen_context_pipe_state_set_fs_resource(&rctx->ctx, rstate, i); + } else { + r600_pipe_set_buffer_resource(rctx, rstate, rbuffer, offset, vertex_buffer->stride); + r600_context_pipe_state_set_fs_resource(&rctx->ctx, rstate, i); + } + } +} + +void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info) +{ + struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; + struct r600_resource *rbuffer; + u32 vgt_dma_index_type, vgt_draw_initiator, mask; + struct r600_draw rdraw; + struct r600_pipe_state vgt; + struct r600_drawl draw = {}; + unsigned prim; + + r600_flush_depth_textures(rctx); + u_vbuf_mgr_draw_begin(rctx->vbuf_mgr, info, NULL, NULL); + r600_vertex_buffer_update(rctx); + + draw.info = *info; + draw.ctx = ctx; + if (info->indexed && rctx->index_buffer.buffer) { + draw.info.start += rctx->index_buffer.offset / rctx->index_buffer.index_size; + pipe_resource_reference(&draw.index_buffer, rctx->index_buffer.buffer); + + r600_translate_index_buffer(rctx, &draw.index_buffer, + &rctx->index_buffer.index_size, + &draw.info.start, + info->count); + + draw.index_size = rctx->index_buffer.index_size; + draw.index_buffer_offset = draw.info.start * draw.index_size; + draw.info.start = 0; + + if (u_vbuf_resource(draw.index_buffer)->user_ptr) { + r600_upload_index_buffer(rctx, &draw); + } + } else { + draw.info.index_bias = info->start; + } + + switch (draw.index_size) { + case 2: + vgt_draw_initiator = 0; + vgt_dma_index_type = 0; + break; + case 4: + vgt_draw_initiator = 0; + vgt_dma_index_type = 1; + break; + case 0: + vgt_draw_initiator = 2; + vgt_dma_index_type = 0; + break; + default: + R600_ERR("unsupported index size %d\n", draw.index_size); + return; + } + if (r600_conv_pipe_prim(draw.info.mode, &prim)) + return; + if (unlikely(rctx->ps_shader == NULL)) { + R600_ERR("missing vertex shader\n"); + return; + } + if (unlikely(rctx->vs_shader == NULL)) { + R600_ERR("missing vertex shader\n"); + return; + } + /* there should be enough input */ + if (rctx->vertex_elements->count < rctx->vs_shader->shader.bc.nresource) { + R600_ERR("%d resources provided, expecting %d\n", + rctx->vertex_elements->count, rctx->vs_shader->shader.bc.nresource); + return; + } + + r600_spi_update(rctx); + + mask = 0; + for (int i = 0; i < rctx->framebuffer.nr_cbufs; i++) { + mask |= (0xF << (i * 4)); + } + + vgt.id = R600_PIPE_STATE_VGT; + vgt.nregs = 0; + r600_pipe_state_add_reg(&vgt, R_008958_VGT_PRIMITIVE_TYPE, prim, 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(&vgt, R_028408_VGT_INDX_OFFSET, draw.info.index_bias, 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(&vgt, R_028400_VGT_MAX_VTX_INDX, draw.info.max_index, 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(&vgt, R_028404_VGT_MIN_VTX_INDX, draw.info.min_index, 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(&vgt, R_028238_CB_TARGET_MASK, rctx->cb_target_mask & mask, 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(&vgt, R_03CFF0_SQ_VTX_BASE_VTX_LOC, 0, 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(&vgt, R_03CFF4_SQ_VTX_START_INST_LOC, 0, 0xFFFFFFFF, NULL); + r600_context_pipe_state_set(&rctx->ctx, &vgt); + + rdraw.vgt_num_indices = draw.info.count; + rdraw.vgt_num_instances = 1; + rdraw.vgt_index_type = vgt_dma_index_type; + rdraw.vgt_draw_initiator = vgt_draw_initiator; + rdraw.indices = NULL; + if (draw.index_buffer) { + rbuffer = (struct r600_resource*)draw.index_buffer; + rdraw.indices = rbuffer->bo; + rdraw.indices_bo_offset = draw.index_buffer_offset; + } + + if (rctx->family >= CHIP_CEDAR) { + evergreen_context_draw(&rctx->ctx, &rdraw); + } else { + r600_context_draw(&rctx->ctx, &rdraw); + } + + if (rctx->framebuffer.zsbuf) + { + struct pipe_resource *tex = rctx->framebuffer.zsbuf->texture; + ((struct r600_resource_texture *)tex)->dirty_db = TRUE; + } + + pipe_resource_reference(&draw.index_buffer, NULL); + + u_vbuf_mgr_draw_end(rctx->vbuf_mgr); +} diff --git a/src/gallium/drivers/r600/r600_state_inlines.h b/src/gallium/drivers/r600/r600_state_inlines.h index a0ec493fc85..3dd54f45202 100644 --- a/src/gallium/drivers/r600/r600_state_inlines.h +++ b/src/gallium/drivers/r600/r600_state_inlines.h @@ -253,9 +253,13 @@ static inline unsigned r600_tex_dim(unsigned dim) default: case PIPE_TEXTURE_1D: return V_038000_SQ_TEX_DIM_1D; + case PIPE_TEXTURE_1D_ARRAY: + return V_038000_SQ_TEX_DIM_1D_ARRAY; case PIPE_TEXTURE_2D: case PIPE_TEXTURE_RECT: return V_038000_SQ_TEX_DIM_2D; + case PIPE_TEXTURE_2D_ARRAY: + return V_038000_SQ_TEX_DIM_2D_ARRAY; case PIPE_TEXTURE_3D: return V_038000_SQ_TEX_DIM_3D; case PIPE_TEXTURE_CUBE: @@ -285,10 +289,14 @@ static inline uint32_t r600_translate_colorswap(enum pipe_format format) return V_0280A0_SWAP_ALT_REV; case PIPE_FORMAT_I8_UNORM: case PIPE_FORMAT_L8_UNORM: + case PIPE_FORMAT_L8_SRGB: case PIPE_FORMAT_R8_UNORM: case PIPE_FORMAT_R8_SNORM: return V_0280A0_SWAP_STD; + case PIPE_FORMAT_L4A4_UNORM: + return V_0280A0_SWAP_ALT; + /* 16-bit buffers. */ case PIPE_FORMAT_B5G6R5_UNORM: return V_0280A0_SWAP_STD_REV; @@ -305,6 +313,7 @@ static inline uint32_t r600_translate_colorswap(enum pipe_format format) return V_0280A0_SWAP_STD; case PIPE_FORMAT_L8A8_UNORM: + case PIPE_FORMAT_L8A8_SRGB: return V_0280A0_SWAP_ALT; case PIPE_FORMAT_R8G8_UNORM: return V_0280A0_SWAP_STD; @@ -328,6 +337,7 @@ static inline uint32_t r600_translate_colorswap(enum pipe_format format) case PIPE_FORMAT_X8R8G8B8_UNORM: return V_0280A0_SWAP_ALT_REV; case PIPE_FORMAT_R8G8B8A8_SNORM: + case PIPE_FORMAT_R8G8B8A8_UNORM: case PIPE_FORMAT_R8G8B8X8_UNORM: return V_0280A0_SWAP_STD; @@ -346,9 +356,11 @@ static inline uint32_t r600_translate_colorswap(enum pipe_format format) case PIPE_FORMAT_R10G10B10A2_UNORM: case PIPE_FORMAT_R10G10B10X2_SNORM: - case PIPE_FORMAT_B10G10R10A2_UNORM: case PIPE_FORMAT_R10SG10SB10SA2U_NORM: - return V_0280A0_SWAP_STD_REV; + return V_0280A0_SWAP_STD; + + case PIPE_FORMAT_B10G10R10A2_UNORM: + return V_0280A0_SWAP_ALT; case PIPE_FORMAT_R16G16_UNORM: return V_0280A0_SWAP_STD; @@ -356,14 +368,13 @@ static inline uint32_t r600_translate_colorswap(enum pipe_format format) /* 64-bit buffers. */ 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; /* 128-bit buffers. */ - //case PIPE_FORMAT_R32G32B32A32_FLOAT: - // return FMT_32_32_32_32_FLOAT; - return 0; + case PIPE_FORMAT_R32G32B32A32_FLOAT: + case PIPE_FORMAT_R32G32B32A32_SNORM: + case PIPE_FORMAT_R32G32B32A32_UNORM: + return V_0280A0_SWAP_STD; default: R600_ERR("unsupported colorswap format %d\n", format); return ~0; @@ -374,10 +385,14 @@ static inline uint32_t r600_translate_colorswap(enum pipe_format format) static INLINE uint32_t r600_translate_colorformat(enum pipe_format format) { switch (format) { + case PIPE_FORMAT_L4A4_UNORM: + return V_0280A0_COLOR_4_4; + /* 8-bit buffers. */ case PIPE_FORMAT_A8_UNORM: case PIPE_FORMAT_I8_UNORM: case PIPE_FORMAT_L8_UNORM: + case PIPE_FORMAT_L8_SRGB: case PIPE_FORMAT_R8_UNORM: case PIPE_FORMAT_R8_SNORM: return V_0280A0_COLOR_8; @@ -398,6 +413,7 @@ static INLINE uint32_t r600_translate_colorformat(enum pipe_format format) return V_0280A0_COLOR_16; case PIPE_FORMAT_L8A8_UNORM: + case PIPE_FORMAT_L8A8_SRGB: case PIPE_FORMAT_R8G8_UNORM: return V_0280A0_COLOR_8_8; @@ -425,7 +441,7 @@ static INLINE uint32_t r600_translate_colorformat(enum pipe_format format) case PIPE_FORMAT_R10G10B10X2_SNORM: case PIPE_FORMAT_B10G10R10A2_UNORM: case PIPE_FORMAT_R10SG10SB10SA2U_NORM: - return V_0280A0_COLOR_10_10_10_2; + return V_0280A0_COLOR_2_10_10_10; case PIPE_FORMAT_Z24X8_UNORM: case PIPE_FORMAT_Z24_UNORM_S8_USCALED: @@ -467,10 +483,13 @@ static INLINE uint32_t r600_translate_colorformat(enum pipe_format format) return V_0280A0_COLOR_32_32; /* 128-bit buffers. */ - //case PIPE_FORMAT_R32G32B32_FLOAT: - // return V_0280A0_COLOR_32_32_32_FLOAT; - //case PIPE_FORMAT_R32G32B32A32_FLOAT: - // return V_0280A0_COLOR_32_32_32_32_FLOAT; + case PIPE_FORMAT_R32G32B32_FLOAT: + return V_0280A0_COLOR_32_32_32_FLOAT; + case PIPE_FORMAT_R32G32B32A32_FLOAT: + return V_0280A0_COLOR_32_32_32_32_FLOAT; + case PIPE_FORMAT_R32G32B32A32_SNORM: + case PIPE_FORMAT_R32G32B32A32_UNORM: + return V_0280A0_COLOR_32_32_32_32; /* YUV buffers. */ case PIPE_FORMAT_UYVY: @@ -497,9 +516,37 @@ static INLINE boolean r600_is_zs_format_supported(enum pipe_format format) return r600_translate_dbformat(format) != ~0; } -static INLINE boolean r600_is_vertex_format_supported(enum pipe_format format) +static INLINE boolean r600_is_vertex_format_supported(enum pipe_format format, + enum radeon_family family) { - return r600_translate_colorformat(format) != ~0; + unsigned i; + const struct util_format_description *desc = util_format_description(format); + if (!desc) + return FALSE; + + /* Find the first non-VOID channel. */ + for (i = 0; i < 4; i++) { + if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID) { + break; + } + } + if (i == 4) + return FALSE; + + /* No fixed, no double. */ + if (desc->layout != UTIL_FORMAT_LAYOUT_PLAIN || + desc->channel[i].type == UTIL_FORMAT_TYPE_FIXED || + (desc->channel[i].size == 64 && + desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT)) + return FALSE; + + /* No scaled/norm formats with 32 bits per channel. */ + if (desc->channel[i].size == 32 && + (desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED || + desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED)) + return FALSE; + + return TRUE; } #endif diff --git a/src/gallium/drivers/r600/r600_texture.c b/src/gallium/drivers/r600/r600_texture.c index 1f4f453c091..03af367401d 100644 --- a/src/gallium/drivers/r600/r600_texture.c +++ b/src/gallium/drivers/r600/r600_texture.c @@ -27,6 +27,7 @@ #include <errno.h> #include <pipe/p_screen.h> #include <util/u_format.h> +#include <util/u_format_s3tc.h> #include <util/u_math.h> #include <util/u_inlines.h> #include <util/u_memory.h> @@ -38,8 +39,6 @@ #include "r600d.h" #include "r600_formats.h" -extern struct u_resource_vtbl r600_texture_vtbl; - /* Copy from a full GPU texture to a transfer's staging one. */ static void r600_copy_to_staging_texture(struct pipe_context *ctx, struct r600_transfer *rtransfer) { @@ -77,17 +76,15 @@ unsigned r600_texture_get_offset(struct r600_resource_texture *rtex, { unsigned offset = rtex->offset[level]; - switch (rtex->resource.base.b.target) { + switch (rtex->resource.b.b.b.target) { case PIPE_TEXTURE_3D: case PIPE_TEXTURE_CUBE: - return offset + layer * rtex->layer_size[level]; default: - assert(layer == 0); - return offset; + return offset + layer * rtex->layer_size[level]; } } -static unsigned r600_get_pixel_alignment(struct pipe_screen *screen, +static unsigned r600_get_block_alignment(struct pipe_screen *screen, enum pipe_format format, unsigned array_mode) { @@ -105,6 +102,9 @@ static unsigned r600_get_pixel_alignment(struct pipe_screen *screen, (((rscreen->tiling_info->group_bytes / 8 / pixsize)) * rscreen->tiling_info->num_banks)) * 8; break; + case V_038000_ARRAY_LINEAR_ALIGNED: + p_align = MAX2(64, rscreen->tiling_info->group_bytes / pixsize); + break; case V_038000_ARRAY_LINEAR_GENERAL: default: p_align = rscreen->tiling_info->group_bytes / pixsize; @@ -124,8 +124,10 @@ static unsigned r600_get_height_alignment(struct pipe_screen *screen, h_align = rscreen->tiling_info->num_channels * 8; break; case V_038000_ARRAY_1D_TILED_THIN1: + case V_038000_ARRAY_LINEAR_ALIGNED: h_align = 8; break; + case V_038000_ARRAY_LINEAR_GENERAL: default: h_align = 1; break; @@ -139,7 +141,7 @@ static unsigned r600_get_base_alignment(struct pipe_screen *screen, { struct r600_screen* rscreen = (struct r600_screen *)screen; unsigned pixsize = util_format_get_blocksize(format); - int p_align = r600_get_pixel_alignment(screen, format, array_mode); + int p_align = r600_get_block_alignment(screen, format, array_mode); int h_align = r600_get_height_alignment(screen, array_mode); int b_align; @@ -149,6 +151,8 @@ static unsigned r600_get_base_alignment(struct pipe_screen *screen, p_align * pixsize * h_align); break; case V_038000_ARRAY_1D_TILED_THIN1: + case V_038000_ARRAY_LINEAR_ALIGNED: + case V_038000_ARRAY_LINEAR_GENERAL: default: b_align = rscreen->tiling_info->group_bytes; break; @@ -165,55 +169,46 @@ static unsigned mip_minify(unsigned size, unsigned level) return val; } -static unsigned r600_texture_get_stride(struct pipe_screen *screen, - struct r600_resource_texture *rtex, - unsigned level) +static unsigned r600_texture_get_nblocksx(struct pipe_screen *screen, + struct r600_resource_texture *rtex, + unsigned level) { - struct pipe_resource *ptex = &rtex->resource.base.b; - unsigned width, stride, tile_width; + struct pipe_resource *ptex = &rtex->resource.b.b.b; + unsigned nblocksx, block_align, width; + unsigned blocksize = util_format_get_blocksize(ptex->format); if (rtex->pitch_override) - return rtex->pitch_override; + return rtex->pitch_override / blocksize; width = mip_minify(ptex->width0, level); - if (util_format_is_plain(ptex->format)) { - tile_width = r600_get_pixel_alignment(screen, ptex->format, - rtex->array_mode[level]); - width = align(width, tile_width); - } - stride = util_format_get_stride(ptex->format, width); + nblocksx = util_format_get_nblocksx(ptex->format, width); - return stride; + block_align = r600_get_block_alignment(screen, ptex->format, + rtex->array_mode[level]); + nblocksx = align(nblocksx, block_align); + return nblocksx; } static unsigned r600_texture_get_nblocksy(struct pipe_screen *screen, struct r600_resource_texture *rtex, unsigned level) { - struct pipe_resource *ptex = &rtex->resource.base.b; + struct pipe_resource *ptex = &rtex->resource.b.b.b; unsigned height, tile_height; height = mip_minify(ptex->height0, level); - if (util_format_is_plain(ptex->format)) { - tile_height = r600_get_height_alignment(screen, - rtex->array_mode[level]); - height = align(height, tile_height); - } - return util_format_get_nblocksy(ptex->format, height); -} - -/* Get a width in pixels from a stride in bytes. */ -static unsigned pitch_to_width(enum pipe_format format, unsigned pitch_in_bytes) -{ - return (pitch_in_bytes / util_format_get_blocksize(format)) * - util_format_get_blockwidth(format); + height = util_format_get_nblocksy(ptex->format, height); + tile_height = r600_get_height_alignment(screen, + rtex->array_mode[level]); + height = align(height, tile_height); + return height; } static void r600_texture_set_array_mode(struct pipe_screen *screen, struct r600_resource_texture *rtex, unsigned level, unsigned array_mode) { - struct pipe_resource *ptex = &rtex->resource.base.b; + struct pipe_resource *ptex = &rtex->resource.b.b.b; switch (array_mode) { case V_0280A0_ARRAY_LINEAR_GENERAL: @@ -227,7 +222,7 @@ static void r600_texture_set_array_mode(struct pipe_screen *screen, unsigned w, h, tile_height, tile_width; tile_height = r600_get_height_alignment(screen, array_mode); - tile_width = r600_get_pixel_alignment(screen, ptex->format, array_mode); + tile_width = r600_get_block_alignment(screen, ptex->format, array_mode); w = mip_minify(ptex->width0, level); h = mip_minify(ptex->height0, level); @@ -244,40 +239,128 @@ static void r600_setup_miptree(struct pipe_screen *screen, struct r600_resource_texture *rtex, unsigned array_mode) { - struct pipe_resource *ptex = &rtex->resource.base.b; + struct pipe_resource *ptex = &rtex->resource.b.b.b; struct radeon *radeon = (struct radeon *)screen->winsys; enum chip_class chipc = r600_get_family_class(radeon); - unsigned pitch, size, layer_size, i, offset; - unsigned nblocksy; + unsigned size, layer_size, i, offset; + unsigned nblocksx, nblocksy; for (i = 0, offset = 0; i <= ptex->last_level; i++) { + unsigned blocksize = util_format_get_blocksize(ptex->format); + r600_texture_set_array_mode(screen, rtex, i, array_mode); - pitch = r600_texture_get_stride(screen, rtex, i); + nblocksx = r600_texture_get_nblocksx(screen, rtex, i); nblocksy = r600_texture_get_nblocksy(screen, rtex, i); - layer_size = pitch * nblocksy; - + layer_size = nblocksx * nblocksy * blocksize; if (ptex->target == PIPE_TEXTURE_CUBE) { if (chipc >= R700) size = layer_size * 8; else size = layer_size * 6; } - else + else if (ptex->target == PIPE_TEXTURE_3D) size = layer_size * u_minify(ptex->depth0, i); + else + size = layer_size * ptex->array_size; + /* align base image and start of miptree */ if ((i == 0) || (i == 1)) offset = align(offset, r600_get_base_alignment(screen, ptex->format, array_mode)); rtex->offset[i] = offset; rtex->layer_size[i] = layer_size; - rtex->pitch_in_bytes[i] = pitch; - rtex->pitch_in_pixels[i] = pitch_to_width(ptex->format, pitch); + rtex->pitch_in_blocks[i] = nblocksx; /* CB talks in elements */ + rtex->pitch_in_bytes[i] = nblocksx * blocksize; + offset += size; } rtex->size = offset; } +/* Figure out whether u_blitter will fallback to a transfer operation. + * If so, don't use a staging resource. + */ +static boolean permit_hardware_blit(struct pipe_screen *screen, + const struct pipe_resource *res) +{ + unsigned bind; + + if (util_format_is_depth_or_stencil(res->format)) + bind = PIPE_BIND_DEPTH_STENCIL; + else + bind = PIPE_BIND_RENDER_TARGET; + + /* hackaround for S3TC */ + if (util_format_is_s3tc(res->format)) + return TRUE; + + if (!screen->is_format_supported(screen, + res->format, + res->target, + res->nr_samples, + bind, 0)) + return FALSE; + + if (!screen->is_format_supported(screen, + res->format, + res->target, + res->nr_samples, + PIPE_BIND_SAMPLER_VIEW, 0)) + return FALSE; + + return TRUE; +} + +static boolean r600_texture_get_handle(struct pipe_screen* screen, + struct pipe_resource *ptex, + struct winsys_handle *whandle) +{ + struct r600_resource_texture *rtex = (struct r600_resource_texture*)ptex; + struct r600_resource *resource = &rtex->resource; + struct radeon *radeon = (struct radeon *)screen->winsys; + + return r600_bo_get_winsys_handle(radeon, resource->bo, + rtex->pitch_in_bytes[0], whandle); +} + +static void r600_texture_destroy(struct pipe_screen *screen, + struct pipe_resource *ptex) +{ + struct r600_resource_texture *rtex = (struct r600_resource_texture*)ptex; + struct r600_resource *resource = &rtex->resource; + struct radeon *radeon = (struct radeon *)screen->winsys; + + if (rtex->flushed_depth_texture) + pipe_resource_reference((struct pipe_resource **)&rtex->flushed_depth_texture, NULL); + + if (resource->bo) { + r600_bo_reference(radeon, &resource->bo, NULL); + } + FREE(rtex); +} + +static unsigned int r600_texture_is_referenced(struct pipe_context *context, + struct pipe_resource *texture, + unsigned level, int layer) +{ + /* FIXME */ + return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; +} + +static const struct u_resource_vtbl r600_texture_vtbl = +{ + r600_texture_get_handle, /* get_handle */ + r600_texture_destroy, /* resource_destroy */ + r600_texture_is_referenced, /* is_resource_referenced */ + r600_texture_get_transfer, /* get_transfer */ + r600_texture_transfer_destroy, /* transfer_destroy */ + r600_texture_transfer_map, /* transfer_map */ + u_default_transfer_flush_region,/* transfer_flush_region */ + r600_texture_transfer_unmap, /* transfer_unmap */ + u_default_transfer_inline_write /* transfer_inline_write */ +}; + static struct r600_resource_texture * r600_texture_create_object(struct pipe_screen *screen, const struct pipe_resource *base, @@ -295,21 +378,22 @@ r600_texture_create_object(struct pipe_screen *screen, return NULL; resource = &rtex->resource; - resource->base.b = *base; - resource->base.vtbl = &r600_texture_vtbl; - pipe_reference_init(&resource->base.b.reference, 1); - resource->base.b.screen = screen; + resource->b.b.b = *base; + resource->b.b.vtbl = &r600_texture_vtbl; + pipe_reference_init(&resource->b.b.b.reference, 1); + resource->b.b.b.screen = screen; resource->bo = bo; rtex->pitch_override = pitch_in_bytes_override; + /* only mark depth textures the HW can hit as depth textures */ + if (util_format_is_depth_or_stencil(base->format) && permit_hardware_blit(screen, base)) + rtex->depth = 1; - if (array_mode) - rtex->tiled = 1; r600_setup_miptree(screen, rtex, array_mode); resource->size = rtex->size; if (!resource->bo) { - struct pipe_resource *ptex = &rtex->resource.base.b; + struct pipe_resource *ptex = &rtex->resource.b.b.b; int base_align = r600_get_base_alignment(screen, ptex->format, array_mode); resource->bo = r600_bo(radeon, rtex->size, base_align, base->bind, base->usage); @@ -321,48 +405,6 @@ r600_texture_create_object(struct pipe_screen *screen, return rtex; } -/* Figure out whether u_blitter will fallback to a transfer operation. - * If so, don't use a staging resource. - */ -static boolean permit_hardware_blit(struct pipe_screen *screen, - const struct pipe_resource *res) -{ - unsigned bind; - - if (util_format_is_depth_or_stencil(res->format)) - bind = PIPE_BIND_DEPTH_STENCIL; - else - bind = PIPE_BIND_RENDER_TARGET; - - /* See r600_resource_copy_region: there is something wrong - * with depth resource copies at the moment so avoid them for - * now. - */ - if (util_format_get_component_bits(res->format, - UTIL_FORMAT_COLORSPACE_ZS, - 0) != 0) - return FALSE; - - if (!screen->is_format_supported(screen, - res->format, - res->target, - res->nr_samples, - bind, 0)) - return FALSE; - - if (!screen->is_format_supported(screen, - res->format, - res->target, - res->nr_samples, - PIPE_BIND_SAMPLER_VIEW, 0)) - return FALSE; - - if (res->usage == PIPE_USAGE_STREAM) - return FALSE; - - return TRUE; -} - struct pipe_resource *r600_texture_create(struct pipe_screen *screen, const struct pipe_resource *templ) { @@ -381,46 +423,21 @@ struct pipe_resource *r600_texture_create(struct pipe_screen *screen, } } + if (!(templ->flags & R600_RESOURCE_FLAG_TRANSFER) && + util_format_is_s3tc(templ->format)) + array_mode = V_038000_ARRAY_1D_TILED_THIN1; + return (struct pipe_resource *)r600_texture_create_object(screen, templ, array_mode, 0, 0, NULL); } -static void r600_texture_destroy(struct pipe_screen *screen, - struct pipe_resource *ptex) -{ - struct r600_resource_texture *rtex = (struct r600_resource_texture*)ptex; - struct r600_resource *resource = &rtex->resource; - struct radeon *radeon = (struct radeon *)screen->winsys; - - if (rtex->flushed_depth_texture) - pipe_resource_reference((struct pipe_resource **)&rtex->flushed_depth_texture, NULL); - - if (resource->bo) { - r600_bo_reference(radeon, &resource->bo, NULL); - } - FREE(rtex); -} - -static boolean r600_texture_get_handle(struct pipe_screen* screen, - struct pipe_resource *ptex, - struct winsys_handle *whandle) -{ - struct r600_resource_texture *rtex = (struct r600_resource_texture*)ptex; - struct r600_resource *resource = &rtex->resource; - struct radeon *radeon = (struct radeon *)screen->winsys; - - return r600_bo_get_winsys_handle(radeon, resource->bo, - rtex->pitch_in_bytes[0], whandle); -} - static struct pipe_surface *r600_create_surface(struct pipe_context *pipe, struct pipe_resource *texture, const struct pipe_surface *surf_tmpl) { struct r600_resource_texture *rtex = (struct r600_resource_texture*)texture; struct r600_surface *surface = CALLOC_STRUCT(r600_surface); - unsigned tile_height; unsigned level = surf_tmpl->u.tex.level; assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer); @@ -440,8 +457,8 @@ static struct pipe_surface *r600_create_surface(struct pipe_context *pipe, surface->base.u.tex.last_layer = surf_tmpl->u.tex.last_layer; surface->base.u.tex.level = level; - tile_height = r600_get_height_alignment(pipe->screen, rtex->array_mode[level]); - surface->aligned_height = align(surface->base.height, tile_height); + surface->aligned_height = r600_texture_get_nblocksy(pipe->screen, + rtex, level); return &surface->base; } @@ -477,16 +494,8 @@ struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen, bo); } -static unsigned int r600_texture_is_referenced(struct pipe_context *context, - struct pipe_resource *texture, - unsigned level, int layer) -{ - /* FIXME */ - return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; -} - int r600_texture_depth_flush(struct pipe_context *ctx, - struct pipe_resource *texture) + struct pipe_resource *texture, boolean just_create) { struct r600_resource_texture *rtex = (struct r600_resource_texture*)texture; struct pipe_resource resource; @@ -499,7 +508,8 @@ int r600_texture_depth_flush(struct pipe_context *ctx, resource.width0 = texture->width0; resource.height0 = texture->height0; resource.depth0 = 1; - resource.last_level = 0; + resource.array_size = 1; + resource.last_level = texture->last_level; resource.nr_samples = 0; resource.usage = PIPE_USAGE_DYNAMIC; resource.bind = 0; @@ -513,7 +523,11 @@ int r600_texture_depth_flush(struct pipe_context *ctx, return -ENOMEM; } + ((struct r600_resource_texture *)rtex->flushed_depth_texture)->is_flushing_texture = TRUE; out: + if (just_create) + return 0; + /* XXX: only do this if the depth texture has actually changed: */ r600_blit_uncompress_depth(ctx, rtex); @@ -546,7 +560,7 @@ struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx, * the CPU is much happier reading out of cached system memory * than uncached VRAM. */ - if (rtex->tiled) + if (R600_TEX_IS_TILED(rtex, level)) use_staging_texture = TRUE; if ((usage & PIPE_TRANSFER_READ) && u_box_volume(box) > 1024) @@ -579,13 +593,16 @@ struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx, */ /* XXX: when discard is true, no need to read back from depth texture */ - r = r600_texture_depth_flush(ctx, texture); + r = r600_texture_depth_flush(ctx, texture, FALSE); if (r < 0) { R600_ERR("failed to create temporary texture to hold untiled copy\n"); pipe_resource_reference(&trans->transfer.resource, NULL); FREE(trans); return NULL; } + trans->transfer.stride = rtex->flushed_depth_texture->pitch_in_bytes[level]; + trans->offset = r600_texture_get_offset(rtex->flushed_depth_texture, level, box->z); + return &trans->transfer; } else if (use_staging_texture) { resource.target = PIPE_TEXTURE_2D; resource.format = texture->format; @@ -627,6 +644,7 @@ struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx, return &trans->transfer; } trans->transfer.stride = rtex->pitch_in_bytes[level]; + trans->transfer.layer_stride = rtex->layer_size[level]; trans->offset = r600_texture_get_offset(rtex, level, box->z); return &trans->transfer; } @@ -635,7 +653,8 @@ void r600_texture_transfer_destroy(struct pipe_context *ctx, struct pipe_transfer *transfer) { struct r600_transfer *rtransfer = (struct r600_transfer*)transfer; - struct r600_resource_texture *rtex = (struct r600_resource_texture*)transfer->resource; + struct pipe_resource *texture = transfer->resource; + struct r600_resource_texture *rtex = (struct r600_resource_texture*)texture; if (rtransfer->staging_texture) { if (transfer->usage & PIPE_TRANSFER_WRITE) { @@ -643,9 +662,12 @@ void r600_texture_transfer_destroy(struct pipe_context *ctx, } pipe_resource_reference(&rtransfer->staging_texture, NULL); } - if (rtex->flushed_depth_texture) { - pipe_resource_reference((struct pipe_resource **)&rtex->flushed_depth_texture, NULL); + + if (rtex->depth && !rtex->is_flushing_texture) { + if ((transfer->usage & PIPE_TRANSFER_WRITE) && rtex->flushed_depth_texture) + r600_blit_push_depth(ctx, rtex); } + pipe_resource_reference(&transfer->resource, NULL); FREE(transfer); } @@ -727,19 +749,6 @@ void r600_texture_transfer_unmap(struct pipe_context *ctx, r600_bo_unmap(radeon, bo); } -struct u_resource_vtbl r600_texture_vtbl = -{ - r600_texture_get_handle, /* get_handle */ - r600_texture_destroy, /* resource_destroy */ - r600_texture_is_referenced, /* is_resource_referenced */ - r600_texture_get_transfer, /* get_transfer */ - r600_texture_transfer_destroy, /* transfer_destroy */ - r600_texture_transfer_map, /* transfer_map */ - u_default_transfer_flush_region,/* transfer_flush_region */ - r600_texture_transfer_unmap, /* transfer_unmap */ - u_default_transfer_inline_write /* transfer_inline_write */ -}; - void r600_init_surface_functions(struct r600_pipe_context *r600) { r600->context.create_surface = r600_create_surface; @@ -802,6 +811,8 @@ uint32_t r600_translate_texformat(enum pipe_format format, uint32_t result = 0, word4 = 0, yuv_format = 0; const struct util_format_description *desc; boolean uniform = TRUE; + static int r600_enable_s3tc = -1; + int i; const uint32_t sign_bit[4] = { S_038010_FORMAT_COMP_X(V_038010_SQ_FORMAT_COMP_SIGNED), @@ -853,34 +864,55 @@ uint32_t r600_translate_texformat(enum pipe_format format, case UTIL_FORMAT_COLORSPACE_SRGB: word4 |= S_038010_FORCE_DEGAMMA(1); - if (format == PIPE_FORMAT_L8A8_SRGB || format == PIPE_FORMAT_L8_SRGB) - goto out_unknown; /* fails for some reason - TODO */ break; default: break; } - /* S3TC formats. TODO */ - if (desc->layout == UTIL_FORMAT_LAYOUT_S3TC) { - static int r600_enable_s3tc = -1; + if (r600_enable_s3tc == -1) + r600_enable_s3tc = debug_get_bool_option("R600_ENABLE_S3TC", FALSE); + + if (desc->layout == UTIL_FORMAT_LAYOUT_RGTC) { + if (!r600_enable_s3tc) + goto out_unknown; + + switch (format) { + case PIPE_FORMAT_RGTC1_UNORM: + case PIPE_FORMAT_RGTC1_SNORM: + result = FMT_BC4; + goto out_word4; + case PIPE_FORMAT_RGTC2_UNORM: + case PIPE_FORMAT_RGTC2_SNORM: + result = FMT_BC5; + goto out_word4; + default: + goto out_unknown; + } + } - if (r600_enable_s3tc == -1) - r600_enable_s3tc = - debug_get_bool_option("R600_ENABLE_S3TC", FALSE); + if (desc->layout == UTIL_FORMAT_LAYOUT_S3TC) { if (!r600_enable_s3tc) goto out_unknown; + if (!util_format_s3tc_enabled) { + goto out_unknown; + } + switch (format) { case PIPE_FORMAT_DXT1_RGB: case PIPE_FORMAT_DXT1_RGBA: + case PIPE_FORMAT_DXT1_SRGB: + case PIPE_FORMAT_DXT1_SRGBA: result = FMT_BC1; goto out_word4; case PIPE_FORMAT_DXT3_RGBA: + case PIPE_FORMAT_DXT3_SRGBA: result = FMT_BC2; goto out_word4; case PIPE_FORMAT_DXT5_RGBA: + case PIPE_FORMAT_DXT5_SRGBA: result = FMT_BC3; goto out_word4; default: @@ -897,8 +929,6 @@ uint32_t r600_translate_texformat(enum pipe_format format, /* R8G8Bx_SNORM - TODO CxV8U8 */ - /* RGTC - TODO */ - /* See whether the components are of the same size. */ for (i = 1; i < desc->nr_channels; i++) { uniform = uniform && desc->channel[0].size == desc->channel[i].size; @@ -927,7 +957,7 @@ uint32_t r600_translate_texformat(enum pipe_format format, desc->channel[1].size == 10 && desc->channel[2].size == 10 && desc->channel[3].size == 2) { - result = FMT_10_10_10_2; + result = FMT_2_10_10_10; goto out_word4; } goto out_unknown; @@ -990,6 +1020,19 @@ uint32_t r600_translate_texformat(enum pipe_format format, result = FMT_16_16_16_16; goto out_word4; } + goto out_unknown; + case 32: + switch (desc->nr_channels) { + case 1: + result = FMT_32; + goto out_word4; + case 2: + result = FMT_32_32; + goto out_word4; + case 4: + result = FMT_32_32_32_32; + goto out_word4; + } } goto out_unknown; diff --git a/src/gallium/drivers/r600/r600_translate.c b/src/gallium/drivers/r600/r600_translate.c index f80fa7af941..7482d15e12f 100644 --- a/src/gallium/drivers/r600/r600_translate.c +++ b/src/gallium/drivers/r600/r600_translate.c @@ -22,178 +22,34 @@ * * Authors: Dave Airlie <[email protected]> */ -#include "translate/translate_cache.h" -#include "translate/translate.h" -#include <pipebuffer/pb_buffer.h> + #include <util/u_index_modify.h> +#include "util/u_inlines.h" +#include "util/u_upload_mgr.h" #include "r600_pipe.h" -void r600_begin_vertex_translate(struct r600_pipe_context *rctx) -{ - struct pipe_context *pipe = &rctx->context; - struct translate_key key = {0}; - struct translate_element *te; - unsigned tr_elem_index[PIPE_MAX_ATTRIBS] = {0}; - struct translate *tr; - struct r600_vertex_element *ve = rctx->vertex_elements; - boolean vb_translated[PIPE_MAX_ATTRIBS] = {0}; - void *vb_map[PIPE_MAX_ATTRIBS] = {0}, *out_map; - struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS] = {0}, *out_transfer; - struct pipe_resource *out_buffer; - unsigned i, num_verts; - struct pipe_vertex_element new_velems[PIPE_MAX_ATTRIBS]; - void *tmp; - - /* Initialize the translate key, i.e. the recipe how vertices should be - * translated. */ - for (i = 0; i < ve->count; i++) { - struct pipe_vertex_buffer *vb = - &rctx->vertex_buffer[ve->elements[i].vertex_buffer_index]; - enum pipe_format output_format = ve->hw_format[i]; - unsigned output_format_size = ve->hw_format_size[i]; - - /* Check for support. */ - if (ve->elements[i].src_format == ve->hw_format[i]) { - continue; - } - - /* Workaround for translate: output floats instead of halfs. */ - switch (output_format) { - case PIPE_FORMAT_R16_FLOAT: - output_format = PIPE_FORMAT_R32_FLOAT; - output_format_size = 4; - break; - case PIPE_FORMAT_R16G16_FLOAT: - output_format = PIPE_FORMAT_R32G32_FLOAT; - output_format_size = 8; - break; - case PIPE_FORMAT_R16G16B16_FLOAT: - output_format = PIPE_FORMAT_R32G32B32_FLOAT; - output_format_size = 12; - break; - case PIPE_FORMAT_R16G16B16A16_FLOAT: - output_format = PIPE_FORMAT_R32G32B32A32_FLOAT; - output_format_size = 16; - break; - default:; - } - - /* Add this vertex element. */ - te = &key.element[key.nr_elements]; - /*te->type; - te->instance_divisor;*/ - te->input_buffer = ve->elements[i].vertex_buffer_index; - te->input_format = ve->elements[i].src_format; - te->input_offset = vb->buffer_offset + ve->elements[i].src_offset; - te->output_format = output_format; - te->output_offset = key.output_stride; - - key.output_stride += output_format_size; - vb_translated[ve->elements[i].vertex_buffer_index] = TRUE; - tr_elem_index[i] = key.nr_elements; - key.nr_elements++; - } - - /* Get a translate object. */ - tr = translate_cache_find(rctx->tran.translate_cache, &key); - - /* Map buffers we want to translate. */ - for (i = 0; i < rctx->nvertex_buffer; i++) { - if (vb_translated[i]) { - struct pipe_vertex_buffer *vb = &rctx->vertex_buffer[i]; - - vb_map[i] = pipe_buffer_map(pipe, vb->buffer, - PIPE_TRANSFER_READ, &vb_transfer[i]); - - tr->set_buffer(tr, i, vb_map[i], vb->stride, vb->max_index); - } - } - - /* Create and map the output buffer. */ - num_verts = rctx->vb_max_index + 1; - - out_buffer = pipe_buffer_create(&rctx->screen->screen, - PIPE_BIND_VERTEX_BUFFER, - key.output_stride * num_verts); - - out_map = pipe_buffer_map(pipe, out_buffer, PIPE_TRANSFER_WRITE, - &out_transfer); - - /* Translate. */ - tr->run(tr, 0, num_verts, 0, out_map); - - /* Unmap all buffers. */ - for (i = 0; i < rctx->nvertex_buffer; i++) { - if (vb_translated[i]) { - pipe_buffer_unmap(pipe, vb_transfer[i]); - } - } - - pipe_buffer_unmap(pipe, out_transfer); - - /* Setup the new vertex buffer in the first free slot. */ - for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { - struct pipe_vertex_buffer *vb = &rctx->vertex_buffer[i]; - - if (!vb->buffer) { - pipe_resource_reference(&vb->buffer, out_buffer); - vb->buffer_offset = 0; - vb->max_index = num_verts - 1; - vb->stride = key.output_stride; - rctx->tran.vb_slot = i; - break; - } - } - - /* Save and replace vertex elements. */ - for (i = 0; i < ve->count; i++) { - if (vb_translated[ve->elements[i].vertex_buffer_index]) { - te = &key.element[tr_elem_index[i]]; - new_velems[i].instance_divisor = ve->elements[i].instance_divisor; - new_velems[i].src_format = te->output_format; - new_velems[i].src_offset = te->output_offset; - new_velems[i].vertex_buffer_index = rctx->tran.vb_slot; - } else { - memcpy(&new_velems[i], &ve->elements[i], - sizeof(struct pipe_vertex_element)); - } - } - - tmp = pipe->create_vertex_elements_state(pipe, ve->count, new_velems); - pipe->bind_vertex_elements_state(pipe, tmp); - rctx->tran.new_velems = tmp; - - pipe_resource_reference(&out_buffer, NULL); -} - -void r600_end_vertex_translate(struct r600_pipe_context *rctx) -{ - struct pipe_context *pipe = &rctx->context; - - if (rctx->tran.new_velems == NULL) { - return; - } - /* Restore vertex elements. */ - pipe->delete_vertex_elements_state(pipe, rctx->tran.new_velems); - rctx->tran.new_velems = NULL; - - /* Delete the now-unused VBO. */ - pipe_resource_reference(&rctx->vertex_buffer[rctx->tran.vb_slot].buffer, NULL); -} void r600_translate_index_buffer(struct r600_pipe_context *r600, - struct pipe_resource **index_buffer, - unsigned *index_size, - unsigned *start, unsigned count) + struct pipe_resource **index_buffer, + unsigned *index_size, + unsigned *start, unsigned count) { + struct pipe_resource *out_buffer = NULL; + unsigned out_offset; + void *ptr; + boolean flushed; + switch (*index_size) { case 1: - util_shorten_ubyte_elts(&r600->context, index_buffer, 0, *start, count); + u_upload_alloc(r600->vbuf_mgr->uploader, 0, count * 2, + &out_offset, &out_buffer, &flushed, &ptr); + + util_shorten_ubyte_elts_to_userptr( + &r600->context, *index_buffer, 0, *start, count, ptr); + + pipe_resource_reference(index_buffer, out_buffer); *index_size = 2; - *start = 0; - break; - case 2: - case 4: + *start = out_offset / 2; break; } } diff --git a/src/gallium/drivers/r600/r600_upload.c b/src/gallium/drivers/r600/r600_upload.c deleted file mode 100644 index 44102ff55b6..00000000000 --- a/src/gallium/drivers/r600/r600_upload.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2010 Jerome Glisse <[email protected]> - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR 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. - * - * Authors: - * Jerome Glisse <[email protected]> - */ -#include <errno.h> -#include "util/u_inlines.h" -#include "util/u_memory.h" -#include "r600.h" -#include "r600_pipe.h" -#include "r600_resource.h" - -struct r600_upload { - struct r600_pipe_context *rctx; - struct r600_bo *buffer; - char *ptr; - unsigned size; - unsigned default_size; - unsigned total_alloc_size; - unsigned offset; - unsigned alignment; -}; - -struct r600_upload *r600_upload_create(struct r600_pipe_context *rctx, - unsigned default_size, - unsigned alignment) -{ - struct r600_upload *upload = CALLOC_STRUCT(r600_upload); - - if (upload == NULL) - return NULL; - - upload->rctx = rctx; - upload->size = 0; - upload->default_size = default_size; - upload->alignment = alignment; - upload->ptr = NULL; - upload->buffer = NULL; - upload->total_alloc_size = 0; - - return upload; -} - -void r600_upload_flush(struct r600_upload *upload) -{ - if (upload->buffer) { - r600_bo_reference(upload->rctx->radeon, &upload->buffer, NULL); - } - upload->default_size = MAX2(upload->total_alloc_size, upload->default_size); - upload->total_alloc_size = 0; - upload->size = 0; - upload->offset = 0; - upload->ptr = NULL; - upload->buffer = NULL; -} - -void r600_upload_destroy(struct r600_upload *upload) -{ - r600_upload_flush(upload); - FREE(upload); -} - -int r600_upload_buffer(struct r600_upload *upload, unsigned offset, - unsigned size, struct r600_resource_buffer *in_buffer, - unsigned *out_offset, unsigned *out_size, - struct r600_bo **out_buffer) -{ - unsigned alloc_size = align(size, upload->alignment); - const void *in_ptr = NULL; - - if (upload->offset + alloc_size > upload->size) { - if (upload->size) { - r600_bo_reference(upload->rctx->radeon, &upload->buffer, NULL); - } - upload->size = align(MAX2(upload->default_size, alloc_size), 4096); - upload->total_alloc_size += upload->size; - upload->offset = 0; - upload->buffer = r600_bo(upload->rctx->radeon, upload->size, 4096, PIPE_BIND_VERTEX_BUFFER, 0); - if (upload->buffer == NULL) { - return -ENOMEM; - } - upload->ptr = r600_bo_map(upload->rctx->radeon, upload->buffer, 0, NULL); - } - - in_ptr = in_buffer->user_buffer; - memcpy(upload->ptr + upload->offset, (uint8_t *) in_ptr + offset, size); - *out_offset = upload->offset; - *out_size = upload->size; - *out_buffer = NULL; - r600_bo_reference(upload->rctx->radeon, out_buffer, upload->buffer); - upload->offset += alloc_size; - - return 0; -} diff --git a/src/gallium/drivers/r600/r600d.h b/src/gallium/drivers/r600/r600d.h index 8c391936db0..e8558c49a7c 100644 --- a/src/gallium/drivers/r600/r600d.h +++ b/src/gallium/drivers/r600/r600d.h @@ -248,6 +248,8 @@ #define S_0280A0_SOURCE_FORMAT(x) (((x) & 0x1) << 27) #define G_0280A0_SOURCE_FORMAT(x) (((x) >> 27) & 0x1) #define C_0280A0_SOURCE_FORMAT 0xF7FFFFFF +#define V_0280A0_EXPORT_FULL 0 +#define V_0280A0_EXPORT_NORM 1 #define R_028060_CB_COLOR0_SIZE 0x028060 #define S_028060_PITCH_TILE_MAX(x) (((x) & 0x3FF) << 0) #define G_028060_PITCH_TILE_MAX(x) (((x) >> 0) & 0x3FF) @@ -2332,31 +2334,6 @@ #define R_0280D4_CB_COLOR5_TILE 0x0280D4 #define R_0280D8_CB_COLOR6_TILE 0x0280D8 #define R_0280DC_CB_COLOR7_TILE 0x0280DC -#define R_028808_CB_COLOR_CONTROL 0x028808 -#define S_028808_FOG_ENABLE(x) (((x) & 0x1) << 0) -#define G_028808_FOG_ENABLE(x) (((x) >> 0) & 0x1) -#define C_028808_FOG_ENABLE 0xFFFFFFFE -#define S_028808_MULTIWRITE_ENABLE(x) (((x) & 0x1) << 1) -#define G_028808_MULTIWRITE_ENABLE(x) (((x) >> 1) & 0x1) -#define C_028808_MULTIWRITE_ENABLE 0xFFFFFFFD -#define S_028808_DITHER_ENABLE(x) (((x) & 0x1) << 2) -#define G_028808_DITHER_ENABLE(x) (((x) >> 2) & 0x1) -#define C_028808_DITHER_ENABLE 0xFFFFFFFB -#define S_028808_DEGAMMA_ENABLE(x) (((x) & 0x1) << 3) -#define G_028808_DEGAMMA_ENABLE(x) (((x) >> 3) & 0x1) -#define C_028808_DEGAMMA_ENABLE 0xFFFFFFF7 -#define S_028808_SPECIAL_OP(x) (((x) & 0x7) << 4) -#define G_028808_SPECIAL_OP(x) (((x) >> 4) & 0x7) -#define C_028808_SPECIAL_OP 0xFFFFFF8F -#define S_028808_PER_MRT_BLEND(x) (((x) & 0x1) << 7) -#define G_028808_PER_MRT_BLEND(x) (((x) >> 7) & 0x1) -#define C_028808_PER_MRT_BLEND 0xFFFFFF7F -#define S_028808_TARGET_BLEND_ENABLE(x) (((x) & 0xFF) << 8) -#define G_028808_TARGET_BLEND_ENABLE(x) (((x) >> 8) & 0xFF) -#define C_028808_TARGET_BLEND_ENABLE 0xFFFF00FF -#define S_028808_ROP3(x) (((x) & 0xFF) << 16) -#define G_028808_ROP3(x) (((x) >> 16) & 0xFF) -#define C_028808_ROP3 0xFF00FFFF #define R_028614_SPI_VS_OUT_ID_0 0x028614 #define S_028614_SEMANTIC_0(x) (((x) & 0xFF) << 0) #define G_028614_SEMANTIC_0(x) (((x) >> 0) & 0xFF) diff --git a/src/gallium/drivers/rbug/rbug_context.c b/src/gallium/drivers/rbug/rbug_context.c index 94e57e40f86..3aefb5b3bb5 100644 --- a/src/gallium/drivers/rbug/rbug_context.c +++ b/src/gallium/drivers/rbug/rbug_context.c @@ -987,6 +987,19 @@ rbug_context_transfer_inline_write(struct pipe_context *_context, } +static void rbug_redefine_user_buffer(struct pipe_context *_context, + struct pipe_resource *_resource, + unsigned offset, unsigned size) +{ + struct rbug_context *rb_pipe = rbug_context(_context); + struct rbug_resource *rb_resource = rbug_resource(_resource); + struct pipe_context *context = rb_pipe->pipe; + struct pipe_resource *resource = rb_resource->resource; + + context->redefine_user_buffer(context, resource, offset, size); +} + + struct pipe_context * rbug_context_create(struct pipe_screen *_screen, struct pipe_context *pipe) { @@ -1072,6 +1085,7 @@ rbug_context_create(struct pipe_screen *_screen, struct pipe_context *pipe) rb_pipe->base.transfer_unmap = rbug_context_transfer_unmap; rb_pipe->base.transfer_flush_region = rbug_context_transfer_flush_region; rb_pipe->base.transfer_inline_write = rbug_context_transfer_inline_write; + rb_pipe->base.redefine_user_buffer = rbug_redefine_user_buffer; rb_pipe->pipe = pipe; diff --git a/src/gallium/drivers/rbug/rbug_objects.c b/src/gallium/drivers/rbug/rbug_objects.c index 7d7cc482ae6..15f5db40093 100644 --- a/src/gallium/drivers/rbug/rbug_objects.c +++ b/src/gallium/drivers/rbug/rbug_objects.c @@ -98,8 +98,9 @@ rbug_surface_create(struct rbug_context *rb_context, pipe_reference_init(&rb_surface->base.reference, 1); rb_surface->base.texture = NULL; + rb_surface->base.context = &rb_context->base; + rb_surface->surface = surface; /* we own the surface already */ pipe_resource_reference(&rb_surface->base.texture, &rb_resource->base); - rb_surface->surface = surface; return &rb_surface->base; @@ -113,8 +114,7 @@ rbug_surface_destroy(struct rbug_context *rb_context, struct rbug_surface *rb_surface) { pipe_resource_reference(&rb_surface->base.texture, NULL); - rb_context->pipe->surface_destroy(rb_context->pipe, - rb_surface->surface); + pipe_surface_reference(&rb_surface->surface, NULL); FREE(rb_surface); } diff --git a/src/gallium/drivers/softpipe/sp_context.c b/src/gallium/drivers/softpipe/sp_context.c index fe54f92addf..70fdfb7ddf3 100644 --- a/src/gallium/drivers/softpipe/sp_context.c +++ b/src/gallium/drivers/softpipe/sp_context.c @@ -230,7 +230,7 @@ softpipe_create_context( struct pipe_screen *screen, softpipe->use_sse = FALSE; #endif - softpipe->dump_fs = debug_get_bool_option( "GALLIUM_DUMP_FS", FALSE ); + softpipe->dump_fs = debug_get_bool_option( "SOFTPIPE_DUMP_FS", FALSE ); softpipe->dump_gs = debug_get_bool_option( "SOFTPIPE_DUMP_GS", FALSE ); softpipe->pipe.winsys = NULL; @@ -315,7 +315,7 @@ softpipe_create_context( struct pipe_screen *screen, (struct tgsi_sampler **) softpipe->tgsi.geom_samplers_list); - if (debug_get_bool_option( "SP_NO_RAST", FALSE )) + if (debug_get_bool_option( "SOFTPIPE_NO_RAST", FALSE )) softpipe->no_rast = TRUE; softpipe->vbuf_backend = sp_create_vbuf_backend(softpipe); diff --git a/src/gallium/drivers/softpipe/sp_context.h b/src/gallium/drivers/softpipe/sp_context.h index 035d712d17c..c91709aef06 100644 --- a/src/gallium/drivers/softpipe/sp_context.h +++ b/src/gallium/drivers/softpipe/sp_context.h @@ -58,7 +58,7 @@ struct softpipe_context { /** Constant state objects */ struct pipe_blend_state *blend; - struct pipe_sampler_state *sampler[PIPE_MAX_SAMPLERS]; + struct pipe_sampler_state *fragment_samplers[PIPE_MAX_SAMPLERS]; struct pipe_sampler_state *vertex_samplers[PIPE_MAX_VERTEX_SAMPLERS]; struct pipe_sampler_state *geometry_samplers[PIPE_MAX_GEOMETRY_SAMPLERS]; struct pipe_depth_stencil_alpha_state *depth_stencil; @@ -91,8 +91,8 @@ struct softpipe_context { } so_target; struct pipe_query_data_so_statistics so_stats; - unsigned num_samplers; - unsigned num_sampler_views; + unsigned num_fragment_samplers; + unsigned num_fragment_sampler_views; unsigned num_vertex_samplers; unsigned num_vertex_sampler_views; unsigned num_geometry_samplers; diff --git a/src/gallium/drivers/softpipe/sp_flush.c b/src/gallium/drivers/softpipe/sp_flush.c index d422cb17a4b..6f7addd441a 100644 --- a/src/gallium/drivers/softpipe/sp_flush.c +++ b/src/gallium/drivers/softpipe/sp_flush.c @@ -51,7 +51,7 @@ softpipe_flush( struct pipe_context *pipe, draw_flush(softpipe->draw); if (flags & PIPE_FLUSH_TEXTURE_CACHE) { - for (i = 0; i < softpipe->num_sampler_views; i++) { + for (i = 0; i < softpipe->num_fragment_sampler_views; i++) { sp_flush_tex_tile_cache(softpipe->fragment_tex_cache[i]); } for (i = 0; i < softpipe->num_vertex_sampler_views; i++) { diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c index c433405cb66..a06817c5735 100644 --- a/src/gallium/drivers/softpipe/sp_screen.c +++ b/src/gallium/drivers/softpipe/sp_screen.c @@ -126,6 +126,8 @@ softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param) return 1; case PIPE_CAP_INSTANCED_DRAWING: return 1; + case PIPE_CAP_ARRAY_TEXTURES: + return 1; default: return 0; } @@ -186,7 +188,9 @@ softpipe_is_format_supported( struct pipe_screen *screen, assert(target == PIPE_BUFFER || target == PIPE_TEXTURE_1D || + target == PIPE_TEXTURE_1D_ARRAY || target == PIPE_TEXTURE_2D || + target == PIPE_TEXTURE_2D_ARRAY || target == PIPE_TEXTURE_RECT || target == PIPE_TEXTURE_3D || target == PIPE_TEXTURE_CUBE); diff --git a/src/gallium/drivers/softpipe/sp_setup.c b/src/gallium/drivers/softpipe/sp_setup.c index 5d727dc00df..0ce28f4c6ee 100644 --- a/src/gallium/drivers/softpipe/sp_setup.c +++ b/src/gallium/drivers/softpipe/sp_setup.c @@ -575,7 +575,7 @@ setup_fragcoord_coeff(struct setup_context *setup, uint slot) setup->coef[slot].dady[0] = 0.0; /*Y*/ setup->coef[slot].a0[1] = - (spfs->origin_lower_left ? setup->softpipe->framebuffer.height : 0) + (spfs->origin_lower_left ? setup->softpipe->framebuffer.height-1 : 0) + (spfs->pixel_center_integer ? 0.0 : 0.5); setup->coef[slot].dadx[1] = 0.0; setup->coef[slot].dady[1] = spfs->origin_lower_left ? -1.0 : 1.0; diff --git a/src/gallium/drivers/softpipe/sp_state_sampler.c b/src/gallium/drivers/softpipe/sp_state_sampler.c index 38943563800..60331bc4976 100644 --- a/src/gallium/drivers/softpipe/sp_state_sampler.c +++ b/src/gallium/drivers/softpipe/sp_state_sampler.c @@ -76,18 +76,18 @@ softpipe_bind_fragment_sampler_states(struct pipe_context *pipe, assert(num <= PIPE_MAX_SAMPLERS); /* Check for no-op */ - if (num == softpipe->num_samplers && - !memcmp(softpipe->sampler, sampler, num * sizeof(void *))) + if (num == softpipe->num_fragment_samplers && + !memcmp(softpipe->fragment_samplers, sampler, num * sizeof(void *))) return; draw_flush(softpipe->draw); for (i = 0; i < num; ++i) - softpipe->sampler[i] = sampler[i]; + softpipe->fragment_samplers[i] = sampler[i]; for (i = num; i < PIPE_MAX_SAMPLERS; ++i) - softpipe->sampler[i] = NULL; + softpipe->fragment_samplers[i] = NULL; - softpipe->num_samplers = num; + softpipe->num_fragment_samplers = num; softpipe->dirty |= SP_NEW_SAMPLER; } @@ -191,7 +191,7 @@ softpipe_set_fragment_sampler_views(struct pipe_context *pipe, assert(num <= PIPE_MAX_SAMPLERS); /* Check for no-op */ - if (num == softpipe->num_sampler_views && + if (num == softpipe->num_fragment_sampler_views && !memcmp(softpipe->fragment_sampler_views, views, num * sizeof(struct pipe_sampler_view *))) return; @@ -205,7 +205,7 @@ softpipe_set_fragment_sampler_views(struct pipe_context *pipe, sp_tex_tile_cache_set_sampler_view(softpipe->fragment_tex_cache[i], view); } - softpipe->num_sampler_views = num; + softpipe->num_fragment_sampler_views = num; softpipe->dirty |= SP_NEW_TEXTURE; } @@ -374,10 +374,10 @@ softpipe_reset_sampler_variants(struct softpipe_context *softpipe) } for (i = 0; i <= softpipe->fs->info.file_max[TGSI_FILE_SAMPLER]; i++) { - if (softpipe->sampler[i]) { + if (softpipe->fragment_samplers[i]) { softpipe->tgsi.frag_samplers_list[i] = get_sampler_variant( i, - sp_sampler(softpipe->sampler[i]), + sp_sampler(softpipe->fragment_samplers[i]), softpipe->fragment_sampler_views[i], TGSI_PROCESSOR_FRAGMENT ); diff --git a/src/gallium/drivers/softpipe/sp_state_vertex.c b/src/gallium/drivers/softpipe/sp_state_vertex.c index 5f4d661abde..aa0b333c7a9 100644 --- a/src/gallium/drivers/softpipe/sp_state_vertex.c +++ b/src/gallium/drivers/softpipe/sp_state_vertex.c @@ -34,6 +34,7 @@ #include "util/u_memory.h" #include "util/u_inlines.h" +#include "util/u_transfer.h" #include "draw/draw_context.h" @@ -119,4 +120,5 @@ softpipe_init_vertex_funcs(struct pipe_context *pipe) pipe->set_vertex_buffers = softpipe_set_vertex_buffers; pipe->set_index_buffer = softpipe_set_index_buffer; + pipe->redefine_user_buffer = u_default_redefine_user_buffer; } diff --git a/src/gallium/drivers/softpipe/sp_tex_sample.c b/src/gallium/drivers/softpipe/sp_tex_sample.c index 242c27c7ebd..8a4ef934348 100644 --- a/src/gallium/drivers/softpipe/sp_tex_sample.c +++ b/src/gallium/drivers/softpipe/sp_tex_sample.c @@ -539,6 +539,19 @@ wrap_linear_unorm_clamp_to_edge(const float s[4], unsigned size, } +/** + * Do coordinate to array index conversion. For array textures. + */ +static INLINE void +wrap_array_layer(const float coord[4], unsigned size, int layer[4]) +{ + uint ch; + for (ch = 0; ch < 4; ch++) { + int c = util_ifloor(coord[ch] + 0.5F); + layer[ch] = CLAMP(c, 0, size - 1); + } +} + /** * Examine the quad's texture coordinates to compute the partial @@ -761,6 +774,43 @@ get_texel_3d(const struct sp_sampler_variant *samp, } +/* Get texel pointer for 1D array texture */ +static INLINE const float * +get_texel_1d_array(const struct sp_sampler_variant *samp, + union tex_tile_address addr, int x, int y) +{ + const struct pipe_resource *texture = samp->view->texture; + unsigned level = addr.bits.level; + + if (x < 0 || x >= (int) u_minify(texture->width0, level)) { + return samp->sampler->border_color; + } + else { + return get_texel_2d_no_border(samp, addr, x, y); + } +} + + +/* Get texel pointer for 2D array texture */ +static INLINE const float * +get_texel_2d_array(const struct sp_sampler_variant *samp, + union tex_tile_address addr, int x, int y, int layer) +{ + const struct pipe_resource *texture = samp->view->texture; + unsigned level = addr.bits.level; + + assert(layer < texture->array_size); + + if (x < 0 || x >= (int) u_minify(texture->width0, level) || + y < 0 || y >= (int) u_minify(texture->height0, level)) { + return samp->sampler->border_color; + } + else { + return get_texel_3d_no_border(samp, addr, x, y, layer); + } +} + + /** * Given the logbase2 of a mipmap's base level size and a mipmap level, * return the size (in texels) of that mipmap level. @@ -990,6 +1040,47 @@ img_filter_1d_nearest(struct tgsi_sampler *tgsi_sampler, static void +img_filter_1d_array_nearest(struct tgsi_sampler *tgsi_sampler, + const float s[QUAD_SIZE], + const float t[QUAD_SIZE], + const float p[QUAD_SIZE], + const float c0[QUAD_SIZE], + enum tgsi_sampler_control control, + float rgba[NUM_CHANNELS][QUAD_SIZE]) +{ + const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); + const struct pipe_resource *texture = samp->view->texture; + unsigned level0, j; + int width; + int x[4], layer[4]; + union tex_tile_address addr; + + level0 = samp->level; + width = u_minify(texture->width0, level0); + + assert(width > 0); + + addr.value = 0; + addr.bits.level = samp->level; + + samp->nearest_texcoord_s(s, width, x); + wrap_array_layer(t, texture->array_size, layer); + + for (j = 0; j < QUAD_SIZE; j++) { + const float *out = get_texel_1d_array(samp, addr, x[j], layer[j]); + int c; + for (c = 0; c < 4; c++) { + rgba[c][j] = out[c]; + } + } + + if (DEBUG_TEX) { + print_sample(__FUNCTION__, rgba); + } +} + + +static void img_filter_2d_nearest(struct tgsi_sampler *tgsi_sampler, const float s[QUAD_SIZE], const float t[QUAD_SIZE], @@ -1033,6 +1124,50 @@ img_filter_2d_nearest(struct tgsi_sampler *tgsi_sampler, } +static void +img_filter_2d_array_nearest(struct tgsi_sampler *tgsi_sampler, + const float s[QUAD_SIZE], + const float t[QUAD_SIZE], + const float p[QUAD_SIZE], + const float c0[QUAD_SIZE], + enum tgsi_sampler_control control, + float rgba[NUM_CHANNELS][QUAD_SIZE]) +{ + const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); + const struct pipe_resource *texture = samp->view->texture; + unsigned level0, j; + int width, height; + int x[4], y[4], layer[4]; + union tex_tile_address addr; + + level0 = samp->level; + width = u_minify(texture->width0, level0); + height = u_minify(texture->height0, level0); + + assert(width > 0); + assert(height > 0); + + addr.value = 0; + addr.bits.level = samp->level; + + samp->nearest_texcoord_s(s, width, x); + samp->nearest_texcoord_t(t, height, y); + wrap_array_layer(p, texture->array_size, layer); + + for (j = 0; j < QUAD_SIZE; j++) { + const float *out = get_texel_2d_array(samp, addr, x[j], y[j], layer[j]); + int c; + for (c = 0; c < 4; c++) { + rgba[c][j] = out[c]; + } + } + + if (DEBUG_TEX) { + print_sample(__FUNCTION__, rgba); + } +} + + static INLINE union tex_tile_address face(union tex_tile_address addr, unsigned face ) { @@ -1168,6 +1303,47 @@ img_filter_1d_linear(struct tgsi_sampler *tgsi_sampler, static void +img_filter_1d_array_linear(struct tgsi_sampler *tgsi_sampler, + const float s[QUAD_SIZE], + const float t[QUAD_SIZE], + const float p[QUAD_SIZE], + const float c0[QUAD_SIZE], + enum tgsi_sampler_control control, + float rgba[NUM_CHANNELS][QUAD_SIZE]) +{ + const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); + const struct pipe_resource *texture = samp->view->texture; + unsigned level0, j; + int width; + int x0[4], x1[4], layer[4]; + float xw[4]; /* weights */ + union tex_tile_address addr; + + level0 = samp->level; + width = u_minify(texture->width0, level0); + + assert(width > 0); + + addr.value = 0; + addr.bits.level = samp->level; + + samp->linear_texcoord_s(s, width, x0, x1, xw); + wrap_array_layer(t, texture->array_size, layer); + + for (j = 0; j < QUAD_SIZE; j++) { + const float *tx0 = get_texel_1d_array(samp, addr, x0[j], layer[j]); + const float *tx1 = get_texel_1d_array(samp, addr, x1[j], layer[j]); + int c; + + /* interpolate R, G, B, A */ + for (c = 0; c < 4; c++) { + rgba[c][j] = lerp(xw[j], tx0[c], tx1[c]); + } + } +} + + +static void img_filter_2d_linear(struct tgsi_sampler *tgsi_sampler, const float s[QUAD_SIZE], const float t[QUAD_SIZE], @@ -1215,6 +1391,54 @@ img_filter_2d_linear(struct tgsi_sampler *tgsi_sampler, static void +img_filter_2d_array_linear(struct tgsi_sampler *tgsi_sampler, + const float s[QUAD_SIZE], + const float t[QUAD_SIZE], + const float p[QUAD_SIZE], + const float c0[QUAD_SIZE], + enum tgsi_sampler_control control, + float rgba[NUM_CHANNELS][QUAD_SIZE]) +{ + const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); + const struct pipe_resource *texture = samp->view->texture; + unsigned level0, j; + int width, height; + int x0[4], y0[4], x1[4], y1[4], layer[4]; + float xw[4], yw[4]; /* weights */ + union tex_tile_address addr; + + level0 = samp->level; + width = u_minify(texture->width0, level0); + height = u_minify(texture->height0, level0); + + assert(width > 0); + assert(height > 0); + + addr.value = 0; + addr.bits.level = samp->level; + + samp->linear_texcoord_s(s, width, x0, x1, xw); + samp->linear_texcoord_t(t, height, y0, y1, yw); + wrap_array_layer(p, texture->array_size, layer); + + for (j = 0; j < QUAD_SIZE; j++) { + const float *tx0 = get_texel_2d_array(samp, addr, x0[j], y0[j], layer[j]); + const float *tx1 = get_texel_2d_array(samp, addr, x1[j], y0[j], layer[j]); + const float *tx2 = get_texel_2d_array(samp, addr, x0[j], y1[j], layer[j]); + const float *tx3 = get_texel_2d_array(samp, addr, x1[j], y1[j], layer[j]); + int c; + + /* interpolate R, G, B, A */ + for (c = 0; c < 4; c++) { + rgba[c][j] = lerp_2d(xw[j], yw[j], + tx0[c], tx1[c], + tx2[c], tx3[c]); + } + } +} + + +static void img_filter_cube_linear(struct tgsi_sampler *tgsi_sampler, const float s[QUAD_SIZE], const float t[QUAD_SIZE], @@ -1906,8 +2130,10 @@ get_lambda_func(const union sp_sampler_key key) switch (key.bits.target) { case PIPE_TEXTURE_1D: + case PIPE_TEXTURE_1D_ARRAY: return compute_lambda_1d; case PIPE_TEXTURE_2D: + case PIPE_TEXTURE_2D_ARRAY: case PIPE_TEXTURE_RECT: case PIPE_TEXTURE_CUBE: return compute_lambda_2d; @@ -1932,6 +2158,12 @@ get_img_filter(const union sp_sampler_key key, else return img_filter_1d_linear; break; + case PIPE_TEXTURE_1D_ARRAY: + if (filter == PIPE_TEX_FILTER_NEAREST) + return img_filter_1d_array_nearest; + else + return img_filter_1d_array_linear; + break; case PIPE_TEXTURE_2D: case PIPE_TEXTURE_RECT: /* Try for fast path: @@ -1967,6 +2199,12 @@ get_img_filter(const union sp_sampler_key key, else return img_filter_2d_linear; break; + case PIPE_TEXTURE_2D_ARRAY: + if (filter == PIPE_TEX_FILTER_NEAREST) + return img_filter_2d_array_nearest; + else + return img_filter_2d_array_linear; + break; case PIPE_TEXTURE_CUBE: if (filter == PIPE_TEX_FILTER_NEAREST) return img_filter_cube_nearest; diff --git a/src/gallium/drivers/softpipe/sp_tex_tile_cache.c b/src/gallium/drivers/softpipe/sp_tex_tile_cache.c index e42015ad498..e589ee7c841 100644 --- a/src/gallium/drivers/softpipe/sp_tex_tile_cache.c +++ b/src/gallium/drivers/softpipe/sp_tex_tile_cache.c @@ -251,6 +251,7 @@ sp_find_cached_tile_tex(struct softpipe_tex_tile_cache *tc, tc->tex_level != addr.bits.level || tc->tex_z != addr.bits.z) { /* get new transfer (view into texture) */ + unsigned width, height, layer; if (tc->tex_trans) { if (tc->tex_trans_map) { @@ -262,14 +263,22 @@ sp_find_cached_tile_tex(struct softpipe_tex_tile_cache *tc, tc->tex_trans = NULL; } + width = u_minify(tc->texture->width0, addr.bits.level); + if (tc->texture->target == PIPE_TEXTURE_1D_ARRAY) { + height = tc->texture->array_size; + layer = 0; + } + else { + height = u_minify(tc->texture->height0, addr.bits.level); + layer = addr.bits.face + addr.bits.z; + } + tc->tex_trans = pipe_get_transfer(tc->pipe, tc->texture, addr.bits.level, - addr.bits.face + addr.bits.z, + layer, PIPE_TRANSFER_READ | PIPE_TRANSFER_UNSYNCHRONIZED, - 0, 0, - u_minify(tc->texture->width0, addr.bits.level), - u_minify(tc->texture->height0, addr.bits.level)); + 0, 0, width, height); tc->tex_trans_map = tc->pipe->transfer_map(tc->pipe, tc->tex_trans); @@ -278,22 +287,17 @@ sp_find_cached_tile_tex(struct softpipe_tex_tile_cache *tc, tc->tex_z = addr.bits.z; } - /* get tile from the transfer (view into texture) - * Note we're using the swizzle version of this fuction only because - * we need to pass the texture cache's format explicitly. + /* Get tile from the transfer (view into texture), explicitly passing + * the image format. */ - pipe_get_tile_swizzle(tc->pipe, - tc->tex_trans, - addr.bits.x * TILE_SIZE, - addr.bits.y * TILE_SIZE, - TILE_SIZE, - TILE_SIZE, - PIPE_SWIZZLE_RED, - PIPE_SWIZZLE_GREEN, - PIPE_SWIZZLE_BLUE, - PIPE_SWIZZLE_ALPHA, - tc->format, - (float *) tile->data.color); + pipe_get_tile_rgba_format(tc->pipe, + tc->tex_trans, + addr.bits.x * TILE_SIZE, + addr.bits.y * TILE_SIZE, + TILE_SIZE, + TILE_SIZE, + tc->format, + (float *) tile->data.color); tile->addr = addr; } diff --git a/src/gallium/drivers/softpipe/sp_tex_tile_cache.h b/src/gallium/drivers/softpipe/sp_tex_tile_cache.h index 2220955b715..9bced37990a 100644 --- a/src/gallium/drivers/softpipe/sp_tex_tile_cache.h +++ b/src/gallium/drivers/softpipe/sp_tex_tile_cache.h @@ -92,7 +92,7 @@ struct softpipe_tex_tile_cache unsigned swizzle_g; unsigned swizzle_b; unsigned swizzle_a; - unsigned format; + enum pipe_format format; struct softpipe_tex_cached_tile *last_tile; /**< most recently retrieved tile */ }; diff --git a/src/gallium/drivers/softpipe/sp_texture.c b/src/gallium/drivers/softpipe/sp_texture.c index 509d9982b17..95374c34ec3 100644 --- a/src/gallium/drivers/softpipe/sp_texture.c +++ b/src/gallium/drivers/softpipe/sp_texture.c @@ -62,13 +62,21 @@ softpipe_resource_layout(struct pipe_screen *screen, unsigned buffer_size = 0; for (level = 0; level <= pt->last_level; level++) { + unsigned slices; + + if (pt->target == PIPE_TEXTURE_CUBE) + slices = 6; + else if (pt->target == PIPE_TEXTURE_3D) + slices = depth; + else + slices = pt->array_size; + spr->stride[level] = util_format_get_stride(pt->format, width); spr->level_offset[level] = buffer_size; buffer_size += (util_format_get_nblocksy(pt->format, height) * - ((pt->target == PIPE_TEXTURE_CUBE) ? 6 : depth) * - spr->stride[level]); + slices * spr->stride[level]); width = u_minify(width, 1); height = u_minify(height, 1); @@ -227,9 +235,13 @@ sp_get_tex_image_offset(const struct softpipe_resource *spr, unsigned offset = spr->level_offset[level]; if (spr->base.target == PIPE_TEXTURE_CUBE || - spr->base.target == PIPE_TEXTURE_3D) { + spr->base.target == PIPE_TEXTURE_3D || + spr->base.target == PIPE_TEXTURE_2D_ARRAY) { offset += layer * nblocksy * spr->stride[level]; } + else if (spr->base.target == PIPE_TEXTURE_1D_ARRAY) { + offset += layer * spr->stride[level]; + } else { assert(layer == 0); } @@ -292,7 +304,7 @@ softpipe_surface_destroy(struct pipe_context *pipe, * a resource object. * \param pipe rendering context * \param resource the resource to transfer in/out of - * \param sr indicates cube face or 3D texture slice + * \param level which mipmap level * \param usage bitmask of PIPE_TRANSFER_x flags * \param box the 1D/2D/3D region of interest */ @@ -311,8 +323,21 @@ softpipe_get_transfer(struct pipe_context *pipe, /* make sure the requested region is in the image bounds */ assert(box->x + box->width <= u_minify(resource->width0, level)); - assert(box->y + box->height <= u_minify(resource->height0, level)); - assert(box->z + box->depth <= (u_minify(resource->depth0, level) + resource->array_size - 1)); + if (resource->target == PIPE_TEXTURE_1D_ARRAY) { + assert(box->y + box->height <= resource->array_size); + } + else { + assert(box->y + box->height <= u_minify(resource->height0, level)); + if (resource->target == PIPE_TEXTURE_2D_ARRAY) { + assert(box->z + box->depth <= resource->array_size); + } + else if (resource->target == PIPE_TEXTURE_CUBE) { + assert(box->z < 6); + } + else { + assert(box->z + box->depth <= (u_minify(resource->depth0, level))); + } + } /* * Transfers, like other pipe operations, must happen in order, so flush the diff --git a/src/gallium/drivers/softpipe/sp_tile_cache.c b/src/gallium/drivers/softpipe/sp_tile_cache.c index 480860af63b..60870b8bee5 100644 --- a/src/gallium/drivers/softpipe/sp_tile_cache.c +++ b/src/gallium/drivers/softpipe/sp_tile_cache.c @@ -357,11 +357,12 @@ sp_flush_tile(struct softpipe_tile_cache* tc, unsigned pos) tc->entries[pos]->data.depth32, 0/*STRIDE*/); } else { - pipe_put_tile_rgba(tc->pipe, tc->transfer, - tc->tile_addrs[pos].bits.x * TILE_SIZE, - tc->tile_addrs[pos].bits.y * TILE_SIZE, - TILE_SIZE, TILE_SIZE, - (float *) tc->entries[pos]->data.color); + pipe_put_tile_rgba_format(tc->pipe, tc->transfer, + tc->tile_addrs[pos].bits.x * TILE_SIZE, + tc->tile_addrs[pos].bits.y * TILE_SIZE, + TILE_SIZE, TILE_SIZE, + tc->surface->format, + (float *) tc->entries[pos]->data.color); } tc->tile_addrs[pos].bits.invalid = 1; /* mark as empty */ } @@ -468,11 +469,12 @@ sp_find_cached_tile(struct softpipe_tile_cache *tc, tile->data.depth32, 0/*STRIDE*/); } else { - pipe_put_tile_rgba(tc->pipe, pt, - tc->tile_addrs[pos].bits.x * TILE_SIZE, - tc->tile_addrs[pos].bits.y * TILE_SIZE, - TILE_SIZE, TILE_SIZE, - (float *) tile->data.color); + pipe_put_tile_rgba_format(tc->pipe, pt, + tc->tile_addrs[pos].bits.x * TILE_SIZE, + tc->tile_addrs[pos].bits.y * TILE_SIZE, + TILE_SIZE, TILE_SIZE, + tc->surface->format, + (float *) tile->data.color); } } diff --git a/src/gallium/drivers/svga/svga_context.c b/src/gallium/drivers/svga/svga_context.c index 1e513f1039f..f0f875b2b23 100644 --- a/src/gallium/drivers/svga/svga_context.c +++ b/src/gallium/drivers/svga/svga_context.c @@ -34,6 +34,7 @@ #include "svga_context.h" #include "svga_screen.h" +#include "svga_surface.h" #include "svga_resource_texture.h" #include "svga_resource_buffer.h" #include "svga_resource.h" @@ -43,6 +44,12 @@ #include "svga_debug.h" #include "svga_state.h" +DEBUG_GET_ONCE_BOOL_OPTION(no_swtnl, "SVGA_NO_SWTNL", FALSE) +DEBUG_GET_ONCE_BOOL_OPTION(force_swtnl, "SVGA_FORCE_SWTNL", FALSE); +DEBUG_GET_ONCE_BOOL_OPTION(use_min_mipmap, "SVGA_USE_MIN_MIPMAP", FALSE); +DEBUG_GET_ONCE_NUM_OPTION(disable_shader, "SVGA_DISABLE_SHADER", ~0); +DEBUG_GET_ONCE_BOOL_OPTION(no_line_width, "SVGA_NO_LINE_WIDTH", FALSE); +DEBUG_GET_ONCE_BOOL_OPTION(force_hw_line_stipple, "SVGA_FORCE_HW_LINE_STIPPLE", FALSE); static void svga_destroy( struct pipe_context *pipe ) { @@ -113,13 +120,12 @@ struct pipe_context *svga_context_create( struct pipe_screen *screen, /* debug */ - svga->debug.no_swtnl = debug_get_bool_option("SVGA_NO_SWTNL", FALSE); - svga->debug.force_swtnl = debug_get_bool_option("SVGA_FORCE_SWTNL", FALSE); - svga->debug.use_min_mipmap = debug_get_bool_option("SVGA_USE_MIN_MIPMAP", FALSE); - svga->debug.disable_shader = debug_get_num_option("SVGA_DISABLE_SHADER", ~0); - - if (!svga_init_swtnl(svga)) - goto no_swtnl; + svga->debug.no_swtnl = debug_get_option_no_swtnl(); + svga->debug.force_swtnl = debug_get_option_force_swtnl(); + svga->debug.use_min_mipmap = debug_get_option_use_min_mipmap(); + svga->debug.disable_shader = debug_get_option_disable_shader(); + svga->debug.no_line_width = debug_get_option_no_line_width(); + svga->debug.force_hw_line_stipple = debug_get_option_force_hw_line_stipple(); svga->fs_bm = util_bitmask_create(); if (svga->fs_bm == NULL) @@ -149,6 +155,8 @@ struct pipe_context *svga_context_create( struct pipe_screen *screen, if (svga->hwtnl == NULL) goto no_hwtnl; + if (!svga_init_swtnl(svga)) + goto no_swtnl; ret = svga_emit_initial_state( svga ); if (ret) @@ -171,6 +179,8 @@ struct pipe_context *svga_context_create( struct pipe_screen *screen, return &svga->pipe; no_state: + svga_destroy_swtnl(svga); +no_swtnl: svga_hwtnl_destroy( svga->hwtnl ); no_hwtnl: u_upload_destroy( svga->upload_vb ); @@ -181,8 +191,6 @@ no_upload_ib: no_vs_bm: util_bitmask_destroy( svga->fs_bm ); no_fs_bm: - svga_destroy_swtnl(svga); -no_swtnl: svga->swc->destroy(svga->swc); no_swc: FREE(svga); @@ -196,14 +204,10 @@ void svga_context_flush( struct svga_context *svga, { struct svga_screen *svgascreen = svga_screen(svga->pipe.screen); struct pipe_fence_handle *fence = NULL; + enum pipe_error ret; svga->curr.nr_fbs = 0; - /* Unmap upload manager buffers: - */ - u_upload_flush(svga->upload_vb); - u_upload_flush(svga->upload_ib); - /* Ensure that texture dma uploads are processed * before submitting commands. */ @@ -220,6 +224,21 @@ void svga_context_flush( struct svga_context *svga, */ svga->dirty |= SVGA_NEW_COMMAND_BUFFER; + /* + * We must reemit the surface bindings here, because svga_update_state + * will always flush the primitives before processing the + * SVGA_NEW_COMMAND_BUFFER state change. + * + * TODO: Refactor this. + */ + ret = svga_reemit_framebuffer_bindings(svga); + assert(ret == PIPE_OK); + + ret = svga_reemit_tss_bindings(svga); + assert(ret == PIPE_OK); + + svga->dirty &= ~SVGA_NEW_COMMAND_BUFFER; + if (SVGA_DEBUG & DEBUG_SYNC) { if (fence) svga->pipe.screen->fence_finish( svga->pipe.screen, fence, 0); @@ -245,6 +264,30 @@ void svga_hwtnl_flush_retry( struct svga_context *svga ) assert(ret == 0); } + +/* Emit all operations pending on host surfaces. + */ +void svga_surfaces_flush(struct svga_context *svga) +{ + unsigned i; + + /* Emit buffered drawing commands. + */ + svga_hwtnl_flush_retry( svga ); + + /* Emit back-copy from render target view to texture. + */ + for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { + if (svga->curr.framebuffer.cbufs[i]) + svga_propagate_surface(svga, svga->curr.framebuffer.cbufs[i]); + } + + if (svga->curr.framebuffer.zsbuf) + svga_propagate_surface(svga, svga->curr.framebuffer.zsbuf); + +} + + struct svga_winsys_context * svga_winsys_context( struct pipe_context *pipe ) { diff --git a/src/gallium/drivers/svga/svga_context.h b/src/gallium/drivers/svga/svga_context.h index d4970908b1e..7b36a3606e0 100644 --- a/src/gallium/drivers/svga/svga_context.h +++ b/src/gallium/drivers/svga/svga_context.h @@ -35,6 +35,8 @@ #include "tgsi/tgsi_scan.h" +#include "svga_state.h" + #define SVGA_TEX_UNITS 8 #define SVGA_MAX_POINTSIZE 80.0 @@ -147,7 +149,14 @@ struct svga_rasterizer_state { float pointsize; unsigned hw_unfilled:16; /* PIPE_POLYGON_MODE_x */ - unsigned need_pipeline:16; /* which prims do we need help for? */ + + /** Which prims do we need help for? Bitmask of (1 << PIPE_PRIM_x) flags */ + unsigned need_pipeline:16; + + /** For debugging: */ + const char* need_pipeline_tris_str; + const char* need_pipeline_lines_str; + const char* need_pipeline_points_str; }; struct svga_sampler_state { @@ -237,7 +246,7 @@ struct svga_prescale { }; -/* Updated by calling svga_update_state( SVGA_STATE_HW_VIEWPORT ) +/* Updated by calling svga_update_state( SVGA_STATE_HW_CLEAR ) */ struct svga_hw_clear_state { @@ -317,6 +326,9 @@ struct svga_context unsigned shader_id; unsigned disable_shader; + + boolean no_line_width; + boolean force_hw_line_stipple; } debug; struct { @@ -332,7 +344,7 @@ struct svga_context struct util_bitmask *vs_bm; struct { - unsigned dirty[4]; + unsigned dirty[SVGA_STATE_MAX]; unsigned texture_timestamp; @@ -355,6 +367,9 @@ struct svga_context /** List of buffers with queued transfers */ struct list_head dirty_buffers; + + /** Was the previous draw done with the SW path? */ + boolean prev_draw_swtnl; }; /* A flag for each state_tracker state object: @@ -438,6 +453,8 @@ void svga_context_flush( struct svga_context *svga, void svga_hwtnl_flush_retry( struct svga_context *svga ); +void svga_surfaces_flush(struct svga_context *svga); + struct pipe_context * svga_context_create(struct pipe_screen *screen, void *priv); diff --git a/src/gallium/drivers/svga/svga_draw.c b/src/gallium/drivers/svga/svga_draw.c index 97cbac447d6..2c873a0f7ac 100644 --- a/src/gallium/drivers/svga/svga_draw.c +++ b/src/gallium/drivers/svga/svga_draw.c @@ -28,6 +28,7 @@ #include "pipe/p_defines.h" #include "util/u_memory.h" #include "util/u_math.h" +#include "util/u_upload_mgr.h" #include "svga_context.h" #include "svga_draw.h" @@ -143,6 +144,9 @@ svga_hwtnl_flush( struct svga_hwtnl *hwtnl ) SVGA3dPrimitiveRange *prim; unsigned i; + /* Unmap upload manager vertex buffers */ + u_upload_flush(svga->upload_vb); + for (i = 0; i < hwtnl->cmd.vdecl_count; i++) { handle = svga_buffer_handle(svga, hwtnl->cmd.vdecl_vb[i]); if (handle == NULL) @@ -151,6 +155,9 @@ svga_hwtnl_flush( struct svga_hwtnl *hwtnl ) vb_handle[i] = handle; } + /* Unmap upload manager index buffers */ + u_upload_flush(svga->upload_ib); + for (i = 0; i < hwtnl->cmd.prim_count; i++) { if (hwtnl->cmd.prim_ib[i]) { handle = svga_buffer_handle(svga, hwtnl->cmd.prim_ib[i]); diff --git a/src/gallium/drivers/svga/svga_draw_arrays.c b/src/gallium/drivers/svga/svga_draw_arrays.c index be0e7abe21b..a6518042eb9 100644 --- a/src/gallium/drivers/svga/svga_draw_arrays.c +++ b/src/gallium/drivers/svga/svga_draw_arrays.c @@ -53,6 +53,7 @@ static enum pipe_error generate_indices( struct svga_hwtnl *hwtnl, dst = pipe_buffer_create( pipe->screen, PIPE_BIND_INDEX_BUFFER, + PIPE_USAGE_STATIC, size ); if (dst == NULL) goto fail; diff --git a/src/gallium/drivers/svga/svga_draw_elements.c b/src/gallium/drivers/svga/svga_draw_elements.c index 83527c6ef49..7d420c6b295 100644 --- a/src/gallium/drivers/svga/svga_draw_elements.c +++ b/src/gallium/drivers/svga/svga_draw_elements.c @@ -56,6 +56,7 @@ translate_indices( struct svga_hwtnl *hwtnl, dst = pipe_buffer_create( pipe->screen, PIPE_BIND_INDEX_BUFFER, + PIPE_USAGE_STATIC, size ); if (dst == NULL) goto fail; diff --git a/src/gallium/drivers/svga/svga_pipe_blit.c b/src/gallium/drivers/svga/svga_pipe_blit.c index 426698806c8..c87afb6946c 100644 --- a/src/gallium/drivers/svga/svga_pipe_blit.c +++ b/src/gallium/drivers/svga/svga_pipe_blit.c @@ -50,7 +50,9 @@ static void svga_surface_copy(struct pipe_context *pipe, struct pipe_surface *srcsurf, *dstsurf;*/ unsigned dst_face, dst_z, src_face, src_z; - svga_hwtnl_flush_retry( svga ); + /* Emit buffered drawing commands, and any back copies. + */ + svga_surfaces_flush( svga ); #if 0 srcsurf = screen->get_tex_surface(screen, src_tex, diff --git a/src/gallium/drivers/svga/svga_pipe_draw.c b/src/gallium/drivers/svga/svga_pipe_draw.c index 001ec3616c4..d98b9b0e000 100644 --- a/src/gallium/drivers/svga/svga_pipe_draw.c +++ b/src/gallium/drivers/svga/svga_pipe_draw.c @@ -157,6 +157,14 @@ svga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info) if (!u_trim_pipe_prim( info->mode, &count )) return; + if (svga->state.sw.need_swtnl != svga->prev_draw_swtnl) { + /* We're switching between SW and HW drawing. Do a flush to avoid + * mixing HW and SW rendering with the same vertex buffer. + */ + pipe->flush(pipe, ~0, NULL); + svga->prev_draw_swtnl = svga->state.sw.need_swtnl; + } + /* * Mark currently bound target surfaces as dirty * doesn't really matter if it is done before drawing. diff --git a/src/gallium/drivers/svga/svga_pipe_flush.c b/src/gallium/drivers/svga/svga_pipe_flush.c index ab243aa6ec5..9357d827f28 100644 --- a/src/gallium/drivers/svga/svga_pipe_flush.c +++ b/src/gallium/drivers/svga/svga_pipe_flush.c @@ -24,6 +24,7 @@ **********************************************************/ #include "pipe/p_defines.h" +#include "util/u_string.h" #include "svga_screen.h" #include "svga_surface.h" #include "svga_context.h" @@ -35,20 +36,10 @@ static void svga_flush( struct pipe_context *pipe, struct pipe_fence_handle **fence ) { struct svga_context *svga = svga_context(pipe); - int i; - /* Emit buffered drawing commands. + /* Emit buffered drawing commands, and any back copies. */ - svga_hwtnl_flush_retry( svga ); - - /* Emit back-copy from render target view to texture. - */ - for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { - if (svga->curr.framebuffer.cbufs[i]) - svga_propagate_surface(pipe, svga->curr.framebuffer.cbufs[i]); - } - if (svga->curr.framebuffer.zsbuf) - svga_propagate_surface(pipe, svga->curr.framebuffer.zsbuf); + svga_surfaces_flush( svga ); /* Flush command queue. */ @@ -56,6 +47,28 @@ static void svga_flush( struct pipe_context *pipe, SVGA_DBG(DEBUG_DMA|DEBUG_PERF, "%s flags %x fence_ptr %p\n", __FUNCTION__, flags, fence ? *fence : 0x0); + + /* Enable to dump BMPs of the color/depth buffers each frame */ + if (0) { + if (flags & PIPE_FLUSH_FRAME) { + struct pipe_framebuffer_state *fb = &svga->curr.framebuffer; + static unsigned frame_no = 1; + char filename[256]; + unsigned i; + + for (i = 0; i < fb->nr_cbufs; i++) { + util_snprintf(filename, sizeof(filename), "cbuf%u_%04u", i, frame_no); + debug_dump_surface_bmp(&svga->pipe, filename, fb->cbufs[i]); + } + + if (0 && fb->zsbuf) { + util_snprintf(filename, sizeof(filename), "zsbuf_%04u", frame_no); + debug_dump_surface_bmp(&svga->pipe, filename, fb->zsbuf); + } + + ++frame_no; + } + } } diff --git a/src/gallium/drivers/svga/svga_pipe_misc.c b/src/gallium/drivers/svga/svga_pipe_misc.c index 8c24fb302f7..440919c6262 100644 --- a/src/gallium/drivers/svga/svga_pipe_misc.c +++ b/src/gallium/drivers/svga/svga_pipe_misc.c @@ -94,7 +94,7 @@ static void svga_set_framebuffer_state(struct pipe_context *pipe, for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) if (dst->cbufs[i] && dst->cbufs[i] != fb->cbufs[i]) - svga_propagate_surface(pipe, dst->cbufs[i]); + svga_propagate_surface(svga, dst->cbufs[i]); } /* XXX: Actually the virtual hardware may support rendertargets with diff --git a/src/gallium/drivers/svga/svga_pipe_rasterizer.c b/src/gallium/drivers/svga/svga_pipe_rasterizer.c index e97b4e57415..4a1a37f1765 100644 --- a/src/gallium/drivers/svga/svga_pipe_rasterizer.c +++ b/src/gallium/drivers/svga/svga_pipe_rasterizer.c @@ -64,7 +64,9 @@ static void * svga_create_rasterizer_state(struct pipe_context *pipe, const struct pipe_rasterizer_state *templ) { + struct svga_context *svga = svga_context(pipe); struct svga_rasterizer_state *rast = CALLOC_STRUCT( svga_rasterizer_state ); + /* need this for draw module. */ rast->templ = *templ; @@ -75,7 +77,6 @@ svga_create_rasterizer_state(struct pipe_context *pipe, /* point_quad_rasterization - ? */ /* point_size_per_vertex - ? */ /* sprite_coord_mode - ??? */ - /* bypass_vs_viewport_and_clip - handled by viewport setup */ /* flatshade_first - handled by index translation */ /* gl_rasterization_rules - XXX - viewport code */ /* line_width - draw module */ @@ -93,17 +94,22 @@ svga_create_rasterizer_state(struct pipe_context *pipe, /* Use swtnl + decomposition implement these: */ - if (templ->poly_stipple_enable) + if (templ->poly_stipple_enable) { rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS; + rast->need_pipeline_tris_str = "poly stipple"; + } - if (templ->line_width != 1.0 && - templ->line_width != 0.0) + if (templ->line_width >= 1.5f && + !svga->debug.no_line_width) { rast->need_pipeline |= SVGA_PIPELINE_FLAG_LINES; + rast->need_pipeline_lines_str = "line width"; + } if (templ->line_stipple_enable) { - /* LinePattern not implemented on all backends. + /* XXX: LinePattern not implemented on all backends, and there is no + * mechanism to query it. */ - if (0) { + if (!svga->debug.force_hw_line_stipple) { SVGA3dLinePattern lp; lp.repeat = templ->line_stipple_factor + 1; lp.pattern = templ->line_stipple_pattern; @@ -111,11 +117,19 @@ svga_create_rasterizer_state(struct pipe_context *pipe, } else { rast->need_pipeline |= SVGA_PIPELINE_FLAG_LINES; + rast->need_pipeline_lines_str = "line stipple"; } } - if (templ->point_smooth) + if (templ->point_smooth) { rast->need_pipeline |= SVGA_PIPELINE_FLAG_POINTS; + rast->need_pipeline_points_str = "smooth points"; + } + + if (templ->line_smooth) { + rast->need_pipeline |= SVGA_PIPELINE_FLAG_LINES; + rast->need_pipeline_lines_str = "smooth lines"; + } { int fill_front = templ->fill_front; @@ -148,6 +162,7 @@ svga_create_rasterizer_state(struct pipe_context *pipe, * front/back fill modes: */ rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS; + rast->need_pipeline_tris_str = "different front/back fillmodes"; } else { offset = offset_front; @@ -172,6 +187,7 @@ svga_create_rasterizer_state(struct pipe_context *pipe, { fill = PIPE_POLYGON_MODE_FILL; rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS; + rast->need_pipeline_tris_str = "unfilled primitives with no index manipulation"; } /* If we are decomposing to lines, and lines need the pipeline, @@ -182,6 +198,7 @@ svga_create_rasterizer_state(struct pipe_context *pipe, { fill = PIPE_POLYGON_MODE_FILL; rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS; + rast->need_pipeline_tris_str = "decomposing lines"; } /* Similarly for points: @@ -191,6 +208,7 @@ svga_create_rasterizer_state(struct pipe_context *pipe, { fill = PIPE_POLYGON_MODE_FILL; rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS; + rast->need_pipeline_tris_str = "decomposing points"; } if (offset) { @@ -201,9 +219,6 @@ svga_create_rasterizer_state(struct pipe_context *pipe, rast->hw_unfilled = fill; } - - - if (rast->need_pipeline & SVGA_PIPELINE_FLAG_TRIS) { /* Turn off stuff which will get done in the draw module: */ diff --git a/src/gallium/drivers/svga/svga_pipe_sampler.c b/src/gallium/drivers/svga/svga_pipe_sampler.c index f44a0e1325a..446fcc44078 100644 --- a/src/gallium/drivers/svga/svga_pipe_sampler.c +++ b/src/gallium/drivers/svga/svga_pipe_sampler.c @@ -144,8 +144,9 @@ svga_create_sampler_state(struct pipe_context *pipe, return cso; } -static void svga_bind_sampler_states(struct pipe_context *pipe, - unsigned num, void **sampler) +static void +svga_bind_fragment_sampler_states(struct pipe_context *pipe, + unsigned num, void **sampler) { struct svga_context *svga = svga_context(pipe); unsigned i; @@ -203,9 +204,10 @@ svga_sampler_view_destroy(struct pipe_context *pipe, FREE(view); } -static void svga_set_sampler_views(struct pipe_context *pipe, - unsigned num, - struct pipe_sampler_view **views) +static void +svga_set_fragment_sampler_views(struct pipe_context *pipe, + unsigned num, + struct pipe_sampler_view **views) { struct svga_context *svga = svga_context(pipe); unsigned flag_1d = 0; @@ -256,9 +258,9 @@ static void svga_set_sampler_views(struct pipe_context *pipe, void svga_init_sampler_functions( struct svga_context *svga ) { svga->pipe.create_sampler_state = svga_create_sampler_state; - svga->pipe.bind_fragment_sampler_states = svga_bind_sampler_states; + svga->pipe.bind_fragment_sampler_states = svga_bind_fragment_sampler_states; svga->pipe.delete_sampler_state = svga_delete_sampler_state; - svga->pipe.set_fragment_sampler_views = svga_set_sampler_views; + svga->pipe.set_fragment_sampler_views = svga_set_fragment_sampler_views; svga->pipe.create_sampler_view = svga_create_sampler_view; svga->pipe.sampler_view_destroy = svga_sampler_view_destroy; } diff --git a/src/gallium/drivers/svga/svga_pipe_vertex.c b/src/gallium/drivers/svga/svga_pipe_vertex.c index 86c79459f3e..58469910732 100644 --- a/src/gallium/drivers/svga/svga_pipe_vertex.c +++ b/src/gallium/drivers/svga/svga_pipe_vertex.c @@ -27,6 +27,7 @@ #include "pipe/p_defines.h" #include "util/u_math.h" #include "util/u_memory.h" +#include "util/u_transfer.h" #include "tgsi/tgsi_parse.h" #include "svga_screen.h" diff --git a/src/gallium/drivers/svga/svga_resource.c b/src/gallium/drivers/svga/svga_resource.c index ef2a0c40f03..bed15ec02e5 100644 --- a/src/gallium/drivers/svga/svga_resource.c +++ b/src/gallium/drivers/svga/svga_resource.c @@ -40,6 +40,7 @@ svga_init_resource_functions(struct svga_context *svga) svga->pipe.transfer_unmap = u_transfer_unmap_vtbl; svga->pipe.transfer_destroy = u_transfer_destroy_vtbl; svga->pipe.transfer_inline_write = u_transfer_inline_write_vtbl; + svga->pipe.redefine_user_buffer = svga_redefine_user_buffer; } void diff --git a/src/gallium/drivers/svga/svga_resource_buffer.c b/src/gallium/drivers/svga/svga_resource_buffer.c index f12e2b68627..e1f07d655b9 100644 --- a/src/gallium/drivers/svga/svga_resource_buffer.c +++ b/src/gallium/drivers/svga/svga_resource_buffer.c @@ -105,9 +105,12 @@ svga_buffer_map_range( struct pipe_screen *screen, * We can't create a hardware buffer big enough, so create a malloc * buffer instead. */ - debug_printf("%s: failed to allocate %u KB of DMA, splitting DMA transfers\n", - __FUNCTION__, - (sbuf->b.b.width0 + 1023)/1024); + if (0) { + debug_printf("%s: failed to allocate %u KB of DMA, " + "splitting DMA transfers\n", + __FUNCTION__, + (sbuf->b.b.width0 + 1023)/1024); + } sbuf->swbuf = align_malloc(sbuf->b.b.width0, 16); } @@ -308,6 +311,9 @@ svga_buffer_create(struct pipe_screen *screen, goto error2; } + debug_reference(&sbuf->b.b.reference, + (debug_reference_descriptor)debug_describe_resource, 0); + return &sbuf->b.b; error2: @@ -341,6 +347,9 @@ svga_user_buffer_create(struct pipe_screen *screen, sbuf->swbuf = ptr; sbuf->user = TRUE; + + debug_reference(&sbuf->b.b.reference, + (debug_reference_descriptor)debug_describe_resource, 0); return &sbuf->b.b; diff --git a/src/gallium/drivers/svga/svga_resource_buffer.h b/src/gallium/drivers/svga/svga_resource_buffer.h index d3ec11bfd52..c559f70ec12 100644 --- a/src/gallium/drivers/svga/svga_resource_buffer.h +++ b/src/gallium/drivers/svga/svga_resource_buffer.h @@ -243,4 +243,10 @@ svga_winsys_buffer_create(struct svga_context *svga, unsigned usage, unsigned size); +void +svga_redefine_user_buffer(struct pipe_context *ctx, + struct pipe_resource *resource, + unsigned offset, + unsigned size); + #endif /* SVGA_BUFFER_H */ diff --git a/src/gallium/drivers/svga/svga_resource_buffer_upload.c b/src/gallium/drivers/svga/svga_resource_buffer_upload.c index 3de5216a949..76a3803224a 100644 --- a/src/gallium/drivers/svga/svga_resource_buffer_upload.c +++ b/src/gallium/drivers/svga/svga_resource_buffer_upload.c @@ -40,6 +40,9 @@ #include "svga_debug.h" +#define MAX_DMA_SIZE (8 * 1024 * 1024) + + /** * Allocate a winsys_buffer (ie. DMA, aka GMR memory). * @@ -57,6 +60,13 @@ svga_winsys_buffer_create( struct svga_context *svga, struct svga_winsys_screen *sws = svgascreen->sws; struct svga_winsys_buffer *buf; + /* XXX this shouldn't be a hard-coded number; it should be queried + * somehow. + */ + if (size > MAX_DMA_SIZE) { + return NULL; + } + /* Just try */ buf = sws->buffer_create(sws, alignment, usage, size); if(!buf) { @@ -248,6 +258,7 @@ svga_buffer_upload_flush(struct svga_context *svga, { SVGA3dCopyBox *boxes; unsigned i; + struct pipe_resource *dummy; assert(sbuf->handle); assert(sbuf->hwbuf); @@ -289,9 +300,9 @@ svga_buffer_upload_flush(struct svga_context *svga, sbuf->dma.svga = NULL; sbuf->dma.boxes = NULL; - /* Decrement reference count */ - pipe_reference(&(sbuf->b.b.reference), NULL); - sbuf = NULL; + /* Decrement reference count (and potentially destroy) */ + dummy = &sbuf->b.b; + pipe_resource_reference(&dummy, NULL); } @@ -638,3 +649,54 @@ svga_context_flush_buffers(struct svga_context *svga) next = curr->next; } } + + +void +svga_redefine_user_buffer(struct pipe_context *pipe, + struct pipe_resource *resource, + unsigned offset, + unsigned size) +{ + struct svga_screen *ss = svga_screen(pipe->screen); + struct svga_context *svga = svga_context(pipe); + struct svga_buffer *sbuf = svga_buffer(resource); + + assert(sbuf->user); + + /* + * Release any uploaded user buffer. + * + * TODO: As an optimization, we could try to update the uploaded buffer + * instead. + */ + + pipe_resource_reference(&sbuf->uploaded.buffer, NULL); + + pipe_mutex_lock(ss->swc_mutex); + + if (offset + size > resource->width0) { + /* + * User buffers shouldn't have DMA directly, unless + * SVGA_COMBINE_USERBUFFERS is not set. + */ + + if (sbuf->dma.pending) { + svga_buffer_upload_flush(svga, sbuf); + } + + if (sbuf->handle) { + svga_buffer_destroy_host_surface(ss, sbuf); + } + + if (sbuf->hwbuf) { + svga_buffer_destroy_hw_storage(ss, sbuf); + } + + sbuf->key.size.width = sbuf->b.b.width0 = offset + size; + } + + pipe_mutex_unlock(ss->swc_mutex); + + svga->curr.any_user_vertex_buffers = TRUE; + svga->dirty |= SVGA_NEW_VBUFFER | SVGA_NEW_VELEMENT; +} diff --git a/src/gallium/drivers/svga/svga_resource_texture.c b/src/gallium/drivers/svga/svga_resource_texture.c index 7c9e600b9f4..994f30719ae 100644 --- a/src/gallium/drivers/svga/svga_resource_texture.c +++ b/src/gallium/drivers/svga/svga_resource_texture.c @@ -146,16 +146,6 @@ svga_translate_format_render(enum pipe_format format) case PIPE_FORMAT_L8_UNORM: return svga_translate_format(format); -#if 1 - /* For on host conversion */ - case PIPE_FORMAT_DXT1_RGB: - return SVGA3D_X8R8G8B8; - case PIPE_FORMAT_DXT1_RGBA: - case PIPE_FORMAT_DXT3_RGBA: - case PIPE_FORMAT_DXT5_RGBA: - return SVGA3D_A8R8G8B8; -#endif - default: return SVGA3D_FORMAT_INVALID; } @@ -204,7 +194,7 @@ svga_transfer_dma_band(struct svga_context *svga, ret = SVGA3D_SurfaceDMA(svga->swc, st, transfer, &box, 1); if(ret != PIPE_OK) { - svga->swc->flush(svga->swc, NULL); + svga_context_flush(svga, NULL); ret = SVGA3D_SurfaceDMA(svga->swc, st, transfer, &box, 1); assert(ret == PIPE_OK); } @@ -225,6 +215,10 @@ svga_transfer_dma(struct svga_context *svga, SVGA_DBG(DEBUG_PERF, "%s: readback transfer\n", __FUNCTION__); } + /* Ensure any pending operations on host surfaces are queued on the command + * buffer first. + */ + svga_surfaces_flush( svga ); if(!st->swbuf) { /* Do the DMA transfer in a single go */ @@ -390,11 +384,15 @@ svga_texture_get_transfer(struct pipe_context *pipe, if(st->hw_nblocksy < nblocksy) { /* We couldn't allocate a hardware buffer big enough for the transfer, * so allocate regular malloc memory instead */ - debug_printf("%s: failed to allocate %u KB of DMA, splitting into %u x %u KB DMA transfers\n", - __FUNCTION__, - (nblocksy*st->base.stride + 1023)/1024, - (nblocksy + st->hw_nblocksy - 1)/st->hw_nblocksy, - (st->hw_nblocksy*st->base.stride + 1023)/1024); + if (0) { + debug_printf("%s: failed to allocate %u KB of DMA, " + "splitting into %u x %u KB DMA transfers\n", + __FUNCTION__, + (nblocksy*st->base.stride + 1023)/1024, + (nblocksy + st->hw_nblocksy - 1)/st->hw_nblocksy, + (st->hw_nblocksy*st->base.stride + 1023)/1024); + } + st->swbuf = MALLOC(nblocksy*st->base.stride); if(!st->swbuf) goto no_swbuf; @@ -527,7 +525,8 @@ svga_texture_create(struct pipe_screen *screen, tex->key.numFaces = 1; } - tex->key.cachable = 1; + /* XXX: Disabled for now */ + tex->key.cachable = 0; if (template->bind & PIPE_BIND_SAMPLER_VIEW) tex->key.flags |= SVGA3D_SURFACE_HINT_TEXTURE; @@ -571,6 +570,9 @@ svga_texture_create(struct pipe_screen *screen, if (tex->handle) SVGA_DBG(DEBUG_DMA, " --> got sid %p (texture)\n", tex->handle); + debug_reference(&tex->b.b.reference, + (debug_reference_descriptor)debug_describe_resource, 0); + return &tex->b.b; error2: diff --git a/src/gallium/drivers/svga/svga_sampler_view.c b/src/gallium/drivers/svga/svga_sampler_view.c index 6911f13f778..4f1f4b597e8 100644 --- a/src/gallium/drivers/svga/svga_sampler_view.c +++ b/src/gallium/drivers/svga/svga_sampler_view.c @@ -32,6 +32,7 @@ #include "util/u_format.h" #include "util/u_math.h" #include "util/u_memory.h" +#include "util/u_string.h" #include "svga_screen.h" #include "svga_context.h" @@ -41,14 +42,24 @@ #include "svga_surface.h" +void +svga_debug_describe_sampler_view(char *buf, const struct svga_sampler_view *sv) +{ + char res[128]; + debug_describe_resource(res, sv->texture); + util_sprintf(buf, "svga_sampler_view<%s,[%u,%u]>", res, sv->min_lod, sv->max_lod); +} + struct svga_sampler_view * svga_get_tex_sampler_view(struct pipe_context *pipe, struct pipe_resource *pt, unsigned min_lod, unsigned max_lod) { - struct svga_screen *ss = svga_screen(pt->screen); + struct svga_context *svga = svga_context(pipe); + struct svga_screen *ss = svga_screen(pipe->screen); struct svga_texture *tex = svga_texture(pt); struct svga_sampler_view *sv = NULL; + SVGA3dSurfaceFlags flags = SVGA3D_SURFACE_HINT_TEXTURE; SVGA3dSurfaceFormat format = svga_translate_format(pt->format); boolean view = TRUE; @@ -68,10 +79,6 @@ svga_get_tex_sampler_view(struct pipe_context *pipe, if (min_lod == 0 && max_lod >= pt->last_level) view = FALSE; - if (util_format_is_s3tc(pt->format) && view) { - format = svga_translate_format_render(pt->format); - } - if (ss->debug.no_sampler_view) view = FALSE; @@ -113,6 +120,8 @@ svga_get_tex_sampler_view(struct pipe_context *pipe, pt->last_level); sv->key.cachable = 0; sv->handle = tex->handle; + debug_reference(&sv->reference, + (debug_reference_descriptor)svga_debug_describe_sampler_view, 0); return sv; } @@ -126,7 +135,7 @@ svga_get_tex_sampler_view(struct pipe_context *pipe, pt->last_level); sv->age = tex->age; - sv->handle = svga_texture_view_surface(pipe, tex, format, + sv->handle = svga_texture_view_surface(svga, tex, flags, format, min_lod, max_lod - min_lod + 1, -1, -1, @@ -136,6 +145,8 @@ svga_get_tex_sampler_view(struct pipe_context *pipe, assert(0); sv->key.cachable = 0; sv->handle = tex->handle; + debug_reference(&sv->reference, + (debug_reference_descriptor)svga_debug_describe_sampler_view, 0); return sv; } @@ -143,6 +154,9 @@ svga_get_tex_sampler_view(struct pipe_context *pipe, svga_sampler_view_reference(&tex->cached_view, sv); pipe_mutex_unlock(ss->tex_mutex); + debug_reference(&sv->reference, + (debug_reference_descriptor)svga_debug_describe_sampler_view, 0); + return sv; } diff --git a/src/gallium/drivers/svga/svga_sampler_view.h b/src/gallium/drivers/svga/svga_sampler_view.h index e64665f2e58..2087c1be85e 100644 --- a/src/gallium/drivers/svga/svga_sampler_view.h +++ b/src/gallium/drivers/svga/svga_sampler_view.h @@ -83,12 +83,16 @@ svga_validate_sampler_view(struct svga_context *svga, struct svga_sampler_view * void svga_destroy_sampler_view_priv(struct svga_sampler_view *v); +void +svga_debug_describe_sampler_view(char *buf, const struct svga_sampler_view *sv); + static INLINE void svga_sampler_view_reference(struct svga_sampler_view **ptr, struct svga_sampler_view *v) { struct svga_sampler_view *old = *ptr; - if (pipe_reference(&(*ptr)->reference, &v->reference)) + if (pipe_reference_described(&(*ptr)->reference, &v->reference, + (debug_reference_descriptor)svga_debug_describe_sampler_view)) svga_destroy_sampler_view_priv(old); *ptr = v; } diff --git a/src/gallium/drivers/svga/svga_screen.c b/src/gallium/drivers/svga/svga_screen.c index d0f42c614c9..ef1d3098d51 100644 --- a/src/gallium/drivers/svga/svga_screen.c +++ b/src/gallium/drivers/svga/svga_screen.c @@ -225,13 +225,18 @@ static int svga_get_shader_param(struct pipe_screen *screen, unsigned shader, en return svgascreen->use_ps30 ? 32 : 12; return result.u; case PIPE_SHADER_CAP_MAX_ADDRS: - return svgascreen->use_ps30 ? 1 : 0; + case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR: + /* + * Although PS 3.0 has some addressing abilities it can only represent + * loops that can be statically determined and unrolled. Given we can + * only handle a subset of the cases that the state tracker already + * does it is better to defer loop unrolling to the state tracker. + */ + return 0; case PIPE_SHADER_CAP_MAX_PREDS: return svgascreen->use_ps30 ? 1 : 0; case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED: return 1; - case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR: - return svgascreen->use_ps30 ? 1 : 0; case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR: case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR: case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR: @@ -360,13 +365,6 @@ svga_is_format_supported( struct pipe_screen *screen, case PIPE_FORMAT_B5G5R5A1_UNORM: return FALSE; - /* Simulate ability to render into compressed textures */ - case PIPE_FORMAT_DXT1_RGB: - case PIPE_FORMAT_DXT1_RGBA: - case PIPE_FORMAT_DXT3_RGBA: - case PIPE_FORMAT_DXT5_RGBA: - return TRUE; - default: break; } diff --git a/src/gallium/drivers/svga/svga_state.h b/src/gallium/drivers/svga/svga_state.h index 22d5a6d552a..7f239e7a322 100644 --- a/src/gallium/drivers/svga/svga_state.h +++ b/src/gallium/drivers/svga/svga_state.h @@ -92,4 +92,8 @@ void svga_update_state_retry( struct svga_context *svga, enum pipe_error svga_emit_initial_state( struct svga_context *svga ); +enum pipe_error svga_reemit_framebuffer_bindings( struct svga_context *svga ); + +enum pipe_error svga_reemit_tss_bindings( struct svga_context *svga ); + #endif diff --git a/src/gallium/drivers/svga/svga_state_framebuffer.c b/src/gallium/drivers/svga/svga_state_framebuffer.c index fcbb35e7972..cdadb20c178 100644 --- a/src/gallium/drivers/svga/svga_state_framebuffer.c +++ b/src/gallium/drivers/svga/svga_state_framebuffer.c @@ -93,6 +93,55 @@ static int emit_framebuffer( struct svga_context *svga, } +/* + * Rebind rendertargets. + * + * Similar to emit_framebuffer, but without any state checking/update. + * + * Called at the beginning of every new command buffer to ensure that + * non-dirty rendertargets are properly paged-in. + */ +enum pipe_error +svga_reemit_framebuffer_bindings(struct svga_context *svga) +{ + struct pipe_framebuffer_state *hw = &svga->state.hw_clear.framebuffer; + unsigned i; + enum pipe_error ret; + + for (i = 0; i < MIN2(PIPE_MAX_COLOR_BUFS, 8); ++i) { + if (hw->cbufs[i]) { + ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_COLOR0 + i, hw->cbufs[i]); + if (ret != PIPE_OK) { + return ret; + } + } + } + + if (hw->zsbuf) { + ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_DEPTH, hw->zsbuf); + if (ret != PIPE_OK) { + return ret; + } + + if (hw->zsbuf && + hw->zsbuf->format == PIPE_FORMAT_S8_USCALED_Z24_UNORM) { + ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_STENCIL, hw->zsbuf); + if (ret != PIPE_OK) { + return ret; + } + } + else { + ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_STENCIL, NULL); + if (ret != PIPE_OK) { + return ret; + } + } + } + + return PIPE_OK; +} + + struct svga_tracked_state svga_hw_framebuffer = { "hw framebuffer state", diff --git a/src/gallium/drivers/svga/svga_state_need_swtnl.c b/src/gallium/drivers/svga/svga_state_need_swtnl.c index 8ba5ac8cdb4..68c02578789 100644 --- a/src/gallium/drivers/svga/svga_state_need_swtnl.c +++ b/src/gallium/drivers/svga/svga_state_need_swtnl.c @@ -35,6 +35,11 @@ /*********************************************************************** */ + +/** + * Given a gallium vertex element format, return the corresponding SVGA3D + * format. Return SVGA3D_DECLTYPE_MAX for unsupported gallium formats. + */ static INLINE SVGA3dDeclType svga_translate_vertex_format(enum pipe_format format) { @@ -80,6 +85,7 @@ static int update_need_swvfetch( struct svga_context *svga, for (i = 0; i < svga->curr.velems->count; i++) { svga->state.sw.ve_format[i] = svga_translate_vertex_format(svga->curr.velems->velem[i].src_format); if (svga->state.sw.ve_format[i] == SVGA3D_DECLTYPE_MAX) { + /* Unsupported format - use software fetch */ need_swvfetch = TRUE; break; } @@ -118,6 +124,11 @@ static int update_need_pipeline( struct svga_context *svga, __FUNCTION__, svga->curr.rast->need_pipeline, (1 << svga->curr.reduced_prim) ); + SVGA_DBG(DEBUG_SWTNL, "%s: rast need_pipeline tris (%s), lines (%s), points (%s)\n", + __FUNCTION__, + svga->curr.rast->need_pipeline_tris_str, + svga->curr.rast->need_pipeline_lines_str, + svga->curr.rast->need_pipeline_points_str); need_pipeline = TRUE; } @@ -140,6 +151,10 @@ static int update_need_pipeline( struct svga_context *svga, svga->dirty |= SVGA_NEW_NEED_PIPELINE; } + /* DEBUG */ + if (0 && svga->state.sw.need_pipeline) + debug_printf("sw.need_pipeline = %d\n", svga->state.sw.need_pipeline); + return 0; } @@ -164,15 +179,15 @@ static int update_need_swtnl( struct svga_context *svga, boolean need_swtnl; if (svga->debug.no_swtnl) { - svga->state.sw.need_swvfetch = 0; - svga->state.sw.need_pipeline = 0; + svga->state.sw.need_swvfetch = FALSE; + svga->state.sw.need_pipeline = FALSE; } need_swtnl = (svga->state.sw.need_swvfetch || svga->state.sw.need_pipeline); if (svga->debug.force_swtnl) { - need_swtnl = 1; + need_swtnl = TRUE; } /* @@ -181,7 +196,7 @@ static int update_need_swtnl( struct svga_context *svga, * the wrong buffers and vertex formats. Try trivial/line-wide. */ if (svga->state.sw.in_swtnl_draw) - need_swtnl = 1; + need_swtnl = TRUE; if (need_swtnl != svga->state.sw.need_swtnl) { SVGA_DBG(DEBUG_SWTNL|DEBUG_PERF, diff --git a/src/gallium/drivers/svga/svga_state_tss.c b/src/gallium/drivers/svga/svga_state_tss.c index f8b269a101e..c502506b93b 100644 --- a/src/gallium/drivers/svga/svga_state_tss.c +++ b/src/gallium/drivers/svga/svga_state_tss.c @@ -52,6 +52,16 @@ void svga_cleanup_tss_binding(struct svga_context *svga) } +struct bind_queue { + struct { + unsigned unit; + struct svga_hw_view_state *view; + } bind[PIPE_MAX_SAMPLERS]; + + unsigned bind_count; +}; + + static int update_tss_binding(struct svga_context *svga, unsigned dirty ) @@ -63,15 +73,7 @@ update_tss_binding(struct svga_context *svga, unsigned min_lod; unsigned max_lod; - - struct { - struct { - unsigned unit; - struct svga_hw_view_state *view; - } bind[PIPE_MAX_SAMPLERS]; - - unsigned bind_count; - } queue; + struct bind_queue queue; queue.bind_count = 0; @@ -164,6 +166,64 @@ fail: } +/* + * Rebind textures. + * + * Similar to update_tss_binding, but without any state checking/update. + * + * Called at the beginning of every new command buffer to ensure that + * non-dirty textures are properly paged-in. + */ +enum pipe_error +svga_reemit_tss_bindings(struct svga_context *svga) +{ + unsigned i; + enum pipe_error ret; + struct bind_queue queue; + + queue.bind_count = 0; + + for (i = 0; i < svga->state.hw_draw.num_views; i++) { + struct svga_hw_view_state *view = &svga->state.hw_draw.views[i]; + + if (view->v) { + queue.bind[queue.bind_count].unit = i; + queue.bind[queue.bind_count].view = view; + queue.bind_count++; + } + } + + if (queue.bind_count) { + SVGA3dTextureState *ts; + + ret = SVGA3D_BeginSetTextureState(svga->swc, + &ts, + queue.bind_count); + if (ret != PIPE_OK) { + return ret; + } + + for (i = 0; i < queue.bind_count; i++) { + struct svga_winsys_surface *handle; + + ts[i].stage = queue.bind[i].unit; + ts[i].name = SVGA3D_TS_BIND_TEXTURE; + + assert(queue.bind[i].view->v); + handle = queue.bind[i].view->v->handle; + svga->swc->surface_relocation(svga->swc, + &ts[i].value, + handle, + SVGA_RELOC_READ); + } + + SVGA_FIFOCommitAll(svga->swc); + } + + return PIPE_OK; +} + + struct svga_tracked_state svga_hw_tss_binding = { "texture binding emit", SVGA_NEW_TEXTURE_BINDING | diff --git a/src/gallium/drivers/svga/svga_state_vs.c b/src/gallium/drivers/svga/svga_state_vs.c index 6682a1efe66..ae9a20ebb81 100644 --- a/src/gallium/drivers/svga/svga_state_vs.c +++ b/src/gallium/drivers/svga/svga_state_vs.c @@ -229,7 +229,7 @@ static int update_zero_stride( struct svga_context *svga, translate->set_buffer(translate, vel->vertex_buffer_index, mapped_buffer, - vbuffer->stride, vbuffer->max_index); + vbuffer->stride, ~0); translate->run(translate, 0, 1, 0, svga->curr.zero_stride_constants); diff --git a/src/gallium/drivers/svga/svga_surface.c b/src/gallium/drivers/svga/svga_surface.c index 3e4bed76c05..3e8fb5f0271 100644 --- a/src/gallium/drivers/svga/svga_surface.c +++ b/src/gallium/drivers/svga/svga_surface.c @@ -100,8 +100,9 @@ svga_texture_copy_handle(struct svga_context *svga, struct svga_winsys_surface * -svga_texture_view_surface(struct pipe_context *pipe, +svga_texture_view_surface(struct svga_context *svga, struct svga_texture *tex, + SVGA3dSurfaceFlags flags, SVGA3dSurfaceFormat format, unsigned start_mip, unsigned num_mip, @@ -109,7 +110,7 @@ svga_texture_view_surface(struct pipe_context *pipe, int zslice_pick, struct svga_host_surface_cache_key *key) /* OUT */ { - struct svga_screen *ss = svga_screen(pipe->screen); + struct svga_screen *ss = svga_screen(svga->pipe.screen); struct svga_winsys_surface *handle; uint32_t i, j; unsigned z_offset = 0; @@ -118,7 +119,7 @@ svga_texture_view_surface(struct pipe_context *pipe, "svga: Create surface view: face %d zslice %d mips %d..%d\n", face_pick, zslice_pick, start_mip, start_mip+num_mip-1); - key->flags = 0; + key->flags = flags; key->format = format; key->numMipLevels = num_mip; key->size.width = u_minify(tex->b.b.width0, start_mip); @@ -161,7 +162,7 @@ svga_texture_view_surface(struct pipe_context *pipe, u_minify(tex->b.b.depth0, i + start_mip) : 1); - svga_texture_copy_handle(svga_context(pipe), + svga_texture_copy_handle(svga, tex->handle, 0, 0, z_offset, i + start_mip, @@ -183,6 +184,7 @@ svga_create_surface(struct pipe_context *pipe, struct pipe_resource *pt, const struct pipe_surface *surf_tmpl) { + struct svga_context *svga = svga_context(pipe); struct svga_texture *tex = svga_texture(pt); struct pipe_screen *screen = pipe->screen; struct svga_surface *s; @@ -191,6 +193,7 @@ svga_create_surface(struct pipe_context *pipe, boolean render = (surf_tmpl->usage & (PIPE_BIND_RENDER_TARGET | PIPE_BIND_DEPTH_STENCIL)) ? TRUE : FALSE; boolean view = FALSE; + SVGA3dSurfaceFlags flags; SVGA3dSurfaceFormat format; assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer); @@ -219,10 +222,18 @@ svga_create_surface(struct pipe_context *pipe, s->base.u.tex.first_layer = surf_tmpl->u.tex.first_layer; s->base.u.tex.last_layer = surf_tmpl->u.tex.last_layer; - if (!render) + if (!render) { + flags = SVGA3D_SURFACE_HINT_TEXTURE; format = svga_translate_format(surf_tmpl->format); - else + } else { + if (surf_tmpl->usage & PIPE_BIND_RENDER_TARGET) { + flags = SVGA3D_SURFACE_HINT_RENDERTARGET; + } + if (surf_tmpl->usage & PIPE_BIND_DEPTH_STENCIL) { + flags = SVGA3D_SURFACE_HINT_DEPTHSTENCIL; + } format = svga_translate_format_render(surf_tmpl->format); + } assert(format != SVGA3D_FORMAT_INVALID); @@ -249,7 +260,8 @@ svga_create_surface(struct pipe_context *pipe, SVGA_DBG(DEBUG_VIEWS, "svga: Surface view: yes %p, level %u face %u z %u, %p\n", pt, surf_tmpl->u.tex.level, face, zslice, s); - s->handle = svga_texture_view_surface(NULL, tex, format, surf_tmpl->u.tex.level, + s->handle = svga_texture_view_surface(svga, tex, flags, format, + surf_tmpl->u.tex.level, 1, face, zslice, &s->key); s->real_face = 0; s->real_level = 0; @@ -329,7 +341,7 @@ void svga_mark_surfaces_dirty(struct svga_context *svga) * pipe is optional context to inline the blit command in. */ void -svga_propagate_surface(struct pipe_context *pipe, struct pipe_surface *surf) +svga_propagate_surface(struct svga_context *svga, struct pipe_surface *surf) { struct svga_surface *s = svga_surface(surf); struct svga_texture *tex = svga_texture(surf->texture); @@ -354,7 +366,7 @@ svga_propagate_surface(struct pipe_context *pipe, struct pipe_surface *surf) if (s->handle != tex->handle) { SVGA_DBG(DEBUG_VIEWS, "svga: Surface propagate: tex %p, level %u, from %p\n", tex, surf->u.tex.level, surf); - svga_texture_copy_handle(svga_context(pipe), + svga_texture_copy_handle(svga, s->handle, 0, 0, 0, s->real_level, s->real_face, tex->handle, 0, 0, zslice, surf->u.tex.level, face, u_minify(tex->b.b.width0, surf->u.tex.level), diff --git a/src/gallium/drivers/svga/svga_surface.h b/src/gallium/drivers/svga/svga_surface.h index afb8326e1f3..bffc8c22c60 100644 --- a/src/gallium/drivers/svga/svga_surface.h +++ b/src/gallium/drivers/svga/svga_surface.h @@ -56,14 +56,15 @@ struct svga_surface extern void -svga_propagate_surface(struct pipe_context *pipe, struct pipe_surface *surf); +svga_propagate_surface(struct svga_context *svga, struct pipe_surface *surf); extern boolean svga_surface_needs_propagation(struct pipe_surface *surf); struct svga_winsys_surface * -svga_texture_view_surface(struct pipe_context *pipe, +svga_texture_view_surface(struct svga_context *svga, struct svga_texture *tex, + SVGA3dSurfaceFlags flags, SVGA3dSurfaceFormat format, unsigned start_mip, unsigned num_mip, diff --git a/src/gallium/drivers/svga/svga_swtnl_backend.c b/src/gallium/drivers/svga/svga_swtnl_backend.c index d5db6bf641a..ac9d637f8cb 100644 --- a/src/gallium/drivers/svga/svga_swtnl_backend.c +++ b/src/gallium/drivers/svga/svga_swtnl_backend.c @@ -87,11 +87,14 @@ svga_vbuf_render_allocate_vertices( struct vbuf_render *render, svga_render->vbuf_size = MAX2(size, svga_render->vbuf_alloc_size); svga_render->vbuf = pipe_buffer_create(screen, PIPE_BIND_VERTEX_BUFFER, + PIPE_USAGE_STREAM, svga_render->vbuf_size); if(!svga_render->vbuf) { svga_context_flush(svga, NULL); + assert(!svga_render->vbuf); svga_render->vbuf = pipe_buffer_create(screen, PIPE_BIND_VERTEX_BUFFER, + PIPE_USAGE_STREAM, svga_render->vbuf_size); assert(svga_render->vbuf); } @@ -261,6 +264,7 @@ svga_vbuf_render_draw_elements( struct vbuf_render *render, svga_render->ibuf_size = MAX2(size, svga_render->ibuf_alloc_size); svga_render->ibuf = pipe_buffer_create(screen, PIPE_BIND_INDEX_BUFFER, + PIPE_USAGE_STREAM, svga_render->ibuf_size); svga_render->ibuf_offset = 0; } diff --git a/src/gallium/drivers/svga/svga_swtnl_draw.c b/src/gallium/drivers/svga/svga_swtnl_draw.c index 05d86e1fb16..ad29c1b6425 100644 --- a/src/gallium/drivers/svga/svga_swtnl_draw.c +++ b/src/gallium/drivers/svga/svga_swtnl_draw.c @@ -124,6 +124,7 @@ svga_swtnl_draw_vbo(struct svga_context *svga, /* Now safe to remove the need_swtnl flag in any update_state call */ svga->state.sw.in_swtnl_draw = FALSE; + svga->dirty |= SVGA_NEW_NEED_PIPELINE | SVGA_NEW_NEED_SWVFETCH; return ret; } diff --git a/src/gallium/drivers/svga/svga_swtnl_state.c b/src/gallium/drivers/svga/svga_swtnl_state.c index a7592382936..efda2f605b9 100644 --- a/src/gallium/drivers/svga/svga_swtnl_state.c +++ b/src/gallium/drivers/svga/svga_swtnl_state.c @@ -61,7 +61,7 @@ static void set_draw_viewport( struct svga_context *svga ) * going to be drawn with triangles, but we're not catching all * cases where that will happen. */ - if (svga->curr.rast->templ.line_width > 1.0) + if (svga->curr.rast->need_pipeline & SVGA_PIPELINE_FLAG_LINES) { adjx = SVGA_LINE_ADJ_X + 0.175; adjy = SVGA_LINE_ADJ_Y - 0.175; diff --git a/src/gallium/drivers/svga/svga_tgsi_insn.c b/src/gallium/drivers/svga/svga_tgsi_insn.c index f2591c5721a..99600cf5c00 100644 --- a/src/gallium/drivers/svga/svga_tgsi_insn.c +++ b/src/gallium/drivers/svga/svga_tgsi_insn.c @@ -57,7 +57,6 @@ translate_opcode( case TGSI_OPCODE_MUL: return SVGA3DOP_MUL; case TGSI_OPCODE_NOP: return SVGA3DOP_NOP; case TGSI_OPCODE_NRM4: return SVGA3DOP_NRM; - case TGSI_OPCODE_SSG: return SVGA3DOP_SGN; default: debug_printf("Unkown opcode %u\n", opcode); assert( 0 ); @@ -285,6 +284,41 @@ static void reset_temp_regs( struct svga_shader_emitter *emit ) } +/* Replace the src with the temporary specified in the dst, but copying + * only the necessary channels, and preserving the original swizzle (which is + * important given that several opcodes have constraints in the allowed + * swizzles). + */ +static boolean emit_repl( struct svga_shader_emitter *emit, + SVGA3dShaderDestToken dst, + struct src_register *src0) +{ + unsigned src0_swizzle; + unsigned chan; + + assert(SVGA3dShaderGetRegType(dst.value) == SVGA3DREG_TEMP); + + src0_swizzle = src0->base.swizzle; + + dst.mask = 0; + for (chan = 0; chan < 4; ++chan) { + unsigned swizzle = (src0_swizzle >> (chan *2)) & 0x3; + dst.mask |= 1 << swizzle; + } + assert(dst.mask); + + src0->base.swizzle = SVGA3DSWIZZLE_NONE; + + if (!emit_op1( emit, inst_token( SVGA3DOP_MOV ), dst, *src0 )) + return FALSE; + + *src0 = src( dst ); + src0->base.swizzle = src0_swizzle; + + return TRUE; +} + + static boolean submit_op0( struct svga_shader_emitter *emit, SVGA3dShaderInstToken inst, SVGA3dShaderDestToken dest ) @@ -333,14 +367,11 @@ static boolean submit_op2( struct svga_shader_emitter *emit, src0.base.num != src1.base.num) need_temp = TRUE; - if (need_temp) - { + if (need_temp) { temp = get_temp( emit ); - if (!emit_op1( emit, inst_token( SVGA3DOP_MOV ), temp, src0 )) + if (!emit_repl( emit, temp, &src0 )) return FALSE; - - src0 = src( temp ); } if (!emit_op2( emit, inst, dest, src0, src1 )) @@ -396,24 +427,18 @@ static boolean submit_op3( struct svga_shader_emitter *emit, (type2 == SVGA3DREG_INPUT && src1.base.num != src2.base.num)) need_temp1 = TRUE; - if (need_temp0) - { + if (need_temp0) { temp0 = get_temp( emit ); - if (!emit_op1( emit, inst_token( SVGA3DOP_MOV ), temp0, src0 )) + if (!emit_repl( emit, temp0, &src0 )) return FALSE; - - src0 = src( temp0 ); } - if (need_temp1) - { + if (need_temp1) { temp1 = get_temp( emit ); - if (!emit_op1( emit, inst_token( SVGA3DOP_MOV ), temp1, src1 )) + if (!emit_repl( emit, temp1, &src1 )) return FALSE; - - src1 = src( temp1 ); } if (!emit_op3( emit, inst, dest, src0, src1, src2 )) @@ -478,24 +503,18 @@ static boolean submit_op4( struct svga_shader_emitter *emit, (type2 == SVGA3DREG_INPUT && src3.base.num != src2.base.num)) need_temp3 = TRUE; - if (need_temp0) - { + if (need_temp0) { temp0 = get_temp( emit ); - if (!emit_op1( emit, inst_token( SVGA3DOP_MOV ), temp0, src0 )) + if (!emit_repl( emit, temp0, &src0 )) return FALSE; - - src0 = src( temp0 ); } - if (need_temp3) - { + if (need_temp3) { temp3 = get_temp( emit ); - if (!emit_op1( emit, inst_token( SVGA3DOP_MOV ), temp3, src3 )) + if (!emit_repl( emit, temp3, &src3 )) return FALSE; - - src3 = src( temp3 ); } if (!emit_op4( emit, inst, dest, src0, src1, src2, src3 )) @@ -509,6 +528,55 @@ static boolean submit_op4( struct svga_shader_emitter *emit, } +static boolean alias_src_dst( struct src_register src, + SVGA3dShaderDestToken dst ) +{ + if (src.base.num != dst.num) + return FALSE; + + if (SVGA3dShaderGetRegType(dst.value) != + SVGA3dShaderGetRegType(src.base.value)) + return FALSE; + + return TRUE; +} + + +static boolean submit_lrp(struct svga_shader_emitter *emit, + SVGA3dShaderDestToken dst, + struct src_register src0, + struct src_register src1, + struct src_register src2) +{ + SVGA3dShaderDestToken tmp; + boolean need_dst_tmp = FALSE; + + /* The dst reg must be a temporary, and not be the same as src0 or src2 */ + if (SVGA3dShaderGetRegType(dst.value) != SVGA3DREG_TEMP || + alias_src_dst(src0, dst) || + alias_src_dst(src2, dst)) + need_dst_tmp = TRUE; + + if (need_dst_tmp) { + tmp = get_temp( emit ); + tmp.mask = dst.mask; + } + else { + tmp = dst; + } + + if (!submit_op3(emit, inst_token( SVGA3DOP_LRP ), tmp, src0, src1, src2)) + return FALSE; + + if (need_dst_tmp) { + if (!submit_op1(emit, inst_token( SVGA3DOP_MOV ), dst, src( tmp ))) + return FALSE; + } + + return TRUE; +} + + static boolean emit_def_const( struct svga_shader_emitter *emit, SVGA3dShaderConstType type, unsigned idx, @@ -747,7 +815,7 @@ static boolean emit_fake_arl(struct svga_shader_emitter *emit, static boolean emit_if(struct svga_shader_emitter *emit, const struct tgsi_full_instruction *insn) { - const struct src_register src = translate_src_register( + struct src_register src0 = translate_src_register( emit, &insn->Src[0] ); struct src_register zero = get_zero_immediate( emit ); SVGA3dShaderInstToken if_token = inst_token( SVGA3DOP_IFC ); @@ -755,10 +823,23 @@ static boolean emit_if(struct svga_shader_emitter *emit, if_token.control = SVGA3DOPCOMPC_NE; zero = scalar(zero, TGSI_SWIZZLE_X); + if (SVGA3dShaderGetRegType(src0.base.value) == SVGA3DREG_CONST) { + /* + * Max different constant registers readable per IFC instruction is 1. + */ + + SVGA3dShaderDestToken tmp = get_temp( emit ); + + if (!submit_op1(emit, inst_token( SVGA3DOP_MOV ), tmp, src0)) + return FALSE; + + src0 = scalar(src( tmp ), TGSI_SWIZZLE_X); + } + emit->dynamic_branching_level++; return (emit_instruction( emit, if_token ) && - emit_src( emit, src ) && + emit_src( emit, src0 ) && emit_src( emit, zero ) ); } @@ -832,7 +913,7 @@ static boolean emit_cmp(struct svga_shader_emitter *emit, */ if (!submit_op2(emit, inst_token(SVGA3DOP_SLT), temp, src0, zero)) return FALSE; - return submit_op3(emit, inst_token(SVGA3DOP_LRP), dst, src(temp), src1, src2); + return submit_lrp(emit, dst, src(temp), src1, src2); } /* CMP DST, SRC0, SRC2, SRC1 */ @@ -1066,6 +1147,41 @@ static boolean emit_cos(struct svga_shader_emitter *emit, return TRUE; } +static boolean emit_ssg(struct svga_shader_emitter *emit, + const struct tgsi_full_instruction *insn ) +{ + SVGA3dShaderDestToken dst = translate_dst_register( emit, insn, 0 ); + struct src_register src0 = translate_src_register( + emit, &insn->Src[0] ); + SVGA3dShaderDestToken temp0 = get_temp( emit ); + SVGA3dShaderDestToken temp1 = get_temp( emit ); + struct src_register zero, one; + + if (emit->unit == PIPE_SHADER_VERTEX) { + /* SGN DST, SRC0, TMP0, TMP1 */ + return submit_op3( emit, inst_token( SVGA3DOP_SGN ), dst, src0, + src( temp0 ), src( temp1 ) ); + } + + zero = get_zero_immediate( emit ); + one = scalar( zero, TGSI_SWIZZLE_W ); + zero = scalar( zero, TGSI_SWIZZLE_X ); + + /* CMP TMP0, SRC0, one, zero */ + if (!submit_op3( emit, inst_token( SVGA3DOP_CMP ), + writemask( temp0, dst.mask ), src0, one, zero )) + return FALSE; + + /* CMP TMP1, negate(SRC0), negate(one), zero */ + if (!submit_op3( emit, inst_token( SVGA3DOP_CMP ), + writemask( temp1, dst.mask ), negate( src0 ), negate( one ), + zero )) + return FALSE; + + /* ADD DST, TMP0, TMP1 */ + return submit_op2( emit, inst_token( SVGA3DOP_ADD ), dst, src( temp0 ), + src( temp1 ) ); +} /* * ADD DST SRC0, negate(SRC0) @@ -1588,6 +1704,10 @@ static boolean emit_deriv(struct svga_shader_emitter *emit, } else { unsigned opcode; + const struct tgsi_full_src_register *reg = &insn->Src[0]; + SVGA3dShaderInstToken inst; + SVGA3dShaderDestToken dst; + struct src_register src0; switch (insn->Instruction.Opcode) { case TGSI_OPCODE_DDX: @@ -1600,7 +1720,21 @@ static boolean emit_deriv(struct svga_shader_emitter *emit, return FALSE; } - return emit_simple_instruction( emit, opcode, insn ); + inst = inst_token( opcode ); + dst = translate_dst_register( emit, insn, 0 ); + src0 = translate_src_register( emit, reg ); + + /* We cannot use negate or abs on source to dsx/dsy instruction. + */ + if (reg->Register.Absolute || + reg->Register.Negate) { + SVGA3dShaderDestToken temp = get_temp( emit ); + + if (!emit_repl( emit, temp, &src0 )) + return FALSE; + } + + return submit_op1( emit, inst, dst, src0 ); } } @@ -1624,19 +1758,6 @@ static boolean emit_arl(struct svga_shader_emitter *emit, } } -static boolean alias_src_dst( struct src_register src, - SVGA3dShaderDestToken dst ) -{ - if (src.base.num != dst.num) - return FALSE; - - if (SVGA3dShaderGetRegType(dst.value) != - SVGA3dShaderGetRegType(src.base.value)) - return FALSE; - - return TRUE; -} - static boolean emit_pow(struct svga_shader_emitter *emit, const struct tgsi_full_instruction *insn) { @@ -1729,37 +1850,14 @@ static boolean emit_lrp(struct svga_shader_emitter *emit, const struct tgsi_full_instruction *insn) { SVGA3dShaderDestToken dst = translate_dst_register( emit, insn, 0 ); - SVGA3dShaderDestToken tmp; const struct src_register src0 = translate_src_register( emit, &insn->Src[0] ); const struct src_register src1 = translate_src_register( emit, &insn->Src[1] ); const struct src_register src2 = translate_src_register( emit, &insn->Src[2] ); - boolean need_dst_tmp = FALSE; - - /* The dst reg must not be the same as src0 or src2 */ - if (alias_src_dst(src0, dst) || - alias_src_dst(src2, dst)) - need_dst_tmp = TRUE; - if (need_dst_tmp) { - tmp = get_temp( emit ); - tmp.mask = dst.mask; - } - else { - tmp = dst; - } - - if (!submit_op3(emit, inst_token( SVGA3DOP_LRP ), tmp, src0, src1, src2)) - return FALSE; - - if (need_dst_tmp) { - if (!submit_op1(emit, inst_token( SVGA3DOP_MOV ), dst, src( tmp ))) - return FALSE; - } - - return TRUE; + return submit_lrp(emit, dst, src0, src1, src2); } @@ -2366,6 +2464,9 @@ static boolean svga_emit_instruction( struct svga_shader_emitter *emit, case TGSI_OPCODE_LRP: return emit_lrp( emit, insn ); + case TGSI_OPCODE_SSG: + return emit_ssg( emit, insn ); + default: { unsigned opcode = translate_opcode(insn->Instruction.Opcode); @@ -2715,6 +2816,7 @@ needs_to_create_zero( struct svga_shader_emitter *emit ) return TRUE; if (emit->info.opcode_count[TGSI_OPCODE_DST] >= 1 || + emit->info.opcode_count[TGSI_OPCODE_SSG] >= 1 || emit->info.opcode_count[TGSI_OPCODE_LIT] >= 1) return TRUE; } diff --git a/src/gallium/drivers/svga/svgadump/svga_shader_op.c b/src/gallium/drivers/svga/svgadump/svga_shader_op.c index 95612a80063..ad1549d9f81 100644 --- a/src/gallium/drivers/svga/svgadump/svga_shader_op.c +++ b/src/gallium/drivers/svga/svgadump/svga_shader_op.c @@ -136,7 +136,7 @@ static struct sh_opcode_info opcode_info[] = { "dsy", 1, 1, 0, 0, SVGA3DOP_INVALID, }, { "texldd", 1, 4, 0, 0, SVGA3DOP_INVALID, }, { "setp", 1, 2, 0, 0, SVGA3DOP_SETP, }, - { "texldl", 1, 2, 0, 0, SVGA3DOP_INVALID, }, + { "texldl", 1, 2, 0, 0, SVGA3DOP_TEXLDL, }, { "breakp", 0, 1, 0, 0, SVGA3DOP_INVALID, }, }; @@ -156,6 +156,8 @@ const struct sh_opcode_info *svga_opcode_info( uint op ) if (info->svga_opcode == SVGA3DOP_INVALID) { /* No valid information. Please provide number of dst/src registers. */ + _debug_printf("Missing information for opcode %u, '%s'\n", op, + opcode_info[op].mnemonic); assert( 0 ); return NULL; } diff --git a/src/gallium/drivers/trace/tr_context.c b/src/gallium/drivers/trace/tr_context.c index eaabae8ce42..d24cc623c2e 100644 --- a/src/gallium/drivers/trace/tr_context.c +++ b/src/gallium/drivers/trace/tr_context.c @@ -1419,6 +1419,28 @@ trace_context_transfer_inline_write(struct pipe_context *_context, } +static void trace_redefine_user_buffer(struct pipe_context *_context, + struct pipe_resource *_resource, + unsigned offset, unsigned size) +{ + struct trace_context *tr_context = trace_context(_context); + struct trace_resource *tr_tex = trace_resource(_resource); + struct pipe_context *context = tr_context->pipe; + struct pipe_resource *resource = tr_tex->resource; + + assert(resource->screen == context->screen); + + trace_dump_call_begin("pipe_context", "redefine_user_buffer"); + + trace_dump_arg(ptr, context); + trace_dump_arg(ptr, resource); + trace_dump_arg(uint, offset); + trace_dump_arg(uint, size); + + trace_dump_call_end(); + + context->redefine_user_buffer(context, resource, offset, size); +} static const struct debug_named_value rbug_blocker_flags[] = { @@ -1506,6 +1528,7 @@ trace_context_create(struct trace_screen *tr_scr, tr_ctx->base.transfer_unmap = trace_context_transfer_unmap; tr_ctx->base.transfer_flush_region = trace_context_transfer_flush_region; tr_ctx->base.transfer_inline_write = trace_context_transfer_inline_write; + tr_ctx->base.redefine_user_buffer = trace_redefine_user_buffer; tr_ctx->pipe = pipe; diff --git a/src/gallium/drivers/trace/tr_dump_state.c b/src/gallium/drivers/trace/tr_dump_state.c index 155c869fbd9..18805655bd7 100644 --- a/src/gallium/drivers/trace/tr_dump_state.c +++ b/src/gallium/drivers/trace/tr_dump_state.c @@ -517,7 +517,6 @@ void trace_dump_vertex_buffer(const struct pipe_vertex_buffer *state) trace_dump_struct_begin("pipe_vertex_buffer"); trace_dump_member(uint, state, stride); - trace_dump_member(uint, state, max_index); trace_dump_member(uint, state, buffer_offset); trace_dump_member(resource_ptr, state, buffer); diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h index 589cac2ddd3..24ee3fe1175 100644 --- a/src/gallium/include/pipe/p_context.h +++ b/src/gallium/include/pipe/p_context.h @@ -399,6 +399,14 @@ struct pipe_context { unsigned stride, unsigned layer_stride); + + /* Notify a driver that a content of a user buffer has been changed. + * The changed range is [offset, offset+size-1]. + * The new width0 of the buffer is offset+size. */ + void (*redefine_user_buffer)(struct pipe_context *, + struct pipe_resource *, + unsigned offset, + unsigned size); }; diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h index a7f8503251b..8cf738fa2c0 100644 --- a/src/gallium/include/pipe/p_defines.h +++ b/src/gallium/include/pipe/p_defines.h @@ -225,13 +225,13 @@ enum pipe_transfer_usage { /** * Discards the memory within the mapped region. * - * It should not be used with PIPE_TRANSFER_CPU_READ. + * It should not be used with PIPE_TRANSFER_READ. * * See also: * - OpenGL's ARB_map_buffer_range extension, MAP_INVALIDATE_RANGE_BIT flag. - * - Direct3D's D3DLOCK_DISCARD flag. */ - PIPE_TRANSFER_DISCARD = (1 << 8), + PIPE_TRANSFER_DISCARD = (1 << 8), /* DEPRECATED */ + PIPE_TRANSFER_DISCARD_RANGE = (1 << 8), /** * Fail if the resource cannot be mapped immediately. @@ -246,7 +246,7 @@ enum pipe_transfer_usage { /** * Do not attempt to synchronize pending operations on the resource when mapping. * - * It should not be used with PIPE_TRANSFER_CPU_READ. + * It should not be used with PIPE_TRANSFER_READ. * * See also: * - OpenGL's ARB_map_buffer_range extension, MAP_UNSYNCHRONIZED_BIT flag. @@ -260,13 +260,28 @@ enum pipe_transfer_usage { * Written ranges will be notified later with * pipe_context::transfer_flush_region. * - * It should not be used with PIPE_TRANSFER_CPU_READ. + * It should not be used with PIPE_TRANSFER_READ. * * See also: * - pipe_context::transfer_flush_region * - OpenGL's ARB_map_buffer_range extension, MAP_FLUSH_EXPLICIT_BIT flag. */ - PIPE_TRANSFER_FLUSH_EXPLICIT = (1 << 11) + PIPE_TRANSFER_FLUSH_EXPLICIT = (1 << 11), + + /** + * Discards all memory backing the resource. + * + * It should not be used with PIPE_TRANSFER_READ. + * + * This is equivalent to: + * - OpenGL's ARB_map_buffer_range extension, MAP_INVALIDATE_BUFFER_BIT + * - BufferData(NULL) on a GL buffer + * - Direct3D's D3DLOCK_DISCARD flag. + * - WDDM's D3DDDICB_LOCKFLAGS.Discard flag. + * - D3D10 DDI's D3D10_DDI_MAP_WRITE_DISCARD flag + * - D3D10's D3D10_MAP_WRITE_DISCARD flag. + */ + PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE = (1 << 12) }; @@ -380,7 +395,8 @@ enum pipe_transfer_usage { #define PIPE_QUERY_SO_STATISTICS 5 #define PIPE_QUERY_GPU_FINISHED 6 #define PIPE_QUERY_TIMESTAMP_DISJOINT 7 -#define PIPE_QUERY_TYPES 8 +#define PIPE_QUERY_OCCLUSION_PREDICATE 8 +#define PIPE_QUERY_TYPES 9 /** diff --git a/src/gallium/include/pipe/p_format.h b/src/gallium/include/pipe/p_format.h index 3aa11be4b5b..e2cc32222de 100644 --- a/src/gallium/include/pipe/p_format.h +++ b/src/gallium/include/pipe/p_format.h @@ -33,6 +33,16 @@ extern "C" { #endif + +enum pipe_type { + PIPE_TYPE_UNORM = 0, + PIPE_TYPE_SNORM, + PIPE_TYPE_SINT, + PIPE_TYPE_UINT, + PIPE_TYPE_FLOAT, + PIPE_TYPE_COUNT +}; + /** * Texture/surface image formats (preliminary) */ diff --git a/src/gallium/include/pipe/p_shader_tokens.h b/src/gallium/include/pipe/p_shader_tokens.h index 0a9e14154d7..d3a3632654c 100644 --- a/src/gallium/include/pipe/p_shader_tokens.h +++ b/src/gallium/include/pipe/p_shader_tokens.h @@ -75,6 +75,7 @@ enum tgsi_file_type { TGSI_FILE_SYSTEM_VALUE =9, TGSI_FILE_IMMEDIATE_ARRAY =10, TGSI_FILE_TEMPORARY_ARRAY =11, + TGSI_FILE_RESOURCE =12, TGSI_FILE_COUNT /**< how many TGSI_FILE_ types */ }; @@ -153,6 +154,14 @@ struct tgsi_declaration_semantic unsigned Padding : 8; }; +struct tgsi_declaration_resource { + unsigned Resource : 8; /**< one of TGSI_TEXTURE_ */ + unsigned ReturnTypeX : 6; /**< one of enum pipe_type */ + unsigned ReturnTypeY : 6; /**< one of enum pipe_type */ + unsigned ReturnTypeZ : 6; /**< one of enum pipe_type */ + unsigned ReturnTypeW : 6; /**< one of enum pipe_type */ +}; + #define TGSI_IMM_FLOAT32 0 #define TGSI_IMM_UINT32 1 #define TGSI_IMM_INT32 2 @@ -339,7 +348,22 @@ struct tgsi_property_data { #define TGSI_OPCODE_CASE 142 #define TGSI_OPCODE_DEFAULT 143 #define TGSI_OPCODE_ENDSWITCH 144 -#define TGSI_OPCODE_LAST 145 + +/* resource related opcodes */ +#define TGSI_OPCODE_LOAD 145 +#define TGSI_OPCODE_LOAD_MS 146 +#define TGSI_OPCODE_SAMPLE 147 +#define TGSI_OPCODE_SAMPLE_B 148 +#define TGSI_OPCODE_SAMPLE_C 149 +#define TGSI_OPCODE_SAMPLE_C_LZ 150 +#define TGSI_OPCODE_SAMPLE_D 151 +#define TGSI_OPCODE_SAMPLE_L 152 +#define TGSI_OPCODE_GATHER4 153 +#define TGSI_OPCODE_RESINFO 154 +#define TGSI_OPCODE_SAMPLE_POS 155 +#define TGSI_OPCODE_SAMPLE_INFO 156 + +#define TGSI_OPCODE_LAST 157 #define TGSI_SAT_NONE 0 /* do not saturate */ #define TGSI_SAT_ZERO_ONE 1 /* clamp to [0,1] */ @@ -406,7 +430,9 @@ struct tgsi_instruction_label #define TGSI_TEXTURE_SHADOW1D 6 #define TGSI_TEXTURE_SHADOW2D 7 #define TGSI_TEXTURE_SHADOWRECT 8 -#define TGSI_TEXTURE_COUNT 9 +#define TGSI_TEXTURE_1D_ARRAY 9 +#define TGSI_TEXTURE_2D_ARRAY 10 +#define TGSI_TEXTURE_COUNT 11 struct tgsi_instruction_texture { diff --git a/src/gallium/include/pipe/p_state.h b/src/gallium/include/pipe/p_state.h index 226ae8667b7..cf6c5b50268 100644 --- a/src/gallium/include/pipe/p_state.h +++ b/src/gallium/include/pipe/p_state.h @@ -62,6 +62,7 @@ extern "C" { #define PIPE_MAX_GEOMETRY_SAMPLERS 16 #define PIPE_MAX_SHADER_INPUTS 32 #define PIPE_MAX_SHADER_OUTPUTS 32 +#define PIPE_MAX_SHADER_RESOURCES 32 #define PIPE_MAX_TEXTURE_LEVELS 16 #define PIPE_MAX_SO_BUFFERS 4 @@ -389,11 +390,11 @@ struct pipe_stream_output_state struct pipe_transfer { struct pipe_resource *resource; /**< resource to transfer to/from */ - unsigned level; + unsigned level; /**< texture mipmap level */ enum pipe_transfer_usage usage; - struct pipe_box box; - unsigned stride; - unsigned layer_stride; + struct pipe_box box; /**< region of the resource to access */ + unsigned stride; /**< row stride in bytes */ + unsigned layer_stride; /**< image/layer stride in bytes */ void *data; }; @@ -407,7 +408,6 @@ struct pipe_transfer struct pipe_vertex_buffer { unsigned stride; /**< stride to same attrib in next vertex, in bytes */ - unsigned max_index; /**< number of vertices in this buffer */ unsigned buffer_offset; /**< offset to start of data in buffer, in bytes */ struct pipe_resource *buffer; /**< the actual buffer */ }; diff --git a/src/gallium/state_trackers/d3d1x/dxgi/src/dxgi_native.cpp b/src/gallium/state_trackers/d3d1x/dxgi/src/dxgi_native.cpp index 2ff24e17d41..2e45f3f43e9 100644 --- a/src/gallium/state_trackers/d3d1x/dxgi/src/dxgi_native.cpp +++ b/src/gallium/state_trackers/d3d1x/dxgi/src/dxgi_native.cpp @@ -794,9 +794,9 @@ struct dxgi_blitter const unsigned semantic_indices[] = { 0, 0 }; vs = util_make_vertex_passthrough_shader(pipe, 2, semantic_names, semantic_indices); - vbuf.buffer = pipe_buffer_create(pipe->screen, PIPE_BIND_VERTEX_BUFFER, sizeof(quad_data)); + vbuf.buffer = pipe_buffer_create(pipe->screen, PIPE_BIND_VERTEX_BUFFER, + PIPE_USAGE_STREAM, sizeof(quad_data)); vbuf.buffer_offset = 0; - vbuf.max_index = ~0; vbuf.stride = 4 * sizeof(float); pipe_buffer_write(pipe, vbuf.buffer, 0, sizeof(quad_data), quad_data); diff --git a/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_context.h b/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_context.h index e1ba6c184fd..542d6591293 100644 --- a/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_context.h +++ b/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_context.h @@ -623,7 +623,6 @@ struct GalliumD3D10Device : public GalliumD3D10ScreenImpl<threadsafe> vertex_buffers[start + i].buffer = buffer ? ((GalliumD3D11Buffer*)buffer)->resource : 0; vertex_buffers[start + i].buffer_offset = new_offsets[i]; vertex_buffers[start + i].stride = new_strides[i]; - vertex_buffers[start + i].max_index = ~0; last_different = i; } } diff --git a/src/gallium/state_trackers/dri/common/dri_context.c b/src/gallium/state_trackers/dri/common/dri_context.c index 3d5d24e692c..fc68ee13eaa 100644 --- a/src/gallium/state_trackers/dri/common/dri_context.c +++ b/src/gallium/state_trackers/dri/common/dri_context.c @@ -141,12 +141,18 @@ GLboolean dri_unbind_context(__DRIcontext * cPriv) { /* dri_util.c ensures cPriv is not null */ + struct dri_screen *screen = dri_screen(cPriv->driScreenPriv); struct dri_context *ctx = dri_context(cPriv); + struct dri_drawable *draw = dri_drawable(ctx->dPriv); + struct dri_drawable *read = dri_drawable(ctx->rPriv); + struct st_api *stapi = screen->st_api; if (--ctx->bind_count == 0) { if (ctx->st == ctx->stapi->get_current(ctx->stapi)) { ctx->st->flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); - ctx->stapi->make_current(ctx->stapi, NULL, NULL, NULL); + stapi->make_current(stapi, NULL, NULL, NULL); + draw->context = NULL; + read->context = NULL; } } @@ -169,17 +175,23 @@ dri_make_current(__DRIcontext * cPriv, ++ctx->bind_count; + if (!driDrawPriv && !driReadPriv) + return ctx->stapi->make_current(ctx->stapi, ctx->st, NULL, NULL); + else if (!driDrawPriv || !driReadPriv) + return GL_FALSE; + + draw->context = ctx; if (ctx->dPriv != driDrawPriv) { ctx->dPriv = driDrawPriv; draw->texture_stamp = driDrawPriv->lastStamp - 1; } + read->context = ctx; if (ctx->rPriv != driReadPriv) { ctx->rPriv = driReadPriv; read->texture_stamp = driReadPriv->lastStamp - 1; } - ctx->stapi->make_current(ctx->stapi, ctx->st, - (draw) ? &draw->base : NULL, (read) ? &read->base : NULL); + ctx->stapi->make_current(ctx->stapi, ctx->st, &draw->base, &read->base); return GL_TRUE; } diff --git a/src/gallium/state_trackers/dri/common/dri_drawable.c b/src/gallium/state_trackers/dri/common/dri_drawable.c index 060748622c9..28a33ac7d07 100644 --- a/src/gallium/state_trackers/dri/common/dri_drawable.c +++ b/src/gallium/state_trackers/dri/common/dri_drawable.c @@ -132,6 +132,7 @@ dri_create_buffer(__DRIscreen * sPriv, drawable->base.validate = dri_st_framebuffer_validate; drawable->base.st_manager_private = (void *) drawable; + drawable->screen = screen; drawable->sPriv = sPriv; drawable->dPriv = dPriv; dPriv->driverPrivate = (void *)drawable; diff --git a/src/gallium/state_trackers/dri/common/dri_drawable.h b/src/gallium/state_trackers/dri/common/dri_drawable.h index 2ff6b713293..7f1aa512ca1 100644 --- a/src/gallium/state_trackers/dri/common/dri_drawable.h +++ b/src/gallium/state_trackers/dri/common/dri_drawable.h @@ -41,6 +41,9 @@ struct dri_drawable struct st_framebuffer_iface base; struct st_visual stvis; + struct dri_screen *screen; + struct dri_context *context; + /* dri */ __DRIdrawable *dPriv; __DRIscreen *sPriv; diff --git a/src/gallium/state_trackers/dri/common/dri_screen.c b/src/gallium/state_trackers/dri/common/dri_screen.c index f6e22c74b4e..69c2e7e9ec8 100644 --- a/src/gallium/state_trackers/dri/common/dri_screen.c +++ b/src/gallium/state_trackers/dri/common/dri_screen.c @@ -235,7 +235,6 @@ dri_fill_st_visual(struct st_visual *stvis, struct dri_screen *screen, return; stvis->samples = mode->samples; - stvis->render_buffer = ST_ATTACHMENT_INVALID; if (mode->redBits == 8) { if (mode->alphaBits == 8) @@ -274,8 +273,11 @@ dri_fill_st_visual(struct st_visual *stvis, struct dri_screen *screen, PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE; stvis->buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK; - if (mode->doubleBufferMode) + stvis->render_buffer = ST_ATTACHMENT_FRONT_LEFT; + if (mode->doubleBufferMode) { stvis->buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK; + stvis->render_buffer = ST_ATTACHMENT_BACK_LEFT; + } if (mode->stereoMode) { stvis->buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK; if (mode->doubleBufferMode) diff --git a/src/gallium/state_trackers/dri/drm/dri2.c b/src/gallium/state_trackers/dri/drm/dri2.c index a9d05a80fbd..0181588096d 100644 --- a/src/gallium/state_trackers/dri/drm/dri2.c +++ b/src/gallium/state_trackers/dri/drm/dri2.c @@ -38,6 +38,7 @@ #include "dri_screen.h" #include "dri_context.h" #include "dri_drawable.h" +#include "dri2_buffer.h" /** * DRI2 flush extension. @@ -51,7 +52,7 @@ static void dri2_invalidate_drawable(__DRIdrawable *dPriv) { struct dri_drawable *drawable = dri_drawable(dPriv); - struct dri_context *ctx = dri_context(dPriv->driContextPriv); + struct dri_context *ctx = drawable->context; dri2InvalidateDrawable(dPriv); drawable->dPriv->lastStamp = *drawable->dPriv->pStamp; @@ -259,6 +260,91 @@ dri2_drawable_process_buffers(struct dri_drawable *drawable, memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * count); } +static __DRIbuffer * +dri2_allocate_buffer(__DRIscreen *sPriv, + unsigned attachment, unsigned format, + int width, int height) +{ + struct dri_screen *screen = dri_screen(sPriv); + struct dri2_buffer *buffer; + struct pipe_resource templ; + enum st_attachment_type statt; + enum pipe_format pf; + unsigned bind; + struct winsys_handle whandle; + + switch (attachment) { + case __DRI_BUFFER_FRONT_LEFT: + case __DRI_BUFFER_FAKE_FRONT_LEFT: + statt = ST_ATTACHMENT_FRONT_LEFT; + bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; + break; + case __DRI_BUFFER_BACK_LEFT: + statt = ST_ATTACHMENT_BACK_LEFT; + bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; + break; + case __DRI_BUFFER_DEPTH: + case __DRI_BUFFER_DEPTH_STENCIL: + case __DRI_BUFFER_STENCIL: + statt = ST_ATTACHMENT_DEPTH_STENCIL; + bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */ + break; + default: + statt = ST_ATTACHMENT_INVALID; + break; + } + + switch (format) { + case 32: + pf = PIPE_FORMAT_B8G8R8X8_UNORM; + break; + case 16: + pf = PIPE_FORMAT_Z16_UNORM; + break; + default: + return NULL; + } + + buffer = CALLOC_STRUCT(dri2_buffer); + if (!buffer) + return NULL; + + memset(&templ, 0, sizeof(templ)); + templ.bind = bind; + templ.format = pf; + templ.target = PIPE_TEXTURE_2D; + templ.last_level = 0; + templ.width0 = width; + templ.height0 = height; + templ.depth0 = 1; + + buffer->resource = + screen->base.screen->resource_create(screen->base.screen, &templ); + if (!buffer->resource) + return NULL; + + memset(&whandle, 0, sizeof(whandle)); + whandle.type = DRM_API_HANDLE_TYPE_SHARED; + screen->base.screen->resource_get_handle(screen->base.screen, + buffer->resource, &whandle); + + buffer->base.attachment = attachment; + buffer->base.name = whandle.handle; + buffer->base.cpp = util_format_get_blocksize(pf); + buffer->base.pitch = whandle.stride; + + return &buffer->base; +} + +static void +dri2_release_buffer(__DRIscreen *sPriv, __DRIbuffer *bPriv) +{ + struct dri2_buffer *buffer = dri2_buffer(bPriv); + + pipe_resource_reference(&buffer->resource, NULL); + FREE(buffer); +} + /* * Backend functions for st_framebuffer interface. */ @@ -373,7 +459,7 @@ static __DRIimage * dri2_create_image_from_renderbuffer(__DRIcontext *context, int renderbuffer, void *loaderPrivate) { - struct dri_context *ctx = dri_context(context->driverPrivate); + struct dri_context *ctx = dri_context(context); if (!ctx->st->get_resource_for_egl_image) return NULL; @@ -601,6 +687,9 @@ const struct __DriverAPIRec driDriverAPI = { .SwapBuffers = NULL, .CopySubBuffer = NULL, + + .AllocateBuffer = dri2_allocate_buffer, + .ReleaseBuffer = dri2_release_buffer, }; /* This is the table of extensions that the loader will dlsym() for. */ diff --git a/src/gallium/state_trackers/dri/drm/dri2_buffer.h b/src/gallium/state_trackers/dri/drm/dri2_buffer.h new file mode 100644 index 00000000000..1cd8dbbda22 --- /dev/null +++ b/src/gallium/state_trackers/dri/drm/dri2_buffer.h @@ -0,0 +1,22 @@ +#ifndef DRI2_BUFFER_H +#define DRI2_BUFFER_H + +#include "dri_wrapper.h" + +struct pipe_surface; + +struct dri2_buffer +{ + __DRIbuffer base; + struct pipe_resource *resource; +}; + +static INLINE struct dri2_buffer * +dri2_buffer(__DRIbuffer * driBufferPriv) +{ + return (struct dri2_buffer *) driBufferPriv; +} + +#endif + +/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/egl/Makefile b/src/gallium/state_trackers/egl/Makefile index 8cfcef968ed..98167cceeb3 100644 --- a/src/gallium/state_trackers/egl/Makefile +++ b/src/gallium/state_trackers/egl/Makefile @@ -23,6 +23,13 @@ x11_SOURCES = $(wildcard x11/*.c) \ $(TOP)/src/glx/dri2.c x11_OBJECTS = $(x11_SOURCES:.c=.o) +wayland_INCLUDES = \ + -I$(TOP)/src/gallium/winsys \ + -I$(TOP)/src/egl/wayland \ + $(shell pkg-config --cflags-only-I libdrm wayland-client) + +wayland_SOURCES = $(wildcard wayland/*.c) +wayland_OBJECTS = $(wayland_SOURCES:.c=.o) drm_INCLUDES = -I$(TOP)/src/gallium/winsys $(shell pkg-config --cflags-only-I libdrm) drm_SOURCES = $(wildcard drm/*.c) @@ -45,6 +52,10 @@ ifneq ($(findstring x11, $(EGL_PLATFORMS)),) EGL_OBJECTS += $(x11_OBJECTS) EGL_CPPFLAGS += -DHAVE_X11_BACKEND endif +ifneq ($(findstring wayland, $(EGL_PLATFORMS)),) +EGL_OBJECTS += $(wayland_OBJECTS) +EGL_CPPFLAGS += -DHAVE_WAYLAND_BACKEND +endif ifneq ($(findstring drm, $(EGL_PLATFORMS)),) EGL_OBJECTS += $(drm_OBJECTS) EGL_CPPFLAGS += -DHAVE_DRM_BACKEND @@ -87,6 +98,9 @@ $(common_OBJECTS): %.o: %.c $(x11_OBJECTS): %.o: %.c $(call egl-cc,x11) +$(wayland_OBJECTS): %.o: %.c + $(call egl-cc,wayland) + $(drm_OBJECTS): %.o: %.c $(call egl-cc,drm) diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.c b/src/gallium/state_trackers/egl/common/egl_g3d.c index 9024f945b8c..6107df48822 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d.c @@ -102,6 +102,12 @@ egl_g3d_get_platform(_EGLDriver *drv, _EGLPlatformType plat) #ifdef HAVE_X11_BACKEND nplat = native_get_x11_platform(); #endif + break; + case _EGL_PLATFORM_WAYLAND: + plat_name = "wayland"; +#ifdef HAVE_WAYLAND_BACKEND + nplat = native_get_wayland_platform(); +#endif break; case _EGL_PLATFORM_DRM: plat_name = "DRM"; @@ -546,6 +552,9 @@ egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy) dpy->Extensions.MESA_drm_image = EGL_TRUE; } + if (dpy->Platform == _EGL_PLATFORM_WAYLAND && gdpy->native->buffer) + dpy->Extensions.MESA_drm_image = EGL_TRUE; + if (egl_g3d_add_configs(drv, dpy, 1) == 1) { _eglError(EGL_NOT_INITIALIZED, "eglInitialize(unable to add configs)"); goto fail; diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_image.c b/src/gallium/state_trackers/egl/common/egl_g3d_image.c index 78c035a2af0..81ce7ab45c7 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d_image.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d_image.c @@ -135,7 +135,7 @@ egl_g3d_reference_drm_buffer(_EGLDisplay *dpy, EGLint name, _EGLImageAttribs attrs; EGLint format; - if (dpy->Platform != _EGL_PLATFORM_DRM) + if (!dpy->Extensions.MESA_drm_image) return NULL; if (_eglParseImageAttribList(&attrs, dpy, attribs) != EGL_SUCCESS) @@ -295,7 +295,7 @@ egl_g3d_export_drm_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *img, struct egl_g3d_image *gimg = egl_g3d_image(img); struct winsys_handle wsh; - if (dpy->Platform != _EGL_PLATFORM_DRM) + if (!dpy->Extensions.MESA_drm_image) return EGL_FALSE; /* get shared handle */ diff --git a/src/gallium/state_trackers/egl/common/native.h b/src/gallium/state_trackers/egl/common/native.h index 6461b5edbdf..42889075a39 100644 --- a/src/gallium/state_trackers/egl/common/native.h +++ b/src/gallium/state_trackers/egl/common/native.h @@ -239,6 +239,9 @@ const struct native_platform * native_get_x11_platform(void); const struct native_platform * +native_get_wayland_platform(void); + +const struct native_platform * native_get_drm_platform(void); const struct native_platform * diff --git a/src/gallium/state_trackers/egl/common/native_helper.c b/src/gallium/state_trackers/egl/common/native_helper.c index 0f2d02032b5..a9d8f32e007 100644 --- a/src/gallium/state_trackers/egl/common/native_helper.c +++ b/src/gallium/state_trackers/egl/common/native_helper.c @@ -143,6 +143,14 @@ resource_surface_add_resources(struct resource_surface *rsurf, return ((rsurf->resource_mask & resource_mask) == resource_mask); } +void +resource_surface_import_resource(struct resource_surface *rsurf, + enum native_attachment which, + struct pipe_resource *pres) +{ + pipe_resource_reference(&rsurf->resources[which], pres); + rsurf->resource_mask |= 1 << which; +} void resource_surface_get_resources(struct resource_surface *rsurf, diff --git a/src/gallium/state_trackers/egl/common/native_helper.h b/src/gallium/state_trackers/egl/common/native_helper.h index d1569ac3ea6..03995de19ae 100644 --- a/src/gallium/state_trackers/egl/common/native_helper.h +++ b/src/gallium/state_trackers/egl/common/native_helper.h @@ -51,6 +51,11 @@ resource_surface_add_resources(struct resource_surface *rsurf, uint resource_mask); void +resource_surface_import_resource(struct resource_surface *rsurf, + enum native_attachment which, + struct pipe_resource *pres); + +void resource_surface_get_resources(struct resource_surface *rsurf, struct pipe_resource **resources, uint resource_mask); diff --git a/src/gallium/state_trackers/egl/drm/native_drm.c b/src/gallium/state_trackers/egl/drm/native_drm.c index 14c134ea1ad..6932f30a6a4 100644 --- a/src/gallium/state_trackers/egl/drm/native_drm.c +++ b/src/gallium/state_trackers/egl/drm/native_drm.c @@ -178,7 +178,7 @@ drm_display_init_screen(struct native_display *ndpy) drmFreeVersion(version); if (!drmdpy->base.screen) { - _eglLog(_EGL_WARNING, "failed to create DRM screen"); + _eglLog(_EGL_DEBUG, "failed to create DRM screen"); return FALSE; } diff --git a/src/gallium/state_trackers/egl/wayland/native_wayland.c b/src/gallium/state_trackers/egl/wayland/native_wayland.c new file mode 100644 index 00000000000..d4d5f9c2ebb --- /dev/null +++ b/src/gallium/state_trackers/egl/wayland/native_wayland.c @@ -0,0 +1,626 @@ +/* + * Mesa 3-D graphics library + * Version: 7.11 + * + * Copyright (C) 2011 Benjamin Franzke <[email protected]> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and 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 shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS 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 "util/u_memory.h" +#include "util/u_inlines.h" + +#include "pipe/p_compiler.h" +#include "pipe/p_screen.h" +#include "pipe/p_context.h" +#include "pipe/p_state.h" +#include "state_tracker/drm_driver.h" + +#include "egllog.h" + +#include "native_wayland.h" + +/* see get_drm_screen_name */ +#include <radeon_drm.h> +#include "radeon/drm/radeon_drm_public.h" + +#include <wayland-client.h> +#include "wayland-egl-priv.h" + +#include <xf86drm.h> + +static struct native_event_handler *wayland_event_handler; + +static void +sync_callback(void *data) +{ + int *done = data; + + *done = 1; +} + +static void +force_roundtrip(struct wl_display *display) +{ + int done = 0; + + wl_display_sync_callback(display, sync_callback, &done); + wl_display_iterate(display, WL_DISPLAY_WRITABLE); + while (!done) + wl_display_iterate(display, WL_DISPLAY_READABLE); +} + +static const struct native_config ** +wayland_display_get_configs (struct native_display *ndpy, int *num_configs) +{ + struct wayland_display *display = wayland_display(ndpy); + const struct native_config **configs; + + if (!display->config) { + struct native_config *nconf; + enum pipe_format format; + display->config = CALLOC(1, sizeof(*display->config)); + if (!display->config) + return NULL; + nconf = &display->config->base; + + nconf->buffer_mask = + (1 << NATIVE_ATTACHMENT_FRONT_LEFT) | + (1 << NATIVE_ATTACHMENT_BACK_LEFT); + + format = PIPE_FORMAT_B8G8R8A8_UNORM; + + nconf->color_format = format; + nconf->window_bit = TRUE; + nconf->pixmap_bit = TRUE; + } + + configs = MALLOC(sizeof(*configs)); + if (configs) { + configs[0] = &display->config->base; + if (num_configs) + *num_configs = 1; + } + + return configs; +} + +static int +wayland_display_get_param(struct native_display *ndpy, + enum native_param_type param) +{ + int val; + + switch (param) { + case NATIVE_PARAM_USE_NATIVE_BUFFER: + case NATIVE_PARAM_PRESERVE_BUFFER: + case NATIVE_PARAM_MAX_SWAP_INTERVAL: + default: + val = 0; + break; + } + + return val; +} + +static boolean +wayland_display_is_pixmap_supported(struct native_display *ndpy, + EGLNativePixmapType pix, + const struct native_config *nconf) +{ + /* all wl_egl_pixmaps are supported */ + + return TRUE; +} + +static void +wayland_display_destroy(struct native_display *ndpy) +{ + struct wayland_display *display = wayland_display(ndpy); + + if (display->config) + FREE(display->config); + + if (display->base.screen) + display->base.screen->destroy(display->base.screen); + + FREE(display); +} + + +static struct wl_buffer * +wayland_create_buffer(struct wayland_surface *surface, + enum native_attachment attachment) +{ + struct wayland_display *display = surface->display; + struct pipe_resource *resource; + struct winsys_handle wsh; + uint width, height; + + resource = resource_surface_get_single_resource(surface->rsurf, attachment); + resource_surface_get_size(surface->rsurf, &width, &height); + + wsh.type = DRM_API_HANDLE_TYPE_SHARED; + display->base.screen->resource_get_handle(display->base.screen, resource, &wsh); + + pipe_resource_reference(&resource, NULL); + + return wl_drm_create_buffer(display->dpy->drm, wsh.handle, + width, height, + wsh.stride, surface->win->visual); +} + +static void +wayland_pixmap_destroy(struct wl_egl_pixmap *egl_pixmap) +{ + struct pipe_resource *resource = egl_pixmap->driver_private; + + assert(resource); + + pipe_resource_reference(&resource, NULL); + + egl_pixmap->driver_private = NULL; + egl_pixmap->destroy = NULL; + egl_pixmap->name = 0; +} + +static void +wayland_pixmap_surface_intialize(struct wayland_surface *surface) +{ + struct native_display *ndpy = &surface->display->base; + struct pipe_resource *resource; + struct winsys_handle wsh; + const enum native_attachment front_natt = NATIVE_ATTACHMENT_FRONT_LEFT; + + if (surface->pix->name > 0) + return; + + resource = resource_surface_get_single_resource(surface->rsurf, front_natt); + + wsh.type = DRM_API_HANDLE_TYPE_SHARED; + ndpy->screen->resource_get_handle(ndpy->screen, resource, &wsh); + + surface->pix->name = wsh.handle; + surface->pix->stride = wsh.stride; + surface->pix->destroy = wayland_pixmap_destroy; + surface->pix->driver_private = resource; +} + +static void +wayland_release_pending_resource(void *data) +{ + struct wayland_surface *surface = data; + + /* FIXME: print internal error */ + if (!surface->pending_resource) + return; + + pipe_resource_reference(&surface->pending_resource, NULL); +} + +static void +wayland_window_surface_handle_resize(struct wayland_surface *surface) +{ + struct wayland_display *display = surface->display; + struct pipe_resource *front_resource; + const enum native_attachment front_natt = NATIVE_ATTACHMENT_FRONT_LEFT; + int i; + + front_resource = resource_surface_get_single_resource(surface->rsurf, + front_natt); + if (resource_surface_set_size(surface->rsurf, + surface->win->width, surface->win->height)) { + + if (surface->pending_resource) + force_roundtrip(display->dpy->display); + + if (front_resource) { + surface->pending_resource = front_resource; + front_resource = NULL; + wl_display_sync_callback(display->dpy->display, + wayland_release_pending_resource, surface); + } + + for (i = 0; i < WL_BUFFER_COUNT; ++i) { + if (surface->buffer[i]) + wl_buffer_destroy(surface->buffer[i]); + surface->buffer[i] = NULL; + } + } + pipe_resource_reference(&front_resource, NULL); + + surface->dx = surface->win->dx; + surface->dy = surface->win->dy; + surface->win->dx = 0; + surface->win->dy = 0; +} + +static boolean +wayland_surface_validate(struct native_surface *nsurf, uint attachment_mask, + unsigned int *seq_num, struct pipe_resource **textures, + int *width, int *height) +{ + struct wayland_surface *surface = wayland_surface(nsurf); + + if (surface->type == WL_WINDOW_SURFACE) + wayland_window_surface_handle_resize(surface); + + if (!resource_surface_add_resources(surface->rsurf, attachment_mask | + surface->attachment_mask)) + return FALSE; + + if (textures) + resource_surface_get_resources(surface->rsurf, textures, attachment_mask); + + if (seq_num) + *seq_num = surface->sequence_number; + + resource_surface_get_size(surface->rsurf, (uint *) width, (uint *) height); + + if (surface->type == WL_PIXMAP_SURFACE) + wayland_pixmap_surface_intialize(surface); + + return TRUE; +} + +static void +wayland_frame_callback(void *data, uint32_t time) +{ + struct wayland_surface *surface = data; + + surface->block_swap_buffers = FALSE; +} + +static INLINE void +wayland_buffers_swap(struct wl_buffer **buffer, + enum wayland_buffer_type buf1, + enum wayland_buffer_type buf2) +{ + struct wl_buffer *tmp = buffer[buf1]; + buffer[buf1] = buffer[buf2]; + buffer[buf2] = tmp; +} + +static boolean +wayland_surface_swap_buffers(struct native_surface *nsurf) +{ + struct wayland_surface *surface = wayland_surface(nsurf); + struct wayland_display *display = surface->display; + + while (surface->block_swap_buffers) + wl_display_iterate(display->dpy->display, WL_DISPLAY_READABLE); + + surface->block_swap_buffers = TRUE; + wl_display_frame_callback(display->dpy->display, wayland_frame_callback, + surface); + + if (surface->type == WL_WINDOW_SURFACE) { + resource_surface_swap_buffers(surface->rsurf, + NATIVE_ATTACHMENT_FRONT_LEFT, NATIVE_ATTACHMENT_BACK_LEFT, FALSE); + + wayland_buffers_swap(surface->buffer, WL_BUFFER_FRONT, WL_BUFFER_BACK); + + if (surface->buffer[WL_BUFFER_FRONT] == NULL) + surface->buffer[WL_BUFFER_FRONT] = + wayland_create_buffer(surface, NATIVE_ATTACHMENT_FRONT_LEFT); + + wl_surface_attach(surface->win->surface, surface->buffer[WL_BUFFER_FRONT], + surface->dx, surface->dy); + + resource_surface_get_size(surface->rsurf, + (uint *) &surface->win->attached_width, + (uint *) &surface->win->attached_height); + surface->dx = 0; + surface->dy = 0; + } + + surface->sequence_number++; + wayland_event_handler->invalid_surface(&display->base, + &surface->base, surface->sequence_number); + + return TRUE; +} + +static boolean +wayland_surface_present(struct native_surface *nsurf, + enum native_attachment natt, + boolean preserve, + uint swap_interval) +{ + struct wayland_surface *surface = wayland_surface(nsurf); + uint width, height; + boolean ret; + + if (preserve || swap_interval) + return FALSE; + + switch (natt) { + case NATIVE_ATTACHMENT_FRONT_LEFT: + ret = TRUE; + break; + case NATIVE_ATTACHMENT_BACK_LEFT: + ret = wayland_surface_swap_buffers(nsurf); + break; + default: + ret = FALSE; + break; + } + + if (surface->type == WL_WINDOW_SURFACE) { + resource_surface_get_size(surface->rsurf, &width, &height); + wl_surface_damage(surface->win->surface, 0, 0, width, height); + } + + return ret; +} + +static void +wayland_surface_wait(struct native_surface *nsurf) +{ + /* no-op */ +} + +static void +wayland_surface_destroy(struct native_surface *nsurf) +{ + struct wayland_surface *surface = wayland_surface(nsurf); + enum wayland_buffer_type buffer; + + for (buffer = 0; buffer < WL_BUFFER_COUNT; ++buffer) { + if (surface->buffer[buffer]) + wl_buffer_destroy(surface->buffer[buffer]); + } + + resource_surface_destroy(surface->rsurf); + FREE(surface); +} + +static struct native_surface * +wayland_create_pixmap_surface(struct native_display *ndpy, + EGLNativePixmapType pix, + const struct native_config *nconf) +{ + struct wayland_display *display = wayland_display(ndpy); + struct wayland_config *config = wayland_config(nconf); + struct wayland_surface *surface; + struct wl_egl_pixmap *egl_pixmap = (struct wl_egl_pixmap *) pix; + enum native_attachment natt = NATIVE_ATTACHMENT_FRONT_LEFT; + + surface = CALLOC_STRUCT(wayland_surface); + if (!surface) + return NULL; + + surface->display = display; + + surface->pending_resource = NULL; + surface->type = WL_PIXMAP_SURFACE; + surface->pix = egl_pixmap; + + if (surface->pix->visual == wl_display_get_rgb_visual(display->dpy->display)) + surface->color_format = PIPE_FORMAT_B8G8R8X8_UNORM; + else + surface->color_format = PIPE_FORMAT_B8G8R8A8_UNORM; + + surface->attachment_mask = (1 << NATIVE_ATTACHMENT_FRONT_LEFT); + + surface->rsurf = resource_surface_create(display->base.screen, + surface->color_format, + PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW | + PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_SCANOUT); + + if (!surface->rsurf) { + FREE(surface); + return NULL; + } + + resource_surface_set_size(surface->rsurf, + egl_pixmap->width, egl_pixmap->height); + + /* the pixmap is already allocated, so import it */ + if (surface->pix->name > 0) + resource_surface_import_resource(surface->rsurf, natt, + surface->pix->driver_private); + + surface->base.destroy = wayland_surface_destroy; + surface->base.present = wayland_surface_present; + surface->base.validate = wayland_surface_validate; + surface->base.wait = wayland_surface_wait; + + return &surface->base; +} + +static struct native_surface * +wayland_create_window_surface(struct native_display *ndpy, + EGLNativeWindowType win, + const struct native_config *nconf) +{ + struct wayland_display *display = wayland_display(ndpy); + struct wayland_config *config = wayland_config(nconf); + struct wayland_surface *surface; + + surface = CALLOC_STRUCT(wayland_surface); + if (!surface) + return NULL; + + surface->display = display; + surface->color_format = config->base.color_format; + + surface->win = (struct wl_egl_window *) win; + + surface->pending_resource = NULL; + surface->block_swap_buffers = FALSE; + surface->type = WL_WINDOW_SURFACE; + + surface->buffer[WL_BUFFER_FRONT] = NULL; + surface->buffer[WL_BUFFER_BACK] = NULL; + surface->attachment_mask = (1 << NATIVE_ATTACHMENT_FRONT_LEFT) | + (1 << NATIVE_ATTACHMENT_BACK_LEFT); + + surface->rsurf = resource_surface_create(display->base.screen, + surface->color_format, + PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW | + PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_SCANOUT); + + if (!surface->rsurf) { + FREE(surface); + return NULL; + } + + surface->base.destroy = wayland_surface_destroy; + surface->base.present = wayland_surface_present; + surface->base.validate = wayland_surface_validate; + surface->base.wait = wayland_surface_wait; + + return &surface->base; +} + +static const char * +get_drm_screen_name(int fd, drmVersionPtr version) +{ + const char *name = version->name; + + if (name && !strcmp(name, "radeon")) { + int chip_id; + struct drm_radeon_info info; + + memset(&info, 0, sizeof(info)); + info.request = RADEON_INFO_DEVICE_ID; + info.value = pointer_to_intptr(&chip_id); + if (drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info)) != 0) + return NULL; + + name = is_r3xx(chip_id) ? "r300" : "r600"; + } + + return name; +} + +static boolean +wayland_display_init_screen(struct native_display *ndpy) +{ + struct wayland_display *display = wayland_display(ndpy); + drmVersionPtr version; + const char *driver_name; + + if (display->dpy->fd == -1) + force_roundtrip(display->dpy->display); + if (display->dpy->fd == -1) + return FALSE; + + if (!display->dpy->authenticated) + force_roundtrip(display->dpy->display); + if (!display->dpy->authenticated) + return FALSE; + + version = drmGetVersion(display->dpy->fd); + if (!version) { + _eglLog(_EGL_WARNING, "invalid fd %d", display->dpy->fd); + return FALSE; + } + + /* FIXME: share this with native_drm or egl_dri2 */ + driver_name = get_drm_screen_name(display->dpy->fd, version); + + display->base.screen = + wayland_event_handler->new_drm_screen(&display->base, + driver_name, display->dpy->fd); + drmFreeVersion(version); + + if (!display->base.screen) { + _eglLog(_EGL_WARNING, "failed to create DRM screen"); + return FALSE; + } + + return TRUE; +} + + +static void +wayland_set_event_handler(struct native_event_handler *event_handler) +{ + wayland_event_handler = event_handler; +} + +static struct pipe_resource * +wayland_display_import_buffer(struct native_display *ndpy, + const struct pipe_resource *templ, + void *buf) +{ + return ndpy->screen->resource_from_handle(ndpy->screen, + templ, (struct winsys_handle *) buf); +} + +static boolean +wayland_display_export_buffer(struct native_display *ndpy, + struct pipe_resource *res, + void *buf) +{ + return ndpy->screen->resource_get_handle(ndpy->screen, + res, (struct winsys_handle *) buf); +} + +static struct native_display_buffer wayland_display_buffer = { + wayland_display_import_buffer, + wayland_display_export_buffer +}; + +static struct native_display * +wayland_display_create(void *dpy, boolean use_sw, void *user_data) +{ + struct wayland_display *display; + + display = CALLOC_STRUCT(wayland_display); + if (!display) + return NULL; + + display->base.user_data = user_data; + + display->dpy = dpy; + if (!display->dpy->display) { + wayland_display_destroy(&display->base); + return NULL; + } + + if (!wayland_display_init_screen(&display->base)) { + wayland_display_destroy(&display->base); + return NULL; + } + + display->base.destroy = wayland_display_destroy; + display->base.get_param = wayland_display_get_param; + display->base.get_configs = wayland_display_get_configs; + display->base.is_pixmap_supported = wayland_display_is_pixmap_supported; + display->base.create_window_surface = wayland_create_window_surface; + display->base.create_pixmap_surface = wayland_create_pixmap_surface; + display->base.buffer = &wayland_display_buffer; + + return &display->base; +} + +static const struct native_platform wayland_platform = { + "wayland", /* name */ + wayland_set_event_handler, + wayland_display_create +}; + +const struct native_platform * +native_get_wayland_platform(void) +{ + return &wayland_platform; +} diff --git a/src/gallium/state_trackers/egl/wayland/native_wayland.h b/src/gallium/state_trackers/egl/wayland/native_wayland.h new file mode 100644 index 00000000000..271c10dc113 --- /dev/null +++ b/src/gallium/state_trackers/egl/wayland/native_wayland.h @@ -0,0 +1,97 @@ +/* + * Mesa 3-D graphics library + * Version: 7.11 + * + * Copyright (C) 2011 Benjamin Franzke <[email protected]> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and 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 shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS 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 _NATIVE_WAYLAND_H_ +#define _NATIVE_WAYLAND_H_ + +#include "pipe/p_compiler.h" +#include "pipe/p_format.h" + +#include "common/native.h" +#include "common/native_helper.h" + +#include "wayland-egl-priv.h" + +struct wayland_display { + struct native_display base; + + struct wayland_config *config; + struct wl_egl_display *dpy; +}; + +enum wayland_buffer_type { + WL_BUFFER_FRONT, + WL_BUFFER_BACK, + WL_BUFFER_COUNT +}; + +enum wayland_surface_type { + WL_WINDOW_SURFACE, + WL_PIXMAP_SURFACE, + WL_PBUFFER_SURFACE +}; + +struct wayland_surface { + struct native_surface base; + struct wayland_display *display; + + struct wl_egl_window *win; + struct wl_egl_pixmap *pix; + enum wayland_surface_type type; + int dx, dy; + struct resource_surface *rsurf; + struct pipe_resource *pending_resource; + enum pipe_format color_format; + + unsigned int sequence_number; + struct wl_buffer *buffer[WL_BUFFER_COUNT]; + unsigned int attachment_mask; + + boolean block_swap_buffers; +}; + +struct wayland_config { + struct native_config base; +}; + +static INLINE struct wayland_display * +wayland_display(const struct native_display *ndpy) +{ + return (struct wayland_display *) ndpy; +} + +static INLINE struct wayland_surface * +wayland_surface(const struct native_surface *nsurf) +{ + return (struct wayland_surface *) nsurf; +} + +static INLINE struct wayland_config * +wayland_config(const struct native_config *nconf) +{ + return (struct wayland_config *) nconf; +} + +#endif /* _NATIVE_WAYLAND_H_ */ diff --git a/src/gallium/state_trackers/egl/x11/native_dri2.c b/src/gallium/state_trackers/egl/x11/native_dri2.c index c82e2da863b..b18c3132c57 100644 --- a/src/gallium/state_trackers/egl/x11/native_dri2.c +++ b/src/gallium/state_trackers/egl/x11/native_dri2.c @@ -782,7 +782,7 @@ dri2_display_init_screen(struct native_display *ndpy) dri2dpy->event_handler->new_drm_screen(&dri2dpy->base, dri2dpy->dri_driver, fd); if (!dri2dpy->base.screen) { - _eglLog(_EGL_WARNING, "failed to create DRM screen"); + _eglLog(_EGL_DEBUG, "failed to create DRM screen"); return FALSE; } diff --git a/src/gallium/state_trackers/python/p_context.i b/src/gallium/state_trackers/python/p_context.i index d694651eef7..b30050bf6d4 100644 --- a/src/gallium/state_trackers/python/p_context.i +++ b/src/gallium/state_trackers/python/p_context.i @@ -268,7 +268,6 @@ struct st_context { void set_vertex_buffer(unsigned index, unsigned stride, - unsigned max_index, unsigned buffer_offset, struct pipe_resource *buffer) { @@ -277,7 +276,6 @@ struct st_context { memset(&state, 0, sizeof(state)); state.stride = stride; - state.max_index = max_index; state.buffer_offset = buffer_offset; state.buffer = buffer; @@ -352,6 +350,7 @@ struct st_context { vbuf = pipe_buffer_create(screen, PIPE_BIND_VERTEX_BUFFER, + PIPE_USAGE_STATIC, size); if(!vbuf) goto error1; @@ -378,7 +377,6 @@ struct st_context { vbuffer.buffer = vbuf; vbuffer.stride = num_attribs * 4 * sizeof(float); /* vertex size */ vbuffer.buffer_offset = 0; - vbuffer.max_index = num_verts - 1; pipe->set_vertex_buffers(pipe, 1, &vbuffer); /* draw */ diff --git a/src/gallium/state_trackers/python/p_device.i b/src/gallium/state_trackers/python/p_device.i index d55086fefd5..cc67da937cd 100644 --- a/src/gallium/state_trackers/python/p_device.i +++ b/src/gallium/state_trackers/python/p_device.i @@ -134,7 +134,7 @@ struct st_device { } struct pipe_resource * - buffer_create(unsigned size, unsigned bind = 0) { - return pipe_buffer_create($self->screen, bind, size); + buffer_create(unsigned size, unsigned usage, unsigned bind = 0) { + return pipe_buffer_create($self->screen, bind, usage, size); } }; diff --git a/src/gallium/state_trackers/vega/Makefile b/src/gallium/state_trackers/vega/Makefile index 7342c124c28..3e8ad49b767 100644 --- a/src/gallium/state_trackers/vega/Makefile +++ b/src/gallium/state_trackers/vega/Makefile @@ -24,23 +24,25 @@ C_SOURCES = \ api_path.c \ api_text.c \ api_transform.c \ - vgu.c \ - vg_context.c \ - vg_manager.c \ - vg_state.c \ - vg_translate.c \ - polygon.c \ - bezier.c \ - path.c \ - paint.c \ arc.c \ + bezier.c \ + handle.c \ image.c \ + mask.c \ + paint.c \ + path.c \ + polygon.c \ renderer.c \ + shader.c \ + shaders_cache.c \ stroker.c \ - mask.c \ text.c \ - shader.c \ - shaders_cache.c + vg_context.c \ + vg_manager.c \ + vg_state.c \ + vg_translate.c \ + vgu.c + GENERATED_SOURCES := api_tmp.h diff --git a/src/gallium/state_trackers/vega/SConscript b/src/gallium/state_trackers/vega/SConscript index 4900135a1c5..f3732aa1577 100644 --- a/src/gallium/state_trackers/vega/SConscript +++ b/src/gallium/state_trackers/vega/SConscript @@ -26,23 +26,24 @@ vega_sources = [ 'api_path.c', 'api_text.c', 'api_transform.c', - 'vgu.c', - 'vg_context.c', - 'vg_manager.c', - 'vg_state.c', - 'vg_translate.c', - 'polygon.c', - 'bezier.c', - 'path.c', - 'paint.c', 'arc.c', + 'bezier.c', + 'handle.c', 'image.c', - 'renderer.c', - 'stroker.c', 'mask.c', + 'paint.c', + 'path.c', + 'polygon.c', + 'renderer.c', 'shader.c', 'shaders_cache.c', + 'stroker.c', 'text.c', + 'vg_context.c', + 'vg_manager.c', + 'vg_state.c', + 'vg_translate.c', + 'vgu.c' ] api_tmp = env.CodeGenerate( diff --git a/src/gallium/state_trackers/vega/api_filters.c b/src/gallium/state_trackers/vega/api_filters.c index 724e38241b5..6be460c495c 100644 --- a/src/gallium/state_trackers/vega/api_filters.c +++ b/src/gallium/state_trackers/vega/api_filters.c @@ -29,6 +29,7 @@ #include "vg_context.h" #include "image.h" #include "api.h" +#include "handle.h" #include "renderer.h" #include "shaders_cache.h" @@ -251,8 +252,8 @@ void vegaColorMatrix(VGImage dst, VGImage src, return; } - d = (struct vg_image*)dst; - s = (struct vg_image*)src; + d = handle_to_image(dst); + s = handle_to_image(src); if (vg_image_overlaps(d, s)) { vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); @@ -293,7 +294,7 @@ void vegaConvolve(VGImage dst, VGImage src, struct vg_image *d, *s; VGint kernel_size = kernelWidth * kernelHeight; struct filter_info info; - const VGint max_kernel_size = vgGeti(VG_MAX_KERNEL_SIZE); + const VGint max_kernel_size = vegaGeti(VG_MAX_KERNEL_SIZE); if (dst == VG_INVALID_HANDLE || src == VG_INVALID_HANDLE) { vg_set_error(ctx, VG_BAD_HANDLE_ERROR); @@ -317,8 +318,8 @@ void vegaConvolve(VGImage dst, VGImage src, return; } - d = (struct vg_image*)dst; - s = (struct vg_image*)src; + d = handle_to_image(dst); + s = handle_to_image(src); if (vg_image_overlaps(d, s)) { vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); @@ -395,7 +396,7 @@ void vegaSeparableConvolve(VGImage dst, VGImage src, struct vg_context *ctx = vg_current_context(); VGshort *kernel; VGint i, j, idx = 0; - const VGint max_kernel_size = vgGeti(VG_MAX_SEPARABLE_KERNEL_SIZE); + const VGint max_kernel_size = vegaGeti(VG_MAX_SEPARABLE_KERNEL_SIZE); if (dst == VG_INVALID_HANDLE || src == VG_INVALID_HANDLE) { vg_set_error(ctx, VG_BAD_HANDLE_ERROR); @@ -425,8 +426,8 @@ void vegaSeparableConvolve(VGImage dst, VGImage src, ++idx; } } - vgConvolve(dst, src, kernelWidth, kernelHeight, shiftX, shiftY, - kernel, scale, bias, tilingMode); + vegaConvolve(dst, src, kernelWidth, kernelHeight, shiftX, shiftY, + kernel, scale, bias, tilingMode); free(kernel); } @@ -502,8 +503,8 @@ void vegaGaussianBlur(VGImage dst, VGImage src, return; } - d = (struct vg_image*)dst; - s = (struct vg_image*)src; + d = handle_to_image(dst); + s = handle_to_image(src); if (vg_image_overlaps(d, s)) { vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); @@ -599,8 +600,8 @@ void vegaLookup(VGImage dst, VGImage src, return; } - d = (struct vg_image*)dst; - s = (struct vg_image*)src; + d = handle_to_image(dst); + s = handle_to_image(src); if (vg_image_overlaps(d, s)) { vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); @@ -662,8 +663,8 @@ void vegaLookupSingle(VGImage dst, VGImage src, return; } - d = (struct vg_image*)dst; - s = (struct vg_image*)src; + d = handle_to_image(dst); + s = handle_to_image(src); if (vg_image_overlaps(d, s)) { vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); diff --git a/src/gallium/state_trackers/vega/api_images.c b/src/gallium/state_trackers/vega/api_images.c index ad95409cd00..b993ba62c26 100644 --- a/src/gallium/state_trackers/vega/api_images.c +++ b/src/gallium/state_trackers/vega/api_images.c @@ -32,6 +32,7 @@ #include "vg_translate.h" #include "api_consts.h" #include "api.h" +#include "handle.h" #include "pipe/p_context.h" #include "pipe/p_screen.h" @@ -105,12 +106,12 @@ VGImage vegaCreateImage(VGImageFormat format, vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); return VG_INVALID_HANDLE; } - if (width > vgGeti(VG_MAX_IMAGE_WIDTH) || - height > vgGeti(VG_MAX_IMAGE_HEIGHT)) { + if (width > vegaGeti(VG_MAX_IMAGE_WIDTH) || + height > vegaGeti(VG_MAX_IMAGE_HEIGHT)) { vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); return VG_INVALID_HANDLE; } - if (width * height > vgGeti(VG_MAX_IMAGE_PIXELS)) { + if (width * height > vegaGeti(VG_MAX_IMAGE_PIXELS)) { vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); return VG_INVALID_HANDLE; } @@ -122,19 +123,19 @@ VGImage vegaCreateImage(VGImageFormat format, return VG_INVALID_HANDLE; } - return (VGImage)image_create(format, width, height); + return image_to_handle(image_create(format, width, height)); } void vegaDestroyImage(VGImage image) { struct vg_context *ctx = vg_current_context(); - struct vg_image *img = (struct vg_image *)image; + struct vg_image *img = handle_to_image(image); if (image == VG_INVALID_HANDLE) { vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return; } - if (!vg_object_is_valid((void*)image, VG_OBJECT_IMAGE)) { + if (!vg_object_is_valid(image, VG_OBJECT_IMAGE)) { vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return; } @@ -157,7 +158,7 @@ void vegaClearImage(VGImage image, return; } - img = (struct vg_image*)image; + img = handle_to_image(image); if (x + width < 0 || y + height < 0) return; @@ -189,7 +190,7 @@ void vegaImageSubData(VGImage image, return; } - img = (struct vg_image*)(image); + img = handle_to_image(image); image_sub_data(img, data, dataStride, dataFormat, x, y, width, height); } @@ -216,7 +217,7 @@ void vegaGetImageSubData(VGImage image, vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); return; } - img = (struct vg_image*)image; + img = handle_to_image(image); image_get_sub_data(img, data, dataStride, dataFormat, x, y, width, height); } @@ -229,8 +230,8 @@ VGImage vegaChildImage(VGImage parent, struct vg_image *p; if (parent == VG_INVALID_HANDLE || - !vg_context_is_object_valid(ctx, VG_OBJECT_IMAGE, (void*)parent) || - !vg_object_is_valid((void*)parent, VG_OBJECT_IMAGE)) { + !vg_context_is_object_valid(ctx, VG_OBJECT_IMAGE, parent) || + !vg_object_is_valid(parent, VG_OBJECT_IMAGE)) { vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return VG_INVALID_HANDLE; } @@ -238,7 +239,7 @@ VGImage vegaChildImage(VGImage parent, vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); return VG_INVALID_HANDLE; } - p = (struct vg_image *)parent; + p = handle_to_image(parent); if (x > p->width || y > p->height) { vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); return VG_INVALID_HANDLE; @@ -248,7 +249,7 @@ VGImage vegaChildImage(VGImage parent, return VG_INVALID_HANDLE; } - return (VGImage)image_child_image(p, x, y, width, height); + return image_to_handle(image_child_image(p, x, y, width, height)); } VGImage vegaGetParent(VGImage image) @@ -261,9 +262,9 @@ VGImage vegaGetParent(VGImage image) return VG_INVALID_HANDLE; } - img = (struct vg_image*)image; + img = handle_to_image(image); if (img->parent) - return (VGImage)img->parent; + return image_to_handle(img->parent); else return image; } @@ -285,8 +286,8 @@ void vegaCopyImage(VGImage dst, VGint dx, VGint dy, return; } vg_validate_state(ctx); - image_copy((struct vg_image*)dst, dx, dy, - (struct vg_image*)src, sx, sy, + image_copy(handle_to_image(dst), dx, dy, + handle_to_image(src), sx, sy, width, height, dither); } @@ -303,7 +304,7 @@ void vegaDrawImage(VGImage image) } vg_validate_state(ctx); - image_draw((struct vg_image*)image, + image_draw(handle_to_image(image), &ctx->state.vg.image_user_to_surface_matrix); } @@ -323,7 +324,7 @@ void vegaSetPixels(VGint dx, VGint dy, vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); return; } - image_set_pixels(dx, dy, (struct vg_image*)src, sx, sy, width, + image_set_pixels(dx, dy, handle_to_image(src), sx, sy, width, height); } @@ -343,7 +344,7 @@ void vegaGetPixels(VGImage dst, VGint dx, VGint dy, return; } - img = (struct vg_image*)dst; + img = handle_to_image(dst); image_get_pixels(img, dx, dy, sx, sy, width, height); @@ -487,7 +488,7 @@ void vegaCopyPixels(VGint dx, VGint dy, vg_validate_state(ctx); /* make sure rendering has completed */ - vgFinish(); + vegaFinish(); vg_copy_surface(ctx, strb->surface, dx, dy, strb->surface, sx, sy, width, height); diff --git a/src/gallium/state_trackers/vega/api_masks.c b/src/gallium/state_trackers/vega/api_masks.c index d96afe66387..cdbf0026e89 100644 --- a/src/gallium/state_trackers/vega/api_masks.c +++ b/src/gallium/state_trackers/vega/api_masks.c @@ -28,6 +28,7 @@ #include "mask.h" #include "api.h" +#include "handle.h" #include "renderer.h" #include "vg_context.h" @@ -56,11 +57,11 @@ void vegaMask(VGHandle mask, VGMaskOperation operation, mask_fill(x, y, width, height, 0.f); } else if (operation == VG_FILL_MASK) { mask_fill(x, y, width, height, 1.f); - } else if (vg_object_is_valid((void*)mask, VG_OBJECT_IMAGE)) { - struct vg_image *image = (struct vg_image *)mask; + } else if (vg_object_is_valid(mask, VG_OBJECT_IMAGE)) { + struct vg_image *image = handle_to_image(mask); mask_using_image(image, operation, x, y, width, height); - } else if (vg_object_is_valid((void*)mask, VG_OBJECT_MASK)) { - struct vg_mask_layer *layer = (struct vg_mask_layer *)mask; + } else if (vg_object_is_valid(mask, VG_OBJECT_MASK)) { + struct vg_mask_layer *layer = handle_to_masklayer(mask); mask_using_layer(layer, operation, x, y, width, height); } else { vg_set_error(ctx, VG_BAD_HANDLE_ERROR); @@ -123,14 +124,14 @@ void vegaRenderToMask(VGPath path, vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); return; } - if (!vg_object_is_valid((void*)path, VG_OBJECT_PATH)) { + if (!vg_object_is_valid(path, VG_OBJECT_PATH)) { vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return; } vg_validate_state(ctx); - mask_render_to((struct path *)path, paintModes, operation); + mask_render_to(handle_to_path(path), paintModes, operation); } VGMaskLayer vegaCreateMaskLayer(VGint width, VGint height) @@ -138,13 +139,13 @@ VGMaskLayer vegaCreateMaskLayer(VGint width, VGint height) struct vg_context *ctx = vg_current_context(); if (width <= 0 || height <= 0 || - width > vgGeti(VG_MAX_IMAGE_WIDTH) || - height > vgGeti(VG_MAX_IMAGE_HEIGHT)) { + width > vegaGeti(VG_MAX_IMAGE_WIDTH) || + height > vegaGeti(VG_MAX_IMAGE_HEIGHT)) { vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); return VG_INVALID_HANDLE; } - return (VGMaskLayer)mask_layer_create(width, height); + return masklayer_to_handle(mask_layer_create(width, height)); } void vegaDestroyMaskLayer(VGMaskLayer maskLayer) @@ -156,12 +157,12 @@ void vegaDestroyMaskLayer(VGMaskLayer maskLayer) vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return; } - if (!vg_object_is_valid((void*)maskLayer, VG_OBJECT_MASK)) { + if (!vg_object_is_valid(maskLayer, VG_OBJECT_MASK)) { vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return; } - mask = (struct vg_mask_layer *)maskLayer; + mask = handle_to_masklayer(maskLayer); mask_layer_destroy(mask); } @@ -192,12 +193,12 @@ void vegaFillMaskLayer(VGMaskLayer maskLayer, return; } - if (!vg_object_is_valid((void*)maskLayer, VG_OBJECT_MASK)) { + if (!vg_object_is_valid(maskLayer, VG_OBJECT_MASK)) { vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return; } - mask = (struct vg_mask_layer*)maskLayer; + mask = handle_to_masklayer(maskLayer); if (x + width > mask_layer_width(mask) || y + height > mask_layer_height(mask)) { @@ -226,14 +227,14 @@ void vegaCopyMask(VGMaskLayer maskLayer, vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); return; } - if (!vg_object_is_valid((void*)maskLayer, VG_OBJECT_MASK)) { + if (!vg_object_is_valid(maskLayer, VG_OBJECT_MASK)) { vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return; } vg_validate_state(ctx); - mask = (struct vg_mask_layer*)maskLayer; + mask = handle_to_masklayer(maskLayer); mask_copy(mask, sx, sy, dx, dy, width, height); } diff --git a/src/gallium/state_trackers/vega/api_paint.c b/src/gallium/state_trackers/vega/api_paint.c index 1411806455c..2610ebe0576 100644 --- a/src/gallium/state_trackers/vega/api_paint.c +++ b/src/gallium/state_trackers/vega/api_paint.c @@ -29,24 +29,24 @@ #include "vg_context.h" #include "paint.h" #include "api.h" +#include "handle.h" + VGPaint vegaCreatePaint(void) { - return (VGPaint) paint_create(vg_current_context()); + return paint_to_handle(paint_create(vg_current_context())); } void vegaDestroyPaint(VGPaint p) { struct vg_context *ctx = vg_current_context(); - struct vg_paint *paint; if (p == VG_INVALID_HANDLE) { vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return; } - paint = (struct vg_paint *)p; - paint_destroy(paint); + paint_destroy(handle_to_paint(p)); } void vegaSetPaint(VGPaint paint, VGbitfield paintModes) @@ -55,8 +55,8 @@ void vegaSetPaint(VGPaint paint, VGbitfield paintModes) if (paint == VG_INVALID_HANDLE) { /* restore the default */ - paint = (VGPaint)ctx->default_paint; - } else if (!vg_object_is_valid((void*)paint, VG_OBJECT_PAINT)) { + paint = paint_to_handle(ctx->default_paint); + } else if (!vg_object_is_valid(paint, VG_OBJECT_PAINT)) { vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return; } @@ -67,11 +67,13 @@ void vegaSetPaint(VGPaint paint, VGbitfield paintModes) } if (paintModes & VG_FILL_PATH) { - ctx->state.vg.fill_paint = (struct vg_paint *)paint; + ctx->state.vg.fill_paint = handle_to_paint(paint); } if (paintModes & VG_STROKE_PATH) { - ctx->state.vg.stroke_paint = (struct vg_paint *)paint; + ctx->state.vg.stroke_paint = handle_to_paint(paint); } + + ctx->state.dirty |= PAINT_DIRTY; } VGPaint vegaGetPaint(VGPaintMode paintMode) @@ -85,11 +87,11 @@ VGPaint vegaGetPaint(VGPaintMode paintMode) } if (paintMode == VG_FILL_PATH) - paint = (VGPaint)ctx->state.vg.fill_paint; + paint = paint_to_handle(ctx->state.vg.fill_paint); else if (paintMode == VG_STROKE_PATH) - paint = (VGPaint)ctx->state.vg.stroke_paint; + paint = paint_to_handle(ctx->state.vg.stroke_paint); - if (paint == (VGPaint)ctx->default_paint) + if (paint == paint_to_handle(ctx->default_paint)) paint = VG_INVALID_HANDLE; return paint; @@ -98,20 +100,24 @@ VGPaint vegaGetPaint(VGPaintMode paintMode) void vegaSetColor(VGPaint paint, VGuint rgba) { struct vg_context *ctx = vg_current_context(); + struct vg_paint *p; if (paint == VG_INVALID_HANDLE) { vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return; } - if (!vg_object_is_valid((void*)paint, VG_OBJECT_PAINT)) { + if (!vg_object_is_valid(paint, VG_OBJECT_PAINT)) { vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return; } - { - struct vg_paint *p = (struct vg_paint *)paint; - paint_set_colori(p, rgba); - } + + p = handle_to_paint(paint); + paint_set_colori(p, rgba); + + if (ctx->state.vg.fill_paint == p || + ctx->state.vg.stroke_paint == p) + ctx->state.dirty |= PAINT_DIRTY; } VGuint vegaGetColor(VGPaint paint) @@ -125,11 +131,11 @@ VGuint vegaGetColor(VGPaint paint) return rgba; } - if (!vg_object_is_valid((void*)paint, VG_OBJECT_PAINT)) { + if (!vg_object_is_valid(paint, VG_OBJECT_PAINT)) { vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return rgba; } - p = (struct vg_paint *)paint; + p = handle_to_paint(paint); return paint_colori(p); } @@ -139,28 +145,28 @@ void vegaPaintPattern(VGPaint paint, VGImage pattern) struct vg_context *ctx = vg_current_context(); if (paint == VG_INVALID_HANDLE || - !vg_context_is_object_valid(ctx, VG_OBJECT_PAINT, (void *)paint)) { + !vg_context_is_object_valid(ctx, VG_OBJECT_PAINT, paint)) { vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return; } if (pattern == VG_INVALID_HANDLE) { - paint_set_type((struct vg_paint*)paint, VG_PAINT_TYPE_COLOR); + paint_set_type(handle_to_paint(paint), VG_PAINT_TYPE_COLOR); return; } - if (!vg_context_is_object_valid(ctx, VG_OBJECT_IMAGE, (void *)pattern)) { + if (!vg_context_is_object_valid(ctx, VG_OBJECT_IMAGE, pattern)) { vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return; } - if (!vg_object_is_valid((void*)paint, VG_OBJECT_PAINT) || - !vg_object_is_valid((void*)pattern, VG_OBJECT_IMAGE)) { + if (!vg_object_is_valid(paint, VG_OBJECT_PAINT) || + !vg_object_is_valid(pattern, VG_OBJECT_IMAGE)) { vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return; } - paint_set_pattern((struct vg_paint*)paint, - (struct vg_image*)pattern); + paint_set_pattern(handle_to_paint(paint), + handle_to_image(pattern)); } diff --git a/src/gallium/state_trackers/vega/api_params.c b/src/gallium/state_trackers/vega/api_params.c index a73b6c3effe..aa1e5dd280a 100644 --- a/src/gallium/state_trackers/vega/api_params.c +++ b/src/gallium/state_trackers/vega/api_params.c @@ -29,6 +29,7 @@ #include "vg_context.h" #include "paint.h" #include "path.h" +#include "handle.h" #include "image.h" #include "text.h" #include "matrix.h" @@ -60,7 +61,7 @@ static INLINE VGboolean count_in_bounds(VGParamType type, VGint count) else if (type == VG_STROKE_DASH_PATTERN) { return count <= VEGA_MAX_DASH_COUNT; } else { - VGint real_count = vgGetVectorSize(type); + VGint real_count = vegaGetVectorSize(type); return count == real_count; } } @@ -103,7 +104,7 @@ void vegaSetf (VGParamType type, VGfloat value) case VG_MAX_IMAGE_BYTES: case VG_MAX_GAUSSIAN_STD_DEVIATION: case VG_MAX_FLOAT: - vgSeti(type, floor(value)); + vegaSeti(type, floor(value)); return; break; case VG_STROKE_LINE_WIDTH: @@ -289,7 +290,7 @@ void vegaSetfv(VGParamType type, VGint count, case VG_FILTER_FORMAT_LINEAR: case VG_FILTER_FORMAT_PREMULTIPLIED: case VG_FILTER_CHANNEL_MASK: - vgSeti(type, floor(values[0])); + vegaSeti(type, floor(values[0])); return; break; case VG_SCISSOR_RECTS: { @@ -416,7 +417,7 @@ void vegaSetiv(VGParamType type, VGint count, case VG_FILTER_FORMAT_LINEAR: case VG_FILTER_FORMAT_PREMULTIPLIED: case VG_FILTER_CHANNEL_MASK: - vgSeti(type, values[0]); + vegaSeti(type, values[0]); return; break; case VG_SCISSOR_RECTS: { @@ -536,7 +537,7 @@ VGfloat vegaGetf(VGParamType type) case VG_FILTER_FORMAT_LINEAR: case VG_FILTER_FORMAT_PREMULTIPLIED: case VG_FILTER_CHANNEL_MASK: - return vgGeti(type); + return vegaGeti(type); break; case VG_STROKE_LINE_WIDTH: value = state->stroke.line_width.f; @@ -558,7 +559,7 @@ VGfloat vegaGetf(VGParamType type) case VG_MAX_IMAGE_PIXELS: case VG_MAX_IMAGE_BYTES: case VG_MAX_GAUSSIAN_STD_DEVIATION: - return vgGeti(type); + return vegaGeti(type); break; case VG_MAX_FLOAT: value = 1e+10;/*must be at least 1e+10*/ @@ -674,7 +675,7 @@ VGint vegaGeti(VGParamType type) break; case VG_MAX_FLOAT: { - VGfloat val = vgGetf(type); + VGfloat val = vegaGetf(type); value = float_to_int_floor(*((VGuint*)&val)); } break; @@ -765,7 +766,7 @@ void vegaGetfv(VGParamType type, VGint count, { const struct vg_state *state = current_state(); struct vg_context *ctx = vg_current_context(); - VGint real_count = vgGetVectorSize(type); + VGint real_count = vegaGetVectorSize(type); if (!values || count <= 0 || count > real_count || !is_aligned(values)) { vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); @@ -802,10 +803,10 @@ void vegaGetfv(VGParamType type, VGint count, case VG_MAX_IMAGE_PIXELS: case VG_MAX_IMAGE_BYTES: case VG_MAX_GAUSSIAN_STD_DEVIATION: - values[0] = vgGeti(type); + values[0] = vegaGeti(type); break; case VG_MAX_FLOAT: - values[0] = vgGetf(type); + values[0] = vegaGetf(type); break; case VG_SCISSOR_RECTS: { VGint i; @@ -866,7 +867,7 @@ void vegaGetiv(VGParamType type, VGint count, { const struct vg_state *state = current_state(); struct vg_context *ctx = vg_current_context(); - VGint real_count = vgGetVectorSize(type); + VGint real_count = vegaGetVectorSize(type); if (!values || count <= 0 || count > real_count || !is_aligned(values)) { vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); @@ -903,10 +904,10 @@ void vegaGetiv(VGParamType type, VGint count, case VG_MAX_IMAGE_PIXELS: case VG_MAX_IMAGE_BYTES: case VG_MAX_GAUSSIAN_STD_DEVIATION: - values[0] = vgGeti(type); + values[0] = vegaGeti(type); break; case VG_MAX_FLOAT: { - VGfloat val = vgGetf(type); + VGfloat val = vegaGetf(type); values[0] = float_to_int_floor(*((VGuint*)&val)); } break; @@ -972,9 +973,9 @@ void vegaSetParameterf(VGHandle object, VGfloat value) { struct vg_context *ctx = vg_current_context(); - void *ptr = (void*)object; + void *ptr = handle_to_pointer(object); - if (!object || object == VG_INVALID_HANDLE || !is_aligned(ptr)) { + if (object == VG_INVALID_HANDLE || !is_aligned(ptr)) { vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return; } @@ -983,7 +984,7 @@ void vegaSetParameterf(VGHandle object, case VG_PAINT_TYPE: case VG_PAINT_COLOR_RAMP_SPREAD_MODE: case VG_PAINT_PATTERN_TILING_MODE: - vgSetParameteri(object, paramType, floor(value)); + vegaSetParameteri(object, paramType, floor(value)); return; break; case VG_PAINT_COLOR: @@ -994,7 +995,7 @@ void vegaSetParameterf(VGHandle object, vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); break; case VG_PAINT_COLOR_RAMP_PREMULTIPLIED: { - struct vg_paint *p = (struct vg_paint *)object; + struct vg_paint *p = handle_to_paint(object); paint_set_color_ramp_premultiplied(p, value); } break; @@ -1026,9 +1027,9 @@ void vegaSetParameteri(VGHandle object, VGint value) { struct vg_context *ctx = vg_current_context(); - void *ptr = (void*)object; + void *ptr = handle_to_pointer(object); - if (!object || object == VG_INVALID_HANDLE || !is_aligned(ptr)) { + if (object == VG_INVALID_HANDLE || !is_aligned(ptr)) { vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return; } @@ -1039,7 +1040,7 @@ void vegaSetParameteri(VGHandle object, value > VG_PAINT_TYPE_PATTERN) vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); else { - struct vg_paint *paint = (struct vg_paint *)ptr; + struct vg_paint *paint = handle_to_paint(object); paint_set_type(paint, value); } break; @@ -1055,12 +1056,12 @@ void vegaSetParameteri(VGHandle object, value > VG_COLOR_RAMP_SPREAD_REFLECT) vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); else { - struct vg_paint *paint = (struct vg_paint *)ptr; + struct vg_paint *paint = handle_to_paint(object); paint_set_spread_mode(paint, value); } break; case VG_PAINT_COLOR_RAMP_PREMULTIPLIED: { - struct vg_paint *p = (struct vg_paint *)object; + struct vg_paint *p = handle_to_paint(object); paint_set_color_ramp_premultiplied(p, value); } break; @@ -1069,7 +1070,7 @@ void vegaSetParameteri(VGHandle object, value > VG_TILE_REFLECT) vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); else { - struct vg_paint *paint = (struct vg_paint *)ptr; + struct vg_paint *paint = handle_to_paint(object); paint_set_pattern_tiling(paint, value); } break; @@ -1102,10 +1103,10 @@ void vegaSetParameterfv(VGHandle object, const VGfloat * values) { struct vg_context *ctx = vg_current_context(); - void *ptr = (void*)object; - VGint real_count = vgGetParameterVectorSize(object, paramType); + void *ptr = handle_to_pointer(object); + VGint real_count = vegaGetParameterVectorSize(object, paramType); - if (!object || object == VG_INVALID_HANDLE || !is_aligned(ptr)) { + if (object == VG_INVALID_HANDLE || !is_aligned(ptr)) { vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return; } @@ -1125,15 +1126,18 @@ void vegaSetParameterfv(VGHandle object, if (count != 1) vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); else - vgSetParameterf(object, paramType, values[0]); + vegaSetParameterf(object, paramType, values[0]); return; break; case VG_PAINT_COLOR: { if (count != 4) vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); else { - struct vg_paint *paint = (struct vg_paint *)object; + struct vg_paint *paint = handle_to_paint(object); paint_set_color(paint, values); + if (ctx->state.vg.fill_paint == paint || + ctx->state.vg.stroke_paint == paint) + ctx->state.dirty |= PAINT_DIRTY; } } break; @@ -1141,7 +1145,7 @@ void vegaSetParameterfv(VGHandle object, if (count && count < 4) vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); else { - struct vg_paint *paint = (struct vg_paint *)object; + struct vg_paint *paint = handle_to_paint(object); count = MIN2(count, VEGA_MAX_COLOR_RAMP_STOPS); paint_set_ramp_stops(paint, values, count); { @@ -1159,7 +1163,7 @@ void vegaSetParameterfv(VGHandle object, if (count != 4) vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); else { - struct vg_paint *paint = (struct vg_paint *)object; + struct vg_paint *paint = handle_to_paint(object); paint_set_linear_gradient(paint, values); { VGint vals[4]; @@ -1176,7 +1180,7 @@ void vegaSetParameterfv(VGHandle object, if (count != 5) vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); else { - struct vg_paint *paint = (struct vg_paint *)object; + struct vg_paint *paint = handle_to_paint(object); paint_set_radial_gradient(paint, values); { VGint vals[5]; @@ -1215,10 +1219,10 @@ void vegaSetParameteriv(VGHandle object, const VGint * values) { struct vg_context *ctx = vg_current_context(); - void *ptr = (void*)object; - VGint real_count = vgGetParameterVectorSize(object, paramType); + void *ptr = handle_to_pointer(object); + VGint real_count = vegaGetParameterVectorSize(object, paramType); - if (!object || object == VG_INVALID_HANDLE || !is_aligned(ptr)) { + if (object == VG_INVALID_HANDLE || !is_aligned(ptr)) { vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return; } @@ -1238,15 +1242,18 @@ void vegaSetParameteriv(VGHandle object, if (count != 1) vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); else - vgSetParameteri(object, paramType, values[0]); + vegaSetParameteri(object, paramType, values[0]); return; break; case VG_PAINT_COLOR: { if (count != 4) vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); else { - struct vg_paint *paint = (struct vg_paint *)object; + struct vg_paint *paint = handle_to_paint(object); paint_set_coloriv(paint, values); + if (ctx->state.vg.fill_paint == paint || + ctx->state.vg.stroke_paint == paint) + ctx->state.dirty |= PAINT_DIRTY; } } break; @@ -1256,7 +1263,7 @@ void vegaSetParameteriv(VGHandle object, else { VGfloat *vals = 0; int i; - struct vg_paint *paint = (struct vg_paint *)object; + struct vg_paint *paint = handle_to_paint(object); if (count) { vals = malloc(sizeof(VGfloat)*count); for (i = 0; i < count; ++i) @@ -1274,7 +1281,7 @@ void vegaSetParameteriv(VGHandle object, vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); else { VGfloat vals[4]; - struct vg_paint *paint = (struct vg_paint *)object; + struct vg_paint *paint = handle_to_paint(object); vals[0] = values[0]; vals[1] = values[1]; vals[2] = values[2]; @@ -1289,7 +1296,7 @@ void vegaSetParameteriv(VGHandle object, vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); else { VGfloat vals[5]; - struct vg_paint *paint = (struct vg_paint *)object; + struct vg_paint *paint = handle_to_paint(object); vals[0] = values[0]; vals[1] = values[1]; vals[2] = values[2]; @@ -1318,9 +1325,8 @@ VGint vegaGetParameterVectorSize(VGHandle object, VGint paramType) { struct vg_context *ctx = vg_current_context(); - void *ptr = (void*)object; - if (!ptr || object == VG_INVALID_HANDLE) { + if (object == VG_INVALID_HANDLE) { vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return 0; } @@ -1334,7 +1340,7 @@ VGint vegaGetParameterVectorSize(VGHandle object, case VG_PAINT_COLOR: return 4; case VG_PAINT_COLOR_RAMP_STOPS: { - struct vg_paint *p = (struct vg_paint *)object; + struct vg_paint *p = handle_to_paint(object); return paint_num_ramp_stops(p); } break; @@ -1374,9 +1380,8 @@ VGfloat vegaGetParameterf(VGHandle object, VGint paramType) { struct vg_context *ctx = vg_current_context(); - void *ptr = (void*)object; - if (!ptr || object == VG_INVALID_HANDLE) { + if (object == VG_INVALID_HANDLE) { vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return 0; } @@ -1386,7 +1391,7 @@ VGfloat vegaGetParameterf(VGHandle object, case VG_PAINT_COLOR_RAMP_SPREAD_MODE: case VG_PAINT_COLOR_RAMP_PREMULTIPLIED: case VG_PAINT_PATTERN_TILING_MODE: - return vgGetParameteri(object, paramType); + return vegaGetParameteri(object, paramType); break; case VG_PAINT_COLOR: case VG_PAINT_COLOR_RAMP_STOPS: @@ -1398,17 +1403,17 @@ VGfloat vegaGetParameterf(VGHandle object, case VG_PATH_FORMAT: return VG_PATH_FORMAT_STANDARD; case VG_PATH_SCALE: { - struct path *p = (struct path*)object; + struct path *p = handle_to_path(object); return path_scale(p); } case VG_PATH_BIAS: { - struct path *p = (struct path*)object; + struct path *p = handle_to_path(object); return path_bias(p); } case VG_PATH_DATATYPE: case VG_PATH_NUM_SEGMENTS: case VG_PATH_NUM_COORDS: - return vgGetParameteri(object, paramType); + return vegaGetParameteri(object, paramType); break; case VG_IMAGE_FORMAT: @@ -1416,7 +1421,7 @@ VGfloat vegaGetParameterf(VGHandle object, case VG_IMAGE_HEIGHT: #ifdef OPENVG_VERSION_1_1 case VG_FONT_NUM_GLYPHS: - return vgGetParameteri(object, paramType); + return vegaGetParameteri(object, paramType); break; #endif @@ -1431,30 +1436,29 @@ VGint vegaGetParameteri(VGHandle object, VGint paramType) { struct vg_context *ctx = vg_current_context(); - void *ptr = (void*)object; - if (!ptr || object == VG_INVALID_HANDLE) { + if (object == VG_INVALID_HANDLE) { vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return 0; } switch(paramType) { case VG_PAINT_TYPE: { - struct vg_paint *paint = (struct vg_paint *)ptr; + struct vg_paint *paint = handle_to_paint(object); return paint_type(paint); } break; case VG_PAINT_COLOR_RAMP_SPREAD_MODE: { - struct vg_paint *p = (struct vg_paint *)object; + struct vg_paint *p = handle_to_paint(object); return paint_spread_mode(p); } case VG_PAINT_COLOR_RAMP_PREMULTIPLIED: { - struct vg_paint *p = (struct vg_paint *)object; + struct vg_paint *p = handle_to_paint(object); return paint_color_ramp_premultiplied(p); } break; case VG_PAINT_PATTERN_TILING_MODE: { - struct vg_paint *p = (struct vg_paint *)object; + struct vg_paint *p = handle_to_paint(object); return paint_pattern_tiling(p); } break; @@ -1469,40 +1473,40 @@ VGint vegaGetParameteri(VGHandle object, return VG_PATH_FORMAT_STANDARD; case VG_PATH_SCALE: case VG_PATH_BIAS: - return vgGetParameterf(object, paramType); + return vegaGetParameterf(object, paramType); case VG_PATH_DATATYPE: { - struct path *p = (struct path*)object; + struct path *p = handle_to_path(object); return path_datatype(p); } case VG_PATH_NUM_SEGMENTS: { - struct path *p = (struct path*)object; + struct path *p = handle_to_path(object); return path_num_segments(p); } case VG_PATH_NUM_COORDS: { - struct path *p = (struct path*)object; + struct path *p = handle_to_path(object); return path_num_coords(p); } break; case VG_IMAGE_FORMAT: { - struct vg_image *img = (struct vg_image*)object; + struct vg_image *img = handle_to_image(object); return img->format; } break; case VG_IMAGE_WIDTH: { - struct vg_image *img = (struct vg_image*)object; + struct vg_image *img = handle_to_image(object); return img->width; } break; case VG_IMAGE_HEIGHT: { - struct vg_image *img = (struct vg_image*)object; + struct vg_image *img = handle_to_image(object); return img->height; } break; #ifdef OPENVG_VERSION_1_1 case VG_FONT_NUM_GLYPHS: { - struct vg_font *font = (struct vg_font*)object; + struct vg_font *font = handle_to_font(object); return font_num_glyphs(font); } break; @@ -1521,10 +1525,9 @@ void vegaGetParameterfv(VGHandle object, VGfloat * values) { struct vg_context *ctx = vg_current_context(); - void *ptr = (void*)object; - VGint real_count = vgGetParameterVectorSize(object, paramType); + VGint real_count = vegaGetParameterVectorSize(object, paramType); - if (!ptr || object == VG_INVALID_HANDLE) { + if (object == VG_INVALID_HANDLE) { vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return; } @@ -1537,41 +1540,41 @@ void vegaGetParameterfv(VGHandle object, switch(paramType) { case VG_PAINT_TYPE: { - struct vg_paint *p = (struct vg_paint *)object; + struct vg_paint *p = handle_to_paint(object); values[0] = paint_type(p); } break; case VG_PAINT_COLOR_RAMP_SPREAD_MODE: { - struct vg_paint *p = (struct vg_paint *)object; + struct vg_paint *p = handle_to_paint(object); values[0] = paint_spread_mode(p); } break; case VG_PAINT_COLOR_RAMP_PREMULTIPLIED: { - struct vg_paint *p = (struct vg_paint *)object; + struct vg_paint *p = handle_to_paint(object); values[0] = paint_color_ramp_premultiplied(p); } break; case VG_PAINT_PATTERN_TILING_MODE: { - values[0] = vgGetParameterf(object, paramType); + values[0] = vegaGetParameterf(object, paramType); } break; case VG_PAINT_COLOR: { - struct vg_paint *paint = (struct vg_paint *)object; + struct vg_paint *paint = handle_to_paint(object); paint_get_color(paint, values); } break; case VG_PAINT_COLOR_RAMP_STOPS: { - struct vg_paint *paint = (struct vg_paint *)object; + struct vg_paint *paint = handle_to_paint(object); paint_ramp_stops(paint, values, count); } break; case VG_PAINT_LINEAR_GRADIENT: { - struct vg_paint *paint = (struct vg_paint *)object; + struct vg_paint *paint = handle_to_paint(object); paint_linear_gradient(paint, values); } break; case VG_PAINT_RADIAL_GRADIENT: { - struct vg_paint *paint = (struct vg_paint *)object; + struct vg_paint *paint = handle_to_paint(object); paint_radial_gradient(paint, values); } break; @@ -1580,11 +1583,11 @@ void vegaGetParameterfv(VGHandle object, case VG_PATH_DATATYPE: case VG_PATH_NUM_SEGMENTS: case VG_PATH_NUM_COORDS: - values[0] = vgGetParameteri(object, paramType); + values[0] = vegaGetParameteri(object, paramType); break; case VG_PATH_SCALE: case VG_PATH_BIAS: - values[0] = vgGetParameterf(object, paramType); + values[0] = vegaGetParameterf(object, paramType); break; case VG_IMAGE_FORMAT: @@ -1592,7 +1595,7 @@ void vegaGetParameterfv(VGHandle object, case VG_IMAGE_HEIGHT: #ifdef OPENVG_VERSION_1_1 case VG_FONT_NUM_GLYPHS: - values[0] = vgGetParameteri(object, paramType); + values[0] = vegaGetParameteri(object, paramType); break; #endif @@ -1608,10 +1611,9 @@ void vegaGetParameteriv(VGHandle object, VGint * values) { struct vg_context *ctx = vg_current_context(); - void *ptr = (void*)object; - VGint real_count = vgGetParameterVectorSize(object, paramType); + VGint real_count = vegaGetParameterVectorSize(object, paramType); - if (!ptr || object == VG_INVALID_HANDLE) { + if (object || object == VG_INVALID_HANDLE) { vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return; } @@ -1629,45 +1631,45 @@ void vegaGetParameteriv(VGHandle object, case VG_PAINT_PATTERN_TILING_MODE: #ifdef OPENVG_VERSION_1_1 case VG_FONT_NUM_GLYPHS: - values[0] = vgGetParameteri(object, paramType); + values[0] = vegaGetParameteri(object, paramType); break; #endif case VG_PAINT_COLOR: { - struct vg_paint *paint = (struct vg_paint *)object; + struct vg_paint *paint = handle_to_paint(object); paint_get_coloriv(paint, values); } break; case VG_PAINT_COLOR_RAMP_STOPS: { - struct vg_paint *paint = (struct vg_paint *)object; + struct vg_paint *paint = handle_to_paint(object); paint_ramp_stopsi(paint, values, count); } break; case VG_PAINT_LINEAR_GRADIENT: { - struct vg_paint *paint = (struct vg_paint *)object; + struct vg_paint *paint = handle_to_paint(object); paint_linear_gradienti(paint, values); } break; case VG_PAINT_RADIAL_GRADIENT: { - struct vg_paint *paint = (struct vg_paint *)object; + struct vg_paint *paint = handle_to_paint(object); paint_radial_gradienti(paint, values); } break; case VG_PATH_SCALE: case VG_PATH_BIAS: - values[0] = vgGetParameterf(object, paramType); + values[0] = vegaGetParameterf(object, paramType); break; case VG_PATH_FORMAT: case VG_PATH_DATATYPE: case VG_PATH_NUM_SEGMENTS: case VG_PATH_NUM_COORDS: - values[0] = vgGetParameteri(object, paramType); + values[0] = vegaGetParameteri(object, paramType); break; case VG_IMAGE_FORMAT: case VG_IMAGE_WIDTH: case VG_IMAGE_HEIGHT: - values[0] = vgGetParameteri(object, paramType); + values[0] = vegaGetParameteri(object, paramType); break; default: diff --git a/src/gallium/state_trackers/vega/api_path.c b/src/gallium/state_trackers/vega/api_path.c index fe57b7671d9..ab6ce958945 100644 --- a/src/gallium/state_trackers/vega/api_path.c +++ b/src/gallium/state_trackers/vega/api_path.c @@ -27,6 +27,7 @@ #include "VG/openvg.h" #include "vg_context.h" +#include "handle.h" #include "path.h" #include "api.h" @@ -55,9 +56,9 @@ VGPath vegaCreatePath(VGint pathFormat, return VG_INVALID_HANDLE; } - return (VGPath)path_create(datatype, scale, bias, - segmentCapacityHint, coordCapacityHint, - capabilities); + return path_to_handle(path_create(datatype, scale, bias, + segmentCapacityHint, coordCapacityHint, + capabilities)); } void vegaClearPath(VGPath path, VGbitfield capabilities) @@ -70,7 +71,7 @@ void vegaClearPath(VGPath path, VGbitfield capabilities) return; } - p = (struct path *)path; + p = handle_to_path(path); path_clear(p, capabilities); } @@ -84,7 +85,7 @@ void vegaDestroyPath(VGPath p) return; } - path = (struct path *)p; + path = handle_to_path(p); path_destroy(path); } @@ -100,7 +101,7 @@ void vegaRemovePathCapabilities(VGPath path, return; } - p = (struct path*)path; + p = handle_to_path(path); current = path_capabilities(p); path_set_capabilities(p, (current & (~(capabilities & VG_PATH_CAPABILITY_ALL)))); @@ -115,7 +116,7 @@ VGbitfield vegaGetPathCapabilities(VGPath path) vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return 0; } - p = (struct path*)path; + p = handle_to_path(path); return path_capabilities(p); } @@ -128,8 +129,8 @@ void vegaAppendPath(VGPath dstPath, VGPath srcPath) vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return; } - src = (struct path *)srcPath; - dst = (struct path *)dstPath; + src = handle_to_path(srcPath); + dst = handle_to_path(dstPath); if (!(path_capabilities(src) & VG_PATH_CAPABILITY_APPEND_FROM) || !(path_capabilities(dst) & VG_PATH_CAPABILITY_APPEND_TO)) { @@ -167,9 +168,9 @@ void vegaAppendPathData(VGPath dstPath, } } - p = (struct path*)dstPath; + p = handle_to_path(dstPath); - if (!pathData || !is_aligned_to(pathData, path_datatype_size(p))) { + if (!p || !is_aligned_to(p, path_datatype_size(p))) { vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); return; } @@ -199,7 +200,7 @@ void vegaModifyPathCoords(VGPath dstPath, return; } - p = (struct path *)dstPath; + p = handle_to_path(dstPath); if (!pathData || !is_aligned_to(pathData, path_datatype_size(p))) { vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); @@ -226,8 +227,8 @@ void vegaTransformPath(VGPath dstPath, VGPath srcPath) vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return; } - src = (struct path *)srcPath; - dst = (struct path *)dstPath; + src = handle_to_path(srcPath); + dst = handle_to_path(dstPath); if (!(path_capabilities(src) & VG_PATH_CAPABILITY_TRANSFORM_FROM) || !(path_capabilities(dst) & VG_PATH_CAPABILITY_TRANSFORM_TO)) { @@ -251,9 +252,9 @@ VGboolean vegaInterpolatePath(VGPath dstPath, vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return VG_FALSE; } - dst = (struct path *)dstPath; - start = (struct path *)startPath; - end = (struct path *)endPath; + dst = handle_to_path(dstPath); + start = handle_to_path(startPath); + end = handle_to_path(endPath); if (!(path_capabilities(dst) & VG_PATH_CAPABILITY_INTERPOLATE_TO) || !(path_capabilities(start) & VG_PATH_CAPABILITY_INTERPOLATE_FROM) || @@ -285,7 +286,7 @@ VGfloat vegaPathLength(VGPath path, vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); return -1; } - p = (struct path*)path; + p = handle_to_path(path); if (!(path_capabilities(p) & VG_PATH_CAPABILITY_PATH_LENGTH)) { vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR); @@ -330,7 +331,7 @@ void vegaPointAlongPath(VGPath path, return; } - p = (struct path*)path; + p = handle_to_path(path); caps = path_capabilities(p); if (!(caps & VG_PATH_CAPABILITY_POINT_ALONG_PATH) || @@ -385,7 +386,7 @@ void vegaPathBounds(VGPath path, return; } - p = (struct path*)path; + p = handle_to_path(path); caps = path_capabilities(p); if (!(caps & VG_PATH_CAPABILITY_PATH_BOUNDS)) { @@ -422,7 +423,7 @@ void vegaPathTransformedBounds(VGPath path, return; } - p = (struct path*)path; + p = handle_to_path(path); caps = path_capabilities(p); if (!(caps & VG_PATH_CAPABILITY_PATH_TRANSFORMED_BOUNDS)) { @@ -466,6 +467,7 @@ void vegaPathTransformedBounds(VGPath path, void vegaDrawPath(VGPath path, VGbitfield paintModes) { struct vg_context *ctx = vg_current_context(); + struct path *p = handle_to_path(path); if (path == VG_INVALID_HANDLE) { vg_set_error(ctx, VG_BAD_HANDLE_ERROR); @@ -477,9 +479,9 @@ void vegaDrawPath(VGPath path, VGbitfield paintModes) return; } - if (path_is_empty((struct path*)path)) + if (path_is_empty(p)) return; - path_render((struct path*)path, paintModes, + path_render(p, paintModes, &ctx->state.vg.path_user_to_surface_matrix); } diff --git a/src/gallium/state_trackers/vega/api_text.c b/src/gallium/state_trackers/vega/api_text.c index 7c6b4794099..824c7630403 100644 --- a/src/gallium/state_trackers/vega/api_text.c +++ b/src/gallium/state_trackers/vega/api_text.c @@ -29,6 +29,7 @@ #include "vg_context.h" #include "text.h" #include "api.h" +#include "handle.h" #include "util/u_memory.h" @@ -43,19 +44,19 @@ VGFont vegaCreateFont(VGint glyphCapacityHint) return VG_INVALID_HANDLE; } - return (VGFont) font_create(glyphCapacityHint); + return font_to_handle(font_create(glyphCapacityHint)); } void vegaDestroyFont(VGFont f) { - struct vg_font *font = (struct vg_font *)f; + struct vg_font *font = handle_to_font(f); struct vg_context *ctx = vg_current_context(); if (f == VG_INVALID_HANDLE) { vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return; } - if (!vg_object_is_valid((void *) font, VG_OBJECT_FONT)) { + if (!vg_object_is_valid(f, VG_OBJECT_FONT)) { vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return; } @@ -75,7 +76,7 @@ void vegaSetGlyphToPath(VGFont font, struct vg_font *f; if (font == VG_INVALID_HANDLE || - !vg_context_is_object_valid(ctx, VG_OBJECT_FONT, (void *)font)) { + !vg_context_is_object_valid(ctx, VG_OBJECT_FONT, font)) { vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return; } @@ -85,13 +86,13 @@ void vegaSetGlyphToPath(VGFont font, return; } if (path != VG_INVALID_HANDLE && - !vg_context_is_object_valid(ctx, VG_OBJECT_PATH, (void *)path)) { + !vg_context_is_object_valid(ctx, VG_OBJECT_PATH, path)) { vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return; } - pathObj = (struct path*) path; - f = (struct vg_font*) font; + pathObj = handle_to_path(path); + f = handle_to_font(font); font_set_glyph_to_path(f, glyphIndex, pathObj, isHinted, glyphOrigin, escapement); @@ -108,7 +109,7 @@ void vegaSetGlyphToImage(VGFont font, struct vg_font *f; if (font == VG_INVALID_HANDLE || - !vg_context_is_object_valid(ctx, VG_OBJECT_FONT, (void *)font)) { + !vg_context_is_object_valid(ctx, VG_OBJECT_FONT, font)) { vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return; } @@ -118,13 +119,13 @@ void vegaSetGlyphToImage(VGFont font, return; } if (image != VG_INVALID_HANDLE && - !vg_context_is_object_valid(ctx, VG_OBJECT_IMAGE, (void *)image)) { + !vg_context_is_object_valid(ctx, VG_OBJECT_IMAGE, image)) { vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return; } - img_obj = (struct vg_image*)image; - f = (struct vg_font*)font; + img_obj = handle_to_image(image); + f = handle_to_font(font); font_set_glyph_to_image(f, glyphIndex, img_obj, glyphOrigin, escapement); } @@ -140,7 +141,7 @@ void vegaClearGlyph(VGFont font, return; } - f = (struct vg_font*) font; + f = handle_to_font(font); font_clear_glyph(f, glyphIndex); } @@ -161,7 +162,7 @@ void vegaDrawGlyph(VGFont font, vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); return; } - f = (struct vg_font*)font; + f = handle_to_font(font); font_draw_glyph(f, glyphIndex, paintModes, allowAutoHinting); } @@ -199,7 +200,7 @@ void vegaDrawGlyphs(VGFont font, return; } - f = (struct vg_font*)font; + f = handle_to_font(font); font_draw_glyphs(f, glyphCount, glyphIndices, adjustments_x, adjustments_y, paintModes, allowAutoHinting); diff --git a/src/gallium/state_trackers/vega/handle.c b/src/gallium/state_trackers/vega/handle.c new file mode 100644 index 00000000000..11eedd923ed --- /dev/null +++ b/src/gallium/state_trackers/vega/handle.c @@ -0,0 +1,93 @@ +/************************************************************************** + * + * Copyright 2010 VMware, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE 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. + * + **************************************************************************/ + + +#include "handle.h" +#include "util/u_hash.h" +#include "util/u_hash_table.h" + + +/** + * Hash keys are 32-bit VGHandles + */ + +struct util_hash_table *handle_hash = NULL; + + +static unsigned next_handle = 1; + + +static unsigned +hash_func(void *key) +{ + /* XXX this kind of ugly */ + intptr_t ip = pointer_to_intptr(key); + return (unsigned) (ip & 0xffffffff); +} + + +static int +compare(void *key1, void *key2) +{ + if (key1 < key2) + return -1; + else if (key1 > key2) + return +1; + else + return 0; +} + + +void +init_handles(void) +{ + if (!handle_hash) + handle_hash = util_hash_table_create(hash_func, compare); +} + + +void +free_handles(void) +{ + /* XXX destroy */ +} + + +VGHandle +create_handle(void *object) +{ + VGHandle h = next_handle++; + util_hash_table_set(handle_hash, intptr_to_pointer(h), object); + return h; +} + + +void +destroy_handle(VGHandle h) +{ + util_hash_table_remove(handle_hash, intptr_to_pointer(h)); +} + diff --git a/src/gallium/state_trackers/vega/handle.h b/src/gallium/state_trackers/vega/handle.h new file mode 100644 index 00000000000..9ed326d5098 --- /dev/null +++ b/src/gallium/state_trackers/vega/handle.h @@ -0,0 +1,171 @@ +/************************************************************************** + * + * Copyright 2010 VMware, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE 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. + * + **************************************************************************/ + + +/** + * Convert opaque VG object handles into pointers and vice versa. + * XXX This is not yet 64-bit safe! All VG handles are 32 bits in size. + */ + + +#ifndef HANDLE_H +#define HANDLE_H + +#include "pipe/p_compiler.h" +#include "util/u_hash_table.h" +#include "util/u_pointer.h" + +#include "VG/openvg.h" +#include "vg_context.h" + + +extern struct util_hash_table *handle_hash; + + +struct vg_mask_layer; +struct vg_font; +struct vg_image; +struct vg_paint; +struct path; + + +extern void +init_handles(void); + + +extern void +free_handles(void); + + +extern VGHandle +create_handle(void *object); + + +extern void +destroy_handle(VGHandle h); + + +static INLINE VGHandle +object_to_handle(struct vg_object *obj) +{ + return obj ? obj->handle : VG_INVALID_HANDLE; +} + + +static INLINE VGHandle +image_to_handle(struct vg_image *img) +{ + /* vg_image is derived from vg_object */ + return object_to_handle((struct vg_object *) img); +} + + +static INLINE VGHandle +masklayer_to_handle(struct vg_mask_layer *mask) +{ + /* vg_object is derived from vg_object */ + return object_to_handle((struct vg_object *) mask); +} + + +static INLINE VGHandle +font_to_handle(struct vg_font *font) +{ + return object_to_handle((struct vg_object *) font); +} + + +static INLINE VGHandle +paint_to_handle(struct vg_paint *paint) +{ + return object_to_handle((struct vg_object *) paint); +} + + +static INLINE VGHandle +path_to_handle(struct path *path) +{ + return object_to_handle((struct vg_object *) path); +} + + +static INLINE void * +handle_to_pointer(VGHandle h) +{ + void *v = util_hash_table_get(handle_hash, intptr_to_pointer(h)); +#ifdef DEBUG + if (v) { + struct vg_object *obj = (struct vg_object *) v; + assert(obj->handle == h); + } +#endif + return v; +} + + +static INLINE struct vg_font * +handle_to_font(VGHandle h) +{ + return (struct vg_font *) handle_to_pointer(h); +} + + +static INLINE struct vg_image * +handle_to_image(VGHandle h) +{ + return (struct vg_image *) handle_to_pointer(h); +} + + +static INLINE struct vg_mask_layer * +handle_to_masklayer(VGHandle h) +{ + return (struct vg_mask_layer *) handle_to_pointer(h); +} + + +static INLINE struct vg_object * +handle_to_object(VGHandle h) +{ + return (struct vg_object *) handle_to_pointer(h); +} + + +static INLINE struct vg_paint * +handle_to_paint(VGHandle h) +{ + return (struct vg_paint *) handle_to_pointer(h); +} + + +static INLINE struct path * +handle_to_path(VGHandle h) +{ + return (struct path *) handle_to_pointer(h); +} + + +#endif /* HANDLE_H */ diff --git a/src/gallium/state_trackers/vega/image.c b/src/gallium/state_trackers/vega/image.c index 318ea94bdfb..73351b671f9 100644 --- a/src/gallium/state_trackers/vega/image.c +++ b/src/gallium/state_trackers/vega/image.c @@ -349,6 +349,8 @@ void image_destroy(struct vg_image *img) array_destroy(img->children_array); } + vg_free_object(&img->base); + pipe_sampler_view_reference(&img->sampler_view, NULL); FREE(img); } diff --git a/src/gallium/state_trackers/vega/paint.c b/src/gallium/state_trackers/vega/paint.c index 2db8cbcf7c8..6e5348a1ff2 100644 --- a/src/gallium/state_trackers/vega/paint.c +++ b/src/gallium/state_trackers/vega/paint.c @@ -748,3 +748,10 @@ void paint_fill_constant_buffer(struct vg_paint *paint, abort(); } } + +VGboolean paint_is_opaque(struct vg_paint *paint) +{ + /* TODO add other paint types and make sure PAINT_DIRTY gets set */ + return (paint->type == VG_PAINT_TYPE_COLOR && + floatsEqual(paint->solid.color[3], 1.0f)); +} diff --git a/src/gallium/state_trackers/vega/paint.h b/src/gallium/state_trackers/vega/paint.h index 3de3bbe12ed..e5357763b89 100644 --- a/src/gallium/state_trackers/vega/paint.h +++ b/src/gallium/state_trackers/vega/paint.h @@ -118,5 +118,6 @@ void paint_fill_constant_buffer(struct vg_paint *paint, const struct matrix *mat, void *buffer); +VGboolean paint_is_opaque(struct vg_paint *paint); #endif diff --git a/src/gallium/state_trackers/vega/polygon.c b/src/gallium/state_trackers/vega/polygon.c index a491de27fa6..bcc5cb272ca 100644 --- a/src/gallium/state_trackers/vega/polygon.c +++ b/src/gallium/state_trackers/vega/polygon.c @@ -303,7 +303,6 @@ void polygon_fill(struct polygon *poly, struct vg_context *ctx) vbuffer.buffer = poly->vbuf; vbuffer.stride = COMPONENTS * sizeof(float); /* vertex size */ vbuffer.buffer_offset = 0; - vbuffer.max_index = poly->num_verts - 1; renderer_polygon_stencil_begin(ctx->renderer, &velement, ctx->state.vg.fill_rule, VG_FALSE); @@ -354,7 +353,6 @@ void polygon_array_fill(struct polygon_array *polyarray, struct vg_context *ctx) polygon_prepare_buffer(ctx, poly); vbuffer.buffer = poly->vbuf; - vbuffer.max_index = poly->num_verts - 1; renderer_polygon_stencil(ctx->renderer, &vbuffer, PIPE_PRIM_TRIANGLE_FAN, 0, (VGuint) poly->num_verts); diff --git a/src/gallium/state_trackers/vega/renderer.c b/src/gallium/state_trackers/vega/renderer.c index e42bad76492..9de2cb1014d 100644 --- a/src/gallium/state_trackers/vega/renderer.c +++ b/src/gallium/state_trackers/vega/renderer.c @@ -28,6 +28,7 @@ #include "renderer.h" #include "vg_context.h" +#include "paint.h" /* for paint_is_opaque */ #include "pipe/p_context.h" #include "pipe/p_state.h" @@ -173,6 +174,7 @@ static void renderer_set_mvp(struct renderer *renderer, pipe_resource_reference(&cbuf, NULL); cbuf = pipe_buffer_create(renderer->pipe->screen, PIPE_BIND_CONSTANT_BUFFER, + PIPE_USAGE_STATIC, sizeof(consts)); if (cbuf) { pipe_buffer_write(renderer->pipe, cbuf, @@ -473,7 +475,8 @@ static void renderer_set_custom_fs(struct renderer *renderer, pipe_resource_reference(&cbuf, NULL); cbuf = pipe_buffer_create(renderer->pipe->screen, - PIPE_BIND_CONSTANT_BUFFER, const_buffer_len); + PIPE_BIND_CONSTANT_BUFFER, PIPE_USAGE_STATIC, + const_buffer_len); pipe_buffer_write(renderer->pipe, cbuf, 0, const_buffer_len, const_buffer); renderer->pipe->set_constant_buffer(renderer->pipe, @@ -571,7 +574,7 @@ static void renderer_quad_draw(struct renderer *r) sizeof(r->vertices), PIPE_BIND_VERTEX_BUFFER); if (buf) { - util_draw_vertex_buffer(r->pipe, buf, 0, + util_draw_vertex_buffer(r->pipe, r->cso, buf, 0, PIPE_PRIM_TRIANGLE_FAN, Elements(r->vertices), /* verts */ Elements(r->vertices[0])); /* attribs/vert */ @@ -1049,7 +1052,7 @@ void renderer_polygon_stencil(struct renderer *renderer, { assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL); - renderer->pipe->set_vertex_buffers(renderer->pipe, 1, vbuf); + cso_set_vertex_buffers(renderer->cso, 1, vbuf); if (!renderer->u.polygon_stencil.manual_two_sides) { util_draw_arrays(renderer->pipe, mode, start, count); @@ -1289,7 +1292,11 @@ static void renderer_validate_blend(struct renderer *renderer, blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; break; case VG_BLEND_SRC_OVER: - if (!util_format_has_alpha(fb_format)) { + if (paint_is_opaque(state->fill_paint) && + paint_is_opaque(state->stroke_paint)) { + /* no blending */ + } + else if (!util_format_has_alpha(fb_format)) { blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA; blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; diff --git a/src/gallium/state_trackers/vega/shader.c b/src/gallium/state_trackers/vega/shader.c index 2a6bae8a630..bee6d84001d 100644 --- a/src/gallium/state_trackers/vega/shader.c +++ b/src/gallium/state_trackers/vega/shader.c @@ -134,6 +134,8 @@ static VGboolean blend_use_shader(struct vg_context *ctx) switch (ctx->state.vg.blend_mode) { case VG_BLEND_SRC_OVER: advanced_blending = + (!paint_is_opaque(ctx->state.vg.fill_paint) || + !paint_is_opaque(ctx->state.vg.stroke_paint)) && util_format_has_alpha(ctx->draw_buffer->strb->format); break; case VG_BLEND_DST_OVER: diff --git a/src/gallium/state_trackers/vega/vg_context.c b/src/gallium/state_trackers/vega/vg_context.c index f36f55d6c89..83b42609e03 100644 --- a/src/gallium/state_trackers/vega/vg_context.c +++ b/src/gallium/state_trackers/vega/vg_context.c @@ -33,6 +33,7 @@ #include "vg_manager.h" #include "api.h" #include "mask.h" +#include "handle.h" #include "pipe/p_context.h" #include "util/u_inlines.h" @@ -182,17 +183,26 @@ void vg_init_object(struct vg_object *obj, struct vg_context *ctx, enum vg_objec { obj->type = type; obj->ctx = ctx; + obj->handle = create_handle(obj); +} + +/** free object resources, but not the object itself */ +void vg_free_object(struct vg_object *obj) +{ + obj->type = 0; + obj->ctx = NULL; + destroy_handle(obj->handle); } VGboolean vg_context_is_object_valid(struct vg_context *ctx, enum vg_object_type type, - void *ptr) + VGHandle object) { if (ctx) { struct cso_hash *hash = ctx->owned_objects[type]; if (!hash) return VG_FALSE; - return cso_hash_contains(hash, (unsigned)(long)ptr); + return cso_hash_contains(hash, (unsigned)(long)object); } return VG_FALSE; } @@ -398,8 +408,9 @@ void vg_validate_state(struct vg_context *ctx) if (vg_context_update_depth_stencil_rb(ctx, stfb->width, stfb->height)) ctx->state.dirty |= DEPTH_STENCIL_DIRTY; - /* blend state depends on fb format */ - if (ctx->state.dirty & FRAMEBUFFER_DIRTY) + /* blend state depends on fb format and paint color */ + if ((ctx->state.dirty & FRAMEBUFFER_DIRTY) || + (ctx->state.dirty & PAINT_DIRTY)) ctx->state.dirty |= BLEND_DIRTY; renderer_validate(ctx->renderer, ctx->state.dirty, @@ -412,10 +423,10 @@ void vg_validate_state(struct vg_context *ctx) shader_set_color_transform(ctx->shader, ctx->state.vg.color_transform); } -VGboolean vg_object_is_valid(void *ptr, enum vg_object_type type) +VGboolean vg_object_is_valid(VGHandle object, enum vg_object_type type) { - struct vg_object *obj = ptr; - if (ptr && is_aligned(obj) && obj->type == type) + struct vg_object *obj = handle_to_object(object); + if (obj && is_aligned(obj) && obj->type == type) return VG_TRUE; else return VG_FALSE; diff --git a/src/gallium/state_trackers/vega/vg_context.h b/src/gallium/state_trackers/vega/vg_context.h index d616a20a3d9..71491a5aa22 100644 --- a/src/gallium/state_trackers/vega/vg_context.h +++ b/src/gallium/state_trackers/vega/vg_context.h @@ -81,10 +81,12 @@ enum dirty_state { BLEND_DIRTY = 1 << 0, FRAMEBUFFER_DIRTY = 1 << 1, DEPTH_STENCIL_DIRTY = 1 << 2, + PAINT_DIRTY = 1 << 3, ALL_DIRTY = BLEND_DIRTY | FRAMEBUFFER_DIRTY | - DEPTH_STENCIL_DIRTY + DEPTH_STENCIL_DIRTY | + PAINT_DIRTY }; struct vg_context @@ -129,12 +131,21 @@ struct vg_context struct blit_state *blit; }; + +/** + * Base class for VG objects like paths, images, fonts. + */ struct vg_object { enum vg_object_type type; + VGHandle handle; struct vg_context *ctx; }; + + void vg_init_object(struct vg_object *obj, struct vg_context *ctx, enum vg_object_type type); -VGboolean vg_object_is_valid(void *ptr, enum vg_object_type type); +void vg_free_object(struct vg_object *obj); + +VGboolean vg_object_is_valid(VGHandle object, enum vg_object_type type); struct vg_context *vg_create_context(struct pipe_context *pipe, const void *visual, @@ -145,7 +156,7 @@ void vg_set_current_context(struct vg_context *ctx); VGboolean vg_context_is_object_valid(struct vg_context *ctx, enum vg_object_type type, - void *ptr); + VGHandle object); void vg_context_add_object(struct vg_context *ctx, enum vg_object_type type, void *ptr); diff --git a/src/gallium/state_trackers/vega/vg_manager.c b/src/gallium/state_trackers/vega/vg_manager.c index ec713b7fb1d..44d2996bb45 100644 --- a/src/gallium/state_trackers/vega/vg_manager.c +++ b/src/gallium/state_trackers/vega/vg_manager.c @@ -40,6 +40,7 @@ #include "vg_manager.h" #include "vg_context.h" #include "api.h" +#include "handle.h" static boolean vg_context_update_color_rb(struct vg_context *ctx, struct pipe_resource *pt) @@ -172,6 +173,9 @@ vg_api_create_context(struct st_api *stapi, struct st_manager *smapi, if (attribs->major > 1 || (attribs->major == 1 && attribs->minor > 0)) return NULL; + /* for VGHandle / pointer lookups */ + init_handles(); + pipe = smapi->screen->context_create(smapi->screen, NULL); if (!pipe) return NULL; diff --git a/src/gallium/state_trackers/vega/vgu.c b/src/gallium/state_trackers/vega/vgu.c index 7dc51c5599c..4206a91e006 100644 --- a/src/gallium/state_trackers/vega/vgu.c +++ b/src/gallium/state_trackers/vega/vgu.c @@ -29,6 +29,7 @@ #include "matrix.h" #include "path.h" +#include "handle.h" #include "util/u_debug.h" #include "util/u_pointer.h" @@ -36,16 +37,6 @@ #include <math.h> #include <assert.h> -static VGboolean is_aligned_to(const void *ptr, VGbyte alignment) -{ - void *aligned = align_pointer(ptr, alignment); - return (ptr == aligned) ? VG_TRUE : VG_FALSE; -} - -static VGboolean is_aligned(const void *ptr) -{ - return is_aligned_to(ptr, 4); -} static void vgu_append_float_coords(VGPath path, const VGubyte *cmds, @@ -54,7 +45,7 @@ static void vgu_append_float_coords(VGPath path, VGint num_coords) { VGubyte common_data[40 * sizeof(VGfloat)]; - struct path *p = (struct path *)path; + struct path *p = handle_to_path(path); vg_float_to_datatype(path_datatype(p), common_data, coords, num_coords); vgAppendPathData(path, num_cmds, cmds, common_data); diff --git a/src/gallium/state_trackers/wgl/SConscript b/src/gallium/state_trackers/wgl/SConscript index 1b7597de440..7cb953ba742 100644 --- a/src/gallium/state_trackers/wgl/SConscript +++ b/src/gallium/state_trackers/wgl/SConscript @@ -15,6 +15,9 @@ env.AppendUnique(CPPDEFINES = [ 'BUILD_GL32', # declare gl* as __declspec(dllexport) in Mesa headers 'WIN32_LEAN_AND_MEAN', # http://msdn2.microsoft.com/en-us/library/6dwk3a1z.aspx ]) +if not env['gles']: + # prevent _glapi_* from being declared __declspec(dllimport) + env.Append(CPPDEFINES = ['_GLAPI_NO_EXPORTS']) sources = [ 'stw_context.c', diff --git a/src/gallium/state_trackers/wgl/stw_device.c b/src/gallium/state_trackers/wgl/stw_device.c index c4822d4d8aa..4ece4e4979a 100644 --- a/src/gallium/state_trackers/wgl/stw_device.c +++ b/src/gallium/state_trackers/wgl/stw_device.c @@ -170,7 +170,10 @@ stw_cleanup(void) _glthread_DESTROY_MUTEX(OneTimeLock); + /* glapi is statically linked: we can call the local destroy function. */ +#ifdef _GLAPI_NO_EXPORTS _glapi_destroy_multithread(); +#endif #ifdef DEBUG debug_memory_end(stw_dev->memdbg_no); diff --git a/src/gallium/state_trackers/xorg/xorg_crtc.c b/src/gallium/state_trackers/xorg/xorg_crtc.c index 71f7b8c21d0..d751ac18704 100644 --- a/src/gallium/state_trackers/xorg/xorg_crtc.c +++ b/src/gallium/state_trackers/xorg/xorg_crtc.c @@ -135,14 +135,12 @@ crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, /* Only set gamma when needed, to avoid unneeded delays. */ #if defined(XF86_CRTC_VERSION) && XF86_CRTC_VERSION >= 3 - if (!crtc->active) -#endif + if (!crtc->active && crtc->version >= 3) crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green, crtc->gamma_blue, crtc->gamma_size); - -#if defined(XF86_CRTC_VERSION) && XF86_CRTC_VERSION >= 3 crtc->active = TRUE; #endif + crtc->x = x; crtc->y = y; crtc->mode = *mode; diff --git a/src/gallium/state_trackers/xorg/xorg_renderer.c b/src/gallium/state_trackers/xorg/xorg_renderer.c index a3d7c5a70e2..3b3ae455c0b 100644 --- a/src/gallium/state_trackers/xorg/xorg_renderer.c +++ b/src/gallium/state_trackers/xorg/xorg_renderer.c @@ -73,7 +73,7 @@ renderer_draw(struct xorg_renderer *r) if (buf) { cso_set_vertex_elements(r->cso, r->attrs_per_vertex, r->velems); - util_draw_vertex_buffer(pipe, buf, 0, + util_draw_vertex_buffer(pipe, r->cso, buf, 0, PIPE_PRIM_QUADS, num_verts, /* verts */ r->attrs_per_vertex); /* attribs/vert */ @@ -429,6 +429,7 @@ void renderer_set_constants(struct xorg_renderer *r, pipe_resource_reference(cbuf, NULL); *cbuf = pipe_buffer_create(r->pipe->screen, PIPE_BIND_CONSTANT_BUFFER, + PIPE_USAGE_STATIC, param_bytes); if (*cbuf) { @@ -616,7 +617,7 @@ void renderer_draw_yuv(struct xorg_renderer *r, cso_set_vertex_elements(r->cso, num_attribs, r->velems); - util_draw_vertex_buffer(pipe, buf, 0, + util_draw_vertex_buffer(pipe, r->cso, buf, 0, PIPE_PRIM_QUADS, 4, /* verts */ num_attribs); /* attribs/vert */ diff --git a/src/gallium/state_trackers/xorg/xvmc/subpicture.c b/src/gallium/state_trackers/xorg/xvmc/subpicture.c index 4a835c04d8a..78de154bdd7 100644 --- a/src/gallium/state_trackers/xorg/xvmc/subpicture.c +++ b/src/gallium/state_trackers/xorg/xvmc/subpicture.c @@ -14,7 +14,7 @@ * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. @@ -176,6 +176,7 @@ Status XvMCCreateSubpicture(Display *dpy, XvMCContext *context, XvMCSubpicture * template.height0 = util_next_power_of_two(height); } template.depth0 = 1; + template.array_size = 1; template.usage = PIPE_USAGE_DYNAMIC; template.bind = PIPE_BIND_SAMPLER_VIEW; template.flags = 0; @@ -222,7 +223,7 @@ Status XvMCClearSubpicture(Display *dpy, XvMCSubpicture *subpicture, short x, sh if (!subpicture) return XvMCBadSubpicture; - + /* Convert color to float */ util_format_read_4f(PIPE_FORMAT_B8G8R8A8_UNORM, color_f, 1, diff --git a/src/gallium/state_trackers/xorg/xvmc/surface.c b/src/gallium/state_trackers/xorg/xvmc/surface.c index d7285a478fb..c90ad409c10 100644 --- a/src/gallium/state_trackers/xorg/xvmc/surface.c +++ b/src/gallium/state_trackers/xorg/xvmc/surface.c @@ -122,6 +122,7 @@ CreateOrResizeBackBuffer(struct vl_context *vctx, unsigned int width, unsigned i template.width0 = width; template.height0 = height; template.depth0 = 1; + template.array_size = 1; template.usage = PIPE_USAGE_DEFAULT; template.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_BLIT_SOURCE; template.flags = 0; @@ -240,6 +241,7 @@ Status XvMCCreateSurface(Display *dpy, XvMCContext *context, XvMCSurface *surfac template.height0 = util_next_power_of_two(context->height); } template.depth0 = 1; + template.array_size = 1; template.usage = PIPE_USAGE_DEFAULT; template.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; template.flags = 0; diff --git a/src/gallium/targets/SConscript.dri b/src/gallium/targets/SConscript.dri index bc3671a256b..101863a6848 100644 --- a/src/gallium/targets/SConscript.dri +++ b/src/gallium/targets/SConscript.dri @@ -72,7 +72,6 @@ COMMON_DRI_DRM_OBJECTS = [ drienv.AppendUnique(LIBS = [ 'expat', - 'talloc', ]) Export([ diff --git a/src/gallium/targets/dri-r300/Makefile b/src/gallium/targets/dri-r300/Makefile index 9afbb13276d..cc77a4bc20d 100644 --- a/src/gallium/targets/dri-r300/Makefile +++ b/src/gallium/targets/dri-r300/Makefile @@ -22,6 +22,4 @@ DRIVER_DEFINES = \ include ../Makefile.dri -DRI_LIB_DEPS += -ldrm_radeon - symlinks: diff --git a/src/gallium/targets/dri-r300/SConscript b/src/gallium/targets/dri-r300/SConscript index 005b4bbf7f1..683b6c6972d 100644 --- a/src/gallium/targets/dri-r300/SConscript +++ b/src/gallium/targets/dri-r300/SConscript @@ -2,8 +2,6 @@ Import('*') env = drienv.Clone() -env.ParseConfig('pkg-config --cflags --libs libdrm_radeon') - env.Append(CPPDEFINES = ['GALLIUM_RBUG', 'GALLIUM_TRACE', 'GALLIUM_GALAHAD']) env.Prepend(LIBS = [ diff --git a/src/gallium/targets/dri-r600/SConscript b/src/gallium/targets/dri-r600/SConscript index aa771db2d1a..1df11a8747b 100644 --- a/src/gallium/targets/dri-r600/SConscript +++ b/src/gallium/targets/dri-r600/SConscript @@ -2,8 +2,6 @@ Import('*') env = drienv.Clone() -env.ParseConfig('pkg-config --cflags --libs libdrm_radeon') - env.Append(CPPDEFINES = ['GALLIUM_RBUG', 'GALLIUM_TRACE']) env.Prepend(LIBS = [ diff --git a/src/gallium/targets/dri-vmwgfx/Makefile b/src/gallium/targets/dri-vmwgfx/Makefile index 38f78932e13..8c716f42fe2 100644 --- a/src/gallium/targets/dri-vmwgfx/Makefile +++ b/src/gallium/targets/dri-vmwgfx/Makefile @@ -6,6 +6,7 @@ LIBNAME = vmwgfx_dri.so PIPE_DRIVERS = \ $(TOP)/src/gallium/state_trackers/dri/drm/libdridrm.a \ $(TOP)/src/gallium/winsys/svga/drm/libsvgadrm.a \ + $(TOP)/src/gallium/winsys/sw/wrapper/libwsw.a \ $(TOP)/src/gallium/drivers/trace/libtrace.a \ $(TOP)/src/gallium/drivers/rbug/librbug.a \ $(TOP)/src/gallium/drivers/svga/libsvga.a diff --git a/src/gallium/targets/egl-static/SConscript b/src/gallium/targets/egl-static/SConscript index 381ef4e862d..cbd98cc416a 100644 --- a/src/gallium/targets/egl-static/SConscript +++ b/src/gallium/targets/egl-static/SConscript @@ -58,10 +58,18 @@ if env['platform'] == 'windows': env.Prepend(LIBS = [ ws_gdi, ]) -else: - # OpenGL - env.Append(CPPDEFINES = ['FEATURE_GL=1']) - env.Prepend(LIBS = ['GL', 'talloc', glsl, mesa]) + +# OpenGL ES and OpenGL +if env['gles']: + env.Append(CPPDEFINES = [ + 'FEATURE_GL=1', + 'FEATURE_ES1=1', + 'FEATURE_ES2=1' + ]) + env.Prepend(LIBPATH = [shared_glapi.dir]) + # manually add LIBPREFIX on windows + glapi_name = 'glapi' if env['platform'] != 'windows' else 'libglapi' + env.Prepend(LIBS = [glapi_name, glsl, mesa]) # OpenVG if True: @@ -96,7 +104,6 @@ if env['drm']: ]) if env['drm_radeon']: - env.ParseConfig('pkg-config --cflags --libs libdrm_radeon') env.Append(CPPDEFINES = ['_EGL_PIPE_R300', '_EGL_PIPE_R600']) env.Prepend(LIBS = [ radeonwinsys, diff --git a/src/gallium/targets/egl/Makefile b/src/gallium/targets/egl/Makefile index 92d971bab01..de01939e5f1 100644 --- a/src/gallium/targets/egl/Makefile +++ b/src/gallium/targets/egl/Makefile @@ -46,6 +46,9 @@ ifneq ($(findstring x11, $(EGL_PLATFORMS)),) egl_SYS += -lX11 -lXext -lXfixes $(LIBDRM_LIB) egl_LIBS += $(TOP)/src/gallium/winsys/sw/xlib/libws_xlib.a endif +ifneq ($(findstring wayland, $(EGL_PLATFORMS)),) +egl_SYS += $(WAYLAND_LIBS) $(LIBDRM_LIB) +endif ifneq ($(findstring drm, $(EGL_PLATFORMS)),) egl_SYS += $(LIBDRM_LIB) endif @@ -89,7 +92,7 @@ nouveau_LIBS := \ # r300 pipe driver r300_CPPFLAGS := -r300_SYS := -ldrm -ldrm_radeon +r300_SYS := -ldrm r300_LIBS := \ $(TOP)/src/gallium/winsys/radeon/drm/libradeonwinsys.a \ $(TOP)/src/gallium/drivers/r300/libr300.a diff --git a/src/gallium/targets/libgl-gdi/SConscript b/src/gallium/targets/libgl-gdi/SConscript index 6fa0851a1ab..49462a8e309 100644 --- a/src/gallium/targets/libgl-gdi/SConscript +++ b/src/gallium/targets/libgl-gdi/SConscript @@ -15,7 +15,6 @@ env.Append(LIBS = [ 'user32', 'kernel32', 'ws2_32', - talloc, ]) sources = ['libgl_gdi.c'] @@ -37,6 +36,12 @@ drivers += [trace, rbug] env['no_import_lib'] = 1 +# when GLES is enabled, gl* and _glapi_* belong to bridge_glapi and +# shared_glapi respectively +if env['gles']: + env.Prepend(LIBPATH = [shared_glapi.dir]) + glapi = [bridge_glapi, 'libglapi'] + opengl32 = env.SharedLibrary( target ='opengl32', source = sources, diff --git a/src/gallium/targets/libgl-xlib/SConscript b/src/gallium/targets/libgl-xlib/SConscript index d932736be78..ca15372f1d9 100644 --- a/src/gallium/targets/libgl-xlib/SConscript +++ b/src/gallium/targets/libgl-xlib/SConscript @@ -16,6 +16,12 @@ env.Append(CPPDEFINES = ['USE_XSHM']) env.Prepend(LIBS = env['X11_LIBS']) +# when GLES is enabled, gl* and _glapi_* belong to bridge_glapi and +# shared_glapi respectively +if env['gles']: + env.Prepend(LIBPATH = [shared_glapi.dir]) + glapi = [bridge_glapi, 'glapi'] + env.Prepend(LIBS = [ st_xlib, ws_xlib, @@ -23,7 +29,6 @@ env.Prepend(LIBS = [ mesa, glsl, gallium, - 'talloc' ]) sources = [ diff --git a/src/gallium/targets/xorg-radeon/Makefile b/src/gallium/targets/xorg-radeon/Makefile index d3bc3569929..6d5f2c3d16e 100644 --- a/src/gallium/targets/xorg-radeon/Makefile +++ b/src/gallium/targets/xorg-radeon/Makefile @@ -19,6 +19,6 @@ DRIVER_PIPES = \ $(TOP)/src/gallium/drivers/rbug/librbug.a DRIVER_LINKS = \ - $(shell pkg-config --libs libdrm libdrm_radeon) + $(shell pkg-config --libs libdrm) include ../Makefile.xorg diff --git a/src/gallium/tests/graw/SConscript b/src/gallium/tests/graw/SConscript index 3341b884985..565fa5279cd 100644 --- a/src/gallium/tests/graw/SConscript +++ b/src/gallium/tests/graw/SConscript @@ -24,6 +24,7 @@ progs = [ 'gs-test', 'shader-leak', 'tri-gs', + 'quad-sample', ] for name in progs: diff --git a/src/gallium/tests/graw/fs-test.c b/src/gallium/tests/graw/fs-test.c index d21eb44e116..ff82b607110 100644 --- a/src/gallium/tests/graw/fs-test.c +++ b/src/gallium/tests/graw/fs-test.c @@ -215,7 +215,6 @@ static void set_vertices( void ) vbuf.stride = sizeof( struct vertex ); - vbuf.max_index = sizeof(vertices) / vbuf.stride; vbuf.buffer_offset = 0; vbuf.buffer = screen->user_buffer_create(screen, vertices, diff --git a/src/gallium/tests/graw/gs-test.c b/src/gallium/tests/graw/gs-test.c index 0c65390e109..cc05889dd05 100644 --- a/src/gallium/tests/graw/gs-test.c +++ b/src/gallium/tests/graw/gs-test.c @@ -251,13 +251,11 @@ static void set_vertices( void ) vbuf.stride = sizeof( struct vertex ); vbuf.buffer_offset = 0; if (draw_strip) { - vbuf.max_index = sizeof(vertices_strip) / vbuf.stride; vbuf.buffer = screen->user_buffer_create(screen, vertices_strip, sizeof(vertices_strip), PIPE_BIND_VERTEX_BUFFER); } else { - vbuf.max_index = sizeof(vertices) / vbuf.stride; vbuf.buffer = screen->user_buffer_create(screen, vertices, sizeof(vertices), diff --git a/src/gallium/tests/graw/quad-sample.c b/src/gallium/tests/graw/quad-sample.c new file mode 100644 index 00000000000..3c6458b434e --- /dev/null +++ b/src/gallium/tests/graw/quad-sample.c @@ -0,0 +1,414 @@ +/* Display a cleared blue window. This demo has no dependencies on + * any utility code, just the graw interface and gallium. + */ + +#include "state_tracker/graw.h" +#include "pipe/p_screen.h" +#include "pipe/p_context.h" +#include "pipe/p_shader_tokens.h" +#include "pipe/p_state.h" +#include "pipe/p_defines.h" + +#include "util/u_debug.h" /* debug_dump_surface_bmp() */ +#include "util/u_inlines.h" +#include "util/u_memory.h" /* Offset() */ +#include "util/u_draw_quad.h" +#include "util/u_box.h" + +#include <stdio.h> + +enum pipe_format formats[] = { + PIPE_FORMAT_R8G8B8A8_UNORM, + PIPE_FORMAT_B8G8R8A8_UNORM, + PIPE_FORMAT_NONE +}; + +static const int WIDTH = 300; +static const int HEIGHT = 300; + +static struct pipe_screen *screen = NULL; +static struct pipe_context *ctx = NULL; +static struct pipe_resource *rttex = NULL; +static struct pipe_resource *samptex = NULL; +static struct pipe_surface *surf = NULL; +static struct pipe_sampler_view *sv = NULL; +static void *sampler = NULL; +static void *window = NULL; + +struct vertex { + float position[4]; + float color[4]; +}; + +static struct vertex vertices[] = +{ + { { 0.9, -0.9, 0.0, 1.0 }, + { 1, 0, 0, 1 } }, + + { { 0.9, 0.9, 0.0, 1.0 }, + { 1, 1, 0, 1 } }, + + { {-0.9, 0.9, 0.0, 1.0 }, + { 0, 1, 0, 1 } }, + + { {-0.9, -0.9, 0.0, 1.0 }, + { 0, 0, 0, 1 } }, +}; + + + + +static void set_viewport( float x, float y, + float width, float height, + float near, float far) +{ + float z = far; + float half_width = (float)width / 2.0f; + float half_height = (float)height / 2.0f; + float half_depth = ((float)far - (float)near) / 2.0f; + struct pipe_viewport_state vp; + + vp.scale[0] = half_width; + vp.scale[1] = half_height; + vp.scale[2] = half_depth; + vp.scale[3] = 1.0f; + + vp.translate[0] = half_width + x; + vp.translate[1] = half_height + y; + vp.translate[2] = half_depth + z; + vp.translate[3] = 0.0f; + + ctx->set_viewport_state( ctx, &vp ); +} + +static void set_vertices( void ) +{ + struct pipe_vertex_element ve[2]; + struct pipe_vertex_buffer vbuf; + void *handle; + + memset(ve, 0, sizeof ve); + + ve[0].src_offset = Offset(struct vertex, position); + ve[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + ve[1].src_offset = Offset(struct vertex, color); + ve[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + + handle = ctx->create_vertex_elements_state(ctx, 2, ve); + ctx->bind_vertex_elements_state(ctx, handle); + + + vbuf.stride = sizeof( struct vertex ); + vbuf.buffer_offset = 0; + vbuf.buffer = screen->user_buffer_create(screen, + vertices, + sizeof(vertices), + PIPE_BIND_VERTEX_BUFFER); + + ctx->set_vertex_buffers(ctx, 1, &vbuf); +} + +static void set_vertex_shader( void ) +{ + void *handle; + const char *text = + "VERT\n" + "DCL IN[0]\n" + "DCL IN[1]\n" + "DCL OUT[0], POSITION\n" + "DCL OUT[1], GENERIC[0]\n" + " 0: MOV OUT[1], IN[1]\n" + " 1: MOV OUT[0], IN[0]\n" + " 2: END\n"; + + handle = graw_parse_vertex_shader(ctx, text); + ctx->bind_vs_state(ctx, handle); +} + +static void set_fragment_shader( void ) +{ + void *handle; + const char *text = + "FRAG\n" + "DCL IN[0], GENERIC[0], PERSPECTIVE\n" + "DCL OUT[0], COLOR\n" + "DCL TEMP[0]\n" + "DCL SAMP[0]\n" + "DCL RES[0], 2D, FLOAT\n" + " 0: SAMPLE TEMP[0], IN[0], RES[0], SAMP[0]\n" + " 1: MOV OUT[0], TEMP[0]\n" + " 2: END\n"; + + handle = graw_parse_fragment_shader(ctx, text); + ctx->bind_fs_state(ctx, handle); +} + + +static void draw( void ) +{ + float clear_color[4] = {.5,.5,.5,1}; + + ctx->clear(ctx, PIPE_CLEAR_COLOR, clear_color, 0, 0); + util_draw_arrays(ctx, PIPE_PRIM_QUADS, 0, 4); + ctx->flush(ctx, PIPE_FLUSH_RENDER_CACHE, NULL); + + graw_save_surface_to_file(ctx, surf, NULL); + + screen->flush_frontbuffer(screen, rttex, 0, 0, window); +} + +#define SIZE 16 + +static void init_tex( void ) +{ + struct pipe_sampler_view sv_template; + struct pipe_sampler_state sampler_desc; + struct pipe_resource templat; + struct pipe_box box; + ubyte tex2d[SIZE][SIZE][4]; + int s, t; + +#if (SIZE != 2) + for (s = 0; s < SIZE; s++) { + for (t = 0; t < SIZE; t++) { + if (0) { + int x = (s ^ t) & 1; + tex2d[t][s][0] = (x) ? 0 : 63; + tex2d[t][s][1] = (x) ? 0 : 128; + tex2d[t][s][2] = 0; + tex2d[t][s][3] = 0xff; + } + else { + int x = ((s ^ t) >> 2) & 1; + tex2d[t][s][0] = s*255/(SIZE-1); + tex2d[t][s][1] = t*255/(SIZE-1); + tex2d[t][s][2] = (x) ? 0 : 128; + tex2d[t][s][3] = 0xff; + } + } + } +#else + tex2d[0][0][0] = 0; + tex2d[0][0][1] = 255; + tex2d[0][0][2] = 255; + tex2d[0][0][3] = 0; + + tex2d[0][1][0] = 0; + tex2d[0][1][1] = 0; + tex2d[0][1][2] = 255; + tex2d[0][1][3] = 255; + + tex2d[1][0][0] = 255; + tex2d[1][0][1] = 255; + tex2d[1][0][2] = 0; + tex2d[1][0][3] = 255; + + tex2d[1][1][0] = 255; + tex2d[1][1][1] = 0; + tex2d[1][1][2] = 0; + tex2d[1][1][3] = 255; +#endif + + templat.target = PIPE_TEXTURE_2D; + templat.format = PIPE_FORMAT_B8G8R8A8_UNORM; + templat.width0 = SIZE; + templat.height0 = SIZE; + templat.depth0 = 1; + templat.last_level = 0; + templat.nr_samples = 1; + templat.bind = PIPE_BIND_SAMPLER_VIEW; + + + samptex = screen->resource_create(screen, + &templat); + if (samptex == NULL) + exit(4); + + u_box_2d(0,0,SIZE,SIZE, &box); + + ctx->transfer_inline_write(ctx, + samptex, + 0, + PIPE_TRANSFER_WRITE, + &box, + tex2d, + sizeof tex2d[0], + sizeof tex2d); + + /* Possibly read back & compare against original data: + */ + if (0) + { + struct pipe_transfer *t; + uint32_t *ptr; + t = pipe_get_transfer(ctx, samptex, + 0, 0, /* level, layer */ + PIPE_TRANSFER_READ, + 0, 0, SIZE, SIZE); /* x, y, width, height */ + + ptr = ctx->transfer_map(ctx, t); + + if (memcmp(ptr, tex2d, sizeof tex2d) != 0) { + assert(0); + exit(9); + } + + ctx->transfer_unmap(ctx, t); + + ctx->transfer_destroy(ctx, t); + } + + memset(&sv_template, 0, sizeof sv_template); + sv_template.format = samptex->format; + sv_template.texture = samptex; + sv_template.swizzle_r = 0; + sv_template.swizzle_g = 1; + sv_template.swizzle_b = 2; + sv_template.swizzle_a = 3; + sv = ctx->create_sampler_view(ctx, samptex, &sv_template); + if (sv == NULL) + exit(5); + + ctx->set_fragment_sampler_views(ctx, 1, &sv); + + + memset(&sampler_desc, 0, sizeof sampler_desc); + sampler_desc.wrap_s = PIPE_TEX_WRAP_REPEAT; + sampler_desc.wrap_t = PIPE_TEX_WRAP_REPEAT; + sampler_desc.wrap_r = PIPE_TEX_WRAP_REPEAT; + sampler_desc.min_img_filter = PIPE_TEX_FILTER_NEAREST; + sampler_desc.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; + sampler_desc.mag_img_filter = PIPE_TEX_FILTER_NEAREST; + sampler_desc.compare_mode = PIPE_TEX_COMPARE_NONE; + sampler_desc.compare_func = 0; + sampler_desc.normalized_coords = 1; + sampler_desc.max_anisotropy = 0; + + sampler = ctx->create_sampler_state(ctx, &sampler_desc); + if (sampler == NULL) + exit(6); + + ctx->bind_fragment_sampler_states(ctx, 1, &sampler); + +} + +static void init( void ) +{ + struct pipe_framebuffer_state fb; + struct pipe_resource templat; + struct pipe_surface surf_tmpl; + int i; + + /* It's hard to say whether window or screen should be created + * first. Different environments would prefer one or the other. + * + * Also, no easy way of querying supported formats if the screen + * cannot be created first. + */ + for (i = 0; formats[i] != PIPE_FORMAT_NONE; i++) { + screen = graw_create_window_and_screen(0, 0, 300, 300, + formats[i], + &window); + if (window && screen) + break; + } + if (!screen || !window) { + fprintf(stderr, "Unable to create window\n"); + exit(1); + } + + ctx = screen->context_create(screen, NULL); + if (ctx == NULL) + exit(3); + + templat.target = PIPE_TEXTURE_2D; + templat.format = formats[i]; + templat.width0 = WIDTH; + templat.height0 = HEIGHT; + templat.depth0 = 1; + templat.array_size = 1; + templat.last_level = 0; + templat.nr_samples = 1; + templat.bind = (PIPE_BIND_RENDER_TARGET | + PIPE_BIND_DISPLAY_TARGET); + + rttex = screen->resource_create(screen, + &templat); + if (rttex == NULL) + exit(4); + + surf_tmpl.format = templat.format; + surf_tmpl.usage = PIPE_BIND_RENDER_TARGET; + surf_tmpl.u.tex.level = 0; + surf_tmpl.u.tex.first_layer = 0; + surf_tmpl.u.tex.last_layer = 0; + surf = ctx->create_surface(ctx, rttex, &surf_tmpl); + if (surf == NULL) + exit(5); + + memset(&fb, 0, sizeof fb); + fb.nr_cbufs = 1; + fb.width = WIDTH; + fb.height = HEIGHT; + fb.cbufs[0] = surf; + + ctx->set_framebuffer_state(ctx, &fb); + + { + struct pipe_blend_state blend; + void *handle; + memset(&blend, 0, sizeof blend); + blend.rt[0].colormask = PIPE_MASK_RGBA; + handle = ctx->create_blend_state(ctx, &blend); + ctx->bind_blend_state(ctx, handle); + } + + { + struct pipe_depth_stencil_alpha_state depthstencil; + void *handle; + memset(&depthstencil, 0, sizeof depthstencil); + handle = ctx->create_depth_stencil_alpha_state(ctx, &depthstencil); + ctx->bind_depth_stencil_alpha_state(ctx, handle); + } + + { + struct pipe_rasterizer_state rasterizer; + void *handle; + memset(&rasterizer, 0, sizeof rasterizer); + rasterizer.cull_face = PIPE_FACE_NONE; + rasterizer.gl_rasterization_rules = 1; + handle = ctx->create_rasterizer_state(ctx, &rasterizer); + ctx->bind_rasterizer_state(ctx, handle); + } + + set_viewport(0, 0, WIDTH, HEIGHT, 30, 1000); + + init_tex(); + + set_vertices(); + set_vertex_shader(); + set_fragment_shader(); +} + +static void args(int argc, char *argv[]) +{ + int i; + + for (i = 1; i < argc;) { + if (graw_parse_args(&i, argc, argv)) { + continue; + } + exit(1); + } +} + + +int main( int argc, char *argv[] ) +{ + args(argc, argv); + init(); + + graw_set_display_func( draw ); + graw_main_loop(); + return 0; +} diff --git a/src/gallium/tests/graw/quad-tex.c b/src/gallium/tests/graw/quad-tex.c index 58ca639d207..4e66813b301 100644 --- a/src/gallium/tests/graw/quad-tex.c +++ b/src/gallium/tests/graw/quad-tex.c @@ -97,7 +97,6 @@ static void set_vertices( void ) vbuf.stride = sizeof( struct vertex ); - vbuf.max_index = sizeof(vertices) / vbuf.stride; vbuf.buffer_offset = 0; vbuf.buffer = screen->user_buffer_create(screen, vertices, diff --git a/src/gallium/tests/graw/shader-leak.c b/src/gallium/tests/graw/shader-leak.c index 9af76f51ea2..a23ca73ac1d 100644 --- a/src/gallium/tests/graw/shader-leak.c +++ b/src/gallium/tests/graw/shader-leak.c @@ -88,7 +88,6 @@ static void set_vertices( void ) vbuf.stride = sizeof(struct vertex); - vbuf.max_index = sizeof(vertices) / vbuf.stride; vbuf.buffer_offset = 0; vbuf.buffer = screen->user_buffer_create(screen, vertices, diff --git a/src/gallium/tests/graw/tri-gs.c b/src/gallium/tests/graw/tri-gs.c index a1a00b32098..47b76530c6b 100644 --- a/src/gallium/tests/graw/tri-gs.c +++ b/src/gallium/tests/graw/tri-gs.c @@ -89,7 +89,6 @@ static void set_vertices( void ) vbuf.stride = sizeof( struct vertex ); - vbuf.max_index = sizeof(vertices) / vbuf.stride; vbuf.buffer_offset = 0; vbuf.buffer = screen->user_buffer_create(screen, vertices, diff --git a/src/gallium/tests/graw/tri-instanced.c b/src/gallium/tests/graw/tri-instanced.c index f61d8b9844d..259b3d9527c 100644 --- a/src/gallium/tests/graw/tri-instanced.c +++ b/src/gallium/tests/graw/tri-instanced.c @@ -132,7 +132,6 @@ static void set_vertices( void ) /* vertex data */ vbuf[0].stride = sizeof( struct vertex ); - vbuf[0].max_index = sizeof(vertices) / vbuf[0].stride; vbuf[0].buffer_offset = 0; vbuf[0].buffer = screen->user_buffer_create(screen, vertices, @@ -141,7 +140,6 @@ static void set_vertices( void ) /* instance data */ vbuf[1].stride = sizeof( inst_data[0] ); - vbuf[1].max_index = sizeof(inst_data) / vbuf[1].stride; vbuf[1].buffer_offset = 0; vbuf[1].buffer = screen->user_buffer_create(screen, inst_data, diff --git a/src/gallium/tests/graw/tri.c b/src/gallium/tests/graw/tri.c index 006d61ca88c..4266c0394d8 100644 --- a/src/gallium/tests/graw/tri.c +++ b/src/gallium/tests/graw/tri.c @@ -93,7 +93,6 @@ static void set_vertices( void ) vbuf.stride = sizeof( struct vertex ); - vbuf.max_index = sizeof(vertices) / vbuf.stride; vbuf.buffer_offset = 0; vbuf.buffer = screen->user_buffer_create(screen, vertices, diff --git a/src/gallium/tests/graw/vs-test.c b/src/gallium/tests/graw/vs-test.c index 1358fa85dfd..dd64d8b9301 100644 --- a/src/gallium/tests/graw/vs-test.c +++ b/src/gallium/tests/graw/vs-test.c @@ -171,7 +171,6 @@ static void set_vertices( void ) } vbuf.stride = sizeof( struct vertex ); - vbuf.max_index = sizeof(vertices) / vbuf.stride; vbuf.buffer_offset = 0; vbuf.buffer = screen->user_buffer_create(screen, vertices, diff --git a/src/gallium/tests/trivial/quad-tex.c b/src/gallium/tests/trivial/quad-tex.c index 92c5b4dbb18..af93e09d8d4 100644 --- a/src/gallium/tests/trivial/quad-tex.c +++ b/src/gallium/tests/trivial/quad-tex.c @@ -129,7 +129,8 @@ static void init_prog(struct program *p) } }; - p->vbuf = pipe_buffer_create(p->screen, PIPE_BIND_VERTEX_BUFFER, sizeof(vertices)); + p->vbuf = pipe_buffer_create(p->screen, PIPE_BIND_VERTEX_BUFFER, + PIPE_USAGE_STATIC, sizeof(vertices)); pipe_buffer_write(p->pipe, p->vbuf, 0, sizeof(vertices), vertices); } diff --git a/src/gallium/tests/trivial/tri.c b/src/gallium/tests/trivial/tri.c index 37c1573051f..b89cfe0d989 100644 --- a/src/gallium/tests/trivial/tri.c +++ b/src/gallium/tests/trivial/tri.c @@ -120,7 +120,8 @@ static void init_prog(struct program *p) } }; - p->vbuf = pipe_buffer_create(p->screen, PIPE_BIND_VERTEX_BUFFER, sizeof(vertices)); + p->vbuf = pipe_buffer_create(p->screen, PIPE_BIND_VERTEX_BUFFER, + PIPE_USAGE_STATIC, sizeof(vertices)); pipe_buffer_write(p->pipe, p->vbuf, 0, sizeof(vertices), vertices); } diff --git a/src/gallium/winsys/SConscript b/src/gallium/winsys/SConscript index d74f8a2e989..9f36d225e10 100644 --- a/src/gallium/winsys/SConscript +++ b/src/gallium/winsys/SConscript @@ -13,6 +13,10 @@ SConscript([ 'sw/gdi/SConscript', ]) +SConscript([ + 'i915/sw/SConscript', +]) + if env['dri']: SConscript([ 'sw/dri/SConscript', diff --git a/src/gallium/winsys/i915/drm/i915_drm_batchbuffer.c b/src/gallium/winsys/i915/drm/i915_drm_batchbuffer.c index ebe86dcf196..afeab5eef42 100644 --- a/src/gallium/winsys/i915/drm/i915_drm_batchbuffer.c +++ b/src/gallium/winsys/i915/drm/i915_drm_batchbuffer.c @@ -4,6 +4,7 @@ #include "i915_drm.h" #include "i915/i915_debug.h" +#include <xf86drm.h> #define BATCH_RESERVED 16 @@ -34,7 +35,6 @@ static void i915_drm_batchbuffer_reset(struct i915_drm_batchbuffer *batch) { struct i915_drm_winsys *idws = i915_drm_winsys(batch->base.iws); - int ret; if (batch->bo) drm_intel_bo_unreference(batch->bo); @@ -43,18 +43,6 @@ i915_drm_batchbuffer_reset(struct i915_drm_batchbuffer *batch) batch->actual_size, 4096); -#ifdef INTEL_MAP_BATCHBUFFER -#ifdef INTEL_MAP_GTT - ret = drm_intel_gem_bo_map_gtt(batch->bo); -#else - ret = drm_intel_bo_map(batch->bo, TRUE); -#endif - assert(ret == 0); - batch->base.map = batch->bo->virtual; -#else - (void)ret; -#endif - memset(batch->base.map, 0, batch->actual_size); batch->base.ptr = batch->base.map; batch->base.size = batch->actual_size - BATCH_RESERVED; @@ -87,7 +75,7 @@ static int i915_drm_batchbuffer_reloc(struct i915_winsys_batchbuffer *ibatch, struct i915_winsys_buffer *buffer, enum i915_winsys_buffer_usage usage, - unsigned pre_add, bool fenced) + unsigned pre_add, boolean fenced) { struct i915_drm_batchbuffer *batch = i915_drm_batchbuffer(ibatch); unsigned write_domain = 0; @@ -145,6 +133,12 @@ i915_drm_batchbuffer_reloc(struct i915_winsys_batchbuffer *ibatch, return ret; } +static void +i915_drm_throttle(struct i915_drm_winsys *idws) +{ + drmIoctl(idws->fd, DRM_IOCTL_I915_GEM_THROTTLE, NULL); +} + static void i915_drm_batchbuffer_flush(struct i915_winsys_batchbuffer *ibatch, struct pipe_fence_handle **fence) @@ -168,6 +162,8 @@ i915_drm_batchbuffer_flush(struct i915_winsys_batchbuffer *ibatch, if (ret == 0 && i915_drm_winsys(ibatch->iws)->send_cmd) ret = drm_intel_bo_exec(batch->bo, used, NULL, 0, 0); + i915_drm_throttle(i915_drm_winsys(ibatch->iws)); + if (ret != 0 || i915_drm_winsys(ibatch->iws)->dump_cmd) { i915_dump_batchbuffer(ibatch); assert(ret == 0); diff --git a/src/gallium/winsys/i915/sw/i915_sw_batchbuffer.c b/src/gallium/winsys/i915/sw/i915_sw_batchbuffer.c index 44773ae30e7..8085591c8eb 100644 --- a/src/gallium/winsys/i915/sw/i915_sw_batchbuffer.c +++ b/src/gallium/winsys/i915/sw/i915_sw_batchbuffer.c @@ -1,6 +1,7 @@ #include "i915_sw_winsys.h" #include "i915/i915_batchbuffer.h" +#include "i915/i915_debug.h" #include "util/u_memory.h" #define BATCH_RESERVED 16 @@ -61,7 +62,7 @@ static int i915_sw_batchbuffer_reloc(struct i915_winsys_batchbuffer *ibatch, struct i915_winsys_buffer *buffer, enum i915_winsys_buffer_usage usage, - unsigned pre_add, bool fenced) + unsigned pre_add, boolean fenced) { struct i915_sw_batchbuffer *batch = i915_sw_batchbuffer(ibatch); int ret = 0; @@ -98,7 +99,6 @@ i915_sw_batchbuffer_flush(struct i915_winsys_batchbuffer *ibatch, { struct i915_sw_batchbuffer *batch = i915_sw_batchbuffer(ibatch); unsigned used = 0; - int i; assert(i915_winsys_batchbuffer_space(ibatch) >= 0); @@ -122,12 +122,7 @@ i915_sw_batchbuffer_flush(struct i915_winsys_batchbuffer *ibatch, assert((used & 4) == 0); if (i915_sw_winsys(ibatch->iws)->dump_cmd) { - unsigned *ptr = (unsigned *)batch->base.map; - - debug_printf("%s:\n", __func__); - for (i = 0; i < used / 4; i++, ptr++) { - debug_printf("\t%08x: %08x\n", i*4, *ptr); - } + i915_dump_batchbuffer(ibatch); } if (fence) { diff --git a/src/gallium/winsys/i915/sw/i915_sw_buffer.c b/src/gallium/winsys/i915/sw/i915_sw_buffer.c index 834805e621d..9a7e90e2173 100644 --- a/src/gallium/winsys/i915/sw/i915_sw_buffer.c +++ b/src/gallium/winsys/i915/sw/i915_sw_buffer.c @@ -84,7 +84,7 @@ i915_sw_buffer_write(struct i915_winsys *iws, { struct i915_sw_buffer *buf = i915_sw_buffer(buffer); - memcpy(buf->ptr + offset, data, size); + memcpy((char*)buf->ptr + offset, data, size); return 0; } diff --git a/src/gallium/winsys/r600/drm/SConscript b/src/gallium/winsys/r600/drm/SConscript index f97434e995d..cc9a06a2393 100644 --- a/src/gallium/winsys/r600/drm/SConscript +++ b/src/gallium/winsys/r600/drm/SConscript @@ -13,7 +13,12 @@ r600_sources = [ 'r600_bomgr.c', ] -env.ParseConfig('pkg-config --cflags libdrm_radeon') +try: + env.ParseConfig('pkg-config --cflags libdrm_radeon') +except OSError: + print 'warning: not building r600g' + Return() + env.Append(CPPPATH = '#/src/gallium/drivers/r600') r600winsys = env.ConvenienceLibrary( diff --git a/src/gallium/winsys/r600/drm/evergreen_hw_context.c b/src/gallium/winsys/r600/drm/evergreen_hw_context.c index 3fdafc39283..aa4035a302b 100644 --- a/src/gallium/winsys/r600/drm/evergreen_hw_context.c +++ b/src/gallium/winsys/r600/drm/evergreen_hw_context.c @@ -621,6 +621,8 @@ int evergreen_context_init(struct r600_context *ctx, struct radeon *radeon) /* save 16dwords space for fence mecanism */ ctx->pm4_ndwords -= 16; + ctx->max_db = 8; + LIST_INITHEAD(&ctx->fenced_bo); /* init dirty list */ diff --git a/src/gallium/winsys/r600/drm/r600_bo.c b/src/gallium/winsys/r600/drm/r600_bo.c index 339d5dc47f4..06e8f6910f3 100644 --- a/src/gallium/winsys/r600/drm/r600_bo.c +++ b/src/gallium/winsys/r600/drm/r600_bo.c @@ -108,11 +108,10 @@ struct r600_bo *r600_bo_handle(struct radeon *radeon, radeon_bo_get_tiling_flags(radeon, rbo, &bo->tiling_flags, &bo->kernel_pitch); if (array_mode) { if (bo->tiling_flags) { - if (bo->tiling_flags & RADEON_TILING_MICRO) - *array_mode = V_0280A0_ARRAY_1D_TILED_THIN1; - if ((bo->tiling_flags & (RADEON_TILING_MICRO | RADEON_TILING_MACRO)) == - (RADEON_TILING_MICRO | RADEON_TILING_MACRO)) + if (bo->tiling_flags & RADEON_TILING_MACRO) *array_mode = V_0280A0_ARRAY_2D_TILED_THIN1; + else if (bo->tiling_flags & RADEON_TILING_MICRO) + *array_mode = V_0280A0_ARRAY_1D_TILED_THIN1; } else { *array_mode = 0; } diff --git a/src/gallium/winsys/r600/drm/r600_drm.c b/src/gallium/winsys/r600/drm/r600_drm.c index 69b0a1dcd72..f5cd48d39c6 100644 --- a/src/gallium/winsys/r600/drm/r600_drm.c +++ b/src/gallium/winsys/r600/drm/r600_drm.c @@ -41,6 +41,10 @@ #define RADEON_INFO_TILING_CONFIG 0x6 #endif +#ifndef RADEON_INFO_CLOCK_CRYSTAL_FREQ +#define RADEON_INFO_CLOCK_CRYSTAL_FREQ 0x9 +#endif + enum radeon_family r600_get_family(struct radeon *r600) { return r600->family; @@ -56,9 +60,14 @@ struct r600_tiling_info *r600_get_tiling_info(struct radeon *radeon) return &radeon->tiling_info; } +unsigned r600_get_clock_crystal_freq(struct radeon *radeon) +{ + return radeon->clock_crystal_freq; +} + static int radeon_get_device(struct radeon *radeon) { - struct drm_radeon_info info; + struct drm_radeon_info info = {}; int r; radeon->device = 0; @@ -69,20 +78,8 @@ static int radeon_get_device(struct radeon *radeon) return r; } -static int radeon_drm_get_tiling(struct radeon *radeon) +static int r600_interpret_tiling(struct radeon *radeon, uint32_t tiling_config) { - struct drm_radeon_info info; - int r; - uint32_t tiling_config; - - info.request = RADEON_INFO_TILING_CONFIG; - info.value = (uintptr_t)&tiling_config; - r = drmCommandWriteRead(radeon->fd, DRM_RADEON_INFO, &info, - sizeof(struct drm_radeon_info)); - - if (r) - return 0; - switch ((tiling_config & 0xe) >> 1) { case 0: radeon->tiling_info.num_channels = 1; @@ -124,6 +121,80 @@ static int radeon_drm_get_tiling(struct radeon *radeon) return 0; } +static int eg_interpret_tiling(struct radeon *radeon, uint32_t tiling_config) +{ + switch (tiling_config & 0xf) { + case 0: + radeon->tiling_info.num_channels = 1; + break; + case 1: + radeon->tiling_info.num_channels = 2; + break; + case 2: + radeon->tiling_info.num_channels = 4; + break; + case 3: + radeon->tiling_info.num_channels = 8; + break; + default: + return -EINVAL; + } + + radeon->tiling_info.num_banks = (tiling_config & 0xf0) >> 4; + + switch ((tiling_config & 0xf00) >> 8) { + case 0: + radeon->tiling_info.group_bytes = 256; + break; + case 1: + radeon->tiling_info.group_bytes = 512; + break; + default: + return -EINVAL; + } + return 0; +} + +static int radeon_drm_get_tiling(struct radeon *radeon) +{ + struct drm_radeon_info info; + int r; + uint32_t tiling_config = 0; + + info.request = RADEON_INFO_TILING_CONFIG; + info.value = (uintptr_t)&tiling_config; + r = drmCommandWriteRead(radeon->fd, DRM_RADEON_INFO, &info, + sizeof(struct drm_radeon_info)); + + if (r) + return 0; + + if (radeon->chip_class == R600 || radeon->chip_class == R700) { + r = r600_interpret_tiling(radeon, tiling_config); + } else { + r = eg_interpret_tiling(radeon, tiling_config); + } + return r; +} + +static int radeon_get_clock_crystal_freq(struct radeon *radeon) +{ + struct drm_radeon_info info; + uint32_t clock_crystal_freq; + int r; + + radeon->device = 0; + info.request = RADEON_INFO_CLOCK_CRYSTAL_FREQ; + info.value = (uintptr_t)&clock_crystal_freq; + r = drmCommandWriteRead(radeon->fd, DRM_RADEON_INFO, &info, + sizeof(struct drm_radeon_info)); + if (r) + return r; + + radeon->clock_crystal_freq = clock_crystal_freq; + return 0; +} + static int radeon_init_fence(struct radeon *radeon) { radeon->fence = 1; @@ -201,10 +272,12 @@ static struct radeon *radeon_new(int fd, unsigned device) break; } - if (radeon->chip_class == R600 || radeon->chip_class == R700) { - if (radeon_drm_get_tiling(radeon)) - return NULL; - } + if (radeon_drm_get_tiling(radeon)) + return NULL; + + /* get the GPU counter frequency, failure is non fatal */ + radeon_get_clock_crystal_freq(radeon); + radeon->bomgr = r600_bomgr_create(radeon, 1000000); if (radeon->bomgr == NULL) { return NULL; diff --git a/src/gallium/winsys/r600/drm/r600_hw_context.c b/src/gallium/winsys/r600/drm/r600_hw_context.c index f10e2fda6f2..f170640407d 100644 --- a/src/gallium/winsys/r600/drm/r600_hw_context.c +++ b/src/gallium/winsys/r600/drm/r600_hw_context.c @@ -637,7 +637,8 @@ int r600_context_init(struct r600_context *ctx, struct radeon *radeon) ctx->range[i].end_offset = ((i + 1) << ctx->hash_shift) - 1; ctx->range[i].blocks = calloc(1 << ctx->hash_shift, sizeof(void*)); if (ctx->range[i].blocks == NULL) { - return -ENOMEM; + r = -ENOMEM; + goto out_err; } } @@ -750,6 +751,9 @@ int r600_context_init(struct r600_context *ctx, struct radeon *radeon) /* init dirty list */ LIST_INITHEAD(&ctx->dirty); + + ctx->max_db = 4; + return 0; out_err: r600_context_fini(ctx); @@ -1084,7 +1088,7 @@ void r600_context_draw(struct r600_context *ctx, const struct r600_draw *draw) void r600_context_flush(struct r600_context *ctx) { - struct drm_radeon_cs drmib; + struct drm_radeon_cs drmib = {}; struct drm_radeon_cs_chunk chunks[2]; uint64_t chunk_array[2]; unsigned fence; @@ -1246,43 +1250,70 @@ out_err: bof_decref(root); } -static void r600_query_result(struct r600_context *ctx, struct r600_query *query) +static boolean r600_query_result(struct r600_context *ctx, struct r600_query *query, boolean wait) { u64 start, end; u32 *results; int i; + int size; + + if (wait) + results = r600_bo_map(ctx->radeon, query->buffer, PB_USAGE_CPU_READ, NULL); + else + results = r600_bo_map(ctx->radeon, query->buffer, PB_USAGE_DONTBLOCK | PB_USAGE_CPU_READ, NULL); + if (!results) + return FALSE; - results = r600_bo_map(ctx->radeon, query->buffer, 0, NULL); - for (i = 0; i < query->num_results; i += 4) { + size = query->num_results * (query->type == PIPE_QUERY_OCCLUSION_COUNTER ? ctx->max_db : 1); + for (i = 0; i < size; i += 4) { start = (u64)results[i] | (u64)results[i + 1] << 32; end = (u64)results[i + 2] | (u64)results[i + 3] << 32; - if ((start & 0x8000000000000000UL) && (end & 0x8000000000000000UL)) { + if (((start & 0x8000000000000000UL) && (end & 0x8000000000000000UL)) + || query->type == PIPE_QUERY_TIME_ELAPSED) { query->result += end - start; } } r600_bo_unmap(ctx->radeon, query->buffer); query->num_results = 0; + + return TRUE; } void r600_query_begin(struct r600_context *ctx, struct r600_query *query) { - /* query request needs 6 dwords for begin + 6 dwords for end */ - if ((12 + ctx->pm4_cdwords) > ctx->pm4_ndwords) { + unsigned required_space; + + /* query request needs 6/8 dwords for begin + 6/8 dwords for end */ + if (query->type == PIPE_QUERY_TIME_ELAPSED) + required_space = 16; + else + required_space = 12; + + if ((required_space + ctx->pm4_cdwords) > ctx->pm4_ndwords) { /* need to flush */ r600_context_flush(ctx); } /* if query buffer is full force a flush */ - if (query->num_results >= ((query->buffer_size >> 2) - 2)) { + if (query->num_results*4 >= query->buffer_size - 16) { r600_context_flush(ctx); - r600_query_result(ctx, query); + r600_query_result(ctx, query, TRUE); } /* emit begin query */ - ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE, 2); - ctx->pm4[ctx->pm4_cdwords++] = EVENT_TYPE(EVENT_TYPE_ZPASS_DONE) | EVENT_INDEX(1); - ctx->pm4[ctx->pm4_cdwords++] = query->num_results + r600_bo_offset(query->buffer); - ctx->pm4[ctx->pm4_cdwords++] = 0; + if (query->type == PIPE_QUERY_TIME_ELAPSED) { + ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE_EOP, 4); + ctx->pm4[ctx->pm4_cdwords++] = EVENT_TYPE(EVENT_TYPE_CACHE_FLUSH_AND_INV_TS_EVENT) | EVENT_INDEX(5); + ctx->pm4[ctx->pm4_cdwords++] = query->num_results*4 + r600_bo_offset(query->buffer); + ctx->pm4[ctx->pm4_cdwords++] = (3 << 29); + ctx->pm4[ctx->pm4_cdwords++] = 0; + ctx->pm4[ctx->pm4_cdwords++] = 0; + } else { + ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE, 2); + ctx->pm4[ctx->pm4_cdwords++] = EVENT_TYPE(EVENT_TYPE_ZPASS_DONE) | EVENT_INDEX(1); + ctx->pm4[ctx->pm4_cdwords++] = query->num_results*4 + r600_bo_offset(query->buffer); + ctx->pm4[ctx->pm4_cdwords++] = 0; + } ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_NOP, 0); ctx->pm4[ctx->pm4_cdwords++] = 0; r600_context_bo_reloc(ctx, &ctx->pm4[ctx->pm4_cdwords - 1], query->buffer); @@ -1295,15 +1326,24 @@ void r600_query_begin(struct r600_context *ctx, struct r600_query *query) void r600_query_end(struct r600_context *ctx, struct r600_query *query) { /* emit begin query */ - ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE, 2); - ctx->pm4[ctx->pm4_cdwords++] = EVENT_TYPE(EVENT_TYPE_ZPASS_DONE) | EVENT_INDEX(1); - ctx->pm4[ctx->pm4_cdwords++] = query->num_results + 8 + r600_bo_offset(query->buffer); - ctx->pm4[ctx->pm4_cdwords++] = 0; + if (query->type == PIPE_QUERY_TIME_ELAPSED) { + ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE_EOP, 4); + ctx->pm4[ctx->pm4_cdwords++] = EVENT_TYPE(EVENT_TYPE_CACHE_FLUSH_AND_INV_TS_EVENT) | EVENT_INDEX(5); + ctx->pm4[ctx->pm4_cdwords++] = query->num_results*4 + 8 + r600_bo_offset(query->buffer); + ctx->pm4[ctx->pm4_cdwords++] = (3 << 29); + ctx->pm4[ctx->pm4_cdwords++] = 0; + ctx->pm4[ctx->pm4_cdwords++] = 0; + } else { + ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE, 2); + ctx->pm4[ctx->pm4_cdwords++] = EVENT_TYPE(EVENT_TYPE_ZPASS_DONE) | EVENT_INDEX(1); + ctx->pm4[ctx->pm4_cdwords++] = query->num_results*4 + 8 + r600_bo_offset(query->buffer); + ctx->pm4[ctx->pm4_cdwords++] = 0; + } ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_NOP, 0); ctx->pm4[ctx->pm4_cdwords++] = 0; r600_context_bo_reloc(ctx, &ctx->pm4[ctx->pm4_cdwords - 1], query->buffer); - query->num_results += 16; + query->num_results += 4 * (query->type == PIPE_QUERY_OCCLUSION_COUNTER ? ctx->max_db : 1); query->state ^= R600_QUERY_STATE_STARTED; query->state |= R600_QUERY_STATE_ENDED; ctx->num_query_running--; @@ -1313,7 +1353,7 @@ struct r600_query *r600_context_query_create(struct r600_context *ctx, unsigned { struct r600_query *query; - if (query_type != PIPE_QUERY_OCCLUSION_COUNTER) + if (query_type != PIPE_QUERY_OCCLUSION_COUNTER && query_type != PIPE_QUERY_TIME_ELAPSED) return NULL; query = calloc(1, sizeof(struct r600_query)); @@ -1355,8 +1395,12 @@ boolean r600_context_query_result(struct r600_context *ctx, if (query->num_results) { r600_context_flush(ctx); } - r600_query_result(ctx, query); - *result = query->result; + if (!r600_query_result(ctx, query, wait)) + return FALSE; + if (query->type == PIPE_QUERY_TIME_ELAPSED) + *result = (1000000*query->result)/r600_get_clock_crystal_freq(ctx->radeon); + else + *result = query->result; query->result = 0; return TRUE; } diff --git a/src/gallium/winsys/r600/drm/r600_priv.h b/src/gallium/winsys/r600/drm/r600_priv.h index a38a6481b4f..2d91cd97d68 100644 --- a/src/gallium/winsys/r600/drm/r600_priv.h +++ b/src/gallium/winsys/r600/drm/r600_priv.h @@ -49,6 +49,7 @@ struct radeon { unsigned fence; unsigned *cfence; struct r600_bo *fence_bo; + unsigned clock_crystal_freq; }; struct r600_reg { diff --git a/src/gallium/winsys/r600/drm/radeon_bo.c b/src/gallium/winsys/r600/drm/radeon_bo.c index 999de82646d..3643ddbcb93 100644 --- a/src/gallium/winsys/r600/drm/radeon_bo.c +++ b/src/gallium/winsys/r600/drm/radeon_bo.c @@ -98,7 +98,7 @@ struct radeon_bo *radeon_bo(struct radeon *radeon, unsigned handle, bo->size = open_arg.size; bo->shared = TRUE; } else { - struct drm_radeon_gem_create args; + struct drm_radeon_gem_create args = {}; args.size = size; args.alignment = alignment; @@ -204,7 +204,7 @@ int radeon_bo_get_tiling_flags(struct radeon *radeon, uint32_t *tiling_flags, uint32_t *pitch) { - struct drm_radeon_gem_get_tiling args; + struct drm_radeon_gem_get_tiling args = {}; int ret; args.handle = bo->handle; diff --git a/src/gallium/winsys/r600/drm/radeon_pciid.c b/src/gallium/winsys/r600/drm/radeon_pciid.c index 06681791e57..f19956931de 100644 --- a/src/gallium/winsys/r600/drm/radeon_pciid.c +++ b/src/gallium/winsys/r600/drm/radeon_pciid.c @@ -32,7 +32,7 @@ struct pci_id { unsigned family; }; -struct pci_id radeon_pci_id[] = { +static const struct pci_id radeon_pci_id[] = { {0x1002, 0x3150, CHIP_RV380}, {0x1002, 0x3152, CHIP_RV380}, {0x1002, 0x3154, CHIP_RV380}, diff --git a/src/gallium/winsys/radeon/drm/Makefile b/src/gallium/winsys/radeon/drm/Makefile index 7e339a2ecfe..e63ae6f5006 100644 --- a/src/gallium/winsys/radeon/drm/Makefile +++ b/src/gallium/winsys/radeon/drm/Makefile @@ -5,10 +5,9 @@ include $(TOP)/configs/current LIBNAME = radeonwinsys C_SOURCES = \ - radeon_drm_buffer.c \ + radeon_drm_bo.c \ radeon_drm_cs.c \ - radeon_drm_common.c \ - radeon_r300.c + radeon_drm_common.c LIBRARY_INCLUDES = -I$(TOP)/src/gallium/drivers/r300 \ $(shell pkg-config libdrm --cflags-only-I) diff --git a/src/gallium/winsys/radeon/drm/SConscript b/src/gallium/winsys/radeon/drm/SConscript index 80816621848..b16e03556d3 100644 --- a/src/gallium/winsys/radeon/drm/SConscript +++ b/src/gallium/winsys/radeon/drm/SConscript @@ -3,13 +3,17 @@ Import('*') env = env.Clone() radeon_sources = [ - 'radeon_drm_buffer.c', + 'radeon_drm_bo.c', 'radeon_drm_cs.c', 'radeon_drm_common.c', - 'radeon_r300.c', ] -env.ParseConfig('pkg-config --cflags libdrm_radeon') +try: + env.ParseConfig('pkg-config --cflags libdrm_radeon') +except: + print 'warning: not building r300g' + Return() + env.Append(CPPPATH = '#/src/gallium/drivers/r300') radeonwinsys = env.ConvenienceLibrary( diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c new file mode 100644 index 00000000000..3094337a3cd --- /dev/null +++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c @@ -0,0 +1,599 @@ +/* + * Copyright © 2011 Marek Olšák <[email protected]> + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS + * 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. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + */ + +#define _FILE_OFFSET_BITS 64 +#include "radeon_drm_cs.h" + +#include "util/u_hash_table.h" +#include "util/u_memory.h" +#include "util/u_simple_list.h" +#include "os/os_thread.h" + +#include "state_tracker/drm_driver.h" + +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <xf86drm.h> +#include <errno.h> + +#define RADEON_BO_FLAGS_MACRO_TILE 1 +#define RADEON_BO_FLAGS_MICRO_TILE 2 +#define RADEON_BO_FLAGS_MICRO_TILE_SQUARE 0x20 + +extern const struct pb_vtbl radeon_bo_vtbl; + + +static INLINE struct radeon_bo *radeon_bo(struct pb_buffer *bo) +{ + assert(bo->vtbl == &radeon_bo_vtbl); + return (struct radeon_bo *)bo; +} + +struct radeon_bomgr { + /* Base class. */ + struct pb_manager base; + + /* Winsys. */ + struct radeon_drm_winsys *rws; + + /* List of buffer handles and its mutex. */ + struct util_hash_table *bo_handles; + pipe_mutex bo_handles_mutex; +}; + +static INLINE struct radeon_bomgr *radeon_bomgr(struct pb_manager *mgr) +{ + return (struct radeon_bomgr *)mgr; +} + +static struct radeon_bo *get_radeon_bo(struct pb_buffer *_buf) +{ + struct radeon_bo *bo = NULL; + + if (_buf->vtbl == &radeon_bo_vtbl) { + bo = radeon_bo(_buf); + } else { + struct pb_buffer *base_buf; + pb_size offset; + pb_get_base_buffer(_buf, &base_buf, &offset); + + if (base_buf->vtbl == &radeon_bo_vtbl) + bo = radeon_bo(base_buf); + } + + return bo; +} + +void radeon_bo_unref(struct radeon_bo *bo) +{ + struct drm_gem_close args = {}; + + if (!p_atomic_dec_zero(&bo->ref_count)) + return; + + if (bo->name) { + pipe_mutex_lock(bo->mgr->bo_handles_mutex); + util_hash_table_remove(bo->mgr->bo_handles, + (void*)(uintptr_t)bo->name); + pipe_mutex_unlock(bo->mgr->bo_handles_mutex); + } + + if (bo->ptr) + munmap(bo->ptr, bo->size); + + /* Close object. */ + args.handle = bo->handle; + drmIoctl(bo->rws->fd, DRM_IOCTL_GEM_CLOSE, &args); + pipe_mutex_destroy(bo->map_mutex); + FREE(bo); +} + +static void radeon_bo_wait(struct r300_winsys_bo *_buf) +{ + struct radeon_bo *bo = get_radeon_bo(pb_buffer(_buf)); + struct drm_radeon_gem_wait_idle args = {}; + + while (p_atomic_read(&bo->num_active_ioctls)) { + sched_yield(); + } + + args.handle = bo->handle; + while (drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_WAIT_IDLE, + &args, sizeof(args)) == -EBUSY); +} + +static boolean radeon_bo_is_busy(struct r300_winsys_bo *_buf) +{ + struct radeon_bo *bo = get_radeon_bo(pb_buffer(_buf)); + struct drm_radeon_gem_busy args = {}; + + if (p_atomic_read(&bo->num_active_ioctls)) { + return TRUE; + } + + args.handle = bo->handle; + return drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_BUSY, + &args, sizeof(args)) != 0; +} + +static void radeon_bo_destroy(struct pb_buffer *_buf) +{ + struct radeon_bo *bo = radeon_bo(_buf); + + radeon_bo_unref(bo); +} + +static unsigned get_pb_usage_from_transfer_flags(enum pipe_transfer_usage usage) +{ + unsigned res = 0; + + if (usage & PIPE_TRANSFER_DONTBLOCK) + res |= PB_USAGE_DONTBLOCK; + + if (usage & PIPE_TRANSFER_UNSYNCHRONIZED) + res |= PB_USAGE_UNSYNCHRONIZED; + + return res; +} + +static void *radeon_bo_map_internal(struct pb_buffer *_buf, + unsigned flags, void *flush_ctx) +{ + struct radeon_bo *bo = radeon_bo(_buf); + struct radeon_drm_cs *cs = flush_ctx; + struct drm_radeon_gem_mmap args = {}; + void *ptr; + + /* If it's not unsynchronized bo_map, flush CS if needed and then wait. */ + if (!(flags & PB_USAGE_UNSYNCHRONIZED)) { + /* DONTBLOCK doesn't make sense with UNSYNCHRONIZED. */ + if (flags & PB_USAGE_DONTBLOCK) { + if (radeon_bo_is_referenced_by_cs(cs, bo)) { + cs->flush_cs(cs->flush_data); + return NULL; + } + + if (radeon_bo_is_busy((struct r300_winsys_bo*)bo)) { + return NULL; + } + } else { + if (radeon_bo_is_referenced_by_cs(cs, bo)) { + cs->flush_cs(cs->flush_data); + } + + radeon_bo_wait((struct r300_winsys_bo*)bo); + } + } + + /* Return the pointer if it's already mapped. */ + if (bo->ptr) + return bo->ptr; + + /* Map the buffer. */ + pipe_mutex_lock(bo->map_mutex); + args.handle = bo->handle; + args.offset = 0; + args.size = (uint64_t)bo->size; + if (drmCommandWriteRead(bo->rws->fd, + DRM_RADEON_GEM_MMAP, + &args, + sizeof(args))) { + pipe_mutex_unlock(bo->map_mutex); + fprintf(stderr, "radeon: gem_mmap failed: %p 0x%08X\n", + bo, bo->handle); + return NULL; + } + + ptr = mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED, + bo->rws->fd, args.addr_ptr); + if (ptr == MAP_FAILED) { + pipe_mutex_unlock(bo->map_mutex); + fprintf(stderr, "radeon: mmap failed, errno: %i\n", errno); + return NULL; + } + bo->ptr = ptr; + pipe_mutex_unlock(bo->map_mutex); + + return bo->ptr; +} + +static void radeon_bo_unmap_internal(struct pb_buffer *_buf) +{ + /* NOP */ +} + +static void radeon_bo_get_base_buffer(struct pb_buffer *buf, + struct pb_buffer **base_buf, + unsigned *offset) +{ + *base_buf = buf; + *offset = 0; +} + +static enum pipe_error radeon_bo_validate(struct pb_buffer *_buf, + struct pb_validate *vl, + unsigned flags) +{ + /* Always pinned */ + return PIPE_OK; +} + +static void radeon_bo_fence(struct pb_buffer *buf, + struct pipe_fence_handle *fence) +{ +} + +const struct pb_vtbl radeon_bo_vtbl = { + radeon_bo_destroy, + radeon_bo_map_internal, + radeon_bo_unmap_internal, + radeon_bo_validate, + radeon_bo_fence, + radeon_bo_get_base_buffer, +}; + +static struct pb_buffer *radeon_bomgr_create_bo(struct pb_manager *_mgr, + pb_size size, + const struct pb_desc *desc) +{ + struct radeon_bomgr *mgr = radeon_bomgr(_mgr); + struct radeon_drm_winsys *rws = mgr->rws; + struct radeon_bo *bo; + struct drm_radeon_gem_create args = {}; + + args.size = size; + args.alignment = desc->alignment; + args.initial_domain = + (desc->usage & RADEON_PB_USAGE_DOMAIN_GTT ? + RADEON_GEM_DOMAIN_GTT : 0) | + (desc->usage & RADEON_PB_USAGE_DOMAIN_VRAM ? + RADEON_GEM_DOMAIN_VRAM : 0); + + if (drmCommandWriteRead(rws->fd, DRM_RADEON_GEM_CREATE, + &args, sizeof(args))) { + fprintf(stderr, "Failed to allocate :\n"); + fprintf(stderr, " size : %d bytes\n", size); + fprintf(stderr, " alignment : %d bytes\n", desc->alignment); + fprintf(stderr, " domains : %d\n", args.initial_domain); + return NULL; + } + + bo = CALLOC_STRUCT(radeon_bo); + if (!bo) + return NULL; + + pipe_reference_init(&bo->base.base.reference, 1); + bo->base.base.alignment = desc->alignment; + bo->base.base.usage = desc->usage; + bo->base.base.size = size; + bo->base.vtbl = &radeon_bo_vtbl; + bo->mgr = mgr; + bo->rws = mgr->rws; + bo->handle = args.handle; + bo->size = size; + pipe_mutex_init(bo->map_mutex); + + radeon_bo_ref(bo); + return &bo->base; +} + +static void radeon_bomgr_flush(struct pb_manager *mgr) +{ + /* NOP */ +} + +/* This is for the cache bufmgr. */ +static boolean radeon_bomgr_is_buffer_busy(struct pb_manager *_mgr, + struct pb_buffer *_buf) +{ + struct radeon_bo *bo = radeon_bo(_buf); + + if (radeon_bo_is_referenced_by_any_cs(bo)) { + return TRUE; + } + + if (radeon_bo_is_busy((struct r300_winsys_bo*)bo)) { + return TRUE; + } + + return FALSE; +} + +static void radeon_bomgr_destroy(struct pb_manager *_mgr) +{ + struct radeon_bomgr *mgr = radeon_bomgr(_mgr); + util_hash_table_destroy(mgr->bo_handles); + pipe_mutex_destroy(mgr->bo_handles_mutex); + FREE(mgr); +} + +#define PTR_TO_UINT(x) ((unsigned)((intptr_t)(x))) + +static unsigned handle_hash(void *key) +{ + return PTR_TO_UINT(key); +} + +static int handle_compare(void *key1, void *key2) +{ + return PTR_TO_UINT(key1) != PTR_TO_UINT(key2); +} + +struct pb_manager *radeon_bomgr_create(struct radeon_drm_winsys *rws) +{ + struct radeon_bomgr *mgr; + + mgr = CALLOC_STRUCT(radeon_bomgr); + if (!mgr) + return NULL; + + mgr->base.destroy = radeon_bomgr_destroy; + mgr->base.create_buffer = radeon_bomgr_create_bo; + mgr->base.flush = radeon_bomgr_flush; + mgr->base.is_buffer_busy = radeon_bomgr_is_buffer_busy; + + mgr->rws = rws; + mgr->bo_handles = util_hash_table_create(handle_hash, handle_compare); + pipe_mutex_init(mgr->bo_handles_mutex); + return &mgr->base; +} + +static void *radeon_bo_map(struct r300_winsys_bo *buf, + struct r300_winsys_cs *cs, + enum pipe_transfer_usage usage) +{ + struct pb_buffer *_buf = pb_buffer(buf); + + return pb_map(_buf, get_pb_usage_from_transfer_flags(usage), cs); +} + +static void radeon_bo_get_tiling(struct r300_winsys_bo *_buf, + enum r300_buffer_tiling *microtiled, + enum r300_buffer_tiling *macrotiled) +{ + struct radeon_bo *bo = get_radeon_bo(pb_buffer(_buf)); + struct drm_radeon_gem_set_tiling args = {}; + + args.handle = bo->handle; + + drmCommandWriteRead(bo->rws->fd, + DRM_RADEON_GEM_GET_TILING, + &args, + sizeof(args)); + + *microtiled = R300_BUFFER_LINEAR; + *macrotiled = R300_BUFFER_LINEAR; + if (args.tiling_flags & RADEON_BO_FLAGS_MICRO_TILE) + *microtiled = R300_BUFFER_TILED; + + if (args.tiling_flags & RADEON_BO_FLAGS_MACRO_TILE) + *macrotiled = R300_BUFFER_TILED; +} + +static void radeon_bo_set_tiling(struct r300_winsys_bo *_buf, + struct r300_winsys_cs *rcs, + enum r300_buffer_tiling microtiled, + enum r300_buffer_tiling macrotiled, + uint32_t pitch) +{ + struct radeon_bo *bo = get_radeon_bo(pb_buffer(_buf)); + struct radeon_drm_cs *cs = radeon_drm_cs(rcs); + struct drm_radeon_gem_set_tiling args = {}; + + /* Tiling determines how DRM treats the buffer data. + * We must flush CS when changing it if the buffer is referenced. */ + if (cs && radeon_bo_is_referenced_by_cs(cs, bo)) { + radeon_drm_cs_flush(rcs); + radeon_drm_cs_sync_flush(rcs); + } + + while (p_atomic_read(&bo->num_active_ioctls)) { + sched_yield(); + } + + if (microtiled == R300_BUFFER_TILED) + args.tiling_flags |= RADEON_BO_FLAGS_MICRO_TILE; + else if (microtiled == R300_BUFFER_SQUARETILED) + args.tiling_flags |= RADEON_BO_FLAGS_MICRO_TILE_SQUARE; + + if (macrotiled == R300_BUFFER_TILED) + args.tiling_flags |= RADEON_BO_FLAGS_MACRO_TILE; + + args.handle = bo->handle; + args.pitch = pitch; + + drmCommandWriteRead(bo->rws->fd, + DRM_RADEON_GEM_SET_TILING, + &args, + sizeof(args)); +} + +static struct r300_winsys_cs_handle *radeon_drm_get_cs_handle( + struct r300_winsys_bo *_buf) +{ + /* return radeon_bo. */ + return (struct r300_winsys_cs_handle*) + get_radeon_bo(pb_buffer(_buf)); +} + +static unsigned get_pb_usage_from_create_flags(unsigned bind, unsigned usage, + enum r300_buffer_domain domain) +{ + unsigned res = 0; + + if (bind & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER)) + res |= RADEON_PB_USAGE_CACHE; + + if (domain & R300_DOMAIN_GTT) + res |= RADEON_PB_USAGE_DOMAIN_GTT; + + if (domain & R300_DOMAIN_VRAM) + res |= RADEON_PB_USAGE_DOMAIN_VRAM; + + return res; +} + +static struct r300_winsys_bo * +radeon_winsys_bo_create(struct r300_winsys_screen *rws, + unsigned size, + unsigned alignment, + unsigned bind, + unsigned usage, + enum r300_buffer_domain domain) +{ + struct radeon_drm_winsys *ws = radeon_drm_winsys(rws); + struct pb_desc desc; + struct pb_manager *provider; + struct pb_buffer *buffer; + + memset(&desc, 0, sizeof(desc)); + desc.alignment = alignment; + desc.usage = get_pb_usage_from_create_flags(bind, usage, domain); + + /* Assign a buffer manager. */ + if (bind & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER)) + provider = ws->cman; + else + provider = ws->kman; + + buffer = provider->create_buffer(provider, size, &desc); + if (!buffer) + return NULL; + + return (struct r300_winsys_bo*)buffer; +} + +static struct r300_winsys_bo *radeon_winsys_bo_from_handle(struct r300_winsys_screen *rws, + struct winsys_handle *whandle, + unsigned *stride, + unsigned *size) +{ + struct radeon_drm_winsys *ws = radeon_drm_winsys(rws); + struct radeon_bo *bo; + struct radeon_bomgr *mgr = radeon_bomgr(ws->kman); + struct drm_gem_open open_arg = {}; + + /* We must maintain a list of pairs <handle, bo>, so that we always return + * the same BO for one particular handle. If we didn't do that and created + * more than one BO for the same handle and then relocated them in a CS, + * we would hit a deadlock in the kernel. + * + * The list of pairs is guarded by a mutex, of course. */ + pipe_mutex_lock(mgr->bo_handles_mutex); + + /* First check if there already is an existing bo for the handle. */ + bo = util_hash_table_get(mgr->bo_handles, (void*)(uintptr_t)whandle->handle); + if (bo) { + /* Increase the refcount. */ + struct pb_buffer *b = NULL; + pb_reference(&b, &bo->base); + goto done; + } + + /* There isn't, create a new one. */ + bo = CALLOC_STRUCT(radeon_bo); + if (!bo) { + goto fail; + } + + /* Open the BO. */ + open_arg.name = whandle->handle; + if (drmIoctl(ws->fd, DRM_IOCTL_GEM_OPEN, &open_arg)) { + FREE(bo); + goto fail; + } + bo->handle = open_arg.handle; + bo->size = open_arg.size; + bo->name = whandle->handle; + radeon_bo_ref(bo); + + /* Initialize it. */ + pipe_reference_init(&bo->base.base.reference, 1); + bo->base.base.alignment = 0; + bo->base.base.usage = PB_USAGE_GPU_WRITE | PB_USAGE_GPU_READ; + bo->base.base.size = bo->size; + bo->base.vtbl = &radeon_bo_vtbl; + bo->mgr = mgr; + bo->rws = mgr->rws; + pipe_mutex_init(bo->map_mutex); + + util_hash_table_set(mgr->bo_handles, (void*)(uintptr_t)whandle->handle, bo); + +done: + pipe_mutex_unlock(mgr->bo_handles_mutex); + + if (stride) + *stride = whandle->stride; + if (size) + *size = bo->base.base.size; + + return (struct r300_winsys_bo*)bo; + +fail: + pipe_mutex_unlock(mgr->bo_handles_mutex); + return NULL; +} + +static boolean radeon_winsys_bo_get_handle(struct r300_winsys_bo *buffer, + unsigned stride, + struct winsys_handle *whandle) +{ + struct drm_gem_flink flink = {}; + struct radeon_bo *bo = get_radeon_bo(pb_buffer(buffer)); + + if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) { + if (!bo->flinked) { + flink.handle = bo->handle; + + if (ioctl(bo->rws->fd, DRM_IOCTL_GEM_FLINK, &flink)) { + return FALSE; + } + + bo->flinked = TRUE; + bo->flink = flink.name; + } + whandle->handle = bo->flink; + } else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) { + whandle->handle = bo->handle; + } + + whandle->stride = stride; + return TRUE; +} + +void radeon_bomgr_init_functions(struct radeon_drm_winsys *ws) +{ + ws->base.buffer_get_cs_handle = radeon_drm_get_cs_handle; + ws->base.buffer_set_tiling = radeon_bo_set_tiling; + ws->base.buffer_get_tiling = radeon_bo_get_tiling; + ws->base.buffer_map = radeon_bo_map; + ws->base.buffer_unmap = pb_unmap; + ws->base.buffer_wait = radeon_bo_wait; + ws->base.buffer_is_busy = radeon_bo_is_busy; + ws->base.buffer_create = radeon_winsys_bo_create; + ws->base.buffer_from_handle = radeon_winsys_bo_from_handle; + ws->base.buffer_get_handle = radeon_winsys_bo_get_handle; +} diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_buffer.h b/src/gallium/winsys/radeon/drm/radeon_drm_bo.h index 494abdc0b48..a26866b7e75 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_buffer.h +++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.h @@ -1,5 +1,6 @@ /* * Copyright © 2008 Jérôme Glisse + * Copyright © 2011 Marek Olšák <[email protected]> * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining @@ -26,28 +27,61 @@ /* * Authors: * Jérôme Glisse <[email protected]> + * Marek Olšák <[email protected]> */ #ifndef RADEON_DRM_BUFFER_H #define RADEON_DRM_BUFFER_H #include "radeon_winsys.h" +#include "pipebuffer/pb_bufmgr.h" +#include "os/os_thread.h" -#define RADEON_PB_USAGE_VERTEX (1 << 28) +#define RADEON_PB_USAGE_CACHE (1 << 28) #define RADEON_PB_USAGE_DOMAIN_GTT (1 << 29) #define RADEON_PB_USAGE_DOMAIN_VRAM (1 << 30) +struct radeon_bomgr; + +struct radeon_bo { + struct pb_buffer base; + struct radeon_bomgr *mgr; + struct radeon_drm_winsys *rws; + + void *ptr; + pipe_mutex map_mutex; + + uint32_t size; + uint32_t handle; + uint32_t name; + + int ref_count; + + /* how many command streams is this bo referenced in? */ + int num_cs_references; + + /* how many command streams, which are being emitted in a separate + * thread, is this bo referenced in? */ + int num_active_ioctls; + + boolean flinked; + uint32_t flink; +}; + +struct pb_manager *radeon_bomgr_create(struct radeon_drm_winsys *rws); +void radeon_bomgr_init_functions(struct radeon_drm_winsys *ws); + +void radeon_bo_unref(struct radeon_bo *buf); + + +static INLINE void radeon_bo_ref(struct radeon_bo *bo) +{ + p_atomic_inc(&bo->ref_count); +} + static INLINE struct pb_buffer * -radeon_pb_buffer(struct r300_winsys_buffer *buffer) +pb_buffer(struct r300_winsys_bo *buffer) { return (struct pb_buffer *)buffer; } -struct pb_manager *radeon_drm_bufmgr_create(struct radeon_drm_winsys *rws); -struct pb_buffer *radeon_drm_bufmgr_create_buffer_from_handle(struct pb_manager *_mgr, - uint32_t handle); -void radeon_drm_bufmgr_flush_maps(struct pb_manager *_mgr); -boolean radeon_drm_bufmgr_get_handle(struct pb_buffer *_buf, - struct winsys_handle *whandle); -void radeon_drm_bufmgr_init_functions(struct radeon_drm_winsys *ws); - #endif diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_buffer.c b/src/gallium/winsys/radeon/drm/radeon_drm_buffer.c deleted file mode 100644 index 5e14287ec2d..00000000000 --- a/src/gallium/winsys/radeon/drm/radeon_drm_buffer.c +++ /dev/null @@ -1,532 +0,0 @@ -#include "radeon_drm_buffer.h" -#include "radeon_drm_cs.h" - -#include "util/u_hash_table.h" -#include "util/u_memory.h" -#include "util/u_simple_list.h" -#include "pipebuffer/pb_bufmgr.h" -#include "os/os_thread.h" - -#include "state_tracker/drm_driver.h" - -#include <radeon_drm.h> -#include <radeon_bo_gem.h> -#include <sys/ioctl.h> - -struct radeon_drm_bufmgr; - -struct radeon_drm_buffer { - struct pb_buffer base; - struct radeon_drm_bufmgr *mgr; - - struct radeon_bo *bo; - - boolean flinked; - uint32_t flink; - - struct radeon_drm_buffer *next, *prev; -}; - -extern const struct pb_vtbl radeon_drm_buffer_vtbl; - - -static INLINE struct radeon_drm_buffer * -radeon_drm_buffer(struct pb_buffer *buf) -{ - assert(buf); - assert(buf->vtbl == &radeon_drm_buffer_vtbl); - return (struct radeon_drm_buffer *)buf; -} - -struct radeon_drm_bufmgr { - /* Base class. */ - struct pb_manager base; - - /* Winsys. */ - struct radeon_drm_winsys *rws; - - /* List of mapped buffers and its mutex. */ - struct radeon_drm_buffer buffer_map_list; - pipe_mutex buffer_map_list_mutex; - - /* List of buffer handles and its mutex. */ - struct util_hash_table *buffer_handles; - pipe_mutex buffer_handles_mutex; -}; - -static INLINE struct radeon_drm_bufmgr * -radeon_drm_bufmgr(struct pb_manager *mgr) -{ - assert(mgr); - return (struct radeon_drm_bufmgr *)mgr; -} - -static void -radeon_drm_buffer_destroy(struct pb_buffer *_buf) -{ - struct radeon_drm_buffer *buf = radeon_drm_buffer(_buf); - int name; - - if (buf->bo->ptr != NULL) { - pipe_mutex_lock(buf->mgr->buffer_map_list_mutex); - /* Now test it again inside the mutex. */ - if (buf->bo->ptr != NULL) { - remove_from_list(buf); - radeon_bo_unmap(buf->bo); - buf->bo->ptr = NULL; - } - pipe_mutex_unlock(buf->mgr->buffer_map_list_mutex); - } - name = radeon_gem_name_bo(buf->bo); - if (name) { - pipe_mutex_lock(buf->mgr->buffer_handles_mutex); - util_hash_table_remove(buf->mgr->buffer_handles, - (void*)(uintptr_t)name); - pipe_mutex_unlock(buf->mgr->buffer_handles_mutex); - } - radeon_bo_unref(buf->bo); - - FREE(buf); -} - -static unsigned get_pb_usage_from_transfer_flags(enum pipe_transfer_usage usage) -{ - unsigned res = 0; - - if (usage & PIPE_TRANSFER_READ) - res |= PB_USAGE_CPU_READ; - - if (usage & PIPE_TRANSFER_WRITE) - res |= PB_USAGE_CPU_WRITE; - - if (usage & PIPE_TRANSFER_DONTBLOCK) - res |= PB_USAGE_DONTBLOCK; - - if (usage & PIPE_TRANSFER_UNSYNCHRONIZED) - res |= PB_USAGE_UNSYNCHRONIZED; - - return res; -} - -static void * -radeon_drm_buffer_map_internal(struct pb_buffer *_buf, - unsigned flags, void *flush_ctx) -{ - struct radeon_drm_buffer *buf = radeon_drm_buffer(_buf); - struct radeon_drm_cs *cs = flush_ctx; - int write = 0; - - /* Note how we use radeon_bo_is_referenced_by_cs here. There are - * basically two places this map function can be called from: - * - pb_map - * - create_buffer (in the buffer reuse case) - * - * Since pb managers are per-winsys managers, not per-context managers, - * and we shouldn't reuse buffers if they are in-use in any context, - * we simply ask: is this buffer referenced by *any* CS? - * - * The problem with buffer_create is that it comes from pipe_screen, - * so we have no CS to look at, though luckily the following code - * is sufficient to tell whether the buffer is in use. */ - if (flags & PB_USAGE_DONTBLOCK) { - if (_buf->base.usage & RADEON_PB_USAGE_VERTEX) - if (radeon_bo_is_referenced_by_cs(buf->bo, NULL)) - return NULL; - } - - if (buf->bo->ptr != NULL) { - pipe_mutex_lock(buf->mgr->buffer_map_list_mutex); - /* Now test ptr again inside the mutex. We might have gotten a race - * during the first test. */ - if (buf->bo->ptr != NULL) { - remove_from_list(buf); - } - pipe_mutex_unlock(buf->mgr->buffer_map_list_mutex); - return buf->bo->ptr; - } - - if (flags & PB_USAGE_DONTBLOCK) { - uint32_t domain; - if (radeon_bo_is_busy(buf->bo, &domain)) - return NULL; - } - - /* If we don't have any CS and the buffer is referenced, - * we cannot flush. */ - assert(cs || !radeon_bo_is_referenced_by_cs(buf->bo, NULL)); - - if (cs && radeon_bo_is_referenced_by_cs(buf->bo, NULL)) { - cs->flush_cs(cs->flush_data); - } - - if (flags & PB_USAGE_CPU_WRITE) { - write = 1; - } - - if (radeon_bo_map(buf->bo, write)) { - return NULL; - } - - pipe_mutex_lock(buf->mgr->buffer_map_list_mutex); - remove_from_list(buf); - pipe_mutex_unlock(buf->mgr->buffer_map_list_mutex); - return buf->bo->ptr; -} - -static void -radeon_drm_buffer_unmap_internal(struct pb_buffer *_buf) -{ - struct radeon_drm_buffer *buf = radeon_drm_buffer(_buf); - pipe_mutex_lock(buf->mgr->buffer_map_list_mutex); - if (is_empty_list(buf)) { /* = is not inserted... */ - insert_at_tail(&buf->mgr->buffer_map_list, buf); - } - pipe_mutex_unlock(buf->mgr->buffer_map_list_mutex); -} - -static void -radeon_drm_buffer_get_base_buffer(struct pb_buffer *buf, - struct pb_buffer **base_buf, - unsigned *offset) -{ - *base_buf = buf; - *offset = 0; -} - - -static enum pipe_error -radeon_drm_buffer_validate(struct pb_buffer *_buf, - struct pb_validate *vl, - unsigned flags) -{ - /* Always pinned */ - return PIPE_OK; -} - -static void -radeon_drm_buffer_fence(struct pb_buffer *buf, - struct pipe_fence_handle *fence) -{ -} - -const struct pb_vtbl radeon_drm_buffer_vtbl = { - radeon_drm_buffer_destroy, - radeon_drm_buffer_map_internal, - radeon_drm_buffer_unmap_internal, - radeon_drm_buffer_validate, - radeon_drm_buffer_fence, - radeon_drm_buffer_get_base_buffer, -}; - -static struct pb_buffer * -radeon_drm_bufmgr_create_buffer_from_handle_unsafe(struct pb_manager *_mgr, - uint32_t handle) -{ - struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr); - struct radeon_drm_winsys *rws = mgr->rws; - struct radeon_drm_buffer *buf; - struct radeon_bo *bo; - - buf = util_hash_table_get(mgr->buffer_handles, (void*)(uintptr_t)handle); - - if (buf) { - struct pb_buffer *b = NULL; - pb_reference(&b, &buf->base); - return b; - } - - bo = radeon_bo_open(rws->bom, handle, 0, - 0, 0, 0); - if (bo == NULL) - return NULL; - - buf = CALLOC_STRUCT(radeon_drm_buffer); - if (!buf) { - radeon_bo_unref(bo); - return NULL; - } - - make_empty_list(buf); - - pipe_reference_init(&buf->base.base.reference, 1); - buf->base.base.alignment = 0; - buf->base.base.usage = PB_USAGE_GPU_WRITE | PB_USAGE_GPU_READ; - buf->base.base.size = bo->size; - buf->base.vtbl = &radeon_drm_buffer_vtbl; - buf->mgr = mgr; - - buf->bo = bo; - - util_hash_table_set(mgr->buffer_handles, (void*)(uintptr_t)handle, buf); - - return &buf->base; -} - -struct pb_buffer * -radeon_drm_bufmgr_create_buffer_from_handle(struct pb_manager *_mgr, - uint32_t handle) -{ - struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr); - struct pb_buffer *pb; - - pipe_mutex_lock(mgr->buffer_handles_mutex); - pb = radeon_drm_bufmgr_create_buffer_from_handle_unsafe(_mgr, handle); - pipe_mutex_unlock(mgr->buffer_handles_mutex); - - return pb; -} - -static struct pb_buffer * -radeon_drm_bufmgr_create_buffer(struct pb_manager *_mgr, - pb_size size, - const struct pb_desc *desc) -{ - struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr); - struct radeon_drm_winsys *rws = mgr->rws; - struct radeon_drm_buffer *buf; - uint32_t domain; - - buf = CALLOC_STRUCT(radeon_drm_buffer); - if (!buf) - goto error1; - - pipe_reference_init(&buf->base.base.reference, 1); - buf->base.base.alignment = desc->alignment; - buf->base.base.usage = desc->usage; - buf->base.base.size = size; - buf->base.vtbl = &radeon_drm_buffer_vtbl; - buf->mgr = mgr; - - make_empty_list(buf); - - domain = - (desc->usage & RADEON_PB_USAGE_DOMAIN_GTT ? RADEON_GEM_DOMAIN_GTT : 0) | - (desc->usage & RADEON_PB_USAGE_DOMAIN_VRAM ? RADEON_GEM_DOMAIN_VRAM : 0); - - buf->bo = radeon_bo_open(rws->bom, 0, size, - desc->alignment, domain, 0); - if (buf->bo == NULL) - goto error2; - - return &buf->base; - - error2: - FREE(buf); - error1: - return NULL; -} - -static void -radeon_drm_bufmgr_flush(struct pb_manager *mgr) -{ - /* NOP */ -} - -static void -radeon_drm_bufmgr_destroy(struct pb_manager *_mgr) -{ - struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr); - util_hash_table_destroy(mgr->buffer_handles); - pipe_mutex_destroy(mgr->buffer_map_list_mutex); - pipe_mutex_destroy(mgr->buffer_handles_mutex); - FREE(mgr); -} - -static unsigned handle_hash(void *key) -{ - return (unsigned)key; -} - -static int handle_compare(void *key1, void *key2) -{ - return !((int)key1 == (int)key2); -} - -struct pb_manager * -radeon_drm_bufmgr_create(struct radeon_drm_winsys *rws) -{ - struct radeon_drm_bufmgr *mgr; - - mgr = CALLOC_STRUCT(radeon_drm_bufmgr); - if (!mgr) - return NULL; - - mgr->base.destroy = radeon_drm_bufmgr_destroy; - mgr->base.create_buffer = radeon_drm_bufmgr_create_buffer; - mgr->base.flush = radeon_drm_bufmgr_flush; - - mgr->rws = rws; - make_empty_list(&mgr->buffer_map_list); - mgr->buffer_handles = util_hash_table_create(handle_hash, handle_compare); - pipe_mutex_init(mgr->buffer_map_list_mutex); - pipe_mutex_init(mgr->buffer_handles_mutex); - return &mgr->base; -} - -static struct radeon_drm_buffer *get_drm_buffer(struct pb_buffer *_buf) -{ - struct radeon_drm_buffer *buf = NULL; - - if (_buf->vtbl == &radeon_drm_buffer_vtbl) { - buf = radeon_drm_buffer(_buf); - } else { - struct pb_buffer *base_buf; - pb_size offset; - pb_get_base_buffer(_buf, &base_buf, &offset); - - if (base_buf->vtbl == &radeon_drm_buffer_vtbl) - buf = radeon_drm_buffer(base_buf); - } - - return buf; -} - -static void *radeon_drm_buffer_map(struct r300_winsys_screen *ws, - struct r300_winsys_buffer *buf, - struct r300_winsys_cs *cs, - enum pipe_transfer_usage usage) -{ - struct pb_buffer *_buf = radeon_pb_buffer(buf); - - return pb_map(_buf, get_pb_usage_from_transfer_flags(usage), radeon_drm_cs(cs)); -} - -static void radeon_drm_buffer_unmap(struct r300_winsys_screen *ws, - struct r300_winsys_buffer *buf) -{ - struct pb_buffer *_buf = radeon_pb_buffer(buf); - - pb_unmap(_buf); -} - -boolean radeon_drm_bufmgr_get_handle(struct pb_buffer *_buf, - struct winsys_handle *whandle) -{ - struct drm_gem_flink flink; - struct radeon_drm_buffer *buf = get_drm_buffer(_buf); - - if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) { - if (!buf->flinked) { - flink.handle = buf->bo->handle; - - if (ioctl(buf->mgr->rws->fd, DRM_IOCTL_GEM_FLINK, &flink)) { - return FALSE; - } - - buf->flinked = TRUE; - buf->flink = flink.name; - } - whandle->handle = buf->flink; - } else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) { - whandle->handle = buf->bo->handle; - } - return TRUE; -} - -static void radeon_drm_buffer_get_tiling(struct r300_winsys_screen *ws, - struct r300_winsys_buffer *_buf, - enum r300_buffer_tiling *microtiled, - enum r300_buffer_tiling *macrotiled) -{ - struct radeon_drm_buffer *buf = get_drm_buffer(radeon_pb_buffer(_buf)); - uint32_t flags = 0, pitch; - - radeon_bo_get_tiling(buf->bo, &flags, &pitch); - - *microtiled = R300_BUFFER_LINEAR; - *macrotiled = R300_BUFFER_LINEAR; - if (flags & RADEON_BO_FLAGS_MICRO_TILE) - *microtiled = R300_BUFFER_TILED; - - if (flags & RADEON_BO_FLAGS_MACRO_TILE) - *macrotiled = R300_BUFFER_TILED; -} - -static void radeon_drm_buffer_set_tiling(struct r300_winsys_screen *ws, - struct r300_winsys_buffer *_buf, - enum r300_buffer_tiling microtiled, - enum r300_buffer_tiling macrotiled, - uint32_t pitch) -{ - struct radeon_drm_buffer *buf = get_drm_buffer(radeon_pb_buffer(_buf)); - uint32_t flags = 0; - if (microtiled == R300_BUFFER_TILED) - flags |= RADEON_BO_FLAGS_MICRO_TILE; -/* XXX Remove this ifdef when libdrm version 2.4.19 becomes mandatory. */ -#ifdef RADEON_BO_FLAGS_MICRO_TILE_SQUARE - else if (microtiled == R300_BUFFER_SQUARETILED) - flags |= RADEON_BO_FLAGS_MICRO_TILE_SQUARE; -#endif - if (macrotiled == R300_BUFFER_TILED) - flags |= RADEON_BO_FLAGS_MACRO_TILE; - - radeon_bo_set_tiling(buf->bo, flags, pitch); -} - -static struct r300_winsys_cs_buffer *radeon_drm_get_cs_handle( - struct r300_winsys_screen *rws, - struct r300_winsys_buffer *_buf) -{ - /* return pure radeon_bo. */ - return (struct r300_winsys_cs_buffer*) - get_drm_buffer(radeon_pb_buffer(_buf))->bo; -} - -static boolean radeon_drm_is_buffer_referenced(struct r300_winsys_cs *rcs, - struct r300_winsys_cs_buffer *_buf, - enum r300_reference_domain domain) -{ - struct radeon_bo *bo = (struct radeon_bo*)_buf; - uint32_t tmp; - - if (domain & R300_REF_CS) { - if (radeon_bo_is_referenced_by_cs(bo, NULL)) { - return TRUE; - } - } - - if (domain & R300_REF_HW) { - if (radeon_bo_is_busy(bo, &tmp)) { - return TRUE; - } - } - - return FALSE; -} - -void radeon_drm_bufmgr_flush_maps(struct pb_manager *_mgr) -{ - struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr); - struct radeon_drm_buffer *rpb, *t_rpb; - - pipe_mutex_lock(mgr->buffer_map_list_mutex); - - foreach_s(rpb, t_rpb, &mgr->buffer_map_list) { - radeon_bo_unmap(rpb->bo); - rpb->bo->ptr = NULL; - remove_from_list(rpb); - } - - make_empty_list(&mgr->buffer_map_list); - - pipe_mutex_unlock(mgr->buffer_map_list_mutex); -} - -static void radeon_drm_buffer_wait(struct r300_winsys_screen *ws, - struct r300_winsys_buffer *_buf) -{ - struct radeon_drm_buffer *buf = get_drm_buffer(radeon_pb_buffer(_buf)); - - radeon_bo_wait(buf->bo); -} - -void radeon_drm_bufmgr_init_functions(struct radeon_drm_winsys *ws) -{ - ws->base.buffer_get_cs_handle = radeon_drm_get_cs_handle; - ws->base.buffer_set_tiling = radeon_drm_buffer_set_tiling; - ws->base.buffer_get_tiling = radeon_drm_buffer_get_tiling; - ws->base.buffer_map = radeon_drm_buffer_map; - ws->base.buffer_unmap = radeon_drm_buffer_unmap; - ws->base.buffer_wait = radeon_drm_buffer_wait; - ws->base.cs_is_buffer_referenced = radeon_drm_is_buffer_referenced; -} diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_common.c b/src/gallium/winsys/radeon/drm/radeon_drm_common.c index fe71f080592..4676c2a1ea9 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_common.c +++ b/src/gallium/winsys/radeon/drm/radeon_drm_common.c @@ -1,5 +1,6 @@ /* * Copyright © 2009 Corbin Simpson + * Copyright © 2011 Marek Olšák <[email protected]> * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining @@ -27,38 +28,35 @@ * Authors: * Corbin Simpson <[email protected]> * Joakim Sindholt <[email protected]> + * Marek Olšák <[email protected]> */ #include "radeon_winsys.h" -#include "radeon_drm_buffer.h" +#include "radeon_drm_bo.h" #include "radeon_drm_cs.h" #include "radeon_drm_public.h" #include "pipebuffer/pb_bufmgr.h" #include "util/u_memory.h" -#include <radeon_drm.h> -#include <radeon_bo_gem.h> -#include <radeon_cs_gem.h> #include <xf86drm.h> #include <stdio.h> - -/* Enable/disable Hyper-Z access. Return TRUE on success. */ -static boolean radeon_set_hyperz_access(int fd, boolean enable) -{ #ifndef RADEON_INFO_WANT_HYPERZ #define RADEON_INFO_WANT_HYPERZ 7 #endif +#ifndef RADEON_INFO_WANT_CMASK +#define RADEON_INFO_WANT_CMASK 8 +#endif +/* Enable/disable feature access. Return TRUE on success. */ +static boolean radeon_set_fd_access(int fd, unsigned request, boolean enable) +{ struct drm_radeon_info info = {0}; unsigned value = enable ? 1 : 0; - if (!debug_get_bool_option("RADEON_HYPERZ", FALSE)) - return FALSE; - info.value = (unsigned long)&value; - info.request = RADEON_INFO_WANT_HYPERZ; + info.request = request; if (drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info)) != 0) return FALSE; @@ -107,23 +105,9 @@ static void do_ioctls(struct radeon_drm_winsys *winsys) exit(1); } -/* XXX Remove this ifdef when libdrm version 2.4.19 becomes mandatory. */ -#ifdef RADEON_BO_FLAGS_MICRO_TILE_SQUARE - // Supported since 2.1.0. - winsys->squaretiling = version->version_major > 2 || - version->version_minor >= 1; -#endif - - winsys->drm_2_3_0 = version->version_major > 2 || - version->version_minor >= 3; - - winsys->drm_2_6_0 = version->version_major > 2 || - (version->version_major == 2 && - version->version_minor >= 6); - - winsys->drm_2_8_0 = version->version_major > 2 || - (version->version_major == 2 && - version->version_minor >= 8); + winsys->drm_major = version->version_major; + winsys->drm_minor = version->version_minor; + winsys->drm_patchlevel = version->version_patchlevel; info.request = RADEON_INFO_DEVICE_ID; retval = drmCommandWriteRead(winsys->fd, DRM_RADEON_INFO, &info, sizeof(info)); @@ -152,7 +136,15 @@ static void do_ioctls(struct radeon_drm_winsys *winsys) } winsys->z_pipes = target; - winsys->hyperz = radeon_set_hyperz_access(winsys->fd, TRUE); + if (debug_get_bool_option("RADEON_HYPERZ", FALSE)) { + winsys->hyperz = radeon_set_fd_access(winsys->fd, + RADEON_INFO_WANT_HYPERZ, TRUE); + } + + if (debug_get_bool_option("RADEON_CMASK", FALSE)) { + winsys->aacompress = radeon_set_fd_access(winsys->fd, + RADEON_INFO_WANT_CMASK, TRUE); + } retval = drmCommandWriteRead(winsys->fd, DRM_RADEON_GEM_INFO, &gem_info, sizeof(gem_info)); @@ -164,17 +156,6 @@ static void do_ioctls(struct radeon_drm_winsys *winsys) winsys->gart_size = gem_info.gart_size; winsys->vram_size = gem_info.vram_size; - debug_printf("radeon: Successfully grabbed chipset info from kernel!\n" - "radeon: DRM version: %d.%d.%d ID: 0x%04x GB: %d Z: %d\n" - "radeon: GART size: %d MB VRAM size: %d MB\n" - "radeon: HyperZ: %s\n", - version->version_major, version->version_minor, - version->version_patchlevel, winsys->pci_id, - winsys->gb_pipes, winsys->z_pipes, - winsys->gart_size / 1024 / 1024, - winsys->vram_size / 1024 / 1024, - winsys->hyperz ? "YES" : "NO"); - drmFreeVersion(version); } @@ -184,11 +165,47 @@ static void radeon_winsys_destroy(struct r300_winsys_screen *rws) ws->cman->destroy(ws->cman); ws->kman->destroy(ws->kman); - - radeon_bo_manager_gem_dtor(ws->bom); FREE(rws); } +static uint32_t radeon_get_value(struct r300_winsys_screen *rws, + enum r300_value_id id) +{ + struct radeon_drm_winsys *ws = (struct radeon_drm_winsys *)rws; + + switch(id) { + case R300_VID_PCI_ID: + return ws->pci_id; + case R300_VID_GB_PIPES: + return ws->gb_pipes; + case R300_VID_Z_PIPES: + return ws->z_pipes; + case R300_VID_GART_SIZE: + return ws->gart_size; + case R300_VID_VRAM_SIZE: + return ws->vram_size; + case R300_VID_DRM_MAJOR: + return ws->drm_major; + case R300_VID_DRM_MINOR: + return ws->drm_minor; + case R300_VID_DRM_PATCHLEVEL: + return ws->drm_patchlevel; + case R300_VID_DRM_2_1_0: + return ws->drm_major*100 + ws->drm_minor >= 201; + case R300_VID_DRM_2_3_0: + return ws->drm_major*100 + ws->drm_minor >= 203; + case R300_VID_DRM_2_6_0: + return ws->drm_major*100 + ws->drm_minor >= 206; + case R300_VID_DRM_2_8_0: + return ws->drm_major*100 + ws->drm_minor >= 208; + case R300_CAN_HYPERZ: + return ws->hyperz; + case R300_CAN_AACOMPRESS: + return ws->aacompress; + } + return 0; +} + struct r300_winsys_screen *r300_drm_winsys_screen_create(int fd) { struct radeon_drm_winsys *ws = CALLOC_STRUCT(radeon_drm_winsys); @@ -204,10 +221,7 @@ struct r300_winsys_screen *r300_drm_winsys_screen_create(int fd) } /* Create managers. */ - ws->bom = radeon_bo_manager_gem_ctor(fd); - if (!ws->bom) - goto fail; - ws->kman = radeon_drm_bufmgr_create(ws); + ws->kman = radeon_bomgr_create(ws); if (!ws->kman) goto fail; ws->cman = pb_cache_manager_create(ws->kman, 1000000); @@ -216,22 +230,18 @@ struct r300_winsys_screen *r300_drm_winsys_screen_create(int fd) /* Set functions. */ ws->base.destroy = radeon_winsys_destroy; + ws->base.get_value = radeon_get_value; - radeon_drm_bufmgr_init_functions(ws); + radeon_bomgr_init_functions(ws); radeon_drm_cs_init_functions(ws); - radeon_winsys_init_functions(ws); return &ws->base; fail: - if (ws->bom) - radeon_bo_manager_gem_dtor(ws->bom); - if (ws->cman) ws->cman->destroy(ws->cman); if (ws->kman) ws->kman->destroy(ws->kman); - FREE(ws); return NULL; } diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_cs.c b/src/gallium/winsys/radeon/drm/radeon_drm_cs.c index 60bc36b0929..a38b01048b2 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_cs.c +++ b/src/gallium/winsys/radeon/drm/radeon_drm_cs.c @@ -63,17 +63,73 @@ */ #include "radeon_drm_cs.h" -#include "radeon_drm_buffer.h" #include "util/u_memory.h" +#include <stdio.h> #include <stdlib.h> #include <stdint.h> -#include <radeon_bo.h> #include <xf86drm.h> #define RELOC_DWORDS (sizeof(struct drm_radeon_cs_reloc) / sizeof(uint32_t)) +static boolean radeon_init_cs_context(struct radeon_cs_context *csc, int fd) +{ + csc->fd = fd; + csc->nrelocs = 512; + csc->relocs_bo = (struct radeon_bo**) + CALLOC(1, csc->nrelocs * sizeof(struct radeon_bo*)); + if (!csc->relocs_bo) { + return FALSE; + } + + csc->relocs = (struct drm_radeon_cs_reloc*) + CALLOC(1, csc->nrelocs * sizeof(struct drm_radeon_cs_reloc)); + if (!csc->relocs) { + FREE(csc->relocs_bo); + return FALSE; + } + + csc->chunks[0].chunk_id = RADEON_CHUNK_ID_IB; + csc->chunks[0].length_dw = 0; + csc->chunks[0].chunk_data = (uint64_t)(uintptr_t)csc->buf; + csc->chunks[1].chunk_id = RADEON_CHUNK_ID_RELOCS; + csc->chunks[1].length_dw = 0; + csc->chunks[1].chunk_data = (uint64_t)(uintptr_t)csc->relocs; + + csc->chunk_array[0] = (uint64_t)(uintptr_t)&csc->chunks[0]; + csc->chunk_array[1] = (uint64_t)(uintptr_t)&csc->chunks[1]; + + csc->cs.num_chunks = 2; + csc->cs.chunks = (uint64_t)(uintptr_t)csc->chunk_array; + return TRUE; +} + +static void radeon_cs_context_cleanup(struct radeon_cs_context *csc) +{ + unsigned i; + + for (i = 0; i < csc->crelocs; i++) { + p_atomic_dec(&csc->relocs_bo[i]->num_cs_references); + radeon_bo_unref(csc->relocs_bo[i]); + csc->relocs_bo[i] = NULL; + } + + csc->crelocs = 0; + csc->chunks[0].length_dw = 0; + csc->chunks[1].length_dw = 0; + csc->used_gart = 0; + csc->used_vram = 0; + memset(csc->is_handle_added, 0, sizeof(csc->is_handle_added)); +} + +static void radeon_destroy_cs_context(struct radeon_cs_context *csc) +{ + radeon_cs_context_cleanup(csc); + FREE(csc->relocs_bo); + FREE(csc->relocs); +} + static struct r300_winsys_cs *radeon_drm_cs_create(struct r300_winsys_screen *rws) { struct radeon_drm_winsys *ws = radeon_drm_winsys(rws); @@ -85,34 +141,29 @@ static struct r300_winsys_cs *radeon_drm_cs_create(struct r300_winsys_screen *rw } cs->ws = ws; - cs->nrelocs = 256; - cs->relocs_bo = (struct radeon_bo**) - CALLOC(1, cs->nrelocs * sizeof(struct radeon_bo*)); - if (!cs->relocs_bo) { + + if (!radeon_init_cs_context(&cs->csc1, cs->ws->fd)) { FREE(cs); return NULL; } - - cs->relocs = (struct drm_radeon_cs_reloc*) - CALLOC(1, cs->nrelocs * sizeof(struct drm_radeon_cs_reloc)); - if (!cs->relocs) { - FREE(cs->relocs_bo); + if (!radeon_init_cs_context(&cs->csc2, cs->ws->fd)) { + radeon_destroy_cs_context(&cs->csc1); FREE(cs); return NULL; } - cs->chunks[0].chunk_id = RADEON_CHUNK_ID_IB; - cs->chunks[0].length_dw = 0; - cs->chunks[0].chunk_data = (uint64_t)(uintptr_t)cs->base.buf; - cs->chunks[1].chunk_id = RADEON_CHUNK_ID_RELOCS; - cs->chunks[1].length_dw = 0; - cs->chunks[1].chunk_data = (uint64_t)(uintptr_t)cs->relocs; + /* Set the first command buffer as current. */ + cs->csc = &cs->csc1; + cs->cst = &cs->csc2; + cs->base.buf = cs->csc->buf; + + p_atomic_inc(&ws->num_cs); return &cs->base; } #define OUT_CS(cs, value) (cs)->buf[(cs)->cdw++] = (value) -static inline void update_domains(struct drm_radeon_cs_reloc *reloc, +static INLINE void update_domains(struct drm_radeon_cs_reloc *reloc, enum r300_buffer_domain rd, enum r300_buffer_domain wd, enum r300_buffer_domain *added_domains) @@ -131,23 +182,22 @@ static inline void update_domains(struct drm_radeon_cs_reloc *reloc, } } -static int radeon_get_reloc(struct radeon_drm_cs *cs, - struct radeon_bo *bo) +int radeon_get_reloc(struct radeon_cs_context *csc, struct radeon_bo *bo) { struct drm_radeon_cs_reloc *reloc; unsigned i; - unsigned hash = bo->handle & (sizeof(cs->is_handle_added)-1); + unsigned hash = bo->handle & (sizeof(csc->is_handle_added)-1); - if (cs->is_handle_added[hash]) { - reloc = cs->relocs_hashlist[hash]; + if (csc->is_handle_added[hash]) { + reloc = csc->relocs_hashlist[hash]; if (reloc->handle == bo->handle) { - return cs->reloc_indices_hashlist[hash]; + return csc->reloc_indices_hashlist[hash]; } /* Hash collision, look for the BO in the list of relocs linearly. */ - for (i = cs->crelocs; i != 0;) { + for (i = csc->crelocs; i != 0;) { --i; - reloc = &cs->relocs[i]; + reloc = &csc->relocs[i]; if (reloc->handle == bo->handle) { /* Put this reloc in the hash list. * This will prevent additional hash collisions if there are @@ -158,8 +208,8 @@ static int radeon_get_reloc(struct radeon_drm_cs *cs, * AAAAAAAAAAABBBBBBBBBBBBBBCCCCCCCC * will collide here: ^ and here: ^, * meaning that we should get very few collisions in the end. */ - cs->relocs_hashlist[hash] = reloc; - cs->reloc_indices_hashlist[hash] = i; + csc->relocs_hashlist[hash] = reloc; + csc->reloc_indices_hashlist[hash] = i; /*printf("write_reloc collision, hash: %i, handle: %i\n", hash, bo->handle);*/ return i; } @@ -169,7 +219,7 @@ static int radeon_get_reloc(struct radeon_drm_cs *cs, return -1; } -static void radeon_add_reloc(struct radeon_drm_cs *cs, +static void radeon_add_reloc(struct radeon_cs_context *csc, struct radeon_bo *bo, enum r300_buffer_domain rd, enum r300_buffer_domain wd, @@ -177,24 +227,24 @@ static void radeon_add_reloc(struct radeon_drm_cs *cs, { struct drm_radeon_cs_reloc *reloc; unsigned i; - unsigned hash = bo->handle & (sizeof(cs->is_handle_added)-1); + unsigned hash = bo->handle & (sizeof(csc->is_handle_added)-1); - if (cs->is_handle_added[hash]) { - reloc = cs->relocs_hashlist[hash]; + if (csc->is_handle_added[hash]) { + reloc = csc->relocs_hashlist[hash]; if (reloc->handle == bo->handle) { update_domains(reloc, rd, wd, added_domains); return; } /* Hash collision, look for the BO in the list of relocs linearly. */ - for (i = cs->crelocs; i != 0;) { + for (i = csc->crelocs; i != 0;) { --i; - reloc = &cs->relocs[i]; + reloc = &csc->relocs[i]; if (reloc->handle == bo->handle) { update_domains(reloc, rd, wd, added_domains); - cs->relocs_hashlist[hash] = reloc; - cs->reloc_indices_hashlist[hash] = i; + csc->relocs_hashlist[hash] = reloc; + csc->reloc_indices_hashlist[hash] = i; /*printf("write_reloc collision, hash: %i, handle: %i\n", hash, bo->handle);*/ return; } @@ -202,40 +252,41 @@ static void radeon_add_reloc(struct radeon_drm_cs *cs, } /* New relocation, check if the backing array is large enough. */ - if (cs->crelocs >= cs->nrelocs) { + if (csc->crelocs >= csc->nrelocs) { uint32_t size; - cs->nrelocs += 10; + csc->nrelocs += 10; - size = cs->nrelocs * sizeof(struct radeon_bo*); - cs->relocs_bo = (struct radeon_bo**)realloc(cs->relocs_bo, size); + size = csc->nrelocs * sizeof(struct radeon_bo*); + csc->relocs_bo = (struct radeon_bo**)realloc(csc->relocs_bo, size); - size = cs->nrelocs * sizeof(struct drm_radeon_cs_reloc); - cs->relocs = (struct drm_radeon_cs_reloc*)realloc(cs->relocs, size); + size = csc->nrelocs * sizeof(struct drm_radeon_cs_reloc); + csc->relocs = (struct drm_radeon_cs_reloc*)realloc(csc->relocs, size); - cs->chunks[1].chunk_data = (uint64_t)(uintptr_t)cs->relocs; + csc->chunks[1].chunk_data = (uint64_t)(uintptr_t)csc->relocs; } /* Initialize the new relocation. */ radeon_bo_ref(bo); - cs->relocs_bo[cs->crelocs] = bo; - reloc = &cs->relocs[cs->crelocs]; + p_atomic_inc(&bo->num_cs_references); + csc->relocs_bo[csc->crelocs] = bo; + reloc = &csc->relocs[csc->crelocs]; reloc->handle = bo->handle; reloc->read_domains = rd; reloc->write_domain = wd; reloc->flags = 0; - cs->is_handle_added[hash] = TRUE; - cs->relocs_hashlist[hash] = reloc; - cs->reloc_indices_hashlist[hash] = cs->crelocs; + csc->is_handle_added[hash] = TRUE; + csc->relocs_hashlist[hash] = reloc; + csc->reloc_indices_hashlist[hash] = csc->crelocs; - cs->chunks[1].length_dw += RELOC_DWORDS; - cs->crelocs++; + csc->chunks[1].length_dw += RELOC_DWORDS; + csc->crelocs++; *added_domains = rd | wd; } static void radeon_drm_cs_add_reloc(struct r300_winsys_cs *rcs, - struct r300_winsys_cs_buffer *buf, + struct r300_winsys_cs_handle *buf, enum r300_buffer_domain rd, enum r300_buffer_domain wd) { @@ -243,32 +294,32 @@ static void radeon_drm_cs_add_reloc(struct r300_winsys_cs *rcs, struct radeon_bo *bo = (struct radeon_bo*)buf; enum r300_buffer_domain added_domains; - radeon_add_reloc(cs, bo, rd, wd, &added_domains); + radeon_add_reloc(cs->csc, bo, rd, wd, &added_domains); if (!added_domains) return; if (added_domains & R300_DOMAIN_GTT) - cs->used_gart += bo->size; + cs->csc->used_gart += bo->size; if (added_domains & R300_DOMAIN_VRAM) - cs->used_vram += bo->size; + cs->csc->used_vram += bo->size; } static boolean radeon_drm_cs_validate(struct r300_winsys_cs *rcs) { struct radeon_drm_cs *cs = radeon_drm_cs(rcs); - return cs->used_gart < cs->ws->gart_size * 0.8 && - cs->used_vram < cs->ws->vram_size * 0.8; + return cs->csc->used_gart < cs->ws->gart_size * 0.8 && + cs->csc->used_vram < cs->ws->vram_size * 0.8; } static void radeon_drm_cs_write_reloc(struct r300_winsys_cs *rcs, - struct r300_winsys_cs_buffer *buf) + struct r300_winsys_cs_handle *buf) { struct radeon_drm_cs *cs = radeon_drm_cs(rcs); struct radeon_bo *bo = (struct radeon_bo*)buf; - unsigned index = radeon_get_reloc(cs, bo); + unsigned index = radeon_get_reloc(cs->csc, bo); if (index == -1) { fprintf(stderr, "r300: Cannot get a relocation in %s.\n", __func__); @@ -279,75 +330,109 @@ static void radeon_drm_cs_write_reloc(struct r300_winsys_cs *rcs, OUT_CS(&cs->base, index * RELOC_DWORDS); } -static void radeon_drm_cs_emit(struct r300_winsys_cs *rcs) +static PIPE_THREAD_ROUTINE(radeon_drm_cs_emit_ioctl, param) { - struct radeon_drm_cs *cs = radeon_drm_cs(rcs); - uint64_t chunk_array[2]; + struct radeon_cs_context *csc = (struct radeon_cs_context*)param; unsigned i; - int r; - if (cs->base.cdw) { - /* Unmap buffers. */ - radeon_drm_bufmgr_flush_maps(cs->ws->kman); - - /* Prepare the arguments. */ - cs->chunks[0].length_dw = cs->base.cdw; - - chunk_array[0] = (uint64_t)(uintptr_t)&cs->chunks[0]; - chunk_array[1] = (uint64_t)(uintptr_t)&cs->chunks[1]; - - cs->cs.num_chunks = 2; - cs->cs.chunks = (uint64_t)(uintptr_t)chunk_array; - - /* Emit. */ - r = drmCommandWriteRead(cs->ws->fd, DRM_RADEON_CS, - &cs->cs, sizeof(struct drm_radeon_cs)); - if (r) { - if (debug_get_bool_option("RADEON_DUMP_CS", FALSE)) { - fprintf(stderr, "radeon: The kernel rejected CS, dumping...\n"); - fprintf(stderr, "VENDORID:DEVICEID 0x%04X:0x%04X\n", 0x1002, - cs->ws->pci_id); - for (i = 0; i < cs->base.cdw; i++) { - fprintf(stderr, "0x%08X\n", cs->base.buf[i]); - } - } else { - fprintf(stderr, "radeon: The kernel rejected CS, " - "see dmesg for more information.\n"); + if (drmCommandWriteRead(csc->fd, DRM_RADEON_CS, + &csc->cs, sizeof(struct drm_radeon_cs))) { + if (debug_get_bool_option("RADEON_DUMP_CS", FALSE)) { + unsigned i; + + fprintf(stderr, "radeon: The kernel rejected CS, dumping...\n"); + for (i = 0; i < csc->chunks[0].length_dw; i++) { + fprintf(stderr, "0x%08X\n", csc->buf[i]); } + } else { + fprintf(stderr, "radeon: The kernel rejected CS, " + "see dmesg for more information.\n"); } } - /* Unreference buffers, cleanup. */ - for (i = 0; i < cs->crelocs; i++) { - radeon_bo_unref((struct radeon_bo*)cs->relocs_bo[i]); - cs->relocs_bo[i] = NULL; + for (i = 0; i < csc->crelocs; i++) + p_atomic_dec(&csc->relocs_bo[i]->num_active_ioctls); + return NULL; +} + +void radeon_drm_cs_sync_flush(struct r300_winsys_cs *rcs) +{ + struct radeon_drm_cs *cs = radeon_drm_cs(rcs); + + /* Wait for any pending ioctl to complete. */ + if (cs->thread) { + pipe_thread_wait(cs->thread); + cs->thread = 0; } +} + +DEBUG_GET_ONCE_BOOL_OPTION(thread, "RADEON_THREAD", TRUE) + +void radeon_drm_cs_flush(struct r300_winsys_cs *rcs) +{ + struct radeon_drm_cs *cs = radeon_drm_cs(rcs); + struct radeon_cs_context *tmp; + + radeon_drm_cs_sync_flush(rcs); + + /* If the CS is not empty, emit it in a newly-spawned thread. */ + if (cs->base.cdw) { + unsigned i, crelocs = cs->csc->crelocs; + cs->csc->chunks[0].length_dw = cs->base.cdw; + + for (i = 0; i < crelocs; i++) + p_atomic_inc(&cs->csc->relocs_bo[i]->num_active_ioctls); + + if (debug_get_option_thread()) { + cs->thread = pipe_thread_create(radeon_drm_cs_emit_ioctl, cs->csc); + assert(cs->thread); + } else { + radeon_drm_cs_emit_ioctl(cs->csc); + } + } + + /* Flip command streams. */ + tmp = cs->csc; + cs->csc = cs->cst; + cs->cst = tmp; + + /* Prepare a new CS. */ + radeon_cs_context_cleanup(cs->csc); + + cs->base.buf = cs->csc->buf; cs->base.cdw = 0; - cs->crelocs = 0; - cs->chunks[0].length_dw = 0; - cs->chunks[1].length_dw = 0; - cs->used_gart = 0; - cs->used_vram = 0; - memset(cs->is_handle_added, 0, sizeof(cs->is_handle_added)); } static void radeon_drm_cs_destroy(struct r300_winsys_cs *rcs) { struct radeon_drm_cs *cs = radeon_drm_cs(rcs); - FREE(cs->relocs_bo); - FREE(cs->relocs); + radeon_drm_cs_sync_flush(rcs); + radeon_cs_context_cleanup(&cs->csc1); + radeon_cs_context_cleanup(&cs->csc2); + p_atomic_dec(&cs->ws->num_cs); + radeon_destroy_cs_context(&cs->csc1); + radeon_destroy_cs_context(&cs->csc2); FREE(cs); } static void radeon_drm_cs_set_flush(struct r300_winsys_cs *rcs, - void (*flush)(void *), void *user) + void (*flush)(void *), void *user) { struct radeon_drm_cs *cs = radeon_drm_cs(rcs); cs->flush_cs = flush; cs->flush_data = user; } +static boolean radeon_bo_is_referenced(struct r300_winsys_cs *rcs, + struct r300_winsys_cs_handle *_buf) +{ + struct radeon_drm_cs *cs = radeon_drm_cs(rcs); + struct radeon_bo *bo = (struct radeon_bo*)_buf; + + return radeon_bo_is_referenced_by_cs(cs, bo); +} + void radeon_drm_cs_init_functions(struct radeon_drm_winsys *ws) { ws->base.cs_create = radeon_drm_cs_create; @@ -355,6 +440,8 @@ void radeon_drm_cs_init_functions(struct radeon_drm_winsys *ws) ws->base.cs_add_reloc = radeon_drm_cs_add_reloc; ws->base.cs_validate = radeon_drm_cs_validate; ws->base.cs_write_reloc = radeon_drm_cs_write_reloc; - ws->base.cs_flush = radeon_drm_cs_emit; + ws->base.cs_flush = radeon_drm_cs_flush; + ws->base.cs_sync_flush = radeon_drm_cs_sync_flush; ws->base.cs_set_flush = radeon_drm_cs_set_flush; + ws->base.cs_is_buffer_referenced = radeon_bo_is_referenced; } diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_cs.h b/src/gallium/winsys/radeon/drm/radeon_drm_cs.h index 76046534b65..4cc97f37e09 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_cs.h +++ b/src/gallium/winsys/radeon/drm/radeon_drm_cs.h @@ -1,42 +1,103 @@ +/* + * Copyright © 2011 Marek Olšák <[email protected]> + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS + * 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. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + */ + #ifndef RADEON_DRM_CS_H #define RADEON_DRM_CS_H -#include "radeon_winsys.h" +#include "radeon_drm_bo.h" #include <radeon_drm.h> -struct radeon_drm_cs { - struct r300_winsys_cs base; - - /* The winsys. */ - struct radeon_drm_winsys *ws; +struct radeon_cs_context { + uint32_t buf[R300_MAX_CMDBUF_DWORDS]; - /* Flush CS. */ - void (*flush_cs)(void *); - void *flush_data; + int fd; + struct drm_radeon_cs cs; + struct drm_radeon_cs_chunk chunks[2]; + uint64_t chunk_array[2]; /* Relocs. */ - unsigned crelocs; unsigned nrelocs; - struct drm_radeon_cs_reloc *relocs; + unsigned crelocs; struct radeon_bo **relocs_bo; - struct drm_radeon_cs cs; - struct drm_radeon_cs_chunk chunks[2]; - - unsigned used_vram; - unsigned used_gart; + struct drm_radeon_cs_reloc *relocs; /* 0 = BO not added, 1 = BO added */ char is_handle_added[256]; struct drm_radeon_cs_reloc *relocs_hashlist[256]; unsigned reloc_indices_hashlist[256]; + + unsigned used_vram; + unsigned used_gart; }; +struct radeon_drm_cs { + struct r300_winsys_cs base; + + /* We flip between these two CS. While one is being consumed + * by the kernel in another thread, the other one is being filled + * by the pipe driver. */ + struct radeon_cs_context csc1; + struct radeon_cs_context csc2; + /* The currently-used CS. */ + struct radeon_cs_context *csc; + /* The CS being currently-owned by the other thread. */ + struct radeon_cs_context *cst; + + /* The winsys. */ + struct radeon_drm_winsys *ws; + + /* Flush CS. */ + void (*flush_cs)(void *); + void *flush_data; + + pipe_thread thread; +}; + +int radeon_get_reloc(struct radeon_cs_context *csc, struct radeon_bo *bo); + static INLINE struct radeon_drm_cs * radeon_drm_cs(struct r300_winsys_cs *base) { return (struct radeon_drm_cs*)base; } +static INLINE boolean radeon_bo_is_referenced_by_cs(struct radeon_drm_cs *cs, + struct radeon_bo *bo) +{ + return bo->num_cs_references == bo->rws->num_cs || + (bo->num_cs_references && radeon_get_reloc(cs->csc, bo) != -1); +} + +static INLINE boolean radeon_bo_is_referenced_by_any_cs(struct radeon_bo *bo) +{ + return bo->num_cs_references; +} + +void radeon_drm_cs_flush(struct r300_winsys_cs *rcs); +void radeon_drm_cs_sync_flush(struct r300_winsys_cs *rcs); void radeon_drm_cs_init_functions(struct radeon_drm_winsys *ws); #endif diff --git a/src/gallium/winsys/radeon/drm/radeon_r300.c b/src/gallium/winsys/radeon/drm/radeon_r300.c deleted file mode 100644 index bacf181b47c..00000000000 --- a/src/gallium/winsys/radeon/drm/radeon_r300.c +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright 2008 Corbin Simpson <[email protected]> - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR 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. */ - -#include "radeon_drm_buffer.h" - -#include "util/u_memory.h" -#include "pipebuffer/pb_bufmgr.h" - -#include "state_tracker/drm_driver.h" - -static unsigned get_pb_usage_from_create_flags(unsigned bind, unsigned usage, - enum r300_buffer_domain domain) -{ - unsigned res = 0; - - if (bind & (PIPE_BIND_DEPTH_STENCIL | PIPE_BIND_RENDER_TARGET | - PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_SCANOUT)) - res |= PB_USAGE_GPU_WRITE; - - if (bind & PIPE_BIND_SAMPLER_VIEW) - res |= PB_USAGE_GPU_READ | PB_USAGE_GPU_WRITE; - - if (bind & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER)) - res |= PB_USAGE_GPU_READ; - - if (bind & PIPE_BIND_TRANSFER_WRITE) - res |= PB_USAGE_CPU_WRITE; - - if (bind & PIPE_BIND_TRANSFER_READ) - res |= PB_USAGE_CPU_READ; - - /* Is usage of any use for us? Probably not. */ - - /* Now add driver-specific usage flags. */ - if (bind & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER)) - res |= RADEON_PB_USAGE_VERTEX; - - if (domain & R300_DOMAIN_GTT) - res |= RADEON_PB_USAGE_DOMAIN_GTT; - - if (domain & R300_DOMAIN_VRAM) - res |= RADEON_PB_USAGE_DOMAIN_VRAM; - - return res; -} - -static struct r300_winsys_buffer * -radeon_r300_winsys_buffer_create(struct r300_winsys_screen *rws, - unsigned size, - unsigned alignment, - unsigned bind, - unsigned usage, - enum r300_buffer_domain domain) -{ - struct radeon_drm_winsys *ws = radeon_drm_winsys(rws); - struct pb_desc desc; - struct pb_manager *provider; - struct pb_buffer *buffer; - - memset(&desc, 0, sizeof(desc)); - desc.alignment = alignment; - desc.usage = get_pb_usage_from_create_flags(bind, usage, domain); - - /* Assign a buffer manager. */ - if (bind & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER)) - provider = ws->cman; - else - provider = ws->kman; - - buffer = provider->create_buffer(provider, size, &desc); - if (!buffer) - return NULL; - - return (struct r300_winsys_buffer*)buffer; -} - -static void radeon_r300_winsys_buffer_reference(struct r300_winsys_screen *rws, - struct r300_winsys_buffer **pdst, - struct r300_winsys_buffer *src) -{ - struct pb_buffer *_src = radeon_pb_buffer(src); - struct pb_buffer *_dst = radeon_pb_buffer(*pdst); - - pb_reference(&_dst, _src); - - *pdst = (struct r300_winsys_buffer*)_dst; -} - -static struct r300_winsys_buffer *radeon_r300_winsys_buffer_from_handle(struct r300_winsys_screen *rws, - struct winsys_handle *whandle, - unsigned *stride, - unsigned *size) -{ - struct radeon_drm_winsys *ws = radeon_drm_winsys(rws); - struct pb_buffer *_buf; - - _buf = radeon_drm_bufmgr_create_buffer_from_handle(ws->kman, whandle->handle); - - if (stride) - *stride = whandle->stride; - if (size) - *size = _buf->base.size; - - return (struct r300_winsys_buffer*)_buf; -} - -static boolean radeon_r300_winsys_buffer_get_handle(struct r300_winsys_screen *rws, - struct r300_winsys_buffer *buffer, - unsigned stride, - struct winsys_handle *whandle) -{ - struct pb_buffer *_buf = radeon_pb_buffer(buffer); - whandle->stride = stride; - return radeon_drm_bufmgr_get_handle(_buf, whandle); -} - -static uint32_t radeon_get_value(struct r300_winsys_screen *rws, - enum r300_value_id id) -{ - struct radeon_drm_winsys *ws = (struct radeon_drm_winsys *)rws; - - switch(id) { - case R300_VID_PCI_ID: - return ws->pci_id; - case R300_VID_GB_PIPES: - return ws->gb_pipes; - case R300_VID_Z_PIPES: - return ws->z_pipes; - case R300_VID_SQUARE_TILING_SUPPORT: - return ws->squaretiling; - case R300_VID_DRM_2_3_0: - return ws->drm_2_3_0; - case R300_VID_DRM_2_6_0: - return ws->drm_2_6_0; - case R300_VID_DRM_2_8_0: - return ws->drm_2_8_0; - case R300_CAN_HYPERZ: - return ws->hyperz; - } - return 0; -} - -void radeon_winsys_init_functions(struct radeon_drm_winsys *ws) -{ - ws->base.get_value = radeon_get_value; - ws->base.buffer_create = radeon_r300_winsys_buffer_create; - ws->base.buffer_reference = radeon_r300_winsys_buffer_reference; - ws->base.buffer_from_handle = radeon_r300_winsys_buffer_from_handle; - ws->base.buffer_get_handle = radeon_r300_winsys_buffer_get_handle; -} diff --git a/src/gallium/winsys/radeon/drm/radeon_winsys.h b/src/gallium/winsys/radeon/drm/radeon_winsys.h index 492edfef8c3..f8a89abcfe4 100644 --- a/src/gallium/winsys/radeon/drm/radeon_winsys.h +++ b/src/gallium/winsys/radeon/drm/radeon_winsys.h @@ -36,8 +36,8 @@ struct radeon_drm_winsys { struct r300_winsys_screen base; int fd; /* DRM file descriptor */ + int num_cs; /* The number of command streams created. */ - struct radeon_bo_manager *bom; /* Radeon BO manager. */ struct pb_manager *kman; struct pb_manager *cman; @@ -46,15 +46,15 @@ struct radeon_drm_winsys { uint32_t z_pipes; /* Z pipe count (rv530 only) */ uint32_t gart_size; /* GART size. */ uint32_t vram_size; /* VRAM size. */ - boolean squaretiling; /* Square tiling support. */ - /* DRM 2.3.0 (R500 VAP regs, MSPOS regs, fixed tex3D size checking) */ - boolean drm_2_3_0; - /* DRM 2.6.0 (Hyper-Z, GB_Z_PEQ_CONFIG allowed on rv350->r4xx, FG_ALPHA_VALUE) */ - boolean drm_2_6_0; - /* DRM 2.8.0 (US_FORMAT regs, ARGB2101010 colorbuffer) */ - boolean drm_2_8_0; + + unsigned drm_major; + unsigned drm_minor; + unsigned drm_patchlevel; + /* Hyper-Z user */ boolean hyperz; + /* AA compression (CMask) */ + boolean aacompress; }; static INLINE struct radeon_drm_winsys * @@ -63,6 +63,4 @@ radeon_drm_winsys(struct r300_winsys_screen *base) return (struct radeon_drm_winsys*)base; } -void radeon_winsys_init_functions(struct radeon_drm_winsys *ws); - #endif diff --git a/src/gallium/winsys/svga/drm/vmw_buffer.c b/src/gallium/winsys/svga/drm/vmw_buffer.c index eca174a6c56..80d5dfc3ed4 100644 --- a/src/gallium/winsys/svga/drm/vmw_buffer.c +++ b/src/gallium/winsys/svga/drm/vmw_buffer.c @@ -120,7 +120,8 @@ vmw_gmr_buffer_destroy(struct pb_buffer *_buf) static void * vmw_gmr_buffer_map(struct pb_buffer *_buf, - unsigned flags) + unsigned flags, + void *flush_ctx) { struct vmw_gmr_buffer *buf = vmw_gmr_buffer(_buf); return buf->map; diff --git a/src/gallium/winsys/svga/drm/vmw_context.c b/src/gallium/winsys/svga/drm/vmw_context.c index 11626ee637d..f2124c1bf65 100644 --- a/src/gallium/winsys/svga/drm/vmw_context.c +++ b/src/gallium/winsys/svga/drm/vmw_context.c @@ -320,7 +320,7 @@ vmw_swc_region_relocation(struct svga_winsys_context *swc, * to the FIFO won't cause flushing in the host. */ vswc->seen_regions += reloc->buffer->base.size; - if(vswc->seen_regions >= VMW_GMR_POOL_SIZE/2) + if(vswc->seen_regions >= VMW_GMR_POOL_SIZE/3) vswc->preemptive_flush = TRUE; } diff --git a/src/gallium/winsys/sw/xlib/SConscript b/src/gallium/winsys/sw/xlib/SConscript index df01a9ec2bf..f6c47411831 100644 --- a/src/gallium/winsys/sw/xlib/SConscript +++ b/src/gallium/winsys/sw/xlib/SConscript @@ -4,7 +4,7 @@ Import('*') -if env['platform'] in ('cygwin', 'linux'): +if env['platform'] in ('cygwin_nt-5.1', 'cygwin_nt-6.1', 'linux'): env = env.Clone() diff --git a/src/glsl/Makefile b/src/glsl/Makefile index c9525446633..876f0dfc2a5 100644 --- a/src/glsl/Makefile +++ b/src/glsl/Makefile @@ -1,3 +1,4 @@ + #src/glsl/pp/Makefile TOP = ../.. @@ -13,10 +14,12 @@ LIBGLCPP_SOURCES = \ GLCPP_SOURCES = \ $(LIBGLCPP_SOURCES) \ + ralloc.c \ glcpp/glcpp.c C_SOURCES = \ strtod.c \ + ralloc.c \ $(LIBGLCPP_SOURCES) CXX_SOURCES = \ @@ -68,6 +71,7 @@ CXX_SOURCES = \ opt_constant_propagation.cpp \ opt_constant_variable.cpp \ opt_copy_propagation.cpp \ + opt_copy_propagation_elements.cpp \ opt_dead_code.cpp \ opt_dead_code_local.cpp \ opt_dead_functions.cpp \ @@ -82,8 +86,7 @@ CXX_SOURCES = \ s_expression.cpp LIBS = \ - $(TOP)/src/glsl/libglsl.a \ - $(TALLOC_LIBS) + $(TOP)/src/glsl/libglsl.a APPS = glsl_compiler glcpp/glcpp @@ -111,8 +114,10 @@ OBJECTS = \ $(C_SOURCES:.c=.o) \ $(CXX_SOURCES:.cpp=.o) +DRICORE_OBJ_DIR = obj-visible +OBJECTS_DRICORE = $(addprefix $(DRICORE_OBJ_DIR)/,$(OBJECTS)) + INCLUDES = \ - $(TALLOC_CFLAGS) \ -I. \ -I../mesa \ -I../mapi \ @@ -127,7 +132,13 @@ ALL_SOURCES = \ ##### TARGETS ##### -default: depend lib$(LIBNAME).a $(APPS) +default: depend lib$(LIBNAME).a $(APPS) $(DRICORE_GLSL_LIBS) + +$(TOP)/$(LIB_DIR)/libglsl.so: $(OBJECTS_DRICORE) builtin_function.o Makefile $(TOP)/src/glsl/Makefile.template + $(MKLIB) -o $@ -linker '$(CXX)' -ldflags '$(LDFLAGS)' \ + -cplusplus -noprefix \ + -install $(TOP)/$(LIB_DIR) -id $(INSTALL_LIB_DIR)/[email protected] \ + $(OBJECTS_DRICORE) builtin_function.o lib$(LIBNAME).a: $(OBJECTS) builtin_function.o Makefile $(TOP)/src/glsl/Makefile.template $(MKLIB) -cplusplus -o $(LIBNAME) -static $(OBJECTS) builtin_function.o @@ -138,22 +149,33 @@ depend: $(ALL_SOURCES) Makefile $(MKDEP) $(MKDEP_OPTIONS) $(INCLUDES) $(ALL_SOURCES) 2> /dev/null # Remove .o and backup files -clean: +clean: clean-dricore rm -f $(GLCPP_OBJECTS) $(GLSL2_OBJECTS) $(OBJECTS) lib$(LIBNAME).a depend depend.bak builtin_function.cpp builtin_function.o builtin_stubs.o builtin_compiler -rm -f $(APPS) +clean-dricore: + -rm -f $(DRICORE_OBJ_DIR) $(TOP)/$(LIB_DIR)/libglsl.so libglsl.so + +ifneq (,$(DRICORE_GLSL_LIBS)) +DRICORE_INSTALL_TARGET = install-dricore +endif + # Dummy target -install: +install: $(DRICORE_INSTALL_TARGET) @echo -n "" +install-dricore: default + $(INSTALL) -d $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR) + $(INSTALL) -m 755 $(DRICORE_GLSL_LIBS) $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR) ##### RULES ##### -glsl_compiler: $(GLSL2_OBJECTS) libglsl.a - $(APP_CXX) $(INCLUDES) $(CFLAGS) $(LDFLAGS) $(GLSL2_OBJECTS) $(LIBS) -o $@ +glsl_compiler: $(GLSL2_OBJECTS) libglsl.a builtin_stubs.o + $(APP_CXX) $(INCLUDES) $(CFLAGS) $(LDFLAGS) $(GLSL2_OBJECTS) builtin_stubs.o $(LIBS) -o $@ -glcpp/glcpp: $(GLCPP_OBJECTS) libglsl.a - $(APP_CC) $(INCLUDES) $(CFLAGS) $(LDFLAGS) $(GLCPP_OBJECTS) $(LIBS) -o $@ +glcpp: glcpp/glcpp +glcpp/glcpp: $(GLCPP_OBJECTS) + $(APP_CC) $(INCLUDES) $(CFLAGS) $(LDFLAGS) $(GLCPP_OBJECTS) -o $@ .cpp.o: $(CXX) -c $(INCLUDES) $(CXXFLAGS) $(DEFINES) $< -o $@ @@ -161,6 +183,14 @@ glcpp/glcpp: $(GLCPP_OBJECTS) libglsl.a .c.o: $(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@ +$(DRICORE_OBJ_DIR)/%.o : %.cpp + @mkdir -p $(dir $@) + $(CXX) -c $(INCLUDES) $(DRI_CXXFLAGS) $(DEFINES) $< -o $@ + +$(DRICORE_OBJ_DIR)/%.o : %.c + @mkdir -p $(dir $@) + $(CC) -c $(INCLUDES) $(DRI_CFLAGS) $(DEFINES) $< -o $@ + glsl_lexer.cpp: glsl_lexer.lpp flex --nounistd -o$@ $< @@ -174,10 +204,10 @@ glcpp/glcpp-parse.c: glcpp/glcpp-parse.y bison -v -o "$@" --defines=glcpp/glcpp-parse.h $< builtin_compiler: $(GLSL2_OBJECTS) $(OBJECTS) builtin_stubs.o - $(APP_CXX) $(INCLUDES) $(CFLAGS) $(LDFLAGS) $(OBJECTS) $(GLSL2_OBJECTS) builtin_stubs.o $(TALLOC_LIBS) -o $@ + $(APP_CXX) $(INCLUDES) $(CFLAGS) $(LDFLAGS) $(OBJECTS) $(GLSL2_OBJECTS) builtin_stubs.o -o $@ builtin_function.cpp: builtins/profiles/* builtins/ir/* builtins/tools/generate_builtins.py builtins/tools/texture_builtins.py builtin_compiler @echo Regenerating builtin_function.cpp... - $(PYTHON2) $(PYTHON_FLAGS) builtins/tools/generate_builtins.py $(PWD)/builtin_compiler > builtin_function.cpp + $(PYTHON2) $(PYTHON_FLAGS) builtins/tools/generate_builtins.py ./builtin_compiler > builtin_function.cpp -include depend diff --git a/src/glsl/SConscript b/src/glsl/SConscript index 88a83fdb6fa..7c6b6ae8c4d 100644 --- a/src/glsl/SConscript +++ b/src/glsl/SConscript @@ -7,14 +7,12 @@ from sys import executable as python_cmd env = env.Clone() env.Prepend(CPPPATH = [ + '#include', '#src/mapi', '#src/mesa', '#src/glsl', ]) -if env['platform'] == 'windows': - env.Prepend(CPPPATH = ['#src/talloc']) - sources = [ 'glcpp/glcpp-lex.c', 'glcpp/glcpp-parse.c', @@ -66,6 +64,7 @@ sources = [ 'opt_constant_propagation.cpp', 'opt_constant_variable.cpp', 'opt_copy_propagation.cpp', + 'opt_copy_propagation_elements.cpp', 'opt_dead_code.cpp', 'opt_dead_code_local.cpp', 'opt_dead_functions.cpp', @@ -77,22 +76,19 @@ sources = [ 'opt_structure_splitting.cpp', 'opt_swizzle_swizzle.cpp', 'opt_tree_grafting.cpp', + 'ralloc.c', 's_expression.cpp', 'strtod.c', ] -if env['platform'] == common.host_platform: +if env['crosscompile'] and env['platform'] != 'embedded': + Import('builtin_glsl_function') +else: if env['msvc']: env.Prepend(CPPPATH = ['#/src/getopt']) env.PrependUnique(LIBS = [getopt]) - if env['platform'] == 'windows': - env.Prepend(CPPPATH = ['#src/talloc']) - env.Prepend(LIBS = [talloc]) - else: - env.Prepend(LIBS = ['talloc']) - builtin_compiler = env.Program( target = 'builtin_compiler', source = sources + ['main.cpp', 'builtin_stubs.cpp', @@ -109,19 +105,12 @@ if env['platform'] == common.host_platform: env.Depends(builtin_glsl_function, ['builtins/tools/generate_builtins.py', 'builtins/tools/texture_builtins.py'] + Glob('builtins/ir/*')) - if env['msvc']: - # There is no LD_LIBRARY_PATH equivalent on Windows. We need to ensure - # talloc.dll is on the same dir as builtin_function. - talloc_dll_src = talloc.dir.File('talloc.dll') - talloc_dll_dst = builtin_compiler[0].dir.File('talloc.dll') - talloc_dll = env.Command(talloc_dll_dst, talloc_dll_src, Copy(talloc_dll_dst, talloc_dll_src)) - env.Depends('builtin_function.cpp', talloc_dll) - Export('builtin_glsl_function') - if common.cross_compiling: + if env['hostonly']: Return() + sources += builtin_glsl_function glsl = env.ConvenienceLibrary( @@ -141,7 +130,7 @@ if env['platform'] == 'windows': 'user32', ]) -env.Prepend(LIBS = [glsl, talloc]) +env.Prepend(LIBS = [glsl]) env.Program( target = 'glsl2', diff --git a/src/glsl/ast.h b/src/glsl/ast.h index 0e2811ca665..878f48b2070 100644 --- a/src/glsl/ast.h +++ b/src/glsl/ast.h @@ -49,23 +49,23 @@ struct YYLTYPE; */ class ast_node { public: - /* Callers of this talloc-based new need not call delete. It's - * easier to just talloc_free 'ctx' (or any of its ancestors). */ + /* Callers of this ralloc-based new need not call delete. It's + * easier to just ralloc_free 'ctx' (or any of its ancestors). */ static void* operator new(size_t size, void *ctx) { void *node; - node = talloc_zero_size(ctx, size); + node = rzalloc_size(ctx, size); assert(node != NULL); return node; } /* If the user *does* call delete, that's OK, we will just - * talloc_free in that case. */ + * ralloc_free in that case. */ static void operator delete(void *table) { - talloc_free(table); + ralloc_free(table); } /** @@ -350,6 +350,14 @@ struct ast_type_qualifier { * qualifier is used. */ unsigned explicit_location:1; + + /** \name Layout qualifiers for GL_AMD_conservative_depth */ + /** \{ */ + unsigned depth_any:1; + unsigned depth_greater:1; + unsigned depth_less:1; + unsigned depth_unchanged:1; + /** \} */ } /** \brief Set of flags, accessed by name. */ q; @@ -606,25 +614,6 @@ private: }; -class ast_declaration_statement : public ast_node { -public: - ast_declaration_statement(void); - - enum { - ast_function, - ast_declaration, - ast_precision - } mode; - - union { - class ast_function *function; - ast_declarator_list *declarator; - ast_type_specifier *type; - ast_node *node; - } declaration; -}; - - class ast_expression_statement : public ast_node { public: ast_expression_statement(ast_expression *); diff --git a/src/glsl/ast_expr.cpp b/src/glsl/ast_expr.cpp index 4e83decb924..e624d11cf3b 100644 --- a/src/glsl/ast_expr.cpp +++ b/src/glsl/ast_expr.cpp @@ -20,8 +20,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -#include <cstdio> -#include <cassert> +#include <assert.h> #include "ast.h" const char * diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp index 6ecf779c935..e5cb8733952 100644 --- a/src/glsl/ast_function.cpp +++ b/src/glsl/ast_function.cpp @@ -66,7 +66,7 @@ process_parameters(exec_list *instructions, exec_list *actual_parameters, * formal or actual parameter list. Only the type is used. * * \return - * A talloced string representing the prototype of the function. + * A ralloced string representing the prototype of the function. */ char * prototype_string(const glsl_type *return_type, const char *name, @@ -75,19 +75,19 @@ prototype_string(const glsl_type *return_type, const char *name, char *str = NULL; if (return_type != NULL) - str = talloc_asprintf(str, "%s ", return_type->name); + str = ralloc_asprintf(NULL, "%s ", return_type->name); - str = talloc_asprintf_append(str, "%s(", name); + ralloc_asprintf_append(&str, "%s(", name); const char *comma = ""; foreach_list(node, parameters) { const ir_instruction *const param = (ir_instruction *) node; - str = talloc_asprintf_append(str, "%s%s", comma, param->type->name); + ralloc_asprintf_append(&str, "%s%s", comma, param->type->name); comma = ", "; } - str = talloc_strdup_append(str, ")"); + ralloc_strcat(&str, ")"); return str; } @@ -132,6 +132,9 @@ match_function_by_name(exec_list *instructions, const char *name, /* Verify that 'out' and 'inout' actual parameters are lvalues. This * isn't done in ir_function::matching_signature because that function * cannot generate the necessary diagnostics. + * + * Also, validate that 'const_in' formal parameters (an extension of our + * IR) correspond to ir_constant actual parameters. */ exec_list_iterator actual_iter = actual_parameters->iterator(); exec_list_iterator formal_iter = sig->parameters.iterator(); @@ -143,14 +146,35 @@ match_function_by_name(exec_list *instructions, const char *name, assert(actual != NULL); assert(formal != NULL); + if (formal->mode == ir_var_const_in && !actual->as_constant()) { + _mesa_glsl_error(loc, state, + "parameter `%s' must be a constant expression", + formal->name); + } + if ((formal->mode == ir_var_out) || (formal->mode == ir_var_inout)) { - if (! actual->is_lvalue()) { - /* FINISHME: Log a better diagnostic here. There is no way - * FINISHME: to tell the user which parameter is invalid. - */ - _mesa_glsl_error(loc, state, "`%s' parameter is not lvalue", - (formal->mode == ir_var_out) ? "out" : "inout"); + const char *mode = NULL; + switch (formal->mode) { + case ir_var_out: mode = "out"; break; + case ir_var_inout: mode = "inout"; break; + default: assert(false); break; + } + /* FIXME: 'loc' is incorrect (as of 2011-01-21). It is always + * FIXME: 0:0(0). + */ + if (actual->variable_referenced() + && actual->variable_referenced()->read_only) { + _mesa_glsl_error(loc, state, + "function parameter '%s %s' references the " + "read-only variable '%s'", + mode, formal->name, + actual->variable_referenced()->name); + + } else if (!actual->is_lvalue()) { + _mesa_glsl_error(loc, state, + "function parameter '%s %s' is not an lvalue", + mode, formal->name); } } @@ -173,7 +197,7 @@ match_function_by_name(exec_list *instructions, const char *name, ir_dereference_variable *deref; var = new(ctx) ir_variable(sig->return_type, - talloc_asprintf(ctx, "%s_retval", + ralloc_asprintf(ctx, "%s_retval", sig->function_name()), ir_var_temporary); instructions->push_tail(var); @@ -195,11 +219,11 @@ match_function_by_name(exec_list *instructions, const char *name, _mesa_glsl_error(loc, state, "no matching function for call to `%s'", str); - talloc_free(str); + ralloc_free(str); const char *prefix = "candidates are: "; - for (int i = -1; i < state->num_builtins_to_link; i++) { + for (int i = -1; i < (int) state->num_builtins_to_link; i++) { glsl_symbol_table *syms = i >= 0 ? state->builtins_to_link[i]->symbols : state->symbols; f = syms->get_function(name); @@ -211,7 +235,7 @@ match_function_by_name(exec_list *instructions, const char *name, str = prototype_string(sig->return_type, f->name, &sig->parameters); _mesa_glsl_error(loc, state, "%s%s\n", prefix, str); - talloc_free(str); + ralloc_free(str); prefix = " "; } @@ -232,7 +256,7 @@ match_function_by_name(exec_list *instructions, const char *name, static ir_rvalue * convert_component(ir_rvalue *src, const glsl_type *desired_type) { - void *ctx = talloc_parent(src); + void *ctx = ralloc_parent(src); const unsigned a = desired_type->base_type; const unsigned b = src->type->base_type; ir_expression *result = NULL; @@ -295,7 +319,7 @@ convert_component(ir_rvalue *src, const glsl_type *desired_type) static ir_rvalue * dereference_component(ir_rvalue *src, unsigned component) { - void *ctx = talloc_parent(src); + void *ctx = ralloc_parent(src); assert(component < src->type->components()); /* If the source is a constant, just create a new constant instead of a @@ -993,6 +1017,16 @@ ast_function_expression::hir(exec_list *instructions, const glsl_type *const constructor_type = type->glsl_type(& name, state); + /* constructor_type can be NULL if a variable with the same name as the + * structure has come into scope. + */ + if (constructor_type == NULL) { + _mesa_glsl_error(& loc, state, "unknown type `%s' (structure name " + "may be shadowed by a variable with the same name)", + type->type_name); + return ir_call::get_error_instruction(ctx); + } + /* Constructors for samplers are illegal. */ @@ -1022,6 +1056,57 @@ ast_function_expression::hir(exec_list *instructions, * correct order. These constructors follow essentially the same type * matching rules as functions. */ + if (constructor_type->is_record()) { + exec_list actual_parameters; + + process_parameters(instructions, &actual_parameters, + &this->expressions, state); + + exec_node *node = actual_parameters.head; + for (unsigned i = 0; i < constructor_type->length; i++) { + ir_rvalue *ir = (ir_rvalue *) node; + + if (node->is_tail_sentinel()) { + _mesa_glsl_error(&loc, state, + "insufficient parameters to constructor " + "for `%s'", + constructor_type->name); + return ir_call::get_error_instruction(ctx); + } + + if (apply_implicit_conversion(constructor_type->fields.structure[i].type, + ir, state)) { + node->replace_with(ir); + } else { + _mesa_glsl_error(&loc, state, + "parameter type mismatch in constructor " + "for `%s.%s' (%s vs %s)", + constructor_type->name, + constructor_type->fields.structure[i].name, + ir->type->name, + constructor_type->fields.structure[i].type->name); + return ir_call::get_error_instruction(ctx);; + } + + node = node->next; + } + + if (!node->is_tail_sentinel()) { + _mesa_glsl_error(&loc, state, "too many parameters in constructor " + "for `%s'", constructor_type->name); + return ir_call::get_error_instruction(ctx); + } + + ir_rvalue *const constant = + constant_record_constructor(constructor_type, &actual_parameters, + state); + + return (constant != NULL) + ? constant + : emit_inline_record_constructor(constructor_type, instructions, + &actual_parameters, state); + } + if (!constructor_type->is_numeric() && !constructor_type->is_boolean()) return ir_call::get_error_instruction(ctx); @@ -1197,54 +1282,6 @@ ast_function_expression::hir(exec_list *instructions, process_parameters(instructions, &actual_parameters, &this->expressions, state); - const glsl_type *const type = - state->symbols->get_type(id->primary_expression.identifier); - - if ((type != NULL) && type->is_record()) { - exec_node *node = actual_parameters.head; - for (unsigned i = 0; i < type->length; i++) { - ir_rvalue *ir = (ir_rvalue *) node; - - if (node->is_tail_sentinel()) { - _mesa_glsl_error(&loc, state, - "insufficient parameters to constructor " - "for `%s'", - type->name); - return ir_call::get_error_instruction(ctx); - } - - if (apply_implicit_conversion(type->fields.structure[i].type, ir, - state)) { - node->replace_with(ir); - } else { - _mesa_glsl_error(&loc, state, - "parameter type mismatch in constructor " - "for `%s.%s' (%s vs %s)", - type->name, - type->fields.structure[i].name, - ir->type->name, - type->fields.structure[i].type->name); - return ir_call::get_error_instruction(ctx);; - } - - node = node->next; - } - - if (!node->is_tail_sentinel()) { - _mesa_glsl_error(&loc, state, "too many parameters in constructor " - "for `%s'", type->name); - return ir_call::get_error_instruction(ctx); - } - - ir_rvalue *const constant = - constant_record_constructor(type, &actual_parameters, state); - - return (constant != NULL) - ? constant - : emit_inline_record_constructor(type, instructions, - &actual_parameters, state); - } - return match_function_by_name(instructions, id->primary_expression.identifier, & loc, &actual_parameters, state); diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp index 7a171f3a2bb..bef099cca3b 100644 --- a/src/glsl/ast_to_hir.cpp +++ b/src/glsl/ast_to_hir.cpp @@ -435,6 +435,13 @@ modulus_result_type(const struct glsl_type *type_a, const struct glsl_type *type_b, struct _mesa_glsl_parse_state *state, YYLTYPE *loc) { + if (state->language_version < 130) { + _mesa_glsl_error(loc, state, + "operator '%%' is reserved in %s", + state->version_string); + return glsl_type::error_type; + } + /* From GLSL 1.50 spec, page 56: * "The operator modulus (%) operates on signed or unsigned integers or * integer vectors. The operand types must both be signed or both be @@ -639,7 +646,14 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state, bool error_emitted = (lhs->type->is_error() || rhs->type->is_error()); if (!error_emitted) { - if (!lhs->is_lvalue()) { + if (lhs->variable_referenced() != NULL + && lhs->variable_referenced()->read_only) { + _mesa_glsl_error(&lhs_loc, state, + "assignment to read-only variable '%s'", + lhs->variable_referenced()->name); + error_emitted = true; + + } else if (!lhs->is_lvalue()) { _mesa_glsl_error(& lhs_loc, state, "non-lvalue in assignment"); error_emitted = true; } @@ -712,7 +726,7 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state, static ir_rvalue * get_lvalue_copy(exec_list *instructions, ir_rvalue *lvalue) { - void *ctx = talloc_parent(lvalue); + void *ctx = ralloc_parent(lvalue); ir_variable *var; var = new(ctx) ir_variable(lvalue->type, "_post_incdec_tmp", @@ -1809,7 +1823,6 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, } } - /* FINISHME: Mark 'in' variables at global scope as read-only. */ if (qual->flags.q.constant || qual->flags.q.attribute || qual->flags.q.uniform || (qual->flags.q.varying && (state->target == fragment_shader))) @@ -2003,6 +2016,40 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, } } + /* Layout qualifiers for gl_FragDepth, which are enabled by extension + * AMD_conservative_depth. + */ + int depth_layout_count = qual->flags.q.depth_any + + qual->flags.q.depth_greater + + qual->flags.q.depth_less + + qual->flags.q.depth_unchanged; + if (depth_layout_count > 0 + && !state->AMD_conservative_depth_enable) { + _mesa_glsl_error(loc, state, + "extension GL_AMD_conservative_depth must be enabled " + "to use depth layout qualifiers"); + } else if (depth_layout_count > 0 + && strcmp(var->name, "gl_FragDepth") != 0) { + _mesa_glsl_error(loc, state, + "depth layout qualifiers can be applied only to " + "gl_FragDepth"); + } else if (depth_layout_count > 1 + && strcmp(var->name, "gl_FragDepth") == 0) { + _mesa_glsl_error(loc, state, + "at most one depth layout qualifier can be applied to " + "gl_FragDepth"); + } + if (qual->flags.q.depth_any) + var->depth_layout = ir_depth_layout_any; + else if (qual->flags.q.depth_greater) + var->depth_layout = ir_depth_layout_greater; + else if (qual->flags.q.depth_less) + var->depth_layout = ir_depth_layout_less; + else if (qual->flags.q.depth_unchanged) + var->depth_layout = ir_depth_layout_unchanged; + else + var->depth_layout = ir_depth_layout_none; + if (var->type->is_array() && state->language_version != 110) { var->array_lvalue = true; } @@ -2206,6 +2253,8 @@ ast_declarator_list::hir(exec_list *instructions, mode, var->name, extra); } } else if (var->mode == ir_var_in) { + var->read_only = true; + if (state->target == vertex_shader) { bool error_emitted = false; @@ -2591,6 +2640,36 @@ ast_declarator_list::hir(exec_list *instructions, && earlier->type == var->type && earlier->mode == var->mode) { earlier->interpolation = var->interpolation; + + /* Layout qualifiers for gl_FragDepth. */ + } else if (state->AMD_conservative_depth_enable + && strcmp(var->name, "gl_FragDepth") == 0 + && earlier->type == var->type + && earlier->mode == var->mode) { + + /** From the AMD_conservative_depth spec: + * Within any shader, the first redeclarations of gl_FragDepth + * must appear before any use of gl_FragDepth. + */ + if (earlier->used) { + _mesa_glsl_error(&loc, state, + "the first redeclaration of gl_FragDepth " + "must appear before any use of gl_FragDepth"); + } + + /* Prevent inconsistent redeclaration of depth layout qualifier. */ + if (earlier->depth_layout != ir_depth_layout_none + && earlier->depth_layout != var->depth_layout) { + _mesa_glsl_error(&loc, state, + "gl_FragDepth: depth layout is declared here " + "as '%s, but it was previously declared as " + "'%s'", + depth_layout_string(var->depth_layout), + depth_layout_string(earlier->depth_layout)); + } + + earlier->depth_layout = var->depth_layout; + } else { YYLTYPE loc = this->get_location(); _mesa_glsl_error(&loc, state, "`%s' redeclared", decl->identifier); @@ -3002,27 +3081,26 @@ ast_jump_statement::hir(exec_list *instructions, assert(state->current_function); if (opt_return_value) { - if (state->current_function->return_type->base_type == - GLSL_TYPE_VOID) { - YYLTYPE loc = this->get_location(); - - _mesa_glsl_error(& loc, state, - "`return` with a value, in function `%s' " - "returning void", - state->current_function->function_name()); - } - ir_rvalue *const ret = opt_return_value->hir(instructions, state); - assert(ret != NULL); + + /* The value of the return type can be NULL if the shader says + * 'return foo();' and foo() is a function that returns void. + * + * NOTE: The GLSL spec doesn't say that this is an error. The type + * of the return value is void. If the return type of the function is + * also void, then this should compile without error. Seriously. + */ + const glsl_type *const ret_type = + (ret == NULL) ? glsl_type::void_type : ret->type; /* Implicit conversions are not allowed for return values. */ - if (state->current_function->return_type != ret->type) { + if (state->current_function->return_type != ret_type) { YYLTYPE loc = this->get_location(); _mesa_glsl_error(& loc, state, "`return' with wrong type %s, in function `%s' " "returning %s", - ret->type->name, + ret_type->name, state->current_function->function_name(), state->current_function->return_type->name); } @@ -3321,7 +3399,7 @@ ast_struct_specifier::hir(exec_list *instructions, * the types to HIR. This ensures that structure definitions embedded in * other structure definitions are processed. */ - glsl_struct_field *const fields = talloc_array(state, glsl_struct_field, + glsl_struct_field *const fields = ralloc_array(state, glsl_struct_field, decl_count); unsigned i = 0; diff --git a/src/glsl/ast_type.cpp b/src/glsl/ast_type.cpp index d14077473f0..c680ae5f671 100644 --- a/src/glsl/ast_type.cpp +++ b/src/glsl/ast_type.cpp @@ -21,7 +21,6 @@ * DEALINGS IN THE SOFTWARE. */ -#include <cstdio> #include "ast.h" extern "C" { #include "program/symbol_table.h" diff --git a/src/glsl/builtins/profiles/130.frag b/src/glsl/builtins/profiles/130.frag index 329116f2a28..43653a906f8 100644 --- a/src/glsl/builtins/profiles/130.frag +++ b/src/glsl/builtins/profiles/130.frag @@ -635,7 +635,6 @@ uvec4 textureLod(usampler2DArray sampler, vec3 P, float lod); float textureLod(sampler1DArrayShadow sampler, vec3 P, float lod); -#if 0 /* textureOffset - no bias */ vec4 textureOffset( sampler1D sampler, float P, int offset); ivec4 textureOffset(isampler1D sampler, float P, int offset); @@ -687,7 +686,6 @@ ivec4 textureOffset(isampler2DArray sampler, vec3 P, ivec2 offset, float bias); uvec4 textureOffset(usampler2DArray sampler, vec3 P, ivec2 offset, float bias); float textureOffset(sampler1DArrayShadow samp, vec3 P, int offset, float bias); -#endif /* texelFetch */ vec4 texelFetch( sampler1D sampler, int P, int lod); @@ -710,7 +708,6 @@ uvec4 texelFetch(usampler1DArray sampler, ivec2 P, int lod); ivec4 texelFetch(isampler2DArray sampler, ivec3 P, int lod); uvec4 texelFetch(usampler2DArray sampler, ivec3 P, int lod); -#if 0 /* texelFetchOffset */ vec4 texelFetchOffset( sampler1D sampler, int P, int lod, int offset); ivec4 texelFetchOffset(isampler1D sampler, int P, int lod, int offset); @@ -801,7 +798,6 @@ ivec4 textureLodOffset(isampler2DArray samp, vec3 P, float lod, ivec2 offset); uvec4 textureLodOffset(usampler2DArray samp, vec3 P, float lod, ivec2 offset); float textureLodOffset(sampler1DArrayShadow s, vec3 P, float lod, int offset); -#endif /* textureProjLod */ vec4 textureProjLod( sampler1D sampler, vec2 P, float lod); @@ -825,7 +821,6 @@ uvec4 textureProjLod(usampler3D sampler, vec4 P, float lod); float textureProjLod(sampler1DShadow sampler, vec4 P, float lod); float textureProjLod(sampler2DShadow sampler, vec4 P, float lod); -#if 0 /* textureProjLodOffset */ vec4 textureProjLodOffset( sampler1D sampler, vec2 P, float lod, int offset); ivec4 textureProjLodOffset(isampler1D sampler, vec2 P, float lod, int offset); @@ -847,7 +842,6 @@ uvec4 textureProjLodOffset(usampler3D sampler, vec4 P, float lod, ivec3 offset); float textureProjLodOffset(sampler1DShadow s, vec4 P, float lod, int offset); float textureProjLodOffset(sampler2DShadow s, vec4 P, float lod, ivec2 offset); -#endif /* textureGrad */ vec4 textureGrad( sampler1D sampler, float P, float dPdx, float dPdy); @@ -881,7 +875,6 @@ uvec4 textureGrad(usampler2DArray sampler, vec3 P, vec2 dPdx, vec2 dPdy); float textureGrad(sampler1DArrayShadow sampler, vec3 P, float dPdx, float dPdy); float textureGrad(sampler2DArrayShadow sampler, vec4 P, vec2 dPdx, vec2 dPdy); -#if 0 /* textureGradOffset */ vec4 textureGradOffset( sampler1D s, float P, float dx, float dy, int off); ivec4 textureGradOffset(isampler1D s, float P, float dx, float dy, int offset); @@ -912,7 +905,6 @@ uvec4 textureGradOffset(usampler2DArray s, vec3 P, vec2 dx, vec2 dy, ivec2 off); float textureGradOffset(sampler1DArrayShadow s, vec3 P, float dx, float dy, int o); float textureGradOffset(sampler2DArrayShadow s, vec4 P, vec2 dx, vec2 dy, ivec2 o); -#endif /* textureProjGrad */ vec4 textureProjGrad( sampler1D sampler, vec2 P, float dPdx, float dPdy); @@ -936,7 +928,6 @@ uvec4 textureProjGrad(usampler3D sampler, vec4 P, vec3 dPdx, vec3 dPdy); float textureProjGrad(sampler1DShadow sampler, vec4 P, float dPdx, float dPdy); float textureProjGrad(sampler2DShadow sampler, vec4 P, vec2 dPdx, vec2 dPdy); -#if 0 /* textureProjGradOffset */ vec4 textureProjGradOffset( sampler1D s, vec2 P, float dx, float dy, int off); ivec4 textureProjGradOffset(isampler1D s, vec2 P, float dx, float dy, int off); @@ -958,7 +949,6 @@ uvec4 textureProjGradOffset(usampler3D s, vec4 P, vec3 dx, vec3 dy, ivec3 off); float textureProjGradOffset(sampler1DShadow s, vec4 P, float dx, float dy, int o); float textureProjGradOffset(sampler2DShadow s, vec4 P, vec2 dx, vec2 dy, vec2 o); -#endif /* * The following texture functions are deprecated: diff --git a/src/glsl/builtins/profiles/130.vert b/src/glsl/builtins/profiles/130.vert index 1c212ebb3c5..742dec6e6d5 100644 --- a/src/glsl/builtins/profiles/130.vert +++ b/src/glsl/builtins/profiles/130.vert @@ -637,7 +637,6 @@ uvec4 textureLod(usampler2DArray sampler, vec3 P, float lod); float textureLod(sampler1DArrayShadow sampler, vec3 P, float lod); -#if 0 /* textureOffset - no bias */ vec4 textureOffset( sampler1D sampler, float P, int offset); ivec4 textureOffset(isampler1D sampler, float P, int offset); @@ -689,7 +688,6 @@ ivec4 textureOffset(isampler2DArray sampler, vec3 P, ivec2 offset, float bias); uvec4 textureOffset(usampler2DArray sampler, vec3 P, ivec2 offset, float bias); float textureOffset(sampler1DArrayShadow samp, vec3 P, int offset, float bias); -#endif /* texelFetch */ vec4 texelFetch( sampler1D sampler, int P, int lod); @@ -712,7 +710,6 @@ uvec4 texelFetch(usampler1DArray sampler, ivec2 P, int lod); ivec4 texelFetch(isampler2DArray sampler, ivec3 P, int lod); uvec4 texelFetch(usampler2DArray sampler, ivec3 P, int lod); -#if 0 /* texelFetchOffset */ vec4 texelFetchOffset( sampler1D sampler, int P, int lod, int offset); ivec4 texelFetchOffset(isampler1D sampler, int P, int lod, int offset); @@ -803,7 +800,6 @@ ivec4 textureLodOffset(isampler2DArray samp, vec3 P, float lod, ivec2 offset); uvec4 textureLodOffset(usampler2DArray samp, vec3 P, float lod, ivec2 offset); float textureLodOffset(sampler1DArrayShadow s, vec3 P, float lod, int offset); -#endif /* textureProjLod */ vec4 textureProjLod( sampler1D sampler, vec2 P, float lod); @@ -827,7 +823,6 @@ uvec4 textureProjLod(usampler3D sampler, vec4 P, float lod); float textureProjLod(sampler1DShadow sampler, vec4 P, float lod); float textureProjLod(sampler2DShadow sampler, vec4 P, float lod); -#if 0 /* textureProjLodOffset */ vec4 textureProjLodOffset( sampler1D sampler, vec2 P, float lod, int offset); ivec4 textureProjLodOffset(isampler1D sampler, vec2 P, float lod, int offset); @@ -849,7 +844,6 @@ uvec4 textureProjLodOffset(usampler3D sampler, vec4 P, float lod, ivec3 offset); float textureProjLodOffset(sampler1DShadow s, vec4 P, float lod, int offset); float textureProjLodOffset(sampler2DShadow s, vec4 P, float lod, ivec2 offset); -#endif /* textureGrad */ vec4 textureGrad( sampler1D sampler, float P, float dPdx, float dPdy); @@ -883,7 +877,6 @@ uvec4 textureGrad(usampler2DArray sampler, vec3 P, vec2 dPdx, vec2 dPdy); float textureGrad(sampler1DArrayShadow sampler, vec3 P, float dPdx, float dPdy); float textureGrad(sampler2DArrayShadow sampler, vec4 P, vec2 dPdx, vec2 dPdy); -#if 0 /* textureGradOffset */ vec4 textureGradOffset( sampler1D s, float P, float dx, float dy, int off); ivec4 textureGradOffset(isampler1D s, float P, float dx, float dy, int offset); @@ -914,7 +907,6 @@ uvec4 textureGradOffset(usampler2DArray s, vec3 P, vec2 dx, vec2 dy, ivec2 off); float textureGradOffset(sampler1DArrayShadow s, vec3 P, float dx, float dy, int o); float textureGradOffset(sampler2DArrayShadow s, vec4 P, vec2 dx, vec2 dy, ivec2 o); -#endif /* textureProjGrad */ vec4 textureProjGrad( sampler1D sampler, vec2 P, float dPdx, float dPdy); @@ -938,7 +930,6 @@ uvec4 textureProjGrad(usampler3D sampler, vec4 P, vec3 dPdx, vec3 dPdy); float textureProjGrad(sampler1DShadow sampler, vec4 P, float dPdx, float dPdy); float textureProjGrad(sampler2DShadow sampler, vec4 P, vec2 dPdx, vec2 dPdy); -#if 0 /* textureProjGradOffset */ vec4 textureProjGradOffset( sampler1D s, vec2 P, float dx, float dy, int off); ivec4 textureProjGradOffset(isampler1D s, vec2 P, float dx, float dy, int off); @@ -960,7 +951,6 @@ uvec4 textureProjGradOffset(usampler3D s, vec4 P, vec3 dx, vec3 dy, ivec3 off); float textureProjGradOffset(sampler1DShadow s, vec4 P, float dx, float dy, int o); float textureProjGradOffset(sampler2DShadow s, vec4 P, vec2 dx, vec2 dy, vec2 o); -#endif /* * The following texture functions are deprecated: diff --git a/src/glsl/builtins/tools/generate_builtins.py b/src/glsl/builtins/tools/generate_builtins.py index 3a938a022da..edd3c70e00b 100755 --- a/src/glsl/builtins/tools/generate_builtins.py +++ b/src/glsl/builtins/tools/generate_builtins.py @@ -152,6 +152,8 @@ read_builtins(GLenum target, const char *protos, const char **functions, unsigne { struct gl_context fakeCtx; fakeCtx.API = API_OPENGL; + fakeCtx.Const.GLSLVersion = 130; + fakeCtx.Extensions.ARB_ES2_compatibility = true; gl_shader *sh = _mesa_new_shader(NULL, 0, target); struct _mesa_glsl_parse_state *st = new(sh) _mesa_glsl_parse_state(&fakeCtx, target, sh); @@ -178,7 +180,7 @@ read_builtins(GLenum target, const char *protos, const char **functions, unsigne if (st->error) { printf("error reading builtin: %.35s ...\\n", functions[i]); printf("Info log:\\n%s\\n", st->info_log); - talloc_free(sh); + ralloc_free(sh); return NULL; } } @@ -203,7 +205,7 @@ void *builtin_mem_ctx = NULL; void _mesa_glsl_release_functions(void) { - talloc_free(builtin_mem_ctx); + ralloc_free(builtin_mem_ctx); builtin_mem_ctx = NULL; memset(builtin_profiles, 0, sizeof(builtin_profiles)); } @@ -219,7 +221,7 @@ _mesa_read_profile(struct _mesa_glsl_parse_state *state, if (sh == NULL) { sh = read_builtins(GL_VERTEX_SHADER, prototypes, functions, count); - talloc_steal(builtin_mem_ctx, sh); + ralloc_steal(builtin_mem_ctx, sh); builtin_profiles[profile_index] = sh; } @@ -231,7 +233,7 @@ void _mesa_glsl_initialize_functions(struct _mesa_glsl_parse_state *state) { if (builtin_mem_ctx == NULL) { - builtin_mem_ctx = talloc_init("GLSL built-in functions"); + builtin_mem_ctx = ralloc_context(NULL); // "GLSL built-in functions" memset(&builtin_profiles, 0, sizeof(builtin_profiles)); } diff --git a/src/glsl/builtins/tools/texture_builtins.py b/src/glsl/builtins/tools/texture_builtins.py index 8bf708b5aac..8017e943b1b 100755 --- a/src/glsl/builtins/tools/texture_builtins.py +++ b/src/glsl/builtins/tools/texture_builtins.py @@ -3,6 +3,10 @@ import sys import StringIO +# Bitfield constants for the 'variant' argument to generate_sigs +Proj = 1 +Offset = 2 + def vec_type(g, size): if size == 1: if g == "i": @@ -12,16 +16,20 @@ def vec_type(g, size): return "float" return g + "vec" + str(size) -# Get the base dimension - i.e. sampler3D gives 3 -# Array samplers also get +1 here since the layer is really an extra coordinate -def get_coord_dim(sampler_type): +# Get the sampler dimension - i.e. sampler3D gives 3 +def get_sampler_dim(sampler_type): if sampler_type[0].isdigit(): - coord_dim = int(sampler_type[0]) + sampler_dim = int(sampler_type[0]) elif sampler_type.startswith("Cube"): - coord_dim = 3 + sampler_dim = 3 else: assert False ("coord_dim: invalid sampler_type: " + sampler_type) + return sampler_dim +# Get the coordinate dimension for a given sampler type. +# Array samplers also get +1 here since the layer is really an extra coordinate +def get_coord_dim(sampler_type): + coord_dim = get_sampler_dim(sampler_type) if sampler_type.find("Array") != -1: coord_dim += 1 return coord_dim @@ -35,18 +43,17 @@ def get_extra_dim(sampler_type, use_proj, unused_fields): extra_dim += 1 return extra_dim -def generate_sigs(g, tex_inst, sampler_type, use_proj = False, unused_fields = 0): +def generate_sigs(g, tex_inst, sampler_type, variant = 0, unused_fields = 0): coord_dim = get_coord_dim(sampler_type) - extra_dim = get_extra_dim(sampler_type, use_proj, unused_fields) + extra_dim = get_extra_dim(sampler_type, variant & Proj, unused_fields) + offset_dim = get_sampler_dim(sampler_type) # Print parameters print " (signature " + g + "vec4" print " (parameters" print " (declare (in) " + g + "sampler" + sampler_type + " sampler)" print " (declare (in) " + vec_type("i" if tex_inst == "txf" else "", coord_dim + extra_dim) + " P)", - if tex_inst == "txb": - print "\n (declare (in) float bias)", - elif tex_inst == "txl": + if tex_inst == "txl": print "\n (declare (in) float lod)", elif tex_inst == "txf": print "\n (declare (in) int lod)", @@ -55,6 +62,11 @@ def generate_sigs(g, tex_inst, sampler_type, use_proj = False, unused_fields = 0 print "\n (declare (in) " + grad_type + " dPdx)", print "\n (declare (in) " + grad_type + " dPdy)", + if variant & Offset: + print "\n (declare (const_in) " + vec_type("i", offset_dim) + " offset)", + if tex_inst == "txb": + print "\n (declare (in) float bias)", + print ")\n ((return (" + tex_inst + " (var_ref sampler)", # Coordinate @@ -63,12 +75,14 @@ def generate_sigs(g, tex_inst, sampler_type, use_proj = False, unused_fields = 0 else: print "(var_ref P)", - # Offset - print "(0 0 0)", + if variant & Offset: + print "(var_ref offset)", + else: + print "0", if tex_inst != "txf": # Projective divisor - if use_proj: + if variant & Proj: print "(swiz " + "xyzw"[coord_dim + extra_dim-1] + " (var_ref P))", else: print "1", @@ -90,10 +104,10 @@ def generate_sigs(g, tex_inst, sampler_type, use_proj = False, unused_fields = 0 print "((var_ref dPdx) (var_ref dPdy))", print "))))\n" -def generate_fiu_sigs(tex_inst, sampler_type, use_proj = False, unused_fields = 0): - generate_sigs("", tex_inst, sampler_type, use_proj, unused_fields) - generate_sigs("i", tex_inst, sampler_type, use_proj, unused_fields) - generate_sigs("u", tex_inst, sampler_type, use_proj, unused_fields) +def generate_fiu_sigs(tex_inst, sampler_type, variant = 0, unused_fields = 0): + generate_sigs("", tex_inst, sampler_type, variant, unused_fields) + generate_sigs("i", tex_inst, sampler_type, variant, unused_fields) + generate_sigs("u", tex_inst, sampler_type, variant, unused_fields) def start_function(name): sys.stdout = StringIO.StringIO() @@ -127,17 +141,17 @@ def generate_texture_functions(fs): end_function(fs, "texture") start_function("textureProj") - generate_fiu_sigs("tex", "1D", True) - generate_fiu_sigs("tex", "1D", True, 2) - generate_fiu_sigs("tex", "2D", True) - generate_fiu_sigs("tex", "2D", True, 1) - generate_fiu_sigs("tex", "3D", True) - - generate_fiu_sigs("txb", "1D", True) - generate_fiu_sigs("txb", "1D", True, 2) - generate_fiu_sigs("txb", "2D", True) - generate_fiu_sigs("txb", "2D", True, 1) - generate_fiu_sigs("txb", "3D", True) + generate_fiu_sigs("tex", "1D", Proj) + generate_fiu_sigs("tex", "1D", Proj, 2) + generate_fiu_sigs("tex", "2D", Proj) + generate_fiu_sigs("tex", "2D", Proj, 1) + generate_fiu_sigs("tex", "3D", Proj) + + generate_fiu_sigs("txb", "1D", Proj) + generate_fiu_sigs("txb", "1D", Proj, 2) + generate_fiu_sigs("txb", "2D", Proj) + generate_fiu_sigs("txb", "2D", Proj, 1) + generate_fiu_sigs("txb", "3D", Proj) end_function(fs, "textureProj") start_function("textureLod") @@ -149,6 +163,28 @@ def generate_texture_functions(fs): generate_fiu_sigs("txl", "2DArray") end_function(fs, "textureLod") + start_function("textureLodOffset") + generate_fiu_sigs("txl", "1D", Offset) + generate_fiu_sigs("txl", "2D", Offset) + generate_fiu_sigs("txl", "3D", Offset) + generate_fiu_sigs("txl", "1DArray", Offset) + generate_fiu_sigs("txl", "2DArray", Offset) + end_function(fs, "textureLodOffset") + + start_function("textureOffset") + generate_fiu_sigs("tex", "1D", Offset) + generate_fiu_sigs("tex", "2D", Offset) + generate_fiu_sigs("tex", "3D", Offset) + generate_fiu_sigs("tex", "1DArray", Offset) + generate_fiu_sigs("tex", "2DArray", Offset) + + generate_fiu_sigs("txb", "1D", Offset) + generate_fiu_sigs("txb", "2D", Offset) + generate_fiu_sigs("txb", "3D", Offset) + generate_fiu_sigs("txb", "1DArray", Offset) + generate_fiu_sigs("txb", "2DArray", Offset) + end_function(fs, "textureOffset") + start_function("texelFetch") generate_fiu_sigs("txf", "1D") generate_fiu_sigs("txf", "2D") @@ -157,14 +193,44 @@ def generate_texture_functions(fs): generate_fiu_sigs("txf", "2DArray") end_function(fs, "texelFetch") + start_function("texelFetchOffset") + generate_fiu_sigs("txf", "1D", Offset) + generate_fiu_sigs("txf", "2D", Offset) + generate_fiu_sigs("txf", "3D", Offset) + generate_fiu_sigs("txf", "1DArray", Offset) + generate_fiu_sigs("txf", "2DArray", Offset) + end_function(fs, "texelFetchOffset") + + start_function("textureProjOffset") + generate_fiu_sigs("tex", "1D", Proj | Offset) + generate_fiu_sigs("tex", "1D", Proj | Offset, 2) + generate_fiu_sigs("tex", "2D", Proj | Offset) + generate_fiu_sigs("tex", "2D", Proj | Offset, 1) + generate_fiu_sigs("tex", "3D", Proj | Offset) + + generate_fiu_sigs("txb", "1D", Proj | Offset) + generate_fiu_sigs("txb", "1D", Proj | Offset, 2) + generate_fiu_sigs("txb", "2D", Proj | Offset) + generate_fiu_sigs("txb", "2D", Proj | Offset, 1) + generate_fiu_sigs("txb", "3D", Proj | Offset) + end_function(fs, "textureProjOffset") + start_function("textureProjLod") - generate_fiu_sigs("txl", "1D", True) - generate_fiu_sigs("txl", "1D", True, 2) - generate_fiu_sigs("txl", "2D", True) - generate_fiu_sigs("txl", "2D", True, 1) - generate_fiu_sigs("txl", "3D", True) + generate_fiu_sigs("txl", "1D", Proj) + generate_fiu_sigs("txl", "1D", Proj, 2) + generate_fiu_sigs("txl", "2D", Proj) + generate_fiu_sigs("txl", "2D", Proj, 1) + generate_fiu_sigs("txl", "3D", Proj) end_function(fs, "textureProjLod") + start_function("textureProjLodOffset") + generate_fiu_sigs("txl", "1D", Proj | Offset) + generate_fiu_sigs("txl", "1D", Proj | Offset, 2) + generate_fiu_sigs("txl", "2D", Proj | Offset) + generate_fiu_sigs("txl", "2D", Proj | Offset, 1) + generate_fiu_sigs("txl", "3D", Proj | Offset) + end_function(fs, "textureProjLodOffset") + start_function("textureGrad") generate_fiu_sigs("txd", "1D") generate_fiu_sigs("txd", "2D") @@ -174,22 +240,40 @@ def generate_texture_functions(fs): generate_fiu_sigs("txd", "2DArray") end_function(fs, "textureGrad") + start_function("textureGradOffset") + generate_fiu_sigs("txd", "1D", Offset) + generate_fiu_sigs("txd", "2D", Offset) + generate_fiu_sigs("txd", "3D", Offset) + generate_fiu_sigs("txd", "Cube", Offset) + generate_fiu_sigs("txd", "1DArray", Offset) + generate_fiu_sigs("txd", "2DArray", Offset) + end_function(fs, "textureGradOffset") + start_function("textureProjGrad") - generate_fiu_sigs("txd", "1D", True) - generate_fiu_sigs("txd", "1D", True, 2) - generate_fiu_sigs("txd", "2D", True) - generate_fiu_sigs("txd", "2D", True, 1) - generate_fiu_sigs("txd", "3D", True) + generate_fiu_sigs("txd", "1D", Proj) + generate_fiu_sigs("txd", "1D", Proj, 2) + generate_fiu_sigs("txd", "2D", Proj) + generate_fiu_sigs("txd", "2D", Proj, 1) + generate_fiu_sigs("txd", "3D", Proj) end_function(fs, "textureProjGrad") + start_function("textureProjGradOffset") + generate_fiu_sigs("txd", "1D", Proj | Offset) + generate_fiu_sigs("txd", "1D", Proj | Offset, 2) + generate_fiu_sigs("txd", "2D", Proj | Offset) + generate_fiu_sigs("txd", "2D", Proj | Offset, 1) + generate_fiu_sigs("txd", "3D", Proj | Offset) + end_function(fs, "textureProjGradOffset") + + # ARB_texture_rectangle extension start_function("texture2DRect") generate_sigs("", "tex", "2DRect") end_function(fs, "texture2DRect") start_function("texture2DRectProj") - generate_sigs("", "tex", "2DRect", True) - generate_sigs("", "tex", "2DRect", True, 1) + generate_sigs("", "tex", "2DRect", Proj) + generate_sigs("", "tex", "2DRect", Proj, 1) end_function(fs, "texture2DRectProj") start_function("shadow2DRect") @@ -197,7 +281,7 @@ def generate_texture_functions(fs): end_function(fs, "shadow2DRect") start_function("shadow2DRectProj") - generate_sigs("", "tex", "2DRectShadow", True) + generate_sigs("", "tex", "2DRectShadow", Proj) end_function(fs, "shadow2DRectProj") # EXT_texture_array extension @@ -243,15 +327,15 @@ def generate_texture_functions(fs): end_function(fs, "texture1DLod") start_function("texture1DProj") - generate_sigs("", "tex", "1D", True) - generate_sigs("", "tex", "1D", True, 2) - generate_sigs("", "txb", "1D", True) - generate_sigs("", "txb", "1D", True, 2) + generate_sigs("", "tex", "1D", Proj) + generate_sigs("", "tex", "1D", Proj, 2) + generate_sigs("", "txb", "1D", Proj) + generate_sigs("", "txb", "1D", Proj, 2) end_function(fs, "texture1DProj") start_function("texture1DProjLod") - generate_sigs("", "txl", "1D", True) - generate_sigs("", "txl", "1D", True, 2) + generate_sigs("", "txl", "1D", Proj) + generate_sigs("", "txl", "1D", Proj, 2) end_function(fs, "texture1DProjLod") start_function("texture2D") @@ -264,15 +348,15 @@ def generate_texture_functions(fs): end_function(fs, "texture2DLod") start_function("texture2DProj") - generate_sigs("", "tex", "2D", True) - generate_sigs("", "tex", "2D", True, 1) - generate_sigs("", "txb", "2D", True) - generate_sigs("", "txb", "2D", True, 1) + generate_sigs("", "tex", "2D", Proj) + generate_sigs("", "tex", "2D", Proj, 1) + generate_sigs("", "txb", "2D", Proj) + generate_sigs("", "txb", "2D", Proj, 1) end_function(fs, "texture2DProj") start_function("texture2DProjLod") - generate_sigs("", "txl", "2D", True) - generate_sigs("", "txl", "2D", True, 1) + generate_sigs("", "txl", "2D", Proj) + generate_sigs("", "txl", "2D", Proj, 1) end_function(fs, "texture2DProjLod") start_function("texture3D") @@ -285,12 +369,12 @@ def generate_texture_functions(fs): end_function(fs, "texture3DLod") start_function("texture3DProj") - generate_sigs("", "tex", "3D", True) - generate_sigs("", "txb", "3D", True) + generate_sigs("", "tex", "3D", Proj) + generate_sigs("", "txb", "3D", Proj) end_function(fs, "texture3DProj") start_function("texture3DProjLod") - generate_sigs("", "txl", "3D", True) + generate_sigs("", "txl", "3D", Proj) end_function(fs, "texture3DProjLod") start_function("textureCube") @@ -312,12 +396,12 @@ def generate_texture_functions(fs): end_function(fs, "shadow1DLod") start_function("shadow1DProj") - generate_sigs("", "tex", "1DShadow", True, 1) - generate_sigs("", "txb", "1DShadow", True, 1) + generate_sigs("", "tex", "1DShadow", Proj, 1) + generate_sigs("", "txb", "1DShadow", Proj, 1) end_function(fs, "shadow1DProj") start_function("shadow1DProjLod") - generate_sigs("", "txl", "1DShadow", True, 1) + generate_sigs("", "txl", "1DShadow", Proj, 1) end_function(fs, "shadow1DProjLod") start_function("shadow2D") @@ -330,12 +414,12 @@ def generate_texture_functions(fs): end_function(fs, "shadow2DLod") start_function("shadow2DProj") - generate_sigs("", "tex", "2DShadow", True) - generate_sigs("", "txb", "2DShadow", True) + generate_sigs("", "tex", "2DShadow", Proj) + generate_sigs("", "txb", "2DShadow", Proj) end_function(fs, "shadow2DProj") start_function("shadow2DProjLod") - generate_sigs("", "txl", "2DShadow", True) + generate_sigs("", "txl", "2DShadow", Proj) end_function(fs, "shadow2DProjLod") sys.stdout = sys.__stdout__ @@ -346,4 +430,4 @@ if __name__ == "__main__": fs = {} generate_texture_functions(fs); for k, v in fs.iteritems(): - print v + print v diff --git a/src/glsl/configure.ac b/src/glsl/configure.ac deleted file mode 100644 index 73ce67de3d1..00000000000 --- a/src/glsl/configure.ac +++ /dev/null @@ -1,69 +0,0 @@ -# -*- Autoconf -*- -# Process this file with autoconf to produce a configure script. - -AC_PREREQ(2.61) -AC_INIT(glsl, XXXXX, [email protected], glsl) -AC_CONFIG_SRCDIR([Makefile.am]) -AM_CONFIG_HEADER([config.h]) -AC_CONFIG_FILES([glcpp/Makefile]) - -AM_INIT_AUTOMAKE -LT_INIT - -AM_MAINTAINER_MODE - -# Checks for programs. -AC_PROG_CXX -AC_PROG_CC -AC_PROG_MAKE_SET -AC_PROG_YACC -AC_PROG_LEX - -m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) - -# Checks for libraries. - -# Checks for header files. - -# Checks for typedefs, structures, and compiler characteristics. - -# Checks for library functions. -AC_HEADER_STDC - -AH_TOP([#ifndef GLSL_CONFIG_H -#define GLSL_CONFIG_H]) -AH_BOTTOM([#endif /* GLSL_CONFIG_H */]) - -PKG_CHECK_MODULES([talloc], [talloc >= 2.0]) - -AC_ARG_ENABLE([debug], - [AS_HELP_STRING([--enable-debug], - [use debug compiler flags and macros @<:@default=disabled@:>@])], - [enable_debug="$enableval"], - [enable_debug=no] -) -if test "x$enable_debug" = xyes; then - DEFINES="$DEFINES -DDEBUG" - if test "x$GCC" = xyes; then - # Remove any -g or -O flags from the command line - CFLAGS=[`echo $CFLAGS | sed 's/-g[^ \t]*[ \t]*//g;s/-O[^ \t]*[ \t]*//g'`] - CFLAGS="$CFLAGS -O0 -ggdb3 -fstack-protector -D_FORTIFY_SOURCE=2" - fi - if test "x$GXX" = xyes; then - # Remove any -g flags from the command line - CXXFLAGS=[`echo $CXXFLAGS | sed 's/-g[^ \t]*[ \t]*//g;s/-O[^ \t]*[ \t]*//g'`] - CXXFLAGS="$CXXFLAGS -O0 -ggdb3 -fstack-protector -D_FORTIFY_SOURCE=2" - fi -fi - -if test "x$GXX" = xyes ; then - WARN="-Wall -Wextra -Wunsafe-loop-optimizations -Wstack-protector" -else - WARN="" -fi - -CFLAGS="$CFLAGS $WARN" -CXXFLAGS="$CXXFLAGS $WARN" -YFLAGS="-d -v" - -AC_OUTPUT([Makefile]) diff --git a/src/glsl/glcpp/glcpp-lex.c b/src/glsl/glcpp/glcpp-lex.c index 156af3008c0..b53bea6271d 100644 --- a/src/glsl/glcpp/glcpp-lex.c +++ b/src/glsl/glcpp/glcpp-lex.c @@ -795,6 +795,10 @@ int glcpp_get_lineno (yyscan_t yyscanner ); void glcpp_set_lineno (int line_number ,yyscan_t yyscanner ); +int glcpp_get_column (yyscan_t yyscanner ); + +void glcpp_set_column (int column_no ,yyscan_t yyscanner ); + YYSTYPE * glcpp_get_lval (yyscan_t yyscanner ); void glcpp_set_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner ); @@ -954,7 +958,7 @@ YY_DECL /* Single-line comments */ -#line 958 "glcpp/glcpp-lex.c" +#line 962 "glcpp/glcpp-lex.c" yylval = yylval_param; @@ -1121,7 +1125,7 @@ case 8: YY_RULE_SETUP #line 94 "glcpp/glcpp-lex.l" { - yylval->str = talloc_strdup (yyextra, yytext); + yylval->str = ralloc_strdup (yyextra, yytext); yyextra->space_tokens = 0; return HASH_VERSION; } @@ -1132,7 +1136,7 @@ case 9: YY_RULE_SETUP #line 102 "glcpp/glcpp-lex.l" { - yylval->str = talloc_strdup (yyextra, yytext); + yylval->str = ralloc_strdup (yyextra, yytext); yylineno++; yycolumn = 0; return OTHER; @@ -1312,7 +1316,7 @@ case 24: YY_RULE_SETUP #line 221 "glcpp/glcpp-lex.l" { - yylval->str = talloc_strdup (yyextra, yytext); + yylval->str = ralloc_strdup (yyextra, yytext); return INTEGER_STRING; } YY_BREAK @@ -1320,7 +1324,7 @@ case 25: YY_RULE_SETUP #line 226 "glcpp/glcpp-lex.l" { - yylval->str = talloc_strdup (yyextra, yytext); + yylval->str = ralloc_strdup (yyextra, yytext); return INTEGER_STRING; } YY_BREAK @@ -1328,7 +1332,7 @@ case 26: YY_RULE_SETUP #line 231 "glcpp/glcpp-lex.l" { - yylval->str = talloc_strdup (yyextra, yytext); + yylval->str = ralloc_strdup (yyextra, yytext); return INTEGER_STRING; } YY_BREAK @@ -1406,7 +1410,7 @@ case 37: YY_RULE_SETUP #line 276 "glcpp/glcpp-lex.l" { - yylval->str = talloc_strdup (yyextra, yytext); + yylval->str = ralloc_strdup (yyextra, yytext); return IDENTIFIER; } YY_BREAK @@ -1421,7 +1425,7 @@ case 39: YY_RULE_SETUP #line 285 "glcpp/glcpp-lex.l" { - yylval->str = talloc_strdup (yyextra, yytext); + yylval->str = ralloc_strdup (yyextra, yytext); return OTHER; } YY_BREAK @@ -1471,7 +1475,7 @@ YY_RULE_SETUP #line 319 "glcpp/glcpp-lex.l" ECHO; YY_BREAK -#line 1475 "glcpp/glcpp-lex.c" +#line 1479 "glcpp/glcpp-lex.c" case YY_STATE_EOF(DONE): case YY_STATE_EOF(COMMENT): case YY_STATE_EOF(UNREACHABLE): diff --git a/src/glsl/glcpp/glcpp-lex.l b/src/glsl/glcpp/glcpp-lex.l index e936854cf2c..11b73aea88b 100644 --- a/src/glsl/glcpp/glcpp-lex.l +++ b/src/glsl/glcpp/glcpp-lex.l @@ -92,7 +92,7 @@ HEXADECIMAL_INTEGER 0[xX][0-9a-fA-F]+[uU]? } {HASH}version { - yylval->str = talloc_strdup (yyextra, yytext); + yylval->str = ralloc_strdup (yyextra, yytext); yyextra->space_tokens = 0; return HASH_VERSION; } @@ -100,7 +100,7 @@ HEXADECIMAL_INTEGER 0[xX][0-9a-fA-F]+[uU]? /* glcpp doesn't handle #extension, #version, or #pragma directives. * Simply pass them through to the main compiler's lexer/parser. */ {HASH}(extension|pragma)[^\n]+ { - yylval->str = talloc_strdup (yyextra, yytext); + yylval->str = ralloc_strdup (yyextra, yytext); yylineno++; yycolumn = 0; return OTHER; @@ -219,17 +219,17 @@ HEXADECIMAL_INTEGER 0[xX][0-9a-fA-F]+[uU]? } {DECIMAL_INTEGER} { - yylval->str = talloc_strdup (yyextra, yytext); + yylval->str = ralloc_strdup (yyextra, yytext); return INTEGER_STRING; } {OCTAL_INTEGER} { - yylval->str = talloc_strdup (yyextra, yytext); + yylval->str = ralloc_strdup (yyextra, yytext); return INTEGER_STRING; } {HEXADECIMAL_INTEGER} { - yylval->str = talloc_strdup (yyextra, yytext); + yylval->str = ralloc_strdup (yyextra, yytext); return INTEGER_STRING; } @@ -274,7 +274,7 @@ HEXADECIMAL_INTEGER 0[xX][0-9a-fA-F]+[uU]? } {IDENTIFIER} { - yylval->str = talloc_strdup (yyextra, yytext); + yylval->str = ralloc_strdup (yyextra, yytext); return IDENTIFIER; } @@ -283,7 +283,7 @@ HEXADECIMAL_INTEGER 0[xX][0-9a-fA-F]+[uU]? } {OTHER}+ { - yylval->str = talloc_strdup (yyextra, yytext); + yylval->str = ralloc_strdup (yyextra, yytext); return OTHER; } diff --git a/src/glsl/glcpp/glcpp-parse.c b/src/glsl/glcpp/glcpp-parse.c index a5566dc0aaf..1e71b18c4cb 100644 --- a/src/glsl/glcpp/glcpp-parse.c +++ b/src/glsl/glcpp/glcpp-parse.c @@ -1,10 +1,9 @@ - -/* A Bison parser, made by GNU Bison 2.4.1. */ +/* A Bison parser, made by GNU Bison 2.4.3. */ /* Skeleton implementation for Bison's Yacc-like parsers in C - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 - Free Software Foundation, Inc. + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006, + 2009, 2010 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -46,7 +45,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "2.4.1" +#define YYBISON_VERSION "2.4.3" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -103,10 +102,6 @@ #include "main/core.h" /* for struct gl_extensions */ #include "main/mtypes.h" /* for gl_api enum */ -#define glcpp_print(stream, str) stream = talloc_strdup_append(stream, str) -#define glcpp_printf(stream, fmt, args, ...) \ - stream = talloc_asprintf_append(stream, fmt, args) - static void yyerror (YYLTYPE *locp, glcpp_parser_t *parser, const char *error); @@ -150,7 +145,7 @@ _argument_list_length (argument_list_t *list); static token_list_t * _argument_list_member_at (argument_list_t *list, int index); -/* Note: This function talloc_steal()s the str pointer. */ +/* Note: This function ralloc_steal()s the str pointer. */ static token_t * _token_create_str (void *ctx, int type, char *str); @@ -160,10 +155,7 @@ _token_create_ival (void *ctx, int type, int ival); static token_list_t * _token_list_create (void *ctx); -/* Note: This function adds a talloc_reference() to token. - * - * You may want to talloc_unlink any current reference if you no - * longer need it. */ +/* Note: This function calls ralloc_steal on token. */ static void _token_list_append (token_list_t *list, token_t *token); @@ -220,7 +212,7 @@ add_builtin_define(glcpp_parser_t *parser, const char *name, int value); /* Line 189 of yacc.c */ -#line 224 "glcpp/glcpp-parse.c" +#line 216 "glcpp/glcpp-parse.c" /* Enabling traces. */ #ifndef YYDEBUG @@ -308,7 +300,7 @@ typedef struct YYLTYPE /* Line 264 of yacc.c */ -#line 312 "glcpp/glcpp-parse.c" +#line 304 "glcpp/glcpp-parse.c" #ifdef short # undef short @@ -358,7 +350,7 @@ typedef short int yytype_int16; #define YYSIZE_MAXIMUM ((YYSIZE_T) -1) #ifndef YY_ -# if YYENABLE_NLS +# if defined YYENABLE_NLS && YYENABLE_NLS # if ENABLE_NLS # include <libintl.h> /* INFRINGES ON USER NAME SPACE */ # define YY_(msgid) dgettext ("bison-runtime", msgid) @@ -633,17 +625,17 @@ static const yytype_int8 yyrhs[] = /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 188, 188, 190, 194, 197, 202, 203, 207, 210, - 216, 219, 222, 225, 233, 252, 262, 267, 272, 291, - 306, 309, 312, 333, 337, 346, 351, 352, 355, 358, - 361, 364, 367, 370, 373, 376, 379, 382, 385, 388, - 391, 394, 397, 400, 408, 411, 414, 417, 420, 423, - 429, 434, 442, 443, 447, 453, 454, 457, 459, 466, - 470, 474, 479, 484, 492, 498, 506, 510, 514, 518, - 522, 529, 530, 531, 532, 533, 534, 535, 536, 537, - 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, - 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, - 558, 559 + 0, 181, 181, 183, 187, 190, 195, 196, 200, 203, + 209, 212, 215, 218, 226, 245, 255, 260, 265, 284, + 299, 302, 305, 326, 330, 339, 344, 345, 348, 351, + 354, 357, 360, 363, 366, 369, 372, 375, 378, 381, + 384, 387, 390, 398, 406, 409, 412, 415, 418, 421, + 427, 432, 440, 441, 445, 451, 452, 455, 457, 464, + 468, 472, 477, 481, 488, 493, 500, 504, 508, 512, + 516, 523, 524, 525, 526, 527, 528, 529, 530, 531, + 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, + 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, + 552, 553 }; #endif @@ -946,9 +938,18 @@ static const yytype_uint8 yystos[] = /* Like YYERROR except do call yyerror. This remains here temporarily to ease the transition to the new meaning of YYERROR, for GCC. - Once GCC version 2 has supplanted version 1, this can go. */ + Once GCC version 2 has supplanted version 1, this can go. However, + YYFAIL appears to be in use. Nevertheless, it is formally deprecated + in Bison 2.4.2's NEWS entry, where a plan to phase it out is + discussed. */ #define YYFAIL goto yyerrlab +#if defined YYFAIL + /* This is here to suppress warnings from the GCC cpp's + -Wunused-macros. Normally we don't worry about that warning, but + some users do, and we want to make it easy for users to remove + YYFAIL uses, which will produce warnings from Bison 2.5. */ +#endif #define YYRECOVERING() (!!yyerrstatus) @@ -1005,7 +1006,7 @@ while (YYID (0)) we won't break user code: when these are the locations we know. */ #ifndef YY_LOCATION_PRINT -# if YYLTYPE_IS_TRIVIAL +# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL # define YY_LOCATION_PRINT(File, Loc) \ fprintf (File, "%d.%d-%d.%d", \ (Loc).first_line, (Loc).first_column, \ @@ -1547,7 +1548,7 @@ YYLTYPE yylloc; YYLTYPE *yylsp; /* The locations where the error started and ended. */ - YYLTYPE yyerror_range[2]; + YYLTYPE yyerror_range[3]; YYSIZE_T yystacksize; @@ -1594,7 +1595,7 @@ YYLTYPE yylloc; yyvsp = yyvs; yylsp = yyls; -#if YYLTYPE_IS_TRIVIAL +#if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL /* Initialize the default location before parsing starts. */ yylloc.first_line = yylloc.last_line = 1; yylloc.first_column = yylloc.last_column = 1; @@ -1602,8 +1603,8 @@ YYLTYPE yylloc; /* User initialization code. */ -/* Line 1242 of yacc.c */ -#line 155 "glcpp/glcpp-parse.y" +/* Line 1251 of yacc.c */ +#line 148 "glcpp/glcpp-parse.y" { yylloc.first_line = 1; yylloc.first_column = 1; @@ -1612,8 +1613,8 @@ YYLTYPE yylloc; yylloc.source = 0; } -/* Line 1242 of yacc.c */ -#line 1617 "glcpp/glcpp-parse.c" +/* Line 1251 of yacc.c */ +#line 1618 "glcpp/glcpp-parse.c" yylsp[0] = yylloc; goto yysetstate; @@ -1800,28 +1801,28 @@ yyreduce: { case 4: -/* Line 1455 of yacc.c */ -#line 194 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 187 "glcpp/glcpp-parse.y" { - glcpp_print(parser->output, "\n"); + ralloc_strcat (&parser->output, "\n"); ;} break; case 5: -/* Line 1455 of yacc.c */ -#line 197 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 190 "glcpp/glcpp-parse.y" { _glcpp_parser_print_expanded_token_list (parser, (yyvsp[(1) - (1)].token_list)); - glcpp_print(parser->output, "\n"); - talloc_free ((yyvsp[(1) - (1)].token_list)); + ralloc_strcat (&parser->output, "\n"); + ralloc_free ((yyvsp[(1) - (1)].token_list)); ;} break; case 8: -/* Line 1455 of yacc.c */ -#line 207 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 200 "glcpp/glcpp-parse.y" { _glcpp_parser_skip_stack_push_if (parser, & (yylsp[(1) - (3)]), (yyvsp[(2) - (3)].ival)); ;} @@ -1829,8 +1830,8 @@ yyreduce: case 9: -/* Line 1455 of yacc.c */ -#line 210 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 203 "glcpp/glcpp-parse.y" { _glcpp_parser_skip_stack_change_if (parser, & (yylsp[(1) - (3)]), "elif", (yyvsp[(2) - (3)].ival)); ;} @@ -1838,8 +1839,8 @@ yyreduce: case 10: -/* Line 1455 of yacc.c */ -#line 216 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 209 "glcpp/glcpp-parse.y" { _define_object_macro (parser, & (yylsp[(2) - (4)]), (yyvsp[(2) - (4)].str), (yyvsp[(3) - (4)].token_list)); ;} @@ -1847,8 +1848,8 @@ yyreduce: case 11: -/* Line 1455 of yacc.c */ -#line 219 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 212 "glcpp/glcpp-parse.y" { _define_function_macro (parser, & (yylsp[(2) - (6)]), (yyvsp[(2) - (6)].str), NULL, (yyvsp[(5) - (6)].token_list)); ;} @@ -1856,8 +1857,8 @@ yyreduce: case 12: -/* Line 1455 of yacc.c */ -#line 222 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 215 "glcpp/glcpp-parse.y" { _define_function_macro (parser, & (yylsp[(2) - (7)]), (yyvsp[(2) - (7)].str), (yyvsp[(4) - (7)].string_list), (yyvsp[(6) - (7)].token_list)); ;} @@ -1865,22 +1866,22 @@ yyreduce: case 13: -/* Line 1455 of yacc.c */ -#line 225 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 218 "glcpp/glcpp-parse.y" { macro_t *macro = hash_table_find (parser->defines, (yyvsp[(2) - (3)].str)); if (macro) { hash_table_remove (parser->defines, (yyvsp[(2) - (3)].str)); - talloc_free (macro); + ralloc_free (macro); } - talloc_free ((yyvsp[(2) - (3)].str)); + ralloc_free ((yyvsp[(2) - (3)].str)); ;} break; case 14: -/* Line 1455 of yacc.c */ -#line 233 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 226 "glcpp/glcpp-parse.y" { /* Be careful to only evaluate the 'if' expression if * we are not skipping. When we are skipping, we @@ -1904,8 +1905,8 @@ yyreduce: case 15: -/* Line 1455 of yacc.c */ -#line 252 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 245 "glcpp/glcpp-parse.y" { /* #if without an expression is only an error if we * are not skipping */ @@ -1920,30 +1921,30 @@ yyreduce: case 16: -/* Line 1455 of yacc.c */ -#line 262 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 255 "glcpp/glcpp-parse.y" { macro_t *macro = hash_table_find (parser->defines, (yyvsp[(2) - (4)].str)); - talloc_free ((yyvsp[(2) - (4)].str)); + ralloc_free ((yyvsp[(2) - (4)].str)); _glcpp_parser_skip_stack_push_if (parser, & (yylsp[(1) - (4)]), macro != NULL); ;} break; case 17: -/* Line 1455 of yacc.c */ -#line 267 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 260 "glcpp/glcpp-parse.y" { macro_t *macro = hash_table_find (parser->defines, (yyvsp[(2) - (4)].str)); - talloc_free ((yyvsp[(2) - (4)].str)); + ralloc_free ((yyvsp[(2) - (4)].str)); _glcpp_parser_skip_stack_push_if (parser, & (yylsp[(1) - (4)]), macro == NULL); ;} break; case 18: -/* Line 1455 of yacc.c */ -#line 272 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 265 "glcpp/glcpp-parse.y" { /* Be careful to only evaluate the 'elif' expression * if we are not skipping. When we are skipping, we @@ -1967,8 +1968,8 @@ yyreduce: case 19: -/* Line 1455 of yacc.c */ -#line 291 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 284 "glcpp/glcpp-parse.y" { /* #elif without an expression is an error unless we * are skipping. */ @@ -1988,8 +1989,8 @@ yyreduce: case 20: -/* Line 1455 of yacc.c */ -#line 306 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 299 "glcpp/glcpp-parse.y" { _glcpp_parser_skip_stack_change_if (parser, & (yylsp[(1) - (2)]), "else", 1); ;} @@ -1997,8 +1998,8 @@ yyreduce: case 21: -/* Line 1455 of yacc.c */ -#line 309 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 302 "glcpp/glcpp-parse.y" { _glcpp_parser_skip_stack_pop (parser, & (yylsp[(1) - (2)])); ;} @@ -2006,13 +2007,13 @@ yyreduce: case 22: -/* Line 1455 of yacc.c */ -#line 312 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 305 "glcpp/glcpp-parse.y" { macro_t *macro = hash_table_find (parser->defines, "__VERSION__"); if (macro) { hash_table_remove (parser->defines, "__VERSION__"); - talloc_free (macro); + ralloc_free (macro); } add_builtin_define (parser, "__VERSION__", (yyvsp[(2) - (3)].ival)); @@ -2027,14 +2028,14 @@ yyreduce: if ((yyvsp[(2) - (3)].ival) >= 130 || (yyvsp[(2) - (3)].ival) == 100) add_builtin_define (parser, "GL_FRAGMENT_PRECISION_HIGH", 1); - glcpp_printf(parser->output, "#version %" PRIiMAX, (yyvsp[(2) - (3)].ival)); + ralloc_asprintf_append (&parser->output, "#version %" PRIiMAX, (yyvsp[(2) - (3)].ival)); ;} break; case 24: -/* Line 1455 of yacc.c */ -#line 337 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 330 "glcpp/glcpp-parse.y" { if (strlen ((yyvsp[(1) - (1)].str)) >= 3 && strncmp ((yyvsp[(1) - (1)].str), "0x", 2) == 0) { (yyval.ival) = strtoll ((yyvsp[(1) - (1)].str) + 2, NULL, 16); @@ -2048,8 +2049,8 @@ yyreduce: case 25: -/* Line 1455 of yacc.c */ -#line 346 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 339 "glcpp/glcpp-parse.y" { (yyval.ival) = (yyvsp[(1) - (1)].ival); ;} @@ -2057,8 +2058,8 @@ yyreduce: case 27: -/* Line 1455 of yacc.c */ -#line 352 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 345 "glcpp/glcpp-parse.y" { (yyval.ival) = (yyvsp[(1) - (3)].ival) || (yyvsp[(3) - (3)].ival); ;} @@ -2066,8 +2067,8 @@ yyreduce: case 28: -/* Line 1455 of yacc.c */ -#line 355 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 348 "glcpp/glcpp-parse.y" { (yyval.ival) = (yyvsp[(1) - (3)].ival) && (yyvsp[(3) - (3)].ival); ;} @@ -2075,8 +2076,8 @@ yyreduce: case 29: -/* Line 1455 of yacc.c */ -#line 358 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 351 "glcpp/glcpp-parse.y" { (yyval.ival) = (yyvsp[(1) - (3)].ival) | (yyvsp[(3) - (3)].ival); ;} @@ -2084,8 +2085,8 @@ yyreduce: case 30: -/* Line 1455 of yacc.c */ -#line 361 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 354 "glcpp/glcpp-parse.y" { (yyval.ival) = (yyvsp[(1) - (3)].ival) ^ (yyvsp[(3) - (3)].ival); ;} @@ -2093,8 +2094,8 @@ yyreduce: case 31: -/* Line 1455 of yacc.c */ -#line 364 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 357 "glcpp/glcpp-parse.y" { (yyval.ival) = (yyvsp[(1) - (3)].ival) & (yyvsp[(3) - (3)].ival); ;} @@ -2102,8 +2103,8 @@ yyreduce: case 32: -/* Line 1455 of yacc.c */ -#line 367 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 360 "glcpp/glcpp-parse.y" { (yyval.ival) = (yyvsp[(1) - (3)].ival) != (yyvsp[(3) - (3)].ival); ;} @@ -2111,8 +2112,8 @@ yyreduce: case 33: -/* Line 1455 of yacc.c */ -#line 370 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 363 "glcpp/glcpp-parse.y" { (yyval.ival) = (yyvsp[(1) - (3)].ival) == (yyvsp[(3) - (3)].ival); ;} @@ -2120,8 +2121,8 @@ yyreduce: case 34: -/* Line 1455 of yacc.c */ -#line 373 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 366 "glcpp/glcpp-parse.y" { (yyval.ival) = (yyvsp[(1) - (3)].ival) >= (yyvsp[(3) - (3)].ival); ;} @@ -2129,8 +2130,8 @@ yyreduce: case 35: -/* Line 1455 of yacc.c */ -#line 376 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 369 "glcpp/glcpp-parse.y" { (yyval.ival) = (yyvsp[(1) - (3)].ival) <= (yyvsp[(3) - (3)].ival); ;} @@ -2138,8 +2139,8 @@ yyreduce: case 36: -/* Line 1455 of yacc.c */ -#line 379 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 372 "glcpp/glcpp-parse.y" { (yyval.ival) = (yyvsp[(1) - (3)].ival) > (yyvsp[(3) - (3)].ival); ;} @@ -2147,8 +2148,8 @@ yyreduce: case 37: -/* Line 1455 of yacc.c */ -#line 382 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 375 "glcpp/glcpp-parse.y" { (yyval.ival) = (yyvsp[(1) - (3)].ival) < (yyvsp[(3) - (3)].ival); ;} @@ -2156,8 +2157,8 @@ yyreduce: case 38: -/* Line 1455 of yacc.c */ -#line 385 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 378 "glcpp/glcpp-parse.y" { (yyval.ival) = (yyvsp[(1) - (3)].ival) >> (yyvsp[(3) - (3)].ival); ;} @@ -2165,8 +2166,8 @@ yyreduce: case 39: -/* Line 1455 of yacc.c */ -#line 388 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 381 "glcpp/glcpp-parse.y" { (yyval.ival) = (yyvsp[(1) - (3)].ival) << (yyvsp[(3) - (3)].ival); ;} @@ -2174,8 +2175,8 @@ yyreduce: case 40: -/* Line 1455 of yacc.c */ -#line 391 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 384 "glcpp/glcpp-parse.y" { (yyval.ival) = (yyvsp[(1) - (3)].ival) - (yyvsp[(3) - (3)].ival); ;} @@ -2183,8 +2184,8 @@ yyreduce: case 41: -/* Line 1455 of yacc.c */ -#line 394 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 387 "glcpp/glcpp-parse.y" { (yyval.ival) = (yyvsp[(1) - (3)].ival) + (yyvsp[(3) - (3)].ival); ;} @@ -2192,17 +2193,22 @@ yyreduce: case 42: -/* Line 1455 of yacc.c */ -#line 397 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 390 "glcpp/glcpp-parse.y" { - (yyval.ival) = (yyvsp[(1) - (3)].ival) % (yyvsp[(3) - (3)].ival); + if ((yyvsp[(3) - (3)].ival) == 0) { + yyerror (& (yylsp[(1) - (3)]), parser, + "zero modulus in preprocessor directive"); + } else { + (yyval.ival) = (yyvsp[(1) - (3)].ival) % (yyvsp[(3) - (3)].ival); + } ;} break; case 43: -/* Line 1455 of yacc.c */ -#line 400 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 398 "glcpp/glcpp-parse.y" { if ((yyvsp[(3) - (3)].ival) == 0) { yyerror (& (yylsp[(1) - (3)]), parser, @@ -2215,8 +2221,8 @@ yyreduce: case 44: -/* Line 1455 of yacc.c */ -#line 408 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 406 "glcpp/glcpp-parse.y" { (yyval.ival) = (yyvsp[(1) - (3)].ival) * (yyvsp[(3) - (3)].ival); ;} @@ -2224,8 +2230,8 @@ yyreduce: case 45: -/* Line 1455 of yacc.c */ -#line 411 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 409 "glcpp/glcpp-parse.y" { (yyval.ival) = ! (yyvsp[(2) - (2)].ival); ;} @@ -2233,8 +2239,8 @@ yyreduce: case 46: -/* Line 1455 of yacc.c */ -#line 414 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 412 "glcpp/glcpp-parse.y" { (yyval.ival) = ~ (yyvsp[(2) - (2)].ival); ;} @@ -2242,8 +2248,8 @@ yyreduce: case 47: -/* Line 1455 of yacc.c */ -#line 417 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 415 "glcpp/glcpp-parse.y" { (yyval.ival) = - (yyvsp[(2) - (2)].ival); ;} @@ -2251,8 +2257,8 @@ yyreduce: case 48: -/* Line 1455 of yacc.c */ -#line 420 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 418 "glcpp/glcpp-parse.y" { (yyval.ival) = + (yyvsp[(2) - (2)].ival); ;} @@ -2260,8 +2266,8 @@ yyreduce: case 49: -/* Line 1455 of yacc.c */ -#line 423 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 421 "glcpp/glcpp-parse.y" { (yyval.ival) = (yyvsp[(2) - (3)].ival); ;} @@ -2269,37 +2275,37 @@ yyreduce: case 50: -/* Line 1455 of yacc.c */ -#line 429 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 427 "glcpp/glcpp-parse.y" { (yyval.string_list) = _string_list_create (parser); _string_list_append_item ((yyval.string_list), (yyvsp[(1) - (1)].str)); - talloc_steal ((yyval.string_list), (yyvsp[(1) - (1)].str)); + ralloc_steal ((yyval.string_list), (yyvsp[(1) - (1)].str)); ;} break; case 51: -/* Line 1455 of yacc.c */ -#line 434 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 432 "glcpp/glcpp-parse.y" { (yyval.string_list) = (yyvsp[(1) - (3)].string_list); _string_list_append_item ((yyval.string_list), (yyvsp[(3) - (3)].str)); - talloc_steal ((yyval.string_list), (yyvsp[(3) - (3)].str)); + ralloc_steal ((yyval.string_list), (yyvsp[(3) - (3)].str)); ;} break; case 52: -/* Line 1455 of yacc.c */ -#line 442 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 440 "glcpp/glcpp-parse.y" { (yyval.token_list) = NULL; ;} break; case 54: -/* Line 1455 of yacc.c */ -#line 447 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 445 "glcpp/glcpp-parse.y" { yyerror (& (yylsp[(1) - (2)]), parser, "Invalid tokens after #"); ;} @@ -2307,15 +2313,15 @@ yyreduce: case 55: -/* Line 1455 of yacc.c */ -#line 453 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 451 "glcpp/glcpp-parse.y" { (yyval.token_list) = NULL; ;} break; case 58: -/* Line 1455 of yacc.c */ -#line 459 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 457 "glcpp/glcpp-parse.y" { glcpp_warning(&(yylsp[(1) - (1)]), parser, "extra tokens at end of directive"); ;} @@ -2323,8 +2329,8 @@ yyreduce: case 59: -/* Line 1455 of yacc.c */ -#line 466 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 464 "glcpp/glcpp-parse.y" { int v = hash_table_find (parser->defines, (yyvsp[(2) - (2)].str)) ? 1 : 0; (yyval.token) = _token_create_ival (parser, INTEGER, v); @@ -2333,8 +2339,8 @@ yyreduce: case 60: -/* Line 1455 of yacc.c */ -#line 470 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 468 "glcpp/glcpp-parse.y" { int v = hash_table_find (parser->defines, (yyvsp[(3) - (4)].str)) ? 1 : 0; (yyval.token) = _token_create_ival (parser, INTEGER, v); @@ -2343,53 +2349,49 @@ yyreduce: case 62: -/* Line 1455 of yacc.c */ -#line 479 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 477 "glcpp/glcpp-parse.y" { (yyval.token_list) = _token_list_create (parser); _token_list_append ((yyval.token_list), (yyvsp[(1) - (1)].token)); - talloc_unlink (parser, (yyvsp[(1) - (1)].token)); ;} break; case 63: -/* Line 1455 of yacc.c */ -#line 484 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 481 "glcpp/glcpp-parse.y" { (yyval.token_list) = (yyvsp[(1) - (2)].token_list); _token_list_append ((yyval.token_list), (yyvsp[(2) - (2)].token)); - talloc_unlink (parser, (yyvsp[(2) - (2)].token)); ;} break; case 64: -/* Line 1455 of yacc.c */ -#line 492 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 488 "glcpp/glcpp-parse.y" { parser->space_tokens = 1; (yyval.token_list) = _token_list_create (parser); _token_list_append ((yyval.token_list), (yyvsp[(1) - (1)].token)); - talloc_unlink (parser, (yyvsp[(1) - (1)].token)); ;} break; case 65: -/* Line 1455 of yacc.c */ -#line 498 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 493 "glcpp/glcpp-parse.y" { (yyval.token_list) = (yyvsp[(1) - (2)].token_list); _token_list_append ((yyval.token_list), (yyvsp[(2) - (2)].token)); - talloc_unlink (parser, (yyvsp[(2) - (2)].token)); ;} break; case 66: -/* Line 1455 of yacc.c */ -#line 506 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 500 "glcpp/glcpp-parse.y" { (yyval.token) = _token_create_str (parser, IDENTIFIER, (yyvsp[(1) - (1)].str)); (yyval.token)->location = yylloc; @@ -2398,8 +2400,8 @@ yyreduce: case 67: -/* Line 1455 of yacc.c */ -#line 510 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 504 "glcpp/glcpp-parse.y" { (yyval.token) = _token_create_str (parser, INTEGER_STRING, (yyvsp[(1) - (1)].str)); (yyval.token)->location = yylloc; @@ -2408,8 +2410,8 @@ yyreduce: case 68: -/* Line 1455 of yacc.c */ -#line 514 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 508 "glcpp/glcpp-parse.y" { (yyval.token) = _token_create_ival (parser, (yyvsp[(1) - (1)].ival), (yyvsp[(1) - (1)].ival)); (yyval.token)->location = yylloc; @@ -2418,8 +2420,8 @@ yyreduce: case 69: -/* Line 1455 of yacc.c */ -#line 518 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 512 "glcpp/glcpp-parse.y" { (yyval.token) = _token_create_str (parser, OTHER, (yyvsp[(1) - (1)].str)); (yyval.token)->location = yylloc; @@ -2428,8 +2430,8 @@ yyreduce: case 70: -/* Line 1455 of yacc.c */ -#line 522 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 516 "glcpp/glcpp-parse.y" { (yyval.token) = _token_create_ival (parser, SPACE, SPACE); (yyval.token)->location = yylloc; @@ -2438,225 +2440,225 @@ yyreduce: case 71: -/* Line 1455 of yacc.c */ -#line 529 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 523 "glcpp/glcpp-parse.y" { (yyval.ival) = '['; ;} break; case 72: -/* Line 1455 of yacc.c */ -#line 530 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 524 "glcpp/glcpp-parse.y" { (yyval.ival) = ']'; ;} break; case 73: -/* Line 1455 of yacc.c */ -#line 531 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 525 "glcpp/glcpp-parse.y" { (yyval.ival) = '('; ;} break; case 74: -/* Line 1455 of yacc.c */ -#line 532 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 526 "glcpp/glcpp-parse.y" { (yyval.ival) = ')'; ;} break; case 75: -/* Line 1455 of yacc.c */ -#line 533 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 527 "glcpp/glcpp-parse.y" { (yyval.ival) = '{'; ;} break; case 76: -/* Line 1455 of yacc.c */ -#line 534 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 528 "glcpp/glcpp-parse.y" { (yyval.ival) = '}'; ;} break; case 77: -/* Line 1455 of yacc.c */ -#line 535 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 529 "glcpp/glcpp-parse.y" { (yyval.ival) = '.'; ;} break; case 78: -/* Line 1455 of yacc.c */ -#line 536 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 530 "glcpp/glcpp-parse.y" { (yyval.ival) = '&'; ;} break; case 79: -/* Line 1455 of yacc.c */ -#line 537 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 531 "glcpp/glcpp-parse.y" { (yyval.ival) = '*'; ;} break; case 80: -/* Line 1455 of yacc.c */ -#line 538 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 532 "glcpp/glcpp-parse.y" { (yyval.ival) = '+'; ;} break; case 81: -/* Line 1455 of yacc.c */ -#line 539 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 533 "glcpp/glcpp-parse.y" { (yyval.ival) = '-'; ;} break; case 82: -/* Line 1455 of yacc.c */ -#line 540 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 534 "glcpp/glcpp-parse.y" { (yyval.ival) = '~'; ;} break; case 83: -/* Line 1455 of yacc.c */ -#line 541 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 535 "glcpp/glcpp-parse.y" { (yyval.ival) = '!'; ;} break; case 84: -/* Line 1455 of yacc.c */ -#line 542 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 536 "glcpp/glcpp-parse.y" { (yyval.ival) = '/'; ;} break; case 85: -/* Line 1455 of yacc.c */ -#line 543 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 537 "glcpp/glcpp-parse.y" { (yyval.ival) = '%'; ;} break; case 86: -/* Line 1455 of yacc.c */ -#line 544 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 538 "glcpp/glcpp-parse.y" { (yyval.ival) = LEFT_SHIFT; ;} break; case 87: -/* Line 1455 of yacc.c */ -#line 545 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 539 "glcpp/glcpp-parse.y" { (yyval.ival) = RIGHT_SHIFT; ;} break; case 88: -/* Line 1455 of yacc.c */ -#line 546 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 540 "glcpp/glcpp-parse.y" { (yyval.ival) = '<'; ;} break; case 89: -/* Line 1455 of yacc.c */ -#line 547 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 541 "glcpp/glcpp-parse.y" { (yyval.ival) = '>'; ;} break; case 90: -/* Line 1455 of yacc.c */ -#line 548 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 542 "glcpp/glcpp-parse.y" { (yyval.ival) = LESS_OR_EQUAL; ;} break; case 91: -/* Line 1455 of yacc.c */ -#line 549 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 543 "glcpp/glcpp-parse.y" { (yyval.ival) = GREATER_OR_EQUAL; ;} break; case 92: -/* Line 1455 of yacc.c */ -#line 550 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 544 "glcpp/glcpp-parse.y" { (yyval.ival) = EQUAL; ;} break; case 93: -/* Line 1455 of yacc.c */ -#line 551 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 545 "glcpp/glcpp-parse.y" { (yyval.ival) = NOT_EQUAL; ;} break; case 94: -/* Line 1455 of yacc.c */ -#line 552 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 546 "glcpp/glcpp-parse.y" { (yyval.ival) = '^'; ;} break; case 95: -/* Line 1455 of yacc.c */ -#line 553 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 547 "glcpp/glcpp-parse.y" { (yyval.ival) = '|'; ;} break; case 96: -/* Line 1455 of yacc.c */ -#line 554 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 548 "glcpp/glcpp-parse.y" { (yyval.ival) = AND; ;} break; case 97: -/* Line 1455 of yacc.c */ -#line 555 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 549 "glcpp/glcpp-parse.y" { (yyval.ival) = OR; ;} break; case 98: -/* Line 1455 of yacc.c */ -#line 556 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 550 "glcpp/glcpp-parse.y" { (yyval.ival) = ';'; ;} break; case 99: -/* Line 1455 of yacc.c */ -#line 557 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 551 "glcpp/glcpp-parse.y" { (yyval.ival) = ','; ;} break; case 100: -/* Line 1455 of yacc.c */ -#line 558 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 552 "glcpp/glcpp-parse.y" { (yyval.ival) = '='; ;} break; case 101: -/* Line 1455 of yacc.c */ -#line 559 "glcpp/glcpp-parse.y" +/* Line 1464 of yacc.c */ +#line 553 "glcpp/glcpp-parse.y" { (yyval.ival) = PASTE; ;} break; -/* Line 1455 of yacc.c */ -#line 2660 "glcpp/glcpp-parse.c" +/* Line 1464 of yacc.c */ +#line 2662 "glcpp/glcpp-parse.c" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); @@ -2728,7 +2730,7 @@ yyerrlab: #endif } - yyerror_range[0] = yylloc; + yyerror_range[1] = yylloc; if (yyerrstatus == 3) { @@ -2765,7 +2767,7 @@ yyerrorlab: if (/*CONSTCOND*/ 0) goto yyerrorlab; - yyerror_range[0] = yylsp[1-yylen]; + yyerror_range[1] = yylsp[1-yylen]; /* Do not reclaim the symbols of the rule which action triggered this YYERROR. */ YYPOPSTACK (yylen); @@ -2799,7 +2801,7 @@ yyerrlab1: if (yyssp == yyss) YYABORT; - yyerror_range[0] = *yylsp; + yyerror_range[1] = *yylsp; yydestruct ("Error: popping", yystos[yystate], yyvsp, yylsp, parser); YYPOPSTACK (1); @@ -2809,10 +2811,10 @@ yyerrlab1: *++yyvsp = yylval; - yyerror_range[1] = yylloc; + yyerror_range[2] = yylloc; /* Using YYLLOC is tempting, but would change the location of the lookahead. YYLOC is available though. */ - YYLLOC_DEFAULT (yyloc, (yyerror_range - 1), 2); + YYLLOC_DEFAULT (yyloc, yyerror_range, 2); *++yylsp = yyloc; /* Shift the error token. */ @@ -2874,8 +2876,8 @@ yyreturn: -/* Line 1675 of yacc.c */ -#line 562 "glcpp/glcpp-parse.y" +/* Line 1684 of yacc.c */ +#line 556 "glcpp/glcpp-parse.y" string_list_t * @@ -2883,7 +2885,7 @@ _string_list_create (void *ctx) { string_list_t *list; - list = talloc (ctx, string_list_t); + list = ralloc (ctx, string_list_t); list->head = NULL; list->tail = NULL; @@ -2895,8 +2897,8 @@ _string_list_append_item (string_list_t *list, const char *str) { string_node_t *node; - node = talloc (list, string_node_t); - node->str = talloc_strdup (node, str); + node = ralloc (list, string_node_t); + node->str = ralloc_strdup (node, str); node->next = NULL; @@ -2974,7 +2976,7 @@ _argument_list_create (void *ctx) { argument_list_t *list; - list = talloc (ctx, argument_list_t); + list = ralloc (ctx, argument_list_t); list->head = NULL; list->tail = NULL; @@ -2986,7 +2988,7 @@ _argument_list_append (argument_list_t *list, token_list_t *argument) { argument_node_t *node; - node = talloc (list, argument_node_t); + node = ralloc (list, argument_node_t); node->argument = argument; node->next = NULL; @@ -3037,15 +3039,17 @@ _argument_list_member_at (argument_list_t *list, int index) return NULL; } -/* Note: This function talloc_steal()s the str pointer. */ +/* Note: This function ralloc_steal()s the str pointer. */ token_t * _token_create_str (void *ctx, int type, char *str) { token_t *token; - token = talloc (ctx, token_t); + token = ralloc (ctx, token_t); token->type = type; - token->value.str = talloc_steal (token, str); + token->value.str = str; + + ralloc_steal (token, str); return token; } @@ -3055,7 +3059,7 @@ _token_create_ival (void *ctx, int type, int ival) { token_t *token; - token = talloc (ctx, token_t); + token = ralloc (ctx, token_t); token->type = type; token->value.ival = ival; @@ -3067,7 +3071,7 @@ _token_list_create (void *ctx) { token_list_t *list; - list = talloc (ctx, token_list_t); + list = ralloc (ctx, token_list_t); list->head = NULL; list->tail = NULL; list->non_space_tail = NULL; @@ -3080,11 +3084,12 @@ _token_list_append (token_list_t *list, token_t *token) { token_node_t *node; - node = talloc (list, token_node_t); - node->token = talloc_reference (list, token); - + node = ralloc (list, token_node_t); + node->token = token; node->next = NULL; + ralloc_steal (list, token); + if (list->head == NULL) { list->head = node; } else { @@ -3122,8 +3127,11 @@ _token_list_copy (void *ctx, token_list_t *other) return NULL; copy = _token_list_create (ctx); - for (node = other->head; node; node = node->next) - _token_list_append (copy, node->token); + for (node = other->head; node; node = node->next) { + token_t *new_token = ralloc (copy, token_t); + *new_token = *node->token; + _token_list_append (copy, new_token); + } return copy; } @@ -3140,13 +3148,13 @@ _token_list_trim_trailing_space (token_list_t *list) while (tail) { next = tail->next; - talloc_free (tail); + ralloc_free (tail); tail = next; } } } -int +static int _token_list_is_empty_ignoring_space (token_list_t *l) { token_node_t *n; @@ -3226,51 +3234,51 @@ static void _token_print (char **out, token_t *token) { if (token->type < 256) { - glcpp_printf (*out, "%c", token->type); + ralloc_asprintf_append (out, "%c", token->type); return; } switch (token->type) { case INTEGER: - glcpp_printf (*out, "%" PRIiMAX, token->value.ival); + ralloc_asprintf_append (out, "%" PRIiMAX, token->value.ival); break; case IDENTIFIER: case INTEGER_STRING: case OTHER: - glcpp_print (*out, token->value.str); + ralloc_strcat (out, token->value.str); break; case SPACE: - glcpp_print (*out, " "); + ralloc_strcat (out, " "); break; case LEFT_SHIFT: - glcpp_print (*out, "<<"); + ralloc_strcat (out, "<<"); break; case RIGHT_SHIFT: - glcpp_print (*out, ">>"); + ralloc_strcat (out, ">>"); break; case LESS_OR_EQUAL: - glcpp_print (*out, "<="); + ralloc_strcat (out, "<="); break; case GREATER_OR_EQUAL: - glcpp_print (*out, ">="); + ralloc_strcat (out, ">="); break; case EQUAL: - glcpp_print (*out, "=="); + ralloc_strcat (out, "=="); break; case NOT_EQUAL: - glcpp_print (*out, "!="); + ralloc_strcat (out, "!="); break; case AND: - glcpp_print (*out, "&&"); + ralloc_strcat (out, "&&"); break; case OR: - glcpp_print (*out, "||"); + ralloc_strcat (out, "||"); break; case PASTE: - glcpp_print (*out, "##"); + ralloc_strcat (out, "##"); break; case COMMA_FINAL: - glcpp_print (*out, ","); + ralloc_strcat (out, ","); break; case PLACEHOLDER: /* Nothing to print. */ @@ -3281,7 +3289,7 @@ _token_print (char **out, token_t *token) } } -/* Return a new token (talloc()ed off of 'token') formed by pasting +/* Return a new token (ralloc()ed off of 'token') formed by pasting * 'token' and 'other'. Note that this function may return 'token' or * 'other' directly rather than allocating anything new. * @@ -3352,7 +3360,7 @@ _token_paste (glcpp_parser_t *parser, token_t *token, token_t *other) { char *str; - str = talloc_asprintf (token, "%s%s", token->value.str, + str = ralloc_asprintf (token, "%s%s", token->value.str, other->value.str); combined = _token_create_str (token, token->type, str); combined->location = token->location; @@ -3360,11 +3368,11 @@ _token_paste (glcpp_parser_t *parser, token_t *token, token_t *other) } glcpp_error (&token->location, parser, ""); - glcpp_print (parser->info_log, "Pasting \""); + ralloc_strcat (&parser->info_log, "Pasting \""); _token_print (&parser->info_log, token); - glcpp_print (parser->info_log, "\" and \""); + ralloc_strcat (&parser->info_log, "\" and \""); _token_print (&parser->info_log, other); - glcpp_print (parser->info_log, "\" does not give a valid preprocessing token.\n"); + ralloc_strcat (&parser->info_log, "\" does not give a valid preprocessing token.\n"); return token; } @@ -3398,8 +3406,6 @@ static void add_builtin_define(glcpp_parser_t *parser, list = _token_list_create(parser); _token_list_append(list, tok); _define_object_macro(parser, NULL, name, list); - - talloc_unlink(parser, tok); } glcpp_parser_t * @@ -3408,7 +3414,7 @@ glcpp_parser_create (const struct gl_extensions *extensions, int api) glcpp_parser_t *parser; int language_version; - parser = talloc (NULL, glcpp_parser_t); + parser = ralloc (NULL, glcpp_parser_t); glcpp_lex_init_extra (parser, &parser->scanner); parser->defines = hash_table_ctor (32, hash_table_string_hash, @@ -3425,8 +3431,8 @@ glcpp_parser_create (const struct gl_extensions *extensions, int api) parser->lex_from_list = NULL; parser->lex_from_node = NULL; - parser->output = talloc_strdup(parser, ""); - parser->info_log = talloc_strdup(parser, ""); + parser->output = ralloc_strdup(parser, ""); + parser->info_log = ralloc_strdup(parser, ""); parser->error = 0; /* Add pre-defined macros. */ @@ -3447,6 +3453,8 @@ glcpp_parser_create (const struct gl_extensions *extensions, int api) if (extensions->ARB_explicit_attrib_location) add_builtin_define(parser, "GL_ARB_explicit_attrib_location", 1); + if (extensions->AMD_conservative_depth) + add_builtin_define(parser, "GL_AMD_conservative_depth", 1); } language_version = 110; @@ -3466,7 +3474,7 @@ glcpp_parser_destroy (glcpp_parser_t *parser) { glcpp_lex_destroy (parser->scanner); hash_table_dtor (parser->defines); - talloc_free (parser); + ralloc_free (parser); } typedef enum function_status @@ -3637,7 +3645,7 @@ _glcpp_parser_expand_function (glcpp_parser_t *parser, /* Replace a macro defined as empty with a SPACE token. */ if (macro->replacements == NULL) { - talloc_free (arguments); + ralloc_free (arguments); return _token_list_create_with_one_space (parser); } @@ -3793,7 +3801,7 @@ _glcpp_parser_expand_node (glcpp_parser_t *parser, token_list_t *expansion; token_t *final; - str = talloc_strdup (parser, token->value.str); + str = ralloc_strdup (parser, token->value.str); final = _token_create_str (parser, OTHER, str); expansion = _token_list_create (parser); _token_list_append (expansion, final); @@ -3829,8 +3837,8 @@ _active_list_push (active_list_t *list, { active_list_t *node; - node = talloc (list, active_list_t); - node->identifier = talloc_strdup (node, identifier); + node = ralloc (list, active_list_t); + node->identifier = ralloc_strdup (node, identifier); node->marker = marker; node->next = list; @@ -3846,7 +3854,7 @@ _active_list_pop (active_list_t *list) return NULL; node = list->next; - talloc_free (list); + ralloc_free (list); return node; } @@ -3995,17 +4003,18 @@ _define_object_macro (glcpp_parser_t *parser, if (loc != NULL) _check_for_reserved_macro_name(parser, loc, identifier); - macro = talloc (parser, macro_t); + macro = ralloc (parser, macro_t); macro->is_function = 0; macro->parameters = NULL; - macro->identifier = talloc_strdup (macro, identifier); - macro->replacements = talloc_steal (macro, replacements); + macro->identifier = ralloc_strdup (macro, identifier); + macro->replacements = replacements; + ralloc_steal (macro, replacements); previous = hash_table_find (parser->defines, identifier); if (previous) { if (_macro_equal (macro, previous)) { - talloc_free (macro); + ralloc_free (macro); return; } glcpp_error (loc, parser, "Redefinition of macro %s\n", @@ -4026,17 +4035,18 @@ _define_function_macro (glcpp_parser_t *parser, _check_for_reserved_macro_name(parser, loc, identifier); - macro = talloc (parser, macro_t); + macro = ralloc (parser, macro_t); + ralloc_steal (macro, parameters); + ralloc_steal (macro, replacements); macro->is_function = 1; - macro->parameters = talloc_steal (macro, parameters); - macro->identifier = talloc_strdup (macro, identifier); - macro->replacements = talloc_steal (macro, replacements); - + macro->parameters = parameters; + macro->identifier = ralloc_strdup (macro, identifier); + macro->replacements = replacements; previous = hash_table_find (parser->defines, identifier); if (previous) { if (_macro_equal (macro, previous)) { - talloc_free (macro); + ralloc_free (macro); return; } glcpp_error (loc, parser, "Redefinition of macro %s\n", @@ -4112,7 +4122,7 @@ glcpp_parser_lex (YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser) node = parser->lex_from_node; if (node == NULL) { - talloc_free (parser->lex_from_list); + ralloc_free (parser->lex_from_list); parser->lex_from_list = NULL; return NEWLINE; } @@ -4141,13 +4151,13 @@ glcpp_parser_lex_from (glcpp_parser_t *parser, token_list_t *list) _token_list_append (parser->lex_from_list, node->token); } - talloc_free (list); + ralloc_free (list); parser->lex_from_node = parser->lex_from_list->head; /* It's possible the list consisted of nothing but whitespace. */ if (parser->lex_from_node == NULL) { - talloc_free (parser->lex_from_list); + ralloc_free (parser->lex_from_list); parser->lex_from_list = NULL; } } @@ -4162,7 +4172,7 @@ _glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, YYLTYPE *loc, if (parser->skip_stack) current = parser->skip_stack->type; - node = talloc (parser, skip_node_t); + node = ralloc (parser, skip_node_t); node->loc = *loc; if (current == SKIP_NO_SKIP) { @@ -4207,6 +4217,6 @@ _glcpp_parser_skip_stack_pop (glcpp_parser_t *parser, YYLTYPE *loc) node = parser->skip_stack; parser->skip_stack = node->next; - talloc_free (node); + ralloc_free (node); } diff --git a/src/glsl/glcpp/glcpp-parse.y b/src/glsl/glcpp/glcpp-parse.y index e71c0e8b382..1f6e67fa062 100644 --- a/src/glsl/glcpp/glcpp-parse.y +++ b/src/glsl/glcpp/glcpp-parse.y @@ -32,10 +32,6 @@ #include "main/core.h" /* for struct gl_extensions */ #include "main/mtypes.h" /* for gl_api enum */ -#define glcpp_print(stream, str) stream = talloc_strdup_append(stream, str) -#define glcpp_printf(stream, fmt, args, ...) \ - stream = talloc_asprintf_append(stream, fmt, args) - static void yyerror (YYLTYPE *locp, glcpp_parser_t *parser, const char *error); @@ -79,7 +75,7 @@ _argument_list_length (argument_list_t *list); static token_list_t * _argument_list_member_at (argument_list_t *list, int index); -/* Note: This function talloc_steal()s the str pointer. */ +/* Note: This function ralloc_steal()s the str pointer. */ static token_t * _token_create_str (void *ctx, int type, char *str); @@ -89,10 +85,7 @@ _token_create_ival (void *ctx, int type, int ival); static token_list_t * _token_list_create (void *ctx); -/* Note: This function adds a talloc_reference() to token. - * - * You may want to talloc_unlink any current reference if you no - * longer need it. */ +/* Note: This function calls ralloc_steal on token. */ static void _token_list_append (token_list_t *list, token_t *token); @@ -192,12 +185,12 @@ input: line: control_line { - glcpp_print(parser->output, "\n"); + ralloc_strcat (&parser->output, "\n"); } | text_line { _glcpp_parser_print_expanded_token_list (parser, $1); - glcpp_print(parser->output, "\n"); - talloc_free ($1); + ralloc_strcat (&parser->output, "\n"); + ralloc_free ($1); } | expanded_line | HASH non_directive @@ -226,9 +219,9 @@ control_line: macro_t *macro = hash_table_find (parser->defines, $2); if (macro) { hash_table_remove (parser->defines, $2); - talloc_free (macro); + ralloc_free (macro); } - talloc_free ($2); + ralloc_free ($2); } | HASH_IF conditional_tokens NEWLINE { /* Be careful to only evaluate the 'if' expression if @@ -261,12 +254,12 @@ control_line: } | HASH_IFDEF IDENTIFIER junk NEWLINE { macro_t *macro = hash_table_find (parser->defines, $2); - talloc_free ($2); + ralloc_free ($2); _glcpp_parser_skip_stack_push_if (parser, & @1, macro != NULL); } | HASH_IFNDEF IDENTIFIER junk NEWLINE { macro_t *macro = hash_table_find (parser->defines, $2); - talloc_free ($2); + ralloc_free ($2); _glcpp_parser_skip_stack_push_if (parser, & @1, macro == NULL); } | HASH_ELIF conditional_tokens NEWLINE { @@ -313,7 +306,7 @@ control_line: macro_t *macro = hash_table_find (parser->defines, "__VERSION__"); if (macro) { hash_table_remove (parser->defines, "__VERSION__"); - talloc_free (macro); + ralloc_free (macro); } add_builtin_define (parser, "__VERSION__", $2); @@ -328,7 +321,7 @@ control_line: if ($2 >= 130 || $2 == 100) add_builtin_define (parser, "GL_FRAGMENT_PRECISION_HIGH", 1); - glcpp_printf(parser->output, "#version %" PRIiMAX, $2); + ralloc_asprintf_append (&parser->output, "#version %" PRIiMAX, $2); } | HASH NEWLINE ; @@ -395,7 +388,12 @@ expression: $$ = $1 + $3; } | expression '%' expression { - $$ = $1 % $3; + if ($3 == 0) { + yyerror (& @1, parser, + "zero modulus in preprocessor directive"); + } else { + $$ = $1 % $3; + } } | expression '/' expression { if ($3 == 0) { @@ -429,12 +427,12 @@ identifier_list: IDENTIFIER { $$ = _string_list_create (parser); _string_list_append_item ($$, $1); - talloc_steal ($$, $1); + ralloc_steal ($$, $1); } | identifier_list ',' IDENTIFIER { $$ = $1; _string_list_append_item ($$, $3); - talloc_steal ($$, $3); + ralloc_steal ($$, $3); } ; @@ -479,12 +477,10 @@ conditional_tokens: conditional_token { $$ = _token_list_create (parser); _token_list_append ($$, $1); - talloc_unlink (parser, $1); } | conditional_tokens conditional_token { $$ = $1; _token_list_append ($$, $2); - talloc_unlink (parser, $2); } ; @@ -493,12 +489,10 @@ pp_tokens: parser->space_tokens = 1; $$ = _token_list_create (parser); _token_list_append ($$, $1); - talloc_unlink (parser, $1); } | pp_tokens preprocessing_token { $$ = $1; _token_list_append ($$, $2); - talloc_unlink (parser, $2); } ; @@ -566,7 +560,7 @@ _string_list_create (void *ctx) { string_list_t *list; - list = talloc (ctx, string_list_t); + list = ralloc (ctx, string_list_t); list->head = NULL; list->tail = NULL; @@ -578,8 +572,8 @@ _string_list_append_item (string_list_t *list, const char *str) { string_node_t *node; - node = talloc (list, string_node_t); - node->str = talloc_strdup (node, str); + node = ralloc (list, string_node_t); + node->str = ralloc_strdup (node, str); node->next = NULL; @@ -657,7 +651,7 @@ _argument_list_create (void *ctx) { argument_list_t *list; - list = talloc (ctx, argument_list_t); + list = ralloc (ctx, argument_list_t); list->head = NULL; list->tail = NULL; @@ -669,7 +663,7 @@ _argument_list_append (argument_list_t *list, token_list_t *argument) { argument_node_t *node; - node = talloc (list, argument_node_t); + node = ralloc (list, argument_node_t); node->argument = argument; node->next = NULL; @@ -720,15 +714,17 @@ _argument_list_member_at (argument_list_t *list, int index) return NULL; } -/* Note: This function talloc_steal()s the str pointer. */ +/* Note: This function ralloc_steal()s the str pointer. */ token_t * _token_create_str (void *ctx, int type, char *str) { token_t *token; - token = talloc (ctx, token_t); + token = ralloc (ctx, token_t); token->type = type; - token->value.str = talloc_steal (token, str); + token->value.str = str; + + ralloc_steal (token, str); return token; } @@ -738,7 +734,7 @@ _token_create_ival (void *ctx, int type, int ival) { token_t *token; - token = talloc (ctx, token_t); + token = ralloc (ctx, token_t); token->type = type; token->value.ival = ival; @@ -750,7 +746,7 @@ _token_list_create (void *ctx) { token_list_t *list; - list = talloc (ctx, token_list_t); + list = ralloc (ctx, token_list_t); list->head = NULL; list->tail = NULL; list->non_space_tail = NULL; @@ -763,11 +759,12 @@ _token_list_append (token_list_t *list, token_t *token) { token_node_t *node; - node = talloc (list, token_node_t); - node->token = talloc_reference (list, token); - + node = ralloc (list, token_node_t); + node->token = token; node->next = NULL; + ralloc_steal (list, token); + if (list->head == NULL) { list->head = node; } else { @@ -805,8 +802,11 @@ _token_list_copy (void *ctx, token_list_t *other) return NULL; copy = _token_list_create (ctx); - for (node = other->head; node; node = node->next) - _token_list_append (copy, node->token); + for (node = other->head; node; node = node->next) { + token_t *new_token = ralloc (copy, token_t); + *new_token = *node->token; + _token_list_append (copy, new_token); + } return copy; } @@ -823,13 +823,13 @@ _token_list_trim_trailing_space (token_list_t *list) while (tail) { next = tail->next; - talloc_free (tail); + ralloc_free (tail); tail = next; } } } -int +static int _token_list_is_empty_ignoring_space (token_list_t *l) { token_node_t *n; @@ -909,51 +909,51 @@ static void _token_print (char **out, token_t *token) { if (token->type < 256) { - glcpp_printf (*out, "%c", token->type); + ralloc_asprintf_append (out, "%c", token->type); return; } switch (token->type) { case INTEGER: - glcpp_printf (*out, "%" PRIiMAX, token->value.ival); + ralloc_asprintf_append (out, "%" PRIiMAX, token->value.ival); break; case IDENTIFIER: case INTEGER_STRING: case OTHER: - glcpp_print (*out, token->value.str); + ralloc_strcat (out, token->value.str); break; case SPACE: - glcpp_print (*out, " "); + ralloc_strcat (out, " "); break; case LEFT_SHIFT: - glcpp_print (*out, "<<"); + ralloc_strcat (out, "<<"); break; case RIGHT_SHIFT: - glcpp_print (*out, ">>"); + ralloc_strcat (out, ">>"); break; case LESS_OR_EQUAL: - glcpp_print (*out, "<="); + ralloc_strcat (out, "<="); break; case GREATER_OR_EQUAL: - glcpp_print (*out, ">="); + ralloc_strcat (out, ">="); break; case EQUAL: - glcpp_print (*out, "=="); + ralloc_strcat (out, "=="); break; case NOT_EQUAL: - glcpp_print (*out, "!="); + ralloc_strcat (out, "!="); break; case AND: - glcpp_print (*out, "&&"); + ralloc_strcat (out, "&&"); break; case OR: - glcpp_print (*out, "||"); + ralloc_strcat (out, "||"); break; case PASTE: - glcpp_print (*out, "##"); + ralloc_strcat (out, "##"); break; case COMMA_FINAL: - glcpp_print (*out, ","); + ralloc_strcat (out, ","); break; case PLACEHOLDER: /* Nothing to print. */ @@ -964,7 +964,7 @@ _token_print (char **out, token_t *token) } } -/* Return a new token (talloc()ed off of 'token') formed by pasting +/* Return a new token (ralloc()ed off of 'token') formed by pasting * 'token' and 'other'. Note that this function may return 'token' or * 'other' directly rather than allocating anything new. * @@ -1035,7 +1035,7 @@ _token_paste (glcpp_parser_t *parser, token_t *token, token_t *other) { char *str; - str = talloc_asprintf (token, "%s%s", token->value.str, + str = ralloc_asprintf (token, "%s%s", token->value.str, other->value.str); combined = _token_create_str (token, token->type, str); combined->location = token->location; @@ -1043,11 +1043,11 @@ _token_paste (glcpp_parser_t *parser, token_t *token, token_t *other) } glcpp_error (&token->location, parser, ""); - glcpp_print (parser->info_log, "Pasting \""); + ralloc_strcat (&parser->info_log, "Pasting \""); _token_print (&parser->info_log, token); - glcpp_print (parser->info_log, "\" and \""); + ralloc_strcat (&parser->info_log, "\" and \""); _token_print (&parser->info_log, other); - glcpp_print (parser->info_log, "\" does not give a valid preprocessing token.\n"); + ralloc_strcat (&parser->info_log, "\" does not give a valid preprocessing token.\n"); return token; } @@ -1081,8 +1081,6 @@ static void add_builtin_define(glcpp_parser_t *parser, list = _token_list_create(parser); _token_list_append(list, tok); _define_object_macro(parser, NULL, name, list); - - talloc_unlink(parser, tok); } glcpp_parser_t * @@ -1091,7 +1089,7 @@ glcpp_parser_create (const struct gl_extensions *extensions, int api) glcpp_parser_t *parser; int language_version; - parser = talloc (NULL, glcpp_parser_t); + parser = ralloc (NULL, glcpp_parser_t); glcpp_lex_init_extra (parser, &parser->scanner); parser->defines = hash_table_ctor (32, hash_table_string_hash, @@ -1108,8 +1106,8 @@ glcpp_parser_create (const struct gl_extensions *extensions, int api) parser->lex_from_list = NULL; parser->lex_from_node = NULL; - parser->output = talloc_strdup(parser, ""); - parser->info_log = talloc_strdup(parser, ""); + parser->output = ralloc_strdup(parser, ""); + parser->info_log = ralloc_strdup(parser, ""); parser->error = 0; /* Add pre-defined macros. */ @@ -1130,6 +1128,8 @@ glcpp_parser_create (const struct gl_extensions *extensions, int api) if (extensions->ARB_explicit_attrib_location) add_builtin_define(parser, "GL_ARB_explicit_attrib_location", 1); + if (extensions->AMD_conservative_depth) + add_builtin_define(parser, "GL_AMD_conservative_depth", 1); } language_version = 110; @@ -1149,7 +1149,7 @@ glcpp_parser_destroy (glcpp_parser_t *parser) { glcpp_lex_destroy (parser->scanner); hash_table_dtor (parser->defines); - talloc_free (parser); + ralloc_free (parser); } typedef enum function_status @@ -1320,7 +1320,7 @@ _glcpp_parser_expand_function (glcpp_parser_t *parser, /* Replace a macro defined as empty with a SPACE token. */ if (macro->replacements == NULL) { - talloc_free (arguments); + ralloc_free (arguments); return _token_list_create_with_one_space (parser); } @@ -1476,7 +1476,7 @@ _glcpp_parser_expand_node (glcpp_parser_t *parser, token_list_t *expansion; token_t *final; - str = talloc_strdup (parser, token->value.str); + str = ralloc_strdup (parser, token->value.str); final = _token_create_str (parser, OTHER, str); expansion = _token_list_create (parser); _token_list_append (expansion, final); @@ -1512,8 +1512,8 @@ _active_list_push (active_list_t *list, { active_list_t *node; - node = talloc (list, active_list_t); - node->identifier = talloc_strdup (node, identifier); + node = ralloc (list, active_list_t); + node->identifier = ralloc_strdup (node, identifier); node->marker = marker; node->next = list; @@ -1529,7 +1529,7 @@ _active_list_pop (active_list_t *list) return NULL; node = list->next; - talloc_free (list); + ralloc_free (list); return node; } @@ -1678,17 +1678,18 @@ _define_object_macro (glcpp_parser_t *parser, if (loc != NULL) _check_for_reserved_macro_name(parser, loc, identifier); - macro = talloc (parser, macro_t); + macro = ralloc (parser, macro_t); macro->is_function = 0; macro->parameters = NULL; - macro->identifier = talloc_strdup (macro, identifier); - macro->replacements = talloc_steal (macro, replacements); + macro->identifier = ralloc_strdup (macro, identifier); + macro->replacements = replacements; + ralloc_steal (macro, replacements); previous = hash_table_find (parser->defines, identifier); if (previous) { if (_macro_equal (macro, previous)) { - talloc_free (macro); + ralloc_free (macro); return; } glcpp_error (loc, parser, "Redefinition of macro %s\n", @@ -1709,17 +1710,18 @@ _define_function_macro (glcpp_parser_t *parser, _check_for_reserved_macro_name(parser, loc, identifier); - macro = talloc (parser, macro_t); + macro = ralloc (parser, macro_t); + ralloc_steal (macro, parameters); + ralloc_steal (macro, replacements); macro->is_function = 1; - macro->parameters = talloc_steal (macro, parameters); - macro->identifier = talloc_strdup (macro, identifier); - macro->replacements = talloc_steal (macro, replacements); - + macro->parameters = parameters; + macro->identifier = ralloc_strdup (macro, identifier); + macro->replacements = replacements; previous = hash_table_find (parser->defines, identifier); if (previous) { if (_macro_equal (macro, previous)) { - talloc_free (macro); + ralloc_free (macro); return; } glcpp_error (loc, parser, "Redefinition of macro %s\n", @@ -1795,7 +1797,7 @@ glcpp_parser_lex (YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser) node = parser->lex_from_node; if (node == NULL) { - talloc_free (parser->lex_from_list); + ralloc_free (parser->lex_from_list); parser->lex_from_list = NULL; return NEWLINE; } @@ -1824,13 +1826,13 @@ glcpp_parser_lex_from (glcpp_parser_t *parser, token_list_t *list) _token_list_append (parser->lex_from_list, node->token); } - talloc_free (list); + ralloc_free (list); parser->lex_from_node = parser->lex_from_list->head; /* It's possible the list consisted of nothing but whitespace. */ if (parser->lex_from_node == NULL) { - talloc_free (parser->lex_from_list); + ralloc_free (parser->lex_from_list); parser->lex_from_list = NULL; } } @@ -1845,7 +1847,7 @@ _glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, YYLTYPE *loc, if (parser->skip_stack) current = parser->skip_stack->type; - node = talloc (parser, skip_node_t); + node = ralloc (parser, skip_node_t); node->loc = *loc; if (current == SKIP_NO_SKIP) { @@ -1890,5 +1892,5 @@ _glcpp_parser_skip_stack_pop (glcpp_parser_t *parser, YYLTYPE *loc) node = parser->skip_stack; parser->skip_stack = node->next; - talloc_free (node); + ralloc_free (node); } diff --git a/src/glsl/glcpp/glcpp.c b/src/glsl/glcpp/glcpp.c index 062eb6b72d4..564194caac2 100644 --- a/src/glsl/glcpp/glcpp.c +++ b/src/glsl/glcpp/glcpp.c @@ -54,7 +54,7 @@ load_text_fd (void *ctx, int fd) while (1) { if (total_read + CHUNK + 1 > text_size) { text_size = text_size ? text_size * 2 : CHUNK + 1; - text = talloc_realloc_size (ctx, text, text_size); + text = reralloc_size (ctx, text, text_size); if (text == NULL) { fprintf (stderr, "Out of memory\n"); return NULL; @@ -64,7 +64,7 @@ load_text_fd (void *ctx, int fd) if (bytes < 0) { fprintf (stderr, "Error while reading: %s\n", strerror (errno)); - talloc_free (text); + ralloc_free (text); return NULL; } @@ -107,8 +107,8 @@ int main (int argc, char *argv[]) { char *filename = NULL; - void *ctx = talloc(NULL, void*); - char *info_log = talloc_strdup(ctx, ""); + void *ctx = ralloc(NULL, void*); + char *info_log = ralloc_strdup(ctx, ""); const char *shader; int ret; @@ -125,7 +125,7 @@ main (int argc, char *argv[]) printf("%s", shader); fprintf(stderr, "%s", info_log); - talloc_free(ctx); + ralloc_free(ctx); return ret; } diff --git a/src/glsl/glcpp/glcpp.h b/src/glsl/glcpp/glcpp.h index 7125d325dff..dc816e90ee7 100644 --- a/src/glsl/glcpp/glcpp.h +++ b/src/glsl/glcpp/glcpp.h @@ -26,7 +26,7 @@ #include <stdint.h> -#include <talloc.h> +#include "../ralloc.h" #include "program/hash_table.h" @@ -189,7 +189,7 @@ void glcpp_parser_destroy (glcpp_parser_t *parser); int -preprocess(void *talloc_ctx, const char **shader, char **info_log, +preprocess(void *ralloc_ctx, const char **shader, char **info_log, const struct gl_extensions *extensions, int api); /* Functions for writing to the info log */ diff --git a/src/glsl/glcpp/pp.c b/src/glsl/glcpp/pp.c index e1a3a88a3e5..3640896a2c2 100644 --- a/src/glsl/glcpp/pp.c +++ b/src/glsl/glcpp/pp.c @@ -33,16 +33,15 @@ glcpp_error (YYLTYPE *locp, glcpp_parser_t *parser, const char *fmt, ...) va_list ap; parser->error = 1; - parser->info_log = talloc_asprintf_append(parser->info_log, - "%u:%u(%u): " + ralloc_asprintf_append(&parser->info_log, "%u:%u(%u): " "preprocessor error: ", locp->source, locp->first_line, locp->first_column); va_start(ap, fmt); - parser->info_log = talloc_vasprintf_append(parser->info_log, fmt, ap); + ralloc_vasprintf_append(&parser->info_log, fmt, ap); va_end(ap); - parser->info_log = talloc_strdup_append(parser->info_log, "\n"); + ralloc_strcat(&parser->info_log, "\n"); } void @@ -50,16 +49,15 @@ glcpp_warning (YYLTYPE *locp, glcpp_parser_t *parser, const char *fmt, ...) { va_list ap; - parser->info_log = talloc_asprintf_append(parser->info_log, - "%u:%u(%u): " + ralloc_asprintf_append(&parser->info_log, "%u:%u(%u): " "preprocessor warning: ", locp->source, locp->first_line, locp->first_column); va_start(ap, fmt); - parser->info_log = talloc_vasprintf_append(parser->info_log, fmt, ap); + ralloc_vasprintf_append(&parser->info_log, fmt, ap); va_end(ap); - parser->info_log = talloc_strdup_append(parser->info_log, "\n"); + ralloc_strcat(&parser->info_log, "\n"); } /* Searches backwards for '^ *#' from a given starting point. */ @@ -92,7 +90,7 @@ remove_line_continuations(glcpp_parser_t *ctx, const char *shader) { int in_continued_line = 0; int extra_newlines = 0; - char *clean = talloc_strdup(ctx, ""); + char *clean = ralloc_strdup(ctx, ""); const char *search_start = shader; const char *newline; while ((newline = strchr(search_start, '\n')) != NULL) { @@ -122,27 +120,27 @@ remove_line_continuations(glcpp_parser_t *ctx, const char *shader) } if (in_continued_line) { /* Copy everything before the \ */ - clean = talloc_strndup_append(clean, shader, backslash - shader); + ralloc_strncat(&clean, shader, backslash - shader); shader = newline + 1; extra_newlines++; } } else if (in_continued_line) { /* Copy everything up to and including the \n */ - clean = talloc_strndup_append(clean, shader, newline - shader + 1); + ralloc_strncat(&clean, shader, newline - shader + 1); shader = newline + 1; /* Output extra newlines to make line numbers match */ for (; extra_newlines > 0; extra_newlines--) - clean = talloc_strdup_append(clean, "\n"); + ralloc_strcat(&clean, "\n"); in_continued_line = 0; } search_start = newline + 1; } - clean = talloc_strdup_append(clean, shader); + ralloc_strcat(&clean, shader); return clean; } int -preprocess(void *talloc_ctx, const char **shader, char **info_log, +preprocess(void *ralloc_ctx, const char **shader, char **info_log, const struct gl_extensions *extensions, int api) { int errors; @@ -156,9 +154,9 @@ preprocess(void *talloc_ctx, const char **shader, char **info_log, if (parser->skip_stack) glcpp_error (&parser->skip_stack->loc, parser, "Unterminated #if\n"); - *info_log = talloc_strdup_append(*info_log, parser->info_log); + ralloc_strcat(info_log, parser->info_log); - talloc_steal(talloc_ctx, parser->output); + ralloc_steal(ralloc_ctx, parser->output); *shader = parser->output; errors = parser->error; diff --git a/src/glsl/glsl_lexer.cpp b/src/glsl/glsl_lexer.cpp index 7c0a51b99bf..40d2294ef8c 100644 --- a/src/glsl/glsl_lexer.cpp +++ b/src/glsl/glsl_lexer.cpp @@ -54,6 +54,7 @@ typedef int flex_int32_t; typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; +#endif /* ! C99 */ /* Limits of integral types. */ #ifndef INT8_MIN @@ -84,8 +85,6 @@ typedef unsigned int flex_uint32_t; #define UINT32_MAX (4294967295U) #endif -#endif /* ! C99 */ - #endif /* ! FLEXINT_H */ #ifdef __cplusplus @@ -159,15 +158,7 @@ typedef void* yyscan_t; /* Size of default input buffer. */ #ifndef YY_BUF_SIZE -#ifdef __ia64__ -/* On IA-64, the buffer size is 16k, not 8k. - * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. - * Ditto for the __ia64__ case accordingly. - */ -#define YY_BUF_SIZE 32768 -#else #define YY_BUF_SIZE 16384 -#endif /* __ia64__ */ #endif /* The state buf must be large enough to hold one state per character in the main buffer. @@ -1027,6 +1018,8 @@ static yyconst flex_int16_t yy_chk[1283] = #include "glsl_parser_extras.h" #include "glsl_parser.h" +static int classify_identifier(struct _mesa_glsl_parse_state *, const char *); + #define YY_USER_ACTION \ do { \ yylloc->source = 0; \ @@ -1062,7 +1055,7 @@ static yyconst flex_int16_t yy_chk[1283] = return ERROR_TOK; \ } else { \ yylval->identifier = strdup(yytext); \ - return IDENTIFIER; \ + return classify_identifier(yyextra, yytext); \ } \ } while (0) @@ -1076,7 +1069,7 @@ static yyconst flex_int16_t yy_chk[1283] = */ #define ES yyextra->es_shader -#line 1080 "glsl_lexer.cpp" +#line 1073 "glsl_lexer.cpp" #define INITIAL 0 #define PP 1 @@ -1163,6 +1156,10 @@ int _mesa_glsl_get_lineno (yyscan_t yyscanner ); void _mesa_glsl_set_lineno (int line_number ,yyscan_t yyscanner ); +int _mesa_glsl_get_column (yyscan_t yyscanner ); + +void _mesa_glsl_set_column (int column_no ,yyscan_t yyscanner ); + YYSTYPE * _mesa_glsl_get_lval (yyscan_t yyscanner ); void _mesa_glsl_set_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner ); @@ -1203,12 +1200,7 @@ static int input (yyscan_t yyscanner ); /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE -#ifdef __ia64__ -/* On IA-64, the buffer size is 16k, not 8k */ -#define YY_READ_BUF_SIZE 16384 -#else #define YY_READ_BUF_SIZE 8192 -#endif /* __ia64__ */ #endif /* Copy whatever the last rule matched to the standard output. */ @@ -1227,7 +1219,7 @@ static int input (yyscan_t yyscanner ); if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ { \ int c = '*'; \ - size_t n; \ + unsigned n; \ for ( n = 0; n < max_size && \ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ @@ -1315,10 +1307,10 @@ YY_DECL register int yy_act; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; -#line 95 "glsl_lexer.lpp" +#line 97 "glsl_lexer.lpp" -#line 1322 "glsl_lexer.cpp" +#line 1314 "glsl_lexer.cpp" yylval = yylval_param; @@ -1404,7 +1396,7 @@ do_action: /* This label is used only to access EOF actions. */ case 1: YY_RULE_SETUP -#line 97 "glsl_lexer.lpp" +#line 99 "glsl_lexer.lpp" ; YY_BREAK /* Preprocessor tokens. */ @@ -1413,17 +1405,17 @@ case 2: yyg->yy_c_buf_p = yy_cp -= 1; YY_DO_BEFORE_ACTION; /* set up yytext again */ YY_RULE_SETUP -#line 100 "glsl_lexer.lpp" +#line 102 "glsl_lexer.lpp" ; YY_BREAK case 3: YY_RULE_SETUP -#line 101 "glsl_lexer.lpp" +#line 103 "glsl_lexer.lpp" { BEGIN PP; return VERSION; } YY_BREAK case 4: YY_RULE_SETUP -#line 102 "glsl_lexer.lpp" +#line 104 "glsl_lexer.lpp" { BEGIN PP; return EXTENSION; } YY_BREAK case 5: @@ -1431,7 +1423,7 @@ case 5: yyg->yy_c_buf_p = yy_cp -= 1; YY_DO_BEFORE_ACTION; /* set up yytext again */ YY_RULE_SETUP -#line 103 "glsl_lexer.lpp" +#line 105 "glsl_lexer.lpp" { /* Eat characters until the first digit is * encountered @@ -1453,7 +1445,7 @@ case 6: yyg->yy_c_buf_p = yy_cp -= 1; YY_DO_BEFORE_ACTION; /* set up yytext again */ YY_RULE_SETUP -#line 118 "glsl_lexer.lpp" +#line 120 "glsl_lexer.lpp" { /* Eat characters until the first digit is * encountered @@ -1471,7 +1463,7 @@ YY_RULE_SETUP YY_BREAK case 7: YY_RULE_SETUP -#line 132 "glsl_lexer.lpp" +#line 134 "glsl_lexer.lpp" { BEGIN PP; return PRAGMA_DEBUG_ON; @@ -1479,7 +1471,7 @@ YY_RULE_SETUP YY_BREAK case 8: YY_RULE_SETUP -#line 136 "glsl_lexer.lpp" +#line 138 "glsl_lexer.lpp" { BEGIN PP; return PRAGMA_DEBUG_OFF; @@ -1487,7 +1479,7 @@ YY_RULE_SETUP YY_BREAK case 9: YY_RULE_SETUP -#line 140 "glsl_lexer.lpp" +#line 142 "glsl_lexer.lpp" { BEGIN PP; return PRAGMA_OPTIMIZE_ON; @@ -1495,7 +1487,7 @@ YY_RULE_SETUP YY_BREAK case 10: YY_RULE_SETUP -#line 144 "glsl_lexer.lpp" +#line 146 "glsl_lexer.lpp" { BEGIN PP; return PRAGMA_OPTIMIZE_OFF; @@ -1503,7 +1495,7 @@ YY_RULE_SETUP YY_BREAK case 11: YY_RULE_SETUP -#line 148 "glsl_lexer.lpp" +#line 150 "glsl_lexer.lpp" { BEGIN PP; return PRAGMA_INVARIANT_ALL; @@ -1511,38 +1503,38 @@ YY_RULE_SETUP YY_BREAK case 12: YY_RULE_SETUP -#line 152 "glsl_lexer.lpp" +#line 154 "glsl_lexer.lpp" { BEGIN PRAGMA; } YY_BREAK case 13: /* rule 13 can match eol */ YY_RULE_SETUP -#line 154 "glsl_lexer.lpp" +#line 156 "glsl_lexer.lpp" { BEGIN 0; yylineno++; yycolumn = 0; } YY_BREAK case 14: YY_RULE_SETUP -#line 155 "glsl_lexer.lpp" +#line 157 "glsl_lexer.lpp" { } YY_BREAK case 15: YY_RULE_SETUP -#line 157 "glsl_lexer.lpp" +#line 159 "glsl_lexer.lpp" { } YY_BREAK case 16: YY_RULE_SETUP -#line 158 "glsl_lexer.lpp" +#line 160 "glsl_lexer.lpp" { } YY_BREAK case 17: YY_RULE_SETUP -#line 159 "glsl_lexer.lpp" +#line 161 "glsl_lexer.lpp" return COLON; YY_BREAK case 18: YY_RULE_SETUP -#line 160 "glsl_lexer.lpp" +#line 162 "glsl_lexer.lpp" { yylval->identifier = strdup(yytext); return IDENTIFIER; @@ -1550,7 +1542,7 @@ YY_RULE_SETUP YY_BREAK case 19: YY_RULE_SETUP -#line 164 "glsl_lexer.lpp" +#line 166 "glsl_lexer.lpp" { yylval->n = strtol(yytext, NULL, 10); return INTCONSTANT; @@ -1559,392 +1551,393 @@ YY_RULE_SETUP case 20: /* rule 20 can match eol */ YY_RULE_SETUP -#line 168 "glsl_lexer.lpp" +#line 170 "glsl_lexer.lpp" { BEGIN 0; yylineno++; yycolumn = 0; return EOL; } YY_BREAK case 21: /* rule 21 can match eol */ YY_RULE_SETUP -#line 170 "glsl_lexer.lpp" +#line 172 "glsl_lexer.lpp" { yylineno++; yycolumn = 0; } YY_BREAK case 22: YY_RULE_SETUP -#line 172 "glsl_lexer.lpp" +#line 174 "glsl_lexer.lpp" return ATTRIBUTE; YY_BREAK case 23: YY_RULE_SETUP -#line 173 "glsl_lexer.lpp" +#line 175 "glsl_lexer.lpp" return CONST_TOK; YY_BREAK case 24: YY_RULE_SETUP -#line 174 "glsl_lexer.lpp" +#line 176 "glsl_lexer.lpp" return BOOL_TOK; YY_BREAK case 25: YY_RULE_SETUP -#line 175 "glsl_lexer.lpp" +#line 177 "glsl_lexer.lpp" return FLOAT_TOK; YY_BREAK case 26: YY_RULE_SETUP -#line 176 "glsl_lexer.lpp" +#line 178 "glsl_lexer.lpp" return INT_TOK; YY_BREAK case 27: YY_RULE_SETUP -#line 177 "glsl_lexer.lpp" +#line 179 "glsl_lexer.lpp" KEYWORD(130, 130, UINT_TOK); YY_BREAK case 28: YY_RULE_SETUP -#line 179 "glsl_lexer.lpp" +#line 181 "glsl_lexer.lpp" return BREAK; YY_BREAK case 29: YY_RULE_SETUP -#line 180 "glsl_lexer.lpp" +#line 182 "glsl_lexer.lpp" return CONTINUE; YY_BREAK case 30: YY_RULE_SETUP -#line 181 "glsl_lexer.lpp" +#line 183 "glsl_lexer.lpp" return DO; YY_BREAK case 31: YY_RULE_SETUP -#line 182 "glsl_lexer.lpp" +#line 184 "glsl_lexer.lpp" return WHILE; YY_BREAK case 32: YY_RULE_SETUP -#line 183 "glsl_lexer.lpp" +#line 185 "glsl_lexer.lpp" return ELSE; YY_BREAK case 33: YY_RULE_SETUP -#line 184 "glsl_lexer.lpp" +#line 186 "glsl_lexer.lpp" return FOR; YY_BREAK case 34: YY_RULE_SETUP -#line 185 "glsl_lexer.lpp" +#line 187 "glsl_lexer.lpp" return IF; YY_BREAK case 35: YY_RULE_SETUP -#line 186 "glsl_lexer.lpp" +#line 188 "glsl_lexer.lpp" return DISCARD; YY_BREAK case 36: YY_RULE_SETUP -#line 187 "glsl_lexer.lpp" +#line 189 "glsl_lexer.lpp" return RETURN; YY_BREAK case 37: YY_RULE_SETUP -#line 189 "glsl_lexer.lpp" +#line 191 "glsl_lexer.lpp" return BVEC2; YY_BREAK case 38: YY_RULE_SETUP -#line 190 "glsl_lexer.lpp" +#line 192 "glsl_lexer.lpp" return BVEC3; YY_BREAK case 39: YY_RULE_SETUP -#line 191 "glsl_lexer.lpp" +#line 193 "glsl_lexer.lpp" return BVEC4; YY_BREAK case 40: YY_RULE_SETUP -#line 192 "glsl_lexer.lpp" +#line 194 "glsl_lexer.lpp" return IVEC2; YY_BREAK case 41: YY_RULE_SETUP -#line 193 "glsl_lexer.lpp" +#line 195 "glsl_lexer.lpp" return IVEC3; YY_BREAK case 42: YY_RULE_SETUP -#line 194 "glsl_lexer.lpp" +#line 196 "glsl_lexer.lpp" return IVEC4; YY_BREAK case 43: YY_RULE_SETUP -#line 195 "glsl_lexer.lpp" +#line 197 "glsl_lexer.lpp" KEYWORD(130, 130, UVEC2); YY_BREAK case 44: YY_RULE_SETUP -#line 196 "glsl_lexer.lpp" +#line 198 "glsl_lexer.lpp" KEYWORD(130, 130, UVEC3); YY_BREAK case 45: YY_RULE_SETUP -#line 197 "glsl_lexer.lpp" +#line 199 "glsl_lexer.lpp" KEYWORD(130, 130, UVEC4); YY_BREAK case 46: YY_RULE_SETUP -#line 198 "glsl_lexer.lpp" +#line 200 "glsl_lexer.lpp" return VEC2; YY_BREAK case 47: YY_RULE_SETUP -#line 199 "glsl_lexer.lpp" +#line 201 "glsl_lexer.lpp" return VEC3; YY_BREAK case 48: YY_RULE_SETUP -#line 200 "glsl_lexer.lpp" +#line 202 "glsl_lexer.lpp" return VEC4; YY_BREAK case 49: YY_RULE_SETUP -#line 201 "glsl_lexer.lpp" +#line 203 "glsl_lexer.lpp" return MAT2X2; YY_BREAK case 50: YY_RULE_SETUP -#line 202 "glsl_lexer.lpp" +#line 204 "glsl_lexer.lpp" return MAT3X3; YY_BREAK case 51: YY_RULE_SETUP -#line 203 "glsl_lexer.lpp" +#line 205 "glsl_lexer.lpp" return MAT4X4; YY_BREAK case 52: YY_RULE_SETUP -#line 204 "glsl_lexer.lpp" +#line 206 "glsl_lexer.lpp" KEYWORD(120, 120, MAT2X2); YY_BREAK case 53: YY_RULE_SETUP -#line 205 "glsl_lexer.lpp" +#line 207 "glsl_lexer.lpp" KEYWORD(120, 120, MAT2X3); YY_BREAK case 54: YY_RULE_SETUP -#line 206 "glsl_lexer.lpp" +#line 208 "glsl_lexer.lpp" KEYWORD(120, 120, MAT2X4); YY_BREAK case 55: YY_RULE_SETUP -#line 207 "glsl_lexer.lpp" +#line 209 "glsl_lexer.lpp" KEYWORD(120, 120, MAT3X2); YY_BREAK case 56: YY_RULE_SETUP -#line 208 "glsl_lexer.lpp" +#line 210 "glsl_lexer.lpp" KEYWORD(120, 120, MAT3X3); YY_BREAK case 57: YY_RULE_SETUP -#line 209 "glsl_lexer.lpp" +#line 211 "glsl_lexer.lpp" KEYWORD(120, 120, MAT3X4); YY_BREAK case 58: YY_RULE_SETUP -#line 210 "glsl_lexer.lpp" +#line 212 "glsl_lexer.lpp" KEYWORD(120, 120, MAT4X2); YY_BREAK case 59: YY_RULE_SETUP -#line 211 "glsl_lexer.lpp" +#line 213 "glsl_lexer.lpp" KEYWORD(120, 120, MAT4X3); YY_BREAK case 60: YY_RULE_SETUP -#line 212 "glsl_lexer.lpp" +#line 214 "glsl_lexer.lpp" KEYWORD(120, 120, MAT4X4); YY_BREAK case 61: YY_RULE_SETUP -#line 214 "glsl_lexer.lpp" +#line 216 "glsl_lexer.lpp" return IN_TOK; YY_BREAK case 62: YY_RULE_SETUP -#line 215 "glsl_lexer.lpp" +#line 217 "glsl_lexer.lpp" return OUT_TOK; YY_BREAK case 63: YY_RULE_SETUP -#line 216 "glsl_lexer.lpp" +#line 218 "glsl_lexer.lpp" return INOUT_TOK; YY_BREAK case 64: YY_RULE_SETUP -#line 217 "glsl_lexer.lpp" +#line 219 "glsl_lexer.lpp" return UNIFORM; YY_BREAK case 65: YY_RULE_SETUP -#line 218 "glsl_lexer.lpp" +#line 220 "glsl_lexer.lpp" return VARYING; YY_BREAK case 66: YY_RULE_SETUP -#line 219 "glsl_lexer.lpp" +#line 221 "glsl_lexer.lpp" KEYWORD(120, 120, CENTROID); YY_BREAK case 67: YY_RULE_SETUP -#line 220 "glsl_lexer.lpp" +#line 222 "glsl_lexer.lpp" KEYWORD(120 || ES, 120 || ES, INVARIANT); YY_BREAK case 68: YY_RULE_SETUP -#line 221 "glsl_lexer.lpp" +#line 223 "glsl_lexer.lpp" KEYWORD(130 || ES, 130, FLAT); YY_BREAK case 69: YY_RULE_SETUP -#line 222 "glsl_lexer.lpp" +#line 224 "glsl_lexer.lpp" KEYWORD(130, 130, SMOOTH); YY_BREAK case 70: YY_RULE_SETUP -#line 223 "glsl_lexer.lpp" +#line 225 "glsl_lexer.lpp" KEYWORD(130, 130, NOPERSPECTIVE); YY_BREAK case 71: YY_RULE_SETUP -#line 225 "glsl_lexer.lpp" +#line 227 "glsl_lexer.lpp" return SAMPLER1D; YY_BREAK case 72: YY_RULE_SETUP -#line 226 "glsl_lexer.lpp" +#line 228 "glsl_lexer.lpp" return SAMPLER2D; YY_BREAK case 73: YY_RULE_SETUP -#line 227 "glsl_lexer.lpp" +#line 229 "glsl_lexer.lpp" return SAMPLER3D; YY_BREAK case 74: YY_RULE_SETUP -#line 228 "glsl_lexer.lpp" +#line 230 "glsl_lexer.lpp" return SAMPLERCUBE; YY_BREAK case 75: YY_RULE_SETUP -#line 229 "glsl_lexer.lpp" +#line 231 "glsl_lexer.lpp" KEYWORD(130, 130, SAMPLER1DARRAY); YY_BREAK case 76: YY_RULE_SETUP -#line 230 "glsl_lexer.lpp" +#line 232 "glsl_lexer.lpp" KEYWORD(130, 130, SAMPLER2DARRAY); YY_BREAK case 77: YY_RULE_SETUP -#line 231 "glsl_lexer.lpp" +#line 233 "glsl_lexer.lpp" return SAMPLER1DSHADOW; YY_BREAK case 78: YY_RULE_SETUP -#line 232 "glsl_lexer.lpp" +#line 234 "glsl_lexer.lpp" return SAMPLER2DSHADOW; YY_BREAK case 79: YY_RULE_SETUP -#line 233 "glsl_lexer.lpp" +#line 235 "glsl_lexer.lpp" KEYWORD(130, 130, SAMPLERCUBESHADOW); YY_BREAK case 80: YY_RULE_SETUP -#line 234 "glsl_lexer.lpp" +#line 236 "glsl_lexer.lpp" KEYWORD(130, 130, SAMPLER1DARRAYSHADOW); YY_BREAK case 81: YY_RULE_SETUP -#line 235 "glsl_lexer.lpp" +#line 237 "glsl_lexer.lpp" KEYWORD(130, 130, SAMPLER2DARRAYSHADOW); YY_BREAK case 82: YY_RULE_SETUP -#line 236 "glsl_lexer.lpp" +#line 238 "glsl_lexer.lpp" KEYWORD(130, 130, ISAMPLER1D); YY_BREAK case 83: YY_RULE_SETUP -#line 237 "glsl_lexer.lpp" +#line 239 "glsl_lexer.lpp" KEYWORD(130, 130, ISAMPLER2D); YY_BREAK case 84: YY_RULE_SETUP -#line 238 "glsl_lexer.lpp" +#line 240 "glsl_lexer.lpp" KEYWORD(130, 130, ISAMPLER3D); YY_BREAK case 85: YY_RULE_SETUP -#line 239 "glsl_lexer.lpp" +#line 241 "glsl_lexer.lpp" KEYWORD(130, 130, ISAMPLERCUBE); YY_BREAK case 86: YY_RULE_SETUP -#line 240 "glsl_lexer.lpp" +#line 242 "glsl_lexer.lpp" KEYWORD(130, 130, ISAMPLER1DARRAY); YY_BREAK case 87: YY_RULE_SETUP -#line 241 "glsl_lexer.lpp" +#line 243 "glsl_lexer.lpp" KEYWORD(130, 130, ISAMPLER2DARRAY); YY_BREAK case 88: YY_RULE_SETUP -#line 242 "glsl_lexer.lpp" +#line 244 "glsl_lexer.lpp" KEYWORD(130, 130, USAMPLER1D); YY_BREAK case 89: YY_RULE_SETUP -#line 243 "glsl_lexer.lpp" +#line 245 "glsl_lexer.lpp" KEYWORD(130, 130, USAMPLER2D); YY_BREAK case 90: YY_RULE_SETUP -#line 244 "glsl_lexer.lpp" +#line 246 "glsl_lexer.lpp" KEYWORD(130, 130, USAMPLER3D); YY_BREAK case 91: YY_RULE_SETUP -#line 245 "glsl_lexer.lpp" +#line 247 "glsl_lexer.lpp" KEYWORD(130, 130, USAMPLERCUBE); YY_BREAK case 92: YY_RULE_SETUP -#line 246 "glsl_lexer.lpp" +#line 248 "glsl_lexer.lpp" KEYWORD(130, 130, USAMPLER1DARRAY); YY_BREAK case 93: YY_RULE_SETUP -#line 247 "glsl_lexer.lpp" +#line 249 "glsl_lexer.lpp" KEYWORD(130, 130, USAMPLER2DARRAY); YY_BREAK case 94: YY_RULE_SETUP -#line 250 "glsl_lexer.lpp" +#line 252 "glsl_lexer.lpp" return STRUCT; YY_BREAK case 95: YY_RULE_SETUP -#line 251 "glsl_lexer.lpp" +#line 253 "glsl_lexer.lpp" return VOID_TOK; YY_BREAK case 96: YY_RULE_SETUP -#line 253 "glsl_lexer.lpp" +#line 255 "glsl_lexer.lpp" { if ((yyextra->language_version >= 140) + || yyextra->AMD_conservative_depth_enable || yyextra->ARB_explicit_attrib_location_enable - || (yyextra->ARB_fragment_coord_conventions_enable)){ + || yyextra->ARB_fragment_coord_conventions_enable) { return LAYOUT_TOK; } else { yylval->identifier = strdup(yytext); @@ -1954,112 +1947,112 @@ YY_RULE_SETUP YY_BREAK case 97: YY_RULE_SETUP -#line 264 "glsl_lexer.lpp" +#line 267 "glsl_lexer.lpp" return INC_OP; YY_BREAK case 98: YY_RULE_SETUP -#line 265 "glsl_lexer.lpp" +#line 268 "glsl_lexer.lpp" return DEC_OP; YY_BREAK case 99: YY_RULE_SETUP -#line 266 "glsl_lexer.lpp" +#line 269 "glsl_lexer.lpp" return LE_OP; YY_BREAK case 100: YY_RULE_SETUP -#line 267 "glsl_lexer.lpp" +#line 270 "glsl_lexer.lpp" return GE_OP; YY_BREAK case 101: YY_RULE_SETUP -#line 268 "glsl_lexer.lpp" +#line 271 "glsl_lexer.lpp" return EQ_OP; YY_BREAK case 102: YY_RULE_SETUP -#line 269 "glsl_lexer.lpp" +#line 272 "glsl_lexer.lpp" return NE_OP; YY_BREAK case 103: YY_RULE_SETUP -#line 270 "glsl_lexer.lpp" +#line 273 "glsl_lexer.lpp" return AND_OP; YY_BREAK case 104: YY_RULE_SETUP -#line 271 "glsl_lexer.lpp" +#line 274 "glsl_lexer.lpp" return OR_OP; YY_BREAK case 105: YY_RULE_SETUP -#line 272 "glsl_lexer.lpp" +#line 275 "glsl_lexer.lpp" return XOR_OP; YY_BREAK case 106: YY_RULE_SETUP -#line 273 "glsl_lexer.lpp" +#line 276 "glsl_lexer.lpp" return LEFT_OP; YY_BREAK case 107: YY_RULE_SETUP -#line 274 "glsl_lexer.lpp" +#line 277 "glsl_lexer.lpp" return RIGHT_OP; YY_BREAK case 108: YY_RULE_SETUP -#line 276 "glsl_lexer.lpp" +#line 279 "glsl_lexer.lpp" return MUL_ASSIGN; YY_BREAK case 109: YY_RULE_SETUP -#line 277 "glsl_lexer.lpp" +#line 280 "glsl_lexer.lpp" return DIV_ASSIGN; YY_BREAK case 110: YY_RULE_SETUP -#line 278 "glsl_lexer.lpp" +#line 281 "glsl_lexer.lpp" return ADD_ASSIGN; YY_BREAK case 111: YY_RULE_SETUP -#line 279 "glsl_lexer.lpp" +#line 282 "glsl_lexer.lpp" return MOD_ASSIGN; YY_BREAK case 112: YY_RULE_SETUP -#line 280 "glsl_lexer.lpp" +#line 283 "glsl_lexer.lpp" return LEFT_ASSIGN; YY_BREAK case 113: YY_RULE_SETUP -#line 281 "glsl_lexer.lpp" +#line 284 "glsl_lexer.lpp" return RIGHT_ASSIGN; YY_BREAK case 114: YY_RULE_SETUP -#line 282 "glsl_lexer.lpp" +#line 285 "glsl_lexer.lpp" return AND_ASSIGN; YY_BREAK case 115: YY_RULE_SETUP -#line 283 "glsl_lexer.lpp" +#line 286 "glsl_lexer.lpp" return XOR_ASSIGN; YY_BREAK case 116: YY_RULE_SETUP -#line 284 "glsl_lexer.lpp" +#line 287 "glsl_lexer.lpp" return OR_ASSIGN; YY_BREAK case 117: YY_RULE_SETUP -#line 285 "glsl_lexer.lpp" +#line 288 "glsl_lexer.lpp" return SUB_ASSIGN; YY_BREAK case 118: YY_RULE_SETUP -#line 287 "glsl_lexer.lpp" +#line 290 "glsl_lexer.lpp" { yylval->n = strtol(yytext, NULL, 10); return IS_UINT ? UINTCONSTANT : INTCONSTANT; @@ -2067,7 +2060,7 @@ YY_RULE_SETUP YY_BREAK case 119: YY_RULE_SETUP -#line 291 "glsl_lexer.lpp" +#line 294 "glsl_lexer.lpp" { yylval->n = strtol(yytext + 2, NULL, 16); return IS_UINT ? UINTCONSTANT : INTCONSTANT; @@ -2075,7 +2068,7 @@ YY_RULE_SETUP YY_BREAK case 120: YY_RULE_SETUP -#line 295 "glsl_lexer.lpp" +#line 298 "glsl_lexer.lpp" { yylval->n = strtol(yytext, NULL, 8); return IS_UINT ? UINTCONSTANT : INTCONSTANT; @@ -2083,7 +2076,7 @@ YY_RULE_SETUP YY_BREAK case 121: YY_RULE_SETUP -#line 300 "glsl_lexer.lpp" +#line 303 "glsl_lexer.lpp" { yylval->real = glsl_strtod(yytext, NULL); return FLOATCONSTANT; @@ -2091,7 +2084,7 @@ YY_RULE_SETUP YY_BREAK case 122: YY_RULE_SETUP -#line 304 "glsl_lexer.lpp" +#line 307 "glsl_lexer.lpp" { yylval->real = glsl_strtod(yytext, NULL); return FLOATCONSTANT; @@ -2099,7 +2092,7 @@ YY_RULE_SETUP YY_BREAK case 123: YY_RULE_SETUP -#line 308 "glsl_lexer.lpp" +#line 311 "glsl_lexer.lpp" { yylval->real = glsl_strtod(yytext, NULL); return FLOATCONSTANT; @@ -2107,7 +2100,7 @@ YY_RULE_SETUP YY_BREAK case 124: YY_RULE_SETUP -#line 312 "glsl_lexer.lpp" +#line 315 "glsl_lexer.lpp" { yylval->real = glsl_strtod(yytext, NULL); return FLOATCONSTANT; @@ -2115,7 +2108,7 @@ YY_RULE_SETUP YY_BREAK case 125: YY_RULE_SETUP -#line 316 "glsl_lexer.lpp" +#line 319 "glsl_lexer.lpp" { yylval->real = glsl_strtod(yytext, NULL); return FLOATCONSTANT; @@ -2123,7 +2116,7 @@ YY_RULE_SETUP YY_BREAK case 126: YY_RULE_SETUP -#line 321 "glsl_lexer.lpp" +#line 324 "glsl_lexer.lpp" { yylval->n = 1; return BOOLCONSTANT; @@ -2131,7 +2124,7 @@ YY_RULE_SETUP YY_BREAK case 127: YY_RULE_SETUP -#line 325 "glsl_lexer.lpp" +#line 328 "glsl_lexer.lpp" { yylval->n = 0; return BOOLCONSTANT; @@ -2140,427 +2133,427 @@ YY_RULE_SETUP /* Reserved words in GLSL 1.10. */ case 128: YY_RULE_SETUP -#line 332 "glsl_lexer.lpp" +#line 335 "glsl_lexer.lpp" KEYWORD(110 || ES, 999, ASM); YY_BREAK case 129: YY_RULE_SETUP -#line 333 "glsl_lexer.lpp" +#line 336 "glsl_lexer.lpp" KEYWORD(110 || ES, 999, CLASS); YY_BREAK case 130: YY_RULE_SETUP -#line 334 "glsl_lexer.lpp" +#line 337 "glsl_lexer.lpp" KEYWORD(110 || ES, 999, UNION); YY_BREAK case 131: YY_RULE_SETUP -#line 335 "glsl_lexer.lpp" +#line 338 "glsl_lexer.lpp" KEYWORD(110 || ES, 999, ENUM); YY_BREAK case 132: YY_RULE_SETUP -#line 336 "glsl_lexer.lpp" +#line 339 "glsl_lexer.lpp" KEYWORD(110 || ES, 999, TYPEDEF); YY_BREAK case 133: YY_RULE_SETUP -#line 337 "glsl_lexer.lpp" +#line 340 "glsl_lexer.lpp" KEYWORD(110 || ES, 999, TEMPLATE); YY_BREAK case 134: YY_RULE_SETUP -#line 338 "glsl_lexer.lpp" +#line 341 "glsl_lexer.lpp" KEYWORD(110 || ES, 999, THIS); YY_BREAK case 135: YY_RULE_SETUP -#line 339 "glsl_lexer.lpp" +#line 342 "glsl_lexer.lpp" KEYWORD(110 || ES, 999, PACKED_TOK); YY_BREAK case 136: YY_RULE_SETUP -#line 340 "glsl_lexer.lpp" +#line 343 "glsl_lexer.lpp" KEYWORD(110 || ES, 999, GOTO); YY_BREAK case 137: YY_RULE_SETUP -#line 341 "glsl_lexer.lpp" +#line 344 "glsl_lexer.lpp" KEYWORD(110 || ES, 130, SWITCH); YY_BREAK case 138: YY_RULE_SETUP -#line 342 "glsl_lexer.lpp" +#line 345 "glsl_lexer.lpp" KEYWORD(110 || ES, 130, DEFAULT); YY_BREAK case 139: YY_RULE_SETUP -#line 343 "glsl_lexer.lpp" +#line 346 "glsl_lexer.lpp" KEYWORD(110 || ES, 999, INLINE_TOK); YY_BREAK case 140: YY_RULE_SETUP -#line 344 "glsl_lexer.lpp" +#line 347 "glsl_lexer.lpp" KEYWORD(110 || ES, 999, NOINLINE); YY_BREAK case 141: YY_RULE_SETUP -#line 345 "glsl_lexer.lpp" +#line 348 "glsl_lexer.lpp" KEYWORD(110 || ES, 999, VOLATILE); YY_BREAK case 142: YY_RULE_SETUP -#line 346 "glsl_lexer.lpp" +#line 349 "glsl_lexer.lpp" KEYWORD(110 || ES, 999, PUBLIC_TOK); YY_BREAK case 143: YY_RULE_SETUP -#line 347 "glsl_lexer.lpp" +#line 350 "glsl_lexer.lpp" KEYWORD(110 || ES, 999, STATIC); YY_BREAK case 144: YY_RULE_SETUP -#line 348 "glsl_lexer.lpp" +#line 351 "glsl_lexer.lpp" KEYWORD(110 || ES, 999, EXTERN); YY_BREAK case 145: YY_RULE_SETUP -#line 349 "glsl_lexer.lpp" +#line 352 "glsl_lexer.lpp" KEYWORD(110 || ES, 999, EXTERNAL); YY_BREAK case 146: YY_RULE_SETUP -#line 350 "glsl_lexer.lpp" +#line 353 "glsl_lexer.lpp" KEYWORD(110 || ES, 999, INTERFACE); YY_BREAK case 147: YY_RULE_SETUP -#line 351 "glsl_lexer.lpp" +#line 354 "glsl_lexer.lpp" KEYWORD(110 || ES, 999, LONG_TOK); YY_BREAK case 148: YY_RULE_SETUP -#line 352 "glsl_lexer.lpp" +#line 355 "glsl_lexer.lpp" KEYWORD(110 || ES, 999, SHORT_TOK); YY_BREAK case 149: YY_RULE_SETUP -#line 353 "glsl_lexer.lpp" +#line 356 "glsl_lexer.lpp" KEYWORD(110 || ES, 400, DOUBLE_TOK); YY_BREAK case 150: YY_RULE_SETUP -#line 354 "glsl_lexer.lpp" +#line 357 "glsl_lexer.lpp" KEYWORD(110 || ES, 999, HALF); YY_BREAK case 151: YY_RULE_SETUP -#line 355 "glsl_lexer.lpp" +#line 358 "glsl_lexer.lpp" KEYWORD(110 || ES, 999, FIXED_TOK); YY_BREAK case 152: YY_RULE_SETUP -#line 356 "glsl_lexer.lpp" +#line 359 "glsl_lexer.lpp" KEYWORD(110 || ES, 999, UNSIGNED); YY_BREAK case 153: YY_RULE_SETUP -#line 357 "glsl_lexer.lpp" +#line 360 "glsl_lexer.lpp" KEYWORD(110 || ES, 999, INPUT_TOK); YY_BREAK case 154: YY_RULE_SETUP -#line 358 "glsl_lexer.lpp" +#line 361 "glsl_lexer.lpp" KEYWORD(110 || ES, 999, OUTPUT); YY_BREAK case 155: YY_RULE_SETUP -#line 359 "glsl_lexer.lpp" +#line 362 "glsl_lexer.lpp" KEYWORD(110 || ES, 999, HVEC2); YY_BREAK case 156: YY_RULE_SETUP -#line 360 "glsl_lexer.lpp" +#line 363 "glsl_lexer.lpp" KEYWORD(110 || ES, 999, HVEC3); YY_BREAK case 157: YY_RULE_SETUP -#line 361 "glsl_lexer.lpp" +#line 364 "glsl_lexer.lpp" KEYWORD(110 || ES, 999, HVEC4); YY_BREAK case 158: YY_RULE_SETUP -#line 362 "glsl_lexer.lpp" +#line 365 "glsl_lexer.lpp" KEYWORD(110 || ES, 400, DVEC2); YY_BREAK case 159: YY_RULE_SETUP -#line 363 "glsl_lexer.lpp" +#line 366 "glsl_lexer.lpp" KEYWORD(110 || ES, 400, DVEC3); YY_BREAK case 160: YY_RULE_SETUP -#line 364 "glsl_lexer.lpp" +#line 367 "glsl_lexer.lpp" KEYWORD(110 || ES, 400, DVEC4); YY_BREAK case 161: YY_RULE_SETUP -#line 365 "glsl_lexer.lpp" +#line 368 "glsl_lexer.lpp" KEYWORD(110 || ES, 999, FVEC2); YY_BREAK case 162: YY_RULE_SETUP -#line 366 "glsl_lexer.lpp" +#line 369 "glsl_lexer.lpp" KEYWORD(110 || ES, 999, FVEC3); YY_BREAK case 163: YY_RULE_SETUP -#line 367 "glsl_lexer.lpp" +#line 370 "glsl_lexer.lpp" KEYWORD(110 || ES, 999, FVEC4); YY_BREAK case 164: YY_RULE_SETUP -#line 368 "glsl_lexer.lpp" +#line 371 "glsl_lexer.lpp" return SAMPLER2DRECT; YY_BREAK case 165: YY_RULE_SETUP -#line 369 "glsl_lexer.lpp" +#line 372 "glsl_lexer.lpp" KEYWORD(110 || ES, 999, SAMPLER3DRECT); YY_BREAK case 166: YY_RULE_SETUP -#line 370 "glsl_lexer.lpp" +#line 373 "glsl_lexer.lpp" return SAMPLER2DRECTSHADOW; YY_BREAK case 167: YY_RULE_SETUP -#line 371 "glsl_lexer.lpp" +#line 374 "glsl_lexer.lpp" KEYWORD(110 || ES, 999, SIZEOF); YY_BREAK case 168: YY_RULE_SETUP -#line 372 "glsl_lexer.lpp" +#line 375 "glsl_lexer.lpp" KEYWORD(110 || ES, 999, CAST); YY_BREAK case 169: YY_RULE_SETUP -#line 373 "glsl_lexer.lpp" +#line 376 "glsl_lexer.lpp" KEYWORD(110 || ES, 999, NAMESPACE); YY_BREAK case 170: YY_RULE_SETUP -#line 374 "glsl_lexer.lpp" +#line 377 "glsl_lexer.lpp" KEYWORD(110 || ES, 999, USING); YY_BREAK /* Additional reserved words in GLSL 1.20. */ case 171: YY_RULE_SETUP -#line 377 "glsl_lexer.lpp" +#line 380 "glsl_lexer.lpp" KEYWORD(120, 130 || ES, LOWP); YY_BREAK case 172: YY_RULE_SETUP -#line 378 "glsl_lexer.lpp" +#line 381 "glsl_lexer.lpp" KEYWORD(120, 130 || ES, MEDIUMP); YY_BREAK case 173: YY_RULE_SETUP -#line 379 "glsl_lexer.lpp" +#line 382 "glsl_lexer.lpp" KEYWORD(120, 130 || ES, HIGHP); YY_BREAK case 174: YY_RULE_SETUP -#line 380 "glsl_lexer.lpp" +#line 383 "glsl_lexer.lpp" KEYWORD(120, 130 || ES, PRECISION); YY_BREAK /* Additional reserved words in GLSL 1.30. */ case 175: YY_RULE_SETUP -#line 383 "glsl_lexer.lpp" +#line 386 "glsl_lexer.lpp" KEYWORD(130, 130, CASE); YY_BREAK case 176: YY_RULE_SETUP -#line 384 "glsl_lexer.lpp" +#line 387 "glsl_lexer.lpp" KEYWORD(130, 999, COMMON); YY_BREAK case 177: YY_RULE_SETUP -#line 385 "glsl_lexer.lpp" +#line 388 "glsl_lexer.lpp" KEYWORD(130, 999, PARTITION); YY_BREAK case 178: YY_RULE_SETUP -#line 386 "glsl_lexer.lpp" +#line 389 "glsl_lexer.lpp" KEYWORD(130, 999, ACTIVE); YY_BREAK case 179: YY_RULE_SETUP -#line 387 "glsl_lexer.lpp" +#line 390 "glsl_lexer.lpp" KEYWORD(130 || ES, 999, SUPERP); YY_BREAK case 180: YY_RULE_SETUP -#line 388 "glsl_lexer.lpp" +#line 391 "glsl_lexer.lpp" KEYWORD(130, 140, SAMPLERBUFFER); YY_BREAK case 181: YY_RULE_SETUP -#line 389 "glsl_lexer.lpp" +#line 392 "glsl_lexer.lpp" KEYWORD(130, 999, FILTER); YY_BREAK case 182: YY_RULE_SETUP -#line 390 "glsl_lexer.lpp" +#line 393 "glsl_lexer.lpp" KEYWORD(130, 999, IMAGE1D); YY_BREAK case 183: YY_RULE_SETUP -#line 391 "glsl_lexer.lpp" +#line 394 "glsl_lexer.lpp" KEYWORD(130, 999, IMAGE2D); YY_BREAK case 184: YY_RULE_SETUP -#line 392 "glsl_lexer.lpp" +#line 395 "glsl_lexer.lpp" KEYWORD(130, 999, IMAGE3D); YY_BREAK case 185: YY_RULE_SETUP -#line 393 "glsl_lexer.lpp" +#line 396 "glsl_lexer.lpp" KEYWORD(130, 999, IMAGECUBE); YY_BREAK case 186: YY_RULE_SETUP -#line 394 "glsl_lexer.lpp" +#line 397 "glsl_lexer.lpp" KEYWORD(130, 999, IIMAGE1D); YY_BREAK case 187: YY_RULE_SETUP -#line 395 "glsl_lexer.lpp" +#line 398 "glsl_lexer.lpp" KEYWORD(130, 999, IIMAGE2D); YY_BREAK case 188: YY_RULE_SETUP -#line 396 "glsl_lexer.lpp" +#line 399 "glsl_lexer.lpp" KEYWORD(130, 999, IIMAGE3D); YY_BREAK case 189: YY_RULE_SETUP -#line 397 "glsl_lexer.lpp" +#line 400 "glsl_lexer.lpp" KEYWORD(130, 999, IIMAGECUBE); YY_BREAK case 190: YY_RULE_SETUP -#line 398 "glsl_lexer.lpp" +#line 401 "glsl_lexer.lpp" KEYWORD(130, 999, UIMAGE1D); YY_BREAK case 191: YY_RULE_SETUP -#line 399 "glsl_lexer.lpp" +#line 402 "glsl_lexer.lpp" KEYWORD(130, 999, UIMAGE2D); YY_BREAK case 192: YY_RULE_SETUP -#line 400 "glsl_lexer.lpp" +#line 403 "glsl_lexer.lpp" KEYWORD(130, 999, UIMAGE3D); YY_BREAK case 193: YY_RULE_SETUP -#line 401 "glsl_lexer.lpp" +#line 404 "glsl_lexer.lpp" KEYWORD(130, 999, UIMAGECUBE); YY_BREAK case 194: YY_RULE_SETUP -#line 402 "glsl_lexer.lpp" +#line 405 "glsl_lexer.lpp" KEYWORD(130, 999, IMAGE1DARRAY); YY_BREAK case 195: YY_RULE_SETUP -#line 403 "glsl_lexer.lpp" +#line 406 "glsl_lexer.lpp" KEYWORD(130, 999, IMAGE2DARRAY); YY_BREAK case 196: YY_RULE_SETUP -#line 404 "glsl_lexer.lpp" +#line 407 "glsl_lexer.lpp" KEYWORD(130, 999, IIMAGE1DARRAY); YY_BREAK case 197: YY_RULE_SETUP -#line 405 "glsl_lexer.lpp" +#line 408 "glsl_lexer.lpp" KEYWORD(130, 999, IIMAGE2DARRAY); YY_BREAK case 198: YY_RULE_SETUP -#line 406 "glsl_lexer.lpp" +#line 409 "glsl_lexer.lpp" KEYWORD(130, 999, UIMAGE1DARRAY); YY_BREAK case 199: YY_RULE_SETUP -#line 407 "glsl_lexer.lpp" +#line 410 "glsl_lexer.lpp" KEYWORD(130, 999, UIMAGE2DARRAY); YY_BREAK case 200: YY_RULE_SETUP -#line 408 "glsl_lexer.lpp" +#line 411 "glsl_lexer.lpp" KEYWORD(130, 999, IMAGE1DSHADOW); YY_BREAK case 201: YY_RULE_SETUP -#line 409 "glsl_lexer.lpp" +#line 412 "glsl_lexer.lpp" KEYWORD(130, 999, IMAGE2DSHADOW); YY_BREAK case 202: YY_RULE_SETUP -#line 410 "glsl_lexer.lpp" +#line 413 "glsl_lexer.lpp" KEYWORD(130, 999, IMAGE1DARRAYSHADOW); YY_BREAK case 203: YY_RULE_SETUP -#line 411 "glsl_lexer.lpp" +#line 414 "glsl_lexer.lpp" KEYWORD(130, 999, IMAGE2DARRAYSHADOW); YY_BREAK case 204: YY_RULE_SETUP -#line 412 "glsl_lexer.lpp" +#line 415 "glsl_lexer.lpp" KEYWORD(130, 999, IMAGEBUFFER); YY_BREAK case 205: YY_RULE_SETUP -#line 413 "glsl_lexer.lpp" +#line 416 "glsl_lexer.lpp" KEYWORD(130, 999, IIMAGEBUFFER); YY_BREAK case 206: YY_RULE_SETUP -#line 414 "glsl_lexer.lpp" +#line 417 "glsl_lexer.lpp" KEYWORD(130, 999, UIMAGEBUFFER); YY_BREAK case 207: YY_RULE_SETUP -#line 415 "glsl_lexer.lpp" +#line 418 "glsl_lexer.lpp" KEYWORD(130, 999, ROW_MAJOR); YY_BREAK case 208: YY_RULE_SETUP -#line 417 "glsl_lexer.lpp" +#line 420 "glsl_lexer.lpp" { struct _mesa_glsl_parse_state *state = yyextra; void *ctx = state; - yylval->identifier = talloc_strdup(ctx, yytext); - return IDENTIFIER; + yylval->identifier = ralloc_strdup(ctx, yytext); + return classify_identifier(state, yytext); } YY_BREAK case 209: YY_RULE_SETUP -#line 424 "glsl_lexer.lpp" +#line 427 "glsl_lexer.lpp" { return yytext[0]; } YY_BREAK case 210: YY_RULE_SETUP -#line 426 "glsl_lexer.lpp" +#line 429 "glsl_lexer.lpp" ECHO; YY_BREAK -#line 2564 "glsl_lexer.cpp" +#line 2557 "glsl_lexer.cpp" case YY_STATE_EOF(INITIAL): case YY_STATE_EOF(PP): case YY_STATE_EOF(PRAGMA): @@ -3296,8 +3289,8 @@ YY_BUFFER_STATE _mesa_glsl__scan_string (yyconst char * yystr , yyscan_t yyscann /** Setup the input buffer state to scan the given bytes. The next call to _mesa_glsl_lex() will * scan from a @e copy of @a bytes. - * @param yybytes the byte buffer to scan - * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. + * @param bytes the byte buffer to scan + * @param len the number of bytes in the buffer pointed to by @a bytes. * @param yyscanner The scanner object. * @return the newly allocated buffer state object. */ @@ -3703,9 +3696,20 @@ void _mesa_glsl_free (void * ptr , yyscan_t yyscanner) #define YYTABLES_NAME "yytables" -#line 426 "glsl_lexer.lpp" +#line 429 "glsl_lexer.lpp" + +int +classify_identifier(struct _mesa_glsl_parse_state *state, const char *name) +{ + if (state->symbols->get_variable(name) || state->symbols->get_function(name)) + return IDENTIFIER; + else if (state->symbols->get_type(name)) + return TYPE_IDENTIFIER; + else + return NEW_IDENTIFIER; +} void _mesa_glsl_lexer_ctor(struct _mesa_glsl_parse_state *state, const char *string) diff --git a/src/glsl/glsl_lexer.lpp b/src/glsl/glsl_lexer.lpp index d30759be2b8..e4c469f9e0a 100644 --- a/src/glsl/glsl_lexer.lpp +++ b/src/glsl/glsl_lexer.lpp @@ -27,6 +27,8 @@ #include "glsl_parser_extras.h" #include "glsl_parser.h" +static int classify_identifier(struct _mesa_glsl_parse_state *, const char *); + #define YY_USER_ACTION \ do { \ yylloc->source = 0; \ @@ -62,7 +64,7 @@ return ERROR_TOK; \ } else { \ yylval->identifier = strdup(yytext); \ - return IDENTIFIER; \ + return classify_identifier(yyextra, yytext); \ } \ } while (0) @@ -252,8 +254,9 @@ void return VOID_TOK; layout { if ((yyextra->language_version >= 140) + || yyextra->AMD_conservative_depth_enable || yyextra->ARB_explicit_attrib_location_enable - || (yyextra->ARB_fragment_coord_conventions_enable)){ + || yyextra->ARB_fragment_coord_conventions_enable) { return LAYOUT_TOK; } else { yylval->identifier = strdup(yytext); @@ -417,14 +420,25 @@ row_major KEYWORD(130, 999, ROW_MAJOR); [_a-zA-Z][_a-zA-Z0-9]* { struct _mesa_glsl_parse_state *state = yyextra; void *ctx = state; - yylval->identifier = talloc_strdup(ctx, yytext); - return IDENTIFIER; + yylval->identifier = ralloc_strdup(ctx, yytext); + return classify_identifier(state, yytext); } . { return yytext[0]; } %% +int +classify_identifier(struct _mesa_glsl_parse_state *state, const char *name) +{ + if (state->symbols->get_variable(name) || state->symbols->get_function(name)) + return IDENTIFIER; + else if (state->symbols->get_type(name)) + return TYPE_IDENTIFIER; + else + return NEW_IDENTIFIER; +} + void _mesa_glsl_lexer_ctor(struct _mesa_glsl_parse_state *state, const char *string) { diff --git a/src/glsl/glsl_parser.cpp b/src/glsl/glsl_parser.cpp index 8b196ae7fc6..1db7e901a96 100644 --- a/src/glsl/glsl_parser.cpp +++ b/src/glsl/glsl_parser.cpp @@ -214,123 +214,125 @@ VOID_TOK = 329, WHILE = 330, IDENTIFIER = 331, - FLOATCONSTANT = 332, - INTCONSTANT = 333, - UINTCONSTANT = 334, - BOOLCONSTANT = 335, - FIELD_SELECTION = 336, - LEFT_OP = 337, - RIGHT_OP = 338, - INC_OP = 339, - DEC_OP = 340, - LE_OP = 341, - GE_OP = 342, - EQ_OP = 343, - NE_OP = 344, - AND_OP = 345, - OR_OP = 346, - XOR_OP = 347, - MUL_ASSIGN = 348, - DIV_ASSIGN = 349, - ADD_ASSIGN = 350, - MOD_ASSIGN = 351, - LEFT_ASSIGN = 352, - RIGHT_ASSIGN = 353, - AND_ASSIGN = 354, - XOR_ASSIGN = 355, - OR_ASSIGN = 356, - SUB_ASSIGN = 357, - INVARIANT = 358, - LOWP = 359, - MEDIUMP = 360, - HIGHP = 361, - SUPERP = 362, - PRECISION = 363, - VERSION = 364, - EXTENSION = 365, - LINE = 366, - COLON = 367, - EOL = 368, - INTERFACE = 369, - OUTPUT = 370, - PRAGMA_DEBUG_ON = 371, - PRAGMA_DEBUG_OFF = 372, - PRAGMA_OPTIMIZE_ON = 373, - PRAGMA_OPTIMIZE_OFF = 374, - PRAGMA_INVARIANT_ALL = 375, - LAYOUT_TOK = 376, - ASM = 377, - CLASS = 378, - UNION = 379, - ENUM = 380, - TYPEDEF = 381, - TEMPLATE = 382, - THIS = 383, - PACKED_TOK = 384, - GOTO = 385, - INLINE_TOK = 386, - NOINLINE = 387, - VOLATILE = 388, - PUBLIC_TOK = 389, - STATIC = 390, - EXTERN = 391, - EXTERNAL = 392, - LONG_TOK = 393, - SHORT_TOK = 394, - DOUBLE_TOK = 395, - HALF = 396, - FIXED_TOK = 397, - UNSIGNED = 398, - INPUT_TOK = 399, - OUPTUT = 400, - HVEC2 = 401, - HVEC3 = 402, - HVEC4 = 403, - DVEC2 = 404, - DVEC3 = 405, - DVEC4 = 406, - FVEC2 = 407, - FVEC3 = 408, - FVEC4 = 409, - SAMPLER2DRECT = 410, - SAMPLER3DRECT = 411, - SAMPLER2DRECTSHADOW = 412, - SIZEOF = 413, - CAST = 414, - NAMESPACE = 415, - USING = 416, - ERROR_TOK = 417, - COMMON = 418, - PARTITION = 419, - ACTIVE = 420, - SAMPLERBUFFER = 421, - FILTER = 422, - IMAGE1D = 423, - IMAGE2D = 424, - IMAGE3D = 425, - IMAGECUBE = 426, - IMAGE1DARRAY = 427, - IMAGE2DARRAY = 428, - IIMAGE1D = 429, - IIMAGE2D = 430, - IIMAGE3D = 431, - IIMAGECUBE = 432, - IIMAGE1DARRAY = 433, - IIMAGE2DARRAY = 434, - UIMAGE1D = 435, - UIMAGE2D = 436, - UIMAGE3D = 437, - UIMAGECUBE = 438, - UIMAGE1DARRAY = 439, - UIMAGE2DARRAY = 440, - IMAGE1DSHADOW = 441, - IMAGE2DSHADOW = 442, - IMAGEBUFFER = 443, - IIMAGEBUFFER = 444, - UIMAGEBUFFER = 445, - IMAGE1DARRAYSHADOW = 446, - IMAGE2DARRAYSHADOW = 447, - ROW_MAJOR = 448 + TYPE_IDENTIFIER = 332, + NEW_IDENTIFIER = 333, + FLOATCONSTANT = 334, + INTCONSTANT = 335, + UINTCONSTANT = 336, + BOOLCONSTANT = 337, + FIELD_SELECTION = 338, + LEFT_OP = 339, + RIGHT_OP = 340, + INC_OP = 341, + DEC_OP = 342, + LE_OP = 343, + GE_OP = 344, + EQ_OP = 345, + NE_OP = 346, + AND_OP = 347, + OR_OP = 348, + XOR_OP = 349, + MUL_ASSIGN = 350, + DIV_ASSIGN = 351, + ADD_ASSIGN = 352, + MOD_ASSIGN = 353, + LEFT_ASSIGN = 354, + RIGHT_ASSIGN = 355, + AND_ASSIGN = 356, + XOR_ASSIGN = 357, + OR_ASSIGN = 358, + SUB_ASSIGN = 359, + INVARIANT = 360, + LOWP = 361, + MEDIUMP = 362, + HIGHP = 363, + SUPERP = 364, + PRECISION = 365, + VERSION = 366, + EXTENSION = 367, + LINE = 368, + COLON = 369, + EOL = 370, + INTERFACE = 371, + OUTPUT = 372, + PRAGMA_DEBUG_ON = 373, + PRAGMA_DEBUG_OFF = 374, + PRAGMA_OPTIMIZE_ON = 375, + PRAGMA_OPTIMIZE_OFF = 376, + PRAGMA_INVARIANT_ALL = 377, + LAYOUT_TOK = 378, + ASM = 379, + CLASS = 380, + UNION = 381, + ENUM = 382, + TYPEDEF = 383, + TEMPLATE = 384, + THIS = 385, + PACKED_TOK = 386, + GOTO = 387, + INLINE_TOK = 388, + NOINLINE = 389, + VOLATILE = 390, + PUBLIC_TOK = 391, + STATIC = 392, + EXTERN = 393, + EXTERNAL = 394, + LONG_TOK = 395, + SHORT_TOK = 396, + DOUBLE_TOK = 397, + HALF = 398, + FIXED_TOK = 399, + UNSIGNED = 400, + INPUT_TOK = 401, + OUPTUT = 402, + HVEC2 = 403, + HVEC3 = 404, + HVEC4 = 405, + DVEC2 = 406, + DVEC3 = 407, + DVEC4 = 408, + FVEC2 = 409, + FVEC3 = 410, + FVEC4 = 411, + SAMPLER2DRECT = 412, + SAMPLER3DRECT = 413, + SAMPLER2DRECTSHADOW = 414, + SIZEOF = 415, + CAST = 416, + NAMESPACE = 417, + USING = 418, + ERROR_TOK = 419, + COMMON = 420, + PARTITION = 421, + ACTIVE = 422, + SAMPLERBUFFER = 423, + FILTER = 424, + IMAGE1D = 425, + IMAGE2D = 426, + IMAGE3D = 427, + IMAGECUBE = 428, + IMAGE1DARRAY = 429, + IMAGE2DARRAY = 430, + IIMAGE1D = 431, + IIMAGE2D = 432, + IIMAGE3D = 433, + IIMAGECUBE = 434, + IIMAGE1DARRAY = 435, + IIMAGE2DARRAY = 436, + UIMAGE1D = 437, + UIMAGE2D = 438, + UIMAGE3D = 439, + UIMAGECUBE = 440, + UIMAGE1DARRAY = 441, + UIMAGE2DARRAY = 442, + IMAGE1DSHADOW = 443, + IMAGE2DSHADOW = 444, + IMAGEBUFFER = 445, + IIMAGEBUFFER = 446, + UIMAGEBUFFER = 447, + IMAGE1DARRAYSHADOW = 448, + IMAGE2DARRAYSHADOW = 449, + ROW_MAJOR = 450 }; #endif @@ -374,7 +376,7 @@ typedef union YYSTYPE /* Line 214 of yacc.c */ -#line 378 "glsl_parser.cpp" +#line 380 "glsl_parser.cpp" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ @@ -399,7 +401,7 @@ typedef struct YYLTYPE /* Line 264 of yacc.c */ -#line 403 "glsl_parser.cpp" +#line 405 "glsl_parser.cpp" #ifdef short # undef short @@ -616,20 +618,20 @@ union yyalloc /* YYFINAL -- State number of the termination state. */ #define YYFINAL 5 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 3738 +#define YYLAST 3692 /* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 218 +#define YYNTOKENS 220 /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 87 +#define YYNNTS 93 /* YYNRULES -- Number of rules. */ -#define YYNRULES 279 +#define YYNRULES 291 /* YYNRULES -- Number of states. */ -#define YYNSTATES 415 +#define YYNSTATES 434 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 -#define YYMAXUTOK 448 +#define YYMAXUTOK 450 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) @@ -640,16 +642,16 @@ static const yytype_uint8 yytranslate[] = 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 202, 2, 2, 2, 206, 209, 2, - 194, 195, 204, 200, 199, 201, 198, 205, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 213, 215, - 207, 214, 208, 212, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 204, 2, 2, 2, 208, 211, 2, + 196, 197, 206, 202, 201, 203, 200, 207, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 215, 217, + 209, 216, 210, 214, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 196, 2, 197, 210, 2, 2, 2, 2, 2, + 2, 198, 2, 199, 212, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 216, 211, 217, 203, 2, 2, 2, + 2, 2, 2, 218, 213, 219, 205, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -681,7 +683,8 @@ static const yytype_uint8 yytranslate[] = 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, - 185, 186, 187, 188, 189, 190, 191, 192, 193 + 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, + 195 }; #if YYDEBUG @@ -690,151 +693,158 @@ static const yytype_uint8 yytranslate[] = static const yytype_uint16 yyprhs[] = { 0, 0, 3, 4, 9, 10, 14, 17, 20, 23, - 26, 29, 30, 33, 39, 41, 44, 46, 48, 50, - 52, 54, 56, 60, 62, 67, 69, 73, 76, 79, - 81, 83, 85, 89, 92, 95, 98, 100, 103, 107, - 110, 112, 114, 116, 118, 121, 124, 127, 129, 131, - 133, 135, 137, 141, 145, 149, 151, 155, 159, 161, - 165, 169, 171, 175, 179, 183, 187, 189, 193, 197, - 199, 203, 205, 209, 211, 215, 217, 221, 223, 227, - 229, 233, 235, 241, 243, 247, 249, 251, 253, 255, - 257, 259, 261, 263, 265, 267, 269, 271, 275, 277, - 280, 283, 288, 291, 293, 295, 298, 302, 306, 309, - 315, 319, 322, 326, 329, 330, 332, 334, 336, 338, - 340, 344, 350, 357, 365, 374, 380, 382, 385, 390, - 396, 403, 411, 416, 419, 421, 424, 429, 431, 435, - 437, 441, 443, 445, 447, 449, 451, 453, 456, 458, - 461, 464, 468, 470, 472, 474, 476, 479, 481, 483, - 486, 489, 491, 493, 496, 498, 502, 507, 509, 511, - 513, 515, 517, 519, 521, 523, 525, 527, 529, 531, - 533, 535, 537, 539, 541, 543, 545, 547, 549, 551, - 553, 555, 557, 559, 561, 563, 565, 567, 569, 571, - 573, 575, 577, 579, 581, 583, 585, 587, 589, 591, - 593, 595, 597, 599, 601, 603, 605, 607, 609, 611, - 613, 615, 617, 619, 621, 627, 632, 634, 637, 641, - 643, 647, 649, 654, 656, 658, 660, 662, 664, 666, - 668, 670, 672, 674, 676, 679, 683, 685, 687, 690, - 694, 696, 699, 701, 704, 710, 714, 716, 718, 723, - 729, 733, 736, 742, 750, 757, 759, 761, 763, 764, - 767, 771, 774, 777, 780, 784, 787, 789, 791, 793 + 26, 29, 30, 33, 35, 37, 39, 45, 47, 50, + 52, 54, 56, 58, 60, 62, 64, 68, 70, 75, + 77, 81, 84, 87, 89, 91, 93, 97, 100, 103, + 106, 108, 111, 115, 118, 120, 122, 124, 127, 130, + 133, 135, 138, 142, 145, 147, 150, 153, 156, 158, + 160, 162, 164, 166, 170, 174, 178, 180, 184, 188, + 190, 194, 198, 200, 204, 208, 212, 216, 218, 222, + 226, 228, 232, 234, 238, 240, 244, 246, 250, 252, + 256, 258, 262, 264, 270, 272, 276, 278, 280, 282, + 284, 286, 288, 290, 292, 294, 296, 298, 300, 304, + 306, 309, 312, 317, 320, 322, 324, 327, 331, 335, + 338, 344, 348, 351, 355, 358, 359, 361, 363, 365, + 367, 369, 373, 379, 386, 394, 403, 409, 411, 414, + 419, 425, 432, 440, 445, 448, 450, 453, 458, 460, + 464, 466, 470, 472, 474, 476, 478, 480, 482, 485, + 487, 490, 493, 497, 499, 501, 503, 505, 508, 510, + 512, 515, 518, 520, 522, 525, 527, 531, 536, 538, + 540, 542, 544, 546, 548, 550, 552, 554, 556, 558, + 560, 562, 564, 566, 568, 570, 572, 574, 576, 578, + 580, 582, 584, 586, 588, 590, 592, 594, 596, 598, + 600, 602, 604, 606, 608, 610, 612, 614, 616, 618, + 620, 622, 624, 626, 628, 630, 632, 634, 636, 638, + 640, 642, 644, 646, 648, 650, 656, 661, 663, 666, + 670, 672, 676, 678, 683, 685, 687, 689, 691, 693, + 695, 697, 699, 701, 703, 705, 708, 709, 714, 716, + 718, 721, 725, 727, 730, 732, 735, 741, 745, 747, + 749, 754, 760, 764, 767, 773, 781, 788, 790, 792, + 794, 795, 798, 802, 805, 808, 811, 815, 818, 820, + 822, 824 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int16 yyrhs[] = { - 219, 0, -1, -1, 221, 223, 220, 225, -1, -1, - 109, 78, 113, -1, 116, 113, -1, 117, 113, -1, - 118, 113, -1, 119, 113, -1, 120, 113, -1, -1, - 223, 224, -1, 110, 76, 112, 76, 113, -1, 303, - -1, 225, 303, -1, 76, -1, 226, -1, 78, -1, - 79, -1, 77, -1, 80, -1, 194, 253, 195, -1, - 227, -1, 228, 196, 229, 197, -1, 230, -1, 228, - 198, 76, -1, 228, 84, -1, 228, 85, -1, 253, - -1, 231, -1, 232, -1, 228, 198, 232, -1, 234, - 195, -1, 233, 195, -1, 235, 74, -1, 235, -1, - 235, 251, -1, 234, 199, 251, -1, 236, 194, -1, - 274, -1, 76, -1, 81, -1, 228, -1, 84, 237, - -1, 85, 237, -1, 238, 237, -1, 200, -1, 201, - -1, 202, -1, 203, -1, 237, -1, 239, 204, 237, - -1, 239, 205, 237, -1, 239, 206, 237, -1, 239, - -1, 240, 200, 239, -1, 240, 201, 239, -1, 240, - -1, 241, 82, 240, -1, 241, 83, 240, -1, 241, - -1, 242, 207, 241, -1, 242, 208, 241, -1, 242, - 86, 241, -1, 242, 87, 241, -1, 242, -1, 243, - 88, 242, -1, 243, 89, 242, -1, 243, -1, 244, - 209, 243, -1, 244, -1, 245, 210, 244, -1, 245, - -1, 246, 211, 245, -1, 246, -1, 247, 90, 246, - -1, 247, -1, 248, 92, 247, -1, 248, -1, 249, - 91, 248, -1, 249, -1, 249, 212, 253, 213, 251, - -1, 250, -1, 237, 252, 251, -1, 214, -1, 93, - -1, 94, -1, 96, -1, 95, -1, 102, -1, 97, - -1, 98, -1, 99, -1, 100, -1, 101, -1, 251, - -1, 253, 199, 251, -1, 250, -1, 256, 215, -1, - 264, 215, -1, 108, 278, 275, 215, -1, 257, 195, - -1, 259, -1, 258, -1, 259, 261, -1, 258, 199, - 261, -1, 266, 76, 194, -1, 274, 76, -1, 274, - 76, 196, 254, 197, -1, 271, 262, 260, -1, 262, - 260, -1, 271, 262, 263, -1, 262, 263, -1, -1, - 33, -1, 34, -1, 35, -1, 274, -1, 265, -1, - 264, 199, 76, -1, 264, 199, 76, 196, 197, -1, - 264, 199, 76, 196, 254, 197, -1, 264, 199, 76, - 196, 197, 214, 284, -1, 264, 199, 76, 196, 254, - 197, 214, 284, -1, 264, 199, 76, 214, 284, -1, - 266, -1, 266, 76, -1, 266, 76, 196, 197, -1, - 266, 76, 196, 254, 197, -1, 266, 76, 196, 197, - 214, 284, -1, 266, 76, 196, 254, 197, 214, 284, - -1, 266, 76, 214, 284, -1, 103, 76, -1, 274, - -1, 272, 274, -1, 121, 194, 268, 195, -1, 269, - -1, 268, 199, 269, -1, 76, -1, 76, 214, 78, - -1, 40, -1, 39, -1, 38, -1, 4, -1, 273, - -1, 267, -1, 267, 273, -1, 270, -1, 270, 273, - -1, 103, 273, -1, 103, 270, 273, -1, 103, -1, - 4, -1, 3, -1, 37, -1, 32, 37, -1, 33, - -1, 34, -1, 32, 33, -1, 32, 34, -1, 36, - -1, 275, -1, 278, 275, -1, 276, -1, 276, 196, - 197, -1, 276, 196, 254, 197, -1, 277, -1, 279, - -1, 76, -1, 74, -1, 6, -1, 7, -1, 8, - -1, 5, -1, 29, -1, 30, -1, 31, -1, 20, - -1, 21, -1, 22, -1, 23, -1, 24, -1, 25, - -1, 26, -1, 27, -1, 28, -1, 41, -1, 42, - -1, 43, -1, 44, -1, 45, -1, 46, -1, 47, - -1, 48, -1, 49, -1, 50, -1, 51, -1, 155, - -1, 52, -1, 53, -1, 54, -1, 55, -1, 157, - -1, 56, -1, 57, -1, 58, -1, 59, -1, 60, - -1, 61, -1, 62, -1, 63, -1, 64, -1, 65, - -1, 66, -1, 67, -1, 68, -1, 69, -1, 70, - -1, 71, -1, 72, -1, 106, -1, 105, -1, 104, - -1, 73, 76, 216, 280, 217, -1, 73, 216, 280, - 217, -1, 281, -1, 280, 281, -1, 274, 282, 215, - -1, 283, -1, 282, 199, 283, -1, 76, -1, 76, - 196, 254, 197, -1, 251, -1, 255, -1, 288, -1, - 287, -1, 285, -1, 292, -1, 293, -1, 296, -1, - 297, -1, 298, -1, 302, -1, 216, 217, -1, 216, - 291, 217, -1, 290, -1, 287, -1, 216, 217, -1, - 216, 291, 217, -1, 286, -1, 291, 286, -1, 215, - -1, 253, 215, -1, 14, 194, 253, 195, 294, -1, - 286, 12, 286, -1, 286, -1, 253, -1, 266, 76, - 214, 284, -1, 17, 194, 253, 195, 288, -1, 18, - 253, 213, -1, 19, 213, -1, 75, 194, 295, 195, - 289, -1, 11, 286, 75, 194, 253, 195, 215, -1, - 13, 194, 299, 301, 195, 289, -1, 292, -1, 285, - -1, 295, -1, -1, 300, 215, -1, 300, 215, 253, - -1, 10, 215, -1, 9, 215, -1, 16, 215, -1, - 16, 253, 215, -1, 15, 215, -1, 304, -1, 255, - -1, 222, -1, 256, 290, -1 + 221, 0, -1, -1, 223, 225, 222, 228, -1, -1, + 111, 80, 115, -1, 118, 115, -1, 119, 115, -1, + 120, 115, -1, 121, 115, -1, 122, 115, -1, -1, + 225, 227, -1, 76, -1, 77, -1, 78, -1, 112, + 226, 114, 226, 115, -1, 311, -1, 228, 311, -1, + 76, -1, 78, -1, 229, -1, 80, -1, 81, -1, + 79, -1, 82, -1, 196, 260, 197, -1, 230, -1, + 231, 198, 232, 199, -1, 233, -1, 231, 200, 226, + -1, 231, 86, -1, 231, 87, -1, 260, -1, 234, + -1, 235, -1, 231, 200, 240, -1, 237, 197, -1, + 236, 197, -1, 238, 74, -1, 238, -1, 238, 258, + -1, 237, 201, 258, -1, 239, 196, -1, 281, -1, + 229, -1, 83, -1, 242, 197, -1, 241, 197, -1, + 243, 74, -1, 243, -1, 243, 258, -1, 242, 201, + 258, -1, 229, 196, -1, 231, -1, 86, 244, -1, + 87, 244, -1, 245, 244, -1, 202, -1, 203, -1, + 204, -1, 205, -1, 244, -1, 246, 206, 244, -1, + 246, 207, 244, -1, 246, 208, 244, -1, 246, -1, + 247, 202, 246, -1, 247, 203, 246, -1, 247, -1, + 248, 84, 247, -1, 248, 85, 247, -1, 248, -1, + 249, 209, 248, -1, 249, 210, 248, -1, 249, 88, + 248, -1, 249, 89, 248, -1, 249, -1, 250, 90, + 249, -1, 250, 91, 249, -1, 250, -1, 251, 211, + 250, -1, 251, -1, 252, 212, 251, -1, 252, -1, + 253, 213, 252, -1, 253, -1, 254, 92, 253, -1, + 254, -1, 255, 94, 254, -1, 255, -1, 256, 93, + 255, -1, 256, -1, 256, 214, 260, 215, 258, -1, + 257, -1, 244, 259, 258, -1, 216, -1, 95, -1, + 96, -1, 98, -1, 97, -1, 104, -1, 99, -1, + 100, -1, 101, -1, 102, -1, 103, -1, 258, -1, + 260, 201, 258, -1, 257, -1, 263, 217, -1, 271, + 217, -1, 110, 285, 282, 217, -1, 264, 197, -1, + 266, -1, 265, -1, 266, 268, -1, 265, 201, 268, + -1, 273, 229, 196, -1, 281, 226, -1, 281, 226, + 198, 261, 199, -1, 278, 269, 267, -1, 269, 267, + -1, 278, 269, 270, -1, 269, 270, -1, -1, 33, + -1, 34, -1, 35, -1, 281, -1, 272, -1, 271, + 201, 226, -1, 271, 201, 226, 198, 199, -1, 271, + 201, 226, 198, 261, 199, -1, 271, 201, 226, 198, + 199, 216, 291, -1, 271, 201, 226, 198, 261, 199, + 216, 291, -1, 271, 201, 226, 216, 291, -1, 273, + -1, 273, 226, -1, 273, 226, 198, 199, -1, 273, + 226, 198, 261, 199, -1, 273, 226, 198, 199, 216, + 291, -1, 273, 226, 198, 261, 199, 216, 291, -1, + 273, 226, 216, 291, -1, 105, 229, -1, 281, -1, + 279, 281, -1, 123, 196, 275, 197, -1, 276, -1, + 275, 201, 276, -1, 226, -1, 226, 216, 80, -1, + 40, -1, 39, -1, 38, -1, 4, -1, 280, -1, + 274, -1, 274, 280, -1, 277, -1, 277, 280, -1, + 105, 280, -1, 105, 277, 280, -1, 105, -1, 4, + -1, 3, -1, 37, -1, 32, 37, -1, 33, -1, + 34, -1, 32, 33, -1, 32, 34, -1, 36, -1, + 282, -1, 285, 282, -1, 283, -1, 283, 198, 199, + -1, 283, 198, 261, 199, -1, 284, -1, 286, -1, + 77, -1, 74, -1, 6, -1, 7, -1, 8, -1, + 5, -1, 29, -1, 30, -1, 31, -1, 20, -1, + 21, -1, 22, -1, 23, -1, 24, -1, 25, -1, + 26, -1, 27, -1, 28, -1, 41, -1, 42, -1, + 43, -1, 44, -1, 45, -1, 46, -1, 47, -1, + 48, -1, 49, -1, 50, -1, 51, -1, 157, -1, + 52, -1, 53, -1, 54, -1, 55, -1, 159, -1, + 56, -1, 57, -1, 58, -1, 59, -1, 60, -1, + 61, -1, 62, -1, 63, -1, 64, -1, 65, -1, + 66, -1, 67, -1, 68, -1, 69, -1, 70, -1, + 71, -1, 72, -1, 108, -1, 107, -1, 106, -1, + 73, 226, 218, 287, 219, -1, 73, 218, 287, 219, + -1, 288, -1, 287, 288, -1, 281, 289, 217, -1, + 290, -1, 289, 201, 290, -1, 226, -1, 226, 198, + 261, 199, -1, 258, -1, 262, -1, 295, -1, 294, + -1, 292, -1, 300, -1, 301, -1, 304, -1, 305, + -1, 306, -1, 310, -1, 218, 219, -1, -1, 218, + 296, 299, 219, -1, 298, -1, 294, -1, 218, 219, + -1, 218, 299, 219, -1, 293, -1, 299, 293, -1, + 217, -1, 260, 217, -1, 14, 196, 260, 197, 302, + -1, 293, 12, 293, -1, 293, -1, 260, -1, 273, + 226, 216, 291, -1, 17, 196, 260, 197, 295, -1, + 18, 260, 215, -1, 19, 215, -1, 75, 196, 303, + 197, 297, -1, 11, 293, 75, 196, 260, 197, 217, + -1, 13, 196, 307, 309, 197, 297, -1, 300, -1, + 292, -1, 303, -1, -1, 308, 217, -1, 308, 217, + 260, -1, 10, 217, -1, 9, 217, -1, 16, 217, + -1, 16, 260, 217, -1, 15, 217, -1, 312, -1, + 262, -1, 224, -1, 263, 298, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 213, 213, 212, 219, 221, 246, 247, 248, 249, - 250, 262, 264, 268, 277, 285, 296, 300, 307, 314, - 321, 328, 335, 342, 343, 349, 353, 360, 366, 375, - 379, 383, 384, 393, 394, 398, 399, 403, 409, 421, - 425, 431, 438, 449, 450, 456, 462, 472, 473, 474, - 475, 479, 480, 486, 492, 501, 502, 508, 517, 518, - 524, 533, 534, 540, 546, 552, 561, 562, 568, 577, - 578, 587, 588, 597, 598, 607, 608, 617, 618, 627, - 628, 637, 638, 647, 648, 657, 658, 659, 660, 661, - 662, 663, 664, 665, 666, 667, 671, 675, 691, 695, - 699, 703, 712, 716, 717, 721, 726, 734, 745, 755, - 770, 777, 782, 793, 806, 809, 814, 819, 828, 832, - 833, 842, 851, 860, 869, 878, 891, 902, 911, 920, - 929, 938, 947, 956, 970, 977, 988, 995, 996, 1015, - 1044, 1085, 1090, 1095, 1103, 1111, 1112, 1113, 1118, 1119, - 1124, 1129, 1135, 1143, 1148, 1153, 1158, 1164, 1169, 1174, - 1179, 1184, 1192, 1196, 1204, 1205, 1211, 1220, 1226, 1232, - 1241, 1242, 1243, 1244, 1245, 1246, 1247, 1248, 1249, 1250, - 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258, 1259, 1260, - 1261, 1262, 1263, 1264, 1265, 1266, 1267, 1268, 1269, 1270, - 1271, 1272, 1273, 1274, 1275, 1276, 1277, 1278, 1279, 1280, - 1281, 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1289, 1290, - 1291, 1295, 1305, 1315, 1328, 1334, 1343, 1348, 1356, 1371, - 1376, 1384, 1390, 1399, 1403, 1409, 1410, 1414, 1415, 1416, - 1417, 1418, 1419, 1420, 1424, 1430, 1439, 1440, 1444, 1450, - 1459, 1469, 1481, 1487, 1496, 1505, 1510, 1518, 1522, 1536, - 1540, 1541, 1545, 1552, 1559, 1569, 1570, 1574, 1576, 1582, - 1587, 1596, 1602, 1608, 1614, 1620, 1629, 1630, 1631, 1635 + 0, 218, 218, 217, 229, 231, 271, 272, 273, 274, + 275, 287, 289, 293, 294, 295, 299, 308, 316, 327, + 328, 332, 339, 346, 353, 360, 367, 374, 375, 381, + 385, 392, 398, 407, 411, 415, 416, 425, 426, 430, + 431, 435, 441, 453, 457, 463, 470, 480, 481, 485, + 486, 490, 496, 508, 519, 520, 526, 532, 542, 543, + 544, 545, 549, 550, 556, 562, 571, 572, 578, 587, + 588, 594, 603, 604, 610, 616, 622, 631, 632, 638, + 647, 648, 657, 658, 667, 668, 677, 678, 687, 688, + 697, 698, 707, 708, 717, 718, 727, 728, 729, 730, + 731, 732, 733, 734, 735, 736, 737, 741, 745, 761, + 765, 770, 774, 783, 787, 788, 792, 797, 805, 819, + 829, 844, 851, 856, 867, 880, 883, 888, 893, 902, + 906, 907, 917, 927, 937, 947, 957, 971, 982, 991, + 1000, 1009, 1018, 1027, 1036, 1050, 1057, 1068, 1075, 1076, + 1095, 1147, 1188, 1193, 1198, 1206, 1214, 1215, 1216, 1221, + 1222, 1227, 1232, 1238, 1246, 1251, 1256, 1261, 1267, 1272, + 1277, 1282, 1287, 1295, 1299, 1307, 1308, 1314, 1323, 1329, + 1335, 1344, 1345, 1346, 1347, 1348, 1349, 1350, 1351, 1352, + 1353, 1354, 1355, 1356, 1357, 1358, 1359, 1360, 1361, 1362, + 1363, 1364, 1365, 1366, 1367, 1368, 1369, 1370, 1371, 1372, + 1373, 1374, 1375, 1376, 1377, 1378, 1379, 1380, 1381, 1382, + 1383, 1384, 1385, 1386, 1387, 1388, 1389, 1390, 1391, 1392, + 1393, 1394, 1398, 1408, 1418, 1431, 1438, 1447, 1452, 1460, + 1475, 1480, 1488, 1495, 1504, 1508, 1514, 1515, 1519, 1520, + 1521, 1522, 1523, 1524, 1525, 1529, 1536, 1535, 1549, 1550, + 1554, 1560, 1569, 1579, 1591, 1597, 1606, 1615, 1620, 1628, + 1632, 1646, 1650, 1651, 1655, 1662, 1669, 1679, 1680, 1684, + 1686, 1692, 1697, 1706, 1712, 1718, 1724, 1730, 1739, 1740, + 1741, 1745 }; #endif @@ -857,38 +867,41 @@ static const char *const yytname[] = "ISAMPLERCUBE", "ISAMPLER1DARRAY", "ISAMPLER2DARRAY", "USAMPLER1D", "USAMPLER2D", "USAMPLER3D", "USAMPLERCUBE", "USAMPLER1DARRAY", "USAMPLER2DARRAY", "STRUCT", "VOID_TOK", "WHILE", "IDENTIFIER", - "FLOATCONSTANT", "INTCONSTANT", "UINTCONSTANT", "BOOLCONSTANT", - "FIELD_SELECTION", "LEFT_OP", "RIGHT_OP", "INC_OP", "DEC_OP", "LE_OP", - "GE_OP", "EQ_OP", "NE_OP", "AND_OP", "OR_OP", "XOR_OP", "MUL_ASSIGN", - "DIV_ASSIGN", "ADD_ASSIGN", "MOD_ASSIGN", "LEFT_ASSIGN", "RIGHT_ASSIGN", - "AND_ASSIGN", "XOR_ASSIGN", "OR_ASSIGN", "SUB_ASSIGN", "INVARIANT", - "LOWP", "MEDIUMP", "HIGHP", "SUPERP", "PRECISION", "VERSION", - "EXTENSION", "LINE", "COLON", "EOL", "INTERFACE", "OUTPUT", - "PRAGMA_DEBUG_ON", "PRAGMA_DEBUG_OFF", "PRAGMA_OPTIMIZE_ON", - "PRAGMA_OPTIMIZE_OFF", "PRAGMA_INVARIANT_ALL", "LAYOUT_TOK", "ASM", - "CLASS", "UNION", "ENUM", "TYPEDEF", "TEMPLATE", "THIS", "PACKED_TOK", - "GOTO", "INLINE_TOK", "NOINLINE", "VOLATILE", "PUBLIC_TOK", "STATIC", - "EXTERN", "EXTERNAL", "LONG_TOK", "SHORT_TOK", "DOUBLE_TOK", "HALF", - "FIXED_TOK", "UNSIGNED", "INPUT_TOK", "OUPTUT", "HVEC2", "HVEC3", - "HVEC4", "DVEC2", "DVEC3", "DVEC4", "FVEC2", "FVEC3", "FVEC4", - "SAMPLER2DRECT", "SAMPLER3DRECT", "SAMPLER2DRECTSHADOW", "SIZEOF", - "CAST", "NAMESPACE", "USING", "ERROR_TOK", "COMMON", "PARTITION", - "ACTIVE", "SAMPLERBUFFER", "FILTER", "IMAGE1D", "IMAGE2D", "IMAGE3D", - "IMAGECUBE", "IMAGE1DARRAY", "IMAGE2DARRAY", "IIMAGE1D", "IIMAGE2D", - "IIMAGE3D", "IIMAGECUBE", "IIMAGE1DARRAY", "IIMAGE2DARRAY", "UIMAGE1D", - "UIMAGE2D", "UIMAGE3D", "UIMAGECUBE", "UIMAGE1DARRAY", "UIMAGE2DARRAY", - "IMAGE1DSHADOW", "IMAGE2DSHADOW", "IMAGEBUFFER", "IIMAGEBUFFER", - "UIMAGEBUFFER", "IMAGE1DARRAYSHADOW", "IMAGE2DARRAYSHADOW", "ROW_MAJOR", - "'('", "')'", "'['", "']'", "'.'", "','", "'+'", "'-'", "'!'", "'~'", - "'*'", "'/'", "'%'", "'<'", "'>'", "'&'", "'^'", "'|'", "'?'", "':'", - "'='", "';'", "'{'", "'}'", "$accept", "translation_unit", "$@1", - "version_statement", "pragma_statement", "extension_statement_list", - "extension_statement", "external_declaration_list", - "variable_identifier", "primary_expression", "postfix_expression", - "integer_expression", "function_call", "function_call_or_method", - "function_call_generic", "function_call_header_no_parameters", + "TYPE_IDENTIFIER", "NEW_IDENTIFIER", "FLOATCONSTANT", "INTCONSTANT", + "UINTCONSTANT", "BOOLCONSTANT", "FIELD_SELECTION", "LEFT_OP", "RIGHT_OP", + "INC_OP", "DEC_OP", "LE_OP", "GE_OP", "EQ_OP", "NE_OP", "AND_OP", + "OR_OP", "XOR_OP", "MUL_ASSIGN", "DIV_ASSIGN", "ADD_ASSIGN", + "MOD_ASSIGN", "LEFT_ASSIGN", "RIGHT_ASSIGN", "AND_ASSIGN", "XOR_ASSIGN", + "OR_ASSIGN", "SUB_ASSIGN", "INVARIANT", "LOWP", "MEDIUMP", "HIGHP", + "SUPERP", "PRECISION", "VERSION", "EXTENSION", "LINE", "COLON", "EOL", + "INTERFACE", "OUTPUT", "PRAGMA_DEBUG_ON", "PRAGMA_DEBUG_OFF", + "PRAGMA_OPTIMIZE_ON", "PRAGMA_OPTIMIZE_OFF", "PRAGMA_INVARIANT_ALL", + "LAYOUT_TOK", "ASM", "CLASS", "UNION", "ENUM", "TYPEDEF", "TEMPLATE", + "THIS", "PACKED_TOK", "GOTO", "INLINE_TOK", "NOINLINE", "VOLATILE", + "PUBLIC_TOK", "STATIC", "EXTERN", "EXTERNAL", "LONG_TOK", "SHORT_TOK", + "DOUBLE_TOK", "HALF", "FIXED_TOK", "UNSIGNED", "INPUT_TOK", "OUPTUT", + "HVEC2", "HVEC3", "HVEC4", "DVEC2", "DVEC3", "DVEC4", "FVEC2", "FVEC3", + "FVEC4", "SAMPLER2DRECT", "SAMPLER3DRECT", "SAMPLER2DRECTSHADOW", + "SIZEOF", "CAST", "NAMESPACE", "USING", "ERROR_TOK", "COMMON", + "PARTITION", "ACTIVE", "SAMPLERBUFFER", "FILTER", "IMAGE1D", "IMAGE2D", + "IMAGE3D", "IMAGECUBE", "IMAGE1DARRAY", "IMAGE2DARRAY", "IIMAGE1D", + "IIMAGE2D", "IIMAGE3D", "IIMAGECUBE", "IIMAGE1DARRAY", "IIMAGE2DARRAY", + "UIMAGE1D", "UIMAGE2D", "UIMAGE3D", "UIMAGECUBE", "UIMAGE1DARRAY", + "UIMAGE2DARRAY", "IMAGE1DSHADOW", "IMAGE2DSHADOW", "IMAGEBUFFER", + "IIMAGEBUFFER", "UIMAGEBUFFER", "IMAGE1DARRAYSHADOW", + "IMAGE2DARRAYSHADOW", "ROW_MAJOR", "'('", "')'", "'['", "']'", "'.'", + "','", "'+'", "'-'", "'!'", "'~'", "'*'", "'/'", "'%'", "'<'", "'>'", + "'&'", "'^'", "'|'", "'?'", "':'", "'='", "';'", "'{'", "'}'", "$accept", + "translation_unit", "$@1", "version_statement", "pragma_statement", + "extension_statement_list", "any_identifier", "extension_statement", + "external_declaration_list", "variable_identifier", "primary_expression", + "postfix_expression", "integer_expression", "function_call", + "function_call_or_method", "function_call_generic", + "function_call_header_no_parameters", "function_call_header_with_parameters", "function_call_header", - "function_identifier", "unary_expression", "unary_operator", + "function_identifier", "method_call_generic", + "method_call_header_no_parameters", "method_call_header_with_parameters", + "method_call_header", "unary_expression", "unary_operator", "multiplicative_expression", "additive_expression", "shift_expression", "relational_expression", "equality_expression", "and_expression", "exclusive_or_expression", "inclusive_or_expression", @@ -907,7 +920,7 @@ static const char *const yytname[] = "precision_qualifier", "struct_specifier", "struct_declaration_list", "struct_declaration", "struct_declarator_list", "struct_declarator", "initializer", "declaration_statement", "statement", "simple_statement", - "compound_statement", "statement_no_new_scope", + "compound_statement", "$@2", "statement_no_new_scope", "compound_statement_no_new_scope", "statement_list", "expression_statement", "selection_statement", "selection_rest_statement", "condition", "switch_statement", @@ -941,76 +954,80 @@ static const yytype_uint16 yytoknum[] = 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, - 445, 446, 447, 448, 40, 41, 91, 93, 46, 44, - 43, 45, 33, 126, 42, 47, 37, 60, 62, 38, - 94, 124, 63, 58, 61, 59, 123, 125 + 445, 446, 447, 448, 449, 450, 40, 41, 91, 93, + 46, 44, 43, 45, 33, 126, 42, 47, 37, 60, + 62, 38, 94, 124, 63, 58, 61, 59, 123, 125 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint16 yyr1[] = { - 0, 218, 220, 219, 221, 221, 222, 222, 222, 222, - 222, 223, 223, 224, 225, 225, 226, 227, 227, 227, - 227, 227, 227, 228, 228, 228, 228, 228, 228, 229, - 230, 231, 231, 232, 232, 233, 233, 234, 234, 235, - 236, 236, 236, 237, 237, 237, 237, 238, 238, 238, - 238, 239, 239, 239, 239, 240, 240, 240, 241, 241, - 241, 242, 242, 242, 242, 242, 243, 243, 243, 244, - 244, 245, 245, 246, 246, 247, 247, 248, 248, 249, - 249, 250, 250, 251, 251, 252, 252, 252, 252, 252, - 252, 252, 252, 252, 252, 252, 253, 253, 254, 255, - 255, 255, 256, 257, 257, 258, 258, 259, 260, 260, - 261, 261, 261, 261, 262, 262, 262, 262, 263, 264, - 264, 264, 264, 264, 264, 264, 265, 265, 265, 265, - 265, 265, 265, 265, 266, 266, 267, 268, 268, 269, - 269, 270, 270, 270, 271, 272, 272, 272, 272, 272, - 272, 272, 272, 273, 273, 273, 273, 273, 273, 273, - 273, 273, 274, 274, 275, 275, 275, 276, 276, 276, - 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, - 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, - 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, - 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, - 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, - 277, 278, 278, 278, 279, 279, 280, 280, 281, 282, - 282, 283, 283, 284, 285, 286, 286, 287, 287, 287, - 287, 287, 287, 287, 288, 288, 289, 289, 290, 290, - 291, 291, 292, 292, 293, 294, 294, 295, 295, 296, - 297, 297, 298, 298, 298, 299, 299, 300, 300, 301, - 301, 302, 302, 302, 302, 302, 303, 303, 303, 304 + 0, 220, 222, 221, 223, 223, 224, 224, 224, 224, + 224, 225, 225, 226, 226, 226, 227, 228, 228, 229, + 229, 230, 230, 230, 230, 230, 230, 231, 231, 231, + 231, 231, 231, 232, 233, 234, 234, 235, 235, 236, + 236, 237, 237, 238, 239, 239, 239, 240, 240, 241, + 241, 242, 242, 243, 244, 244, 244, 244, 245, 245, + 245, 245, 246, 246, 246, 246, 247, 247, 247, 248, + 248, 248, 249, 249, 249, 249, 249, 250, 250, 250, + 251, 251, 252, 252, 253, 253, 254, 254, 255, 255, + 256, 256, 257, 257, 258, 258, 259, 259, 259, 259, + 259, 259, 259, 259, 259, 259, 259, 260, 260, 261, + 262, 262, 262, 263, 264, 264, 265, 265, 266, 267, + 267, 268, 268, 268, 268, 269, 269, 269, 269, 270, + 271, 271, 271, 271, 271, 271, 271, 272, 272, 272, + 272, 272, 272, 272, 272, 273, 273, 274, 275, 275, + 276, 276, 277, 277, 277, 278, 279, 279, 279, 279, + 279, 279, 279, 279, 280, 280, 280, 280, 280, 280, + 280, 280, 280, 281, 281, 282, 282, 282, 283, 283, + 283, 284, 284, 284, 284, 284, 284, 284, 284, 284, + 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, + 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, + 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, + 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, + 284, 284, 285, 285, 285, 286, 286, 287, 287, 288, + 289, 289, 290, 290, 291, 292, 293, 293, 294, 294, + 294, 294, 294, 294, 294, 295, 296, 295, 297, 297, + 298, 298, 299, 299, 300, 300, 301, 302, 302, 303, + 303, 304, 305, 305, 306, 306, 306, 307, 307, 308, + 308, 309, 309, 310, 310, 310, 310, 310, 311, 311, + 311, 312 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const yytype_uint8 yyr2[] = { 0, 2, 0, 4, 0, 3, 2, 2, 2, 2, - 2, 0, 2, 5, 1, 2, 1, 1, 1, 1, - 1, 1, 3, 1, 4, 1, 3, 2, 2, 1, - 1, 1, 3, 2, 2, 2, 1, 2, 3, 2, - 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, - 1, 1, 3, 3, 3, 1, 3, 3, 1, 3, - 3, 1, 3, 3, 3, 3, 1, 3, 3, 1, - 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, - 3, 1, 5, 1, 3, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 3, 1, 2, - 2, 4, 2, 1, 1, 2, 3, 3, 2, 5, - 3, 2, 3, 2, 0, 1, 1, 1, 1, 1, - 3, 5, 6, 7, 8, 5, 1, 2, 4, 5, - 6, 7, 4, 2, 1, 2, 4, 1, 3, 1, - 3, 1, 1, 1, 1, 1, 1, 2, 1, 2, - 2, 3, 1, 1, 1, 1, 2, 1, 1, 2, - 2, 1, 1, 2, 1, 3, 4, 1, 1, 1, + 2, 0, 2, 1, 1, 1, 5, 1, 2, 1, + 1, 1, 1, 1, 1, 1, 3, 1, 4, 1, + 3, 2, 2, 1, 1, 1, 3, 2, 2, 2, + 1, 2, 3, 2, 1, 1, 1, 2, 2, 2, + 1, 2, 3, 2, 1, 2, 2, 2, 1, 1, + 1, 1, 1, 3, 3, 3, 1, 3, 3, 1, + 3, 3, 1, 3, 3, 3, 3, 1, 3, 3, + 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, + 1, 3, 1, 5, 1, 3, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, + 2, 2, 4, 2, 1, 1, 2, 3, 3, 2, + 5, 3, 2, 3, 2, 0, 1, 1, 1, 1, + 1, 3, 5, 6, 7, 8, 5, 1, 2, 4, + 5, 6, 7, 4, 2, 1, 2, 4, 1, 3, + 1, 3, 1, 1, 1, 1, 1, 1, 2, 1, + 2, 2, 3, 1, 1, 1, 1, 2, 1, 1, + 2, 2, 1, 1, 2, 1, 3, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 5, 4, 1, 2, 3, 1, - 3, 1, 4, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 2, 3, 1, 1, 2, 3, - 1, 2, 1, 2, 5, 3, 1, 1, 4, 5, - 3, 2, 5, 7, 6, 1, 1, 1, 0, 2, - 3, 2, 2, 2, 3, 2, 1, 1, 1, 2 + 1, 1, 1, 1, 1, 5, 4, 1, 2, 3, + 1, 3, 1, 4, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 2, 0, 4, 1, 1, + 2, 3, 1, 2, 1, 2, 5, 3, 1, 1, + 4, 5, 3, 2, 5, 7, 6, 1, 1, 1, + 0, 2, 3, 2, 2, 2, 3, 2, 1, 1, + 1, 2 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state @@ -1019,637 +1036,620 @@ static const yytype_uint8 yyr2[] = static const yytype_uint16 yydefact[] = { 4, 0, 0, 11, 0, 1, 2, 5, 0, 0, - 12, 0, 154, 153, 174, 171, 172, 173, 178, 179, - 180, 181, 182, 183, 184, 185, 186, 175, 176, 177, - 0, 157, 158, 161, 155, 143, 142, 141, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 197, 199, - 200, 201, 202, 204, 205, 206, 207, 208, 209, 210, - 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, - 0, 170, 169, 152, 223, 222, 221, 0, 0, 0, - 0, 0, 0, 0, 198, 203, 278, 3, 277, 0, - 0, 104, 114, 0, 119, 126, 146, 148, 0, 145, - 134, 162, 164, 167, 0, 168, 14, 276, 0, 159, - 160, 156, 0, 0, 133, 0, 150, 0, 6, 7, - 8, 9, 10, 0, 15, 99, 0, 279, 102, 114, - 144, 115, 116, 117, 105, 0, 114, 0, 100, 127, - 147, 149, 135, 0, 163, 0, 0, 0, 0, 226, - 151, 0, 139, 0, 137, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 16, 20, 18, 19, - 21, 42, 0, 0, 0, 47, 48, 49, 50, 252, - 0, 248, 17, 23, 43, 25, 30, 31, 0, 0, - 36, 0, 51, 0, 55, 58, 61, 66, 69, 71, - 73, 75, 77, 79, 81, 83, 96, 0, 234, 0, - 134, 237, 250, 236, 235, 0, 238, 239, 240, 241, - 242, 243, 106, 111, 113, 118, 0, 120, 107, 0, - 0, 165, 51, 98, 0, 40, 13, 0, 231, 0, - 229, 225, 227, 101, 0, 136, 0, 272, 271, 0, - 0, 0, 275, 273, 0, 0, 0, 261, 0, 44, - 45, 0, 244, 0, 27, 28, 0, 0, 34, 33, - 0, 170, 37, 39, 86, 87, 89, 88, 91, 92, - 93, 94, 95, 90, 85, 0, 46, 0, 0, 0, + 12, 13, 14, 15, 0, 165, 164, 185, 182, 183, + 184, 189, 190, 191, 192, 193, 194, 195, 196, 197, + 186, 187, 188, 0, 168, 169, 172, 166, 154, 153, + 152, 198, 199, 200, 201, 202, 203, 204, 205, 206, + 207, 208, 210, 211, 212, 213, 215, 216, 217, 218, + 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, + 229, 230, 231, 0, 181, 180, 163, 234, 233, 232, + 0, 0, 0, 0, 0, 0, 0, 209, 214, 290, + 3, 289, 0, 0, 115, 125, 0, 130, 137, 157, + 159, 0, 156, 145, 173, 175, 178, 0, 179, 17, + 288, 0, 170, 171, 167, 0, 0, 19, 20, 144, + 0, 161, 0, 6, 7, 8, 9, 10, 0, 18, + 110, 0, 291, 113, 125, 155, 126, 127, 128, 116, + 0, 125, 0, 111, 13, 15, 138, 0, 158, 160, + 146, 0, 174, 0, 0, 0, 237, 0, 162, 0, + 150, 0, 148, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 24, 22, 23, 25, 46, 0, + 0, 0, 58, 59, 60, 61, 264, 256, 260, 21, + 27, 54, 29, 34, 35, 0, 0, 40, 0, 62, + 0, 66, 69, 72, 77, 80, 82, 84, 86, 88, + 90, 92, 94, 107, 0, 245, 0, 145, 248, 262, + 247, 246, 0, 249, 250, 251, 252, 253, 254, 117, + 122, 124, 129, 0, 131, 0, 0, 118, 176, 62, + 109, 0, 44, 16, 242, 0, 240, 236, 238, 0, + 112, 0, 147, 0, 284, 283, 0, 0, 0, 287, + 285, 0, 0, 0, 273, 0, 55, 56, 0, 255, + 0, 31, 32, 0, 0, 38, 37, 0, 181, 41, + 43, 97, 98, 100, 99, 102, 103, 104, 105, 106, + 101, 96, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 253, 249, - 251, 108, 110, 112, 0, 0, 128, 0, 233, 132, - 166, 224, 0, 0, 228, 140, 138, 0, 266, 265, - 268, 0, 274, 0, 260, 152, 257, 0, 0, 22, - 245, 0, 29, 26, 32, 38, 84, 52, 53, 54, - 56, 57, 59, 60, 64, 65, 62, 63, 67, 68, - 70, 72, 74, 76, 78, 80, 0, 97, 0, 121, - 0, 125, 0, 129, 0, 230, 0, 267, 0, 0, - 0, 0, 0, 0, 24, 0, 0, 0, 122, 130, - 0, 232, 0, 269, 0, 256, 254, 259, 0, 247, - 262, 246, 82, 109, 123, 0, 131, 0, 270, 264, - 0, 258, 124, 263, 255 + 0, 0, 0, 0, 0, 265, 261, 263, 119, 121, + 123, 0, 0, 139, 0, 244, 143, 177, 0, 0, + 239, 235, 151, 149, 0, 278, 277, 280, 0, 286, + 0, 272, 163, 269, 0, 0, 26, 0, 0, 33, + 30, 0, 36, 0, 0, 50, 42, 95, 63, 64, + 65, 67, 68, 70, 71, 75, 76, 73, 74, 78, + 79, 81, 83, 85, 87, 89, 91, 0, 108, 0, + 132, 0, 136, 0, 140, 0, 241, 0, 279, 0, + 0, 0, 0, 0, 0, 257, 28, 53, 48, 47, + 0, 181, 51, 0, 0, 0, 133, 141, 0, 243, + 0, 281, 0, 268, 266, 271, 0, 259, 274, 258, + 52, 93, 120, 134, 0, 142, 0, 282, 276, 0, + 270, 135, 275, 267 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { - -1, 2, 9, 3, 86, 6, 10, 87, 182, 183, - 184, 341, 185, 186, 187, 188, 189, 190, 191, 192, - 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, - 203, 204, 205, 206, 285, 207, 234, 208, 209, 90, - 91, 92, 223, 134, 135, 224, 93, 94, 95, 96, - 153, 154, 97, 136, 98, 99, 235, 101, 102, 103, - 104, 105, 148, 149, 239, 240, 319, 211, 212, 213, - 214, 400, 401, 215, 216, 217, 396, 338, 218, 219, - 220, 330, 378, 379, 221, 106, 107 + -1, 2, 9, 3, 89, 6, 160, 10, 90, 189, + 190, 191, 348, 192, 193, 194, 195, 196, 197, 198, + 352, 353, 354, 355, 199, 200, 201, 202, 203, 204, + 205, 206, 207, 208, 209, 210, 211, 212, 213, 292, + 214, 241, 215, 216, 93, 94, 95, 230, 139, 140, + 231, 96, 97, 98, 99, 161, 162, 100, 141, 101, + 102, 242, 104, 105, 106, 107, 108, 155, 156, 245, + 246, 326, 218, 219, 220, 221, 270, 418, 419, 222, + 223, 224, 414, 345, 225, 226, 227, 337, 389, 390, + 228, 109, 110 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ -#define YYPACT_NINF -321 +#define YYPACT_NINF -366 static const yytype_int16 yypact[] = { - -86, -57, 45, -321, -56, -321, -50, -321, -10, 3320, - -321, -26, -321, -321, -321, -321, -321, -321, -321, -321, - -321, -321, -321, -321, -321, -321, -321, -321, -321, -321, - 79, -321, -321, -321, -321, -321, -321, -321, -321, -321, - -321, -321, -321, -321, -321, -321, -321, -321, -321, -321, - -321, -321, -321, -321, -321, -321, -321, -321, -321, -321, - -321, -321, -321, -321, -321, -321, -321, -321, -321, -321, - -70, -321, -321, 43, -321, -321, -321, 18, -22, -12, - -5, 2, 25, -101, -321, -321, -321, 3320, -321, -43, - -55, -54, 6, -148, -321, 52, 211, 211, 3509, -321, - -321, -321, -47, -321, 3581, -321, -321, -321, 110, -321, - -321, -321, -14, 3509, -321, 211, -321, 3581, -321, -321, - -321, -321, -321, 131, -321, -321, 389, -321, -321, 15, - -321, -321, -321, -321, -321, 3509, 109, 136, -321, -152, - -321, -321, -321, 2400, -321, 105, 3509, 143, 1781, -321, - -321, 7, 9, -107, -321, 10, 12, 1249, 27, 36, - 17, 2015, 40, 2952, 22, 42, -65, -321, -321, -321, - -321, -321, 2952, 2952, 2952, -321, -321, -321, -321, -321, - 604, -321, -321, -321, -20, -321, -321, -321, 47, -92, - 3136, 46, -67, 2952, -24, -16, 111, -73, 108, 37, - 41, 39, 162, 161, -82, -321, -321, -147, -321, 44, - 61, -321, -321, -321, -321, 819, -321, -321, -321, -321, - -321, -321, -321, -321, -321, 181, 3509, -160, -321, 2584, - 2952, -321, -321, -321, 63, -321, -321, 1898, 62, -146, - -321, -321, -321, -321, 183, -321, 131, -321, -321, 187, - 1664, 2952, -321, -321, -144, 2952, -140, -321, 2216, -321, - -321, -81, -321, 1034, -321, -321, 2952, 3437, -321, -321, - 2952, 70, -321, -321, -321, -321, -321, -321, -321, -321, - -321, -321, -321, -321, -321, 2952, -321, 2952, 2952, 2952, - 2952, 2952, 2952, 2952, 2952, 2952, 2952, 2952, 2952, 2952, - 2952, 2952, 2952, 2952, 2952, 2952, 2952, 2952, -321, -321, - -321, 74, -321, -321, 2768, 2952, 64, 69, -321, -321, - -321, -321, 2952, 143, -321, -321, -321, 82, -321, -321, - 2216, -74, -321, -68, -321, 235, 78, 203, 85, -321, - -321, 84, 78, 88, -321, -321, -321, -321, -321, -321, - -24, -24, -16, -16, 111, 111, 111, 111, -73, -73, - 108, 37, 41, 39, 162, 161, -129, -321, 2952, 71, - 86, -321, 2952, 72, 87, -321, 2952, -321, 73, 92, - 1249, 75, 76, 1463, -321, 2952, 95, 2952, 80, -321, - 2952, -321, -63, 2952, 1463, 277, -321, -321, 2952, -321, - -321, -321, -321, -321, -321, 2952, -321, 81, 78, -321, - 1249, -321, -321, -321, -321 + -57, -43, 62, -366, -50, -366, -30, -366, 67, 3341, + -366, -366, -366, -366, -6, -366, -366, -366, -366, -366, + -366, -366, -366, -366, -366, -366, -366, -366, -366, -366, + -366, -366, -366, 8, -366, -366, -366, -366, -366, -366, + -366, -366, -366, -366, -366, -366, -366, -366, -366, -366, + -366, -366, -366, -366, -366, -366, -366, -366, -366, -366, + -366, -366, -366, -366, -366, -366, -366, -366, -366, -366, + -366, -366, -366, -65, -366, -366, 226, -366, -366, -366, + 51, -31, -28, 6, 13, 15, -44, -366, -366, -366, + 3341, -366, -183, -47, -29, 18, -169, -366, 140, 24, + 24, 3460, -366, -366, -366, -24, -366, 3533, -366, -366, + -366, 67, -366, -366, -366, 3460, -48, -366, -366, -366, + 24, -366, 3533, -366, -366, -366, -366, -366, 67, -366, + -366, 408, -366, -366, 55, -366, -366, -366, -366, -366, + 3460, 200, 67, -366, -20, -18, -178, 23, -366, -366, + -366, 2225, -366, 72, 67, 1598, -366, 3460, -366, 4, + 10, -84, -366, 11, 14, 1059, 40, 42, 29, 1836, + 43, 2783, 34, 54, -366, -366, -366, -366, -366, 2783, + 2783, 2783, -366, -366, -366, -366, -366, 32, -366, 56, + -366, -71, -366, -366, -366, 57, -81, 2969, 61, -27, + 2783, 35, -88, -41, -70, 33, 60, 41, 59, 181, + 180, -89, -366, -366, -168, -366, 58, 80, -366, -366, + -366, -366, 625, -366, -366, -366, -366, -366, -366, -366, + -366, -366, 67, 3460, -177, 2411, 2783, -366, -366, -366, + -366, 78, -366, -366, 81, -137, -366, -366, -366, 1717, + -366, 201, -366, 67, -366, -366, 205, 1478, 2783, -366, + -366, -134, 2783, -115, -366, 2039, -366, -366, -60, -366, + 1059, -366, -366, 2783, 140, -366, -366, 2783, 85, -366, + -366, -366, -366, -366, -366, -366, -366, -366, -366, -366, + -366, -366, 2783, -366, 2783, 2783, 2783, 2783, 2783, 2783, + 2783, 2783, 2783, 2783, 2783, 2783, 2783, 2783, 2783, 2783, + 2783, 2783, 2783, 2783, 2783, -366, -366, -366, 86, -366, + -366, 2597, 2783, 69, 87, -366, -366, -366, 2783, 67, + -366, -366, -366, -366, 91, -366, -366, 2039, -59, -366, + -46, -366, 129, 88, 67, 93, -366, 842, 89, 88, + -366, 95, -366, 96, -37, 3155, -366, -366, -366, -366, + -366, 35, 35, -88, -88, -41, -41, -41, -41, -70, + -70, 33, 60, 41, 59, 181, 180, -96, -366, 2783, + 76, 97, -366, 2783, 79, 98, -366, 2783, -366, 77, + 101, 1059, 83, 90, 1275, -366, -366, -366, -366, -366, + 2783, 102, -366, 2783, 108, 2783, 94, -366, 2783, -366, + -26, 2783, 1275, 297, -366, -366, 2783, -366, -366, -366, + -366, -366, -366, -366, 2783, -366, 100, 88, -366, 1059, + -366, -366, -366, -366 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { - -321, -321, -321, -321, -321, -321, -321, -321, -321, -321, - -321, -321, -321, -321, 26, -321, -321, -321, -321, -135, - -321, -91, -88, -106, -90, -3, -6, -4, -2, -1, - 0, -321, -139, -174, -321, -156, -217, 11, 13, -321, - -321, -321, 83, 170, 164, 89, -321, -321, -243, -321, - -321, 56, -71, -321, -321, -72, -9, -32, -321, -321, - 227, -321, 160, -131, -321, -15, -195, 57, -154, -320, - -69, -84, 222, 133, 66, -321, -321, -13, -321, -321, - -321, -321, -321, -321, -321, 231, -321 + -366, -366, -366, -366, -366, -366, -7, -366, -366, -62, + -366, -366, -366, -366, -366, -366, -366, -366, -366, -366, + -366, -366, -366, -366, -101, -366, -113, -109, -121, -61, + 5, 3, 9, 16, 2, 7, -366, -142, -100, -366, + -164, -225, 21, 22, -366, -366, -366, 82, 186, 173, + 92, -366, -366, -242, -366, -366, 68, -73, -366, -366, + -74, -9, -67, -366, -366, 243, -366, 170, -147, -366, + 0, -298, 73, -159, -365, -58, -366, -80, 239, 63, + 84, -366, -366, -2, -366, -366, -366, -366, -366, -366, + -366, 246, -366 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If zero, do what YYDEFACT says. If YYTABLE_NINF, syntax error. */ -#define YYTABLE_NINF -170 +#define YYTABLE_NINF -115 static const yytype_int16 yytable[] = { - 100, 116, 115, 249, 233, 254, 112, 256, 232, 305, - 130, -169, 317, 294, 295, 337, 272, 242, 261, 130, - 88, 4, 89, 1, 140, 141, 274, 275, 276, 277, - 278, 279, 280, 281, 282, 283, 314, 259, 260, 131, - 132, 133, 228, 150, 229, 5, 12, 13, 131, 132, - 133, 137, 307, 323, 315, 307, 318, 7, 286, 307, - 8, 310, 230, 399, 264, 265, 11, 138, 308, 324, - 307, 332, 144, 334, 399, 30, 31, 32, 100, 33, - 34, 35, 36, 37, 385, 151, 108, 337, 245, 142, - 233, 118, 246, 123, 232, 331, 345, 370, 88, 333, - 89, 119, 336, 269, 147, 374, 242, 270, 120, 310, - 342, 346, 109, 110, 339, 121, 111, 210, 307, 114, - 371, 380, 74, 75, 76, 307, 225, 381, 139, -41, - 306, 307, 407, 367, 296, 297, 307, 147, 122, 147, - 128, 318, 131, 132, 133, 129, 113, 284, 210, 143, - 366, 386, 347, 348, 349, 232, 232, 232, 232, 232, - 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, - 232, 210, 125, 126, 336, 233, 266, 389, 267, 232, - 287, 288, 289, 233, 290, 291, 145, 232, 354, 355, - 356, 357, 404, 292, 293, 406, 298, 299, 318, 350, - 351, -103, 146, 411, 352, 353, 210, 152, 358, 359, - 412, 402, 227, 318, 12, 13, 318, 225, 236, 238, - 392, 250, 243, 244, 318, 247, 395, 248, 147, 233, - 251, 318, 252, 232, 255, 257, 258, 408, 12, 13, - 273, 210, 268, 30, 31, 32, 300, 33, 34, 210, - 302, 301, 303, 304, 210, -40, 414, 311, 322, 125, - 320, 325, 327, 116, 115, -35, 373, 30, 31, 32, - 368, 33, 34, 35, 36, 37, 376, 307, 372, 382, - 383, 384, -41, 388, 391, 387, 390, 394, 393, 410, - 398, 180, 403, 344, 405, 361, 413, 360, 362, 222, - 226, 363, 326, 364, 117, 365, 237, 328, 375, 312, - 409, 127, 397, 263, 0, 313, 329, 377, 124, 0, - 0, 210, 0, 0, 0, 0, 0, 0, 0, 0, + 103, 14, 121, 120, 312, 261, 256, 263, 248, 240, + 324, 11, 12, 13, 119, 271, 272, 268, 301, 302, + 235, 321, 135, 344, 382, 148, 149, 15, 16, 417, + 91, 92, 142, 314, 130, 131, 147, 4, 236, 322, + 152, 112, 113, 299, 300, 114, 158, 417, 143, 315, + 239, 136, 137, 138, 1, 159, 33, 34, 35, 135, + 36, 37, 5, 317, 329, 7, 116, 314, 281, 282, + 283, 284, 285, 286, 287, 288, 289, 290, 266, 267, + 330, 103, 8, 339, 123, 407, 314, 124, 136, 137, + 138, 146, 150, 240, 338, 344, 381, 279, 340, 293, + 341, 343, 248, 385, 153, 314, 154, 423, 111, 349, + 425, 91, 92, 252, 297, 298, 276, 253, 430, 403, + 277, 125, 217, 305, 306, 313, 431, 273, 126, 274, + 127, 232, 15, 16, 239, 234, 325, 346, 391, 303, + 304, 314, 314, 11, 12, 13, 154, 244, 154, 377, + 133, 392, 128, 115, 404, 314, 217, 77, 78, 79, + 399, 33, 34, 35, 400, 36, 37, 38, 39, 40, + 157, 426, 134, 343, 151, 314, -19, 356, -20, 240, + 365, 366, 367, 368, 361, 362, 240, 243, 317, 291, + 363, 364, 357, 358, 359, 360, 239, 239, 239, 239, + 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, + 239, 239, 351, 217, 378, -114, 144, 12, 145, 237, + 239, 250, 325, 410, 232, 318, 251, 239, 254, 15, + 16, 255, 413, 136, 137, 138, 257, 240, 258, 262, + 154, 294, 295, 296, 369, 370, 259, 427, 217, 264, + 265, 269, -45, 308, 275, 402, 217, 280, 33, 34, + 35, 217, 36, 37, 38, 39, 40, 350, 121, 120, + 433, 307, 309, 310, 311, 130, -44, 327, 239, 328, + 334, 332, -39, 325, 379, 383, 384, 387, 396, 314, + 394, 397, 405, 398, 411, 408, 406, 409, 412, -49, + 420, 187, 117, 421, 118, 325, 416, 422, 325, 429, + 424, 372, 371, 375, 233, 319, 325, 432, 373, 376, + 229, 333, 244, 122, 325, 320, 374, 249, 217, 386, + 335, 132, 428, 347, 415, 388, 129, 393, 217, 0, + 0, 336, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 217, 0, 0, 217, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 210, 0, 0, 210, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 210, 0, 0, 0, 0, - 0, 0, 12, 13, 14, 15, 16, 17, 155, 156, - 157, 210, 158, 159, 160, 161, 162, 163, 164, 18, - 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, - 29, 30, 31, 32, 0, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, - 68, 69, 70, 71, 165, 166, 167, 168, 169, 170, - 171, 0, 0, 172, 173, 0, 0, 0, 0, 0, + 0, 0, 0, 217, 0, 0, 0, 0, 0, 0, + 0, 15, 16, 17, 18, 19, 20, 163, 164, 165, + 217, 166, 167, 168, 169, 170, 171, 172, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 0, 36, 37, 38, 39, 40, 41, + 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 173, 117, 75, 118, 174, 175, 176, + 177, 178, 0, 0, 179, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 73, 74, 75, 76, 0, 77, 0, 0, + 0, 0, 0, 76, 77, 78, 79, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 84, 0, 85, 0, 0, 0, + 0, 0, 0, 0, 0, 87, 0, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 174, 0, 0, 0, 0, 0, 175, - 176, 177, 178, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 179, 180, 181, 12, 13, 14, - 15, 16, 17, 155, 156, 157, 0, 158, 159, 160, - 161, 162, 163, 164, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, 32, 0, - 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, - 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, - 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, - 63, 64, 65, 66, 67, 68, 69, 70, 71, 165, - 166, 167, 168, 169, 170, 171, 0, 0, 172, 173, + 0, 0, 0, 0, 181, 0, 0, 0, 0, 0, + 182, 183, 184, 185, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 186, 187, 188, 15, 16, + 17, 18, 19, 20, 163, 164, 165, 0, 166, 167, + 168, 169, 170, 171, 172, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + 0, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 173, 117, 75, 118, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 73, 74, 75, - 76, 0, 77, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 83, 0, 0, 0, 0, + 76, 77, 78, 79, 0, 80, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, - 0, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 87, 0, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 174, 0, - 0, 0, 0, 0, 175, 176, 177, 178, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, - 180, 262, 12, 13, 14, 15, 16, 17, 155, 156, - 157, 0, 158, 159, 160, 161, 162, 163, 164, 18, - 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, - 29, 30, 31, 32, 0, 33, 34, 35, 36, 37, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 181, 0, 0, 0, 0, 0, 182, 183, 184, + 185, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 186, 187, 316, 15, 16, 17, 18, 19, + 20, 163, 164, 165, 0, 166, 167, 168, 169, 170, + 171, 172, 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 0, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, - 68, 69, 70, 71, 165, 166, 167, 168, 169, 170, - 171, 0, 0, 172, 173, 0, 0, 0, 0, 0, + 68, 69, 70, 71, 72, 73, 74, 173, 117, 75, + 118, 174, 175, 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 73, 74, 75, 76, 0, 77, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 76, 77, 78, + 79, 0, 80, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, + 0, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 84, 0, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 181, 0, + 0, 0, 0, 0, 182, 183, 184, 185, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 186, + 187, 395, 15, 16, 17, 18, 19, 20, 163, 164, + 165, 0, 166, 167, 168, 169, 170, 171, 172, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 0, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, + 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, 173, 117, 75, 118, 174, 175, + 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 76, 77, 78, 79, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 174, 0, 0, 0, 0, 0, 175, - 176, 177, 178, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 179, 180, 309, 12, 13, 14, - 15, 16, 17, 155, 156, 157, 0, 158, 159, 160, - 161, 162, 163, 164, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, 32, 0, - 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, - 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, - 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, - 63, 64, 65, 66, 67, 68, 69, 70, 71, 165, - 166, 167, 168, 169, 170, 171, 0, 0, 172, 173, + 0, 0, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 73, 74, 75, - 76, 0, 77, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 87, 0, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, - 0, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 174, 0, - 0, 0, 0, 0, 175, 176, 177, 178, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, - 180, 340, 12, 13, 14, 15, 16, 17, 155, 156, - 157, 0, 158, 159, 160, 161, 162, 163, 164, 18, - 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, - 29, 30, 31, 32, 0, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, - 68, 69, 70, 71, 165, 166, 167, 168, 169, 170, - 171, 0, 0, 172, 173, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 181, 0, 0, 0, 0, + 0, 182, 183, 184, 185, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 186, 187, 15, 16, + 17, 18, 19, 20, 163, 164, 165, 0, 166, 167, + 168, 169, 170, 171, 172, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + 0, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 173, 117, 75, 118, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 73, 74, 75, 76, 0, 77, 0, 0, + 76, 77, 78, 79, 0, 80, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 84, 0, 85, 0, 0, 0, + 0, 0, 87, 0, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 174, 0, 0, 0, 0, 0, 175, - 176, 177, 178, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 179, 180, 12, 13, 14, 15, - 16, 17, 155, 156, 157, 0, 158, 159, 160, 161, - 162, 163, 164, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 0, 33, - 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 165, 166, - 167, 168, 169, 170, 171, 0, 0, 172, 173, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 73, 74, 75, 76, - 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 83, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 181, 0, 0, 0, 0, 0, 182, 183, 184, + 185, 15, 16, 17, 18, 19, 20, 0, 0, 0, + 0, 0, 186, 131, 0, 0, 0, 0, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 0, 36, 37, 38, 39, 40, 41, + 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 0, 117, 75, 118, 174, 175, 176, + 177, 178, 0, 0, 179, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 84, 0, - 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 76, 77, 78, 79, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 86, 0, 17, 18, 19, 20, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 0, 0, 0, 0, 0, 87, 0, 88, 0, 41, + 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 0, 181, 75, 0, 0, 0, 0, + 182, 183, 184, 185, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 77, 78, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 174, 0, 0, - 0, 0, 0, 175, 176, 177, 178, 12, 13, 14, - 15, 16, 17, 0, 0, 0, 0, 0, 179, 126, - 0, 0, 0, 0, 18, 19, 20, 21, 22, 23, + 0, 0, 17, 18, 19, 20, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 0, - 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, + 0, 0, 0, 0, 0, 87, 0, 88, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, - 63, 64, 65, 66, 67, 68, 69, 70, 71, 0, - 166, 167, 168, 169, 170, 171, 0, 0, 172, 173, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 73, 74, 75, - 76, 0, 77, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 83, 14, 15, 16, 17, + 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 0, 0, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 0, 0, 0, 0, 0, 0, 84, - 0, 85, 38, 39, 40, 41, 42, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, - 66, 67, 68, 69, 70, 71, 0, 72, 174, 0, - 0, 0, 0, 0, 175, 176, 177, 178, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, - 0, 0, 0, 0, 0, 74, 75, 76, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 247, 0, 0, + 0, 0, 0, 77, 78, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 14, 15, 16, 17, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 0, 0, 0, 0, 0, 0, 84, 0, 85, 38, - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, - 69, 70, 71, 0, 72, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 241, 0, - 0, 0, 74, 75, 76, 0, 0, 0, 0, 0, + 0, 17, 18, 19, 20, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 0, 0, + 0, 0, 0, 0, 87, 0, 88, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, + 74, 0, 117, 75, 118, 174, 175, 176, 177, 178, + 0, 0, 179, 180, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 331, 0, 0, 0, + 0, 0, 77, 78, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 14, 15, 16, 17, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 18, 19, 20, 21, 22, - 23, 24, 25, 26, 27, 28, 29, 0, 0, 0, - 0, 0, 0, 84, 0, 85, 38, 39, 40, 41, - 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, - 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, - 0, 166, 167, 168, 169, 170, 171, 0, 0, 172, - 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 321, 0, 0, 0, 74, - 75, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 87, 0, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 84, 0, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, - 0, 0, 0, 0, 0, 175, 176, 177, 178, 12, - 13, 14, 15, 16, 17, 0, 0, 0, 0, 0, - 253, 0, 0, 0, 0, 0, 18, 19, 20, 21, + 0, 0, 181, 0, 0, 0, 0, 0, 182, 183, + 184, 185, 15, 16, 17, 18, 19, 20, 0, 0, + 0, 0, 0, 260, 0, 0, 0, 0, 0, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 0, 33, 34, 35, 36, 37, 38, 39, 40, + 32, 33, 34, 35, 0, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, - 71, 0, 166, 167, 168, 169, 170, 171, 0, 0, - 172, 173, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 335, - 74, 75, 76, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 83, 0, 0, + 71, 72, 73, 74, 0, 117, 75, 118, 174, 175, + 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 342, 77, 78, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 84, 0, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 87, 0, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 14, 15, 16, 17, 0, - 174, 0, 0, 0, 0, 0, 175, 176, 177, 178, - 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 0, 166, 167, 168, 169, - 170, 171, 0, 0, 172, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 74, 75, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 17, 18, 19, 20, 0, 181, 0, 0, 0, 0, + 0, 182, 183, 184, 185, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 0, 117, 75, 118, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 77, 78, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 84, 0, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, - 15, 16, 17, 0, 174, 0, 0, 231, 0, 0, - 175, 176, 177, 178, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 38, 39, 40, 41, 42, - 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, - 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, - 63, 64, 65, 66, 67, 68, 69, 70, 71, 0, - 166, 167, 168, 169, 170, 171, 0, 0, 172, 173, + 0, 0, 87, 0, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 74, 75, - 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 17, 18, 19, 20, + 0, 181, 0, 0, 238, 0, 0, 182, 183, 184, + 185, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 72, 73, 74, 0, 117, 75, 118, + 174, 175, 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 77, 78, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, - 0, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 14, 15, 16, 17, 0, 174, 0, - 0, 316, 0, 0, 175, 176, 177, 178, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, - 69, 70, 71, 0, 166, 167, 168, 169, 170, 171, - 0, 0, 172, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 74, 75, 76, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 87, 0, + 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 17, 18, 19, 20, 0, 181, 0, 0, + 323, 0, 0, 182, 183, 184, 185, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, + 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 0, 117, 75, 118, 174, 175, 176, 177, + 178, 0, 0, 179, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 77, 78, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 84, 0, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 14, 15, 16, - 17, 0, 174, 0, 0, 369, 0, 0, 175, 176, - 177, 178, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 38, 39, 40, 41, 42, 43, 44, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, - 65, 66, 67, 68, 69, 70, 71, 0, 166, 167, - 168, 169, 170, 171, 0, 0, 172, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 74, 75, 76, 0, + 0, 0, 0, 0, 87, 0, 88, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 17, 18, + 19, 20, 0, 181, 0, 0, 380, 0, 0, 182, + 183, 184, 185, 21, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 41, 42, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, 0, 117, + 75, 118, 174, 175, 176, 177, 178, 0, 0, 179, + 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, + 78, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 84, 0, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 87, 0, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 14, 15, 16, 17, 0, 174, 0, 0, 0, - 0, 0, 175, 176, 177, 178, 18, 19, 20, 21, - 22, 23, 24, 25, 26, 27, 28, 29, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 38, 39, 40, + 0, 0, 0, 0, 17, 18, 19, 20, 0, 181, + 0, 0, 0, 0, 0, 182, 183, 184, 185, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, - 271, 0, 166, 167, 168, 169, 170, 171, 0, 0, - 172, 173, 0, 0, 0, 0, 0, 0, 0, 0, + 71, 72, 73, 278, 0, 117, 75, 118, 174, 175, + 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 74, 75, 76, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 77, 78, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 84, 0, 85, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 87, 0, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 12, 13, 14, 15, 16, 17, 0, - 174, 0, 0, 0, 0, 0, 175, 176, 177, 178, - 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 0, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 17, 18, 19, 20, 0, 181, 0, 0, 0, 0, + 0, 182, 183, 184, 185, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 401, + 0, 117, 75, 118, 174, 175, 176, 177, 178, 0, + 0, 179, 180, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 77, 78, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 73, 74, 75, 76, 0, 77, 0, - 0, 0, 0, 0, 0, 0, 78, 79, 80, 81, - 82, 83, 14, 15, 16, 17, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 18, 19, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 0, - 0, 0, 0, 0, 0, 84, 0, 85, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 87, 0, 88, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 15, 16, 17, 18, 19, 20, + 0, 181, 0, 0, 0, 0, 0, 182, 183, 184, + 185, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 0, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 72, 73, 74, 0, 0, 75, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 76, 77, 78, 79, + 0, 80, 0, 0, 0, 0, 0, 0, 0, 81, + 82, 83, 84, 85, 86, 17, 18, 19, 20, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 0, 0, 0, 0, 0, 0, 87, 0, + 88, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, - 70, 71, 0, 343, 14, 15, 16, 17, 171, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, - 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, - 29, 74, 75, 76, 0, 0, 0, 0, 0, 0, - 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, - 68, 69, 70, 71, 0, 72, 14, 15, 16, 17, - 0, 0, 84, 0, 85, 0, 0, 0, 0, 0, - 0, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 74, 75, 76, 0, 0, 0, 0, - 0, 0, 38, 39, 40, 41, 42, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, - 66, 67, 68, 69, 70, 71, 0, 72, 0, 0, - 0, 0, 0, 0, 84, 0, 85, 0, 0, 0, + 70, 71, 72, 73, 74, 0, 0, 75, 17, 18, + 19, 20, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 21, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 0, 77, 78, 79, 0, + 0, 0, 0, 0, 41, 42, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, 0, 0, + 75, 0, 0, 0, 0, 0, 0, 87, 0, 88, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 84, 0, 85 + 87, 0, 88 }; static const yytype_int16 yycheck[] = { - 9, 73, 73, 157, 143, 161, 76, 163, 143, 91, - 4, 76, 229, 86, 87, 258, 190, 148, 174, 4, - 9, 78, 9, 109, 96, 97, 93, 94, 95, 96, - 97, 98, 99, 100, 101, 102, 196, 172, 173, 33, - 34, 35, 194, 115, 196, 0, 3, 4, 33, 34, - 35, 199, 199, 199, 214, 199, 230, 113, 193, 199, - 110, 215, 214, 383, 84, 85, 76, 215, 215, 215, - 199, 215, 104, 213, 394, 32, 33, 34, 87, 36, - 37, 38, 39, 40, 213, 117, 112, 330, 195, 98, - 229, 113, 199, 194, 229, 251, 270, 314, 87, 255, - 87, 113, 258, 195, 113, 322, 237, 199, 113, 263, - 266, 285, 33, 34, 195, 113, 37, 126, 199, 76, - 315, 195, 104, 105, 106, 199, 135, 195, 76, 194, - 212, 199, 195, 307, 207, 208, 199, 146, 113, 148, - 195, 315, 33, 34, 35, 199, 216, 214, 157, 196, - 306, 368, 287, 288, 289, 290, 291, 292, 293, 294, - 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, - 305, 180, 215, 216, 330, 314, 196, 372, 198, 314, - 204, 205, 206, 322, 200, 201, 76, 322, 294, 295, - 296, 297, 387, 82, 83, 390, 88, 89, 372, 290, - 291, 195, 216, 398, 292, 293, 215, 76, 298, 299, - 405, 385, 76, 387, 3, 4, 390, 226, 113, 76, - 376, 194, 215, 214, 398, 215, 380, 215, 237, 368, - 194, 405, 215, 368, 194, 213, 194, 393, 3, 4, - 194, 250, 195, 32, 33, 34, 209, 36, 37, 258, - 211, 210, 90, 92, 263, 194, 410, 76, 196, 215, - 197, 78, 75, 335, 335, 195, 197, 32, 33, 34, - 196, 36, 37, 38, 39, 40, 194, 199, 214, 76, - 195, 197, 194, 197, 197, 214, 214, 195, 215, 12, - 214, 216, 197, 267, 214, 301, 215, 300, 302, 129, - 136, 303, 246, 304, 77, 305, 146, 250, 323, 226, - 394, 89, 381, 180, -1, 226, 250, 330, 87, -1, - -1, 330, -1, -1, -1, -1, -1, -1, -1, -1, + 9, 8, 76, 76, 93, 169, 165, 171, 155, 151, + 235, 76, 77, 78, 76, 86, 87, 181, 88, 89, + 198, 198, 4, 265, 322, 99, 100, 3, 4, 394, + 9, 9, 201, 201, 217, 218, 98, 80, 216, 216, + 107, 33, 34, 84, 85, 37, 120, 412, 217, 217, + 151, 33, 34, 35, 111, 122, 32, 33, 34, 4, + 36, 37, 0, 222, 201, 115, 73, 201, 95, 96, + 97, 98, 99, 100, 101, 102, 103, 104, 179, 180, + 217, 90, 112, 217, 115, 383, 201, 115, 33, 34, + 35, 98, 101, 235, 258, 337, 321, 197, 262, 200, + 215, 265, 249, 328, 111, 201, 115, 405, 114, 273, + 408, 90, 90, 197, 202, 203, 197, 201, 416, 215, + 201, 115, 131, 90, 91, 214, 424, 198, 115, 200, + 115, 140, 3, 4, 235, 142, 236, 197, 197, 209, + 210, 201, 201, 76, 77, 78, 155, 154, 157, 313, + 197, 197, 196, 218, 379, 201, 165, 106, 107, 108, + 197, 32, 33, 34, 201, 36, 37, 38, 39, 40, + 218, 197, 201, 337, 198, 201, 196, 277, 196, 321, + 301, 302, 303, 304, 297, 298, 328, 115, 347, 216, + 299, 300, 292, 294, 295, 296, 297, 298, 299, 300, + 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, + 311, 312, 274, 222, 314, 197, 76, 77, 78, 196, + 321, 217, 322, 387, 233, 232, 216, 328, 217, 3, + 4, 217, 391, 33, 34, 35, 196, 379, 196, 196, + 249, 206, 207, 208, 305, 306, 217, 411, 257, 215, + 196, 219, 196, 212, 197, 355, 265, 196, 32, 33, + 34, 270, 36, 37, 38, 39, 40, 274, 342, 342, + 429, 211, 213, 92, 94, 217, 196, 199, 379, 198, + 75, 80, 197, 383, 198, 216, 199, 196, 199, 201, + 197, 196, 216, 197, 217, 216, 199, 199, 197, 197, + 400, 218, 76, 403, 78, 405, 216, 199, 408, 12, + 216, 308, 307, 311, 141, 233, 416, 217, 309, 312, + 134, 253, 329, 80, 424, 233, 310, 157, 337, 329, + 257, 92, 412, 270, 392, 337, 90, 344, 347, -1, + -1, 257, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 391, -1, -1, 394, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 380, -1, -1, 383, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 394, -1, -1, -1, -1, - -1, -1, 3, 4, 5, 6, 7, 8, 9, 10, - 11, 410, 13, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33, 34, -1, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, - 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, - 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, - 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, - 81, -1, -1, 84, 85, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 103, 104, 105, 106, -1, 108, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 121, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 155, -1, 157, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 412, -1, -1, -1, -1, -1, -1, + -1, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 429, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, -1, 36, 37, 38, 39, 40, 41, + 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, + 82, 83, -1, -1, 86, 87, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 105, 106, 107, 108, -1, 110, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 194, -1, -1, -1, -1, -1, 200, - 201, 202, 203, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 215, 216, 217, 3, 4, 5, - 6, 7, 8, 9, 10, 11, -1, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 33, 34, -1, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, - 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, - 76, 77, 78, 79, 80, 81, -1, -1, 84, 85, + -1, 123, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 103, 104, 105, - 106, -1, 108, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 121, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 157, -1, 159, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 155, - -1, 157, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 194, -1, - -1, -1, -1, -1, 200, 201, 202, 203, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 215, - 216, 217, 3, 4, 5, 6, 7, 8, 9, 10, - 11, -1, 13, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33, 34, -1, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, - 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, - 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, - 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, - 81, -1, -1, 84, 85, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 196, -1, -1, -1, -1, -1, + 202, 203, 204, 205, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 217, 218, 219, 3, 4, + 5, 6, 7, 8, 9, 10, 11, -1, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + -1, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 103, 104, 105, 106, -1, 108, -1, -1, + 105, 106, 107, 108, -1, 110, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 123, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 121, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 155, -1, 157, -1, -1, -1, + -1, -1, 157, -1, 159, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 194, -1, -1, -1, -1, -1, 200, - 201, 202, 203, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 215, 216, 217, 3, 4, 5, - 6, 7, 8, 9, 10, 11, -1, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 33, 34, -1, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, - 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, - 76, 77, 78, 79, 80, 81, -1, -1, 84, 85, + -1, 196, -1, -1, -1, -1, -1, 202, 203, 204, + 205, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 217, 218, 219, 3, 4, 5, 6, 7, + 8, 9, 10, 11, -1, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 33, 34, -1, 36, 37, + 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, + 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, + 78, 79, 80, 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 103, 104, 105, - 106, -1, 108, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 121, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 105, 106, 107, + 108, -1, 110, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 123, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 155, - -1, 157, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 157, + -1, 159, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 194, -1, - -1, -1, -1, -1, 200, 201, 202, 203, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 215, - 216, 217, 3, 4, 5, 6, 7, 8, 9, 10, + -1, -1, -1, -1, -1, -1, -1, -1, 196, -1, + -1, -1, -1, -1, 202, 203, 204, 205, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 217, + 218, 219, 3, 4, 5, 6, 7, 8, 9, 10, 11, -1, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, -1, 36, 37, 38, 39, 40, @@ -1657,295 +1657,312 @@ static const yytype_int16 yycheck[] = 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, - 81, -1, -1, 84, 85, -1, -1, -1, -1, -1, + 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 103, 104, 105, 106, -1, 108, -1, -1, + -1, -1, -1, -1, 105, 106, 107, 108, -1, 110, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 121, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 123, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 155, -1, 157, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 157, -1, 159, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 194, -1, -1, -1, -1, -1, 200, - 201, 202, 203, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 215, 216, 3, 4, 5, 6, - 7, 8, 9, 10, 11, -1, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, -1, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, - 77, 78, 79, 80, 81, -1, -1, 84, 85, -1, + -1, -1, -1, -1, -1, 196, -1, -1, -1, -1, + -1, 202, 203, 204, 205, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 217, 218, 3, 4, + 5, 6, 7, 8, 9, 10, 11, -1, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + -1, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 103, 104, 105, 106, - -1, 108, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 121, -1, -1, -1, -1, -1, + 105, 106, 107, 108, -1, 110, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 123, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 155, -1, - 157, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 157, -1, 159, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 194, -1, -1, - -1, -1, -1, 200, 201, 202, 203, 3, 4, 5, - 6, 7, 8, -1, -1, -1, -1, -1, 215, 216, - -1, -1, -1, -1, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 33, 34, -1, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, - 66, 67, 68, 69, 70, 71, 72, 73, 74, -1, - 76, 77, 78, 79, 80, 81, -1, -1, 84, 85, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 103, 104, 105, - 106, -1, 108, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 121, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 20, 21, 22, 23, 24, 25, 26, 27, 28, - 29, 30, 31, -1, -1, -1, -1, -1, -1, 155, - -1, 157, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, - 69, 70, 71, 72, 73, 74, -1, 76, 194, -1, - -1, -1, -1, -1, 200, 201, 202, 203, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 215, - -1, -1, -1, -1, -1, 104, 105, 106, -1, -1, + -1, 196, -1, -1, -1, -1, -1, 202, 203, 204, + 205, 3, 4, 5, 6, 7, 8, -1, -1, -1, + -1, -1, 217, 218, -1, -1, -1, -1, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, -1, 36, 37, 38, 39, 40, 41, + 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, -1, 76, 77, 78, 79, 80, 81, + 82, 83, -1, -1, 86, 87, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 105, 106, 107, 108, -1, 110, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 5, 6, 7, 8, -1, -1, -1, + -1, 123, -1, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - -1, -1, -1, -1, -1, -1, 155, -1, 157, 41, + -1, -1, -1, -1, -1, 157, -1, 159, -1, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 74, -1, 76, -1, -1, -1, -1, -1, + 72, 73, 74, -1, 196, 77, -1, -1, -1, -1, + 202, 203, 204, 205, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 217, -1, -1, -1, -1, + -1, -1, -1, -1, 106, 107, 108, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 5, 6, 7, 8, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 31, -1, + -1, -1, -1, -1, -1, 157, -1, 159, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, + 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, + 73, 74, -1, -1, 77, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 219, -1, -1, + -1, -1, -1, 106, 107, 108, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 5, 6, 7, 8, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, -1, -1, + -1, -1, -1, -1, 157, -1, 159, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, + 74, -1, 76, 77, 78, 79, 80, 81, 82, 83, + -1, -1, 86, 87, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 219, -1, -1, -1, + -1, -1, 106, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 217, -1, - -1, -1, 104, 105, 106, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 20, 21, 22, 23, 24, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 157, -1, 159, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 196, -1, -1, -1, -1, -1, 202, 203, + 204, 205, 3, 4, 5, 6, 7, 8, -1, -1, + -1, -1, -1, 217, -1, -1, -1, -1, -1, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, -1, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, + 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, -1, 76, 77, 78, 79, 80, + 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 105, 106, 107, 108, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 123, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 157, -1, 159, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 5, 6, 7, 8, -1, 196, -1, -1, -1, -1, + -1, 202, 203, 204, 205, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, -1, -1, -1, - -1, -1, -1, 155, -1, 157, 41, 42, 43, 44, + -1, -1, -1, -1, -1, -1, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - -1, 76, 77, 78, 79, 80, 81, -1, -1, 84, - 85, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 217, -1, -1, -1, 104, - 105, 106, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 106, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 155, -1, 157, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 194, - -1, -1, -1, -1, -1, 200, 201, 202, 203, 3, - 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, - 215, -1, -1, -1, -1, -1, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, - 34, -1, 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, - 74, -1, 76, 77, 78, 79, 80, 81, -1, -1, - 84, 85, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 103, - 104, 105, 106, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 121, -1, -1, + -1, -1, 157, -1, 159, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 5, 6, 7, 8, + -1, 196, -1, -1, 199, -1, -1, 202, 203, 204, + 205, 20, 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 72, 73, 74, -1, 76, 77, 78, + 79, 80, 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 155, -1, 157, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 106, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 5, 6, 7, 8, -1, - 194, -1, -1, -1, -1, -1, 200, 201, 202, 203, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 41, 42, 43, 44, 45, 46, 47, 48, 49, - 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, - 70, 71, 72, 73, 74, -1, 76, 77, 78, 79, - 80, 81, -1, -1, 84, 85, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 104, 105, 106, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 157, -1, + 159, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 5, 6, 7, 8, -1, 196, -1, -1, + 199, -1, -1, 202, 203, 204, 205, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 31, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, + 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, + 73, 74, -1, 76, 77, 78, 79, 80, 81, 82, + 83, -1, -1, 86, 87, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 155, -1, 157, -1, -1, + -1, -1, -1, 106, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, - 6, 7, 8, -1, 194, -1, -1, 197, -1, -1, - 200, 201, 202, 203, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 41, 42, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, - 66, 67, 68, 69, 70, 71, 72, 73, 74, -1, - 76, 77, 78, 79, 80, 81, -1, -1, 84, 85, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 104, 105, - 106, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 157, -1, 159, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 155, - -1, 157, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 5, 6, + 7, 8, -1, 196, -1, -1, 199, -1, -1, 202, + 203, 204, 205, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 41, 42, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, -1, 76, + 77, 78, 79, 80, 81, 82, 83, -1, -1, 86, + 87, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 106, + 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 5, 6, 7, 8, -1, 194, -1, - -1, 197, -1, -1, 200, 201, 202, 203, 20, 21, - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 41, - 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, - 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 74, -1, 76, 77, 78, 79, 80, 81, - -1, -1, 84, 85, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 104, 105, 106, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 157, -1, 159, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 5, 6, 7, 8, -1, 196, + -1, -1, -1, -1, -1, 202, 203, 204, 205, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, + 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, -1, 76, 77, 78, 79, 80, + 81, 82, 83, -1, -1, 86, 87, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 155, -1, 157, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 106, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 5, 6, 7, - 8, -1, 194, -1, -1, 197, -1, -1, 200, 201, - 202, 203, 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, - 68, 69, 70, 71, 72, 73, 74, -1, 76, 77, - 78, 79, 80, 81, -1, -1, 84, 85, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 104, 105, 106, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 157, -1, 159, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 155, -1, 157, + 5, 6, 7, 8, -1, 196, -1, -1, -1, -1, + -1, 202, 203, 204, 205, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + -1, 76, 77, 78, 79, 80, 81, 82, 83, -1, + -1, 86, 87, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 106, 107, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 5, 6, 7, 8, -1, 194, -1, -1, -1, - -1, -1, 200, 201, 202, 203, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, - 74, -1, 76, 77, 78, 79, 80, 81, -1, -1, - 84, 85, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 104, 105, 106, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 157, -1, 159, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 3, 4, 5, 6, 7, 8, + -1, 196, -1, -1, -1, -1, -1, 202, 203, 204, + 205, 20, 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, -1, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 72, 73, 74, -1, -1, 77, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 155, -1, 157, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 105, 106, 107, 108, + -1, 110, -1, -1, -1, -1, -1, -1, -1, 118, + 119, 120, 121, 122, 123, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 3, 4, 5, 6, 7, 8, -1, - 194, -1, -1, -1, -1, -1, 200, 201, 202, 203, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31, 32, 33, 34, -1, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 30, 31, -1, -1, -1, -1, -1, -1, 157, -1, + 159, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, - 70, 71, 72, 73, 74, -1, 76, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 70, 71, 72, 73, 74, -1, -1, 77, 5, 6, + 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, -1, 106, 107, 108, -1, + -1, -1, -1, -1, 41, 42, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, -1, -1, + 77, -1, -1, -1, -1, -1, -1, 157, -1, 159, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 103, 104, 105, 106, -1, 108, -1, - -1, -1, -1, -1, -1, -1, 116, 117, 118, 119, - 120, 121, 5, 6, 7, 8, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 20, 21, 22, - 23, 24, 25, 26, 27, 28, 29, 30, 31, -1, - -1, -1, -1, -1, -1, 155, -1, 157, 41, 42, - 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, - 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, - 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, - 73, 74, -1, 76, 5, 6, 7, 8, 81, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 104, 105, 106, -1, -1, -1, -1, -1, -1, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, - 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, - 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, - 71, 72, 73, 74, -1, 76, 5, 6, 7, 8, - -1, -1, 155, -1, 157, -1, -1, -1, -1, -1, - -1, 20, 21, 22, 23, 24, 25, 26, 27, 28, - 29, 30, 31, 104, 105, 106, -1, -1, -1, -1, - -1, -1, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, - 69, 70, 71, 72, 73, 74, -1, 76, -1, -1, - -1, -1, -1, -1, 155, -1, 157, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 155, -1, 157 + 157, -1, 159 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint16 yystos[] = { - 0, 109, 219, 221, 78, 0, 223, 113, 110, 220, - 224, 76, 3, 4, 5, 6, 7, 8, 20, 21, - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 36, 37, 38, 39, 40, 41, 42, - 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, - 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, - 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, - 73, 74, 76, 103, 104, 105, 106, 108, 116, 117, - 118, 119, 120, 121, 155, 157, 222, 225, 255, 256, - 257, 258, 259, 264, 265, 266, 267, 270, 272, 273, - 274, 275, 276, 277, 278, 279, 303, 304, 112, 33, - 34, 37, 76, 216, 76, 270, 273, 278, 113, 113, - 113, 113, 113, 194, 303, 215, 216, 290, 195, 199, - 4, 33, 34, 35, 261, 262, 271, 199, 215, 76, - 273, 273, 274, 196, 275, 76, 216, 274, 280, 281, - 273, 275, 76, 268, 269, 9, 10, 11, 13, 14, - 15, 16, 17, 18, 19, 75, 76, 77, 78, 79, - 80, 81, 84, 85, 194, 200, 201, 202, 203, 215, - 216, 217, 226, 227, 228, 230, 231, 232, 233, 234, - 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, - 245, 246, 247, 248, 249, 250, 251, 253, 255, 256, - 274, 285, 286, 287, 288, 291, 292, 293, 296, 297, - 298, 302, 261, 260, 263, 274, 262, 76, 194, 196, - 214, 197, 237, 250, 254, 274, 113, 280, 76, 282, - 283, 217, 281, 215, 214, 195, 199, 215, 215, 286, - 194, 194, 215, 215, 253, 194, 253, 213, 194, 237, - 237, 253, 217, 291, 84, 85, 196, 198, 195, 195, - 199, 74, 251, 194, 93, 94, 95, 96, 97, 98, - 99, 100, 101, 102, 214, 252, 237, 204, 205, 206, - 200, 201, 82, 83, 86, 87, 207, 208, 88, 89, - 209, 210, 211, 90, 92, 91, 212, 199, 215, 217, - 286, 76, 260, 263, 196, 214, 197, 254, 251, 284, - 197, 217, 196, 199, 215, 78, 269, 75, 285, 292, - 299, 253, 215, 253, 213, 103, 253, 266, 295, 195, - 217, 229, 253, 76, 232, 251, 251, 237, 237, 237, - 239, 239, 240, 240, 241, 241, 241, 241, 242, 242, - 243, 244, 245, 246, 247, 248, 253, 251, 196, 197, - 254, 284, 214, 197, 254, 283, 194, 295, 300, 301, - 195, 195, 76, 195, 197, 213, 254, 214, 197, 284, - 214, 197, 253, 215, 195, 286, 294, 288, 214, 287, - 289, 290, 251, 197, 284, 214, 284, 195, 253, 289, - 12, 284, 284, 215, 286 + 0, 111, 221, 223, 80, 0, 225, 115, 112, 222, + 227, 76, 77, 78, 226, 3, 4, 5, 6, 7, + 8, 20, 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + 70, 71, 72, 73, 74, 77, 105, 106, 107, 108, + 110, 118, 119, 120, 121, 122, 123, 157, 159, 224, + 228, 262, 263, 264, 265, 266, 271, 272, 273, 274, + 277, 279, 280, 281, 282, 283, 284, 285, 286, 311, + 312, 114, 33, 34, 37, 218, 226, 76, 78, 229, + 277, 280, 285, 115, 115, 115, 115, 115, 196, 311, + 217, 218, 298, 197, 201, 4, 33, 34, 35, 268, + 269, 278, 201, 217, 76, 78, 226, 229, 280, 280, + 281, 198, 282, 226, 281, 287, 288, 218, 280, 282, + 226, 275, 276, 9, 10, 11, 13, 14, 15, 16, + 17, 18, 19, 75, 79, 80, 81, 82, 83, 86, + 87, 196, 202, 203, 204, 205, 217, 218, 219, 229, + 230, 231, 233, 234, 235, 236, 237, 238, 239, 244, + 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, + 255, 256, 257, 258, 260, 262, 263, 281, 292, 293, + 294, 295, 299, 300, 301, 304, 305, 306, 310, 268, + 267, 270, 281, 269, 226, 198, 216, 196, 199, 244, + 257, 261, 281, 115, 226, 289, 290, 219, 288, 287, + 217, 216, 197, 201, 217, 217, 293, 196, 196, 217, + 217, 260, 196, 260, 215, 196, 244, 244, 260, 219, + 296, 86, 87, 198, 200, 197, 197, 201, 74, 258, + 196, 95, 96, 97, 98, 99, 100, 101, 102, 103, + 104, 216, 259, 244, 206, 207, 208, 202, 203, 84, + 85, 88, 89, 209, 210, 90, 91, 211, 212, 213, + 92, 94, 93, 214, 201, 217, 219, 293, 226, 267, + 270, 198, 216, 199, 261, 258, 291, 199, 198, 201, + 217, 219, 80, 276, 75, 292, 300, 307, 260, 217, + 260, 215, 105, 260, 273, 303, 197, 299, 232, 260, + 226, 229, 240, 241, 242, 243, 258, 258, 244, 244, + 244, 246, 246, 247, 247, 248, 248, 248, 248, 249, + 249, 250, 251, 252, 253, 254, 255, 260, 258, 198, + 199, 261, 291, 216, 199, 261, 290, 196, 303, 308, + 309, 197, 197, 226, 197, 219, 199, 196, 197, 197, + 201, 74, 258, 215, 261, 216, 199, 291, 216, 199, + 260, 217, 197, 293, 302, 295, 216, 294, 297, 298, + 258, 258, 199, 291, 216, 291, 197, 260, 297, 12, + 291, 291, 217, 293 }; #define yyerrok (yyerrstatus = 0) @@ -2636,7 +2653,7 @@ YYLTYPE yylloc; } /* Line 1251 of yacc.c */ -#line 2640 "glsl_parser.cpp" +#line 2657 "glsl_parser.cpp" yylsp[0] = yylloc; goto yysetstate; @@ -2824,43 +2841,69 @@ yyreduce: case 2: /* Line 1464 of yacc.c */ -#line 213 "glsl_parser.ypp" +#line 218 "glsl_parser.ypp" { _mesa_glsl_initialize_types(state); ;} break; - case 5: + case 3: /* Line 1464 of yacc.c */ #line 222 "glsl_parser.ypp" { + delete state->symbols; + state->symbols = new(ralloc_parent(state)) glsl_symbol_table; + _mesa_glsl_initialize_types(state); + ;} + break; + + case 5: + +/* Line 1464 of yacc.c */ +#line 232 "glsl_parser.ypp" + { + bool supported = false; + switch ((yyvsp[(2) - (3)].n)) { case 100: state->es_shader = true; + supported = state->Const.GLSL_100ES; + break; case 110: + supported = state->Const.GLSL_110; + break; case 120: + supported = state->Const.GLSL_120; + break; case 130: - /* FINISHME: Check against implementation support versions. */ - state->language_version = (yyvsp[(2) - (3)].n); - state->version_string = - talloc_asprintf(state, "GLSL%s %d.%02d", - state->es_shader ? " ES" : "", - state->language_version / 100, - state->language_version % 100); + supported = state->Const.GLSL_130; break; default: - _mesa_glsl_error(& (yylsp[(2) - (3)]), state, "Shading language version" - "%u is not supported\n", (yyvsp[(2) - (3)].n)); + supported = false; break; } + + state->language_version = (yyvsp[(2) - (3)].n); + state->version_string = + ralloc_asprintf(state, "GLSL%s %d.%02d", + state->es_shader ? " ES" : "", + state->language_version / 100, + state->language_version % 100); + + if (!supported) { + _mesa_glsl_error(& (yylsp[(2) - (3)]), state, "%s is not supported. " + "Supported versions are: %s\n", + state->version_string, + state->supported_version_string); + } ;} break; case 10: /* Line 1464 of yacc.c */ -#line 251 "glsl_parser.ypp" +#line 276 "glsl_parser.ypp" { if (state->language_version < 120) { _mesa_glsl_warning(& (yylsp[(1) - (2)]), state, @@ -2872,10 +2915,10 @@ yyreduce: ;} break; - case 13: + case 16: /* Line 1464 of yacc.c */ -#line 269 "glsl_parser.ypp" +#line 300 "glsl_parser.ypp" { if (!_mesa_glsl_process_extension((yyvsp[(2) - (5)].identifier), & (yylsp[(2) - (5)]), (yyvsp[(4) - (5)].identifier), & (yylsp[(4) - (5)]), state)) { YYERROR; @@ -2883,10 +2926,10 @@ yyreduce: ;} break; - case 14: + case 17: /* Line 1464 of yacc.c */ -#line 278 "glsl_parser.ypp" +#line 309 "glsl_parser.ypp" { /* FINISHME: The NULL test is required because pragmas are set to * FINISHME: NULL. (See production rule for external_declaration.) @@ -2896,10 +2939,10 @@ yyreduce: ;} break; - case 15: + case 18: /* Line 1464 of yacc.c */ -#line 286 "glsl_parser.ypp" +#line 317 "glsl_parser.ypp" { /* FINISHME: The NULL test is required because pragmas are set to * FINISHME: NULL. (See production rule for external_declaration.) @@ -2909,10 +2952,10 @@ yyreduce: ;} break; - case 17: + case 21: /* Line 1464 of yacc.c */ -#line 301 "glsl_parser.ypp" +#line 333 "glsl_parser.ypp" { void *ctx = state; (yyval.expression) = new(ctx) ast_expression(ast_identifier, NULL, NULL, NULL); @@ -2921,10 +2964,10 @@ yyreduce: ;} break; - case 18: + case 22: /* Line 1464 of yacc.c */ -#line 308 "glsl_parser.ypp" +#line 340 "glsl_parser.ypp" { void *ctx = state; (yyval.expression) = new(ctx) ast_expression(ast_int_constant, NULL, NULL, NULL); @@ -2933,10 +2976,10 @@ yyreduce: ;} break; - case 19: + case 23: /* Line 1464 of yacc.c */ -#line 315 "glsl_parser.ypp" +#line 347 "glsl_parser.ypp" { void *ctx = state; (yyval.expression) = new(ctx) ast_expression(ast_uint_constant, NULL, NULL, NULL); @@ -2945,10 +2988,10 @@ yyreduce: ;} break; - case 20: + case 24: /* Line 1464 of yacc.c */ -#line 322 "glsl_parser.ypp" +#line 354 "glsl_parser.ypp" { void *ctx = state; (yyval.expression) = new(ctx) ast_expression(ast_float_constant, NULL, NULL, NULL); @@ -2957,10 +3000,10 @@ yyreduce: ;} break; - case 21: + case 25: /* Line 1464 of yacc.c */ -#line 329 "glsl_parser.ypp" +#line 361 "glsl_parser.ypp" { void *ctx = state; (yyval.expression) = new(ctx) ast_expression(ast_bool_constant, NULL, NULL, NULL); @@ -2969,19 +3012,19 @@ yyreduce: ;} break; - case 22: + case 26: /* Line 1464 of yacc.c */ -#line 336 "glsl_parser.ypp" +#line 368 "glsl_parser.ypp" { (yyval.expression) = (yyvsp[(2) - (3)].expression); ;} break; - case 24: + case 28: /* Line 1464 of yacc.c */ -#line 344 "glsl_parser.ypp" +#line 376 "glsl_parser.ypp" { void *ctx = state; (yyval.expression) = new(ctx) ast_expression(ast_array_index, (yyvsp[(1) - (4)].expression), (yyvsp[(3) - (4)].expression), NULL); @@ -2989,19 +3032,19 @@ yyreduce: ;} break; - case 25: + case 29: /* Line 1464 of yacc.c */ -#line 350 "glsl_parser.ypp" +#line 382 "glsl_parser.ypp" { (yyval.expression) = (yyvsp[(1) - (1)].expression); ;} break; - case 26: + case 30: /* Line 1464 of yacc.c */ -#line 354 "glsl_parser.ypp" +#line 386 "glsl_parser.ypp" { void *ctx = state; (yyval.expression) = new(ctx) ast_expression(ast_field_selection, (yyvsp[(1) - (3)].expression), NULL, NULL); @@ -3010,10 +3053,10 @@ yyreduce: ;} break; - case 27: + case 31: /* Line 1464 of yacc.c */ -#line 361 "glsl_parser.ypp" +#line 393 "glsl_parser.ypp" { void *ctx = state; (yyval.expression) = new(ctx) ast_expression(ast_post_inc, (yyvsp[(1) - (2)].expression), NULL, NULL); @@ -3021,10 +3064,10 @@ yyreduce: ;} break; - case 28: + case 32: /* Line 1464 of yacc.c */ -#line 367 "glsl_parser.ypp" +#line 399 "glsl_parser.ypp" { void *ctx = state; (yyval.expression) = new(ctx) ast_expression(ast_post_dec, (yyvsp[(1) - (2)].expression), NULL, NULL); @@ -3032,10 +3075,10 @@ yyreduce: ;} break; - case 32: + case 36: /* Line 1464 of yacc.c */ -#line 385 "glsl_parser.ypp" +#line 417 "glsl_parser.ypp" { void *ctx = state; (yyval.expression) = new(ctx) ast_expression(ast_field_selection, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression), NULL); @@ -3043,10 +3086,10 @@ yyreduce: ;} break; - case 37: + case 41: /* Line 1464 of yacc.c */ -#line 404 "glsl_parser.ypp" +#line 436 "glsl_parser.ypp" { (yyval.expression) = (yyvsp[(1) - (2)].expression); (yyval.expression)->set_location(yylloc); @@ -3054,10 +3097,10 @@ yyreduce: ;} break; - case 38: + case 42: /* Line 1464 of yacc.c */ -#line 410 "glsl_parser.ypp" +#line 442 "glsl_parser.ypp" { (yyval.expression) = (yyvsp[(1) - (3)].expression); (yyval.expression)->set_location(yylloc); @@ -3065,10 +3108,10 @@ yyreduce: ;} break; - case 40: + case 44: /* Line 1464 of yacc.c */ -#line 426 "glsl_parser.ypp" +#line 458 "glsl_parser.ypp" { void *ctx = state; (yyval.expression) = new(ctx) ast_function_expression((yyvsp[(1) - (1)].type_specifier)); @@ -3076,10 +3119,10 @@ yyreduce: ;} break; - case 41: + case 45: /* Line 1464 of yacc.c */ -#line 432 "glsl_parser.ypp" +#line 464 "glsl_parser.ypp" { void *ctx = state; ast_expression *callee = new(ctx) ast_expression((yyvsp[(1) - (1)].identifier)); @@ -3088,10 +3131,10 @@ yyreduce: ;} break; - case 42: + case 46: /* Line 1464 of yacc.c */ -#line 439 "glsl_parser.ypp" +#line 471 "glsl_parser.ypp" { void *ctx = state; ast_expression *callee = new(ctx) ast_expression((yyvsp[(1) - (1)].identifier)); @@ -3100,10 +3143,44 @@ yyreduce: ;} break; - case 44: + case 51: /* Line 1464 of yacc.c */ -#line 451 "glsl_parser.ypp" +#line 491 "glsl_parser.ypp" + { + (yyval.expression) = (yyvsp[(1) - (2)].expression); + (yyval.expression)->set_location(yylloc); + (yyval.expression)->expressions.push_tail(& (yyvsp[(2) - (2)].expression)->link); + ;} + break; + + case 52: + +/* Line 1464 of yacc.c */ +#line 497 "glsl_parser.ypp" + { + (yyval.expression) = (yyvsp[(1) - (3)].expression); + (yyval.expression)->set_location(yylloc); + (yyval.expression)->expressions.push_tail(& (yyvsp[(3) - (3)].expression)->link); + ;} + break; + + case 53: + +/* Line 1464 of yacc.c */ +#line 509 "glsl_parser.ypp" + { + void *ctx = state; + ast_expression *callee = new(ctx) ast_expression((yyvsp[(1) - (2)].identifier)); + (yyval.expression) = new(ctx) ast_function_expression(callee); + (yyval.expression)->set_location(yylloc); + ;} + break; + + case 55: + +/* Line 1464 of yacc.c */ +#line 521 "glsl_parser.ypp" { void *ctx = state; (yyval.expression) = new(ctx) ast_expression(ast_pre_inc, (yyvsp[(2) - (2)].expression), NULL, NULL); @@ -3111,10 +3188,10 @@ yyreduce: ;} break; - case 45: + case 56: /* Line 1464 of yacc.c */ -#line 457 "glsl_parser.ypp" +#line 527 "glsl_parser.ypp" { void *ctx = state; (yyval.expression) = new(ctx) ast_expression(ast_pre_dec, (yyvsp[(2) - (2)].expression), NULL, NULL); @@ -3122,10 +3199,10 @@ yyreduce: ;} break; - case 46: + case 57: /* Line 1464 of yacc.c */ -#line 463 "glsl_parser.ypp" +#line 533 "glsl_parser.ypp" { void *ctx = state; (yyval.expression) = new(ctx) ast_expression((yyvsp[(1) - (2)].n), (yyvsp[(2) - (2)].expression), NULL, NULL); @@ -3133,38 +3210,38 @@ yyreduce: ;} break; - case 47: + case 58: /* Line 1464 of yacc.c */ -#line 472 "glsl_parser.ypp" +#line 542 "glsl_parser.ypp" { (yyval.n) = ast_plus; ;} break; - case 48: + case 59: /* Line 1464 of yacc.c */ -#line 473 "glsl_parser.ypp" +#line 543 "glsl_parser.ypp" { (yyval.n) = ast_neg; ;} break; - case 49: + case 60: /* Line 1464 of yacc.c */ -#line 474 "glsl_parser.ypp" +#line 544 "glsl_parser.ypp" { (yyval.n) = ast_logic_not; ;} break; - case 50: + case 61: /* Line 1464 of yacc.c */ -#line 475 "glsl_parser.ypp" +#line 545 "glsl_parser.ypp" { (yyval.n) = ast_bit_not; ;} break; - case 52: + case 63: /* Line 1464 of yacc.c */ -#line 481 "glsl_parser.ypp" +#line 551 "glsl_parser.ypp" { void *ctx = state; (yyval.expression) = new(ctx) ast_expression_bin(ast_mul, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression)); @@ -3172,10 +3249,10 @@ yyreduce: ;} break; - case 53: + case 64: /* Line 1464 of yacc.c */ -#line 487 "glsl_parser.ypp" +#line 557 "glsl_parser.ypp" { void *ctx = state; (yyval.expression) = new(ctx) ast_expression_bin(ast_div, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression)); @@ -3183,10 +3260,10 @@ yyreduce: ;} break; - case 54: + case 65: /* Line 1464 of yacc.c */ -#line 493 "glsl_parser.ypp" +#line 563 "glsl_parser.ypp" { void *ctx = state; (yyval.expression) = new(ctx) ast_expression_bin(ast_mod, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression)); @@ -3194,10 +3271,10 @@ yyreduce: ;} break; - case 56: + case 67: /* Line 1464 of yacc.c */ -#line 503 "glsl_parser.ypp" +#line 573 "glsl_parser.ypp" { void *ctx = state; (yyval.expression) = new(ctx) ast_expression_bin(ast_add, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression)); @@ -3205,10 +3282,10 @@ yyreduce: ;} break; - case 57: + case 68: /* Line 1464 of yacc.c */ -#line 509 "glsl_parser.ypp" +#line 579 "glsl_parser.ypp" { void *ctx = state; (yyval.expression) = new(ctx) ast_expression_bin(ast_sub, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression)); @@ -3216,10 +3293,10 @@ yyreduce: ;} break; - case 59: + case 70: /* Line 1464 of yacc.c */ -#line 519 "glsl_parser.ypp" +#line 589 "glsl_parser.ypp" { void *ctx = state; (yyval.expression) = new(ctx) ast_expression_bin(ast_lshift, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression)); @@ -3227,10 +3304,10 @@ yyreduce: ;} break; - case 60: + case 71: /* Line 1464 of yacc.c */ -#line 525 "glsl_parser.ypp" +#line 595 "glsl_parser.ypp" { void *ctx = state; (yyval.expression) = new(ctx) ast_expression_bin(ast_rshift, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression)); @@ -3238,10 +3315,10 @@ yyreduce: ;} break; - case 62: + case 73: /* Line 1464 of yacc.c */ -#line 535 "glsl_parser.ypp" +#line 605 "glsl_parser.ypp" { void *ctx = state; (yyval.expression) = new(ctx) ast_expression_bin(ast_less, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression)); @@ -3249,10 +3326,10 @@ yyreduce: ;} break; - case 63: + case 74: /* Line 1464 of yacc.c */ -#line 541 "glsl_parser.ypp" +#line 611 "glsl_parser.ypp" { void *ctx = state; (yyval.expression) = new(ctx) ast_expression_bin(ast_greater, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression)); @@ -3260,10 +3337,10 @@ yyreduce: ;} break; - case 64: + case 75: /* Line 1464 of yacc.c */ -#line 547 "glsl_parser.ypp" +#line 617 "glsl_parser.ypp" { void *ctx = state; (yyval.expression) = new(ctx) ast_expression_bin(ast_lequal, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression)); @@ -3271,10 +3348,10 @@ yyreduce: ;} break; - case 65: + case 76: /* Line 1464 of yacc.c */ -#line 553 "glsl_parser.ypp" +#line 623 "glsl_parser.ypp" { void *ctx = state; (yyval.expression) = new(ctx) ast_expression_bin(ast_gequal, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression)); @@ -3282,10 +3359,10 @@ yyreduce: ;} break; - case 67: + case 78: /* Line 1464 of yacc.c */ -#line 563 "glsl_parser.ypp" +#line 633 "glsl_parser.ypp" { void *ctx = state; (yyval.expression) = new(ctx) ast_expression_bin(ast_equal, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression)); @@ -3293,10 +3370,10 @@ yyreduce: ;} break; - case 68: + case 79: /* Line 1464 of yacc.c */ -#line 569 "glsl_parser.ypp" +#line 639 "glsl_parser.ypp" { void *ctx = state; (yyval.expression) = new(ctx) ast_expression_bin(ast_nequal, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression)); @@ -3304,10 +3381,10 @@ yyreduce: ;} break; - case 70: + case 81: /* Line 1464 of yacc.c */ -#line 579 "glsl_parser.ypp" +#line 649 "glsl_parser.ypp" { void *ctx = state; (yyval.expression) = new(ctx) ast_expression_bin(ast_bit_and, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression)); @@ -3315,10 +3392,10 @@ yyreduce: ;} break; - case 72: + case 83: /* Line 1464 of yacc.c */ -#line 589 "glsl_parser.ypp" +#line 659 "glsl_parser.ypp" { void *ctx = state; (yyval.expression) = new(ctx) ast_expression_bin(ast_bit_xor, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression)); @@ -3326,10 +3403,10 @@ yyreduce: ;} break; - case 74: + case 85: /* Line 1464 of yacc.c */ -#line 599 "glsl_parser.ypp" +#line 669 "glsl_parser.ypp" { void *ctx = state; (yyval.expression) = new(ctx) ast_expression_bin(ast_bit_or, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression)); @@ -3337,10 +3414,10 @@ yyreduce: ;} break; - case 76: + case 87: /* Line 1464 of yacc.c */ -#line 609 "glsl_parser.ypp" +#line 679 "glsl_parser.ypp" { void *ctx = state; (yyval.expression) = new(ctx) ast_expression_bin(ast_logic_and, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression)); @@ -3348,10 +3425,10 @@ yyreduce: ;} break; - case 78: + case 89: /* Line 1464 of yacc.c */ -#line 619 "glsl_parser.ypp" +#line 689 "glsl_parser.ypp" { void *ctx = state; (yyval.expression) = new(ctx) ast_expression_bin(ast_logic_xor, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression)); @@ -3359,10 +3436,10 @@ yyreduce: ;} break; - case 80: + case 91: /* Line 1464 of yacc.c */ -#line 629 "glsl_parser.ypp" +#line 699 "glsl_parser.ypp" { void *ctx = state; (yyval.expression) = new(ctx) ast_expression_bin(ast_logic_or, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression)); @@ -3370,10 +3447,10 @@ yyreduce: ;} break; - case 82: + case 93: /* Line 1464 of yacc.c */ -#line 639 "glsl_parser.ypp" +#line 709 "glsl_parser.ypp" { void *ctx = state; (yyval.expression) = new(ctx) ast_expression(ast_conditional, (yyvsp[(1) - (5)].expression), (yyvsp[(3) - (5)].expression), (yyvsp[(5) - (5)].expression)); @@ -3381,10 +3458,10 @@ yyreduce: ;} break; - case 84: + case 95: /* Line 1464 of yacc.c */ -#line 649 "glsl_parser.ypp" +#line 719 "glsl_parser.ypp" { void *ctx = state; (yyval.expression) = new(ctx) ast_expression((yyvsp[(2) - (3)].n), (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression), NULL); @@ -3392,96 +3469,96 @@ yyreduce: ;} break; - case 85: + case 96: /* Line 1464 of yacc.c */ -#line 657 "glsl_parser.ypp" +#line 727 "glsl_parser.ypp" { (yyval.n) = ast_assign; ;} break; - case 86: + case 97: /* Line 1464 of yacc.c */ -#line 658 "glsl_parser.ypp" +#line 728 "glsl_parser.ypp" { (yyval.n) = ast_mul_assign; ;} break; - case 87: + case 98: /* Line 1464 of yacc.c */ -#line 659 "glsl_parser.ypp" +#line 729 "glsl_parser.ypp" { (yyval.n) = ast_div_assign; ;} break; - case 88: + case 99: /* Line 1464 of yacc.c */ -#line 660 "glsl_parser.ypp" +#line 730 "glsl_parser.ypp" { (yyval.n) = ast_mod_assign; ;} break; - case 89: + case 100: /* Line 1464 of yacc.c */ -#line 661 "glsl_parser.ypp" +#line 731 "glsl_parser.ypp" { (yyval.n) = ast_add_assign; ;} break; - case 90: + case 101: /* Line 1464 of yacc.c */ -#line 662 "glsl_parser.ypp" +#line 732 "glsl_parser.ypp" { (yyval.n) = ast_sub_assign; ;} break; - case 91: + case 102: /* Line 1464 of yacc.c */ -#line 663 "glsl_parser.ypp" +#line 733 "glsl_parser.ypp" { (yyval.n) = ast_ls_assign; ;} break; - case 92: + case 103: /* Line 1464 of yacc.c */ -#line 664 "glsl_parser.ypp" +#line 734 "glsl_parser.ypp" { (yyval.n) = ast_rs_assign; ;} break; - case 93: + case 104: /* Line 1464 of yacc.c */ -#line 665 "glsl_parser.ypp" +#line 735 "glsl_parser.ypp" { (yyval.n) = ast_and_assign; ;} break; - case 94: + case 105: /* Line 1464 of yacc.c */ -#line 666 "glsl_parser.ypp" +#line 736 "glsl_parser.ypp" { (yyval.n) = ast_xor_assign; ;} break; - case 95: + case 106: /* Line 1464 of yacc.c */ -#line 667 "glsl_parser.ypp" +#line 737 "glsl_parser.ypp" { (yyval.n) = ast_or_assign; ;} break; - case 96: + case 107: /* Line 1464 of yacc.c */ -#line 672 "glsl_parser.ypp" +#line 742 "glsl_parser.ypp" { (yyval.expression) = (yyvsp[(1) - (1)].expression); ;} break; - case 97: + case 108: /* Line 1464 of yacc.c */ -#line 676 "glsl_parser.ypp" +#line 746 "glsl_parser.ypp" { void *ctx = state; if ((yyvsp[(1) - (3)].expression)->oper != ast_sequence) { @@ -3496,28 +3573,29 @@ yyreduce: ;} break; - case 99: + case 110: /* Line 1464 of yacc.c */ -#line 696 "glsl_parser.ypp" +#line 766 "glsl_parser.ypp" { + state->symbols->pop_scope(); (yyval.node) = (yyvsp[(1) - (2)].function); ;} break; - case 100: + case 111: /* Line 1464 of yacc.c */ -#line 700 "glsl_parser.ypp" +#line 771 "glsl_parser.ypp" { (yyval.node) = (yyvsp[(1) - (2)].declarator_list); ;} break; - case 101: + case 112: /* Line 1464 of yacc.c */ -#line 704 "glsl_parser.ypp" +#line 775 "glsl_parser.ypp" { (yyvsp[(3) - (4)].type_specifier)->precision = (yyvsp[(2) - (4)].n); (yyvsp[(3) - (4)].type_specifier)->is_precision_statement = true; @@ -3525,43 +3603,46 @@ yyreduce: ;} break; - case 105: + case 116: /* Line 1464 of yacc.c */ -#line 722 "glsl_parser.ypp" +#line 793 "glsl_parser.ypp" { (yyval.function) = (yyvsp[(1) - (2)].function); (yyval.function)->parameters.push_tail(& (yyvsp[(2) - (2)].parameter_declarator)->link); ;} break; - case 106: + case 117: /* Line 1464 of yacc.c */ -#line 727 "glsl_parser.ypp" +#line 798 "glsl_parser.ypp" { (yyval.function) = (yyvsp[(1) - (3)].function); (yyval.function)->parameters.push_tail(& (yyvsp[(3) - (3)].parameter_declarator)->link); ;} break; - case 107: + case 118: /* Line 1464 of yacc.c */ -#line 735 "glsl_parser.ypp" +#line 806 "glsl_parser.ypp" { void *ctx = state; (yyval.function) = new(ctx) ast_function(); (yyval.function)->set_location(yylloc); (yyval.function)->return_type = (yyvsp[(1) - (3)].fully_specified_type); (yyval.function)->identifier = (yyvsp[(2) - (3)].identifier); + + state->symbols->add_function(new(state) ir_function((yyvsp[(2) - (3)].identifier))); + state->symbols->push_scope(); ;} break; - case 108: + case 119: /* Line 1464 of yacc.c */ -#line 746 "glsl_parser.ypp" +#line 820 "glsl_parser.ypp" { void *ctx = state; (yyval.parameter_declarator) = new(ctx) ast_parameter_declarator(); @@ -3573,10 +3654,10 @@ yyreduce: ;} break; - case 109: + case 120: /* Line 1464 of yacc.c */ -#line 756 "glsl_parser.ypp" +#line 830 "glsl_parser.ypp" { void *ctx = state; (yyval.parameter_declarator) = new(ctx) ast_parameter_declarator(); @@ -3590,10 +3671,10 @@ yyreduce: ;} break; - case 110: + case 121: /* Line 1464 of yacc.c */ -#line 771 "glsl_parser.ypp" +#line 845 "glsl_parser.ypp" { (yyvsp[(1) - (3)].type_qualifier).flags.i |= (yyvsp[(2) - (3)].type_qualifier).flags.i; @@ -3602,20 +3683,20 @@ yyreduce: ;} break; - case 111: + case 122: /* Line 1464 of yacc.c */ -#line 778 "glsl_parser.ypp" +#line 852 "glsl_parser.ypp" { (yyval.parameter_declarator) = (yyvsp[(2) - (2)].parameter_declarator); (yyval.parameter_declarator)->type->qualifier = (yyvsp[(1) - (2)].type_qualifier); ;} break; - case 112: + case 123: /* Line 1464 of yacc.c */ -#line 783 "glsl_parser.ypp" +#line 857 "glsl_parser.ypp" { void *ctx = state; (yyvsp[(1) - (3)].type_qualifier).flags.i |= (yyvsp[(2) - (3)].type_qualifier).flags.i; @@ -3628,10 +3709,10 @@ yyreduce: ;} break; - case 113: + case 124: /* Line 1464 of yacc.c */ -#line 794 "glsl_parser.ypp" +#line 868 "glsl_parser.ypp" { void *ctx = state; (yyval.parameter_declarator) = new(ctx) ast_parameter_declarator(); @@ -3642,39 +3723,39 @@ yyreduce: ;} break; - case 114: + case 125: /* Line 1464 of yacc.c */ -#line 806 "glsl_parser.ypp" +#line 880 "glsl_parser.ypp" { memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier))); ;} break; - case 115: + case 126: /* Line 1464 of yacc.c */ -#line 810 "glsl_parser.ypp" +#line 884 "glsl_parser.ypp" { memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier))); (yyval.type_qualifier).flags.q.in = 1; ;} break; - case 116: + case 127: /* Line 1464 of yacc.c */ -#line 815 "glsl_parser.ypp" +#line 889 "glsl_parser.ypp" { memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier))); (yyval.type_qualifier).flags.q.out = 1; ;} break; - case 117: + case 128: /* Line 1464 of yacc.c */ -#line 820 "glsl_parser.ypp" +#line 894 "glsl_parser.ypp" { memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier))); (yyval.type_qualifier).flags.q.in = 1; @@ -3682,10 +3763,10 @@ yyreduce: ;} break; - case 120: + case 131: /* Line 1464 of yacc.c */ -#line 834 "glsl_parser.ypp" +#line 908 "glsl_parser.ypp" { void *ctx = state; ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(3) - (3)].identifier), false, NULL, NULL); @@ -3693,13 +3774,14 @@ yyreduce: (yyval.declarator_list) = (yyvsp[(1) - (3)].declarator_list); (yyval.declarator_list)->declarations.push_tail(&decl->link); + state->symbols->add_variable(new(state) ir_variable(NULL, (yyvsp[(3) - (3)].identifier), ir_var_auto)); ;} break; - case 121: + case 132: /* Line 1464 of yacc.c */ -#line 843 "glsl_parser.ypp" +#line 918 "glsl_parser.ypp" { void *ctx = state; ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(3) - (5)].identifier), true, NULL, NULL); @@ -3707,13 +3789,14 @@ yyreduce: (yyval.declarator_list) = (yyvsp[(1) - (5)].declarator_list); (yyval.declarator_list)->declarations.push_tail(&decl->link); + state->symbols->add_variable(new(state) ir_variable(NULL, (yyvsp[(3) - (5)].identifier), ir_var_auto)); ;} break; - case 122: + case 133: /* Line 1464 of yacc.c */ -#line 852 "glsl_parser.ypp" +#line 928 "glsl_parser.ypp" { void *ctx = state; ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(3) - (6)].identifier), true, (yyvsp[(5) - (6)].expression), NULL); @@ -3721,13 +3804,14 @@ yyreduce: (yyval.declarator_list) = (yyvsp[(1) - (6)].declarator_list); (yyval.declarator_list)->declarations.push_tail(&decl->link); + state->symbols->add_variable(new(state) ir_variable(NULL, (yyvsp[(3) - (6)].identifier), ir_var_auto)); ;} break; - case 123: + case 134: /* Line 1464 of yacc.c */ -#line 861 "glsl_parser.ypp" +#line 938 "glsl_parser.ypp" { void *ctx = state; ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(3) - (7)].identifier), true, NULL, (yyvsp[(7) - (7)].expression)); @@ -3735,13 +3819,14 @@ yyreduce: (yyval.declarator_list) = (yyvsp[(1) - (7)].declarator_list); (yyval.declarator_list)->declarations.push_tail(&decl->link); + state->symbols->add_variable(new(state) ir_variable(NULL, (yyvsp[(3) - (7)].identifier), ir_var_auto)); ;} break; - case 124: + case 135: /* Line 1464 of yacc.c */ -#line 870 "glsl_parser.ypp" +#line 948 "glsl_parser.ypp" { void *ctx = state; ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(3) - (8)].identifier), true, (yyvsp[(5) - (8)].expression), (yyvsp[(8) - (8)].expression)); @@ -3749,13 +3834,14 @@ yyreduce: (yyval.declarator_list) = (yyvsp[(1) - (8)].declarator_list); (yyval.declarator_list)->declarations.push_tail(&decl->link); + state->symbols->add_variable(new(state) ir_variable(NULL, (yyvsp[(3) - (8)].identifier), ir_var_auto)); ;} break; - case 125: + case 136: /* Line 1464 of yacc.c */ -#line 879 "glsl_parser.ypp" +#line 958 "glsl_parser.ypp" { void *ctx = state; ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(3) - (5)].identifier), false, NULL, (yyvsp[(5) - (5)].expression)); @@ -3763,13 +3849,14 @@ yyreduce: (yyval.declarator_list) = (yyvsp[(1) - (5)].declarator_list); (yyval.declarator_list)->declarations.push_tail(&decl->link); + state->symbols->add_variable(new(state) ir_variable(NULL, (yyvsp[(3) - (5)].identifier), ir_var_auto)); ;} break; - case 126: + case 137: /* Line 1464 of yacc.c */ -#line 892 "glsl_parser.ypp" +#line 972 "glsl_parser.ypp" { void *ctx = state; if ((yyvsp[(1) - (1)].fully_specified_type)->specifier->type_specifier != ast_struct) { @@ -3782,10 +3869,10 @@ yyreduce: ;} break; - case 127: + case 138: /* Line 1464 of yacc.c */ -#line 903 "glsl_parser.ypp" +#line 983 "glsl_parser.ypp" { void *ctx = state; ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(2) - (2)].identifier), false, NULL, NULL); @@ -3796,10 +3883,10 @@ yyreduce: ;} break; - case 128: + case 139: /* Line 1464 of yacc.c */ -#line 912 "glsl_parser.ypp" +#line 992 "glsl_parser.ypp" { void *ctx = state; ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(2) - (4)].identifier), true, NULL, NULL); @@ -3810,10 +3897,10 @@ yyreduce: ;} break; - case 129: + case 140: /* Line 1464 of yacc.c */ -#line 921 "glsl_parser.ypp" +#line 1001 "glsl_parser.ypp" { void *ctx = state; ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(2) - (5)].identifier), true, (yyvsp[(4) - (5)].expression), NULL); @@ -3824,10 +3911,10 @@ yyreduce: ;} break; - case 130: + case 141: /* Line 1464 of yacc.c */ -#line 930 "glsl_parser.ypp" +#line 1010 "glsl_parser.ypp" { void *ctx = state; ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(2) - (6)].identifier), true, NULL, (yyvsp[(6) - (6)].expression)); @@ -3838,10 +3925,10 @@ yyreduce: ;} break; - case 131: + case 142: /* Line 1464 of yacc.c */ -#line 939 "glsl_parser.ypp" +#line 1019 "glsl_parser.ypp" { void *ctx = state; ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(2) - (7)].identifier), true, (yyvsp[(4) - (7)].expression), (yyvsp[(7) - (7)].expression)); @@ -3852,10 +3939,10 @@ yyreduce: ;} break; - case 132: + case 143: /* Line 1464 of yacc.c */ -#line 948 "glsl_parser.ypp" +#line 1028 "glsl_parser.ypp" { void *ctx = state; ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(2) - (4)].identifier), false, NULL, (yyvsp[(4) - (4)].expression)); @@ -3866,10 +3953,10 @@ yyreduce: ;} break; - case 133: + case 144: /* Line 1464 of yacc.c */ -#line 957 "glsl_parser.ypp" +#line 1037 "glsl_parser.ypp" { void *ctx = state; ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(2) - (2)].identifier), false, NULL, NULL); @@ -3882,10 +3969,10 @@ yyreduce: ;} break; - case 134: + case 145: /* Line 1464 of yacc.c */ -#line 971 "glsl_parser.ypp" +#line 1051 "glsl_parser.ypp" { void *ctx = state; (yyval.fully_specified_type) = new(ctx) ast_fully_specified_type(); @@ -3894,10 +3981,10 @@ yyreduce: ;} break; - case 135: + case 146: /* Line 1464 of yacc.c */ -#line 978 "glsl_parser.ypp" +#line 1058 "glsl_parser.ypp" { void *ctx = state; (yyval.fully_specified_type) = new(ctx) ast_fully_specified_type(); @@ -3907,19 +3994,19 @@ yyreduce: ;} break; - case 136: + case 147: /* Line 1464 of yacc.c */ -#line 989 "glsl_parser.ypp" +#line 1069 "glsl_parser.ypp" { (yyval.type_qualifier) = (yyvsp[(3) - (4)].type_qualifier); ;} break; - case 138: + case 149: /* Line 1464 of yacc.c */ -#line 997 "glsl_parser.ypp" +#line 1077 "glsl_parser.ypp" { if (((yyvsp[(1) - (3)].type_qualifier).flags.i & (yyvsp[(3) - (3)].type_qualifier).flags.i) != 0) { _mesa_glsl_error(& (yylsp[(3) - (3)]), state, @@ -3937,16 +4024,17 @@ yyreduce: ;} break; - case 139: + case 150: /* Line 1464 of yacc.c */ -#line 1016 "glsl_parser.ypp" +#line 1096 "glsl_parser.ypp" { bool got_one = false; memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier))); - if (state->ARB_fragment_coord_conventions_enable) { + /* Layout qualifiers for ARB_fragment_coord_conventions. */ + if (!got_one && state->ARB_fragment_coord_conventions_enable) { if (strcmp((yyvsp[(1) - (1)].identifier), "origin_upper_left") == 0) { got_one = true; (yyval.type_qualifier).flags.q.origin_upper_left = 1; @@ -3954,27 +4042,49 @@ yyreduce: got_one = true; (yyval.type_qualifier).flags.q.pixel_center_integer = 1; } + + if (got_one && state->ARB_fragment_coord_conventions_warn) { + _mesa_glsl_warning(& (yylsp[(1) - (1)]), state, + "GL_ARB_fragment_coord_conventions layout " + "identifier `%s' used\n", (yyvsp[(1) - (1)].identifier)); + } + } + + /* Layout qualifiers for AMD_conservative_depth. */ + if (!got_one && state->AMD_conservative_depth_enable) { + if (strcmp((yyvsp[(1) - (1)].identifier), "depth_any") == 0) { + got_one = true; + (yyval.type_qualifier).flags.q.depth_any = 1; + } else if (strcmp((yyvsp[(1) - (1)].identifier), "depth_greater") == 0) { + got_one = true; + (yyval.type_qualifier).flags.q.depth_greater = 1; + } else if (strcmp((yyvsp[(1) - (1)].identifier), "depth_less") == 0) { + got_one = true; + (yyval.type_qualifier).flags.q.depth_less = 1; + } else if (strcmp((yyvsp[(1) - (1)].identifier), "depth_unchanged") == 0) { + got_one = true; + (yyval.type_qualifier).flags.q.depth_unchanged = 1; + } + + if (got_one && state->AMD_conservative_depth_warn) { + _mesa_glsl_warning(& (yylsp[(1) - (1)]), state, + "GL_AMD_conservative_depth " + "layout qualifier `%s' is used\n", (yyvsp[(1) - (1)].identifier)); + } } - /* If the identifier didn't match any known layout identifiers, - * emit an error. - */ if (!got_one) { _mesa_glsl_error(& (yylsp[(1) - (1)]), state, "unrecognized layout identifier " "`%s'\n", (yyvsp[(1) - (1)].identifier)); YYERROR; - } else if (state->ARB_fragment_coord_conventions_warn) { - _mesa_glsl_warning(& (yylsp[(1) - (1)]), state, - "GL_ARB_fragment_coord_conventions layout " - "identifier `%s' used\n", (yyvsp[(1) - (1)].identifier)); } ;} break; - case 140: + case 151: /* Line 1464 of yacc.c */ -#line 1045 "glsl_parser.ypp" +#line 1148 "glsl_parser.ypp" { bool got_one = false; @@ -4014,80 +4124,80 @@ yyreduce: ;} break; - case 141: + case 152: /* Line 1464 of yacc.c */ -#line 1086 "glsl_parser.ypp" +#line 1189 "glsl_parser.ypp" { memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier))); (yyval.type_qualifier).flags.q.smooth = 1; ;} break; - case 142: + case 153: /* Line 1464 of yacc.c */ -#line 1091 "glsl_parser.ypp" +#line 1194 "glsl_parser.ypp" { memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier))); (yyval.type_qualifier).flags.q.flat = 1; ;} break; - case 143: + case 154: /* Line 1464 of yacc.c */ -#line 1096 "glsl_parser.ypp" +#line 1199 "glsl_parser.ypp" { memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier))); (yyval.type_qualifier).flags.q.noperspective = 1; ;} break; - case 144: + case 155: /* Line 1464 of yacc.c */ -#line 1104 "glsl_parser.ypp" +#line 1207 "glsl_parser.ypp" { memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier))); (yyval.type_qualifier).flags.q.constant = 1; ;} break; - case 147: + case 158: /* Line 1464 of yacc.c */ -#line 1114 "glsl_parser.ypp" +#line 1217 "glsl_parser.ypp" { (yyval.type_qualifier) = (yyvsp[(1) - (2)].type_qualifier); (yyval.type_qualifier).flags.i |= (yyvsp[(2) - (2)].type_qualifier).flags.i; ;} break; - case 149: + case 160: /* Line 1464 of yacc.c */ -#line 1120 "glsl_parser.ypp" +#line 1223 "glsl_parser.ypp" { (yyval.type_qualifier) = (yyvsp[(1) - (2)].type_qualifier); (yyval.type_qualifier).flags.i |= (yyvsp[(2) - (2)].type_qualifier).flags.i; ;} break; - case 150: + case 161: /* Line 1464 of yacc.c */ -#line 1125 "glsl_parser.ypp" +#line 1228 "glsl_parser.ypp" { (yyval.type_qualifier) = (yyvsp[(2) - (2)].type_qualifier); (yyval.type_qualifier).flags.q.invariant = 1; ;} break; - case 151: + case 162: /* Line 1464 of yacc.c */ -#line 1130 "glsl_parser.ypp" +#line 1233 "glsl_parser.ypp" { (yyval.type_qualifier) = (yyvsp[(2) - (3)].type_qualifier); (yyval.type_qualifier).flags.i |= (yyvsp[(3) - (3)].type_qualifier).flags.i; @@ -4095,50 +4205,50 @@ yyreduce: ;} break; - case 152: + case 163: /* Line 1464 of yacc.c */ -#line 1136 "glsl_parser.ypp" +#line 1239 "glsl_parser.ypp" { memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier))); (yyval.type_qualifier).flags.q.invariant = 1; ;} break; - case 153: + case 164: /* Line 1464 of yacc.c */ -#line 1144 "glsl_parser.ypp" +#line 1247 "glsl_parser.ypp" { memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier))); (yyval.type_qualifier).flags.q.constant = 1; ;} break; - case 154: + case 165: /* Line 1464 of yacc.c */ -#line 1149 "glsl_parser.ypp" +#line 1252 "glsl_parser.ypp" { memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier))); (yyval.type_qualifier).flags.q.attribute = 1; ;} break; - case 155: + case 166: /* Line 1464 of yacc.c */ -#line 1154 "glsl_parser.ypp" +#line 1257 "glsl_parser.ypp" { memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier))); (yyval.type_qualifier).flags.q.varying = 1; ;} break; - case 156: + case 167: /* Line 1464 of yacc.c */ -#line 1159 "glsl_parser.ypp" +#line 1262 "glsl_parser.ypp" { memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier))); (yyval.type_qualifier).flags.q.centroid = 1; @@ -4146,79 +4256,79 @@ yyreduce: ;} break; - case 157: + case 168: /* Line 1464 of yacc.c */ -#line 1165 "glsl_parser.ypp" +#line 1268 "glsl_parser.ypp" { memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier))); (yyval.type_qualifier).flags.q.in = 1; ;} break; - case 158: + case 169: /* Line 1464 of yacc.c */ -#line 1170 "glsl_parser.ypp" +#line 1273 "glsl_parser.ypp" { memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier))); (yyval.type_qualifier).flags.q.out = 1; ;} break; - case 159: + case 170: /* Line 1464 of yacc.c */ -#line 1175 "glsl_parser.ypp" +#line 1278 "glsl_parser.ypp" { memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier))); (yyval.type_qualifier).flags.q.centroid = 1; (yyval.type_qualifier).flags.q.in = 1; ;} break; - case 160: + case 171: /* Line 1464 of yacc.c */ -#line 1180 "glsl_parser.ypp" +#line 1283 "glsl_parser.ypp" { memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier))); (yyval.type_qualifier).flags.q.centroid = 1; (yyval.type_qualifier).flags.q.out = 1; ;} break; - case 161: + case 172: /* Line 1464 of yacc.c */ -#line 1185 "glsl_parser.ypp" +#line 1288 "glsl_parser.ypp" { memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier))); (yyval.type_qualifier).flags.q.uniform = 1; ;} break; - case 162: + case 173: /* Line 1464 of yacc.c */ -#line 1193 "glsl_parser.ypp" +#line 1296 "glsl_parser.ypp" { (yyval.type_specifier) = (yyvsp[(1) - (1)].type_specifier); ;} break; - case 163: + case 174: /* Line 1464 of yacc.c */ -#line 1197 "glsl_parser.ypp" +#line 1300 "glsl_parser.ypp" { (yyval.type_specifier) = (yyvsp[(2) - (2)].type_specifier); (yyval.type_specifier)->precision = (yyvsp[(1) - (2)].n); ;} break; - case 165: + case 176: /* Line 1464 of yacc.c */ -#line 1206 "glsl_parser.ypp" +#line 1309 "glsl_parser.ypp" { (yyval.type_specifier) = (yyvsp[(1) - (3)].type_specifier); (yyval.type_specifier)->is_array = true; @@ -4226,10 +4336,10 @@ yyreduce: ;} break; - case 166: + case 177: /* Line 1464 of yacc.c */ -#line 1212 "glsl_parser.ypp" +#line 1315 "glsl_parser.ypp" { (yyval.type_specifier) = (yyvsp[(1) - (4)].type_specifier); (yyval.type_specifier)->is_array = true; @@ -4237,10 +4347,10 @@ yyreduce: ;} break; - case 167: + case 178: /* Line 1464 of yacc.c */ -#line 1221 "glsl_parser.ypp" +#line 1324 "glsl_parser.ypp" { void *ctx = state; (yyval.type_specifier) = new(ctx) ast_type_specifier((yyvsp[(1) - (1)].n)); @@ -4248,10 +4358,10 @@ yyreduce: ;} break; - case 168: + case 179: /* Line 1464 of yacc.c */ -#line 1227 "glsl_parser.ypp" +#line 1330 "glsl_parser.ypp" { void *ctx = state; (yyval.type_specifier) = new(ctx) ast_type_specifier((yyvsp[(1) - (1)].struct_specifier)); @@ -4259,10 +4369,10 @@ yyreduce: ;} break; - case 169: + case 180: /* Line 1464 of yacc.c */ -#line 1233 "glsl_parser.ypp" +#line 1336 "glsl_parser.ypp" { void *ctx = state; (yyval.type_specifier) = new(ctx) ast_type_specifier((yyvsp[(1) - (1)].identifier)); @@ -4270,367 +4380,367 @@ yyreduce: ;} break; - case 170: + case 181: /* Line 1464 of yacc.c */ -#line 1241 "glsl_parser.ypp" +#line 1344 "glsl_parser.ypp" { (yyval.n) = ast_void; ;} break; - case 171: + case 182: /* Line 1464 of yacc.c */ -#line 1242 "glsl_parser.ypp" +#line 1345 "glsl_parser.ypp" { (yyval.n) = ast_float; ;} break; - case 172: + case 183: /* Line 1464 of yacc.c */ -#line 1243 "glsl_parser.ypp" +#line 1346 "glsl_parser.ypp" { (yyval.n) = ast_int; ;} break; - case 173: + case 184: /* Line 1464 of yacc.c */ -#line 1244 "glsl_parser.ypp" +#line 1347 "glsl_parser.ypp" { (yyval.n) = ast_uint; ;} break; - case 174: + case 185: /* Line 1464 of yacc.c */ -#line 1245 "glsl_parser.ypp" +#line 1348 "glsl_parser.ypp" { (yyval.n) = ast_bool; ;} break; - case 175: + case 186: /* Line 1464 of yacc.c */ -#line 1246 "glsl_parser.ypp" +#line 1349 "glsl_parser.ypp" { (yyval.n) = ast_vec2; ;} break; - case 176: + case 187: /* Line 1464 of yacc.c */ -#line 1247 "glsl_parser.ypp" +#line 1350 "glsl_parser.ypp" { (yyval.n) = ast_vec3; ;} break; - case 177: + case 188: /* Line 1464 of yacc.c */ -#line 1248 "glsl_parser.ypp" +#line 1351 "glsl_parser.ypp" { (yyval.n) = ast_vec4; ;} break; - case 178: + case 189: /* Line 1464 of yacc.c */ -#line 1249 "glsl_parser.ypp" +#line 1352 "glsl_parser.ypp" { (yyval.n) = ast_bvec2; ;} break; - case 179: + case 190: /* Line 1464 of yacc.c */ -#line 1250 "glsl_parser.ypp" +#line 1353 "glsl_parser.ypp" { (yyval.n) = ast_bvec3; ;} break; - case 180: + case 191: /* Line 1464 of yacc.c */ -#line 1251 "glsl_parser.ypp" +#line 1354 "glsl_parser.ypp" { (yyval.n) = ast_bvec4; ;} break; - case 181: + case 192: /* Line 1464 of yacc.c */ -#line 1252 "glsl_parser.ypp" +#line 1355 "glsl_parser.ypp" { (yyval.n) = ast_ivec2; ;} break; - case 182: + case 193: /* Line 1464 of yacc.c */ -#line 1253 "glsl_parser.ypp" +#line 1356 "glsl_parser.ypp" { (yyval.n) = ast_ivec3; ;} break; - case 183: + case 194: /* Line 1464 of yacc.c */ -#line 1254 "glsl_parser.ypp" +#line 1357 "glsl_parser.ypp" { (yyval.n) = ast_ivec4; ;} break; - case 184: + case 195: /* Line 1464 of yacc.c */ -#line 1255 "glsl_parser.ypp" +#line 1358 "glsl_parser.ypp" { (yyval.n) = ast_uvec2; ;} break; - case 185: + case 196: /* Line 1464 of yacc.c */ -#line 1256 "glsl_parser.ypp" +#line 1359 "glsl_parser.ypp" { (yyval.n) = ast_uvec3; ;} break; - case 186: + case 197: /* Line 1464 of yacc.c */ -#line 1257 "glsl_parser.ypp" +#line 1360 "glsl_parser.ypp" { (yyval.n) = ast_uvec4; ;} break; - case 187: + case 198: /* Line 1464 of yacc.c */ -#line 1258 "glsl_parser.ypp" +#line 1361 "glsl_parser.ypp" { (yyval.n) = ast_mat2; ;} break; - case 188: + case 199: /* Line 1464 of yacc.c */ -#line 1259 "glsl_parser.ypp" +#line 1362 "glsl_parser.ypp" { (yyval.n) = ast_mat2x3; ;} break; - case 189: + case 200: /* Line 1464 of yacc.c */ -#line 1260 "glsl_parser.ypp" +#line 1363 "glsl_parser.ypp" { (yyval.n) = ast_mat2x4; ;} break; - case 190: + case 201: /* Line 1464 of yacc.c */ -#line 1261 "glsl_parser.ypp" +#line 1364 "glsl_parser.ypp" { (yyval.n) = ast_mat3x2; ;} break; - case 191: + case 202: /* Line 1464 of yacc.c */ -#line 1262 "glsl_parser.ypp" +#line 1365 "glsl_parser.ypp" { (yyval.n) = ast_mat3; ;} break; - case 192: + case 203: /* Line 1464 of yacc.c */ -#line 1263 "glsl_parser.ypp" +#line 1366 "glsl_parser.ypp" { (yyval.n) = ast_mat3x4; ;} break; - case 193: + case 204: /* Line 1464 of yacc.c */ -#line 1264 "glsl_parser.ypp" +#line 1367 "glsl_parser.ypp" { (yyval.n) = ast_mat4x2; ;} break; - case 194: + case 205: /* Line 1464 of yacc.c */ -#line 1265 "glsl_parser.ypp" +#line 1368 "glsl_parser.ypp" { (yyval.n) = ast_mat4x3; ;} break; - case 195: + case 206: /* Line 1464 of yacc.c */ -#line 1266 "glsl_parser.ypp" +#line 1369 "glsl_parser.ypp" { (yyval.n) = ast_mat4; ;} break; - case 196: + case 207: /* Line 1464 of yacc.c */ -#line 1267 "glsl_parser.ypp" +#line 1370 "glsl_parser.ypp" { (yyval.n) = ast_sampler1d; ;} break; - case 197: + case 208: /* Line 1464 of yacc.c */ -#line 1268 "glsl_parser.ypp" +#line 1371 "glsl_parser.ypp" { (yyval.n) = ast_sampler2d; ;} break; - case 198: + case 209: /* Line 1464 of yacc.c */ -#line 1269 "glsl_parser.ypp" +#line 1372 "glsl_parser.ypp" { (yyval.n) = ast_sampler2drect; ;} break; - case 199: + case 210: /* Line 1464 of yacc.c */ -#line 1270 "glsl_parser.ypp" +#line 1373 "glsl_parser.ypp" { (yyval.n) = ast_sampler3d; ;} break; - case 200: + case 211: /* Line 1464 of yacc.c */ -#line 1271 "glsl_parser.ypp" +#line 1374 "glsl_parser.ypp" { (yyval.n) = ast_samplercube; ;} break; - case 201: + case 212: /* Line 1464 of yacc.c */ -#line 1272 "glsl_parser.ypp" +#line 1375 "glsl_parser.ypp" { (yyval.n) = ast_sampler1dshadow; ;} break; - case 202: + case 213: /* Line 1464 of yacc.c */ -#line 1273 "glsl_parser.ypp" +#line 1376 "glsl_parser.ypp" { (yyval.n) = ast_sampler2dshadow; ;} break; - case 203: + case 214: /* Line 1464 of yacc.c */ -#line 1274 "glsl_parser.ypp" +#line 1377 "glsl_parser.ypp" { (yyval.n) = ast_sampler2drectshadow; ;} break; - case 204: + case 215: /* Line 1464 of yacc.c */ -#line 1275 "glsl_parser.ypp" +#line 1378 "glsl_parser.ypp" { (yyval.n) = ast_samplercubeshadow; ;} break; - case 205: + case 216: /* Line 1464 of yacc.c */ -#line 1276 "glsl_parser.ypp" +#line 1379 "glsl_parser.ypp" { (yyval.n) = ast_sampler1darray; ;} break; - case 206: + case 217: /* Line 1464 of yacc.c */ -#line 1277 "glsl_parser.ypp" +#line 1380 "glsl_parser.ypp" { (yyval.n) = ast_sampler2darray; ;} break; - case 207: + case 218: /* Line 1464 of yacc.c */ -#line 1278 "glsl_parser.ypp" +#line 1381 "glsl_parser.ypp" { (yyval.n) = ast_sampler1darrayshadow; ;} break; - case 208: + case 219: /* Line 1464 of yacc.c */ -#line 1279 "glsl_parser.ypp" +#line 1382 "glsl_parser.ypp" { (yyval.n) = ast_sampler2darrayshadow; ;} break; - case 209: + case 220: /* Line 1464 of yacc.c */ -#line 1280 "glsl_parser.ypp" +#line 1383 "glsl_parser.ypp" { (yyval.n) = ast_isampler1d; ;} break; - case 210: + case 221: /* Line 1464 of yacc.c */ -#line 1281 "glsl_parser.ypp" +#line 1384 "glsl_parser.ypp" { (yyval.n) = ast_isampler2d; ;} break; - case 211: + case 222: /* Line 1464 of yacc.c */ -#line 1282 "glsl_parser.ypp" +#line 1385 "glsl_parser.ypp" { (yyval.n) = ast_isampler3d; ;} break; - case 212: + case 223: /* Line 1464 of yacc.c */ -#line 1283 "glsl_parser.ypp" +#line 1386 "glsl_parser.ypp" { (yyval.n) = ast_isamplercube; ;} break; - case 213: + case 224: /* Line 1464 of yacc.c */ -#line 1284 "glsl_parser.ypp" +#line 1387 "glsl_parser.ypp" { (yyval.n) = ast_isampler1darray; ;} break; - case 214: + case 225: /* Line 1464 of yacc.c */ -#line 1285 "glsl_parser.ypp" +#line 1388 "glsl_parser.ypp" { (yyval.n) = ast_isampler2darray; ;} break; - case 215: + case 226: /* Line 1464 of yacc.c */ -#line 1286 "glsl_parser.ypp" +#line 1389 "glsl_parser.ypp" { (yyval.n) = ast_usampler1d; ;} break; - case 216: + case 227: /* Line 1464 of yacc.c */ -#line 1287 "glsl_parser.ypp" +#line 1390 "glsl_parser.ypp" { (yyval.n) = ast_usampler2d; ;} break; - case 217: + case 228: /* Line 1464 of yacc.c */ -#line 1288 "glsl_parser.ypp" +#line 1391 "glsl_parser.ypp" { (yyval.n) = ast_usampler3d; ;} break; - case 218: + case 229: /* Line 1464 of yacc.c */ -#line 1289 "glsl_parser.ypp" +#line 1392 "glsl_parser.ypp" { (yyval.n) = ast_usamplercube; ;} break; - case 219: + case 230: /* Line 1464 of yacc.c */ -#line 1290 "glsl_parser.ypp" +#line 1393 "glsl_parser.ypp" { (yyval.n) = ast_usampler1darray; ;} break; - case 220: + case 231: /* Line 1464 of yacc.c */ -#line 1291 "glsl_parser.ypp" +#line 1394 "glsl_parser.ypp" { (yyval.n) = ast_usampler2darray; ;} break; - case 221: + case 232: /* Line 1464 of yacc.c */ -#line 1295 "glsl_parser.ypp" +#line 1398 "glsl_parser.ypp" { if (!state->es_shader && state->language_version < 130) _mesa_glsl_error(& (yylsp[(1) - (1)]), state, @@ -4643,10 +4753,10 @@ yyreduce: ;} break; - case 222: + case 233: /* Line 1464 of yacc.c */ -#line 1305 "glsl_parser.ypp" +#line 1408 "glsl_parser.ypp" { if (!state->es_shader && state->language_version < 130) _mesa_glsl_error(& (yylsp[(1) - (1)]), state, @@ -4659,10 +4769,10 @@ yyreduce: ;} break; - case 223: + case 234: /* Line 1464 of yacc.c */ -#line 1315 "glsl_parser.ypp" +#line 1418 "glsl_parser.ypp" { if (!state->es_shader && state->language_version < 130) _mesa_glsl_error(& (yylsp[(1) - (1)]), state, @@ -4675,21 +4785,22 @@ yyreduce: ;} break; - case 224: + case 235: /* Line 1464 of yacc.c */ -#line 1329 "glsl_parser.ypp" +#line 1432 "glsl_parser.ypp" { void *ctx = state; (yyval.struct_specifier) = new(ctx) ast_struct_specifier((yyvsp[(2) - (5)].identifier), (yyvsp[(4) - (5)].node)); (yyval.struct_specifier)->set_location(yylloc); + state->symbols->add_type((yyvsp[(2) - (5)].identifier), glsl_type::void_type); ;} break; - case 225: + case 236: /* Line 1464 of yacc.c */ -#line 1335 "glsl_parser.ypp" +#line 1439 "glsl_parser.ypp" { void *ctx = state; (yyval.struct_specifier) = new(ctx) ast_struct_specifier(NULL, (yyvsp[(3) - (4)].node)); @@ -4697,30 +4808,30 @@ yyreduce: ;} break; - case 226: + case 237: /* Line 1464 of yacc.c */ -#line 1344 "glsl_parser.ypp" +#line 1448 "glsl_parser.ypp" { (yyval.node) = (ast_node *) (yyvsp[(1) - (1)].declarator_list); (yyvsp[(1) - (1)].declarator_list)->link.self_link(); ;} break; - case 227: + case 238: /* Line 1464 of yacc.c */ -#line 1349 "glsl_parser.ypp" +#line 1453 "glsl_parser.ypp" { (yyval.node) = (ast_node *) (yyvsp[(1) - (2)].node); (yyval.node)->link.insert_before(& (yyvsp[(2) - (2)].declarator_list)->link); ;} break; - case 228: + case 239: /* Line 1464 of yacc.c */ -#line 1357 "glsl_parser.ypp" +#line 1461 "glsl_parser.ypp" { void *ctx = state; ast_fully_specified_type *type = new(ctx) ast_fully_specified_type(); @@ -4734,41 +4845,42 @@ yyreduce: ;} break; - case 229: + case 240: /* Line 1464 of yacc.c */ -#line 1372 "glsl_parser.ypp" +#line 1476 "glsl_parser.ypp" { (yyval.declaration) = (yyvsp[(1) - (1)].declaration); (yyvsp[(1) - (1)].declaration)->link.self_link(); ;} break; - case 230: + case 241: /* Line 1464 of yacc.c */ -#line 1377 "glsl_parser.ypp" +#line 1481 "glsl_parser.ypp" { (yyval.declaration) = (yyvsp[(1) - (3)].declaration); (yyval.declaration)->link.insert_before(& (yyvsp[(3) - (3)].declaration)->link); ;} break; - case 231: + case 242: /* Line 1464 of yacc.c */ -#line 1385 "glsl_parser.ypp" +#line 1489 "glsl_parser.ypp" { void *ctx = state; (yyval.declaration) = new(ctx) ast_declaration((yyvsp[(1) - (1)].identifier), false, NULL, NULL); (yyval.declaration)->set_location(yylloc); + state->symbols->add_variable(new(state) ir_variable(NULL, (yyvsp[(1) - (1)].identifier), ir_var_auto)); ;} break; - case 232: + case 243: /* Line 1464 of yacc.c */ -#line 1391 "glsl_parser.ypp" +#line 1496 "glsl_parser.ypp" { void *ctx = state; (yyval.declaration) = new(ctx) ast_declaration((yyvsp[(1) - (4)].identifier), true, (yyvsp[(3) - (4)].expression), NULL); @@ -4776,31 +4888,31 @@ yyreduce: ;} break; - case 235: + case 246: /* Line 1464 of yacc.c */ -#line 1409 "glsl_parser.ypp" +#line 1514 "glsl_parser.ypp" { (yyval.node) = (ast_node *) (yyvsp[(1) - (1)].compound_statement); ;} break; - case 240: + case 251: /* Line 1464 of yacc.c */ -#line 1417 "glsl_parser.ypp" +#line 1522 "glsl_parser.ypp" { (yyval.node) = NULL; ;} break; - case 241: + case 252: /* Line 1464 of yacc.c */ -#line 1418 "glsl_parser.ypp" +#line 1523 "glsl_parser.ypp" { (yyval.node) = NULL; ;} break; - case 244: + case 255: /* Line 1464 of yacc.c */ -#line 1425 "glsl_parser.ypp" +#line 1530 "glsl_parser.ypp" { void *ctx = state; (yyval.compound_statement) = new(ctx) ast_compound_statement(true, NULL); @@ -4808,28 +4920,38 @@ yyreduce: ;} break; - case 245: + case 256: + +/* Line 1464 of yacc.c */ +#line 1536 "glsl_parser.ypp" + { + state->symbols->push_scope(); + ;} + break; + + case 257: /* Line 1464 of yacc.c */ -#line 1431 "glsl_parser.ypp" +#line 1540 "glsl_parser.ypp" { void *ctx = state; - (yyval.compound_statement) = new(ctx) ast_compound_statement(true, (yyvsp[(2) - (3)].node)); + (yyval.compound_statement) = new(ctx) ast_compound_statement(true, (yyvsp[(3) - (4)].node)); (yyval.compound_statement)->set_location(yylloc); + state->symbols->pop_scope(); ;} break; - case 246: + case 258: /* Line 1464 of yacc.c */ -#line 1439 "glsl_parser.ypp" +#line 1549 "glsl_parser.ypp" { (yyval.node) = (ast_node *) (yyvsp[(1) - (1)].compound_statement); ;} break; - case 248: + case 260: /* Line 1464 of yacc.c */ -#line 1445 "glsl_parser.ypp" +#line 1555 "glsl_parser.ypp" { void *ctx = state; (yyval.compound_statement) = new(ctx) ast_compound_statement(false, NULL); @@ -4837,10 +4959,10 @@ yyreduce: ;} break; - case 249: + case 261: /* Line 1464 of yacc.c */ -#line 1451 "glsl_parser.ypp" +#line 1561 "glsl_parser.ypp" { void *ctx = state; (yyval.compound_statement) = new(ctx) ast_compound_statement(false, (yyvsp[(2) - (3)].node)); @@ -4848,10 +4970,10 @@ yyreduce: ;} break; - case 250: + case 262: /* Line 1464 of yacc.c */ -#line 1460 "glsl_parser.ypp" +#line 1570 "glsl_parser.ypp" { if ((yyvsp[(1) - (1)].node) == NULL) { _mesa_glsl_error(& (yylsp[(1) - (1)]), state, "<nil> statement\n"); @@ -4863,10 +4985,10 @@ yyreduce: ;} break; - case 251: + case 263: /* Line 1464 of yacc.c */ -#line 1470 "glsl_parser.ypp" +#line 1580 "glsl_parser.ypp" { if ((yyvsp[(2) - (2)].node) == NULL) { _mesa_glsl_error(& (yylsp[(2) - (2)]), state, "<nil> statement\n"); @@ -4877,10 +4999,10 @@ yyreduce: ;} break; - case 252: + case 264: /* Line 1464 of yacc.c */ -#line 1482 "glsl_parser.ypp" +#line 1592 "glsl_parser.ypp" { void *ctx = state; (yyval.node) = new(ctx) ast_expression_statement(NULL); @@ -4888,10 +5010,10 @@ yyreduce: ;} break; - case 253: + case 265: /* Line 1464 of yacc.c */ -#line 1488 "glsl_parser.ypp" +#line 1598 "glsl_parser.ypp" { void *ctx = state; (yyval.node) = new(ctx) ast_expression_statement((yyvsp[(1) - (2)].expression)); @@ -4899,10 +5021,10 @@ yyreduce: ;} break; - case 254: + case 266: /* Line 1464 of yacc.c */ -#line 1497 "glsl_parser.ypp" +#line 1607 "glsl_parser.ypp" { (yyval.node) = new(state) ast_selection_statement((yyvsp[(3) - (5)].expression), (yyvsp[(5) - (5)].selection_rest_statement).then_statement, (yyvsp[(5) - (5)].selection_rest_statement).else_statement); @@ -4910,39 +5032,39 @@ yyreduce: ;} break; - case 255: + case 267: /* Line 1464 of yacc.c */ -#line 1506 "glsl_parser.ypp" +#line 1616 "glsl_parser.ypp" { (yyval.selection_rest_statement).then_statement = (yyvsp[(1) - (3)].node); (yyval.selection_rest_statement).else_statement = (yyvsp[(3) - (3)].node); ;} break; - case 256: + case 268: /* Line 1464 of yacc.c */ -#line 1511 "glsl_parser.ypp" +#line 1621 "glsl_parser.ypp" { (yyval.selection_rest_statement).then_statement = (yyvsp[(1) - (1)].node); (yyval.selection_rest_statement).else_statement = NULL; ;} break; - case 257: + case 269: /* Line 1464 of yacc.c */ -#line 1519 "glsl_parser.ypp" +#line 1629 "glsl_parser.ypp" { (yyval.node) = (ast_node *) (yyvsp[(1) - (1)].expression); ;} break; - case 258: + case 270: /* Line 1464 of yacc.c */ -#line 1523 "glsl_parser.ypp" +#line 1633 "glsl_parser.ypp" { void *ctx = state; ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(2) - (4)].identifier), false, NULL, (yyvsp[(4) - (4)].expression)); @@ -4955,10 +5077,10 @@ yyreduce: ;} break; - case 262: + case 274: /* Line 1464 of yacc.c */ -#line 1546 "glsl_parser.ypp" +#line 1656 "glsl_parser.ypp" { void *ctx = state; (yyval.node) = new(ctx) ast_iteration_statement(ast_iteration_statement::ast_while, @@ -4967,10 +5089,10 @@ yyreduce: ;} break; - case 263: + case 275: /* Line 1464 of yacc.c */ -#line 1553 "glsl_parser.ypp" +#line 1663 "glsl_parser.ypp" { void *ctx = state; (yyval.node) = new(ctx) ast_iteration_statement(ast_iteration_statement::ast_do_while, @@ -4979,10 +5101,10 @@ yyreduce: ;} break; - case 264: + case 276: /* Line 1464 of yacc.c */ -#line 1560 "glsl_parser.ypp" +#line 1670 "glsl_parser.ypp" { void *ctx = state; (yyval.node) = new(ctx) ast_iteration_statement(ast_iteration_statement::ast_for, @@ -4991,39 +5113,39 @@ yyreduce: ;} break; - case 268: + case 280: /* Line 1464 of yacc.c */ -#line 1576 "glsl_parser.ypp" +#line 1686 "glsl_parser.ypp" { (yyval.node) = NULL; ;} break; - case 269: + case 281: /* Line 1464 of yacc.c */ -#line 1583 "glsl_parser.ypp" +#line 1693 "glsl_parser.ypp" { (yyval.for_rest_statement).cond = (yyvsp[(1) - (2)].node); (yyval.for_rest_statement).rest = NULL; ;} break; - case 270: + case 282: /* Line 1464 of yacc.c */ -#line 1588 "glsl_parser.ypp" +#line 1698 "glsl_parser.ypp" { (yyval.for_rest_statement).cond = (yyvsp[(1) - (3)].node); (yyval.for_rest_statement).rest = (yyvsp[(3) - (3)].expression); ;} break; - case 271: + case 283: /* Line 1464 of yacc.c */ -#line 1597 "glsl_parser.ypp" +#line 1707 "glsl_parser.ypp" { void *ctx = state; (yyval.node) = new(ctx) ast_jump_statement(ast_jump_statement::ast_continue, NULL); @@ -5031,10 +5153,10 @@ yyreduce: ;} break; - case 272: + case 284: /* Line 1464 of yacc.c */ -#line 1603 "glsl_parser.ypp" +#line 1713 "glsl_parser.ypp" { void *ctx = state; (yyval.node) = new(ctx) ast_jump_statement(ast_jump_statement::ast_break, NULL); @@ -5042,10 +5164,10 @@ yyreduce: ;} break; - case 273: + case 285: /* Line 1464 of yacc.c */ -#line 1609 "glsl_parser.ypp" +#line 1719 "glsl_parser.ypp" { void *ctx = state; (yyval.node) = new(ctx) ast_jump_statement(ast_jump_statement::ast_return, NULL); @@ -5053,10 +5175,10 @@ yyreduce: ;} break; - case 274: + case 286: /* Line 1464 of yacc.c */ -#line 1615 "glsl_parser.ypp" +#line 1725 "glsl_parser.ypp" { void *ctx = state; (yyval.node) = new(ctx) ast_jump_statement(ast_jump_statement::ast_return, (yyvsp[(2) - (3)].expression)); @@ -5064,10 +5186,10 @@ yyreduce: ;} break; - case 275: + case 287: /* Line 1464 of yacc.c */ -#line 1621 "glsl_parser.ypp" +#line 1731 "glsl_parser.ypp" { void *ctx = state; (yyval.node) = new(ctx) ast_jump_statement(ast_jump_statement::ast_discard, NULL); @@ -5075,44 +5197,46 @@ yyreduce: ;} break; - case 276: + case 288: /* Line 1464 of yacc.c */ -#line 1629 "glsl_parser.ypp" +#line 1739 "glsl_parser.ypp" { (yyval.node) = (yyvsp[(1) - (1)].function_definition); ;} break; - case 277: + case 289: /* Line 1464 of yacc.c */ -#line 1630 "glsl_parser.ypp" +#line 1740 "glsl_parser.ypp" { (yyval.node) = (yyvsp[(1) - (1)].node); ;} break; - case 278: + case 290: /* Line 1464 of yacc.c */ -#line 1631 "glsl_parser.ypp" +#line 1741 "glsl_parser.ypp" { (yyval.node) = NULL; ;} break; - case 279: + case 291: /* Line 1464 of yacc.c */ -#line 1636 "glsl_parser.ypp" +#line 1746 "glsl_parser.ypp" { void *ctx = state; (yyval.function_definition) = new(ctx) ast_function_definition(); (yyval.function_definition)->set_location(yylloc); (yyval.function_definition)->prototype = (yyvsp[(1) - (2)].function); (yyval.function_definition)->body = (yyvsp[(2) - (2)].compound_statement); + + state->symbols->pop_scope(); ;} break; /* Line 1464 of yacc.c */ -#line 5116 "glsl_parser.cpp" +#line 5240 "glsl_parser.cpp" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); diff --git a/src/glsl/glsl_parser.h b/src/glsl/glsl_parser.h index 1bf3b3538c7..7f36492f7a1 100644 --- a/src/glsl/glsl_parser.h +++ b/src/glsl/glsl_parser.h @@ -112,123 +112,125 @@ VOID_TOK = 329, WHILE = 330, IDENTIFIER = 331, - FLOATCONSTANT = 332, - INTCONSTANT = 333, - UINTCONSTANT = 334, - BOOLCONSTANT = 335, - FIELD_SELECTION = 336, - LEFT_OP = 337, - RIGHT_OP = 338, - INC_OP = 339, - DEC_OP = 340, - LE_OP = 341, - GE_OP = 342, - EQ_OP = 343, - NE_OP = 344, - AND_OP = 345, - OR_OP = 346, - XOR_OP = 347, - MUL_ASSIGN = 348, - DIV_ASSIGN = 349, - ADD_ASSIGN = 350, - MOD_ASSIGN = 351, - LEFT_ASSIGN = 352, - RIGHT_ASSIGN = 353, - AND_ASSIGN = 354, - XOR_ASSIGN = 355, - OR_ASSIGN = 356, - SUB_ASSIGN = 357, - INVARIANT = 358, - LOWP = 359, - MEDIUMP = 360, - HIGHP = 361, - SUPERP = 362, - PRECISION = 363, - VERSION = 364, - EXTENSION = 365, - LINE = 366, - COLON = 367, - EOL = 368, - INTERFACE = 369, - OUTPUT = 370, - PRAGMA_DEBUG_ON = 371, - PRAGMA_DEBUG_OFF = 372, - PRAGMA_OPTIMIZE_ON = 373, - PRAGMA_OPTIMIZE_OFF = 374, - PRAGMA_INVARIANT_ALL = 375, - LAYOUT_TOK = 376, - ASM = 377, - CLASS = 378, - UNION = 379, - ENUM = 380, - TYPEDEF = 381, - TEMPLATE = 382, - THIS = 383, - PACKED_TOK = 384, - GOTO = 385, - INLINE_TOK = 386, - NOINLINE = 387, - VOLATILE = 388, - PUBLIC_TOK = 389, - STATIC = 390, - EXTERN = 391, - EXTERNAL = 392, - LONG_TOK = 393, - SHORT_TOK = 394, - DOUBLE_TOK = 395, - HALF = 396, - FIXED_TOK = 397, - UNSIGNED = 398, - INPUT_TOK = 399, - OUPTUT = 400, - HVEC2 = 401, - HVEC3 = 402, - HVEC4 = 403, - DVEC2 = 404, - DVEC3 = 405, - DVEC4 = 406, - FVEC2 = 407, - FVEC3 = 408, - FVEC4 = 409, - SAMPLER2DRECT = 410, - SAMPLER3DRECT = 411, - SAMPLER2DRECTSHADOW = 412, - SIZEOF = 413, - CAST = 414, - NAMESPACE = 415, - USING = 416, - ERROR_TOK = 417, - COMMON = 418, - PARTITION = 419, - ACTIVE = 420, - SAMPLERBUFFER = 421, - FILTER = 422, - IMAGE1D = 423, - IMAGE2D = 424, - IMAGE3D = 425, - IMAGECUBE = 426, - IMAGE1DARRAY = 427, - IMAGE2DARRAY = 428, - IIMAGE1D = 429, - IIMAGE2D = 430, - IIMAGE3D = 431, - IIMAGECUBE = 432, - IIMAGE1DARRAY = 433, - IIMAGE2DARRAY = 434, - UIMAGE1D = 435, - UIMAGE2D = 436, - UIMAGE3D = 437, - UIMAGECUBE = 438, - UIMAGE1DARRAY = 439, - UIMAGE2DARRAY = 440, - IMAGE1DSHADOW = 441, - IMAGE2DSHADOW = 442, - IMAGEBUFFER = 443, - IIMAGEBUFFER = 444, - UIMAGEBUFFER = 445, - IMAGE1DARRAYSHADOW = 446, - IMAGE2DARRAYSHADOW = 447, - ROW_MAJOR = 448 + TYPE_IDENTIFIER = 332, + NEW_IDENTIFIER = 333, + FLOATCONSTANT = 334, + INTCONSTANT = 335, + UINTCONSTANT = 336, + BOOLCONSTANT = 337, + FIELD_SELECTION = 338, + LEFT_OP = 339, + RIGHT_OP = 340, + INC_OP = 341, + DEC_OP = 342, + LE_OP = 343, + GE_OP = 344, + EQ_OP = 345, + NE_OP = 346, + AND_OP = 347, + OR_OP = 348, + XOR_OP = 349, + MUL_ASSIGN = 350, + DIV_ASSIGN = 351, + ADD_ASSIGN = 352, + MOD_ASSIGN = 353, + LEFT_ASSIGN = 354, + RIGHT_ASSIGN = 355, + AND_ASSIGN = 356, + XOR_ASSIGN = 357, + OR_ASSIGN = 358, + SUB_ASSIGN = 359, + INVARIANT = 360, + LOWP = 361, + MEDIUMP = 362, + HIGHP = 363, + SUPERP = 364, + PRECISION = 365, + VERSION = 366, + EXTENSION = 367, + LINE = 368, + COLON = 369, + EOL = 370, + INTERFACE = 371, + OUTPUT = 372, + PRAGMA_DEBUG_ON = 373, + PRAGMA_DEBUG_OFF = 374, + PRAGMA_OPTIMIZE_ON = 375, + PRAGMA_OPTIMIZE_OFF = 376, + PRAGMA_INVARIANT_ALL = 377, + LAYOUT_TOK = 378, + ASM = 379, + CLASS = 380, + UNION = 381, + ENUM = 382, + TYPEDEF = 383, + TEMPLATE = 384, + THIS = 385, + PACKED_TOK = 386, + GOTO = 387, + INLINE_TOK = 388, + NOINLINE = 389, + VOLATILE = 390, + PUBLIC_TOK = 391, + STATIC = 392, + EXTERN = 393, + EXTERNAL = 394, + LONG_TOK = 395, + SHORT_TOK = 396, + DOUBLE_TOK = 397, + HALF = 398, + FIXED_TOK = 399, + UNSIGNED = 400, + INPUT_TOK = 401, + OUPTUT = 402, + HVEC2 = 403, + HVEC3 = 404, + HVEC4 = 405, + DVEC2 = 406, + DVEC3 = 407, + DVEC4 = 408, + FVEC2 = 409, + FVEC3 = 410, + FVEC4 = 411, + SAMPLER2DRECT = 412, + SAMPLER3DRECT = 413, + SAMPLER2DRECTSHADOW = 414, + SIZEOF = 415, + CAST = 416, + NAMESPACE = 417, + USING = 418, + ERROR_TOK = 419, + COMMON = 420, + PARTITION = 421, + ACTIVE = 422, + SAMPLERBUFFER = 423, + FILTER = 424, + IMAGE1D = 425, + IMAGE2D = 426, + IMAGE3D = 427, + IMAGECUBE = 428, + IMAGE1DARRAY = 429, + IMAGE2DARRAY = 430, + IIMAGE1D = 431, + IIMAGE2D = 432, + IIMAGE3D = 433, + IIMAGECUBE = 434, + IIMAGE1DARRAY = 435, + IIMAGE2DARRAY = 436, + UIMAGE1D = 437, + UIMAGE2D = 438, + UIMAGE3D = 439, + UIMAGECUBE = 440, + UIMAGE1DARRAY = 441, + UIMAGE2DARRAY = 442, + IMAGE1DSHADOW = 443, + IMAGE2DSHADOW = 444, + IMAGEBUFFER = 445, + IIMAGEBUFFER = 446, + UIMAGEBUFFER = 447, + IMAGE1DARRAYSHADOW = 448, + IMAGE2DARRAYSHADOW = 449, + ROW_MAJOR = 450 }; #endif @@ -272,7 +274,7 @@ typedef union YYSTYPE /* Line 1685 of yacc.c */ -#line 276 "glsl_parser.h" +#line 278 "glsl_parser.h" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ diff --git a/src/glsl/glsl_parser.ypp b/src/glsl/glsl_parser.ypp index 3982167c482..2c0498ece7a 100644 --- a/src/glsl/glsl_parser.ypp +++ b/src/glsl/glsl_parser.ypp @@ -93,7 +93,8 @@ %token ISAMPLER1DARRAY ISAMPLER2DARRAY USAMPLER1D USAMPLER2D USAMPLER3D %token USAMPLERCUBE USAMPLER1DARRAY USAMPLER2DARRAY %token STRUCT VOID_TOK WHILE -%token <identifier> IDENTIFIER +%token <identifier> IDENTIFIER TYPE_IDENTIFIER NEW_IDENTIFIER +%type <identifier> any_identifier %token <real> FLOATCONSTANT %token <n> INTCONSTANT UINTCONSTANT BOOLCONSTANT %token <identifier> FIELD_SELECTION @@ -184,6 +185,10 @@ %type <expression> function_call_generic %type <expression> function_call_or_method %type <expression> function_call +%type <expression> method_call_generic +%type <expression> method_call_header_with_parameters +%type <expression> method_call_header_no_parameters +%type <expression> method_call_header %type <n> assignment_operator %type <n> unary_operator %type <expression> function_identifier @@ -214,31 +219,51 @@ translation_unit: _mesa_glsl_initialize_types(state); } external_declaration_list + { + delete state->symbols; + state->symbols = new(ralloc_parent(state)) glsl_symbol_table; + _mesa_glsl_initialize_types(state); + } ; version_statement: /* blank - no #version specified: defaults are already set */ | VERSION INTCONSTANT EOL { + bool supported = false; + switch ($2) { case 100: state->es_shader = true; + supported = state->Const.GLSL_100ES; + break; case 110: + supported = state->Const.GLSL_110; + break; case 120: + supported = state->Const.GLSL_120; + break; case 130: - /* FINISHME: Check against implementation support versions. */ - state->language_version = $2; - state->version_string = - talloc_asprintf(state, "GLSL%s %d.%02d", - state->es_shader ? " ES" : "", - state->language_version / 100, - state->language_version % 100); + supported = state->Const.GLSL_130; break; default: - _mesa_glsl_error(& @2, state, "Shading language version" - "%u is not supported\n", $2); + supported = false; break; } + + state->language_version = $2; + state->version_string = + ralloc_asprintf(state, "GLSL%s %d.%02d", + state->es_shader ? " ES" : "", + state->language_version / 100, + state->language_version % 100); + + if (!supported) { + _mesa_glsl_error(& @2, state, "%s is not supported. " + "Supported versions are: %s\n", + state->version_string, + state->supported_version_string); + } } ; @@ -264,8 +289,14 @@ extension_statement_list: | extension_statement_list extension_statement ; +any_identifier: + IDENTIFIER + | TYPE_IDENTIFIER + | NEW_IDENTIFIER + ; + extension_statement: - EXTENSION IDENTIFIER COLON IDENTIFIER EOL + EXTENSION any_identifier COLON any_identifier EOL { if (!_mesa_glsl_process_extension($2, & @2, $4, & @4, state)) { YYERROR; @@ -294,6 +325,7 @@ external_declaration_list: variable_identifier: IDENTIFIER + | NEW_IDENTIFIER ; primary_expression: @@ -350,7 +382,7 @@ postfix_expression: { $$ = $1; } - | postfix_expression '.' IDENTIFIER + | postfix_expression '.' any_identifier { void *ctx = state; $$ = new(ctx) ast_expression(ast_field_selection, $1, NULL, NULL); @@ -381,7 +413,7 @@ function_call: function_call_or_method: function_call_generic - | postfix_expression '.' function_call_generic + | postfix_expression '.' method_call_generic { void *ctx = state; $$ = new(ctx) ast_expression(ast_field_selection, $1, $3, NULL); @@ -428,7 +460,7 @@ function_identifier: $$ = new(ctx) ast_function_expression($1); $$->set_location(yylloc); } - | IDENTIFIER + | variable_identifier { void *ctx = state; ast_expression *callee = new(ctx) ast_expression($1); @@ -444,6 +476,44 @@ function_identifier: } ; +method_call_generic: + method_call_header_with_parameters ')' + | method_call_header_no_parameters ')' + ; + +method_call_header_no_parameters: + method_call_header VOID_TOK + | method_call_header + ; + +method_call_header_with_parameters: + method_call_header assignment_expression + { + $$ = $1; + $$->set_location(yylloc); + $$->expressions.push_tail(& $2->link); + } + | method_call_header_with_parameters ',' assignment_expression + { + $$ = $1; + $$->set_location(yylloc); + $$->expressions.push_tail(& $3->link); + } + ; + + // Grammar Note: Constructors look like methods, but lexical + // analysis recognized most of them as keywords. They are now + // recognized through "type_specifier". +method_call_header: + variable_identifier '(' + { + void *ctx = state; + ast_expression *callee = new(ctx) ast_expression($1); + $$ = new(ctx) ast_function_expression(callee); + $$->set_location(yylloc); + } + ; + // Grammar Note: No traditional style type casts. unary_expression: postfix_expression @@ -694,6 +764,7 @@ constant_expression: declaration: function_prototype ';' { + state->symbols->pop_scope(); $$ = $1; } | init_declarator_list ';' @@ -731,18 +802,21 @@ function_header_with_parameters: ; function_header: - fully_specified_type IDENTIFIER '(' + fully_specified_type variable_identifier '(' { void *ctx = state; $$ = new(ctx) ast_function(); $$->set_location(yylloc); $$->return_type = $1; $$->identifier = $2; + + state->symbols->add_function(new(state) ir_function($2)); + state->symbols->push_scope(); } ; parameter_declarator: - type_specifier IDENTIFIER + type_specifier any_identifier { void *ctx = state; $$ = new(ctx) ast_parameter_declarator(); @@ -752,7 +826,7 @@ parameter_declarator: $$->type->specifier = $1; $$->identifier = $2; } - | type_specifier IDENTIFIER '[' constant_expression ']' + | type_specifier any_identifier '[' constant_expression ']' { void *ctx = state; $$ = new(ctx) ast_parameter_declarator(); @@ -830,7 +904,7 @@ parameter_type_specifier: init_declarator_list: single_declaration - | init_declarator_list ',' IDENTIFIER + | init_declarator_list ',' any_identifier { void *ctx = state; ast_declaration *decl = new(ctx) ast_declaration($3, false, NULL, NULL); @@ -838,8 +912,9 @@ init_declarator_list: $$ = $1; $$->declarations.push_tail(&decl->link); + state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto)); } - | init_declarator_list ',' IDENTIFIER '[' ']' + | init_declarator_list ',' any_identifier '[' ']' { void *ctx = state; ast_declaration *decl = new(ctx) ast_declaration($3, true, NULL, NULL); @@ -847,8 +922,9 @@ init_declarator_list: $$ = $1; $$->declarations.push_tail(&decl->link); + state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto)); } - | init_declarator_list ',' IDENTIFIER '[' constant_expression ']' + | init_declarator_list ',' any_identifier '[' constant_expression ']' { void *ctx = state; ast_declaration *decl = new(ctx) ast_declaration($3, true, $5, NULL); @@ -856,8 +932,9 @@ init_declarator_list: $$ = $1; $$->declarations.push_tail(&decl->link); + state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto)); } - | init_declarator_list ',' IDENTIFIER '[' ']' '=' initializer + | init_declarator_list ',' any_identifier '[' ']' '=' initializer { void *ctx = state; ast_declaration *decl = new(ctx) ast_declaration($3, true, NULL, $7); @@ -865,8 +942,9 @@ init_declarator_list: $$ = $1; $$->declarations.push_tail(&decl->link); + state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto)); } - | init_declarator_list ',' IDENTIFIER '[' constant_expression ']' '=' initializer + | init_declarator_list ',' any_identifier '[' constant_expression ']' '=' initializer { void *ctx = state; ast_declaration *decl = new(ctx) ast_declaration($3, true, $5, $8); @@ -874,8 +952,9 @@ init_declarator_list: $$ = $1; $$->declarations.push_tail(&decl->link); + state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto)); } - | init_declarator_list ',' IDENTIFIER '=' initializer + | init_declarator_list ',' any_identifier '=' initializer { void *ctx = state; ast_declaration *decl = new(ctx) ast_declaration($3, false, NULL, $5); @@ -883,6 +962,7 @@ init_declarator_list: $$ = $1; $$->declarations.push_tail(&decl->link); + state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto)); } ; @@ -899,7 +979,7 @@ single_declaration: $$->set_location(yylloc); } } - | fully_specified_type IDENTIFIER + | fully_specified_type any_identifier { void *ctx = state; ast_declaration *decl = new(ctx) ast_declaration($2, false, NULL, NULL); @@ -908,7 +988,7 @@ single_declaration: $$->set_location(yylloc); $$->declarations.push_tail(&decl->link); } - | fully_specified_type IDENTIFIER '[' ']' + | fully_specified_type any_identifier '[' ']' { void *ctx = state; ast_declaration *decl = new(ctx) ast_declaration($2, true, NULL, NULL); @@ -917,7 +997,7 @@ single_declaration: $$->set_location(yylloc); $$->declarations.push_tail(&decl->link); } - | fully_specified_type IDENTIFIER '[' constant_expression ']' + | fully_specified_type any_identifier '[' constant_expression ']' { void *ctx = state; ast_declaration *decl = new(ctx) ast_declaration($2, true, $4, NULL); @@ -926,7 +1006,7 @@ single_declaration: $$->set_location(yylloc); $$->declarations.push_tail(&decl->link); } - | fully_specified_type IDENTIFIER '[' ']' '=' initializer + | fully_specified_type any_identifier '[' ']' '=' initializer { void *ctx = state; ast_declaration *decl = new(ctx) ast_declaration($2, true, NULL, $6); @@ -935,7 +1015,7 @@ single_declaration: $$->set_location(yylloc); $$->declarations.push_tail(&decl->link); } - | fully_specified_type IDENTIFIER '[' constant_expression ']' '=' initializer + | fully_specified_type any_identifier '[' constant_expression ']' '=' initializer { void *ctx = state; ast_declaration *decl = new(ctx) ast_declaration($2, true, $4, $7); @@ -944,7 +1024,7 @@ single_declaration: $$->set_location(yylloc); $$->declarations.push_tail(&decl->link); } - | fully_specified_type IDENTIFIER '=' initializer + | fully_specified_type any_identifier '=' initializer { void *ctx = state; ast_declaration *decl = new(ctx) ast_declaration($2, false, NULL, $4); @@ -953,7 +1033,7 @@ single_declaration: $$->set_location(yylloc); $$->declarations.push_tail(&decl->link); } - | INVARIANT IDENTIFIER // Vertex only. + | INVARIANT variable_identifier // Vertex only. { void *ctx = state; ast_declaration *decl = new(ctx) ast_declaration($2, false, NULL, NULL); @@ -1012,13 +1092,14 @@ layout_qualifier_id_list: ; layout_qualifier_id: - IDENTIFIER + any_identifier { bool got_one = false; memset(& $$, 0, sizeof($$)); - if (state->ARB_fragment_coord_conventions_enable) { + /* Layout qualifiers for ARB_fragment_coord_conventions. */ + if (!got_one && state->ARB_fragment_coord_conventions_enable) { if (strcmp($1, "origin_upper_left") == 0) { got_one = true; $$.flags.q.origin_upper_left = 1; @@ -1026,22 +1107,44 @@ layout_qualifier_id: got_one = true; $$.flags.q.pixel_center_integer = 1; } + + if (got_one && state->ARB_fragment_coord_conventions_warn) { + _mesa_glsl_warning(& @1, state, + "GL_ARB_fragment_coord_conventions layout " + "identifier `%s' used\n", $1); + } + } + + /* Layout qualifiers for AMD_conservative_depth. */ + if (!got_one && state->AMD_conservative_depth_enable) { + if (strcmp($1, "depth_any") == 0) { + got_one = true; + $$.flags.q.depth_any = 1; + } else if (strcmp($1, "depth_greater") == 0) { + got_one = true; + $$.flags.q.depth_greater = 1; + } else if (strcmp($1, "depth_less") == 0) { + got_one = true; + $$.flags.q.depth_less = 1; + } else if (strcmp($1, "depth_unchanged") == 0) { + got_one = true; + $$.flags.q.depth_unchanged = 1; + } + + if (got_one && state->AMD_conservative_depth_warn) { + _mesa_glsl_warning(& @1, state, + "GL_AMD_conservative_depth " + "layout qualifier `%s' is used\n", $1); + } } - /* If the identifier didn't match any known layout identifiers, - * emit an error. - */ if (!got_one) { _mesa_glsl_error(& @1, state, "unrecognized layout identifier " "`%s'\n", $1); YYERROR; - } else if (state->ARB_fragment_coord_conventions_warn) { - _mesa_glsl_warning(& @1, state, - "GL_ARB_fragment_coord_conventions layout " - "identifier `%s' used\n", $1); } } - | IDENTIFIER '=' INTCONSTANT + | any_identifier '=' INTCONSTANT { bool got_one = false; @@ -1229,7 +1332,7 @@ type_specifier_nonarray: $$ = new(ctx) ast_type_specifier($1); $$->set_location(yylloc); } - | IDENTIFIER + | TYPE_IDENTIFIER { void *ctx = state; $$ = new(ctx) ast_type_specifier($1); @@ -1325,11 +1428,12 @@ precision_qualifier: ; struct_specifier: - STRUCT IDENTIFIER '{' struct_declaration_list '}' + STRUCT any_identifier '{' struct_declaration_list '}' { void *ctx = state; $$ = new(ctx) ast_struct_specifier($2, $4); $$->set_location(yylloc); + state->symbols->add_type($2, glsl_type::void_type); } | STRUCT '{' struct_declaration_list '}' { @@ -1381,13 +1485,14 @@ struct_declarator_list: ; struct_declarator: - IDENTIFIER + any_identifier { void *ctx = state; $$ = new(ctx) ast_declaration($1, false, NULL, NULL); $$->set_location(yylloc); + state->symbols->add_variable(new(state) ir_variable(NULL, $1, ir_var_auto)); } - | IDENTIFIER '[' constant_expression ']' + | any_identifier '[' constant_expression ']' { void *ctx = state; $$ = new(ctx) ast_declaration($1, true, $3, NULL); @@ -1427,11 +1532,16 @@ compound_statement: $$ = new(ctx) ast_compound_statement(true, NULL); $$->set_location(yylloc); } - | '{' statement_list '}' + | '{' + { + state->symbols->push_scope(); + } + statement_list '}' { void *ctx = state; - $$ = new(ctx) ast_compound_statement(true, $2); + $$ = new(ctx) ast_compound_statement(true, $3); $$->set_location(yylloc); + state->symbols->pop_scope(); } ; @@ -1519,7 +1629,7 @@ condition: { $$ = (ast_node *) $1; } - | fully_specified_type IDENTIFIER '=' initializer + | fully_specified_type any_identifier '=' initializer { void *ctx = state; ast_declaration *decl = new(ctx) ast_declaration($2, false, NULL, $4); @@ -1639,5 +1749,7 @@ function_definition: $$->set_location(yylloc); $$->prototype = $1; $$->body = $2; + + state->symbols->pop_scope(); } ; diff --git a/src/glsl/glsl_parser_extras.cpp b/src/glsl/glsl_parser_extras.cpp index 77885d4e1e3..d7a37aef46d 100644 --- a/src/glsl/glsl_parser_extras.cpp +++ b/src/glsl/glsl_parser_extras.cpp @@ -26,10 +26,10 @@ #include <assert.h> extern "C" { -#include <talloc.h> #include "main/core.h" /* for struct gl_context */ } +#include "ralloc.h" #include "ast.h" #include "glsl_parser_extras.h" #include "glsl_parser.h" @@ -48,7 +48,7 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *ctx, this->scanner = NULL; this->translation_unit.make_empty(); this->symbols = new(mem_ctx) glsl_symbol_table; - this->info_log = talloc_strdup(mem_ctx, ""); + this->info_log = ralloc_strdup(mem_ctx, ""); this->error = false; this->loop_or_switch_nesting = NULL; @@ -79,6 +79,38 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *ctx, this->Const.MaxFragmentUniformComponents = ctx->Const.FragmentProgram.MaxUniformComponents; this->Const.MaxDrawBuffers = ctx->Const.MaxDrawBuffers; + + /* Note: Once the OpenGL 3.0 'forward compatible' context or the OpenGL 3.2 + * Core context is supported, this logic will need change. Older versions of + * GLSL are no longer supported outside the compatibility contexts of 3.x. + */ + this->Const.GLSL_100ES = (ctx->API == API_OPENGLES2) + || ctx->Extensions.ARB_ES2_compatibility; + this->Const.GLSL_110 = (ctx->API == API_OPENGL); + this->Const.GLSL_120 = (ctx->API == API_OPENGL) + && (ctx->Const.GLSLVersion >= 120); + this->Const.GLSL_130 = (ctx->API == API_OPENGL) + && (ctx->Const.GLSLVersion >= 130); + + const unsigned lowest_version = + (ctx->API == API_OPENGLES2) || ctx->Extensions.ARB_ES2_compatibility + ? 100 : 110; + const unsigned highest_version = + (ctx->API == API_OPENGL) ? ctx->Const.GLSLVersion : 100; + char *supported = ralloc_strdup(this, ""); + + for (unsigned ver = lowest_version; ver <= highest_version; ver += 10) { + const char *const prefix = (ver == lowest_version) + ? "" + : ((ver == highest_version) ? ", and " : ", "); + + ralloc_asprintf_append(& supported, "%s%d.%02d%s", + prefix, + ver / 100, ver % 100, + (ver == 100) ? " ES" : ""); + } + + this->supported_version_string = supported; } const char * @@ -104,15 +136,14 @@ _mesa_glsl_error(YYLTYPE *locp, _mesa_glsl_parse_state *state, state->error = true; assert(state->info_log != NULL); - state->info_log = talloc_asprintf_append(state->info_log, - "%u:%u(%u): error: ", + ralloc_asprintf_append(&state->info_log, "%u:%u(%u): error: ", locp->source, locp->first_line, locp->first_column); va_start(ap, fmt); - state->info_log = talloc_vasprintf_append(state->info_log, fmt, ap); + ralloc_vasprintf_append(&state->info_log, fmt, ap); va_end(ap); - state->info_log = talloc_strdup_append(state->info_log, "\n"); + ralloc_strcat(&state->info_log, "\n"); } @@ -123,15 +154,14 @@ _mesa_glsl_warning(const YYLTYPE *locp, _mesa_glsl_parse_state *state, va_list ap; assert(state->info_log != NULL); - state->info_log = talloc_asprintf_append(state->info_log, - "%u:%u(%u): warning: ", + ralloc_asprintf_append(&state->info_log, "%u:%u(%u): warning: ", locp->source, locp->first_line, locp->first_column); va_start(ap, fmt); - state->info_log = talloc_vasprintf_append(state->info_log, fmt, ap); + ralloc_vasprintf_append(&state->info_log, fmt, ap); va_end(ap); - state->info_log = talloc_strdup_append(state->info_log, "\n"); + ralloc_strcat(&state->info_log, "\n"); } @@ -219,6 +249,13 @@ _mesa_glsl_process_extension(const char *name, YYLTYPE *name_locp, state->ARB_shader_stencil_export_warn = (ext_mode == extension_warn); unsupported = !state->extensions->ARB_shader_stencil_export; } + } else if (strcmp(name, "GL_AMD_conservative_depth") == 0) { + /* The AMD_conservative spec does not forbid requiring the extension in + * the vertex shader. + */ + state->AMD_conservative_depth_enable = (ext_mode != extension_disable); + state->AMD_conservative_depth_warn = (ext_mode == extension_warn); + unsupported = !state->extensions->AMD_conservative_depth; } else { unsupported = true; } @@ -705,7 +742,7 @@ ast_struct_specifier::ast_struct_specifier(char *identifier, { if (identifier == NULL) { static unsigned anon_count = 1; - identifier = talloc_asprintf(this, "#anon_struct_%04x", anon_count); + identifier = ralloc_asprintf(this, "#anon_struct_%04x", anon_count); anon_count++; } name = identifier; @@ -727,6 +764,7 @@ do_common_optimization(exec_list *ir, bool linked, unsigned max_unroll_iteration progress = do_if_simplification(ir) || progress; progress = do_discard_simplification(ir) || progress; progress = do_copy_propagation(ir) || progress; + /*progress = do_copy_propagation_elements(ir) || progress;*/ if (linked) progress = do_dead_code(ir) || progress; else diff --git a/src/glsl/glsl_parser_extras.h b/src/glsl/glsl_parser_extras.h index 030d27a2627..10cb673c694 100644 --- a/src/glsl/glsl_parser_extras.h +++ b/src/glsl/glsl_parser_extras.h @@ -31,7 +31,7 @@ #ifdef __cplusplus -#include <cstdlib> +#include <stdlib.h> #include "glsl_symbol_table.h" enum _mesa_glsl_parser_targets { @@ -46,21 +46,21 @@ struct _mesa_glsl_parse_state { _mesa_glsl_parse_state(struct gl_context *ctx, GLenum target, void *mem_ctx); - /* Callers of this talloc-based new need not call delete. It's - * easier to just talloc_free 'ctx' (or any of its ancestors). */ + /* Callers of this ralloc-based new need not call delete. It's + * easier to just ralloc_free 'ctx' (or any of its ancestors). */ static void* operator new(size_t size, void *ctx) { - void *mem = talloc_zero_size(ctx, size); + void *mem = rzalloc_size(ctx, size); assert(mem != NULL); return mem; } /* If the user *does* call delete, that's OK, we will just - * talloc_free in that case. */ + * ralloc_free in that case. */ static void operator delete(void *mem) { - talloc_free(mem); + ralloc_free(mem); } void *scanner; @@ -73,6 +73,16 @@ struct _mesa_glsl_parse_state { enum _mesa_glsl_parser_targets target; /** + * Printable list of GLSL versions supported by the current context + * + * \note + * This string should probably be generated per-context instead of per + * invokation of the compiler. This should be changed when the method of + * tracking supported GLSL versions changes. + */ + const char *supported_version_string; + + /** * Implementation defined limits that affect built-in variables, etc. * * \sa struct gl_constants (in mtypes.h) @@ -93,6 +103,22 @@ struct _mesa_glsl_parse_state { /* ARB_draw_buffers */ unsigned MaxDrawBuffers; + + /** + * Set of GLSL versions supported by the current context + * + * Knowing that version X is supported doesn't mean that versions before + * X are also supported. Version 1.00 is only supported in an ES2 + * context or when GL_ARB_ES2_compatibility is supported. In an OpenGL + * 3.0 "forward compatible" context, GLSL 1.10 and 1.20 are \b not + * supported. + */ + /*@{*/ + unsigned GLSL_100ES:1; + unsigned GLSL_110:1; + unsigned GLSL_120:1; + unsigned GLSL_130:1; + /*@}*/ } Const; /** @@ -144,6 +170,8 @@ struct _mesa_glsl_parse_state { unsigned EXT_texture_array_warn:1; unsigned ARB_shader_stencil_export_enable:1; unsigned ARB_shader_stencil_export_warn:1; + unsigned AMD_conservative_depth_enable:1; + unsigned AMD_conservative_depth_warn:1; /*@}*/ /** Extensions supported by the OpenGL implementation. */ diff --git a/src/glsl/glsl_symbol_table.cpp b/src/glsl/glsl_symbol_table.cpp index 6fcfe07b9c2..2f291d4f97f 100644 --- a/src/glsl/glsl_symbol_table.cpp +++ b/src/glsl/glsl_symbol_table.cpp @@ -26,19 +26,19 @@ class symbol_table_entry { public: - /* Callers of this talloc-based new need not call delete. It's - * easier to just talloc_free 'ctx' (or any of its ancestors). */ + /* Callers of this ralloc-based new need not call delete. It's + * easier to just ralloc_free 'ctx' (or any of its ancestors). */ static void* operator new(size_t size, void *ctx) { - void *entry = talloc_size(ctx, size); + void *entry = ralloc_size(ctx, size); assert(entry != NULL); return entry; } - /* If the user *does* call delete, that's OK, we will just talloc_free. */ + /* If the user *does* call delete, that's OK, we will just ralloc_free. */ static void operator delete(void *entry) { - talloc_free(entry); + ralloc_free(entry); } symbol_table_entry(ir_variable *v) : v(v), f(0), t(0) {} @@ -54,13 +54,13 @@ glsl_symbol_table::glsl_symbol_table() { this->language_version = 120; this->table = _mesa_symbol_table_ctor(); - this->mem_ctx = talloc_init("symbol table entries"); + this->mem_ctx = ralloc_context(NULL); } glsl_symbol_table::~glsl_symbol_table() { _mesa_symbol_table_dtor(table); - talloc_free(mem_ctx); + ralloc_free(mem_ctx); } void glsl_symbol_table::push_scope() diff --git a/src/glsl/glsl_symbol_table.h b/src/glsl/glsl_symbol_table.h index 28a44ebe91c..637bc033b93 100644 --- a/src/glsl/glsl_symbol_table.h +++ b/src/glsl/glsl_symbol_table.h @@ -44,36 +44,34 @@ class symbol_table_entry; */ struct glsl_symbol_table { private: - static int + static void _glsl_symbol_table_destructor (glsl_symbol_table *table) { table->~glsl_symbol_table(); - - return 0; } public: - /* Callers of this talloc-based new need not call delete. It's - * easier to just talloc_free 'ctx' (or any of its ancestors). */ + /* Callers of this ralloc-based new need not call delete. It's + * easier to just ralloc_free 'ctx' (or any of its ancestors). */ static void* operator new(size_t size, void *ctx) { void *table; - table = talloc_size(ctx, size); + table = ralloc_size(ctx, size); assert(table != NULL); - talloc_set_destructor(table, (int (*)(void*)) _glsl_symbol_table_destructor); + ralloc_set_destructor(table, (void (*)(void*)) _glsl_symbol_table_destructor); return table; } /* If the user *does* call delete, that's OK, we will just - * talloc_free in that case. Here, C++ will have already called the - * destructor so tell talloc not to do that again. */ + * ralloc_free in that case. Here, C++ will have already called the + * destructor so tell ralloc not to do that again. */ static void operator delete(void *table) { - talloc_set_destructor(table, NULL); - talloc_free(table); + ralloc_set_destructor(table, NULL); + ralloc_free(table); } glsl_symbol_table(); diff --git a/src/glsl/glsl_types.cpp b/src/glsl/glsl_types.cpp index 95b85926482..76b4f3e4cb0 100644 --- a/src/glsl/glsl_types.cpp +++ b/src/glsl/glsl_types.cpp @@ -21,7 +21,7 @@ * DEALINGS IN THE SOFTWARE. */ -#include <cstdio> +#include <stdio.h> #include <stdlib.h> #include "main/core.h" /* for Elements */ #include "glsl_symbol_table.h" @@ -37,10 +37,10 @@ hash_table *glsl_type::record_types = NULL; void *glsl_type::mem_ctx = NULL; void -glsl_type::init_talloc_type_ctx(void) +glsl_type::init_ralloc_type_ctx(void) { if (glsl_type::mem_ctx == NULL) { - glsl_type::mem_ctx = talloc_autofree_context(); + glsl_type::mem_ctx = ralloc_autofree_context(); assert(glsl_type::mem_ctx != NULL); } } @@ -55,8 +55,8 @@ glsl_type::glsl_type(GLenum gl_type, vector_elements(vector_elements), matrix_columns(matrix_columns), length(0) { - init_talloc_type_ctx(); - this->name = talloc_strdup(this->mem_ctx, name); + init_ralloc_type_ctx(); + this->name = ralloc_strdup(this->mem_ctx, name); /* Neither dimension is zero or both dimensions are zero. */ assert((vector_elements == 0) == (matrix_columns == 0)); @@ -73,8 +73,8 @@ glsl_type::glsl_type(GLenum gl_type, vector_elements(0), matrix_columns(0), length(0) { - init_talloc_type_ctx(); - this->name = talloc_strdup(this->mem_ctx, name); + init_ralloc_type_ctx(); + this->name = ralloc_strdup(this->mem_ctx, name); memset(& fields, 0, sizeof(fields)); } @@ -88,13 +88,13 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields, { unsigned int i; - init_talloc_type_ctx(); - this->name = talloc_strdup(this->mem_ctx, name); - this->fields.structure = talloc_array(this->mem_ctx, + init_ralloc_type_ctx(); + this->name = ralloc_strdup(this->mem_ctx, name); + this->fields.structure = ralloc_array(this->mem_ctx, glsl_struct_field, length); for (i = 0; i < length; i++) { this->fields.structure[i].type = fields[i].type; - this->fields.structure[i].name = talloc_strdup(this->fields.structure, + this->fields.structure[i].name = ralloc_strdup(this->fields.structure, fields[i].name); } } @@ -264,7 +264,7 @@ glsl_type::glsl_type(const glsl_type *array, unsigned length) : * NUL. */ const unsigned name_length = strlen(array->name) + 10 + 3; - char *const n = (char *) talloc_size(this->mem_ctx, name_length); + char *const n = (char *) ralloc_size(this->mem_ctx, name_length); if (length == 0) snprintf(n, name_length, "%s[]", array->name); @@ -354,7 +354,7 @@ glsl_type::get_array_instance(const glsl_type *base, unsigned array_size) if (t == NULL) { t = new glsl_type(base, array_size); - hash_table_insert(array_types, (void *) t, talloc_strdup(mem_ctx, key)); + hash_table_insert(array_types, (void *) t, ralloc_strdup(mem_ctx, key)); } assert(t->base_type == GLSL_TYPE_ARRAY); diff --git a/src/glsl/glsl_types.h b/src/glsl/glsl_types.h index 57e7b09d98c..61bf5e0cfd2 100644 --- a/src/glsl/glsl_types.h +++ b/src/glsl/glsl_types.h @@ -26,14 +26,15 @@ #ifndef GLSL_TYPES_H #define GLSL_TYPES_H -#include <cstring> -#include <cassert> +#include <string.h> +#include <assert.h> extern "C" { #include "GL/gl.h" -#include <talloc.h> } +#include "ralloc.h" + struct _mesa_glsl_parse_state; struct glsl_symbol_table; @@ -77,28 +78,28 @@ struct glsl_type { * and \c GLSL_TYPE_UINT are valid. */ - /* Callers of this talloc-based new need not call delete. It's - * easier to just talloc_free 'mem_ctx' (or any of its ancestors). */ + /* Callers of this ralloc-based new need not call delete. It's + * easier to just ralloc_free 'mem_ctx' (or any of its ancestors). */ static void* operator new(size_t size) { if (glsl_type::mem_ctx == NULL) { - glsl_type::mem_ctx = talloc_init("glsl_type"); + glsl_type::mem_ctx = ralloc_context(NULL); assert(glsl_type::mem_ctx != NULL); } void *type; - type = talloc_size(glsl_type::mem_ctx, size); + type = ralloc_size(glsl_type::mem_ctx, size); assert(type != NULL); return type; } /* If the user *does* call delete, that's OK, we will just - * talloc_free in that case. */ + * ralloc_free in that case. */ static void operator delete(void *type) { - talloc_free(type); + ralloc_free(type); } /** @@ -386,13 +387,13 @@ struct glsl_type { private: /** - * talloc context for all glsl_type allocations + * ralloc context for all glsl_type allocations * * Set on the first call to \c glsl_type::new. */ static void *mem_ctx; - void init_talloc_type_ctx(void); + void init_ralloc_type_ctx(void); /** Constructor for vector and matrix types */ glsl_type(GLenum gl_type, diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index 460d43b02e1..fc356ba5275 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -472,6 +472,22 @@ const char *ir_expression::operator_string() return operator_string(this->operation); } +const char* +depth_layout_string(ir_depth_layout layout) +{ + switch(layout) { + case ir_depth_layout_none: return ""; + case ir_depth_layout_any: return "depth_any"; + case ir_depth_layout_greater: return "depth_greater"; + case ir_depth_layout_less: return "depth_less"; + case ir_depth_layout_unchanged: return "depth_unchanged"; + + default: + assert(0); + return ""; + } +} + ir_expression_operation ir_expression::get_operator(const char *str) { @@ -562,7 +578,7 @@ ir_constant::ir_constant(const struct glsl_type *type, exec_list *value_list) || type->is_record() || type->is_array()); if (type->is_array()) { - this->array_elements = talloc_array(this, ir_constant *, type->length); + this->array_elements = ralloc_array(this, ir_constant *, type->length); unsigned i = 0; foreach_list(node, value_list) { ir_constant *value = (ir_constant *) node; @@ -1020,7 +1036,7 @@ ir_dereference_array::ir_dereference_array(ir_rvalue *value, ir_dereference_array::ir_dereference_array(ir_variable *var, ir_rvalue *array_index) { - void *ctx = talloc_parent(var); + void *ctx = ralloc_parent(var); this->ir_type = ir_type_dereference_array; this->array_index = array_index; @@ -1053,7 +1069,7 @@ ir_dereference_record::ir_dereference_record(ir_rvalue *value, { this->ir_type = ir_type_dereference_record; this->record = value; - this->field = talloc_strdup(this, field); + this->field = ralloc_strdup(this, field); this->type = (this->record != NULL) ? this->record->type->field_type(field) : glsl_type::error_type; } @@ -1062,11 +1078,11 @@ ir_dereference_record::ir_dereference_record(ir_rvalue *value, ir_dereference_record::ir_dereference_record(ir_variable *var, const char *field) { - void *ctx = talloc_parent(var); + void *ctx = ralloc_parent(var); this->ir_type = ir_type_dereference_record; this->record = new(ctx) ir_dereference_variable(var); - this->field = talloc_strdup(this, field); + this->field = ralloc_strdup(this, field); this->type = (this->record != NULL) ? this->record->type->field_type(field) : glsl_type::error_type; } @@ -1229,7 +1245,7 @@ ir_swizzle::ir_swizzle(ir_rvalue *val, ir_swizzle_mask mask) ir_swizzle * ir_swizzle::create(ir_rvalue *val, const char *str, unsigned vector_length) { - void *ctx = talloc_parent(val); + void *ctx = ralloc_parent(val); /* For each possible swizzle character, this table encodes the value in * \c idx_map that represents the 0th element of the vector. For invalid @@ -1318,13 +1334,14 @@ ir_variable::ir_variable(const struct glsl_type *type, const char *name, { this->ir_type = ir_type_variable; this->type = type; - this->name = talloc_strdup(this, name); + this->name = ralloc_strdup(this, name); this->explicit_location = false; this->location = -1; this->warn_extension = NULL; this->constant_value = NULL; this->origin_upper_left = false; this->pixel_center_integer = false; + this->depth_layout = ir_depth_layout_none; this->used = false; if (type && type->base_type == GLSL_TYPE_SAMPLER) @@ -1362,6 +1379,21 @@ ir_function_signature::ir_function_signature(const glsl_type *return_type) } +static bool +modes_match(unsigned a, unsigned b) +{ + if (a == b) + return true; + + /* Accept "in" vs. "const in" */ + if ((a == ir_var_const_in && b == ir_var_in) || + (b == ir_var_const_in && a == ir_var_in)) + return true; + + return false; +} + + const char * ir_function_signature::qualifiers_match(exec_list *params) { @@ -1374,7 +1406,7 @@ ir_function_signature::qualifiers_match(exec_list *params) ir_variable *b = (ir_variable *)iter_b.get(); if (a->read_only != b->read_only || - a->mode != b->mode || + !modes_match(a->mode, b->mode) || a->interpolation != b->interpolation || a->centroid != b->centroid) { @@ -1409,7 +1441,7 @@ ir_function_signature::replace_parameters(exec_list *new_params) ir_function::ir_function(const char *name) { this->ir_type = ir_type_function; - this->name = talloc_strdup(this, name); + this->name = ralloc_strdup(this, name); } @@ -1475,7 +1507,7 @@ steal_memory(ir_instruction *ir, void *new_ctx) } } - talloc_steal(new_ctx, ir); + ralloc_steal(new_ctx, ir); } diff --git a/src/glsl/ir.h b/src/glsl/ir.h index 7b83c2836ee..f2f902c0a77 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -26,13 +26,10 @@ #ifndef IR_H #define IR_H -#include <cstdio> -#include <cstdlib> - -extern "C" { -#include <talloc.h> -} +#include <stdio.h> +#include <stdlib.h> +#include "ralloc.h" #include "glsl_types.h" #include "list.h" #include "ir_visitor.h" @@ -225,6 +222,7 @@ enum ir_variable_mode { ir_var_in, ir_var_out, ir_var_inout, + ir_var_const_in, /**< "in" param that must be a constant expression */ ir_var_system_value, /**< Ex: front-face, instance-id, etc. */ ir_var_temporary /**< Temporary variable generated during compilation. */ }; @@ -235,6 +233,25 @@ enum ir_variable_interpolation { ir_var_noperspective }; +/** + * \brief Layout qualifiers for gl_FragDepth. + * + * The AMD_conservative_depth extension allows gl_FragDepth to be redeclared + * with a layout qualifier. + */ +enum ir_depth_layout { + ir_depth_layout_none, /**< No depth layout is specified. */ + ir_depth_layout_any, + ir_depth_layout_greater, + ir_depth_layout_less, + ir_depth_layout_unchanged +}; + +/** + * \brief Convert depth layout qualifier to string. + */ +const char* +depth_layout_string(ir_depth_layout layout); class ir_variable : public ir_instruction { public: @@ -335,6 +352,14 @@ public: /*@}*/ /** + * \brief Layout qualifier for gl_FragDepth. + * + * This is not equal to \c ir_depth_layout_none if and only if this + * variable is \c gl_FragDepth and a layout qualifier is specified. + */ + ir_depth_layout depth_layout; + + /** * Was the location explicitly set in the shader? * * If the location is explicitly set in the shader, it \b cannot be changed @@ -959,7 +984,7 @@ public: /** * Get a generic ir_call object when an error occurs * - * Any allocation will be performed with 'ctx' as talloc owner. + * Any allocation will be performed with 'ctx' as ralloc owner. */ static ir_call *get_error_instruction(void *ctx); @@ -1166,21 +1191,21 @@ enum ir_texture_opcode { * selected from \c ir_texture_opcodes. In the printed IR, these will * appear as: * - * Texel offset - * | Projection divisor - * | | Shadow comparitor - * | | | - * v v v - * (tex (sampler) (coordinate) (0 0 0) (1) ( )) - * (txb (sampler) (coordinate) (0 0 0) (1) ( ) (bias)) - * (txl (sampler) (coordinate) (0 0 0) (1) ( ) (lod)) - * (txd (sampler) (coordinate) (0 0 0) (1) ( ) (dPdx dPdy)) - * (txf (sampler) (coordinate) (0 0 0) (lod)) + * Texel offset (0 or an expression) + * | Projection divisor + * | | Shadow comparitor + * | | | + * v v v + * (tex <sampler> <coordinate> 0 1 ( )) + * (txb <sampler> <coordinate> 0 1 ( ) <bias>) + * (txl <sampler> <coordinate> 0 1 ( ) <lod>) + * (txd <sampler> <coordinate> 0 1 ( ) (dPdx dPdy)) + * (txf <sampler> <coordinate> 0 <lod>) */ class ir_texture : public ir_rvalue { public: ir_texture(enum ir_texture_opcode op) - : op(op), projector(NULL), shadow_comparitor(NULL) + : op(op), projector(NULL), shadow_comparitor(NULL), offset(NULL) { this->ir_type = ir_type_texture; } @@ -1234,8 +1259,8 @@ public: */ ir_rvalue *shadow_comparitor; - /** Explicit texel offsets. */ - signed char offsets[3]; + /** Texel offset. */ + ir_rvalue *offset; union { ir_rvalue *lod; /**< Floating point LOD */ diff --git a/src/glsl/ir_clone.cpp b/src/glsl/ir_clone.cpp index 1522af682bb..2c0574dc6bf 100644 --- a/src/glsl/ir_clone.cpp +++ b/src/glsl/ir_clone.cpp @@ -217,8 +217,8 @@ ir_texture::clone(void *mem_ctx, struct hash_table *ht) const new_tex->shadow_comparitor = this->shadow_comparitor->clone(mem_ctx, ht); } - for (int i = 0; i < 3; i++) - new_tex->offsets[i] = this->offsets[i]; + if (this->offset != NULL) + new_tex->offset = this->offset->clone(mem_ctx, ht); switch (this->op) { case ir_tex: @@ -346,7 +346,7 @@ ir_constant::clone(void *mem_ctx, struct hash_table *ht) const ir_constant *c = new(mem_ctx) ir_constant; c->type = this->type; - c->array_elements = talloc_array(c, ir_constant *, this->type->length); + c->array_elements = ralloc_array(c, ir_constant *, this->type->length); for (unsigned i = 0; i < this->type->length; i++) { c->array_elements[i] = this->array_elements[i]->clone(mem_ctx, NULL); } diff --git a/src/glsl/ir_constant_expression.cpp b/src/glsl/ir_constant_expression.cpp index 4fd6d09a3af..2a308489656 100644 --- a/src/glsl/ir_constant_expression.cpp +++ b/src/glsl/ir_constant_expression.cpp @@ -86,7 +86,7 @@ ir_expression::constant_expression_value() components = op[1]->type->components(); } - void *ctx = talloc_parent(this); + void *ctx = ralloc_parent(this); /* Handle array operations here, rather than below. */ if (op[0]->type->is_array()) { @@ -507,6 +507,7 @@ ir_expression::constant_expression_value() break; case ir_binop_div: + /* FINISHME: Emit warning when division-by-zero is detected. */ assert(op[0]->type == op[1]->type || op0_scalar || op1_scalar); for (unsigned c = 0, c0 = 0, c1 = 0; c < components; @@ -514,10 +515,18 @@ ir_expression::constant_expression_value() switch (op[0]->type->base_type) { case GLSL_TYPE_UINT: - data.u[c] = op[0]->value.u[c0] / op[1]->value.u[c1]; + if (op[1]->value.u[c1] == 0) { + data.u[c] = 0; + } else { + data.u[c] = op[0]->value.u[c0] / op[1]->value.u[c1]; + } break; case GLSL_TYPE_INT: - data.i[c] = op[0]->value.i[c0] / op[1]->value.i[c1]; + if (op[1]->value.i[c1] == 0) { + data.i[c] = 0; + } else { + data.i[c] = op[0]->value.i[c0] / op[1]->value.i[c1]; + } break; case GLSL_TYPE_FLOAT: data.f[c] = op[0]->value.f[c0] / op[1]->value.f[c1]; @@ -529,6 +538,7 @@ ir_expression::constant_expression_value() break; case ir_binop_mod: + /* FINISHME: Emit warning when division-by-zero is detected. */ assert(op[0]->type == op[1]->type || op0_scalar || op1_scalar); for (unsigned c = 0, c0 = 0, c1 = 0; c < components; @@ -536,10 +546,18 @@ ir_expression::constant_expression_value() switch (op[0]->type->base_type) { case GLSL_TYPE_UINT: - data.u[c] = op[0]->value.u[c0] % op[1]->value.u[c1]; + if (op[1]->value.u[c1] == 0) { + data.u[c] = 0; + } else { + data.u[c] = op[0]->value.u[c0] % op[1]->value.u[c1]; + } break; case GLSL_TYPE_INT: - data.i[c] = op[0]->value.i[c0] % op[1]->value.i[c1]; + if (op[1]->value.i[c1] == 0) { + data.i[c] = 0; + } else { + data.i[c] = op[0]->value.i[c0] % op[1]->value.i[c1]; + } break; case GLSL_TYPE_FLOAT: /* We don't use fmod because it rounds toward zero; GLSL specifies @@ -845,7 +863,7 @@ ir_swizzle::constant_expression_value() } } - void *ctx = talloc_parent(this); + void *ctx = ralloc_parent(this); return new(ctx) ir_constant(this->type, &data); } return NULL; @@ -868,7 +886,7 @@ ir_dereference_variable::constant_expression_value() if (!var->constant_value) return NULL; - return var->constant_value->clone(talloc_parent(var), NULL); + return var->constant_value->clone(ralloc_parent(var), NULL); } @@ -879,7 +897,7 @@ ir_dereference_array::constant_expression_value() ir_constant *idx = this->array_index->constant_expression_value(); if ((array != NULL) && (idx != NULL)) { - void *ctx = talloc_parent(this); + void *ctx = ralloc_parent(this); if (array->type->is_matrix()) { /* Array access of a matrix results in a vector. */ @@ -984,7 +1002,7 @@ ir_call::constant_expression_value() * - Fill "data" with appopriate constant data * - Return an ir_constant directly. */ - void *mem_ctx = talloc_parent(this); + void *mem_ctx = ralloc_parent(this); ir_expression *expr = NULL; ir_constant_data data; diff --git a/src/glsl/ir_expression_flattening.cpp b/src/glsl/ir_expression_flattening.cpp index 7b1b8dbfef1..0b7c537bd8a 100644 --- a/src/glsl/ir_expression_flattening.cpp +++ b/src/glsl/ir_expression_flattening.cpp @@ -78,7 +78,7 @@ ir_expression_flattening_visitor::handle_rvalue(ir_rvalue **rvalue) if (!ir || !this->predicate(ir)) return; - void *ctx = talloc_parent(ir); + void *ctx = ralloc_parent(ir); var = new(ctx) ir_variable(ir->type, "flattening_tmp", ir_var_temporary); base_ir->insert_before(var); diff --git a/src/glsl/ir_function.cpp b/src/glsl/ir_function.cpp index 8db70119ec2..caee9296af9 100644 --- a/src/glsl/ir_function.cpp +++ b/src/glsl/ir_function.cpp @@ -123,6 +123,7 @@ parameter_lists_match(const exec_list *list_a, const exec_list *list_b) assert(0); return -1; + case ir_var_const_in: case ir_var_in: score = type_compare(param->type, actual->type); break; diff --git a/src/glsl/ir_hv_accept.cpp b/src/glsl/ir_hv_accept.cpp index be8b36a7cf8..4a607dc8749 100644 --- a/src/glsl/ir_hv_accept.cpp +++ b/src/glsl/ir_hv_accept.cpp @@ -187,6 +187,12 @@ ir_texture::accept(ir_hierarchical_visitor *v) return (s == visit_continue_with_parent) ? visit_continue : s; } + if (this->offset) { + s = this->offset->accept(v); + if (s != visit_continue) + return (s == visit_continue_with_parent) ? visit_continue : s; + } + switch (this->op) { case ir_tex: break; diff --git a/src/glsl/ir_import_prototypes.cpp b/src/glsl/ir_import_prototypes.cpp index 4e0b30aa90e..3585bf6b24b 100644 --- a/src/glsl/ir_import_prototypes.cpp +++ b/src/glsl/ir_import_prototypes.cpp @@ -27,7 +27,6 @@ * * \author Ian Romanick */ -#include <cstdio> #include "ir.h" #include "glsl_symbol_table.h" @@ -109,7 +108,7 @@ private: * \param dest Destination instruction stream where new \c ir_function and * \c ir_function_signature nodes will be stored * \param symbols Symbol table where new functions will be stored - * \param mem_ctx talloc memory context used for new allocations + * \param mem_ctx ralloc memory context used for new allocations */ void import_prototypes(const exec_list *source, exec_list *dest, diff --git a/src/glsl/ir_optimization.h b/src/glsl/ir_optimization.h index dbc9f4ab975..dd265673c55 100644 --- a/src/glsl/ir_optimization.h +++ b/src/glsl/ir_optimization.h @@ -43,6 +43,7 @@ bool do_constant_folding(exec_list *instructions); bool do_constant_variable(exec_list *instructions); bool do_constant_variable_unlinked(exec_list *instructions); bool do_copy_propagation(exec_list *instructions); +bool do_copy_propagation_elements(exec_list *instructions); bool do_constant_propagation(exec_list *instructions); bool do_dead_code(exec_list *instructions); bool do_dead_code_local(exec_list *instructions); diff --git a/src/glsl/ir_print_visitor.cpp b/src/glsl/ir_print_visitor.cpp index c56bafd00c5..82ccc722fa2 100644 --- a/src/glsl/ir_print_visitor.cpp +++ b/src/glsl/ir_print_visitor.cpp @@ -97,7 +97,7 @@ void ir_print_visitor::visit(ir_variable *ir) const char *const cent = (ir->centroid) ? "centroid " : ""; const char *const inv = (ir->invariant) ? "invariant " : ""; const char *const mode[] = { "", "uniform ", "in ", "out ", "inout ", - "temporary " }; + "const_in ", "sys ", "temporary " }; const char *const interp[] = { "", "flat", "noperspective" }; printf("(%s%s%s%s) ", @@ -192,7 +192,15 @@ void ir_print_visitor::visit(ir_texture *ir) ir->coordinate->accept(this); - printf(" (%d %d %d) ", ir->offsets[0], ir->offsets[1], ir->offsets[2]); + printf(" "); + + if (ir->offset != NULL) { + ir->offset->accept(this); + } else { + printf("0"); + } + + printf(" "); if (ir->op != ir_txf) { if (ir->projector) diff --git a/src/glsl/ir_reader.cpp b/src/glsl/ir_reader.cpp index 40901dc6c92..af85e06ae0e 100644 --- a/src/glsl/ir_reader.cpp +++ b/src/glsl/ir_reader.cpp @@ -21,10 +21,6 @@ * DEALINGS IN THE SOFTWARE. */ -extern "C" { -#include <talloc.h> -} - #include "ir_reader.h" #include "glsl_parser_extras.h" #include "glsl_types.h" @@ -96,7 +92,7 @@ ir_reader::read(exec_list *instructions, const char *src, bool scan_for_protos) } read_instructions(instructions, expr, NULL); - talloc_free(expr); + ralloc_free(expr); if (debug) validate_ir_tree(instructions); @@ -110,21 +106,19 @@ ir_reader::ir_read_error(s_expression *expr, const char *fmt, ...) state->error = true; if (state->current_function != NULL) - state->info_log = talloc_asprintf_append(state->info_log, - "In function %s:\n", - state->current_function->function_name()); - state->info_log = talloc_strdup_append(state->info_log, "error: "); + ralloc_asprintf_append(&state->info_log, "In function %s:\n", + state->current_function->function_name()); + ralloc_strcat(&state->info_log, "error: "); va_start(ap, fmt); - state->info_log = talloc_vasprintf_append(state->info_log, fmt, ap); + ralloc_vasprintf_append(&state->info_log, fmt, ap); va_end(ap); - state->info_log = talloc_strdup_append(state->info_log, "\n"); + ralloc_strcat(&state->info_log, "\n"); if (expr != NULL) { - state->info_log = talloc_strdup_append(state->info_log, - "...in this context:\n "); + ralloc_strcat(&state->info_log, "...in this context:\n "); expr->print(); - state->info_log = talloc_strdup_append(state->info_log, "\n\n"); + ralloc_strcat(&state->info_log, "\n\n"); } } @@ -403,6 +397,8 @@ ir_reader::read_declaration(s_expression *expr) var->mode = ir_var_auto; } else if (strcmp(qualifier->value(), "in") == 0) { var->mode = ir_var_in; + } else if (strcmp(qualifier->value(), "const_in") == 0) { + var->mode = ir_var_const_in; } else if (strcmp(qualifier->value(), "out") == 0) { var->mode = ir_var_out; } else if (strcmp(qualifier->value(), "inout") == 0) { @@ -875,12 +871,12 @@ ir_reader::read_texture(s_expression *expr) s_symbol *tag = NULL; s_expression *s_sampler = NULL; s_expression *s_coord = NULL; - s_list *s_offset = NULL; + s_expression *s_offset = NULL; s_expression *s_proj = NULL; s_list *s_shadow = NULL; s_expression *s_lod = NULL; - ir_texture_opcode op; + ir_texture_opcode op = ir_tex; /* silence warning */ s_pattern tex_pattern[] = { "tex", s_sampler, s_coord, s_offset, s_proj, s_shadow }; @@ -897,6 +893,9 @@ ir_reader::read_texture(s_expression *expr) op = ir_texture::get_opcode(tag->value()); if (op == -1) return NULL; + } else { + ir_read_error(NULL, "unexpected texture pattern"); + return NULL; } ir_texture *tex = new(mem_ctx) ir_texture(op); @@ -918,18 +917,15 @@ ir_reader::read_texture(s_expression *expr) return NULL; } - // Read texel offset, i.e. (0 0 0) - s_int *offset_x; - s_int *offset_y; - s_int *offset_z; - s_pattern offset_pat[] = { offset_x, offset_y, offset_z }; - if (!MATCH(s_offset, offset_pat)) { - ir_read_error(s_offset, "expected (<int> <int> <int>)"); - return NULL; + // Read texel offset - either 0 or an rvalue. + s_int *si_offset = SX_AS_INT(s_offset); + if (si_offset == NULL || si_offset->value() != 0) { + tex->offset = read_rvalue(s_offset); + if (tex->offset == NULL) { + ir_read_error(s_offset, "expected 0 or an expression"); + return NULL; + } } - tex->offsets[0] = offset_x->value(); - tex->offsets[1] = offset_y->value(); - tex->offsets[2] = offset_z->value(); if (op != ir_txf) { s_int *proj_as_int = SX_AS_INT(s_proj); diff --git a/src/glsl/ir_rvalue_visitor.cpp b/src/glsl/ir_rvalue_visitor.cpp index 773bfcfa3ec..ed6c7cb6a1a 100644 --- a/src/glsl/ir_rvalue_visitor.cpp +++ b/src/glsl/ir_rvalue_visitor.cpp @@ -53,6 +53,7 @@ ir_rvalue_visitor::visit_leave(ir_texture *ir) handle_rvalue(&ir->coordinate); handle_rvalue(&ir->projector); handle_rvalue(&ir->shadow_comparitor); + handle_rvalue(&ir->offset); switch (ir->op) { case ir_tex: diff --git a/src/glsl/ir_validate.cpp b/src/glsl/ir_validate.cpp index 5b055f64d38..44d7549ea28 100644 --- a/src/glsl/ir_validate.cpp +++ b/src/glsl/ir_validate.cpp @@ -179,7 +179,7 @@ ir_validate::visit_enter(ir_function *ir) ir_visitor_status ir_validate::visit_leave(ir_function *ir) { - assert(talloc_parent(ir->name) == ir); + assert(ralloc_parent(ir->name) == ir); this->current_function = NULL; return visit_continue; @@ -450,7 +450,7 @@ ir_validate::visit(ir_variable *ir) * declared before it is dereferenced. */ if (ir->name) - assert(talloc_parent(ir->name) == ir); + assert(ralloc_parent(ir->name) == ir); hash_table_insert(ht, ir, ir); return visit_continue; diff --git a/src/glsl/ir_variable.cpp b/src/glsl/ir_variable.cpp index 73da28faf4f..18a3e0fb0d9 100644 --- a/src/glsl/ir_variable.cpp +++ b/src/glsl/ir_variable.cpp @@ -45,6 +45,7 @@ add_variable(const char *name, enum ir_variable_mode mode, int slot, switch (var->mode) { case ir_var_auto: case ir_var_in: + case ir_var_const_in: case ir_var_uniform: case ir_var_system_value: var->read_only = true; diff --git a/src/glsl/ir_variable_refcount.h b/src/glsl/ir_variable_refcount.h index 8b43bad71f8..906135a9e1e 100644 --- a/src/glsl/ir_variable_refcount.h +++ b/src/glsl/ir_variable_refcount.h @@ -54,13 +54,13 @@ class ir_variable_refcount_visitor : public ir_hierarchical_visitor { public: ir_variable_refcount_visitor(void) { - this->mem_ctx = talloc_new(NULL); + this->mem_ctx = ralloc_context(NULL); this->variable_list.make_empty(); } ~ir_variable_refcount_visitor(void) { - talloc_free(this->mem_ctx); + ralloc_free(this->mem_ctx); } virtual ir_visitor_status visit(ir_variable *); diff --git a/src/glsl/link_functions.cpp b/src/glsl/link_functions.cpp index 05930edb80e..5851c14d624 100644 --- a/src/glsl/link_functions.cpp +++ b/src/glsl/link_functions.cpp @@ -21,14 +21,6 @@ * DEALINGS IN THE SOFTWARE. */ -#include <cstdlib> -#include <cstdio> -#include <cstdarg> - -extern "C" { -#include <talloc.h> -} - #include "main/core.h" #include "glsl_symbol_table.h" #include "glsl_parser_extras.h" @@ -185,6 +177,18 @@ public: var = ir->var->clone(linked, NULL); linked->symbols->add_variable(var); linked->ir->push_head(var); + } else if (var->type->is_array()) { + /* It is possible to have a global array declared in multiple + * shaders without a size. The array is implicitly sized by the + * maximal access to it in *any* shader. Because of this, we + * need to track the maximal access to the array as linking pulls + * more functions in that access the array. + */ + var->max_array_access = + MAX2(var->max_array_access, ir->var->max_array_access); + + if (var->type->length == 0 && ir->var->type->length != 0) + var->type = ir->var->type; } ir->var = var; diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index c906d744212..7db5c5e8d53 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -63,14 +63,6 @@ * * \author Ian Romanick <[email protected]> */ -#include <cstdlib> -#include <cstdio> -#include <cstdarg> -#include <climits> - -extern "C" { -#include <talloc.h> -} #include "main/core.h" #include "glsl_symbol_table.h" @@ -176,9 +168,9 @@ linker_error_printf(gl_shader_program *prog, const char *fmt, ...) { va_list ap; - prog->InfoLog = talloc_strdup_append(prog->InfoLog, "error: "); + ralloc_strcat(&prog->InfoLog, "error: "); va_start(ap, fmt); - prog->InfoLog = talloc_vasprintf_append(prog->InfoLog, fmt, ap); + ralloc_vasprintf_append(&prog->InfoLog, fmt, ap); va_end(ap); } @@ -303,6 +295,7 @@ mode_string(const ir_variable *var) case ir_var_out: return "shader output"; case ir_var_inout: return "shader inout"; + case ir_var_const_in: case ir_var_temporary: default: assert(!"Should not get here."); @@ -360,11 +353,8 @@ cross_validate_globals(struct gl_shader_program *prog, && (var->type->fields.array == existing->type->fields.array) && ((var->type->length == 0) || (existing->type->length == 0))) { - if (existing->type->length == 0) { + if (var->type->length != 0) { existing->type = var->type; - existing->max_array_access = - MAX2(existing->max_array_access, - var->max_array_access); } } else { linker_error_printf(prog, "%s `%s' declared as type " @@ -389,6 +379,32 @@ cross_validate_globals(struct gl_shader_program *prog, existing->explicit_location = true; } + /* Validate layout qualifiers for gl_FragDepth. + * + * From the AMD_conservative_depth spec: + * "If gl_FragDepth is redeclared in any fragment shader in + * a program, it must be redeclared in all fragment shaders in that + * program that have static assignments to gl_FragDepth. All + * redeclarations of gl_FragDepth in all fragment shaders in + * a single program must have the same set of qualifiers." + */ + if (strcmp(var->name, "gl_FragDepth") == 0) { + bool layout_declared = var->depth_layout != ir_depth_layout_none; + bool layout_differs = var->depth_layout != existing->depth_layout; + if (layout_declared && layout_differs) { + linker_error_printf(prog, + "All redeclarations of gl_FragDepth in all fragment shaders " + "in a single program must have the same set of qualifiers."); + } + if (var->used && layout_differs) { + linker_error_printf(prog, + "If gl_FragDepth is redeclared with a layout qualifier in" + "any fragment shader, it must be redeclared with the same" + "layout qualifier in all fragment shaders that have" + "assignments to gl_FragDepth"); + } + } + /* FINISHME: Handle non-constant initializers. */ if (var->constant_value != NULL) { @@ -413,7 +429,7 @@ cross_validate_globals(struct gl_shader_program *prog, * FINISHME: will fail. */ existing->constant_value = - var->constant_value->clone(talloc_parent(existing), NULL); + var->constant_value->clone(ralloc_parent(existing), NULL); } if (existing->invariant != var->invariant) { @@ -894,30 +910,29 @@ link_intrastage_shaders(void *mem_ctx, free(linking_shaders); - /* Make a pass over all global variables to ensure that arrays with + /* Make a pass over all variable declarations to ensure that arrays with * unspecified sizes have a size specified. The size is inferred from the * max_array_access field. */ if (linked != NULL) { - foreach_list(node, linked->ir) { - ir_variable *const var = ((ir_instruction *) node)->as_variable(); - - if (var == NULL) - continue; - - if ((var->mode != ir_var_auto) && (var->mode != ir_var_temporary)) - continue; - - if (!var->type->is_array() || (var->type->length != 0)) - continue; + class array_sizing_visitor : public ir_hierarchical_visitor { + public: + virtual ir_visitor_status visit(ir_variable *var) + { + if (var->type->is_array() && (var->type->length == 0)) { + const glsl_type *type = + glsl_type::get_array_instance(var->type->fields.array, + var->max_array_access + 1); + + assert(type != NULL); + var->type = type; + } - const glsl_type *type = - glsl_type::get_array_instance(var->type->fields.array, - var->max_array_access); + return visit_continue; + } + } v; - assert(type != NULL); - var->type = type; - } + v.run(linked->ir); } return linked; @@ -997,7 +1012,7 @@ add_uniform(void *mem_ctx, exec_list *uniforms, struct hash_table *ht, if (type->is_record()) { for (unsigned int i = 0; i < type->length; i++) { const glsl_type *field_type = type->fields.structure[i].type; - char *field_name = talloc_asprintf(mem_ctx, "%s.%s", name, + char *field_name = ralloc_asprintf(mem_ctx, "%s.%s", name, type->fields.structure[i].name); add_uniform(mem_ctx, uniforms, ht, field_name, field_type, @@ -1013,7 +1028,7 @@ add_uniform(void *mem_ctx, exec_list *uniforms, struct hash_table *ht, /* Array of structures. */ if (array_elem_type->is_record()) { for (unsigned int i = 0; i < type->length; i++) { - char *elem_name = talloc_asprintf(mem_ctx, "%s[%d]", name, i); + char *elem_name = ralloc_asprintf(mem_ctx, "%s[%d]", name, i); add_uniform(mem_ctx, uniforms, ht, elem_name, array_elem_type, shader_type, next_shader_pos, total_uniforms); } @@ -1075,7 +1090,7 @@ assign_uniform_locations(struct gl_shader_program *prog) unsigned total_uniforms = 0; hash_table *ht = hash_table_ctor(32, hash_table_string_hash, hash_table_string_compare); - void *mem_ctx = talloc_new(NULL); + void *mem_ctx = ralloc_context(NULL); for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) { if (prog->_LinkedShaders[i] == NULL) @@ -1104,7 +1119,7 @@ assign_uniform_locations(struct gl_shader_program *prog) } } - talloc_free(mem_ctx); + ralloc_free(mem_ctx); gl_uniform_list *ul = (gl_uniform_list *) calloc(1, sizeof(gl_uniform_list)); @@ -1472,16 +1487,16 @@ assign_varying_locations(struct gl_shader_program *prog, void link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) { - void *mem_ctx = talloc_init("temporary linker context"); + void *mem_ctx = ralloc_context(NULL); // temporary linker context prog->LinkStatus = false; prog->Validated = false; prog->_Used = false; if (prog->InfoLog != NULL) - talloc_free(prog->InfoLog); + ralloc_free(prog->InfoLog); - prog->InfoLog = talloc_strdup(NULL, ""); + prog->InfoLog = ralloc_strdup(NULL, ""); /* Separate the shaders into groups based on their type. */ @@ -1663,6 +1678,20 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) demote_shader_inputs_and_outputs(sh, ir_var_in); } + /* OpenGL ES requires that a vertex shader and a fragment shader both be + * present in a linked program. By checking for use of shading language + * version 1.00, we also catch the GL_ARB_ES2_compatibility case. + */ + if (ctx->API == API_OPENGLES2 || prog->Version == 100) { + if (prog->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) { + linker_error_printf(prog, "program lacks a vertex shader\n"); + prog->LinkStatus = false; + } else if (prog->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL) { + linker_error_printf(prog, "program lacks a fragment shader\n"); + prog->LinkStatus = false; + } + } + /* FINISHME: Assign fragment shader output locations. */ done: @@ -1676,5 +1705,5 @@ done: reparent_ir(prog->_LinkedShaders[i]->ir, prog->_LinkedShaders[i]->ir); } - talloc_free(mem_ctx); + ralloc_free(mem_ctx); } diff --git a/src/glsl/list.h b/src/glsl/list.h index 3197b03cf28..1d46365faec 100644 --- a/src/glsl/list.h +++ b/src/glsl/list.h @@ -66,37 +66,33 @@ #ifndef __cplusplus #include <stddef.h> -#include <talloc.h> -#else -extern "C" { -#include <talloc.h> -} #endif - #include <assert.h> +#include "ralloc.h" + struct exec_node { struct exec_node *next; struct exec_node *prev; #ifdef __cplusplus - /* Callers of this talloc-based new need not call delete. It's - * easier to just talloc_free 'ctx' (or any of its ancestors). */ + /* Callers of this ralloc-based new need not call delete. It's + * easier to just ralloc_free 'ctx' (or any of its ancestors). */ static void* operator new(size_t size, void *ctx) { void *node; - node = talloc_size(ctx, size); + node = ralloc_size(ctx, size); assert(node != NULL); return node; } /* If the user *does* call delete, that's OK, we will just - * talloc_free in that case. */ + * ralloc_free in that case. */ static void operator delete(void *node) { - talloc_free(node); + ralloc_free(node); } exec_node() : next(NULL), prev(NULL) @@ -289,23 +285,23 @@ struct exec_list { struct exec_node *tail_pred; #ifdef __cplusplus - /* Callers of this talloc-based new need not call delete. It's - * easier to just talloc_free 'ctx' (or any of its ancestors). */ + /* Callers of this ralloc-based new need not call delete. It's + * easier to just ralloc_free 'ctx' (or any of its ancestors). */ static void* operator new(size_t size, void *ctx) { void *node; - node = talloc_size(ctx, size); + node = ralloc_size(ctx, size); assert(node != NULL); return node; } /* If the user *does* call delete, that's OK, we will just - * talloc_free in that case. */ + * ralloc_free in that case. */ static void operator delete(void *node) { - talloc_free(node); + ralloc_free(node); } exec_list() diff --git a/src/glsl/loop_analysis.cpp b/src/glsl/loop_analysis.cpp index 3cf86ebaa38..9bba6a97c48 100644 --- a/src/glsl/loop_analysis.cpp +++ b/src/glsl/loop_analysis.cpp @@ -37,7 +37,7 @@ loop_state::loop_state() { this->ht = hash_table_ctor(0, hash_table_pointer_hash, hash_table_pointer_compare); - this->mem_ctx = talloc_init("loop state"); + this->mem_ctx = ralloc_context(NULL); this->loop_found = false; } @@ -45,7 +45,7 @@ loop_state::loop_state() loop_state::~loop_state() { hash_table_dtor(this->ht); - talloc_free(this->mem_ctx); + ralloc_free(this->mem_ctx); } @@ -78,8 +78,8 @@ loop_variable_state::get(const ir_variable *ir) loop_variable * loop_variable_state::insert(ir_variable *var) { - void *mem_ctx = talloc_parent(this); - loop_variable *lv = talloc_zero(mem_ctx, loop_variable); + void *mem_ctx = ralloc_parent(this); + loop_variable *lv = rzalloc(mem_ctx, loop_variable); lv->var = var; @@ -93,8 +93,8 @@ loop_variable_state::insert(ir_variable *var) loop_terminator * loop_variable_state::insert(ir_if *if_stmt) { - void *mem_ctx = talloc_parent(this); - loop_terminator *t = talloc_zero(mem_ctx, loop_terminator); + void *mem_ctx = ralloc_parent(this); + loop_terminator *t = rzalloc(mem_ctx, loop_terminator); t->ir = if_stmt; this->terminators.push_tail(t); @@ -450,7 +450,7 @@ get_basic_induction_increment(ir_assignment *ir, hash_table *var_hash) } if ((inc != NULL) && (rhs->operation == ir_binop_sub)) { - void *mem_ctx = talloc_parent(ir); + void *mem_ctx = ralloc_parent(ir); inc = new(mem_ctx) ir_expression(ir_unop_neg, inc->type, diff --git a/src/glsl/loop_controls.cpp b/src/glsl/loop_controls.cpp index b528810f40d..9acbadc50ea 100644 --- a/src/glsl/loop_controls.cpp +++ b/src/glsl/loop_controls.cpp @@ -21,7 +21,7 @@ * DEALINGS IN THE SOFTWARE. */ -#include <climits> +#include <limits.h> #include "main/compiler.h" #include "glsl_types.h" #include "loop_analysis.h" @@ -88,7 +88,7 @@ calculate_iterations(ir_rvalue *from, ir_rvalue *to, ir_rvalue *increment, if (from == NULL || to == NULL || increment == NULL) return -1; - void *mem_ctx = talloc_init("%s", __func__); + void *mem_ctx = ralloc_context(NULL); ir_expression *const sub = new(mem_ctx) ir_expression(ir_binop_sub, from->type, to, from); @@ -147,7 +147,7 @@ calculate_iterations(ir_rvalue *from, ir_rvalue *to, ir_rvalue *increment, } } - talloc_free(mem_ctx); + ralloc_free(mem_ctx); return (valid_loop) ? iter_value : -1; } diff --git a/src/glsl/loop_unroll.cpp b/src/glsl/loop_unroll.cpp index 46000524ba1..5b84e101477 100644 --- a/src/glsl/loop_unroll.cpp +++ b/src/glsl/loop_unroll.cpp @@ -150,7 +150,7 @@ loop_unroll_visitor::visit_leave(ir_loop *ir) */ break_ir->remove(); - void *const mem_ctx = talloc_parent(ir); + void *const mem_ctx = ralloc_parent(ir); ir_instruction *ir_to_replace = ir; for (int i = 0; i < iterations; i++) { @@ -182,7 +182,7 @@ loop_unroll_visitor::visit_leave(ir_loop *ir) } } - void *const mem_ctx = talloc_parent(ir); + void *const mem_ctx = ralloc_parent(ir); for (int i = 0; i < iterations; i++) { exec_list copy_list; diff --git a/src/glsl/lower_discard.cpp b/src/glsl/lower_discard.cpp index b95313df8c8..cafd2dd3b44 100644 --- a/src/glsl/lower_discard.cpp +++ b/src/glsl/lower_discard.cpp @@ -170,7 +170,7 @@ lower_discard_visitor::visit_leave(ir_if *ir) if (then_discard == NULL && else_discard == NULL) return visit_continue; - void *mem_ctx = talloc_parent(ir); + void *mem_ctx = ralloc_parent(ir); ir_variable *temp = new(mem_ctx) ir_variable(glsl_type::bool_type, "discard_cond_temp", diff --git a/src/glsl/lower_if_to_cond_assign.cpp b/src/glsl/lower_if_to_cond_assign.cpp index 40ffc45c86c..e3a1065d996 100644 --- a/src/glsl/lower_if_to_cond_assign.cpp +++ b/src/glsl/lower_if_to_cond_assign.cpp @@ -171,7 +171,7 @@ ir_if_to_cond_assign_visitor::visit_leave(ir_if *ir) if (found_control_flow) return visit_continue; - void *mem_ctx = talloc_parent(ir); + void *mem_ctx = ralloc_parent(ir); /* Store the condition to a variable so the assignment conditions are * simpler. diff --git a/src/glsl/lower_mat_op_to_vec.cpp b/src/glsl/lower_mat_op_to_vec.cpp index 7065fdec35f..8cbbfa713c9 100644 --- a/src/glsl/lower_mat_op_to_vec.cpp +++ b/src/glsl/lower_mat_op_to_vec.cpp @@ -368,7 +368,7 @@ ir_mat_op_to_vec_visitor::visit_leave(ir_assignment *orig_assign) assert(orig_expr->get_num_operands() <= 2); - mem_ctx = talloc_parent(orig_assign); + mem_ctx = ralloc_parent(orig_assign); ir_dereference_variable *lhs_deref = orig_assign->lhs->as_dereference_variable(); diff --git a/src/glsl/lower_noise.cpp b/src/glsl/lower_noise.cpp index cb32d283486..85f59b675e0 100644 --- a/src/glsl/lower_noise.cpp +++ b/src/glsl/lower_noise.cpp @@ -51,7 +51,7 @@ public: * that implements noise. No hardware has a noise instruction. */ if (expr->operation == ir_unop_noise) { - *rvalue = ir_constant::zero(talloc_parent(expr), expr->type); + *rvalue = ir_constant::zero(ralloc_parent(expr), expr->type); this->progress = true; } } diff --git a/src/glsl/lower_texture_projection.cpp b/src/glsl/lower_texture_projection.cpp index 1fd26a7a2b5..6e3aaecceee 100644 --- a/src/glsl/lower_texture_projection.cpp +++ b/src/glsl/lower_texture_projection.cpp @@ -55,7 +55,7 @@ lower_texture_projection_visitor::visit_leave(ir_texture *ir) if (!ir->projector) return visit_continue; - void *mem_ctx = talloc_parent(ir); + void *mem_ctx = ralloc_parent(ir); ir_variable *var = new(mem_ctx) ir_variable(ir->projector->type, "projector", ir_var_auto); diff --git a/src/glsl/lower_variable_index_to_cond_assign.cpp b/src/glsl/lower_variable_index_to_cond_assign.cpp index 7b4e4ad07cb..8eb1612f0a0 100644 --- a/src/glsl/lower_variable_index_to_cond_assign.cpp +++ b/src/glsl/lower_variable_index_to_cond_assign.cpp @@ -54,7 +54,7 @@ struct assignment_generator /* Just clone the rest of the deref chain when trying to get at the * underlying variable. */ - void *mem_ctx = talloc_parent(base_ir); + void *mem_ctx = ralloc_parent(base_ir); ir_dereference *element = new(mem_ctx) ir_dereference_array(this->array->clone(mem_ctx, NULL), new(mem_ctx) ir_constant(i)); @@ -91,7 +91,7 @@ struct switch_generator linear_sequence_max_length(linear_sequence_max_length), condition_components(condition_components) { - this->mem_ctx = talloc_parent(index); + this->mem_ctx = ralloc_parent(index); } void linear_sequence(unsigned begin, unsigned end, exec_list *list) @@ -255,6 +255,7 @@ public: case ir_var_uniform: return this->lower_uniforms; case ir_var_in: + case ir_var_const_in: return (var->location == -1) ? this->lower_temps : this->lower_inputs; case ir_var_out: return (var->location == -1) ? this->lower_temps : this->lower_outputs; @@ -275,7 +276,7 @@ public: ? orig_deref->array->type->length : orig_deref->array->type->matrix_columns; - void *const mem_ctx = talloc_parent(base_ir); + void *const mem_ctx = ralloc_parent(base_ir); /* Temporary storage for either the result of the dereference of * the array, or the RHS that's being assigned into the @@ -342,7 +343,7 @@ public: if (needs_lowering(orig_deref)) { ir_variable* var = convert_dereference_array(orig_deref, 0); assert(var); - *pir = new(talloc_parent(base_ir)) ir_dereference_variable(var); + *pir = new(ralloc_parent(base_ir)) ir_dereference_variable(var); this->progress = true; } } diff --git a/src/glsl/lower_vec_index_to_cond_assign.cpp b/src/glsl/lower_vec_index_to_cond_assign.cpp index f8011a16e5b..3c4d93201d2 100644 --- a/src/glsl/lower_vec_index_to_cond_assign.cpp +++ b/src/glsl/lower_vec_index_to_cond_assign.cpp @@ -82,7 +82,7 @@ ir_vec_index_to_cond_assign_visitor::convert_vec_index_to_cond_assign(ir_rvalue orig_deref->array->type->is_array()) return ir; - void *mem_ctx = talloc_parent(ir); + void *mem_ctx = ralloc_parent(ir); assert(orig_deref->array_index->type->base_type == GLSL_TYPE_INT); @@ -167,7 +167,7 @@ ir_vec_index_to_cond_assign_visitor::visit_leave(ir_assignment *ir) orig_deref->array->type->is_array()) return visit_continue; - void *mem_ctx = talloc_parent(ir); + void *mem_ctx = ralloc_parent(ir); assert(orig_deref->array_index->type->base_type == GLSL_TYPE_INT); diff --git a/src/glsl/lower_vec_index_to_swizzle.cpp b/src/glsl/lower_vec_index_to_swizzle.cpp index 9ae43c0db17..c7630c28a83 100644 --- a/src/glsl/lower_vec_index_to_swizzle.cpp +++ b/src/glsl/lower_vec_index_to_swizzle.cpp @@ -74,7 +74,7 @@ ir_vec_index_to_swizzle_visitor::convert_vec_index_to_swizzle(ir_rvalue *ir) if (!ir_constant) return ir; - void *ctx = talloc_parent(ir); + void *ctx = ralloc_parent(ir); this->progress = true; return new(ctx) ir_swizzle(deref->array, ir_constant->value.i[0], 0, 0, 0, 1); diff --git a/src/glsl/lower_vector.cpp b/src/glsl/lower_vector.cpp index 93c37638bbd..57963a121ad 100644 --- a/src/glsl/lower_vector.cpp +++ b/src/glsl/lower_vector.cpp @@ -125,7 +125,7 @@ lower_vector_visitor::handle_rvalue(ir_rvalue **rvalue) if (this->dont_lower_swz && is_extended_swizzle(expr)) return; - /* FINISHME: Is this the right thing to use for the talloc context? + /* FINISHME: Is this the right thing to use for the ralloc context? */ void *const mem_ctx = expr; diff --git a/src/glsl/main.cpp b/src/glsl/main.cpp index 9b041aafe42..096da93dcef 100644 --- a/src/glsl/main.cpp +++ b/src/glsl/main.cpp @@ -20,8 +20,6 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -#include <cstdlib> -#include <cstdio> #include <getopt.h> #include "ast.h" @@ -56,7 +54,7 @@ _mesa_new_shader(struct gl_context *ctx, GLuint name, GLenum type) (void) ctx; assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER); - shader = talloc_zero(NULL, struct gl_shader); + shader = rzalloc(NULL, struct gl_shader); if (shader) { shader->Type = type; shader->Name = name; @@ -72,12 +70,18 @@ initialize_context(struct gl_context *ctx, gl_api api) ctx->API = api; + ctx->Extensions.ARB_ES2_compatibility = GL_TRUE; ctx->Extensions.ARB_draw_buffers = GL_TRUE; ctx->Extensions.ARB_draw_instanced = GL_TRUE; ctx->Extensions.ARB_fragment_coord_conventions = GL_TRUE; ctx->Extensions.EXT_texture_array = GL_TRUE; ctx->Extensions.NV_texture_rectangle = GL_TRUE; + /* GLSL 1.30 isn't fully supported, but we need to advertise 1.30 so that + * the built-in functions for 1.30 can be built. + */ + ctx->Const.GLSLVersion = 130; + /* 1.10 minimums. */ ctx->Const.MaxLights = 8; ctx->Const.MaxClipPlanes = 8; @@ -101,7 +105,7 @@ initialize_context(struct gl_context *ctx, gl_api api) ctx->Driver.NewShader = _mesa_new_shader; } -/* Returned string will have 'ctx' as its talloc owner. */ +/* Returned string will have 'ctx' as its ralloc owner. */ static char * load_text_file(void *ctx, const char *file_name) { @@ -118,7 +122,7 @@ load_text_file(void *ctx, const char *file_name) size = ftell(fp); fseek(fp, 0L, SEEK_SET); - text = (char *) talloc_size(ctx, size + 1); + text = (char *) ralloc_size(ctx, size + 1); if (text != NULL) { do { size_t bytes = fread(text + total_read, @@ -236,14 +240,14 @@ compile_shader(struct gl_context *ctx, struct gl_shader *shader) shader->num_builtins_to_link = state->num_builtins_to_link; if (shader->InfoLog) - talloc_free(shader->InfoLog); + ralloc_free(shader->InfoLog); shader->InfoLog = state->info_log; /* Retain any live IR, but trash the rest. */ reparent_ir(shader->ir, shader); - talloc_free(state); + ralloc_free(state); return; } @@ -268,16 +272,16 @@ main(int argc, char **argv) struct gl_shader_program *whole_program; - whole_program = talloc_zero (NULL, struct gl_shader_program); + whole_program = rzalloc (NULL, struct gl_shader_program); assert(whole_program != NULL); for (/* empty */; argc > optind; optind++) { - whole_program->Shaders = (struct gl_shader **) - talloc_realloc(whole_program, whole_program->Shaders, - struct gl_shader *, whole_program->NumShaders + 1); + whole_program->Shaders = + reralloc(whole_program, whole_program->Shaders, + struct gl_shader *, whole_program->NumShaders + 1); assert(whole_program->Shaders != NULL); - struct gl_shader *shader = talloc_zero(whole_program, gl_shader); + struct gl_shader *shader = rzalloc(whole_program, gl_shader); whole_program->Shaders[whole_program->NumShaders] = shader; whole_program->NumShaders++; @@ -320,9 +324,9 @@ main(int argc, char **argv) } for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) - talloc_free(whole_program->_LinkedShaders[i]); + ralloc_free(whole_program->_LinkedShaders[i]); - talloc_free(whole_program); + ralloc_free(whole_program); _mesa_glsl_release_types(); _mesa_glsl_release_functions(); diff --git a/src/glsl/opt_algebraic.cpp b/src/glsl/opt_algebraic.cpp index 20f6159f0e6..cade9611dbb 100644 --- a/src/glsl/opt_algebraic.cpp +++ b/src/glsl/opt_algebraic.cpp @@ -191,7 +191,7 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) } if (this->mem_ctx == NULL) - this->mem_ctx = talloc_parent(ir); + this->mem_ctx = ralloc_parent(ir); switch (ir->operation) { case ir_unop_logic_not: { diff --git a/src/glsl/opt_constant_folding.cpp b/src/glsl/opt_constant_folding.cpp index d69ca75fe03..599b21525de 100644 --- a/src/glsl/opt_constant_folding.cpp +++ b/src/glsl/opt_constant_folding.cpp @@ -122,7 +122,7 @@ ir_constant_folding_visitor::visit_enter(ir_call *ir) ir_rvalue *param_rval = (ir_rvalue *)iter.get(); ir_variable *sig_param = (ir_variable *)sig_iter.get(); - if (sig_param->mode == ir_var_in) { + if (sig_param->mode == ir_var_in || sig_param->mode == ir_var_const_in) { ir_rvalue *new_param = param_rval; handle_rvalue(&new_param); diff --git a/src/glsl/opt_constant_propagation.cpp b/src/glsl/opt_constant_propagation.cpp index 6719fc81863..4425f421193 100644 --- a/src/glsl/opt_constant_propagation.cpp +++ b/src/glsl/opt_constant_propagation.cpp @@ -78,13 +78,13 @@ public: ir_constant_propagation_visitor() { progress = false; - mem_ctx = talloc_new(0); + mem_ctx = ralloc_context(0); this->acp = new(mem_ctx) exec_list; this->kills = new(mem_ctx) exec_list; } ~ir_constant_propagation_visitor() { - talloc_free(mem_ctx); + ralloc_free(mem_ctx); } virtual ir_visitor_status visit_enter(class ir_loop *); @@ -195,7 +195,7 @@ ir_constant_propagation_visitor::handle_rvalue(ir_rvalue **rvalue) } } - *rvalue = new(talloc_parent(deref)) ir_constant(type, &data); + *rvalue = new(ralloc_parent(deref)) ir_constant(type, &data); this->progress = true; } @@ -398,11 +398,8 @@ ir_constant_propagation_visitor::add_constant(ir_assignment *ir) { acp_entry *entry; - if (ir->condition) { - ir_constant *condition = ir->condition->as_constant(); - if (!condition || !condition->value.b[0]) - return; - } + if (ir->condition) + return; if (!ir->write_mask) return; diff --git a/src/glsl/opt_constant_variable.cpp b/src/glsl/opt_constant_variable.cpp index 8068d0c1435..3fa7c3badc8 100644 --- a/src/glsl/opt_constant_variable.cpp +++ b/src/glsl/opt_constant_variable.cpp @@ -104,11 +104,8 @@ ir_constant_variable_visitor::visit_enter(ir_assignment *ir) /* OK, now find if we actually have all the right conditions for * this to be a constant value assigned to the var. */ - if (ir->condition) { - constval = ir->condition->constant_expression_value(); - if (!constval || !constval->value.b[0]) - return visit_continue; - } + if (ir->condition) + return visit_continue; ir_variable *var = ir->whole_variable_written(); if (!var) diff --git a/src/glsl/opt_copy_propagation.cpp b/src/glsl/opt_copy_propagation.cpp index 8d07fefbfd0..efa3afda35a 100644 --- a/src/glsl/opt_copy_propagation.cpp +++ b/src/glsl/opt_copy_propagation.cpp @@ -71,13 +71,13 @@ public: ir_copy_propagation_visitor() { progress = false; - mem_ctx = talloc_new(0); + mem_ctx = ralloc_context(0); this->acp = new(mem_ctx) exec_list; this->kills = new(mem_ctx) exec_list; } ~ir_copy_propagation_visitor() { - talloc_free(mem_ctx); + ralloc_free(mem_ctx); } virtual ir_visitor_status visit(class ir_dereference_variable *); @@ -191,7 +191,7 @@ ir_copy_propagation_visitor::visit_enter(ir_call *ir) sig_param_iter.next(); } - /* Since we're unlinked, we don't (necssarily) know the side effects of + /* Since we're unlinked, we don't (necessarily) know the side effects of * this call. So kill all copies. */ acp->make_empty(); @@ -309,11 +309,8 @@ ir_copy_propagation_visitor::add_copy(ir_assignment *ir) { acp_entry *entry; - if (ir->condition) { - ir_constant *condition = ir->condition->as_constant(); - if (!condition || !condition->value.b[0]) - return; - } + if (ir->condition) + return; ir_variable *lhs_var = ir->whole_variable_written(); ir_variable *rhs_var = ir->rhs->whole_variable_referenced(); @@ -325,7 +322,7 @@ ir_copy_propagation_visitor::add_copy(ir_assignment *ir) * calling us. Just flag it to not execute, and someone else * will clean up the mess. */ - ir->condition = new(talloc_parent(ir)) ir_constant(false); + ir->condition = new(ralloc_parent(ir)) ir_constant(false); this->progress = true; } else { entry = new(this->mem_ctx) acp_entry(lhs_var, rhs_var); diff --git a/src/glsl/opt_copy_propagation_elements.cpp b/src/glsl/opt_copy_propagation_elements.cpp new file mode 100644 index 00000000000..8541d9a8ee1 --- /dev/null +++ b/src/glsl/opt_copy_propagation_elements.cpp @@ -0,0 +1,458 @@ +/* + * Copyright © 2010 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * \file opt_copy_propagation_elements.cpp + * + * Replaces usage of recently-copied components of variables with the + * previous copy of the variable. + * + * This pass can be compared with opt_copy_propagation, which operands + * on arbitrary whole-variable copies. However, in order to handle + * the copy propagation of swizzled variables or writemasked writes, + * we want to track things on a channel-wise basis. I found that + * trying to mix the swizzled/writemasked support here with the + * whole-variable stuff in opt_copy_propagation.cpp just made a mess, + * so this is separate despite the ACP handling being somewhat + * similar. + * + * This should reduce the number of MOV instructions in the generated + * programs unless copy propagation is also done on the LIR, and may + * help anyway by triggering other optimizations that live in the HIR. + */ + +#include "ir.h" +#include "ir_rvalue_visitor.h" +#include "ir_basic_block.h" +#include "ir_optimization.h" +#include "glsl_types.h" + +static bool debug = false; + +class acp_entry : public exec_node +{ +public: + acp_entry(ir_variable *lhs, ir_variable *rhs, int write_mask, int swizzle[4]) + { + this->lhs = lhs; + this->rhs = rhs; + this->write_mask = write_mask; + memcpy(this->swizzle, swizzle, sizeof(this->swizzle)); + } + + acp_entry(acp_entry *a) + { + this->lhs = a->lhs; + this->rhs = a->rhs; + this->write_mask = a->write_mask; + memcpy(this->swizzle, a->swizzle, sizeof(this->swizzle)); + } + + ir_variable *lhs; + ir_variable *rhs; + unsigned int write_mask; + int swizzle[4]; +}; + + +class kill_entry : public exec_node +{ +public: + kill_entry(ir_variable *var, int write_mask) + { + this->var = var; + this->write_mask = write_mask; + } + + ir_variable *var; + unsigned int write_mask; +}; + +class ir_copy_propagation_elements_visitor : public ir_rvalue_visitor { +public: + ir_copy_propagation_elements_visitor() + { + this->progress = false; + this->mem_ctx = ralloc_context(NULL); + this->shader_mem_ctx = NULL; + this->acp = new(mem_ctx) exec_list; + this->kills = new(mem_ctx) exec_list; + } + ~ir_copy_propagation_elements_visitor() + { + ralloc_free(mem_ctx); + } + + virtual ir_visitor_status visit_enter(class ir_loop *); + virtual ir_visitor_status visit_enter(class ir_function_signature *); + virtual ir_visitor_status visit_leave(class ir_assignment *); + virtual ir_visitor_status visit_enter(class ir_call *); + virtual ir_visitor_status visit_enter(class ir_if *); + + void handle_rvalue(ir_rvalue **rvalue); + + void add_copy(ir_assignment *ir); + void kill(kill_entry *k); + void handle_if_block(exec_list *instructions); + + /** List of acp_entry: The available copies to propagate */ + exec_list *acp; + /** + * List of kill_entry: The variables whose values were killed in this + * block. + */ + exec_list *kills; + + bool progress; + + bool killed_all; + + /* Context for our local data structures. */ + void *mem_ctx; + /* Context for allocating new shader nodes. */ + void *shader_mem_ctx; +}; + +ir_visitor_status +ir_copy_propagation_elements_visitor::visit_enter(ir_function_signature *ir) +{ + /* Treat entry into a function signature as a completely separate + * block. Any instructions at global scope will be shuffled into + * main() at link time, so they're irrelevant to us. + */ + exec_list *orig_acp = this->acp; + exec_list *orig_kills = this->kills; + bool orig_killed_all = this->killed_all; + + this->acp = new(mem_ctx) exec_list; + this->kills = new(mem_ctx) exec_list; + this->killed_all = false; + + visit_list_elements(this, &ir->body); + + this->kills = orig_kills; + this->acp = orig_acp; + this->killed_all = orig_killed_all; + + return visit_continue_with_parent; +} + +ir_visitor_status +ir_copy_propagation_elements_visitor::visit_leave(ir_assignment *ir) +{ + ir_dereference_variable *lhs = ir->lhs->as_dereference_variable(); + + if (lhs && (lhs->type->is_scalar() || lhs->type->is_vector())) { + kill_entry *k = new(mem_ctx) kill_entry(lhs->var, ir->write_mask); + kill(k); + } + + add_copy(ir); + + return visit_continue; +} + +/** + * Replaces dereferences of ACP RHS variables with ACP LHS variables. + * + * This is where the actual copy propagation occurs. Note that the + * rewriting of ir_dereference means that the ir_dereference instance + * must not be shared by multiple IR operations! + */ +void +ir_copy_propagation_elements_visitor::handle_rvalue(ir_rvalue **ir) +{ + int swizzle_chan[4]; + ir_dereference_variable *deref_var; + ir_variable *source[4] = {NULL, NULL, NULL, NULL}; + int source_chan[4]; + int chans; + + if (!*ir) + return; + + ir_swizzle *swizzle = (*ir)->as_swizzle(); + if (swizzle) { + deref_var = swizzle->val->as_dereference_variable(); + if (!deref_var) + return; + + swizzle_chan[0] = swizzle->mask.x; + swizzle_chan[1] = swizzle->mask.y; + swizzle_chan[2] = swizzle->mask.z; + swizzle_chan[3] = swizzle->mask.w; + chans = swizzle->type->vector_elements; + } else { + deref_var = (*ir)->as_dereference_variable(); + if (!deref_var) + return; + + swizzle_chan[0] = 0; + swizzle_chan[1] = 1; + swizzle_chan[2] = 2; + swizzle_chan[3] = 3; + chans = deref_var->type->vector_elements; + } + + if (this->in_assignee) + return; + + ir_variable *var = deref_var->var; + + /* Try to find ACP entries covering swizzle_chan[], hoping they're + * the same source variable. + */ + foreach_iter(exec_list_iterator, iter, *this->acp) { + acp_entry *entry = (acp_entry *)iter.get(); + + if (var == entry->lhs) { + for (int c = 0; c < chans; c++) { + if (entry->write_mask & (1 << swizzle_chan[c])) { + source[c] = entry->rhs; + source_chan[c] = entry->swizzle[swizzle_chan[c]]; + } + } + } + } + + /* Make sure all channels are copying from the same source variable. */ + if (!source[0]) + return; + for (int c = 1; c < chans; c++) { + if (source[c] != source[0]) + return; + } + + if (!shader_mem_ctx) + shader_mem_ctx = ralloc_parent(deref_var); + + if (debug) { + printf("Copy propagation from:\n"); + (*ir)->print(); + } + + deref_var = new(shader_mem_ctx) ir_dereference_variable(source[0]); + *ir = new(shader_mem_ctx) ir_swizzle(deref_var, + source_chan[0], + source_chan[1], + source_chan[2], + source_chan[3], + chans); + + if (debug) { + printf("to:\n"); + (*ir)->print(); + printf("\n"); + } +} + + +ir_visitor_status +ir_copy_propagation_elements_visitor::visit_enter(ir_call *ir) +{ + /* Do copy propagation on call parameters, but skip any out params */ + exec_list_iterator sig_param_iter = ir->get_callee()->parameters.iterator(); + foreach_iter(exec_list_iterator, iter, ir->actual_parameters) { + ir_variable *sig_param = (ir_variable *)sig_param_iter.get(); + ir_instruction *ir = (ir_instruction *)iter.get(); + if (sig_param->mode != ir_var_out && sig_param->mode != ir_var_inout) { + ir->accept(this); + } + sig_param_iter.next(); + } + + /* Since we're unlinked, we don't (necessarily) know the side effects of + * this call. So kill all copies. + */ + acp->make_empty(); + this->killed_all = true; + + return visit_continue_with_parent; +} + +void +ir_copy_propagation_elements_visitor::handle_if_block(exec_list *instructions) +{ + exec_list *orig_acp = this->acp; + exec_list *orig_kills = this->kills; + bool orig_killed_all = this->killed_all; + + this->acp = new(mem_ctx) exec_list; + this->kills = new(mem_ctx) exec_list; + this->killed_all = false; + + /* Populate the initial acp with a copy of the original */ + foreach_iter(exec_list_iterator, iter, *orig_acp) { + acp_entry *a = (acp_entry *)iter.get(); + this->acp->push_tail(new(this->mem_ctx) acp_entry(a)); + } + + visit_list_elements(this, instructions); + + if (this->killed_all) { + orig_acp->make_empty(); + } + + exec_list *new_kills = this->kills; + this->kills = orig_kills; + this->acp = orig_acp; + this->killed_all = this->killed_all || orig_killed_all; + + /* Move the new kills into the parent block's list, removing them + * from the parent's ACP list in the process. + */ + foreach_list_safe(node, new_kills) { + kill_entry *k = (kill_entry *)node; + kill(k); + } +} + +ir_visitor_status +ir_copy_propagation_elements_visitor::visit_enter(ir_if *ir) +{ + ir->condition->accept(this); + + handle_if_block(&ir->then_instructions); + handle_if_block(&ir->else_instructions); + + /* handle_if_block() already descended into the children. */ + return visit_continue_with_parent; +} + +ir_visitor_status +ir_copy_propagation_elements_visitor::visit_enter(ir_loop *ir) +{ + exec_list *orig_acp = this->acp; + exec_list *orig_kills = this->kills; + bool orig_killed_all = this->killed_all; + + /* FINISHME: For now, the initial acp for loops is totally empty. + * We could go through once, then go through again with the acp + * cloned minus the killed entries after the first run through. + */ + this->acp = new(mem_ctx) exec_list; + this->kills = new(mem_ctx) exec_list; + this->killed_all = false; + + visit_list_elements(this, &ir->body_instructions); + + if (this->killed_all) { + orig_acp->make_empty(); + } + + exec_list *new_kills = this->kills; + this->kills = orig_kills; + this->acp = orig_acp; + this->killed_all = this->killed_all || orig_killed_all; + + foreach_list_safe(node, new_kills) { + kill_entry *k = (kill_entry *)node; + kill(k); + } + + /* already descended into the children. */ + return visit_continue_with_parent; +} + +/* Remove any entries currently in the ACP for this kill. */ +void +ir_copy_propagation_elements_visitor::kill(kill_entry *k) +{ + foreach_list_safe(node, acp) { + acp_entry *entry = (acp_entry *)node; + + if (entry->lhs == k->var) { + entry->write_mask = entry->write_mask & ~k->write_mask; + if (entry->write_mask == 0) + entry->remove(); + } + if (entry->rhs == k->var) { + entry->remove(); + } + } + + /* If we were on a list, remove ourselves before inserting */ + if (k->next) + k->remove(); + + this->kills->push_tail(k); +} + +/** + * Adds directly-copied channels between vector variables to the available + * copy propagation list. + */ +void +ir_copy_propagation_elements_visitor::add_copy(ir_assignment *ir) +{ + acp_entry *entry; + int orig_swizzle[4] = {0, 1, 2, 3}; + int swizzle[4]; + + if (ir->condition) + return; + + ir_dereference_variable *lhs = ir->lhs->as_dereference_variable(); + if (!lhs || !(lhs->type->is_scalar() || lhs->type->is_vector())) + return; + + ir_dereference_variable *rhs = ir->rhs->as_dereference_variable(); + if (!rhs) { + ir_swizzle *swiz = ir->rhs->as_swizzle(); + if (!swiz) + return; + + rhs = swiz->val->as_dereference_variable(); + if (!rhs) + return; + + orig_swizzle[0] = swiz->mask.x; + orig_swizzle[1] = swiz->mask.y; + orig_swizzle[2] = swiz->mask.z; + orig_swizzle[3] = swiz->mask.w; + } + + /* Move the swizzle channels out to the positions they match in the + * destination. We don't want to have to rewrite the swizzle[] + * array every time we clear a bit of the write_mask. + */ + int j = 0; + for (int i = 0; i < 4; i++) { + if (ir->write_mask & (1 << i)) + swizzle[i] = orig_swizzle[j++]; + } + + entry = new(this->mem_ctx) acp_entry(lhs->var, rhs->var, ir->write_mask, + swizzle); + this->acp->push_tail(entry); +} + +bool +do_copy_propagation_elements(exec_list *instructions) +{ + ir_copy_propagation_elements_visitor v; + + visit_list_elements(&v, instructions); + + return v.progress; +} diff --git a/src/glsl/opt_dead_code_local.cpp b/src/glsl/opt_dead_code_local.cpp index 5689e7d20db..39962bd602e 100644 --- a/src/glsl/opt_dead_code_local.cpp +++ b/src/glsl/opt_dead_code_local.cpp @@ -129,15 +129,8 @@ process_assignment(void *ctx, ir_assignment *ir, exec_list *assignments) var = ir->lhs->variable_referenced(); assert(var); - bool always_assign = true; - if (ir->condition) { - ir_constant *condition = ir->condition->as_constant(); - if (!condition || !condition->value.b[0]) - always_assign = false; - } - /* Now, check if we did a whole-variable assignment. */ - if (always_assign && (ir->whole_variable_written() != NULL)) { + if (!ir->condition && (ir->whole_variable_written() != NULL)) { /* We did a whole-variable assignment. So, any instruction in * the assignment list with the same LHS is dead. */ @@ -190,7 +183,7 @@ dead_code_local_basic_block(ir_instruction *first, bool *out_progress = (bool *)data; bool progress = false; - void *ctx = talloc_new(NULL); + void *ctx = ralloc_context(NULL); /* Safe looping, since process_assignment */ for (ir = first, ir_next = (ir_instruction *)first->next;; ir = ir_next, ir_next = (ir_instruction *)ir->next) { @@ -212,7 +205,7 @@ dead_code_local_basic_block(ir_instruction *first, break; } *out_progress = progress; - talloc_free(ctx); + ralloc_free(ctx); } /** diff --git a/src/glsl/opt_dead_functions.cpp b/src/glsl/opt_dead_functions.cpp index cf91cb6d368..ceb79080a75 100644 --- a/src/glsl/opt_dead_functions.cpp +++ b/src/glsl/opt_dead_functions.cpp @@ -49,12 +49,12 @@ public: ir_dead_functions_visitor() { - this->mem_ctx = talloc_new(NULL); + this->mem_ctx = ralloc_context(NULL); } ~ir_dead_functions_visitor() { - talloc_free(this->mem_ctx); + ralloc_free(this->mem_ctx); } virtual ir_visitor_status visit_enter(ir_function_signature *); diff --git a/src/glsl/opt_function_inlining.cpp b/src/glsl/opt_function_inlining.cpp index 169fd826882..2e7831dcbdb 100644 --- a/src/glsl/opt_function_inlining.cpp +++ b/src/glsl/opt_function_inlining.cpp @@ -89,7 +89,7 @@ do_function_inlining(exec_list *instructions) static void replace_return_with_assignment(ir_instruction *ir, void *data) { - void *ctx = talloc_parent(ir); + void *ctx = ralloc_parent(ir); ir_variable *retval = (ir_variable *)data; ir_return *ret = ir->as_return(); @@ -110,7 +110,7 @@ replace_return_with_assignment(ir_instruction *ir, void *data) ir_rvalue * ir_call::generate_inline(ir_instruction *next_ir) { - void *ctx = talloc_parent(this); + void *ctx = ralloc_parent(this); ir_variable **parameters; int num_parameters; int i; @@ -165,6 +165,7 @@ ir_call::generate_inline(ir_instruction *next_ir) /* Move the actual param into our param variable if it's an 'in' type. */ if (parameters[i] && (sig_param->mode == ir_var_in || + sig_param->mode == ir_var_const_in || sig_param->mode == ir_var_inout)) { ir_assignment *assign; @@ -357,7 +358,7 @@ ir_sampler_replacement_visitor::replace_deref(ir_dereference **deref) { ir_dereference_variable *deref_var = (*deref)->as_dereference_variable(); if (deref_var && deref_var->var == this->sampler) { - *deref = this->deref->clone(talloc_parent(*deref), NULL); + *deref = this->deref->clone(ralloc_parent(*deref), NULL); } } diff --git a/src/glsl/opt_structure_splitting.cpp b/src/glsl/opt_structure_splitting.cpp index d6191002c2f..014407c0be2 100644 --- a/src/glsl/opt_structure_splitting.cpp +++ b/src/glsl/opt_structure_splitting.cpp @@ -65,7 +65,7 @@ public: ir_variable **components; - /** talloc_parent(this->var) -- the shader's talloc context. */ + /** ralloc_parent(this->var) -- the shader's ralloc context. */ void *mem_ctx; }; @@ -74,13 +74,13 @@ class ir_structure_reference_visitor : public ir_hierarchical_visitor { public: ir_structure_reference_visitor(void) { - this->mem_ctx = talloc_new(NULL); + this->mem_ctx = ralloc_context(NULL); this->variable_list.make_empty(); } ~ir_structure_reference_visitor(void) { - talloc_free(mem_ctx); + ralloc_free(mem_ctx); } virtual ir_visitor_status visit(ir_variable *); @@ -322,7 +322,7 @@ do_structure_splitting(exec_list *instructions) if (refs.variable_list.is_empty()) return false; - void *mem_ctx = talloc_new(NULL); + void *mem_ctx = ralloc_context(NULL); /* Replace the decls of the structures to be split with their split * components. @@ -331,14 +331,14 @@ do_structure_splitting(exec_list *instructions) variable_entry2 *entry = (variable_entry2 *)iter.get(); const struct glsl_type *type = entry->var->type; - entry->mem_ctx = talloc_parent(entry->var); + entry->mem_ctx = ralloc_parent(entry->var); - entry->components = talloc_array(mem_ctx, + entry->components = ralloc_array(mem_ctx, ir_variable *, type->length); for (unsigned int i = 0; i < entry->var->type->length; i++) { - const char *name = talloc_asprintf(mem_ctx, "%s_%s", + const char *name = ralloc_asprintf(mem_ctx, "%s_%s", entry->var->name, type->fields.structure[i].name); @@ -355,7 +355,7 @@ do_structure_splitting(exec_list *instructions) ir_structure_splitting_visitor split(&refs.variable_list); visit_list_elements(&split, instructions); - talloc_free(mem_ctx); + ralloc_free(mem_ctx); return true; } diff --git a/src/glsl/opt_tree_grafting.cpp b/src/glsl/opt_tree_grafting.cpp index 9917c045b1d..1ef940f9c72 100644 --- a/src/glsl/opt_tree_grafting.cpp +++ b/src/glsl/opt_tree_grafting.cpp @@ -195,7 +195,7 @@ ir_tree_grafting_visitor::visit_enter(ir_call *ir) ir_rvalue *ir = (ir_rvalue *)iter.get(); ir_rvalue *new_ir = ir; - if (sig_param->mode != ir_var_in) + if (sig_param->mode != ir_var_in && sig_param->mode != ir_var_const_in) continue; if (do_graft(&new_ir)) { @@ -245,6 +245,7 @@ ir_tree_grafting_visitor::visit_enter(ir_texture *ir) { if (do_graft(&ir->coordinate) || do_graft(&ir->projector) || + do_graft(&ir->offset) || do_graft(&ir->shadow_comparitor)) return visit_stop; diff --git a/src/glsl/ralloc.c b/src/glsl/ralloc.c new file mode 100644 index 00000000000..6a5eac6b9a3 --- /dev/null +++ b/src/glsl/ralloc.c @@ -0,0 +1,458 @@ +/* + * Copyright © 2010 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include <assert.h> +#include <stdlib.h> +#include <stdarg.h> +#include <stdio.h> +#include <string.h> +#include <stdint.h> + +#include "ralloc.h" + +#ifdef __GNUC__ +#define likely(x) __builtin_expect(!!(x),1) +#define unlikely(x) __builtin_expect(!!(x),0) +#else +#define likely(x) !!(x) +#define unlikely(x) !!(x) +#endif + +#ifndef va_copy +#ifdef __va_copy +#define va_copy(dest, src) __va_copy((dest), (src)) +#else +#define va_copy(dest, src) (dest) = (src) +#endif +#endif + +#define CANARY 0x5A1106 + +struct ralloc_header +{ + /* A canary value used to determine whether a pointer is ralloc'd. */ + unsigned canary; + + struct ralloc_header *parent; + + /* The first child (head of a linked list) */ + struct ralloc_header *child; + + /* Linked list of siblings */ + struct ralloc_header *prev; + struct ralloc_header *next; + + void (*destructor)(void *); +}; + +typedef struct ralloc_header ralloc_header; + +static void unlink_block(ralloc_header *info); +static void unsafe_free(ralloc_header *info); + +static ralloc_header * +get_header(const void *ptr) +{ + ralloc_header *info = (ralloc_header *) (((char *) ptr) - + sizeof(ralloc_header)); + assert(info->canary == CANARY); + return info; +} + +#define PTR_FROM_HEADER(info) (((char *) info) + sizeof(ralloc_header)) + +static void +add_child(ralloc_header *parent, ralloc_header *info) +{ + if (parent != NULL) { + info->parent = parent; + info->next = parent->child; + parent->child = info; + + if (info->next != NULL) + info->next->prev = info; + } +} + +void * +ralloc_context(const void *ctx) +{ + return ralloc_size(ctx, 0); +} + +void * +ralloc_size(const void *ctx, size_t size) +{ + void *block = calloc(1, size + sizeof(ralloc_header)); + + ralloc_header *info = (ralloc_header *) block; + ralloc_header *parent = ctx != NULL ? get_header(ctx) : NULL; + + add_child(parent, info); + + info->canary = CANARY; + + return PTR_FROM_HEADER(info); +} + +void * +rzalloc_size(const void *ctx, size_t size) +{ + void *ptr = ralloc_size(ctx, size); + if (likely(ptr != NULL)) + memset(ptr, 0, size); + return ptr; +} + +/* helper function - assumes ptr != NULL */ +static void * +resize(void *ptr, size_t size) +{ + ralloc_header *child, *old, *info; + + old = get_header(ptr); + info = realloc(old, size + sizeof(ralloc_header)); + + if (info == NULL) + return NULL; + + /* Update parent and sibling's links to the reallocated node. */ + if (info != old && info->parent != NULL) { + if (info->parent->child == old) + info->parent->child = info; + + if (info->prev != NULL) + info->prev->next = info; + + if (info->next != NULL) + info->next->prev = info; + } + + /* Update child->parent links for all children */ + for (child = info->child; child != NULL; child = child->next) + child->parent = info; + + return PTR_FROM_HEADER(info); +} + +void * +reralloc_size(const void *ctx, void *ptr, size_t size) +{ + if (unlikely(ptr == NULL)) + return ralloc_size(ctx, size); + + assert(ralloc_parent(ptr) == ctx); + return resize(ptr, size); +} + +void * +ralloc_array_size(const void *ctx, size_t size, unsigned count) +{ + if (count > SIZE_MAX/size) + return NULL; + + return ralloc_size(ctx, size * count); +} + +void * +rzalloc_array_size(const void *ctx, size_t size, unsigned count) +{ + if (count > SIZE_MAX/size) + return NULL; + + return rzalloc_size(ctx, size * count); +} + +void * +reralloc_array_size(const void *ctx, void *ptr, size_t size, unsigned count) +{ + if (count > SIZE_MAX/size) + return NULL; + + return reralloc_size(ctx, ptr, size * count); +} + +void +ralloc_free(void *ptr) +{ + ralloc_header *info; + + if (ptr == NULL) + return; + + info = get_header(ptr); + unlink_block(info); + unsafe_free(info); +} + +static void +unlink_block(ralloc_header *info) +{ + /* Unlink from parent & siblings */ + if (info->parent != NULL) { + if (info->parent->child == info) + info->parent->child = info->next; + + if (info->prev != NULL) + info->prev->next = info->next; + + if (info->next != NULL) + info->next->prev = info->prev; + } + info->parent = NULL; + info->prev = NULL; + info->next = NULL; +} + +static void +unsafe_free(ralloc_header *info) +{ + /* Recursively free any children...don't waste time unlinking them. */ + ralloc_header *temp; + while (info->child != NULL) { + temp = info->child; + info->child = temp->next; + unsafe_free(temp); + } + + /* Free the block itself. Call the destructor first, if any. */ + if (info->destructor != NULL) + info->destructor(PTR_FROM_HEADER(info)); + + free(info); +} + +void +ralloc_steal(const void *new_ctx, void *ptr) +{ + ralloc_header *info, *parent; + + if (unlikely(ptr == NULL)) + return; + + info = get_header(ptr); + parent = get_header(new_ctx); + + unlink_block(info); + + add_child(parent, info); +} + +void * +ralloc_parent(const void *ptr) +{ + ralloc_header *info; + + if (unlikely(ptr == NULL)) + return NULL; + + info = get_header(ptr); + return PTR_FROM_HEADER(info->parent); +} + +static void *autofree_context = NULL; + +static void +autofree(void) +{ + ralloc_free(autofree_context); +} + +void * +ralloc_autofree_context(void) +{ + if (unlikely(autofree_context == NULL)) { + autofree_context = ralloc_context(NULL); + atexit(autofree); + } + return autofree_context; +} + +void +ralloc_set_destructor(const void *ptr, void(*destructor)(void *)) +{ + ralloc_header *info = get_header(ptr); + info->destructor = destructor; +} + +char * +ralloc_strdup(const void *ctx, const char *str) +{ + size_t n; + char *ptr; + + if (unlikely(str == NULL)) + return NULL; + + n = strlen(str); + ptr = ralloc_array(ctx, char, n + 1); + memcpy(ptr, str, n); + ptr[n] = '\0'; + return ptr; +} + +char * +ralloc_strndup(const void *ctx, const char *str, size_t max) +{ + size_t n; + char *ptr; + + if (unlikely(str == NULL)) + return NULL; + + n = strlen(str); + if (n > max) + n = max; + + ptr = ralloc_array(ctx, char, n + 1); + memcpy(ptr, str, n); + ptr[n] = '\0'; + return ptr; +} + +/* helper routine for strcat/strncat - n is the exact amount to copy */ +static bool +cat(char **dest, const char *str, size_t n) +{ + char *both; + size_t existing_length; + assert(dest != NULL && *dest != NULL); + + existing_length = strlen(*dest); + both = resize(*dest, existing_length + n + 1); + if (unlikely(both == NULL)) + return false; + + memcpy(both + existing_length, str, n); + both[existing_length + n] = '\0'; + + *dest = both; + return true; +} + + +bool +ralloc_strcat(char **dest, const char *str) +{ + return cat(dest, str, strlen(str)); +} + +bool +ralloc_strncat(char **dest, const char *str, size_t n) +{ + /* Clamp n to the string length */ + size_t str_length = strlen(str); + if (str_length < n) + n = str_length; + + return cat(dest, str, n); +} + +char * +ralloc_asprintf(const void *ctx, const char *fmt, ...) +{ + char *ptr; + va_list args; + va_start(args, fmt); + ptr = ralloc_vasprintf(ctx, fmt, args); + va_end(args); + return ptr; +} + +/* Return the length of the string that would be generated by a printf-style + * format and argument list, not including the \0 byte. + */ +static size_t +printf_length(const char *fmt, va_list untouched_args) +{ + int size; + char junk; + + /* Make a copy of the va_list so the original caller can still use it */ + va_list args; + va_copy(args, untouched_args); + +#ifdef _MSC_VER + /* We need to use _vcsprintf to calculate the size as vsnprintf returns -1 + * if the number of characters to write is greater than count. + */ + size = _vscprintf(fmt, args); + (void)junk; +#else + size = vsnprintf(&junk, 1, fmt, args); +#endif + assert(size >= 0); + + va_end(args); + + return size; +} + +char * +ralloc_vasprintf(const void *ctx, const char *fmt, va_list args) +{ + size_t size = printf_length(fmt, args) + 1; + + char *ptr = ralloc_size(ctx, size); + if (ptr != NULL) + vsnprintf(ptr, size, fmt, args); + + return ptr; +} + +bool +ralloc_asprintf_append(char **str, const char *fmt, ...) +{ + bool success; + va_list args; + va_start(args, fmt); + success = ralloc_vasprintf_append(str, fmt, args); + va_end(args); + return success; +} + +bool +ralloc_vasprintf_append(char **str, const char *fmt, va_list args) +{ + size_t existing_length, new_length; + char *ptr; + + assert(str != NULL); + + if (unlikely(*str == NULL)) { + // Assuming a NULL context is probably bad, but it's expected behavior. + *str = ralloc_vasprintf(NULL, fmt, args); + return true; + } + + existing_length = strlen(*str); + new_length = printf_length(fmt, args); + + ptr = resize(*str, existing_length + new_length + 1); + if (unlikely(ptr == NULL)) + return false; + + vsnprintf(ptr + existing_length, new_length + 1, fmt, args); + *str = ptr; + return true; +} diff --git a/src/glsl/ralloc.h b/src/glsl/ralloc.h new file mode 100644 index 00000000000..d5338152f10 --- /dev/null +++ b/src/glsl/ralloc.h @@ -0,0 +1,345 @@ +/* + * Copyright © 2010 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * \file ralloc.h + * + * ralloc: a recursive memory allocator + * + * The ralloc memory allocator creates a hierarchy of allocated + * objects. Every allocation is in reference to some parent, and + * every allocated object can in turn be used as the parent of a + * subsequent allocation. This allows for extremely convenient + * discarding of an entire tree/sub-tree of allocations by calling + * ralloc_free on any particular object to free it and all of its + * children. + * + * The conceptual working of ralloc was directly inspired by Andrew + * Tridgell's talloc, but ralloc is an independent implementation + * released under the MIT license and tuned for Mesa. + * + * The talloc implementation is available under the GNU Lesser + * General Public License (GNU LGPL), version 3 or later. It is + * more sophisticated than ralloc in that it includes reference + * counting and debugging features. See: http://talloc.samba.org/ + */ + +#ifndef RALLOC_H +#define RALLOC_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stddef.h> +#include <stdarg.h> +#include <stdbool.h> + +/** + * \def ralloc(ctx, type) + * Allocate a new object chained off of the given context. + * + * This is equivalent to: + * \code + * ((type *) ralloc_size(ctx, sizeof(type)) + * \endcode + */ +#define ralloc(ctx, type) ((type *) ralloc_size(ctx, sizeof(type))) + +/** + * \def rzalloc(ctx, type) + * Allocate a new object out of the given context and initialize it to zero. + * + * This is equivalent to: + * \code + * ((type *) rzalloc_size(ctx, sizeof(type)) + * \endcode + */ +#define rzalloc(ctx, type) ((type *) rzalloc_size(ctx, sizeof(type))) + +/** + * Allocate a new ralloc context. + * + * While any ralloc'd pointer can be used as a context, sometimes it is useful + * to simply allocate a context with no associated memory. + * + * It is equivalent to: + * \code + * ((type *) ralloc_size(ctx, 0) + * \endcode + */ +void *ralloc_context(const void *ctx); + +/** + * Allocate memory chained off of the given context. + * + * This is the core allocation routine which is used by all others. It + * simply allocates storage for \p size bytes and returns the pointer, + * similar to \c malloc. + */ +void *ralloc_size(const void *ctx, size_t size); + +/** + * Allocate zero-initialized memory chained off of the given context. + * + * This is similar to \c calloc with a size of 1. + */ +void *rzalloc_size(const void *ctx, size_t size); + +/** + * Resize a piece of ralloc-managed memory, preserving data. + * + * Similar to \c realloc. Unlike C89, passing 0 for \p size does not free the + * memory. Instead, it resizes it to a 0-byte ralloc context, just like + * calling ralloc_size(ctx, 0). This is different from talloc. + * + * \param ctx The context to use for new allocation. If \p ptr != NULL, + * it must be the same as ralloc_parent(\p ptr). + * \param ptr Pointer to the memory to be resized. May be NULL. + * \param size The amount of memory to allocate, in bytes. + */ +void *reralloc_size(const void *ctx, void *ptr, size_t size); + +/// \defgroup array Array Allocators @{ + +/** + * \def ralloc_array(ctx, type, count) + * Allocate an array of objects chained off the given context. + * + * Similar to \c calloc, but does not initialize the memory to zero. + * + * More than a convenience function, this also checks for integer overflow when + * multiplying \c sizeof(type) and \p count. This is necessary for security. + * + * This is equivalent to: + * \code + * ((type *) ralloc_array_size(ctx, sizeof(type), count) + * \endcode + */ +#define ralloc_array(ctx, type, count) \ + ((type *) ralloc_array_size(ctx, sizeof(type), count)) + +/** + * \def rzalloc_array(ctx, type, count) + * Allocate a zero-initialized array chained off the given context. + * + * Similar to \c calloc. + * + * More than a convenience function, this also checks for integer overflow when + * multiplying \c sizeof(type) and \p count. This is necessary for security. + * + * This is equivalent to: + * \code + * ((type *) rzalloc_array_size(ctx, sizeof(type), count) + * \endcode + */ +#define rzalloc_array(ctx, type, count) \ + ((type *) rzalloc_array_size(ctx, sizeof(type), count)) + +/** + * \def reralloc(ctx, ptr, type, count) + * Resize a ralloc-managed array, preserving data. + * + * Similar to \c realloc. Unlike C89, passing 0 for \p size does not free the + * memory. Instead, it resizes it to a 0-byte ralloc context, just like + * calling ralloc_size(ctx, 0). This is different from talloc. + * + * More than a convenience function, this also checks for integer overflow when + * multiplying \c sizeof(type) and \p count. This is necessary for security. + * + * \param ctx The context to use for new allocation. If \p ptr != NULL, + * it must be the same as ralloc_parent(\p ptr). + * \param ptr Pointer to the array to be resized. May be NULL. + * \param type The element type. + * \param count The number of elements to allocate. + */ +#define reralloc(ctx, ptr, type, count) \ + ((type *) reralloc_array_size(ctx, ptr, sizeof(type), count)) + +/** + * Allocate memory for an array chained off the given context. + * + * Similar to \c calloc, but does not initialize the memory to zero. + * + * More than a convenience function, this also checks for integer overflow when + * multiplying \p size and \p count. This is necessary for security. + */ +void *ralloc_array_size(const void *ctx, size_t size, unsigned count); + +/** + * Allocate a zero-initialized array chained off the given context. + * + * Similar to \c calloc. + * + * More than a convenience function, this also checks for integer overflow when + * multiplying \p size and \p count. This is necessary for security. + */ +void *rzalloc_array_size(const void *ctx, size_t size, unsigned count); + +/** + * Resize a ralloc-managed array, preserving data. + * + * Similar to \c realloc. Unlike C89, passing 0 for \p size does not free the + * memory. Instead, it resizes it to a 0-byte ralloc context, just like + * calling ralloc_size(ctx, 0). This is different from talloc. + * + * More than a convenience function, this also checks for integer overflow when + * multiplying \c sizeof(type) and \p count. This is necessary for security. + * + * \param ctx The context to use for new allocation. If \p ptr != NULL, + * it must be the same as ralloc_parent(\p ptr). + * \param ptr Pointer to the array to be resized. May be NULL. + * \param size The size of an individual element. + * \param count The number of elements to allocate. + * + * \return True unless allocation failed. + */ +void *reralloc_array_size(const void *ctx, void *ptr, size_t size, + unsigned count); +/// @} + +/** + * Free a piece of ralloc-managed memory. + * + * This will also free the memory of any children allocated this context. + */ +void ralloc_free(void *ptr); + +/** + * "Steal" memory from one context, changing it to another. + * + * This changes \p ptr's context to \p new_ctx. This is quite useful if + * memory is allocated out of a temporary context. + */ +void ralloc_steal(const void *new_ctx, void *ptr); + +/** + * Return the given pointer's ralloc context. + */ +void *ralloc_parent(const void *ptr); + +/** + * Return a context whose memory will be automatically freed at program exit. + * + * The first call to this function creates a context and registers a handler + * to free it using \c atexit. This may cause trouble if used in a library + * loaded with \c dlopen. + */ +void *ralloc_autofree_context(void); + +/** + * Set a callback to occur just before an object is freed. + */ +void ralloc_set_destructor(const void *ptr, void(*destructor)(void *)); + +/// \defgroup array String Functions @{ +/** + * Duplicate a string, allocating the memory from the given context. + */ +char *ralloc_strdup(const void *ctx, const char *str); + +/** + * Duplicate a string, allocating the memory from the given context. + * + * Like \c strndup, at most \p n characters are copied. If \p str is longer + * than \p n characters, \p n are copied, and a termining \c '\0' byte is added. + */ +char *ralloc_strndup(const void *ctx, const char *str, size_t n); + +/** + * Concatenate two strings, allocating the necessary space. + * + * This appends \p str to \p *dest, similar to \c strcat, using ralloc_resize + * to expand \p *dest to the appropriate size. \p dest will be updated to the + * new pointer unless allocation fails. + * + * The result will always be null-terminated. + * + * \return True unless allocation failed. + */ +bool ralloc_strcat(char **dest, const char *str); + +/** + * Concatenate two strings, allocating the necessary space. + * + * This appends at most \p n bytes of \p str to \p *dest, using ralloc_resize + * to expand \p *dest to the appropriate size. \p dest will be updated to the + * new pointer unless allocation fails. + * + * The result will always be null-terminated; \p str does not need to be null + * terminated if it is longer than \p n. + * + * \return True unless allocation failed. + */ +bool ralloc_strncat(char **dest, const char *str, size_t n); + +/** + * Print to a string. + * + * This is analogous to \c sprintf, but allocates enough space (using \p ctx + * as the context) for the resulting string. + * + * \return The newly allocated string. + */ +char *ralloc_asprintf (const void *ctx, const char *fmt, ...); + +/** + * Print to a string, given a va_list. + * + * This is analogous to \c vsprintf, but allocates enough space (using \p ctx + * as the context) for the resulting string. + * + * \return The newly allocated string. + */ +char *ralloc_vasprintf(const void *ctx, const char *fmt, va_list args); + +/** + * Append formatted text to the supplied string. + * + * \sa ralloc_asprintf + * \sa ralloc_strcat + * + * \p str will be updated to the new pointer unless allocation fails. + * + * \return True unless allocation failed. + */ +bool ralloc_asprintf_append (char **str, const char *fmt, ...); + +/** + * Append formatted text to the supplied string, given a va_list. + * + * \sa ralloc_vasprintf + * \sa ralloc_strcat + * + * \p str will be updated to the new pointer unless allocation fails. + * + * \return True unless allocation failed. + */ +bool ralloc_vasprintf_append(char **str, const char *fmt, va_list args); +/// @} + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif diff --git a/src/glsl/s_expression.cpp b/src/glsl/s_expression.cpp index 6edbf62e488..a922a50d3b9 100644 --- a/src/glsl/s_expression.cpp +++ b/src/glsl/s_expression.cpp @@ -22,15 +22,12 @@ * DEALINGS IN THE SOFTWARE. */ -#include <cstdio> -#include <cstdlib> -#include <cstring> #include <assert.h> #include "s_expression.h" s_symbol::s_symbol(const char *tmp, size_t n) { - this->str = talloc_strndup (this, tmp, n); + this->str = ralloc_strndup (this, tmp, n); assert(this->str != NULL); } diff --git a/src/glsl/s_expression.h b/src/glsl/s_expression.h index 795f3fccea7..c9dc676b319 100644 --- a/src/glsl/s_expression.h +++ b/src/glsl/s_expression.h @@ -57,7 +57,7 @@ public: * Read an S-Expression from the given string. * Advances the supplied pointer to just after the expression read. * - * Any allocation will be performed with 'ctx' as the talloc owner. + * Any allocation will be performed with 'ctx' as the ralloc owner. */ static s_expression *read_expression(void *ctx, const char *&src); diff --git a/src/glx/dri2_glx.c b/src/glx/dri2_glx.c index 75b1a103f01..a275ba5b9fe 100644 --- a/src/glx/dri2_glx.c +++ b/src/glx/dri2_glx.c @@ -804,11 +804,16 @@ dri2CreateScreen(int screen, struct glx_display * priv) return NULL; memset(psc, 0, sizeof *psc); - if (!glx_screen_init(&psc->base, screen, priv)) - return NULL; + psc->fd = -1; + + if (!glx_screen_init(&psc->base, screen, priv)) { + Xfree(psc); + return NULL; + } if (!DRI2Connect(priv->dpy, RootWindow(priv->dpy, screen), &driverName, &deviceName)) { + glx_screen_cleanup(&psc->base); XFree(psc); return NULL; } @@ -918,12 +923,15 @@ dri2CreateScreen(int screen, struct glx_display * priv) return &psc->base; handle_error: + if (psc->fd >= 0) + close(psc->fd); + if (psc->driver) + dlclose(psc->driver); Xfree(driverName); Xfree(deviceName); + glx_screen_cleanup(&psc->base); XFree(psc); - /* FIXME: clean up here */ - return NULL; } diff --git a/src/glx/dri_glx.c b/src/glx/dri_glx.c index 42b263c6377..ff027dc9e9c 100644 --- a/src/glx/dri_glx.c +++ b/src/glx/dri_glx.c @@ -836,26 +836,24 @@ driCreateScreen(int screen, struct glx_display *priv) return NULL; memset(psc, 0, sizeof *psc); - if (!glx_screen_init(&psc->base, screen, priv)) - return NULL; - - if (!driGetDriverName(priv->dpy, screen, &driverName)) { + if (!glx_screen_init(&psc->base, screen, priv)) { Xfree(psc); return NULL; } + if (!driGetDriverName(priv->dpy, screen, &driverName)) { + goto cleanup; + } + psc->driver = driOpenDriver(driverName); Xfree(driverName); - if (psc->driver == NULL) { - Xfree(psc); - return NULL; - } + if (psc->driver == NULL) + goto cleanup; extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS); if (extensions == NULL) { ErrorMessageF("driver exports no extensions (%s)\n", dlerror()); - Xfree(psc); - return NULL; + goto cleanup; } for (i = 0; extensions[i]; i++) { @@ -865,19 +863,14 @@ driCreateScreen(int screen, struct glx_display *priv) psc->legacy = (__DRIlegacyExtension *) extensions[i]; } - if (psc->core == NULL || psc->legacy == NULL) { - Xfree(psc); - return NULL; - } + if (psc->core == NULL || psc->legacy == NULL) + goto cleanup; pdp = (struct dri_display *) priv->driDisplay; psc->driScreen = CallCreateNewScreen(psc->base.dpy, screen, psc, pdp); - if (psc->driScreen == NULL) { - dlclose(psc->driver); - Xfree(psc); - return NULL; - } + if (psc->driScreen == NULL) + goto cleanup; extensions = psc->core->getExtensions(psc->driScreen); driBindExtensions(psc, extensions); @@ -902,6 +895,14 @@ driCreateScreen(int screen, struct glx_display *priv) psp->getSwapInterval = driGetSwapInterval; return &psc->base; + +cleanup: + if (psc->driver) + dlclose(psc->driver); + glx_screen_cleanup(&psc->base); + Xfree(psc); + + return NULL; } /* Called from __glXFreeDisplayPrivate. diff --git a/src/glx/drisw_glx.c b/src/glx/drisw_glx.c index 237ce176176..5c7f40cdffa 100644 --- a/src/glx/drisw_glx.c +++ b/src/glx/drisw_glx.c @@ -452,8 +452,10 @@ driCreateScreen(int screen, struct glx_display *priv) return NULL; memset(psc, 0, sizeof *psc); - if (!glx_screen_init(&psc->base, screen, priv)) - return NULL; + if (!glx_screen_init(&psc->base, screen, priv)) { + Xfree(psc); + return NULL; + } psc->driver = driOpenSwrast(); if (psc->driver == NULL) @@ -504,6 +506,7 @@ driCreateScreen(int screen, struct glx_display *priv) handle_error: if (psc->driver) dlclose(psc->driver); + glx_screen_cleanup(&psc->base); Xfree(psc); ErrorMessageF("reverting to indirect rendering\n"); diff --git a/src/glx/glx_pbuffer.c b/src/glx/glx_pbuffer.c index 34892e8b1a2..5f91bc623a9 100644 --- a/src/glx/glx_pbuffer.c +++ b/src/glx/glx_pbuffer.c @@ -106,7 +106,7 @@ ChangeDrawableAttribute(Display * dpy, GLXDrawable drawable, if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) { xGLXChangeDrawableAttributesReq *req; - GetReqExtra(GLXChangeDrawableAttributes, 8 + (8 * num_attribs), req); + GetReqExtra(GLXChangeDrawableAttributes, 8 * num_attribs, req); output = (CARD32 *) (req + 1); req->reqType = opcode; @@ -117,7 +117,7 @@ ChangeDrawableAttribute(Display * dpy, GLXDrawable drawable, else { xGLXVendorPrivateWithReplyReq *vpreq; - GetReqExtra(GLXVendorPrivateWithReply, 4 + (8 * num_attribs), vpreq); + GetReqExtra(GLXVendorPrivateWithReply, 8 + (8 * num_attribs), vpreq); output = (CARD32 *) (vpreq + 1); vpreq->reqType = opcode; @@ -125,7 +125,8 @@ ChangeDrawableAttribute(Display * dpy, GLXDrawable drawable, vpreq->vendorCode = X_GLXvop_ChangeDrawableAttributesSGIX; output[0] = (CARD32) drawable; - output++; + output[1] = num_attribs; + output += 2; } (void) memcpy(output, attribs, sizeof(CARD32) * 2 * num_attribs); @@ -297,7 +298,7 @@ GetDrawableAttribute(Display * dpy, GLXDrawable drawable, if (use_glx_1_3) { xGLXGetDrawableAttributesReq *req; - GetReqExtra(GLXGetDrawableAttributes, 4, req); + GetReq(GLXGetDrawableAttributes, req); req->reqType = opcode; req->glxCode = X_GLXGetDrawableAttributes; req->drawable = drawable; @@ -435,7 +436,7 @@ DestroyDrawable(Display * dpy, GLXDrawable drawable, CARD32 glxCode) LockDisplay(dpy); - GetReqExtra(GLXDestroyPbuffer, 4, req); + GetReq(GLXDestroyPbuffer, req); req->reqType = opcode; req->glxCode = glxCode; req->pbuffer = (GLXPbuffer) drawable; diff --git a/src/glx/glxclient.h b/src/glx/glxclient.h index 36a0808c048..fdcef8075a8 100644 --- a/src/glx/glxclient.h +++ b/src/glx/glxclient.h @@ -585,6 +585,8 @@ struct glx_display extern int glx_screen_init(struct glx_screen *psc, int screen, struct glx_display * priv); +extern void +glx_screen_cleanup(struct glx_screen *psc); #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) extern __GLXDRIdrawable * diff --git a/src/glx/glxcmds.c b/src/glx/glxcmds.c index d12ff9684e2..80eaf72b7d5 100644 --- a/src/glx/glxcmds.c +++ b/src/glx/glxcmds.c @@ -215,12 +215,16 @@ CreateContext(Display * dpy, int generic_id, Bool allowDirect, unsigned code, int renderType, int screen) { - struct glx_context *gc = NULL; - struct glx_screen *const psc = GetGLXScreenConfigs(dpy, screen); + struct glx_context *gc; + struct glx_screen *psc; struct glx_context *shareList = (struct glx_context *) shareList_user; if (dpy == NULL) return NULL; + psc = GetGLXScreenConfigs(dpy, screen); + if (psc == NULL) + return NULL; + if (generic_id == None) return NULL; diff --git a/src/glx/glxext.c b/src/glx/glxext.c index c5e9d0510b6..25d266e18e1 100644 --- a/src/glx/glxext.c +++ b/src/glx/glxext.c @@ -194,17 +194,7 @@ FreeScreenConfigs(struct glx_display * priv) screens = ScreenCount(priv->dpy); for (i = 0; i < screens; i++) { psc = priv->screens[i]; - if (psc->configs) { - glx_config_destroy_list(psc->configs); - if (psc->effectiveGLXexts) - Xfree(psc->effectiveGLXexts); - psc->configs = NULL; /* NOTE: just for paranoia */ - } - if (psc->visuals) { - glx_config_destroy_list(psc->visuals); - psc->visuals = NULL; /* NOTE: just for paranoia */ - } - Xfree((char *) psc->serverGLXexts); + glx_screen_cleanup(psc); #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) if (psc->driScreen) { @@ -688,7 +678,7 @@ static GLboolean } else if (strstr(psc->serverGLXexts, "GLX_SGIX_fbconfig") != NULL) { GetReqExtra(GLXVendorPrivateWithReply, - sz_xGLXGetFBConfigsSGIXReq + + sz_xGLXGetFBConfigsSGIXReq - sz_xGLXVendorPrivateWithReplyReq, vpreq); sgi_req = (xGLXGetFBConfigsSGIXReq *) vpreq; sgi_req->reqType = priv->majorOpcode; @@ -728,6 +718,22 @@ glx_screen_init(struct glx_screen *psc, return GL_TRUE; } +_X_HIDDEN void +glx_screen_cleanup(struct glx_screen *psc) +{ + if (psc->configs) { + glx_config_destroy_list(psc->configs); + if (psc->effectiveGLXexts) + Xfree(psc->effectiveGLXexts); + psc->configs = NULL; /* NOTE: just for paranoia */ + } + if (psc->visuals) { + glx_config_destroy_list(psc->visuals); + psc->visuals = NULL; /* NOTE: just for paranoia */ + } + Xfree((char *) psc->serverGLXexts); +} + /* ** Allocate the memory for the per screen configs for each screen. ** If that works then fetch the per screen configs data. diff --git a/src/mapi/es1api/.gitignore b/src/mapi/es1api/.gitignore index 7c9ca37247b..b21f1d14c6f 100644 --- a/src/mapi/es1api/.gitignore +++ b/src/mapi/es1api/.gitignore @@ -1,3 +1,4 @@ +glapi_mapi_tmp.h glapi-stamp glapi main diff --git a/src/mapi/es1api/Makefile b/src/mapi/es1api/Makefile index 4fa68e5c39d..aef694866c2 100644 --- a/src/mapi/es1api/Makefile +++ b/src/mapi/es1api/Makefile @@ -124,10 +124,15 @@ install: default install-headers install-pc $(MINSTALL) $(TOP)/$(LIB_DIR)/$(esapi_LIB_GLOB) \ $(DESTDIR)$(INSTALL_LIB_DIR) +# workaround a bug in makedepend +makedepend_CPPFLAGS := \ + $(filter-out -DMAPI_ABI_HEADER=%, $(esapi_CPPFLAGS)) +$(esapi_OBJECTS): glapi_mapi_tmp.h + depend: $(esapi_SOURCES) @echo "running $(MKDEP)" @touch depend - @$(MKDEP) $(MKDEP_OPTIONS) -f- $(DEFINES) $(esapi_CPPFLAGS) \ + @$(MKDEP) $(MKDEP_OPTIONS) -f- $(DEFINES) $(makedepend_CPPFLAGS) \ $(esapi_SOURCES) 2>/dev/null | \ sed -e 's,^$(GLAPI)/,,' -e 's,^$(MAPI)/,,' > depend diff --git a/src/mapi/es2api/.gitignore b/src/mapi/es2api/.gitignore index 7c9ca37247b..b21f1d14c6f 100644 --- a/src/mapi/es2api/.gitignore +++ b/src/mapi/es2api/.gitignore @@ -1,3 +1,4 @@ +glapi_mapi_tmp.h glapi-stamp glapi main diff --git a/src/mapi/glapi/Makefile b/src/mapi/glapi/Makefile index 203a8abd018..bb4ed6585d9 100644 --- a/src/mapi/glapi/Makefile +++ b/src/mapi/glapi/Makefile @@ -13,11 +13,12 @@ include $(MAPI)/sources.mak glapi_CPPFLAGS := \ -I$(TOP)/include \ -I$(TOP)/src/mapi \ - -I$(TOP)/src/mesa \ - -DMAPI_ABI_HEADER=\"glapi/glapi_mapi_tmp.h\" + -I$(TOP)/src/mesa ifeq ($(SHARED_GLAPI),1) -glapi_CPPFLAGS += -DMAPI_MODE_BRIDGE +glapi_CPPFLAGS += \ + -DMAPI_MODE_BRIDGE \ + -DMAPI_ABI_HEADER=\"glapi/glapi_mapi_tmp.h\" glapi_SOURCES := $(addprefix $(MAPI)/, $(MAPI_BRIDGE_SOURCES)) glapi_GLAPI_OBJECTS := @@ -58,10 +59,19 @@ clean: -rm -f lib$(TARGET).a -rm -f depend depend.bak +ifeq ($(SHARED_GLAPI),1) +# workaround a bug in makedepend +makedepend_CPPFLAGS := \ + $(filter-out -DMAPI_ABI_HEADER=%, $(glapi_CPPFLAGS)) +$(glapi_OBJECTS): glapi_mapi_tmp.h +else +makedepend_CPPFLAGS := $(glapi_CPPFLAGS) +endif + depend: $(glapi_SOURCES) @ echo "running $(MKDEP)" @ touch depend - @$(MKDEP) $(MKDEP_OPTIONS) -f- $(DEFINES) $(glapi_CPPFLAGS) \ + @$(MKDEP) $(MKDEP_OPTIONS) -f- $(DEFINES) $(makedepend_CPPFLAGS) \ $(glapi_SOURCES) 2>/dev/null | sed -e 's,^$(MAPI)/,,' > depend -include depend diff --git a/src/mapi/glapi/SConscript b/src/mapi/glapi/SConscript index 4057991ec8d..276b2160246 100644 --- a/src/mapi/glapi/SConscript +++ b/src/mapi/glapi/SConscript @@ -17,6 +17,11 @@ if env['platform'] != 'winddk': '_GDI32_', # prevent gl* being declared __declspec(dllimport) in MS headers 'BUILD_GL32', # declare gl* as __declspec(dllexport) in Mesa headers ]) + if env['gles']: + env.Append(CPPDEFINES = ['_GLAPI_DLL_EXPORTS']) + else: + # prevent _glapi_* from being declared __declspec(dllimport) + env.Append(CPPDEFINES = ['_GLAPI_NO_EXPORTS']) env.Append(CPPPATH = [ '#/src/mapi', diff --git a/src/mapi/glapi/gen/gl_x86-64_asm.py b/src/mapi/glapi/gen/gl_x86-64_asm.py index 2fa140dc308..11cd9af4061 100644 --- a/src/mapi/glapi/gen/gl_x86-64_asm.py +++ b/src/mapi/glapi/gen/gl_x86-64_asm.py @@ -166,7 +166,8 @@ class PrintGenericStubs(gl_XML.gl_print_base): print '' print '\t.p2align\t4,,15' print '_x86_64_get_dispatch:' - print '\tmovq\t_gl_DispatchTSD(%rip), %rdi' + print '\tmovq\t_gl_DispatchTSD@GOTPCREL(%rip), %rax' + print '\tmovl\t(%rax), %edi' print '\tjmp\tpthread_getspecific@PLT' print '' print '#elif defined(THREADS)' diff --git a/src/mapi/glapi/gen/gl_x86_asm.py b/src/mapi/glapi/gen/gl_x86_asm.py index 21996a39421..4ef4acb564e 100644 --- a/src/mapi/glapi/gen/gl_x86_asm.py +++ b/src/mapi/glapi/gen/gl_x86_asm.py @@ -73,7 +73,7 @@ class PrintGenericStubs(gl_XML.gl_print_base): print '#define GL_OFFSET(x) CODEPTR(REGOFF(4 * x, EAX))' print '' print '#if defined(GNU_ASSEMBLER) && !defined(__DJGPP__) && !defined(__MINGW32__) && !defined(__APPLE__)' - print '#define GLOBL_FN(x) GLOBL x ; .type x, function' + print '#define GLOBL_FN(x) GLOBL x ; .type x, @function' print '#else' print '#define GLOBL_FN(x) GLOBL x' print '#endif' diff --git a/src/mapi/glapi/glapi.h b/src/mapi/glapi/glapi.h index 8cca50487c4..e909cf892ab 100644 --- a/src/mapi/glapi/glapi.h +++ b/src/mapi/glapi/glapi.h @@ -45,11 +45,6 @@ #define _GLAPI_H -/* opengl.dll does not export _glapi_* */ -#if defined(_WIN32) -#define _GLAPI_NO_EXPORTS -#endif - #ifdef _GLAPI_NO_EXPORTS # define _GLAPI_EXPORT #else /* _GLAPI_NO_EXPORTS */ diff --git a/src/mapi/glapi/glapi_x86-64.S b/src/mapi/glapi/glapi_x86-64.S index 469fac31ae6..c42646f0165 100644 --- a/src/mapi/glapi/glapi_x86-64.S +++ b/src/mapi/glapi/glapi_x86-64.S @@ -73,7 +73,8 @@ _x86_64_get_dispatch: .p2align 4,,15 _x86_64_get_dispatch: - movq _gl_DispatchTSD(%rip), %rdi + movq _gl_DispatchTSD@GOTPCREL(%rip), %rax + movl (%rax), %edi jmp pthread_getspecific@PLT #elif defined(THREADS) diff --git a/src/mapi/glapi/glapi_x86.S b/src/mapi/glapi/glapi_x86.S index fa448c1704f..8d85f61ce00 100644 --- a/src/mapi/glapi/glapi_x86.S +++ b/src/mapi/glapi/glapi_x86.S @@ -46,7 +46,7 @@ #define GL_OFFSET(x) CODEPTR(REGOFF(4 * x, EAX)) #if defined(GNU_ASSEMBLER) && !defined(__DJGPP__) && !defined(__MINGW32__) && !defined(__APPLE__) -#define GLOBL_FN(x) GLOBL x ; .type x, function +#define GLOBL_FN(x) GLOBL x ; .type x, @function #else #define GLOBL_FN(x) GLOBL x #endif diff --git a/src/mapi/mapi/entry.c b/src/mapi/mapi/entry.c index f378ccfda95..3d9168a7243 100644 --- a/src/mapi/mapi/entry.c +++ b/src/mapi/mapi/entry.c @@ -37,7 +37,7 @@ #ifdef MAPI_MODE_BRIDGE #define ENTRY_CURRENT_TABLE_GET "_glapi_get_dispatch" #else -#define ENTRY_CURRENT_TABLE_GET "u_current_get_internal" +#define ENTRY_CURRENT_TABLE_GET U_STRINGIFY(u_current_get_internal) #endif #if defined(USE_X86_ASM) && defined(__GNUC__) diff --git a/src/mapi/shared-glapi/.gitignore b/src/mapi/shared-glapi/.gitignore new file mode 100644 index 00000000000..c3e0647dd81 --- /dev/null +++ b/src/mapi/shared-glapi/.gitignore @@ -0,0 +1,2 @@ +glapi_mapi_tmp.h + diff --git a/src/mapi/shared-glapi/Makefile b/src/mapi/shared-glapi/Makefile index ee937bd681b..c928f822c81 100644 --- a/src/mapi/shared-glapi/Makefile +++ b/src/mapi/shared-glapi/Makefile @@ -51,10 +51,15 @@ install: $(MINSTALL) $(TOP)/$(LIB_DIR)/$(GLAPI_LIB_GLOB) \ $(DESTDIR)$(INSTALL_LIB_DIR) +# workaround a bug in makedepend +makedepend_CPPFLAGS := \ + $(filter-out -DMAPI_ABI_HEADER=%, $(glapi_CPPFLAGS)) +$(glapi_OBJECTS): glapi_mapi_tmp.h + depend: $(glapi_SOURCES) @echo "running $(MKDEP)" @touch depend - @$(MKDEP) $(MKDEP_OPTIONS) -f- $(DEFINES) $(glapi_CPPFLAGS) \ + @$(MKDEP) $(MKDEP_OPTIONS) -f- $(DEFINES) $(makedepend_CPPFLAGS) \ $(glapi_SOURCES) 2>/dev/null | sed -e 's,^$(MAPI)/,,' \ > depend diff --git a/src/mapi/shared-glapi/SConscript b/src/mapi/shared-glapi/SConscript new file mode 100644 index 00000000000..b7c43a73476 --- /dev/null +++ b/src/mapi/shared-glapi/SConscript @@ -0,0 +1,116 @@ +####################################################################### +# SConscript for shared-glapi/es1api/es2api + +from sys import executable as python_cmd + +Import('*') + +def mapi_objects(env, printer, mode): + """Return mapi objects built for the given printer and mode.""" + mapi_sources = { + 'glapi': ['entry.c', 'mapi_glapi.c', 'stub.c', 'table.c', + 'u_current.c', 'u_execmem.c', 'u_thread.c'], + 'bridge': ['entry.c'], + } + mapi_defines = { + 'glapi': ['MAPI_MODE_GLAPI'], + 'bridge': ['MAPI_MODE_BRIDGE'], + } + + header_name = '%s-tmp.h' % (printer) + + # generate ABI header + header = env.CodeGenerate( + target = header_name, + script = '../mapi/mapi_abi.py', + source = '../glapi/gen/gl_and_es_API.xml', + command = python_cmd + ' $SCRIPT ' + \ + '--printer %s --mode lib $SOURCE > $TARGET' % (printer), + ) + + cpppath = [ + header[0].dir, + '#/include', + '#/src/mapi', + ] + + cppdefines = mapi_defines[mode] + [ + 'MAPI_ABI_HEADER=\\"%s\\"' % (header_name), + ] + + if env['platform'] == 'windows': + if mode == 'glapi': + cppdefines += [ + '_GLAPI_DLL_EXPORTS', # declare _glapi_* as __declspec(dllexport) in glapi.h + ] + else: + cppdefines += [ + '_GDI32_', # prevent gl* being declared __declspec(dllimport) in MS headers + 'BUILD_GL32', # declare gl* as __declspec(dllexport) in Mesa headers + ] + + objects = [] + for s in mapi_sources[mode]: + o = env.SharedObject( + target = '%s-%s' % (printer, s[:-2]), + source = '../mapi/' + s, + CPPPATH = cpppath, + CPPDEFINES = cppdefines, + ) + objects.append(o[0]) + + env.Depends(objects, header) + + return objects + +if env['platform'] != 'winddk': + env = env.Clone() + + env['SHLIBPREFIX'] = 'lib' + env['LIBPREFIX'] = 'lib' + + shared_glapi_objects = mapi_objects(env, 'shared-glapi', 'glapi') + shared_glapi = env.SharedLibrary( + target = 'glapi', + source = shared_glapi_objects, + ) + + # manually add LIBPREFIX on windows + if env['platform'] == 'windows': + libs = ['libglapi'] + else: + libs = ['glapi'] + + es1api_objects = mapi_objects(env, 'es1api', 'bridge') + es1api = env.SharedLibrary( + target = 'GLESv1_CM', + source = es1api_objects, + LIBPATH = ['.'], + LIBS = libs, + ) + + es2api_objects = mapi_objects(env, 'es2api', 'bridge') + es2api = env.SharedLibrary( + target = 'GLESv2', + source = es2api_objects, + LIBPATH = ['.'], + LIBS = libs, + ) + + env.InstallSharedLibrary(shared_glapi, version=(0, 0, 0)) + env.InstallSharedLibrary(es1api, version=(1, 0, 0)) + env.InstallSharedLibrary(es2api, version=(2, 0, 0)) + + if env['platform'] == 'windows': + shared_glapi = env.FindIxes(shared_glapi, 'LIBPREFIX', 'LIBSUFFIX') + else: + shared_glapi = env.FindIxes(shared_glapi, 'SHLIBPREFIX', 'SHLIBSUFFIX') + + # build glapi bridge as a convenience libarary for libgl-xlib/libgl-gdi + bridge_glapi_objects = mapi_objects(env, 'glapi', 'bridge') + bridge_glapi = env.ConvenienceLibrary( + target = 'glapi_bridge', + source = bridge_glapi_objects, + ) + + Export(['shared_glapi', 'bridge_glapi']) diff --git a/src/mapi/vgapi/Makefile b/src/mapi/vgapi/Makefile index e239e20987e..68cf26e83c3 100644 --- a/src/mapi/vgapi/Makefile +++ b/src/mapi/vgapi/Makefile @@ -81,11 +81,14 @@ install: default install-headers install-pc $(MINSTALL) $(TOP)/$(LIB_DIR)/$(VG_LIB_GLOB) \ $(DESTDIR)$(INSTALL_LIB_DIR) +# due to a bug in makedepend, cannot pass VGAPI_CPPFLAGS to it +$(VGAPI_OBJECTS): vgapi_tmp.h + depend: $(VGAPI_SOURCES) @echo "running $(MKDEP)" @touch depend @$(MKDEP) $(MKDEP_OPTIONS) -f- $(DEFINES) $(INCLUDE_DIRS) \ - $(VGAPI_CPPFLAGS) $(VGAPI_SOURCES) 2>/dev/null | \ + $(VGAPI_SOURCES) 2>/dev/null | \ sed -e 's,^$(MAPI)/,,' > depend -include depend diff --git a/src/mesa/Makefile b/src/mesa/Makefile index 25e7cce425c..48f79a5d550 100644 --- a/src/mesa/Makefile +++ b/src/mesa/Makefile @@ -7,7 +7,7 @@ MESA_LIBS := libmesa.a libmesagallium.a DEPENDS := depend MESA_OBJ_DIR := . - +DRICORE_OBJ_DIR := objs-dricore include sources.mak @@ -15,27 +15,35 @@ include sources.mak MESA_OBJECTS := $(addprefix $(MESA_OBJ_DIR)/, $(MESA_OBJECTS)) MESA_GALLIUM_OBJECTS := $(addprefix $(MESA_OBJ_DIR)/, $(MESA_GALLIUM_OBJECTS)) +DRICORE_OBJECTS := $(addprefix $(DRICORE_OBJ_DIR)/, $(MESA_OBJECTS)) + # define preprocessor flags MESA_CPPFLAGS := $(API_DEFINES) $(DEFINES) # append include dirs -MESA_CPPFLAGS += $(INCLUDE_DIRS) $(TALLOC_CFLAGS) +MESA_CPPFLAGS += $(INCLUDE_DIRS) + +DRICORE_CPPFLAGS = $(MESA_CPPFLAGS) # tidy compiler flags CFLAGS := $(filter-out $(DEFINES), $(CFLAGS)) CXXFLAGS := $(filter-out $(DEFINES), $(CXXFLAGS)) # LLVM is needed for the state tracker -MESA_CFLAGS := $(LLVM_CFLAGS) +MESA_CFLAGS := $(LLVM_CFLAGS) $(CFLAGS) +DRICORE_CFLAGS := $(LLVM_CFLAGS) $(DRI_CFLAGS) + +MESA_CXXFLAGS := $(LLVM_CFLAGS) $(CXXFLAGS) +DRICORE_CXXFLAGS := $(LLVM_CFLAGS) $(DRI_CXXFLAGS) define mesa-cc-c @mkdir -p $(dir $@) - $(CC) -c -o $@ $< $($(1)_CPPFLAGS) $($(1)_CFLAGS) $(CFLAGS) + $(CC) -c -o $@ $< $($(1)_CPPFLAGS) $($(1)_CFLAGS) endef define mesa-cxx-c @mkdir -p $(dir $@) - $(CXX) -c -o $@ $< $($(1)_CPPFLAGS) $($(1)_CFLAGS) $(CXXFLAGS) + $(CXX) -c -o $@ $< $($(1)_CPPFLAGS) $($(1)_CFLAGS) $($(1)_CXXFLAGS) endef $(MESA_OBJ_DIR)/%.o: %.c @@ -47,9 +55,18 @@ $(MESA_OBJ_DIR)/%.o: %.cpp $(MESA_OBJ_DIR)/%.o: %.S $(call mesa-cc-c,MESA) +$(DRICORE_OBJ_DIR)/%.o: %.c + $(call mesa-cc-c,DRICORE) + +$(DRICORE_OBJ_DIR)/%.o: %.cpp + $(call mesa-cxx-c,DRICORE) + +$(DRICORE_OBJ_DIR)/%.o: %.S + $(call mesa-cc-c,DRICORE) + # Default: build dependencies, then asm_subdirs, GLSL built-in lib, # then convenience libs (.a) and finally the device drivers: -default: $(DEPENDS) asm_subdirs $(MESA_LIBS) driver_subdirs +default: $(DEPENDS) asm_subdirs $(MESA_LIBS) $(DRICORE_LIBS) driver_subdirs main/api_exec_es1.c: main/APIspec.xml main/es_generator.py main/APIspecutil.py main/APIspec.py $(PYTHON2) $(PYTHON_FLAGS) main/es_generator.py -S main/APIspec.xml -V GLES1.1 > $@ @@ -64,13 +81,20 @@ main/api_exec_es2.c: main/APIspec.xml main/es_generator.py main/APIspecutil.py m libmesa.a: $(MESA_OBJECTS) $(GLSL_LIBS) @ $(MKLIB) -o mesa -static $(MESA_OBJECTS) $(GLSL_LIBS) +# Shared dricore library for classic DRI drivers +$(TOP)/$(LIB_DIR)/libdricore.so: $(DRICORE_OBJECTS) $(DRICORE_GLSL_LIBS) + @$(MKLIB) -o $@ -linker '$(CXX)' -ldflags '$(LDFLAGS)' \ + -cplusplus -noprefix \ + -install $(TOP)/$(LIB_DIR) -id $(DRI_DRIVER_INSTALL_DIR)/[email protected] \ + $(DRICORE_LIB_DEPS) $(DRICORE_OBJECTS) + # Make archive of subset of core mesa object files for gallium libmesagallium.a: $(MESA_GALLIUM_OBJECTS) $(GLSL_LIBS) @ $(MKLIB) -o mesagallium -static $(MESA_GALLIUM_OBJECTS) $(GLSL_LIBS) ###################################################################### # Device drivers -driver_subdirs: $(MESA_LIBS) +driver_subdirs: $(MESA_LIBS) $(DRICORE_LIBS) @ (cd drivers && $(MAKE)) @@ -102,9 +126,12 @@ depend: $(ALL_SOURCES) new_install: (cd drivers && $(MAKE) install) +ifneq (,$(DRICORE_LIBS)) +DRICORE_INSTALL_TARGET = install-dricore +endif # XXX replace this with new_install above someday -install: default +install: default $(DRICORE_INSTALL_TARGET) @for driver in $(DRIVER_DIRS) ; do \ case "$$driver" in \ osmesa) if [ "$(DRIVER_DIRS)" = osmesa ]; then \ @@ -166,13 +193,22 @@ install-osmesa: default osmesa.pc install-dri: default cd drivers/dri && $(MAKE) install +# We don't need MINSTALL here because we're not installing symbolic links +install-dricore: default + $(INSTALL) -d $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR) + $(INSTALL) -m 755 $(DRICORE_LIBS) $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR) # Emacs tags tags: etags `find . -name \*.[ch]` $(TOP)/include/GL/*.h -clean: +clean-dricore: + -rm -f libdricore.so + -rm -f $(DRICORE_LIBS) + -rm -rf $(DRICORE_OBJ_DIR) + +clean: clean-dricore -rm -f */*.o -rm -f */*/*.o -rm -f depend depend.bak libmesa.a libmesagallium.a diff --git a/src/mesa/SConscript b/src/mesa/SConscript index cc4ad09fa33..ea04fb1a0ee 100644 --- a/src/mesa/SConscript +++ b/src/mesa/SConscript @@ -12,12 +12,18 @@ env.Append(CPPPATH = [ '#/src/mesa', ]) +env.Append(CPPDEFINES = [ + 'FEATURE_GL=1', +]) + if env['platform'] == 'windows': env.Append(CPPDEFINES = [ '_GDI32_', # prevent gl* being declared __declspec(dllimport) in MS headers 'BUILD_GL32', # declare gl* as __declspec(dllexport) in Mesa headers ]) - env.Prepend(CPPPATH = ['#src/talloc']) + if not env['gles']: + # prevent _glapi_* from being declared __declspec(dllimport) + env.Append(CPPDEFINES = ['_GLAPI_NO_EXPORTS']) else: env.Append(CPPDEFINES = [ 'IN_DRI_DRIVER', # enable the remap table (for DRI drivers) @@ -240,6 +246,61 @@ mesa_sources = ( statetracker_sources ) +if env['gles']: + from sys import executable as python_cmd + + env.Append(CPPDEFINES = ['FEATURE_ES1=1', 'FEATURE_ES2=1']) + + # generate GLES sources + gles_sources = [] + gles_sources += env.CodeGenerate( + target = 'main/api_exec_es1.c', + script = 'main/es_generator.py', + source = 'main/APIspec.xml', + command = python_cmd + ' $SCRIPT -S $SOURCE -V GLES1.1 > $TARGET' + ) + gles_sources += env.CodeGenerate( + target = 'main/api_exec_es2.c', + script = 'main/es_generator.py', + source = 'main/APIspec.xml', + command = python_cmd + ' $SCRIPT -S $SOURCE -V GLES2.0 > $TARGET' + ) + + # generate GLES headers + GLAPI = '#src/mapi/glapi/' + gles_headers = [] + gles_headers += env.CodeGenerate( + target = 'es1api/main/glapidispatch.h', + script = GLAPI + 'gen/gl_table.py', + source = GLAPI + 'gen-es/es1_API.xml', + command = python_cmd + ' $SCRIPT -c -m remap_table -f $SOURCE > $TARGET', + ) + gles_headers += env.CodeGenerate( + target = 'es1api/main/remap_helper.h', + script = GLAPI + 'gen/remap_helper.py', + source = GLAPI + 'gen-es/es1_API.xml', + command = python_cmd + ' $SCRIPT -f $SOURCE > $TARGET', + ) + gles_headers += env.CodeGenerate( + target = 'es2api/main/glapidispatch.h', + script = GLAPI + 'gen/gl_table.py', + source = GLAPI + 'gen-es/es2_API.xml', + command = python_cmd + ' $SCRIPT -c -m remap_table -f $SOURCE > $TARGET', + ) + gles_headers += env.CodeGenerate( + target = 'es2api/main/remap_helper.h', + script = GLAPI + 'gen/remap_helper.py', + source = GLAPI + 'gen-es/es2_API.xml', + command = python_cmd + ' $SCRIPT -f $SOURCE > $TARGET', + ) + + env.Depends(gles_sources, gles_headers) + + # gles_sources #include gles_headers with full path + env.Append(CPPPATH = [gles_headers[0].dir.up().up()]) + + mesa_sources += gles_sources + # # Assembly sources # diff --git a/src/mesa/drivers/beos/GLView.cpp b/src/mesa/drivers/beos/GLView.cpp index ee3415b3d1a..57c4614f32d 100644 --- a/src/mesa/drivers/beos/GLView.cpp +++ b/src/mesa/drivers/beos/GLView.cpp @@ -50,7 +50,6 @@ extern "C" { #include "swrast/s_depth.h" #include "swrast/s_lines.h" #include "swrast/s_triangle.h" -#include "swrast/s_trispan.h" #include "tnl/tnl.h" #include "tnl/t_context.h" #include "tnl/t_pipeline.h" @@ -319,7 +318,8 @@ BGLView::BGLView(BRect rect, char *name, functions.Viewport = md->Viewport; // create core context - struct gl_context *ctx = _mesa_create_context(visual, NULL, &functions, md); + struct gl_context *ctx = _mesa_create_context(API_OPENGL, visual, + NULL, &functions, md); if (! ctx) { _mesa_destroy_visual(visual); delete md; diff --git a/src/mesa/drivers/common/driverfuncs.c b/src/mesa/drivers/common/driverfuncs.c index 3c6ecb83f0a..5389a500111 100644 --- a/src/mesa/drivers/common/driverfuncs.c +++ b/src/mesa/drivers/common/driverfuncs.c @@ -184,6 +184,7 @@ _mesa_init_driver_functions(struct dd_function_table *driver) driver->RenderTexture = _mesa_render_texture; driver->FinishRenderTexture = _mesa_finish_render_texture; driver->FramebufferRenderbuffer = _mesa_framebuffer_renderbuffer; + driver->ValidateFramebuffer = _mesa_validate_framebuffer; driver->BlitFramebuffer = _swrast_BlitFramebuffer; diff --git a/src/mesa/drivers/dri/Makefile.template b/src/mesa/drivers/dri/Makefile.template index 4ecddbc0483..d1a119379ed 100644 --- a/src/mesa/drivers/dri/Makefile.template +++ b/src/mesa/drivers/dri/Makefile.template @@ -1,7 +1,5 @@ # -*-makefile-*- -MESA_MODULES = $(TOP)/src/mesa/libmesa.a - COMMON_GALLIUM_SOURCES = \ ../common/utils.c \ ../common/vblank.c \ @@ -11,8 +9,7 @@ COMMON_GALLIUM_SOURCES = \ COMMON_SOURCES = $(COMMON_GALLIUM_SOURCES) \ ../../common/driverfuncs.c \ ../common/texmem.c \ - ../common/drirenderbuffer.c \ - ../common/dri_metaops.c + ../common/drirenderbuffer.c INCLUDES = $(SHARED_INCLUDES) $(EXPAT_INCLUDES) @@ -39,13 +36,13 @@ CXXFLAGS += $(API_DEFINES) ##### RULES ##### .c.o: - $(CC) -c $(INCLUDES) $(CFLAGS) $(DRIVER_DEFINES) $< -o $@ + $(CC) -c $(INCLUDES) $(DRI_CFLAGS) $(DRIVER_DEFINES) $< -o $@ .cpp.o: - $(CC) -c $(INCLUDES) $(CXXFLAGS) $(DRIVER_DEFINES) $< -o $@ + $(CC) -c $(INCLUDES) $(DRI_CXXFLAGS) $(DRIVER_DEFINES) $< -o $@ .S.o: - $(CC) -c $(INCLUDES) $(CFLAGS) $(DRIVER_DEFINES) $< -o $@ + $(CC) -c $(INCLUDES) $(DRI_CFLAGS) $(DRIVER_DEFINES) $< -o $@ ##### TARGETS ##### @@ -57,10 +54,10 @@ default: subdirs lib lib: symlinks subdirs depend @$(MAKE) $(LIBNAME) $(TOP)/$(LIB_DIR)/$(LIBNAME) -$(LIBNAME): $(OBJECTS) $(MESA_MODULES) $(EXTRA_MODULES) Makefile \ +$(LIBNAME): $(OBJECTS) $(EXTRA_MODULES) $(MESA_MODULES) Makefile \ $(TOP)/src/mesa/drivers/dri/Makefile.template $(TOP)/src/mesa/drivers/dri/common/dri_test.o $(MKLIB) -o [email protected] -noprefix -linker '$(CXX)' -ldflags '$(LDFLAGS)' \ - $(OBJECTS) $(MESA_MODULES) $(EXTRA_MODULES) $(DRI_LIB_DEPS) + $(OBJECTS) $(EXTRA_MODULES) $(DRI_LIB_DEPS) $(CXX) $(CFLAGS) -o [email protected] $(TOP)/src/mesa/drivers/dri/common/dri_test.o [email protected] $(DRI_LIB_DEPS) @rm -f [email protected] mv -f [email protected] $@ diff --git a/src/mesa/drivers/dri/common/dri_metaops.c b/src/mesa/drivers/dri/common/dri_metaops.c deleted file mode 100644 index e0bc3b88ecd..00000000000 --- a/src/mesa/drivers/dri/common/dri_metaops.c +++ /dev/null @@ -1,291 +0,0 @@ -/************************************************************************** - * - * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. - * Copyright 2009 Intel Corporation. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS 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. - * - **************************************************************************/ - -#include "main/arbprogram.h" -#include "main/arrayobj.h" -#include "main/bufferobj.h" -#include "main/context.h" -#include "main/enable.h" -#include "main/matrix.h" -#include "main/texstate.h" -#include "main/varray.h" -#include "main/viewport.h" -#include "program/program.h" -#include "dri_metaops.h" - -void -meta_set_passthrough_transform(struct dri_metaops *meta) -{ - struct gl_context *ctx = meta->ctx; - - meta->saved_vp_x = ctx->Viewport.X; - meta->saved_vp_y = ctx->Viewport.Y; - meta->saved_vp_width = ctx->Viewport.Width; - meta->saved_vp_height = ctx->Viewport.Height; - meta->saved_matrix_mode = ctx->Transform.MatrixMode; - - meta->internal_viewport_call = GL_TRUE; - _mesa_Viewport(0, 0, ctx->DrawBuffer->Width, ctx->DrawBuffer->Height); - meta->internal_viewport_call = GL_FALSE; - - _mesa_MatrixMode(GL_PROJECTION); - _mesa_PushMatrix(); - _mesa_LoadIdentity(); - _mesa_Ortho(0, ctx->DrawBuffer->Width, 0, ctx->DrawBuffer->Height, 1, -1); - - _mesa_MatrixMode(GL_MODELVIEW); - _mesa_PushMatrix(); - _mesa_LoadIdentity(); -} - -void -meta_restore_transform(struct dri_metaops *meta) -{ - _mesa_MatrixMode(GL_PROJECTION); - _mesa_PopMatrix(); - _mesa_MatrixMode(GL_MODELVIEW); - _mesa_PopMatrix(); - - _mesa_MatrixMode(meta->saved_matrix_mode); - - meta->internal_viewport_call = GL_TRUE; - _mesa_Viewport(meta->saved_vp_x, meta->saved_vp_y, - meta->saved_vp_width, meta->saved_vp_height); - meta->internal_viewport_call = GL_FALSE; -} - - -/** - * Set up a vertex program to pass through the position and first texcoord - * for pixel path. - */ -void -meta_set_passthrough_vertex_program(struct dri_metaops *meta) -{ - struct gl_context *ctx = meta->ctx; - static const char *vp = - "!!ARBvp1.0\n" - "TEMP vertexClip;\n" - "DP4 vertexClip.x, state.matrix.mvp.row[0], vertex.position;\n" - "DP4 vertexClip.y, state.matrix.mvp.row[1], vertex.position;\n" - "DP4 vertexClip.z, state.matrix.mvp.row[2], vertex.position;\n" - "DP4 vertexClip.w, state.matrix.mvp.row[3], vertex.position;\n" - "MOV result.position, vertexClip;\n" - "MOV result.texcoord[0], vertex.texcoord[0];\n" - "MOV result.color, vertex.color;\n" - "END\n"; - - assert(meta->saved_vp == NULL); - - _mesa_reference_vertprog(ctx, &meta->saved_vp, - ctx->VertexProgram.Current); - if (meta->passthrough_vp == NULL) { - GLuint prog_name; - _mesa_GenPrograms(1, &prog_name); - _mesa_BindProgram(GL_VERTEX_PROGRAM_ARB, prog_name); - _mesa_ProgramStringARB(GL_VERTEX_PROGRAM_ARB, - GL_PROGRAM_FORMAT_ASCII_ARB, - strlen(vp), (const GLubyte *)vp); - _mesa_reference_vertprog(ctx, &meta->passthrough_vp, - ctx->VertexProgram.Current); - _mesa_DeletePrograms(1, &prog_name); - } - - FLUSH_VERTICES(ctx, _NEW_PROGRAM); - _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, - meta->passthrough_vp); - ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB, - &meta->passthrough_vp->Base); - - meta->saved_vp_enable = ctx->VertexProgram.Enabled; - _mesa_Enable(GL_VERTEX_PROGRAM_ARB); -} - -/** - * Restores the previous vertex program after - * meta_set_passthrough_vertex_program() - */ -void -meta_restore_vertex_program(struct dri_metaops *meta) -{ - struct gl_context *ctx = meta->ctx; - - FLUSH_VERTICES(ctx, _NEW_PROGRAM); - _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, - meta->saved_vp); - _mesa_reference_vertprog(ctx, &meta->saved_vp, NULL); - ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB, - &ctx->VertexProgram.Current->Base); - - if (!meta->saved_vp_enable) - _mesa_Disable(GL_VERTEX_PROGRAM_ARB); -} - -/** - * Binds the given program string to GL_FRAGMENT_PROGRAM_ARB, caching the - * program object. - */ -void -meta_set_fragment_program(struct dri_metaops *meta, - struct gl_fragment_program **prog, - const char *prog_string) -{ - struct gl_context *ctx = meta->ctx; - assert(meta->saved_fp == NULL); - - _mesa_reference_fragprog(ctx, &meta->saved_fp, - ctx->FragmentProgram.Current); - if (*prog == NULL) { - GLuint prog_name; - _mesa_GenPrograms(1, &prog_name); - _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, prog_name); - _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, - GL_PROGRAM_FORMAT_ASCII_ARB, - strlen(prog_string), (const GLubyte *)prog_string); - _mesa_reference_fragprog(ctx, prog, ctx->FragmentProgram.Current); - /* Note that DeletePrograms unbinds the program on us */ - _mesa_DeletePrograms(1, &prog_name); - } - - FLUSH_VERTICES(ctx, _NEW_PROGRAM); - _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, *prog); - ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, &((*prog)->Base)); - - meta->saved_fp_enable = ctx->FragmentProgram.Enabled; - _mesa_Enable(GL_FRAGMENT_PROGRAM_ARB); -} - -/** - * Restores the previous fragment program after - * meta_set_fragment_program() - */ -void -meta_restore_fragment_program(struct dri_metaops *meta) -{ - struct gl_context *ctx = meta->ctx; - - FLUSH_VERTICES(ctx, _NEW_PROGRAM); - _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, - meta->saved_fp); - _mesa_reference_fragprog(ctx, &meta->saved_fp, NULL); - ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, - &ctx->FragmentProgram.Current->Base); - - if (!meta->saved_fp_enable) - _mesa_Disable(GL_FRAGMENT_PROGRAM_ARB); -} - -static const float default_texcoords[4][2] = { { 0.0, 0.0 }, - { 1.0, 0.0 }, - { 1.0, 1.0 }, - { 0.0, 1.0 } }; - -void -meta_set_default_texrect(struct dri_metaops *meta) -{ - struct gl_context *ctx = meta->ctx; - struct gl_client_array *old_texcoord_array; - - meta->saved_active_texture = ctx->Texture.CurrentUnit; - if (meta->saved_array_vbo == NULL) { - _mesa_reference_buffer_object(ctx, &meta->saved_array_vbo, - ctx->Array.ArrayBufferObj); - } - - old_texcoord_array = &ctx->Array.ArrayObj->TexCoord[0]; - meta->saved_texcoord_type = old_texcoord_array->Type; - meta->saved_texcoord_size = old_texcoord_array->Size; - meta->saved_texcoord_stride = old_texcoord_array->Stride; - meta->saved_texcoord_enable = old_texcoord_array->Enabled; - meta->saved_texcoord_ptr = old_texcoord_array->Ptr; - _mesa_reference_buffer_object(ctx, &meta->saved_texcoord_vbo, - old_texcoord_array->BufferObj); - - _mesa_ClientActiveTextureARB(GL_TEXTURE0); - - if (meta->texcoord_vbo == NULL) { - GLuint vbo_name; - - _mesa_GenBuffersARB(1, &vbo_name); - _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, vbo_name); - _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(default_texcoords), - default_texcoords, GL_STATIC_DRAW_ARB); - _mesa_reference_buffer_object(ctx, &meta->texcoord_vbo, - ctx->Array.ArrayBufferObj); - } else { - _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, - meta->texcoord_vbo->Name); - } - _mesa_TexCoordPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), NULL); - - _mesa_Enable(GL_TEXTURE_COORD_ARRAY); -} - -void -meta_restore_texcoords(struct dri_metaops *meta) -{ - struct gl_context *ctx = meta->ctx; - - /* Restore the old TexCoordPointer */ - if (meta->saved_texcoord_vbo) { - _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, - meta->saved_texcoord_vbo->Name); - _mesa_reference_buffer_object(ctx, &meta->saved_texcoord_vbo, NULL); - } else { - _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, 0); - } - - _mesa_TexCoordPointer(meta->saved_texcoord_size, - meta->saved_texcoord_type, - meta->saved_texcoord_stride, - meta->saved_texcoord_ptr); - if (!meta->saved_texcoord_enable) - _mesa_Disable(GL_TEXTURE_COORD_ARRAY); - - _mesa_ClientActiveTextureARB(GL_TEXTURE0 + - meta->saved_active_texture); - - if (meta->saved_array_vbo) { - _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, - meta->saved_array_vbo->Name); - _mesa_reference_buffer_object(ctx, &meta->saved_array_vbo, NULL); - } else { - _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, 0); - } -} - - -void meta_init_metaops(struct gl_context *ctx, struct dri_metaops *meta) -{ - meta->ctx = ctx; -} - -void meta_destroy_metaops(struct dri_metaops *meta) -{ - -} diff --git a/src/mesa/drivers/dri/common/dri_metaops.h b/src/mesa/drivers/dri/common/dri_metaops.h deleted file mode 100644 index aa7d4baa6e9..00000000000 --- a/src/mesa/drivers/dri/common/dri_metaops.h +++ /dev/null @@ -1,81 +0,0 @@ -/************************************************************************** - * - * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. - * Copyright 2009 Intel Corporation. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS 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. - * - **************************************************************************/ - -#ifndef DRI_METAOPS_H -#define DRI_METAOPS_H - - -struct dri_metaops { - struct gl_context *ctx; - GLboolean internal_viewport_call; - struct gl_fragment_program *bitmap_fp; - struct gl_vertex_program *passthrough_vp; - struct gl_buffer_object *texcoord_vbo; - - struct gl_fragment_program *saved_fp; - GLboolean saved_fp_enable; - struct gl_vertex_program *saved_vp; - GLboolean saved_vp_enable; - - struct gl_fragment_program *tex2d_fp; - - GLboolean saved_texcoord_enable; - struct gl_buffer_object *saved_array_vbo, *saved_texcoord_vbo; - GLenum saved_texcoord_type; - GLsizei saved_texcoord_size, saved_texcoord_stride; - const void *saved_texcoord_ptr; - int saved_active_texture; - - GLint saved_vp_x, saved_vp_y; - GLsizei saved_vp_width, saved_vp_height; - GLenum saved_matrix_mode; -}; - - -void meta_set_passthrough_transform(struct dri_metaops *meta); - -void meta_restore_transform(struct dri_metaops *meta); - -void meta_set_passthrough_vertex_program(struct dri_metaops *meta); - -void meta_restore_vertex_program(struct dri_metaops *meta); - -void meta_set_fragment_program(struct dri_metaops *meta, - struct gl_fragment_program **prog, - const char *prog_string); - -void meta_restore_fragment_program(struct dri_metaops *meta); - -void meta_set_default_texrect(struct dri_metaops *meta); - -void meta_restore_texcoords(struct dri_metaops *meta); - -void meta_init_metaops(struct gl_context *ctx, struct dri_metaops *meta); -void meta_destroy_metaops(struct dri_metaops *meta); - -#endif diff --git a/src/mesa/drivers/dri/common/dri_util.c b/src/mesa/drivers/dri/common/dri_util.c index bf8cf6eec07..82638fa7207 100644 --- a/src/mesa/drivers/dri/common/dri_util.c +++ b/src/mesa/drivers/dri/common/dri_util.c @@ -481,6 +481,22 @@ dri2CreateNewDrawable(__DRIscreen *screen, return pdraw; } +static __DRIbuffer * +dri2AllocateBuffer(__DRIscreen *screen, + unsigned int attachment, unsigned int format, + int width, int height) +{ + return (*screen->DriverAPI.AllocateBuffer)(screen, attachment, format, + width, height); +} + +static void +dri2ReleaseBuffer(__DRIscreen *screen, __DRIbuffer *buffer) +{ + (*screen->DriverAPI.ReleaseBuffer)(screen, buffer); +} + + static int dri2ConfigQueryb(__DRIscreen *screen, const char *var, GLboolean *val) { @@ -930,7 +946,9 @@ const __DRIdri2Extension driDRI2Extension = { dri2CreateNewDrawable, dri2CreateNewContext, dri2GetAPIMask, - dri2CreateNewContextForAPI + dri2CreateNewContextForAPI, + dri2AllocateBuffer, + dri2ReleaseBuffer }; const __DRI2configQueryExtension dri2ConfigQueryExtension = { diff --git a/src/mesa/drivers/dri/common/dri_util.h b/src/mesa/drivers/dri/common/dri_util.h index ffffb99b301..3d3d5c9cd24 100644 --- a/src/mesa/drivers/dri/common/dri_util.h +++ b/src/mesa/drivers/dri/common/dri_util.h @@ -223,6 +223,12 @@ struct __DriverAPIRec { /* DRI2 Entry point */ const __DRIconfig **(*InitScreen2) (__DRIscreen * priv); + + __DRIbuffer *(*AllocateBuffer) (__DRIscreen *screenPrivate, + unsigned int attachment, + unsigned int format, + int width, int height); + void (*ReleaseBuffer) (__DRIscreen *screenPrivate, __DRIbuffer *buffer); }; extern const struct __DriverAPIRec driDriverAPI; diff --git a/src/mesa/drivers/dri/common/drisw_util.c b/src/mesa/drivers/dri/common/drisw_util.c index 1529c23b16d..1bdb6d8939e 100644 --- a/src/mesa/drivers/dri/common/drisw_util.c +++ b/src/mesa/drivers/dri/common/drisw_util.c @@ -121,6 +121,48 @@ driCreateNewContext(__DRIscreen *psp, const __DRIconfig *config, return pcp; } +static __DRIcontext * +driCreateNewContextForAPI(__DRIscreen *psp, int api, + const __DRIconfig *config, + __DRIcontext *shared, void *data) +{ + __DRIcontext *pcp; + void * const shareCtx = (shared != NULL) ? shared->driverPrivate : NULL; + gl_api mesa_api; + + switch (api) { + case __DRI_API_OPENGL: + mesa_api = API_OPENGL; + break; + case __DRI_API_GLES: + mesa_api = API_OPENGLES; + break; + case __DRI_API_GLES2: + mesa_api = API_OPENGLES2; + break; + default: + return NULL; + } + + pcp = CALLOC_STRUCT(__DRIcontextRec); + if (!pcp) + return NULL; + + pcp->loaderPrivate = data; + + pcp->driScreenPriv = psp; + pcp->driDrawablePriv = NULL; + pcp->driReadablePriv = NULL; + + if (!driDriverAPI.CreateContext(mesa_api, + &config->modes, pcp, shareCtx)) { + FREE(pcp); + return NULL; + } + + return pcp; +} + static void driDestroyContext(__DRIcontext *pcp) { @@ -269,5 +311,6 @@ const __DRIcoreExtension driCoreExtension = { const __DRIswrastExtension driSWRastExtension = { { __DRI_SWRAST, __DRI_SWRAST_VERSION }, driCreateNewScreen, - driCreateNewDrawable + driCreateNewDrawable, + driCreateNewContextForAPI }; diff --git a/src/mesa/drivers/dri/i810/i810context.c b/src/mesa/drivers/dri/i810/i810context.c index dc58e91e8c1..90dbb6bbe80 100644 --- a/src/mesa/drivers/dri/i810/i810context.c +++ b/src/mesa/drivers/dri/i810/i810context.c @@ -204,7 +204,7 @@ i810CreateContext( gl_api api, shareCtx = ((i810ContextPtr) sharedContextPrivate)->glCtx; else shareCtx = NULL; - imesa->glCtx = _mesa_create_context(mesaVis, shareCtx, + imesa->glCtx = _mesa_create_context(API_OPENGL, mesaVis, shareCtx, &functions, (void*) imesa); if (!imesa->glCtx) { FREE(imesa); diff --git a/src/mesa/drivers/dri/i915/i830_vtbl.c b/src/mesa/drivers/dri/i915/i830_vtbl.c index ebdefeac874..19f08077599 100644 --- a/src/mesa/drivers/dri/i915/i830_vtbl.c +++ b/src/mesa/drivers/dri/i915/i830_vtbl.c @@ -364,7 +364,7 @@ i830_emit_invarient_state(struct intel_context *intel) #define emit( intel, state, size ) \ - intel_batchbuffer_data(intel->batch, state, size, false) + intel_batchbuffer_data(intel, state, size, false) static GLuint get_dirty(struct i830_hw_state *state) @@ -428,7 +428,7 @@ i830_emit_state(struct intel_context *intel) * scheduling is allowed, rather than assume that it is whenever a * batchbuffer fills up. */ - intel_batchbuffer_require_space(intel->batch, + intel_batchbuffer_require_space(intel, get_state_size(state) + INTEL_PRIM_EMIT_SIZE, false); count = 0; @@ -436,7 +436,7 @@ i830_emit_state(struct intel_context *intel) aper_count = 0; dirty = get_dirty(state); - aper_array[aper_count++] = intel->batch->buf; + aper_array[aper_count++] = intel->batch.bo; if (dirty & I830_UPLOAD_BUFFERS) { aper_array[aper_count++] = state->draw_region->buffer; if (state->depth_region) @@ -453,7 +453,7 @@ i830_emit_state(struct intel_context *intel) if (dri_bufmgr_check_aperture_space(aper_array, aper_count)) { if (count == 0) { count++; - intel_batchbuffer_flush(intel->batch); + intel_batchbuffer_flush(intel); goto again; } else { _mesa_error(ctx, GL_OUT_OF_MEMORY, "i830 emit state"); @@ -556,9 +556,7 @@ i830_emit_state(struct intel_context *intel) } } - intel->batch->dirty_state &= ~dirty; assert(get_dirty(state) == 0); - assert((intel->batch->dirty_state & (1<<1)) == 0); } static void diff --git a/src/mesa/drivers/dri/i915/i915_context.c b/src/mesa/drivers/dri/i915/i915_context.c index 474252b640d..7389a1d57a9 100644 --- a/src/mesa/drivers/dri/i915/i915_context.c +++ b/src/mesa/drivers/dri/i915/i915_context.c @@ -188,9 +188,17 @@ i915CreateContext(int api, * FINISHME: vertex shaders? */ ctx->ShaderCompilerOptions[MESA_SHADER_VERTEX].EmitCondCodes = GL_TRUE; - ctx->ShaderCompilerOptions[MESA_SHADER_FRAGMENT].EmitNoIfs = GL_TRUE; - ctx->ShaderCompilerOptions[MESA_SHADER_FRAGMENT].EmitNoNoise = GL_TRUE; - ctx->ShaderCompilerOptions[MESA_SHADER_FRAGMENT].EmitNoPow = GL_TRUE; + + struct gl_shader_compiler_options *const fs_options = + & ctx->ShaderCompilerOptions[MESA_SHADER_FRAGMENT]; + fs_options->EmitNoIfs = GL_TRUE; + fs_options->EmitNoNoise = GL_TRUE; + fs_options->EmitNoPow = GL_TRUE; + fs_options->EmitNoMainReturn = GL_TRUE; + fs_options->EmitNoIndirectInput = GL_TRUE; + fs_options->EmitNoIndirectOutput = GL_TRUE; + fs_options->EmitNoIndirectUniform = GL_TRUE; + fs_options->EmitNoIndirectTemp = GL_TRUE; ctx->Const.MaxDrawBuffers = 1; diff --git a/src/mesa/drivers/dri/i915/i915_context.h b/src/mesa/drivers/dri/i915/i915_context.h index 2c80ded075b..601620275f4 100644 --- a/src/mesa/drivers/dri/i915/i915_context.h +++ b/src/mesa/drivers/dri/i915/i915_context.h @@ -29,7 +29,6 @@ #define I915CONTEXT_INC #include "intel_context.h" -#include "i915_reg.h" #define I915_FALLBACK_TEXTURE 0x1000 #define I915_FALLBACK_COLORMASK 0x2000 @@ -51,6 +50,7 @@ #define I915_UPLOAD_INVARIENT 0x40 #define I915_UPLOAD_DEFAULTS 0x80 #define I915_UPLOAD_RASTER_RULES 0x100 +#define I915_UPLOAD_BLEND 0x200 #define I915_UPLOAD_TEX(i) (0x00010000<<(i)) #define I915_UPLOAD_TEX_ALL (0x00ff0000) #define I915_UPLOAD_TEX_0_SHIFT 16 @@ -77,17 +77,19 @@ #define I915_DEST_SETUP_SIZE 18 #define I915_CTXREG_STATE4 0 -#define I915_CTXREG_LI 1 -#define I915_CTXREG_LIS2 2 -#define I915_CTXREG_LIS4 3 -#define I915_CTXREG_LIS5 4 -#define I915_CTXREG_LIS6 5 -#define I915_CTXREG_IAB 6 -#define I915_CTXREG_BLENDCOLOR0 7 -#define I915_CTXREG_BLENDCOLOR1 8 -#define I915_CTXREG_BF_STENCIL_OPS 9 -#define I915_CTXREG_BF_STENCIL_MASKS 10 -#define I915_CTX_SETUP_SIZE 11 +#define I915_CTXREG_LI 1 +#define I915_CTXREG_LIS2 2 +#define I915_CTXREG_LIS4 3 +#define I915_CTXREG_LIS5 4 +#define I915_CTXREG_LIS6 5 +#define I915_CTXREG_BF_STENCIL_OPS 6 +#define I915_CTXREG_BF_STENCIL_MASKS 7 +#define I915_CTX_SETUP_SIZE 8 + +#define I915_BLENDREG_IAB 0 +#define I915_BLENDREG_BLENDCOLOR0 1 +#define I915_BLENDREG_BLENDCOLOR1 2 +#define I915_BLEND_SETUP_SIZE 3 #define I915_FOGREG_COLOR 0 #define I915_FOGREG_MODE0 1 @@ -123,6 +125,12 @@ enum { #define I915_MAX_CONSTANT 32 #define I915_CONSTANT_SIZE (2+(4*I915_MAX_CONSTANT)) +#define I915_MAX_TEX_INDIRECT 4 +#define I915_MAX_TEX_INSN 32 +#define I915_MAX_ALU_INSN 64 +#define I915_MAX_DECL_INSN 27 +#define I915_MAX_TEMPORARY 16 + #define I915_MAX_INSN (I915_MAX_DECL_INSN + \ I915_MAX_TEX_INSN + \ I915_MAX_ALU_INSN) @@ -216,6 +224,7 @@ struct i915_fragment_program struct i915_hw_state { GLuint Ctx[I915_CTX_SETUP_SIZE]; + GLuint Blend[I915_BLEND_SETUP_SIZE]; GLuint Buffer[I915_DEST_SETUP_SIZE]; GLuint Stipple[I915_STP_SETUP_SIZE]; GLuint Fog[I915_FOG_SETUP_SIZE]; @@ -260,8 +269,12 @@ struct i915_context struct i915_fragment_program *current_program; + drm_intel_bo *current_vb_bo; + unsigned int current_vertex_size; + struct i915_hw_state state; uint32_t last_draw_offset; + GLuint last_sampler; }; diff --git a/src/mesa/drivers/dri/i915/i915_fragprog.c b/src/mesa/drivers/dri/i915/i915_fragprog.c index 1c6e9845172..25f4fc3c8b1 100644 --- a/src/mesa/drivers/dri/i915/i915_fragprog.c +++ b/src/mesa/drivers/dri/i915/i915_fragprog.c @@ -306,6 +306,7 @@ static void calc_live_regs( struct i915_fragment_program *p ) { const struct gl_fragment_program *program = p->ctx->FragmentProgram._Current; GLuint regsUsed = 0xffff0000; + uint8_t live_components[16] = { 0, }; GLint i; for (i = program->Base.NumInstructions - 1; i >= 0; i--) { @@ -314,13 +315,26 @@ static void calc_live_regs( struct i915_fragment_program *p ) int a; /* Register is written to: unmark as live for this and preceeding ops */ - if (inst->DstReg.File == PROGRAM_TEMPORARY) - regsUsed &= ~(1 << inst->DstReg.Index); + if (inst->DstReg.File == PROGRAM_TEMPORARY) { + live_components[inst->DstReg.Index] &= ~inst->DstReg.WriteMask; + if (live_components[inst->DstReg.Index] == 0) + regsUsed &= ~(1 << inst->DstReg.Index); + } for (a = 0; a < opArgs; a++) { /* Register is read from: mark as live for this and preceeding ops */ - if (inst->SrcReg[a].File == PROGRAM_TEMPORARY) + if (inst->SrcReg[a].File == PROGRAM_TEMPORARY) { + unsigned c; + regsUsed |= 1 << inst->SrcReg[a].Index; + + for (c = 0; c < 4; c++) { + const unsigned field = GET_SWZ(inst->SrcReg[a].Swizzle, c); + + if (field <= SWIZZLE_W) + live_components[inst->SrcReg[a].Index] |= (1U << field); + } + } } p->usedRegs[i] = regsUsed; @@ -795,18 +809,18 @@ upload_program(struct i915_fragment_program *p) flags = get_result_flags(inst); dst = get_result_vector(p, inst); - /* dst = src1 >= src2 */ + /* tmp = src1 >= src2 */ i915_emit_arith(p, A0_SGE, - dst, + tmp, flags, 0, src_vector(p, &inst->SrcReg[0], program), src_vector(p, &inst->SrcReg[1], program), 0); - /* tmp = src1 <= src2 */ + /* dst = src1 <= src2 */ i915_emit_arith(p, A0_SGE, - tmp, + dst, flags, 0, negate(src_vector(p, &inst->SrcReg[0], program), 1, 1, 1, 1), @@ -944,18 +958,18 @@ upload_program(struct i915_fragment_program *p) flags = get_result_flags(inst); dst = get_result_vector(p, inst); - /* dst = src1 < src2 */ + /* tmp = src1 < src2 */ i915_emit_arith(p, A0_SLT, - dst, + tmp, flags, 0, src_vector(p, &inst->SrcReg[0], program), src_vector(p, &inst->SrcReg[1], program), 0); - /* tmp = src1 > src2 */ + /* dst = src1 > src2 */ i915_emit_arith(p, A0_SLT, - tmp, + dst, flags, 0, negate(src_vector(p, &inst->SrcReg[0], program), 1, 1, 1, 1), @@ -1408,6 +1422,10 @@ i915ValidateFragmentProgram(struct i915_context *i915) intel->vertex_attr_count, intel->ViewportMatrix.m, 0); + assert(intel->prim.current_offset == intel->prim.start_offset); + intel->prim.start_offset = (intel->prim.current_offset + intel->vertex_size-1) / intel->vertex_size * intel->vertex_size; + intel->prim.current_offset = intel->prim.start_offset; + intel->vertex_size >>= 2; i915->state.Ctx[I915_CTXREG_LIS2] = s2; diff --git a/src/mesa/drivers/dri/i915/i915_program.c b/src/mesa/drivers/dri/i915/i915_program.c index ca1949b223e..507adf1d3dc 100644 --- a/src/mesa/drivers/dri/i915/i915_program.c +++ b/src/mesa/drivers/dri/i915/i915_program.c @@ -538,6 +538,7 @@ i915_upload_program(struct i915_context *i915, { GLuint program_size = p->csr - p->program; GLuint decl_size = p->decl - p->declarations; + GLuint nr; if (p->error) return; @@ -554,32 +555,32 @@ i915_upload_program(struct i915_context *i915, i915->state.ProgramSize = decl_size + program_size; } - /* Always seemed to get a failure if I used memcmp() to - * shortcircuit this state upload. Needs further investigation? - */ - if (p->nr_constants) { - GLuint nr = p->nr_constants; - - I915_ACTIVESTATE(i915, I915_UPLOAD_CONSTANTS, 1); - I915_STATECHANGE(i915, I915_UPLOAD_CONSTANTS); - - i915->state.Constant[0] = _3DSTATE_PIXEL_SHADER_CONSTANTS | ((nr) * 4); - i915->state.Constant[1] = (1 << (nr - 1)) | ((1 << (nr - 1)) - 1); - - memcpy(&i915->state.Constant[2], p->constant, 4 * sizeof(int) * (nr)); - i915->state.ConstantSize = 2 + (nr) * 4; - - if (0) { - GLuint i; - for (i = 0; i < nr; i++) { - fprintf(stderr, "const[%d]: %f %f %f %f\n", i, - p->constant[i][0], - p->constant[i][1], p->constant[i][2], p->constant[i][3]); - } + nr = p->nr_constants; + if (i915->state.ConstantSize != 2 + nr*4 || + memcmp(i915->state.Constant + 2, + p->constant, 4*sizeof(int)*nr)) { + if (nr) { + I915_ACTIVESTATE(i915, I915_UPLOAD_CONSTANTS, 1); + I915_STATECHANGE(i915, I915_UPLOAD_CONSTANTS); + + i915->state.Constant[0] = _3DSTATE_PIXEL_SHADER_CONSTANTS | (nr * 4); + i915->state.Constant[1] = (1 << nr) -1; + + memcpy(&i915->state.Constant[2], p->constant, 4 * sizeof(int) * nr); + i915->state.ConstantSize = 2 + nr * 4; + + if (0) { + GLuint i; + for (i = 0; i < nr; i++) { + fprintf(stderr, "const[%d]: %f %f %f %f\n", i, + p->constant[i][0], + p->constant[i][1], p->constant[i][2], p->constant[i][3]); + } + } + } + else { + I915_ACTIVESTATE(i915, I915_UPLOAD_CONSTANTS, 0); } - } - else { - I915_ACTIVESTATE(i915, I915_UPLOAD_CONSTANTS, 0); } p->on_hardware = 1; diff --git a/src/mesa/drivers/dri/i915/i915_reg.h b/src/mesa/drivers/dri/i915/i915_reg.h index 7f31ff674f2..766547a4c6a 100644 --- a/src/mesa/drivers/dri/i915/i915_reg.h +++ b/src/mesa/drivers/dri/i915/i915_reg.h @@ -361,13 +361,6 @@ /* p222 */ -#define I915_MAX_TEX_INDIRECT 4 -#define I915_MAX_TEX_INSN 32 -#define I915_MAX_ALU_INSN 64 -#define I915_MAX_DECL_INSN 27 -#define I915_MAX_TEMPORARY 16 - - /* Each instruction is 3 dwords long, though most don't require all * this space. Maximum of 123 instructions. Smaller maxes per insn * type. diff --git a/src/mesa/drivers/dri/i915/i915_state.c b/src/mesa/drivers/dri/i915/i915_state.c index 63c6e78ebe9..58d4f5daffd 100644 --- a/src/mesa/drivers/dri/i915/i915_state.c +++ b/src/mesa/drivers/dri/i915/i915_state.c @@ -56,8 +56,7 @@ i915_update_stencil(struct gl_context * ctx) GLenum front_func, front_fail, front_pass_z_fail, front_pass_z_pass; GLuint back_ref, back_writemask, back_mask; GLenum back_func, back_fail, back_pass_z_fail, back_pass_z_pass; - - I915_STATECHANGE(i915, I915_UPLOAD_CTX); + GLuint dirty = 0; /* The 915 considers CW to be "front" for two-sided stencil, so choose * appropriately. @@ -94,56 +93,68 @@ i915_update_stencil(struct gl_context * ctx) back_pass_z_fail = ctx->Stencil.ZFailFunc[0]; back_pass_z_pass = ctx->Stencil.ZPassFunc[0]; } +#define set_ctx_bits(reg, mask, set) do{ \ + GLuint dw = i915->state.Ctx[reg]; \ + dw &= ~(mask); \ + dw |= (set); \ + dirty |= dw != i915->state.Ctx[reg]; \ + i915->state.Ctx[reg] = dw; \ +} while(0) /* Set front state. */ - i915->state.Ctx[I915_CTXREG_STATE4] &= ~(MODE4_ENABLE_STENCIL_TEST_MASK | - MODE4_ENABLE_STENCIL_WRITE_MASK); - i915->state.Ctx[I915_CTXREG_STATE4] |= (ENABLE_STENCIL_TEST_MASK | - ENABLE_STENCIL_WRITE_MASK | - STENCIL_TEST_MASK(front_mask) | - STENCIL_WRITE_MASK(front_writemask)); - - i915->state.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_REF_MASK | - S5_STENCIL_TEST_FUNC_MASK | - S5_STENCIL_FAIL_MASK | - S5_STENCIL_PASS_Z_FAIL_MASK | - S5_STENCIL_PASS_Z_PASS_MASK); - - i915->state.Ctx[I915_CTXREG_LIS5] |= - (front_ref << S5_STENCIL_REF_SHIFT) | - (intel_translate_compare_func(front_func) << S5_STENCIL_TEST_FUNC_SHIFT) | - (intel_translate_stencil_op(front_fail) << S5_STENCIL_FAIL_SHIFT) | - (intel_translate_stencil_op(front_pass_z_fail) << - S5_STENCIL_PASS_Z_FAIL_SHIFT) | - (intel_translate_stencil_op(front_pass_z_pass) << - S5_STENCIL_PASS_Z_PASS_SHIFT); + set_ctx_bits(I915_CTXREG_STATE4, + MODE4_ENABLE_STENCIL_TEST_MASK | + MODE4_ENABLE_STENCIL_WRITE_MASK, + ENABLE_STENCIL_TEST_MASK | + ENABLE_STENCIL_WRITE_MASK | + STENCIL_TEST_MASK(front_mask) | + STENCIL_WRITE_MASK(front_writemask)); + + set_ctx_bits(I915_CTXREG_LIS5, + S5_STENCIL_REF_MASK | + S5_STENCIL_TEST_FUNC_MASK | + S5_STENCIL_FAIL_MASK | + S5_STENCIL_PASS_Z_FAIL_MASK | + S5_STENCIL_PASS_Z_PASS_MASK, + (front_ref << S5_STENCIL_REF_SHIFT) | + (intel_translate_compare_func(front_func) << S5_STENCIL_TEST_FUNC_SHIFT) | + (intel_translate_stencil_op(front_fail) << S5_STENCIL_FAIL_SHIFT) | + (intel_translate_stencil_op(front_pass_z_fail) << + S5_STENCIL_PASS_Z_FAIL_SHIFT) | + (intel_translate_stencil_op(front_pass_z_pass) << + S5_STENCIL_PASS_Z_PASS_SHIFT)); /* Set back state if different from front. */ if (ctx->Stencil._TestTwoSide) { - i915->state.Ctx[I915_CTXREG_BF_STENCIL_OPS] &= - ~(BFO_STENCIL_REF_MASK | - BFO_STENCIL_TEST_MASK | - BFO_STENCIL_FAIL_MASK | - BFO_STENCIL_PASS_Z_FAIL_MASK | - BFO_STENCIL_PASS_Z_PASS_MASK); - i915->state.Ctx[I915_CTXREG_BF_STENCIL_OPS] |= BFO_STENCIL_TWO_SIDE | - (back_ref << BFO_STENCIL_REF_SHIFT) | - (intel_translate_compare_func(back_func) << BFO_STENCIL_TEST_SHIFT) | - (intel_translate_stencil_op(back_fail) << BFO_STENCIL_FAIL_SHIFT) | - (intel_translate_stencil_op(back_pass_z_fail) << - BFO_STENCIL_PASS_Z_FAIL_SHIFT) | - (intel_translate_stencil_op(back_pass_z_pass) << - BFO_STENCIL_PASS_Z_PASS_SHIFT); - - i915->state.Ctx[I915_CTXREG_BF_STENCIL_MASKS] &= - ~(BFM_STENCIL_TEST_MASK_MASK | - BFM_STENCIL_WRITE_MASK_MASK); - i915->state.Ctx[I915_CTXREG_BF_STENCIL_MASKS] |= - BFM_STENCIL_TEST_MASK(back_mask) | - BFM_STENCIL_WRITE_MASK(back_writemask); + set_ctx_bits(I915_CTXREG_BF_STENCIL_OPS, + BFO_STENCIL_REF_MASK | + BFO_STENCIL_TEST_MASK | + BFO_STENCIL_FAIL_MASK | + BFO_STENCIL_PASS_Z_FAIL_MASK | + BFO_STENCIL_PASS_Z_PASS_MASK, + BFO_STENCIL_TWO_SIDE | + (back_ref << BFO_STENCIL_REF_SHIFT) | + (intel_translate_compare_func(back_func) << BFO_STENCIL_TEST_SHIFT) | + (intel_translate_stencil_op(back_fail) << BFO_STENCIL_FAIL_SHIFT) | + (intel_translate_stencil_op(back_pass_z_fail) << + BFO_STENCIL_PASS_Z_FAIL_SHIFT) | + (intel_translate_stencil_op(back_pass_z_pass) << + BFO_STENCIL_PASS_Z_PASS_SHIFT)); + + set_ctx_bits(I915_CTXREG_BF_STENCIL_MASKS, + BFM_STENCIL_TEST_MASK_MASK | + BFM_STENCIL_WRITE_MASK_MASK, + BFM_STENCIL_TEST_MASK(back_mask) | + BFM_STENCIL_WRITE_MASK(back_writemask)); } else { - i915->state.Ctx[I915_CTXREG_BF_STENCIL_OPS] &= ~BFO_STENCIL_TWO_SIDE; + set_ctx_bits(I915_CTXREG_BF_STENCIL_OPS, + BFO_STENCIL_TWO_SIDE, 0); } + +#undef set_ctx_bits + + if (dirty) + I915_STATECHANGE(i915, I915_UPLOAD_CTX); } static void @@ -169,15 +180,18 @@ i915AlphaFunc(struct gl_context * ctx, GLenum func, GLfloat ref) struct i915_context *i915 = I915_CONTEXT(ctx); int test = intel_translate_compare_func(func); GLubyte refByte; + GLuint dw; UNCLAMPED_FLOAT_TO_UBYTE(refByte, ref); - I915_STATECHANGE(i915, I915_UPLOAD_CTX); - i915->state.Ctx[I915_CTXREG_LIS6] &= ~(S6_ALPHA_TEST_FUNC_MASK | - S6_ALPHA_REF_MASK); - i915->state.Ctx[I915_CTXREG_LIS6] |= ((test << S6_ALPHA_TEST_FUNC_SHIFT) | - (((GLuint) refByte) << - S6_ALPHA_REF_SHIFT)); + dw = i915->state.Ctx[I915_CTXREG_LIS6]; + dw &= ~(S6_ALPHA_TEST_FUNC_MASK | S6_ALPHA_REF_MASK); + dw |= ((test << S6_ALPHA_TEST_FUNC_SHIFT) | + (((GLuint) refByte) << S6_ALPHA_REF_SHIFT)); + if (dw != i915->state.Ctx[I915_CTXREG_LIS6]) { + i915->state.Ctx[I915_CTXREG_LIS6] = dw; + I915_STATECHANGE(i915, I915_UPLOAD_CTX); + } } /* This function makes sure that the proper enables are @@ -190,23 +204,32 @@ static void i915EvalLogicOpBlendState(struct gl_context * ctx) { struct i915_context *i915 = I915_CONTEXT(ctx); + GLuint dw0, dw1; - I915_STATECHANGE(i915, I915_UPLOAD_CTX); + dw0 = i915->state.Ctx[I915_CTXREG_LIS5]; + dw1 = i915->state.Ctx[I915_CTXREG_LIS6]; if (RGBA_LOGICOP_ENABLED(ctx)) { - i915->state.Ctx[I915_CTXREG_LIS5] |= S5_LOGICOP_ENABLE; - i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_CBUF_BLEND_ENABLE; + dw0 |= S5_LOGICOP_ENABLE; + dw1 &= ~S6_CBUF_BLEND_ENABLE; } else { - i915->state.Ctx[I915_CTXREG_LIS5] &= ~S5_LOGICOP_ENABLE; + dw0 &= ~S5_LOGICOP_ENABLE; if (ctx->Color.BlendEnabled) { - i915->state.Ctx[I915_CTXREG_LIS6] |= S6_CBUF_BLEND_ENABLE; + dw1 |= S6_CBUF_BLEND_ENABLE; } else { - i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_CBUF_BLEND_ENABLE; + dw1 &= ~S6_CBUF_BLEND_ENABLE; } } + if (dw0 != i915->state.Ctx[I915_CTXREG_LIS5] || + dw1 != i915->state.Ctx[I915_CTXREG_LIS6]) { + i915->state.Ctx[I915_CTXREG_LIS5] = dw0; + i915->state.Ctx[I915_CTXREG_LIS6] = dw1; + + I915_STATECHANGE(i915, I915_UPLOAD_CTX); + } } static void @@ -214,6 +237,7 @@ i915BlendColor(struct gl_context * ctx, const GLfloat color[4]) { struct i915_context *i915 = I915_CONTEXT(ctx); GLubyte r, g, b, a; + GLuint dw; DBG("%s\n", __FUNCTION__); @@ -222,9 +246,11 @@ i915BlendColor(struct gl_context * ctx, const GLfloat color[4]) UNCLAMPED_FLOAT_TO_UBYTE(b, color[BCOMP]); UNCLAMPED_FLOAT_TO_UBYTE(a, color[ACOMP]); - I915_STATECHANGE(i915, I915_UPLOAD_CTX); - i915->state.Ctx[I915_CTXREG_BLENDCOLOR1] = - (a << 24) | (r << 16) | (g << 8) | b; + dw = (a << 24) | (r << 16) | (g << 8) | b; + if (dw != i915->state.Blend[I915_BLENDREG_BLENDCOLOR1]) { + i915->state.Blend[I915_BLENDREG_BLENDCOLOR1] = dw; + I915_STATECHANGE(i915, I915_UPLOAD_BLEND); + } } @@ -258,7 +284,7 @@ static void i915UpdateBlendState(struct gl_context * ctx) { struct i915_context *i915 = I915_CONTEXT(ctx); - GLuint iab = (i915->state.Ctx[I915_CTXREG_IAB] & + GLuint iab = (i915->state.Blend[I915_BLENDREG_IAB] & ~(IAB_SRC_FACTOR_MASK | IAB_DST_FACTOR_MASK | (BLENDFUNC_MASK << IAB_FUNC_SHIFT) | IAB_ENABLE)); @@ -293,11 +319,13 @@ i915UpdateBlendState(struct gl_context * ctx) if (srcA != srcRGB || dstA != dstRGB || eqA != eqRGB) iab |= IAB_ENABLE; - if (iab != i915->state.Ctx[I915_CTXREG_IAB] || - lis6 != i915->state.Ctx[I915_CTXREG_LIS6]) { - I915_STATECHANGE(i915, I915_UPLOAD_CTX); - i915->state.Ctx[I915_CTXREG_IAB] = iab; + if (iab != i915->state.Blend[I915_BLENDREG_IAB]) { + i915->state.Blend[I915_BLENDREG_IAB] = iab; + I915_STATECHANGE(i915, I915_UPLOAD_BLEND); + } + if (lis6 != i915->state.Ctx[I915_CTXREG_LIS6]) { i915->state.Ctx[I915_CTXREG_LIS6] = lis6; + I915_STATECHANGE(i915, I915_UPLOAD_CTX); } /* This will catch a logicop blend equation */ @@ -325,27 +353,36 @@ i915DepthFunc(struct gl_context * ctx, GLenum func) { struct i915_context *i915 = I915_CONTEXT(ctx); int test = intel_translate_compare_func(func); + GLuint dw; DBG("%s\n", __FUNCTION__); - I915_STATECHANGE(i915, I915_UPLOAD_CTX); - i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_DEPTH_TEST_FUNC_MASK; - i915->state.Ctx[I915_CTXREG_LIS6] |= test << S6_DEPTH_TEST_FUNC_SHIFT; + dw = i915->state.Ctx[I915_CTXREG_LIS6]; + dw &= ~S6_DEPTH_TEST_FUNC_MASK; + dw |= test << S6_DEPTH_TEST_FUNC_SHIFT; + if (dw != i915->state.Ctx[I915_CTXREG_LIS6]) { + I915_STATECHANGE(i915, I915_UPLOAD_CTX); + i915->state.Ctx[I915_CTXREG_LIS6] = dw; + } } static void i915DepthMask(struct gl_context * ctx, GLboolean flag) { struct i915_context *i915 = I915_CONTEXT(ctx); + GLuint dw; DBG("%s flag (%d)\n", __FUNCTION__, flag); - - I915_STATECHANGE(i915, I915_UPLOAD_CTX); + dw = i915->state.Ctx[I915_CTXREG_LIS6]; if (flag && ctx->Depth.Test) - i915->state.Ctx[I915_CTXREG_LIS6] |= S6_DEPTH_WRITE_ENABLE; + dw |= S6_DEPTH_WRITE_ENABLE; else - i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_DEPTH_WRITE_ENABLE; + dw &= ~S6_DEPTH_WRITE_ENABLE; + if (dw != i915->state.Ctx[I915_CTXREG_LIS6]) { + I915_STATECHANGE(i915, I915_UPLOAD_CTX); + i915->state.Ctx[I915_CTXREG_LIS6] = dw; + } } @@ -532,7 +569,7 @@ static void i915CullFaceFrontFace(struct gl_context * ctx, GLenum unused) { struct i915_context *i915 = I915_CONTEXT(ctx); - GLuint mode; + GLuint mode, dw; DBG("%s %d\n", __FUNCTION__, ctx->DrawBuffer ? ctx->DrawBuffer->Name : 0); @@ -554,9 +591,13 @@ i915CullFaceFrontFace(struct gl_context * ctx, GLenum unused) mode = S4_CULLMODE_BOTH; } - I915_STATECHANGE(i915, I915_UPLOAD_CTX); - i915->state.Ctx[I915_CTXREG_LIS4] &= ~S4_CULLMODE_MASK; - i915->state.Ctx[I915_CTXREG_LIS4] |= mode; + dw = i915->state.Ctx[I915_CTXREG_LIS4]; + dw &= ~S4_CULLMODE_MASK; + dw |= mode; + if (dw != i915->state.Ctx[I915_CTXREG_LIS4]) { + i915->state.Ctx[I915_CTXREG_LIS4] = dw; + I915_STATECHANGE(i915, I915_UPLOAD_CTX); + } } static void @@ -690,6 +731,7 @@ i915_update_fog(struct gl_context * ctx) GLenum mode; GLboolean enabled; GLboolean try_pixel_fog; + GLuint dw; if (ctx->FragmentProgram._Current) { /* Pull in static fog state from program */ @@ -765,12 +807,16 @@ i915_update_fog(struct gl_context * ctx) i915->vertex_fog = I915_FOG_VERTEX; } - I915_STATECHANGE(i915, I915_UPLOAD_CTX); I915_ACTIVESTATE(i915, I915_UPLOAD_FOG, enabled); + dw = i915->state.Ctx[I915_CTXREG_LIS5]; if (enabled) - i915->state.Ctx[I915_CTXREG_LIS5] |= S5_FOG_ENABLE; + dw |= S5_FOG_ENABLE; else - i915->state.Ctx[I915_CTXREG_LIS5] &= ~S5_FOG_ENABLE; + dw &= ~S5_FOG_ENABLE; + if (dw != i915->state.Ctx[I915_CTXREG_LIS5]) { + i915->state.Ctx[I915_CTXREG_LIS5] = dw; + I915_STATECHANGE(i915, I915_UPLOAD_CTX); + } /* Always enable pixel fog. Vertex fog using fog coord will conflict * with fog code appended onto fragment program. @@ -837,6 +883,7 @@ static void i915Enable(struct gl_context * ctx, GLenum cap, GLboolean state) { struct i915_context *i915 = I915_CONTEXT(ctx); + GLuint dw; switch (cap) { case GL_TEXTURE_2D: @@ -848,11 +895,15 @@ i915Enable(struct gl_context * ctx, GLenum cap, GLboolean state) break; case GL_ALPHA_TEST: - I915_STATECHANGE(i915, I915_UPLOAD_CTX); + dw = i915->state.Ctx[I915_CTXREG_LIS6]; if (state) - i915->state.Ctx[I915_CTXREG_LIS6] |= S6_ALPHA_TEST_ENABLE; + dw |= S6_ALPHA_TEST_ENABLE; else - i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_ALPHA_TEST_ENABLE; + dw &= ~S6_ALPHA_TEST_ENABLE; + if (dw != i915->state.Ctx[I915_CTXREG_LIS6]) { + i915->state.Ctx[I915_CTXREG_LIS6] = dw; + I915_STATECHANGE(i915, I915_UPLOAD_CTX); + } break; case GL_BLEND: @@ -872,19 +923,27 @@ i915Enable(struct gl_context * ctx, GLenum cap, GLboolean state) break; case GL_DITHER: - I915_STATECHANGE(i915, I915_UPLOAD_CTX); + dw = i915->state.Ctx[I915_CTXREG_LIS5]; if (state) - i915->state.Ctx[I915_CTXREG_LIS5] |= S5_COLOR_DITHER_ENABLE; + dw |= S5_COLOR_DITHER_ENABLE; else - i915->state.Ctx[I915_CTXREG_LIS5] &= ~S5_COLOR_DITHER_ENABLE; + dw &= ~S5_COLOR_DITHER_ENABLE; + if (dw != i915->state.Ctx[I915_CTXREG_LIS5]) { + i915->state.Ctx[I915_CTXREG_LIS5] = dw; + I915_STATECHANGE(i915, I915_UPLOAD_CTX); + } break; case GL_DEPTH_TEST: - I915_STATECHANGE(i915, I915_UPLOAD_CTX); + dw = i915->state.Ctx[I915_CTXREG_LIS6]; if (state) - i915->state.Ctx[I915_CTXREG_LIS6] |= S6_DEPTH_TEST_ENABLE; + dw |= S6_DEPTH_TEST_ENABLE; else - i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_DEPTH_TEST_ENABLE; + dw &= ~S6_DEPTH_TEST_ENABLE; + if (dw != i915->state.Ctx[I915_CTXREG_LIS6]) { + i915->state.Ctx[I915_CTXREG_LIS6] = dw; + I915_STATECHANGE(i915, I915_UPLOAD_CTX); + } i915DepthMask(ctx, ctx->Depth.Mask); break; @@ -900,11 +959,15 @@ i915Enable(struct gl_context * ctx, GLenum cap, GLboolean state) break; case GL_LINE_SMOOTH: - I915_STATECHANGE(i915, I915_UPLOAD_CTX); + dw = i915->state.Ctx[I915_CTXREG_LIS4]; if (state) - i915->state.Ctx[I915_CTXREG_LIS4] |= S4_LINE_ANTIALIAS_ENABLE; + dw |= S4_LINE_ANTIALIAS_ENABLE; else - i915->state.Ctx[I915_CTXREG_LIS4] &= ~S4_LINE_ANTIALIAS_ENABLE; + dw &= ~S4_LINE_ANTIALIAS_ENABLE; + if (dw != i915->state.Ctx[I915_CTXREG_LIS4]) { + i915->state.Ctx[I915_CTXREG_LIS4] = dw; + I915_STATECHANGE(i915, I915_UPLOAD_CTX); + } break; case GL_FOG: @@ -923,13 +986,15 @@ i915Enable(struct gl_context * ctx, GLenum cap, GLboolean state) hw_stencil = (irbStencil && irbStencil->region); } if (hw_stencil) { - I915_STATECHANGE(i915, I915_UPLOAD_CTX); + dw = i915->state.Ctx[I915_CTXREG_LIS5]; if (state) - i915->state.Ctx[I915_CTXREG_LIS5] |= (S5_STENCIL_TEST_ENABLE | - S5_STENCIL_WRITE_ENABLE); + dw |= (S5_STENCIL_TEST_ENABLE | S5_STENCIL_WRITE_ENABLE); else - i915->state.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_TEST_ENABLE | - S5_STENCIL_WRITE_ENABLE); + dw &= ~(S5_STENCIL_TEST_ENABLE | S5_STENCIL_WRITE_ENABLE); + if (dw != i915->state.Ctx[I915_CTXREG_LIS5]) { + i915->state.Ctx[I915_CTXREG_LIS5] = dw; + I915_STATECHANGE(i915, I915_UPLOAD_CTX); + } } else { FALLBACK(&i915->intel, I915_FALLBACK_STENCIL, state); @@ -959,11 +1024,15 @@ i915Enable(struct gl_context * ctx, GLenum cap, GLboolean state) /* This state change is handled in i915_reduced_primitive_state because * the hardware bit should only be set when rendering points. */ - I915_STATECHANGE(i915, I915_UPLOAD_CTX); + dw = i915->state.Ctx[I915_CTXREG_LIS4]; if (state) - i915->state.Ctx[I915_CTXREG_LIS4] |= S4_SPRITE_POINT_ENABLE; + dw |= S4_SPRITE_POINT_ENABLE; else - i915->state.Ctx[I915_CTXREG_LIS4] &= ~S4_SPRITE_POINT_ENABLE; + dw &= ~S4_SPRITE_POINT_ENABLE; + if (dw != i915->state.Ctx[I915_CTXREG_LIS4]) { + i915->state.Ctx[I915_CTXREG_LIS4] = dw; + I915_STATECHANGE(i915, I915_UPLOAD_CTX); + } break; case GL_POINT_SMOOTH: @@ -984,6 +1053,7 @@ i915_init_packets(struct i915_context *i915) { I915_STATECHANGE(i915, I915_UPLOAD_CTX); + I915_STATECHANGE(i915, I915_UPLOAD_BLEND); /* Probably don't want to upload all this stuff every time one * piece changes. */ @@ -1010,13 +1080,13 @@ i915_init_packets(struct i915_context *i915) ENABLE_STENCIL_WRITE_MASK | STENCIL_WRITE_MASK(0xff)); - i915->state.Ctx[I915_CTXREG_IAB] = + i915->state.Blend[I915_BLENDREG_IAB] = (_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD | IAB_MODIFY_ENABLE | IAB_MODIFY_FUNC | IAB_MODIFY_SRC_FACTOR | IAB_MODIFY_DST_FACTOR); - i915->state.Ctx[I915_CTXREG_BLENDCOLOR0] = + i915->state.Blend[I915_BLENDREG_BLENDCOLOR0] = _3DSTATE_CONST_BLEND_COLOR_CMD; - i915->state.Ctx[I915_CTXREG_BLENDCOLOR1] = 0; + i915->state.Blend[I915_BLENDREG_BLENDCOLOR1] = 0; i915->state.Ctx[I915_CTXREG_BF_STENCIL_MASKS] = _3DSTATE_BACKFACE_STENCIL_MASKS | @@ -1087,6 +1157,7 @@ i915_init_packets(struct i915_context *i915) i915->state.active = (I915_UPLOAD_PROGRAM | I915_UPLOAD_STIPPLE | I915_UPLOAD_CTX | + I915_UPLOAD_BLEND | I915_UPLOAD_BUFFERS | I915_UPLOAD_INVARIENT | I915_UPLOAD_RASTER_RULES); diff --git a/src/mesa/drivers/dri/i915/i915_vtbl.c b/src/mesa/drivers/dri/i915/i915_vtbl.c index a94b9571275..921183b81df 100644 --- a/src/mesa/drivers/dri/i915/i915_vtbl.c +++ b/src/mesa/drivers/dri/i915/i915_vtbl.c @@ -217,7 +217,7 @@ i915_emit_invarient_state(struct intel_context *intel) #define emit(intel, state, size ) \ - intel_batchbuffer_data(intel->batch, state, size, false) + intel_batchbuffer_data(intel, state, size, false) static GLuint get_dirty(struct i915_hw_state *state) @@ -251,6 +251,9 @@ get_state_size(struct i915_hw_state *state) if (dirty & I915_UPLOAD_CTX) sz += sizeof(state->Ctx); + if (dirty & I915_UPLOAD_BLEND) + sz += sizeof(state->Blend); + if (dirty & I915_UPLOAD_BUFFERS) sz += sizeof(state->Buffer); @@ -299,7 +302,7 @@ i915_emit_state(struct intel_context *intel) * scheduling is allowed, rather than assume that it is whenever a * batchbuffer fills up. */ - intel_batchbuffer_require_space(intel->batch, + intel_batchbuffer_require_space(intel, get_state_size(state) + INTEL_PRIM_EMIT_SIZE, false); count = 0; @@ -307,7 +310,7 @@ i915_emit_state(struct intel_context *intel) aper_count = 0; dirty = get_dirty(state); - aper_array[aper_count++] = intel->batch->buf; + aper_array[aper_count++] = intel->batch.bo; if (dirty & I915_UPLOAD_BUFFERS) { aper_array[aper_count++] = state->draw_region->buffer; if (state->depth_region) @@ -327,7 +330,7 @@ i915_emit_state(struct intel_context *intel) if (dri_bufmgr_check_aperture_space(aper_array, aper_count)) { if (count == 0) { count++; - intel_batchbuffer_flush(intel->batch); + intel_batchbuffer_flush(intel); goto again; } else { _mesa_error(ctx, GL_OUT_OF_MEMORY, "i915 emit state"); @@ -366,6 +369,13 @@ i915_emit_state(struct intel_context *intel) emit(intel, state->Ctx, sizeof(state->Ctx)); } + if (dirty & I915_UPLOAD_BLEND) { + if (INTEL_DEBUG & DEBUG_STATE) + fprintf(stderr, "I915_UPLOAD_BLEND:\n"); + + emit(intel, state->Blend, sizeof(state->Blend)); + } + if (dirty & I915_UPLOAD_BUFFERS) { GLuint count; @@ -426,6 +436,7 @@ i915_emit_state(struct intel_context *intel) */ if (dirty & I915_UPLOAD_TEX_ALL) { int nr = 0; + GLuint unwind; for (i = 0; i < I915_TEX_UNITS; i++) if (dirty & I915_UPLOAD_TEX(i)) @@ -445,6 +456,7 @@ i915_emit_state(struct intel_context *intel) } ADVANCE_BATCH(); + unwind = intel->batch.used; BEGIN_BATCH(2 + nr * 3); OUT_BATCH(_3DSTATE_SAMPLER_STATE | (3 * nr)); OUT_BATCH((dirty & I915_UPLOAD_TEX_ALL) >> I915_UPLOAD_TEX_0_SHIFT); @@ -455,6 +467,13 @@ i915_emit_state(struct intel_context *intel) OUT_BATCH(state->Tex[i][I915_TEXREG_SS4]); } ADVANCE_BATCH(); + if (i915->last_sampler && + memcmp(intel->batch.map + i915->last_sampler, + intel->batch.map + unwind, + (2 + nr*3)*sizeof(int)) == 0) + intel->batch.used = unwind; + else + i915->last_sampler = unwind; } if (dirty & I915_UPLOAD_CONSTANTS) { @@ -476,9 +495,7 @@ i915_emit_state(struct intel_context *intel) } } - intel->batch->dirty_state &= ~dirty; assert(get_dirty(state) == 0); - assert((intel->batch->dirty_state & (1<<1)) == 0); } static void @@ -660,6 +677,10 @@ i915_new_batch(struct intel_context *intel) */ i915->state.emitted = 0; i915->last_draw_offset = 0; + i915->last_sampler = 0; + + i915->current_vb_bo = NULL; + i915->current_vertex_size = 0; } static void diff --git a/src/mesa/drivers/dri/i915/intel_render.c b/src/mesa/drivers/dri/i915/intel_render.c index 0d8ab4b507e..2d361ca0a9a 100644 --- a/src/mesa/drivers/dri/i915/intel_render.c +++ b/src/mesa/drivers/dri/i915/intel_render.c @@ -124,7 +124,7 @@ static INLINE GLuint intel_get_vb_max(struct intel_context *intel) GLuint ret; if (intel->intelScreen->no_vbo) - ret = intel->batch->size - 1500; + ret = sizeof(intel->batch.map) - 1500; else ret = INTEL_VB_SIZE; ret /= (intel->vertex_size * 4); diff --git a/src/mesa/drivers/dri/i915/intel_tris.c b/src/mesa/drivers/dri/i915/intel_tris.c index b9a8aeb12f2..cf9291cdfca 100644 --- a/src/mesa/drivers/dri/i915/intel_tris.c +++ b/src/mesa/drivers/dri/i915/intel_tris.c @@ -54,6 +54,7 @@ #include "intel_span.h" #include "i830_context.h" #include "i830_reg.h" +#include "i915_context.h" static void intelRenderPrimitive(struct gl_context * ctx, GLenum prim); static void intelRasterPrimitive(struct gl_context * ctx, GLenum rprim, @@ -62,22 +63,22 @@ static void intelRasterPrimitive(struct gl_context * ctx, GLenum rprim, static void intel_flush_inline_primitive(struct intel_context *intel) { - GLuint used = intel->batch->ptr - intel->prim.start_ptr; + GLuint used = intel->batch.used - intel->prim.start_ptr; assert(intel->prim.primitive != ~0); /* printf("/\n"); */ - if (used < 8) + if (used < 2) goto do_discard; - *(int *) intel->prim.start_ptr = (_3DPRIMITIVE | - intel->prim.primitive | (used / 4 - 2)); + intel->batch.map[intel->prim.start_ptr] = + _3DPRIMITIVE | intel->prim.primitive | (used - 2); goto finished; do_discard: - intel->batch->ptr -= used; + intel->batch.used = intel->prim.start_ptr; finished: intel->prim.primitive = ~0; @@ -100,9 +101,7 @@ static void intel_start_inline(struct intel_context *intel, uint32_t prim) */ BEGIN_BATCH(1); - assert((intel->batch->dirty_state & (1<<1)) == 0); - - intel->prim.start_ptr = intel->batch->ptr; + intel->prim.start_ptr = intel->batch.used; intel->prim.primitive = prim; intel->prim.flush = intel_flush_inline_primitive; @@ -118,26 +117,25 @@ static void intel_wrap_inline(struct intel_context *intel) GLuint prim = intel->prim.primitive; intel_flush_inline_primitive(intel); - intel_batchbuffer_flush(intel->batch); + intel_batchbuffer_flush(intel); intel_start_inline(intel, prim); /* ??? */ } static GLuint *intel_extend_inline(struct intel_context *intel, GLuint dwords) { - GLuint sz = dwords * sizeof(GLuint); GLuint *ptr; assert(intel->prim.flush == intel_flush_inline_primitive); - if (intel_batchbuffer_space(intel->batch) < sz) + if (intel_batchbuffer_space(intel) < dwords * sizeof(GLuint)) intel_wrap_inline(intel); /* printf("."); */ intel->vtbl.assert_not_dirty(intel); - ptr = (GLuint *) intel->batch->ptr; - intel->batch->ptr += sz; + ptr = intel->batch.map + intel->batch.used; + intel->batch.used += dwords; return ptr; } @@ -218,15 +216,15 @@ void intel_flush_prim(struct intel_context *intel) offset = intel->prim.start_offset; intel->prim.start_offset = intel->prim.current_offset; if (intel->gen < 3) - intel->prim.start_offset = ALIGN(intel->prim.start_offset, 128); + intel->prim.current_offset = intel->prim.start_offset = ALIGN(intel->prim.start_offset, 128); intel->prim.flush = NULL; intel->vtbl.emit_state(intel); - aper_array[0] = intel->batch->buf; + aper_array[0] = intel->batch.bo; aper_array[1] = vb_bo; if (dri_bufmgr_check_aperture_space(aper_array, 2)) { - intel_batchbuffer_flush(intel->batch); + intel_batchbuffer_flush(intel); intel->vtbl.emit_state(intel); } @@ -236,11 +234,6 @@ void intel_flush_prim(struct intel_context *intel) */ intel->no_batch_wrap = GL_TRUE; - /* Check that we actually emitted the state into this batch, using the - * UPLOAD_CTX bit as the signal. - */ - assert((intel->batch->dirty_state & (1<<1)) == 0); - #if 0 printf("emitting %d..%d=%d vertices size %d\n", offset, intel->prim.current_offset, count, @@ -248,20 +241,39 @@ void intel_flush_prim(struct intel_context *intel) #endif if (intel->gen >= 3) { - BEGIN_BATCH(5); - OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | - I1_LOAD_S(0) | I1_LOAD_S(1) | 1); - assert((offset & ~S0_VB_OFFSET_MASK) == 0); - OUT_RELOC(vb_bo, I915_GEM_DOMAIN_VERTEX, 0, offset); - OUT_BATCH((intel->vertex_size << S1_VERTEX_WIDTH_SHIFT) | - (intel->vertex_size << S1_VERTEX_PITCH_SHIFT)); + struct i915_context *i915 = i915_context(&intel->ctx); + unsigned int cmd = 0, len = 0; + if (vb_bo != i915->current_vb_bo) { + cmd |= I1_LOAD_S(0); + len++; + } + + if (intel->vertex_size != i915->current_vertex_size) { + cmd |= I1_LOAD_S(1); + len++; + } + if (len) + len++; + + BEGIN_BATCH(2+len); + if (cmd) + OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | cmd | (len - 2)); + if (vb_bo != i915->current_vb_bo) { + OUT_RELOC(vb_bo, I915_GEM_DOMAIN_VERTEX, 0, 0); + i915->current_vb_bo = vb_bo; + } + if (intel->vertex_size != i915->current_vertex_size) { + OUT_BATCH((intel->vertex_size << S1_VERTEX_WIDTH_SHIFT) | + (intel->vertex_size << S1_VERTEX_PITCH_SHIFT)); + i915->current_vertex_size = intel->vertex_size; + } OUT_BATCH(_3DPRIMITIVE | PRIM_INDIRECT | PRIM_INDIRECT_SEQUENTIAL | intel->prim.primitive | count); - OUT_BATCH(0); /* Beginning vertex index */ + OUT_BATCH(offset / (intel->vertex_size * 4)); ADVANCE_BATCH(); } else { struct i830_context *i830 = i830_context(&intel->ctx); diff --git a/src/mesa/drivers/dri/i965/brw_cc.c b/src/mesa/drivers/dri/i965/brw_cc.c index c986970a757..412d82ab3ca 100644 --- a/src/mesa/drivers/dri/i965/brw_cc.c +++ b/src/mesa/drivers/dri/i965/brw_cc.c @@ -35,6 +35,7 @@ #include "brw_defines.h" #include "brw_util.h" #include "main/macros.h" +#include "intel_batchbuffer.h" void brw_update_cc_vp(struct brw_context *brw) @@ -92,54 +93,54 @@ static void upload_cc_unit(struct brw_context *brw) { struct intel_context *intel = &brw->intel; struct gl_context *ctx = &brw->intel.ctx; - struct brw_cc_unit_state cc; - void *map; + struct brw_cc_unit_state *cc; - memset(&cc, 0, sizeof(cc)); + cc = brw_state_batch(brw, sizeof(*cc), 64, &brw->cc.state_offset); + memset(cc, 0, sizeof(*cc)); /* _NEW_STENCIL */ if (ctx->Stencil._Enabled) { const unsigned back = ctx->Stencil._BackFace; - cc.cc0.stencil_enable = 1; - cc.cc0.stencil_func = + cc->cc0.stencil_enable = 1; + cc->cc0.stencil_func = intel_translate_compare_func(ctx->Stencil.Function[0]); - cc.cc0.stencil_fail_op = + cc->cc0.stencil_fail_op = intel_translate_stencil_op(ctx->Stencil.FailFunc[0]); - cc.cc0.stencil_pass_depth_fail_op = + cc->cc0.stencil_pass_depth_fail_op = intel_translate_stencil_op(ctx->Stencil.ZFailFunc[0]); - cc.cc0.stencil_pass_depth_pass_op = + cc->cc0.stencil_pass_depth_pass_op = intel_translate_stencil_op(ctx->Stencil.ZPassFunc[0]); - cc.cc1.stencil_ref = ctx->Stencil.Ref[0]; - cc.cc1.stencil_write_mask = ctx->Stencil.WriteMask[0]; - cc.cc1.stencil_test_mask = ctx->Stencil.ValueMask[0]; + cc->cc1.stencil_ref = ctx->Stencil.Ref[0]; + cc->cc1.stencil_write_mask = ctx->Stencil.WriteMask[0]; + cc->cc1.stencil_test_mask = ctx->Stencil.ValueMask[0]; if (ctx->Stencil._TestTwoSide) { - cc.cc0.bf_stencil_enable = 1; - cc.cc0.bf_stencil_func = + cc->cc0.bf_stencil_enable = 1; + cc->cc0.bf_stencil_func = intel_translate_compare_func(ctx->Stencil.Function[back]); - cc.cc0.bf_stencil_fail_op = + cc->cc0.bf_stencil_fail_op = intel_translate_stencil_op(ctx->Stencil.FailFunc[back]); - cc.cc0.bf_stencil_pass_depth_fail_op = + cc->cc0.bf_stencil_pass_depth_fail_op = intel_translate_stencil_op(ctx->Stencil.ZFailFunc[back]); - cc.cc0.bf_stencil_pass_depth_pass_op = + cc->cc0.bf_stencil_pass_depth_pass_op = intel_translate_stencil_op(ctx->Stencil.ZPassFunc[back]); - cc.cc1.bf_stencil_ref = ctx->Stencil.Ref[back]; - cc.cc2.bf_stencil_write_mask = ctx->Stencil.WriteMask[back]; - cc.cc2.bf_stencil_test_mask = ctx->Stencil.ValueMask[back]; + cc->cc1.bf_stencil_ref = ctx->Stencil.Ref[back]; + cc->cc2.bf_stencil_write_mask = ctx->Stencil.WriteMask[back]; + cc->cc2.bf_stencil_test_mask = ctx->Stencil.ValueMask[back]; } /* Not really sure about this: */ if (ctx->Stencil.WriteMask[0] || (ctx->Stencil._TestTwoSide && ctx->Stencil.WriteMask[back])) - cc.cc0.stencil_write_enable = 1; + cc->cc0.stencil_write_enable = 1; } /* _NEW_COLOR */ if (ctx->Color._LogicOpEnabled && ctx->Color.LogicOp != GL_COPY) { - cc.cc2.logicop_enable = 1; - cc.cc5.logicop_func = intel_translate_logic_op(ctx->Color.LogicOp); + cc->cc2.logicop_enable = 1; + cc->cc5.logicop_func = intel_translate_logic_op(ctx->Color.LogicOp); } else if (ctx->Color.BlendEnabled) { GLenum eqRGB = ctx->Color.Blend[0].EquationRGB; GLenum eqA = ctx->Color.Blend[0].EquationA; @@ -167,58 +168,55 @@ static void upload_cc_unit(struct brw_context *brw) srcA = dstA = GL_ONE; } - cc.cc6.dest_blend_factor = brw_translate_blend_factor(dstRGB); - cc.cc6.src_blend_factor = brw_translate_blend_factor(srcRGB); - cc.cc6.blend_function = brw_translate_blend_equation(eqRGB); + cc->cc6.dest_blend_factor = brw_translate_blend_factor(dstRGB); + cc->cc6.src_blend_factor = brw_translate_blend_factor(srcRGB); + cc->cc6.blend_function = brw_translate_blend_equation(eqRGB); - cc.cc5.ia_dest_blend_factor = brw_translate_blend_factor(dstA); - cc.cc5.ia_src_blend_factor = brw_translate_blend_factor(srcA); - cc.cc5.ia_blend_function = brw_translate_blend_equation(eqA); + cc->cc5.ia_dest_blend_factor = brw_translate_blend_factor(dstA); + cc->cc5.ia_src_blend_factor = brw_translate_blend_factor(srcA); + cc->cc5.ia_blend_function = brw_translate_blend_equation(eqA); - cc.cc3.blend_enable = 1; - cc.cc3.ia_blend_enable = (srcA != srcRGB || + cc->cc3.blend_enable = 1; + cc->cc3.ia_blend_enable = (srcA != srcRGB || dstA != dstRGB || eqA != eqRGB); } if (ctx->Color.AlphaEnabled) { - cc.cc3.alpha_test = 1; - cc.cc3.alpha_test_func = + cc->cc3.alpha_test = 1; + cc->cc3.alpha_test_func = intel_translate_compare_func(ctx->Color.AlphaFunc); - cc.cc3.alpha_test_format = BRW_ALPHATEST_FORMAT_UNORM8; + cc->cc3.alpha_test_format = BRW_ALPHATEST_FORMAT_UNORM8; - UNCLAMPED_FLOAT_TO_UBYTE(cc.cc7.alpha_ref.ub[0], ctx->Color.AlphaRef); + UNCLAMPED_FLOAT_TO_UBYTE(cc->cc7.alpha_ref.ub[0], ctx->Color.AlphaRef); } if (ctx->Color.DitherFlag) { - cc.cc5.dither_enable = 1; - cc.cc6.y_dither_offset = 0; - cc.cc6.x_dither_offset = 0; + cc->cc5.dither_enable = 1; + cc->cc6.y_dither_offset = 0; + cc->cc6.x_dither_offset = 0; } /* _NEW_DEPTH */ if (ctx->Depth.Test) { - cc.cc2.depth_test = 1; - cc.cc2.depth_test_function = + cc->cc2.depth_test = 1; + cc->cc2.depth_test_function = intel_translate_compare_func(ctx->Depth.Func); - cc.cc2.depth_write_enable = ctx->Depth.Mask; + cc->cc2.depth_write_enable = ctx->Depth.Mask; } if (intel->stats_wm || unlikely(INTEL_DEBUG & DEBUG_STATS)) - cc.cc5.statistics_enable = 1; + cc->cc5.statistics_enable = 1; /* CACHE_NEW_CC_VP */ - cc.cc4.cc_viewport_state_offset = brw->cc.vp_bo->offset >> 5; /* reloc */ + cc->cc4.cc_viewport_state_offset = brw->cc.vp_bo->offset >> 5; /* reloc */ - map = brw_state_batch(brw, sizeof(cc), 64, - &brw->cc.state_bo, &brw->cc.state_offset); - memcpy(map, &cc, sizeof(cc)); brw->state.dirty.cache |= CACHE_NEW_CC_UNIT; /* Emit CC viewport relocation */ - drm_intel_bo_emit_reloc(brw->cc.state_bo, (brw->cc.state_offset + - offsetof(struct brw_cc_unit_state, - cc4)), + drm_intel_bo_emit_reloc(brw->intel.batch.bo, + (brw->cc.state_offset + + offsetof(struct brw_cc_unit_state, cc4)), brw->cc.vp_bo, 0, I915_GEM_DOMAIN_INSTRUCTION, 0); } @@ -235,18 +233,16 @@ const struct brw_tracked_state brw_cc_unit = { static void upload_blend_constant_color(struct brw_context *brw) { - struct gl_context *ctx = &brw->intel.ctx; - struct brw_blend_constant_color bcc; - - memset(&bcc, 0, sizeof(bcc)); - bcc.header.opcode = _3DSTATE_BLEND_CONSTANT_COLOR; - bcc.header.length = sizeof(bcc)/4-2; - bcc.blend_constant_color[0] = ctx->Color.BlendColor[0]; - bcc.blend_constant_color[1] = ctx->Color.BlendColor[1]; - bcc.blend_constant_color[2] = ctx->Color.BlendColor[2]; - bcc.blend_constant_color[3] = ctx->Color.BlendColor[3]; - - BRW_CACHED_BATCH_STRUCT(brw, &bcc); + struct intel_context *intel = &brw->intel; + struct gl_context *ctx = &intel->ctx; + + BEGIN_BATCH(5); + OUT_BATCH(_3DSTATE_BLEND_CONSTANT_COLOR << 16 | (5-2)); + OUT_BATCH_F(ctx->Color.BlendColor[0]); + OUT_BATCH_F(ctx->Color.BlendColor[1]); + OUT_BATCH_F(ctx->Color.BlendColor[2]); + OUT_BATCH_F(ctx->Color.BlendColor[3]); + CACHED_BATCH(); } const struct brw_tracked_state brw_blend_constant_color = { diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h index 7069724466a..3e52304f6ab 100644 --- a/src/mesa/drivers/dri/i965/brw_context.h +++ b/src/mesa/drivers/dri/i965/brw_context.h @@ -145,7 +145,7 @@ struct brw_context; #define BRW_NEW_NR_VS_SURFACES 0x80000 #define BRW_NEW_INDEX_BUFFER 0x100000 #define BRW_NEW_VS_CONSTBUF 0x200000 -#define BRW_NEW_WM_CONSTBUF 0x200000 +#define BRW_NEW_WM_CONSTBUF 0x400000 struct brw_state_flags { /** State update flags signalled by mesa internals */ @@ -408,21 +408,26 @@ struct brw_cached_batch_item { */ #define ATTRIB_BIT_DWORDS ((VERT_ATTRIB_MAX+31)/32) +struct brw_vertex_buffer { + /** Buffer object containing the uploaded vertex data */ + drm_intel_bo *bo; + uint32_t offset; + /** Byte stride between elements in the uploaded array */ + GLuint stride; +}; struct brw_vertex_element { const struct gl_client_array *glarray; + int buffer; + /** The corresponding Mesa vertex attribute */ gl_vert_attrib attrib; /** Size of a complete element */ GLuint element_size; /** Number of uploaded elements for this input. */ GLuint count; - /** Byte stride between elements in the uploaded array */ - GLuint stride; /** Offset of the first element within the buffer object */ unsigned int offset; - /** Buffer object containing the uploaded vertex data */ - drm_intel_bo *bo; }; @@ -461,8 +466,6 @@ struct brw_context struct { struct brw_state_flags dirty; - GLuint nr_color_regions; - struct intel_region *color_regions[MAX_DRAW_BUFFERS]; struct intel_region *depth_region; /** @@ -485,23 +488,27 @@ struct brw_context struct { struct brw_vertex_element inputs[VERT_ATTRIB_MAX]; + struct brw_vertex_buffer buffers[VERT_ATTRIB_MAX]; + struct { + uint32_t handle; + uint32_t offset; + uint32_t stride; + } current_buffers[VERT_ATTRIB_MAX]; struct brw_vertex_element *enabled[VERT_ATTRIB_MAX]; GLuint nr_enabled; - -#define BRW_NR_UPLOAD_BUFS 17 -#define BRW_UPLOAD_INIT_SIZE (128*1024) - - struct { - drm_intel_bo *bo; - GLuint offset; - } upload; + GLuint nr_buffers, nr_current_buffers; /* Summary of size and varying of active arrays, so we can check * for changes to this state: */ struct brw_vertex_info info; unsigned int min_index, max_index; + + /* Offset from start of vertex buffer so we can avoid redefining + * the same VB packed over and over again. + */ + unsigned int start_vertex_bias; } vb; struct { @@ -515,7 +522,7 @@ struct brw_context /* Updates to these fields are signaled by BRW_NEW_INDEX_BUFFER. */ drm_intel_bo *bo; unsigned int offset; - unsigned int size; + /* Offset to index buffer index to use in CMD_3D_PRIM so that we can * avoid re-uploading the IB packet over and over if we're actually * referencing the same index buffer. @@ -528,11 +535,6 @@ struct brw_context const struct gl_vertex_program *vertex_program; const struct gl_fragment_program *fragment_program; - - /* For populating the gtt: - */ - GLuint next_free_page; - /* hw-dependent 3DSTATE_VF_STATISTICS opcode */ uint32_t CMD_VF_STATISTICS; /* hw-dependent 3DSTATE_PIPELINE_SELECT opcode */ @@ -612,9 +614,7 @@ struct brw_context drm_intel_bo *const_bo; /** Binding table of pointers to surf_bo entries */ - drm_intel_bo *bind_bo; uint32_t bind_bo_offset; - drm_intel_bo *surf_bo[BRW_VS_MAX_SURF]; uint32_t surf_offset[BRW_VS_MAX_SURF]; GLuint nr_surfaces; } vs; @@ -666,9 +666,7 @@ struct brw_context drm_intel_bo *sampler_bo; /** Binding table of pointers to surf_bo entries */ - drm_intel_bo *bind_bo; uint32_t bind_bo_offset; - drm_intel_bo *surf_bo[BRW_WM_MAX_SURF]; uint32_t surf_offset[BRW_WM_MAX_SURF]; drm_intel_bo *prog_bo; @@ -693,7 +691,6 @@ struct brw_context drm_intel_bo *depth_stencil_state_bo; drm_intel_bo *color_calc_state_bo; - drm_intel_bo *state_bo; uint32_t state_offset; } cc; @@ -841,4 +838,3 @@ float convert_param(enum param_conversion conversion, float param) GLboolean brw_do_cubemap_normalize(struct exec_list *instructions); #endif - diff --git a/src/mesa/drivers/dri/i965/brw_cubemap_normalize.cpp b/src/mesa/drivers/dri/i965/brw_cubemap_normalize.cpp index 35bea681214..8574169e472 100644 --- a/src/mesa/drivers/dri/i965/brw_cubemap_normalize.cpp +++ b/src/mesa/drivers/dri/i965/brw_cubemap_normalize.cpp @@ -51,7 +51,7 @@ brw_cubemap_normalize_visitor::visit_leave(ir_texture *ir) if (ir->sampler->type->sampler_dimensionality != GLSL_SAMPLER_DIM_CUBE) return visit_continue; - void *mem_ctx = talloc_parent(ir); + void *mem_ctx = ralloc_parent(ir); ir_variable *var = new(mem_ctx) ir_variable(ir->coordinate->type, "coordinate", ir_var_auto); diff --git a/src/mesa/drivers/dri/i965/brw_curbe.c b/src/mesa/drivers/dri/i965/brw_curbe.c index 877b22fec19..ae11c487a2c 100644 --- a/src/mesa/drivers/dri/i965/brw_curbe.c +++ b/src/mesa/drivers/dri/i965/brw_curbe.c @@ -146,22 +146,24 @@ const struct brw_tracked_state brw_curbe_offsets = { */ void brw_upload_cs_urb_state(struct brw_context *brw) { - struct brw_cs_urb_state cs_urb; - memset(&cs_urb, 0, sizeof(cs_urb)); + struct intel_context *intel = &brw->intel; + BEGIN_BATCH(2); /* It appears that this is the state packet for the CS unit, ie. the * urb entries detailed here are housed in the CS range from the * URB_FENCE command. */ - cs_urb.header.opcode = CMD_CS_URB_STATE; - cs_urb.header.length = sizeof(cs_urb)/4 - 2; + OUT_BATCH(CMD_CS_URB_STATE << 16 | (2-2)); /* BRW_NEW_URB_FENCE */ - cs_urb.bits0.nr_urb_entries = brw->urb.nr_cs_entries; - cs_urb.bits0.urb_entry_size = brw->urb.csize - 1; - - assert(brw->urb.nr_cs_entries); - BRW_CACHED_BATCH_STRUCT(brw, &cs_urb); + if (brw->urb.csize == 0) { + OUT_BATCH(0); + } else { + /* BRW_NEW_URB_FENCE */ + assert(brw->urb.nr_cs_entries); + OUT_BATCH((brw->urb.csize - 1) << 4 | brw->urb.nr_cs_entries); + } + CACHED_BATCH(); } static GLfloat fixed_plane[6][4] = { diff --git a/src/mesa/drivers/dri/i965/brw_defines.h b/src/mesa/drivers/dri/i965/brw_defines.h index 2f7dcc2dda7..a413c02b573 100644 --- a/src/mesa/drivers/dri/i965/brw_defines.h +++ b/src/mesa/drivers/dri/i965/brw_defines.h @@ -817,8 +817,8 @@ #define CMD_PIPELINE_SELECT_965 0x6104 #define CMD_PIPELINE_SELECT_GM45 0x6904 -#define CMD_PIPELINED_STATE_POINTERS 0x7800 -#define CMD_BINDING_TABLE_PTRS 0x7801 +#define _3DSTATE_PIPELINED_POINTERS 0x7800 +#define _3DSTATE_BINDING_TABLE_POINTERS 0x7801 # define GEN6_BINDING_TABLE_MODIFY_VS (1 << 8) # define GEN6_BINDING_TABLE_MODIFY_GS (1 << 9) # define GEN6_BINDING_TABLE_MODIFY_PS (1 << 12) diff --git a/src/mesa/drivers/dri/i965/brw_draw.c b/src/mesa/drivers/dri/i965/brw_draw.c index 7eb16b71f4a..f5abe021c43 100644 --- a/src/mesa/drivers/dri/i965/brw_draw.c +++ b/src/mesa/drivers/dri/i965/brw_draw.c @@ -145,9 +145,14 @@ static void brw_emit_prim(struct brw_context *brw, prim_packet.start_vert_location = prim->start; if (prim->indexed) prim_packet.start_vert_location += brw->ib.start_vertex_offset; + else + prim_packet.start_vert_location += brw->vb.start_vertex_bias; prim_packet.instance_count = 1; prim_packet.start_instance_location = 0; prim_packet.base_vert_location = prim->basevertex; + if (prim->indexed) + prim_packet.base_vert_location += brw->vb.start_vertex_bias; + /* If we're set to always flush, do it before and after the primitive emit. * We want to catch both missed flushes that hurt instruction/state cache @@ -155,14 +160,14 @@ static void brw_emit_prim(struct brw_context *brw, * the besides the draw code. */ if (intel->always_flush_cache) { - intel_batchbuffer_emit_mi_flush(intel->batch); + intel_batchbuffer_emit_mi_flush(intel); } if (prim_packet.verts_per_instance) { - intel_batchbuffer_data( brw->intel.batch, &prim_packet, + intel_batchbuffer_data(&brw->intel, &prim_packet, sizeof(prim_packet), false); } if (intel->always_flush_cache) { - intel_batchbuffer_emit_mi_flush(intel->batch); + intel_batchbuffer_emit_mi_flush(intel); } } @@ -172,13 +177,16 @@ static void brw_merge_inputs( struct brw_context *brw, struct brw_vertex_info old = brw->vb.info; GLuint i; - for (i = 0; i < VERT_ATTRIB_MAX; i++) - drm_intel_bo_unreference(brw->vb.inputs[i].bo); + for (i = 0; i < brw->vb.nr_buffers; i++) { + drm_intel_bo_unreference(brw->vb.buffers[i].bo); + brw->vb.buffers[i].bo = NULL; + } + brw->vb.nr_buffers = 0; - memset(&brw->vb.inputs, 0, sizeof(brw->vb.inputs)); memset(&brw->vb.info, 0, sizeof(brw->vb.info)); for (i = 0; i < VERT_ATTRIB_MAX; i++) { + brw->vb.inputs[i].buffer = -1; brw->vb.inputs[i].glarray = arrays[i]; brw->vb.inputs[i].attrib = (gl_vert_attrib) i; @@ -303,7 +311,6 @@ static GLboolean brw_try_draw_prims( struct gl_context *ctx, struct brw_context *brw = brw_context(ctx); GLboolean retval = GL_FALSE; GLboolean warn = GL_FALSE; - GLboolean first_time = GL_TRUE; GLuint i; if (ctx->NewState) @@ -351,14 +358,10 @@ static GLboolean brw_try_draw_prims( struct gl_context *ctx, * an upper bound of how much we might emit in a single * brw_try_draw_prims(). */ - intel_batchbuffer_require_space(intel->batch, intel->batch->size / 4, - false); + intel_batchbuffer_require_space(intel, 1024, false); hw_prim = brw_set_prim(brw, &prim[i]); - - if (first_time || (brw->state.dirty.brw & BRW_NEW_PRIMITIVE)) { - first_time = GL_FALSE; - + if (brw->state.dirty.brw) { brw_validate_state(brw); /* Various fallback checks: */ @@ -371,7 +374,7 @@ static GLboolean brw_try_draw_prims( struct gl_context *ctx, if (dri_bufmgr_check_aperture_space(brw->state.validated_bos, brw->state.validated_bo_count)) { static GLboolean warned; - intel_batchbuffer_flush(intel->batch); + intel_batchbuffer_flush(intel); /* Validate the state after we flushed the batch (which would have * changed the set of dirty state). If we still fail to @@ -400,7 +403,7 @@ static GLboolean brw_try_draw_prims( struct gl_context *ctx, } if (intel->always_flush_batch) - intel_batchbuffer_flush(intel->batch); + intel_batchbuffer_flush(intel); out: brw_state_cache_check_size(brw); @@ -461,25 +464,32 @@ void brw_draw_init( struct brw_context *brw ) { struct gl_context *ctx = &brw->intel.ctx; struct vbo_context *vbo = vbo_context(ctx); + int i; /* Register our drawing function: */ vbo->draw_prims = brw_draw_prims; + + for (i = 0; i < VERT_ATTRIB_MAX; i++) + brw->vb.inputs[i].buffer = -1; + brw->vb.nr_buffers = 0; + brw->vb.nr_enabled = 0; } void brw_draw_destroy( struct brw_context *brw ) { int i; - if (brw->vb.upload.bo != NULL) { - drm_intel_bo_unreference(brw->vb.upload.bo); - brw->vb.upload.bo = NULL; + for (i = 0; i < brw->vb.nr_buffers; i++) { + drm_intel_bo_unreference(brw->vb.buffers[i].bo); + brw->vb.buffers[i].bo = NULL; } + brw->vb.nr_buffers = 0; - for (i = 0; i < VERT_ATTRIB_MAX; i++) { - drm_intel_bo_unreference(brw->vb.inputs[i].bo); - brw->vb.inputs[i].bo = NULL; + for (i = 0; i < brw->vb.nr_enabled; i++) { + brw->vb.enabled[i]->buffer = -1; } + brw->vb.nr_enabled = 0; drm_intel_bo_unreference(brw->ib.bo); brw->ib.bo = NULL; diff --git a/src/mesa/drivers/dri/i965/brw_draw_upload.c b/src/mesa/drivers/dri/i965/brw_draw_upload.c index 2cefe614dd2..7234ce210b5 100644 --- a/src/mesa/drivers/dri/i965/brw_draw_upload.c +++ b/src/mesa/drivers/dri/i965/brw_draw_upload.c @@ -25,6 +25,7 @@ * **************************************************************************/ +#undef NDEBUG #include "main/glheader.h" #include "main/bufferobj.h" @@ -238,76 +239,31 @@ static GLuint get_index_type(GLenum type) } } -static void wrap_buffers( struct brw_context *brw, - GLuint size ) -{ - if (size < BRW_UPLOAD_INIT_SIZE) - size = BRW_UPLOAD_INIT_SIZE; - - brw->vb.upload.offset = 0; - - if (brw->vb.upload.bo != NULL) - drm_intel_bo_unreference(brw->vb.upload.bo); - brw->vb.upload.bo = drm_intel_bo_alloc(brw->intel.bufmgr, "temporary VBO", - size, 1); -} - -static void get_space( struct brw_context *brw, - GLuint size, - drm_intel_bo **bo_return, - GLuint *offset_return ) -{ - size = ALIGN(size, 64); - - if (brw->vb.upload.bo == NULL || - brw->vb.upload.offset + size > brw->vb.upload.bo->size) { - wrap_buffers(brw, size); - } - - assert(*bo_return == NULL); - drm_intel_bo_reference(brw->vb.upload.bo); - *bo_return = brw->vb.upload.bo; - *offset_return = brw->vb.upload.offset; - brw->vb.upload.offset += size; -} - static void copy_array_to_vbo_array( struct brw_context *brw, struct brw_vertex_element *element, + struct brw_vertex_buffer *buffer, GLuint dst_stride) { GLuint size = element->count * dst_stride; - get_space(brw, size, &element->bo, &element->offset); - - if (element->glarray->StrideB == 0) { - assert(element->count == 1); - element->stride = 0; - } else { - element->stride = dst_stride; - } - + buffer->stride = dst_stride; if (dst_stride == element->glarray->StrideB) { - drm_intel_gem_bo_map_gtt(element->bo); - memcpy((char *)element->bo->virtual + element->offset, - element->glarray->Ptr, size); - drm_intel_gem_bo_unmap_gtt(element->bo); + intel_upload_data(&brw->intel, element->glarray->Ptr, size, dst_stride, + &buffer->bo, &buffer->offset); } else { - char *dest; const unsigned char *src = element->glarray->Ptr; + char *map = intel_upload_map(&brw->intel, size, dst_stride); + char *dst = map; int i; - drm_intel_gem_bo_map_gtt(element->bo); - dest = element->bo->virtual; - dest += element->offset; - for (i = 0; i < element->count; i++) { - memcpy(dest, src, dst_stride); + memcpy(dst, src, dst_stride); src += element->glarray->StrideB; - dest += dst_stride; + dst += dst_stride; } - - drm_intel_gem_bo_unmap_gtt(element->bo); + intel_upload_unmap(&brw->intel, map, size, dst_stride, + &buffer->bo, &buffer->offset); } } @@ -316,11 +272,11 @@ static void brw_prepare_vertices(struct brw_context *brw) struct gl_context *ctx = &brw->intel.ctx; struct intel_context *intel = intel_context(ctx); GLbitfield vs_inputs = brw->vs.prog_data->inputs_read; - GLuint i; const unsigned char *ptr = NULL; - GLuint interleave = 0; + GLuint interleaved = 0, total_size = 0, count = -1; unsigned int min_index = brw->vb.min_index; unsigned int max_index = brw->vb.max_index; + int i, j; struct brw_vertex_element *upload[VERT_ATTRIB_MAX]; GLuint nr_uploads = 0; @@ -340,6 +296,12 @@ static void brw_prepare_vertices(struct brw_context *brw) brw->vb.enabled[brw->vb.nr_enabled++] = input; } + if (brw->vb.nr_enabled == 0) + return; + + if (brw->vb.nr_buffers) + goto validate; + /* XXX: In the rare cases where this happens we fallback all * the way to software rasterization, although a tnl fallback * would be sufficient. I don't know of *any* real world @@ -351,23 +313,43 @@ static void brw_prepare_vertices(struct brw_context *brw) return; } - for (i = 0; i < brw->vb.nr_enabled; i++) { + for (i = j = 0; i < brw->vb.nr_enabled; i++) { struct brw_vertex_element *input = brw->vb.enabled[i]; + const struct gl_client_array *glarray = input->glarray; + int type_size = get_size(glarray->Type); - input->element_size = get_size(input->glarray->Type) * input->glarray->Size; + input->element_size = type_size * glarray->Size; - if (_mesa_is_bufferobj(input->glarray->BufferObj)) { + if (_mesa_is_bufferobj(glarray->BufferObj)) { struct intel_buffer_object *intel_buffer = - intel_buffer_object(input->glarray->BufferObj); - - /* Named buffer object: Just reference its contents directly. */ - drm_intel_bo_unreference(input->bo); - input->bo = intel_bufferobj_buffer(intel, intel_buffer, - INTEL_READ); - drm_intel_bo_reference(input->bo); - input->offset = (unsigned long)input->glarray->Ptr; - input->stride = input->glarray->StrideB; - input->count = input->glarray->_MaxElement; + intel_buffer_object(glarray->BufferObj); + int k; + + for (k = 0; k < i; k++) { + const struct gl_client_array *other = brw->vb.enabled[k]->glarray; + if (glarray->BufferObj == other->BufferObj && + glarray->StrideB == other->StrideB && + (uintptr_t)(glarray->Ptr - other->Ptr) < glarray->StrideB) + { + input->buffer = brw->vb.enabled[k]->buffer; + input->offset = glarray->Ptr - other->Ptr; + break; + } + } + if (k == i) { + struct brw_vertex_buffer *buffer = &brw->vb.buffers[j]; + + /* Named buffer object: Just reference its contents directly. */ + buffer->bo = intel_bufferobj_source(intel, intel_buffer, + &buffer->offset); + drm_intel_bo_reference(buffer->bo); + buffer->offset += (uintptr_t)glarray->Ptr; + buffer->stride = glarray->StrideB; + + input->buffer = j++; + input->offset = 0; + } + input->count = glarray->_MaxElement; /* This is a common place to reach if the user mistakenly supplies * a pointer in place of a VBO offset. If we just let it go through, @@ -381,71 +363,138 @@ static void brw_prepare_vertices(struct brw_context *brw) * probably a service to the poor programmer to do so rather than * trying to just not render. */ - assert(input->offset < input->bo->size); + assert(input->offset < brw->vb.buffers[input->buffer].bo->size); } else { - input->count = input->glarray->StrideB ? max_index + 1 : 1; - if (input->bo != NULL) { - /* Already-uploaded vertex data is present from a previous - * prepare_vertices, but we had to re-validate state due to - * check_aperture failing and a new batch being produced. - */ - continue; - } + input->count = glarray->StrideB ? max_index + 1 : 1; /* Queue the buffer object up to be uploaded in the next pass, * when we've decided if we're doing interleaved or not. */ - if (input->attrib == VERT_ATTRIB_POS) { + if (nr_uploads == 0) { /* Position array not properly enabled: */ - if (input->glarray->StrideB == 0) { + if (input->attrib == VERT_ATTRIB_POS && glarray->StrideB == 0) { intel->Fallback = GL_TRUE; /* boolean, not bitfield */ return; } - interleave = input->glarray->StrideB; - ptr = input->glarray->Ptr; + interleaved = glarray->StrideB; + ptr = glarray->Ptr; } - else if (interleave != input->glarray->StrideB || - (const unsigned char *)input->glarray->Ptr - ptr < 0 || - (const unsigned char *)input->glarray->Ptr - ptr > interleave) + else if (interleaved != glarray->StrideB || + (uintptr_t)(glarray->Ptr - ptr) > interleaved) { - interleave = 0; + interleaved = 0; } + else if (total_size & (type_size -1)) + { + /* enforce natural alignment (for doubles) */ + interleaved = 0; + } + + if (count > input->count) + count = input->count; upload[nr_uploads++] = input; + total_size += input->element_size; } } /* Handle any arrays to be uploaded. */ - if (nr_uploads > 1 && interleave && interleave <= 256) { - /* All uploads are interleaved, so upload the arrays together as - * interleaved. First, upload the contents and set up upload[0]. - */ - copy_array_to_vbo_array(brw, upload[0], interleave); - - for (i = 1; i < nr_uploads; i++) { - /* Then, just point upload[i] at upload[0]'s buffer. */ - upload[i]->stride = interleave; - upload[i]->offset = upload[0]->offset + - ((const unsigned char *)upload[i]->glarray->Ptr - ptr); - upload[i]->bo = upload[0]->bo; - drm_intel_bo_reference(upload[i]->bo); + if (nr_uploads > 1) { + if (interleaved && interleaved <= 2*total_size) { + /* All uploads are interleaved, so upload the arrays together as + * interleaved. First, upload the contents and set up upload[0]. + */ + upload[0]->count = count; /* trim the upload over all arrays */ + copy_array_to_vbo_array(brw, + upload[0], &brw->vb.buffers[j], + interleaved); + + for (i = 0; i < nr_uploads; i++) { + /* Then, just point upload[i] at upload[0]'s buffer. */ + upload[i]->offset = + ((const unsigned char *)upload[i]->glarray->Ptr - ptr); + upload[i]->buffer = j; + } + j++; + + nr_uploads = 0; } - } - else { - /* Upload non-interleaved arrays */ - for (i = 0; i < nr_uploads; i++) { - copy_array_to_vbo_array(brw, upload[i], upload[i]->element_size); + else if (total_size < 2048) { + /* Upload non-interleaved arrays into a single interleaved array */ + struct brw_vertex_buffer *buffer = &brw->vb.buffers[j]; + int count = upload[0]->count, offset; + char *map; + + map = intel_upload_map(&brw->intel, total_size * count, total_size); + for (i = offset = 0; i < nr_uploads; i++) { + const unsigned char *src = upload[i]->glarray->Ptr; + int size = upload[i]->element_size; + int stride = upload[i]->glarray->StrideB; + char *dst = map + offset; + int n; + + for (n = 0; n < count; n++) { + memcpy(dst, src, size); + src += stride; + dst += total_size; + } + + upload[i]->offset = offset; + upload[i]->buffer = j; + + offset += size; + } + intel_upload_unmap(&brw->intel, map, total_size * count, total_size, + &buffer->bo, &buffer->offset); + buffer->stride = offset; + j++; + + nr_uploads = 0; } } + /* Upload non-interleaved arrays */ + for (i = 0; i < nr_uploads; i++) { + copy_array_to_vbo_array(brw, + upload[i], &brw->vb.buffers[j], + upload[i]->element_size); + upload[i]->buffer = j++; + upload[i]->offset = 0; + } - brw_prepare_query_begin(brw); + /* can we simply extend the current vb? */ + brw->vb.start_vertex_bias = 0; + if (j == brw->vb.nr_current_buffers) { + int delta = 0; + for (i = 0; i < j; i++) { + int d; + + if (brw->vb.current_buffers[i].handle != brw->vb.buffers[i].bo->handle || + brw->vb.current_buffers[i].stride != brw->vb.buffers[i].stride) + break; + + d = brw->vb.buffers[i].offset - brw->vb.current_buffers[i].offset; + if (delta == 0) + delta = d / brw->vb.current_buffers[i].stride; + if (delta * brw->vb.current_buffers[i].stride != d) + break; + } - for (i = 0; i < brw->vb.nr_enabled; i++) { - struct brw_vertex_element *input = brw->vb.enabled[i]; + if (i == j) { + brw->vb.start_vertex_bias = delta; + while (--j >= 0) + drm_intel_bo_unreference(brw->vb.buffers[j].bo); + j = 0; + } + } - brw_add_validated_bo(brw, input->bo); + brw->vb.nr_buffers = j; + +validate: + brw_prepare_query_begin(brw); + for (i = 0; i < brw->vb.nr_buffers; i++) { + brw_add_validated_bo(brw, brw->vb.buffers[i].bo); } } @@ -482,49 +531,44 @@ static void brw_emit_vertices(struct brw_context *brw) (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_1_SHIFT) | (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_2_SHIFT) | (BRW_VE1_COMPONENT_STORE_1_FLT << BRW_VE1_COMPONENT_3_SHIFT)); - ADVANCE_BATCH(); + CACHED_BATCH(); return; } /* Now emit VB and VEP state packets. - * - * This still defines a hardware VB for each input, even if they - * are interleaved or from the same VBO. TBD if this makes a - * performance difference. */ - BEGIN_BATCH(1 + brw->vb.nr_enabled * 4); - OUT_BATCH((CMD_VERTEX_BUFFER << 16) | - ((1 + brw->vb.nr_enabled * 4) - 2)); - for (i = 0; i < brw->vb.nr_enabled; i++) { - struct brw_vertex_element *input = brw->vb.enabled[i]; - uint32_t dw0; + if (brw->vb.nr_buffers) { + BEGIN_BATCH(1 + 4*brw->vb.nr_buffers); + OUT_BATCH((CMD_VERTEX_BUFFER << 16) | (4*brw->vb.nr_buffers - 1)); + for (i = 0; i < brw->vb.nr_buffers; i++) { + struct brw_vertex_buffer *buffer = &brw->vb.buffers[i]; + uint32_t dw0; + + if (intel->gen >= 6) { + dw0 = GEN6_VB0_ACCESS_VERTEXDATA | (i << GEN6_VB0_INDEX_SHIFT); + } else { + dw0 = BRW_VB0_ACCESS_VERTEXDATA | (i << BRW_VB0_INDEX_SHIFT); + } - if (intel->gen >= 6) { - dw0 = GEN6_VB0_ACCESS_VERTEXDATA | - (i << GEN6_VB0_INDEX_SHIFT); - } else { - dw0 = BRW_VB0_ACCESS_VERTEXDATA | - (i << BRW_VB0_INDEX_SHIFT); + OUT_BATCH(dw0 | (buffer->stride << BRW_VB0_PITCH_SHIFT)); + OUT_RELOC(buffer->bo, I915_GEM_DOMAIN_VERTEX, 0, buffer->offset); + if (intel->gen >= 5) { + OUT_RELOC(buffer->bo, I915_GEM_DOMAIN_VERTEX, 0, buffer->bo->size - 1); + } else + OUT_BATCH(buffer->bo->size / buffer->stride); + OUT_BATCH(0); /* Instance data step rate */ + + brw->vb.current_buffers[i].handle = buffer->bo->handle; + brw->vb.current_buffers[i].offset = buffer->offset; + brw->vb.current_buffers[i].stride = buffer->stride; } - - OUT_BATCH(dw0 | - (input->stride << BRW_VB0_PITCH_SHIFT)); - OUT_RELOC(input->bo, - I915_GEM_DOMAIN_VERTEX, 0, - input->offset); - if (intel->gen >= 5) { - OUT_RELOC(input->bo, - I915_GEM_DOMAIN_VERTEX, 0, - input->bo->size - 1); - } else - OUT_BATCH(input->stride ? input->count : 0); - OUT_BATCH(0); /* Instance data step rate */ + brw->vb.nr_current_buffers = i; + ADVANCE_BATCH(); } - ADVANCE_BATCH(); BEGIN_BATCH(1 + brw->vb.nr_enabled * 2); - OUT_BATCH((CMD_VERTEX_ELEMENT << 16) | ((1 + brw->vb.nr_enabled * 2) - 2)); + OUT_BATCH((CMD_VERTEX_ELEMENT << 16) | (2*brw->vb.nr_enabled - 1)); for (i = 0; i < brw->vb.nr_enabled; i++) { struct brw_vertex_element *input = brw->vb.enabled[i]; uint32_t format = get_surface_type(input->glarray->Type, @@ -545,15 +589,15 @@ static void brw_emit_vertices(struct brw_context *brw) } if (intel->gen >= 6) { - OUT_BATCH((i << GEN6_VE0_INDEX_SHIFT) | + OUT_BATCH((input->buffer << GEN6_VE0_INDEX_SHIFT) | GEN6_VE0_VALID | (format << BRW_VE0_FORMAT_SHIFT) | - (0 << BRW_VE0_SRC_OFFSET_SHIFT)); + (input->offset << BRW_VE0_SRC_OFFSET_SHIFT)); } else { - OUT_BATCH((i << BRW_VE0_INDEX_SHIFT) | + OUT_BATCH((input->buffer << BRW_VE0_INDEX_SHIFT) | BRW_VE0_VALID | (format << BRW_VE0_FORMAT_SHIFT) | - (0 << BRW_VE0_SRC_OFFSET_SHIFT)); + (input->offset << BRW_VE0_SRC_OFFSET_SHIFT)); } if (intel->gen >= 5) @@ -568,7 +612,7 @@ static void brw_emit_vertices(struct brw_context *brw) (comp3 << BRW_VE1_COMPONENT_3_SHIFT) | ((i * 4) << BRW_VE1_DST_OFFSET_SHIFT)); } - ADVANCE_BATCH(); + CACHED_BATCH(); } const struct brw_tracked_state brw_vertices = { @@ -597,25 +641,20 @@ static void brw_prepare_indices(struct brw_context *brw) ib_type_size = get_size(index_buffer->type); ib_size = ib_type_size * index_buffer->count; - bufferobj = index_buffer->obj;; + bufferobj = index_buffer->obj; /* Turn into a proper VBO: */ if (!_mesa_is_bufferobj(bufferobj)) { - brw->ib.start_vertex_offset = 0; /* Get new bufferobj, offset: */ - get_space(brw, ib_size, &bo, &offset); - - /* Straight upload - */ - drm_intel_gem_bo_map_gtt(bo); - memcpy((char *)bo->virtual + offset, index_buffer->ptr, ib_size); - drm_intel_gem_bo_unmap_gtt(bo); + intel_upload_data(&brw->intel, index_buffer->ptr, ib_size, ib_type_size, + &bo, &offset); + brw->ib.start_vertex_offset = offset / ib_type_size; + offset = 0; } else { offset = (GLuint) (unsigned long) index_buffer->ptr; - brw->ib.start_vertex_offset = 0; /* If the index buffer isn't aligned to its element size, we have to * rebase it into a temporary. @@ -627,41 +666,35 @@ static void brw_prepare_indices(struct brw_context *brw) bufferobj); map += offset; - get_space(brw, ib_size, &bo, &offset); - - drm_intel_bo_subdata(bo, offset, ib_size, map); + intel_upload_data(&brw->intel, map, ib_size, ib_type_size, + &bo, &offset); + brw->ib.start_vertex_offset = offset / ib_type_size; + offset = 0; ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER_ARB, bufferobj); } else { - bo = intel_bufferobj_buffer(intel, intel_buffer_object(bufferobj), - INTEL_READ); - drm_intel_bo_reference(bo); - /* Use CMD_3D_PRIM's start_vertex_offset to avoid re-uploading * the index buffer state when we're just moving the start index * of our drawing. */ brw->ib.start_vertex_offset = offset / ib_type_size; - offset = 0; - ib_size = bo->size; + + bo = intel_bufferobj_source(intel, intel_buffer_object(bufferobj), + &offset); + drm_intel_bo_reference(bo); } } - if (brw->ib.bo != bo || - brw->ib.offset != offset || - brw->ib.size != ib_size) - { + if (brw->ib.bo != bo || brw->ib.offset != offset) { drm_intel_bo_unreference(brw->ib.bo); brw->ib.bo = bo; brw->ib.offset = offset; - brw->ib.size = ib_size; + brw_add_validated_bo(brw, brw->ib.bo); brw->state.dirty.brw |= BRW_NEW_INDEX_BUFFER; } else { drm_intel_bo_unreference(bo); } - - brw_add_validated_bo(brw, brw->ib.bo); } const struct brw_tracked_state brw_indices = { @@ -681,29 +714,18 @@ static void brw_emit_index_buffer(struct brw_context *brw) if (index_buffer == NULL) return; - /* Emit the indexbuffer packet: - */ - { - struct brw_indexbuffer ib; - - memset(&ib, 0, sizeof(ib)); - - ib.header.bits.opcode = CMD_INDEX_BUFFER; - ib.header.bits.length = sizeof(ib)/4 - 2; - ib.header.bits.index_format = get_index_type(index_buffer->type); - ib.header.bits.cut_index_enable = 0; - - BEGIN_BATCH(4); - OUT_BATCH( ib.header.dword ); - OUT_RELOC(brw->ib.bo, - I915_GEM_DOMAIN_VERTEX, 0, - brw->ib.offset); - OUT_RELOC(brw->ib.bo, - I915_GEM_DOMAIN_VERTEX, 0, - brw->ib.offset + brw->ib.size - 1); - OUT_BATCH( 0 ); - ADVANCE_BATCH(); - } + BEGIN_BATCH(3); + OUT_BATCH(CMD_INDEX_BUFFER << 16 | + /* cut index enable << 10 */ + get_index_type(index_buffer->type) << 8 | + 1); + OUT_RELOC(brw->ib.bo, + I915_GEM_DOMAIN_VERTEX, 0, + brw->ib.offset); + OUT_RELOC(brw->ib.bo, + I915_GEM_DOMAIN_VERTEX, 0, + brw->ib.bo->size - 1); + ADVANCE_BATCH(); } const struct brw_tracked_state brw_index_buffer = { diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp index 9a71e5377df..30e3bd54469 100644 --- a/src/mesa/drivers/dri/i965/brw_fs.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs.cpp @@ -41,7 +41,6 @@ extern "C" { #include "brw_context.h" #include "brw_eu.h" #include "brw_wm.h" -#include "talloc.h" } #include "brw_fs.h" #include "../glsl/glsl_types.h" @@ -56,7 +55,7 @@ brw_new_shader(struct gl_context *ctx, GLuint name, GLuint type) { struct brw_shader *shader; - shader = talloc_zero(NULL, struct brw_shader); + shader = rzalloc(NULL, struct brw_shader); if (shader) { shader->base.Type = type; shader->base.Name = name; @@ -70,7 +69,7 @@ struct gl_shader_program * brw_new_shader_program(struct gl_context *ctx, GLuint name) { struct brw_shader_program *prog; - prog = talloc_zero(NULL, struct brw_shader_program); + prog = rzalloc(NULL, struct brw_shader_program); if (prog) { prog->base.Name = name; _mesa_init_shader_program(ctx, &prog->base); @@ -96,11 +95,11 @@ brw_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) struct brw_shader *shader = (struct brw_shader *)prog->_LinkedShaders[MESA_SHADER_FRAGMENT]; if (shader != NULL) { - void *mem_ctx = talloc_new(NULL); + void *mem_ctx = ralloc_context(NULL); bool progress; if (shader->ir) - talloc_free(shader->ir); + ralloc_free(shader->ir); shader->ir = new(shader) exec_list; clone_ir_list(mem_ctx, shader->ir, shader->base.ir); @@ -150,7 +149,7 @@ brw_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) validate_ir_tree(shader->ir); reparent_ir(shader->ir, shader->ir); - talloc_free(mem_ctx); + ralloc_free(mem_ctx); } if (!_mesa_ir_link_shader(ctx, prog)) @@ -237,8 +236,8 @@ fs_visitor::virtual_grf_alloc(int size) virtual_grf_array_size = 16; else virtual_grf_array_size *= 2; - virtual_grf_sizes = talloc_realloc(mem_ctx, virtual_grf_sizes, - int, virtual_grf_array_size); + virtual_grf_sizes = reralloc(mem_ctx, virtual_grf_sizes, int, + virtual_grf_array_size); /* This slot is always unused. */ virtual_grf_sizes[0] = 0; @@ -495,7 +494,7 @@ fs_visitor::emit_fragcoord_interpolation(ir_variable *ir) wpos.reg_offset++; /* gl_FragCoord.w: Already set up in emit_interpolation */ - emit(fs_inst(BRW_OPCODE_MOV, wpos, this->wpos_w)); + emit(fs_inst(BRW_OPCODE_MOV, wpos, this->pixel_w)); return reg; } @@ -662,14 +661,18 @@ fs_visitor::emit_math(fs_opcodes opcode, fs_reg dst, fs_reg src0, fs_reg src1) assert(opcode == FS_OPCODE_POW); if (intel->gen >= 6) { - /* Can't do hstride == 0 args to gen6 math, so expand it out. */ - if (src0.file == UNIFORM) { + /* Can't do hstride == 0 args to gen6 math, so expand it out. + * + * The hardware ignores source modifiers (negate and abs) on math + * instructions, so we also move to a temp to set those up. + */ + if (src0.file == UNIFORM || src0.abs || src0.negate) { fs_reg expanded = fs_reg(this, glsl_type::float_type); emit(fs_inst(BRW_OPCODE_MOV, expanded, src0)); src0 = expanded; } - if (src1.file == UNIFORM) { + if (src1.file == UNIFORM || src1.abs || src1.negate) { fs_reg expanded = fs_reg(this, glsl_type::float_type); emit(fs_inst(BRW_OPCODE_MOV, expanded, src1)); src1 = expanded; @@ -1338,6 +1341,37 @@ fs_visitor::visit(ir_texture *ir) ir->coordinate->accept(this); fs_reg coordinate = this->result; + if (ir->offset != NULL) { + ir_constant *offset = ir->offset->as_constant(); + assert(offset != NULL); + + signed char offsets[3]; + for (unsigned i = 0; i < ir->offset->type->vector_elements; i++) + offsets[i] = (signed char) offset->value.i[i]; + + /* Combine all three offsets into a single unsigned dword: + * + * bits 11:8 - U Offset (X component) + * bits 7:4 - V Offset (Y component) + * bits 3:0 - R Offset (Z component) + */ + unsigned offset_bits = 0; + for (unsigned i = 0; i < ir->offset->type->vector_elements; i++) { + const unsigned shift = 4 * (2 - i); + offset_bits |= (offsets[i] << shift) & (0xF << shift); + } + + /* Explicitly set up the message header by copying g0 to msg reg m1. */ + emit(fs_inst(BRW_OPCODE_MOV, fs_reg(MRF, 1, BRW_REGISTER_TYPE_UD), + fs_reg(GRF, 0, BRW_REGISTER_TYPE_UD))); + + /* Then set the offset bits in DWord 2 of the message header. */ + emit(fs_inst(BRW_OPCODE_MOV, + fs_reg(retype(brw_vec1_reg(BRW_MESSAGE_REGISTER_FILE, 1, 2), + BRW_REGISTER_TYPE_UD)), + fs_reg(brw_imm_uw(offset_bits)))); + } + /* Should be lowered by do_lower_texture_projection */ assert(!ir->projector); @@ -1398,6 +1432,14 @@ fs_visitor::visit(ir_texture *ir) inst = emit_texture_gen5(ir, dst, coordinate); } + /* If there's an offset, we already set up m1. To avoid the implied move, + * use the null register. Otherwise, we want an implied move from g0. + */ + if (ir->offset != NULL) + inst->src[0] = fs_reg(brw_null_reg()); + else + inst->src[0] = fs_reg(retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UW)); + inst->sampler = sampler; this->result = dst; @@ -2066,7 +2108,7 @@ fs_visitor::emit_fb_writes() } for (int target = 0; target < c->key.nr_color_regions; target++) { - this->current_annotation = talloc_asprintf(this->mem_ctx, + this->current_annotation = ralloc_asprintf(this->mem_ctx, "FB write target %d", target); if (this->frag_color || this->frag_data) { @@ -2244,7 +2286,7 @@ fs_visitor::generate_math(fs_inst *inst, } void -fs_visitor::generate_tex(fs_inst *inst, struct brw_reg dst) +fs_visitor::generate_tex(fs_inst *inst, struct brw_reg dst, struct brw_reg src) { int msg_type = -1; int rlen = 4; @@ -2302,7 +2344,7 @@ fs_visitor::generate_tex(fs_inst *inst, struct brw_reg dst) brw_SAMPLE(p, retype(dst, BRW_REGISTER_TYPE_UW), inst->base_mrf, - retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UW), + src, SURF_INDEX_TEXTURE(inst->sampler), inst->sampler, WRITEMASK_XYZW, @@ -2756,8 +2798,8 @@ void fs_visitor::calculate_live_intervals() { int num_vars = this->virtual_grf_next; - int *def = talloc_array(mem_ctx, int, num_vars); - int *use = talloc_array(mem_ctx, int, num_vars); + int *def = ralloc_array(mem_ctx, int, num_vars); + int *use = ralloc_array(mem_ctx, int, num_vars); int loop_depth = 0; int loop_start = 0; int bb_header_ip = 0; @@ -2840,8 +2882,8 @@ fs_visitor::calculate_live_intervals() } } - talloc_free(this->virtual_grf_def); - talloc_free(this->virtual_grf_use); + ralloc_free(this->virtual_grf_def); + ralloc_free(this->virtual_grf_use); this->virtual_grf_def = def; this->virtual_grf_use = use; @@ -3017,6 +3059,8 @@ fs_visitor::register_coalesce() inst->dst.type != inst->src[0].type) continue; + bool has_source_modifiers = inst->src[0].abs || inst->src[0].negate; + /* Found a move of a GRF to a GRF. Let's see if we can coalesce * them: check for no writes to either one until the exit of the * program. @@ -3041,6 +3085,14 @@ fs_visitor::register_coalesce() break; } } + + /* The gen6 MATH instruction can't handle source modifiers, so avoid + * coalescing those for now. We should do something more specific. + */ + if (intel->gen == 6 && scan_inst->is_math() && has_source_modifiers) { + interfered = true; + break; + } } if (interfered) { continue; @@ -3358,20 +3410,25 @@ void fs_visitor::generate_code() { int last_native_inst = 0; - struct brw_instruction *if_stack[16], *loop_stack[16]; - int if_stack_depth = 0, loop_stack_depth = 0; - int if_depth_in_loop[16]; const char *last_annotation_string = NULL; ir_instruction *last_annotation_ir = NULL; + int if_stack_array_size = 16; + int loop_stack_array_size = 16; + int if_stack_depth = 0, loop_stack_depth = 0; + brw_instruction **if_stack = + rzalloc_array(this->mem_ctx, brw_instruction *, if_stack_array_size); + brw_instruction **loop_stack = + rzalloc_array(this->mem_ctx, brw_instruction *, loop_stack_array_size); + int *if_depth_in_loop = + rzalloc_array(this->mem_ctx, int, loop_stack_array_size); + + if (unlikely(INTEL_DEBUG & DEBUG_WM)) { printf("Native code for fragment shader %d:\n", ctx->Shader.CurrentFragmentProgram->Name); } - if_depth_in_loop[loop_stack_depth] = 0; - - memset(&if_stack, 0, sizeof(if_stack)); foreach_iter(exec_list_iterator, iter, this->instructions) { fs_inst *inst = (fs_inst *)iter.get(); struct brw_reg src[3], dst; @@ -3455,7 +3512,6 @@ fs_visitor::generate_code() break; case BRW_OPCODE_IF: - assert(if_stack_depth < 16); if (inst->src[0].file != BAD_FILE) { assert(intel->gen >= 6); if_stack[if_stack_depth] = brw_IF_gen6(p, inst->conditional_mod, src[0], src[1]); @@ -3464,6 +3520,11 @@ fs_visitor::generate_code() } if_depth_in_loop[loop_stack_depth]++; if_stack_depth++; + if (if_stack_array_size <= if_stack_depth) { + if_stack_array_size *= 2; + if_stack = reralloc(this->mem_ctx, if_stack, brw_instruction *, + if_stack_array_size); + } break; case BRW_OPCODE_ELSE: @@ -3478,6 +3539,13 @@ fs_visitor::generate_code() case BRW_OPCODE_DO: loop_stack[loop_stack_depth++] = brw_DO(p, BRW_EXECUTE_8); + if (loop_stack_array_size <= loop_stack_depth) { + loop_stack_array_size *= 2; + loop_stack = reralloc(this->mem_ctx, loop_stack, brw_instruction *, + loop_stack_array_size); + if_depth_in_loop = reralloc(this->mem_ctx, if_depth_in_loop, int, + loop_stack_array_size); + } if_depth_in_loop[loop_stack_depth] = 0; break; @@ -3540,7 +3608,7 @@ fs_visitor::generate_code() case FS_OPCODE_TEX: case FS_OPCODE_TXB: case FS_OPCODE_TXL: - generate_tex(inst, dst); + generate_tex(inst, dst, src[0]); break; case FS_OPCODE_DISCARD_NOT: generate_discard_not(inst, dst); @@ -3596,6 +3664,10 @@ fs_visitor::generate_code() last_native_inst = p->nr_insn; } + ralloc_free(if_stack); + ralloc_free(loop_stack); + ralloc_free(if_depth_in_loop); + brw_set_uip_jip(p); /* OK, while the INTEL_DEBUG=wm above is very nice for debugging FS diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h index f0497957bc4..8352760acf7 100644 --- a/src/mesa/drivers/dri/i965/brw_fs.h +++ b/src/mesa/drivers/dri/i965/brw_fs.h @@ -41,7 +41,6 @@ extern "C" { #include "brw_context.h" #include "brw_eu.h" #include "brw_wm.h" -#include "talloc.h" } #include "../glsl/glsl_types.h" #include "../glsl/ir.h" @@ -83,13 +82,13 @@ enum fs_opcodes { class fs_reg { public: - /* Callers of this talloc-based new need not call delete. It's - * easier to just talloc_free 'ctx' (or any of its ancestors). */ + /* Callers of this ralloc-based new need not call delete. It's + * easier to just ralloc_free 'ctx' (or any of its ancestors). */ static void* operator new(size_t size, void *ctx) { void *node; - node = talloc_size(ctx, size); + node = ralloc_size(ctx, size); assert(node != NULL); return node; @@ -193,13 +192,13 @@ static const fs_reg reg_null_d(ARF, BRW_ARF_NULL, BRW_REGISTER_TYPE_D); class fs_inst : public exec_node { public: - /* Callers of this talloc-based new need not call delete. It's - * easier to just talloc_free 'ctx' (or any of its ancestors). */ + /* Callers of this ralloc-based new need not call delete. It's + * easier to just ralloc_free 'ctx' (or any of its ancestors). */ static void* operator new(size_t size, void *ctx) { void *node; - node = talloc_zero_size(ctx, size); + node = rzalloc_size(ctx, size); assert(node != NULL); return node; @@ -361,7 +360,7 @@ public: this->fp = brw->fragment_program; this->intel = &brw->intel; this->ctx = &intel->ctx; - this->mem_ctx = talloc_new(NULL); + this->mem_ctx = ralloc_context(NULL); this->shader = shader; this->fail = false; this->variable_ht = hash_table_ctor(0, @@ -405,7 +404,7 @@ public: ~fs_visitor() { - talloc_free(this->mem_ctx); + ralloc_free(this->mem_ctx); hash_table_dtor(this->variable_ht); } @@ -454,7 +453,7 @@ public: void generate_fb_write(fs_inst *inst); void generate_linterp(fs_inst *inst, struct brw_reg dst, struct brw_reg *src); - void generate_tex(fs_inst *inst, struct brw_reg dst); + void generate_tex(fs_inst *inst, struct brw_reg dst, struct brw_reg src); void generate_math(fs_inst *inst, struct brw_reg dst, struct brw_reg *src); void generate_discard_not(fs_inst *inst, struct brw_reg temp); void generate_discard_and(fs_inst *inst, struct brw_reg temp); diff --git a/src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp b/src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp index 20bfa4c3ea3..7f3f52854d2 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp @@ -141,7 +141,7 @@ ir_channel_expressions_visitor::visit_leave(ir_assignment *ir) return visit_continue; if (!this->mem_ctx) - this->mem_ctx = talloc_parent(ir); + this->mem_ctx = ralloc_parent(ir); for (i = 0; i < expr->get_num_operands(); i++) { if (expr->operands[i]->type->is_vector()) { diff --git a/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp b/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp index 078a349abdf..f0277423170 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp @@ -41,7 +41,6 @@ extern "C" { #include "brw_context.h" #include "brw_eu.h" #include "brw_wm.h" -#include "talloc.h" } #include "brw_fs.h" #include "../glsl/glsl_types.h" @@ -234,8 +233,8 @@ fs_visitor::assign_regs() } - talloc_free(g); - talloc_free(regs); + ralloc_free(g); + ralloc_free(regs); return false; } @@ -273,8 +272,8 @@ fs_visitor::assign_regs() this->grf_used = last_grf + 1; - talloc_free(g); - talloc_free(regs); + ralloc_free(g); + ralloc_free(regs); return true; } diff --git a/src/mesa/drivers/dri/i965/brw_fs_schedule_instructions.cpp b/src/mesa/drivers/dri/i965/brw_fs_schedule_instructions.cpp index c8f0b27b76f..bff8f82f3f7 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_schedule_instructions.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_schedule_instructions.cpp @@ -39,7 +39,6 @@ extern "C" { #include "brw_context.h" #include "brw_eu.h" #include "brw_wm.h" -#include "talloc.h" } #include "brw_fs.h" #include "../glsl/glsl_types.h" @@ -129,7 +128,7 @@ public: instruction_scheduler(fs_visitor *v, void *mem_ctx, int virtual_grf_count) { this->v = v; - this->mem_ctx = talloc_new(mem_ctx); + this->mem_ctx = ralloc_context(mem_ctx); this->virtual_grf_count = virtual_grf_count; this->instructions.make_empty(); this->instructions_to_schedule = 0; @@ -137,7 +136,7 @@ public: ~instruction_scheduler() { - talloc_free(this->mem_ctx); + ralloc_free(this->mem_ctx); } void add_barrier_deps(schedule_node *n); void add_dep(schedule_node *before, schedule_node *after, int latency); @@ -196,11 +195,11 @@ instruction_scheduler::add_dep(schedule_node *before, schedule_node *after, else before->child_array_size *= 2; - before->children = talloc_realloc(mem_ctx, before->children, - schedule_node *, - before->child_array_size); - before->child_latency = talloc_realloc(mem_ctx, before->child_latency, - int, before->child_array_size); + before->children = reralloc(mem_ctx, before->children, + schedule_node *, + before->child_array_size); + before->child_latency = reralloc(mem_ctx, before->child_latency, + int, before->child_array_size); } before->children[before->child_count] = after; diff --git a/src/mesa/drivers/dri/i965/brw_fs_vector_splitting.cpp b/src/mesa/drivers/dri/i965/brw_fs_vector_splitting.cpp index 2be6b08b5c7..530ffa26580 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_vector_splitting.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_vector_splitting.cpp @@ -69,7 +69,7 @@ public: ir_variable *components[4]; - /** talloc_parent(this->var) -- the shader's talloc context. */ + /** ralloc_parent(this->var) -- the shader's ralloc context. */ void *mem_ctx; }; @@ -77,13 +77,13 @@ class ir_vector_reference_visitor : public ir_hierarchical_visitor { public: ir_vector_reference_visitor(void) { - this->mem_ctx = talloc_new(NULL); + this->mem_ctx = ralloc_context(NULL); this->variable_list.make_empty(); } ~ir_vector_reference_visitor(void) { - talloc_free(mem_ctx); + ralloc_free(mem_ctx); } virtual ir_visitor_status visit(ir_variable *); @@ -358,7 +358,7 @@ brw_do_vector_splitting(exec_list *instructions) if (refs.variable_list.is_empty()) return false; - void *mem_ctx = talloc_new(NULL); + void *mem_ctx = ralloc_context(NULL); /* Replace the decls of the vectors to be split with their split * components. @@ -368,10 +368,10 @@ brw_do_vector_splitting(exec_list *instructions) const struct glsl_type *type; type = glsl_type::get_instance(entry->var->type->base_type, 1, 1); - entry->mem_ctx = talloc_parent(entry->var); + entry->mem_ctx = ralloc_parent(entry->var); for (unsigned int i = 0; i < entry->var->type->vector_elements; i++) { - const char *name = talloc_asprintf(mem_ctx, "%s_%c", + const char *name = ralloc_asprintf(mem_ctx, "%s_%c", entry->var->name, "xyzw"[i]); @@ -386,7 +386,7 @@ brw_do_vector_splitting(exec_list *instructions) ir_vector_splitting_visitor split(&refs.variable_list); visit_list_elements(&split, instructions); - talloc_free(mem_ctx); + ralloc_free(mem_ctx); return true; } diff --git a/src/mesa/drivers/dri/i965/brw_misc_state.c b/src/mesa/drivers/dri/i965/brw_misc_state.c index 79afe19deba..c768be23fa7 100644 --- a/src/mesa/drivers/dri/i965/brw_misc_state.c +++ b/src/mesa/drivers/dri/i965/brw_misc_state.c @@ -74,7 +74,7 @@ static void upload_binding_table_pointers(struct brw_context *brw) struct intel_context *intel = &brw->intel; BEGIN_BATCH(6); - OUT_BATCH(CMD_BINDING_TABLE_PTRS << 16 | (6 - 2)); + OUT_BATCH(_3DSTATE_BINDING_TABLE_POINTERS << 16 | (6 - 2)); OUT_BATCH(brw->vs.bind_bo_offset); OUT_BATCH(0); /* gs */ OUT_BATCH(0); /* clip */ @@ -104,7 +104,7 @@ static void upload_gen6_binding_table_pointers(struct brw_context *brw) struct intel_context *intel = &brw->intel; BEGIN_BATCH(4); - OUT_BATCH(CMD_BINDING_TABLE_PTRS << 16 | + OUT_BATCH(_3DSTATE_BINDING_TABLE_POINTERS << 16 | GEN6_BINDING_TABLE_MODIFY_VS | GEN6_BINDING_TABLE_MODIFY_GS | GEN6_BINDING_TABLE_MODIFY_PS | @@ -142,7 +142,7 @@ static void upload_pipelined_state_pointers(struct brw_context *brw ) } BEGIN_BATCH(7); - OUT_BATCH(CMD_PIPELINED_STATE_POINTERS << 16 | (7 - 2)); + OUT_BATCH(_3DSTATE_PIPELINED_POINTERS << 16 | (7 - 2)); OUT_RELOC(brw->vs.state_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 0); if (brw->gs.prog_active) OUT_RELOC(brw->gs.state_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 1); @@ -151,7 +151,7 @@ static void upload_pipelined_state_pointers(struct brw_context *brw ) OUT_RELOC(brw->clip.state_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 1); OUT_RELOC(brw->sf.state_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 0); OUT_RELOC(brw->wm.state_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 0); - OUT_RELOC(brw->cc.state_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, + OUT_RELOC(brw->intel.batch.bo, I915_GEM_DOMAIN_INSTRUCTION, 0, brw->cc.state_offset); ADVANCE_BATCH(); @@ -301,16 +301,15 @@ const struct brw_tracked_state brw_depthbuffer = { static void upload_polygon_stipple(struct brw_context *brw) { + struct intel_context *intel = &brw->intel; struct gl_context *ctx = &brw->intel.ctx; - struct brw_polygon_stipple bps; GLuint i; if (!ctx->Polygon.StippleFlag) return; - memset(&bps, 0, sizeof(bps)); - bps.header.opcode = _3DSTATE_POLY_STIPPLE_PATTERN; - bps.header.length = sizeof(bps)/4-2; + BEGIN_BATCH(33); + OUT_BATCH(_3DSTATE_POLY_STIPPLE_PATTERN << 16 | (33 - 2)); /* Polygon stipple is provided in OpenGL order, i.e. bottom * row first. If we're rendering to a window (i.e. the @@ -321,14 +320,13 @@ static void upload_polygon_stipple(struct brw_context *brw) */ if (ctx->DrawBuffer->Name == 0) { for (i = 0; i < 32; i++) - bps.stipple[i] = ctx->PolygonStipple[31 - i]; /* invert */ + OUT_BATCH(ctx->PolygonStipple[31 - i]); /* invert */ } else { for (i = 0; i < 32; i++) - bps.stipple[i] = ctx->PolygonStipple[i]; /* don't invert */ + OUT_BATCH(ctx->PolygonStipple[i]); } - - BRW_CACHED_BATCH_STRUCT(brw, &bps); + CACHED_BATCH(); } const struct brw_tracked_state brw_polygon_stipple = { @@ -347,15 +345,14 @@ const struct brw_tracked_state brw_polygon_stipple = { static void upload_polygon_stipple_offset(struct brw_context *brw) { + struct intel_context *intel = &brw->intel; struct gl_context *ctx = &brw->intel.ctx; - struct brw_polygon_stipple_offset bpso; if (!ctx->Polygon.StippleFlag) return; - memset(&bpso, 0, sizeof(bpso)); - bpso.header.opcode = _3DSTATE_POLY_STIPPLE_OFFSET; - bpso.header.length = sizeof(bpso)/4-2; + BEGIN_BATCH(2); + OUT_BATCH(_3DSTATE_POLY_STIPPLE_OFFSET << 16 | (2-2)); /* If we're drawing to a system window (ctx->DrawBuffer->Name == 0), * we have to invert the Y axis in order to match the OpenGL @@ -365,16 +362,11 @@ static void upload_polygon_stipple_offset(struct brw_context *brw) * system works just fine, and there's no window system to * worry about. */ - if (brw->intel.ctx.DrawBuffer->Name == 0) { - bpso.bits0.x_offset = 0; - bpso.bits0.y_offset = (32 - (ctx->DrawBuffer->Height & 31)) & 31; - } - else { - bpso.bits0.y_offset = 0; - bpso.bits0.x_offset = 0; - } - - BRW_CACHED_BATCH_STRUCT(brw, &bpso); + if (brw->intel.ctx.DrawBuffer->Name == 0) + OUT_BATCH((32 - (ctx->DrawBuffer->Height & 31)) & 31); + else + OUT_BATCH(0); + CACHED_BATCH(); } #define _NEW_WINDOW_POS 0x40000000 @@ -393,18 +385,17 @@ const struct brw_tracked_state brw_polygon_stipple_offset = { */ static void upload_aa_line_parameters(struct brw_context *brw) { + struct intel_context *intel = &brw->intel; struct gl_context *ctx = &brw->intel.ctx; - struct brw_aa_line_parameters balp; if (!ctx->Line.SmoothFlag || !brw->has_aa_line_parameters) return; + OUT_BATCH(_3DSTATE_AA_LINE_PARAMETERS << 16 | (3 - 2)); /* use legacy aa line coverage computation */ - memset(&balp, 0, sizeof(balp)); - balp.header.opcode = _3DSTATE_AA_LINE_PARAMETERS; - balp.header.length = sizeof(balp) / 4 - 2; - - BRW_CACHED_BATCH_STRUCT(brw, &balp); + OUT_BATCH(0); + OUT_BATCH(0); + CACHED_BATCH(); } const struct brw_tracked_state brw_aa_line_parameters = { @@ -422,28 +413,21 @@ const struct brw_tracked_state brw_aa_line_parameters = { static void upload_line_stipple(struct brw_context *brw) { + struct intel_context *intel = &brw->intel; struct gl_context *ctx = &brw->intel.ctx; - struct brw_line_stipple bls; GLfloat tmp; GLint tmpi; if (!ctx->Line.StippleFlag) return; - memset(&bls, 0, sizeof(bls)); - bls.header.opcode = _3DSTATE_LINE_STIPPLE_PATTERN; - bls.header.length = sizeof(bls)/4 - 2; - - bls.bits0.pattern = ctx->Line.StipplePattern; - bls.bits1.repeat_count = ctx->Line.StippleFactor; - + BEGIN_BATCH(3); + OUT_BATCH(_3DSTATE_LINE_STIPPLE_PATTERN << 16 | (3 - 2)); + OUT_BATCH(ctx->Line.StipplePattern); tmp = 1.0 / (GLfloat) ctx->Line.StippleFactor; tmpi = tmp * (1<<13); - - - bls.bits1.inverse_repeat_count = tmpi; - - BRW_CACHED_BATCH_STRUCT(brw, &bls); + OUT_BATCH(tmpi << 16 | ctx->Line.StippleFactor); + CACHED_BATCH(); } const struct brw_tracked_state brw_line_stipple = { @@ -565,7 +549,7 @@ static void upload_state_base_address( struct brw_context *brw ) BEGIN_BATCH(10); OUT_BATCH(CMD_STATE_BASE_ADDRESS << 16 | (10 - 2)); OUT_BATCH(1); /* General state base address */ - OUT_RELOC(intel->batch->buf, I915_GEM_DOMAIN_SAMPLER, 0, + OUT_RELOC(intel->batch.bo, I915_GEM_DOMAIN_SAMPLER, 0, 1); /* Surface state base address */ OUT_BATCH(1); /* Dynamic state base address */ OUT_BATCH(1); /* Indirect object base address */ @@ -579,7 +563,7 @@ static void upload_state_base_address( struct brw_context *brw ) BEGIN_BATCH(8); OUT_BATCH(CMD_STATE_BASE_ADDRESS << 16 | (8 - 2)); OUT_BATCH(1); /* General state base address */ - OUT_RELOC(intel->batch->buf, I915_GEM_DOMAIN_SAMPLER, 0, + OUT_RELOC(intel->batch.bo, I915_GEM_DOMAIN_SAMPLER, 0, 1); /* Surface state base address */ OUT_BATCH(1); /* Indirect object base address */ OUT_BATCH(1); /* Instruction base address */ @@ -591,7 +575,7 @@ static void upload_state_base_address( struct brw_context *brw ) BEGIN_BATCH(6); OUT_BATCH(CMD_STATE_BASE_ADDRESS << 16 | (6 - 2)); OUT_BATCH(1); /* General state base address */ - OUT_RELOC(intel->batch->buf, I915_GEM_DOMAIN_SAMPLER, 0, + OUT_RELOC(intel->batch.bo, I915_GEM_DOMAIN_SAMPLER, 0, 1); /* Surface state base address */ OUT_BATCH(1); /* Indirect object base address */ OUT_BATCH(1); /* General state upper bound */ diff --git a/src/mesa/drivers/dri/i965/brw_program.c b/src/mesa/drivers/dri/i965/brw_program.c index 94efa791091..7d653327e30 100644 --- a/src/mesa/drivers/dri/i965/brw_program.c +++ b/src/mesa/drivers/dri/i965/brw_program.c @@ -36,7 +36,7 @@ #include "program/program.h" #include "program/programopt.h" #include "tnl/tnl.h" -#include "talloc.h" +#include "../glsl/ralloc.h" #include "brw_context.h" #include "brw_wm.h" @@ -115,7 +115,7 @@ shader_error(struct gl_context *ctx, struct gl_program *prog, const char *msg) shader = _mesa_lookup_shader_program(ctx, prog->Id); if (shader) { - shader->InfoLog = talloc_strdup_append(shader->InfoLog, msg); + ralloc_strcat(&shader->InfoLog, msg); shader->LinkStatus = GL_FALSE; } } diff --git a/src/mesa/drivers/dri/i965/brw_queryobj.c b/src/mesa/drivers/dri/i965/brw_queryobj.c index 656aad630a1..b41d05dd438 100644 --- a/src/mesa/drivers/dri/i965/brw_queryobj.c +++ b/src/mesa/drivers/dri/i965/brw_queryobj.c @@ -177,7 +177,7 @@ brw_end_query(struct gl_context *ctx, struct gl_query_object *q) ADVANCE_BATCH(); } - intel_batchbuffer_flush(intel->batch); + intel_batchbuffer_flush(intel); } else { /* Flush the batchbuffer in case it has writes to our query BO. * Have later queries write to a new query BO so that further rendering @@ -185,7 +185,7 @@ brw_end_query(struct gl_context *ctx, struct gl_query_object *q) */ if (query->bo) { brw_emit_query_end(brw); - intel_batchbuffer_flush(intel->batch); + intel_batchbuffer_flush(intel); drm_intel_bo_unreference(brw->query.bo); brw->query.bo = NULL; diff --git a/src/mesa/drivers/dri/i965/brw_state.h b/src/mesa/drivers/dri/i965/brw_state.h index 4bb93e73369..86b0caa4a4e 100644 --- a/src/mesa/drivers/dri/i965/brw_state.h +++ b/src/mesa/drivers/dri/i965/brw_state.h @@ -164,26 +164,18 @@ void brw_destroy_caches( struct brw_context *brw ); /*********************************************************************** * brw_state_batch.c */ -#define BRW_BATCH_STRUCT(brw, s) intel_batchbuffer_data(brw->intel.batch, (s), \ +#define BRW_BATCH_STRUCT(brw, s) intel_batchbuffer_data(&brw->intel, (s), \ sizeof(*(s)), false) -#define BRW_CACHED_BATCH_STRUCT(brw, s) brw_cached_batch_struct( brw, (s), sizeof(*(s)) ) -GLboolean brw_cached_batch_struct( struct brw_context *brw, - const void *data, - GLuint sz ); -void brw_destroy_batch_cache( struct brw_context *brw ); -void brw_clear_batch_cache( struct brw_context *brw ); void *brw_state_batch(struct brw_context *brw, int size, int alignment, - drm_intel_bo **out_bo, uint32_t *out_offset); /* brw_wm_surface_state.c */ void brw_create_constant_surface(struct brw_context *brw, drm_intel_bo *bo, int width, - drm_intel_bo **out_bo, uint32_t *out_offset); #endif diff --git a/src/mesa/drivers/dri/i965/brw_state_batch.c b/src/mesa/drivers/dri/i965/brw_state_batch.c index a21af13caa3..213c7a38d8c 100644 --- a/src/mesa/drivers/dri/i965/brw_state_batch.c +++ b/src/mesa/drivers/dri/i965/brw_state_batch.c @@ -29,75 +29,10 @@ * Keith Whitwell <[email protected]> */ - - #include "brw_state.h" #include "intel_batchbuffer.h" #include "main/imports.h" - - -/* A facility similar to the data caching code above, which aims to - * prevent identical commands being issued repeatedly. - */ -GLboolean brw_cached_batch_struct( struct brw_context *brw, - const void *data, - GLuint sz ) -{ - struct brw_cached_batch_item *item = brw->cached_batch_items; - struct header *newheader = (struct header *)data; - - if (brw->emit_state_always) { - intel_batchbuffer_data(brw->intel.batch, data, sz, false); - return GL_TRUE; - } - - while (item) { - if (item->header->opcode == newheader->opcode) { - if (item->sz == sz && memcmp(item->header, newheader, sz) == 0) - return GL_FALSE; - if (item->sz != sz) { - free(item->header); - item->header = malloc(sz); - item->sz = sz; - } - goto emit; - } - item = item->next; - } - - assert(!item); - item = CALLOC_STRUCT(brw_cached_batch_item); - item->header = malloc(sz); - item->sz = sz; - item->next = brw->cached_batch_items; - brw->cached_batch_items = item; - - emit: - memcpy(item->header, newheader, sz); - intel_batchbuffer_data(brw->intel.batch, data, sz, false); - return GL_TRUE; -} - -void brw_clear_batch_cache( struct brw_context *brw ) -{ - struct brw_cached_batch_item *item = brw->cached_batch_items; - - while (item) { - struct brw_cached_batch_item *next = item->next; - free((void *)item->header); - free(item); - item = next; - } - - brw->cached_batch_items = NULL; -} - -void brw_destroy_batch_cache( struct brw_context *brw ) -{ - brw_clear_batch_cache(brw); -} - /** * Allocates a block of space in the batchbuffer for indirect state. * @@ -116,13 +51,12 @@ void * brw_state_batch(struct brw_context *brw, int size, int alignment, - drm_intel_bo **out_bo, uint32_t *out_offset) { - struct intel_batchbuffer *batch = brw->intel.batch; + struct intel_batchbuffer *batch = &brw->intel.batch; uint32_t offset; - assert(size < batch->buf->size); + assert(size < batch->bo->size); offset = ROUND_DOWN_TO(batch->state_batch_offset - size, alignment); /* If allocating from the top would wrap below the batchbuffer, or @@ -130,19 +64,13 @@ brw_state_batch(struct brw_context *brw, * space, then flush and try again. */ if (batch->state_batch_offset < size || - offset < batch->ptr - batch->map + batch->reserved_space) { - intel_batchbuffer_flush(batch); + offset < 4*batch->used + batch->reserved_space) { + intel_batchbuffer_flush(&brw->intel); offset = ROUND_DOWN_TO(batch->state_batch_offset - size, alignment); } batch->state_batch_offset = offset; - if (*out_bo != batch->buf) { - drm_intel_bo_unreference(*out_bo); - drm_intel_bo_reference(batch->buf); - *out_bo = batch->buf; - } - *out_offset = offset; - return batch->map + offset; + return batch->map + (offset>>2); } diff --git a/src/mesa/drivers/dri/i965/brw_state_cache.c b/src/mesa/drivers/dri/i965/brw_state_cache.c index 7045888ad4a..01eeb19a684 100644 --- a/src/mesa/drivers/dri/i965/brw_state_cache.c +++ b/src/mesa/drivers/dri/i965/brw_state_cache.c @@ -431,8 +431,6 @@ brw_clear_cache(struct brw_context *brw, struct brw_cache *cache) void brw_state_cache_check_size(struct brw_context *brw) { - DBG("%s (n_items=%d)\n", __FUNCTION__, brw->cache.n_items); - /* un-tuned guess. Each object is generally a page, so 1000 of them is 4 MB of * state cache. */ diff --git a/src/mesa/drivers/dri/i965/brw_state_dump.c b/src/mesa/drivers/dri/i965/brw_state_dump.c index e2628874712..fdce79da2f4 100644 --- a/src/mesa/drivers/dri/i965/brw_state_dump.c +++ b/src/mesa/drivers/dri/i965/brw_state_dump.c @@ -26,6 +26,7 @@ */ #include "main/mtypes.h" +#include "intel_batchbuffer.h" #include "brw_context.h" #include "brw_defines.h" @@ -54,7 +55,8 @@ state_out(const char *name, void *data, uint32_t hw_offset, int index, /** Generic, undecoded state buffer debug printout */ static void -state_struct_out(const char *name, drm_intel_bo *buffer, unsigned int state_size) +state_struct_out(const char *name, drm_intel_bo *buffer, + unsigned int offset, unsigned int size) { int i; @@ -62,8 +64,8 @@ state_struct_out(const char *name, drm_intel_bo *buffer, unsigned int state_size return; drm_intel_bo_map(buffer, GL_FALSE); - for (i = 0; i < state_size / 4; i++) { - state_out(name, buffer->virtual, buffer->offset, i, + for (i = 0; i < size / 4; i++) { + state_out(name, buffer->virtual + offset, buffer->offset + offset, i, "dword %d\n", i); } drm_intel_bo_unmap(buffer); @@ -98,21 +100,25 @@ get_965_surface_format(unsigned int surface_format) static void dump_wm_surface_state(struct brw_context *brw) { + dri_bo *bo; + GLubyte *base; int i; + bo = brw->intel.batch.bo; + drm_intel_bo_map(bo, GL_FALSE); + base = bo->virtual; + for (i = 0; i < brw->wm.nr_surfaces; i++) { - drm_intel_bo *surf_bo = brw->wm.surf_bo[i]; unsigned int surfoff; struct brw_surface_state *surf; char name[20]; - if (surf_bo == NULL) { + if (brw->wm.surf_offset[i] == 0) { fprintf(stderr, "WM SURF%d: NULL\n", i); continue; } - drm_intel_bo_map(surf_bo, GL_FALSE); - surfoff = surf_bo->offset + brw->wm.surf_offset[i]; - surf = (struct brw_surface_state *)(surf_bo->virtual + brw->wm.surf_offset[i]); + surfoff = bo->offset + brw->wm.surf_offset[i]; + surf = (struct brw_surface_state *)(base + brw->wm.surf_offset[i]); sprintf(name, "WM SURF%d", i); state_out(name, surf, surfoff, 0, "%s %s\n", @@ -127,9 +133,8 @@ static void dump_wm_surface_state(struct brw_context *brw) surf->ss4.min_lod); state_out(name, surf, surfoff, 5, "x,y offset: %d,%d\n", surf->ss5.x_offset, surf->ss5.y_offset); - - drm_intel_bo_unmap(surf_bo); } + drm_intel_bo_unmap(bo); } @@ -280,13 +285,14 @@ static void dump_cc_state(struct brw_context *brw) const char *name = "CC"; struct gen6_color_calc_state *cc; uint32_t cc_off; + dri_bo *bo = brw->intel.batch.bo; - if (brw->cc.state_bo == NULL) + if (brw->cc.state_offset == 0) return; - drm_intel_bo_map(brw->cc.state_bo, GL_FALSE); - cc = brw->cc.state_bo->virtual; - cc_off = brw->cc.state_bo->offset; + drm_intel_bo_map(bo, GL_FALSE); + cc = bo->virtual; + cc_off = bo->offset; state_out(name, cc, cc_off, 0, "alpha test format %s, round disable %d, stencil ref %d," "bf stencil ref %d\n", @@ -300,7 +306,7 @@ static void dump_cc_state(struct brw_context *brw) state_out(name, cc, cc_off, 4, "constant blue %f\n", cc->constant_b); state_out(name, cc, cc_off, 5, "constant alpha %f\n", cc->constant_a); - drm_intel_bo_unmap(brw->cc.state_bo); + drm_intel_bo_unmap(bo); } @@ -369,26 +375,29 @@ void brw_debug_batch(struct intel_context *intel) { struct brw_context *brw = brw_context(&intel->ctx); - state_struct_out("WM bind", brw->wm.bind_bo, 4 * brw->wm.nr_surfaces); + state_struct_out("WM bind", + brw->intel.batch.bo, + brw->wm.bind_bo_offset, + 4 * brw->wm.nr_surfaces); dump_wm_surface_state(brw); dump_wm_sampler_state(brw); if (intel->gen < 6) - state_struct_out("VS", brw->vs.state_bo, sizeof(struct brw_vs_unit_state)); + state_struct_out("VS", brw->vs.state_bo, 0, sizeof(struct brw_vs_unit_state)); brw_debug_prog("VS prog", brw->vs.prog_bo); if (intel->gen < 6) - state_struct_out("GS", brw->gs.state_bo, sizeof(struct brw_gs_unit_state)); + state_struct_out("GS", brw->gs.state_bo, 0, sizeof(struct brw_gs_unit_state)); brw_debug_prog("GS prog", brw->gs.prog_bo); if (intel->gen < 6) { - state_struct_out("SF", brw->sf.state_bo, sizeof(struct brw_sf_unit_state)); + state_struct_out("SF", brw->sf.state_bo, 0, sizeof(struct brw_sf_unit_state)); brw_debug_prog("SF prog", brw->sf.prog_bo); } dump_sf_viewport_state(brw); if (intel->gen < 6) - state_struct_out("WM", brw->wm.state_bo, sizeof(struct brw_wm_unit_state)); + state_struct_out("WM", brw->wm.state_bo, 0, sizeof(struct brw_wm_unit_state)); brw_debug_prog("WM prog", brw->wm.prog_bo); if (intel->gen >= 6) { diff --git a/src/mesa/drivers/dri/i965/brw_state_upload.c b/src/mesa/drivers/dri/i965/brw_state_upload.c index eba4411ca70..2d6fb37355d 100644 --- a/src/mesa/drivers/dri/i965/brw_state_upload.c +++ b/src/mesa/drivers/dri/i965/brw_state_upload.c @@ -176,17 +176,16 @@ void brw_init_state( struct brw_context *brw ) void brw_destroy_state( struct brw_context *brw ) { brw_destroy_caches(brw); - brw_destroy_batch_cache(brw); } /*********************************************************************** */ -static GLboolean check_state( const struct brw_state_flags *a, - const struct brw_state_flags *b ) +static GLuint check_state( const struct brw_state_flags *a, + const struct brw_state_flags *b ) { - return ((a->mesa & b->mesa) || - (a->brw & b->brw) || + return ((a->mesa & b->mesa) | + (a->brw & b->brw) | (a->cache & b->cache)); } @@ -233,7 +232,6 @@ static struct dirty_bit_map mesa_bits[] = { DEFINE_BIT(_NEW_MODELVIEW), DEFINE_BIT(_NEW_PROJECTION), DEFINE_BIT(_NEW_TEXTURE_MATRIX), - DEFINE_BIT(_NEW_ACCUM), DEFINE_BIT(_NEW_COLOR), DEFINE_BIT(_NEW_DEPTH), DEFINE_BIT(_NEW_EVAL), @@ -279,6 +277,10 @@ static struct dirty_bit_map brw_bits[] = { DEFINE_BIT(BRW_NEW_VERTICES), DEFINE_BIT(BRW_NEW_BATCH), DEFINE_BIT(BRW_NEW_DEPTH_BUFFER), + DEFINE_BIT(BRW_NEW_NR_WM_SURFACES), + DEFINE_BIT(BRW_NEW_NR_VS_SURFACES), + DEFINE_BIT(BRW_NEW_VS_CONSTBUF), + DEFINE_BIT(BRW_NEW_WM_CONSTBUF), {0, 0, 0} }; @@ -349,7 +351,7 @@ void brw_validate_state( struct brw_context *brw ) state->mesa |= brw->intel.NewGLState; brw->intel.NewGLState = 0; - brw_add_validated_bo(brw, intel->batch->buf); + brw_add_validated_bo(brw, intel->batch.bo); if (intel->gen >= 6) { atoms = gen6_atoms; @@ -375,14 +377,9 @@ void brw_validate_state( struct brw_context *brw ) brw->state.dirty.brw |= BRW_NEW_VERTEX_PROGRAM; } - if (state->mesa == 0 && - state->cache == 0 && - state->brw == 0) + if ((state->mesa | state->cache | state->brw) == 0) return; - if (brw->state.dirty.brw & BRW_NEW_CONTEXT) - brw_clear_batch_cache(brw); - brw->intel.Fallback = GL_FALSE; /* boolean, not bitfield */ /* do prepare stage for all atoms */ diff --git a/src/mesa/drivers/dri/i965/brw_util.c b/src/mesa/drivers/dri/i965/brw_util.c index e878da3850d..d28d9abcb33 100644 --- a/src/mesa/drivers/dri/i965/brw_util.c +++ b/src/mesa/drivers/dri/i965/brw_util.c @@ -37,16 +37,6 @@ #include "brw_util.h" #include "brw_defines.h" -GLuint brw_count_bits(uint64_t val) -{ - GLuint i; - for (i = 0; val ; val >>= 1) - if (val & 1) - i++; - return i; -} - - GLuint brw_translate_blend_equation( GLenum mode ) { switch (mode) { diff --git a/src/mesa/drivers/dri/i965/brw_util.h b/src/mesa/drivers/dri/i965/brw_util.h index 04f3175d3e1..940a8715502 100644 --- a/src/mesa/drivers/dri/i965/brw_util.h +++ b/src/mesa/drivers/dri/i965/brw_util.h @@ -35,7 +35,14 @@ #include "main/mtypes.h" -extern GLuint brw_count_bits(uint64_t val); +#ifdef __GNUC__ +#define brw_count_bits(v) __builtin_popcount(v) +#else +static inline GLuint brw_count_bits(uint64_t v) +{ + return _mesa_popcount(v>>32) + _mesa_popcount(v&0xffffffff); +} +#endif extern GLuint brw_parameter_list_state_flags(struct gl_program_parameter_list *paramList); extern GLuint brw_translate_blend_factor( GLenum factor ); extern GLuint brw_translate_blend_equation( GLenum mode ); diff --git a/src/mesa/drivers/dri/i965/brw_vs_surface_state.c b/src/mesa/drivers/dri/i965/brw_vs_surface_state.c index b0b05445eb9..48cf265e51b 100644 --- a/src/mesa/drivers/dri/i965/brw_vs_surface_state.c +++ b/src/mesa/drivers/dri/i965/brw_vs_surface_state.c @@ -124,13 +124,11 @@ brw_update_vs_constant_surface( struct gl_context *ctx, * it. */ if (brw->vs.const_bo == NULL) { - drm_intel_bo_unreference(brw->vs.surf_bo[surf]); - brw->vs.surf_bo[surf] = NULL; + brw->vs.surf_offset[surf] = 0; return; } brw_create_constant_surface(brw, brw->vs.const_bo, params->NumParameters, - &brw->vs.surf_bo[surf], &brw->vs.surf_offset[surf]); } @@ -166,11 +164,10 @@ static void upload_vs_surfaces(struct brw_context *brw) /* BRW_NEW_NR_VS_SURFACES */ if (brw->vs.nr_surfaces == 0) { - if (brw->vs.bind_bo) { - drm_intel_bo_unreference(brw->vs.bind_bo); - brw->vs.bind_bo = NULL; + if (brw->vs.bind_bo_offset) { brw->state.dirty.brw |= BRW_NEW_BINDING_TABLE; } + brw->vs.bind_bo_offset = 0; return; } @@ -180,15 +177,11 @@ static void upload_vs_surfaces(struct brw_context *brw) * space for the binding table. (once we have vs samplers) */ bind = brw_state_batch(brw, sizeof(uint32_t) * BRW_VS_MAX_SURF, - 32, &brw->vs.bind_bo, &brw->vs.bind_bo_offset); + 32, &brw->vs.bind_bo_offset); for (i = 0; i < BRW_VS_MAX_SURF; i++) { /* BRW_NEW_VS_CONSTBUF */ - if (brw->vs.surf_bo[i]) { - bind[i] = brw->vs.surf_offset[i]; - } else { - bind[i] = 0; - } + bind[i] = brw->vs.surf_offset[i]; } brw->state.dirty.brw |= BRW_NEW_BINDING_TABLE; diff --git a/src/mesa/drivers/dri/i965/brw_vtbl.c b/src/mesa/drivers/dri/i965/brw_vtbl.c index 100a21b59d7..152ee141568 100644 --- a/src/mesa/drivers/dri/i965/brw_vtbl.c +++ b/src/mesa/drivers/dri/i965/brw_vtbl.c @@ -73,15 +73,11 @@ static void brw_destroy_context( struct intel_context *intel ) free(brw->wm.compile_data); } - for (i = 0; i < brw->state.nr_color_regions; i++) - intel_region_release(&brw->state.color_regions[i]); - brw->state.nr_color_regions = 0; intel_region_release(&brw->state.depth_region); dri_bo_release(&brw->curbe.curbe_bo); dri_bo_release(&brw->vs.prog_bo); dri_bo_release(&brw->vs.state_bo); - dri_bo_release(&brw->vs.bind_bo); dri_bo_release(&brw->vs.const_bo); dri_bo_release(&brw->gs.prog_bo); dri_bo_release(&brw->gs.state_bo); @@ -93,16 +89,12 @@ static void brw_destroy_context( struct intel_context *intel ) dri_bo_release(&brw->sf.vp_bo); for (i = 0; i < BRW_MAX_TEX_UNIT; i++) dri_bo_release(&brw->wm.sdc_bo[i]); - dri_bo_release(&brw->wm.bind_bo); - for (i = 0; i < BRW_WM_MAX_SURF; i++) - dri_bo_release(&brw->wm.surf_bo[i]); dri_bo_release(&brw->wm.sampler_bo); dri_bo_release(&brw->wm.prog_bo); dri_bo_release(&brw->wm.state_bo); dri_bo_release(&brw->wm.const_bo); dri_bo_release(&brw->wm.push_const_bo); dri_bo_release(&brw->cc.prog_bo); - dri_bo_release(&brw->cc.state_bo); dri_bo_release(&brw->cc.vp_bo); dri_bo_release(&brw->cc.blend_state_bo); dri_bo_release(&brw->cc.depth_stencil_state_bo); @@ -122,20 +114,14 @@ static void brw_set_draw_region( struct intel_context *intel, GLuint num_color_regions) { struct brw_context *brw = brw_context(&intel->ctx); - GLuint i; /* release old color/depth regions */ if (brw->state.depth_region != depth_region) brw->state.dirty.brw |= BRW_NEW_DEPTH_BUFFER; - for (i = 0; i < brw->state.nr_color_regions; i++) - intel_region_release(&brw->state.color_regions[i]); intel_region_release(&brw->state.depth_region); /* reference new color/depth regions */ - for (i = 0; i < num_color_regions; i++) - intel_region_reference(&brw->state.color_regions[i], color_regions[i]); intel_region_reference(&brw->state.depth_region, depth_region); - brw->state.nr_color_regions = num_color_regions; } @@ -173,14 +159,7 @@ static void brw_new_batch( struct intel_context *intel ) brw->state.dirty.brw |= ~0; brw->state.dirty.cache |= ~0; - /* Move to the end of the current upload buffer so that we'll force choosing - * a new buffer next time. - */ - if (brw->vb.upload.bo != NULL) { - drm_intel_bo_unreference(brw->vb.upload.bo); - brw->vb.upload.bo = NULL; - brw->vb.upload.offset = 0; - } + brw->vb.nr_current_buffers = 0; } static void brw_invalidate_state( struct intel_context *intel, GLuint new_state ) diff --git a/src/mesa/drivers/dri/i965/brw_wm.c b/src/mesa/drivers/dri/i965/brw_wm.c index 656501b4f79..ee8212f6f16 100644 --- a/src/mesa/drivers/dri/i965/brw_wm.c +++ b/src/mesa/drivers/dri/i965/brw_wm.c @@ -431,7 +431,8 @@ static void brw_wm_populate_key( struct brw_context *brw, key->render_to_fbo = ctx->DrawBuffer->Name != 0; } - key->nr_color_regions = brw->state.nr_color_regions; + /* _NEW_BUFFERS */ + key->nr_color_regions = ctx->DrawBuffer->_NumColorDrawBuffers; /* CACHE_NEW_VS_PROG */ key->vp_outputs_written = brw->vs.prog_data->outputs_written; diff --git a/src/mesa/drivers/dri/i965/brw_wm_state.c b/src/mesa/drivers/dri/i965/brw_wm_state.c index e9ef635bca2..5b5afc4626b 100644 --- a/src/mesa/drivers/dri/i965/brw_wm_state.c +++ b/src/mesa/drivers/dri/i965/brw_wm_state.c @@ -47,7 +47,6 @@ struct brw_wm_unit_key { unsigned int dispatch_grf_start_reg; unsigned int curbe_offset; - unsigned int urb_size; unsigned int nr_surfaces, sampler_count; GLboolean uses_depth, computes_depth, uses_kill, is_glsl; @@ -98,9 +97,6 @@ wm_unit_populate_key(struct brw_context *brw, struct brw_wm_unit_key *key) key->dispatch_grf_start_reg = brw->wm.prog_data->first_curbe_grf; key->total_scratch = brw->wm.prog_data->total_scratch; - /* BRW_NEW_URB_FENCE */ - key->urb_size = brw->urb.vsize; - /* BRW_NEW_CURBE_OFFSETS */ key->curbe_offset = brw->curbe.wm_start; diff --git a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c index a372554555c..1010d9f6f9c 100644 --- a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c +++ b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c @@ -188,47 +188,43 @@ brw_update_texture_surface( struct gl_context *ctx, GLuint unit ) struct intel_texture_object *intelObj = intel_texture_object(tObj); struct gl_texture_image *firstImage = tObj->Image[0][tObj->BaseLevel]; const GLuint surf_index = SURF_INDEX_TEXTURE(unit); - struct brw_surface_state surf; - void *map; + struct brw_surface_state *surf; - memset(&surf, 0, sizeof(surf)); + surf = brw_state_batch(brw, sizeof(*surf), 32, + &brw->wm.surf_offset[surf_index]); + memset(surf, 0, sizeof(*surf)); - surf.ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW; - surf.ss0.surface_type = translate_tex_target(tObj->Target); - surf.ss0.surface_format = translate_tex_format(firstImage->TexFormat, + surf->ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW; + surf->ss0.surface_type = translate_tex_target(tObj->Target); + surf->ss0.surface_format = translate_tex_format(firstImage->TexFormat, firstImage->InternalFormat, tObj->DepthMode, tObj->sRGBDecode); /* This is ok for all textures with channel width 8bit or less: */ -/* surf.ss0.data_return_format = BRW_SURFACERETURNFORMAT_S1; */ - surf.ss1.base_addr = intelObj->mt->region->buffer->offset; /* reloc */ +/* surf->ss0.data_return_format = BRW_SURFACERETURNFORMAT_S1; */ + surf->ss1.base_addr = intelObj->mt->region->buffer->offset; /* reloc */ - surf.ss2.mip_count = intelObj->_MaxLevel - tObj->BaseLevel; - surf.ss2.width = firstImage->Width - 1; - surf.ss2.height = firstImage->Height - 1; - brw_set_surface_tiling(&surf, intelObj->mt->region->tiling); - surf.ss3.pitch = (intelObj->mt->region->pitch * intelObj->mt->cpp) - 1; - surf.ss3.depth = firstImage->Depth - 1; + surf->ss2.mip_count = intelObj->_MaxLevel - tObj->BaseLevel; + surf->ss2.width = firstImage->Width - 1; + surf->ss2.height = firstImage->Height - 1; + brw_set_surface_tiling(surf, intelObj->mt->region->tiling); + surf->ss3.pitch = (intelObj->mt->region->pitch * intelObj->mt->cpp) - 1; + surf->ss3.depth = firstImage->Depth - 1; - surf.ss4.min_lod = 0; + surf->ss4.min_lod = 0; if (tObj->Target == GL_TEXTURE_CUBE_MAP) { - surf.ss0.cube_pos_x = 1; - surf.ss0.cube_pos_y = 1; - surf.ss0.cube_pos_z = 1; - surf.ss0.cube_neg_x = 1; - surf.ss0.cube_neg_y = 1; - surf.ss0.cube_neg_z = 1; + surf->ss0.cube_pos_x = 1; + surf->ss0.cube_pos_y = 1; + surf->ss0.cube_pos_z = 1; + surf->ss0.cube_neg_x = 1; + surf->ss0.cube_neg_y = 1; + surf->ss0.cube_neg_z = 1; } - map = brw_state_batch(brw, sizeof(surf), 32, - &brw->wm.surf_bo[surf_index], - &brw->wm.surf_offset[surf_index]); - memcpy(map, &surf, sizeof(surf)); - /* Emit relocation to surface contents */ - drm_intel_bo_emit_reloc(brw->wm.surf_bo[surf_index], + drm_intel_bo_emit_reloc(brw->intel.batch.bo, brw->wm.surf_offset[surf_index] + offsetof(struct brw_surface_state, ss1), intelObj->mt->region->buffer, 0, @@ -243,41 +239,38 @@ void brw_create_constant_surface(struct brw_context *brw, drm_intel_bo *bo, int width, - drm_intel_bo **out_bo, uint32_t *out_offset) { struct intel_context *intel = &brw->intel; const GLint w = width - 1; - struct brw_surface_state surf; - void *map; + struct brw_surface_state *surf; - memset(&surf, 0, sizeof(surf)); + surf = brw_state_batch(brw, sizeof(*surf), 32, out_offset); + memset(surf, 0, sizeof(*surf)); - surf.ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW; - surf.ss0.surface_type = BRW_SURFACE_BUFFER; - surf.ss0.surface_format = BRW_SURFACEFORMAT_R32G32B32A32_FLOAT; + surf->ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW; + surf->ss0.surface_type = BRW_SURFACE_BUFFER; + surf->ss0.surface_format = BRW_SURFACEFORMAT_R32G32B32A32_FLOAT; if (intel->gen >= 6) - surf.ss0.render_cache_read_write = 1; + surf->ss0.render_cache_read_write = 1; assert(bo); - surf.ss1.base_addr = bo->offset; /* reloc */ - - surf.ss2.width = w & 0x7f; /* bits 6:0 of size or width */ - surf.ss2.height = (w >> 7) & 0x1fff; /* bits 19:7 of size or width */ - surf.ss3.depth = (w >> 20) & 0x7f; /* bits 26:20 of size or width */ - surf.ss3.pitch = (width * 16) - 1; /* ignored?? */ - brw_set_surface_tiling(&surf, I915_TILING_NONE); /* tiling now allowed */ + surf->ss1.base_addr = bo->offset; /* reloc */ - map = brw_state_batch(brw, sizeof(surf), 32, out_bo, out_offset); - memcpy(map, &surf, sizeof(surf)); + surf->ss2.width = w & 0x7f; /* bits 6:0 of size or width */ + surf->ss2.height = (w >> 7) & 0x1fff; /* bits 19:7 of size or width */ + surf->ss3.depth = (w >> 20) & 0x7f; /* bits 26:20 of size or width */ + surf->ss3.pitch = (width * 16) - 1; /* ignored?? */ + brw_set_surface_tiling(surf, I915_TILING_NONE); /* tiling now allowed */ /* Emit relocation to surface contents. Section 5.1.1 of the gen4 * bspec ("Data Cache") says that the data cache does not exist as * a separate cache and is just the sampler cache. */ - drm_intel_bo_emit_reloc(*out_bo, (*out_offset + - offsetof(struct brw_surface_state, ss1)), + drm_intel_bo_emit_reloc(brw->intel.batch.bo, + (*out_offset + + offsetof(struct brw_surface_state, ss1)), bo, 0, I915_GEM_DOMAIN_SAMPLER, 0); } @@ -356,16 +349,14 @@ static void upload_wm_constant_surface(struct brw_context *brw ) * it. */ if (brw->wm.const_bo == 0) { - if (brw->wm.surf_bo[surf] != NULL) { - drm_intel_bo_unreference(brw->wm.surf_bo[surf]); - brw->wm.surf_bo[surf] = NULL; + if (brw->wm.surf_offset[surf]) { brw->state.dirty.brw |= BRW_NEW_WM_SURFACES; + brw->wm.surf_offset[surf] = 0; } return; } brw_create_constant_surface(brw, brw->wm.const_bo, params->NumParameters, - &brw->wm.surf_bo[surf], &brw->wm.surf_offset[surf]); brw->state.dirty.brw |= BRW_NEW_WM_SURFACES; } @@ -384,33 +375,23 @@ static void brw_update_null_renderbuffer_surface(struct brw_context *brw, unsigned int unit) { struct intel_context *intel = &brw->intel; - struct brw_surface_state surf; - void *map; + struct brw_surface_state *surf; - memset(&surf, 0, sizeof(surf)); - - surf.ss0.surface_type = BRW_SURFACE_NULL; - surf.ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM; - surf.ss1.base_addr = 0; + surf = brw_state_batch(brw, sizeof(*surf), 32, + &brw->wm.surf_offset[unit]); + memset(surf, 0, sizeof(*surf)); - surf.ss2.width = 0; - surf.ss2.height = 0; - brw_set_surface_tiling(&surf, I915_TILING_NONE); - surf.ss3.pitch = 0; + surf->ss0.surface_type = BRW_SURFACE_NULL; + surf->ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM; if (intel->gen < 6) { /* _NEW_COLOR */ - surf.ss0.color_blend = 0; - surf.ss0.writedisable_red = 1; - surf.ss0.writedisable_green = 1; - surf.ss0.writedisable_blue = 1; - surf.ss0.writedisable_alpha = 1; + surf->ss0.color_blend = 0; + surf->ss0.writedisable_red = 1; + surf->ss0.writedisable_green = 1; + surf->ss0.writedisable_blue = 1; + surf->ss0.writedisable_alpha = 1; } - - map = brw_state_batch(brw, sizeof(surf), 32, - &brw->wm.surf_bo[unit], - &brw->wm.surf_offset[unit]); - memcpy(map, &surf, sizeof(surf)); } /** @@ -427,10 +408,11 @@ brw_update_renderbuffer_surface(struct brw_context *brw, struct gl_context *ctx = &intel->ctx; struct intel_renderbuffer *irb = intel_renderbuffer(rb); struct intel_region *region = irb->region; - struct brw_surface_state surf; - void *map; + struct brw_surface_state *surf; - memset(&surf, 0, sizeof(surf)); + surf = brw_state_batch(brw, sizeof(*surf), 32, + &brw->wm.surf_offset[unit]); + memset(surf, 0, sizeof(*surf)); switch (irb->Base.Format) { case MESA_FORMAT_XRGB8888: @@ -441,21 +423,24 @@ brw_update_renderbuffer_surface(struct brw_context *brw, * cases where GL_DST_ALPHA (or GL_ONE_MINUS_DST_ALPHA) is * used. */ - surf.ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM; + surf->ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM; break; case MESA_FORMAT_SARGB8: /* without GL_EXT_framebuffer_sRGB we shouldn't bind sRGB surfaces to the blend/update as sRGB */ - surf.ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM; + if (ctx->Color.sRGBEnabled) + surf->ss0.surface_format = brw_format_for_mesa_format[irb->Base.Format]; + else + surf->ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM; break; default: - surf.ss0.surface_format = brw_format_for_mesa_format[irb->Base.Format]; - assert(surf.ss0.surface_format != 0); + surf->ss0.surface_format = brw_format_for_mesa_format[irb->Base.Format]; + assert(surf->ss0.surface_format != 0); } - surf.ss0.surface_type = BRW_SURFACE_2D; + surf->ss0.surface_type = BRW_SURFACE_2D; if (region->tiling == I915_TILING_NONE) { - surf.ss1.base_addr = (region->draw_x + + surf->ss1.base_addr = (region->draw_x + region->draw_y * region->pitch) * region->cpp; } else { uint32_t tile_base, tile_x, tile_y; @@ -479,43 +464,38 @@ brw_update_renderbuffer_surface(struct brw_context *brw, /* Note that the low bits of these fields are missing, so * there's the possibility of getting in trouble. */ - surf.ss1.base_addr = tile_base; - surf.ss5.x_offset = tile_x / 4; - surf.ss5.y_offset = tile_y / 2; + surf->ss1.base_addr = tile_base; + surf->ss5.x_offset = tile_x / 4; + surf->ss5.y_offset = tile_y / 2; } - surf.ss1.base_addr += region->buffer->offset; /* reloc */ + surf->ss1.base_addr += region->buffer->offset; /* reloc */ - surf.ss2.width = rb->Width - 1; - surf.ss2.height = rb->Height - 1; - brw_set_surface_tiling(&surf, region->tiling); - surf.ss3.pitch = (region->pitch * region->cpp) - 1; + surf->ss2.width = rb->Width - 1; + surf->ss2.height = rb->Height - 1; + brw_set_surface_tiling(surf, region->tiling); + surf->ss3.pitch = (region->pitch * region->cpp) - 1; if (intel->gen < 6) { /* _NEW_COLOR */ - surf.ss0.color_blend = (!ctx->Color._LogicOpEnabled && + surf->ss0.color_blend = (!ctx->Color._LogicOpEnabled && (ctx->Color.BlendEnabled & (1 << unit))); - surf.ss0.writedisable_red = !ctx->Color.ColorMask[unit][0]; - surf.ss0.writedisable_green = !ctx->Color.ColorMask[unit][1]; - surf.ss0.writedisable_blue = !ctx->Color.ColorMask[unit][2]; + surf->ss0.writedisable_red = !ctx->Color.ColorMask[unit][0]; + surf->ss0.writedisable_green = !ctx->Color.ColorMask[unit][1]; + surf->ss0.writedisable_blue = !ctx->Color.ColorMask[unit][2]; /* As mentioned above, disable writes to the alpha component when the * renderbuffer is XRGB. */ if (ctx->DrawBuffer->Visual.alphaBits == 0) - surf.ss0.writedisable_alpha = 1; + surf->ss0.writedisable_alpha = 1; else - surf.ss0.writedisable_alpha = !ctx->Color.ColorMask[unit][3]; + surf->ss0.writedisable_alpha = !ctx->Color.ColorMask[unit][3]; } - map = brw_state_batch(brw, sizeof(surf), 32, - &brw->wm.surf_bo[unit], - &brw->wm.surf_offset[unit]); - memcpy(map, &surf, sizeof(surf)); - - drm_intel_bo_emit_reloc(brw->wm.surf_bo[unit], + drm_intel_bo_emit_reloc(brw->intel.batch.bo, brw->wm.surf_offset[unit] + offsetof(struct brw_surface_state, ss1), region->buffer, - surf.ss1.base_addr - region->buffer->offset, + surf->ss1.base_addr - region->buffer->offset, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER); } @@ -533,6 +513,11 @@ prepare_wm_surfaces(struct brw_context *brw) struct intel_renderbuffer *irb = intel_renderbuffer(rb); struct intel_region *region = irb ? irb->region : NULL; + if (region == NULL || region->buffer == NULL) { + brw->intel.Fallback = GL_TRUE; /* boolean, not bitfield */ + return; + } + brw_add_validated_bo(brw, region->buffer); nr_surfaces = SURF_INDEX_DRAW(i) + 1; } @@ -598,8 +583,7 @@ upload_wm_surfaces(struct brw_context *brw) if (texUnit->_ReallyEnabled) { brw_update_texture_surface(ctx, i); } else { - drm_intel_bo_unreference(brw->wm.surf_bo[surf]); - brw->wm.surf_bo[surf] = NULL; + brw->wm.surf_offset[surf] = 0; } } @@ -632,16 +616,11 @@ brw_wm_upload_binding_table(struct brw_context *brw) * space for the binding table. */ bind = brw_state_batch(brw, sizeof(uint32_t) * BRW_WM_MAX_SURF, - 32, &brw->wm.bind_bo, &brw->wm.bind_bo_offset); + 32, &brw->wm.bind_bo_offset); for (i = 0; i < BRW_WM_MAX_SURF; i++) { /* BRW_NEW_WM_SURFACES */ bind[i] = brw->wm.surf_offset[i]; - if (brw->wm.surf_bo[i]) { - bind[i] = brw->wm.surf_offset[i]; - } else { - bind[i] = 0; - } } brw->state.dirty.brw |= BRW_NEW_BINDING_TABLE; diff --git a/src/mesa/drivers/dri/i965/gen6_cc.c b/src/mesa/drivers/dri/i965/gen6_cc.c index f51afa40716..d1648a102d4 100644 --- a/src/mesa/drivers/dri/i965/gen6_cc.c +++ b/src/mesa/drivers/dri/i965/gen6_cc.c @@ -254,14 +254,14 @@ prepare_color_calc_state(struct brw_context *brw) color_calc_state_populate_key(brw, &key); - drm_intel_bo_unreference(brw->cc.state_bo); - brw->cc.state_bo = brw_search_cache(&brw->cache, BRW_COLOR_CALC_STATE, + drm_intel_bo_unreference(brw->cc.color_calc_state_bo); + brw->cc.color_calc_state_bo = brw_search_cache(&brw->cache, BRW_COLOR_CALC_STATE, &key, sizeof(key), NULL, 0, NULL); - if (brw->cc.state_bo == NULL) - brw->cc.state_bo = color_calc_state_create_from_key(brw, &key); + if (brw->cc.color_calc_state_bo == NULL) + brw->cc.color_calc_state_bo = color_calc_state_create_from_key(brw, &key); } const struct brw_tracked_state gen6_color_calc_state = { @@ -281,14 +281,14 @@ static void upload_cc_state_pointers(struct brw_context *brw) OUT_BATCH(_3DSTATE_CC_STATE_POINTERS << 16 | (4 - 2)); OUT_RELOC(brw->cc.blend_state_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 1); OUT_RELOC(brw->cc.depth_stencil_state_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 1); - OUT_RELOC(brw->cc.state_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 1); + OUT_RELOC(brw->cc.color_calc_state_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 1); ADVANCE_BATCH(); } static void prepare_cc_state_pointers(struct brw_context *brw) { - brw_add_validated_bo(brw, brw->cc.state_bo); + brw_add_validated_bo(brw, brw->cc.color_calc_state_bo); brw_add_validated_bo(brw, brw->cc.blend_state_bo); brw_add_validated_bo(brw, brw->cc.depth_stencil_state_bo); } diff --git a/src/mesa/drivers/dri/i965/gen6_sf_state.c b/src/mesa/drivers/dri/i965/gen6_sf_state.c index f27782935d4..50a5ad38c6f 100644 --- a/src/mesa/drivers/dri/i965/gen6_sf_state.c +++ b/src/mesa/drivers/dri/i965/gen6_sf_state.c @@ -54,6 +54,8 @@ get_attr_override(struct brw_context *brw, int fs_attr, int two_side_color) * be FRAG_ATTRIB_*. */ for (i = 1; i < vs_attr; i++) { + if (i == VERT_RESULT_PSIZ) + continue; if (brw->vs.prog_data->outputs_written & BITFIELD64_BIT(i)) attr_index++; } @@ -207,7 +209,7 @@ upload_sf_state(struct brw_context *brw) ctx->Point._Attenuated)) dw4 |= GEN6_SF_USE_STATE_POINT_WIDTH; - dw4 |= U_FIXED(CLAMP(ctx->Point.Size, 0.125, 225.875), 3) << + dw4 |= U_FIXED(CLAMP(ctx->Point.Size, 0.125, 255.875), 3) << GEN6_SF_POINT_WIDTH_SHIFT; if (ctx->Point.SpriteOrigin == GL_LOWER_LEFT) dw1 |= GEN6_SF_POINT_SPRITE_LOWERLEFT; diff --git a/src/mesa/drivers/dri/intel/intel_batchbuffer.c b/src/mesa/drivers/dri/intel/intel_batchbuffer.c index 67ce8a4da02..42b4f923e0c 100644 --- a/src/mesa/drivers/dri/intel/intel_batchbuffer.c +++ b/src/mesa/drivers/dri/intel/intel_batchbuffer.c @@ -27,89 +27,89 @@ #include "intel_context.h" #include "intel_batchbuffer.h" +#include "intel_buffer_objects.h" #include "intel_decode.h" #include "intel_reg.h" #include "intel_bufmgr.h" #include "intel_buffers.h" -void -intel_batchbuffer_reset(struct intel_batchbuffer *batch) +struct cached_batch_item { + struct cached_batch_item *next; + uint16_t header; + uint16_t size; +}; + +static void clear_cache( struct intel_context *intel ) { - struct intel_context *intel = batch->intel; + struct cached_batch_item *item = intel->batch.cached_items; - if (batch->buf != NULL) { - drm_intel_bo_unreference(batch->buf); - batch->buf = NULL; + while (item) { + struct cached_batch_item *next = item->next; + free(item); + item = next; } - batch->buf = drm_intel_bo_alloc(intel->bufmgr, "batchbuffer", - intel->maxBatchSize, 4096); - drm_intel_gem_bo_map_gtt(batch->buf); - batch->map = batch->buf->virtual; - - batch->size = intel->maxBatchSize; - batch->ptr = batch->map; - batch->reserved_space = BATCH_RESERVED; - batch->dirty_state = ~0; - batch->state_batch_offset = batch->size; + intel->batch.cached_items = NULL; } -struct intel_batchbuffer * -intel_batchbuffer_alloc(struct intel_context *intel) +void +intel_batchbuffer_reset(struct intel_context *intel) { - struct intel_batchbuffer *batch = calloc(sizeof(*batch), 1); + if (intel->batch.bo != NULL) { + drm_intel_bo_unreference(intel->batch.bo); + intel->batch.bo = NULL; + } + clear_cache(intel); - batch->intel = intel; - intel_batchbuffer_reset(batch); + intel->batch.bo = drm_intel_bo_alloc(intel->bufmgr, "batchbuffer", + intel->maxBatchSize, 4096); - return batch; + intel->batch.reserved_space = BATCH_RESERVED; + intel->batch.state_batch_offset = intel->batch.bo->size; + intel->batch.used = 0; } void -intel_batchbuffer_free(struct intel_batchbuffer *batch) +intel_batchbuffer_free(struct intel_context *intel) { - if (batch->map) { - drm_intel_gem_bo_unmap_gtt(batch->buf); - batch->map = NULL; - } - dri_bo_unreference(batch->buf); - batch->buf = NULL; - free(batch); + drm_intel_bo_unreference(intel->batch.bo); + clear_cache(intel); } - /* TODO: Push this whole function into bufmgr. */ static void -do_flush_locked(struct intel_batchbuffer *batch, GLuint used) +do_flush_locked(struct intel_context *intel) { - struct intel_context *intel = batch->intel; + struct intel_batchbuffer *batch = &intel->batch; int ret = 0; - int x_off = 0, y_off = 0; - - drm_intel_gem_bo_unmap_gtt(batch->buf); - - batch->ptr = NULL; if (!intel->intelScreen->no_hw) { int ring; - if (intel->gen < 6 || !intel->batch->is_blit) { + if (intel->gen < 6 || !batch->is_blit) { ring = I915_EXEC_RENDER; } else { ring = I915_EXEC_BLT; } - drm_intel_bo_mrb_exec(batch->buf, used, NULL, 0, - (x_off & 0xffff) | (y_off << 16), ring); + ret = drm_intel_bo_subdata(batch->bo, 0, 4*batch->used, batch->map); + if (ret == 0 && batch->state_batch_offset != batch->bo->size) { + ret = drm_intel_bo_subdata(batch->bo, + batch->state_batch_offset, + batch->bo->size - batch->state_batch_offset, + (char *)batch->map + batch->state_batch_offset); + } + + if (ret == 0) + ret = drm_intel_bo_mrb_exec(batch->bo, 4*batch->used, NULL, 0, 0, ring); } if (unlikely(INTEL_DEBUG & DEBUG_BATCH)) { - drm_intel_bo_map(batch->buf, GL_FALSE); - intel_decode(batch->buf->virtual, used / 4, batch->buf->offset, + intel_decode(batch->map, batch->used, + batch->bo->offset, intel->intelScreen->deviceID, GL_TRUE); - drm_intel_bo_unmap(batch->buf); if (intel->vtbl.debug_batch != NULL) intel->vtbl.debug_batch(intel); @@ -122,80 +122,54 @@ do_flush_locked(struct intel_batchbuffer *batch, GLuint used) } void -_intel_batchbuffer_flush(struct intel_batchbuffer *batch, const char *file, - int line) +_intel_batchbuffer_flush(struct intel_context *intel, + const char *file, int line) { - struct intel_context *intel = batch->intel; - GLuint used = batch->ptr - batch->map; - - if (intel->first_post_swapbuffers_batch == NULL) { - intel->first_post_swapbuffers_batch = intel->batch->buf; - drm_intel_bo_reference(intel->first_post_swapbuffers_batch); - } - - if (used == 0) + if (intel->batch.used == 0) return; if (unlikely(INTEL_DEBUG & DEBUG_BATCH)) fprintf(stderr, "%s:%d: Batchbuffer flush with %db used\n", file, line, - used); + 4*intel->batch.used); - batch->reserved_space = 0; + intel->batch.reserved_space = 0; if (intel->always_flush_cache) { - intel_batchbuffer_emit_mi_flush(batch); - used = batch->ptr - batch->map; - } - - /* Round batchbuffer usage to 2 DWORDs. */ - - if ((used & 4) == 0) { - *(GLuint *) (batch->ptr) = 0; /* noop */ - batch->ptr += 4; - used = batch->ptr - batch->map; + intel_batchbuffer_emit_mi_flush(intel); } /* Mark the end of the buffer. */ - *(GLuint *) (batch->ptr) = MI_BATCH_BUFFER_END; - batch->ptr += 4; - used = batch->ptr - batch->map; - assert (used <= batch->buf->size); - - /* Workaround for recursive batchbuffer flushing: If the window is - * moved, we can get into a case where we try to flush during a - * flush. What happens is that when we try to grab the lock for - * the first flush, we detect that the window moved which then - * causes another flush (from the intel_draw_buffer() call in - * intelUpdatePageFlipping()). To work around this we reset the - * batchbuffer tail pointer before trying to get the lock. This - * prevent the nested buffer flush, but a better fix would be to - * avoid that in the first place. */ - batch->ptr = batch->map; + intel_batchbuffer_emit_dword(intel, MI_BATCH_BUFFER_END); + if (intel->batch.used & 1) { + /* Round batchbuffer usage to 2 DWORDs. */ + intel_batchbuffer_emit_dword(intel, MI_NOOP); + } if (intel->vtbl.finish_batch) intel->vtbl.finish_batch(intel); + intel_upload_finish(intel); + /* Check that we didn't just wrap our batchbuffer at a bad time. */ assert(!intel->no_batch_wrap); - do_flush_locked(batch, used); + do_flush_locked(intel); if (unlikely(INTEL_DEBUG & DEBUG_SYNC)) { fprintf(stderr, "waiting for idle\n"); - drm_intel_bo_map(batch->buf, GL_TRUE); - drm_intel_bo_unmap(batch->buf); + drm_intel_bo_wait_rendering(intel->batch.bo); } /* Reset the buffer: */ - intel_batchbuffer_reset(batch); + intel_batchbuffer_reset(intel); } /* This is the only way buffers get added to the validate list. */ GLboolean -intel_batchbuffer_emit_reloc(struct intel_batchbuffer *batch, +intel_batchbuffer_emit_reloc(struct intel_context *intel, drm_intel_bo *buffer, uint32_t read_domains, uint32_t write_domain, uint32_t delta) @@ -204,58 +178,98 @@ intel_batchbuffer_emit_reloc(struct intel_batchbuffer *batch, assert(delta < buffer->size); - if (batch->ptr - batch->map > batch->buf->size) - printf ("bad relocation ptr %p map %p offset %d size %lu\n", - batch->ptr, batch->map, batch->ptr - batch->map, batch->buf->size); - ret = drm_intel_bo_emit_reloc(batch->buf, batch->ptr - batch->map, + ret = drm_intel_bo_emit_reloc(intel->batch.bo, 4*intel->batch.used, buffer, delta, read_domains, write_domain); + assert(ret == 0); + (void)ret; /* * Using the old buffer offset, write in what the right data would be, in case * the buffer doesn't move and we can short-circuit the relocation processing * in the kernel */ - intel_batchbuffer_emit_dword (batch, buffer->offset + delta); + intel_batchbuffer_emit_dword(intel, buffer->offset + delta); return GL_TRUE; } GLboolean -intel_batchbuffer_emit_reloc_fenced(struct intel_batchbuffer *batch, +intel_batchbuffer_emit_reloc_fenced(struct intel_context *intel, drm_intel_bo *buffer, - uint32_t read_domains, uint32_t write_domain, + uint32_t read_domains, + uint32_t write_domain, uint32_t delta) { int ret; assert(delta < buffer->size); - if (batch->ptr - batch->map > batch->buf->size) - printf ("bad relocation ptr %p map %p offset %d size %lu\n", - batch->ptr, batch->map, batch->ptr - batch->map, batch->buf->size); - ret = drm_intel_bo_emit_reloc_fence(batch->buf, batch->ptr - batch->map, + ret = drm_intel_bo_emit_reloc_fence(intel->batch.bo, 4*intel->batch.used, buffer, delta, read_domains, write_domain); + assert(ret == 0); + (void)ret; /* * Using the old buffer offset, write in what the right data would * be, in case the buffer doesn't move and we can short-circuit the * relocation processing in the kernel */ - intel_batchbuffer_emit_dword (batch, buffer->offset + delta); + intel_batchbuffer_emit_dword(intel, buffer->offset + delta); return GL_TRUE; } void -intel_batchbuffer_data(struct intel_batchbuffer *batch, +intel_batchbuffer_data(struct intel_context *intel, const void *data, GLuint bytes, bool is_blit) { assert((bytes & 3) == 0); - intel_batchbuffer_require_space(batch, bytes, is_blit); - __memcpy(batch->ptr, data, bytes); - batch->ptr += bytes; + intel_batchbuffer_require_space(intel, bytes, is_blit); + __memcpy(intel->batch.map + intel->batch.used, data, bytes); + intel->batch.used += bytes >> 2; +} + +void +intel_batchbuffer_cached_advance(struct intel_context *intel) +{ + struct cached_batch_item **prev = &intel->batch.cached_items, *item; + uint32_t sz = (intel->batch.used - intel->batch.emit) * sizeof(uint32_t); + uint32_t *start = intel->batch.map + intel->batch.emit; + uint16_t op = *start >> 16; + + while (*prev) { + uint32_t *old; + + item = *prev; + old = intel->batch.map + item->header; + if (op == *old >> 16) { + if (item->size == sz && memcmp(old, start, sz) == 0) { + if (prev != &intel->batch.cached_items) { + *prev = item->next; + item->next = intel->batch.cached_items; + intel->batch.cached_items = item; + } + intel->batch.used = intel->batch.emit; + return; + } + + goto emit; + } + prev = &item->next; + } + + item = malloc(sizeof(struct cached_batch_item)); + if (item == NULL) + return; + + item->next = intel->batch.cached_items; + intel->batch.cached_items = item; + +emit: + item->size = sz; + item->header = intel->batch.emit; } /* Emit a pipelined flush to either flush render and texture cache for @@ -265,12 +279,10 @@ intel_batchbuffer_data(struct intel_batchbuffer *batch, * This is also used for the always_flush_cache driconf debug option. */ void -intel_batchbuffer_emit_mi_flush(struct intel_batchbuffer *batch) +intel_batchbuffer_emit_mi_flush(struct intel_context *intel) { - struct intel_context *intel = batch->intel; - if (intel->gen >= 6) { - if (intel->batch->is_blit) { + if (intel->batch.is_blit) { BEGIN_BATCH_BLT(4); OUT_BATCH(MI_FLUSH_DW); OUT_BATCH(0); diff --git a/src/mesa/drivers/dri/intel/intel_batchbuffer.h b/src/mesa/drivers/dri/intel/intel_batchbuffer.h index 635708587a6..a0a5c9841c6 100644 --- a/src/mesa/drivers/dri/intel/intel_batchbuffer.h +++ b/src/mesa/drivers/dri/intel/intel_batchbuffer.h @@ -7,71 +7,37 @@ #include "intel_bufmgr.h" #include "intel_reg.h" -#define BATCH_SZ 16384 #define BATCH_RESERVED 16 +void intel_batchbuffer_reset(struct intel_context *intel); +void intel_batchbuffer_free(struct intel_context *intel); -struct intel_batchbuffer -{ - struct intel_context *intel; - - drm_intel_bo *buf; - - GLubyte *map; - GLubyte *ptr; - - GLuint size; - uint32_t state_batch_offset; - -#ifdef DEBUG - /** Tracking of BEGIN_BATCH()/OUT_BATCH()/ADVANCE_BATCH() debugging */ - struct { - GLuint total; - GLubyte *start_ptr; - } emit; -#endif - - bool is_blit; - GLuint dirty_state; - GLuint reserved_space; -}; - -struct intel_batchbuffer *intel_batchbuffer_alloc(struct intel_context - *intel); - -void intel_batchbuffer_free(struct intel_batchbuffer *batch); - - -void _intel_batchbuffer_flush(struct intel_batchbuffer *batch, +void _intel_batchbuffer_flush(struct intel_context *intel, const char *file, int line); -#define intel_batchbuffer_flush(batch) \ - _intel_batchbuffer_flush(batch, __FILE__, __LINE__) +#define intel_batchbuffer_flush(intel) \ + _intel_batchbuffer_flush(intel, __FILE__, __LINE__) -void intel_batchbuffer_reset(struct intel_batchbuffer *batch); /* Unlike bmBufferData, this currently requires the buffer be mapped. * Consider it a convenience function wrapping multple * intel_buffer_dword() calls. */ -void intel_batchbuffer_data(struct intel_batchbuffer *batch, +void intel_batchbuffer_data(struct intel_context *intel, const void *data, GLuint bytes, bool is_blit); -void intel_batchbuffer_release_space(struct intel_batchbuffer *batch, - GLuint bytes); - -GLboolean intel_batchbuffer_emit_reloc(struct intel_batchbuffer *batch, +GLboolean intel_batchbuffer_emit_reloc(struct intel_context *intel, drm_intel_bo *buffer, uint32_t read_domains, uint32_t write_domain, uint32_t offset); -GLboolean intel_batchbuffer_emit_reloc_fenced(struct intel_batchbuffer *batch, +GLboolean intel_batchbuffer_emit_reloc_fenced(struct intel_context *intel, drm_intel_bo *buffer, uint32_t read_domains, uint32_t write_domain, uint32_t offset); -void intel_batchbuffer_emit_mi_flush(struct intel_batchbuffer *batch); +void intel_batchbuffer_emit_mi_flush(struct intel_context *intel); static INLINE uint32_t float_as_int(float f) { @@ -90,93 +56,93 @@ static INLINE uint32_t float_as_int(float f) * work... */ static INLINE GLint -intel_batchbuffer_space(struct intel_batchbuffer *batch) +intel_batchbuffer_space(struct intel_context *intel) { - return (batch->state_batch_offset - batch->reserved_space) - - (batch->ptr - batch->map); + return (intel->batch.state_batch_offset - intel->batch.reserved_space) - intel->batch.used*4; } static INLINE void -intel_batchbuffer_emit_dword(struct intel_batchbuffer *batch, GLuint dword) +intel_batchbuffer_emit_dword(struct intel_context *intel, GLuint dword) { #ifdef DEBUG - assert(intel_batchbuffer_space(batch) >= 4); + assert(intel_batchbuffer_space(intel) >= 4); #endif - *(GLuint *) (batch->ptr) = dword; - batch->ptr += 4; + intel->batch.map[intel->batch.used++] = dword; } static INLINE void -intel_batchbuffer_emit_float(struct intel_batchbuffer *batch, float f) +intel_batchbuffer_emit_float(struct intel_context *intel, float f) { - intel_batchbuffer_emit_dword(batch, float_as_int(f)); + intel_batchbuffer_emit_dword(intel, float_as_int(f)); } static INLINE void -intel_batchbuffer_require_space(struct intel_batchbuffer *batch, +intel_batchbuffer_require_space(struct intel_context *intel, GLuint sz, int is_blit) { - if (batch->intel->gen >= 6 && batch->is_blit != is_blit && - batch->ptr != batch->map) { - intel_batchbuffer_flush(batch); + if (intel->gen >= 6 && + intel->batch.is_blit != is_blit && intel->batch.used) { + intel_batchbuffer_flush(intel); } - batch->is_blit = is_blit; + intel->batch.is_blit = is_blit; #ifdef DEBUG - assert(sz < batch->size - 8); + assert(sz < sizeof(intel->batch.map) - BATCH_RESERVED); #endif - if (intel_batchbuffer_space(batch) < sz) - intel_batchbuffer_flush(batch); + if (intel_batchbuffer_space(intel) < sz) + intel_batchbuffer_flush(intel); } static INLINE void -intel_batchbuffer_begin(struct intel_batchbuffer *batch, int n, bool is_blit) +intel_batchbuffer_begin(struct intel_context *intel, int n, bool is_blit) { - intel_batchbuffer_require_space(batch, n * 4, is_blit); + intel_batchbuffer_require_space(intel, n * 4, is_blit); + intel->batch.emit = intel->batch.used; #ifdef DEBUG - assert(batch->map); - assert(batch->emit.start_ptr == NULL); - batch->emit.total = n * 4; - batch->emit.start_ptr = batch->ptr; + intel->batch.total = n; #endif } static INLINE void -intel_batchbuffer_advance(struct intel_batchbuffer *batch) +intel_batchbuffer_advance(struct intel_context *intel) { #ifdef DEBUG - unsigned int _n = batch->ptr - batch->emit.start_ptr; - assert(batch->emit.start_ptr != NULL); - if (_n != batch->emit.total) { + struct intel_batchbuffer *batch = &intel->batch; + unsigned int _n = batch->used - batch->emit; + assert(batch->total != 0); + if (_n != batch->total) { fprintf(stderr, "ADVANCE_BATCH: %d of %d dwords emitted\n", - _n, batch->emit.total); + _n, batch->total); abort(); } - batch->emit.start_ptr = NULL; + batch->total = 0; #endif } +void intel_batchbuffer_cached_advance(struct intel_context *intel); + /* Here are the crusty old macros, to be removed: */ #define BATCH_LOCALS -#define BEGIN_BATCH(n) intel_batchbuffer_begin(intel->batch, n, false) -#define BEGIN_BATCH_BLT(n) intel_batchbuffer_begin(intel->batch, n, true) -#define OUT_BATCH(d) intel_batchbuffer_emit_dword(intel->batch, d) -#define OUT_BATCH_F(f) intel_batchbuffer_emit_float(intel->batch,f) +#define BEGIN_BATCH(n) intel_batchbuffer_begin(intel, n, false) +#define BEGIN_BATCH_BLT(n) intel_batchbuffer_begin(intel, n, true) +#define OUT_BATCH(d) intel_batchbuffer_emit_dword(intel, d) +#define OUT_BATCH_F(f) intel_batchbuffer_emit_float(intel,f) #define OUT_RELOC(buf, read_domains, write_domain, delta) do { \ - intel_batchbuffer_emit_reloc(intel->batch, buf, \ + intel_batchbuffer_emit_reloc(intel, buf, \ read_domains, write_domain, delta); \ } while (0) #define OUT_RELOC_FENCED(buf, read_domains, write_domain, delta) do { \ - intel_batchbuffer_emit_reloc_fenced(intel->batch, buf, \ + intel_batchbuffer_emit_reloc_fenced(intel, buf, \ read_domains, write_domain, delta); \ } while (0) -#define ADVANCE_BATCH() intel_batchbuffer_advance(intel->batch); +#define ADVANCE_BATCH() intel_batchbuffer_advance(intel); +#define CACHED_BATCH() intel_batchbuffer_cached_advance(intel); #endif diff --git a/src/mesa/drivers/dri/intel/intel_blit.c b/src/mesa/drivers/dri/intel/intel_blit.c index 6232e479cb6..e1ab7f16371 100644 --- a/src/mesa/drivers/dri/intel/intel_blit.c +++ b/src/mesa/drivers/dri/intel/intel_blit.c @@ -123,12 +123,12 @@ intelEmitCopyBlit(struct intel_context *intel, /* do space check before going any further */ do { - aper_array[0] = intel->batch->buf; + aper_array[0] = intel->batch.bo; aper_array[1] = dst_buffer; aper_array[2] = src_buffer; if (dri_bufmgr_check_aperture_space(aper_array, 3) != 0) { - intel_batchbuffer_flush(intel->batch); + intel_batchbuffer_flush(intel); pass++; } else break; @@ -137,7 +137,7 @@ intelEmitCopyBlit(struct intel_context *intel, if (pass >= 2) return GL_FALSE; - intel_batchbuffer_require_space(intel->batch, 8 * 4, true); + intel_batchbuffer_require_space(intel, 8 * 4, true); DBG("%s src:buf(%p)/%d+%d %d,%d dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n", __FUNCTION__, src_buffer, src_pitch, src_offset, src_x, src_y, @@ -193,7 +193,7 @@ intelEmitCopyBlit(struct intel_context *intel, src_offset); ADVANCE_BATCH(); - intel_batchbuffer_emit_mi_flush(intel->batch); + intel_batchbuffer_emit_mi_flush(intel); return GL_TRUE; } @@ -343,12 +343,12 @@ intelClearWithBlit(struct gl_context *ctx, GLbitfield mask) assert(y1 < y2); /* do space check before going any further */ - aper_array[0] = intel->batch->buf; + aper_array[0] = intel->batch.bo; aper_array[1] = write_buffer; if (drm_intel_bufmgr_check_aperture_space(aper_array, ARRAY_SIZE(aper_array)) != 0) { - intel_batchbuffer_flush(intel->batch); + intel_batchbuffer_flush(intel); } BEGIN_BATCH_BLT(6); @@ -363,7 +363,7 @@ intelClearWithBlit(struct gl_context *ctx, GLbitfield mask) ADVANCE_BATCH(); if (intel->always_flush_cache) - intel_batchbuffer_emit_mi_flush(intel->batch); + intel_batchbuffer_emit_mi_flush(intel); if (buf == BUFFER_DEPTH || buf == BUFFER_STENCIL) mask &= ~(BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL); @@ -410,10 +410,10 @@ intelEmitImmediateColorExpandBlit(struct intel_context *intel, __FUNCTION__, dst_buffer, dst_pitch, dst_offset, x, y, w, h, src_size, dwords); - intel_batchbuffer_require_space( intel->batch, - (8 * 4) + - (3 * 4) + - dwords * 4, true); + intel_batchbuffer_require_space(intel, + (8 * 4) + + (3 * 4) + + dwords * 4, true); opcode = XY_SETUP_BLT_CMD; if (cpp == 4) @@ -449,11 +449,9 @@ intelEmitImmediateColorExpandBlit(struct intel_context *intel, OUT_BATCH(((y + h) << 16) | (x + w)); ADVANCE_BATCH(); - intel_batchbuffer_data(intel->batch, - src_bits, - dwords * 4, true); + intel_batchbuffer_data(intel, src_bits, dwords * 4, true); - intel_batchbuffer_emit_mi_flush(intel->batch); + intel_batchbuffer_emit_mi_flush(intel); return GL_TRUE; } @@ -543,10 +541,10 @@ intel_set_teximage_alpha_to_one(struct gl_context *ctx, DBG("%s dst:buf(%p)/%d %d,%d sz:%dx%d\n", __FUNCTION__, - intel_image->mt->region->buffer, (pitch * region->cpp), + intel_image->mt->region->buffer, (pitch * cpp), x1, y1, x2 - x1, y2 - y1); - BR13 = br13_for_cpp(region->cpp) | 0xf0 << 16; + BR13 = br13_for_cpp(cpp) | 0xf0 << 16; CMD = XY_COLOR_BLT_CMD; CMD |= XY_BLT_WRITE_ALPHA; @@ -558,15 +556,15 @@ intel_set_teximage_alpha_to_one(struct gl_context *ctx, pitch /= 4; } #endif - BR13 |= (pitch * region->cpp); + BR13 |= (pitch * cpp); /* do space check before going any further */ - aper_array[0] = intel->batch->buf; + aper_array[0] = intel->batch.bo; aper_array[1] = region->buffer; if (drm_intel_bufmgr_check_aperture_space(aper_array, ARRAY_SIZE(aper_array)) != 0) { - intel_batchbuffer_flush(intel->batch); + intel_batchbuffer_flush(intel); } BEGIN_BATCH_BLT(6); @@ -580,5 +578,5 @@ intel_set_teximage_alpha_to_one(struct gl_context *ctx, OUT_BATCH(0xffffffff); /* white, but only alpha gets written */ ADVANCE_BATCH(); - intel_batchbuffer_emit_mi_flush(intel->batch); + intel_batchbuffer_emit_mi_flush(intel); } diff --git a/src/mesa/drivers/dri/intel/intel_buffer_objects.c b/src/mesa/drivers/dri/intel/intel_buffer_objects.c index d917161c4be..2f750a768af 100644 --- a/src/mesa/drivers/dri/intel/intel_buffer_objects.c +++ b/src/mesa/drivers/dri/intel/intel_buffer_objects.c @@ -53,6 +53,15 @@ intel_bufferobj_alloc_buffer(struct intel_context *intel, intel_obj->Base.Size, 64); } +static void +release_buffer(struct intel_buffer_object *intel_obj) +{ + drm_intel_bo_unreference(intel_obj->buffer); + intel_obj->buffer = NULL; + intel_obj->offset = 0; + intel_obj->source = 0; +} + /** * There is some duplication between mesa's bufferobjects and our * bufmgr buffers. Both have an integer handle and a hashtable to @@ -81,8 +90,7 @@ intel_bufferobj_release_region(struct intel_context *intel, intel_obj->region->pbo = NULL; intel_obj->region = NULL; - drm_intel_bo_unreference(intel_obj->buffer); - intel_obj->buffer = NULL; + release_buffer(intel_obj); } /* Break the COW tie to the region. Both the pbo and the region end @@ -120,10 +128,8 @@ intel_bufferobj_free(struct gl_context * ctx, struct gl_buffer_object *obj) if (intel_obj->region) { intel_bufferobj_release_region(intel, intel_obj); } - else if (intel_obj->buffer) { - drm_intel_bo_unreference(intel_obj->buffer); - } + drm_intel_bo_unreference(intel_obj->buffer); free(intel_obj); } @@ -154,19 +160,22 @@ intel_bufferobj_data(struct gl_context * ctx, if (intel_obj->region) intel_bufferobj_release_region(intel, intel_obj); - if (intel_obj->buffer != NULL) { - drm_intel_bo_unreference(intel_obj->buffer); - intel_obj->buffer = NULL; - } + if (intel_obj->buffer != NULL) + release_buffer(intel_obj); + free(intel_obj->sys_buffer); intel_obj->sys_buffer = NULL; if (size != 0) { + if (usage == GL_DYNAMIC_DRAW #ifdef I915 - /* On pre-965, stick VBOs in system memory, as we're always doing swtnl - * with their contents anyway. - */ - if (target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER) { + /* On pre-965, stick VBOs in system memory, as we're always doing + * swtnl with their contents anyway. + */ + || target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER +#endif + ) + { intel_obj->sys_buffer = malloc(size); if (intel_obj->sys_buffer != NULL) { if (data != NULL) @@ -174,7 +183,6 @@ intel_bufferobj_data(struct gl_context * ctx, return GL_TRUE; } } -#endif intel_bufferobj_alloc_buffer(intel, intel_obj); if (!intel_obj->buffer) return GL_FALSE; @@ -202,6 +210,7 @@ intel_bufferobj_subdata(struct gl_context * ctx, { struct intel_context *intel = intel_context(ctx); struct intel_buffer_object *intel_obj = intel_buffer_object(obj); + bool busy; if (size == 0) return; @@ -211,34 +220,53 @@ intel_bufferobj_subdata(struct gl_context * ctx, if (intel_obj->region) intel_bufferobj_cow(intel, intel_obj); - if (intel_obj->sys_buffer) - memcpy((char *)intel_obj->sys_buffer + offset, data, size); - else { - /* Flush any existing batchbuffer that might reference this data. */ - if (intel->gen < 6) { - if (drm_intel_bo_busy(intel_obj->buffer) || - drm_intel_bo_references(intel->batch->buf, intel_obj->buffer)) { - drm_intel_bo *temp_bo; + /* If we have a single copy in system memory, update that */ + if (intel_obj->sys_buffer) { + if (intel_obj->source) + release_buffer(intel_obj); - temp_bo = drm_intel_bo_alloc(intel->bufmgr, "subdata temp", size, 64); + if (intel_obj->buffer == NULL) { + memcpy((char *)intel_obj->sys_buffer + offset, data, size); + return; + } - drm_intel_bo_subdata(temp_bo, 0, size, data); + free(intel_obj->sys_buffer); + intel_obj->sys_buffer = NULL; + } - intel_emit_linear_blit(intel, - intel_obj->buffer, offset, - temp_bo, 0, - size); + /* Otherwise we need to update the copy in video memory. */ + busy = + drm_intel_bo_busy(intel_obj->buffer) || + drm_intel_bo_references(intel->batch.bo, intel_obj->buffer); - drm_intel_bo_unreference(temp_bo); - } else { - drm_intel_bo_subdata(intel_obj->buffer, offset, size, data); - } + /* replace the current busy bo with fresh data */ + if (busy && size == intel_obj->Base.Size) { + drm_intel_bo_unreference(intel_obj->buffer); + intel_bufferobj_alloc_buffer(intel, intel_obj); + drm_intel_bo_subdata(intel_obj->buffer, 0, size, data); + } else if (intel->gen < 6) { + if (busy) { + drm_intel_bo *temp_bo; + + temp_bo = drm_intel_bo_alloc(intel->bufmgr, "subdata temp", size, 64); + + drm_intel_bo_subdata(temp_bo, 0, size, data); + + intel_emit_linear_blit(intel, + intel_obj->buffer, offset, + temp_bo, 0, + size); + + drm_intel_bo_unreference(temp_bo); } else { - if (drm_intel_bo_references(intel->batch->buf, intel_obj->buffer)) { - intel_batchbuffer_flush(intel->batch); - } drm_intel_bo_subdata(intel_obj->buffer, offset, size, data); } + } else { + /* Can't use the blit to modify the buffer in the middle of batch. */ + if (drm_intel_bo_references(intel->batch.bo, intel_obj->buffer)) { + intel_batchbuffer_flush(intel); + } + drm_intel_bo_subdata(intel_obj->buffer, offset, size, data); } } @@ -280,14 +308,23 @@ intel_bufferobj_map(struct gl_context * ctx, assert(intel_obj); if (intel_obj->sys_buffer) { - obj->Pointer = intel_obj->sys_buffer; - obj->Length = obj->Size; - obj->Offset = 0; - return obj->Pointer; + if (!read_only && intel_obj->source) { + release_buffer(intel_obj); + } + + if (!intel_obj->buffer || intel_obj->source) { + obj->Pointer = intel_obj->sys_buffer; + obj->Length = obj->Size; + obj->Offset = 0; + return obj->Pointer; + } + + free(intel_obj->sys_buffer); + intel_obj->sys_buffer = NULL; } /* Flush any existing batchbuffer that might reference this data. */ - if (drm_intel_bo_references(intel->batch->buf, intel_obj->buffer)) + if (drm_intel_bo_references(intel->batch.bo, intel_obj->buffer)) intel_flush(ctx); if (intel_obj->region) @@ -336,6 +373,7 @@ intel_bufferobj_map_range(struct gl_context * ctx, { struct intel_context *intel = intel_context(ctx); struct intel_buffer_object *intel_obj = intel_buffer_object(obj); + GLboolean read_only = (access == GL_READ_ONLY_ARB); assert(intel_obj); @@ -347,8 +385,16 @@ intel_bufferobj_map_range(struct gl_context * ctx, obj->AccessFlags = access; if (intel_obj->sys_buffer) { - obj->Pointer = intel_obj->sys_buffer + offset; - return obj->Pointer; + if (!read_only && intel_obj->source) + release_buffer(intel_obj); + + if (!intel_obj->buffer || intel_obj->source) { + obj->Pointer = intel_obj->sys_buffer + offset; + return obj->Pointer; + } + + free(intel_obj->sys_buffer); + intel_obj->sys_buffer = NULL; } if (intel_obj->region) @@ -359,7 +405,7 @@ intel_bufferobj_map_range(struct gl_context * ctx, * syncing. */ if (!(access & GL_MAP_UNSYNCHRONIZED_BIT) && - drm_intel_bo_references(intel->batch->buf, intel_obj->buffer)) + drm_intel_bo_references(intel->batch.bo, intel_obj->buffer)) intel_flush(ctx); if (intel_obj->buffer == NULL) { @@ -374,8 +420,7 @@ intel_bufferobj_map_range(struct gl_context * ctx, (access & GL_MAP_INVALIDATE_BUFFER_BIT) && drm_intel_bo_busy(intel_obj->buffer)) { drm_intel_bo_unreference(intel_obj->buffer); - intel_obj->buffer = drm_intel_bo_alloc(intel->bufmgr, "bufferobj", - intel_obj->Base.Size, 64); + intel_bufferobj_alloc_buffer(intel, intel_obj); } /* If the user is mapping a range of an active buffer object but @@ -473,7 +518,7 @@ intel_bufferobj_unmap(struct gl_context * ctx, * flush. Once again, we wish for a domain tracker in libdrm to cover * usage inside of a batchbuffer. */ - intel_batchbuffer_emit_mi_flush(intel->batch); + intel_batchbuffer_emit_mi_flush(intel); free(intel_obj->range_map_buffer); intel_obj->range_map_buffer = NULL; } else if (intel_obj->range_map_bo != NULL) { @@ -493,7 +538,7 @@ intel_bufferobj_unmap(struct gl_context * ctx, * flush. Once again, we wish for a domain tracker in libdrm to cover * usage inside of a batchbuffer. */ - intel_batchbuffer_emit_mi_flush(intel->batch); + intel_batchbuffer_emit_mi_flush(intel); drm_intel_bo_unreference(intel_obj->range_map_bo); intel_obj->range_map_bo = NULL; @@ -513,7 +558,8 @@ intel_bufferobj_unmap(struct gl_context * ctx, drm_intel_bo * intel_bufferobj_buffer(struct intel_context *intel, - struct intel_buffer_object *intel_obj, GLuint flag) + struct intel_buffer_object *intel_obj, + GLuint flag) { if (intel_obj->region) { if (flag == INTEL_WRITE_PART) @@ -524,23 +570,169 @@ intel_bufferobj_buffer(struct intel_context *intel, } } - if (intel_obj->buffer == NULL) { - void *sys_buffer = intel_obj->sys_buffer; + if (intel_obj->source) + release_buffer(intel_obj); - /* only one of buffer and sys_buffer could be non-NULL */ + if (intel_obj->buffer == NULL) { intel_bufferobj_alloc_buffer(intel, intel_obj); - intel_obj->sys_buffer = NULL; + drm_intel_bo_subdata(intel_obj->buffer, + 0, intel_obj->Base.Size, + intel_obj->sys_buffer); - intel_bufferobj_subdata(&intel->ctx, - GL_ARRAY_BUFFER_ARB, - 0, - intel_obj->Base.Size, - sys_buffer, - &intel_obj->Base); - free(sys_buffer); + free(intel_obj->sys_buffer); intel_obj->sys_buffer = NULL; + intel_obj->offset = 0; + } + + return intel_obj->buffer; +} + +#define INTEL_UPLOAD_SIZE (64*1024) + +void +intel_upload_finish(struct intel_context *intel) +{ + if (!intel->upload.bo) + return; + + if (intel->upload.buffer_len) { + drm_intel_bo_subdata(intel->upload.bo, + intel->upload.buffer_offset, + intel->upload.buffer_len, + intel->upload.buffer); + intel->upload.buffer_len = 0; + } + + drm_intel_bo_unreference(intel->upload.bo); + intel->upload.bo = NULL; +} + +static void wrap_buffers(struct intel_context *intel, GLuint size) +{ + intel_upload_finish(intel); + + if (size < INTEL_UPLOAD_SIZE) + size = INTEL_UPLOAD_SIZE; + + intel->upload.bo = drm_intel_bo_alloc(intel->bufmgr, "upload", size, 0); + intel->upload.offset = 0; +} + +void intel_upload_data(struct intel_context *intel, + const void *ptr, GLuint size, GLuint align, + drm_intel_bo **return_bo, + GLuint *return_offset) +{ + GLuint base, delta; + + base = (intel->upload.offset + align - 1) / align * align; + if (intel->upload.bo == NULL || base + size > intel->upload.bo->size) { + wrap_buffers(intel, size); + base = 0; + } + + drm_intel_bo_reference(intel->upload.bo); + *return_bo = intel->upload.bo; + *return_offset = base; + + delta = base - intel->upload.offset; + if (intel->upload.buffer_len && + intel->upload.buffer_len + delta + size > sizeof(intel->upload.buffer)) + { + drm_intel_bo_subdata(intel->upload.bo, + intel->upload.buffer_offset, + intel->upload.buffer_len, + intel->upload.buffer); + intel->upload.buffer_len = 0; + } + + if (size < sizeof(intel->upload.buffer)) + { + if (intel->upload.buffer_len == 0) + intel->upload.buffer_offset = base; + else + intel->upload.buffer_len += delta; + + memcpy(intel->upload.buffer + intel->upload.buffer_len, ptr, size); + intel->upload.buffer_len += size; + } + else + { + drm_intel_bo_subdata(intel->upload.bo, base, size, ptr); + } + + intel->upload.offset = base + size; +} + +void *intel_upload_map(struct intel_context *intel, GLuint size, GLuint align) +{ + GLuint base, delta; + char *ptr; + + base = (intel->upload.offset + align - 1) / align * align; + if (intel->upload.bo == NULL || base + size > intel->upload.bo->size) { + wrap_buffers(intel, size); + base = 0; + } + + delta = base - intel->upload.offset; + if (intel->upload.buffer_len && + intel->upload.buffer_len + delta + size > sizeof(intel->upload.buffer)) + { + drm_intel_bo_subdata(intel->upload.bo, + intel->upload.buffer_offset, + intel->upload.buffer_len, + intel->upload.buffer); + intel->upload.buffer_len = 0; + } + + if (size <= sizeof(intel->upload.buffer)) { + if (intel->upload.buffer_len == 0) + intel->upload.buffer_offset = base; + else + intel->upload.buffer_len += delta; + + ptr = intel->upload.buffer + intel->upload.buffer_len; + intel->upload.buffer_len += size; + } else + ptr = malloc(size); + + return ptr; +} + +void intel_upload_unmap(struct intel_context *intel, + const void *ptr, GLuint size, GLuint align, + drm_intel_bo **return_bo, + GLuint *return_offset) +{ + GLuint base; + + base = (intel->upload.offset + align - 1) / align * align; + if (size > sizeof(intel->upload.buffer)) { + drm_intel_bo_subdata(intel->upload.bo, base, size, ptr); + free((void*)ptr); + } + + drm_intel_bo_reference(intel->upload.bo); + *return_bo = intel->upload.bo; + *return_offset = base; + + intel->upload.offset = base + size; +} + +drm_intel_bo * +intel_bufferobj_source(struct intel_context *intel, + struct intel_buffer_object *intel_obj, + GLuint *offset) +{ + if (intel_obj->buffer == NULL) { + intel_upload_data(intel, + intel_obj->sys_buffer, intel_obj->Base.Size, 64, + &intel_obj->buffer, &intel_obj->offset); + intel_obj->source = 1; } + *offset = intel_obj->offset; return intel_obj->buffer; } @@ -555,6 +747,7 @@ intel_bufferobj_copy_subdata(struct gl_context *ctx, struct intel_buffer_object *intel_src = intel_buffer_object(src); struct intel_buffer_object *intel_dst = intel_buffer_object(dst); drm_intel_bo *src_bo, *dst_bo; + GLuint src_offset; if (size == 0) return; @@ -567,7 +760,7 @@ intel_bufferobj_copy_subdata(struct gl_context *ctx, if (src == dst) { char *ptr = intel_bufferobj_map(ctx, GL_COPY_WRITE_BUFFER, GL_READ_WRITE, dst); - memcpy(ptr + write_offset, ptr + read_offset, size); + memmove(ptr + write_offset, ptr + read_offset, size); intel_bufferobj_unmap(ctx, GL_COPY_WRITE_BUFFER, dst); } else { const char *src_ptr; @@ -589,18 +782,18 @@ intel_bufferobj_copy_subdata(struct gl_context *ctx, /* Otherwise, we have real BOs, so blit them. */ dst_bo = intel_bufferobj_buffer(intel, intel_dst, INTEL_WRITE_PART); - src_bo = intel_bufferobj_buffer(intel, intel_src, INTEL_READ); + src_bo = intel_bufferobj_source(intel, intel_src, &src_offset); intel_emit_linear_blit(intel, dst_bo, write_offset, - src_bo, read_offset, size); + src_bo, read_offset + src_offset, size); /* Since we've emitted some blits to buffers that will (likely) be used * in rendering operations in other cache domains in this batch, emit a * flush. Once again, we wish for a domain tracker in libdrm to cover * usage inside of a batchbuffer. */ - intel_batchbuffer_emit_mi_flush(intel->batch); + intel_batchbuffer_emit_mi_flush(intel); } #if FEATURE_APPLE_object_purgeable diff --git a/src/mesa/drivers/dri/intel/intel_buffer_objects.h b/src/mesa/drivers/dri/intel/intel_buffer_objects.h index b15c1921061..3ec3a521382 100644 --- a/src/mesa/drivers/dri/intel/intel_buffer_objects.h +++ b/src/mesa/drivers/dri/intel/intel_buffer_objects.h @@ -42,6 +42,8 @@ struct intel_buffer_object { struct gl_buffer_object Base; drm_intel_bo *buffer; /* the low-level buffer manager's buffer handle */ + GLuint offset; /* any offset into that buffer */ + /** System memory buffer data, if not using a BO to store the data. */ void *sys_buffer; @@ -55,6 +57,7 @@ struct intel_buffer_object GLsizei range_map_size; GLboolean mapped_gtt; + GLboolean source; }; @@ -63,8 +66,25 @@ struct intel_buffer_object drm_intel_bo *intel_bufferobj_buffer(struct intel_context *intel, struct intel_buffer_object *obj, GLuint flag); +drm_intel_bo *intel_bufferobj_source(struct intel_context *intel, + struct intel_buffer_object *obj, + GLuint *offset); + +void intel_upload_data(struct intel_context *intel, + const void *ptr, GLuint size, GLuint align, + drm_intel_bo **return_bo, + GLuint *return_offset); + +void *intel_upload_map(struct intel_context *intel, + GLuint size, GLuint align); +void intel_upload_unmap(struct intel_context *intel, + const void *ptr, GLuint size, GLuint align, + drm_intel_bo **return_bo, + GLuint *return_offset); + +void intel_upload_finish(struct intel_context *intel); -/* Hook the bufferobject implementation into mesa: +/* Hook the bufferobject implementation into mesa: */ void intelInitBufferObjectFuncs(struct dd_function_table *functions); diff --git a/src/mesa/drivers/dri/intel/intel_context.c b/src/mesa/drivers/dri/intel/intel_context.c index 2a5029964be..c2e2a98af5e 100644 --- a/src/mesa/drivers/dri/intel/intel_context.c +++ b/src/mesa/drivers/dri/intel/intel_context.c @@ -470,11 +470,9 @@ intel_prepare_render(struct intel_context *intel) * the swap, and getting our hands on that doesn't seem worth it, * so we just us the first batch we emitted after the last swap. */ - if (intel->need_throttle && intel->first_post_swapbuffers_batch) { - drm_intel_bo_wait_rendering(intel->first_post_swapbuffers_batch); - drm_intel_bo_unreference(intel->first_post_swapbuffers_batch); - intel->first_post_swapbuffers_batch = NULL; - intel->need_throttle = GL_FALSE; + if (intel->need_throttle) { + drmCommandNone(intel->driFd, DRM_I915_GEM_THROTTLE); + intel->need_throttle = GL_FALSE; } } @@ -487,7 +485,7 @@ intel_viewport(struct gl_context *ctx, GLint x, GLint y, GLsizei w, GLsizei h) if (intel->saved_viewport) intel->saved_viewport(ctx, x, y, w, h); - if (!intel->meta.internal_viewport_call && ctx->DrawBuffer->Name == 0) { + if (ctx->DrawBuffer->Name == 0) { dri2InvalidateDrawable(driContext->driDrawablePriv); dri2InvalidateDrawable(driContext->driReadablePriv); } @@ -554,8 +552,8 @@ intel_flush(struct gl_context *ctx) if (intel->gen < 4) INTEL_FIREVERTICES(intel); - if (intel->batch->map != intel->batch->ptr) - intel_batchbuffer_flush(intel->batch); + if (intel->batch.used) + intel_batchbuffer_flush(intel); } static void @@ -583,7 +581,7 @@ intelFinish(struct gl_context * ctx) irb = intel_renderbuffer(fb->_ColorDrawBuffers[i]); - if (irb && irb->region) + if (irb && irb->region && irb->region->buffer) drm_intel_bo_wait_rendering(irb->region->buffer); } if (fb->_DepthBuffer) { @@ -644,8 +642,8 @@ intelInitContext(struct intel_context *intel, mesaVis = &visual; } - if (!_mesa_initialize_context_for_api(&intel->ctx, api, mesaVis, shareCtx, - functions, (void *) intel)) { + if (!_mesa_initialize_context(&intel->ctx, api, mesaVis, shareCtx, + functions, (void *) intel)) { printf("%s: failed to init mesa context\n", __FUNCTION__); return GL_FALSE; } @@ -748,10 +746,10 @@ intelInitContext(struct intel_context *intel, driParseConfigFiles(&intel->optionCache, &intelScreen->optionCache, sPriv->myNum, (intel->gen >= 4) ? "i965" : "i915"); - if (intelScreen->deviceID == PCI_CHIP_I865_G) + if (intel->gen < 4) intel->maxBatchSize = 4096; else - intel->maxBatchSize = BATCH_SZ; + intel->maxBatchSize = sizeof(intel->batch.map); intel->bufmgr = intelScreen->bufmgr; @@ -805,8 +803,8 @@ intelInitContext(struct intel_context *intel, */ _mesa_init_point(ctx); - meta_init_metaops(ctx, &intel->meta); if (intel->gen >= 4) { + ctx->Const.sRGBCapable = GL_TRUE; if (MAX_WIDTH > 8192) ctx->Const.MaxRenderbufferSize = 8192; } else { @@ -863,7 +861,7 @@ intelInitContext(struct intel_context *intel, if (INTEL_DEBUG & DEBUG_BUFMGR) dri_bufmgr_set_debug(intel->bufmgr, GL_TRUE); - intel->batch = intel_batchbuffer_alloc(intel); + intel_batchbuffer_reset(intel); intel_fbo_init(intel); @@ -911,8 +909,6 @@ intelDestroyContext(__DRIcontext * driContextPriv) _mesa_meta_free(&intel->ctx); - meta_destroy_metaops(&intel->meta); - intel->vtbl.destroy(intel); _swsetup_DestroyContext(&intel->ctx); @@ -922,15 +918,12 @@ intelDestroyContext(__DRIcontext * driContextPriv) _swrast_DestroyContext(&intel->ctx); intel->Fallback = 0x0; /* don't call _swrast_Flush later */ - intel_batchbuffer_free(intel->batch); - intel->batch = NULL; + intel_batchbuffer_free(intel); free(intel->prim.vb); intel->prim.vb = NULL; drm_intel_bo_unreference(intel->prim.vb_bo); intel->prim.vb_bo = NULL; - drm_intel_bo_unreference(intel->first_post_swapbuffers_batch); - intel->first_post_swapbuffers_batch = NULL; driDestroyOptionCache(&intel->optionCache); diff --git a/src/mesa/drivers/dri/intel/intel_context.h b/src/mesa/drivers/dri/intel/intel_context.h index fd3c3ba58fc..772b2fba5a8 100644 --- a/src/mesa/drivers/dri/intel/intel_context.h +++ b/src/mesa/drivers/dri/intel/intel_context.h @@ -32,7 +32,6 @@ #include <stdbool.h> #include "main/mtypes.h" #include "main/mm.h" -#include "dri_metaops.h" #ifdef __cplusplus extern "C" { @@ -152,8 +151,6 @@ struct intel_context bool (*render_target_supported)(gl_format format); } vtbl; - struct dri_metaops meta; - GLbitfield Fallback; /**< mask of INTEL_FALLBACK_x bits */ GLuint NewGLState; @@ -172,17 +169,28 @@ struct intel_context int urb_size; - struct intel_batchbuffer *batch; - drm_intel_bo *first_post_swapbuffers_batch; + struct intel_batchbuffer { + drm_intel_bo *bo; + struct cached_batch_item *cached_items; + + uint16_t emit, total; + uint16_t used, reserved_space; + uint32_t map[8192]; +#define BATCH_SZ (8192*sizeof(uint32_t)) + + uint32_t state_batch_offset; + bool is_blit; + } batch; + GLboolean need_throttle; GLboolean no_batch_wrap; struct { GLuint id; + uint32_t start_ptr; /**< for i8xx */ uint32_t primitive; /**< Current hardware primitive type */ void (*flush) (struct intel_context *); - GLubyte *start_ptr; /**< for i8xx */ drm_intel_bo *vb_bo; uint8_t *vb; unsigned int start_offset; /**< Byte offset of primitive sequence */ @@ -190,6 +198,14 @@ struct intel_context unsigned int count; /**< Number of vertices in current primitive */ } prim; + struct { + drm_intel_bo *bo; + GLuint offset; + uint32_t buffer_len; + uint32_t buffer_offset; + char buffer[4096]; + } upload; + GLuint stats_wm; /* Offsets of fields within the current vertex: diff --git a/src/mesa/drivers/dri/intel/intel_extensions.c b/src/mesa/drivers/dri/intel/intel_extensions.c index 747e9dcb717..febc1d4f859 100644 --- a/src/mesa/drivers/dri/intel/intel_extensions.c +++ b/src/mesa/drivers/dri/intel/intel_extensions.c @@ -175,6 +175,7 @@ static const struct dri_extension brw_extensions[] = { { "GL_ARB_texture_non_power_of_two", NULL }, { "GL_ARB_texture_rg", NULL }, { "GL_EXT_draw_buffers2", GL_EXT_draw_buffers2_functions }, + { "GL_EXT_framebuffer_sRGB", NULL }, { "GL_EXT_shadow_funcs", NULL }, { "GL_EXT_stencil_two_side", GL_EXT_stencil_two_side_functions }, { "GL_EXT_texture_sRGB", NULL }, diff --git a/src/mesa/drivers/dri/intel/intel_fbo.c b/src/mesa/drivers/dri/intel/intel_fbo.c index 0db5a491c8f..8b57eb19f56 100644 --- a/src/mesa/drivers/dri/intel/intel_fbo.c +++ b/src/mesa/drivers/dri/intel/intel_fbo.c @@ -34,6 +34,7 @@ #include "main/framebuffer.h" #include "main/renderbuffer.h" #include "main/context.h" +#include "main/teximage.h" #include "main/texrender.h" #include "drivers/common/meta.h" @@ -580,7 +581,7 @@ intel_finish_render_texture(struct gl_context * ctx, * batch. Once again, we wish for a domain tracker in libdrm to cover * usage inside of a batchbuffer like GEM does in the kernel. */ - intel_batchbuffer_emit_mi_flush(intel->batch); + intel_batchbuffer_emit_mi_flush(intel); } /** @@ -647,6 +648,84 @@ intel_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) } } +/** + * Try to do a glBlitFramebuffer using glCopyTexSubImage2D + * We can do this when the dst renderbuffer is actually a texture and + * there is no scaling, mirroring or scissoring. + * + * \return new buffer mask indicating the buffers left to blit using the + * normal path. + */ +static GLbitfield +intel_blit_framebuffer_copy_tex_sub_image(struct gl_context *ctx, + GLint srcX0, GLint srcY0, + GLint srcX1, GLint srcY1, + GLint dstX0, GLint dstY0, + GLint dstX1, GLint dstY1, + GLbitfield mask, GLenum filter) +{ + if (mask & GL_COLOR_BUFFER_BIT) { + const struct gl_framebuffer *drawFb = ctx->DrawBuffer; + const struct gl_framebuffer *readFb = ctx->ReadBuffer; + const struct gl_renderbuffer_attachment *drawAtt = + &drawFb->Attachment[drawFb->_ColorDrawBufferIndexes[0]]; + + /* If the source and destination are the same size with no + mirroring, the rectangles are within the size of the + texture and there is no scissor then we can use + glCopyTexSubimage2D to implement the blit. This will end + up as a fast hardware blit on some drivers */ + if (drawAtt && drawAtt->Texture && + srcX0 - srcX1 == dstX0 - dstX1 && + srcY0 - srcY1 == dstY0 - dstY1 && + srcX1 >= srcX0 && + srcY1 >= srcY0 && + srcX0 >= 0 && srcX1 <= readFb->Width && + srcY0 >= 0 && srcY1 <= readFb->Height && + dstX0 >= 0 && dstX1 <= drawFb->Width && + dstY0 >= 0 && dstY1 <= drawFb->Height && + !ctx->Scissor.Enabled) { + const struct gl_texture_object *texObj = drawAtt->Texture; + const GLuint dstLevel = drawAtt->TextureLevel; + const GLenum target = texObj->Target; + + struct gl_texture_image *texImage = + _mesa_select_tex_image(ctx, texObj, target, dstLevel); + GLenum internalFormat = texImage->InternalFormat; + + if (intel_copy_texsubimage(intel_context(ctx), target, + intel_texture_image(texImage), + internalFormat, + dstX0, dstY0, + srcX0, srcY0, + srcX1 - srcX0, /* width */ + srcY1 - srcY0)) + mask &= ~GL_COLOR_BUFFER_BIT; + } + } + + return mask; +} + +static void +intel_blit_framebuffer(struct gl_context *ctx, + GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, + GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, + GLbitfield mask, GLenum filter) +{ + /* Try faster, glCopyTexSubImage2D approach first which uses the BLT. */ + mask = intel_blit_framebuffer_copy_tex_sub_image(ctx, + srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, + mask, filter); + if (mask == 0x0) + return; + + _mesa_meta_BlitFramebuffer(ctx, + srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, + mask, filter); +} /** * Do one-time context initializations related to GL_EXT_framebuffer_object. @@ -663,7 +742,7 @@ intel_fbo_init(struct intel_context *intel) intel->ctx.Driver.FinishRenderTexture = intel_finish_render_texture; intel->ctx.Driver.ResizeBuffers = intel_resize_buffers; intel->ctx.Driver.ValidateFramebuffer = intel_validate_framebuffer; - intel->ctx.Driver.BlitFramebuffer = _mesa_meta_BlitFramebuffer; + intel->ctx.Driver.BlitFramebuffer = intel_blit_framebuffer; #if FEATURE_OES_EGL_image intel->ctx.Driver.EGLImageTargetRenderbufferStorage = diff --git a/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c b/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c index e7356a6da0d..d7561ee689d 100644 --- a/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c +++ b/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c @@ -285,7 +285,7 @@ do_blit_bitmap( struct gl_context *ctx, out: if (unlikely(INTEL_DEBUG & DEBUG_SYNC)) - intel_batchbuffer_flush(intel->batch); + intel_batchbuffer_flush(intel); if (_mesa_is_bufferobj(unpack->BufferObj)) { /* done with PBO so unmap it now */ diff --git a/src/mesa/drivers/dri/intel/intel_pixel_read.c b/src/mesa/drivers/dri/intel/intel_pixel_read.c index 54da29236d2..b2e77c7986a 100644 --- a/src/mesa/drivers/dri/intel/intel_pixel_read.c +++ b/src/mesa/drivers/dri/intel/intel_pixel_read.c @@ -80,6 +80,7 @@ do_blit_readpixels(struct gl_context * ctx, drm_intel_bo *dst_buffer; GLboolean all; GLint dst_x, dst_y; + GLuint dirty; DBG("%s\n", __FUNCTION__); @@ -129,7 +130,9 @@ do_blit_readpixels(struct gl_context * ctx, return GL_TRUE; } + dirty = intel->front_buffer_dirty; intel_prepare_render(intel); + intel->front_buffer_dirty = dirty; all = (width * height * src->cpp == dst->Base.Size && x == 0 && dst_offset == 0); @@ -138,8 +141,8 @@ do_blit_readpixels(struct gl_context * ctx, dst_y = 0; dst_buffer = intel_bufferobj_buffer(intel, dst, - all ? INTEL_WRITE_FULL : - INTEL_WRITE_PART); + all ? INTEL_WRITE_FULL : + INTEL_WRITE_PART); if (ctx->ReadBuffer->Name == 0) y = ctx->ReadBuffer->Height - (y + height); @@ -171,6 +174,10 @@ intelReadPixels(struct gl_context * ctx, DBG("%s\n", __FUNCTION__); + if (do_blit_readpixels + (ctx, x, y, width, height, format, type, pack, pixels)) + return; + intel_flush(ctx); /* glReadPixels() wont dirty the front buffer, so reset the dirty @@ -179,10 +186,6 @@ intelReadPixels(struct gl_context * ctx, intel_prepare_render(intel); intel->front_buffer_dirty = dirty; - if (do_blit_readpixels - (ctx, x, y, width, height, format, type, pack, pixels)) - return; - fallback_debug("%s: fallback to swrast\n", __FUNCTION__); /* Update Mesa state before calling down into _swrast_ReadPixels, as diff --git a/src/mesa/drivers/dri/intel/intel_regions.c b/src/mesa/drivers/dri/intel/intel_regions.c index e87e29462c3..0857fa8ad70 100644 --- a/src/mesa/drivers/dri/intel/intel_regions.c +++ b/src/mesa/drivers/dri/intel/intel_regions.c @@ -491,7 +491,7 @@ intel_region_cow(struct intel_context *intel, struct intel_region *region) assert(region->cpp * region->pitch * region->height == pbo->Base.Size); - _DBG("%s %p (%d bytes)\n", __FUNCTION__, region, pbo->Base.Size); + _DBG("%s %p (%d bytes)\n", __FUNCTION__, region, (int)pbo->Base.Size); /* Now blit from the texture buffer to the new buffer: */ diff --git a/src/mesa/drivers/dri/intel/intel_screen.c b/src/mesa/drivers/dri/intel/intel_screen.c index 5d14bcd34c0..356d5f72d89 100644 --- a/src/mesa/drivers/dri/intel/intel_screen.c +++ b/src/mesa/drivers/dri/intel/intel_screen.c @@ -111,8 +111,8 @@ intelDRI2Flush(__DRIdrawable *drawable) intel->need_throttle = GL_TRUE; - if (intel->batch->map != intel->batch->ptr) - intel_batchbuffer_flush(intel->batch); + if (intel->batch.used) + intel_batchbuffer_flush(intel); } static const struct __DRI2flushExtensionRec intelFlushExtension = { @@ -634,6 +634,51 @@ __DRIconfig **intelInitScreen2(__DRIscreen *psp) return (const __DRIconfig **)configs; } +struct intel_buffer { + __DRIbuffer base; + struct intel_region *region; +}; + +static __DRIbuffer * +intelAllocateBuffer(__DRIscreen *screen, + unsigned attachment, unsigned format, + int width, int height) +{ + struct intel_buffer *intelBuffer; + struct intel_screen *intelScreen = screen->private; + + intelBuffer = CALLOC(sizeof *intelBuffer); + if (intelBuffer == NULL) + return NULL; + + intelBuffer->region = intel_region_alloc(intelScreen, I915_TILING_NONE, + format / 8, width, height, GL_TRUE); + + if (intelBuffer->region == NULL) { + FREE(intelBuffer); + return NULL; + } + + intel_region_flink(intelBuffer->region, &intelBuffer->base.name); + + intelBuffer->base.attachment = attachment; + intelBuffer->base.cpp = intelBuffer->region->cpp; + intelBuffer->base.pitch = + intelBuffer->region->pitch * intelBuffer->region->cpp; + + return &intelBuffer->base; +} + +static void +intelReleaseBuffer(__DRIscreen *screen, __DRIbuffer *buffer) +{ + struct intel_buffer *intelBuffer = (struct intel_buffer *) buffer; + + intel_region_release(&intelBuffer->region); + free(intelBuffer); +} + + const struct __DriverAPIRec driDriverAPI = { .DestroyScreen = intelDestroyScreen, .CreateContext = intelCreateContext, @@ -643,6 +688,8 @@ const struct __DriverAPIRec driDriverAPI = { .MakeCurrent = intelMakeCurrent, .UnbindContext = intelUnbindContext, .InitScreen2 = intelInitScreen2, + .AllocateBuffer = intelAllocateBuffer, + .ReleaseBuffer = intelReleaseBuffer }; /* This is the table of extensions that the loader will dlsym() for. */ diff --git a/src/mesa/drivers/dri/intel/intel_syncobj.c b/src/mesa/drivers/dri/intel/intel_syncobj.c index bbfac74b605..b303ea84dd8 100644 --- a/src/mesa/drivers/dri/intel/intel_syncobj.c +++ b/src/mesa/drivers/dri/intel/intel_syncobj.c @@ -72,9 +72,9 @@ intel_fence_sync(struct gl_context *ctx, struct gl_sync_object *s, struct intel_sync_object *sync = (struct intel_sync_object *)s; assert(condition == GL_SYNC_GPU_COMMANDS_COMPLETE); - intel_batchbuffer_emit_mi_flush(intel->batch); + intel_batchbuffer_emit_mi_flush(intel); - sync->bo = intel->batch->buf; + sync->bo = intel->batch.bo; drm_intel_bo_reference(sync->bo); intel_flush(ctx); diff --git a/src/mesa/drivers/dri/intel/intel_tex.h b/src/mesa/drivers/dri/intel/intel_tex.h index 6552ed0d332..52462f39d54 100644 --- a/src/mesa/drivers/dri/intel/intel_tex.h +++ b/src/mesa/drivers/dri/intel/intel_tex.h @@ -65,4 +65,12 @@ void intel_tex_unmap_images(struct intel_context *intel, int intel_compressed_num_bytes(GLuint mesaFormat); +GLboolean intel_copy_texsubimage(struct intel_context *intel, + GLenum target, + struct intel_texture_image *intelImage, + GLenum internalFormat, + GLint dstx, GLint dsty, + GLint x, GLint y, + GLsizei width, GLsizei height); + #endif diff --git a/src/mesa/drivers/dri/intel/intel_tex_copy.c b/src/mesa/drivers/dri/intel/intel_tex_copy.c index a40011ab40c..136d8e1d0a9 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_copy.c +++ b/src/mesa/drivers/dri/intel/intel_tex_copy.c @@ -67,13 +67,13 @@ get_teximage_readbuffer(struct intel_context *intel, GLenum internalFormat) } -static GLboolean -do_copy_texsubimage(struct intel_context *intel, - GLenum target, - struct intel_texture_image *intelImage, - GLenum internalFormat, - GLint dstx, GLint dsty, - GLint x, GLint y, GLsizei width, GLsizei height) +GLboolean +intel_copy_texsubimage(struct intel_context *intel, + GLenum target, + struct intel_texture_image *intelImage, + GLenum internalFormat, + GLint dstx, GLint dsty, + GLint x, GLint y, GLsizei width, GLsizei height) { struct gl_context *ctx = &intel->ctx; struct intel_renderbuffer *irb; @@ -191,9 +191,9 @@ intelCopyTexImage1D(struct gl_context * ctx, GLenum target, GLint level, &width, &height)) return; - if (!do_copy_texsubimage(intel_context(ctx), target, - intel_texture_image(texImage), - internalFormat, 0, 0, x, y, width, height)) + if (!intel_copy_texsubimage(intel_context(ctx), target, + intel_texture_image(texImage), + internalFormat, 0, 0, x, y, width, height)) goto fail; return; @@ -239,9 +239,9 @@ intelCopyTexImage2D(struct gl_context * ctx, GLenum target, GLint level, &width, &height)) return; - if (!do_copy_texsubimage(intel_context(ctx), target, - intel_texture_image(texImage), - internalFormat, 0, 0, x, y, width, height)) + if (!intel_copy_texsubimage(intel_context(ctx), target, + intel_texture_image(texImage), + internalFormat, 0, 0, x, y, width, height)) goto fail; return; @@ -269,9 +269,9 @@ intelCopyTexSubImage1D(struct gl_context * ctx, GLenum target, GLint level, /* Need to check texture is compatible with source format. */ - if (!do_copy_texsubimage(intel_context(ctx), target, - intel_texture_image(texImage), - internalFormat, xoffset, 0, x, y, width, 1)) { + if (!intel_copy_texsubimage(intel_context(ctx), target, + intel_texture_image(texImage), + internalFormat, xoffset, 0, x, y, width, 1)) { fallback_debug("%s - fallback to swrast\n", __FUNCTION__); _mesa_meta_CopyTexSubImage1D(ctx, target, level, xoffset, x, y, width); } @@ -293,11 +293,10 @@ intelCopyTexSubImage2D(struct gl_context * ctx, GLenum target, GLint level, /* Need to check texture is compatible with source format. */ - if (!do_copy_texsubimage(intel_context(ctx), target, - intel_texture_image(texImage), - internalFormat, - xoffset, yoffset, x, y, width, height)) { - + if (!intel_copy_texsubimage(intel_context(ctx), target, + intel_texture_image(texImage), + internalFormat, + xoffset, yoffset, x, y, width, height)) { fallback_debug("%s - fallback to swrast\n", __FUNCTION__); _mesa_meta_CopyTexSubImage2D(ctx, target, level, xoffset, yoffset, x, y, width, height); diff --git a/src/mesa/drivers/dri/intel/intel_tex_image.c b/src/mesa/drivers/dri/intel/intel_tex_image.c index cd8c4c22e5a..9dba529c58d 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_image.c +++ b/src/mesa/drivers/dri/intel/intel_tex_image.c @@ -231,15 +231,17 @@ try_pbo_upload(struct intel_context *intel, dst_stride = intelImage->mt->region->pitch; - if (drm_intel_bo_references(intel->batch->buf, dst_buffer)) + if (drm_intel_bo_references(intel->batch.bo, dst_buffer)) intel_flush(&intel->ctx); { - drm_intel_bo *src_buffer = intel_bufferobj_buffer(intel, pbo, INTEL_READ); + GLuint offset; + drm_intel_bo *src_buffer = intel_bufferobj_source(intel, pbo, &offset); if (!intelEmitCopyBlit(intel, intelImage->mt->cpp, - src_stride, src_buffer, src_offset, GL_FALSE, + src_stride, src_buffer, + src_offset + offset, GL_FALSE, dst_stride, dst_buffer, 0, intelImage->mt->region->tiling, 0, 0, dst_x, dst_y, width, height, @@ -429,7 +431,7 @@ intelTexImage(struct gl_context * ctx, if (intelImage->mt) { if (pixels != NULL) { /* Flush any queued rendering with the texture before mapping. */ - if (drm_intel_bo_references(intel->batch->buf, + if (drm_intel_bo_references(intel->batch.bo, intelImage->mt->region->buffer)) { intel_flush(ctx); } diff --git a/src/mesa/drivers/dri/mach64/mach64_context.c b/src/mesa/drivers/dri/mach64/mach64_context.c index 7c989df5ec0..35b01a97402 100644 --- a/src/mesa/drivers/dri/mach64/mach64_context.c +++ b/src/mesa/drivers/dri/mach64/mach64_context.c @@ -120,7 +120,7 @@ GLboolean mach64CreateContext( gl_api api, shareCtx = ((mach64ContextPtr) sharedContextPrivate)->glCtx; else shareCtx = NULL; - mmesa->glCtx = _mesa_create_context(glVisual, shareCtx, + mmesa->glCtx = _mesa_create_context(API_OPENGL, glVisual, shareCtx, &functions, (void *)mmesa); if (!mmesa->glCtx) { FREE(mmesa); diff --git a/src/mesa/drivers/dri/mga/mga_xmesa.c b/src/mesa/drivers/dri/mga/mga_xmesa.c index d1b281a2c05..eb7df9785c1 100644 --- a/src/mesa/drivers/dri/mga/mga_xmesa.c +++ b/src/mesa/drivers/dri/mga/mga_xmesa.c @@ -457,7 +457,7 @@ mgaCreateContext( gl_api api, shareCtx = ((mgaContextPtr) sharedContextPrivate)->glCtx; else shareCtx = NULL; - mmesa->glCtx = _mesa_create_context(mesaVis, shareCtx, + mmesa->glCtx = _mesa_create_context(API_OPENGL, mesaVis, shareCtx, &functions, (void *) mmesa); if (!mmesa->glCtx) { FREE(mmesa); diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.c b/src/mesa/drivers/dri/nouveau/nouveau_context.c index 53a121420d3..71dde413873 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_context.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_context.c @@ -115,7 +115,8 @@ nouveau_context_init(struct gl_context *ctx, struct nouveau_screen *screen, nouveau_fbo_functions_init(&functions); /* Initialize the mesa context. */ - _mesa_initialize_context(ctx, visual, share_ctx, &functions, NULL); + _mesa_initialize_context(ctx, API_OPENGL, visual, + share_ctx, &functions, NULL); nouveau_state_init(ctx); nouveau_bo_state_init(ctx); diff --git a/src/mesa/drivers/dri/r128/r128_context.c b/src/mesa/drivers/dri/r128/r128_context.c index 274108005f3..247d86ca008 100644 --- a/src/mesa/drivers/dri/r128/r128_context.c +++ b/src/mesa/drivers/dri/r128/r128_context.c @@ -128,7 +128,7 @@ GLboolean r128CreateContext( gl_api api, shareCtx = ((r128ContextPtr) sharedContextPrivate)->glCtx; else shareCtx = NULL; - rmesa->glCtx = _mesa_create_context(glVisual, shareCtx, + rmesa->glCtx = _mesa_create_context(API_OPENGL, glVisual, shareCtx, &functions, (void *) rmesa); if (!rmesa->glCtx) { FREE(rmesa); diff --git a/src/mesa/drivers/dri/r200/r200_vertprog.c b/src/mesa/drivers/dri/r200/r200_vertprog.c index 5d69012a81f..63e03b0e0c7 100644 --- a/src/mesa/drivers/dri/r200/r200_vertprog.c +++ b/src/mesa/drivers/dri/r200/r200_vertprog.c @@ -438,7 +438,7 @@ static GLboolean r200_translate_vertex_program(struct gl_context *ctx, struct r2 (1 << VERT_RESULT_TEX5) | (1 << VERT_RESULT_PSIZ))) != 0) { if (R200_DEBUG & RADEON_FALLBACKS) { fprintf(stderr, "can't handle vert prog outputs 0x%llx\n", - mesa_vp->Base.OutputsWritten); + (unsigned long long) mesa_vp->Base.OutputsWritten); } return GL_FALSE; } diff --git a/src/mesa/drivers/dri/r300/compiler/r300_fragprog.c b/src/mesa/drivers/dri/r300/compiler/r300_fragprog.c index 782671bac01..deba9ca834d 100644 --- a/src/mesa/drivers/dri/r300/compiler/r300_fragprog.c +++ b/src/mesa/drivers/dri/r300/compiler/r300_fragprog.c @@ -49,6 +49,11 @@ static void presub_string(char out[10], unsigned int inst) } } +static int get_msb(unsigned int bit, unsigned int r400_ext_addr) +{ + return (r400_ext_addr & bit) ? 1 << 5 : 0; +} + /* just some random things... */ void r300FragmentProgramDump(struct radeon_compiler *c, void *user) { @@ -61,16 +66,21 @@ void r300FragmentProgramDump(struct radeon_compiler *c, void *user) fprintf(stderr, "Hardware program\n"); fprintf(stderr, "----------------\n"); + if (c->is_r400) { + fprintf(stderr, "code_offset_ext: %08x\n", code->r400_code_offset_ext); + } for (n = 0; n <= (code->config & 3); n++) { uint32_t code_addr = code->code_addr[3 - (code->config & 3) + n]; - int alu_offset = (code_addr & R300_ALU_START_MASK) >> R300_ALU_START_SHIFT; - int alu_end = (code_addr & R300_ALU_SIZE_MASK) >> R300_ALU_SIZE_SHIFT; + unsigned int alu_offset = ((code_addr & R300_ALU_START_MASK) >> R300_ALU_START_SHIFT) + + (((code->r400_code_offset_ext >> (24 - (n * 6))) & 0x7) << 6); + unsigned int alu_end = ((code_addr & R300_ALU_SIZE_MASK) >> R300_ALU_SIZE_SHIFT) + + (((code->r400_code_offset_ext >> (27 - (n * 6))) & 0x7) << 6); int tex_offset = (code_addr & R300_TEX_START_MASK) >> R300_TEX_START_SHIFT; int tex_end = (code_addr & R300_TEX_SIZE_MASK) >> R300_TEX_SIZE_SHIFT; - fprintf(stderr, "NODE %d: alu_offset: %d, tex_offset: %d, " - "alu_end: %d, tex_end: %d (code_addr: %08x)\n", n, + fprintf(stderr, "NODE %d: alu_offset: %u, tex_offset: %d, " + "alu_end: %u, tex_end: %d (code_addr: %08x)\n", n, alu_offset, tex_offset, alu_end, tex_end, code_addr); if (n > 0 || (code->config & R300_PFS_CNTL_FIRST_NODE_HAS_TEX)) { @@ -125,11 +135,15 @@ void r300FragmentProgramDump(struct radeon_compiler *c, void *user) for (j = 0; j < 3; ++j) { int regc = code->alu.inst[i].rgb_addr >> (j * 6); int rega = code->alu.inst[i].alpha_addr >> (j * 6); + int msbc = get_msb(R400_ADDR_EXT_RGB_MSB_BIT(j), + code->alu.inst[i].r400_ext_addr); + int msba = get_msb(R400_ADDR_EXT_A_MSB_BIT(j), + code->alu.inst[i].r400_ext_addr); sprintf(srcc[j], "%c%i", - (regc & 32) ? 'c' : 't', regc & 31); + (regc & 32) ? 'c' : 't', (regc & 31) | msbc); sprintf(srca[j], "%c%i", - (rega & 32) ? 'c' : 't', rega & 31); + (rega & 32) ? 'c' : 't', (rega & 31) | msba); } dstc[0] = 0; @@ -141,9 +155,14 @@ void r300FragmentProgramDump(struct radeon_compiler *c, void *user) (code->alu.inst[i]. rgb_addr & R300_ALU_DSTC_REG_Z) ? "z" : ""); if (flags[0] != 0) { + unsigned int msb = get_msb( + R400_ADDRD_EXT_RGB_MSB_BIT, + code->alu.inst[i].r400_ext_addr); + sprintf(dstc, "t%i.%s ", - (code->alu.inst[i]. - rgb_addr >> R300_ALU_DSTC_SHIFT) & 31, + ((code->alu.inst[i]. + rgb_addr >> R300_ALU_DSTC_SHIFT) + & 31) | msb, flags); } sprintf(flags, "%s%s%s", @@ -166,9 +185,13 @@ void r300FragmentProgramDump(struct radeon_compiler *c, void *user) dsta[0] = 0; if (code->alu.inst[i].alpha_addr & R300_ALU_DSTA_REG) { + unsigned int msb = get_msb( + R400_ADDRD_EXT_A_MSB_BIT, + code->alu.inst[i].r400_ext_addr); sprintf(dsta, "t%i.w ", - (code->alu.inst[i]. - alpha_addr >> R300_ALU_DSTA_SHIFT) & 31); + ((code->alu.inst[i]. + alpha_addr >> R300_ALU_DSTA_SHIFT) & 31) + | msb); } if (code->alu.inst[i].alpha_addr & R300_ALU_DSTA_OUTPUT) { sprintf(tmp, "o%i.w ", diff --git a/src/mesa/drivers/dri/r300/compiler/r300_fragprog_emit.c b/src/mesa/drivers/dri/r300/compiler/r300_fragprog_emit.c index 1db8678e890..28d132a5fe3 100644 --- a/src/mesa/drivers/dri/r300/compiler/r300_fragprog_emit.c +++ b/src/mesa/drivers/dri/r300/compiler/r300_fragprog_emit.c @@ -64,6 +64,20 @@ struct r300_emit_state { __FILE__, __FUNCTION__, ##args); \ } while(0) +static unsigned int get_msbs_alu(unsigned int bits) +{ + return (bits >> 6) & 0x7; +} + +/** + * @param lsbs The number of least significant bits + */ +static unsigned int get_msbs_tex(unsigned int bits, unsigned int lsbs) +{ + return (bits >> lsbs) & 0x15; +} + +#define R400_EXT_GET_MSBS(x, lsbs, mask) (((x) >> lsbs) & mask) /** * Mark a temporary register as used. @@ -83,7 +97,7 @@ static unsigned int use_source(struct r300_fragment_program_code* code, struct r return src.Index | (1 << 5); } else if (src.File == RC_FILE_TEMPORARY) { use_temporary(code, src.Index); - return src.Index; + return src.Index & 0x1f; } return 0; @@ -151,11 +165,19 @@ static int emit_alu(struct r300_emit_state * emit, struct rc_pair_instruction* i code->alu.inst[ip].alpha_inst = translate_alpha_opcode(c, inst->Alpha.Opcode); for(j = 0; j < 3; ++j) { + /* Set the RGB address */ unsigned int src = use_source(code, inst->RGB.Src[j]); unsigned int arg; + if (inst->RGB.Src[j].Index >= R300_PFS_NUM_TEMP_REGS) + code->alu.inst[ip].r400_ext_addr |= R400_ADDR_EXT_RGB_MSB_BIT(j); + code->alu.inst[ip].rgb_addr |= src << (6*j); + /* Set the Alpha address */ src = use_source(code, inst->Alpha.Src[j]); + if (inst->Alpha.Src[j].Index >= R300_PFS_NUM_TEMP_REGS) + code->alu.inst[ip].r400_ext_addr |= R400_ADDR_EXT_A_MSB_BIT(j); + code->alu.inst[ip].alpha_addr |= src << (6*j); arg = r300FPTranslateRGBSwizzle(inst->RGB.Arg[j].Source, inst->RGB.Arg[j].Swizzle); @@ -223,8 +245,10 @@ static int emit_alu(struct r300_emit_state * emit, struct rc_pair_instruction* i if (inst->RGB.WriteMask) { use_temporary(code, inst->RGB.DestIndex); + if (inst->RGB.DestIndex >= R300_PFS_NUM_TEMP_REGS) + code->alu.inst[ip].r400_ext_addr |= R400_ADDRD_EXT_RGB_MSB_BIT; code->alu.inst[ip].rgb_addr |= - (inst->RGB.DestIndex << R300_ALU_DSTC_SHIFT) | + ((inst->RGB.DestIndex & 0x1f) << R300_ALU_DSTC_SHIFT) | (inst->RGB.WriteMask << R300_ALU_DSTC_REG_MASK_SHIFT); } if (inst->RGB.OutputWriteMask) { @@ -236,8 +260,10 @@ static int emit_alu(struct r300_emit_state * emit, struct rc_pair_instruction* i if (inst->Alpha.WriteMask) { use_temporary(code, inst->Alpha.DestIndex); + if (inst->Alpha.DestIndex >= R300_PFS_NUM_TEMP_REGS) + code->alu.inst[ip].r400_ext_addr |= R400_ADDRD_EXT_A_MSB_BIT; code->alu.inst[ip].alpha_addr |= - (inst->Alpha.DestIndex << R300_ALU_DSTA_SHIFT) | + ((inst->Alpha.DestIndex & 0x1f) << R300_ALU_DSTA_SHIFT) | R300_ALU_DSTA_REG; } if (inst->Alpha.OutputWriteMask) { @@ -269,6 +295,8 @@ static int finish_node(struct r300_emit_state * emit) unsigned tex_offset; unsigned tex_end; + unsigned int alu_offset_msbs, alu_end_msbs; + if (code->alu.length == emit->node_first_alu) { /* Generate a single NOP for this node */ struct rc_pair_instruction inst; @@ -301,13 +329,48 @@ static int finish_node(struct r300_emit_state * emit) * * Also note that the register specification from AMD is slightly * incorrect in its description of this register. */ - code->code_addr[emit->current_node] = - (alu_offset << R300_ALU_START_SHIFT) | - (alu_end << R300_ALU_SIZE_SHIFT) | - (tex_offset << R300_TEX_START_SHIFT) | - (tex_end << R300_TEX_SIZE_SHIFT) | - emit->node_flags; - + code->code_addr[emit->current_node] = + ((alu_offset << R300_ALU_START_SHIFT) + & R300_ALU_START_MASK) + | ((alu_end << R300_ALU_SIZE_SHIFT) + & R300_ALU_SIZE_MASK) + | ((tex_offset << R300_TEX_START_SHIFT) + & R300_TEX_START_MASK) + | ((tex_end << R300_TEX_SIZE_SHIFT) + & R300_TEX_SIZE_MASK) + | emit->node_flags + | (get_msbs_tex(tex_offset, 5) + << R400_TEX_START_MSB_SHIFT) + | (get_msbs_tex(tex_end, 5) + << R400_TEX_SIZE_MSB_SHIFT) + ; + + /* Write r400 extended instruction fields. These will be ignored on + * r300 cards. */ + alu_offset_msbs = get_msbs_alu(alu_offset); + alu_end_msbs = get_msbs_alu(alu_end); + switch(emit->current_node) { + case 0: + code->r400_code_offset_ext |= + alu_offset_msbs << R400_ALU_START3_MSB_SHIFT + | alu_end_msbs << R400_ALU_SIZE3_MSB_SHIFT; + break; + case 1: + code->r400_code_offset_ext |= + alu_offset_msbs << R400_ALU_START2_MSB_SHIFT + | alu_end_msbs << R400_ALU_SIZE2_MSB_SHIFT; + break; + case 2: + code->r400_code_offset_ext |= + alu_offset_msbs << R400_ALU_START1_MSB_SHIFT + | alu_end_msbs << R400_ALU_SIZE1_MSB_SHIFT; + break; + case 3: + code->r400_code_offset_ext |= + alu_offset_msbs << R400_ALU_START0_MSB_SHIFT + | alu_end_msbs << R400_ALU_SIZE0_MSB_SHIFT; + break; + } return 1; } @@ -348,7 +411,7 @@ static int emit_tex(struct r300_emit_state * emit, struct rc_instruction * inst) unsigned int opcode; PROG_CODE; - if (code->tex.length >= R300_PFS_MAX_TEX_INST) { + if (code->tex.length >= emit->compiler->Base.max_tex_insts) { error("Too many TEX instructions"); return 0; } @@ -376,10 +439,17 @@ static int emit_tex(struct r300_emit_state * emit, struct rc_instruction * inst) use_temporary(code, inst->U.I.SrcReg[0].Index); code->tex.inst[code->tex.length++] = - (inst->U.I.SrcReg[0].Index << R300_SRC_ADDR_SHIFT) | - (dest << R300_DST_ADDR_SHIFT) | - (unit << R300_TEX_ID_SHIFT) | - (opcode << R300_TEX_INST_SHIFT); + ((inst->U.I.SrcReg[0].Index << R300_SRC_ADDR_SHIFT) + & R300_SRC_ADDR_MASK) + | ((dest << R300_DST_ADDR_SHIFT) + & R300_DST_ADDR_MASK) + | (unit << R300_TEX_ID_SHIFT) + | (opcode << R300_TEX_INST_SHIFT) + | (inst->U.I.SrcReg[0].Index >= R300_PFS_NUM_TEMP_REGS ? + R400_SRC_ADDR_EXT_BIT : 0) + | (dest >= R300_PFS_NUM_TEMP_REGS ? + R400_DST_ADDR_EXT_BIT : 0) + ; return 1; } @@ -393,6 +463,7 @@ void r300BuildFragmentProgramHwCode(struct radeon_compiler *c, void *user) struct r300_fragment_program_compiler *compiler = (struct r300_fragment_program_compiler*)c; struct r300_emit_state emit; struct r300_fragment_program_code *code = &compiler->code->code.r300; + unsigned int tex_end; memset(&emit, 0, sizeof(emit)); emit.compiler = compiler; @@ -424,11 +495,28 @@ void r300BuildFragmentProgramHwCode(struct radeon_compiler *c, void *user) finish_node(&emit); code->config |= emit.current_node; /* FIRST_NODE_HAS_TEX set by finish_node */ + + /* Set r400 extended instruction fields. These values will be ignored + * on r300 cards. */ + code->r400_code_offset_ext |= + (get_msbs_alu(0) + << R400_ALU_OFFSET_MSB_SHIFT) + | (get_msbs_alu(code->alu.length - 1) + << R400_ALU_SIZE_MSB_SHIFT); + + tex_end = code->tex.length ? code->tex.length - 1 : 0; code->code_offset = - (0 << R300_PFS_CNTL_ALU_OFFSET_SHIFT) | - ((code->alu.length-1) << R300_PFS_CNTL_ALU_END_SHIFT) | - (0 << R300_PFS_CNTL_TEX_OFFSET_SHIFT) | - ((code->tex.length ? code->tex.length-1 : 0) << R300_PFS_CNTL_TEX_END_SHIFT); + ((0 << R300_PFS_CNTL_ALU_OFFSET_SHIFT) + & R300_PFS_CNTL_ALU_OFFSET_MASK) + | (((code->alu.length - 1) << R300_PFS_CNTL_ALU_END_SHIFT) + & R300_PFS_CNTL_ALU_END_MASK) + | ((0 << R300_PFS_CNTL_TEX_OFFSET_SHIFT) + & R300_PFS_CNTL_TEX_OFFSET_MASK) + | ((tex_end << R300_PFS_CNTL_TEX_END_SHIFT) + & R300_PFS_CNTL_TEX_END_MASK) + | (get_msbs_tex(0, 5) << R400_TEX_START_MSB_SHIFT) + | (get_msbs_tex(tex_end, 6) << R400_TEX_SIZE_MSB_SHIFT) + ; if (emit.current_node < 3) { int shift = 3 - emit.current_node; @@ -438,4 +526,11 @@ void r300BuildFragmentProgramHwCode(struct radeon_compiler *c, void *user) for(i = 0; i < shift; ++i) code->code_addr[i] = 0; } + + if (code->pixsize >= R300_PFS_NUM_TEMP_REGS + || code->alu.length > R300_PFS_MAX_ALU_INST + || code->tex.length > R300_PFS_MAX_TEX_INST) { + + code->r390_mode = 1; + } } diff --git a/src/mesa/drivers/dri/r300/compiler/r300_fragprog_swizzle.c b/src/mesa/drivers/dri/r300/compiler/r300_fragprog_swizzle.c index 05d3da8a10d..fa906f2fdde 100644 --- a/src/mesa/drivers/dri/r300/compiler/r300_fragprog_swizzle.c +++ b/src/mesa/drivers/dri/r300/compiler/r300_fragprog_swizzle.c @@ -222,13 +222,14 @@ unsigned int r300FPTranslateRGBSwizzle(unsigned int src, unsigned int swizzle) */ unsigned int r300FPTranslateAlphaSwizzle(unsigned int src, unsigned int swizzle) { + unsigned int swz = GET_SWZ(swizzle, 0); if (src == RC_PAIR_PRESUB_SRC) { - return R300_ALU_ARGA_SRCP_X + swizzle; + return R300_ALU_ARGA_SRCP_X + swz; } - if (swizzle < 3) - return swizzle + 3*src; + if (swz < 3) + return swz + 3*src; - switch(swizzle) { + switch(swz) { case RC_SWIZZLE_W: return R300_ALU_ARGA_SRC0A + src; case RC_SWIZZLE_ONE: return R300_ALU_ARGA_ONE; case RC_SWIZZLE_ZERO: return R300_ALU_ARGA_ZERO; diff --git a/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c b/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c index e0d349b98ce..1616306afbd 100644 --- a/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c +++ b/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c @@ -124,7 +124,7 @@ void r3xx_compile_fragment_program(struct r300_fragment_program_compiler* c) /* This pass makes it easier for the scheduler to group TEX * instructions and reduces the chances of creating too * many texture indirections.*/ - {"register rename", 1, !is_r500 || opt, rc_rename_regs, NULL}, + {"register rename", 1, !is_r500, rc_rename_regs, NULL}, {"pair translate", 1, 1, rc_pair_translate, NULL}, {"pair scheduling", 1, 1, rc_pair_schedule, NULL}, {"register allocation", 1, opt, rc_pair_regalloc, NULL}, diff --git a/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c b/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c index 472029f63d0..8ad2175eadf 100644 --- a/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c +++ b/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c @@ -490,13 +490,6 @@ static void translate_vertex_program(struct radeon_compiler *c, void *user) continue; if (info->HasDstReg) { - /* Relative addressing of destination operands is not supported yet. */ - if (vpi->DstReg.RelAddr) { - rc_error(&compiler->Base, "Vertex program does not support relative " - "addressing of destination operands (yet).\n"); - return; - } - /* Neither is Saturate. */ if (vpi->SaturateMode != RC_SATURATE_NONE) { rc_error(&compiler->Base, "Vertex program does not support the Saturate " @@ -668,7 +661,6 @@ static void allocate_temporary_registers(struct radeon_compiler *c, void *user) char hwtemps[RC_REGISTER_MAX_INDEX]; struct temporary_allocation * ta; unsigned int i, j; - struct rc_instruction *last_inst_src_reladdr = NULL; memset(hwtemps, 0, sizeof(hwtemps)); @@ -693,28 +685,11 @@ static void allocate_temporary_registers(struct radeon_compiler *c, void *user) } } - /* Pass 2: If there is relative addressing of dst temporaries, we cannot change register indices. Give up. - * For src temporaries, save the last instruction which uses relative addressing. */ - for (inst = compiler->Base.Program.Instructions.Next; inst != &compiler->Base.Program.Instructions; inst = inst->Next) { - const struct rc_opcode_info *opcode = rc_get_opcode_info(inst->U.I.Opcode); - - if (opcode->HasDstReg) - if (inst->U.I.DstReg.RelAddr) - return; - - for (i = 0; i < opcode->NumSrcRegs; ++i) { - if (inst->U.I.SrcReg[i].File == RC_FILE_TEMPORARY && - inst->U.I.SrcReg[i].RelAddr) { - last_inst_src_reladdr = inst; - } - } - } - ta = (struct temporary_allocation*)memory_pool_malloc(&compiler->Base.Pool, sizeof(struct temporary_allocation) * num_orig_temps); memset(ta, 0, sizeof(struct temporary_allocation) * num_orig_temps); - /* Pass 3: Determine original temporary lifetimes */ + /* Pass 2: Determine original temporary lifetimes */ for(inst = compiler->Base.Program.Instructions.Next; inst != &compiler->Base.Program.Instructions; inst = inst->Next) { const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode); /* Instructions inside of loops need to use the ENDLOOP @@ -744,41 +719,22 @@ static void allocate_temporary_registers(struct radeon_compiler *c, void *user) for (i = 0; i < opcode->NumSrcRegs; ++i) { if (inst->U.I.SrcReg[i].File == RC_FILE_TEMPORARY) { - struct rc_instruction *last_read; - - /* From "last_inst_src_reladdr", "end_loop", and "inst", - * select the instruction with the highest instruction index (IP). - * Note that "end_loop", if available, has always a higher index than "inst". */ - if (last_inst_src_reladdr) { - if (end_loop) { - last_read = last_inst_src_reladdr->IP > end_loop->IP ? - last_inst_src_reladdr : end_loop; - } else { - last_read = last_inst_src_reladdr->IP > inst->IP ? - last_inst_src_reladdr : inst; - } - } else { - last_read = end_loop ? end_loop : inst; - } - - ta[inst->U.I.SrcReg[i].Index].LastRead = last_read; + ta[inst->U.I.SrcReg[i].Index].LastRead = end_loop ? end_loop : inst; } } } - /* Pass 4: Register allocation */ + /* Pass 3: Register allocation */ for(inst = compiler->Base.Program.Instructions.Next; inst != &compiler->Base.Program.Instructions; inst = inst->Next) { const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode); - if (!last_inst_src_reladdr || last_inst_src_reladdr->IP < inst->IP) { - for (i = 0; i < opcode->NumSrcRegs; ++i) { - if (inst->U.I.SrcReg[i].File == RC_FILE_TEMPORARY) { - unsigned int orig = inst->U.I.SrcReg[i].Index; - inst->U.I.SrcReg[i].Index = ta[orig].HwTemp; + for (i = 0; i < opcode->NumSrcRegs; ++i) { + if (inst->U.I.SrcReg[i].File == RC_FILE_TEMPORARY) { + unsigned int orig = inst->U.I.SrcReg[i].Index; + inst->U.I.SrcReg[i].Index = ta[orig].HwTemp; - if (ta[orig].Allocated && inst == ta[orig].LastRead) - hwtemps[ta[orig].HwTemp] = 0; - } + if (ta[orig].Allocated && inst == ta[orig].LastRead) + hwtemps[ta[orig].HwTemp] = 0; } } @@ -792,12 +748,7 @@ static void allocate_temporary_registers(struct radeon_compiler *c, void *user) break; } ta[orig].Allocated = 1; - if (last_inst_src_reladdr && - last_inst_src_reladdr->IP > inst->IP) { - ta[orig].HwTemp = orig; - } else { - ta[orig].HwTemp = j; - } + ta[orig].HwTemp = j; hwtemps[ta[orig].HwTemp] = 1; } diff --git a/src/mesa/drivers/dri/r300/compiler/r500_fragprog_emit.c b/src/mesa/drivers/dri/r300/compiler/r500_fragprog_emit.c index 5da82d90f67..1febc19cc2d 100644 --- a/src/mesa/drivers/dri/r300/compiler/r500_fragprog_emit.c +++ b/src/mesa/drivers/dri/r300/compiler/r500_fragprog_emit.c @@ -170,7 +170,7 @@ static unsigned int translate_arg_rgb(struct rc_pair_instruction *inst, int arg) static unsigned int translate_arg_alpha(struct rc_pair_instruction *inst, int i) { unsigned int t = inst->Alpha.Arg[i].Source; - t |= fix_hw_swizzle(inst->Alpha.Arg[i].Swizzle) << 2; + t |= fix_hw_swizzle(GET_SWZ(inst->Alpha.Arg[i].Swizzle, 0)) << 2; t |= inst->Alpha.Arg[i].Negate << 5; t |= inst->Alpha.Arg[i].Abs << 6; return t; diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_code.h b/src/mesa/drivers/dri/r300/compiler/radeon_code.h index b69e81698ae..d1451668947 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_code.h +++ b/src/mesa/drivers/dri/r300/compiler/radeon_code.h @@ -31,6 +31,9 @@ #define R300_PFS_NUM_TEMP_REGS 32 #define R300_PFS_NUM_CONST_REGS 32 +#define R400_PFS_MAX_ALU_INST 512 +#define R400_PFS_MAX_TEX_INST 512 + #define R500_PFS_MAX_INST 512 #define R500_PFS_NUM_TEMP_REGS 128 #define R500_PFS_NUM_CONST_REGS 256 @@ -187,24 +190,29 @@ struct r300_fragment_program_node { */ struct r300_fragment_program_code { struct { - int length; /**< total # of texture instructions used */ - uint32_t inst[R300_PFS_MAX_TEX_INST]; + unsigned int length; /**< total # of texture instructions used */ + uint32_t inst[R400_PFS_MAX_TEX_INST]; } tex; struct { - int length; /**< total # of ALU instructions used */ + unsigned int length; /**< total # of ALU instructions used */ struct { uint32_t rgb_inst; uint32_t rgb_addr; uint32_t alpha_inst; uint32_t alpha_addr; - } inst[R300_PFS_MAX_ALU_INST]; + uint32_t r400_ext_addr; + } inst[R400_PFS_MAX_ALU_INST]; } alu; uint32_t config; /* US_CONFIG */ uint32_t pixsize; /* US_PIXSIZE */ uint32_t code_offset; /* US_CODE_OFFSET */ + uint32_t r400_code_offset_ext; /* US_CODE_EXT */ uint32_t code_addr[4]; /* US_CODE_ADDR */ + /*US_CODE_BANK.R390_MODE: Enables 512 instructions and 64 temporaries + * for r400 cards */ + unsigned int r390_mode:1; }; diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_compiler.c b/src/mesa/drivers/dri/r300/compiler/radeon_compiler.c index 65548604bcc..79cd7996f78 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_compiler.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_compiler.c @@ -373,9 +373,11 @@ void rc_get_stats(struct radeon_compiler *c, struct rc_program_stats *s) const struct rc_opcode_info * info; rc_for_all_reads_mask(tmp, reg_count_callback, &max_reg); if (tmp->Type == RC_INSTRUCTION_NORMAL) { + info = rc_get_opcode_info(tmp->U.I.Opcode); + if (info->Opcode == RC_OPCODE_BEGIN_TEX) + continue; if (tmp->U.I.PreSub.Opcode != RC_PRESUB_NONE) s->num_presub_ops++; - info = rc_get_opcode_info(tmp->U.I.Opcode); } else { if (tmp->U.P.RGB.Src[RC_PAIR_PRESUB_SRC].Used) s->num_presub_ops++; @@ -402,11 +404,11 @@ static void print_stats(struct radeon_compiler * c) { struct rc_program_stats s; - rc_get_stats(c, &s); - - if (s.num_insts < 4) + if (c->initial_num_insts <= 5) return; + rc_get_stats(c, &s); + switch (c->type) { case RC_VERTEX_PROGRAM: fprintf(stderr,"~~~~~~~~~ VERTEX PROGRAM ~~~~~~~~\n" @@ -461,6 +463,11 @@ void rc_run_compiler_passes(struct radeon_compiler *c, struct radeon_compiler_pa /* Executes a list of compiler passes given in the parameter 'list'. */ void rc_run_compiler(struct radeon_compiler *c, struct radeon_compiler_pass *list) { + struct rc_program_stats s; + + rc_get_stats(c, &s); + c->initial_num_insts = s.num_insts; + if (c->Debug & RC_DBG_LOG) { fprintf(stderr, "%s: before compilation\n", shader_name[c->type]); rc_print_program(&c->Program); diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_compiler.h b/src/mesa/drivers/dri/r300/compiler/radeon_compiler.h index e6633395895..2d8e415f350 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_compiler.h +++ b/src/mesa/drivers/dri/r300/compiler/radeon_compiler.h @@ -50,6 +50,7 @@ struct radeon_compiler { char * ErrorMsg; /* Hardware specification. */ + unsigned is_r400:1; unsigned is_r500:1; unsigned has_half_swizzles:1; unsigned has_presub:1; @@ -57,6 +58,7 @@ struct radeon_compiler { unsigned max_temp_regs; unsigned max_constants; int max_alu_insts; + unsigned max_tex_insts; /* Whether to remove unused constants and empty holes in constant space. */ unsigned remove_unused_constants:1; @@ -70,6 +72,8 @@ struct radeon_compiler { /*@}*/ struct emulate_loop_state loop_state; + + unsigned initial_num_insts; /* Number of instructions at start. */ }; void rc_init(struct radeon_compiler * c); diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.c b/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.c index 2482fc68beb..15ec4418cb8 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.c @@ -55,6 +55,24 @@ rc_swizzle get_swz(unsigned int swz, rc_swizzle idx) return GET_SWZ(swz, idx); } +/** + * The purpose of this function is to standardize the number channels used by + * swizzles. All swizzles regardless of what instruction they are a part of + * should have 4 channels initialized with values. + * @param channels The number of channels in initial_value that have a + * meaningful value. + * @return An initialized swizzle that has all of the unused channels set to + * RC_SWIZZLE_UNUSED. + */ +unsigned int rc_init_swizzle(unsigned int initial_value, unsigned int channels) +{ + unsigned int i; + for (i = channels; i < 4; i++) { + SET_SWZ(initial_value, i, RC_SWIZZLE_UNUSED); + } + return initial_value; +} + unsigned int combine_swizzles4(unsigned int src, rc_swizzle swz_x, rc_swizzle swz_y, rc_swizzle swz_z, rc_swizzle swz_w) { @@ -147,13 +165,17 @@ unsigned int rc_src_reads_dst_mask( return dst_mask & rc_swizzle_to_writemask(src_swz); } -unsigned int rc_source_type_swz(unsigned int swizzle, unsigned int channels) +/** + * @return A bit mask specifying whether this swizzle will select from an RGB + * source, an Alpha source, or both. + */ +unsigned int rc_source_type_swz(unsigned int swizzle) { unsigned int chan; unsigned int swz = RC_SWIZZLE_UNUSED; unsigned int ret = RC_SOURCE_NONE; - for(chan = 0; chan < channels; chan++) { + for(chan = 0; chan < 4; chan++) { swz = GET_SWZ(swizzle, chan); if (swz == RC_SWIZZLE_W) { ret |= RC_SOURCE_ALPHA; @@ -202,7 +224,7 @@ static void can_use_presub_read_cb( if (d->RemoveSrcs[i].File == file && d->RemoveSrcs[i].Index == index) { src_type &= - ~rc_source_type_swz(d->RemoveSrcs[i].Swizzle, 4); + ~rc_source_type_swz(d->RemoveSrcs[i].Swizzle); } } diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.h b/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.h index 461ab9ffb10..dd0f6c66156 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.h +++ b/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.h @@ -10,6 +10,8 @@ unsigned int rc_swizzle_to_writemask(unsigned int swz); rc_swizzle get_swz(unsigned int swz, rc_swizzle idx); +unsigned int rc_init_swizzle(unsigned int initial_value, unsigned int channels); + unsigned int combine_swizzles4(unsigned int src, rc_swizzle swz_x, rc_swizzle swz_y, rc_swizzle swz_z, rc_swizzle swz_w); @@ -32,7 +34,7 @@ unsigned int rc_src_reads_dst_mask( unsigned int dst_idx, unsigned int dst_mask); -unsigned int rc_source_type_swz(unsigned int swizzle, unsigned int channels); +unsigned int rc_source_type_swz(unsigned int swizzle); unsigned int rc_source_type_mask(unsigned int mask); diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c index d0a64d936e0..c080d5aecc6 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c @@ -140,14 +140,8 @@ static void pair_sub_for_all_args( for(i = 0; i < info->NumSrcRegs; i++) { unsigned int src_type; - unsigned int channels = 0; - if (&fullinst->U.P.RGB == sub) - channels = 3; - else if (&fullinst->U.P.Alpha == sub) - channels = 1; - - assert(channels > 0); - src_type = rc_source_type_swz(sub->Arg[i].Swizzle, channels); + + src_type = rc_source_type_swz(sub->Arg[i].Swizzle); if (src_type == RC_SOURCE_NONE) continue; diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_deadcode.c b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_deadcode.c index 87906f37b12..678e1475883 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_deadcode.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_deadcode.c @@ -160,12 +160,8 @@ static void update_instruction(struct deadcode_state * s, struct rc_instruction unsigned char * pused = get_used_ptr(s, inst->U.I.DstReg.File, inst->U.I.DstReg.Index); if (pused) { usedmask = *pused & inst->U.I.DstReg.WriteMask; - if (!inst->U.I.DstReg.RelAddr) - *pused &= ~usedmask; + *pused &= ~usedmask; } - - if (inst->U.I.DstReg.RelAddr) - mark_used(s, RC_FILE_ADDRESS, 0, RC_MASK_X); } insts->WriteMask |= usedmask; @@ -219,22 +215,9 @@ void rc_dataflow_deadcode(struct radeon_compiler * c, void *user) { struct deadcode_state s; unsigned int nr_instructions; - unsigned has_temp_reladdr_src = 0; rc_dataflow_mark_outputs_fn dce = (rc_dataflow_mark_outputs_fn)user; unsigned int ip; - /* Give up if there is relative addressing of destination operands. */ - for(struct rc_instruction * inst = c->Program.Instructions.Next; - inst != &c->Program.Instructions; - inst = inst->Next) { - const struct rc_opcode_info *opcode = rc_get_opcode_info(inst->U.I.Opcode); - if (opcode->HasDstReg && - inst->U.I.DstReg.WriteMask && - inst->U.I.DstReg.RelAddr) { - return; - } - } - memset(&s, 0, sizeof(s)); s.C = c; @@ -321,32 +304,6 @@ void rc_dataflow_deadcode(struct radeon_compiler * c, void *user) rc_error(c, "%s: Unhandled control flow instruction %s\n", __FUNCTION__, opcode->Name); } } - - if (!has_temp_reladdr_src) { - for (unsigned i = 0; i < opcode->NumSrcRegs; i++) { - if (inst->U.I.SrcReg[i].File == RC_FILE_TEMPORARY && - inst->U.I.SrcReg[i].RelAddr) { - /* If there is a register read from a temporary file with relative addressing, - * mark all preceding written registers as used. */ - for (struct rc_instruction *ptr = inst->Prev; - ptr != &c->Program.Instructions; - ptr = ptr->Prev) { - opcode = rc_get_opcode_info(ptr->U.I.Opcode); - if (opcode->HasDstReg && - ptr->U.I.DstReg.File == RC_FILE_TEMPORARY && - ptr->U.I.DstReg.WriteMask) { - mark_used(&s, - ptr->U.I.DstReg.File, - ptr->U.I.DstReg.Index, - ptr->U.I.DstReg.WriteMask); - } - } - - has_temp_reladdr_src = 1; - break; - } - } - } } update_instruction(&s, inst); diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_optimize.c b/src/mesa/drivers/dri/r300/compiler/radeon_optimize.c index 44f4c0fbdc7..5caff91b00e 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_optimize.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_optimize.c @@ -139,7 +139,6 @@ static void copy_propagate(struct radeon_compiler * c, struct rc_instruction * i unsigned int i; if (inst_mov->U.I.DstReg.File != RC_FILE_TEMPORARY || - inst_mov->U.I.DstReg.RelAddr || inst_mov->U.I.WriteALUResult || inst_mov->U.I.SaturateMode) return; diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_pair_schedule.c b/src/mesa/drivers/dri/r300/compiler/radeon_pair_schedule.c index 9beb5d63579..8e10813ff06 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_pair_schedule.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_pair_schedule.c @@ -365,8 +365,8 @@ static int merge_presub_sources( for(arg = 0; arg < info->NumSrcRegs; arg++) { /*If this arg does not read from an rgb source, * do nothing. */ - if (!(rc_source_type_swz(dst_full->RGB.Arg[arg].Swizzle, - 3) & type)) { + if (!(rc_source_type_swz(dst_full->RGB.Arg[arg].Swizzle) + & type)) { continue; } @@ -423,11 +423,11 @@ static int destructive_merge_instructions( unsigned int index = 0; int source; - if (alpha->Alpha.Arg[arg].Swizzle < 3) { + if (GET_SWZ(alpha->Alpha.Arg[arg].Swizzle, 0) < 3) { srcrgb = 1; file = alpha->RGB.Src[oldsrc].File; index = alpha->RGB.Src[oldsrc].Index; - } else if (alpha->Alpha.Arg[arg].Swizzle < 4) { + } else if (GET_SWZ(alpha->Alpha.Arg[arg].Swizzle, 0) < 4) { srcalpha = 1; file = alpha->Alpha.Src[oldsrc].File; index = alpha->Alpha.Src[oldsrc].Index; @@ -544,18 +544,12 @@ static void rgb_to_alpha_remap ( { int new_src_index; unsigned int i; - struct rc_pair_instruction_source * old_src = - rc_pair_get_src(&inst->U.P, arg); - if (!old_src) { - return; - } for (i = 0; i < 3; i++) { if (get_swz(arg->Swizzle, i) == old_swz) { SET_SWZ(arg->Swizzle, i, RC_SWIZZLE_W); } } - memset(old_src, 0, sizeof(struct rc_pair_instruction_source)); new_src_index = rc_pair_alloc_source(&inst->U.P, 0, 1, old_file, new_index); /* This conversion is not possible, we must have made a mistake in @@ -728,7 +722,8 @@ static int convert_rgb_to_alpha( for (j = 0; j < 3; j++) { unsigned int swz = get_swz(pair_inst->Alpha.Arg[i].Swizzle, j); if (swz != RC_SWIZZLE_UNUSED) { - pair_inst->Alpha.Arg[i].Swizzle = swz; + pair_inst->Alpha.Arg[i].Swizzle = + rc_init_swizzle(swz, 1); break; } } diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_pair_translate.c b/src/mesa/drivers/dri/r300/compiler/radeon_pair_translate.c index fc05366f50e..6d7263b4ab6 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_pair_translate.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_pair_translate.c @@ -28,6 +28,7 @@ #include "radeon_program_pair.h" #include "radeon_compiler.h" +#include "radeon_compiler_util.h" /** @@ -232,7 +233,8 @@ static void set_pair_instruction(struct r300_fragment_program_compiler *c, return; } pair->RGB.Arg[i].Source = source; - pair->RGB.Arg[i].Swizzle = inst->SrcReg[i].Swizzle & 0x1ff; + pair->RGB.Arg[i].Swizzle = + rc_init_swizzle(inst->SrcReg[i].Swizzle, 3); pair->RGB.Arg[i].Abs = inst->SrcReg[i].Abs; pair->RGB.Arg[i].Negate = !!(inst->SrcReg[i].Negate & (RC_MASK_X | RC_MASK_Y | RC_MASK_Z)); } @@ -252,7 +254,7 @@ static void set_pair_instruction(struct r300_fragment_program_compiler *c, return; } pair->Alpha.Arg[i].Source = source; - pair->Alpha.Arg[i].Swizzle = swz; + pair->Alpha.Arg[i].Swizzle = rc_init_swizzle(swz, 1); pair->Alpha.Arg[i].Abs = inst->SrcReg[i].Abs; pair->Alpha.Arg[i].Negate = !!(inst->SrcReg[i].Negate & RC_MASK_W); } @@ -302,12 +304,6 @@ static void check_opcode_support(struct r300_fragment_program_compiler *c, const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->Opcode); if (opcode->HasDstReg) { - if (inst->DstReg.RelAddr) { - rc_error(&c->Base, "Fragment program does not support relative addressing " - "of destination operands.\n"); - return; - } - if (inst->SaturateMode == RC_SATURATE_MINUS_PLUS_ONE) { rc_error(&c->Base, "Fragment program does not support signed Saturate.\n"); return; diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program.h b/src/mesa/drivers/dri/r300/compiler/radeon_program.h index df6c94b35f9..a07f6b63c6e 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_program.h +++ b/src/mesa/drivers/dri/r300/compiler/radeon_program.h @@ -56,11 +56,7 @@ struct rc_src_register { struct rc_dst_register { unsigned int File:3; - - /** Negative values may be used for relative addressing. */ - signed int Index:(RC_REGISTER_INDEX_BITS+1); - unsigned int RelAddr:1; - + unsigned int Index:RC_REGISTER_INDEX_BITS; unsigned int WriteMask:4; }; diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program_alu.c b/src/mesa/drivers/dri/r300/compiler/radeon_program_alu.c index c8063171b81..9fc991166a3 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_program_alu.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_program_alu.c @@ -91,7 +91,6 @@ static struct rc_dst_register dstregtmpmask(int index, int mask) dst.File = RC_FILE_TEMPORARY; dst.Index = index; dst.WriteMask = mask; - dst.RelAddr = 0; return dst; } diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.c b/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.c index 5905d26e521..68874795b8a 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.c @@ -211,27 +211,9 @@ struct rc_pair_instruction_source * rc_pair_get_src( struct rc_pair_instruction * pair_inst, struct rc_pair_instruction_arg * arg) { - unsigned int i, type; - unsigned int channels = 0; + unsigned int type; - for(i = 0; i < 3; i++) { - if (arg == pair_inst->RGB.Arg + i) { - channels = 3; - break; - } - } - - if (channels == 0) { - for (i = 0; i < 3; i++) { - if (arg == pair_inst->Alpha.Arg + i) { - channels = 1; - break; - } - } - } - - assert(channels > 0); - type = rc_source_type_swz(arg->Swizzle, channels); + type = rc_source_type_swz(arg->Swizzle); if (type & RC_SOURCE_RGB) { return &pair_inst->RGB.Src[arg->Source]; diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.h b/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.h index ccf7a0070cd..6708b16d29a 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.h +++ b/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.h @@ -63,7 +63,7 @@ struct rc_pair_instruction_source { struct rc_pair_instruction_arg { unsigned int Source:2; - unsigned int Swizzle:9; + unsigned int Swizzle:12; unsigned int Abs:1; unsigned int Negate:1; }; diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program_print.c b/src/mesa/drivers/dri/r300/compiler/radeon_program_print.c index ae13f6742f8..390d1319460 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_program_print.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_program_print.c @@ -110,7 +110,7 @@ static void rc_print_mask(FILE * f, unsigned int mask) static void rc_print_dst_register(FILE * f, struct rc_dst_register dst) { - rc_print_register(f, dst.File, dst.Index, dst.RelAddr); + rc_print_register(f, dst.File, dst.Index, 0); if (dst.WriteMask != RC_MASK_XYZW) { fprintf(f, "."); rc_print_mask(f, dst.WriteMask); @@ -379,7 +379,7 @@ static void rc_print_pair_instruction(FILE * f, struct rc_instruction * fullinst else fprintf(f,"%d", inst->Alpha.Arg[arg].Source); fprintf(f,".%c%s", - rc_swizzle_char(inst->Alpha.Arg[arg].Swizzle), abs); + rc_swizzle_char(GET_SWZ(inst->Alpha.Arg[arg].Swizzle, 0)), abs); } fprintf(f, "\n"); } diff --git a/src/mesa/drivers/dri/r300/r300_blit.c b/src/mesa/drivers/dri/r300/r300_blit.c index 9fd8e8fde5f..14e60866d93 100644 --- a/src/mesa/drivers/dri/r300/r300_blit.c +++ b/src/mesa/drivers/dri/r300/r300_blit.c @@ -63,7 +63,6 @@ static void create_vertex_program(struct r300_context *r300) inst->U.I.Opcode = RC_OPCODE_MOV; inst->U.I.DstReg.File = RC_FILE_OUTPUT; inst->U.I.DstReg.Index = VERT_RESULT_HPOS; - inst->U.I.DstReg.RelAddr = 0; inst->U.I.DstReg.WriteMask = RC_MASK_XYZW; inst->U.I.SrcReg[0].Abs = 0; inst->U.I.SrcReg[0].File = RC_FILE_INPUT; @@ -76,7 +75,6 @@ static void create_vertex_program(struct r300_context *r300) inst->U.I.Opcode = RC_OPCODE_MOV; inst->U.I.DstReg.File = RC_FILE_OUTPUT; inst->U.I.DstReg.Index = VERT_RESULT_TEX0; - inst->U.I.DstReg.RelAddr = 0; inst->U.I.DstReg.WriteMask = RC_MASK_XYZW; inst->U.I.SrcReg[0].Abs = 0; inst->U.I.SrcReg[0].File = RC_FILE_INPUT; @@ -131,6 +129,7 @@ static void create_fragment_program(struct r300_context *r300) compiler.Base.max_temp_regs = (compiler.Base.is_r500) ? 128 : 32; compiler.Base.max_constants = compiler.Base.is_r500 ? 256 : 32; compiler.Base.max_alu_insts = compiler.Base.is_r500 ? 512 : 64; + compiler.Base.max_tex_insts = compiler.Base.is_r500 ? 512 : 32; compiler.code = &r300->blit.fp_code; compiler.AllocateHwInputs = fp_allocate_hw_inputs; diff --git a/src/mesa/drivers/dri/r300/r300_fragprog_common.c b/src/mesa/drivers/dri/r300/r300_fragprog_common.c index 4e457b51eba..a0a26f1b38d 100644 --- a/src/mesa/drivers/dri/r300/r300_fragprog_common.c +++ b/src/mesa/drivers/dri/r300/r300_fragprog_common.c @@ -226,6 +226,7 @@ static void translate_fragment_program(struct gl_context *ctx, struct r300_fragm compiler.Base.max_temp_regs = (compiler.Base.is_r500) ? 128 : 32; compiler.Base.max_constants = compiler.Base.is_r500 ? 256 : 32; compiler.Base.max_alu_insts = compiler.Base.is_r500 ? 512 : 64; + compiler.Base.max_tex_insts = compiler.Base.is_r500 ? 512 : 32; compiler.OutputDepth = FRAG_RESULT_DEPTH; memset(compiler.OutputColor, 0, 4 * sizeof(unsigned)); compiler.OutputColor[0] = FRAG_RESULT_COLOR; diff --git a/src/mesa/drivers/dri/r300/r300_reg.h b/src/mesa/drivers/dri/r300/r300_reg.h index f7705b0f6fe..2b9d85fae8b 100644 --- a/src/mesa/drivers/dri/r300/r300_reg.h +++ b/src/mesa/drivers/dri/r300/r300_reg.h @@ -1658,6 +1658,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R300_PFS_CNTL_TEX_OFFSET_MASK (31 << 13) # define R300_PFS_CNTL_TEX_END_SHIFT 18 # define R300_PFS_CNTL_TEX_END_MASK (31 << 18) +# define R400_PFS_CNTL_TEX_OFFSET_MSB_SHIFT 24 +# define R400_PFS_CNTL_TEX_OFFSET_MSB_MASK (0xf << 24) +# define R400_PFS_CNTL_TEX_END_MSB_SHIFT 28 +# define R400_PFS_CNTL_TEX_END_MSB_MASK (0xf << 28) /* gap */ @@ -1682,6 +1686,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R300_TEX_SIZE_MASK (31 << 17) # define R300_RGBA_OUT (1 << 22) # define R300_W_OUT (1 << 23) +# define R400_TEX_START_MSB_SHIFT 24 +# define R400_TEX_START_MSG_MASK (0xf << 24) +# define R400_TEX_SIZE_MSB_SHIFT 28 +# define R400_TEX_SIZE_MSG_MASK (0xf << 28) /* TEX * As far as I can tell, texture instructions cannot write into output @@ -1702,6 +1710,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R300_TEX_OP_TXP 3 # define R300_TEX_OP_TXB 4 # define R300_TEX_INST_MASK (7 << 15) +# define R400_SRC_ADDR_EXT_BIT (1 << 19) +# define R400_DST_ADDR_EXT_BIT (1 << 20) /* Output format from the unfied shader */ #define R300_US_OUT_FMT 0x46A4 @@ -1979,6 +1989,40 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R300_ALU_OUTA_CLAMP (1 << 30) /* END: Fragment program instruction set */ +/* R4xx extended fragment shader registers. */ +#define R400_US_ALU_EXT_ADDR_0 0x4ac0 /* up to 63 (0x4bbc) */ +# define R400_ADDR_EXT_RGB_MSB_BIT(x) (1 << (x)) +# define R400_ADDRD_EXT_RGB_MSB_BIT 0x08 +# define R400_ADDR_EXT_A_MSB_BIT(x) (1 << ((x) + 4)) +# define R400_ADDRD_EXT_A_MSB_BIT 0x80 + +#define R400_US_CODE_BANK 0x46b8 +# define R400_BANK_SHIFT 0 +# define R400_BANK_MASK 0xf +# define R400_R390_MODE_ENABLE (1 << 4) +#define R400_US_CODE_EXT 0x46bc +# define R400_ALU_OFFSET_MSB_SHIFT 0 +# define R400_ALU_OFFSET_MSB_MASK (0x7 << 0) +# define R400_ALU_SIZE_MSB_SHIFT 3 +# define R400_ALU_SIZE_MSB_MASK (0x7 << 3) +# define R400_ALU_START0_MSB_SHIFT 6 +# define R400_ALU_START0_MSB_MASK (0x7 << 6) +# define R400_ALU_SIZE0_MSB_SHIFT 9 +# define R400_ALU_SIZE0_MSB_MASK (0x7 << 9) +# define R400_ALU_START1_MSB_SHIFT 12 +# define R400_ALU_START1_MSB_MASK (0x7 << 12) +# define R400_ALU_SIZE1_MSB_SHIFT 15 +# define R400_ALU_SIZE1_MSB_MASK (0x7 << 15) +# define R400_ALU_START2_MSB_SHIFT 18 +# define R400_ALU_START2_MSB_MASK (0x7 << 18) +# define R400_ALU_SIZE2_MSB_SHIFT 21 +# define R400_ALU_SIZE2_MSB_MASK (0x7 << 21) +# define R400_ALU_START3_MSB_SHIFT 24 +# define R400_ALU_START3_MSB_MASK (0x7 << 24) +# define R400_ALU_SIZE3_MSB_SHIFT 27 +# define R400_ALU_SIZE3_MSB_MASK (0x7 << 27) +/* END: R4xx extended fragment shader registers. */ + /* Fog: Fog Blending Enable */ #define R300_FG_FOG_BLEND 0x4bc0 # define R300_FG_FOG_BLEND_DISABLE (0 << 0) diff --git a/src/mesa/drivers/dri/r300/radeon_mesa_to_rc.c b/src/mesa/drivers/dri/r300/radeon_mesa_to_rc.c index 471a3723cb9..232603ece59 100644 --- a/src/mesa/drivers/dri/r300/radeon_mesa_to_rc.c +++ b/src/mesa/drivers/dri/r300/radeon_mesa_to_rc.c @@ -128,7 +128,6 @@ static void translate_dstreg(struct rc_dst_register * dest, struct prog_dst_regi { dest->File = translate_register_file(src->File); dest->Index = src->Index; - dest->RelAddr = src->RelAddr; dest->WriteMask = src->WriteMask; } diff --git a/src/mesa/drivers/dri/r600/evergreen_fragprog.c b/src/mesa/drivers/dri/r600/evergreen_fragprog.c index cfb923efdd5..e527c379b62 100644 --- a/src/mesa/drivers/dri/r600/evergreen_fragprog.c +++ b/src/mesa/drivers/dri/r600/evergreen_fragprog.c @@ -624,10 +624,7 @@ GLboolean evergreenSetupFragmentProgram(struct gl_context * ctx) SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, SEL_CENTROID_bit); SETfield(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, ui, SEMANTIC_shift, SEMANTIC_mask); - if (evergreen->SPI_INTERP_CONTROL_0.u32All & FLAT_SHADE_ENA_bit) - SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); - else - CLEARbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); + CLEARbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); } unBit = 1 << VERT_RESULT_COL0; @@ -663,10 +660,7 @@ GLboolean evergreenSetupFragmentProgram(struct gl_context * ctx) SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, SEL_CENTROID_bit); SETfield(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, ui, SEMANTIC_shift, SEMANTIC_mask); - if (evergreen->SPI_INTERP_CONTROL_0.u32All & FLAT_SHADE_ENA_bit) - SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); - else - CLEARbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); + CLEARbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); } for(i=0; i<8; i++) @@ -694,10 +688,7 @@ GLboolean evergreenSetupFragmentProgram(struct gl_context * ctx) SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, SEL_CENTROID_bit); SETfield(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, ui, SEMANTIC_shift, SEMANTIC_mask); - if (evergreen->SPI_INTERP_CONTROL_0.u32All & FLAT_SHADE_ENA_bit) - SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); - else - CLEARbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); + CLEARbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); } unBit = 1 << FRAG_ATTRIB_PNTC; if(mesa_fp->Base.InputsRead & unBit) @@ -706,10 +697,7 @@ GLboolean evergreenSetupFragmentProgram(struct gl_context * ctx) SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, SEL_CENTROID_bit); SETfield(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, ui, SEMANTIC_shift, SEMANTIC_mask); - if (evergreen->SPI_INTERP_CONTROL_0.u32All & FLAT_SHADE_ENA_bit) - SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); - else - CLEARbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); + CLEARbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, PT_SPRITE_TEX_bit); } @@ -725,10 +713,7 @@ GLboolean evergreenSetupFragmentProgram(struct gl_context * ctx) SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, SEL_CENTROID_bit); SETfield(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, ui, SEMANTIC_shift, SEMANTIC_mask); - if (evergreen->SPI_INTERP_CONTROL_0.u32All & FLAT_SHADE_ENA_bit) - SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); - else - CLEARbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); + CLEARbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); } } diff --git a/src/mesa/drivers/dri/r600/r700_fragprog.c b/src/mesa/drivers/dri/r600/r700_fragprog.c index 0323e32d705..40494cd6af0 100644 --- a/src/mesa/drivers/dri/r600/r700_fragprog.c +++ b/src/mesa/drivers/dri/r600/r700_fragprog.c @@ -657,10 +657,7 @@ GLboolean r700SetupFragmentProgram(struct gl_context * ctx) SETbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, SEL_CENTROID_bit); SETfield(r700->SPI_PS_INPUT_CNTL[ui].u32All, ui, SEMANTIC_shift, SEMANTIC_mask); - if (r700->SPI_INTERP_CONTROL_0.u32All & FLAT_SHADE_ENA_bit) - SETbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); - else - CLEARbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); + CLEARbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); } unBit = 1 << VERT_RESULT_COL0; @@ -696,10 +693,7 @@ GLboolean r700SetupFragmentProgram(struct gl_context * ctx) SETbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, SEL_CENTROID_bit); SETfield(r700->SPI_PS_INPUT_CNTL[ui].u32All, ui, SEMANTIC_shift, SEMANTIC_mask); - if (r700->SPI_INTERP_CONTROL_0.u32All & FLAT_SHADE_ENA_bit) - SETbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); - else - CLEARbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); + CLEARbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); } for(i=0; i<8; i++) @@ -728,10 +722,7 @@ GLboolean r700SetupFragmentProgram(struct gl_context * ctx) SETbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, SEL_CENTROID_bit); SETfield(r700->SPI_PS_INPUT_CNTL[ui].u32All, ui, SEMANTIC_shift, SEMANTIC_mask); - if (r700->SPI_INTERP_CONTROL_0.u32All & FLAT_SHADE_ENA_bit) - SETbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); - else - CLEARbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); + CLEARbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); } unBit = 1 << FRAG_ATTRIB_PNTC; if(mesa_fp->Base.InputsRead & unBit) @@ -759,10 +750,7 @@ GLboolean r700SetupFragmentProgram(struct gl_context * ctx) SETbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, SEL_CENTROID_bit); SETfield(r700->SPI_PS_INPUT_CNTL[ui].u32All, ui, SEMANTIC_shift, SEMANTIC_mask); - if (r700->SPI_INTERP_CONTROL_0.u32All & FLAT_SHADE_ENA_bit) - SETbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); - else - CLEARbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); + CLEARbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); } } diff --git a/src/mesa/drivers/dri/radeon/radeon_chipset.h b/src/mesa/drivers/dri/radeon/radeon_chipset.h index 399052cbcbd..bd6f1c79504 100644 --- a/src/mesa/drivers/dri/radeon/radeon_chipset.h +++ b/src/mesa/drivers/dri/radeon/radeon_chipset.h @@ -34,7 +34,6 @@ #define PCI_CHIP_RV350_AV 0x4156 #define PCI_CHIP_RS250_4237 0x4237 #define PCI_CHIP_R200_BB 0x4242 -#define PCI_CHIP_R200_BC 0x4243 #define PCI_CHIP_RS100_4336 0x4336 #define PCI_CHIP_RS200_4337 0x4337 #define PCI_CHIP_RS250_4437 0x4437 diff --git a/src/mesa/drivers/dri/radeon/radeon_common.c b/src/mesa/drivers/dri/radeon/radeon_common.c index 7361adffcf7..0d73c0e3b1b 100644 --- a/src/mesa/drivers/dri/radeon/radeon_common.c +++ b/src/mesa/drivers/dri/radeon/radeon_common.c @@ -905,7 +905,7 @@ void radeon_viewport(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GL if (!driContext->driScreenPriv->dri2.enabled) return; - if (!radeon->meta.internal_viewport_call && ctx->DrawBuffer->Name == 0) { + if (ctx->DrawBuffer->Name == 0) { if (radeon->is_front_buffer_rendering) { ctx->Driver.Flush(ctx); } diff --git a/src/mesa/drivers/dri/radeon/radeon_common_context.c b/src/mesa/drivers/dri/radeon/radeon_common_context.c index 819d9dd5750..405aecb19ec 100644 --- a/src/mesa/drivers/dri/radeon/radeon_common_context.c +++ b/src/mesa/drivers/dri/radeon/radeon_common_context.c @@ -204,7 +204,7 @@ GLboolean radeonInitContext(radeonContextPtr radeon, shareCtx = ((radeonContextPtr)sharedContextPrivate)->glCtx; else shareCtx = NULL; - radeon->glCtx = _mesa_create_context(glVisual, shareCtx, + radeon->glCtx = _mesa_create_context(API_OPENGL, glVisual, shareCtx, functions, (void *)radeon); if (!radeon->glCtx) return GL_FALSE; @@ -212,8 +212,6 @@ GLboolean radeonInitContext(radeonContextPtr radeon, ctx = radeon->glCtx; driContextPriv->driverPrivate = radeon; - meta_init_metaops(ctx, &radeon->meta); - _mesa_meta_init(ctx); /* DRI fields */ @@ -320,7 +318,6 @@ void radeonDestroyContext(__DRIcontext *driContextPriv ) radeonFreeDmaRegions(radeon); radeonReleaseArrays(radeon->glCtx, ~0); - meta_destroy_metaops(&radeon->meta); if (radeon->vtbl.free_context) radeon->vtbl.free_context(radeon->glCtx); _swsetup_DestroyContext( radeon->glCtx ); diff --git a/src/mesa/drivers/dri/radeon/radeon_common_context.h b/src/mesa/drivers/dri/radeon/radeon_common_context.h index c62913afd0c..3895ab8c4d8 100644 --- a/src/mesa/drivers/dri/radeon/radeon_common_context.h +++ b/src/mesa/drivers/dri/radeon/radeon_common_context.h @@ -14,7 +14,6 @@ #include "dri_util.h" #include "tnl/t_vertex.h" -#include "dri_metaops.h" struct radeon_context; #include "radeon_bocs_wrapper.h" @@ -509,8 +508,6 @@ struct radeon_context { */ GLboolean is_front_buffer_reading; - struct dri_metaops meta; - struct { struct radeon_query_object *current; struct radeon_state_atom queryobj; diff --git a/src/mesa/drivers/dri/radeon/radeon_fbo.c b/src/mesa/drivers/dri/radeon/radeon_fbo.c index 6656d391e09..d3c9257fb66 100644 --- a/src/mesa/drivers/dri/radeon/radeon_fbo.c +++ b/src/mesa/drivers/dri/radeon/radeon_fbo.c @@ -485,6 +485,8 @@ radeon_update_wrapper(struct gl_context *ctx, struct radeon_renderbuffer *rrb, case MESA_FORMAT_S8_Z24: rrb->base.DataType = GL_UNSIGNED_INT_24_8_EXT; break; + default: + _mesa_problem(ctx, "Unexpected texture format in radeon_update_wrapper()"); } rrb->cpp = _mesa_get_format_bytes(texImage->TexFormat); diff --git a/src/mesa/drivers/dri/radeon/radeon_screen.c b/src/mesa/drivers/dri/radeon/radeon_screen.c index a35fcfe9d7f..56c5959b0aa 100644 --- a/src/mesa/drivers/dri/radeon/radeon_screen.c +++ b/src/mesa/drivers/dri/radeon/radeon_screen.c @@ -628,7 +628,6 @@ static int radeon_set_screen_flags(radeonScreenPtr screen, int device_id) break; case PCI_CHIP_R200_BB: - case PCI_CHIP_R200_BC: case PCI_CHIP_R200_QH: case PCI_CHIP_R200_QL: case PCI_CHIP_R200_QM: diff --git a/src/mesa/drivers/dri/savage/savage_xmesa.c b/src/mesa/drivers/dri/savage/savage_xmesa.c index 92fb4f44884..681ed9aae34 100644 --- a/src/mesa/drivers/dri/savage/savage_xmesa.c +++ b/src/mesa/drivers/dri/savage/savage_xmesa.c @@ -314,7 +314,7 @@ savageCreateContext( gl_api api, shareCtx = ((savageContextPtr) sharedContextPrivate)->glCtx; else shareCtx = NULL; - ctx = _mesa_create_context(mesaVis, shareCtx, &functions, imesa); + ctx = _mesa_create_context(api, mesaVis, shareCtx, &functions, imesa); if (!ctx) { free(imesa); return GL_FALSE; diff --git a/src/mesa/drivers/dri/sis/sis_context.c b/src/mesa/drivers/dri/sis/sis_context.c index c5a9fdfb2a0..26ecfc463ca 100644 --- a/src/mesa/drivers/dri/sis/sis_context.c +++ b/src/mesa/drivers/dri/sis/sis_context.c @@ -186,7 +186,7 @@ sisCreateContext( gl_api api, shareCtx = ((sisContextPtr)sharedContextPrivate)->glCtx; else shareCtx = NULL; - smesa->glCtx = _mesa_create_context( glVisual, shareCtx, + smesa->glCtx = _mesa_create_context( API_OPENGL, glVisual, shareCtx, &functions, (void *) smesa); if (!smesa->glCtx) { FREE(smesa); diff --git a/src/mesa/drivers/dri/swrast/swrast.c b/src/mesa/drivers/dri/swrast/swrast.c index c7940e9c0da..719b406ec05 100644 --- a/src/mesa/drivers/dri/swrast/swrast.c +++ b/src/mesa/drivers/dri/swrast/swrast.c @@ -561,6 +561,60 @@ swrast_init_driver_functions(struct dd_function_table *driver) driver->ChooseTextureFormat = swrastChooseTextureFormat; } +static const char *es2_extensions[] = { + /* Used by mesa internally (cf all_mesa_extensions in ../common/utils.c) */ + "GL_ARB_draw_buffers", + "GL_ARB_multisample", + "GL_ARB_texture_compression", + "GL_ARB_transpose_matrix", + "GL_ARB_vertex_buffer_object", + "GL_ARB_window_pos", + "GL_EXT_blend_func_separate", + "GL_EXT_compiled_vertex_array", + "GL_EXT_framebuffer_blit", + "GL_EXT_multi_draw_arrays", + "GL_EXT_polygon_offset", + "GL_EXT_texture_object", + "GL_EXT_vertex_array", + "GL_IBM_multimode_draw_arrays", + "GL_MESA_window_pos", + "GL_NV_vertex_program", + + /* Required by GLES2 */ + "GL_ARB_fragment_program", + "GL_ARB_fragment_shader", + "GL_ARB_multitexture", + "GL_ARB_shader_objects", + "GL_ARB_texture_cube_map", + "GL_ARB_texture_mirrored_repeat", + "GL_ARB_texture_non_power_of_two", + "GL_ARB_vertex_shader", + "GL_EXT_blend_color", + "GL_EXT_blend_equation_separate", + "GL_EXT_blend_minmax", + "GL_EXT_blend_subtract", + "GL_EXT_stencil_wrap", + + /* Optional GLES2 */ + "GL_ARB_framebuffer_object", + "GL_EXT_texture_filter_anisotropic", + "GL_ARB_depth_texture", + "GL_EXT_packed_depth_stencil", + "GL_EXT_framebuffer_object", + NULL, +}; + +static void +InitExtensionsES2(struct gl_context *ctx) +{ + int i; + + /* Can't use driInitExtensions() since it uses extensions from + * main/remap_helper.h when called the first time. */ + + for (i = 0; es2_extensions[i]; i++) + _mesa_enable_extension(ctx, es2_extensions[i]); +} /** * Context-related functions. @@ -597,7 +651,7 @@ dri_create_context(gl_api api, mesaCtx = &ctx->Base; /* basic context setup */ - if (!_mesa_initialize_context(mesaCtx, visual, sharedCtx, &functions, (void *) cPriv)) { + if (!_mesa_initialize_context(mesaCtx, api, visual, sharedCtx, &functions, (void *) cPriv)) { goto context_fail; } @@ -617,16 +671,29 @@ dri_create_context(gl_api api, tnl->Driver.RunPipeline = _tnl_run_pipeline; } - _mesa_enable_sw_extensions(mesaCtx); - _mesa_enable_1_3_extensions(mesaCtx); - _mesa_enable_1_4_extensions(mesaCtx); - _mesa_enable_1_5_extensions(mesaCtx); - _mesa_enable_2_0_extensions(mesaCtx); - _mesa_enable_2_1_extensions(mesaCtx); - _mesa_meta_init(mesaCtx); + _mesa_enable_sw_extensions(mesaCtx); - driInitExtensions( mesaCtx, NULL, GL_FALSE ); + switch (api) { + case API_OPENGL: + _mesa_enable_1_3_extensions(mesaCtx); + _mesa_enable_1_4_extensions(mesaCtx); + _mesa_enable_1_5_extensions(mesaCtx); + _mesa_enable_2_0_extensions(mesaCtx); + _mesa_enable_2_1_extensions(mesaCtx); + + driInitExtensions( mesaCtx, NULL, GL_FALSE ); + break; + case API_OPENGLES: + _mesa_enable_1_3_extensions(mesaCtx); + _mesa_enable_1_4_extensions(mesaCtx); + _mesa_enable_1_5_extensions(mesaCtx); + + break; + case API_OPENGLES2: + InitExtensionsES2( mesaCtx); + break; + } return GL_TRUE; diff --git a/src/mesa/drivers/dri/tdfx/tdfx_context.c b/src/mesa/drivers/dri/tdfx/tdfx_context.c index 63dfa5ae746..ad151359e67 100644 --- a/src/mesa/drivers/dri/tdfx/tdfx_context.c +++ b/src/mesa/drivers/dri/tdfx/tdfx_context.c @@ -194,7 +194,7 @@ GLboolean tdfxCreateContext( gl_api api, else shareCtx = NULL; - fxMesa->glCtx = _mesa_create_context(mesaVis, shareCtx, + fxMesa->glCtx = _mesa_create_context(api, mesaVis, shareCtx, &functions, (void *) fxMesa); if (!fxMesa->glCtx) { FREE(fxMesa); diff --git a/src/mesa/drivers/dri/unichrome/via_context.c b/src/mesa/drivers/dri/unichrome/via_context.c index 963609bde4a..77d7116611a 100644 --- a/src/mesa/drivers/dri/unichrome/via_context.c +++ b/src/mesa/drivers/dri/unichrome/via_context.c @@ -542,7 +542,7 @@ viaCreateContext(gl_api api, else shareCtx = NULL; - vmesa->glCtx = _mesa_create_context(visual, shareCtx, &functions, + vmesa->glCtx = _mesa_create_context(API_OPENGL, visual, shareCtx, &functions, (void*) vmesa); vmesa->shareCtx = shareCtx; diff --git a/src/mesa/drivers/fbdev/glfbdev.c b/src/mesa/drivers/fbdev/glfbdev.c index 5195bca97fa..1e0ac4c7a1f 100644 --- a/src/mesa/drivers/fbdev/glfbdev.c +++ b/src/mesa/drivers/fbdev/glfbdev.c @@ -722,7 +722,7 @@ glFBDevCreateContext( const GLFBDevVisualPtr visual, GLFBDevContextPtr share ) functions.GetBufferSize = get_buffer_size; functions.Viewport = viewport; - if (!_mesa_initialize_context(&ctx->glcontext, &visual->glvisual, + if (!_mesa_initialize_context(&ctx->glcontext, API_OPENGL, &visual->glvisual, share ? &share->glcontext : NULL, &functions, (void *) ctx)) { free(ctx); diff --git a/src/mesa/drivers/osmesa/Makefile b/src/mesa/drivers/osmesa/Makefile index 50dd4526e19..39ab09af805 100644 --- a/src/mesa/drivers/osmesa/Makefile +++ b/src/mesa/drivers/osmesa/Makefile @@ -40,7 +40,7 @@ $(TOP)/$(LIB_DIR)/$(OSMESA_LIB_NAME): $(OBJECTS) $(CORE_MESA) -major $(MESA_MAJOR) -minor $(MESA_MINOR) -patch $(MESA_TINY) \ -install $(TOP)/$(LIB_DIR) -cplusplus $(MKLIB_OPTIONS) \ -id $(INSTALL_LIB_DIR)/lib$(OSMESA_LIB).$(MESA_MAJOR).dylib \ - $(OSMESA_LIB_DEPS) $(OBJECTS) $(CORE_MESA) $(TALLOC_LIBS) + $(OSMESA_LIB_DEPS) $(OBJECTS) $(CORE_MESA) diff --git a/src/mesa/drivers/osmesa/osmesa.c b/src/mesa/drivers/osmesa/osmesa.c index e1f0c69bacf..98f01fe057e 100644 --- a/src/mesa/drivers/osmesa/osmesa.c +++ b/src/mesa/drivers/osmesa/osmesa.c @@ -1155,6 +1155,7 @@ OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits, functions.GetBufferSize = NULL; if (!_mesa_initialize_context(&osmesa->mesa, + API_OPENGL, osmesa->gl_visual, sharelist ? &sharelist->mesa : (struct gl_context *) NULL, diff --git a/src/mesa/drivers/windows/gdi/wmesa.c b/src/mesa/drivers/windows/gdi/wmesa.c index 833e2526f3c..4a8b1b283d5 100644 --- a/src/mesa/drivers/windows/gdi/wmesa.c +++ b/src/mesa/drivers/windows/gdi/wmesa.c @@ -1479,7 +1479,8 @@ WMesaContext WMesaCreateContext(HDC hDC, /* initialize the Mesa context data */ ctx = &c->gl_ctx; - _mesa_initialize_context(ctx, visual, NULL, &functions, (void *)c); + _mesa_initialize_context(ctx, API_OPENGL, visual, + NULL, &functions, (void *)c); /* visual no longer needed - it was copied by _mesa_initialize_context() */ _mesa_destroy_visual(visual); diff --git a/src/mesa/drivers/windows/gldirect/dglcontext.c b/src/mesa/drivers/windows/gldirect/dglcontext.c index 10ea0578506..9aedd2e3c4d 100644 --- a/src/mesa/drivers/windows/gldirect/dglcontext.c +++ b/src/mesa/drivers/windows/gldirect/dglcontext.c @@ -1414,7 +1414,7 @@ SkipPrimaryCreate: } #ifdef _USE_GLD3_WGL - lpCtx->glCtx = _mesa_create_context(lpCtx->glVis, NULL, (void *)lpCtx, GL_TRUE); + lpCtx->glCtx = _mesa_create_context(API_OPENGL, lpCtx->glVis, NULL, (void *)lpCtx, GL_TRUE); #else // Create the Mesa context lpCtx->glCtx = (*mesaFuncs.gl_create_context)( diff --git a/src/mesa/drivers/windows/gldirect/dx7/gld_driver_dx7.c b/src/mesa/drivers/windows/gldirect/dx7/gld_driver_dx7.c index 1c43a38557d..1b070f0a11e 100644 --- a/src/mesa/drivers/windows/gldirect/dx7/gld_driver_dx7.c +++ b/src/mesa/drivers/windows/gldirect/dx7/gld_driver_dx7.c @@ -944,7 +944,6 @@ void gld_update_state_DX7( // Stubs for future use. /* _GLD_TEST_STATE(_NEW_TEXTURE_MATRIX); _GLD_TEST_STATE(_NEW_COLOR_MATRIX); - _GLD_TEST_STATE(_NEW_ACCUM); _GLD_TEST_STATE(_NEW_EVAL); _GLD_TEST_STATE(_NEW_HINT); _GLD_TEST_STATE(_NEW_LINE); @@ -967,7 +966,6 @@ void gld_update_state_DX7( } _GLD_TEST_UNHANDLED_STATE(_NEW_TEXTURE_MATRIX); _GLD_TEST_UNHANDLED_STATE(_NEW_COLOR_MATRIX); - _GLD_TEST_UNHANDLED_STATE(_NEW_ACCUM); _GLD_TEST_UNHANDLED_STATE(_NEW_EVAL); _GLD_TEST_UNHANDLED_STATE(_NEW_HINT); _GLD_TEST_UNHANDLED_STATE(_NEW_LINE); diff --git a/src/mesa/drivers/windows/gldirect/dx7/gld_primitive_dx7.c b/src/mesa/drivers/windows/gldirect/dx7/gld_primitive_dx7.c index 7fc50004de8..d66318e1149 100644 --- a/src/mesa/drivers/windows/gldirect/dx7/gld_primitive_dx7.c +++ b/src/mesa/drivers/windows/gldirect/dx7/gld_primitive_dx7.c @@ -62,7 +62,6 @@ #include "swrast/s_depth.h" #include "swrast/s_lines.h" #include "swrast/s_triangle.h" -#include "swrast/s_trispan.h" #include "tnl/tnl.h" #include "tnl/t_context.h" #include "tnl/t_pipeline.h" diff --git a/src/mesa/drivers/windows/gldirect/dx8/gld_driver_dx8.c b/src/mesa/drivers/windows/gldirect/dx8/gld_driver_dx8.c index c4c2e0b5676..4c272c95d6c 100644 --- a/src/mesa/drivers/windows/gldirect/dx8/gld_driver_dx8.c +++ b/src/mesa/drivers/windows/gldirect/dx8/gld_driver_dx8.c @@ -924,7 +924,6 @@ void gld_update_state_DX8( // Stubs for future use. /* _GLD_TEST_STATE(_NEW_TEXTURE_MATRIX); _GLD_TEST_STATE(_NEW_COLOR_MATRIX); - _GLD_TEST_STATE(_NEW_ACCUM); _GLD_TEST_STATE(_NEW_EVAL); _GLD_TEST_STATE(_NEW_HINT); _GLD_TEST_STATE(_NEW_LINE); @@ -947,7 +946,6 @@ void gld_update_state_DX8( } _GLD_TEST_UNHANDLED_STATE(_NEW_TEXTURE_MATRIX); _GLD_TEST_UNHANDLED_STATE(_NEW_COLOR_MATRIX); - _GLD_TEST_UNHANDLED_STATE(_NEW_ACCUM); _GLD_TEST_UNHANDLED_STATE(_NEW_EVAL); _GLD_TEST_UNHANDLED_STATE(_NEW_HINT); _GLD_TEST_UNHANDLED_STATE(_NEW_LINE); diff --git a/src/mesa/drivers/windows/gldirect/dx8/gld_primitive_dx8.c b/src/mesa/drivers/windows/gldirect/dx8/gld_primitive_dx8.c index 5b9dac09c6d..a2c5d87ecd5 100644 --- a/src/mesa/drivers/windows/gldirect/dx8/gld_primitive_dx8.c +++ b/src/mesa/drivers/windows/gldirect/dx8/gld_primitive_dx8.c @@ -62,7 +62,6 @@ #include "swrast/s_depth.h" #include "swrast/s_lines.h" #include "swrast/s_triangle.h" -#include "swrast/s_trispan.h" #include "tnl/tnl.h" #include "tnl/t_context.h" #include "tnl/t_pipeline.h" diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_driver_dx9.c b/src/mesa/drivers/windows/gldirect/dx9/gld_driver_dx9.c index aab70852016..171585dcf81 100644 --- a/src/mesa/drivers/windows/gldirect/dx9/gld_driver_dx9.c +++ b/src/mesa/drivers/windows/gldirect/dx9/gld_driver_dx9.c @@ -955,7 +955,6 @@ void gld_update_state_DX9( // Stubs for future use. /* _GLD_TEST_STATE(_NEW_TEXTURE_MATRIX); _GLD_TEST_STATE(_NEW_COLOR_MATRIX); - _GLD_TEST_STATE(_NEW_ACCUM); _GLD_TEST_STATE(_NEW_EVAL); _GLD_TEST_STATE(_NEW_HINT); _GLD_TEST_STATE(_NEW_LINE); @@ -977,7 +976,6 @@ void gld_update_state_DX9( } _GLD_TEST_UNHANDLED_STATE(_NEW_TEXTURE_MATRIX); _GLD_TEST_UNHANDLED_STATE(_NEW_COLOR_MATRIX); - _GLD_TEST_UNHANDLED_STATE(_NEW_ACCUM); _GLD_TEST_UNHANDLED_STATE(_NEW_EVAL); _GLD_TEST_UNHANDLED_STATE(_NEW_HINT); _GLD_TEST_UNHANDLED_STATE(_NEW_LINE); diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_primitive_dx9.c b/src/mesa/drivers/windows/gldirect/dx9/gld_primitive_dx9.c index 99edd26e9d2..65a00ae1b59 100644 --- a/src/mesa/drivers/windows/gldirect/dx9/gld_primitive_dx9.c +++ b/src/mesa/drivers/windows/gldirect/dx9/gld_primitive_dx9.c @@ -62,7 +62,6 @@ #include "swrast/s_depth.h" #include "swrast/s_lines.h" #include "swrast/s_triangle.h" -#include "swrast/s_trispan.h" #include "tnl/tnl.h" #include "tnl/t_context.h" #include "tnl/t_pipeline.h" diff --git a/src/mesa/drivers/windows/gldirect/mesasw/gld_wgl_mesasw.c b/src/mesa/drivers/windows/gldirect/mesasw/gld_wgl_mesasw.c index 7a26df8071e..bc66ec79888 100644 --- a/src/mesa/drivers/windows/gldirect/mesasw/gld_wgl_mesasw.c +++ b/src/mesa/drivers/windows/gldirect/mesasw/gld_wgl_mesasw.c @@ -61,7 +61,6 @@ #include "swrast/s_depth.h" #include "swrast/s_lines.h" #include "swrast/s_triangle.h" -#include "swrast/s_trispan.h" #include "tnl/tnl.h" #include "tnl/t_context.h" #include "tnl/t_pipeline.h" diff --git a/src/mesa/drivers/x11/fakeglx.c b/src/mesa/drivers/x11/fakeglx.c index 577e27d4da3..48657b44be1 100644 --- a/src/mesa/drivers/x11/fakeglx.c +++ b/src/mesa/drivers/x11/fakeglx.c @@ -1292,7 +1292,7 @@ Fake_glXCreateContext( Display *dpy, XVisualInfo *visinfo, /* deallocate unused windows/buffers */ #if 0 - XMesaGarbageCollect(); + XMesaGarbageCollect(dpy); #endif xmvis = find_glx_visual( dpy, visinfo ); @@ -1533,7 +1533,7 @@ Fake_glXDestroyContext( Display *dpy, GLXContext ctx ) MakeCurrent_PrevDrawBuffer = 0; MakeCurrent_PrevReadBuffer = 0; XMesaDestroyContext( glxCtx->xmesaContext ); - XMesaGarbageCollect(); + XMesaGarbageCollect(dpy); free(glxCtx); } @@ -2327,7 +2327,7 @@ Fake_glXCreateNewContext( Display *dpy, GLXFBConfig config, return 0; /* deallocate unused windows/buffers */ - XMesaGarbageCollect(); + XMesaGarbageCollect(dpy); glxCtx->xmesaContext = XMesaCreateContext(xmvis, shareCtx ? shareCtx->xmesaContext : NULL); @@ -2542,7 +2542,7 @@ Fake_glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, int re return 0; /* deallocate unused windows/buffers */ - XMesaGarbageCollect(); + XMesaGarbageCollect(dpy); glxCtx->xmesaContext = XMesaCreateContext(xmvis, shareCtx ? shareCtx->xmesaContext : NULL); diff --git a/src/mesa/drivers/x11/xm_api.c b/src/mesa/drivers/x11/xm_api.c index b5eabadf486..aad902d1eda 100644 --- a/src/mesa/drivers/x11/xm_api.c +++ b/src/mesa/drivers/x11/xm_api.c @@ -1398,7 +1398,7 @@ XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list ) /* initialize with default driver functions, then plug in XMesa funcs */ _mesa_init_driver_functions(&functions); xmesa_init_driver_functions(v, &functions); - if (!_mesa_initialize_context(mesaCtx, &v->mesa_visual, + if (!_mesa_initialize_context(mesaCtx, API_OPENGL, &v->mesa_visual, share_list ? &(share_list->mesa) : (struct gl_context *) NULL, &functions, (void *) c)) { free(c); @@ -2064,12 +2064,12 @@ void xmesa_destroy_buffers_on_display(XMesaDisplay *dpy) * Look for XMesaBuffers whose X window has been destroyed. * Deallocate any such XMesaBuffers. */ -void XMesaGarbageCollect( void ) +void XMesaGarbageCollect( XMesaDisplay* dpy ) { XMesaBuffer b, next; for (b=XMesaBufferList; b; b=next) { next = b->Next; - if (b->display && b->frontxrb->drawable && b->type == WINDOW) { + if (b->display && b->display == dpy && b->frontxrb->drawable && b->type == WINDOW) { XSync(b->display, False); if (!window_exists( b->display, b->frontxrb->drawable )) { /* found a dead window, free the ancillary info */ diff --git a/src/mesa/drivers/x11/xmesa.h b/src/mesa/drivers/x11/xmesa.h index 98737fab248..347394e0a26 100644 --- a/src/mesa/drivers/x11/xmesa.h +++ b/src/mesa/drivers/x11/xmesa.h @@ -324,7 +324,7 @@ extern const char *XMesaGetString( XMesaContext c, int name ); * * New in Mesa 2.3. */ -extern void XMesaGarbageCollect( void ); +extern void XMesaGarbageCollect( XMesaDisplay* dpy ); diff --git a/src/mesa/main/APIspec.xml b/src/mesa/main/APIspec.xml index 50446a9093a..0f82d0a38e1 100644 --- a/src/mesa/main/APIspec.xml +++ b/src/mesa/main/APIspec.xml @@ -379,15 +379,68 @@ <value name="GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES" category="OES_texture_cube_map"/> </desc> - <desc name="internalFormat" error="GL_INVALID_VALUE"> + <desc name="internalFormat"> <value name="GL_ALPHA"/> + + <desc name="format" error="GL_INVALID_VALUE"> + <value name="GL_ALPHA"/> + </desc> + </desc> + + <desc name="internalFormat"> <value name="GL_RGB"/> + + <desc name="format" error="GL_INVALID_VALUE"> + <value name="GL_RGB"/> + </desc> + </desc> + + <desc name="internalFormat"> <value name="GL_RGBA"/> - <value name="GL_BGRA_EXT"/> + + <desc name="format" error="GL_INVALID_VALUE"> + <value name="GL_RGBA"/> + </desc> + </desc> + + <desc name="internalFormat"> <value name="GL_LUMINANCE"/> + + <desc name="format" error="GL_INVALID_VALUE"> + <value name="GL_LUMINANCE"/> + </desc> + </desc> + + <desc name="internalFormat"> <value name="GL_LUMINANCE_ALPHA"/> - <value name="GL_DEPTH_COMPONENT" category="OES_depth_texture"/> - <value name="GL_DEPTH_STENCIL_OES" category="OES_packed_depth_stencil"/> + + <desc name="format" error="GL_INVALID_VALUE"> + <value name="GL_LUMINANCE_ALPHA"/> + </desc> + </desc> + + <desc name="internalFormat" category="OES_depth_texture"> + <value name="GL_DEPTH_COMPONENT"/> + + <desc name="format" error="GL_INVALID_VALUE"> + <value name="GL_DEPTH_COMPONENT"/> + </desc> + </desc> + + <desc name="internalFormat" category="OES_packed_depth_stencil"> + <value name="GL_DEPTH_STENCIL_OES"/> + + <desc name="format" error="GL_INVALID_VALUE"> + <value name="GL_DEPTH_STENCIL_OES"/> + </desc> + </desc> + + <desc name="internalFormat" category="EXT_texture_format_BGRA8888"> + <value name="GL_BGRA_EXT"/> + + <desc name="format" error="GL_INVALID_VALUE"> + <value name="GL_BGRA_EXT"/> + </desc> </desc> <desc name="border" error="GL_INVALID_VALUE"> diff --git a/src/mesa/main/accum.c b/src/mesa/main/accum.c index 940f398f023..6a83930a13d 100644 --- a/src/mesa/main/accum.c +++ b/src/mesa/main/accum.c @@ -51,7 +51,6 @@ _mesa_ClearAccum( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha ) if (TEST_EQ_4V(tmp, ctx->Accum.ClearColor)) return; - FLUSH_VERTICES(ctx, _NEW_ACCUM); COPY_4FV( ctx->Accum.ClearColor, tmp ); } diff --git a/src/mesa/main/arrayobj.c b/src/mesa/main/arrayobj.c index 9e9728c2c62..46010223370 100644 --- a/src/mesa/main/arrayobj.c +++ b/src/mesa/main/arrayobj.c @@ -234,7 +234,7 @@ _mesa_initialize_array_object( struct gl_context *ctx, init_array(ctx, &obj->Weight, 1, GL_FLOAT); init_array(ctx, &obj->Normal, 3, GL_FLOAT); init_array(ctx, &obj->Color, 4, GL_FLOAT); - init_array(ctx, &obj->SecondaryColor, 4, GL_FLOAT); + init_array(ctx, &obj->SecondaryColor, 3, GL_FLOAT); init_array(ctx, &obj->FogCoord, 1, GL_FLOAT); init_array(ctx, &obj->Index, 1, GL_FLOAT); for (i = 0; i < Elements(obj->TexCoord); i++) { diff --git a/src/mesa/main/blend.c b/src/mesa/main/blend.c index 43e2f7f8617..c74a168036a 100644 --- a/src/mesa/main/blend.c +++ b/src/mesa/main/blend.c @@ -317,7 +317,7 @@ _mesa_BlendEquation( GLenum mode ) ASSERT_OUTSIDE_BEGIN_END(ctx); if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glBlendEquation %s\n", + _mesa_debug(ctx, "glBlendEquation(%s)\n", _mesa_lookup_enum_by_nr(mode)); if (!legal_blend_equation(ctx, mode, GL_FALSE)) { @@ -398,7 +398,7 @@ _mesa_BlendEquationSeparateEXT( GLenum modeRGB, GLenum modeA ) ASSERT_OUTSIDE_BEGIN_END(ctx); if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glBlendEquationSeparateEXT %s %s\n", + _mesa_debug(ctx, "glBlendEquationSeparateEXT(%s %s)\n", _mesa_lookup_enum_by_nr(modeRGB), _mesa_lookup_enum_by_nr(modeA)); @@ -454,7 +454,7 @@ _mesa_BlendEquationSeparatei(GLuint buf, GLenum modeRGB, GLenum modeA) ASSERT_OUTSIDE_BEGIN_END(ctx); if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glBlendEquationSeparatei %u, %s %s\n", buf, + _mesa_debug(ctx, "glBlendEquationSeparatei(%u, %s %s)\n", buf, _mesa_lookup_enum_by_nr(modeRGB), _mesa_lookup_enum_by_nr(modeA)); @@ -545,6 +545,10 @@ _mesa_AlphaFunc( GLenum func, GLclampf ref ) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glAlphaFunc(%s, %f)\n", + _mesa_lookup_enum_by_nr(func), ref); + switch (func) { case GL_NEVER: case GL_LESS: @@ -590,6 +594,9 @@ _mesa_LogicOp( GLenum opcode ) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glLogicOp(%s)\n", _mesa_lookup_enum_by_nr(opcode)); + switch (opcode) { case GL_CLEAR: case GL_SET: @@ -664,7 +671,8 @@ _mesa_ColorMask( GLboolean red, GLboolean green, ASSERT_OUTSIDE_BEGIN_END(ctx); if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glColorMask %d %d %d %d\n", red, green, blue, alpha); + _mesa_debug(ctx, "glColorMask(%d, %d, %d, %d)\n", + red, green, blue, alpha); /* Shouldn't have any information about channel depth in core mesa * -- should probably store these as the native booleans: diff --git a/src/mesa/main/bufferobj.c b/src/mesa/main/bufferobj.c index 1f9a5212c04..75afae0add1 100644 --- a/src/mesa/main/bufferobj.c +++ b/src/mesa/main/bufferobj.c @@ -970,6 +970,10 @@ _mesa_BindBufferARB(GLenum target, GLuint buffer) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glBindBuffer(%s, %u)\n", + _mesa_lookup_enum_by_nr(target), buffer); + bind_buffer_object(ctx, target, buffer); } @@ -1064,6 +1068,9 @@ _mesa_GenBuffersARB(GLsizei n, GLuint *buffer) GLint i; ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glGenBuffers(%d)\n", n); + if (n < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glGenBuffersARB"); return; @@ -1121,6 +1128,12 @@ _mesa_BufferDataARB(GLenum target, GLsizeiptrARB size, struct gl_buffer_object *bufObj; ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glBufferData(%s, %ld, %p, %s)\n", + _mesa_lookup_enum_by_nr(target), + (long int) size, data, + _mesa_lookup_enum_by_nr(usage)); + if (size < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glBufferDataARB(size < 0)"); return; diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c index e017939a45c..a942314552e 100644 --- a/src/mesa/main/context.c +++ b/src/mesa/main/context.c @@ -886,12 +886,12 @@ _mesa_alloc_dispatch_table(int size) * \param driverContext pointer to driver-specific context data */ GLboolean -_mesa_initialize_context_for_api(struct gl_context *ctx, - gl_api api, - const struct gl_config *visual, - struct gl_context *share_list, - const struct dd_function_table *driverFunctions, - void *driverContext) +_mesa_initialize_context(struct gl_context *ctx, + gl_api api, + const struct gl_config *visual, + struct gl_context *share_list, + const struct dd_function_table *driverFunctions, + void *driverContext) { struct gl_shared_state *shared; int i; @@ -1029,25 +1029,6 @@ _mesa_initialize_context_for_api(struct gl_context *ctx, /** - * Initialize an OpenGL context. - */ -GLboolean -_mesa_initialize_context(struct gl_context *ctx, - const struct gl_config *visual, - struct gl_context *share_list, - const struct dd_function_table *driverFunctions, - void *driverContext) -{ - return _mesa_initialize_context_for_api(ctx, - API_OPENGL, - visual, - share_list, - driverFunctions, - driverContext); -} - - -/** * Allocate and initialize a struct gl_context structure. * Note that the driver needs to pass in its dd_function_table here since * we need to at least call driverFunctions->NewTextureObject to initialize @@ -1063,11 +1044,11 @@ _mesa_initialize_context(struct gl_context *ctx, * \return pointer to a new __struct gl_contextRec or NULL if error. */ struct gl_context * -_mesa_create_context_for_api(gl_api api, - const struct gl_config *visual, - struct gl_context *share_list, - const struct dd_function_table *driverFunctions, - void *driverContext) +_mesa_create_context(gl_api api, + const struct gl_config *visual, + struct gl_context *share_list, + const struct dd_function_table *driverFunctions, + void *driverContext) { struct gl_context *ctx; @@ -1078,8 +1059,8 @@ _mesa_create_context_for_api(gl_api api, if (!ctx) return NULL; - if (_mesa_initialize_context_for_api(ctx, api, visual, share_list, - driverFunctions, driverContext)) { + if (_mesa_initialize_context(ctx, api, visual, share_list, + driverFunctions, driverContext)) { return ctx; } else { @@ -1090,22 +1071,6 @@ _mesa_create_context_for_api(gl_api api, /** - * Create an OpenGL context. - */ -struct gl_context * -_mesa_create_context(const struct gl_config *visual, - struct gl_context *share_list, - const struct dd_function_table *driverFunctions, - void *driverContext) -{ - return _mesa_create_context_for_api(API_OPENGL, visual, - share_list, - driverFunctions, - driverContext); -} - - -/** * Free the data associated with the given context. * * But doesn't free the struct gl_context struct itself. diff --git a/src/mesa/main/context.h b/src/mesa/main/context.h index 8fb9b4c6b7a..4e391dde494 100644 --- a/src/mesa/main/context.h +++ b/src/mesa/main/context.h @@ -99,33 +99,20 @@ _mesa_destroy_visual( struct gl_config *vis ); /** \name Context-related functions */ /*@{*/ -extern struct gl_context * -_mesa_create_context( const struct gl_config *visual, - struct gl_context *share_list, - const struct dd_function_table *driverFunctions, - void *driverContext ); - extern GLboolean _mesa_initialize_context( struct gl_context *ctx, + gl_api api, const struct gl_config *visual, struct gl_context *share_list, const struct dd_function_table *driverFunctions, void *driverContext ); extern struct gl_context * -_mesa_create_context_for_api(gl_api api, - const struct gl_config *visual, - struct gl_context *share_list, - const struct dd_function_table *driverFunctions, - void *driverContext); - -extern GLboolean -_mesa_initialize_context_for_api(struct gl_context *ctx, - gl_api api, - const struct gl_config *visual, - struct gl_context *share_list, - const struct dd_function_table *driverFunctions, - void *driverContext); +_mesa_create_context(gl_api api, + const struct gl_config *visual, + struct gl_context *share_list, + const struct dd_function_table *driverFunctions, + void *driverContext); extern void _mesa_free_context_data( struct gl_context *ctx ); diff --git a/src/mesa/main/debug.c b/src/mesa/main/debug.c index a6a909b48ce..78881668e49 100644 --- a/src/mesa/main/debug.c +++ b/src/mesa/main/debug.c @@ -65,13 +65,12 @@ void _mesa_print_state( const char *msg, GLuint state ) { _mesa_debug(NULL, - "%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", + "%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", msg, state, (state & _NEW_MODELVIEW) ? "ctx->ModelView, " : "", (state & _NEW_PROJECTION) ? "ctx->Projection, " : "", (state & _NEW_TEXTURE_MATRIX) ? "ctx->TextureMatrix, " : "", - (state & _NEW_ACCUM) ? "ctx->Accum, " : "", (state & _NEW_COLOR) ? "ctx->Color, " : "", (state & _NEW_DEPTH) ? "ctx->Depth, " : "", (state & _NEW_EVAL) ? "ctx->Eval/EvalMap, " : "", @@ -214,16 +213,6 @@ void _mesa_init_debug( struct gl_context *ctx ) { char *c; - - /* Dither disable */ - ctx->NoDither = _mesa_getenv("MESA_NO_DITHER") ? GL_TRUE : GL_FALSE; - if (ctx->NoDither) { - if (_mesa_getenv("MESA_DEBUG")) { - _mesa_debug(ctx, "MESA_NO_DITHER set - dithering disabled\n"); - } - ctx->Color.DitherFlag = GL_FALSE; - } - c = _mesa_getenv("MESA_DEBUG"); if (c) add_debug_flags(c); @@ -307,8 +296,8 @@ write_texture_image(struct gl_texture_object *texObj, /** * Write renderbuffer image to a ppm file. */ -static void -write_renderbuffer_image(const struct gl_renderbuffer *rb) +void +_mesa_write_renderbuffer_image(const struct gl_renderbuffer *rb) { GET_CURRENT_CONTEXT(ctx); GLubyte *buffer; @@ -325,6 +314,10 @@ write_renderbuffer_image(const struct gl_renderbuffer *rb) type = GL_UNSIGNED_INT_24_8; } else { + _mesa_debug(NULL, + "Unsupported BaseFormat 0x%x in " + "_mesa_write_renderbuffer_image()\n", + rb->_BaseFormat); return; } @@ -335,8 +328,12 @@ write_renderbuffer_image(const struct gl_renderbuffer *rb) /* make filename */ _mesa_snprintf(s, sizeof(s), "/tmp/renderbuffer%u.ppm", rb->Name); + _mesa_snprintf(s, sizeof(s), "C:\\renderbuffer%u.ppm", rb->Name); printf(" Writing renderbuffer image to %s\n", s); + + _mesa_debug(NULL, " Writing renderbuffer image to %s\n", s); + write_ppm(s, buffer, rb->Width, rb->Height, 4, 0, 1, 2, GL_TRUE); free(buffer); @@ -423,7 +420,7 @@ dump_renderbuffer(const struct gl_renderbuffer *rb, GLboolean writeImage) rb->Name, rb->Width, rb->Height, _mesa_lookup_enum_by_nr(rb->InternalFormat)); if (writeImage) { - write_renderbuffer_image(rb); + _mesa_write_renderbuffer_image(rb); } } diff --git a/src/mesa/main/debug.h b/src/mesa/main/debug.h index 17aa897e8d1..4968a9f1979 100644 --- a/src/mesa/main/debug.h +++ b/src/mesa/main/debug.h @@ -64,6 +64,9 @@ extern void _mesa_init_debug( struct gl_context *ctx ); #endif extern void +_mesa_write_renderbuffer_image(const struct gl_renderbuffer *rb); + +extern void _mesa_dump_texture(GLuint texture, GLuint writeImages); extern void diff --git a/src/mesa/main/depth.c b/src/mesa/main/depth.c index 0bb47731ea3..52c69a6bcd9 100644 --- a/src/mesa/main/depth.c +++ b/src/mesa/main/depth.c @@ -44,6 +44,9 @@ _mesa_ClearDepth( GLclampd depth ) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glClearDepth(%f)\n", depth); + depth = CLAMP( depth, 0.0, 1.0 ); if (ctx->Depth.Clear == depth) @@ -133,6 +136,9 @@ _mesa_DepthBoundsEXT( GLclampd zmin, GLclampd zmax ) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glDepthBounds(%f, %f)\n", zmin, zmax); + if (zmin > zmax) { _mesa_error(ctx, GL_INVALID_VALUE, "glDepthBoundsEXT(zmin > zmax)"); return; diff --git a/src/mesa/main/dlist.c b/src/mesa/main/dlist.c index cdf349104a4..8e904c7787a 100644 --- a/src/mesa/main/dlist.c +++ b/src/mesa/main/dlist.c @@ -8419,8 +8419,6 @@ _mesa_CallList(GLuint list) GLboolean save_compile_flag; GET_CURRENT_CONTEXT(ctx); FLUSH_CURRENT(ctx, 0); - /* VERY IMPORTANT: Save the CompileFlag status, turn it off, */ - /* execute the display list, and restore the CompileFlag. */ if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glCallList %d\n", list); @@ -8430,8 +8428,12 @@ _mesa_CallList(GLuint list) return; } -/* mesa_print_display_list( list ); */ + if (0) + mesa_print_display_list( list ); + /* VERY IMPORTANT: Save the CompileFlag status, turn it off, + * execute the display list, and restore the CompileFlag. + */ save_compile_flag = ctx->CompileFlag; if (save_compile_flag) { ctx->CompileFlag = GL_FALSE; diff --git a/src/mesa/main/drawpix.c b/src/mesa/main/drawpix.c index 6fda3c5665c..df4712de894 100644 --- a/src/mesa/main/drawpix.c +++ b/src/mesa/main/drawpix.c @@ -49,6 +49,17 @@ _mesa_DrawPixels( GLsizei width, GLsizei height, GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glDrawPixels(%d, %d, %s, %s, %p) // to %s at %d, %d\n", + width, height, + _mesa_lookup_enum_by_nr(format), + _mesa_lookup_enum_by_nr(type), + pixels, + _mesa_lookup_enum_by_nr(ctx->DrawBuffer->ColorDrawBuffer[0]), + IROUND(ctx->Current.RasterPos[0]), + IROUND(ctx->Current.RasterPos[1])); + + if (width < 0 || height < 0) { _mesa_error( ctx, GL_INVALID_VALUE, "glDrawPixels(width or height < 0" ); return; @@ -124,6 +135,18 @@ _mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height, GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + _mesa_finish(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, + "glCopyPixels(%d, %d, %d, %d, %s) // from %s to %s at %d, %d\n", + srcx, srcy, width, height, + _mesa_lookup_enum_by_nr(type), + _mesa_lookup_enum_by_nr(ctx->ReadBuffer->ColorReadBuffer), + _mesa_lookup_enum_by_nr(ctx->DrawBuffer->ColorDrawBuffer[0]), + IROUND(ctx->Current.RasterPos[0]), + IROUND(ctx->Current.RasterPos[1])); + if (width < 0 || height < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glCopyPixels(width or height < 0)"); return; diff --git a/src/mesa/main/enable.c b/src/mesa/main/enable.c index c4c4e1bb29d..ea3b8214c3b 100644 --- a/src/mesa/main/enable.c +++ b/src/mesa/main/enable.c @@ -352,9 +352,6 @@ _mesa_set_enable(struct gl_context *ctx, GLenum cap, GLboolean state) ctx->Depth.Test = state; break; case GL_DITHER: - if (ctx->NoDither) { - state = GL_FALSE; /* MESA_NO_DITHER env var */ - } if (ctx->Color.DitherFlag == state) return; FLUSH_VERTICES(ctx, _NEW_COLOR); @@ -970,9 +967,10 @@ _mesa_set_enable(struct gl_context *ctx, GLenum cap, GLboolean state) /* GL3.0 - GL_framebuffer_sRGB */ case GL_FRAMEBUFFER_SRGB_EXT: - CHECK_EXTENSION(EXT_framebuffer_sRGB, cap); - ctx->Color.sRGBEnabled = state; - break; + CHECK_EXTENSION(EXT_framebuffer_sRGB, cap); + FLUSH_VERTICES(ctx, _NEW_BUFFERS); + ctx->Color.sRGBEnabled = state; + break; default: goto invalid_enum_error; diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c index 113ac405073..7504b8a85db 100644 --- a/src/mesa/main/extensions.c +++ b/src/mesa/main/extensions.c @@ -89,6 +89,7 @@ static const struct extension extension_table[] = { { "GL_ARB_fragment_program_shadow", o(ARB_fragment_program_shadow), GL }, { "GL_ARB_fragment_shader", o(ARB_fragment_shader), GL }, { "GL_ARB_framebuffer_object", o(ARB_framebuffer_object), GL }, + { "GL_ARB_framebuffer_sRGB", o(EXT_framebuffer_sRGB), GL }, { "GL_ARB_half_float_pixel", o(ARB_half_float_pixel), GL }, { "GL_ARB_half_float_vertex", o(ARB_half_float_vertex), GL }, { "GL_ARB_instanced_arrays", o(ARB_instanced_arrays), GL }, @@ -249,6 +250,7 @@ static const struct extension extension_table[] = { /* Vendor extensions */ { "GL_3DFX_texture_compression_FXT1", o(TDFX_texture_compression_FXT1), GL }, + { "GL_AMD_conservative_depth", o(AMD_conservative_depth), GL }, { "GL_APPLE_client_storage", o(APPLE_client_storage), GL }, { "GL_APPLE_object_purgeable", o(APPLE_object_purgeable), GL }, { "GL_APPLE_packed_pixels", o(APPLE_packed_pixels), GL }, @@ -729,78 +731,67 @@ _mesa_extension_is_enabled( struct gl_context *ctx, const char *name ) /** - * Append string 'b' onto string 'a'. Free 'a' and return new string. - */ -static char * -append(const char *a, const char *b) -{ - const GLuint aLen = a ? strlen(a) : 0; - const GLuint bLen = b ? strlen(b) : 0; - char *s = calloc(1, aLen + bLen + 1); - if (s) { - if (a) - memcpy(s, a, aLen); - if (b) - memcpy(s + aLen, b, bLen); - s[aLen + bLen] = '\0'; - } - if (a) - free((void *) a); - return s; -} - - -/** - * Check the MESA_EXTENSION_OVERRIDE env var. - * For extension names that are recognized, turn them on. For extension - * names that are recognized and prefixed with '-', turn them off. - * Return a string of the unknown/leftover names. + * \brief Apply the \c MESA_EXTENSION_OVERRIDE environment variable. + * + * \c MESA_EXTENSION_OVERRIDE is a space-separated list of extensions to + * enable or disable. The list is processed thus: + * - Enable recognized extension names that are prefixed with '+'. + * - Disable recognized extension names that are prefixed with '-'. + * - Enable recognized extension names that are not prefixed. + * - Collect unrecognized extension names in a new string. * - * Returnd string needs to be freed. + * \return Space-separated list of unrecognized extension names (which must + * be freed). Does not return \c NULL. */ static char * get_extension_override( struct gl_context *ctx ) { - const char *envExt = _mesa_getenv("MESA_EXTENSION_OVERRIDE"); - char *extraExt = NULL; - char ext[1000]; - GLuint extLen = 0; - GLuint i; - GLboolean disableExt = GL_FALSE; - - if (!envExt) - return NULL; + const char *env_const= _mesa_getenv("MESA_EXTENSION_OVERRIDE"); + char *env; + char *ext; + char *extra_exts; + int len; + + if (env_const == NULL) { + /* Return the empty string rather than NULL. This simplifies the logic + * of client functions. */ + return calloc(1, sizeof(char)); + } - for (i = 0; ; i++) { - if (envExt[i] == '\0' || envExt[i] == ' ') { - /* terminate/process 'ext' if extLen > 0 */ - if (extLen > 0) { - assert(extLen < sizeof(ext)); - /* enable extension named by 'ext' */ - ext[extLen] = 0; - if (!set_extension(ctx, ext, !disableExt)) { - /* unknown extension name, append it to extraExt */ - if (extraExt) { - extraExt = append(extraExt, " "); - } - extraExt = append(extraExt, ext); - } - extLen = 0; - disableExt = GL_FALSE; - } - if (envExt[i] == '\0') - break; - } - else if (envExt[i] == '-') { - disableExt = GL_TRUE; + /* extra_exts: List of unrecognized extensions. */ + extra_exts = calloc(strlen(env_const), sizeof(char)); + + /* Copy env_const because strtok() is destructive. */ + env = strdup(env_const); + for (ext = strtok(env, " "); ext != NULL; ext = strtok(NULL, " ")) { + int enable; + int recognized; + switch (ext[0]) { + case '+': + enable = 1; + ++ext; + break; + case '-': + enable = 0; + ++ext; + break; + default: + enable = 1; + break; } - else { - /* accumulate this non-space character */ - ext[extLen++] = envExt[i]; + recognized = set_extension(ctx, ext, enable); + if (!recognized) { + strcat(extra_exts, ext); + strcat(extra_exts, " "); } } - return extraExt; + /* Remove trailing space. */ + len = strlen(extra_exts); + if (extra_exts[len - 1] == ' ') + extra_exts[len - 1] = '\0'; + + return extra_exts; } diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c index f31d8b36db8..ab6b2a9b17b 100644 --- a/src/mesa/main/fbobject.c +++ b/src/mesa/main/fbobject.c @@ -373,6 +373,37 @@ _mesa_framebuffer_renderbuffer(struct gl_context *ctx, /** + * Fallback for ctx->Driver.ValidateFramebuffer() + * Check if the renderbuffer's formats are supported by the software + * renderer. + * Drivers should probably override this. + */ +void +_mesa_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) +{ + gl_buffer_index buf; + for (buf = 0; buf < BUFFER_COUNT; buf++) { + const struct gl_renderbuffer *rb = fb->Attachment[buf].Renderbuffer; + if (rb) { + switch (rb->_BaseFormat) { + case GL_ALPHA: + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE: + case GL_INTENSITY: + case GL_RED: + case GL_RG: + fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED; + return; + default: + /* render buffer format is supported by software rendering */ + ; + } + } + } +} + + +/** * For debug only. */ static void @@ -960,42 +991,104 @@ _mesa_GenRenderbuffersEXT(GLsizei n, GLuint *renderbuffers) /** - * Given an internal format token for a renderbuffer, return the - * corresponding base format. + * Given an internal format token for a render buffer, return the + * corresponding base format (one of GL_RGB, GL_RGBA, GL_STENCIL_INDEX, + * GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL_EXT, GL_ALPHA, GL_LUMINANCE, + * GL_LUMINANCE_ALPHA, GL_INTENSITY, etc). + * + * This is similar to _mesa_base_tex_format() but the set of valid + * internal formats is different. + * + * Note that even if a format is determined to be legal here, validation + * of the FBO may fail if the format is not supported by the driver/GPU. + * + * \param internalFormat as passed to glRenderbufferStorage() + * \return the base internal format, or 0 if internalFormat is illegal */ GLenum _mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat) { - GLenum baseFormat; - + /* + * Notes: some formats such as alpha, luminance, etc. were added + * with GL_ARB_framebuffer_object. + */ switch (internalFormat) { + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA8: + case GL_ALPHA12: + case GL_ALPHA16: + return ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0; + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE8: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + return ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0; + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE4_ALPHA4: + case GL_LUMINANCE6_ALPHA2: + case GL_LUMINANCE8_ALPHA8: + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + return ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0; + case GL_INTENSITY: + case GL_INTENSITY4: + case GL_INTENSITY8: + case GL_INTENSITY12: + case GL_INTENSITY16: + return ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0; + case GL_RGB: + case GL_R3_G3_B2: + case GL_RGB4: + case GL_RGB5: + case GL_RGB8: + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + case GL_SRGB8_EXT: + return GL_RGB; + case GL_RGBA: + case GL_RGBA2: + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: case GL_RGBA16_SNORM: - /* This is used internally by Mesa for accum buffers. */ + case GL_SRGB8_ALPHA8_EXT: return GL_RGBA; case GL_STENCIL_INDEX: case GL_STENCIL_INDEX1_EXT: case GL_STENCIL_INDEX4_EXT: case GL_STENCIL_INDEX8_EXT: case GL_STENCIL_INDEX16_EXT: - /* This is not a valid texture internalFormat, but valid for - * renderbuffers. - */ return GL_STENCIL_INDEX; case GL_DEPTH_COMPONENT: case GL_DEPTH_COMPONENT16: case GL_DEPTH_COMPONENT24: case GL_DEPTH_COMPONENT32: - /* This is an override of _mesa_base_tex_format's check that - * ARB_depth_texture is present. We allow depth RBs without it. - */ return GL_DEPTH_COMPONENT; - } - - baseFormat = _mesa_base_tex_format(ctx, internalFormat); - if (baseFormat < 0) + case GL_DEPTH_STENCIL_EXT: + case GL_DEPTH24_STENCIL8_EXT: + if (ctx->Extensions.EXT_packed_depth_stencil) + return GL_DEPTH_STENCIL_EXT; + else + return 0; + case GL_RED: + case GL_R8: + case GL_R16: + return ctx->Extensions.ARB_texture_rg ? GL_RED : 0; + case GL_RG: + case GL_RG8: + case GL_RG16: + return ctx->Extensions.ARB_texture_rg ? GL_RG : 0; + /* XXX add floating point and integer formats eventually */ + default: return 0; - - return baseFormat; + } } @@ -1031,14 +1124,6 @@ renderbuffer_storage(GLenum target, GLenum internalFormat, return; } - if (baseFormat != GL_DEPTH_COMPONENT && - baseFormat != GL_STENCIL_INDEX && - baseFormat != GL_DEPTH_STENCIL && - !_mesa_is_legal_color_format(ctx, baseFormat)) { - _mesa_error(ctx, GL_INVALID_ENUM, "%s(internalFormat)", func); - return; - } - if (width < 1 || width > (GLsizei) ctx->Const.MaxRenderbufferSize) { _mesa_error(ctx, GL_INVALID_VALUE, "%s(width)", func); return; @@ -2072,7 +2157,14 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, "glGetFramebufferAttachmentParameterivEXT(pname)"); } else { - *params = _mesa_get_format_color_encoding(att->Renderbuffer->Format); + if (ctx->Extensions.EXT_framebuffer_sRGB && ctx->Const.sRGBCapable) { + *params = _mesa_get_format_color_encoding(att->Renderbuffer->Format); + } + else { + /* According to ARB_framebuffer_sRGB, we should return LINEAR + * if the sRGB conversion is unsupported. */ + *params = GL_LINEAR; + } } return; case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE: @@ -2184,7 +2276,8 @@ _mesa_GenerateMipmapEXT(GLenum target) #if FEATURE_EXT_framebuffer_blit static const struct gl_renderbuffer_attachment * -find_attachment(const struct gl_framebuffer *fb, const struct gl_renderbuffer *rb) +find_attachment(const struct gl_framebuffer *fb, + const struct gl_renderbuffer *rb) { GLuint i; for (i = 0; i < Elements(fb->Attachment); i++) { @@ -2217,6 +2310,13 @@ _mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, ASSERT_OUTSIDE_BEGIN_END(ctx); FLUSH_VERTICES(ctx, _NEW_BUFFERS); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, + "glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d, 0x%x, %s)\n", + srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, + mask, _mesa_lookup_enum_by_nr(filter)); + if (ctx->NewState) { _mesa_update_state(ctx); } diff --git a/src/mesa/main/fbobject.h b/src/mesa/main/fbobject.h index 8763f99c4a7..ba74a95b74c 100644 --- a/src/mesa/main/fbobject.h +++ b/src/mesa/main/fbobject.h @@ -69,6 +69,9 @@ _mesa_framebuffer_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb GLenum attachment, struct gl_renderbuffer *rb); extern void +_mesa_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb); + +extern void _mesa_test_framebuffer_completeness(struct gl_context *ctx, struct gl_framebuffer *fb); extern GLboolean diff --git a/src/mesa/main/formats.c b/src/mesa/main/formats.c index b8fed182570..1e395363475 100644 --- a/src/mesa/main/formats.c +++ b/src/mesa/main/formats.c @@ -1372,7 +1372,11 @@ _mesa_format_to_type_and_comps(gl_format format, *comps = 4; return; - case MESA_FORMAT_AL44: /* XXX this isn't plain GL_UNSIGNED_BYTE */ + case MESA_FORMAT_AL44: + *datatype = MESA_UNSIGNED_BYTE_4_4; + *comps = 2; + return; + case MESA_FORMAT_AL88: case MESA_FORMAT_AL88_REV: case MESA_FORMAT_RG88: diff --git a/src/mesa/main/formats.h b/src/mesa/main/formats.h index d4dc5eac03e..9a5cef37788 100644 --- a/src/mesa/main/formats.h +++ b/src/mesa/main/formats.h @@ -35,6 +35,9 @@ #include <GL/gl.h> +/* OpenGL doesn't have GL_UNSIGNED_BYTE_4_4, so we must define our own type + * for GL_LUMINANCE4_ALPHA4. */ +#define MESA_UNSIGNED_BYTE_4_4 (GL_UNSIGNED_BYTE<<1) /** diff --git a/src/mesa/main/framebuffer.c b/src/mesa/main/framebuffer.c index 63da71c95b4..948b3b7b5a2 100644 --- a/src/mesa/main/framebuffer.c +++ b/src/mesa/main/framebuffer.c @@ -553,6 +553,8 @@ _mesa_update_framebuffer_visual(struct gl_context *ctx, + fb->Visual.greenBits + fb->Visual.blueBits; fb->Visual.floatMode = GL_FALSE; fb->Visual.samples = rb->NumSamples; + if (_mesa_get_format_color_encoding(fmt) == GL_SRGB) + fb->Visual.sRGBCapable = ctx->Const.sRGBCapable; break; } } diff --git a/src/mesa/main/hint.c b/src/mesa/main/hint.c index bdbd7519d37..ff8d88fffe0 100644 --- a/src/mesa/main/hint.c +++ b/src/mesa/main/hint.c @@ -40,8 +40,9 @@ _mesa_Hint( GLenum target, GLenum mode ) ASSERT_OUTSIDE_BEGIN_END(ctx); if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glHint %s %d\n", - _mesa_lookup_enum_by_nr(target), mode); + _mesa_debug(ctx, "glHint %s %s\n", + _mesa_lookup_enum_by_nr(target), + _mesa_lookup_enum_by_nr(mode)); if (mode != GL_NICEST && mode != GL_FASTEST && mode != GL_DONT_CARE) { _mesa_error(ctx, GL_INVALID_ENUM, "glHint(mode)"); diff --git a/src/mesa/main/image.c b/src/mesa/main/image.c index 909c18e7e60..63936132f98 100644 --- a/src/mesa/main/image.c +++ b/src/mesa/main/image.c @@ -68,6 +68,7 @@ _mesa_type_is_packed(GLenum type) switch (type) { case GL_UNSIGNED_BYTE_3_3_2: case GL_UNSIGNED_BYTE_2_3_3_REV: + case MESA_UNSIGNED_BYTE_4_4: case GL_UNSIGNED_SHORT_5_6_5: case GL_UNSIGNED_SHORT_5_6_5_REV: case GL_UNSIGNED_SHORT_4_4_4_4: @@ -194,6 +195,8 @@ _mesa_sizeof_packed_type( GLenum type ) return sizeof(GLubyte); case GL_UNSIGNED_BYTE_2_3_3_REV: return sizeof(GLubyte); + case MESA_UNSIGNED_BYTE_4_4: + return sizeof(GLubyte); case GL_UNSIGNED_SHORT_5_6_5: return sizeof(GLushort); case GL_UNSIGNED_SHORT_5_6_5_REV: @@ -1581,8 +1584,8 @@ _mesa_clip_drawpixels(const struct gl_context *ctx, * scissor box is ignored, and we use the bounds of the current readbuffer * surface. * - * \return GL_TRUE if image is ready for drawing or - * GL_FALSE if image was completely clipped away (draw nothing) + * \return GL_TRUE if region to read is in bounds + * GL_FALSE if region is completely out of bounds (nothing to read) */ GLboolean _mesa_clip_readpixels(const struct gl_context *ctx, diff --git a/src/mesa/main/imports.c b/src/mesa/main/imports.c index bd1fd7cfbf8..bf89815f2d3 100644 --- a/src/mesa/main/imports.c +++ b/src/mesa/main/imports.c @@ -453,6 +453,7 @@ _mesa_inv_sqrtf(float n) #endif } +#ifndef __GNUC__ /** * Find the first bit set in a word. */ @@ -496,9 +497,6 @@ _mesa_ffs(int32_t i) int _mesa_ffsll(int64_t val) { -#ifdef ffsll - return ffsll(val); -#else int bit; assert(sizeof(val) == 8); @@ -512,27 +510,24 @@ _mesa_ffsll(int64_t val) return 32 + bit; return 0; -#endif } +#if ((_GNUC__ == 3 && __GNUC_MINOR__ < 4) || __GNUC__ < 4) /** * Return number of bits set in given GLuint. */ unsigned int _mesa_bitcount(unsigned int n) { -#if defined(__GNUC__) && \ - ((_GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ >= 4) - return __builtin_popcount(n); -#else unsigned int bits; for (bits = 0; n > 0; n = n >> 1) { bits += (n & 1); } return bits; -#endif } +#endif +#endif /** @@ -942,7 +937,7 @@ _mesa_problem( const struct gl_context *ctx, const char *fmtString, ... ) va_end( args ); fprintf(stderr, "Mesa %s implementation error: %s\n", MESA_VERSION_STRING, str); - fprintf(stderr, "Please report at bugzilla.freedesktop.org\n"); + fprintf(stderr, "Please report at bugs.freedesktop.org\n"); } diff --git a/src/mesa/main/imports.h b/src/mesa/main/imports.h index 5ea647ad8d7..ce7baabe2c7 100644 --- a/src/mesa/main/imports.h +++ b/src/mesa/main/imports.h @@ -539,6 +539,24 @@ _mesa_inv_sqrtf(float x); extern void _mesa_init_sqrt_table(void); +#ifdef __GNUC__ + +#ifdef __MINGW32__ +#define ffs __builtin_ffs +#define ffsll __builtin_ffsll +#endif + +#define _mesa_ffs(i) ffs(i) +#define _mesa_ffsll(i) ffsll(i) + +#if ((_GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ >= 4) +#define _mesa_bitcount(i) __builtin_popcount(i) +#else +extern unsigned int +_mesa_bitcount(unsigned int n); +#endif + +#else extern int _mesa_ffs(int32_t i); @@ -547,6 +565,7 @@ _mesa_ffsll(int64_t i); extern unsigned int _mesa_bitcount(unsigned int n); +#endif extern GLhalfARB _mesa_float_to_half(float f); diff --git a/src/mesa/main/lines.c b/src/mesa/main/lines.c index 81e179a9254..79bf5679d8a 100644 --- a/src/mesa/main/lines.c +++ b/src/mesa/main/lines.c @@ -43,6 +43,9 @@ _mesa_LineWidth( GLfloat width ) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glLineWidth %f\n", width); + if (width<=0.0) { _mesa_error( ctx, GL_INVALID_VALUE, "glLineWidth" ); return; @@ -77,6 +80,9 @@ _mesa_LineStipple( GLint factor, GLushort pattern ) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glLineStipple %d %u\n", factor, pattern); + factor = CLAMP( factor, 1, 256 ); if (ctx->Line.StippleFactor == factor && diff --git a/src/mesa/main/mipmap.c b/src/mesa/main/mipmap.c index e073e17039f..d8a56103800 100644 --- a/src/mesa/main/mipmap.c +++ b/src/mesa/main/mipmap.c @@ -612,6 +612,28 @@ do_row(GLenum datatype, GLuint comps, GLint srcWidth, dst[i] = (blue << 5) | (green << 2) | red; } } + + else if (datatype == MESA_UNSIGNED_BYTE_4_4 && comps == 2) { + GLuint i, j, k; + const GLubyte *rowA = (const GLubyte *) srcRowA; + const GLubyte *rowB = (const GLubyte *) srcRowB; + GLubyte *dst = (GLubyte *) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + const GLint rowAr0 = rowA[j] & 0xf; + const GLint rowAr1 = rowA[k] & 0xf; + const GLint rowBr0 = rowB[j] & 0xf; + const GLint rowBr1 = rowB[k] & 0xf; + const GLint rowAg0 = (rowA[j] >> 4) & 0xf; + const GLint rowAg1 = (rowA[k] >> 4) & 0xf; + const GLint rowBg0 = (rowB[j] >> 4) & 0xf; + const GLint rowBg1 = (rowB[k] >> 4) & 0xf; + const GLint r = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; + const GLint g = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; + dst[i] = (g << 4) | r; + } + } + else { _mesa_problem(NULL, "bad format in do_row()"); } @@ -1078,7 +1100,7 @@ do_row_3D(GLenum datatype, GLuint comps, GLint srcWidth, } } else if ((datatype == GL_UNSIGNED_BYTE_3_3_2) && (comps == 3)) { - DECLARE_ROW_POINTERS0(GLushort); + DECLARE_ROW_POINTERS0(GLubyte); for (i = j = 0, k = k0; i < (GLuint) dstWidth; i++, j += colStride, k += colStride) { @@ -1115,6 +1137,34 @@ do_row_3D(GLenum datatype, GLuint comps, GLint srcWidth, dst[i] = (b << 5) | (g << 2) | r; } } + else if (datatype == MESA_UNSIGNED_BYTE_4_4 && comps == 2) { + DECLARE_ROW_POINTERS0(GLubyte); + + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + const GLint rowAr0 = rowA[j] & 0xf; + const GLint rowAr1 = rowA[k] & 0xf; + const GLint rowBr0 = rowB[j] & 0xf; + const GLint rowBr1 = rowB[k] & 0xf; + const GLint rowCr0 = rowC[j] & 0xf; + const GLint rowCr1 = rowC[k] & 0xf; + const GLint rowDr0 = rowD[j] & 0xf; + const GLint rowDr1 = rowD[k] & 0xf; + const GLint rowAg0 = (rowA[j] >> 4) & 0xf; + const GLint rowAg1 = (rowA[k] >> 4) & 0xf; + const GLint rowBg0 = (rowB[j] >> 4) & 0xf; + const GLint rowBg1 = (rowB[k] >> 4) & 0xf; + const GLint rowCg0 = (rowC[j] >> 4) & 0xf; + const GLint rowCg1 = (rowC[k] >> 4) & 0xf; + const GLint rowDg0 = (rowD[j] >> 4) & 0xf; + const GLint rowDg1 = (rowD[k] >> 4) & 0xf; + const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, + rowCr0, rowCr1, rowDr0, rowDr1); + const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, + rowCg0, rowCg1, rowDg0, rowDg1); + dst[i] = (g << 4) | r; + } + } else { _mesa_problem(NULL, "bad format in do_row()"); } diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 34003b4b6fb..b237063a6d8 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -84,23 +84,8 @@ /*@{*/ typedef GLuint64 GLbitfield64; -#define BITFIELD64_ONE 1ULL -#define BITFIELD64_ALLONES ~0ULL - /** Set a single bit */ -#define BITFIELD64_BIT(b) (BITFIELD64_ONE << (b)) - -/** Set a mask of the least significant \c b bits */ -#define BITFIELD64_MASK(b) (((b) >= 64) ? BITFIELD64_ALLONES : \ - (BITFIELD64_BIT(b) - 1)) - -/** - * Set all bits from l (low bit) to h (high bit), inclusive. - * - * \note \C BITFIELD_64_RANGE(0, 63) return 64 set bits. - */ -#define BITFIELD64_RANGE(l, h) (BITFIELD64_MASK((h) + 1) & ~BITFIELD64_MASK(l)) -/*@}*/ +#define BITFIELD64_BIT(b) (1ULL << (b)) /** @@ -867,6 +852,23 @@ struct gl_fog_attrib }; +/** + * \brief Layout qualifiers for gl_FragDepth. + * + * Extension AMD_conservative_depth allows gl_FragDepth to be redeclared with + * a layout qualifier. + * + * \see enum ir_depth_layout + */ +enum gl_frag_depth_layout { + FRAG_DEPTH_LAYOUT_NONE, /**< No layout is specified. */ + FRAG_DEPTH_LAYOUT_ANY, + FRAG_DEPTH_LAYOUT_GREATER, + FRAG_DEPTH_LAYOUT_LESS, + FRAG_DEPTH_LAYOUT_UNCHANGED +}; + + /** * Hint attribute group (GL_HINT_BIT). * @@ -1238,7 +1240,7 @@ struct gl_texture_image * GL_DEPTH_COMPONENT or GL_DEPTH_STENCIL_EXT * only. Used for choosing TexEnv arithmetic. */ - GLuint TexFormat; /**< The actual format: MESA_FORMAT_x */ + gl_format TexFormat; /**< The actual texture memory format */ GLuint Border; /**< 0 or 1 */ GLuint Width; /**< = 2^WidthLog2 + 2*Border */ @@ -1641,6 +1643,7 @@ struct gl_array_attrib GLuint RestartIndex; GLbitfield NewState; /**< mask of _NEW_ARRAY_* values */ + GLboolean RebindArrays; /**< whether the VBO module should rebind arrays */ /* GL_ARB_vertex_buffer_object */ struct gl_buffer_object *ArrayBufferObj; @@ -1889,6 +1892,7 @@ struct gl_fragment_program GLboolean UsesKill; /**< shader uses KIL instruction */ GLboolean OriginUpperLeft; GLboolean PixelCenterInteger; + enum gl_frag_depth_layout FragDepthLayout; }; @@ -2100,8 +2104,6 @@ struct gl_shader GLint RefCount; /**< Reference count */ GLboolean DeletePending; GLboolean CompileStatus; - GLboolean Main; /**< shader defines main() */ - GLboolean UnresolvedRefs; const GLchar *Source; /**< Source code string */ GLuint SourceChecksum; /**< for debug/logging purposes */ struct gl_program *Program; /**< Post-compile assembly code */ @@ -2378,7 +2380,7 @@ struct gl_renderbuffer GLenum InternalFormat; /**< The user-specified format */ GLenum _BaseFormat; /**< Either GL_RGB, GL_RGBA, GL_DEPTH_COMPONENT or GL_STENCIL_INDEX. */ - GLuint Format; /**< The actual format: MESA_FORMAT_x */ + gl_format Format; /**< The actual renderbuffer memory format */ GLubyte NumSamples; @@ -2692,6 +2694,9 @@ struct gl_constants /** GL_EXT_gpu_shader4 */ GLint MinProgramTexelOffset, MaxProgramTexelOffset; + + /* GL_EXT_framebuffer_sRGB */ + GLboolean sRGBCapable; /* can enable sRGB blend/update on FBOs */ }; @@ -2824,6 +2829,7 @@ struct gl_extensions GLboolean EXT_vertex_array_set; GLboolean OES_standard_derivatives; /* vendor extensions */ + GLboolean AMD_conservative_depth; GLboolean APPLE_client_storage; GLboolean APPLE_packed_pixels; GLboolean APPLE_vertex_array_object; @@ -2901,40 +2907,37 @@ struct gl_matrix_stack /** * \name Bits to indicate what state has changed. - * - * 4 unused flags. */ /*@{*/ -#define _NEW_MODELVIEW 0x1 /**< __struct gl_contextRec::ModelView */ -#define _NEW_PROJECTION 0x2 /**< __struct gl_contextRec::Projection */ -#define _NEW_TEXTURE_MATRIX 0x4 /**< __struct gl_contextRec::TextureMatrix */ -#define _NEW_ACCUM 0x10 /**< __struct gl_contextRec::Accum */ -#define _NEW_COLOR 0x20 /**< __struct gl_contextRec::Color */ -#define _NEW_DEPTH 0x40 /**< __struct gl_contextRec::Depth */ -#define _NEW_EVAL 0x80 /**< __struct gl_contextRec::Eval, __struct gl_contextRec::EvalMap */ -#define _NEW_FOG 0x100 /**< __struct gl_contextRec::Fog */ -#define _NEW_HINT 0x200 /**< __struct gl_contextRec::Hint */ -#define _NEW_LIGHT 0x400 /**< __struct gl_contextRec::Light */ -#define _NEW_LINE 0x800 /**< __struct gl_contextRec::Line */ -#define _NEW_PIXEL 0x1000 /**< __struct gl_contextRec::Pixel */ -#define _NEW_POINT 0x2000 /**< __struct gl_contextRec::Point */ -#define _NEW_POLYGON 0x4000 /**< __struct gl_contextRec::Polygon */ -#define _NEW_POLYGONSTIPPLE 0x8000 /**< __struct gl_contextRec::PolygonStipple */ -#define _NEW_SCISSOR 0x10000 /**< __struct gl_contextRec::Scissor */ -#define _NEW_STENCIL 0x20000 /**< __struct gl_contextRec::Stencil */ -#define _NEW_TEXTURE 0x40000 /**< __struct gl_contextRec::Texture */ -#define _NEW_TRANSFORM 0x80000 /**< __struct gl_contextRec::Transform */ -#define _NEW_VIEWPORT 0x100000 /**< __struct gl_contextRec::Viewport */ -#define _NEW_PACKUNPACK 0x200000 /**< __struct gl_contextRec::Pack, __struct gl_contextRec::Unpack */ -#define _NEW_ARRAY 0x400000 /**< __struct gl_contextRec::Array */ -#define _NEW_RENDERMODE 0x800000 /**< __struct gl_contextRec::RenderMode, __struct gl_contextRec::Feedback, __struct gl_contextRec::Select */ -#define _NEW_BUFFERS 0x1000000 /**< __struct gl_contextRec::Visual, __struct gl_contextRec::DrawBuffer, */ -#define _NEW_MULTISAMPLE 0x2000000 /**< __struct gl_contextRec::Multisample */ -#define _NEW_TRACK_MATRIX 0x4000000 /**< __struct gl_contextRec::VertexProgram */ -#define _NEW_PROGRAM 0x8000000 /**< __struct gl_contextRec::VertexProgram */ -#define _NEW_CURRENT_ATTRIB 0x10000000 /**< __struct gl_contextRec::Current */ -#define _NEW_PROGRAM_CONSTANTS 0x20000000 -#define _NEW_BUFFER_OBJECT 0x40000000 +#define _NEW_MODELVIEW (1 << 0) /**< gl_context::ModelView */ +#define _NEW_PROJECTION (1 << 1) /**< gl_context::Projection */ +#define _NEW_TEXTURE_MATRIX (1 << 2) /**< gl_context::TextureMatrix */ +#define _NEW_COLOR (1 << 3) /**< gl_context::Color */ +#define _NEW_DEPTH (1 << 4) /**< gl_context::Depth */ +#define _NEW_EVAL (1 << 5) /**< gl_context::Eval, EvalMap */ +#define _NEW_FOG (1 << 6) /**< gl_context::Fog */ +#define _NEW_HINT (1 << 7) /**< gl_context::Hint */ +#define _NEW_LIGHT (1 << 8) /**< gl_context::Light */ +#define _NEW_LINE (1 << 9) /**< gl_context::Line */ +#define _NEW_PIXEL (1 << 10) /**< gl_context::Pixel */ +#define _NEW_POINT (1 << 11) /**< gl_context::Point */ +#define _NEW_POLYGON (1 << 12) /**< gl_context::Polygon */ +#define _NEW_POLYGONSTIPPLE (1 << 13) /**< gl_context::PolygonStipple */ +#define _NEW_SCISSOR (1 << 14) /**< gl_context::Scissor */ +#define _NEW_STENCIL (1 << 15) /**< gl_context::Stencil */ +#define _NEW_TEXTURE (1 << 16) /**< gl_context::Texture */ +#define _NEW_TRANSFORM (1 << 17) /**< gl_context::Transform */ +#define _NEW_VIEWPORT (1 << 18) /**< gl_context::Viewport */ +#define _NEW_PACKUNPACK (1 << 19) /**< gl_context::Pack, Unpack */ +#define _NEW_ARRAY (1 << 20) /**< gl_context::Array */ +#define _NEW_RENDERMODE (1 << 21) /**< gl_context::RenderMode, etc */ +#define _NEW_BUFFERS (1 << 22) /**< gl_context::Visual, DrawBuffer, */ +#define _NEW_CURRENT_ATTRIB (1 << 23) /**< gl_context::Current */ +#define _NEW_MULTISAMPLE (1 << 24) /**< gl_context::Multisample */ +#define _NEW_TRACK_MATRIX (1 << 25) /**< gl_context::VertexProgram */ +#define _NEW_PROGRAM (1 << 26) /**< New program/shader state */ +#define _NEW_PROGRAM_CONSTANTS (1 << 27) +#define _NEW_BUFFER_OBJECT (1 << 28) #define _NEW_ALL ~0 /*@}*/ @@ -3292,9 +3295,6 @@ struct gl_context GLboolean FirstTimeCurrent; /*@}*/ - /** Dither disable via MESA_NO_DITHER env var */ - GLboolean NoDither; - /** software compression/decompression supported or not */ GLboolean Mesa_DXTn; diff --git a/src/mesa/main/queryobj.c b/src/mesa/main/queryobj.c index ef6460b2f97..fa35c6ce58a 100644 --- a/src/mesa/main/queryobj.c +++ b/src/mesa/main/queryobj.c @@ -25,6 +25,7 @@ #include "glheader.h" #include "context.h" +#include "enums.h" #include "hash.h" #include "imports.h" #include "queryobj.h" @@ -179,6 +180,9 @@ _mesa_GenQueriesARB(GLsizei n, GLuint *ids) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glGenQueries(%d)\n", n); + if (n < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glGenQueriesARB(n < 0)"); return; @@ -215,6 +219,9 @@ _mesa_DeleteQueriesARB(GLsizei n, const GLuint *ids) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glDeleeteQueries(%d)\n", n); + if (n < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteQueriesARB(n < 0)"); return; @@ -246,6 +253,9 @@ _mesa_IsQueryARB(GLuint id) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glIsQuery(%u)\n", id); + if (id && _mesa_lookup_query_object(ctx, id)) return GL_TRUE; else @@ -260,6 +270,10 @@ _mesa_BeginQueryARB(GLenum target, GLuint id) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glBeginQuery(%s, %u)\n", + _mesa_lookup_enum_by_nr(target), id); + FLUSH_VERTICES(ctx, _NEW_DEPTH); bindpt = get_query_binding_point(ctx, target); @@ -311,6 +325,9 @@ _mesa_EndQueryARB(GLenum target) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glEndQuery(%s)\n", _mesa_lookup_enum_by_nr(target)); + FLUSH_VERTICES(ctx, _NEW_DEPTH); bindpt = get_query_binding_point(ctx, target); @@ -341,6 +358,11 @@ _mesa_GetQueryivARB(GLenum target, GLenum pname, GLint *params) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glGetQueryiv(%s, %s)\n", + _mesa_lookup_enum_by_nr(target), + _mesa_lookup_enum_by_nr(pname)); + bindpt = get_query_binding_point(ctx, target); if (!bindpt) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryARB(target)"); @@ -370,6 +392,10 @@ _mesa_GetQueryObjectivARB(GLuint id, GLenum pname, GLint *params) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glGetQueryObjectiv(%u, %s)\n", id, + _mesa_lookup_enum_by_nr(pname)); + if (id) q = _mesa_lookup_query_object(ctx, id); @@ -417,6 +443,10 @@ _mesa_GetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glGetQueryObjectuiv(%u, %s)\n", id, + _mesa_lookup_enum_by_nr(pname)); + if (id) q = _mesa_lookup_query_object(ctx, id); @@ -467,6 +497,10 @@ _mesa_GetQueryObjecti64vEXT(GLuint id, GLenum pname, GLint64EXT *params) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glGetQueryObjecti64v(%u, %s)\n", id, + _mesa_lookup_enum_by_nr(pname)); + if (id) q = _mesa_lookup_query_object(ctx, id); @@ -504,6 +538,10 @@ _mesa_GetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64EXT *params) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glGetQueryObjectui64v(%u, %s)\n", id, + _mesa_lookup_enum_by_nr(pname)); + if (id) q = _mesa_lookup_query_object(ctx, id); diff --git a/src/mesa/main/readpix.c b/src/mesa/main/readpix.c index e5b85ca32b4..9a4f15f7279 100644 --- a/src/mesa/main/readpix.c +++ b/src/mesa/main/readpix.c @@ -26,6 +26,7 @@ #include "imports.h" #include "bufferobj.h" #include "context.h" +#include "enums.h" #include "readpix.h" #include "framebuffer.h" #include "formats.h" @@ -173,6 +174,13 @@ _mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height, FLUSH_CURRENT(ctx, 0); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glReadPixels(%d, %d, %s, %s, %p)\n", + width, height, + _mesa_lookup_enum_by_nr(format), + _mesa_lookup_enum_by_nr(type), + pixels); + if (width < 0 || height < 0) { _mesa_error( ctx, GL_INVALID_VALUE, "glReadPixels(width=%d height=%d)", width, height ); diff --git a/src/mesa/main/renderbuffer.c b/src/mesa/main/renderbuffer.c index 23c662bab7f..67ee589d776 100644 --- a/src/mesa/main/renderbuffer.c +++ b/src/mesa/main/renderbuffer.c @@ -1086,7 +1086,7 @@ _mesa_soft_renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer * pixelSize = sizeof(GLuint); break; default: - _mesa_problem(ctx, "Bad internalFormat in _mesa_soft_renderbuffer_storage"); + /* unsupported format */ return GL_FALSE; } diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c index a5e90d7cbd1..11b0f884fa4 100644 --- a/src/mesa/main/shaderapi.c +++ b/src/mesa/main/shaderapi.c @@ -48,7 +48,7 @@ #include "program/program.h" #include "program/prog_parameter.h" #include "program/prog_uniform.h" -#include "talloc.h" +#include "ralloc.h" #include <stdbool.h> #include "../glsl/glsl_parser_extras.h" @@ -1137,9 +1137,9 @@ validate_program(struct gl_context *ctx, GLuint program) if (!shProg->Validated) { /* update info log */ if (shProg->InfoLog) { - talloc_free(shProg->InfoLog); + ralloc_free(shProg->InfoLog); } - shProg->InfoLog = talloc_strdup(shProg, errMsg); + shProg->InfoLog = ralloc_strdup(shProg, errMsg); } } @@ -1184,6 +1184,8 @@ void GLAPIENTRY _mesa_CompileShaderARB(GLhandleARB shaderObj) { GET_CURRENT_CONTEXT(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glCompileShader %u\n", shaderObj); compile_shader(ctx, shaderObj); } @@ -1192,6 +1194,8 @@ GLuint GLAPIENTRY _mesa_CreateShader(GLenum type) { GET_CURRENT_CONTEXT(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glCreateShader %s\n", _mesa_lookup_enum_by_nr(type)); return create_shader(ctx, type); } @@ -1208,6 +1212,8 @@ GLuint GLAPIENTRY _mesa_CreateProgram(void) { GET_CURRENT_CONTEXT(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glCreateProgram\n"); return create_shader_program(ctx); } @@ -1223,6 +1229,11 @@ _mesa_CreateProgramObjectARB(void) void GLAPIENTRY _mesa_DeleteObjectARB(GLhandleARB obj) { + if (MESA_VERBOSE & VERBOSE_API) { + GET_CURRENT_CONTEXT(ctx); + _mesa_debug(ctx, "glDeleteObjectARB(%u)\n", obj); + } + if (obj) { GET_CURRENT_CONTEXT(ctx); if (is_program(ctx, obj)) { @@ -1855,7 +1866,7 @@ _mesa_CreateShaderProgramEXT(GLenum type, const GLchar *string) #endif } - shProg->InfoLog = talloc_strdup_append(shProg->InfoLog, sh->InfoLog); + ralloc_strcat(&shProg->InfoLog, sh->InfoLog); } delete_shader(ctx, shader); diff --git a/src/mesa/main/shaderobj.c b/src/mesa/main/shaderobj.c index 647fd31cab4..1d75845590f 100644 --- a/src/mesa/main/shaderobj.c +++ b/src/mesa/main/shaderobj.c @@ -38,7 +38,7 @@ #include "program/program.h" #include "program/prog_parameter.h" #include "program/prog_uniform.h" -#include "talloc.h" +#include "ralloc.h" /**********************************************************************/ /*** Shader object functions ***/ @@ -105,7 +105,7 @@ _mesa_new_shader(struct gl_context *ctx, GLuint name, GLenum type) struct gl_shader *shader; assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER || type == GL_GEOMETRY_SHADER_ARB); - shader = talloc_zero(NULL, struct gl_shader); + shader = rzalloc(NULL, struct gl_shader); if (shader) { shader->Type = type; shader->Name = name; @@ -125,7 +125,7 @@ _mesa_delete_shader(struct gl_context *ctx, struct gl_shader *sh) if (sh->Source) free((void *) sh->Source); _mesa_reference_program(ctx, &sh->Program, NULL); - talloc_free(sh); + ralloc_free(sh); } @@ -252,7 +252,7 @@ static struct gl_shader_program * _mesa_new_shader_program(struct gl_context *ctx, GLuint name) { struct gl_shader_program *shProg; - shProg = talloc_zero(NULL, struct gl_shader_program); + shProg = rzalloc(NULL, struct gl_shader_program); if (shProg) { shProg->Name = name; _mesa_init_shader_program(ctx, shProg); @@ -316,7 +316,7 @@ _mesa_free_shader_program_data(struct gl_context *ctx, } if (shProg->InfoLog) { - talloc_free(shProg->InfoLog); + ralloc_free(shProg->InfoLog); shProg->InfoLog = NULL; } @@ -347,7 +347,7 @@ _mesa_delete_shader_program(struct gl_context *ctx, struct gl_shader_program *sh { _mesa_free_shader_program_data(ctx, shProg); - talloc_free(shProg); + ralloc_free(shProg); } diff --git a/src/mesa/main/state.c b/src/mesa/main/state.c index cce1b464f0c..502c429294c 100644 --- a/src/mesa/main/state.c +++ b/src/mesa/main/state.c @@ -662,6 +662,8 @@ _mesa_update_state_locked( struct gl_context *ctx ) ctx->NewState = 0; ctx->Driver.UpdateState(ctx, new_state); ctx->Array.NewState = 0; + if (!ctx->Array.RebindArrays) + ctx->Array.RebindArrays = (new_state & (_NEW_ARRAY | _NEW_PROGRAM)) != 0; } diff --git a/src/mesa/main/stencil.c b/src/mesa/main/stencil.c index 93e2e97ce0c..d898bf1d749 100644 --- a/src/mesa/main/stencil.c +++ b/src/mesa/main/stencil.c @@ -147,6 +147,9 @@ _mesa_StencilFuncSeparateATI( GLenum frontfunc, GLenum backfunc, GLint ref, GLui const GLint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1; ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glStencilFuncSeparateATI()\n"); + if (!validate_stencil_func(ctx, frontfunc)) { _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFuncSeparateATI(frontfunc)"); @@ -203,6 +206,9 @@ _mesa_StencilFunc( GLenum func, GLint ref, GLuint mask ) const GLint face = ctx->Stencil.ActiveFace; ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glStencilFunc()\n"); + if (!validate_stencil_func(ctx, func)) { _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFunc(func)"); return; @@ -267,6 +273,9 @@ _mesa_StencilMask( GLuint mask ) GET_CURRENT_CONTEXT(ctx); const GLint face = ctx->Stencil.ActiveFace; + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glStencilMask()\n"); + ASSERT_OUTSIDE_BEGIN_END(ctx); if (face != 0) { @@ -321,6 +330,9 @@ _mesa_StencilOp(GLenum fail, GLenum zfail, GLenum zpass) GET_CURRENT_CONTEXT(ctx); const GLint face = ctx->Stencil.ActiveFace; + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glStencilOp()\n"); + ASSERT_OUTSIDE_BEGIN_END(ctx); if (!validate_stencil_op(ctx, fail)) { @@ -386,6 +398,9 @@ _mesa_ActiveStencilFaceEXT(GLenum face) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glActiveStencilFaceEXT()\n"); + if (!ctx->Extensions.EXT_stencil_two_side) { _mesa_error(ctx, GL_INVALID_OPERATION, "glActiveStencilFaceEXT"); return; @@ -416,6 +431,9 @@ _mesa_StencilOpSeparate(GLenum face, GLenum sfail, GLenum zfail, GLenum zpass) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glStencilOpSeparate()\n"); + if (!validate_stencil_op(ctx, sfail)) { _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(sfail)"); return; @@ -471,6 +489,9 @@ _mesa_StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) const GLint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1; ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glStencilFuncSeparate()\n"); + if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) { _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFuncSeparate(face)"); return; @@ -509,6 +530,9 @@ _mesa_StencilMaskSeparate(GLenum face, GLuint mask) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glStencilMaskSeparate()\n"); + if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) { _mesa_error(ctx, GL_INVALID_ENUM, "glStencilaMaskSeparate(face)"); return; diff --git a/src/mesa/main/texformat.c b/src/mesa/main/texformat.c index 146b2b340e7..2542cea856b 100644 --- a/src/mesa/main/texformat.c +++ b/src/mesa/main/texformat.c @@ -591,6 +591,17 @@ _mesa_choose_tex_format( struct gl_context *ctx, GLint internalFormat, } } + if (ctx->Extensions.EXT_texture_format_BGRA8888) { + switch (internalFormat) { + case GL_BGRA: + RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888); + break; + + default: + ; /* fallthrough */ + } + } + _mesa_problem(ctx, "unexpected format in _mesa_choose_tex_format()"); return MESA_FORMAT_NONE; } diff --git a/src/mesa/main/texgetimage.c b/src/mesa/main/texgetimage.c index da610798e12..28829694153 100644 --- a/src/mesa/main/texgetimage.c +++ b/src/mesa/main/texgetimage.c @@ -805,8 +805,8 @@ _mesa_GetTexImage( GLenum target, GLint level, GLenum format, * \return GL_TRUE if any error, GL_FALSE if no errors. */ static GLboolean -getcompressedteximage_error_check(struct gl_context *ctx, GLenum target, GLint level, - GLvoid *img) +getcompressedteximage_error_check(struct gl_context *ctx, GLenum target, + GLint level, GLvoid *img) { struct gl_texture_object *texObj; struct gl_texture_image *texImage; diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c index 47d509396a7..1f2ad7f266b 100644 --- a/src/mesa/main/teximage.c +++ b/src/mesa/main/teximage.c @@ -183,6 +183,15 @@ _mesa_base_tex_format( struct gl_context *ctx, GLint internalFormat ) ; /* fallthrough */ } + if (ctx->Extensions.EXT_texture_format_BGRA8888) { + switch (internalFormat) { + case GL_BGRA_EXT: + return GL_RGBA; + default: + ; /* fallthrough */ + } + } + if (ctx->Extensions.EXT_paletted_texture) { switch (internalFormat) { case GL_COLOR_INDEX: @@ -694,6 +703,9 @@ _mesa_select_tex_object(struct gl_context *ctx, const struct gl_texture_unit *texUnit, GLenum target) { + const GLboolean arrayTex = (ctx->Extensions.MESA_texture_array || + ctx->Extensions.EXT_texture_array); + switch (target) { case GL_TEXTURE_1D: return texUnit->CurrentTex[TEXTURE_1D_INDEX]; @@ -726,17 +738,13 @@ _mesa_select_tex_object(struct gl_context *ctx, return ctx->Extensions.NV_texture_rectangle ? ctx->Texture.ProxyTex[TEXTURE_RECT_INDEX] : NULL; case GL_TEXTURE_1D_ARRAY_EXT: - return ctx->Extensions.MESA_texture_array - ? texUnit->CurrentTex[TEXTURE_1D_ARRAY_INDEX] : NULL; + return arrayTex ? texUnit->CurrentTex[TEXTURE_1D_ARRAY_INDEX] : NULL; case GL_PROXY_TEXTURE_1D_ARRAY_EXT: - return ctx->Extensions.MESA_texture_array - ? ctx->Texture.ProxyTex[TEXTURE_1D_ARRAY_INDEX] : NULL; + return arrayTex ? ctx->Texture.ProxyTex[TEXTURE_1D_ARRAY_INDEX] : NULL; case GL_TEXTURE_2D_ARRAY_EXT: - return ctx->Extensions.MESA_texture_array - ? texUnit->CurrentTex[TEXTURE_2D_ARRAY_INDEX] : NULL; + return arrayTex ? texUnit->CurrentTex[TEXTURE_2D_ARRAY_INDEX] : NULL; case GL_PROXY_TEXTURE_2D_ARRAY_EXT: - return ctx->Extensions.MESA_texture_array - ? ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX] : NULL; + return arrayTex ? ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX] : NULL; default: _mesa_problem(NULL, "bad target in _mesa_select_tex_object()"); return NULL; @@ -921,7 +929,8 @@ _mesa_max_texture_levels(struct gl_context *ctx, GLenum target) case GL_PROXY_TEXTURE_1D_ARRAY_EXT: case GL_TEXTURE_2D_ARRAY_EXT: case GL_PROXY_TEXTURE_2D_ARRAY_EXT: - return ctx->Extensions.MESA_texture_array + return (ctx->Extensions.MESA_texture_array || + ctx->Extensions.EXT_texture_array) ? ctx->Const.MaxTextureLevels : 0; default: return 0; /* bad target */ @@ -1373,7 +1382,8 @@ target_can_be_compressed(const struct gl_context *ctx, GLenum target, return ctx->Extensions.ARB_texture_cube_map; case GL_PROXY_TEXTURE_2D_ARRAY_EXT: case GL_TEXTURE_2D_ARRAY_EXT: - return ctx->Extensions.MESA_texture_array; + return (ctx->Extensions.MESA_texture_array || + ctx->Extensions.EXT_texture_array); default: return GL_FALSE; } @@ -1414,7 +1424,8 @@ legal_teximage_target(struct gl_context *ctx, GLuint dims, GLenum target) return ctx->Extensions.NV_texture_rectangle; case GL_TEXTURE_1D_ARRAY_EXT: case GL_PROXY_TEXTURE_1D_ARRAY_EXT: - return ctx->Extensions.MESA_texture_array; + return (ctx->Extensions.MESA_texture_array || + ctx->Extensions.EXT_texture_array); default: return GL_FALSE; } @@ -1425,7 +1436,8 @@ legal_teximage_target(struct gl_context *ctx, GLuint dims, GLenum target) return GL_TRUE; case GL_TEXTURE_2D_ARRAY_EXT: case GL_PROXY_TEXTURE_2D_ARRAY_EXT: - return ctx->Extensions.MESA_texture_array; + return (ctx->Extensions.MESA_texture_array || + ctx->Extensions.EXT_texture_array); default: return GL_FALSE; } @@ -1462,7 +1474,8 @@ legal_texsubimage_target(struct gl_context *ctx, GLuint dims, GLenum target) case GL_TEXTURE_RECTANGLE_NV: return ctx->Extensions.NV_texture_rectangle; case GL_TEXTURE_1D_ARRAY_EXT: - return ctx->Extensions.MESA_texture_array; + return (ctx->Extensions.MESA_texture_array || + ctx->Extensions.EXT_texture_array); default: return GL_FALSE; } @@ -1471,7 +1484,8 @@ legal_texsubimage_target(struct gl_context *ctx, GLuint dims, GLenum target) case GL_TEXTURE_3D: return GL_TRUE; case GL_TEXTURE_2D_ARRAY_EXT: - return ctx->Extensions.MESA_texture_array; + return (ctx->Extensions.MESA_texture_array || + ctx->Extensions.EXT_texture_array); default: return GL_FALSE; } diff --git a/src/mesa/main/texparam.c b/src/mesa/main/texparam.c index 29e409d0b8c..6e14face4dd 100644 --- a/src/mesa/main/texparam.c +++ b/src/mesa/main/texparam.c @@ -33,6 +33,7 @@ #include "main/glheader.h" #include "main/colormac.h" #include "main/context.h" +#include "main/enums.h" #include "main/formats.h" #include "main/macros.h" #include "main/mfeatures.h" @@ -116,12 +117,14 @@ get_texobj(struct gl_context *ctx, GLenum target, GLboolean get) } break; case GL_TEXTURE_1D_ARRAY_EXT: - if (ctx->Extensions.MESA_texture_array) { + if (ctx->Extensions.MESA_texture_array || + ctx->Extensions.EXT_texture_array) { return texUnit->CurrentTex[TEXTURE_1D_ARRAY_INDEX]; } break; case GL_TEXTURE_2D_ARRAY_EXT: - if (ctx->Extensions.MESA_texture_array) { + if (ctx->Extensions.MESA_texture_array || + ctx->Extensions.EXT_texture_array) { return texUnit->CurrentTex[TEXTURE_2D_ARRAY_INDEX]; } break; @@ -175,13 +178,26 @@ set_swizzle_component(GLuint *swizzle, GLuint comp, GLuint swz) /** - * This is called just prior to changing any texture object state. + * This is called just prior to changing any texture object state which + * will not effect texture completeness. + */ +static INLINE void +flush(struct gl_context *ctx) +{ + FLUSH_VERTICES(ctx, _NEW_TEXTURE); +} + + +/** + * This is called just prior to changing any texture object state which + * can effect texture completeness (texture base level, max level, + * minification filter). * Any pending rendering will be flushed out, we'll set the _NEW_TEXTURE * state flag and then mark the texture object as 'incomplete' so that any * per-texture derived state gets recomputed. */ static INLINE void -flush(struct gl_context *ctx, struct gl_texture_object *texObj) +incomplete(struct gl_context *ctx, struct gl_texture_object *texObj) { FLUSH_VERTICES(ctx, _NEW_TEXTURE); texObj->_Complete = GL_FALSE; @@ -204,7 +220,7 @@ set_tex_parameteri(struct gl_context *ctx, switch (params[0]) { case GL_NEAREST: case GL_LINEAR: - flush(ctx, texObj); + incomplete(ctx, texObj); texObj->MinFilter = params[0]; return GL_TRUE; case GL_NEAREST_MIPMAP_NEAREST: @@ -212,14 +228,13 @@ set_tex_parameteri(struct gl_context *ctx, case GL_NEAREST_MIPMAP_LINEAR: case GL_LINEAR_MIPMAP_LINEAR: if (texObj->Target != GL_TEXTURE_RECTANGLE_NV) { - flush(ctx, texObj); + incomplete(ctx, texObj); texObj->MinFilter = params[0]; return GL_TRUE; } /* fall-through */ default: - _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(param=0x%x)", - params[0] ); + goto invalid_param; } return GL_FALSE; @@ -229,12 +244,11 @@ set_tex_parameteri(struct gl_context *ctx, switch (params[0]) { case GL_NEAREST: case GL_LINEAR: - flush(ctx, texObj); + flush(ctx); /* does not effect completeness */ texObj->MagFilter = params[0]; return GL_TRUE; default: - _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(param=0x%x)", - params[0]); + goto invalid_param; } return GL_FALSE; @@ -242,7 +256,7 @@ set_tex_parameteri(struct gl_context *ctx, if (texObj->WrapS == params[0]) return GL_FALSE; if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) { - flush(ctx, texObj); + flush(ctx); texObj->WrapS = params[0]; return GL_TRUE; } @@ -252,7 +266,7 @@ set_tex_parameteri(struct gl_context *ctx, if (texObj->WrapT == params[0]) return GL_FALSE; if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) { - flush(ctx, texObj); + flush(ctx); texObj->WrapT = params[0]; return GL_TRUE; } @@ -262,7 +276,7 @@ set_tex_parameteri(struct gl_context *ctx, if (texObj->WrapR == params[0]) return GL_FALSE; if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) { - flush(ctx, texObj); + flush(ctx); texObj->WrapR = params[0]; return GL_TRUE; } @@ -277,7 +291,7 @@ set_tex_parameteri(struct gl_context *ctx, "glTexParameter(param=%d)", params[0]); return GL_FALSE; } - flush(ctx, texObj); + incomplete(ctx, texObj); texObj->BaseLevel = params[0]; return GL_TRUE; @@ -289,34 +303,31 @@ set_tex_parameteri(struct gl_context *ctx, "glTexParameter(param=%d)", params[0]); return GL_FALSE; } - flush(ctx, texObj); + incomplete(ctx, texObj); texObj->MaxLevel = params[0]; return GL_TRUE; case GL_GENERATE_MIPMAP_SGIS: if (texObj->GenerateMipmap != params[0]) { - flush(ctx, texObj); + /* no flush() */ texObj->GenerateMipmap = params[0] ? GL_TRUE : GL_FALSE; return GL_TRUE; } return GL_FALSE; case GL_TEXTURE_COMPARE_MODE_ARB: - if (ctx->Extensions.ARB_shadow && - (params[0] == GL_NONE || - params[0] == GL_COMPARE_R_TO_TEXTURE_ARB)) { - if (texObj->CompareMode != params[0]) { - flush(ctx, texObj); + if (ctx->Extensions.ARB_shadow) { + if (texObj->CompareMode == params[0]) + return GL_FALSE; + if (params[0] == GL_NONE || + params[0] == GL_COMPARE_R_TO_TEXTURE_ARB) { + flush(ctx); texObj->CompareMode = params[0]; return GL_TRUE; } - return GL_FALSE; - } - else { - _mesa_error(ctx, GL_INVALID_ENUM, - "glTexParameter(GL_TEXTURE_COMPARE_MODE_ARB)"); + goto invalid_param; } - return GL_FALSE; + goto invalid_pname; case GL_TEXTURE_COMPARE_FUNC_ARB: if (ctx->Extensions.ARB_shadow) { @@ -325,7 +336,7 @@ set_tex_parameteri(struct gl_context *ctx, switch (params[0]) { case GL_LEQUAL: case GL_GEQUAL: - flush(ctx, texObj); + flush(ctx); texObj->CompareFunc = params[0]; return GL_TRUE; case GL_EQUAL: @@ -335,38 +346,32 @@ set_tex_parameteri(struct gl_context *ctx, case GL_ALWAYS: case GL_NEVER: if (ctx->Extensions.EXT_shadow_funcs) { - flush(ctx, texObj); + flush(ctx); texObj->CompareFunc = params[0]; return GL_TRUE; } /* fall-through */ default: - _mesa_error(ctx, GL_INVALID_ENUM, - "glTexParameter(GL_TEXTURE_COMPARE_FUNC_ARB)"); + goto invalid_param; } } - else { - _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=0x%x)", pname); - } - return GL_FALSE; + goto invalid_pname; case GL_DEPTH_TEXTURE_MODE_ARB: - if (ctx->Extensions.ARB_depth_texture && - (params[0] == GL_LUMINANCE || - params[0] == GL_INTENSITY || - params[0] == GL_ALPHA || - (ctx->Extensions.ARB_texture_rg && params[0] == GL_RED))) { - if (texObj->DepthMode != params[0]) { - flush(ctx, texObj); + if (ctx->Extensions.ARB_depth_texture) { + if (texObj->DepthMode == params[0]) + return GL_FALSE; + if (params[0] == GL_LUMINANCE || + params[0] == GL_INTENSITY || + params[0] == GL_ALPHA || + (ctx->Extensions.ARB_texture_rg && params[0] == GL_RED)) { + flush(ctx); texObj->DepthMode = params[0]; return GL_TRUE; } + goto invalid_param; } - else { - _mesa_error(ctx, GL_INVALID_ENUM, - "glTexParameter(GL_DEPTH_TEXTURE_MODE_ARB)"); - } - return GL_FALSE; + goto invalid_pname; #if FEATURE_OES_draw_texture case GL_TEXTURE_CROP_RECT_OES: @@ -391,19 +396,18 @@ set_tex_parameteri(struct gl_context *ctx, } ASSERT(comp < 4); if (swz >= 0) { - flush(ctx, texObj); + flush(ctx); texObj->Swizzle[comp] = params[0]; set_swizzle_component(&texObj->_Swizzle, comp, swz); return GL_TRUE; } } - _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=0x%x)", pname); - return GL_FALSE; + goto invalid_pname; case GL_TEXTURE_SWIZZLE_RGBA_EXT: if (ctx->Extensions.EXT_texture_swizzle) { GLuint comp; - flush(ctx, texObj); + flush(ctx); for (comp = 0; comp < 4; comp++) { const GLint swz = comp_to_swizzle(params[comp]); if (swz >= 0) { @@ -418,25 +422,34 @@ set_tex_parameteri(struct gl_context *ctx, } return GL_TRUE; } - _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=0x%x)", pname); - return GL_FALSE; + goto invalid_pname; + case GL_TEXTURE_SRGB_DECODE_EXT: if (ctx->Extensions.EXT_texture_sRGB_decode) { GLenum decode = params[0]; if (decode == GL_DECODE_EXT || decode == GL_SKIP_DECODE_EXT) { if (texObj->sRGBDecode != decode) { - flush(ctx, texObj); + flush(ctx); texObj->sRGBDecode = decode; _mesa_update_fetch_functions(texObj); } return GL_TRUE; } } - _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=0x%x)", pname); - return GL_FALSE; + goto invalid_pname; + default: - _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=0x%x)", pname); + goto invalid_pname; } + +invalid_pname: + _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=%s)", + _mesa_lookup_enum_by_nr(pname)); + return GL_FALSE; + +invalid_param: + _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(param=%s)", + _mesa_lookup_enum_by_nr(params[0])); return GL_FALSE; } @@ -454,19 +467,19 @@ set_tex_parameterf(struct gl_context *ctx, case GL_TEXTURE_MIN_LOD: if (texObj->MinLod == params[0]) return GL_FALSE; - flush(ctx, texObj); + flush(ctx); texObj->MinLod = params[0]; return GL_TRUE; case GL_TEXTURE_MAX_LOD: if (texObj->MaxLod == params[0]) return GL_FALSE; - flush(ctx, texObj); + flush(ctx); texObj->MaxLod = params[0]; return GL_TRUE; case GL_TEXTURE_PRIORITY: - flush(ctx, texObj); + flush(ctx); texObj->Priority = CLAMP(params[0], 0.0F, 1.0F); return GL_TRUE; @@ -478,7 +491,7 @@ set_tex_parameterf(struct gl_context *ctx, _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)" ); return GL_FALSE; } - flush(ctx, texObj); + flush(ctx); /* clamp to max, that's what NVIDIA does */ texObj->MaxAnisotropy = MIN2(params[0], ctx->Const.MaxTextureMaxAnisotropy); @@ -495,7 +508,7 @@ set_tex_parameterf(struct gl_context *ctx, case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB: if (ctx->Extensions.ARB_shadow_ambient) { if (texObj->CompareFailValue != params[0]) { - flush(ctx, texObj); + flush(ctx); texObj->CompareFailValue = CLAMP(params[0], 0.0F, 1.0F); return GL_TRUE; } @@ -510,7 +523,7 @@ set_tex_parameterf(struct gl_context *ctx, /* NOTE: this is really part of OpenGL 1.4, not EXT_texture_lod_bias */ if (ctx->Extensions.EXT_texture_lod_bias) { if (texObj->LodBias != params[0]) { - flush(ctx, texObj); + flush(ctx); texObj->LodBias = params[0]; return GL_TRUE; } @@ -519,7 +532,7 @@ set_tex_parameterf(struct gl_context *ctx, break; case GL_TEXTURE_BORDER_COLOR: - flush(ctx, texObj); + flush(ctx); texObj->BorderColor.f[RCOMP] = params[0]; texObj->BorderColor.f[GCOMP] = params[1]; texObj->BorderColor.f[BCOMP] = params[2]; @@ -821,7 +834,6 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level, const struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; const struct gl_texture_image *img = NULL; - GLboolean isProxy; GLint maxLevels; gl_format texFormat; GET_CURRENT_CONTEXT(ctx); @@ -849,7 +861,6 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level, } texObj = _mesa_select_tex_object(ctx, texUnit, target); - _mesa_lock_texture(ctx, texObj); img = _mesa_select_tex_image(ctx, texObj, target, level); if (!img || !img->TexFormat) { @@ -858,13 +869,11 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level, *params = 1; else *params = 0; - goto out; + return; } texFormat = img->TexFormat; - isProxy = _mesa_is_proxy_texture(target); - switch (pname) { case GL_TEXTURE_WIDTH: *params = img->Width; @@ -876,9 +885,9 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level, *params = img->Depth; break; case GL_TEXTURE_INTERNAL_FORMAT: - if (_mesa_is_format_compressed(img->TexFormat)) { + if (_mesa_is_format_compressed(texFormat)) { /* need to return the actual compressed format */ - *params = _mesa_compressed_format_to_glenum(ctx, img->TexFormat); + *params = _mesa_compressed_format_to_glenum(ctx, texFormat); } else { /* return the user's requested internal format */ @@ -949,8 +958,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level, if (ctx->Extensions.ARB_depth_texture) *params = _mesa_get_format_bits(texFormat, pname); else - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetTexLevelParameter[if]v(pname)"); + goto invalid_pname; break; case GL_TEXTURE_STENCIL_SIZE_EXT: if (ctx->Extensions.EXT_packed_depth_stencil || @@ -958,8 +966,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level, *params = _mesa_get_format_bits(texFormat, pname); } else { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetTexLevelParameter[if]v(pname)"); + goto invalid_pname; } break; case GL_TEXTURE_SHARED_SIZE: @@ -970,14 +977,14 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level, *params = 0; } else { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetTexLevelParameter[if]v(pname)"); + goto invalid_pname; } break; /* GL_ARB_texture_compression */ case GL_TEXTURE_COMPRESSED_IMAGE_SIZE: - if (_mesa_is_format_compressed(img->TexFormat) && !isProxy) { + if (_mesa_is_format_compressed(texFormat) && + !_mesa_is_proxy_texture(target)) { *params = _mesa_format_image_size(texFormat, img->Width, img->Height, img->Depth); } @@ -987,7 +994,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level, } break; case GL_TEXTURE_COMPRESSED: - *params = (GLint) _mesa_is_format_compressed(img->TexFormat); + *params = (GLint) _mesa_is_format_compressed(texFormat); break; /* GL_ARB_texture_float */ @@ -997,8 +1004,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level, _mesa_get_format_datatype(texFormat) : GL_NONE; } else { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetTexLevelParameter[if]v(pname)"); + goto invalid_pname; } break; case GL_TEXTURE_GREEN_TYPE_ARB: @@ -1007,8 +1013,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level, _mesa_get_format_datatype(texFormat) : GL_NONE; } else { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetTexLevelParameter[if]v(pname)"); + goto invalid_pname; } break; case GL_TEXTURE_BLUE_TYPE_ARB: @@ -1017,8 +1022,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level, _mesa_get_format_datatype(texFormat) : GL_NONE; } else { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetTexLevelParameter[if]v(pname)"); + goto invalid_pname; } break; case GL_TEXTURE_ALPHA_TYPE_ARB: @@ -1027,8 +1031,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level, _mesa_get_format_datatype(texFormat) : GL_NONE; } else { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetTexLevelParameter[if]v(pname)"); + goto invalid_pname; } break; case GL_TEXTURE_LUMINANCE_TYPE_ARB: @@ -1037,8 +1040,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level, _mesa_get_format_datatype(texFormat) : GL_NONE; } else { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetTexLevelParameter[if]v(pname)"); + goto invalid_pname; } break; case GL_TEXTURE_INTENSITY_TYPE_ARB: @@ -1047,8 +1049,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level, _mesa_get_format_datatype(texFormat) : GL_NONE; } else { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetTexLevelParameter[if]v(pname)"); + goto invalid_pname; } break; case GL_TEXTURE_DEPTH_TYPE_ARB: @@ -1057,18 +1058,21 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level, _mesa_get_format_datatype(texFormat) : GL_NONE; } else { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetTexLevelParameter[if]v(pname)"); + goto invalid_pname; } break; default: - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetTexLevelParameter[if]v(pname)"); + goto invalid_pname; } - out: - _mesa_unlock_texture(ctx, texObj); + /* no error if we get here */ + return; + +invalid_pname: + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetTexLevelParameter[if]v(pname=%s)", + _mesa_lookup_enum_by_nr(pname)); } diff --git a/src/mesa/main/uniforms.c b/src/mesa/main/uniforms.c index aee2e6b4e9b..eb289722d1a 100644 --- a/src/mesa/main/uniforms.c +++ b/src/mesa/main/uniforms.c @@ -450,6 +450,36 @@ _mesa_get_active_uniform(struct gl_context *ctx, GLuint program, GLuint index, } +static unsigned +get_vector_elements(GLenum type) +{ + switch (type) { + case GL_FLOAT: + case GL_INT: + case GL_BOOL: + case GL_UNSIGNED_INT: + default: /* Catch all the various sampler types. */ + return 1; + + case GL_FLOAT_VEC2: + case GL_INT_VEC2: + case GL_BOOL_VEC2: + case GL_UNSIGNED_INT_VEC2: + return 2; + + case GL_FLOAT_VEC3: + case GL_INT_VEC3: + case GL_BOOL_VEC3: + case GL_UNSIGNED_INT_VEC3: + return 3; + + case GL_FLOAT_VEC4: + case GL_INT_VEC4: + case GL_BOOL_VEC4: + case GL_UNSIGNED_INT_VEC4: + return 4; + } +} static void get_matrix_dims(GLenum type, GLint *rows, GLint *cols) @@ -508,17 +538,8 @@ get_uniform_rows_cols(const struct gl_program_parameter *p, get_matrix_dims(p->DataType, rows, cols); if (*rows == 0 && *cols == 0) { /* not a matrix type, probably a float or vector */ - if (p->Size <= 4) { - *rows = 1; - *cols = p->Size; - } - else { - *rows = (p->Size + 3) / 4; - if (p->Size % 4 == 0) - *cols = 4; - else - *cols = p->Size % 4; - } + *rows = 1; + *cols = get_vector_elements(p->DataType); } } @@ -642,8 +663,10 @@ _mesa_get_uniformfv(struct gl_context *ctx, GLuint program, GLint location, k = 0; for (i = 0; i < rows; i++) { + const int base = paramPos + offset + i; + for (j = 0; j < cols; j++ ) { - params[k++] = prog->Parameters->ParameterValues[paramPos+i][j]; + params[k++] = prog->Parameters->ParameterValues[base][j]; } } } @@ -675,8 +698,10 @@ _mesa_get_uniformiv(struct gl_context *ctx, GLuint program, GLint location, k = 0; for (i = 0; i < rows; i++) { + const int base = paramPos + offset + i; + for (j = 0; j < cols; j++ ) { - params[k++] = (GLint) prog->Parameters->ParameterValues[paramPos+i][j]; + params[k++] = (GLint) prog->Parameters->ParameterValues[base][j]; } } } @@ -709,8 +734,10 @@ _mesa_get_uniformuiv(struct gl_context *ctx, GLuint program, GLint location, k = 0; for (i = 0; i < rows; i++) { + const int base = paramPos + offset + i; + for (j = 0; j < cols; j++ ) { - params[k++] = (GLuint) prog->Parameters->ParameterValues[paramPos+i][j]; + params[k++] = (GLuint) prog->Parameters->ParameterValues[base][j]; } } } diff --git a/src/mesa/main/varray.c b/src/mesa/main/varray.c index 29d8a8827e3..cfed4b506a5 100644 --- a/src/mesa/main/varray.c +++ b/src/mesa/main/varray.c @@ -508,7 +508,7 @@ get_vertex_array_attrib(struct gl_context *ctx, GLuint index, GLenum pname, { const struct gl_client_array *array; - if (index >= MAX_VERTEX_GENERIC_ATTRIBS) { + if (index >= ctx->Const.VertexProgram.MaxAttribs) { _mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%u)", caller, index); return 0; } @@ -550,6 +550,25 @@ error: } +static const GLfloat * +get_current_attrib(struct gl_context *ctx, GLuint index, const char *function) +{ + if (index == 0) { + if (ctx->API != API_OPENGLES2) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(index==0)", function); + return NULL; + } + } + else if (index >= ctx->Const.VertexProgram.MaxAttribs) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(index>=GL_MAX_VERTEX_ATTRIBS)", function); + return NULL; + } + + FLUSH_CURRENT(ctx, 0); + return ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index]; +} + void GLAPIENTRY _mesa_GetVertexAttribfvARB(GLuint index, GLenum pname, GLfloat *params) { @@ -557,13 +576,8 @@ _mesa_GetVertexAttribfvARB(GLuint index, GLenum pname, GLfloat *params) ASSERT_OUTSIDE_BEGIN_END(ctx); if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) { - if (index == 0) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetVertexAttribfv(index==0)"); - } - else { - const GLfloat *v = ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index]; - FLUSH_CURRENT(ctx, 0); + const GLfloat *v = get_current_attrib(ctx, index, "glGetVertexAttribfv"); + if (v != NULL) { COPY_4V(params, v); } } @@ -581,13 +595,8 @@ _mesa_GetVertexAttribdvARB(GLuint index, GLenum pname, GLdouble *params) ASSERT_OUTSIDE_BEGIN_END(ctx); if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) { - if (index == 0) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetVertexAttribdv(index==0)"); - } - else { - const GLfloat *v = ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index]; - FLUSH_CURRENT(ctx, 0); + const GLfloat *v = get_current_attrib(ctx, index, "glGetVertexAttribdv"); + if (v != NULL) { params[0] = (GLdouble) v[0]; params[1] = (GLdouble) v[1]; params[2] = (GLdouble) v[2]; @@ -608,13 +617,8 @@ _mesa_GetVertexAttribivARB(GLuint index, GLenum pname, GLint *params) ASSERT_OUTSIDE_BEGIN_END(ctx); if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) { - if (index == 0) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetVertexAttribiv(index==0)"); - } - else { - const GLfloat *v = ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index]; - FLUSH_CURRENT(ctx, 0); + const GLfloat *v = get_current_attrib(ctx, index, "glGetVertexAttribiv"); + if (v != NULL) { /* XXX should floats in[0,1] be scaled to full int range? */ params[0] = (GLint) v[0]; params[1] = (GLint) v[1]; @@ -637,13 +641,9 @@ _mesa_GetVertexAttribIiv(GLuint index, GLenum pname, GLint *params) ASSERT_OUTSIDE_BEGIN_END(ctx); if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) { - if (index == 0) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetVertexAttribIiv(index==0)"); - } - else { - const GLfloat *v = ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index]; - FLUSH_CURRENT(ctx, 0); + const GLfloat *v = + get_current_attrib(ctx, index, "glGetVertexAttribIiv"); + if (v != NULL) { /* XXX we don't have true integer-valued vertex attribs yet */ params[0] = (GLint) v[0]; params[1] = (GLint) v[1]; @@ -666,13 +666,9 @@ _mesa_GetVertexAttribIuiv(GLuint index, GLenum pname, GLuint *params) ASSERT_OUTSIDE_BEGIN_END(ctx); if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) { - if (index == 0) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetVertexAttribIuiv(index==0)"); - } - else { - const GLfloat *v = ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index]; - FLUSH_CURRENT(ctx, 0); + const GLfloat *v = + get_current_attrib(ctx, index, "glGetVertexAttribIuiv"); + if (v != NULL) { /* XXX we don't have true integer-valued vertex attribs yet */ params[0] = (GLuint) v[0]; params[1] = (GLuint) v[1]; diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 786fdfbd231..33c262f8ca4 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -105,13 +105,13 @@ extern ir_to_mesa_src_reg ir_to_mesa_undef; class ir_to_mesa_instruction : public exec_node { public: - /* Callers of this talloc-based new need not call delete. It's - * easier to just talloc_free 'ctx' (or any of its ancestors). */ + /* Callers of this ralloc-based new need not call delete. It's + * easier to just ralloc_free 'ctx' (or any of its ancestors). */ static void* operator new(size_t size, void *ctx) { void *node; - node = talloc_zero_size(ctx, size); + node = rzalloc_size(ctx, size); assert(node != NULL); return node; @@ -318,7 +318,7 @@ fail_link(struct gl_shader_program *prog, const char *fmt, ...) { va_list args; va_start(args, fmt); - prog->InfoLog = talloc_vasprintf_append(prog->InfoLog, fmt, args); + ralloc_vasprintf_append(&prog->InfoLog, fmt, args); va_end(args); prog->LinkStatus = GL_FALSE; @@ -651,6 +651,7 @@ type_size(const struct glsl_type *type) return 1; } case GLSL_TYPE_ARRAY: + assert(type->length > 0); return type_size(type->fields.array) * type->length; case GLSL_TYPE_STRUCT: size = 0; @@ -726,6 +727,29 @@ ir_to_mesa_visitor::visit(ir_variable *ir) fp->OriginUpperLeft = ir->origin_upper_left; fp->PixelCenterInteger = ir->pixel_center_integer; + + } else if (strcmp(ir->name, "gl_FragDepth") == 0) { + struct gl_fragment_program *fp = (struct gl_fragment_program *)this->prog; + switch (ir->depth_layout) { + case ir_depth_layout_none: + fp->FragDepthLayout = FRAG_DEPTH_LAYOUT_NONE; + break; + case ir_depth_layout_any: + fp->FragDepthLayout = FRAG_DEPTH_LAYOUT_ANY; + break; + case ir_depth_layout_greater: + fp->FragDepthLayout = FRAG_DEPTH_LAYOUT_GREATER; + break; + case ir_depth_layout_less: + fp->FragDepthLayout = FRAG_DEPTH_LAYOUT_LESS; + break; + case ir_depth_layout_unchanged: + fp->FragDepthLayout = FRAG_DEPTH_LAYOUT_UNCHANGED; + break; + default: + assert(0); + break; + } } if (ir->mode == ir_var_uniform && strncmp(ir->name, "gl_", 3) == 0) { @@ -1451,18 +1475,17 @@ void ir_to_mesa_visitor::visit(ir_dereference_variable *ir) { variable_storage *entry = find_variable_storage(ir->var); + ir_variable *var = ir->var; if (!entry) { - switch (ir->var->mode) { + switch (var->mode) { case ir_var_uniform: - entry = new(mem_ctx) variable_storage(ir->var, PROGRAM_UNIFORM, - ir->var->location); + entry = new(mem_ctx) variable_storage(var, PROGRAM_UNIFORM, + var->location); this->variables.push_tail(entry); break; case ir_var_in: - case ir_var_out: case ir_var_inout: - case ir_var_system_value: /* The linker assigns locations for varyings and attributes, * including deprecated builtins (like gl_Color), user-assign * generic attributes (glBindVertexLocation), and @@ -1470,49 +1493,47 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir) * * FINISHME: We would hit this path for function arguments. Fix! */ - assert(ir->var->location != -1); - if (ir->var->mode == ir_var_in || - ir->var->mode == ir_var_inout) { - entry = new(mem_ctx) variable_storage(ir->var, - PROGRAM_INPUT, - ir->var->location); - - if (this->prog->Target == GL_VERTEX_PROGRAM_ARB && - ir->var->location >= VERT_ATTRIB_GENERIC0) { - _mesa_add_attribute(prog->Attributes, - ir->var->name, - _mesa_sizeof_glsl_type(ir->var->type->gl_type), - ir->var->type->gl_type, - ir->var->location - VERT_ATTRIB_GENERIC0); - } - } else if (ir->var->mode == ir_var_system_value) { - entry = new(mem_ctx) variable_storage(ir->var, - PROGRAM_SYSTEM_VALUE, - ir->var->location); - } else { - entry = new(mem_ctx) variable_storage(ir->var, - PROGRAM_OUTPUT, - ir->var->location); - } - + assert(var->location != -1); + entry = new(mem_ctx) variable_storage(var, + PROGRAM_INPUT, + var->location); + if (this->prog->Target == GL_VERTEX_PROGRAM_ARB && + var->location >= VERT_ATTRIB_GENERIC0) { + _mesa_add_attribute(this->prog->Attributes, + var->name, + _mesa_sizeof_glsl_type(var->type->gl_type), + var->type->gl_type, + var->location - VERT_ATTRIB_GENERIC0); + } + break; + case ir_var_out: + assert(var->location != -1); + entry = new(mem_ctx) variable_storage(var, + PROGRAM_OUTPUT, + var->location); break; + case ir_var_system_value: + entry = new(mem_ctx) variable_storage(var, + PROGRAM_SYSTEM_VALUE, + var->location); + break; case ir_var_auto: case ir_var_temporary: - entry = new(mem_ctx) variable_storage(ir->var, PROGRAM_TEMPORARY, + entry = new(mem_ctx) variable_storage(var, PROGRAM_TEMPORARY, this->next_temp); this->variables.push_tail(entry); - next_temp += type_size(ir->var->type); + next_temp += type_size(var->type); break; } if (!entry) { - printf("Failed to make storage for %s\n", ir->var->name); + printf("Failed to make storage for %s\n", var->name); exit(1); } } - this->result = ir_to_mesa_src_reg(entry->file, entry->index, ir->var->type); + this->result = ir_to_mesa_src_reg(entry->file, entry->index, var->type); } void @@ -1549,7 +1570,7 @@ ir_to_mesa_visitor::visit(ir_dereference_array *ir) this->result, src_reg_for_float(element_size)); } - src_reg.reladdr = talloc(mem_ctx, ir_to_mesa_src_reg); + src_reg.reladdr = ralloc(mem_ctx, ir_to_mesa_src_reg); memcpy(src_reg.reladdr, &index_reg, sizeof(index_reg)); } @@ -1906,7 +1927,7 @@ ir_to_mesa_visitor::get_function_signature(ir_function_signature *sig) return entry; } - entry = talloc(mem_ctx, function_entry); + entry = ralloc(mem_ctx, function_entry); entry->sig = sig; entry->sig_id = this->next_signature_id++; entry->bgn_inst = NULL; @@ -2243,12 +2264,12 @@ ir_to_mesa_visitor::ir_to_mesa_visitor() next_temp = 1; next_signature_id = 1; current_function = NULL; - mem_ctx = talloc_new(NULL); + mem_ctx = ralloc_context(NULL); } ir_to_mesa_visitor::~ir_to_mesa_visitor() { - talloc_free(mem_ctx); + ralloc_free(mem_ctx); } static struct prog_src_register @@ -2297,8 +2318,8 @@ set_branchtargets(ir_to_mesa_visitor *v, } } - if_stack = talloc_zero_array(v->mem_ctx, int, if_count); - loop_stack = talloc_zero_array(v->mem_ctx, int, loop_count); + if_stack = rzalloc_array(v->mem_ctx, int, if_count); + loop_stack = rzalloc_array(v->mem_ctx, int, loop_count); for (i = 0; i < num_instructions; i++) { switch (mesa_instructions[i].Opcode) { @@ -2441,7 +2462,7 @@ add_uniforms_to_parameters_list(struct gl_shader_program *shader_program, unsigned int next_sampler = 0, num_uniforms = 0; struct uniform_sort *sorted_uniforms; - sorted_uniforms = talloc_array(NULL, struct uniform_sort, + sorted_uniforms = ralloc_array(NULL, struct uniform_sort, shader_program->Uniforms->NumUniforms); for (i = 0; i < shader_program->Uniforms->NumUniforms; i++) { @@ -2520,7 +2541,7 @@ add_uniforms_to_parameters_list(struct gl_shader_program *shader_program, } } - talloc_free(sorted_uniforms); + ralloc_free(sorted_uniforms); } static void @@ -2536,7 +2557,7 @@ set_uniform_initializer(struct gl_context *ctx, void *mem_ctx, for (unsigned int i = 0; i < type->length; i++) { const glsl_type *field_type = type->fields.structure[i].type; - const char *field_name = talloc_asprintf(mem_ctx, "%s.%s", name, + const char *field_name = ralloc_asprintf(mem_ctx, "%s.%s", name, type->fields.structure[i].name); set_uniform_initializer(ctx, mem_ctx, shader_program, field_name, field_type, field_constant); @@ -2567,7 +2588,7 @@ set_uniform_initializer(struct gl_context *ctx, void *mem_ctx, void *values; if (element_type->base_type == GLSL_TYPE_BOOL) { - int *conv = talloc_array(mem_ctx, int, element_type->components()); + int *conv = ralloc_array(mem_ctx, int, element_type->components()); for (unsigned int j = 0; j < element_type->components(); j++) { conv[j] = element->value.b[j]; } @@ -2613,14 +2634,14 @@ set_uniform_initializers(struct gl_context *ctx, continue; if (!mem_ctx) - mem_ctx = talloc_new(NULL); + mem_ctx = ralloc_context(NULL); set_uniform_initializer(ctx, mem_ctx, shader_program, var->name, var->type, var->constant_value); } } - talloc_free(mem_ctx); + ralloc_free(mem_ctx); } /* @@ -2646,13 +2667,18 @@ set_uniform_initializers(struct gl_context *ctx, void ir_to_mesa_visitor::copy_propagate(void) { - ir_to_mesa_instruction **acp = talloc_zero_array(mem_ctx, + ir_to_mesa_instruction **acp = rzalloc_array(mem_ctx, ir_to_mesa_instruction *, this->next_temp * 4); + int *acp_level = rzalloc_array(mem_ctx, int, this->next_temp * 4); + int level = 0; foreach_iter(exec_list_iterator, iter, this->instructions) { ir_to_mesa_instruction *inst = (ir_to_mesa_instruction *)iter.get(); + assert(inst->dst_reg.file != PROGRAM_TEMPORARY + || inst->dst_reg.index < this->next_temp); + /* First, do any copy propagation possible into the src regs. */ for (int r = 0; r < 3; r++) { ir_to_mesa_instruction *first = NULL; @@ -2676,6 +2702,8 @@ ir_to_mesa_visitor::copy_propagate(void) break; } + assert(acp_level[acp_base + src_chan] <= level); + if (!first) { first = copy_chan; } else { @@ -2708,23 +2736,79 @@ ir_to_mesa_visitor::copy_propagate(void) switch (inst->op) { case OPCODE_BGNLOOP: case OPCODE_ENDLOOP: - case OPCODE_ELSE: - case OPCODE_ENDIF: /* End of a basic block, clear the ACP entirely. */ memset(acp, 0, sizeof(*acp) * this->next_temp * 4); break; + case OPCODE_IF: + ++level; + break; + + case OPCODE_ENDIF: + case OPCODE_ELSE: + /* Clear all channels written inside the block from the ACP, but + * leaving those that were not touched. + */ + for (int r = 0; r < this->next_temp; r++) { + for (int c = 0; c < 4; c++) { + if (!acp[4 * r + c]) + continue; + + if (acp_level[4 * r + c] >= level) + acp[4 * r + c] = NULL; + } + } + if (inst->op == OPCODE_ENDIF) + --level; + break; + default: /* Continuing the block, clear any written channels from * the ACP. */ - if (inst->dst_reg.file == PROGRAM_TEMPORARY) { - if (inst->dst_reg.reladdr) { - memset(acp, 0, sizeof(*acp) * this->next_temp * 4); - } else { - for (int i = 0; i < 4; i++) { - if (inst->dst_reg.writemask & (1 << i)) { - acp[4 * inst->dst_reg.index + i] = NULL; + if (inst->dst_reg.file == PROGRAM_TEMPORARY && inst->dst_reg.reladdr) { + /* Any temporary might be written, so no copy propagation + * across this instruction. + */ + memset(acp, 0, sizeof(*acp) * this->next_temp * 4); + } else if (inst->dst_reg.file == PROGRAM_OUTPUT && + inst->dst_reg.reladdr) { + /* Any output might be written, so no copy propagation + * from outputs across this instruction. + */ + for (int r = 0; r < this->next_temp; r++) { + for (int c = 0; c < 4; c++) { + if (!acp[4 * r + c]) + continue; + + if (acp[4 * r + c]->src_reg[0].file == PROGRAM_OUTPUT) + acp[4 * r + c] = NULL; + } + } + } else if (inst->dst_reg.file == PROGRAM_TEMPORARY || + inst->dst_reg.file == PROGRAM_OUTPUT) { + /* Clear where it's used as dst. */ + if (inst->dst_reg.file == PROGRAM_TEMPORARY) { + for (int c = 0; c < 4; c++) { + if (inst->dst_reg.writemask & (1 << c)) { + acp[4 * inst->dst_reg.index + c] = NULL; + } + } + } + + /* Clear where it's used as src. */ + for (int r = 0; r < this->next_temp; r++) { + for (int c = 0; c < 4; c++) { + if (!acp[4 * r + c]) + continue; + + int src_chan = GET_SWZ(acp[4 * r + c]->src_reg[0].swizzle, c); + + if (acp[4 * r + c]->src_reg[0].file == inst->dst_reg.file && + acp[4 * r + c]->src_reg[0].index == inst->dst_reg.index && + inst->dst_reg.writemask & (1 << src_chan)) + { + acp[4 * r + c] = NULL; } } } @@ -2742,12 +2826,14 @@ ir_to_mesa_visitor::copy_propagate(void) for (int i = 0; i < 4; i++) { if (inst->dst_reg.writemask & (1 << i)) { acp[4 * inst->dst_reg.index + i] = inst; + acp_level[4 * inst->dst_reg.index + i] = level; } } } } - talloc_free(acp); + ralloc_free(acp_level); + ralloc_free(acp); } @@ -2846,7 +2932,7 @@ get_mesa_program(struct gl_context *ctx, mesa_instructions = (struct prog_instruction *)calloc(num_instructions, sizeof(*mesa_instructions)); - mesa_instruction_annotation = talloc_array(v.mem_ctx, ir_instruction *, + mesa_instruction_annotation = ralloc_array(v.mem_ctx, ir_instruction *, num_instructions); v.copy_propagate(); @@ -3103,7 +3189,7 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader) _mesa_glsl_lexer_dtor(state); } - talloc_free(shader->ir); + ralloc_free(shader->ir); shader->ir = new(shader) exec_list; if (!state->error && !state->translation_unit.is_empty()) _mesa_ast_to_hir(shader->ir, state); @@ -3150,7 +3236,7 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader) /* Retain any live IR, but trash the rest. */ reparent_ir(shader->ir, shader->ir); - talloc_free(state); + ralloc_free(state); if (shader->CompileStatus) { if (!ctx->Driver.CompileShader(ctx, shader)) diff --git a/src/mesa/program/register_allocate.c b/src/mesa/program/register_allocate.c index f984e2f1402..95a9bde401a 100644 --- a/src/mesa/program/register_allocate.c +++ b/src/mesa/program/register_allocate.c @@ -30,7 +30,7 @@ * Graph-coloring register allocator. */ -#include <talloc.h> +#include <ralloc.h> #include "main/imports.h" #include "main/macros.h" @@ -96,15 +96,15 @@ ra_alloc_reg_set(unsigned int count) unsigned int i; struct ra_regs *regs; - regs = talloc_zero(NULL, struct ra_regs); + regs = rzalloc(NULL, struct ra_regs); regs->count = count; - regs->regs = talloc_zero_array(regs, struct ra_reg, count); + regs->regs = rzalloc_array(regs, struct ra_reg, count); for (i = 0; i < count; i++) { - regs->regs[i].conflicts = talloc_zero_array(regs->regs, GLboolean, count); + regs->regs[i].conflicts = rzalloc_array(regs->regs, GLboolean, count); regs->regs[i].conflicts[i] = GL_TRUE; - regs->regs[i].conflict_list = talloc_array(regs->regs, unsigned int, 4); + regs->regs[i].conflict_list = ralloc_array(regs->regs, unsigned int, 4); regs->regs[i].conflict_list_size = 4; regs->regs[i].conflict_list[0] = i; regs->regs[i].num_conflicts = 1; @@ -120,10 +120,8 @@ ra_add_conflict_list(struct ra_regs *regs, unsigned int r1, unsigned int r2) if (reg1->conflict_list_size == reg1->num_conflicts) { reg1->conflict_list_size *= 2; - reg1->conflict_list = talloc_realloc(regs, - reg1->conflict_list, - unsigned int, - reg1->conflict_list_size); + reg1->conflict_list = reralloc(regs->regs, reg1->conflict_list, + unsigned int, reg1->conflict_list_size); } reg1->conflict_list[reg1->num_conflicts++] = r2; reg1->conflicts[r2] = GL_TRUE; @@ -143,14 +141,13 @@ ra_alloc_reg_class(struct ra_regs *regs) { struct ra_class *class; - regs->classes = talloc_realloc(regs, regs->classes, - struct ra_class *, - regs->class_count + 1); + regs->classes = reralloc(regs->regs, regs->classes, struct ra_class *, + regs->class_count + 1); - class = talloc_zero(regs, struct ra_class); + class = rzalloc(regs, struct ra_class); regs->classes[regs->class_count] = class; - class->regs = talloc_zero_array(class, GLboolean, regs->count); + class->regs = rzalloc_array(class, GLboolean, regs->count); return regs->class_count++; } @@ -174,7 +171,7 @@ ra_set_finalize(struct ra_regs *regs) unsigned int b, c; for (b = 0; b < regs->class_count; b++) { - regs->classes[b]->q = talloc_array(regs, unsigned int, regs->class_count); + regs->classes[b]->q = ralloc_array(regs, unsigned int, regs->class_count); } /* Compute, for each class B and C, how many regs of B an @@ -218,16 +215,16 @@ ra_alloc_interference_graph(struct ra_regs *regs, unsigned int count) struct ra_graph *g; unsigned int i; - g = talloc_zero(regs, struct ra_graph); + g = rzalloc(regs, struct ra_graph); g->regs = regs; - g->nodes = talloc_zero_array(g, struct ra_node, count); + g->nodes = rzalloc_array(g, struct ra_node, count); g->count = count; - g->stack = talloc_zero_array(g, unsigned int, count); + g->stack = rzalloc_array(g, unsigned int, count); for (i = 0; i < count; i++) { - g->nodes[i].adjacency = talloc_zero_array(g, GLboolean, count); - g->nodes[i].adjacency_list = talloc_array(g, unsigned int, count); + g->nodes[i].adjacency = rzalloc_array(g, GLboolean, count); + g->nodes[i].adjacency_list = ralloc_array(g, unsigned int, count); g->nodes[i].adjacency_count = 0; ra_add_node_adjacency(g, i, i); g->nodes[i].reg = ~0; diff --git a/src/mesa/program/sampler.cpp b/src/mesa/program/sampler.cpp index 9a813c87955..1457d1199fa 100644 --- a/src/mesa/program/sampler.cpp +++ b/src/mesa/program/sampler.cpp @@ -23,7 +23,6 @@ * DEALINGS IN THE SOFTWARE. */ -#include <cstdio> #include "ir.h" #include "glsl_types.h" #include "ir_visitor.h" @@ -40,7 +39,7 @@ static void fail_link(struct gl_shader_program *prog, const char *fmt, ...) { va_list args; va_start(args, fmt); - prog->InfoLog = talloc_vasprintf_append(prog->InfoLog, fmt, args); + ralloc_vasprintf_append(&prog->InfoLog, fmt, args); va_end(args); prog->LinkStatus = GL_FALSE; @@ -52,7 +51,7 @@ public: get_sampler_name(ir_dereference *last, struct gl_shader_program *shader_program) { - this->mem_ctx = talloc_new(NULL); + this->mem_ctx = ralloc_context(NULL); this->shader_program = shader_program; this->name = NULL; this->offset = 0; @@ -61,7 +60,7 @@ public: ~get_sampler_name() { - talloc_free(this->mem_ctx); + ralloc_free(this->mem_ctx); } virtual ir_visitor_status visit(ir_dereference_variable *ir) @@ -72,7 +71,7 @@ public: virtual ir_visitor_status visit_leave(ir_dereference_record *ir) { - this->name = talloc_asprintf(mem_ctx, "%s.%s", name, ir->field); + this->name = ralloc_asprintf(mem_ctx, "%s.%s", name, ir->field); return visit_continue; } @@ -91,16 +90,14 @@ public: * all that would work would be an unrolled loop counter that ends * up being constant above. */ - shader_program->InfoLog = - talloc_asprintf_append(shader_program->InfoLog, - "warning: Variable sampler array index " - "unsupported.\nThis feature of the language " - "was removed in GLSL 1.20 and is unlikely " - "to be supported for 1.10 in Mesa.\n"); + ralloc_strcat(&shader_program->InfoLog, + "warning: Variable sampler array index unsupported.\n" + "This feature of the language was removed in GLSL 1.20 " + "and is unlikely to be supported for 1.10 in Mesa.\n"); i = 0; } if (ir != last) { - this->name = talloc_asprintf(mem_ctx, "%s[%d]", name, i); + this->name = ralloc_asprintf(mem_ctx, "%s[%d]", name, i); } else { offset = i; } diff --git a/src/mesa/state_tracker/st_atom_blend.c b/src/mesa/state_tracker/st_atom_blend.c index 8a3609e569f..fb1c7a4efee 100644 --- a/src/mesa/state_tracker/st_atom_blend.c +++ b/src/mesa/state_tracker/st_atom_blend.c @@ -191,7 +191,7 @@ update_blend( struct st_context *st ) { struct pipe_blend_state *blend = &st->state.blend; unsigned num_state = 1; - unsigned i; + unsigned i, j; memset(blend, 0, sizeof(*blend)); @@ -214,12 +214,15 @@ update_blend( struct st_context *st ) } else if (st->ctx->Color.BlendEnabled) { /* blending enabled */ - for (i = 0; i < num_state; i++) { + for (i = 0, j = 0; i < num_state; i++) { blend->rt[i].blend_enable = (st->ctx->Color.BlendEnabled >> i) & 0x1; + if (st->ctx->Extensions.ARB_draw_buffers_blend) + j = i; + blend->rt[i].rgb_func = - translate_blend(st->ctx->Color.Blend[i].EquationRGB); + translate_blend(st->ctx->Color.Blend[j].EquationRGB); if (st->ctx->Color.Blend[i].EquationRGB == GL_MIN || st->ctx->Color.Blend[i].EquationRGB == GL_MAX) { @@ -229,13 +232,13 @@ update_blend( struct st_context *st ) } else { blend->rt[i].rgb_src_factor = - translate_blend(st->ctx->Color.Blend[i].SrcRGB); + translate_blend(st->ctx->Color.Blend[j].SrcRGB); blend->rt[i].rgb_dst_factor = - translate_blend(st->ctx->Color.Blend[i].DstRGB); + translate_blend(st->ctx->Color.Blend[j].DstRGB); } blend->rt[i].alpha_func = - translate_blend(st->ctx->Color.Blend[i].EquationA); + translate_blend(st->ctx->Color.Blend[j].EquationA); if (st->ctx->Color.Blend[i].EquationA == GL_MIN || st->ctx->Color.Blend[i].EquationA == GL_MAX) { @@ -245,9 +248,9 @@ update_blend( struct st_context *st ) } else { blend->rt[i].alpha_src_factor = - translate_blend(st->ctx->Color.Blend[i].SrcA); + translate_blend(st->ctx->Color.Blend[j].SrcA); blend->rt[i].alpha_dst_factor = - translate_blend(st->ctx->Color.Blend[i].DstA); + translate_blend(st->ctx->Color.Blend[j].DstA); } } } diff --git a/src/mesa/state_tracker/st_atom_framebuffer.c b/src/mesa/state_tracker/st_atom_framebuffer.c index 2843b7b1764..76386fe017a 100644 --- a/src/mesa/state_tracker/st_atom_framebuffer.c +++ b/src/mesa/state_tracker/st_atom_framebuffer.c @@ -39,7 +39,7 @@ #include "cso_cache/cso_context.h" #include "util/u_math.h" #include "util/u_inlines.h" - +#include "util/u_format.h" /** @@ -55,8 +55,10 @@ update_renderbuffer_surface(struct st_context *st, struct pipe_resource *resource = strb->rtt->pt; int rtt_width = strb->Base.Width; int rtt_height = strb->Base.Height; + enum pipe_format format = st->ctx->Color.sRGBEnabled ? resource->format : util_format_linear(resource->format); if (!strb->surface || + strb->surface->format != format || strb->surface->texture != resource || strb->surface->width != rtt_width || strb->surface->height != rtt_height) { @@ -67,7 +69,7 @@ update_renderbuffer_surface(struct st_context *st, u_minify(resource->height0, level) == rtt_height) { struct pipe_surface surf_tmpl; memset(&surf_tmpl, 0, sizeof(surf_tmpl)); - surf_tmpl.format = resource->format; + surf_tmpl.format = format; surf_tmpl.usage = PIPE_BIND_RENDER_TARGET; surf_tmpl.u.tex.level = level; surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice; diff --git a/src/mesa/state_tracker/st_atom_pixeltransfer.c b/src/mesa/state_tracker/st_atom_pixeltransfer.c index 378b30e57cc..739a2eaab7e 100644 --- a/src/mesa/state_tracker/st_atom_pixeltransfer.c +++ b/src/mesa/state_tracker/st_atom_pixeltransfer.c @@ -99,7 +99,7 @@ create_color_map_texture(struct gl_context *ctx) /* create texture for color map/table */ pt = st_texture_create(st, PIPE_TEXTURE_2D, format, 0, - texSize, texSize, 1, PIPE_BIND_SAMPLER_VIEW); + texSize, texSize, 1, 1, PIPE_BIND_SAMPLER_VIEW); return pt; } diff --git a/src/mesa/state_tracker/st_atom_rasterizer.c b/src/mesa/state_tracker/st_atom_rasterizer.c index f92ca13d5e4..8bccceeec53 100644 --- a/src/mesa/state_tracker/st_atom_rasterizer.c +++ b/src/mesa/state_tracker/st_atom_rasterizer.c @@ -70,14 +70,16 @@ static void update_raster_state( struct st_context *st ) { raster->front_ccw = (ctx->Polygon.FrontFace == GL_CCW); - /* XXX - * I think the intention here is that user-created framebuffer objects - * use Y=0=TOP layout instead of OpenGL's normal Y=0=bottom layout. - * Flipping Y changes CW to CCW and vice-versa. - * But this is an implementation/driver-specific artifact - remove... + /* + * Gallium's surfaces are Y=0=TOP orientation. OpenGL is the + * opposite. Window system surfaces are Y=0=TOP. Mesa's FBOs + * must match OpenGL conventions so FBOs use Y=0=BOTTOM. In that + * case, we must invert Y and flip the notion of front vs. back. */ - if (ctx->DrawBuffer && ctx->DrawBuffer->Name != 0) + if (st_fb_orientation(ctx->DrawBuffer) == Y_0_BOTTOM) { + /* Drawing to an FBO. The viewport will be inverted. */ raster->front_ccw ^= 1; + } } /* _NEW_LIGHT diff --git a/src/mesa/state_tracker/st_atom_sampler.c b/src/mesa/state_tracker/st_atom_sampler.c index b67068df373..474cbd5897d 100644 --- a/src/mesa/state_tracker/st_atom_sampler.c +++ b/src/mesa/state_tracker/st_atom_sampler.c @@ -36,6 +36,7 @@ #include "st_context.h" #include "st_cb_texture.h" +#include "st_format.h" #include "st_atom.h" #include "pipe/p_context.h" #include "pipe/p_defines.h" @@ -117,49 +118,6 @@ gl_filter_to_img_filter(GLenum filter) } -static void -xlate_border_color(const GLfloat *colorIn, GLenum baseFormat, GLfloat *colorOut) -{ - switch (baseFormat) { - case GL_RED: - colorOut[0] = colorIn[0]; - colorOut[1] = 0.0F; - colorOut[2] = 0.0F; - colorOut[3] = 1.0F; - break; - case GL_RG: - colorOut[0] = colorIn[0]; - colorOut[1] = colorIn[1]; - colorOut[2] = 0.0F; - colorOut[3] = 1.0F; - break; - case GL_RGB: - colorOut[0] = colorIn[0]; - colorOut[1] = colorIn[1]; - colorOut[2] = colorIn[2]; - colorOut[3] = 1.0F; - break; - case GL_ALPHA: - colorOut[0] = colorOut[1] = colorOut[2] = 0.0; - colorOut[3] = colorIn[3]; - break; - case GL_LUMINANCE: - colorOut[0] = colorOut[1] = colorOut[2] = colorIn[0]; - colorOut[3] = 1.0; - break; - case GL_LUMINANCE_ALPHA: - colorOut[0] = colorOut[1] = colorOut[2] = colorIn[0]; - colorOut[3] = colorIn[3]; - break; - case GL_INTENSITY: - colorOut[0] = colorOut[1] = colorOut[2] = colorOut[3] = colorIn[0]; - break; - default: - COPY_4V(colorOut, colorIn); - } -} - - static void update_samplers(struct st_context *st) { @@ -223,7 +181,7 @@ update_samplers(struct st_context *st) assert(sampler->min_lod <= sampler->max_lod); } - xlate_border_color(texobj->BorderColor.f, + st_translate_color(texobj->BorderColor.f, teximg ? teximg->_BaseFormat : GL_RGBA, sampler->border_color); diff --git a/src/mesa/state_tracker/st_atom_viewport.c b/src/mesa/state_tracker/st_atom_viewport.c index d10f1840df6..133cc49eaf0 100644 --- a/src/mesa/state_tracker/st_atom_viewport.c +++ b/src/mesa/state_tracker/st_atom_viewport.c @@ -47,10 +47,14 @@ update_viewport( struct st_context *st ) /* _NEW_BUFFERS */ if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { + /* Drawing to a window. The corresponding gallium surface uses + * Y=0=TOP but OpenGL is Y=0=BOTTOM. So we need to invert the viewport. + */ yScale = -1; yBias = (GLfloat)ctx->DrawBuffer->Height; } else { + /* Drawing to an FBO where Y=0=BOTTOM, like OpenGL - don't invert */ yScale = 1.0; yBias = 0.0; } diff --git a/src/mesa/state_tracker/st_cb_accum.c b/src/mesa/state_tracker/st_cb_accum.c index 35921f4f614..3e01c440bda 100644 --- a/src/mesa/state_tracker/st_cb_accum.c +++ b/src/mesa/state_tracker/st_cb_accum.c @@ -42,6 +42,7 @@ #include "st_texture.h" #include "pipe/p_context.h" #include "pipe/p_defines.h" +#include "util/u_format.h" #include "util/u_inlines.h" #include "util/u_tile.h" @@ -146,7 +147,9 @@ accum_accum(struct st_context *st, GLfloat value, buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); - pipe_get_tile_rgba(pipe, color_trans, 0, 0, width, height, buf); + pipe_get_tile_rgba_format(pipe, color_trans, 0, 0, width, height, + util_format_linear(color_strb->texture->format), + buf); switch (acc_strb->format) { case PIPE_FORMAT_R16G16B16A16_SNORM: @@ -183,7 +186,6 @@ accum_load(struct st_context *st, GLfloat value, GLubyte *data = acc_strb->data; GLfloat *buf; - if (ST_DEBUG & DEBUG_FALLBACK) debug_printf("%s: fallback processing\n", __FUNCTION__); @@ -194,7 +196,9 @@ accum_load(struct st_context *st, GLfloat value, buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); - pipe_get_tile_rgba(pipe, color_trans, 0, 0, width, height, buf); + pipe_get_tile_rgba_format(pipe, color_trans, 0, 0, width, height, + util_format_linear(color_strb->texture->format), + buf); switch (acc_strb->format) { case PIPE_FORMAT_R16G16B16A16_SNORM: @@ -232,6 +236,7 @@ accum_return(struct gl_context *ctx, GLfloat value, size_t stride = acc_strb->stride; const GLubyte *data = acc_strb->data; GLfloat *buf; + enum pipe_format format = util_format_linear(color_strb->texture->format); if (ST_DEBUG & DEBUG_FALLBACK) debug_printf("%s: fallback processing\n", __FUNCTION__); @@ -250,7 +255,8 @@ accum_return(struct gl_context *ctx, GLfloat value, width, height); if (usage & PIPE_TRANSFER_READ) - pipe_get_tile_rgba(pipe, color_trans, 0, 0, width, height, buf); + pipe_get_tile_rgba_format(pipe, color_trans, 0, 0, width, height, + format, buf); switch (acc_strb->format) { case PIPE_FORMAT_R16G16B16A16_SNORM: @@ -279,7 +285,8 @@ accum_return(struct gl_context *ctx, GLfloat value, _mesa_problem(NULL, "unexpected format in st_clear_accum_buffer()"); } - pipe_put_tile_rgba(pipe, color_trans, 0, 0, width, height, buf); + pipe_put_tile_rgba_format(pipe, color_trans, 0, 0, width, height, + format, buf); free(buf); pipe->transfer_destroy(pipe, color_trans); diff --git a/src/mesa/state_tracker/st_cb_bitmap.c b/src/mesa/state_tracker/st_cb_bitmap.c index e23fe86daeb..0ea5671557c 100644 --- a/src/mesa/state_tracker/st_cb_bitmap.c +++ b/src/mesa/state_tracker/st_cb_bitmap.c @@ -276,7 +276,7 @@ make_bitmap_texture(struct gl_context *ctx, GLsizei width, GLsizei height, * Create texture to hold bitmap pattern. */ pt = st_texture_create(st, st->internal_target, st->bitmap.tex_format, - 0, width, height, 1, + 0, width, height, 1, 1, PIPE_BIND_SAMPLER_VIEW); if (!pt) { _mesa_unmap_pbo_source(ctx, unpack); @@ -349,6 +349,7 @@ setup_bitmap_vertex_data(struct st_context *st, bool normalized, if (!st->bitmap.vbuf) { st->bitmap.vbuf = pipe_buffer_create(pipe->screen, PIPE_BIND_VERTEX_BUFFER, + PIPE_USAGE_STREAM, max_slots * sizeof(st->bitmap.vertices)); } @@ -456,6 +457,7 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, cso_save_fragment_shader(cso); cso_save_vertex_shader(cso); cso_save_vertex_elements(cso); + cso_save_vertex_buffers(cso); /* rasterizer state: just scissor */ st->bitmap.rasterizer.scissor = ctx->Scissor.Enabled; @@ -517,7 +519,7 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, sv->texture->target != PIPE_TEXTURE_RECT, x, y, width, height, z, color); - util_draw_vertex_buffer(pipe, st->bitmap.vbuf, offset, + util_draw_vertex_buffer(pipe, st->cso_context, st->bitmap.vbuf, offset, PIPE_PRIM_TRIANGLE_FAN, 4, /* verts */ 3); /* attribs/vert */ @@ -531,6 +533,7 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, cso_restore_fragment_shader(cso); cso_restore_vertex_shader(cso); cso_restore_vertex_elements(cso); + cso_restore_vertex_buffers(cso); } @@ -559,7 +562,7 @@ reset_cache(struct st_context *st) cache->texture = st_texture_create(st, PIPE_TEXTURE_2D, st->bitmap.tex_format, 0, BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT, - 1, + 1, 1, PIPE_BIND_SAMPLER_VIEW); } diff --git a/src/mesa/state_tracker/st_cb_bufferobjects.c b/src/mesa/state_tracker/st_cb_bufferobjects.c index d4d9af4ada3..12528f49ff7 100644 --- a/src/mesa/state_tracker/st_cb_bufferobjects.c +++ b/src/mesa/state_tracker/st_cb_bufferobjects.c @@ -171,7 +171,7 @@ st_bufferobj_data(struct gl_context *ctx, struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; struct st_buffer_object *st_obj = st_buffer_object(obj); - unsigned buffer_usage; + unsigned bind, pipe_usage; st_obj->Base.Size = size; st_obj->Base.Usage = usage; @@ -179,22 +179,43 @@ st_bufferobj_data(struct gl_context *ctx, switch(target) { case GL_PIXEL_PACK_BUFFER_ARB: case GL_PIXEL_UNPACK_BUFFER_ARB: - buffer_usage = PIPE_BIND_RENDER_TARGET; + bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; break; case GL_ARRAY_BUFFER_ARB: - buffer_usage = PIPE_BIND_VERTEX_BUFFER; + bind = PIPE_BIND_VERTEX_BUFFER; break; case GL_ELEMENT_ARRAY_BUFFER_ARB: - buffer_usage = PIPE_BIND_INDEX_BUFFER; + bind = PIPE_BIND_INDEX_BUFFER; break; default: - buffer_usage = 0; + bind = 0; + } + + switch (usage) { + case GL_STATIC_DRAW: + case GL_STATIC_READ: + case GL_STATIC_COPY: + pipe_usage = PIPE_USAGE_STATIC; + break; + case GL_DYNAMIC_DRAW: + case GL_DYNAMIC_READ: + case GL_DYNAMIC_COPY: + pipe_usage = PIPE_USAGE_DYNAMIC; + break; + case GL_STREAM_DRAW: + case GL_STREAM_READ: + case GL_STREAM_COPY: + pipe_usage = PIPE_USAGE_STREAM; + break; + default: + pipe_usage = PIPE_USAGE_DEFAULT; } pipe_resource_reference( &st_obj->buffer, NULL ); if (size != 0) { - st_obj->buffer = pipe_buffer_create(pipe->screen, buffer_usage, size); + st_obj->buffer = pipe_buffer_create(pipe->screen, bind, + pipe_usage, size); if (!st_obj->buffer) { return GL_FALSE; diff --git a/src/mesa/state_tracker/st_cb_clear.c b/src/mesa/state_tracker/st_cb_clear.c index 6571bf237fb..0e0c4326ed7 100644 --- a/src/mesa/state_tracker/st_cb_clear.c +++ b/src/mesa/state_tracker/st_cb_clear.c @@ -42,6 +42,7 @@ #include "st_cb_accum.h" #include "st_cb_clear.h" #include "st_cb_fbo.h" +#include "st_format.h" #include "st_program.h" #include "pipe/p_context.h" @@ -138,6 +139,7 @@ draw_quad(struct st_context *st, if (!st->clear.vbuf) { st->clear.vbuf = pipe_buffer_create(pipe->screen, PIPE_BIND_VERTEX_BUFFER, + PIPE_USAGE_STREAM, max_slots * sizeof(st->clear.vertices)); } @@ -172,7 +174,8 @@ draw_quad(struct st_context *st, st->clear.vertices); /* draw */ - util_draw_vertex_buffer(pipe, + util_draw_vertex_buffer(pipe, + st->cso_context, st->clear.vbuf, st->clear.vbuf_slot * sizeof(st->clear.vertices), PIPE_PRIM_TRIANGLE_FAN, @@ -202,6 +205,7 @@ clear_with_quad(struct gl_context *ctx, const GLfloat x1 = (GLfloat) ctx->DrawBuffer->_Xmax / fb_width * 2.0f - 1.0f; const GLfloat y0 = (GLfloat) ctx->DrawBuffer->_Ymin / fb_height * 2.0f - 1.0f; const GLfloat y1 = (GLfloat) ctx->DrawBuffer->_Ymax / fb_height * 2.0f - 1.0f; + float clearColor[4]; /* printf("%s %s%s%s %f,%f %f,%f\n", __FUNCTION__, @@ -221,6 +225,7 @@ clear_with_quad(struct gl_context *ctx, cso_save_fragment_shader(st->cso_context); cso_save_vertex_shader(st->cso_context); cso_save_vertex_elements(st->cso_context); + cso_save_vertex_buffers(st->cso_context); /* blend state: RGBA masking */ { @@ -295,9 +300,14 @@ clear_with_quad(struct gl_context *ctx, cso_set_fragment_shader_handle(st->cso_context, st->clear.fs); cso_set_vertex_shader_handle(st->cso_context, st->clear.vs); - /* draw quad matching scissor rect (XXX verify coord round-off) */ - draw_quad(st, x0, y0, x1, y1, - (GLfloat) ctx->Depth.Clear, ctx->Color.ClearColor); + if (ctx->DrawBuffer->_ColorDrawBuffers[0]) { + st_translate_color(ctx->Color.ClearColor, + ctx->DrawBuffer->_ColorDrawBuffers[0]->_BaseFormat, + clearColor); + } + + /* draw quad matching scissor rect */ + draw_quad(st, x0, y0, x1, y1, (GLfloat) ctx->Depth.Clear, clearColor); /* Restore pipe state */ cso_restore_blend(st->cso_context); @@ -309,6 +319,7 @@ clear_with_quad(struct gl_context *ctx, cso_restore_fragment_shader(st->cso_context); cso_restore_vertex_shader(st->cso_context); cso_restore_vertex_elements(st->cso_context); + cso_restore_vertex_buffers(st->cso_context); } @@ -537,12 +548,21 @@ st_Clear(struct gl_context *ctx, GLbitfield mask) * required from the visual. Hence fix this up to avoid potential * read-modify-write in the driver. */ + float clearColor[4]; + if ((clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) && ((clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) && (depthRb == stencilRb) && (ctx->DrawBuffer->Visual.depthBits == 0 || ctx->DrawBuffer->Visual.stencilBits == 0)) clear_buffers |= PIPE_CLEAR_DEPTHSTENCIL; + + if (ctx->DrawBuffer->_ColorDrawBuffers[0]) { + st_translate_color(ctx->Color.ClearColor, + ctx->DrawBuffer->_ColorDrawBuffers[0]->_BaseFormat, + clearColor); + } + st->pipe->clear(st->pipe, clear_buffers, ctx->Color.ClearColor, ctx->Depth.Clear, ctx->Stencil.Clear); } diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c index d128ff98f02..c0da1696247 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/src/mesa/state_tracker/st_cb_drawpixels.c @@ -343,7 +343,7 @@ alloc_texture(struct st_context *st, GLsizei width, GLsizei height, struct pipe_resource *pt; pt = st_texture_create(st, st->internal_target, texFormat, 0, - width, height, 1, PIPE_BIND_SAMPLER_VIEW); + width, height, 1, 1, PIPE_BIND_SAMPLER_VIEW); return pt; } @@ -522,10 +522,11 @@ draw_quad(struct gl_context *ctx, GLfloat x0, GLfloat y0, GLfloat z, /* allocate/load buffer object with vertex data */ buf = pipe_buffer_create(pipe->screen, PIPE_BIND_VERTEX_BUFFER, + PIPE_USAGE_STATIC, sizeof(verts)); pipe_buffer_write(st->pipe, buf, 0, sizeof(verts), verts); - util_draw_vertex_buffer(pipe, buf, 0, + util_draw_vertex_buffer(pipe, st->cso_context, buf, 0, PIPE_PRIM_QUADS, 4, /* verts */ 3); /* attribs/vert */ @@ -570,6 +571,7 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, cso_save_fragment_shader(cso); cso_save_vertex_shader(cso); cso_save_vertex_elements(cso); + cso_save_vertex_buffers(cso); if (write_stencil) { cso_save_depth_stencil_alpha(cso); cso_save_blend(cso); @@ -686,6 +688,7 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, cso_restore_fragment_shader(cso); cso_restore_vertex_shader(cso); cso_restore_vertex_elements(cso); + cso_restore_vertex_buffers(cso); if (write_stencil) { cso_restore_depth_stencil_alpha(cso); cso_restore_blend(cso); @@ -1139,6 +1142,110 @@ copy_stencil_pixels(struct gl_context *ctx, GLint srcx, GLint srcy, } +/** Do the src/dest regions overlap? */ +static GLboolean +regions_overlap(GLint srcX, GLint srcY, GLint dstX, GLint dstY, + GLsizei width, GLsizei height) +{ + if (srcX + width <= dstX || + dstX + width <= srcX || + srcY + height <= dstY || + dstY + height <= srcY) + return GL_FALSE; + else + return GL_TRUE; +} + + +/** + * Try to do a glCopyPixels for simple cases with a blit by calling + * pipe->resource_copy_region(). + * + * We can do this when we're copying color pixels (depth/stencil + * eventually) with no pixel zoom, no pixel transfer ops, no + * per-fragment ops, the src/dest regions don't overlap and the + * src/dest pixel formats are the same. + */ +static GLboolean +blit_copy_pixels(struct gl_context *ctx, GLint srcx, GLint srcy, + GLsizei width, GLsizei height, + GLint dstx, GLint dsty, GLenum type) +{ + struct st_context *st = st_context(ctx); + struct pipe_context *pipe = st->pipe; + struct gl_pixelstore_attrib pack, unpack; + GLint readX, readY, readW, readH; + + if (type == GL_COLOR && + ctx->Pixel.ZoomX == 1.0 && + ctx->Pixel.ZoomY == 1.0 && + ctx->_ImageTransferState == 0x0 && + !ctx->Color.BlendEnabled && + !ctx->Color.AlphaEnabled && + !ctx->Depth.Test && + !ctx->Fog.Enabled && + !ctx->Stencil.Enabled && + !ctx->FragmentProgram.Enabled && + !ctx->VertexProgram.Enabled && + !ctx->Shader.CurrentFragmentProgram && + st_fb_orientation(ctx->ReadBuffer) == st_fb_orientation(ctx->DrawBuffer) && + ctx->DrawBuffer->_NumColorDrawBuffers == 1) { + struct st_renderbuffer *rbRead, *rbDraw; + GLint drawX, drawY; + + /* + * Clip the read region against the src buffer bounds. + * We'll still allocate a temporary buffer/texture for the original + * src region size but we'll only read the region which is on-screen. + * This may mean that we draw garbage pixels into the dest region, but + * that's expected. + */ + readX = srcx; + readY = srcy; + readW = width; + readH = height; + pack = ctx->DefaultPacking; + if (!_mesa_clip_readpixels(ctx, &readX, &readY, &readW, &readH, &pack)) + return GL_TRUE; /* all done */ + + /* clip against dest buffer bounds and scissor box */ + drawX = dstx + pack.SkipPixels; + drawY = dsty + pack.SkipRows; + unpack = pack; + if (!_mesa_clip_drawpixels(ctx, &drawX, &drawY, &readW, &readH, &unpack)) + return GL_TRUE; /* all done */ + + readX = readX - pack.SkipPixels + unpack.SkipPixels; + readY = readY - pack.SkipRows + unpack.SkipRows; + + rbRead = st_get_color_read_renderbuffer(ctx); + rbDraw = st_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0]); + + if ((rbRead != rbDraw || + !regions_overlap(readX, readY, drawX, drawY, readW, readH)) && + rbRead->Base.Format == rbDraw->Base.Format) { + struct pipe_box srcBox; + + /* flip src/dst position if needed */ + if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) { + /* both buffers will have the same orientation */ + readY = ctx->ReadBuffer->Height - readY - readH; + drawY = ctx->DrawBuffer->Height - drawY - readH; + } + + u_box_2d(readX, readY, readW, readH, &srcBox); + + pipe->resource_copy_region(pipe, + rbDraw->texture, 0, drawX, drawY, 0, + rbRead->texture, 0, &srcBox); + return GL_TRUE; + } + } + + return GL_FALSE; +} + + static void st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy, GLsizei width, GLsizei height, @@ -1168,6 +1275,17 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy, return; } + if (blit_copy_pixels(ctx, srcx, srcy, width, height, dstx, dsty, type)) + return; + + /* + * The subsequent code implements glCopyPixels by copying the source + * pixels into a temporary texture that's then applied to a textured quad. + * When we draw the textured quad, all the usual per-fragment operations + * are handled. + */ + + /* * Get vertex/fragment shaders */ @@ -1268,7 +1386,7 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy, if (srcFormat == texFormat) { struct pipe_box src_box; u_box_2d(readX, readY, readW, readH, &src_box); - /* copy source framebuffer surface into mipmap/texture */ + /* copy source framebuffer surface into mipmap/texture */ pipe->resource_copy_region(pipe, pt, /* dest tex */ 0, @@ -1281,7 +1399,8 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy, else { /* CPU-based fallback/conversion */ struct pipe_transfer *ptRead = - pipe_get_transfer(st->pipe, rbRead->texture, 0, 0, + pipe_get_transfer(st->pipe, rbRead->texture, + 0, 0, /* level, layer */ PIPE_TRANSFER_READ, readX, readY, readW, readH); struct pipe_transfer *ptTex; @@ -1302,15 +1421,19 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy, if (type == GL_COLOR) { /* alternate path using get/put_tile() */ GLfloat *buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); - pipe_get_tile_rgba(pipe, ptRead, readX, readY, readW, readH, buf); - pipe_put_tile_rgba(pipe, ptTex, pack.SkipPixels, pack.SkipRows, - readW, readH, buf); + enum pipe_format readFormat, drawFormat; + readFormat = util_format_linear(rbRead->texture->format); + drawFormat = util_format_linear(pt->format); + pipe_get_tile_rgba_format(pipe, ptRead, 0, 0, readW, readH, + readFormat, buf); + pipe_put_tile_rgba_format(pipe, ptTex, pack.SkipPixels, pack.SkipRows, + readW, readH, drawFormat, buf); free(buf); } else { /* GL_DEPTH */ GLuint *buf = (GLuint *) malloc(width * height * sizeof(GLuint)); - pipe_get_tile_z(pipe, ptRead, readX, readY, readW, readH, buf); + pipe_get_tile_z(pipe, ptRead, 0, 0, readW, readH, buf); pipe_put_tile_z(pipe, ptTex, pack.SkipPixels, pack.SkipRows, readW, readH, buf); free(buf); diff --git a/src/mesa/state_tracker/st_cb_drawtex.c b/src/mesa/state_tracker/st_cb_drawtex.c index b540a79331b..86ceb9d78b3 100644 --- a/src/mesa/state_tracker/st_cb_drawtex.c +++ b/src/mesa/state_tracker/st_cb_drawtex.c @@ -139,6 +139,7 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z, /* create the vertex buffer */ vbuffer = pipe_buffer_create(pipe->screen, PIPE_BIND_VERTEX_BUFFER, + PIPE_USAGE_STREAM, numAttribs * 4 * 4 * sizeof(GLfloat)); /* load vertex buffer */ @@ -230,6 +231,7 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z, cso_save_viewport(cso); cso_save_vertex_shader(cso); cso_save_vertex_elements(cso); + cso_save_vertex_buffers(cso); { void *vs = lookup_shader(pipe, numAttribs, @@ -264,7 +266,7 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z, } - util_draw_vertex_buffer(pipe, vbuffer, + util_draw_vertex_buffer(pipe, cso, vbuffer, 0, /* offset */ PIPE_PRIM_TRIANGLE_FAN, 4, /* verts */ @@ -277,6 +279,7 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z, cso_restore_viewport(cso); cso_restore_vertex_shader(cso); cso_restore_vertex_elements(cso); + cso_restore_vertex_buffers(cso); } diff --git a/src/mesa/state_tracker/st_cb_fbo.c b/src/mesa/state_tracker/st_cb_fbo.c index 0c7641f8623..5eda2346c60 100644 --- a/src/mesa/state_tracker/st_cb_fbo.c +++ b/src/mesa/state_tracker/st_cb_fbo.c @@ -84,6 +84,7 @@ st_renderbuffer_alloc_storage(struct gl_context * ctx, strb->Base.Width = width; strb->Base.Height = height; strb->Base.Format = st_pipe_format_to_mesa_format(format); + strb->Base._BaseFormat = _mesa_base_fbo_format(ctx, internalFormat); strb->Base.DataType = st_format_datatype(format); strb->defined = GL_FALSE; /* undefined contents now */ @@ -234,6 +235,7 @@ st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw) strb->Base.ClassID = 0x4242; /* just a unique value */ strb->Base.NumSamples = samples; strb->Base.Format = st_pipe_format_to_mesa_format(format); + strb->Base._BaseFormat = _mesa_get_format_base_format(strb->Base.Format); strb->Base.DataType = st_format_datatype(format); strb->format = format; strb->software = sw; @@ -390,7 +392,7 @@ st_render_texture(struct gl_context *ctx, /* new surface for rendering into the texture */ memset(&surf_tmpl, 0, sizeof(surf_tmpl)); - surf_tmpl.format = strb->texture->format; + surf_tmpl.format = ctx->Color.sRGBEnabled ? strb->texture->format : util_format_linear(strb->texture->format); surf_tmpl.usage = PIPE_BIND_RENDER_TARGET; surf_tmpl.u.tex.level = strb->rtt_level; surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice; @@ -448,11 +450,14 @@ st_finish_render_texture(struct gl_context *ctx, * Validate a renderbuffer attachment for a particular set of bindings. */ static GLboolean -st_validate_attachment(struct pipe_screen *screen, +st_validate_attachment(struct gl_context *ctx, + struct pipe_screen *screen, const struct gl_renderbuffer_attachment *att, unsigned bindings) { const struct st_texture_object *stObj = st_texture_object(att->Texture); + enum pipe_format format; + gl_format texFormat; /* Only validate texture attachments for now, since * st_renderbuffer_alloc_storage makes sure that @@ -464,7 +469,20 @@ st_validate_attachment(struct pipe_screen *screen, if (!stObj) return GL_FALSE; - return screen->is_format_supported(screen, stObj->pt->format, + format = stObj->pt->format; + texFormat = + stObj->base.Image[att->CubeMapFace][att->TextureLevel]->TexFormat; + + /* If the encoding is sRGB and sRGB rendering cannot be enabled, + * check for linear format support instead. + * Later when we create a surface, we change the format to a linear one. */ + if (!ctx->Const.sRGBCapable && + _mesa_get_format_color_encoding(texFormat) == GL_SRGB) { + const gl_format linearFormat = _mesa_get_srgb_format_linear(texFormat); + format = st_mesa_format_to_pipe_format(linearFormat); + } + + return screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, stObj->pt->nr_samples, bindings, 0); } @@ -528,20 +546,23 @@ st_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) return; } - if (!st_validate_attachment(screen, + if (!st_validate_attachment(ctx, + screen, depth, PIPE_BIND_DEPTH_STENCIL)) { fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; return; } - if (!st_validate_attachment(screen, + if (!st_validate_attachment(ctx, + screen, stencil, PIPE_BIND_DEPTH_STENCIL)) { fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; return; } for (i = 0; i < ctx->Const.MaxColorAttachments; i++) { - if (!st_validate_attachment(screen, + if (!st_validate_attachment(ctx, + screen, &fb->Attachment[BUFFER_COLOR0 + i], PIPE_BIND_RENDER_TARGET)) { fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; diff --git a/src/mesa/state_tracker/st_cb_readpixels.c b/src/mesa/state_tracker/st_cb_readpixels.c index 0507be74578..4689a0032b7 100644 --- a/src/mesa/state_tracker/st_cb_readpixels.c +++ b/src/mesa/state_tracker/st_cb_readpixels.c @@ -41,6 +41,7 @@ #include "pipe/p_context.h" #include "pipe/p_defines.h" +#include "util/u_format.h" #include "util/u_inlines.h" #include "util/u_tile.h" @@ -336,6 +337,7 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei h struct st_renderbuffer *strb; struct gl_pixelstore_attrib clippedPacking = *pack; struct pipe_transfer *trans; + enum pipe_format pformat; assert(ctx->ReadBuffer->Width > 0); @@ -421,6 +423,9 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei h yStep = 1; } + /* possibly convert sRGB format to linear RGB format */ + pformat = util_format_linear(trans->resource->format); + if (ST_DEBUG & DEBUG_FALLBACK) debug_printf("%s: fallback processing\n", __FUNCTION__); @@ -435,8 +440,8 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei h const GLint dstStride = _mesa_image_row_stride(&clippedPacking, width, format, type); - if (trans->resource->format == PIPE_FORMAT_Z24_UNORM_S8_USCALED || - trans->resource->format == PIPE_FORMAT_Z24X8_UNORM) { + if (pformat == PIPE_FORMAT_Z24_UNORM_S8_USCALED || + pformat == PIPE_FORMAT_Z24X8_UNORM) { if (format == GL_DEPTH_COMPONENT) { for (i = 0; i < height; i++) { GLuint ztemp[MAX_WIDTH]; @@ -467,8 +472,8 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei h } } } - else if (trans->resource->format == PIPE_FORMAT_S8_USCALED_Z24_UNORM || - trans->resource->format == PIPE_FORMAT_X8Z24_UNORM) { + else if (pformat == PIPE_FORMAT_S8_USCALED_Z24_UNORM || + pformat == PIPE_FORMAT_X8Z24_UNORM) { if (format == GL_DEPTH_COMPONENT) { for (i = 0; i < height; i++) { GLuint ztemp[MAX_WIDTH]; @@ -494,7 +499,7 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei h } } } - else if (trans->resource->format == PIPE_FORMAT_Z16_UNORM) { + else if (pformat == PIPE_FORMAT_Z16_UNORM) { for (i = 0; i < height; i++) { GLushort ztemp[MAX_WIDTH]; GLfloat zfloat[MAX_WIDTH]; @@ -509,7 +514,7 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei h dst += dstStride; } } - else if (trans->resource->format == PIPE_FORMAT_Z32_UNORM) { + else if (pformat == PIPE_FORMAT_Z32_UNORM) { for (i = 0; i < height; i++) { GLuint ztemp[MAX_WIDTH]; GLfloat zfloat[MAX_WIDTH]; @@ -528,7 +533,8 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei h /* RGBA format */ /* Do a row at a time to flip image data vertically */ for (i = 0; i < height; i++) { - pipe_get_tile_rgba(pipe, trans, 0, y, width, 1, df); + pipe_get_tile_rgba_format(pipe, trans, 0, y, width, 1, + pformat, df); y += yStep; df += dfStride; if (!dfStride) { diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c index 09a10ba5819..08c498b1491 100644 --- a/src/mesa/state_tracker/st_cb_texture.c +++ b/src/mesa/state_tracker/st_cb_texture.c @@ -74,19 +74,18 @@ gl_target_to_pipe(GLenum target) switch (target) { case GL_TEXTURE_1D: return PIPE_TEXTURE_1D; - case GL_TEXTURE_2D: return PIPE_TEXTURE_2D; - case GL_TEXTURE_RECTANGLE_NV: return PIPE_TEXTURE_RECT; - case GL_TEXTURE_3D: return PIPE_TEXTURE_3D; - case GL_TEXTURE_CUBE_MAP_ARB: return PIPE_TEXTURE_CUBE; - + case GL_TEXTURE_1D_ARRAY_EXT: + return PIPE_TEXTURE_1D_ARRAY; + case GL_TEXTURE_2D_ARRAY_EXT: + return PIPE_TEXTURE_2D_ARRAY; default: assert(0); return 0; @@ -261,6 +260,55 @@ get_texture_dims(GLenum target) /** + * Given the size of a mipmap image, try to compute the size of the level=0 + * mipmap image. + * + * Note that this isn't always accurate for odd-sized, non-POW textures. + * For example, if level=1 and width=40 then the level=0 width may be 80 or 81. + * + * \return GL_TRUE for success, GL_FALSE for failure + */ +static GLboolean +guess_base_level_size(GLenum target, + GLuint width, GLuint height, GLuint depth, GLuint level, + GLuint *width0, GLuint *height0, GLuint *depth0) +{ + const GLuint dims = get_texture_dims(target); + + assert(width >= 1); + assert(height >= 1); + assert(depth >= 1); + + if (level > 0) { + /* Depending on the image's size, we can't always make a guess here */ + if ((dims >= 1 && width == 1) || + (dims >= 2 && height == 1) || + (dims >= 3 && depth == 1)) { + /* we can't determine the image size at level=0 */ + return GL_FALSE; + } + + /* grow the image size until we hit level = 0 */ + while (level > 0) { + if (width > 1) + width <<= 1; + if (height > 1) + height <<= 1; + if (depth > 1) + depth <<= 1; + level--; + } + } + + *width0 = width; + *height0 = height; + *depth0 = depth; + + return GL_TRUE; +} + + +/** * Try to allocate a pipe_resource object for the given st_texture_object. * * We use the given st_texture_image as a clue to determine the size of the @@ -273,50 +321,27 @@ guess_and_alloc_texture(struct st_context *st, struct st_texture_object *stObj, const struct st_texture_image *stImage) { - const GLuint dims = get_texture_dims(stObj->base.Target); - GLuint level, lastLevel, width, height, depth; + GLuint lastLevel, width, height, depth; GLuint bindings; + GLuint ptWidth, ptHeight, ptDepth, ptLayers; enum pipe_format fmt; DBG("%s\n", __FUNCTION__); assert(!stObj->pt); - level = stImage->level; - width = stImage->base.Width2; /* size w/out border */ - height = stImage->base.Height2; - depth = stImage->base.Depth2; - - assert(width > 0); - assert(height > 0); - assert(depth > 0); - - /* Depending on the image's size, we can't always make a guess here. - */ - if (level > 0) { - if ( (dims >= 1 && width == 1) || - (dims >= 2 && height == 1) || - (dims >= 3 && depth == 1) ) { - /* we can't determine the image size at level=0 */ - stObj->width0 = stObj->height0 = stObj->depth0 = 0; - /* this is not an out of memory error */ - return GL_TRUE; - } + if (!guess_base_level_size(stObj->base.Target, + stImage->base.Width2, + stImage->base.Height2, + stImage->base.Depth2, + stImage->level, + &width, &height, &depth)) { + /* we can't determine the image size at level=0 */ + stObj->width0 = stObj->height0 = stObj->depth0 = 0; + /* this is not an out of memory error */ + return GL_TRUE; } - /* grow the image size until we hit level = 0 */ - while (level > 0) { - if (width != 1) - width <<= 1; - if (height != 1) - height <<= 1; - if (depth != 1) - depth <<= 1; - level--; - } - - assert(level == 0); - /* At this point, (width x height x depth) is the expected size of * the level=0 mipmap image. */ @@ -353,13 +378,18 @@ guess_and_alloc_texture(struct st_context *st, bindings = default_bindings(st, fmt); + st_gl_texture_dims_to_pipe_dims(stObj->base.Target, + width, height, depth, + &ptWidth, &ptHeight, &ptDepth, &ptLayers); + stObj->pt = st_texture_create(st, gl_target_to_pipe(stObj->base.Target), fmt, lastLevel, - width, - height, - depth, + ptWidth, + ptHeight, + ptDepth, + ptLayers, bindings); DBG("%s returning %d\n", __FUNCTION__, (stObj->pt != NULL)); @@ -407,125 +437,6 @@ strip_texture_border(GLint border, /** - * Try to do texture compression via rendering. If the Gallium driver - * can render into a compressed surface this will allow us to do texture - * compression. - * \return GL_TRUE for success, GL_FALSE for failure - */ -static GLboolean -compress_with_blit(struct gl_context * ctx, - GLenum target, GLint level, - GLint xoffset, GLint yoffset, GLint zoffset, - GLint width, GLint height, GLint depth, - GLenum format, GLenum type, const void *pixels, - const struct gl_pixelstore_attrib *unpack, - struct gl_texture_image *texImage) -{ - const GLuint dstImageOffsets[1] = {0}; - struct st_texture_image *stImage = st_texture_image(texImage); - struct st_context *st = st_context(ctx); - struct pipe_context *pipe = st->pipe; - struct pipe_screen *screen = pipe->screen; - gl_format mesa_format; - struct pipe_resource templ; - struct pipe_resource *src_tex; - struct pipe_sampler_view view_templ; - struct pipe_sampler_view *src_view; - struct pipe_surface *dst_surface, surf_tmpl; - struct pipe_transfer *tex_xfer; - void *map; - - if (!stImage->pt) { - /* XXX: Can this happen? Should we assert? */ - return GL_FALSE; - } - - /* get destination surface (in the compressed texture) */ - memset(&surf_tmpl, 0, sizeof(surf_tmpl)); - surf_tmpl.format = stImage->pt->format; - surf_tmpl.usage = PIPE_BIND_RENDER_TARGET; - surf_tmpl.u.tex.level = stImage->level; - surf_tmpl.u.tex.first_layer = stImage->face; - surf_tmpl.u.tex.last_layer = stImage->face; - dst_surface = pipe->create_surface(pipe, stImage->pt, &surf_tmpl); - if (!dst_surface) { - /* can't render into this format (or other problem) */ - return GL_FALSE; - } - - /* Choose format for the temporary RGBA texture image. - */ - mesa_format = st_ChooseTextureFormat(ctx, GL_RGBA, format, type); - assert(mesa_format); - if (!mesa_format) - return GL_FALSE; - - /* Create the temporary source texture - */ - memset(&templ, 0, sizeof(templ)); - templ.target = st->internal_target; - templ.format = st_mesa_format_to_pipe_format(mesa_format); - templ.width0 = width; - templ.height0 = height; - templ.depth0 = 1; - templ.array_size = 1; - templ.last_level = 0; - templ.usage = PIPE_USAGE_DEFAULT; - templ.bind = PIPE_BIND_SAMPLER_VIEW; - src_tex = screen->resource_create(screen, &templ); - - if (!src_tex) - return GL_FALSE; - - /* Put user's tex data into the temporary texture - */ - tex_xfer = pipe_get_transfer(st_context(ctx)->pipe, src_tex, - 0, 0, /* layer, level are zero */ - PIPE_TRANSFER_WRITE, - 0, 0, width, height); /* x, y, w, h */ - map = pipe_transfer_map(pipe, tex_xfer); - - _mesa_texstore(ctx, 2, GL_RGBA, mesa_format, - map, /* dest ptr */ - 0, 0, 0, /* dest x/y/z offset */ - tex_xfer->stride, /* dest row stride (bytes) */ - dstImageOffsets, /* image offsets (for 3D only) */ - width, height, 1, /* size */ - format, type, /* source format/type */ - pixels, /* source data */ - unpack); /* source data packing */ - - pipe_transfer_unmap(pipe, tex_xfer); - pipe->transfer_destroy(pipe, tex_xfer); - - /* Create temporary sampler view */ - u_sampler_view_default_template(&view_templ, - src_tex, - src_tex->format); - src_view = pipe->create_sampler_view(pipe, src_tex, &view_templ); - - - /* copy / compress image */ - util_blit_pixels_tex(st->blit, - src_view, /* sampler view (src) */ - 0, 0, /* src x0, y0 */ - width, height, /* src x1, y1 */ - dst_surface, /* pipe_surface (dst) */ - xoffset, yoffset, /* dst x0, y0 */ - xoffset + width, /* dst x1 */ - yoffset + height, /* dst y1 */ - 0.0, /* z */ - PIPE_TEX_MIPFILTER_NEAREST); - - pipe_surface_reference(&dst_surface, NULL); - pipe_resource_reference(&src_tex, NULL); - pipe_sampler_view_reference(&src_view, NULL); - - return GL_TRUE; -} - - -/** * Do glTexImage1/2/3D(). */ static void @@ -542,7 +453,6 @@ st_TexImage(struct gl_context * ctx, GLsizei imageSize, GLboolean compressed_src) { struct st_context *st = st_context(ctx); - struct pipe_screen *screen = st->pipe->screen; struct st_texture_object *stObj = st_texture_object(texObj); struct st_texture_image *stImage = st_texture_image(texImage); GLuint dstRowStride = 0; @@ -669,22 +579,10 @@ st_TexImage(struct gl_context * ctx, pixels, unpack, "glTexImage"); } - /* See if we can do texture compression with a blit/render. - */ - if (!compressed_src && - !ctx->Mesa_DXTn && - _mesa_is_format_compressed(texImage->TexFormat) && - screen->is_format_supported(screen, - stImage->pt->format, - stImage->pt->target, 0, - PIPE_BIND_RENDER_TARGET, 0)) { - if (!pixels) - goto done; - - if (compress_with_blit(ctx, target, level, 0, 0, 0, width, height, depth, - format, type, pixels, unpack, texImage)) { - goto done; - } + /* for a 1D array upload the image as a series of layer with height = 1 */ + if (target == GL_TEXTURE_1D_ARRAY) { + depth = height; + height = 1; } /* @@ -918,6 +816,7 @@ decompress_with_blit(struct gl_context * ctx, GLenum target, GLint level, else { /* format translation via floats */ GLuint row; + enum pipe_format format = util_format_linear(dst_texture->format); for (row = 0; row < height; row++) { const GLbitfield transferOps = 0x0; /* bypassed for glGetTexImage() */ GLfloat rgba[4 * MAX_WIDTH]; @@ -928,7 +827,8 @@ decompress_with_blit(struct gl_context * ctx, GLenum target, GLint level, debug_printf("%s: fallback format translation\n", __FUNCTION__); /* get float[4] rgba row from surface */ - pipe_get_tile_rgba(pipe, tex_xfer, 0, row, width, 1, rgba); + pipe_get_tile_rgba_format(pipe, tex_xfer, 0, row, width, 1, + format, rgba); _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, format, type, dest, &ctx->Pack, transferOps); @@ -1073,7 +973,6 @@ st_TexSubimage(struct gl_context *ctx, GLint dims, GLenum target, GLint level, struct gl_texture_image *texImage) { struct st_context *st = st_context(ctx); - struct pipe_screen *screen = st->pipe->screen; struct st_texture_image *stImage = st_texture_image(texImage); GLuint dstRowStride; const GLuint srcImageStride = @@ -1093,20 +992,10 @@ st_TexSubimage(struct gl_context *ctx, GLint dims, GLenum target, GLint level, if (!pixels) return; - /* See if we can do texture compression with a blit/render. - */ - if (!ctx->Mesa_DXTn && - _mesa_is_format_compressed(texImage->TexFormat) && - screen->is_format_supported(screen, - stImage->pt->format, - stImage->pt->target, 0, - PIPE_BIND_RENDER_TARGET, 0)) { - if (compress_with_blit(ctx, target, level, - xoffset, yoffset, zoffset, - width, height, depth, - format, type, pixels, packing, texImage)) { - goto done; - } + /* for a 1D array upload the image as a series of layer with height = 1 */ + if (target == GL_TEXTURE_1D_ARRAY) { + depth = height; + height = 1; } /* Map buffer if necessary. Need to lock to prevent other contexts @@ -1387,7 +1276,9 @@ fallback_copy_texsubimage(struct gl_context *ctx, GLenum target, GLint level, /* XXX this usually involves a lot of int/float conversion. * try to avoid that someday. */ - pipe_get_tile_rgba(pipe, src_trans, 0, 0, width, height, tempSrc); + pipe_get_tile_rgba_format(pipe, src_trans, 0, 0, width, height, + util_format_linear(strb->texture->format), + tempSrc); /* Store into texture memory. * Note that this does some special things such as pixel transfer @@ -1834,6 +1725,7 @@ st_finalize_texture(struct gl_context *ctx, GLuint face; struct st_texture_image *firstImage; enum pipe_format firstImageFormat; + GLuint ptWidth, ptHeight, ptDepth, ptLayers; if (stObj->base._Complete) { /* The texture is complete and we know exactly how many mipmap levels @@ -1867,6 +1759,24 @@ st_finalize_texture(struct gl_context *ctx, /* Find gallium format for the Mesa texture */ firstImageFormat = st_mesa_format_to_pipe_format(firstImage->base.TexFormat); + /* Find size of level=0 Gallium mipmap image, plus number of texture layers */ + { + GLuint width, height, depth; + if (!guess_base_level_size(stObj->base.Target, + firstImage->base.Width2, + firstImage->base.Height2, + firstImage->base.Depth2, + stObj->base.BaseLevel, + &width, &height, &depth)) { + width = stObj->width0; + height = stObj->height0; + depth = stObj->depth0; + } + /* convert GL dims to Gallium dims */ + st_gl_texture_dims_to_pipe_dims(stObj->base.Target, width, height, depth, + &ptWidth, &ptHeight, &ptDepth, &ptLayers); + } + /* If we already have a gallium texture, check that it matches the texture * object's format, target, size, num_levels, etc. */ @@ -1874,9 +1784,10 @@ st_finalize_texture(struct gl_context *ctx, if (stObj->pt->target != gl_target_to_pipe(stObj->base.Target) || !st_sampler_compat_formats(stObj->pt->format, firstImageFormat) || stObj->pt->last_level < stObj->lastLevel || - stObj->pt->width0 != stObj->width0 || - stObj->pt->height0 != stObj->height0 || - stObj->pt->depth0 != stObj->depth0) + stObj->pt->width0 != ptWidth || + stObj->pt->height0 != ptHeight || + stObj->pt->depth0 != ptDepth || + stObj->pt->array_size != ptLayers) { /* The gallium texture does not match the Mesa texture so delete the * gallium texture now. We'll make a new one below. @@ -1896,9 +1807,10 @@ st_finalize_texture(struct gl_context *ctx, gl_target_to_pipe(stObj->base.Target), firstImageFormat, stObj->lastLevel, - stObj->width0, - stObj->height0, - stObj->depth0, + ptWidth, + ptHeight, + ptDepth, + ptLayers, bindings); if (!stObj->pt) { diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c index c7f3949bf9e..7a19f35bbf5 100644 --- a/src/mesa/state_tracker/st_context.c +++ b/src/mesa/state_tracker/st_context.c @@ -178,7 +178,7 @@ struct st_context *st_create_context(gl_api api, struct pipe_context *pipe, memset(&funcs, 0, sizeof(funcs)); st_init_driver_functions(&funcs); - ctx = _mesa_create_context_for_api(api, visual, shareCtx, &funcs, NULL); + ctx = _mesa_create_context(api, visual, shareCtx, &funcs, NULL); /* XXX: need a capability bit in gallium to query if the pipe * driver prefers DP4 or MUL/MAD for vertex transformation. @@ -203,6 +203,11 @@ static void st_destroy_context_priv( struct st_context *st ) st_destroy_drawpix(st); st_destroy_drawtex(st); + /* Unreference any user vertex buffers. */ + for (i = 0; i < st->num_user_vbs; i++) { + pipe_resource_reference(&st->user_vb[i], NULL); + } + for (i = 0; i < Elements(st->state.sampler_views); i++) { pipe_sampler_view_reference(&st->state.sampler_views[i], NULL); } diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index 64a8f790e22..77765f02379 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -185,6 +185,11 @@ struct st_context int force_msaa; void *winsys_drawable_handle; + + /* User vertex buffers. */ + struct pipe_resource *user_vb[PIPE_MAX_ATTRIBS]; + unsigned user_vb_stride[PIPE_MAX_ATTRIBS]; + unsigned num_user_vbs; }; diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c index 8e1263fe84e..6530a06ade4 100644 --- a/src/mesa/state_tracker/st_draw.c +++ b/src/mesa/state_tracker/st_draw.c @@ -243,14 +243,13 @@ st_pipe_vertex_format(GLenum type, GLuint size, GLenum format, static GLboolean is_interleaved_arrays(const struct st_vertex_program *vp, const struct st_vp_variant *vpv, - const struct gl_client_array **arrays, - GLboolean *userSpace) + const struct gl_client_array **arrays) { GLuint attr; const struct gl_buffer_object *firstBufObj = NULL; GLint firstStride = -1; - GLuint num_client_arrays = 0; const GLubyte *client_addr = NULL; + GLboolean user_memory; for (attr = 0; attr < vpv->num_inputs; attr++) { const GLuint mesaAttr = vp->index_to_input[attr]; @@ -259,16 +258,19 @@ is_interleaved_arrays(const struct st_vertex_program *vp, if (firstStride < 0) { firstStride = stride; + user_memory = !bufObj || !bufObj->Name; } else if (firstStride != stride) { return GL_FALSE; } - + if (!bufObj || !bufObj->Name) { - num_client_arrays++; /* Try to detect if the client-space arrays are * "close" to each other. */ + if (!user_memory) { + return GL_FALSE; + } if (!client_addr) { client_addr = arrays[mesaAttr]->Ptr; } @@ -278,6 +280,9 @@ is_interleaved_arrays(const struct st_vertex_program *vp, } } else if (!firstBufObj) { + if (user_memory) { + return GL_FALSE; + } firstBufObj = bufObj; } else if (bufObj != firstBufObj) { @@ -285,57 +290,11 @@ is_interleaved_arrays(const struct st_vertex_program *vp, } } - *userSpace = (num_client_arrays == vpv->num_inputs); - /* debug_printf("user space: %s (%d arrays, %d inputs)\n", - (int)*userSpace ? "Yes" : "No", num_client_arrays, vp->num_inputs); */ - return GL_TRUE; } /** - * Compute the memory range occupied by the arrays. - */ -static void -get_arrays_bounds(const struct st_vertex_program *vp, - const struct st_vp_variant *vpv, - const struct gl_client_array **arrays, - GLuint max_index, - const GLubyte **low, const GLubyte **high) -{ - const GLubyte *low_addr = NULL; - const GLubyte *high_addr = NULL; - GLuint attr; - - /* debug_printf("get_arrays_bounds: Handling %u attrs\n", vpv->num_inputs); */ - - for (attr = 0; attr < vpv->num_inputs; attr++) { - const GLuint mesaAttr = vp->index_to_input[attr]; - const GLint stride = arrays[mesaAttr]->StrideB; - const GLubyte *start = arrays[mesaAttr]->Ptr; - const unsigned sz = (arrays[mesaAttr]->Size * - _mesa_sizeof_type(arrays[mesaAttr]->Type)); - const GLubyte *end = start + (max_index * stride) + sz; - - /* debug_printf("attr %u: stride %d size %u start %p end %p\n", - attr, stride, sz, start, end); */ - - if (attr == 0) { - low_addr = start; - high_addr = end; - } - else { - low_addr = MIN2(low_addr, start); - high_addr = MAX2(high_addr, end); - } - } - - *low = low_addr; - *high = high_addr; -} - - -/** * Set up for drawing interleaved arrays that all live in one VBO * or all live in user space. * \param vbuffer returns vertex buffer info @@ -346,15 +305,24 @@ setup_interleaved_attribs(struct gl_context *ctx, const struct st_vertex_program *vp, const struct st_vp_variant *vpv, const struct gl_client_array **arrays, - GLuint max_index, - GLboolean userSpace, struct pipe_vertex_buffer *vbuffer, - struct pipe_vertex_element velements[]) + struct pipe_vertex_element velements[], + unsigned max_index) { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; GLuint attr; - const GLubyte *offset0 = NULL; + const GLubyte *low_addr = NULL; + + /* Find the lowest address. */ + if(vpv->num_inputs) { + low_addr = arrays[vp->index_to_input[0]]->Ptr; + + for (attr = 1; attr < vpv->num_inputs; attr++) { + const GLubyte *start = arrays[vp->index_to_input[attr]]->Ptr; + low_addr = MIN2(low_addr, start); + } + } for (attr = 0; attr < vpv->num_inputs; attr++) { const GLuint mesaAttr = vp->index_to_input[attr]; @@ -362,40 +330,28 @@ setup_interleaved_attribs(struct gl_context *ctx, struct st_buffer_object *stobj = st_buffer_object(bufobj); GLsizei stride = arrays[mesaAttr]->StrideB; - /*printf("stobj %u = %p\n", attr, (void*)stobj);*/ - if (attr == 0) { - const GLubyte *low, *high; - - get_arrays_bounds(vp, vpv, arrays, max_index, &low, &high); - /* debug_printf("buffer range: %p %p range %d max index %u\n", - low, high, high - low, max_index); */ - - offset0 = low; - if (userSpace) { + if (bufobj && bufobj->Name) { + vbuffer->buffer = NULL; + pipe_resource_reference(&vbuffer->buffer, stobj->buffer); + vbuffer->buffer_offset = pointer_to_offset(low_addr); + } else { vbuffer->buffer = - pipe_user_buffer_create(pipe->screen, (void *) low, high - low, + pipe_user_buffer_create(pipe->screen, (void*)low_addr, + stride * (max_index + 1), PIPE_BIND_VERTEX_BUFFER); vbuffer->buffer_offset = 0; - } - else { - vbuffer->buffer = NULL; - pipe_resource_reference(&vbuffer->buffer, stobj->buffer); - vbuffer->buffer_offset = pointer_to_offset(low); + + /* Track user vertex buffers. */ + pipe_resource_reference(&st->user_vb[0], vbuffer->buffer); + st->user_vb_stride[0] = stride; + st->num_user_vbs = 1; } vbuffer->stride = stride; /* in bytes */ - vbuffer->max_index = max_index; } - /* - if (arrays[mesaAttr]->InstanceDivisor) - vbuffer[attr].max_index = arrays[mesaAttr]->_MaxElement; - else - vbuffer[attr].max_index = max_index; - */ - velements[attr].src_offset = - (unsigned) (arrays[mesaAttr]->Ptr - offset0); + (unsigned) (arrays[mesaAttr]->Ptr - low_addr); velements[attr].instance_divisor = arrays[mesaAttr]->InstanceDivisor; velements[attr].vertex_buffer_index = 0; velements[attr].src_format = @@ -419,10 +375,9 @@ setup_non_interleaved_attribs(struct gl_context *ctx, const struct st_vertex_program *vp, const struct st_vp_variant *vpv, const struct gl_client_array **arrays, - GLuint max_index, - GLboolean *userSpace, struct pipe_vertex_buffer vbuffer[], - struct pipe_vertex_element velements[]) + struct pipe_vertex_element velements[], + unsigned max_index) { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; @@ -433,8 +388,6 @@ setup_non_interleaved_attribs(struct gl_context *ctx, struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj; GLsizei stride = arrays[mesaAttr]->StrideB; - *userSpace = GL_FALSE; - if (bufobj && bufobj->Name) { /* Attribute data is in a VBO. * Recall that for VBOs, the gl_client_array->Ptr field is @@ -442,37 +395,23 @@ setup_non_interleaved_attribs(struct gl_context *ctx, */ struct st_buffer_object *stobj = st_buffer_object(bufobj); assert(stobj->buffer); - /*printf("stobj %u = %p\n", attr, (void*) stobj);*/ vbuffer[attr].buffer = NULL; pipe_resource_reference(&vbuffer[attr].buffer, stobj->buffer); vbuffer[attr].buffer_offset = pointer_to_offset(arrays[mesaAttr]->Ptr); } else { - /* attribute data is in user-space memory, not a VBO */ - uint bytes; - /*printf("user-space array %d stride %d\n", attr, stride);*/ - - *userSpace = GL_TRUE; - /* wrap user data */ if (arrays[mesaAttr]->Ptr) { - /* user's vertex array */ - if (arrays[mesaAttr]->StrideB) { - bytes = arrays[mesaAttr]->StrideB * (max_index + 1); - } - else { - bytes = arrays[mesaAttr]->Size - * _mesa_sizeof_type(arrays[mesaAttr]->Type); - } vbuffer[attr].buffer = pipe_user_buffer_create(pipe->screen, - (void *) arrays[mesaAttr]->Ptr, bytes, + (void *) arrays[mesaAttr]->Ptr, + stride * (max_index + 1), PIPE_BIND_VERTEX_BUFFER); } else { /* no array, use ctx->Current.Attrib[] value */ - bytes = sizeof(ctx->Current.Attrib[0]); + uint bytes = sizeof(ctx->Current.Attrib[0]); vbuffer[attr].buffer = pipe_user_buffer_create(pipe->screen, (void *) ctx->Current.Attrib[mesaAttr], @@ -482,16 +421,15 @@ setup_non_interleaved_attribs(struct gl_context *ctx, } vbuffer[attr].buffer_offset = 0; - } - assert(velements[attr].src_offset <= 2048); /* 11-bit field */ + /* Track user vertex buffers. */ + pipe_resource_reference(&st->user_vb[attr], vbuffer->buffer); + st->user_vb_stride[attr] = stride; + st->num_user_vbs = MAX2(st->num_user_vbs, attr+1); + } /* common-case setup */ vbuffer[attr].stride = stride; /* in bytes */ - if (arrays[mesaAttr]->InstanceDivisor) - vbuffer[attr].max_index = arrays[mesaAttr]->_MaxElement; - else - vbuffer[attr].max_index = max_index; velements[attr].src_offset = 0; velements[attr].instance_divisor = arrays[mesaAttr]->InstanceDivisor; @@ -609,6 +547,62 @@ translate_prim(const struct gl_context *ctx, unsigned prim) } +static void +st_validate_varrays(struct gl_context *ctx, + const struct gl_client_array **arrays, + unsigned max_index) +{ + struct st_context *st = st_context(ctx); + const struct st_vertex_program *vp; + const struct st_vp_variant *vpv; + struct pipe_vertex_buffer vbuffer[PIPE_MAX_SHADER_INPUTS]; + struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS]; + unsigned num_vbuffers, num_velements; + GLuint attr; + unsigned i; + + /* must get these after state validation! */ + vp = st->vp; + vpv = st->vp_variant; + + memset(velements, 0, sizeof(struct pipe_vertex_element) * vpv->num_inputs); + + /* Unreference any user vertex buffers. */ + for (i = 0; i < st->num_user_vbs; i++) { + pipe_resource_reference(&st->user_vb[i], NULL); + } + st->num_user_vbs = 0; + + /* + * Setup the vbuffer[] and velements[] arrays. + */ + if (is_interleaved_arrays(vp, vpv, arrays)) { + setup_interleaved_attribs(ctx, vp, vpv, arrays, vbuffer, velements, + max_index); + num_vbuffers = 1; + num_velements = vpv->num_inputs; + if (num_velements == 0) + num_vbuffers = 0; + } + else { + setup_non_interleaved_attribs(ctx, vp, vpv, arrays, + vbuffer, velements, max_index); + num_vbuffers = vpv->num_inputs; + num_velements = vpv->num_inputs; + } + + cso_set_vertex_buffers(st->cso_context, num_vbuffers, vbuffer); + cso_set_vertex_elements(st->cso_context, num_velements, velements); + + /* unreference buffers (frees wrapped user-space buffer objects) + * This is OK, because the pipe driver should reference buffers by itself + * in set_vertex_buffers. */ + for (attr = 0; attr < num_vbuffers; attr++) { + pipe_resource_reference(&vbuffer[attr].buffer, NULL); + assert(!vbuffer[attr].buffer); + } +} + /** * This function gets plugged into the VBO module and is called when @@ -627,90 +621,81 @@ st_draw_vbo(struct gl_context *ctx, { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; - const struct st_vertex_program *vp; - const struct st_vp_variant *vpv; - struct pipe_vertex_buffer vbuffer[PIPE_MAX_SHADER_INPUTS]; - GLuint attr; - struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS]; - unsigned num_vbuffers, num_velements; struct pipe_index_buffer ibuffer; - GLboolean userSpace = GL_FALSE; - GLboolean vertDataEdgeFlags; struct pipe_draw_info info; unsigned i; + GLboolean new_array = GL_TRUE; + /* Fix this (Bug 34378): + GLboolean new_array = + st->dirty.st && (st->dirty.mesa & (_NEW_ARRAY | _NEW_PROGRAM)) != 0;*/ /* Mesa core state should have been validated already */ assert(ctx->NewState == 0x0); - /* Gallium probably doesn't want this in some cases. */ - if (!index_bounds_valid) - if (!vbo_all_varyings_in_vbos(arrays)) - vbo_get_minmax_index(ctx, prims, ib, &min_index, &max_index); + if (ib) { + /* Gallium probably doesn't want this in some cases. */ + if (!index_bounds_valid) + if (!vbo_all_varyings_in_vbos(arrays)) + vbo_get_minmax_index(ctx, prims, ib, &min_index, &max_index); + } else { + /* Get min/max index for non-indexed drawing. */ + min_index = ~0; + max_index = 0; + + for (i = 0; i < nr_prims; i++) { + min_index = MIN2(min_index, prims[i].start); + max_index = MAX2(max_index, prims[i].start + prims[i].count - 1); + } + } + + /* Validate state. */ + if (st->dirty.st) { + GLboolean vertDataEdgeFlags; - /* sanity check for pointer arithmetic below */ - assert(sizeof(arrays[0]->Ptr[0]) == 1); + /* sanity check for pointer arithmetic below */ + assert(sizeof(arrays[0]->Ptr[0]) == 1); - vertDataEdgeFlags = arrays[VERT_ATTRIB_EDGEFLAG]->BufferObj && - arrays[VERT_ATTRIB_EDGEFLAG]->BufferObj->Name; - if (vertDataEdgeFlags != st->vertdata_edgeflags) { - st->vertdata_edgeflags = vertDataEdgeFlags; - st->dirty.st |= ST_NEW_EDGEFLAGS_DATA; - } + vertDataEdgeFlags = arrays[VERT_ATTRIB_EDGEFLAG]->BufferObj && + arrays[VERT_ATTRIB_EDGEFLAG]->BufferObj->Name; + if (vertDataEdgeFlags != st->vertdata_edgeflags) { + st->vertdata_edgeflags = vertDataEdgeFlags; + st->dirty.st |= ST_NEW_EDGEFLAGS_DATA; + } - st_validate_state(st); + st_validate_state(st); - /* must get these after state validation! */ - vp = st->vp; - vpv = st->vp_variant; + if (new_array) { + st_validate_varrays(ctx, arrays, max_index); + } #if 0 - if (MESA_VERBOSE & VERBOSE_GLSL) { - check_uniforms(ctx); - } + if (MESA_VERBOSE & VERBOSE_GLSL) { + check_uniforms(ctx); + } #else - (void) check_uniforms; + (void) check_uniforms; #endif - - memset(velements, 0, sizeof(struct pipe_vertex_element) * vpv->num_inputs); - /* - * Setup the vbuffer[] and velements[] arrays. - */ - if (is_interleaved_arrays(vp, vpv, arrays, &userSpace)) { - /*printf("Draw interleaved\n");*/ - setup_interleaved_attribs(ctx, vp, vpv, arrays, max_index, userSpace, - vbuffer, velements); - num_vbuffers = 1; - num_velements = vpv->num_inputs; - if (num_velements == 0) - num_vbuffers = 0; - } - else { - /*printf("Draw non-interleaved\n");*/ - setup_non_interleaved_attribs(ctx, vp, vpv, arrays, max_index, - &userSpace, vbuffer, velements); - num_vbuffers = vpv->num_inputs; - num_velements = vpv->num_inputs; } -#if 0 - { - GLuint i; - for (i = 0; i < num_vbuffers; i++) { - printf("buffers[%d].stride = %u\n", i, vbuffer[i].stride); - printf("buffers[%d].max_index = %u\n", i, vbuffer[i].max_index); - printf("buffers[%d].buffer_offset = %u\n", i, vbuffer[i].buffer_offset); - printf("buffers[%d].buffer = %p\n", i, (void*) vbuffer[i].buffer); - } - for (i = 0; i < num_velements; i++) { - printf("vlements[%d].vbuffer_index = %u\n", i, velements[i].vertex_buffer_index); - printf("vlements[%d].src_offset = %u\n", i, velements[i].src_offset); - printf("vlements[%d].format = %s\n", i, util_format_name(velements[i].src_format)); + /* Notify the driver that the content of user buffers may have been + * changed. */ + if (!new_array && st->num_user_vbs) { + for (i = 0; i < st->num_user_vbs; i++) { + if (st->user_vb[i]) { + unsigned stride = st->user_vb_stride[i]; + + if (stride) { + pipe->redefine_user_buffer(pipe, st->user_vb[i], + min_index * stride, + (max_index + 1 - min_index) * stride); + } else { + /* stride == 0 */ + pipe->redefine_user_buffer(pipe, st->user_vb[i], + 0, st->user_vb[i]->width0); + } + } } } -#endif - - pipe->set_vertex_buffers(pipe, num_vbuffers, vbuffer); - cso_set_vertex_elements(st->cso_context, num_velements, velements); setup_index_buffer(ctx, ib, &ibuffer); pipe->set_index_buffer(pipe, &ibuffer); @@ -744,17 +729,6 @@ st_draw_vbo(struct gl_context *ctx, } pipe_resource_reference(&ibuffer.buffer, NULL); - - /* unreference buffers (frees wrapped user-space buffer objects) */ - for (attr = 0; attr < num_vbuffers; attr++) { - pipe_resource_reference(&vbuffer[attr].buffer, NULL); - assert(!vbuffer[attr].buffer); - } - - if (userSpace) - { - pipe->set_vertex_buffers(pipe, 0, NULL); - } } diff --git a/src/mesa/state_tracker/st_draw_feedback.c b/src/mesa/state_tracker/st_draw_feedback.c index 4e76a050701..1e1220bfe52 100644 --- a/src/mesa/state_tracker/st_draw_feedback.c +++ b/src/mesa/state_tracker/st_draw_feedback.c @@ -179,7 +179,6 @@ st_feedback_draw_vbo(struct gl_context *ctx, /* common-case setup */ vbuffers[attr].stride = arrays[mesaAttr]->StrideB; /* in bytes */ - vbuffers[attr].max_index = max_index; velements[attr].instance_divisor = 0; velements[attr].vertex_buffer_index = attr; velements[attr].src_format = @@ -220,7 +219,7 @@ st_feedback_draw_vbo(struct gl_context *ctx, break; default: assert(0); - return; + goto out_unref_vertex; } if (bufobj && bufobj->Name) { @@ -256,14 +255,6 @@ st_feedback_draw_vbo(struct gl_context *ctx, /* * unmap vertex/index buffers */ - for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { - if (draw->pt.vertex_buffer[i].buffer) { - pipe_buffer_unmap(pipe, vb_transfer[i]); - pipe_resource_reference(&draw->pt.vertex_buffer[i].buffer, NULL); - draw_set_mapped_vertex_buffer(draw, i, NULL); - } - } - if (ib) { draw_set_mapped_index_buffer(draw, NULL); draw_set_index_buffer(draw, NULL); @@ -272,6 +263,14 @@ st_feedback_draw_vbo(struct gl_context *ctx, pipe_buffer_unmap(pipe, ib_transfer); pipe_resource_reference(&ibuffer.buffer, NULL); } + + out_unref_vertex: + for (attr = 0; attr < vp->num_inputs; attr++) { + pipe_buffer_unmap(pipe, vb_transfer[attr]); + draw_set_mapped_vertex_buffer(draw, attr, NULL); + pipe_resource_reference(&vbuffers[attr].buffer, NULL); + } + draw_set_vertex_buffers(draw, 0, NULL); } #endif /* FEATURE_feedback || FEATURE_rastpos */ diff --git a/src/mesa/state_tracker/st_extensions.c b/src/mesa/state_tracker/st_extensions.c index 974fd78d7c8..2f45f470334 100644 --- a/src/mesa/state_tracker/st_extensions.c +++ b/src/mesa/state_tracker/st_extensions.c @@ -260,6 +260,8 @@ void st_init_extensions(struct st_context *st) ctx->Extensions.EXT_texture_env_dot3 = GL_TRUE; ctx->Extensions.EXT_texture_lod_bias = GL_TRUE; ctx->Extensions.EXT_vertex_array_bgra = GL_TRUE; + if (ctx->API == API_OPENGLES || ctx->API == API_OPENGLES2) + ctx->Extensions.EXT_texture_format_BGRA8888 = GL_TRUE; ctx->Extensions.APPLE_vertex_array_object = GL_TRUE; @@ -388,6 +390,15 @@ void st_init_extensions(struct st_context *st) PIPE_BIND_SAMPLER_VIEW, 0)) { ctx->Extensions.EXT_texture_sRGB = GL_TRUE; ctx->Extensions.EXT_texture_sRGB_decode = GL_TRUE; + if (screen->is_format_supported(screen, PIPE_FORMAT_A8B8G8R8_SRGB, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_RENDER_TARGET, 0) || + screen->is_format_supported(screen, PIPE_FORMAT_B8G8R8A8_SRGB, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_RENDER_TARGET, 0)) { + ctx->Extensions.EXT_framebuffer_sRGB = GL_TRUE; + ctx->Const.sRGBCapable = GL_TRUE; + } } if (screen->is_format_supported(screen, PIPE_FORMAT_R8G8_UNORM, @@ -400,10 +411,7 @@ void st_init_extensions(struct st_context *st) if (screen->is_format_supported(screen, PIPE_FORMAT_DXT5_RGBA, PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW, 0) && - (ctx->Mesa_DXTn || - screen->is_format_supported(screen, PIPE_FORMAT_DXT5_RGBA, - PIPE_TEXTURE_2D, 0, - PIPE_BIND_RENDER_TARGET, 0))) { + ctx->Mesa_DXTn) { ctx->Extensions.EXT_texture_compression_s3tc = GL_TRUE; ctx->Extensions.S3_s3tc = GL_TRUE; } @@ -418,6 +426,12 @@ void st_init_extensions(struct st_context *st) ctx->Extensions.MESA_ycbcr_texture = GL_TRUE; } + /* GL_EXT_texture_array */ + if (screen->get_param(screen, PIPE_CAP_ARRAY_TEXTURES)) { + ctx->Extensions.EXT_texture_array = GL_TRUE; + ctx->Extensions.MESA_texture_array = GL_TRUE; + } + /* GL_ARB_framebuffer_object */ if (ctx->Extensions.EXT_packed_depth_stencil) { /* we support always support GL_EXT_framebuffer_blit */ diff --git a/src/mesa/state_tracker/st_format.c b/src/mesa/state_tracker/st_format.c index 2e0a664dd01..577ee6189bd 100644 --- a/src/mesa/state_tracker/st_format.c +++ b/src/mesa/state_tracker/st_format.c @@ -113,12 +113,9 @@ st_format_datatype(enum pipe_format format) return GL_UNSIGNED_SHORT; } else { - /* compressed format? */ - assert(0); + /* probably a compressed format, unsupported anyway */ + return GL_NONE; } - - assert(0); - return GL_NONE; } @@ -511,6 +508,14 @@ st_choose_format(struct pipe_screen *screen, GLenum internalFormat, return default_rgba_format( screen, target, sample_count, bindings, geom_flags ); + case GL_BGRA: + if (screen->is_format_supported( screen, PIPE_FORMAT_B8G8R8A8_UNORM, + target, sample_count, bindings, + geom_flags )) + return PIPE_FORMAT_B8G8R8A8_UNORM; + return default_rgba_format( screen, target, sample_count, bindings, + geom_flags ); + case 3: case GL_RGB: case GL_RGB8: @@ -1032,7 +1037,8 @@ st_ChooseTextureFormat(struct gl_context *ctx, GLint internalFormat, boolean want_renderable = internalFormat == 3 || internalFormat == 4 || internalFormat == GL_RGB || internalFormat == GL_RGBA || - internalFormat == GL_RGB8 || internalFormat == GL_RGBA8; + internalFormat == GL_RGB8 || internalFormat == GL_RGBA8 || + internalFormat == GL_BGRA; return st_ChooseTextureFormat_renderable(ctx, internalFormat, format, type, want_renderable); @@ -1089,3 +1095,55 @@ st_sampler_compat_formats(enum pipe_format format1, enum pipe_format format2) return GL_FALSE; } + + + +/** + * This is used for translating texture border color and the clear + * color. For example, the clear color is interpreted according to + * the renderbuffer's base format. For example, if clearing a + * GL_LUMINANCE buffer, ClearColor[0] = luminance and ClearColor[1] = + * alpha. Similarly for texture border colors. + */ +void +st_translate_color(const GLfloat colorIn[4], GLenum baseFormat, + GLfloat colorOut[4]) +{ + switch (baseFormat) { + case GL_RED: + colorOut[0] = colorIn[0]; + colorOut[1] = 0.0F; + colorOut[2] = 0.0F; + colorOut[3] = 1.0F; + break; + case GL_RG: + colorOut[0] = colorIn[0]; + colorOut[1] = colorIn[1]; + colorOut[2] = 0.0F; + colorOut[3] = 1.0F; + break; + case GL_RGB: + colorOut[0] = colorIn[0]; + colorOut[1] = colorIn[1]; + colorOut[2] = colorIn[2]; + colorOut[3] = 1.0F; + break; + case GL_ALPHA: + colorOut[0] = colorOut[1] = colorOut[2] = 0.0; + colorOut[3] = colorIn[3]; + break; + case GL_LUMINANCE: + colorOut[0] = colorOut[1] = colorOut[2] = colorIn[0]; + colorOut[3] = 1.0; + break; + case GL_LUMINANCE_ALPHA: + colorOut[0] = colorOut[1] = colorOut[2] = colorIn[0]; + colorOut[3] = colorIn[3]; + break; + case GL_INTENSITY: + colorOut[0] = colorOut[1] = colorOut[2] = colorOut[3] = colorIn[0]; + break; + default: + COPY_4V(colorOut, colorIn); + } +} diff --git a/src/mesa/state_tracker/st_format.h b/src/mesa/state_tracker/st_format.h index fe195c1069b..0fb570f6ee4 100644 --- a/src/mesa/state_tracker/st_format.h +++ b/src/mesa/state_tracker/st_format.h @@ -77,4 +77,10 @@ st_equal_formats(enum pipe_format pFormat, GLenum format, GLenum type); extern GLboolean st_sampler_compat_formats(enum pipe_format format1, enum pipe_format format2); + +extern void +st_translate_color(const GLfloat colorIn[4], GLenum baseFormat, + GLfloat colorOut[4]); + + #endif /* ST_FORMAT_H */ diff --git a/src/mesa/state_tracker/st_gen_mipmap.c b/src/mesa/state_tracker/st_gen_mipmap.c index c5f6008a222..4bf68280839 100644 --- a/src/mesa/state_tracker/st_gen_mipmap.c +++ b/src/mesa/state_tracker/st_gen_mipmap.c @@ -105,13 +105,12 @@ st_render_mipmap(struct st_context *st, static void decompress_image(enum pipe_format format, const uint8_t *src, uint8_t *dst, - unsigned width, unsigned height) + unsigned width, unsigned height, unsigned src_stride) { const struct util_format_description *desc = util_format_description(format); const uint bw = util_format_get_blockwidth(format); const uint bh = util_format_get_blockheight(format); const uint dst_stride = 4 * MAX2(width, bw); - const uint src_stride = util_format_get_stride(format, width); desc->unpack_rgba_8unorm(dst, dst_stride, src, src_stride, width, height); @@ -144,10 +143,9 @@ decompress_image(enum pipe_format format, static void compress_image(enum pipe_format format, const uint8_t *src, uint8_t *dst, - unsigned width, unsigned height) + unsigned width, unsigned height, unsigned dst_stride) { const struct util_format_description *desc = util_format_description(format); - const uint dst_stride = util_format_get_stride(format, width); const uint src_stride = 4 * width; desc->pack_rgba_8unorm(dst, dst_stride, src, src_stride, width, height); @@ -236,7 +234,7 @@ fallback_generate_mipmap(struct gl_context *ctx, GLenum target, dstTemp = malloc(dstWidth2 * dstHeight2 * comps + 000); /* decompress the src image: srcData -> srcTemp */ - decompress_image(format, srcData, srcTemp, srcWidth, srcHeight); + decompress_image(format, srcData, srcTemp, srcWidth, srcHeight, srcTrans->stride); _mesa_generate_mipmap_level(target, datatype, comps, 0 /*border*/, @@ -248,7 +246,7 @@ fallback_generate_mipmap(struct gl_context *ctx, GLenum target, dstWidth2); /* stride in texels */ /* compress the new image: dstTemp -> dstData */ - compress_image(format, dstTemp, dstData, dstWidth, dstHeight); + compress_image(format, dstTemp, dstData, dstWidth, dstHeight, dstTrans->stride); free(srcTemp); free(dstTemp); @@ -338,6 +336,11 @@ st_generate_mipmap(struct gl_context *ctx, GLenum target, if (lastLevel == 0) return; + /* The texture isn't in a "complete" state yet so set the expected + * lastLevel here, since it won't get done in st_finalize_texture(). + */ + stObj->lastLevel = lastLevel; + if (pt->last_level < lastLevel) { /* The current gallium texture doesn't have space for all the * mipmap levels we need to generate. So allocate a new texture. @@ -352,13 +355,9 @@ st_generate_mipmap(struct gl_context *ctx, GLenum target, oldTex->width0, oldTex->height0, oldTex->depth0, + oldTex->array_size, oldTex->bind); - /* The texture isn't in a "complete" state yet so set the expected - * lastLevel here, since it won't get done in st_finalize_texture(). - */ - stObj->lastLevel = lastLevel; - /* This will copy the old texture's base image into the new texture * which we just allocated. */ @@ -367,8 +366,6 @@ st_generate_mipmap(struct gl_context *ctx, GLenum target, /* release the old tex (will likely be freed too) */ pipe_resource_reference(&oldTex, NULL); pipe_sampler_view_reference(&stObj->sampler_view, NULL); - - pt = stObj->pt; } else { /* Make sure that the base texture image data is present in the @@ -377,6 +374,8 @@ st_generate_mipmap(struct gl_context *ctx, GLenum target, st_finalize_texture(ctx, st->pipe, texObj); } + pt = stObj->pt; + assert(pt->last_level >= lastLevel); /* Try to generate the mipmap by rendering/texturing. If that fails, diff --git a/src/mesa/state_tracker/st_manager.c b/src/mesa/state_tracker/st_manager.c index 179e5dc8392..5c8853cfadb 100644 --- a/src/mesa/state_tracker/st_manager.c +++ b/src/mesa/state_tracker/st_manager.c @@ -426,19 +426,13 @@ st_framebuffer_create(struct st_framebuffer_iface *stfbi) struct gl_config mode; gl_buffer_index idx; + if (!stfbi) + return NULL; + stfb = CALLOC_STRUCT(st_framebuffer); if (!stfb) return NULL; - /* for FBO-only context */ - if (!stfbi) { - struct gl_framebuffer *base = _mesa_get_incomplete_framebuffer(); - - stfb->Base = *base; - - return stfb; - } - st_visual_to_context_mode(stfbi->visual, &mode); _mesa_initialize_window_framebuffer(&stfb->Base, &mode); @@ -764,7 +758,8 @@ st_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi, ret = _mesa_make_current(st->ctx, &stdraw->Base, &stread->Base); } else { - ret = FALSE; + struct gl_framebuffer *incomplete = _mesa_get_incomplete_framebuffer(); + ret = _mesa_make_current(st->ctx, incomplete, incomplete); } st_framebuffer_reference(&stdraw, NULL); diff --git a/src/mesa/state_tracker/st_mesa_to_tgsi.c b/src/mesa/state_tracker/st_mesa_to_tgsi.c index 42f1c2017f8..5c68fd78c30 100644 --- a/src/mesa/state_tracker/st_mesa_to_tgsi.c +++ b/src/mesa/state_tracker/st_mesa_to_tgsi.c @@ -286,6 +286,8 @@ translate_texture_target( GLuint textarget, case TEXTURE_3D_INDEX: return TGSI_TEXTURE_3D; case TEXTURE_CUBE_INDEX: return TGSI_TEXTURE_CUBE; case TEXTURE_RECT_INDEX: return TGSI_TEXTURE_RECT; + case TEXTURE_1D_ARRAY_INDEX: return TGSI_TEXTURE_1D_ARRAY; + case TEXTURE_2D_ARRAY_INDEX: return TGSI_TEXTURE_2D_ARRAY; default: debug_assert( 0 ); return TGSI_TEXTURE_1D; @@ -751,10 +753,12 @@ compile_instruction( /** * Emit the TGSI instructions to adjust the WPOS pixel center convention + * Basically, add (adjX, adjY) to the fragment position. */ static void emit_adjusted_wpos( struct st_translate *t, - const struct gl_program *program, GLfloat value) + const struct gl_program *program, + GLfloat adjX, GLfloat adjY) { struct ureg_program *ureg = t->ureg; struct ureg_dst wpos_temp = ureg_DECL_temporary(ureg); @@ -764,7 +768,7 @@ emit_adjusted_wpos( struct st_translate *t, * The shader might also use gl_FragCoord.w and .z. */ ureg_ADD(ureg, wpos_temp, wpos_input, - ureg_imm4f(ureg, value, value, 0.0f, 0.0f)); + ureg_imm4f(ureg, adjX, adjY, 0.0f, 0.0f)); t->inputs[t->inputMapping[FRAG_ATTRIB_WPOS]] = ureg_src(wpos_temp); } @@ -848,9 +852,12 @@ emit_wpos(struct st_context *st, boolean invert = FALSE; if (fp->OriginUpperLeft) { + /* Fragment shader wants origin in upper-left */ if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT)) { + /* the driver supports upper-left origin */ } else if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT)) { + /* the driver supports lower-left origin, need to invert Y */ ureg_property_fs_coord_origin(ureg, TGSI_FS_COORD_ORIGIN_LOWER_LEFT); invert = TRUE; } @@ -858,28 +865,37 @@ emit_wpos(struct st_context *st, assert(0); } else { + /* Fragment shader wants origin in lower-left */ if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT)) + /* the driver supports lower-left origin */ ureg_property_fs_coord_origin(ureg, TGSI_FS_COORD_ORIGIN_LOWER_LEFT); else if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT)) + /* the driver supports upper-left origin, need to invert Y */ invert = TRUE; else assert(0); } if (fp->PixelCenterInteger) { + /* Fragment shader wants pixel center integer */ if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER)) + /* the driver supports pixel center integer */ ureg_property_fs_coord_pixel_center(ureg, TGSI_FS_COORD_PIXEL_CENTER_INTEGER); else if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER)) - emit_adjusted_wpos(t, program, invert ? 0.5f : -0.5f); + /* the driver supports pixel center half integer, need to bias X,Y */ + emit_adjusted_wpos(t, program, 0.5f, invert ? 0.5f : -0.5f); else assert(0); } else { + /* Fragment shader wants pixel center half integer */ if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER)) { + /* the driver supports pixel center half integer */ } else if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER)) { + /* the driver supports pixel center integer, need to bias X,Y */ ureg_property_fs_coord_pixel_center(ureg, TGSI_FS_COORD_PIXEL_CENTER_INTEGER); - emit_adjusted_wpos(t, program, invert ? -0.5f : 0.5f); + emit_adjusted_wpos(t, program, 0.5f, invert ? -0.5f : 0.5f); } else assert(0); diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c index 7b32b46838a..fc1dfb3ef9e 100644 --- a/src/mesa/state_tracker/st_program.c +++ b/src/mesa/state_tracker/st_program.c @@ -108,6 +108,8 @@ delete_fp_variant(struct st_context *st, struct st_fp_variant *fpv) { if (fpv->driver_shader) cso_delete_fragment_shader(st->cso_context, fpv->driver_shader); + if (fpv->parameters) + _mesa_free_parameter_list(fpv->parameters); FREE(fpv); } @@ -404,6 +406,7 @@ st_translate_fragment_program(struct st_context *st, { struct pipe_context *pipe = st->pipe; struct st_fp_variant *variant = CALLOC_STRUCT(st_fp_variant); + GLboolean deleteFP = GL_FALSE; if (!variant) return NULL; @@ -413,17 +416,18 @@ st_translate_fragment_program(struct st_context *st, #if FEATURE_drawpix if (key->bitmap) { /* glBitmap drawing */ - struct gl_fragment_program *fp; + struct gl_fragment_program *fp; /* we free this temp program below */ st_make_bitmap_fragment_program(st, &stfp->Base, &fp, &variant->bitmap_sampler); variant->parameters = _mesa_clone_parameter_list(fp->Base.Parameters); stfp = st_fragment_program(fp); + deleteFP = GL_TRUE; } else if (key->drawpixels) { /* glDrawPixels drawing */ - struct gl_fragment_program *fp; + struct gl_fragment_program *fp; /* we free this temp program below */ if (key->drawpixels_z || key->drawpixels_stencil) { fp = st_make_drawpix_z_stencil_program(st, key->drawpixels_z, @@ -433,6 +437,7 @@ st_translate_fragment_program(struct st_context *st, /* RGBA */ st_make_drawpix_fragment_program(st, &stfp->Base, &fp); variant->parameters = _mesa_clone_parameter_list(fp->Base.Parameters); + deleteFP = GL_TRUE; } stfp = st_fragment_program(fp); } @@ -630,6 +635,12 @@ st_translate_fragment_program(struct st_context *st, debug_printf("\n"); } + if (deleteFP) { + /* Free the temporary program made above */ + struct gl_fragment_program *fp = &stfp->Base; + _mesa_reference_fragprog(st->ctx, &fp, NULL); + } + return variant; } diff --git a/src/mesa/state_tracker/st_texture.c b/src/mesa/state_tracker/st_texture.c index 155ea39f18c..1e0a8323ab8 100644 --- a/src/mesa/state_tracker/st_texture.c +++ b/src/mesa/state_tracker/st_texture.c @@ -59,6 +59,7 @@ st_texture_create(struct st_context *st, GLuint width0, GLuint height0, GLuint depth0, + GLuint layers, GLuint bind ) { struct pipe_resource pt, *newtex; @@ -68,6 +69,8 @@ st_texture_create(struct st_context *st, assert(width0 > 0); assert(height0 > 0); assert(depth0 > 0); + if (target == PIPE_TEXTURE_CUBE) + assert(layers == 6); DBG("%s target %s format %s last_level %d\n", __FUNCTION__, _mesa_lookup_enum_by_nr(target), @@ -84,7 +87,7 @@ st_texture_create(struct st_context *st, pt.width0 = width0; pt.height0 = height0; pt.depth0 = depth0; - pt.array_size = (target == PIPE_TEXTURE_CUBE ? 6 : 1); + pt.array_size = (target == PIPE_TEXTURE_CUBE ? 6 : layers); pt.usage = PIPE_USAGE_DEFAULT; pt.bind = bind; pt.flags = 0; @@ -98,6 +101,72 @@ st_texture_create(struct st_context *st, /** + * In OpenGL the number of 1D array texture layers is the "height" and + * the number of 2D array texture layers is the "depth". In Gallium the + * number of layers in an array texture is a separate 'array_size' field. + * This function converts dimensions from the former to the later. + */ +void +st_gl_texture_dims_to_pipe_dims(GLenum texture, + GLuint widthIn, + GLuint heightIn, + GLuint depthIn, + GLuint *widthOut, + GLuint *heightOut, + GLuint *depthOut, + GLuint *layersOut) +{ + switch (texture) { + case GL_TEXTURE_1D: + assert(heightIn == 1); + assert(depthIn == 1); + *widthOut = widthIn; + *heightOut = 1; + *depthOut = 1; + *layersOut = 1; + break; + case GL_TEXTURE_1D_ARRAY: + assert(depthIn == 1); + *widthOut = widthIn; + *heightOut = 1; + *depthOut = 1; + *layersOut = heightIn; + break; + case GL_TEXTURE_2D: + case GL_TEXTURE_RECTANGLE: + assert(depthIn == 1); + *widthOut = widthIn; + *heightOut = heightIn; + *depthOut = 1; + *layersOut = 1; + break; + case GL_TEXTURE_CUBE_MAP: + assert(depthIn == 1); + *widthOut = widthIn; + *heightOut = heightIn; + *depthOut = 1; + *layersOut = 6; + break; + case GL_TEXTURE_2D_ARRAY: + *widthOut = widthIn; + *heightOut = heightIn; + *depthOut = 1; + *layersOut = depthIn; + break; + default: + assert(0 && "Unexpected texture in st_gl_texture_dims_to_pipe_dims()"); + /* fall-through */ + case GL_TEXTURE_3D: + *widthOut = widthIn; + *heightOut = heightIn; + *depthOut = depthIn; + *layersOut = 1; + break; + } +} + + +/** * Check if a texture image can be pulled into a unified mipmap texture. */ GLboolean @@ -105,6 +174,8 @@ st_texture_match_image(const struct pipe_resource *pt, const struct gl_texture_image *image, GLuint face, GLuint level) { + GLuint ptWidth, ptHeight, ptDepth, ptLayers; + /* Images with borders are never pulled into mipmap textures. */ if (image->Border) @@ -115,12 +186,17 @@ st_texture_match_image(const struct pipe_resource *pt, if (st_mesa_format_to_pipe_format(image->TexFormat) != pt->format) return GL_FALSE; + st_gl_texture_dims_to_pipe_dims(image->TexObject->Target, + image->Width, image->Height, image->Depth, + &ptWidth, &ptHeight, &ptDepth, &ptLayers); + /* Test if this image's size matches what's expected in the * established texture. */ - if (image->Width != u_minify(pt->width0, level) || - image->Height != u_minify(pt->height0, level) || - image->Depth != u_minify(pt->depth0, level)) + if (ptWidth != u_minify(pt->width0, level) || + ptHeight != u_minify(pt->height0, level) || + ptDepth != u_minify(pt->depth0, level) || + ptLayers != pt->array_size) return GL_FALSE; return GL_TRUE; @@ -212,14 +288,20 @@ st_texture_image_data(struct st_context *st, GLuint src_row_stride, GLuint src_image_stride) { struct pipe_context *pipe = st->pipe; - GLuint depth = u_minify(dst->depth0, level); GLuint i; const GLubyte *srcUB = src; struct pipe_transfer *dst_transfer; + GLuint layers; + + if (dst->target == PIPE_TEXTURE_1D_ARRAY || + dst->target == PIPE_TEXTURE_2D_ARRAY) + layers = dst->array_size; + else + layers = u_minify(dst->depth0, level); DBG("%s\n", __FUNCTION__); - for (i = 0; i < depth; i++) { + for (i = 0; i < layers; i++) { dst_transfer = pipe_get_transfer(st->pipe, dst, level, face + i, PIPE_TRANSFER_WRITE, 0, 0, u_minify(dst->width0, level), diff --git a/src/mesa/state_tracker/st_texture.h b/src/mesa/state_tracker/st_texture.h index bca856d7142..d50c3c9af79 100644 --- a/src/mesa/state_tracker/st_texture.h +++ b/src/mesa/state_tracker/st_texture.h @@ -71,7 +71,10 @@ struct st_texture_object */ GLuint lastLevel; - /** The size of the level=0 mipmap image */ + /** The size of the level=0 mipmap image. + * Note that the number of 1D array layers will be in height0 and the + * number of 2D array layers will be in depth0, as in GL. + */ GLuint width0, height0, depth0; /* On validation any active images held in main memory or in other @@ -168,9 +171,20 @@ st_texture_create(struct st_context *st, GLuint width0, GLuint height0, GLuint depth0, + GLuint layers, GLuint tex_usage ); +extern void +st_gl_texture_dims_to_pipe_dims(GLenum texture, + GLuint widthIn, + GLuint heightIn, + GLuint depthIn, + GLuint *widthOut, + GLuint *heightOut, + GLuint *depthOut, + GLuint *layersOut); + /* Check if an image fits into an existing texture object. */ extern GLboolean diff --git a/src/mesa/swrast/s_trispan.h b/src/mesa/swrast/s_trispan.h deleted file mode 100644 index 15207e863e3..00000000000 --- a/src/mesa/swrast/s_trispan.h +++ /dev/null @@ -1,31 +0,0 @@ - -/* - * Mesa 3-D graphics library - * Version: 3.5 - * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and 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 shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS 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 - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION 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 S_TRISPAN_H -#define S_TRISPAN_H - - -#endif /* S_TRISPAN_H */ diff --git a/src/mesa/tnl/t_draw.c b/src/mesa/tnl/t_draw.c index 858b8281da3..b1967e65417 100644 --- a/src/mesa/tnl/t_draw.c +++ b/src/mesa/tnl/t_draw.c @@ -125,6 +125,43 @@ convert_half_to_float(const struct gl_client_array *input, } } +/** + * \brief Convert fixed-point to floating-point. + * + * In OpenGL, a fixed-point number is a "signed 2's complement 16.16 scaled + * integer" (Table 2.2 of the OpenGL ES 2.0 spec). + * + * If the buffer has the \c normalized flag set, the formula + * \code normalize(x) := (2*x + 1) / (2^16 - 1) \endcode + * is used to map the fixed-point numbers into the range [-1, 1]. + */ +static void +convert_fixed_to_float(const struct gl_client_array *input, + const GLubyte *ptr, GLfloat *fptr, + GLuint count) +{ + GLuint i, j; + const GLint size = input->Size; + + if (input->Normalized) { + for (i = 0; i < count; ++i) { + const GLfixed *in = (GLfixed *) ptr; + for (j = 0; j < size; ++j) { + *fptr++ = (GLfloat) (2 * in[j] + 1) / (GLfloat) ((1 << 16) - 1); + } + ptr += input->StrideB; + } + } else { + for (i = 0; i < count; ++i) { + const GLfixed *in = (GLfixed *) ptr; + for (j = 0; j < size; ++j) { + *fptr++ = in[j] / (GLfloat) (1 << 16); + } + ptr += input->StrideB; + } + } +} + /* Adjust pointer to point at first requested element, convert to * floating point, populate VB->AttribPtr[]. */ @@ -174,6 +211,9 @@ static void _tnl_import_array( struct gl_context *ctx, case GL_HALF_FLOAT: convert_half_to_float(input, ptr, fptr, count, sz); break; + case GL_FIXED: + convert_fixed_to_float(input, ptr, fptr, count); + break; default: assert(0); break; diff --git a/src/mesa/vbo/vbo.h b/src/mesa/vbo/vbo.h index 37940efdc11..6834f3b5aa5 100644 --- a/src/mesa/vbo/vbo.h +++ b/src/mesa/vbo/vbo.h @@ -130,6 +130,8 @@ void vbo_use_buffer_objects(struct gl_context *ctx); void vbo_set_draw_func(struct gl_context *ctx, vbo_draw_func func); +void vbo_check_buffers_are_unmapped(struct gl_context *ctx); + void GLAPIENTRY _es_Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a); diff --git a/src/mesa/vbo/vbo_exec.h b/src/mesa/vbo/vbo_exec.h index d56c91cd094..1b0ed79473b 100644 --- a/src/mesa/vbo/vbo_exec.h +++ b/src/mesa/vbo/vbo_exec.h @@ -40,13 +40,16 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "vbo_attrib.h" +/** + * Max number of primitives (number of glBegin/End pairs) per VBO. + */ #define VBO_MAX_PRIM 64 -/* Wierd implementation stuff: + +/** + * Size of the VBO to use for glBegin/glVertex/glEnd-style rendering. */ #define VBO_VERT_BUFFER_SIZE (1024*64) /* bytes */ -#define VBO_MAX_ATTR_CODEGEN 16 -#define ERROR_ATTRIB 16 /** Current vertex program mode */ @@ -152,7 +155,6 @@ struct vbo_exec_context void vbo_exec_init( struct gl_context *ctx ); void vbo_exec_destroy( struct gl_context *ctx ); void vbo_exec_invalidate_state( struct gl_context *ctx, GLuint new_state ); -void vbo_exec_FlushVertices_internal( struct gl_context *ctx, GLboolean unmap ); void vbo_exec_BeginVertices( struct gl_context *ctx ); void vbo_exec_FlushVertices( struct gl_context *ctx, GLuint flags ); diff --git a/src/mesa/vbo/vbo_exec_api.c b/src/mesa/vbo/vbo_exec_api.c index 03d6bb4aefe..2f9f3ec7c46 100644 --- a/src/mesa/vbo/vbo_exec_api.c +++ b/src/mesa/vbo/vbo_exec_api.c @@ -159,8 +159,7 @@ static void vbo_exec_copy_to_current( struct vbo_exec_context *exec ) exec->vtx.attrsz[i], exec->vtx.attrptr[i]); - if (memcmp(current, tmp, sizeof(tmp)) != 0) - { + if (memcmp(current, tmp, sizeof(tmp)) != 0) { memcpy(current, tmp, sizeof(tmp)); /* Given that we explicitly state size here, there is no need @@ -192,14 +191,18 @@ static void vbo_exec_copy_to_current( struct vbo_exec_context *exec ) } -static void vbo_exec_copy_from_current( struct vbo_exec_context *exec ) +/** + * Copy current vertex attribute values into the current vertex. + */ +static void +vbo_exec_copy_from_current(struct vbo_exec_context *exec) { struct gl_context *ctx = exec->ctx; struct vbo_context *vbo = vbo_context(ctx); GLint i; - for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) { - const GLfloat *current = (GLfloat *)vbo->currval[i].Ptr; + for (i = VBO_ATTRIB_POS + 1; i < VBO_ATTRIB_MAX; i++) { + const GLfloat *current = (GLfloat *) vbo->currval[i].Ptr; switch (exec->vtx.attrsz[i]) { case 4: exec->vtx.attrptr[i][3] = current[3]; case 3: exec->vtx.attrptr[i][2] = current[2]; @@ -213,17 +216,21 @@ static void vbo_exec_copy_from_current( struct vbo_exec_context *exec ) /** * Flush existing data, set new attrib size, replay copied vertices. + * This is called when we transition from a small vertex attribute size + * to a larger one. Ex: glTexCoord2f -> glTexCoord4f. + * We need to go back over the previous 2-component texcoords and insert + * zero and one values. */ -static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec, - GLuint attr, - GLuint newsz ) +static void +vbo_exec_wrap_upgrade_vertex(struct vbo_exec_context *exec, + GLuint attr, GLuint newSize ) { struct gl_context *ctx = exec->ctx; struct vbo_context *vbo = vbo_context(ctx); - GLint lastcount = exec->vtx.vert_count; + const GLint lastcount = exec->vtx.vert_count; GLfloat *old_attrptr[VBO_ATTRIB_MAX]; - GLuint old_vtx_size = exec->vtx.vertex_size; - GLuint oldsz = exec->vtx.attrsz[attr]; + const GLuint old_vtx_size = exec->vtx.vertex_size; /* floats per vertex */ + const GLuint oldSize = exec->vtx.attrsz[attr]; GLuint i; /* Run pipeline on current vertices, copy wrapped vertices @@ -239,7 +246,7 @@ static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec, memcpy(old_attrptr, exec->vtx.attrptr, sizeof(old_attrptr)); } - if (unlikely(oldsz)) { + if (unlikely(oldSize)) { /* Do a COPY_TO_CURRENT to ensure back-copying works for the * case when the attribute already exists in the vertex and is * having its size increased. @@ -251,21 +258,21 @@ static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec, * begin/end so that they don't bloat the vertices. */ if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END && - !oldsz && lastcount > 8 && exec->vtx.vertex_size) { + !oldSize && lastcount > 8 && exec->vtx.vertex_size) { vbo_exec_copy_to_current( exec ); reset_attrfv( exec ); } /* Fix up sizes: */ - exec->vtx.attrsz[attr] = newsz; - exec->vtx.vertex_size += newsz - oldsz; + exec->vtx.attrsz[attr] = newSize; + exec->vtx.vertex_size += newSize - oldSize; exec->vtx.max_vert = ((VBO_VERT_BUFFER_SIZE - exec->vtx.buffer_used) / (exec->vtx.vertex_size * sizeof(GLfloat))); exec->vtx.vert_count = 0; exec->vtx.buffer_ptr = exec->vtx.buffer_map; - if (unlikely(oldsz)) { + if (unlikely(oldSize)) { /* Size changed, recalculate all the attrptr[] values */ GLfloat *tmp = exec->vtx.vertex; @@ -283,11 +290,11 @@ static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec, * values. */ vbo_exec_copy_from_current( exec ); - - } else { + } + else { /* Just have to append the new attribute at the end */ exec->vtx.attrptr[attr] = exec->vtx.vertex + - exec->vtx.vertex_size - newsz; + exec->vtx.vertex_size - newSize; } /* Replay stored vertices to translate them @@ -311,10 +318,10 @@ static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec, GLint new_offset = exec->vtx.attrptr[j] - exec->vtx.vertex; if (j == attr) { - if (oldsz) { + if (oldSize) { GLfloat tmp[4]; - COPY_CLEAN_4V(tmp, oldsz, data + old_offset); - COPY_SZ_4V(dest + new_offset, newsz, tmp); + COPY_CLEAN_4V(tmp, oldSize, data + old_offset); + COPY_SZ_4V(dest + new_offset, newSize, tmp); } else { GLfloat *current = (GLfloat *)vbo->currval[j].Ptr; COPY_SZ_4V(dest + new_offset, sz, current); @@ -337,70 +344,82 @@ static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec, } -static void vbo_exec_fixup_vertex( struct gl_context *ctx, - GLuint attr, GLuint sz ) +/** + * This is when a vertex attribute transitions to a different size. + * For example, we saw a bunch of glTexCoord2f() calls and now we got a + * glTexCoord4f() call. We promote the array from size=2 to size=4. + */ +static void +vbo_exec_fixup_vertex(struct gl_context *ctx, GLuint attr, GLuint newSize) { struct vbo_exec_context *exec = &vbo_context(ctx)->exec; - int i; - if (sz > exec->vtx.attrsz[attr]) { + if (newSize > exec->vtx.attrsz[attr]) { /* New size is larger. Need to flush existing vertices and get * an enlarged vertex format. */ - vbo_exec_wrap_upgrade_vertex( exec, attr, sz ); + vbo_exec_wrap_upgrade_vertex( exec, attr, newSize ); } - else if (sz < exec->vtx.active_sz[attr]) { + else if (newSize < exec->vtx.active_sz[attr]) { static const GLfloat id[4] = { 0, 0, 0, 1 }; + GLuint i; /* New size is smaller - just need to fill in some * zeros. Don't need to flush or wrap. */ - for (i = sz ; i <= exec->vtx.attrsz[attr] ; i++) + for (i = newSize; i <= exec->vtx.attrsz[attr]; i++) exec->vtx.attrptr[attr][i-1] = id[i-1]; } - exec->vtx.active_sz[attr] = sz; + exec->vtx.active_sz[attr] = newSize; /* Does setting NeedFlush belong here? Necessitates resetting * vtxfmt on each flush (otherwise flags won't get reset * afterwards). */ if (attr == 0) - exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; + ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; } -/* +/** + * This macro is used to implement all the glVertex, glColor, glTexCoord, + * glVertexAttrib, etc functions. */ -#define ATTR( A, N, V0, V1, V2, V3 ) \ -do { \ - struct vbo_exec_context *exec = &vbo_context(ctx)->exec; \ +#define ATTR( A, N, V0, V1, V2, V3 ) \ +do { \ + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; \ \ - if (unlikely(!(exec->ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT))) \ - ctx->Driver.BeginVertices( ctx ); \ + if (unlikely(!(ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT))) \ + ctx->Driver.BeginVertices( ctx ); \ + \ if (unlikely(exec->vtx.active_sz[A] != N)) \ vbo_exec_fixup_vertex(ctx, A, N); \ \ - { \ - GLfloat *dest = exec->vtx.attrptr[A]; \ - if (N>0) dest[0] = V0; \ - if (N>1) dest[1] = V1; \ - if (N>2) dest[2] = V2; \ - if (N>3) dest[3] = V3; \ - } \ - \ - if ((A) == 0) { \ - GLuint i; \ - \ - for (i = 0; i < exec->vtx.vertex_size; i++) \ - exec->vtx.buffer_ptr[i] = exec->vtx.vertex[i]; \ - \ + { \ + GLfloat *dest = exec->vtx.attrptr[A]; \ + if (N>0) dest[0] = V0; \ + if (N>1) dest[1] = V1; \ + if (N>2) dest[2] = V2; \ + if (N>3) dest[3] = V3; \ + } \ + \ + if ((A) == 0) { \ + /* This is a glVertex call */ \ + GLuint i; \ + \ + for (i = 0; i < exec->vtx.vertex_size; i++) \ + exec->vtx.buffer_ptr[i] = exec->vtx.vertex[i]; \ + \ exec->vtx.buffer_ptr += exec->vtx.vertex_size; \ - exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; \ - \ - if (++exec->vtx.vert_count >= exec->vtx.max_vert) \ - vbo_exec_vtx_wrap( exec ); \ - } \ + \ + /* Set FLUSH_STORED_VERTICES to indicate that there's now */ \ + /* something to draw (not just updating a color or texcoord).*/ \ + ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; \ + \ + if (++exec->vtx.vert_count >= exec->vtx.max_vert) \ + vbo_exec_vtx_wrap( exec ); \ + } \ } while (0) @@ -514,6 +533,24 @@ static void GLAPIENTRY vbo_exec_EvalPoint2( GLint i, GLint j ) /** + * Flush (draw) vertices. + * \param unmap - leave VBO unmapped after flushing? + */ +static void +vbo_exec_FlushVertices_internal(struct vbo_exec_context *exec, GLboolean unmap) +{ + if (exec->vtx.vert_count || unmap) { + vbo_exec_vtx_flush( exec, unmap ); + } + + if (exec->vtx.vertex_size) { + vbo_exec_copy_to_current( exec ); + reset_attrfv( exec ); + } +} + + +/** * Called via glBegin. */ static void GLAPIENTRY vbo_exec_Begin( GLenum mode ) @@ -539,7 +576,7 @@ static void GLAPIENTRY vbo_exec_Begin( GLenum mode ) * begin/end pairs. */ if (exec->vtx.vertex_size && !exec->vtx.attrsz[0]) - vbo_exec_FlushVertices_internal( ctx, GL_FALSE ); + vbo_exec_FlushVertices_internal(exec, GL_FALSE); i = exec->vtx.prim_count++; exec->vtx.prim[i].mode = mode; @@ -825,7 +862,7 @@ void vbo_exec_vtx_init( struct vbo_exec_context *exec ) /* Hook our functions into the dispatch table. */ - _mesa_install_exec_vtxfmt( exec->ctx, &exec->vtxfmt ); + _mesa_install_exec_vtxfmt( ctx, &exec->vtxfmt ); for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) { ASSERT(i < Elements(exec->vtx.attrsz)); @@ -894,32 +931,23 @@ void vbo_exec_vtx_destroy( struct vbo_exec_context *exec ) _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL); } -void vbo_exec_BeginVertices( struct gl_context *ctx ) -{ - struct vbo_exec_context *exec = &vbo_context(ctx)->exec; - if (0) printf("%s\n", __FUNCTION__); - vbo_exec_vtx_map( exec ); - assert((exec->ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) == 0); - exec->ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; -} - -void vbo_exec_FlushVertices_internal( struct gl_context *ctx, GLboolean unmap ) +/** + * Called upon first glVertex, glColor, glTexCoord, etc. + */ +void vbo_exec_BeginVertices( struct gl_context *ctx ) { struct vbo_exec_context *exec = &vbo_context(ctx)->exec; - if (exec->vtx.vert_count || unmap) { - vbo_exec_vtx_flush( exec, unmap ); - } + vbo_exec_vtx_map( exec ); - if (exec->vtx.vertex_size) { - vbo_exec_copy_to_current( exec ); - reset_attrfv( exec ); - } + assert((ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) == 0); + ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; } /** + * Called via ctx->Driver.FlushVertices() * \param flags bitmask of FLUSH_STORED_VERTICES, FLUSH_UPDATE_CURRENT */ void vbo_exec_FlushVertices( struct gl_context *ctx, GLuint flags ) @@ -932,10 +960,8 @@ void vbo_exec_FlushVertices( struct gl_context *ctx, GLuint flags ) assert(exec->flush_call_depth == 1); #endif - if (0) printf("%s\n", __FUNCTION__); - - if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) { - if (0) printf("%s - inside begin/end\n", __FUNCTION__); + if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) { + /* We've had glBegin but not glEnd! */ #ifdef DEBUG exec->flush_call_depth--; assert(exec->flush_call_depth == 0); @@ -943,14 +969,12 @@ void vbo_exec_FlushVertices( struct gl_context *ctx, GLuint flags ) return; } - vbo_exec_FlushVertices_internal( ctx, GL_TRUE ); + /* Flush (draw), and make sure VBO is left unmapped when done */ + vbo_exec_FlushVertices_internal(exec, GL_TRUE); /* Need to do this to ensure BeginVertices gets called again: */ - if (exec->ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) - exec->ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT; - - exec->ctx->Driver.NeedFlush &= ~flags; + ctx->Driver.NeedFlush &= ~(FLUSH_UPDATE_CURRENT | flags); #ifdef DEBUG exec->flush_call_depth--; diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c index 80085c17c5c..457343a1a5c 100644 --- a/src/mesa/vbo/vbo_exec_array.c +++ b/src/mesa/vbo/vbo_exec_array.c @@ -39,6 +39,43 @@ /** + * All vertex buffers should be in an unmapped state when we're about + * to draw. This debug function checks that. + */ +static void +check_buffers_are_unmapped(const struct gl_client_array **inputs) +{ +#ifdef DEBUG + GLuint i; + + for (i = 0; i < VERT_ATTRIB_MAX; i++) { + if (inputs[i]) { + struct gl_buffer_object *obj = inputs[i]->BufferObj; + assert(!_mesa_bufferobj_mapped(obj)); + } + } +#endif +} + + +/** + * A debug function that may be called from other parts of Mesa as + * needed during debugging. + */ +void +vbo_check_buffers_are_unmapped(struct gl_context *ctx) +{ + struct vbo_context *vbo = vbo_context(ctx); + struct vbo_exec_context *exec = &vbo->exec; + /* check the current vertex arrays */ + check_buffers_are_unmapped(exec->array.inputs); + /* check the current glBegin/glVertex/glEnd-style VBO */ + assert(!_mesa_bufferobj_mapped(exec->vtx.bufferobj)); +} + + + +/** * Compute min and max elements by scanning the index buffer for * glDraw[Range]Elements() calls. * If primitive restart is enabled, we need to ignore restart @@ -502,8 +539,13 @@ recalculate_input_bindings(struct gl_context *ctx) static void bind_arrays(struct gl_context *ctx) { + if (!ctx->Array.RebindArrays) { + return; + } + bind_array_obj(ctx); recalculate_input_bindings(ctx); + ctx->Array.RebindArrays = GL_FALSE; } @@ -576,6 +618,7 @@ vbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start, if (primCount > 0) { /* draw one or two prims */ + check_buffers_are_unmapped(exec->array.inputs); vbo->draw_prims(ctx, exec->array.inputs, prim, primCount, NULL, GL_TRUE, start, start + count - 1); } @@ -585,6 +628,7 @@ vbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start, prim[0].start = start; prim[0].count = count; + check_buffers_are_unmapped(exec->array.inputs); vbo->draw_prims(ctx, exec->array.inputs, prim, 1, NULL, GL_TRUE, start, start + count - 1); } @@ -790,6 +834,7 @@ vbo_validated_drawrangeelements(struct gl_context *ctx, GLenum mode, * for the latter case elsewhere. */ + check_buffers_are_unmapped(exec->array.inputs); vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib, index_bounds_valid, start, end ); } @@ -1106,6 +1151,7 @@ vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode, prim[i].basevertex = 0; } + check_buffers_are_unmapped(exec->array.inputs); vbo->draw_prims(ctx, exec->array.inputs, prim, primcount, &ib, GL_FALSE, ~0, ~0); } else { @@ -1130,6 +1176,7 @@ vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode, else prim[0].basevertex = 0; + check_buffers_are_unmapped(exec->array.inputs); vbo->draw_prims(ctx, exec->array.inputs, prim, 1, &ib, GL_FALSE, ~0, ~0); } diff --git a/src/mesa/vbo/vbo_exec_draw.c b/src/mesa/vbo/vbo_exec_draw.c index 87f64310561..539658021e3 100644 --- a/src/mesa/vbo/vbo_exec_draw.c +++ b/src/mesa/vbo/vbo_exec_draw.c @@ -245,6 +245,7 @@ vbo_exec_bind_arrays( struct gl_context *ctx ) arrays[attr]._MaxElement = count; /* ??? */ varying_inputs |= 1 << attr; + ctx->NewState |= _NEW_ARRAY; } } @@ -252,6 +253,9 @@ vbo_exec_bind_arrays( struct gl_context *ctx ) } +/** + * Unmap the VBO. This is called before drawing. + */ static void vbo_exec_vtx_unmap( struct vbo_exec_context *exec ) { @@ -284,6 +288,9 @@ vbo_exec_vtx_unmap( struct vbo_exec_context *exec ) } +/** + * Map the vertex buffer to begin storing glVertex, glColor, etc data. + */ void vbo_exec_vtx_map( struct vbo_exec_context *exec ) { @@ -300,14 +307,12 @@ vbo_exec_vtx_map( struct vbo_exec_context *exec ) if (!_mesa_is_bufferobj(exec->vtx.bufferobj)) return; - if (exec->vtx.buffer_map != NULL) { - assert(0); - exec->vtx.buffer_map = NULL; - exec->vtx.buffer_ptr = NULL; - } + assert(!exec->vtx.buffer_map); + assert(!exec->vtx.buffer_ptr); if (VBO_VERT_BUFFER_SIZE > exec->vtx.buffer_used + 1024 && ctx->Driver.MapBufferRange) { + /* The VBO exists and there's room for more */ exec->vtx.buffer_map = (GLfloat *)ctx->Driver.MapBufferRange(ctx, target, @@ -320,6 +325,7 @@ vbo_exec_vtx_map( struct vbo_exec_context *exec ) } if (!exec->vtx.buffer_map) { + /* Need to allocate a new VBO */ exec->vtx.buffer_used = 0; ctx->Driver.BufferData(ctx, target, @@ -348,9 +354,10 @@ vbo_exec_vtx_map( struct vbo_exec_context *exec ) /** * Execute the buffer and save copied verts. + * \param keep_unmapped if true, leave the VBO unmapped when we're done. */ void -vbo_exec_vtx_flush( struct vbo_exec_context *exec, GLboolean unmap ) +vbo_exec_vtx_flush(struct vbo_exec_context *exec, GLboolean keepUnmapped) { if (0) vbo_exec_debug_verts( exec ); @@ -390,7 +397,7 @@ vbo_exec_vtx_flush( struct vbo_exec_context *exec, GLboolean unmap ) /* If using a real VBO, get new storage -- unless asked not to. */ - if (_mesa_is_bufferobj(exec->vtx.bufferobj) && !unmap) { + if (_mesa_is_bufferobj(exec->vtx.bufferobj) && !keepUnmapped) { vbo_exec_vtx_map( exec ); } } @@ -398,14 +405,13 @@ vbo_exec_vtx_flush( struct vbo_exec_context *exec, GLboolean unmap ) /* May have to unmap explicitly if we didn't draw: */ - if (unmap && + if (keepUnmapped && _mesa_is_bufferobj(exec->vtx.bufferobj) && exec->vtx.buffer_map) { vbo_exec_vtx_unmap( exec ); } - - if (unmap || exec->vtx.vertex_size == 0) + if (keepUnmapped || exec->vtx.vertex_size == 0) exec->vtx.max_vert = 0; else exec->vtx.max_vert = ((VBO_VERT_BUFFER_SIZE - exec->vtx.buffer_used) / diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c index 4ee78e9e103..c8199544526 100644 --- a/src/mesa/vbo/vbo_save_api.c +++ b/src/mesa/vbo/vbo_save_api.c @@ -646,11 +646,11 @@ static void _save_reset_vertex( struct gl_context *ctx ) do { \ struct vbo_save_context *save = &vbo_context(ctx)->save; \ \ - if (save->active_sz[A] != N) \ + if (save->active_sz[A] != N) \ save_fixup_vertex(ctx, A, N); \ \ { \ - GLfloat *dest = save->attrptr[A]; \ + GLfloat *dest = save->attrptr[A]; \ if (N>0) dest[0] = V0; \ if (N>1) dest[1] = V1; \ if (N>2) dest[2] = V2; \ @@ -663,7 +663,7 @@ do { \ for (i = 0; i < save->vertex_size; i++) \ save->buffer_ptr[i] = save->vertex[i]; \ \ - save->buffer_ptr += save->vertex_size; \ + save->buffer_ptr += save->vertex_size; \ \ if (++save->vert_count >= save->max_vert) \ _save_wrap_filled_vertex( ctx ); \ diff --git a/src/mesa/vbo/vbo_save_draw.c b/src/mesa/vbo/vbo_save_draw.c index d0454bf6212..634a6d3f84b 100644 --- a/src/mesa/vbo/vbo_save_draw.c +++ b/src/mesa/vbo/vbo_save_draw.c @@ -202,6 +202,7 @@ static void vbo_bind_vertex_list(struct gl_context *ctx, buffer_offset += node->attrsz[src] * sizeof(GLfloat); varying_inputs |= 1<<attr; + ctx->NewState |= _NEW_ARRAY; } } diff --git a/src/mesa/x86-64/xform4.S b/src/mesa/x86-64/xform4.S index e52a6118c31..6141e434679 100644 --- a/src/mesa/x86-64/xform4.S +++ b/src/mesa/x86-64/xform4.S @@ -55,7 +55,7 @@ _mesa_x86_64_transform_points4_general: * rdx = source */ movl V4F_COUNT(%rdx), %ecx /* count */ - movzx V4F_STRIDE(%rdx), %eax /* stride */ + movzbl V4F_STRIDE(%rdx), %eax /* stride */ movl %ecx, V4F_COUNT(%rdi) /* set dest count */ movl $4, V4F_SIZE(%rdi) /* set dest size */ @@ -138,7 +138,7 @@ _mesa_x86_64_transform_points4_3d: movaps 16(%rax), %xmm10 movl V4F_COUNT(%rdx), %ecx /* count */ - movzx V4F_STRIDE(%rdx), %eax /* stride */ + movzbl V4F_STRIDE(%rdx), %eax /* stride */ movl %ecx, V4F_COUNT(%rdi) /* set dest count */ movl $4, V4F_SIZE(%rdi) /* set dest size */ @@ -199,7 +199,7 @@ p4_3d_done: _mesa_x86_64_transform_points4_identity: movl V4F_COUNT(%rdx), %ecx /* count */ - movzx V4F_STRIDE(%rdx), %eax /* stride */ + movzbl V4F_STRIDE(%rdx), %eax /* stride */ movl %ecx, V4F_COUNT(%rdi) /* set dest count */ movl $4, V4F_SIZE(%rdi) /* set dest size */ @@ -228,7 +228,7 @@ p4_identity_done: _mesa_3dnow_transform_points4_3d_no_rot: movl V4F_COUNT(%rdx), %ecx /* count */ - movzx V4F_STRIDE(%rdx), %eax /* stride */ + movzbl V4F_STRIDE(%rdx), %eax /* stride */ movl %ecx, V4F_COUNT(%rdi) /* set dest count */ movl $4, V4F_SIZE(%rdi) /* set dest size */ @@ -293,7 +293,7 @@ p4_3d_no_rot_done: _mesa_3dnow_transform_points4_perspective: movl V4F_COUNT(%rdx), %ecx /* count */ - movzx V4F_STRIDE(%rdx), %eax /* stride */ + movzbl V4F_STRIDE(%rdx), %eax /* stride */ movl %ecx, V4F_COUNT(%rdi) /* set dest count */ movl $4, V4F_SIZE(%rdi) /* set dest size */ @@ -360,7 +360,7 @@ p4_perspective_done: _mesa_3dnow_transform_points4_2d_no_rot: movl V4F_COUNT(%rdx), %ecx /* count */ - movzx V4F_STRIDE(%rdx), %eax /* stride */ + movzbl V4F_STRIDE(%rdx), %eax /* stride */ movl %ecx, V4F_COUNT(%rdi) /* set dest count */ movl $4, V4F_SIZE(%rdi) /* set dest size */ @@ -416,7 +416,7 @@ p4_2d_no_rot_done: _mesa_3dnow_transform_points4_2d: movl V4F_COUNT(%rdx), %ecx /* count */ - movzx V4F_STRIDE(%rdx), %eax /* stride */ + movzbl V4F_STRIDE(%rdx), %eax /* stride */ movl %ecx, V4F_COUNT(%rdi) /* set dest count */ movl $4, V4F_SIZE(%rdi) /* set dest size */ diff --git a/src/mesa/x86/read_rgba_span_x86.S b/src/mesa/x86/read_rgba_span_x86.S index 3886a510bbc..3be4515b114 100644 --- a/src/mesa/x86/read_rgba_span_x86.S +++ b/src/mesa/x86/read_rgba_span_x86.S @@ -77,7 +77,9 @@ */ .globl _generic_read_RGBA_span_BGRA8888_REV_MMX +#ifndef USE_DRICORE .hidden _generic_read_RGBA_span_BGRA8888_REV_MMX +#endif .type _generic_read_RGBA_span_BGRA8888_REV_MMX, @function _generic_read_RGBA_span_BGRA8888_REV_MMX: pushl %ebx @@ -172,7 +174,9 @@ _generic_read_RGBA_span_BGRA8888_REV_MMX: */ .globl _generic_read_RGBA_span_BGRA8888_REV_SSE +#ifndef USE_DRICORE .hidden _generic_read_RGBA_span_BGRA8888_REV_SSE +#endif .type _generic_read_RGBA_span_BGRA8888_REV_SSE, @function _generic_read_RGBA_span_BGRA8888_REV_SSE: pushl %esi @@ -335,7 +339,9 @@ _generic_read_RGBA_span_BGRA8888_REV_SSE: .text .globl _generic_read_RGBA_span_BGRA8888_REV_SSE2 +#ifndef USE_DRICORE .hidden _generic_read_RGBA_span_BGRA8888_REV_SSE2 +#endif .type _generic_read_RGBA_span_BGRA8888_REV_SSE2, @function _generic_read_RGBA_span_BGRA8888_REV_SSE2: pushl %esi @@ -494,7 +500,9 @@ _generic_read_RGBA_span_BGRA8888_REV_SSE2: .text .globl _generic_read_RGBA_span_RGB565_MMX +#ifndef USE_DRICORE .hidden _generic_read_RGBA_span_RGB565_MMX +#endif .type _generic_read_RGBA_span_RGB565_MMX, @function _generic_read_RGBA_span_RGB565_MMX: @@ -648,7 +656,7 @@ _generic_read_RGBA_span_RGB565_MMX: testl $0x01, %ecx je .L01 - movzxw (%eax), %ecx + movzwl (%eax), %ecx movd %ecx, %mm4 pshufw $0x00, %mm4, %mm0 diff --git a/src/talloc/SConscript b/src/talloc/SConscript deleted file mode 100644 index 3bf7029bb25..00000000000 --- a/src/talloc/SConscript +++ /dev/null @@ -1,20 +0,0 @@ -Import('*') - -if env['platform'] != 'windows': - Return() - -env = env.Clone() - -talloc = env.SharedLibrary( - target = 'talloc', - source = ['talloc.c', 'talloc.def'], -) - -env.InstallSharedLibrary(talloc) - -if env['platform'] == 'windows': - talloc = env.FindIxes(talloc, 'LIBPREFIX', 'LIBSUFFIX') -else: - talloc = env.FindIxes(talloc, 'SHLIBPREFIX', 'SHLIBSUFFIX') - -Export('talloc') diff --git a/src/talloc/gpl-3.0.txt b/src/talloc/gpl-3.0.txt deleted file mode 100644 index 94a9ed024d3..00000000000 --- a/src/talloc/gpl-3.0.txt +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - <one line to give the program's name and a brief idea of what it does.> - Copyright (C) <year> <name of author> - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - <program> Copyright (C) <year> <name of author> - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -<http://www.gnu.org/licenses/>. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -<http://www.gnu.org/philosophy/why-not-lgpl.html>. diff --git a/src/talloc/lgpl-3.0.txt b/src/talloc/lgpl-3.0.txt deleted file mode 100644 index 65c5ca88a67..00000000000 --- a/src/talloc/lgpl-3.0.txt +++ /dev/null @@ -1,165 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - - 0. Additional Definitions. - - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. - - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". - - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - - 1. Exception to Section 3 of the GNU GPL. - - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - - 2. Conveying Modified Versions. - - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or - - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - - 3. Object Code Incorporating Material from Library Header Files. - - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the object code with a copy of the GNU GPL and this license - document. - - 4. Combined Works. - - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. - - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. - - d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. - - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) - - 5. Combined Libraries. - - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. - - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - - 6. Revised Versions of the GNU Lesser General Public License. - - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. - - Each version is given a distinguishing version number. If the -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License "or any later version" -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. - - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. diff --git a/src/talloc/talloc.c b/src/talloc/talloc.c deleted file mode 100644 index cc01346a7f0..00000000000 --- a/src/talloc/talloc.c +++ /dev/null @@ -1,2034 +0,0 @@ -/* - Samba Unix SMB/CIFS implementation. - - Samba trivial allocation library - new interface - - NOTE: Please read talloc_guide.txt for full documentation - - Copyright (C) Andrew Tridgell 2004 - Copyright (C) Stefan Metzmacher 2006 - - ** NOTE! The following LGPL license applies to the talloc - ** library. This does NOT imply that all of Samba is released - ** under the LGPL - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ - -/* - inspired by http://swapped.cc/halloc/ -*/ - -#include "talloc.h" -#include <string.h> - -#define TALLOC_MIN(a,b) ((a)<(b)?(a):(b)) - -/* Visual C++ 2008 compatibility */ -#if defined(_MSC_VER) && !defined(_cplusplus) -typedef size_t ssize_t; -#define inline __inline -#endif - -/* Xcode/gcc4.0 compatibility */ -#if defined(__APPLE__) || defined(__MINGW32__) -static size_t strnlen (const char* s, size_t n) -{ - size_t i; - for (i = 0; i < n; ++i) - { - if (s[i] == '\0') - break; - } - return i; -} -#endif - -/* Visual C++ 2008 & Xcode/gcc4.0 compatibility */ -#if !defined(_cplusplus) && (defined(WIN32) || defined(__APPLE__)) -typedef int bool; -#define false 0 -#define true 1 -#endif - - -#ifdef TALLOC_BUILD_VERSION_MAJOR -#if (TALLOC_VERSION_MAJOR != TALLOC_BUILD_VERSION_MAJOR) -#error "TALLOC_VERSION_MAJOR != TALLOC_BUILD_VERSION_MAJOR" -#endif -#endif - -#ifdef TALLOC_BUILD_VERSION_MINOR -#if (TALLOC_VERSION_MINOR != TALLOC_BUILD_VERSION_MINOR) -#error "TALLOC_VERSION_MINOR != TALLOC_BUILD_VERSION_MINOR" -#endif -#endif - -/* use this to force every realloc to change the pointer, to stress test - code that might not cope */ -#define ALWAYS_REALLOC 0 - - -#define MAX_TALLOC_SIZE 0x10000000 -#define TALLOC_MAGIC_BASE 0xe814ec70 -#define TALLOC_MAGIC ( \ - TALLOC_MAGIC_BASE + \ - (TALLOC_VERSION_MAJOR << 12) + \ - (TALLOC_VERSION_MINOR << 4) \ -) - -#define TALLOC_FLAG_FREE 0x01 -#define TALLOC_FLAG_LOOP 0x02 -#define TALLOC_FLAG_POOL 0x04 /* This is a talloc pool */ -#define TALLOC_FLAG_POOLMEM 0x08 /* This is allocated in a pool */ -#define TALLOC_MAGIC_REFERENCE ((const char *)1) - -/* by default we abort when given a bad pointer (such as when talloc_free() is called - on a pointer that came from malloc() */ -#ifndef TALLOC_ABORT -#define TALLOC_ABORT(reason) abort() -#endif - -#ifndef discard_const_p -#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) -# define discard_const_p(type, ptr) ((type *)((intptr_t)(ptr))) -#else -# define discard_const_p(type, ptr) ((type *)(ptr)) -#endif -#endif - -/* these macros gain us a few percent of speed on gcc */ -#if (__GNUC__ >= 3) -/* the strange !! is to ensure that __builtin_expect() takes either 0 or 1 - as its first argument */ -#ifndef likely -#define likely(x) __builtin_expect(!!(x), 1) -#endif -#ifndef unlikely -#define unlikely(x) __builtin_expect(!!(x), 0) -#endif -#else -#ifndef likely -#define likely(x) (x) -#endif -#ifndef unlikely -#define unlikely(x) (x) -#endif -#endif - -/* this null_context is only used if talloc_enable_leak_report() or - talloc_enable_leak_report_full() is called, otherwise it remains - NULL -*/ -static void *null_context; -static void *autofree_context; - -struct talloc_reference_handle { - struct talloc_reference_handle *next, *prev; - void *ptr; - const char *location; -}; - -typedef int (*talloc_destructor_t)(void *); - -struct talloc_chunk { - struct talloc_chunk *next, *prev; - struct talloc_chunk *parent, *child; - struct talloc_reference_handle *refs; - talloc_destructor_t destructor; - const char *name; - size_t size; - unsigned flags; - - /* - * "pool" has dual use: - * - * For the talloc pool itself (i.e. TALLOC_FLAG_POOL is set), "pool" - * marks the end of the currently allocated area. - * - * For members of the pool (i.e. TALLOC_FLAG_POOLMEM is set), "pool" - * is a pointer to the struct talloc_chunk of the pool that it was - * allocated from. This way children can quickly find the pool to chew - * from. - */ - void *pool; -}; - -/* 16 byte alignment seems to keep everyone happy */ -#define TC_HDR_SIZE ((sizeof(struct talloc_chunk)+15)&~15) -#define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc)) - -int talloc_version_major(void) -{ - return TALLOC_VERSION_MAJOR; -} - -int talloc_version_minor(void) -{ - return TALLOC_VERSION_MINOR; -} - -static void (*talloc_log_fn)(const char *message); - -void talloc_set_log_fn(void (*log_fn)(const char *message)) -{ - talloc_log_fn = log_fn; -} - -static void talloc_log(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2); -static void talloc_log(const char *fmt, ...) -{ - va_list ap; - char *message; - - if (!talloc_log_fn) { - return; - } - - va_start(ap, fmt); - message = talloc_vasprintf(NULL, fmt, ap); - va_end(ap); - - talloc_log_fn(message); - talloc_free(message); -} - -static void talloc_log_stderr(const char *message) -{ - fprintf(stderr, "%s", message); -} - -void talloc_set_log_stderr(void) -{ - talloc_set_log_fn(talloc_log_stderr); -} - -static void (*talloc_abort_fn)(const char *reason); - -void talloc_set_abort_fn(void (*abort_fn)(const char *reason)) -{ - talloc_abort_fn = abort_fn; -} - -static void talloc_abort(const char *reason) -{ - talloc_log("%s\n", reason); - - if (!talloc_abort_fn) { - TALLOC_ABORT(reason); - } - - talloc_abort_fn(reason); -} - -static void talloc_abort_magic(unsigned magic) -{ - unsigned striped = magic - TALLOC_MAGIC_BASE; - unsigned major = (striped & 0xFFFFF000) >> 12; - unsigned minor = (striped & 0x00000FF0) >> 4; - talloc_log("Bad talloc magic[0x%08X/%u/%u] expected[0x%08X/%u/%u]\n", - magic, major, minor, - TALLOC_MAGIC, TALLOC_VERSION_MAJOR, TALLOC_VERSION_MINOR); - talloc_abort("Bad talloc magic value - wrong talloc version used/mixed"); -} - -static void talloc_abort_double_free(void) -{ - talloc_abort("Bad talloc magic value - double free"); -} - -static void talloc_abort_unknown_value(void) -{ - talloc_abort("Bad talloc magic value - unknown value"); -} - -/* panic if we get a bad magic value */ -static inline struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr) -{ - const char *pp = (const char *)ptr; - struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE); - if (unlikely((tc->flags & (TALLOC_FLAG_FREE | ~0xF)) != TALLOC_MAGIC)) { - if ((tc->flags & (~0xFFF)) == TALLOC_MAGIC_BASE) { - talloc_abort_magic(tc->flags & (~0xF)); - return NULL; - } - - if (tc->flags & TALLOC_FLAG_FREE) { - talloc_log("talloc: double free error - first free may be at %s\n", tc->name); - talloc_abort_double_free(); - return NULL; - } else { - talloc_abort_unknown_value(); - return NULL; - } - } - return tc; -} - -/* hook into the front of the list */ -#define _TLIST_ADD(list, p) \ -do { \ - if (!(list)) { \ - (list) = (p); \ - (p)->next = (p)->prev = NULL; \ - } else { \ - (list)->prev = (p); \ - (p)->next = (list); \ - (p)->prev = NULL; \ - (list) = (p); \ - }\ -} while (0) - -/* remove an element from a list - element doesn't have to be in list. */ -#define _TLIST_REMOVE(list, p) \ -do { \ - if ((p) == (list)) { \ - (list) = (p)->next; \ - if (list) (list)->prev = NULL; \ - } else { \ - if ((p)->prev) (p)->prev->next = (p)->next; \ - if ((p)->next) (p)->next->prev = (p)->prev; \ - } \ - if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \ -} while (0) - - -/* - return the parent chunk of a pointer -*/ -static inline struct talloc_chunk *talloc_parent_chunk(const void *ptr) -{ - struct talloc_chunk *tc; - - if (unlikely(ptr == NULL)) { - return NULL; - } - - tc = talloc_chunk_from_ptr(ptr); - while (tc->prev) tc=tc->prev; - - return tc->parent; -} - -void *talloc_parent(const void *ptr) -{ - struct talloc_chunk *tc = talloc_parent_chunk(ptr); - return tc? TC_PTR_FROM_CHUNK(tc) : NULL; -} - -/* - find parents name -*/ -const char *talloc_parent_name(const void *ptr) -{ - struct talloc_chunk *tc = talloc_parent_chunk(ptr); - return tc? tc->name : NULL; -} - -/* - A pool carries an in-pool object count count in the first 16 bytes. - bytes. This is done to support talloc_steal() to a parent outside of the - pool. The count includes the pool itself, so a talloc_free() on a pool will - only destroy the pool if the count has dropped to zero. A talloc_free() of a - pool member will reduce the count, and eventually also call free(3) on the - pool memory. - - The object count is not put into "struct talloc_chunk" because it is only - relevant for talloc pools and the alignment to 16 bytes would increase the - memory footprint of each talloc chunk by those 16 bytes. -*/ - -#define TALLOC_POOL_HDR_SIZE 16 - -static unsigned int *talloc_pool_objectcount(struct talloc_chunk *tc) -{ - return (unsigned int *)((char *)tc + sizeof(struct talloc_chunk)); -} - -/* - Allocate from a pool -*/ - -static struct talloc_chunk *talloc_alloc_pool(struct talloc_chunk *parent, - size_t size) -{ - struct talloc_chunk *pool_ctx = NULL; - size_t space_left; - struct talloc_chunk *result; - size_t chunk_size; - - if (parent == NULL) { - return NULL; - } - - if (parent->flags & TALLOC_FLAG_POOL) { - pool_ctx = parent; - } - else if (parent->flags & TALLOC_FLAG_POOLMEM) { - pool_ctx = (struct talloc_chunk *)parent->pool; - } - - if (pool_ctx == NULL) { - return NULL; - } - - space_left = ((char *)pool_ctx + TC_HDR_SIZE + pool_ctx->size) - - ((char *)pool_ctx->pool); - - /* - * Align size to 16 bytes - */ - chunk_size = ((size + 15) & ~15); - - if (space_left < chunk_size) { - return NULL; - } - - result = (struct talloc_chunk *)pool_ctx->pool; - -#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED) - VALGRIND_MAKE_MEM_UNDEFINED(result, size); -#endif - - pool_ctx->pool = (void *)((char *)result + chunk_size); - - result->flags = TALLOC_MAGIC | TALLOC_FLAG_POOLMEM; - result->pool = pool_ctx; - - *talloc_pool_objectcount(pool_ctx) += 1; - - return result; -} - -/* - Allocate a bit of memory as a child of an existing pointer -*/ -static inline void *__talloc(const void *context, size_t size) -{ - struct talloc_chunk *tc = NULL; - - if (unlikely(context == NULL)) { - context = null_context; - } - - if (unlikely(size >= MAX_TALLOC_SIZE)) { - return NULL; - } - - if (context != NULL) { - tc = talloc_alloc_pool(talloc_chunk_from_ptr(context), - TC_HDR_SIZE+size); - } - - if (tc == NULL) { - tc = (struct talloc_chunk *)malloc(TC_HDR_SIZE+size); - if (unlikely(tc == NULL)) return NULL; - tc->flags = TALLOC_MAGIC; - tc->pool = NULL; - } - - tc->size = size; - tc->destructor = NULL; - tc->child = NULL; - tc->name = NULL; - tc->refs = NULL; - - if (likely(context)) { - struct talloc_chunk *parent = talloc_chunk_from_ptr(context); - - if (parent->child) { - parent->child->parent = NULL; - tc->next = parent->child; - tc->next->prev = tc; - } else { - tc->next = NULL; - } - tc->parent = parent; - tc->prev = NULL; - parent->child = tc; - } else { - tc->next = tc->prev = tc->parent = NULL; - } - - return TC_PTR_FROM_CHUNK(tc); -} - -/* - * Create a talloc pool - */ - -void *talloc_pool(const void *context, size_t size) -{ - void *result = __talloc(context, size + TALLOC_POOL_HDR_SIZE); - struct talloc_chunk *tc; - - if (unlikely(result == NULL)) { - return NULL; - } - - tc = talloc_chunk_from_ptr(result); - - tc->flags |= TALLOC_FLAG_POOL; - tc->pool = (char *)result + TALLOC_POOL_HDR_SIZE; - - *talloc_pool_objectcount(tc) = 1; - -#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS) - VALGRIND_MAKE_MEM_NOACCESS(tc->pool, size); -#endif - - return result; -} - -/* - setup a destructor to be called on free of a pointer - the destructor should return 0 on success, or -1 on failure. - if the destructor fails then the free is failed, and the memory can - be continued to be used -*/ -void _talloc_set_destructor(const void *ptr, int (*destructor)(void *)) -{ - struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); - tc->destructor = destructor; -} - -/* - increase the reference count on a piece of memory. -*/ -int talloc_increase_ref_count(const void *ptr) -{ - if (unlikely(!talloc_reference(null_context, ptr))) { - return -1; - } - return 0; -} - -/* - helper for talloc_reference() - - this is referenced by a function pointer and should not be inline -*/ -static int talloc_reference_destructor(struct talloc_reference_handle *handle) -{ - struct talloc_chunk *ptr_tc = talloc_chunk_from_ptr(handle->ptr); - _TLIST_REMOVE(ptr_tc->refs, handle); - return 0; -} - -/* - more efficient way to add a name to a pointer - the name must point to a - true string constant -*/ -static inline void _talloc_set_name_const(const void *ptr, const char *name) -{ - struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); - tc->name = name; -} - -/* - internal talloc_named_const() -*/ -static inline void *_talloc_named_const(const void *context, size_t size, const char *name) -{ - void *ptr; - - ptr = __talloc(context, size); - if (unlikely(ptr == NULL)) { - return NULL; - } - - _talloc_set_name_const(ptr, name); - - return ptr; -} - -/* - make a secondary reference to a pointer, hanging off the given context. - the pointer remains valid until both the original caller and this given - context are freed. - - the major use for this is when two different structures need to reference the - same underlying data, and you want to be able to free the two instances separately, - and in either order -*/ -void *_talloc_reference_loc(const void *context, const void *ptr, const char *location) -{ - struct talloc_chunk *tc; - struct talloc_reference_handle *handle; - if (unlikely(ptr == NULL)) return NULL; - - tc = talloc_chunk_from_ptr(ptr); - handle = (struct talloc_reference_handle *)_talloc_named_const(context, - sizeof(struct talloc_reference_handle), - TALLOC_MAGIC_REFERENCE); - if (unlikely(handle == NULL)) return NULL; - - /* note that we hang the destructor off the handle, not the - main context as that allows the caller to still setup their - own destructor on the context if they want to */ - talloc_set_destructor(handle, talloc_reference_destructor); - handle->ptr = discard_const_p(void, ptr); - handle->location = location; - _TLIST_ADD(tc->refs, handle); - return handle->ptr; -} - -static void *_talloc_steal_internal(const void *new_ctx, const void *ptr); - -/* - internal talloc_free call -*/ -static inline int _talloc_free_internal(void *ptr, const char *location) -{ - struct talloc_chunk *tc; - - if (unlikely(ptr == NULL)) { - return -1; - } - - tc = talloc_chunk_from_ptr(ptr); - - if (unlikely(tc->refs)) { - int is_child; - /* check this is a reference from a child or grantchild - * back to it's parent or grantparent - * - * in that case we need to remove the reference and - * call another instance of talloc_free() on the current - * pointer. - */ - is_child = talloc_is_parent(tc->refs, ptr); - _talloc_free_internal(tc->refs, location); - if (is_child) { - return _talloc_free_internal(ptr, location); - } - return -1; - } - - if (unlikely(tc->flags & TALLOC_FLAG_LOOP)) { - /* we have a free loop - stop looping */ - return 0; - } - - if (unlikely(tc->destructor)) { - talloc_destructor_t d = tc->destructor; - if (d == (talloc_destructor_t)-1) { - return -1; - } - tc->destructor = (talloc_destructor_t)-1; - if (d(ptr) == -1) { - tc->destructor = d; - return -1; - } - tc->destructor = NULL; - } - - if (tc->parent) { - _TLIST_REMOVE(tc->parent->child, tc); - if (tc->parent->child) { - tc->parent->child->parent = tc->parent; - } - } else { - if (tc->prev) tc->prev->next = tc->next; - if (tc->next) tc->next->prev = tc->prev; - } - - tc->flags |= TALLOC_FLAG_LOOP; - - while (tc->child) { - /* we need to work out who will own an abandoned child - if it cannot be freed. In priority order, the first - choice is owner of any remaining reference to this - pointer, the second choice is our parent, and the - final choice is the null context. */ - void *child = TC_PTR_FROM_CHUNK(tc->child); - const void *new_parent = null_context; - if (unlikely(tc->child->refs)) { - struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs); - if (p) new_parent = TC_PTR_FROM_CHUNK(p); - } - if (unlikely(_talloc_free_internal(child, location) == -1)) { - if (new_parent == null_context) { - struct talloc_chunk *p = talloc_parent_chunk(ptr); - if (p) new_parent = TC_PTR_FROM_CHUNK(p); - } - _talloc_steal_internal(new_parent, child); - } - } - - tc->flags |= TALLOC_FLAG_FREE; - - /* we mark the freed memory with where we called the free - * from. This means on a double free error we can report where - * the first free came from - */ - tc->name = location; - - if (tc->flags & (TALLOC_FLAG_POOL|TALLOC_FLAG_POOLMEM)) { - struct talloc_chunk *pool; - unsigned int *pool_object_count; - - pool = (tc->flags & TALLOC_FLAG_POOL) - ? tc : (struct talloc_chunk *)tc->pool; - - pool_object_count = talloc_pool_objectcount(pool); - - if (*pool_object_count == 0) { - talloc_abort("Pool object count zero!"); - return 0; - } - - *pool_object_count -= 1; - - if (*pool_object_count == 0) { - free(pool); - } - } - else { - free(tc); - } - return 0; -} - -/* - move a lump of memory from one talloc context to another return the - ptr on success, or NULL if it could not be transferred. - passing NULL as ptr will always return NULL with no side effects. -*/ -static void *_talloc_steal_internal(const void *new_ctx, const void *ptr) -{ - struct talloc_chunk *tc, *new_tc; - - if (unlikely(!ptr)) { - return NULL; - } - - if (unlikely(new_ctx == NULL)) { - new_ctx = null_context; - } - - tc = talloc_chunk_from_ptr(ptr); - - if (unlikely(new_ctx == NULL)) { - if (tc->parent) { - _TLIST_REMOVE(tc->parent->child, tc); - if (tc->parent->child) { - tc->parent->child->parent = tc->parent; - } - } else { - if (tc->prev) tc->prev->next = tc->next; - if (tc->next) tc->next->prev = tc->prev; - } - - tc->parent = tc->next = tc->prev = NULL; - return discard_const_p(void, ptr); - } - - new_tc = talloc_chunk_from_ptr(new_ctx); - - if (unlikely(tc == new_tc || tc->parent == new_tc)) { - return discard_const_p(void, ptr); - } - - if (tc->parent) { - _TLIST_REMOVE(tc->parent->child, tc); - if (tc->parent->child) { - tc->parent->child->parent = tc->parent; - } - } else { - if (tc->prev) tc->prev->next = tc->next; - if (tc->next) tc->next->prev = tc->prev; - } - - tc->parent = new_tc; - if (new_tc->child) new_tc->child->parent = NULL; - _TLIST_ADD(new_tc->child, tc); - - return discard_const_p(void, ptr); -} - -/* - move a lump of memory from one talloc context to another return the - ptr on success, or NULL if it could not be transferred. - passing NULL as ptr will always return NULL with no side effects. -*/ -void *_talloc_steal_loc(const void *new_ctx, const void *ptr, const char *location) -{ - struct talloc_chunk *tc; - - if (unlikely(ptr == NULL)) { - return NULL; - } - - tc = talloc_chunk_from_ptr(ptr); - - if (unlikely(tc->refs != NULL) && talloc_parent(ptr) != new_ctx) { - struct talloc_reference_handle *h; - - talloc_log("WARNING: talloc_steal with references at %s\n", - location); - - for (h=tc->refs; h; h=h->next) { - talloc_log("\treference at %s\n", - h->location); - } - } - - return _talloc_steal_internal(new_ctx, ptr); -} - -/* - this is like a talloc_steal(), but you must supply the old - parent. This resolves the ambiguity in a talloc_steal() which is - called on a context that has more than one parent (via references) - - The old parent can be either a reference or a parent -*/ -void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr) -{ - struct talloc_chunk *tc; - struct talloc_reference_handle *h; - - if (unlikely(ptr == NULL)) { - return NULL; - } - - if (old_parent == talloc_parent(ptr)) { - return _talloc_steal_internal(new_parent, ptr); - } - - tc = talloc_chunk_from_ptr(ptr); - for (h=tc->refs;h;h=h->next) { - if (talloc_parent(h) == old_parent) { - if (_talloc_steal_internal(new_parent, h) != h) { - return NULL; - } - return discard_const_p(void, ptr); - } - } - - /* it wasn't a parent */ - return NULL; -} - -/* - remove a secondary reference to a pointer. This undo's what - talloc_reference() has done. The context and pointer arguments - must match those given to a talloc_reference() -*/ -static inline int talloc_unreference(const void *context, const void *ptr) -{ - struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); - struct talloc_reference_handle *h; - - if (unlikely(context == NULL)) { - context = null_context; - } - - for (h=tc->refs;h;h=h->next) { - struct talloc_chunk *p = talloc_parent_chunk(h); - if (p == NULL) { - if (context == NULL) break; - } else if (TC_PTR_FROM_CHUNK(p) == context) { - break; - } - } - if (h == NULL) { - return -1; - } - - return _talloc_free_internal(h, __location__); -} - -/* - remove a specific parent context from a pointer. This is a more - controlled varient of talloc_free() -*/ -int talloc_unlink(const void *context, void *ptr) -{ - struct talloc_chunk *tc_p, *new_p; - void *new_parent; - - if (ptr == NULL) { - return -1; - } - - if (context == NULL) { - context = null_context; - } - - if (talloc_unreference(context, ptr) == 0) { - return 0; - } - - if (context == NULL) { - if (talloc_parent_chunk(ptr) != NULL) { - return -1; - } - } else { - if (talloc_chunk_from_ptr(context) != talloc_parent_chunk(ptr)) { - return -1; - } - } - - tc_p = talloc_chunk_from_ptr(ptr); - - if (tc_p->refs == NULL) { - return _talloc_free_internal(ptr, __location__); - } - - new_p = talloc_parent_chunk(tc_p->refs); - if (new_p) { - new_parent = TC_PTR_FROM_CHUNK(new_p); - } else { - new_parent = NULL; - } - - if (talloc_unreference(new_parent, ptr) != 0) { - return -1; - } - - _talloc_steal_internal(new_parent, ptr); - - return 0; -} - -/* - add a name to an existing pointer - va_list version -*/ -static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); - -static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) -{ - struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); - tc->name = talloc_vasprintf(ptr, fmt, ap); - if (likely(tc->name)) { - _talloc_set_name_const(tc->name, ".name"); - } - return tc->name; -} - -/* - add a name to an existing pointer -*/ -const char *talloc_set_name(const void *ptr, const char *fmt, ...) -{ - const char *name; - va_list ap; - va_start(ap, fmt); - name = talloc_set_name_v(ptr, fmt, ap); - va_end(ap); - return name; -} - - -/* - create a named talloc pointer. Any talloc pointer can be named, and - talloc_named() operates just like talloc() except that it allows you - to name the pointer. -*/ -void *talloc_named(const void *context, size_t size, const char *fmt, ...) -{ - va_list ap; - void *ptr; - const char *name; - - ptr = __talloc(context, size); - if (unlikely(ptr == NULL)) return NULL; - - va_start(ap, fmt); - name = talloc_set_name_v(ptr, fmt, ap); - va_end(ap); - - if (unlikely(name == NULL)) { - _talloc_free_internal(ptr, __location__); - return NULL; - } - - return ptr; -} - -/* - return the name of a talloc ptr, or "UNNAMED" -*/ -const char *talloc_get_name(const void *ptr) -{ - struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); - if (unlikely(tc->name == TALLOC_MAGIC_REFERENCE)) { - return ".reference"; - } - if (likely(tc->name)) { - return tc->name; - } - return "UNNAMED"; -} - - -/* - check if a pointer has the given name. If it does, return the pointer, - otherwise return NULL -*/ -void *talloc_check_name(const void *ptr, const char *name) -{ - const char *pname; - if (unlikely(ptr == NULL)) return NULL; - pname = talloc_get_name(ptr); - if (likely(pname == name || strcmp(pname, name) == 0)) { - return discard_const_p(void, ptr); - } - return NULL; -} - -static void talloc_abort_type_missmatch(const char *location, - const char *name, - const char *expected) -{ - const char *reason; - - reason = talloc_asprintf(NULL, - "%s: Type mismatch: name[%s] expected[%s]", - location, - name?name:"NULL", - expected); - if (!reason) { - reason = "Type mismatch"; - } - - talloc_abort(reason); -} - -void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location) -{ - const char *pname; - - if (unlikely(ptr == NULL)) { - talloc_abort_type_missmatch(location, NULL, name); - return NULL; - } - - pname = talloc_get_name(ptr); - if (likely(pname == name || strcmp(pname, name) == 0)) { - return discard_const_p(void, ptr); - } - - talloc_abort_type_missmatch(location, pname, name); - return NULL; -} - -/* - this is for compatibility with older versions of talloc -*/ -void *talloc_init(const char *fmt, ...) -{ - va_list ap; - void *ptr; - const char *name; - - /* - * samba3 expects talloc_report_depth_cb(NULL, ...) - * reports all talloc'ed memory, so we need to enable - * null_tracking - */ - talloc_enable_null_tracking(); - - ptr = __talloc(NULL, 0); - if (unlikely(ptr == NULL)) return NULL; - - va_start(ap, fmt); - name = talloc_set_name_v(ptr, fmt, ap); - va_end(ap); - - if (unlikely(name == NULL)) { - _talloc_free_internal(ptr, __location__); - return NULL; - } - - return ptr; -} - -/* - this is a replacement for the Samba3 talloc_destroy_pool functionality. It - should probably not be used in new code. It's in here to keep the talloc - code consistent across Samba 3 and 4. -*/ -void talloc_free_children(void *ptr) -{ - struct talloc_chunk *tc; - - if (unlikely(ptr == NULL)) { - return; - } - - tc = talloc_chunk_from_ptr(ptr); - - while (tc->child) { - /* we need to work out who will own an abandoned child - if it cannot be freed. In priority order, the first - choice is owner of any remaining reference to this - pointer, the second choice is our parent, and the - final choice is the null context. */ - void *child = TC_PTR_FROM_CHUNK(tc->child); - const void *new_parent = null_context; - if (unlikely(tc->child->refs)) { - struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs); - if (p) new_parent = TC_PTR_FROM_CHUNK(p); - } - if (unlikely(talloc_free(child) == -1)) { - if (new_parent == null_context) { - struct talloc_chunk *p = talloc_parent_chunk(ptr); - if (p) new_parent = TC_PTR_FROM_CHUNK(p); - } - _talloc_steal_internal(new_parent, child); - } - } - - if ((tc->flags & TALLOC_FLAG_POOL) - && (*talloc_pool_objectcount(tc) == 1)) { - tc->pool = ((char *)tc + TC_HDR_SIZE + TALLOC_POOL_HDR_SIZE); -#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS) - VALGRIND_MAKE_MEM_NOACCESS( - tc->pool, tc->size - TALLOC_POOL_HDR_SIZE); -#endif - } -} - -/* - Allocate a bit of memory as a child of an existing pointer -*/ -void *_talloc(const void *context, size_t size) -{ - return __talloc(context, size); -} - -/* - externally callable talloc_set_name_const() -*/ -void talloc_set_name_const(const void *ptr, const char *name) -{ - _talloc_set_name_const(ptr, name); -} - -/* - create a named talloc pointer. Any talloc pointer can be named, and - talloc_named() operates just like talloc() except that it allows you - to name the pointer. -*/ -void *talloc_named_const(const void *context, size_t size, const char *name) -{ - return _talloc_named_const(context, size, name); -} - -/* - free a talloc pointer. This also frees all child pointers of this - pointer recursively - - return 0 if the memory is actually freed, otherwise -1. The memory - will not be freed if the ref_count is > 1 or the destructor (if - any) returns non-zero -*/ -int _talloc_free(void *ptr, const char *location) -{ - struct talloc_chunk *tc; - - if (unlikely(ptr == NULL)) { - return -1; - } - - tc = talloc_chunk_from_ptr(ptr); - - if (unlikely(tc->refs != NULL)) { - struct talloc_reference_handle *h; - - talloc_log("ERROR: talloc_free with references at %s\n", - location); - - for (h=tc->refs; h; h=h->next) { - talloc_log("\treference at %s\n", - h->location); - } - return -1; - } - - return _talloc_free_internal(ptr, location); -} - - - -/* - A talloc version of realloc. The context argument is only used if - ptr is NULL -*/ -void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name) -{ - struct talloc_chunk *tc; - void *new_ptr; - bool malloced = false; - - /* size zero is equivalent to free() */ - if (unlikely(size == 0)) { - talloc_unlink(context, ptr); - return NULL; - } - - if (unlikely(size >= MAX_TALLOC_SIZE)) { - return NULL; - } - - /* realloc(NULL) is equivalent to malloc() */ - if (ptr == NULL) { - return _talloc_named_const(context, size, name); - } - - tc = talloc_chunk_from_ptr(ptr); - - /* don't allow realloc on referenced pointers */ - if (unlikely(tc->refs)) { - return NULL; - } - - /* don't let anybody try to realloc a talloc_pool */ - if (unlikely(tc->flags & TALLOC_FLAG_POOL)) { - return NULL; - } - - /* don't shrink if we have less than 1k to gain */ - if ((size < tc->size) && ((tc->size - size) < 1024)) { - tc->size = size; - return ptr; - } - - /* by resetting magic we catch users of the old memory */ - tc->flags |= TALLOC_FLAG_FREE; - -#if ALWAYS_REALLOC - new_ptr = malloc(size + TC_HDR_SIZE); - if (new_ptr) { - memcpy(new_ptr, tc, tc->size + TC_HDR_SIZE); - free(tc); - } -#else - if (tc->flags & TALLOC_FLAG_POOLMEM) { - - new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE); - *talloc_pool_objectcount((struct talloc_chunk *) - (tc->pool)) -= 1; - - if (new_ptr == NULL) { - new_ptr = malloc(TC_HDR_SIZE+size); - malloced = true; - } - - if (new_ptr) { - memcpy(new_ptr, tc, TALLOC_MIN(tc->size,size) + TC_HDR_SIZE); - } - } - else { - new_ptr = realloc(tc, size + TC_HDR_SIZE); - } -#endif - if (unlikely(!new_ptr)) { - tc->flags &= ~TALLOC_FLAG_FREE; - return NULL; - } - - tc = (struct talloc_chunk *)new_ptr; - tc->flags &= ~TALLOC_FLAG_FREE; - if (malloced) { - tc->flags &= ~TALLOC_FLAG_POOLMEM; - } - if (tc->parent) { - tc->parent->child = tc; - } - if (tc->child) { - tc->child->parent = tc; - } - - if (tc->prev) { - tc->prev->next = tc; - } - if (tc->next) { - tc->next->prev = tc; - } - - tc->size = size; - _talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name); - - return TC_PTR_FROM_CHUNK(tc); -} - -/* - a wrapper around talloc_steal() for situations where you are moving a pointer - between two structures, and want the old pointer to be set to NULL -*/ -void *_talloc_move(const void *new_ctx, const void *_pptr) -{ - const void **pptr = discard_const_p(const void *,_pptr); - void *ret = talloc_steal(new_ctx, discard_const_p(void, *pptr)); - (*pptr) = NULL; - return ret; -} - -/* - return the total size of a talloc pool (subtree) -*/ -size_t talloc_total_size(const void *ptr) -{ - size_t total = 0; - struct talloc_chunk *c, *tc; - - if (ptr == NULL) { - ptr = null_context; - } - if (ptr == NULL) { - return 0; - } - - tc = talloc_chunk_from_ptr(ptr); - - if (tc->flags & TALLOC_FLAG_LOOP) { - return 0; - } - - tc->flags |= TALLOC_FLAG_LOOP; - - if (likely(tc->name != TALLOC_MAGIC_REFERENCE)) { - total = tc->size; - } - for (c=tc->child;c;c=c->next) { - total += talloc_total_size(TC_PTR_FROM_CHUNK(c)); - } - - tc->flags &= ~TALLOC_FLAG_LOOP; - - return total; -} - -/* - return the total number of blocks in a talloc pool (subtree) -*/ -size_t talloc_total_blocks(const void *ptr) -{ - size_t total = 0; - struct talloc_chunk *c, *tc; - - if (ptr == NULL) { - ptr = null_context; - } - if (ptr == NULL) { - return 0; - } - - tc = talloc_chunk_from_ptr(ptr); - - if (tc->flags & TALLOC_FLAG_LOOP) { - return 0; - } - - tc->flags |= TALLOC_FLAG_LOOP; - - total++; - for (c=tc->child;c;c=c->next) { - total += talloc_total_blocks(TC_PTR_FROM_CHUNK(c)); - } - - tc->flags &= ~TALLOC_FLAG_LOOP; - - return total; -} - -/* - return the number of external references to a pointer -*/ -size_t talloc_reference_count(const void *ptr) -{ - struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); - struct talloc_reference_handle *h; - size_t ret = 0; - - for (h=tc->refs;h;h=h->next) { - ret++; - } - return ret; -} - -/* - report on memory usage by all children of a pointer, giving a full tree view -*/ -void talloc_report_depth_cb(const void *ptr, int depth, int max_depth, - void (*callback)(const void *ptr, - int depth, int max_depth, - int is_ref, - void *private_data), - void *private_data) -{ - struct talloc_chunk *c, *tc; - - if (ptr == NULL) { - ptr = null_context; - } - if (ptr == NULL) return; - - tc = talloc_chunk_from_ptr(ptr); - - if (tc->flags & TALLOC_FLAG_LOOP) { - return; - } - - callback(ptr, depth, max_depth, 0, private_data); - - if (max_depth >= 0 && depth >= max_depth) { - return; - } - - tc->flags |= TALLOC_FLAG_LOOP; - for (c=tc->child;c;c=c->next) { - if (c->name == TALLOC_MAGIC_REFERENCE) { - struct talloc_reference_handle *h = (struct talloc_reference_handle *)TC_PTR_FROM_CHUNK(c); - callback(h->ptr, depth + 1, max_depth, 1, private_data); - } else { - talloc_report_depth_cb(TC_PTR_FROM_CHUNK(c), depth + 1, max_depth, callback, private_data); - } - } - tc->flags &= ~TALLOC_FLAG_LOOP; -} - -static void talloc_report_depth_FILE_helper(const void *ptr, int depth, int max_depth, int is_ref, void *_f) -{ - const char *name = talloc_get_name(ptr); - FILE *f = (FILE *)_f; - - if (is_ref) { - fprintf(f, "%*sreference to: %s\n", depth*4, "", name); - return; - } - - if (depth == 0) { - fprintf(f,"%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n", - (max_depth < 0 ? "full " :""), name, - (unsigned long)talloc_total_size(ptr), - (unsigned long)talloc_total_blocks(ptr)); - return; - } - - fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d) %p\n", - depth*4, "", - name, - (unsigned long)talloc_total_size(ptr), - (unsigned long)talloc_total_blocks(ptr), - (int)talloc_reference_count(ptr), ptr); - -#if 0 - fprintf(f, "content: "); - if (talloc_total_size(ptr)) { - int tot = talloc_total_size(ptr); - int i; - - for (i = 0; i < tot; i++) { - if ((((char *)ptr)[i] > 31) && (((char *)ptr)[i] < 126)) { - fprintf(f, "%c", ((char *)ptr)[i]); - } else { - fprintf(f, "~%02x", ((char *)ptr)[i]); - } - } - } - fprintf(f, "\n"); -#endif -} - -/* - report on memory usage by all children of a pointer, giving a full tree view -*/ -void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f) -{ - if (f) { - talloc_report_depth_cb(ptr, depth, max_depth, talloc_report_depth_FILE_helper, f); - fflush(f); - } -} - -/* - report on memory usage by all children of a pointer, giving a full tree view -*/ -void talloc_report_full(const void *ptr, FILE *f) -{ - talloc_report_depth_file(ptr, 0, -1, f); -} - -/* - report on memory usage by all children of a pointer -*/ -void talloc_report(const void *ptr, FILE *f) -{ - talloc_report_depth_file(ptr, 0, 1, f); -} - -/* - report on any memory hanging off the null context -*/ -static void talloc_report_null(void) -{ - if (talloc_total_size(null_context) != 0) { - talloc_report(null_context, stderr); - } -} - -/* - report on any memory hanging off the null context -*/ -static void talloc_report_null_full(void) -{ - if (talloc_total_size(null_context) != 0) { - talloc_report_full(null_context, stderr); - } -} - -/* - enable tracking of the NULL context -*/ -void talloc_enable_null_tracking(void) -{ - if (null_context == NULL) { - null_context = _talloc_named_const(NULL, 0, "null_context"); - if (autofree_context != NULL) { - talloc_reparent(NULL, null_context, autofree_context); - } - } -} - -/* - enable tracking of the NULL context, not moving the autofree context - into the NULL context. This is needed for the talloc testsuite -*/ -void talloc_enable_null_tracking_no_autofree(void) -{ - if (null_context == NULL) { - null_context = _talloc_named_const(NULL, 0, "null_context"); - } -} - -/* - disable tracking of the NULL context -*/ -void talloc_disable_null_tracking(void) -{ - if (null_context != NULL) { - /* we have to move any children onto the real NULL - context */ - struct talloc_chunk *tc, *tc2; - tc = talloc_chunk_from_ptr(null_context); - for (tc2 = tc->child; tc2; tc2=tc2->next) { - if (tc2->parent == tc) tc2->parent = NULL; - if (tc2->prev == tc) tc2->prev = NULL; - } - for (tc2 = tc->next; tc2; tc2=tc2->next) { - if (tc2->parent == tc) tc2->parent = NULL; - if (tc2->prev == tc) tc2->prev = NULL; - } - tc->child = NULL; - tc->next = NULL; - } - talloc_free(null_context); - null_context = NULL; -} - -/* - enable leak reporting on exit -*/ -void talloc_enable_leak_report(void) -{ - talloc_enable_null_tracking(); - atexit(talloc_report_null); -} - -/* - enable full leak reporting on exit -*/ -void talloc_enable_leak_report_full(void) -{ - talloc_enable_null_tracking(); - atexit(talloc_report_null_full); -} - -/* - talloc and zero memory. -*/ -void *_talloc_zero(const void *ctx, size_t size, const char *name) -{ - void *p = _talloc_named_const(ctx, size, name); - - if (p) { - memset(p, '\0', size); - } - - return p; -} - -/* - memdup with a talloc. -*/ -void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name) -{ - void *newp = _talloc_named_const(t, size, name); - - if (likely(newp)) { - memcpy(newp, p, size); - } - - return newp; -} - -static inline char *__talloc_strlendup(const void *t, const char *p, size_t len) -{ - char *ret; - - ret = (char *)__talloc(t, len + 1); - if (unlikely(!ret)) return NULL; - - memcpy(ret, p, len); - ret[len] = 0; - - _talloc_set_name_const(ret, ret); - return ret; -} - -/* - strdup with a talloc -*/ -char *talloc_strdup(const void *t, const char *p) -{ - if (unlikely(!p)) return NULL; - return __talloc_strlendup(t, p, strlen(p)); -} - -/* - strndup with a talloc -*/ -char *talloc_strndup(const void *t, const char *p, size_t n) -{ - if (unlikely(!p)) return NULL; - return __talloc_strlendup(t, p, strnlen(p, n)); -} - -static inline char *__talloc_strlendup_append(char *s, size_t slen, - const char *a, size_t alen) -{ - char *ret; - - ret = talloc_realloc(NULL, s, char, slen + alen + 1); - if (unlikely(!ret)) return NULL; - - /* append the string and the trailing \0 */ - memcpy(&ret[slen], a, alen); - ret[slen+alen] = 0; - - _talloc_set_name_const(ret, ret); - return ret; -} - -/* - * Appends at the end of the string. - */ -char *talloc_strdup_append(char *s, const char *a) -{ - if (unlikely(!s)) { - return talloc_strdup(NULL, a); - } - - if (unlikely(!a)) { - return s; - } - - return __talloc_strlendup_append(s, strlen(s), a, strlen(a)); -} - -/* - * Appends at the end of the talloc'ed buffer, - * not the end of the string. - */ -char *talloc_strdup_append_buffer(char *s, const char *a) -{ - size_t slen; - - if (unlikely(!s)) { - return talloc_strdup(NULL, a); - } - - if (unlikely(!a)) { - return s; - } - - slen = talloc_get_size(s); - if (likely(slen > 0)) { - slen--; - } - - return __talloc_strlendup_append(s, slen, a, strlen(a)); -} - -/* - * Appends at the end of the string. - */ -char *talloc_strndup_append(char *s, const char *a, size_t n) -{ - if (unlikely(!s)) { - return talloc_strdup(NULL, a); - } - - if (unlikely(!a)) { - return s; - } - - return __talloc_strlendup_append(s, strlen(s), a, strnlen(a, n)); -} - -/* - * Appends at the end of the talloc'ed buffer, - * not the end of the string. - */ -char *talloc_strndup_append_buffer(char *s, const char *a, size_t n) -{ - size_t slen; - - if (unlikely(!s)) { - return talloc_strdup(NULL, a); - } - - if (unlikely(!a)) { - return s; - } - - slen = talloc_get_size(s); - if (likely(slen > 0)) { - slen--; - } - - return __talloc_strlendup_append(s, slen, a, strnlen(a, n)); -} - -#ifndef va_copy -#ifdef HAVE___VA_COPY -#define va_copy(dest, src) __va_copy(dest, src) -#else -#define va_copy(dest, src) (dest) = (src) -#endif -#endif - -char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) -{ - int len; - char *ret; - va_list ap2; - char c; - - /* this call looks strange, but it makes it work on older solaris boxes */ - va_copy(ap2, ap); - #ifdef _MSC_VER - /* MSVC runtime needs to use _vcsprintf to return buffer size; vsnprintf would return -1 */ - len = _vscprintf(fmt, ap2); - #else - len = vsnprintf(&c, 1, fmt, ap2); - #endif - va_end(ap2); - if (unlikely(len < 0)) { - return NULL; - } - - ret = (char *)__talloc(t, len+1); - if (unlikely(!ret)) return NULL; - - va_copy(ap2, ap); - vsnprintf(ret, len+1, fmt, ap2); - va_end(ap2); - - _talloc_set_name_const(ret, ret); - return ret; -} - - -/* - Perform string formatting, and return a pointer to newly allocated - memory holding the result, inside a memory pool. - */ -char *talloc_asprintf(const void *t, const char *fmt, ...) -{ - va_list ap; - char *ret; - - va_start(ap, fmt); - ret = talloc_vasprintf(t, fmt, ap); - va_end(ap); - return ret; -} - -static inline char *__talloc_vaslenprintf_append(char *s, size_t slen, - const char *fmt, va_list ap) - PRINTF_ATTRIBUTE(3,0); - -static inline char *__talloc_vaslenprintf_append(char *s, size_t slen, - const char *fmt, va_list ap) -{ - ssize_t alen; - va_list ap2; - char c; - - va_copy(ap2, ap); - #ifdef _MSC_VER - /* MSVC runtime needs to use _vcsprintf to return buffer size; vsnprintf would return -1 */ - alen = _vscprintf(fmt, ap2); - #else - alen = vsnprintf(&c, 1, fmt, ap2); - #endif - va_end(ap2); - - if (alen <= 0) { - /* Either the vsnprintf failed or the format resulted in - * no characters being formatted. In the former case, we - * ought to return NULL, in the latter we ought to return - * the original string. Most current callers of this - * function expect it to never return NULL. - */ - return s; - } - - s = talloc_realloc(NULL, s, char, slen + alen + 1); - if (!s) return NULL; - - va_copy(ap2, ap); - vsnprintf(s + slen, alen + 1, fmt, ap2); - va_end(ap2); - - _talloc_set_name_const(s, s); - return s; -} - -/** - * Realloc @p s to append the formatted result of @p fmt and @p ap, - * and return @p s, which may have moved. Good for gradually - * accumulating output into a string buffer. Appends at the end - * of the string. - **/ -char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) -{ - if (unlikely(!s)) { - return talloc_vasprintf(NULL, fmt, ap); - } - - return __talloc_vaslenprintf_append(s, strlen(s), fmt, ap); -} - -/** - * Realloc @p s to append the formatted result of @p fmt and @p ap, - * and return @p s, which may have moved. Always appends at the - * end of the talloc'ed buffer, not the end of the string. - **/ -char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap) -{ - size_t slen; - - if (unlikely(!s)) { - return talloc_vasprintf(NULL, fmt, ap); - } - - slen = talloc_get_size(s); - if (likely(slen > 0)) { - slen--; - } - - return __talloc_vaslenprintf_append(s, slen, fmt, ap); -} - -/* - Realloc @p s to append the formatted result of @p fmt and return @p - s, which may have moved. Good for gradually accumulating output - into a string buffer. - */ -char *talloc_asprintf_append(char *s, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - s = talloc_vasprintf_append(s, fmt, ap); - va_end(ap); - return s; -} - -/* - Realloc @p s to append the formatted result of @p fmt and return @p - s, which may have moved. Good for gradually accumulating output - into a buffer. - */ -char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - s = talloc_vasprintf_append_buffer(s, fmt, ap); - va_end(ap); - return s; -} - -/* - alloc an array, checking for integer overflow in the array size -*/ -void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name) -{ - if (count >= MAX_TALLOC_SIZE/el_size) { - return NULL; - } - return _talloc_named_const(ctx, el_size * count, name); -} - -/* - alloc an zero array, checking for integer overflow in the array size -*/ -void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name) -{ - if (count >= MAX_TALLOC_SIZE/el_size) { - return NULL; - } - return _talloc_zero(ctx, el_size * count, name); -} - -/* - realloc an array, checking for integer overflow in the array size -*/ -void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name) -{ - if (count >= MAX_TALLOC_SIZE/el_size) { - return NULL; - } - return _talloc_realloc(ctx, ptr, el_size * count, name); -} - -/* - a function version of talloc_realloc(), so it can be passed as a function pointer - to libraries that want a realloc function (a realloc function encapsulates - all the basic capabilities of an allocation library, which is why this is useful) -*/ -void *talloc_realloc_fn(const void *context, void *ptr, size_t size) -{ - return _talloc_realloc(context, ptr, size, NULL); -} - - -static int talloc_autofree_destructor(void *ptr) -{ - autofree_context = NULL; - return 0; -} - -static void talloc_autofree(void) -{ - talloc_free(autofree_context); -} - -/* - return a context which will be auto-freed on exit - this is useful for reducing the noise in leak reports -*/ -void *talloc_autofree_context(void) -{ - if (autofree_context == NULL) { - autofree_context = _talloc_named_const(NULL, 0, "autofree_context"); - talloc_set_destructor(autofree_context, talloc_autofree_destructor); - atexit(talloc_autofree); - } - return autofree_context; -} - -size_t talloc_get_size(const void *context) -{ - struct talloc_chunk *tc; - - if (context == NULL) { - context = null_context; - } - if (context == NULL) { - return 0; - } - - tc = talloc_chunk_from_ptr(context); - - return tc->size; -} - -/* - find a parent of this context that has the given name, if any -*/ -void *talloc_find_parent_byname(const void *context, const char *name) -{ - struct talloc_chunk *tc; - - if (context == NULL) { - return NULL; - } - - tc = talloc_chunk_from_ptr(context); - while (tc) { - if (tc->name && strcmp(tc->name, name) == 0) { - return TC_PTR_FROM_CHUNK(tc); - } - while (tc && tc->prev) tc = tc->prev; - if (tc) { - tc = tc->parent; - } - } - return NULL; -} - -/* - show the parentage of a context -*/ -void talloc_show_parents(const void *context, FILE *file) -{ - struct talloc_chunk *tc; - - if (context == NULL) { - fprintf(file, "talloc no parents for NULL\n"); - return; - } - - tc = talloc_chunk_from_ptr(context); - fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context)); - while (tc) { - fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc))); - while (tc && tc->prev) tc = tc->prev; - if (tc) { - tc = tc->parent; - } - } - fflush(file); -} - -/* - return 1 if ptr is a parent of context -*/ -int talloc_is_parent(const void *context, const void *ptr) -{ - struct talloc_chunk *tc; - - if (context == NULL) { - return 0; - } - - tc = talloc_chunk_from_ptr(context); - while (tc) { - if (TC_PTR_FROM_CHUNK(tc) == ptr) return 1; - while (tc && tc->prev) tc = tc->prev; - if (tc) { - tc = tc->parent; - } - } - return 0; -} diff --git a/src/talloc/talloc.def b/src/talloc/talloc.def deleted file mode 100644 index 13d7a159cef..00000000000 --- a/src/talloc/talloc.def +++ /dev/null @@ -1,63 +0,0 @@ -EXPORTS - _talloc - _talloc_array - _talloc_free - _talloc_get_type_abort - _talloc_memdup - _talloc_move - _talloc_realloc - _talloc_realloc_array - _talloc_reference_loc - _talloc_set_destructor - _talloc_steal_loc - _talloc_zero - _talloc_zero_array - talloc_asprintf - talloc_asprintf_append - talloc_asprintf_append_buffer - talloc_autofree_context - talloc_check_name - talloc_disable_null_tracking - talloc_enable_leak_report - talloc_enable_leak_report_full - talloc_enable_null_tracking - talloc_enable_null_tracking_no_autofree - talloc_find_parent_byname - talloc_free_children - talloc_get_name - talloc_get_size - talloc_increase_ref_count - talloc_init - talloc_is_parent - talloc_named - talloc_named_const - talloc_parent - talloc_parent_name - talloc_pool - talloc_realloc_fn - talloc_reference_count - talloc_reparent - talloc_report - talloc_report_depth_cb - talloc_report_depth_file - talloc_report_full - talloc_set_abort_fn - talloc_set_log_fn - talloc_set_log_stderr - talloc_set_name - talloc_set_name_const - talloc_show_parents - talloc_strdup - talloc_strdup_append - talloc_strdup_append_buffer - talloc_strndup - talloc_strndup_append - talloc_strndup_append_buffer - talloc_total_blocks - talloc_total_size - talloc_unlink - talloc_vasprintf - talloc_vasprintf_append - talloc_vasprintf_append_buffer - talloc_version_major - talloc_version_minor diff --git a/src/talloc/talloc.h b/src/talloc/talloc.h deleted file mode 100644 index f549a17fba2..00000000000 --- a/src/talloc/talloc.h +++ /dev/null @@ -1,202 +0,0 @@ -#ifndef _TALLOC_H_ -#define _TALLOC_H_ -/* - Unix SMB/CIFS implementation. - Samba temporary memory allocation functions - - Copyright (C) Andrew Tridgell 2004-2005 - Copyright (C) Stefan Metzmacher 2006 - - ** NOTE! The following LGPL license applies to the talloc - ** library. This does NOT imply that all of Samba is released - ** under the LGPL - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ - -#include <stdlib.h> -#include <stdio.h> -#include <stdarg.h> - -#define TALLOC_VERSION_MAJOR 2 -#define TALLOC_VERSION_MINOR 0 - -int talloc_version_major(void); -int talloc_version_minor(void); - -/* this is only needed for compatibility with the old talloc */ -typedef void TALLOC_CTX; - -/* - this uses a little trick to allow __LINE__ to be stringified -*/ -#ifndef __location__ -#define __TALLOC_STRING_LINE1__(s) #s -#define __TALLOC_STRING_LINE2__(s) __TALLOC_STRING_LINE1__(s) -#define __TALLOC_STRING_LINE3__ __TALLOC_STRING_LINE2__(__LINE__) -#define __location__ __FILE__ ":" __TALLOC_STRING_LINE3__ -#endif - -#ifndef TALLOC_DEPRECATED -#define TALLOC_DEPRECATED 0 -#endif - -#ifndef PRINTF_ATTRIBUTE -#if (__GNUC__ >= 3) -/** Use gcc attribute to check printf fns. a1 is the 1-based index of - * the parameter containing the format, and a2 the index of the first - * argument. Note that some gcc 2.x versions don't handle this - * properly **/ -#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2))) -#else -#define PRINTF_ATTRIBUTE(a1, a2) -#endif -#endif - -/* try to make talloc_set_destructor() and talloc_steal() type safe, - if we have a recent gcc */ -#if (__GNUC__ >= 3) -#define _TALLOC_TYPEOF(ptr) __typeof__(ptr) -#define talloc_set_destructor(ptr, function) \ - do { \ - int (*_talloc_destructor_fn)(_TALLOC_TYPEOF(ptr)) = (function); \ - _talloc_set_destructor((ptr), (int (*)(void *))_talloc_destructor_fn); \ - } while(0) -/* this extremely strange macro is to avoid some braindamaged warning - stupidity in gcc 4.1.x */ -#define talloc_steal(ctx, ptr) ({ _TALLOC_TYPEOF(ptr) __talloc_steal_ret = (_TALLOC_TYPEOF(ptr))_talloc_steal_loc((ctx),(ptr), __location__); __talloc_steal_ret; }) -#else -#define talloc_set_destructor(ptr, function) \ - _talloc_set_destructor((ptr), (int (*)(void *))(function)) -#define _TALLOC_TYPEOF(ptr) void * -#define talloc_steal(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_steal_loc((ctx),(ptr), __location__) -#endif - -#define talloc_reference(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_reference_loc((ctx),(ptr), __location__) -#define talloc_move(ctx, ptr) (_TALLOC_TYPEOF(*(ptr)))_talloc_move((ctx),(void *)(ptr)) - -/* useful macros for creating type checked pointers */ -#define talloc(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type) -#define talloc_size(ctx, size) talloc_named_const(ctx, size, __location__) -#define talloc_ptrtype(ctx, ptr) (_TALLOC_TYPEOF(ptr))talloc_size(ctx, sizeof(*(ptr))) - -#define talloc_new(ctx) talloc_named_const(ctx, 0, "talloc_new: " __location__) - -#define talloc_zero(ctx, type) (type *)_talloc_zero(ctx, sizeof(type), #type) -#define talloc_zero_size(ctx, size) _talloc_zero(ctx, size, __location__) - -#define talloc_zero_array(ctx, type, count) (type *)_talloc_zero_array(ctx, sizeof(type), count, #type) -#define talloc_array(ctx, type, count) (type *)_talloc_array(ctx, sizeof(type), count, #type) -#define talloc_array_size(ctx, size, count) _talloc_array(ctx, size, count, __location__) -#define talloc_array_ptrtype(ctx, ptr, count) (_TALLOC_TYPEOF(ptr))talloc_array_size(ctx, sizeof(*(ptr)), count) -#define talloc_array_length(ctx) (talloc_get_size(ctx)/sizeof(*ctx)) - -#define talloc_realloc(ctx, p, type, count) (type *)_talloc_realloc_array(ctx, p, sizeof(type), count, #type) -#define talloc_realloc_size(ctx, ptr, size) _talloc_realloc(ctx, ptr, size, __location__) - -#define talloc_memdup(t, p, size) _talloc_memdup(t, p, size, __location__) - -#define talloc_set_type(ptr, type) talloc_set_name_const(ptr, #type) -#define talloc_get_type(ptr, type) (type *)talloc_check_name(ptr, #type) -#define talloc_get_type_abort(ptr, type) (type *)_talloc_get_type_abort(ptr, #type, __location__) - -#define talloc_find_parent_bytype(ptr, type) (type *)talloc_find_parent_byname(ptr, #type) -#define talloc_free(ctx) _talloc_free(ctx, __location__) - - -#if TALLOC_DEPRECATED -#define talloc_zero_p(ctx, type) talloc_zero(ctx, type) -#define talloc_p(ctx, type) talloc(ctx, type) -#define talloc_array_p(ctx, type, count) talloc_array(ctx, type, count) -#define talloc_realloc_p(ctx, p, type, count) talloc_realloc(ctx, p, type, count) -#define talloc_destroy(ctx) talloc_free(ctx) -#define talloc_append_string(c, s, a) (s?talloc_strdup_append(s,a):talloc_strdup(c, a)) -#endif - -#define TALLOC_FREE(ctx) do { talloc_free(ctx); ctx=NULL; } while(0) - -/* The following definitions come from talloc.c */ -void *_talloc(const void *context, size_t size); -void *talloc_pool(const void *context, size_t size); -void _talloc_set_destructor(const void *ptr, int (*_destructor)(void *)); -int talloc_increase_ref_count(const void *ptr); -size_t talloc_reference_count(const void *ptr); -void *_talloc_reference_loc(const void *context, const void *ptr, const char *location); -int talloc_unlink(const void *context, void *ptr); -const char *talloc_set_name(const void *ptr, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); -void talloc_set_name_const(const void *ptr, const char *name); -void *talloc_named(const void *context, size_t size, - const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); -void *talloc_named_const(const void *context, size_t size, const char *name); -const char *talloc_get_name(const void *ptr); -void *talloc_check_name(const void *ptr, const char *name); -void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location); -void *talloc_parent(const void *ptr); -const char *talloc_parent_name(const void *ptr); -void *talloc_init(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2); -int _talloc_free(void *ptr, const char *location); -void talloc_free_children(void *ptr); -void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name); -void *_talloc_steal_loc(const void *new_ctx, const void *ptr, const char *location); -void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr); -void *_talloc_move(const void *new_ctx, const void *pptr); -size_t talloc_total_size(const void *ptr); -size_t talloc_total_blocks(const void *ptr); -void talloc_report_depth_cb(const void *ptr, int depth, int max_depth, - void (*callback)(const void *ptr, - int depth, int max_depth, - int is_ref, - void *private_data), - void *private_data); -void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f); -void talloc_report_full(const void *ptr, FILE *f); -void talloc_report(const void *ptr, FILE *f); -void talloc_enable_null_tracking(void); -void talloc_enable_null_tracking_no_autofree(void); -void talloc_disable_null_tracking(void); -void talloc_enable_leak_report(void); -void talloc_enable_leak_report_full(void); -void *_talloc_zero(const void *ctx, size_t size, const char *name); -void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name); -void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name); -void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name); -void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name); -void *talloc_realloc_fn(const void *context, void *ptr, size_t size); -void *talloc_autofree_context(void); -size_t talloc_get_size(const void *ctx); -void *talloc_find_parent_byname(const void *ctx, const char *name); -void talloc_show_parents(const void *context, FILE *file); -int talloc_is_parent(const void *context, const void *ptr); - -char *talloc_strdup(const void *t, const char *p); -char *talloc_strdup_append(char *s, const char *a); -char *talloc_strdup_append_buffer(char *s, const char *a); - -char *talloc_strndup(const void *t, const char *p, size_t n); -char *talloc_strndup_append(char *s, const char *a, size_t n); -char *talloc_strndup_append_buffer(char *s, const char *a, size_t n); - -char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); -char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); -char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); - -char *talloc_asprintf(const void *t, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); -char *talloc_asprintf_append(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); -char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); - -void talloc_set_abort_fn(void (*abort_fn)(const char *reason)); -void talloc_set_log_fn(void (*log_fn)(const char *message)); -void talloc_set_log_stderr(void); - -#endif diff --git a/src/talloc/talloc_guide.txt b/src/talloc/talloc_guide.txt deleted file mode 100644 index 01de806662d..00000000000 --- a/src/talloc/talloc_guide.txt +++ /dev/null @@ -1,757 +0,0 @@ -Using talloc in Samba4 -====================== - -.. contents:: - -Andrew Tridgell -August 2009 - -The most current version of this document is available at - http://samba.org/ftp/unpacked/talloc/talloc_guide.txt - -If you are used to the "old" talloc from Samba3 before 3.0.20 then please read -this carefully, as talloc has changed a lot. With 3.0.20 (or 3.0.14?) the -Samba4 talloc has been ported back to Samba3, so this guide applies to both. - -The new talloc is a hierarchical, reference counted memory pool system -with destructors. Quite a mouthful really, but not too bad once you -get used to it. - -Perhaps the biggest change from Samba3 is that there is no distinction -between a "talloc context" and a "talloc pointer". Any pointer -returned from talloc() is itself a valid talloc context. This means -you can do this:: - - struct foo *X = talloc(mem_ctx, struct foo); - X->name = talloc_strdup(X, "foo"); - -and the pointer X->name would be a "child" of the talloc context "X" -which is itself a child of mem_ctx. So if you do talloc_free(mem_ctx) -then it is all destroyed, whereas if you do talloc_free(X) then just X -and X->name are destroyed, and if you do talloc_free(X->name) then -just the name element of X is destroyed. - -If you think about this, then what this effectively gives you is an -n-ary tree, where you can free any part of the tree with -talloc_free(). - -If you find this confusing, then I suggest you run the testsuite to -watch talloc in action. You may also like to add your own tests to -testsuite.c to clarify how some particular situation is handled. - - -Performance ------------ - -All the additional features of talloc() over malloc() do come at a -price. We have a simple performance test in Samba4 that measures -talloc() versus malloc() performance, and it seems that talloc() is -about 4% slower than malloc() on my x86 Debian Linux box. For Samba, -the great reduction in code complexity that we get by using talloc -makes this worthwhile, especially as the total overhead of -talloc/malloc in Samba is already quite small. - - -talloc API ----------- - -The following is a complete guide to the talloc API. Read it all at -least twice. - -Multi-threading ---------------- - -talloc itself does not deal with threads. It is thread-safe (assuming -the underlying "malloc" is), as long as each thread uses different -memory contexts. -If two threads uses the same context then they need to synchronize in -order to be safe. In particular: -- when using talloc_enable_leak_report(), giving directly NULL as a -parent context implicitly refers to a hidden "null context" global -variable, so this should not be used in a multi-threaded environment -without proper synchronization ; -- the context returned by talloc_autofree_context() is also global so -shouldn't be used by several threads simultaneously without -synchronization. - - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -(type *)talloc(const void *context, type); - -The talloc() macro is the core of the talloc library. It takes a -memory context and a type, and returns a pointer to a new area of -memory of the given type. - -The returned pointer is itself a talloc context, so you can use it as -the context argument to more calls to talloc if you wish. - -The returned pointer is a "child" of the supplied context. This means -that if you talloc_free() the context then the new child disappears as -well. Alternatively you can free just the child. - -The context argument to talloc() can be NULL, in which case a new top -level context is created. - - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -void *talloc_size(const void *context, size_t size); - -The function talloc_size() should be used when you don't have a -convenient type to pass to talloc(). Unlike talloc(), it is not type -safe (as it returns a void *), so you are on your own for type checking. - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -(typeof(ptr)) talloc_ptrtype(const void *ctx, ptr); - -The talloc_ptrtype() macro should be used when you have a pointer and -want to allocate memory to point at with this pointer. When compiling -with gcc >= 3 it is typesafe. Note this is a wrapper of talloc_size() -and talloc_get_name() will return the current location in the source file. -and not the type. - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -int talloc_free(void *ptr); - -The talloc_free() function frees a piece of talloc memory, and all its -children. You can call talloc_free() on any pointer returned by -talloc(). - -The return value of talloc_free() indicates success or failure, with 0 -returned for success and -1 for failure. The only possible failure -condition is if the pointer had a destructor attached to it and the -destructor returned -1. See talloc_set_destructor() for details on -destructors. - -If this pointer has an additional parent when talloc_free() is called -then the memory is not actually released, but instead the most -recently established parent is destroyed. See talloc_reference() for -details on establishing additional parents. - -For more control on which parent is removed, see talloc_unlink() - -talloc_free() operates recursively on its children. - -From the 2.0 version of talloc, as a special case, talloc_free() is -refused on pointers that have more than one parent, as talloc would -have no way of knowing which parent should be removed. To free a -pointer that has more than one parent please use talloc_unlink(). - -To help you find problems in your code caused by this behaviour, if -you do try and free a pointer with more than one parent then the -talloc logging function will be called to give output like this: - - ERROR: talloc_free with references at some_dir/source/foo.c:123 - reference at some_dir/source/other.c:325 - reference at some_dir/source/third.c:121 - -Please see the documentation for talloc_set_log_fn() and -talloc_set_log_stderr() for more information on talloc logging -functions. - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -int talloc_free_children(void *ptr); - -The talloc_free_children() walks along the list of all children of a -talloc context and talloc_free()s only the children, not the context -itself. - - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -void *talloc_reference(const void *context, const void *ptr); - -The talloc_reference() function makes "context" an additional parent -of "ptr". - -The return value of talloc_reference() is always the original pointer -"ptr", unless talloc ran out of memory in creating the reference in -which case it will return NULL (each additional reference consumes -around 48 bytes of memory on intel x86 platforms). - -If "ptr" is NULL, then the function is a no-op, and simply returns NULL. - -After creating a reference you can free it in one of the following -ways: - - - you can talloc_free() any parent of the original pointer. That - will reduce the number of parents of this pointer by 1, and will - cause this pointer to be freed if it runs out of parents. - - - you can talloc_free() the pointer itself. That will destroy the - most recently established parent to the pointer and leave the - pointer as a child of its current parent. - -For more control on which parent to remove, see talloc_unlink() - - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -int talloc_unlink(const void *context, const void *ptr); - -The talloc_unlink() function removes a specific parent from ptr. The -context passed must either be a context used in talloc_reference() -with this pointer, or must be a direct parent of ptr. - -Note that if the parent has already been removed using talloc_free() -then this function will fail and will return -1. Likewise, if "ptr" -is NULL, then the function will make no modifications and return -1. - -Usually you can just use talloc_free() instead of talloc_unlink(), but -sometimes it is useful to have the additional control on which parent -is removed. - - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -void talloc_set_destructor(const void *ptr, int (*destructor)(void *)); - -The function talloc_set_destructor() sets the "destructor" for the -pointer "ptr". A destructor is a function that is called when the -memory used by a pointer is about to be released. The destructor -receives the pointer as an argument, and should return 0 for success -and -1 for failure. - -The destructor can do anything it wants to, including freeing other -pieces of memory. A common use for destructors is to clean up -operating system resources (such as open file descriptors) contained -in the structure the destructor is placed on. - -You can only place one destructor on a pointer. If you need more than -one destructor then you can create a zero-length child of the pointer -and place an additional destructor on that. - -To remove a destructor call talloc_set_destructor() with NULL for the -destructor. - -If your destructor attempts to talloc_free() the pointer that it is -the destructor for then talloc_free() will return -1 and the free will -be ignored. This would be a pointless operation anyway, as the -destructor is only called when the memory is just about to go away. - - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -int talloc_increase_ref_count(const void *ptr); - -The talloc_increase_ref_count(ptr) function is exactly equivalent to: - - talloc_reference(NULL, ptr); - -You can use either syntax, depending on which you think is clearer in -your code. - -It returns 0 on success and -1 on failure. - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -size_t talloc_reference_count(const void *ptr); - -Return the number of references to the pointer. - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -void talloc_set_name(const void *ptr, const char *fmt, ...); - -Each talloc pointer has a "name". The name is used principally for -debugging purposes, although it is also possible to set and get the -name on a pointer in as a way of "marking" pointers in your code. - -The main use for names on pointer is for "talloc reports". See -talloc_report() and talloc_report_full() for details. Also see -talloc_enable_leak_report() and talloc_enable_leak_report_full(). - -The talloc_set_name() function allocates memory as a child of the -pointer. It is logically equivalent to: - talloc_set_name_const(ptr, talloc_asprintf(ptr, fmt, ...)); - -Note that multiple calls to talloc_set_name() will allocate more -memory without releasing the name. All of the memory is released when -the ptr is freed using talloc_free(). - - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -void talloc_set_name_const(const void *ptr, const char *name); - -The function talloc_set_name_const() is just like talloc_set_name(), -but it takes a string constant, and is much faster. It is extensively -used by the "auto naming" macros, such as talloc_p(). - -This function does not allocate any memory. It just copies the -supplied pointer into the internal representation of the talloc -ptr. This means you must not pass a name pointer to memory that will -disappear before the ptr is freed with talloc_free(). - - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -void *talloc_named(const void *context, size_t size, const char *fmt, ...); - -The talloc_named() function creates a named talloc pointer. It is -equivalent to: - - ptr = talloc_size(context, size); - talloc_set_name(ptr, fmt, ....); - - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -void *talloc_named_const(const void *context, size_t size, const char *name); - -This is equivalent to:: - - ptr = talloc_size(context, size); - talloc_set_name_const(ptr, name); - - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -const char *talloc_get_name(const void *ptr); - -This returns the current name for the given talloc pointer. See -talloc_set_name() for details. - - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -void *talloc_init(const char *fmt, ...); - -This function creates a zero length named talloc context as a top -level context. It is equivalent to:: - - talloc_named(NULL, 0, fmt, ...); - - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -void *talloc_new(void *ctx); - -This is a utility macro that creates a new memory context hanging -off an exiting context, automatically naming it "talloc_new: __location__" -where __location__ is the source line it is called from. It is -particularly useful for creating a new temporary working context. - - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -(type *)talloc_realloc(const void *context, void *ptr, type, count); - -The talloc_realloc() macro changes the size of a talloc -pointer. The "count" argument is the number of elements of type "type" -that you want the resulting pointer to hold. - -talloc_realloc() has the following equivalences:: - - talloc_realloc(context, NULL, type, 1) ==> talloc(context, type); - talloc_realloc(context, NULL, type, N) ==> talloc_array(context, type, N); - talloc_realloc(context, ptr, type, 0) ==> talloc_free(ptr); - -The "context" argument is only used if "ptr" is NULL, otherwise it is -ignored. - -talloc_realloc() returns the new pointer, or NULL on failure. The call -will fail either due to a lack of memory, or because the pointer has -more than one parent (see talloc_reference()). - - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -void *talloc_realloc_size(const void *context, void *ptr, size_t size); - -the talloc_realloc_size() function is useful when the type is not -known so the typesafe talloc_realloc() cannot be used. - - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -void *talloc_steal(const void *new_ctx, const void *ptr); - -The talloc_steal() function changes the parent context of a talloc -pointer. It is typically used when the context that the pointer is -currently a child of is going to be freed and you wish to keep the -memory for a longer time. - -The talloc_steal() function returns the pointer that you pass it. It -does not have any failure modes. - -NOTE: It is possible to produce loops in the parent/child relationship -if you are not careful with talloc_steal(). No guarantees are provided -as to your sanity or the safety of your data if you do this. - -talloc_steal (new_ctx, NULL) will return NULL with no sideeffects. - -Note that if you try and call talloc_steal() on a pointer that has -more than one parent then the result is ambiguous. Talloc will choose -to remove the parent that is currently indicated by talloc_parent() -and replace it with the chosen parent. You will also get a message -like this via the talloc logging functions: - - WARNING: talloc_steal with references at some_dir/source/foo.c:123 - reference at some_dir/source/other.c:325 - reference at some_dir/source/third.c:121 - -To unambiguously change the parent of a pointer please see the -function talloc_reparent(). See the talloc_set_log_fn() documentation -for more information on talloc logging. - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr); - -The talloc_reparent() function changes the parent context of a talloc -pointer. It is typically used when the context that the pointer is -currently a child of is going to be freed and you wish to keep the -memory for a longer time. - -The talloc_reparent() function returns the pointer that you pass it. It -does not have any failure modes. - -The difference between talloc_reparent() and talloc_steal() is that -talloc_reparent() can specify which parent you wish to change. This is -useful when a pointer has multiple parents via references. - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -void *talloc_parent(const void *ptr); - -The talloc_parent() function returns the current talloc parent. This -is usually the pointer under which this memory was originally created, -but it may have changed due to a talloc_steal() or talloc_reparent() - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -size_t talloc_total_size(const void *ptr); - -The talloc_total_size() function returns the total size in bytes used -by this pointer and all child pointers. Mostly useful for debugging. - -Passing NULL is allowed, but it will only give a meaningful result if -talloc_enable_leak_report() or talloc_enable_leak_report_full() has -been called. - - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -size_t talloc_total_blocks(const void *ptr); - -The talloc_total_blocks() function returns the total memory block -count used by this pointer and all child pointers. Mostly useful for -debugging. - -Passing NULL is allowed, but it will only give a meaningful result if -talloc_enable_leak_report() or talloc_enable_leak_report_full() has -been called. - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -void talloc_report_depth_cb(const void *ptr, int depth, int max_depth, - void (*callback)(const void *ptr, - int depth, int max_depth, - int is_ref, - void *priv), - void *priv); - -This provides a more flexible reports than talloc_report(). It -will recursively call the callback for the entire tree of memory -referenced by the pointer. References in the tree are passed with -is_ref = 1 and the pointer that is referenced. - -You can pass NULL for the pointer, in which case a report is -printed for the top level memory context, but only if -talloc_enable_leak_report() or talloc_enable_leak_report_full() -has been called. - -The recursion is stopped when depth >= max_depth. -max_depth = -1 means only stop at leaf nodes. - - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f); - -This provides a more flexible reports than talloc_report(). It -will let you specify the depth and max_depth. - - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -void talloc_report(const void *ptr, FILE *f); - -The talloc_report() function prints a summary report of all memory -used by ptr. One line of report is printed for each immediate child of -ptr, showing the total memory and number of blocks used by that child. - -You can pass NULL for the pointer, in which case a report is printed -for the top level memory context, but only if -talloc_enable_leak_report() or talloc_enable_leak_report_full() has -been called. - - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -void talloc_report_full(const void *ptr, FILE *f); - -This provides a more detailed report than talloc_report(). It will -recursively print the ensire tree of memory referenced by the -pointer. References in the tree are shown by giving the name of the -pointer that is referenced. - -You can pass NULL for the pointer, in which case a report is printed -for the top level memory context, but only if -talloc_enable_leak_report() or talloc_enable_leak_report_full() has -been called. - - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -void talloc_enable_leak_report(void); - -This enables calling of talloc_report(NULL, stderr) when the program -exits. In Samba4 this is enabled by using the --leak-report command -line option. - -For it to be useful, this function must be called before any other -talloc function as it establishes a "null context" that acts as the -top of the tree. If you don't call this function first then passing -NULL to talloc_report() or talloc_report_full() won't give you the -full tree printout. - -Here is a typical talloc report: - -talloc report on 'null_context' (total 267 bytes in 15 blocks) - libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks - libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks - iconv(UTF8,CP850) contains 42 bytes in 2 blocks - libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks - iconv(CP850,UTF8) contains 42 bytes in 2 blocks - iconv(UTF8,UTF-16LE) contains 45 bytes in 2 blocks - iconv(UTF-16LE,UTF8) contains 45 bytes in 2 blocks - - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -void talloc_enable_leak_report_full(void); - -This enables calling of talloc_report_full(NULL, stderr) when the -program exits. In Samba4 this is enabled by using the ---leak-report-full command line option. - -For it to be useful, this function must be called before any other -talloc function as it establishes a "null context" that acts as the -top of the tree. If you don't call this function first then passing -NULL to talloc_report() or talloc_report_full() won't give you the -full tree printout. - -Here is a typical full report: - -full talloc report on 'root' (total 18 bytes in 8 blocks) - p1 contains 18 bytes in 7 blocks (ref 0) - r1 contains 13 bytes in 2 blocks (ref 0) - reference to: p2 - p2 contains 1 bytes in 1 blocks (ref 1) - x3 contains 1 bytes in 1 blocks (ref 0) - x2 contains 1 bytes in 1 blocks (ref 0) - x1 contains 1 bytes in 1 blocks (ref 0) - - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -void talloc_enable_null_tracking(void); - -This enables tracking of the NULL memory context without enabling leak -reporting on exit. Useful for when you want to do your own leak -reporting call via talloc_report_null_full(); - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -void talloc_disable_null_tracking(void); - -This disables tracking of the NULL memory context. - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -(type *)talloc_zero(const void *ctx, type); - -The talloc_zero() macro is equivalent to:: - - ptr = talloc(ctx, type); - if (ptr) memset(ptr, 0, sizeof(type)); - - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -void *talloc_zero_size(const void *ctx, size_t size) - -The talloc_zero_size() function is useful when you don't have a known type - - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -void *talloc_memdup(const void *ctx, const void *p, size_t size); - -The talloc_memdup() function is equivalent to:: - - ptr = talloc_size(ctx, size); - if (ptr) memcpy(ptr, p, size); - - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -char *talloc_strdup(const void *ctx, const char *p); - -The talloc_strdup() function is equivalent to:: - - ptr = talloc_size(ctx, strlen(p)+1); - if (ptr) memcpy(ptr, p, strlen(p)+1); - -This functions sets the name of the new pointer to the passed -string. This is equivalent to:: - - talloc_set_name_const(ptr, ptr) - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -char *talloc_strndup(const void *t, const char *p, size_t n); - -The talloc_strndup() function is the talloc equivalent of the C -library function strndup() - -This functions sets the name of the new pointer to the passed -string. This is equivalent to: - talloc_set_name_const(ptr, ptr) - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -char *talloc_append_string(const void *t, char *orig, const char *append); - -The talloc_append_string() function appends the given formatted -string to the given string. - -This function sets the name of the new pointer to the new -string. This is equivalent to:: - - talloc_set_name_const(ptr, ptr) - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -char *talloc_vasprintf(const void *t, const char *fmt, va_list ap); - -The talloc_vasprintf() function is the talloc equivalent of the C -library function vasprintf() - -This functions sets the name of the new pointer to the new -string. This is equivalent to:: - - talloc_set_name_const(ptr, ptr) - - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -char *talloc_asprintf(const void *t, const char *fmt, ...); - -The talloc_asprintf() function is the talloc equivalent of the C -library function asprintf() - -This functions sets the name of the new pointer to the new -string. This is equivalent to:: - - talloc_set_name_const(ptr, ptr) - - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -char *talloc_asprintf_append(char *s, const char *fmt, ...); - -The talloc_asprintf_append() function appends the given formatted -string to the given string. -Use this varient when the string in the current talloc buffer may -have been truncated in length. - -This functions sets the name of the new pointer to the new -string. This is equivalent to:: - - talloc_set_name_const(ptr, ptr) - - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...); - -The talloc_asprintf_append() function appends the given formatted -string to the end of the currently allocated talloc buffer. -Use this varient when the string in the current talloc buffer has -not been changed. - -This functions sets the name of the new pointer to the new -string. This is equivalent to:: - - talloc_set_name_const(ptr, ptr) - - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -((type *)talloc_array(const void *ctx, type, uint_t count); - -The talloc_array() macro is equivalent to:: - - (type *)talloc_size(ctx, sizeof(type) * count); - -except that it provides integer overflow protection for the multiply, -returning NULL if the multiply overflows. - - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -void *talloc_array_size(const void *ctx, size_t size, uint_t count); - -The talloc_array_size() function is useful when the type is not -known. It operates in the same way as talloc_array(), but takes a size -instead of a type. - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -(typeof(ptr)) talloc_array_ptrtype(const void *ctx, ptr, uint_t count); - -The talloc_ptrtype() macro should be used when you have a pointer to an array -and want to allocate memory of an array to point at with this pointer. When compiling -with gcc >= 3 it is typesafe. Note this is a wrapper of talloc_array_size() -and talloc_get_name() will return the current location in the source file. -and not the type. - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -void *talloc_realloc_fn(const void *ctx, void *ptr, size_t size); - -This is a non-macro version of talloc_realloc(), which is useful -as libraries sometimes want a ralloc function pointer. A realloc() -implementation encapsulates the functionality of malloc(), free() and -realloc() in one call, which is why it is useful to be able to pass -around a single function pointer. - - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -void *talloc_autofree_context(void); - -This is a handy utility function that returns a talloc context -which will be automatically freed on program exit. This can be used -to reduce the noise in memory leak reports. - - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -void *talloc_check_name(const void *ptr, const char *name); - -This function checks if a pointer has the specified name. If it does -then the pointer is returned. It it doesn't then NULL is returned. - - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -(type *)talloc_get_type(const void *ptr, type); - -This macro allows you to do type checking on talloc pointers. It is -particularly useful for void* private pointers. It is equivalent to -this:: - - (type *)talloc_check_name(ptr, #type) - - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -talloc_set_type(const void *ptr, type); - -This macro allows you to force the name of a pointer to be a -particular type. This can be used in conjunction with -talloc_get_type() to do type checking on void* pointers. - -It is equivalent to this:: - - talloc_set_name_const(ptr, #type) - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -talloc_get_size(const void *ctx); - -This function lets you know the amount of memory alloced so far by -this context. It does NOT account for subcontext memory. -This can be used to calculate the size of an array. - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -void *talloc_find_parent_byname(const void *ctx, const char *name); - -Find a parent memory context of the current context that has the given -name. This can be very useful in complex programs where it may be -difficult to pass all information down to the level you need, but you -know the structure you want is a parent of another context. - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -(type *)talloc_find_parent_bytype(ctx, type); - -Like talloc_find_parent_byname() but takes a type, making it typesafe. - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -void talloc_set_log_fn(void (*log_fn)(const char *message)); - -This function sets a logging function that talloc will use for -warnings and errors. By default talloc will not print any warnings or -errors. - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -void talloc_set_log_stderr(void) - -This sets the talloc log function to write log messages to stderr |