aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/mesa
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/mesa')
-rw-r--r--mesalib/src/mesa/Makefile412
-rw-r--r--mesalib/src/mesa/drivers/dri/Makefile.template12
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_primitive_dx9.c1
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/mesasw/gld_wgl_mesasw.c1
-rw-r--r--mesalib/src/mesa/main/mtypes.h6740
-rw-r--r--mesalib/src/mesa/program/ir_to_mesa.cpp6537
-rw-r--r--mesalib/src/mesa/state_tracker/st_cb_fbo.c1259
-rw-r--r--mesalib/src/mesa/state_tracker/st_manager.c15
-rw-r--r--mesalib/src/mesa/swrast/s_trispan.h31
-rw-r--r--mesalib/src/mesa/x86/read_rgba_span_x86.S1364
10 files changed, 8198 insertions, 8174 deletions
diff --git a/mesalib/src/mesa/Makefile b/mesalib/src/mesa/Makefile
index a6025e990..36cbdd994 100644
--- a/mesalib/src/mesa/Makefile
+++ b/mesalib/src/mesa/Makefile
@@ -1,188 +1,224 @@
-# src/mesa/Makefile
-
-TOP = ../..
-include $(TOP)/configs/current
-
-MESA_LIBS := libmesa.a libmesagallium.a
-DEPENDS := depend
-
-MESA_OBJ_DIR := .
-
-
-include sources.mak
-
-# adjust object dirs
-MESA_OBJECTS := $(addprefix $(MESA_OBJ_DIR)/, $(MESA_OBJECTS))
-MESA_GALLIUM_OBJECTS := $(addprefix $(MESA_OBJ_DIR)/, $(MESA_GALLIUM_OBJECTS))
-
-# define preprocessor flags
-MESA_CPPFLAGS := $(API_DEFINES) $(DEFINES)
-
-# append include dirs
-MESA_CPPFLAGS += $(INCLUDE_DIRS)
-
-# tidy compiler flags
-CFLAGS := $(filter-out $(DEFINES), $(CFLAGS))
-CXXFLAGS := $(filter-out $(DEFINES), $(CXXFLAGS))
-
-# LLVM is needed for the state tracker
-MESA_CFLAGS := $(LLVM_CFLAGS)
-
-define mesa-cc-c
- @mkdir -p $(dir $@)
- $(CC) -c -o $@ $< $($(1)_CPPFLAGS) $($(1)_CFLAGS) $(CFLAGS)
-endef
-
-define mesa-cxx-c
- @mkdir -p $(dir $@)
- $(CXX) -c -o $@ $< $($(1)_CPPFLAGS) $($(1)_CFLAGS) $(CXXFLAGS)
-endef
-
-$(MESA_OBJ_DIR)/%.o: %.c
- $(call mesa-cc-c,MESA)
-
-$(MESA_OBJ_DIR)/%.o: %.cpp
- $(call mesa-cxx-c,MESA)
-
-$(MESA_OBJ_DIR)/%.o: %.S
- $(call mesa-cc-c,MESA)
-
-# 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
-
-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 > $@
-
-main/api_exec_es2.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 GLES2.0 > $@
-
-######################################################################
-# Helper libraries used by many drivers:
-
-# Make archive of core mesa object files
-libmesa.a: $(MESA_OBJECTS) $(GLSL_LIBS)
- @ $(MKLIB) -o mesa -static $(MESA_OBJECTS) $(GLSL_LIBS)
-
-# 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)
- @ (cd drivers && $(MAKE))
-
-
-######################################################################
-# Assembly subdirs
-asm_subdirs:
- @ if echo "$(ASM_FLAGS)" | grep -q USE_X86_ASM ; then \
- (cd x86 && $(MAKE)) || exit 1 ; \
- fi
- @ if echo "$(ASM_FLAGS)" | grep -q USE_X86_64_ASM ; then \
- (cd x86 && $(MAKE)) || exit 1 ; \
- (cd x86-64 && $(MAKE)) || exit 1 ; \
- fi
-
-
-######################################################################
-# Dependency generation
-
-depend: $(ALL_SOURCES)
- @ echo "running $(MKDEP)"
- @ touch depend
- @$(MKDEP) $(MKDEP_OPTIONS) -p$(MESA_OBJ_DIR)/ $(MESA_CPPFLAGS) \
- $(ALL_SOURCES) > /dev/null 2>/dev/null
-
-######################################################################
-# Installation rules
-
-# this isn't fleshed out yet but is probably the way to go in the future
-new_install:
- (cd drivers && $(MAKE) install)
-
-
-# XXX replace this with new_install above someday
-install: default
- @for driver in $(DRIVER_DIRS) ; do \
- case "$$driver" in \
- osmesa) if [ "$(DRIVER_DIRS)" = osmesa ]; then \
- $(MAKE) install-headers install-osmesa || exit 1 ; \
- else \
- $(MAKE) install-osmesa || exit 1 ; \
- fi ;; \
- dri) $(MAKE) install-libgl install-dri || exit 1 ;; \
- *) $(MAKE) install-libgl || exit 1 ;; \
- esac ; \
- done
-
-pcedit = \
- -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),' \
-
-
-gl_pcedit = sed \
- $(pcedit) \
- -e 's,@GL_PC_REQ_PRIV@,$(GL_PC_REQ_PRIV),' \
- -e 's,@GL_PC_LIB_PRIV@,$(GL_PC_LIB_PRIV),' \
- -e 's,@GL_PC_CFLAGS@,$(GL_PC_CFLAGS),' \
- -e 's,@GLX_TLS@,$(GLX_TLS),' \
- -e 's,@GL_LIB@,$(GL_LIB),'
-
-gl.pc: gl.pc.in
- $(gl_pcedit) $< > $@
-
-osmesa_pcedit = sed \
- $(pcedit) \
- -e 's,@OSMESA_LIB@,$(OSMESA_LIB),' \
- -e 's,@OSMESA_PC_REQ@,$(OSMESA_PC_REQ),' \
- -e 's,@OSMESA_PC_LIB_PRIV@,$(OSMESA_PC_LIB_PRIV),'
-
-osmesa.pc: osmesa.pc.in
- $(osmesa_pcedit) $< > $@
-
-install-headers:
- $(INSTALL) -d $(DESTDIR)$(INSTALL_INC_DIR)/GL
- $(INSTALL) -m 644 $(TOP)/include/GL/*.h \
- $(DESTDIR)$(INSTALL_INC_DIR)/GL
-
-install-libgl: default gl.pc install-headers
- $(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR)
- $(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR)/pkgconfig
- $(MINSTALL) $(TOP)/$(LIB_DIR)/$(GL_LIB_GLOB) \
- $(DESTDIR)$(INSTALL_LIB_DIR)
- $(INSTALL) -m 644 gl.pc $(DESTDIR)$(INSTALL_LIB_DIR)/pkgconfig
-
-install-osmesa: default osmesa.pc
- $(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR)
- $(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR)/pkgconfig
- $(MINSTALL) $(TOP)/$(LIB_DIR)/$(OSMESA_LIB_GLOB) \
- $(DESTDIR)$(INSTALL_LIB_DIR)
- $(INSTALL) -m 644 osmesa.pc $(DESTDIR)$(INSTALL_LIB_DIR)/pkgconfig
-
-install-dri: default
- cd drivers/dri && $(MAKE) install
-
-
-
-# Emacs tags
-tags:
- etags `find . -name \*.[ch]` $(TOP)/include/GL/*.h
-
-clean:
- -rm -f */*.o
- -rm -f */*/*.o
- -rm -f depend depend.bak libmesa.a libmesagallium.a
- -rm -f drivers/*/*.o
- -rm -f *.pc
- -@cd drivers/dri && $(MAKE) clean
- -@cd drivers/x11 && $(MAKE) clean
- -@cd drivers/osmesa && $(MAKE) clean
- -@cd x86 && $(MAKE) clean
- -@cd x86-64 && $(MAKE) clean
-
-
--include $(DEPENDS)
+# src/mesa/Makefile
+
+TOP = ../..
+include $(TOP)/configs/current
+
+MESA_LIBS := libmesa.a libmesagallium.a
+DEPENDS := depend
+
+MESA_OBJ_DIR := .
+DRICORE_OBJ_DIR := objs-dricore
+
+include sources.mak
+
+# adjust object dirs
+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)
+
+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) $(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)
+endef
+
+define mesa-cxx-c
+ @mkdir -p $(dir $@)
+ $(CXX) -c -o $@ $< $($(1)_CPPFLAGS) $($(1)_CFLAGS) $($(1)_CXXFLAGS)
+endef
+
+$(MESA_OBJ_DIR)/%.o: %.c
+ $(call mesa-cc-c,MESA)
+
+$(MESA_OBJ_DIR)/%.o: %.cpp
+ $(call mesa-cxx-c,MESA)
+
+$(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) $(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 > $@
+
+main/api_exec_es2.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 GLES2.0 > $@
+
+######################################################################
+# Helper libraries used by many drivers:
+
+# Make archive of core mesa object files
+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)/$@.dylib \
+ $(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) $(DRICORE_LIBS)
+ @ (cd drivers && $(MAKE))
+
+
+######################################################################
+# Assembly subdirs
+asm_subdirs:
+ @ if echo "$(ASM_FLAGS)" | grep -q USE_X86_ASM ; then \
+ (cd x86 && $(MAKE)) || exit 1 ; \
+ fi
+ @ if echo "$(ASM_FLAGS)" | grep -q USE_X86_64_ASM ; then \
+ (cd x86 && $(MAKE)) || exit 1 ; \
+ (cd x86-64 && $(MAKE)) || exit 1 ; \
+ fi
+
+
+######################################################################
+# Dependency generation
+
+depend: $(ALL_SOURCES)
+ @ echo "running $(MKDEP)"
+ @ touch depend
+ @$(MKDEP) $(MKDEP_OPTIONS) -p$(MESA_OBJ_DIR)/ $(MESA_CPPFLAGS) \
+ $(ALL_SOURCES) > /dev/null 2>/dev/null
+
+######################################################################
+# Installation rules
+
+# this isn't fleshed out yet but is probably the way to go in the future
+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 $(DRICORE_INSTALL_TARGET)
+ @for driver in $(DRIVER_DIRS) ; do \
+ case "$$driver" in \
+ osmesa) if [ "$(DRIVER_DIRS)" = osmesa ]; then \
+ $(MAKE) install-headers install-osmesa || exit 1 ; \
+ else \
+ $(MAKE) install-osmesa || exit 1 ; \
+ fi ;; \
+ dri) $(MAKE) install-libgl install-dri || exit 1 ;; \
+ *) $(MAKE) install-libgl || exit 1 ;; \
+ esac ; \
+ done
+
+pcedit = \
+ -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),' \
+
+
+gl_pcedit = sed \
+ $(pcedit) \
+ -e 's,@GL_PC_REQ_PRIV@,$(GL_PC_REQ_PRIV),' \
+ -e 's,@GL_PC_LIB_PRIV@,$(GL_PC_LIB_PRIV),' \
+ -e 's,@GL_PC_CFLAGS@,$(GL_PC_CFLAGS),' \
+ -e 's,@GLX_TLS@,$(GLX_TLS),' \
+ -e 's,@GL_LIB@,$(GL_LIB),'
+
+gl.pc: gl.pc.in
+ $(gl_pcedit) $< > $@
+
+osmesa_pcedit = sed \
+ $(pcedit) \
+ -e 's,@OSMESA_LIB@,$(OSMESA_LIB),' \
+ -e 's,@OSMESA_PC_REQ@,$(OSMESA_PC_REQ),' \
+ -e 's,@OSMESA_PC_LIB_PRIV@,$(OSMESA_PC_LIB_PRIV),'
+
+osmesa.pc: osmesa.pc.in
+ $(osmesa_pcedit) $< > $@
+
+install-headers:
+ $(INSTALL) -d $(DESTDIR)$(INSTALL_INC_DIR)/GL
+ $(INSTALL) -m 644 $(TOP)/include/GL/*.h \
+ $(DESTDIR)$(INSTALL_INC_DIR)/GL
+
+install-libgl: default gl.pc install-headers
+ $(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR)
+ $(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR)/pkgconfig
+ $(MINSTALL) $(TOP)/$(LIB_DIR)/$(GL_LIB_GLOB) \
+ $(DESTDIR)$(INSTALL_LIB_DIR)
+ $(INSTALL) -m 644 gl.pc $(DESTDIR)$(INSTALL_LIB_DIR)/pkgconfig
+
+install-osmesa: default osmesa.pc
+ $(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR)
+ $(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR)/pkgconfig
+ $(MINSTALL) $(TOP)/$(LIB_DIR)/$(OSMESA_LIB_GLOB) \
+ $(DESTDIR)$(INSTALL_LIB_DIR)
+ $(INSTALL) -m 644 osmesa.pc $(DESTDIR)$(INSTALL_LIB_DIR)/pkgconfig
+
+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-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
+ -rm -f drivers/*/*.o
+ -rm -f *.pc
+ -@cd drivers/dri && $(MAKE) clean
+ -@cd drivers/x11 && $(MAKE) clean
+ -@cd drivers/osmesa && $(MAKE) clean
+ -@cd x86 && $(MAKE) clean
+ -@cd x86-64 && $(MAKE) clean
+
+
+-include $(DEPENDS)
diff --git a/mesalib/src/mesa/drivers/dri/Makefile.template b/mesalib/src/mesa/drivers/dri/Makefile.template
index 6be554af7..588210f8a 100644
--- a/mesalib/src/mesa/drivers/dri/Makefile.template
+++ b/mesalib/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 \
@@ -39,13 +37,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 +55,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 $@.tmp -noprefix -linker '$(CXX)' -ldflags '$(LDFLAGS)' \
- $(OBJECTS) $(MESA_MODULES) $(EXTRA_MODULES) $(DRI_LIB_DEPS)
+ $(OBJECTS) $(EXTRA_MODULES) $(DRI_LIB_DEPS)
$(CXX) $(CFLAGS) -o $@.test $(TOP)/src/mesa/drivers/dri/common/dri_test.o $@.tmp $(DRI_LIB_DEPS)
@rm -f $@.test
mv -f $@.tmp $@
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_primitive_dx9.c b/mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_primitive_dx9.c
index aaed87028..256ffcc38 100644
--- a/mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_primitive_dx9.c
+++ b/mesalib/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/mesalib/src/mesa/drivers/windows/gldirect/mesasw/gld_wgl_mesasw.c b/mesalib/src/mesa/drivers/windows/gldirect/mesasw/gld_wgl_mesasw.c
index 36ebe9f31..02f0dfacd 100644
--- a/mesalib/src/mesa/drivers/windows/gldirect/mesasw/gld_wgl_mesasw.c
+++ b/mesalib/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/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h
index 6f0aac6ee..020595bd0 100644
--- a/mesalib/src/mesa/main/mtypes.h
+++ b/mesalib/src/mesa/main/mtypes.h
@@ -1,3371 +1,3369 @@
-/*
- * Mesa 3-D graphics library
- * Version: 7.7
- *
- * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
- * Copyright (C) 2009 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, 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.
- */
-
-/**
- * \file mtypes.h
- * Main Mesa data structures.
- *
- * Please try to mark derived values with a leading underscore ('_').
- */
-
-#ifndef MTYPES_H
-#define MTYPES_H
-
-
-#include "main/glheader.h"
-#include "main/config.h"
-#include "main/mfeatures.h"
-#include "glapi/glapi.h"
-#include "math/m_matrix.h" /* GLmatrix */
-#include "main/simple_list.h" /* struct simple_node */
-#include "main/formats.h" /* MESA_FORMAT_COUNT */
-
-
-/**
- * Color channel data type.
- */
-#if CHAN_BITS == 8
- typedef GLubyte GLchan;
-#define CHAN_MAX 255
-#define CHAN_MAXF 255.0F
-#define CHAN_TYPE GL_UNSIGNED_BYTE
-#elif CHAN_BITS == 16
- typedef GLushort GLchan;
-#define CHAN_MAX 65535
-#define CHAN_MAXF 65535.0F
-#define CHAN_TYPE GL_UNSIGNED_SHORT
-#elif CHAN_BITS == 32
- typedef GLfloat GLchan;
-#define CHAN_MAX 1.0
-#define CHAN_MAXF 1.0F
-#define CHAN_TYPE GL_FLOAT
-#else
-#error "illegal number of color channel bits"
-#endif
-
-
-/**
- * Stencil buffer data type.
- */
-#if STENCIL_BITS==8
- typedef GLubyte GLstencil;
-#elif STENCIL_BITS==16
- typedef GLushort GLstencil;
-#else
-# error "illegal number of stencil bits"
-#endif
-
-
-/**
- * \name 64-bit extension of GLbitfield.
- */
-/*@{*/
-typedef GLuint64 GLbitfield64;
-
-/** Set a single bit */
-#define BITFIELD64_BIT(b) (1ULL << (b))
-
-
-/**
- * \name Some forward type declarations
- */
-/*@{*/
-struct _mesa_HashTable;
-struct gl_attrib_node;
-struct gl_list_extensions;
-struct gl_meta_state;
-struct gl_pixelstore_attrib;
-struct gl_program_cache;
-struct gl_texture_format;
-struct gl_texture_image;
-struct gl_texture_object;
-struct gl_context;
-struct st_context;
-/*@}*/
-
-
-/** Extra draw modes beyond GL_POINTS, GL_TRIANGLE_FAN, etc */
-#define PRIM_OUTSIDE_BEGIN_END (GL_POLYGON+1)
-#define PRIM_INSIDE_UNKNOWN_PRIM (GL_POLYGON+2)
-#define PRIM_UNKNOWN (GL_POLYGON+3)
-
-
-/**
- * Shader stages. Note that these will become 5 with tessellation.
- * These MUST have the same values as gallium's PIPE_SHADER_*
- */
-typedef enum
-{
- MESA_SHADER_VERTEX = 0,
- MESA_SHADER_FRAGMENT = 1,
- MESA_SHADER_GEOMETRY = 2,
- MESA_SHADER_TYPES = 3
-} gl_shader_type;
-
-
-
-/**
- * Indexes for vertex program attributes.
- * GL_NV_vertex_program aliases generic attributes over the conventional
- * attributes. In GL_ARB_vertex_program shader the aliasing is optional.
- * In GL_ARB_vertex_shader / OpenGL 2.0 the aliasing is disallowed (the
- * generic attributes are distinct/separate).
- */
-typedef enum
-{
- VERT_ATTRIB_POS = 0,
- VERT_ATTRIB_WEIGHT = 1,
- VERT_ATTRIB_NORMAL = 2,
- VERT_ATTRIB_COLOR0 = 3,
- VERT_ATTRIB_COLOR1 = 4,
- VERT_ATTRIB_FOG = 5,
- VERT_ATTRIB_COLOR_INDEX = 6,
- VERT_ATTRIB_POINT_SIZE = 6, /*alias*/
- VERT_ATTRIB_EDGEFLAG = 7,
- VERT_ATTRIB_TEX0 = 8,
- VERT_ATTRIB_TEX1 = 9,
- VERT_ATTRIB_TEX2 = 10,
- VERT_ATTRIB_TEX3 = 11,
- VERT_ATTRIB_TEX4 = 12,
- VERT_ATTRIB_TEX5 = 13,
- VERT_ATTRIB_TEX6 = 14,
- VERT_ATTRIB_TEX7 = 15,
- VERT_ATTRIB_GENERIC0 = 16,
- VERT_ATTRIB_GENERIC1 = 17,
- VERT_ATTRIB_GENERIC2 = 18,
- VERT_ATTRIB_GENERIC3 = 19,
- VERT_ATTRIB_GENERIC4 = 20,
- VERT_ATTRIB_GENERIC5 = 21,
- VERT_ATTRIB_GENERIC6 = 22,
- VERT_ATTRIB_GENERIC7 = 23,
- VERT_ATTRIB_GENERIC8 = 24,
- VERT_ATTRIB_GENERIC9 = 25,
- VERT_ATTRIB_GENERIC10 = 26,
- VERT_ATTRIB_GENERIC11 = 27,
- VERT_ATTRIB_GENERIC12 = 28,
- VERT_ATTRIB_GENERIC13 = 29,
- VERT_ATTRIB_GENERIC14 = 30,
- VERT_ATTRIB_GENERIC15 = 31,
- VERT_ATTRIB_MAX = 32
-} gl_vert_attrib;
-
-/**
- * Bitflags for vertex attributes.
- * These are used in bitfields in many places.
- */
-/*@{*/
-#define VERT_BIT_POS (1 << VERT_ATTRIB_POS)
-#define VERT_BIT_WEIGHT (1 << VERT_ATTRIB_WEIGHT)
-#define VERT_BIT_NORMAL (1 << VERT_ATTRIB_NORMAL)
-#define VERT_BIT_COLOR0 (1 << VERT_ATTRIB_COLOR0)
-#define VERT_BIT_COLOR1 (1 << VERT_ATTRIB_COLOR1)
-#define VERT_BIT_FOG (1 << VERT_ATTRIB_FOG)
-#define VERT_BIT_COLOR_INDEX (1 << VERT_ATTRIB_COLOR_INDEX)
-#define VERT_BIT_EDGEFLAG (1 << VERT_ATTRIB_EDGEFLAG)
-#define VERT_BIT_TEX0 (1 << VERT_ATTRIB_TEX0)
-#define VERT_BIT_TEX1 (1 << VERT_ATTRIB_TEX1)
-#define VERT_BIT_TEX2 (1 << VERT_ATTRIB_TEX2)
-#define VERT_BIT_TEX3 (1 << VERT_ATTRIB_TEX3)
-#define VERT_BIT_TEX4 (1 << VERT_ATTRIB_TEX4)
-#define VERT_BIT_TEX5 (1 << VERT_ATTRIB_TEX5)
-#define VERT_BIT_TEX6 (1 << VERT_ATTRIB_TEX6)
-#define VERT_BIT_TEX7 (1 << VERT_ATTRIB_TEX7)
-#define VERT_BIT_GENERIC0 (1 << VERT_ATTRIB_GENERIC0)
-#define VERT_BIT_GENERIC1 (1 << VERT_ATTRIB_GENERIC1)
-#define VERT_BIT_GENERIC2 (1 << VERT_ATTRIB_GENERIC2)
-#define VERT_BIT_GENERIC3 (1 << VERT_ATTRIB_GENERIC3)
-#define VERT_BIT_GENERIC4 (1 << VERT_ATTRIB_GENERIC4)
-#define VERT_BIT_GENERIC5 (1 << VERT_ATTRIB_GENERIC5)
-#define VERT_BIT_GENERIC6 (1 << VERT_ATTRIB_GENERIC6)
-#define VERT_BIT_GENERIC7 (1 << VERT_ATTRIB_GENERIC7)
-#define VERT_BIT_GENERIC8 (1 << VERT_ATTRIB_GENERIC8)
-#define VERT_BIT_GENERIC9 (1 << VERT_ATTRIB_GENERIC9)
-#define VERT_BIT_GENERIC10 (1 << VERT_ATTRIB_GENERIC10)
-#define VERT_BIT_GENERIC11 (1 << VERT_ATTRIB_GENERIC11)
-#define VERT_BIT_GENERIC12 (1 << VERT_ATTRIB_GENERIC12)
-#define VERT_BIT_GENERIC13 (1 << VERT_ATTRIB_GENERIC13)
-#define VERT_BIT_GENERIC14 (1 << VERT_ATTRIB_GENERIC14)
-#define VERT_BIT_GENERIC15 (1 << VERT_ATTRIB_GENERIC15)
-
-#define VERT_BIT_TEX(u) (1 << (VERT_ATTRIB_TEX0 + (u)))
-#define VERT_BIT_GENERIC(g) (1 << (VERT_ATTRIB_GENERIC0 + (g)))
-/*@}*/
-
-
-/**
- * Indexes for vertex program result attributes
- */
-typedef enum
-{
- VERT_RESULT_HPOS = 0,
- VERT_RESULT_COL0 = 1,
- VERT_RESULT_COL1 = 2,
- VERT_RESULT_FOGC = 3,
- VERT_RESULT_TEX0 = 4,
- VERT_RESULT_TEX1 = 5,
- VERT_RESULT_TEX2 = 6,
- VERT_RESULT_TEX3 = 7,
- VERT_RESULT_TEX4 = 8,
- VERT_RESULT_TEX5 = 9,
- VERT_RESULT_TEX6 = 10,
- VERT_RESULT_TEX7 = 11,
- VERT_RESULT_PSIZ = 12,
- VERT_RESULT_BFC0 = 13,
- VERT_RESULT_BFC1 = 14,
- VERT_RESULT_EDGE = 15,
- VERT_RESULT_VAR0 = 16, /**< shader varying */
- VERT_RESULT_MAX = (VERT_RESULT_VAR0 + MAX_VARYING)
-} gl_vert_result;
-
-
-/*********************************************/
-
-/**
- * Indexes for geometry program attributes.
- */
-typedef enum
-{
- GEOM_ATTRIB_POSITION = 0,
- GEOM_ATTRIB_COLOR0 = 1,
- GEOM_ATTRIB_COLOR1 = 2,
- GEOM_ATTRIB_SECONDARY_COLOR0 = 3,
- GEOM_ATTRIB_SECONDARY_COLOR1 = 4,
- GEOM_ATTRIB_FOG_FRAG_COORD = 5,
- GEOM_ATTRIB_POINT_SIZE = 6,
- GEOM_ATTRIB_CLIP_VERTEX = 7,
- GEOM_ATTRIB_PRIMITIVE_ID = 8,
- GEOM_ATTRIB_TEX_COORD = 9,
-
- GEOM_ATTRIB_VAR0 = 16,
- GEOM_ATTRIB_MAX = (GEOM_ATTRIB_VAR0 + MAX_VARYING)
-} gl_geom_attrib;
-
-/**
- * Bitflags for geometry attributes.
- * These are used in bitfields in many places.
- */
-/*@{*/
-#define GEOM_BIT_COLOR0 (1 << GEOM_ATTRIB_COLOR0)
-#define GEOM_BIT_COLOR1 (1 << GEOM_ATTRIB_COLOR1)
-#define GEOM_BIT_SCOLOR0 (1 << GEOM_ATTRIB_SECONDARY_COLOR0)
-#define GEOM_BIT_SCOLOR1 (1 << GEOM_ATTRIB_SECONDARY_COLOR1)
-#define GEOM_BIT_TEX_COORD (1 << GEOM_ATTRIB_TEX_COORD)
-#define GEOM_BIT_FOG_COORD (1 << GEOM_ATTRIB_FOG_FRAG_COORD)
-#define GEOM_BIT_POSITION (1 << GEOM_ATTRIB_POSITION)
-#define GEOM_BIT_POINT_SIDE (1 << GEOM_ATTRIB_POINT_SIZE)
-#define GEOM_BIT_CLIP_VERTEX (1 << GEOM_ATTRIB_CLIP_VERTEX)
-#define GEOM_BIT_PRIM_ID (1 << GEOM_ATTRIB_PRIMITIVE_ID)
-#define GEOM_BIT_VAR0 (1 << GEOM_ATTRIB_VAR0)
-
-#define GEOM_BIT_VAR(g) (1 << (GEOM_BIT_VAR0 + (g)))
-/*@}*/
-
-
-/**
- * Indexes for geometry program result attributes
- */
-typedef enum
-{
- GEOM_RESULT_POS = 0,
- GEOM_RESULT_COL0 = 1,
- GEOM_RESULT_COL1 = 2,
- GEOM_RESULT_SCOL0 = 3,
- GEOM_RESULT_SCOL1 = 4,
- GEOM_RESULT_FOGC = 5,
- GEOM_RESULT_TEX0 = 6,
- GEOM_RESULT_TEX1 = 7,
- GEOM_RESULT_TEX2 = 8,
- GEOM_RESULT_TEX3 = 9,
- GEOM_RESULT_TEX4 = 10,
- GEOM_RESULT_TEX5 = 11,
- GEOM_RESULT_TEX6 = 12,
- GEOM_RESULT_TEX7 = 13,
- GEOM_RESULT_PSIZ = 14,
- GEOM_RESULT_CLPV = 15,
- GEOM_RESULT_PRID = 16,
- GEOM_RESULT_LAYR = 17,
- GEOM_RESULT_VAR0 = 18, /**< shader varying, should really be 16 */
- /* ### we need to -2 because var0 is 18 instead 16 like in the others */
- GEOM_RESULT_MAX = (GEOM_RESULT_VAR0 + MAX_VARYING - 2)
-} gl_geom_result;
-
-
-/**
- * Indexes for fragment program input attributes.
- */
-typedef enum
-{
- FRAG_ATTRIB_WPOS = 0,
- FRAG_ATTRIB_COL0 = 1,
- FRAG_ATTRIB_COL1 = 2,
- FRAG_ATTRIB_FOGC = 3,
- FRAG_ATTRIB_TEX0 = 4,
- FRAG_ATTRIB_TEX1 = 5,
- FRAG_ATTRIB_TEX2 = 6,
- FRAG_ATTRIB_TEX3 = 7,
- FRAG_ATTRIB_TEX4 = 8,
- FRAG_ATTRIB_TEX5 = 9,
- FRAG_ATTRIB_TEX6 = 10,
- FRAG_ATTRIB_TEX7 = 11,
- FRAG_ATTRIB_FACE = 12, /**< front/back face */
- FRAG_ATTRIB_PNTC = 13, /**< sprite/point coord */
- FRAG_ATTRIB_VAR0 = 14, /**< shader varying */
- FRAG_ATTRIB_MAX = (FRAG_ATTRIB_VAR0 + MAX_VARYING)
-} gl_frag_attrib;
-
-/**
- * Bitflags for fragment program input attributes.
- */
-/*@{*/
-#define FRAG_BIT_WPOS (1 << FRAG_ATTRIB_WPOS)
-#define FRAG_BIT_COL0 (1 << FRAG_ATTRIB_COL0)
-#define FRAG_BIT_COL1 (1 << FRAG_ATTRIB_COL1)
-#define FRAG_BIT_FOGC (1 << FRAG_ATTRIB_FOGC)
-#define FRAG_BIT_FACE (1 << FRAG_ATTRIB_FACE)
-#define FRAG_BIT_PNTC (1 << FRAG_ATTRIB_PNTC)
-#define FRAG_BIT_TEX0 (1 << FRAG_ATTRIB_TEX0)
-#define FRAG_BIT_TEX1 (1 << FRAG_ATTRIB_TEX1)
-#define FRAG_BIT_TEX2 (1 << FRAG_ATTRIB_TEX2)
-#define FRAG_BIT_TEX3 (1 << FRAG_ATTRIB_TEX3)
-#define FRAG_BIT_TEX4 (1 << FRAG_ATTRIB_TEX4)
-#define FRAG_BIT_TEX5 (1 << FRAG_ATTRIB_TEX5)
-#define FRAG_BIT_TEX6 (1 << FRAG_ATTRIB_TEX6)
-#define FRAG_BIT_TEX7 (1 << FRAG_ATTRIB_TEX7)
-#define FRAG_BIT_VAR0 (1 << FRAG_ATTRIB_VAR0)
-
-#define FRAG_BIT_TEX(U) (FRAG_BIT_TEX0 << (U))
-#define FRAG_BIT_VAR(V) (FRAG_BIT_VAR0 << (V))
-
-#define FRAG_BITS_TEX_ANY (FRAG_BIT_TEX0| \
- FRAG_BIT_TEX1| \
- FRAG_BIT_TEX2| \
- FRAG_BIT_TEX3| \
- FRAG_BIT_TEX4| \
- FRAG_BIT_TEX5| \
- FRAG_BIT_TEX6| \
- FRAG_BIT_TEX7)
-/*@}*/
-
-
-/**
- * Fragment program results
- */
-typedef enum
-{
- FRAG_RESULT_DEPTH = 0,
- FRAG_RESULT_STENCIL = 1,
- FRAG_RESULT_COLOR = 2,
- FRAG_RESULT_DATA0 = 3,
- FRAG_RESULT_MAX = (FRAG_RESULT_DATA0 + MAX_DRAW_BUFFERS)
-} gl_frag_result;
-
-
-/**
- * Indexes for all renderbuffers
- */
-typedef enum
-{
- /* the four standard color buffers */
- BUFFER_FRONT_LEFT,
- BUFFER_BACK_LEFT,
- BUFFER_FRONT_RIGHT,
- BUFFER_BACK_RIGHT,
- BUFFER_DEPTH,
- BUFFER_STENCIL,
- BUFFER_ACCUM,
- /* optional aux buffer */
- BUFFER_AUX0,
- /* generic renderbuffers */
- BUFFER_COLOR0,
- BUFFER_COLOR1,
- BUFFER_COLOR2,
- BUFFER_COLOR3,
- BUFFER_COLOR4,
- BUFFER_COLOR5,
- BUFFER_COLOR6,
- BUFFER_COLOR7,
- BUFFER_COUNT
-} gl_buffer_index;
-
-/**
- * Bit flags for all renderbuffers
- */
-#define BUFFER_BIT_FRONT_LEFT (1 << BUFFER_FRONT_LEFT)
-#define BUFFER_BIT_BACK_LEFT (1 << BUFFER_BACK_LEFT)
-#define BUFFER_BIT_FRONT_RIGHT (1 << BUFFER_FRONT_RIGHT)
-#define BUFFER_BIT_BACK_RIGHT (1 << BUFFER_BACK_RIGHT)
-#define BUFFER_BIT_AUX0 (1 << BUFFER_AUX0)
-#define BUFFER_BIT_AUX1 (1 << BUFFER_AUX1)
-#define BUFFER_BIT_AUX2 (1 << BUFFER_AUX2)
-#define BUFFER_BIT_AUX3 (1 << BUFFER_AUX3)
-#define BUFFER_BIT_DEPTH (1 << BUFFER_DEPTH)
-#define BUFFER_BIT_STENCIL (1 << BUFFER_STENCIL)
-#define BUFFER_BIT_ACCUM (1 << BUFFER_ACCUM)
-#define BUFFER_BIT_COLOR0 (1 << BUFFER_COLOR0)
-#define BUFFER_BIT_COLOR1 (1 << BUFFER_COLOR1)
-#define BUFFER_BIT_COLOR2 (1 << BUFFER_COLOR2)
-#define BUFFER_BIT_COLOR3 (1 << BUFFER_COLOR3)
-#define BUFFER_BIT_COLOR4 (1 << BUFFER_COLOR4)
-#define BUFFER_BIT_COLOR5 (1 << BUFFER_COLOR5)
-#define BUFFER_BIT_COLOR6 (1 << BUFFER_COLOR6)
-#define BUFFER_BIT_COLOR7 (1 << BUFFER_COLOR7)
-
-/**
- * Mask of all the color buffer bits (but not accum).
- */
-#define BUFFER_BITS_COLOR (BUFFER_BIT_FRONT_LEFT | \
- BUFFER_BIT_BACK_LEFT | \
- BUFFER_BIT_FRONT_RIGHT | \
- BUFFER_BIT_BACK_RIGHT | \
- BUFFER_BIT_AUX0 | \
- BUFFER_BIT_COLOR0 | \
- BUFFER_BIT_COLOR1 | \
- BUFFER_BIT_COLOR2 | \
- BUFFER_BIT_COLOR3 | \
- BUFFER_BIT_COLOR4 | \
- BUFFER_BIT_COLOR5 | \
- BUFFER_BIT_COLOR6 | \
- BUFFER_BIT_COLOR7)
-
-
-/**
- * Framebuffer configuration (aka visual / pixelformat)
- * Note: some of these fields should be boolean, but it appears that
- * code in drivers/dri/common/util.c requires int-sized fields.
- */
-struct gl_config
-{
- GLboolean rgbMode;
- GLboolean floatMode;
- GLboolean colorIndexMode; /* XXX is this used anywhere? */
- GLuint doubleBufferMode;
- GLuint stereoMode;
-
- GLboolean haveAccumBuffer;
- GLboolean haveDepthBuffer;
- GLboolean haveStencilBuffer;
-
- GLint redBits, greenBits, blueBits, alphaBits; /* bits per comp */
- GLuint redMask, greenMask, blueMask, alphaMask;
- GLint rgbBits; /* total bits for rgb */
- GLint indexBits; /* total bits for colorindex */
-
- GLint accumRedBits, accumGreenBits, accumBlueBits, accumAlphaBits;
- GLint depthBits;
- GLint stencilBits;
-
- GLint numAuxBuffers;
-
- GLint level;
-
- /* EXT_visual_rating / GLX 1.2 */
- GLint visualRating;
-
- /* EXT_visual_info / GLX 1.2 */
- GLint transparentPixel;
- /* colors are floats scaled to ints */
- GLint transparentRed, transparentGreen, transparentBlue, transparentAlpha;
- GLint transparentIndex;
-
- /* ARB_multisample / SGIS_multisample */
- GLint sampleBuffers;
- GLint samples;
-
- /* SGIX_pbuffer / GLX 1.3 */
- GLint maxPbufferWidth;
- GLint maxPbufferHeight;
- GLint maxPbufferPixels;
- GLint optimalPbufferWidth; /* Only for SGIX_pbuffer. */
- GLint optimalPbufferHeight; /* Only for SGIX_pbuffer. */
-
- /* OML_swap_method */
- GLint swapMethod;
-
- /* EXT_texture_from_pixmap */
- GLint bindToTextureRgb;
- GLint bindToTextureRgba;
- GLint bindToMipmapTexture;
- GLint bindToTextureTargets;
- GLint yInverted;
-
- /* EXT_framebuffer_sRGB */
- GLint sRGBCapable;
-};
-
-
-/**
- * Data structure for color tables
- */
-struct gl_color_table
-{
- GLenum InternalFormat; /**< The user-specified format */
- GLenum _BaseFormat; /**< GL_ALPHA, GL_RGBA, GL_RGB, etc */
- GLuint Size; /**< number of entries in table */
- GLfloat *TableF; /**< Color table, floating point values */
- GLubyte *TableUB; /**< Color table, ubyte values */
- GLubyte RedSize;
- GLubyte GreenSize;
- GLubyte BlueSize;
- GLubyte AlphaSize;
- GLubyte LuminanceSize;
- GLubyte IntensitySize;
-};
-
-
-/**
- * \name Bit flags used for updating material values.
- */
-/*@{*/
-#define MAT_ATTRIB_FRONT_AMBIENT 0
-#define MAT_ATTRIB_BACK_AMBIENT 1
-#define MAT_ATTRIB_FRONT_DIFFUSE 2
-#define MAT_ATTRIB_BACK_DIFFUSE 3
-#define MAT_ATTRIB_FRONT_SPECULAR 4
-#define MAT_ATTRIB_BACK_SPECULAR 5
-#define MAT_ATTRIB_FRONT_EMISSION 6
-#define MAT_ATTRIB_BACK_EMISSION 7
-#define MAT_ATTRIB_FRONT_SHININESS 8
-#define MAT_ATTRIB_BACK_SHININESS 9
-#define MAT_ATTRIB_FRONT_INDEXES 10
-#define MAT_ATTRIB_BACK_INDEXES 11
-#define MAT_ATTRIB_MAX 12
-
-#define MAT_ATTRIB_AMBIENT(f) (MAT_ATTRIB_FRONT_AMBIENT+(f))
-#define MAT_ATTRIB_DIFFUSE(f) (MAT_ATTRIB_FRONT_DIFFUSE+(f))
-#define MAT_ATTRIB_SPECULAR(f) (MAT_ATTRIB_FRONT_SPECULAR+(f))
-#define MAT_ATTRIB_EMISSION(f) (MAT_ATTRIB_FRONT_EMISSION+(f))
-#define MAT_ATTRIB_SHININESS(f)(MAT_ATTRIB_FRONT_SHININESS+(f))
-#define MAT_ATTRIB_INDEXES(f) (MAT_ATTRIB_FRONT_INDEXES+(f))
-
-#define MAT_INDEX_AMBIENT 0
-#define MAT_INDEX_DIFFUSE 1
-#define MAT_INDEX_SPECULAR 2
-
-#define MAT_BIT_FRONT_AMBIENT (1<<MAT_ATTRIB_FRONT_AMBIENT)
-#define MAT_BIT_BACK_AMBIENT (1<<MAT_ATTRIB_BACK_AMBIENT)
-#define MAT_BIT_FRONT_DIFFUSE (1<<MAT_ATTRIB_FRONT_DIFFUSE)
-#define MAT_BIT_BACK_DIFFUSE (1<<MAT_ATTRIB_BACK_DIFFUSE)
-#define MAT_BIT_FRONT_SPECULAR (1<<MAT_ATTRIB_FRONT_SPECULAR)
-#define MAT_BIT_BACK_SPECULAR (1<<MAT_ATTRIB_BACK_SPECULAR)
-#define MAT_BIT_FRONT_EMISSION (1<<MAT_ATTRIB_FRONT_EMISSION)
-#define MAT_BIT_BACK_EMISSION (1<<MAT_ATTRIB_BACK_EMISSION)
-#define MAT_BIT_FRONT_SHININESS (1<<MAT_ATTRIB_FRONT_SHININESS)
-#define MAT_BIT_BACK_SHININESS (1<<MAT_ATTRIB_BACK_SHININESS)
-#define MAT_BIT_FRONT_INDEXES (1<<MAT_ATTRIB_FRONT_INDEXES)
-#define MAT_BIT_BACK_INDEXES (1<<MAT_ATTRIB_BACK_INDEXES)
-
-
-#define FRONT_MATERIAL_BITS (MAT_BIT_FRONT_EMISSION | \
- MAT_BIT_FRONT_AMBIENT | \
- MAT_BIT_FRONT_DIFFUSE | \
- MAT_BIT_FRONT_SPECULAR | \
- MAT_BIT_FRONT_SHININESS | \
- MAT_BIT_FRONT_INDEXES)
-
-#define BACK_MATERIAL_BITS (MAT_BIT_BACK_EMISSION | \
- MAT_BIT_BACK_AMBIENT | \
- MAT_BIT_BACK_DIFFUSE | \
- MAT_BIT_BACK_SPECULAR | \
- MAT_BIT_BACK_SHININESS | \
- MAT_BIT_BACK_INDEXES)
-
-#define ALL_MATERIAL_BITS (FRONT_MATERIAL_BITS | BACK_MATERIAL_BITS)
-/*@}*/
-
-
-#define EXP_TABLE_SIZE 512 /**< Specular exponent lookup table sizes */
-#define SHINE_TABLE_SIZE 256 /**< Material shininess lookup table sizes */
-
-/**
- * Material shininess lookup table.
- */
-struct gl_shine_tab
-{
- struct gl_shine_tab *next, *prev;
- GLfloat tab[SHINE_TABLE_SIZE+1];
- GLfloat shininess;
- GLuint refcount;
-};
-
-
-/**
- * Light source state.
- */
-struct gl_light
-{
- struct gl_light *next; /**< double linked list with sentinel */
- struct gl_light *prev;
-
- GLfloat Ambient[4]; /**< ambient color */
- GLfloat Diffuse[4]; /**< diffuse color */
- GLfloat Specular[4]; /**< specular color */
- GLfloat EyePosition[4]; /**< position in eye coordinates */
- GLfloat SpotDirection[4]; /**< spotlight direction in eye coordinates */
- GLfloat SpotExponent;
- GLfloat SpotCutoff; /**< in degrees */
- GLfloat _CosCutoffNeg; /**< = cos(SpotCutoff) */
- GLfloat _CosCutoff; /**< = MAX(0, cos(SpotCutoff)) */
- GLfloat ConstantAttenuation;
- GLfloat LinearAttenuation;
- GLfloat QuadraticAttenuation;
- GLboolean Enabled; /**< On/off flag */
-
- /**
- * \name Derived fields
- */
- /*@{*/
- GLbitfield _Flags; /**< State */
-
- GLfloat _Position[4]; /**< position in eye/obj coordinates */
- GLfloat _VP_inf_norm[3]; /**< Norm direction to infinite light */
- GLfloat _h_inf_norm[3]; /**< Norm( _VP_inf_norm + <0,0,1> ) */
- GLfloat _NormSpotDirection[4]; /**< normalized spotlight direction */
- GLfloat _VP_inf_spot_attenuation;
-
- GLfloat _SpotExpTable[EXP_TABLE_SIZE][2]; /**< to replace a pow() call */
- GLfloat _MatAmbient[2][3]; /**< material ambient * light ambient */
- GLfloat _MatDiffuse[2][3]; /**< material diffuse * light diffuse */
- GLfloat _MatSpecular[2][3]; /**< material spec * light specular */
- GLfloat _dli; /**< CI diffuse light intensity */
- GLfloat _sli; /**< CI specular light intensity */
- /*@}*/
-};
-
-
-/**
- * Light model state.
- */
-struct gl_lightmodel
-{
- GLfloat Ambient[4]; /**< ambient color */
- GLboolean LocalViewer; /**< Local (or infinite) view point? */
- GLboolean TwoSide; /**< Two (or one) sided lighting? */
- GLenum ColorControl; /**< either GL_SINGLE_COLOR
- * or GL_SEPARATE_SPECULAR_COLOR */
-};
-
-
-/**
- * Material state.
- */
-struct gl_material
-{
- GLfloat Attrib[MAT_ATTRIB_MAX][4];
-};
-
-
-/**
- * Accumulation buffer attribute group (GL_ACCUM_BUFFER_BIT)
- */
-struct gl_accum_attrib
-{
- GLfloat ClearColor[4]; /**< Accumulation buffer clear color */
-};
-
-
-/**
- * Color buffer attribute group (GL_COLOR_BUFFER_BIT).
- */
-struct gl_colorbuffer_attrib
-{
- GLuint ClearIndex; /**< Index to use for glClear */
- GLclampf ClearColor[4]; /**< Color to use for glClear */
-
- GLuint IndexMask; /**< Color index write mask */
- GLubyte ColorMask[MAX_DRAW_BUFFERS][4];/**< Each flag is 0xff or 0x0 */
-
- GLenum DrawBuffer[MAX_DRAW_BUFFERS]; /**< Which buffer to draw into */
-
- /**
- * \name alpha testing
- */
- /*@{*/
- GLboolean AlphaEnabled; /**< Alpha test enabled flag */
- GLenum AlphaFunc; /**< Alpha test function */
- GLclampf AlphaRef; /**< Alpha reference value */
- /*@}*/
-
- /**
- * \name Blending
- */
- /*@{*/
- GLbitfield BlendEnabled; /**< Per-buffer blend enable flags */
- GLfloat BlendColor[4]; /**< Blending color */
- struct
- {
- GLenum SrcRGB; /**< RGB blend source term */
- GLenum DstRGB; /**< RGB blend dest term */
- GLenum SrcA; /**< Alpha blend source term */
- GLenum DstA; /**< Alpha blend dest term */
- GLenum EquationRGB; /**< GL_ADD, GL_SUBTRACT, etc. */
- GLenum EquationA; /**< GL_ADD, GL_SUBTRACT, etc. */
- } Blend[MAX_DRAW_BUFFERS];
- /** Are the blend func terms currently different for each buffer/target? */
- GLboolean _BlendFuncPerBuffer;
- /** Are the blend equations currently different for each buffer/target? */
- GLboolean _BlendEquationPerBuffer;
- /*@}*/
-
- /**
- * \name Logic op
- */
- /*@{*/
- GLenum LogicOp; /**< Logic operator */
- GLboolean IndexLogicOpEnabled; /**< Color index logic op enabled flag */
- GLboolean ColorLogicOpEnabled; /**< RGBA logic op enabled flag */
- GLboolean _LogicOpEnabled; /**< RGBA logic op + EXT_blend_logic_op enabled flag */
- /*@}*/
-
- GLboolean DitherFlag; /**< Dither enable flag */
-
- GLenum ClampFragmentColor; /**< GL_TRUE, GL_FALSE or GL_FIXED_ONLY_ARB */
- GLenum ClampReadColor; /**< GL_TRUE, GL_FALSE or GL_FIXED_ONLY_ARB */
-
- GLboolean sRGBEnabled; /**< Framebuffer sRGB blending/updating requested */
-};
-
-
-/**
- * Current attribute group (GL_CURRENT_BIT).
- */
-struct gl_current_attrib
-{
- /**
- * \name Current vertex attributes.
- * \note Values are valid only after FLUSH_VERTICES has been called.
- * \note Index and Edgeflag current values are stored as floats in the
- * SIX and SEVEN attribute slots.
- */
- GLfloat Attrib[VERT_ATTRIB_MAX][4]; /**< Position, color, texcoords, etc */
-
- /**
- * \name Current raster position attributes (always valid).
- * \note This set of attributes is very similar to the SWvertex struct.
- */
- /*@{*/
- GLfloat RasterPos[4];
- GLfloat RasterDistance;
- GLfloat RasterColor[4];
- GLfloat RasterSecondaryColor[4];
- GLfloat RasterTexCoords[MAX_TEXTURE_COORD_UNITS][4];
- GLboolean RasterPosValid;
- /*@}*/
-};
-
-
-/**
- * Depth buffer attribute group (GL_DEPTH_BUFFER_BIT).
- */
-struct gl_depthbuffer_attrib
-{
- GLenum Func; /**< Function for depth buffer compare */
- GLclampd Clear; /**< Value to clear depth buffer to */
- GLboolean Test; /**< Depth buffering enabled flag */
- GLboolean Mask; /**< Depth buffer writable? */
- GLboolean BoundsTest; /**< GL_EXT_depth_bounds_test */
- GLfloat BoundsMin, BoundsMax;/**< GL_EXT_depth_bounds_test */
-};
-
-
-/**
- * Evaluator attribute group (GL_EVAL_BIT).
- */
-struct gl_eval_attrib
-{
- /**
- * \name Enable bits
- */
- /*@{*/
- GLboolean Map1Color4;
- GLboolean Map1Index;
- GLboolean Map1Normal;
- GLboolean Map1TextureCoord1;
- GLboolean Map1TextureCoord2;
- GLboolean Map1TextureCoord3;
- GLboolean Map1TextureCoord4;
- GLboolean Map1Vertex3;
- GLboolean Map1Vertex4;
- GLboolean Map1Attrib[16]; /* GL_NV_vertex_program */
- GLboolean Map2Color4;
- GLboolean Map2Index;
- GLboolean Map2Normal;
- GLboolean Map2TextureCoord1;
- GLboolean Map2TextureCoord2;
- GLboolean Map2TextureCoord3;
- GLboolean Map2TextureCoord4;
- GLboolean Map2Vertex3;
- GLboolean Map2Vertex4;
- GLboolean Map2Attrib[16]; /* GL_NV_vertex_program */
- GLboolean AutoNormal;
- /*@}*/
-
- /**
- * \name Map Grid endpoints and divisions and calculated du values
- */
- /*@{*/
- GLint MapGrid1un;
- GLfloat MapGrid1u1, MapGrid1u2, MapGrid1du;
- GLint MapGrid2un, MapGrid2vn;
- GLfloat MapGrid2u1, MapGrid2u2, MapGrid2du;
- GLfloat MapGrid2v1, MapGrid2v2, MapGrid2dv;
- /*@}*/
-};
-
-
-/**
- * Fog attribute group (GL_FOG_BIT).
- */
-struct gl_fog_attrib
-{
- GLboolean Enabled; /**< Fog enabled flag */
- GLfloat Color[4]; /**< Fog color */
- GLfloat Density; /**< Density >= 0.0 */
- GLfloat Start; /**< Start distance in eye coords */
- GLfloat End; /**< End distance in eye coords */
- GLfloat Index; /**< Fog index */
- GLenum Mode; /**< Fog mode */
- GLboolean ColorSumEnabled;
- GLenum FogCoordinateSource; /**< GL_EXT_fog_coord */
- GLfloat _Scale; /**< (End == Start) ? 1.0 : 1.0 / (End - Start) */
-};
-
-
-/**
- * \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).
- *
- * Values are always one of GL_FASTEST, GL_NICEST, or GL_DONT_CARE.
- */
-struct gl_hint_attrib
-{
- GLenum PerspectiveCorrection;
- GLenum PointSmooth;
- GLenum LineSmooth;
- GLenum PolygonSmooth;
- GLenum Fog;
- GLenum ClipVolumeClipping; /**< GL_EXT_clip_volume_hint */
- GLenum TextureCompression; /**< GL_ARB_texture_compression */
- GLenum GenerateMipmap; /**< GL_SGIS_generate_mipmap */
- GLenum FragmentShaderDerivative; /**< GL_ARB_fragment_shader */
-};
-
-/**
- * Light state flags.
- */
-/*@{*/
-#define LIGHT_SPOT 0x1
-#define LIGHT_LOCAL_VIEWER 0x2
-#define LIGHT_POSITIONAL 0x4
-#define LIGHT_NEED_VERTICES (LIGHT_POSITIONAL|LIGHT_LOCAL_VIEWER)
-/*@}*/
-
-
-/**
- * Lighting attribute group (GL_LIGHT_BIT).
- */
-struct gl_light_attrib
-{
- struct gl_light Light[MAX_LIGHTS]; /**< Array of light sources */
- struct gl_lightmodel Model; /**< Lighting model */
-
- /**
- * Must flush FLUSH_VERTICES before referencing:
- */
- /*@{*/
- struct gl_material Material; /**< Includes front & back values */
- /*@}*/
-
- GLboolean Enabled; /**< Lighting enabled flag */
- GLenum ShadeModel; /**< GL_FLAT or GL_SMOOTH */
- GLenum ProvokingVertex; /**< GL_EXT_provoking_vertex */
- GLenum ColorMaterialFace; /**< GL_FRONT, BACK or FRONT_AND_BACK */
- GLenum ColorMaterialMode; /**< GL_AMBIENT, GL_DIFFUSE, etc */
- GLbitfield ColorMaterialBitmask; /**< bitmask formed from Face and Mode */
- GLboolean ColorMaterialEnabled;
- GLenum ClampVertexColor;
-
- struct gl_light EnabledList; /**< List sentinel */
-
- /**
- * Derived state for optimizations:
- */
- /*@{*/
- GLboolean _NeedEyeCoords;
- GLboolean _NeedVertices; /**< Use fast shader? */
- GLbitfield _Flags; /**< LIGHT_* flags, see above */
- GLfloat _BaseColor[2][3];
- /*@}*/
-};
-
-
-/**
- * Line attribute group (GL_LINE_BIT).
- */
-struct gl_line_attrib
-{
- GLboolean SmoothFlag; /**< GL_LINE_SMOOTH enabled? */
- GLboolean StippleFlag; /**< GL_LINE_STIPPLE enabled? */
- GLushort StipplePattern; /**< Stipple pattern */
- GLint StippleFactor; /**< Stipple repeat factor */
- GLfloat Width; /**< Line width */
-};
-
-
-/**
- * Display list attribute group (GL_LIST_BIT).
- */
-struct gl_list_attrib
-{
- GLuint ListBase;
-};
-
-
-/**
- * Multisample attribute group (GL_MULTISAMPLE_BIT).
- */
-struct gl_multisample_attrib
-{
- GLboolean Enabled;
- GLboolean _Enabled; /**< true if Enabled and multisample buffer */
- GLboolean SampleAlphaToCoverage;
- GLboolean SampleAlphaToOne;
- GLboolean SampleCoverage;
- GLfloat SampleCoverageValue;
- GLboolean SampleCoverageInvert;
-};
-
-
-/**
- * A pixelmap (see glPixelMap)
- */
-struct gl_pixelmap
-{
- GLint Size;
- GLfloat Map[MAX_PIXEL_MAP_TABLE];
- GLubyte Map8[MAX_PIXEL_MAP_TABLE]; /**< converted to 8-bit color */
-};
-
-
-/**
- * Collection of all pixelmaps
- */
-struct gl_pixelmaps
-{
- struct gl_pixelmap RtoR; /**< i.e. GL_PIXEL_MAP_R_TO_R */
- struct gl_pixelmap GtoG;
- struct gl_pixelmap BtoB;
- struct gl_pixelmap AtoA;
- struct gl_pixelmap ItoR;
- struct gl_pixelmap ItoG;
- struct gl_pixelmap ItoB;
- struct gl_pixelmap ItoA;
- struct gl_pixelmap ItoI;
- struct gl_pixelmap StoS;
-};
-
-
-/**
- * Pixel attribute group (GL_PIXEL_MODE_BIT).
- */
-struct gl_pixel_attrib
-{
- GLenum ReadBuffer; /**< source buffer for glRead/CopyPixels() */
-
- /*--- Begin Pixel Transfer State ---*/
- /* Fields are in the order in which they're applied... */
-
- /** Scale & Bias (index shift, offset) */
- /*@{*/
- GLfloat RedBias, RedScale;
- GLfloat GreenBias, GreenScale;
- GLfloat BlueBias, BlueScale;
- GLfloat AlphaBias, AlphaScale;
- GLfloat DepthBias, DepthScale;
- GLint IndexShift, IndexOffset;
- /*@}*/
-
- /* Pixel Maps */
- /* Note: actual pixel maps are not part of this attrib group */
- GLboolean MapColorFlag;
- GLboolean MapStencilFlag;
-
- /*--- End Pixel Transfer State ---*/
-
- /** glPixelZoom */
- GLfloat ZoomX, ZoomY;
-
- /** GL_SGI_texture_color_table */
- GLfloat TextureColorTableScale[4]; /**< RGBA */
- GLfloat TextureColorTableBias[4]; /**< RGBA */
-};
-
-
-/**
- * Point attribute group (GL_POINT_BIT).
- */
-struct gl_point_attrib
-{
- GLboolean SmoothFlag; /**< True if GL_POINT_SMOOTH is enabled */
- GLfloat Size; /**< User-specified point size */
- GLfloat Params[3]; /**< GL_EXT_point_parameters */
- GLfloat MinSize, MaxSize; /**< GL_EXT_point_parameters */
- GLfloat Threshold; /**< GL_EXT_point_parameters */
- GLboolean _Attenuated; /**< True if Params != [1, 0, 0] */
- GLboolean PointSprite; /**< GL_NV/ARB_point_sprite */
- GLboolean CoordReplace[MAX_TEXTURE_COORD_UNITS]; /**< GL_ARB_point_sprite*/
- GLenum SpriteRMode; /**< GL_NV_point_sprite (only!) */
- GLenum SpriteOrigin; /**< GL_ARB_point_sprite */
-};
-
-
-/**
- * Polygon attribute group (GL_POLYGON_BIT).
- */
-struct gl_polygon_attrib
-{
- GLenum FrontFace; /**< Either GL_CW or GL_CCW */
- GLenum FrontMode; /**< Either GL_POINT, GL_LINE or GL_FILL */
- GLenum BackMode; /**< Either GL_POINT, GL_LINE or GL_FILL */
- GLboolean _FrontBit; /**< 0=GL_CCW, 1=GL_CW */
- GLboolean CullFlag; /**< Culling on/off flag */
- GLboolean SmoothFlag; /**< True if GL_POLYGON_SMOOTH is enabled */
- GLboolean StippleFlag; /**< True if GL_POLYGON_STIPPLE is enabled */
- GLenum CullFaceMode; /**< Culling mode GL_FRONT or GL_BACK */
- GLfloat OffsetFactor; /**< Polygon offset factor, from user */
- GLfloat OffsetUnits; /**< Polygon offset units, from user */
- GLboolean OffsetPoint; /**< Offset in GL_POINT mode */
- GLboolean OffsetLine; /**< Offset in GL_LINE mode */
- GLboolean OffsetFill; /**< Offset in GL_FILL mode */
-};
-
-
-/**
- * Scissor attributes (GL_SCISSOR_BIT).
- */
-struct gl_scissor_attrib
-{
- GLboolean Enabled; /**< Scissor test enabled? */
- GLint X, Y; /**< Lower left corner of box */
- GLsizei Width, Height; /**< Size of box */
-};
-
-
-/**
- * Stencil attribute group (GL_STENCIL_BUFFER_BIT).
- *
- * Three sets of stencil data are tracked so that OpenGL 2.0,
- * GL_EXT_stencil_two_side, and GL_ATI_separate_stencil can all be supported
- * simultaneously. In each of the stencil state arrays, element 0 corresponds
- * to GL_FRONT. Element 1 corresponds to the OpenGL 2.0 /
- * GL_ATI_separate_stencil GL_BACK state. Element 2 corresponds to the
- * GL_EXT_stencil_two_side GL_BACK state.
- *
- * The derived value \c _BackFace is either 1 or 2 depending on whether or
- * not GL_STENCIL_TEST_TWO_SIDE_EXT is enabled.
- *
- * The derived value \c _TestTwoSide is set when the front-face and back-face
- * stencil state are different.
- */
-struct gl_stencil_attrib
-{
- GLboolean Enabled; /**< Enabled flag */
- GLboolean TestTwoSide; /**< GL_EXT_stencil_two_side */
- GLubyte ActiveFace; /**< GL_EXT_stencil_two_side (0 or 2) */
- GLboolean _Enabled; /**< Enabled and stencil buffer present */
- GLboolean _TestTwoSide;
- GLubyte _BackFace; /**< Current back stencil state (1 or 2) */
- GLenum Function[3]; /**< Stencil function */
- GLenum FailFunc[3]; /**< Fail function */
- GLenum ZPassFunc[3]; /**< Depth buffer pass function */
- GLenum ZFailFunc[3]; /**< Depth buffer fail function */
- GLint Ref[3]; /**< Reference value */
- GLuint ValueMask[3]; /**< Value mask */
- GLuint WriteMask[3]; /**< Write mask */
- GLuint Clear; /**< Clear value */
-};
-
-
-/**
- * An index for each type of texture object. These correspond to the GL
- * texture target enums, such as GL_TEXTURE_2D, GL_TEXTURE_CUBE_MAP, etc.
- * Note: the order is from highest priority to lowest priority.
- */
-typedef enum
-{
- TEXTURE_2D_ARRAY_INDEX,
- TEXTURE_1D_ARRAY_INDEX,
- TEXTURE_CUBE_INDEX,
- TEXTURE_3D_INDEX,
- TEXTURE_RECT_INDEX,
- TEXTURE_2D_INDEX,
- TEXTURE_1D_INDEX,
- NUM_TEXTURE_TARGETS
-} gl_texture_index;
-
-
-/**
- * Bit flags for each type of texture object
- * Used for Texture.Unit[]._ReallyEnabled flags.
- */
-/*@{*/
-#define TEXTURE_2D_ARRAY_BIT (1 << TEXTURE_2D_ARRAY_INDEX)
-#define TEXTURE_1D_ARRAY_BIT (1 << TEXTURE_1D_ARRAY_INDEX)
-#define TEXTURE_CUBE_BIT (1 << TEXTURE_CUBE_INDEX)
-#define TEXTURE_3D_BIT (1 << TEXTURE_3D_INDEX)
-#define TEXTURE_RECT_BIT (1 << TEXTURE_RECT_INDEX)
-#define TEXTURE_2D_BIT (1 << TEXTURE_2D_INDEX)
-#define TEXTURE_1D_BIT (1 << TEXTURE_1D_INDEX)
-/*@}*/
-
-
-/**
- * TexGenEnabled flags.
- */
-/*@{*/
-#define S_BIT 1
-#define T_BIT 2
-#define R_BIT 4
-#define Q_BIT 8
-#define STR_BITS (S_BIT | T_BIT | R_BIT)
-/*@}*/
-
-
-/**
- * Bit flag versions of the corresponding GL_ constants.
- */
-/*@{*/
-#define TEXGEN_SPHERE_MAP 0x1
-#define TEXGEN_OBJ_LINEAR 0x2
-#define TEXGEN_EYE_LINEAR 0x4
-#define TEXGEN_REFLECTION_MAP_NV 0x8
-#define TEXGEN_NORMAL_MAP_NV 0x10
-
-#define TEXGEN_NEED_NORMALS (TEXGEN_SPHERE_MAP | \
- TEXGEN_REFLECTION_MAP_NV | \
- TEXGEN_NORMAL_MAP_NV)
-#define TEXGEN_NEED_EYE_COORD (TEXGEN_SPHERE_MAP | \
- TEXGEN_REFLECTION_MAP_NV | \
- TEXGEN_NORMAL_MAP_NV | \
- TEXGEN_EYE_LINEAR)
-/*@}*/
-
-
-
-/** Tex-gen enabled for texture unit? */
-#define ENABLE_TEXGEN(unit) (1 << (unit))
-
-/** Non-identity texture matrix for texture unit? */
-#define ENABLE_TEXMAT(unit) (1 << (unit))
-
-
-/**
- * Texel fetch function prototype. We use texel fetch functions to
- * extract RGBA, color indexes and depth components out of 1D, 2D and 3D
- * texture images. These functions help to isolate us from the gritty
- * details of all the various texture image encodings.
- *
- * \param texImage texture image.
- * \param col texel column.
- * \param row texel row.
- * \param img texel image level/layer.
- * \param texelOut output texel (up to 4 GLchans)
- */
-typedef void (*FetchTexelFuncC)( const struct gl_texture_image *texImage,
- GLint col, GLint row, GLint img,
- GLchan *texelOut );
-
-/**
- * As above, but returns floats.
- * Used for depth component images and for upcoming signed/float
- * texture images.
- */
-typedef void (*FetchTexelFuncF)( const struct gl_texture_image *texImage,
- GLint col, GLint row, GLint img,
- GLfloat *texelOut );
-
-
-typedef void (*StoreTexelFunc)(struct gl_texture_image *texImage,
- GLint col, GLint row, GLint img,
- const void *texel);
-
-
-/**
- * Texture image state. Describes the dimensions of a texture image,
- * the texel format and pointers to Texel Fetch functions.
- */
-struct gl_texture_image
-{
- GLint InternalFormat; /**< Internal format as given by the user */
- GLenum _BaseFormat; /**< Either GL_RGB, GL_RGBA, GL_ALPHA,
- * GL_LUMINANCE, GL_LUMINANCE_ALPHA,
- * GL_INTENSITY, GL_COLOR_INDEX,
- * GL_DEPTH_COMPONENT or GL_DEPTH_STENCIL_EXT
- * only. Used for choosing TexEnv arithmetic.
- */
- GLuint TexFormat; /**< The actual format: MESA_FORMAT_x */
-
- GLuint Border; /**< 0 or 1 */
- GLuint Width; /**< = 2^WidthLog2 + 2*Border */
- GLuint Height; /**< = 2^HeightLog2 + 2*Border */
- GLuint Depth; /**< = 2^DepthLog2 + 2*Border */
- GLuint Width2; /**< = Width - 2*Border */
- GLuint Height2; /**< = Height - 2*Border */
- GLuint Depth2; /**< = Depth - 2*Border */
- GLuint WidthLog2; /**< = log2(Width2) */
- GLuint HeightLog2; /**< = log2(Height2) */
- GLuint DepthLog2; /**< = log2(Depth2) */
- GLuint MaxLog2; /**< = MAX(WidthLog2, HeightLog2) */
- GLfloat WidthScale; /**< used for mipmap LOD computation */
- GLfloat HeightScale; /**< used for mipmap LOD computation */
- GLfloat DepthScale; /**< used for mipmap LOD computation */
- GLboolean IsClientData; /**< Data owned by client? */
- GLboolean _IsPowerOfTwo; /**< Are all dimensions powers of two? */
-
- struct gl_texture_object *TexObject; /**< Pointer back to parent object */
-
- FetchTexelFuncC FetchTexelc; /**< GLchan texel fetch function pointer */
- FetchTexelFuncF FetchTexelf; /**< Float texel fetch function pointer */
-
- GLuint RowStride; /**< Padded width in units of texels */
- GLuint *ImageOffsets; /**< if 3D texture: array [Depth] of offsets to
- each 2D slice in 'Data', in texels */
- GLvoid *Data; /**< Image data, accessed via FetchTexel() */
-
- /**
- * \name For device driver:
- */
- /*@{*/
- void *DriverData; /**< Arbitrary device driver data */
- /*@}*/
-};
-
-
-/**
- * Indexes for cube map faces.
- */
-typedef enum
-{
- FACE_POS_X = 0,
- FACE_NEG_X = 1,
- FACE_POS_Y = 2,
- FACE_NEG_Y = 3,
- FACE_POS_Z = 4,
- FACE_NEG_Z = 5,
- MAX_FACES = 6
-} gl_face_index;
-
-
-/**
- * Texture object state. Contains the array of mipmap images, border color,
- * wrap modes, filter modes, shadow/texcompare state, and the per-texture
- * color palette.
- */
-struct gl_texture_object
-{
- _glthread_Mutex Mutex; /**< for thread safety */
- GLint RefCount; /**< reference count */
- GLuint Name; /**< the user-visible texture object ID */
- GLenum Target; /**< GL_TEXTURE_1D, GL_TEXTURE_2D, etc. */
- GLfloat Priority; /**< in [0,1] */
- union {
- GLfloat f[4];
- GLuint ui[4];
- GLint i[4];
- } BorderColor; /**< Interpreted according to texture format */
- GLenum WrapS; /**< S-axis texture image wrap mode */
- GLenum WrapT; /**< T-axis texture image wrap mode */
- GLenum WrapR; /**< R-axis texture image wrap mode */
- GLenum MinFilter; /**< minification filter */
- GLenum MagFilter; /**< magnification filter */
- GLfloat MinLod; /**< min lambda, OpenGL 1.2 */
- GLfloat MaxLod; /**< max lambda, OpenGL 1.2 */
- GLfloat LodBias; /**< OpenGL 1.4 */
- GLint BaseLevel; /**< min mipmap level, OpenGL 1.2 */
- GLint MaxLevel; /**< max mipmap level, OpenGL 1.2 */
- GLfloat MaxAnisotropy; /**< GL_EXT_texture_filter_anisotropic */
- GLenum CompareMode; /**< GL_ARB_shadow */
- GLenum CompareFunc; /**< GL_ARB_shadow */
- GLfloat CompareFailValue; /**< GL_ARB_shadow_ambient */
- GLenum DepthMode; /**< GL_ARB_depth_texture */
- GLint _MaxLevel; /**< actual max mipmap level (q in the spec) */
- GLfloat _MaxLambda; /**< = _MaxLevel - BaseLevel (q - b in spec) */
- GLint CropRect[4]; /**< GL_OES_draw_texture */
- GLenum Swizzle[4]; /**< GL_EXT_texture_swizzle */
- GLuint _Swizzle; /**< same as Swizzle, but SWIZZLE_* format */
- GLboolean GenerateMipmap; /**< GL_SGIS_generate_mipmap */
- GLboolean _Complete; /**< Is texture object complete? */
- GLboolean _RenderToTexture; /**< Any rendering to this texture? */
- GLboolean Purgeable; /**< Is the buffer purgeable under memory pressure? */
- GLenum sRGBDecode; /**< GL_DECODE_EXT or GL_SKIP_DECODE_EXT */
-
- /** Actual texture images, indexed by [cube face] and [mipmap level] */
- struct gl_texture_image *Image[MAX_FACES][MAX_TEXTURE_LEVELS];
-
- /** GL_EXT_paletted_texture */
- struct gl_color_table Palette;
-
- /**
- * \name For device driver.
- * Note: instead of attaching driver data to this pointer, it's preferable
- * to instead use this struct as a base class for your own texture object
- * class. Driver->NewTextureObject() can be used to implement the
- * allocation.
- */
- void *DriverData; /**< Arbitrary device driver data */
-};
-
-
-/** Up to four combiner sources are possible with GL_NV_texture_env_combine4 */
-#define MAX_COMBINER_TERMS 4
-
-
-/**
- * Texture combine environment state.
- */
-struct gl_tex_env_combine_state
-{
- GLenum ModeRGB; /**< GL_REPLACE, GL_DECAL, GL_ADD, etc. */
- GLenum ModeA; /**< GL_REPLACE, GL_DECAL, GL_ADD, etc. */
- /** Source terms: GL_PRIMARY_COLOR, GL_TEXTURE, etc */
- GLenum SourceRGB[MAX_COMBINER_TERMS];
- GLenum SourceA[MAX_COMBINER_TERMS];
- /** Source operands: GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, etc */
- GLenum OperandRGB[MAX_COMBINER_TERMS];
- GLenum OperandA[MAX_COMBINER_TERMS];
- GLuint ScaleShiftRGB; /**< 0, 1 or 2 */
- GLuint ScaleShiftA; /**< 0, 1 or 2 */
- GLuint _NumArgsRGB; /**< Number of inputs used for the RGB combiner */
- GLuint _NumArgsA; /**< Number of inputs used for the A combiner */
-};
-
-
-/**
- * Texture coord generation state.
- */
-struct gl_texgen
-{
- GLenum Mode; /**< GL_EYE_LINEAR, GL_SPHERE_MAP, etc */
- GLbitfield _ModeBit; /**< TEXGEN_x bit corresponding to Mode */
- GLfloat ObjectPlane[4];
- GLfloat EyePlane[4];
-};
-
-
-/**
- * Texture unit state. Contains enable flags, texture environment/function/
- * combiners, texgen state, pointers to current texture objects and
- * post-filter color tables.
- */
-struct gl_texture_unit
-{
- GLbitfield Enabled; /**< bitmask of TEXTURE_*_BIT flags */
- GLbitfield _ReallyEnabled; /**< 0 or exactly one of TEXTURE_*_BIT flags */
-
- GLenum EnvMode; /**< GL_MODULATE, GL_DECAL, GL_BLEND, etc. */
- GLfloat EnvColor[4];
-
- struct gl_texgen GenS;
- struct gl_texgen GenT;
- struct gl_texgen GenR;
- struct gl_texgen GenQ;
- GLbitfield TexGenEnabled; /**< Bitwise-OR of [STRQ]_BIT values */
- GLbitfield _GenFlags; /**< Bitwise-OR of Gen[STRQ]._ModeBit */
-
- GLfloat LodBias; /**< for biasing mipmap levels */
- GLenum BumpTarget;
- GLfloat RotMatrix[4]; /* 2x2 matrix */
-
- /**
- * \name GL_EXT_texture_env_combine
- */
- struct gl_tex_env_combine_state Combine;
-
- /**
- * Derived state based on \c EnvMode and the \c BaseFormat of the
- * currently enabled texture.
- */
- struct gl_tex_env_combine_state _EnvMode;
-
- /**
- * Currently enabled combiner state. This will point to either
- * \c Combine or \c _EnvMode.
- */
- struct gl_tex_env_combine_state *_CurrentCombine;
-
- /** Current texture object pointers */
- struct gl_texture_object *CurrentTex[NUM_TEXTURE_TARGETS];
-
- /** Points to highest priority, complete and enabled texture object */
- struct gl_texture_object *_Current;
-
- /** GL_SGI_texture_color_table */
- /*@{*/
- struct gl_color_table ColorTable;
- struct gl_color_table ProxyColorTable;
- GLboolean ColorTableEnabled;
- /*@}*/
-};
-
-
-/**
- * Texture attribute group (GL_TEXTURE_BIT).
- */
-struct gl_texture_attrib
-{
- GLuint CurrentUnit; /**< GL_ACTIVE_TEXTURE */
- struct gl_texture_unit Unit[MAX_COMBINED_TEXTURE_IMAGE_UNITS];
-
- struct gl_texture_object *ProxyTex[NUM_TEXTURE_TARGETS];
-
- /** GL_ARB_seamless_cubemap */
- GLboolean CubeMapSeamless;
-
- /** GL_EXT_shared_texture_palette */
- GLboolean SharedPalette;
- struct gl_color_table Palette;
-
- /** Texture units/samplers used by vertex or fragment texturing */
- GLbitfield _EnabledUnits;
-
- /** Texture coord units/sets used for fragment texturing */
- GLbitfield _EnabledCoordUnits;
-
- /** Texture coord units that have texgen enabled */
- GLbitfield _TexGenEnabled;
-
- /** Texture coord units that have non-identity matrices */
- GLbitfield _TexMatEnabled;
-
- /** Bitwise-OR of all Texture.Unit[i]._GenFlags */
- GLbitfield _GenFlags;
-};
-
-
-/**
- * Transformation attribute group (GL_TRANSFORM_BIT).
- */
-struct gl_transform_attrib
-{
- GLenum MatrixMode; /**< Matrix mode */
- GLfloat EyeUserPlane[MAX_CLIP_PLANES][4]; /**< User clip planes */
- GLfloat _ClipUserPlane[MAX_CLIP_PLANES][4]; /**< derived */
- GLbitfield ClipPlanesEnabled; /**< on/off bitmask */
- GLboolean Normalize; /**< Normalize all normals? */
- GLboolean RescaleNormals; /**< GL_EXT_rescale_normal */
- GLboolean RasterPositionUnclipped; /**< GL_IBM_rasterpos_clip */
- GLboolean DepthClamp; /**< GL_ARB_depth_clamp */
-
- GLfloat CullEyePos[4];
- GLfloat CullObjPos[4];
-};
-
-
-/**
- * Viewport attribute group (GL_VIEWPORT_BIT).
- */
-struct gl_viewport_attrib
-{
- GLint X, Y; /**< position */
- GLsizei Width, Height; /**< size */
- GLfloat Near, Far; /**< Depth buffer range */
- GLmatrix _WindowMap; /**< Mapping transformation as a matrix. */
-};
-
-
-/**
- * GL_ARB_vertex/pixel_buffer_object buffer object
- */
-struct gl_buffer_object
-{
- _glthread_Mutex Mutex;
- GLint RefCount;
- GLuint Name;
- GLenum Usage; /**< GL_STREAM_DRAW_ARB, GL_STREAM_READ_ARB, etc. */
- GLsizeiptrARB Size; /**< Size of buffer storage in bytes */
- GLubyte *Data; /**< Location of storage either in RAM or VRAM. */
- /** Fields describing a mapped buffer */
- /*@{*/
- GLbitfield AccessFlags; /**< Mask of GL_MAP_x_BIT flags */
- GLvoid *Pointer; /**< User-space address of mapping */
- GLintptr Offset; /**< Mapped offset */
- GLsizeiptr Length; /**< Mapped length */
- /*@}*/
- GLboolean Written; /**< Ever written to? (for debugging) */
- GLboolean Purgeable; /**< Is the buffer purgeable under memory pressure? */
-};
-
-
-/**
- * Client pixel packing/unpacking attributes
- */
-struct gl_pixelstore_attrib
-{
- GLint Alignment;
- GLint RowLength;
- GLint SkipPixels;
- GLint SkipRows;
- GLint ImageHeight;
- GLint SkipImages;
- GLboolean SwapBytes;
- GLboolean LsbFirst;
- GLboolean ClientStorage; /**< GL_APPLE_client_storage */
- GLboolean Invert; /**< GL_MESA_pack_invert */
- struct gl_buffer_object *BufferObj; /**< GL_ARB_pixel_buffer_object */
-};
-
-
-/**
- * Client vertex array attributes
- */
-struct gl_client_array
-{
- GLint Size; /**< components per element (1,2,3,4) */
- GLenum Type; /**< datatype: GL_FLOAT, GL_INT, etc */
- GLenum Format; /**< default: GL_RGBA, but may be GL_BGRA */
- GLsizei Stride; /**< user-specified stride */
- GLsizei StrideB; /**< actual stride in bytes */
- const GLubyte *Ptr; /**< Points to array data */
- GLboolean Enabled; /**< Enabled flag is a boolean */
- GLboolean Normalized; /**< GL_ARB_vertex_program */
- GLboolean Integer; /**< Integer-valued? */
- GLuint InstanceDivisor; /**< GL_ARB_instanced_arrays */
- GLuint _ElementSize; /**< size of each element in bytes */
-
- struct gl_buffer_object *BufferObj;/**< GL_ARB_vertex_buffer_object */
- GLuint _MaxElement; /**< max element index into array buffer + 1 */
-};
-
-
-/**
- * Collection of vertex arrays. Defined by the GL_APPLE_vertex_array_object
- * extension, but a nice encapsulation in any case.
- */
-struct gl_array_object
-{
- /** Name of the array object as received from glGenVertexArrayAPPLE. */
- GLuint Name;
-
- GLint RefCount;
- _glthread_Mutex Mutex;
- GLboolean VBOonly; /**< require all arrays to live in VBOs? */
-
- /** Conventional vertex arrays */
- /*@{*/
- struct gl_client_array Vertex;
- struct gl_client_array Weight;
- struct gl_client_array Normal;
- struct gl_client_array Color;
- struct gl_client_array SecondaryColor;
- struct gl_client_array FogCoord;
- struct gl_client_array Index;
- struct gl_client_array EdgeFlag;
- struct gl_client_array TexCoord[MAX_TEXTURE_COORD_UNITS];
- struct gl_client_array PointSize;
- /*@}*/
-
- /**
- * Generic arrays for vertex programs/shaders.
- * For NV vertex programs, these attributes alias and take priority
- * over the conventional attribs above. For ARB vertex programs and
- * GLSL vertex shaders, these attributes are separate.
- */
- struct gl_client_array VertexAttrib[MAX_VERTEX_GENERIC_ATTRIBS];
-
- /** Mask of _NEW_ARRAY_* values indicating which arrays are enabled */
- GLbitfield _Enabled;
-
- /**
- * Min of all enabled arrays' _MaxElement. When arrays reside inside VBOs
- * we can determine the max legal (in bounds) glDrawElements array index.
- */
- GLuint _MaxElement;
-};
-
-
-/**
- * Vertex array state
- */
-struct gl_array_attrib
-{
- /** Currently bound array object. See _mesa_BindVertexArrayAPPLE() */
- struct gl_array_object *ArrayObj;
-
- /** The default vertex array object */
- struct gl_array_object *DefaultArrayObj;
-
- /** Array objects (GL_ARB/APPLE_vertex_array_object) */
- struct _mesa_HashTable *Objects;
-
- GLint ActiveTexture; /**< Client Active Texture */
- GLuint LockFirst; /**< GL_EXT_compiled_vertex_array */
- GLuint LockCount; /**< GL_EXT_compiled_vertex_array */
-
- /** GL 3.1 (slightly different from GL_NV_primitive_restart) */
- GLboolean PrimitiveRestart;
- GLuint RestartIndex;
-
- GLbitfield NewState; /**< mask of _NEW_ARRAY_* values */
-
- /* GL_ARB_vertex_buffer_object */
- struct gl_buffer_object *ArrayBufferObj;
- struct gl_buffer_object *ElementArrayBufferObj;
-};
-
-
-/**
- * Feedback buffer state
- */
-struct gl_feedback
-{
- GLenum Type;
- GLbitfield _Mask; /**< FB_* bits */
- GLfloat *Buffer;
- GLuint BufferSize;
- GLuint Count;
-};
-
-
-/**
- * Selection buffer state
- */
-struct gl_selection
-{
- GLuint *Buffer; /**< selection buffer */
- GLuint BufferSize; /**< size of the selection buffer */
- GLuint BufferCount; /**< number of values in the selection buffer */
- GLuint Hits; /**< number of records in the selection buffer */
- GLuint NameStackDepth; /**< name stack depth */
- GLuint NameStack[MAX_NAME_STACK_DEPTH]; /**< name stack */
- GLboolean HitFlag; /**< hit flag */
- GLfloat HitMinZ; /**< minimum hit depth */
- GLfloat HitMaxZ; /**< maximum hit depth */
-};
-
-
-/**
- * 1-D Evaluator control points
- */
-struct gl_1d_map
-{
- GLuint Order; /**< Number of control points */
- GLfloat u1, u2, du; /**< u1, u2, 1.0/(u2-u1) */
- GLfloat *Points; /**< Points to contiguous control points */
-};
-
-
-/**
- * 2-D Evaluator control points
- */
-struct gl_2d_map
-{
- GLuint Uorder; /**< Number of control points in U dimension */
- GLuint Vorder; /**< Number of control points in V dimension */
- GLfloat u1, u2, du;
- GLfloat v1, v2, dv;
- GLfloat *Points; /**< Points to contiguous control points */
-};
-
-
-/**
- * All evaluator control point state
- */
-struct gl_evaluators
-{
- /**
- * \name 1-D maps
- */
- /*@{*/
- struct gl_1d_map Map1Vertex3;
- struct gl_1d_map Map1Vertex4;
- struct gl_1d_map Map1Index;
- struct gl_1d_map Map1Color4;
- struct gl_1d_map Map1Normal;
- struct gl_1d_map Map1Texture1;
- struct gl_1d_map Map1Texture2;
- struct gl_1d_map Map1Texture3;
- struct gl_1d_map Map1Texture4;
- struct gl_1d_map Map1Attrib[16]; /**< GL_NV_vertex_program */
- /*@}*/
-
- /**
- * \name 2-D maps
- */
- /*@{*/
- struct gl_2d_map Map2Vertex3;
- struct gl_2d_map Map2Vertex4;
- struct gl_2d_map Map2Index;
- struct gl_2d_map Map2Color4;
- struct gl_2d_map Map2Normal;
- struct gl_2d_map Map2Texture1;
- struct gl_2d_map Map2Texture2;
- struct gl_2d_map Map2Texture3;
- struct gl_2d_map Map2Texture4;
- struct gl_2d_map Map2Attrib[16]; /**< GL_NV_vertex_program */
- /*@}*/
-};
-
-
-/**
- * Names of the various vertex/fragment program register files, etc.
- *
- * NOTE: first four tokens must fit into 2 bits (see t_vb_arbprogram.c)
- * All values should fit in a 4-bit field.
- *
- * NOTE: PROGRAM_ENV_PARAM, PROGRAM_STATE_VAR, PROGRAM_NAMED_PARAM,
- * PROGRAM_CONSTANT, and PROGRAM_UNIFORM can all be considered to
- * be "uniform" variables since they can only be set outside glBegin/End.
- * They're also all stored in the same Parameters array.
- */
-typedef enum
-{
- PROGRAM_TEMPORARY, /**< machine->Temporary[] */
- PROGRAM_INPUT, /**< machine->Inputs[] */
- PROGRAM_OUTPUT, /**< machine->Outputs[] */
- PROGRAM_VARYING, /**< machine->Inputs[]/Outputs[] */
- PROGRAM_LOCAL_PARAM, /**< gl_program->LocalParams[] */
- PROGRAM_ENV_PARAM, /**< gl_program->Parameters[] */
- PROGRAM_STATE_VAR, /**< gl_program->Parameters[] */
- PROGRAM_NAMED_PARAM, /**< gl_program->Parameters[] */
- PROGRAM_CONSTANT, /**< gl_program->Parameters[] */
- PROGRAM_UNIFORM, /**< gl_program->Parameters[] */
- PROGRAM_WRITE_ONLY, /**< A dummy, write-only register */
- PROGRAM_ADDRESS, /**< machine->AddressReg */
- PROGRAM_SAMPLER, /**< for shader samplers, compile-time only */
- PROGRAM_SYSTEM_VALUE,/**< InstanceId, PrimitiveID, etc. */
- PROGRAM_UNDEFINED, /**< Invalid/TBD value */
- PROGRAM_FILE_MAX
-} gl_register_file;
-
-
-/**
- * If the register file is PROGRAM_SYSTEM_VALUE, the register index will be
- * one of these values.
- */
-typedef enum
-{
- SYSTEM_VALUE_FRONT_FACE, /**< Fragment shader only (not done yet) */
- SYSTEM_VALUE_INSTANCE_ID, /**< Vertex shader only */
- SYSTEM_VALUE_MAX /**< Number of values */
-} gl_system_value;
-
-
-/** Vertex and fragment instructions */
-struct prog_instruction;
-struct gl_program_parameter_list;
-struct gl_uniform_list;
-
-
-/**
- * Base class for any kind of program object
- */
-struct gl_program
-{
- GLuint Id;
- GLubyte *String; /**< Null-terminated program text */
- GLint RefCount;
- GLenum Target; /**< GL_VERTEX/FRAGMENT_PROGRAM_ARB, GL_FRAGMENT_PROGRAM_NV */
- GLenum Format; /**< String encoding format */
- GLboolean Resident;
-
- struct prog_instruction *Instructions;
-
- GLbitfield InputsRead; /**< Bitmask of which input regs are read */
- GLbitfield64 OutputsWritten; /**< Bitmask of which output regs are written */
- GLbitfield SystemValuesRead; /**< Bitmask of SYSTEM_VALUE_x inputs used */
- GLbitfield InputFlags[MAX_PROGRAM_INPUTS]; /**< PROG_PARAM_BIT_x flags */
- GLbitfield OutputFlags[MAX_PROGRAM_OUTPUTS]; /**< PROG_PARAM_BIT_x flags */
- GLbitfield TexturesUsed[MAX_TEXTURE_UNITS]; /**< TEXTURE_x_BIT bitmask */
- GLbitfield SamplersUsed; /**< Bitfield of which samplers are used */
- GLbitfield ShadowSamplers; /**< Texture units used for shadow sampling. */
-
-
- /** Named parameters, constants, etc. from program text */
- struct gl_program_parameter_list *Parameters;
- /** Numbered local parameters */
- GLfloat LocalParams[MAX_PROGRAM_LOCAL_PARAMS][4];
-
- /** Vertex/fragment shader varying vars */
- struct gl_program_parameter_list *Varying;
- /** Vertex program user-defined attributes */
- struct gl_program_parameter_list *Attributes;
-
- /** Map from sampler unit to texture unit (set by glUniform1i()) */
- GLubyte SamplerUnits[MAX_SAMPLERS];
- /** Which texture target is being sampled (TEXTURE_1D/2D/3D/etc_INDEX) */
- gl_texture_index SamplerTargets[MAX_SAMPLERS];
-
- /** Bitmask of which register files are read/written with indirect
- * addressing. Mask of (1 << PROGRAM_x) bits.
- */
- GLbitfield IndirectRegisterFiles;
-
- /** Logical counts */
- /*@{*/
- GLuint NumInstructions;
- GLuint NumTemporaries;
- GLuint NumParameters;
- GLuint NumAttributes;
- GLuint NumAddressRegs;
- GLuint NumAluInstructions;
- GLuint NumTexInstructions;
- GLuint NumTexIndirections;
- /*@}*/
- /** Native, actual h/w counts */
- /*@{*/
- GLuint NumNativeInstructions;
- GLuint NumNativeTemporaries;
- GLuint NumNativeParameters;
- GLuint NumNativeAttributes;
- GLuint NumNativeAddressRegs;
- GLuint NumNativeAluInstructions;
- GLuint NumNativeTexInstructions;
- GLuint NumNativeTexIndirections;
- /*@}*/
-};
-
-
-/** Vertex program object */
-struct gl_vertex_program
-{
- struct gl_program Base; /**< base class */
- GLboolean IsNVProgram; /**< is this a GL_NV_vertex_program program? */
- GLboolean IsPositionInvariant;
-};
-
-
-/** Geometry program object */
-struct gl_geometry_program
-{
- struct gl_program Base; /**< base class */
-
- GLint VerticesOut;
- GLenum InputType; /**< GL_POINTS, GL_LINES, GL_LINES_ADJACENCY_ARB,
- GL_TRIANGLES, or GL_TRIANGLES_ADJACENCY_ARB */
- GLenum OutputType; /**< GL_POINTS, GL_LINE_STRIP or GL_TRIANGLE_STRIP */
-};
-
-
-/** Fragment program object */
-struct gl_fragment_program
-{
- struct gl_program Base; /**< base class */
- GLenum FogOption;
- GLboolean UsesKill; /**< shader uses KIL instruction */
- GLboolean OriginUpperLeft;
- GLboolean PixelCenterInteger;
- enum gl_frag_depth_layout FragDepthLayout;
-};
-
-
-/**
- * State common to vertex and fragment programs.
- */
-struct gl_program_state
-{
- GLint ErrorPos; /* GL_PROGRAM_ERROR_POSITION_ARB/NV */
- const char *ErrorString; /* GL_PROGRAM_ERROR_STRING_ARB/NV */
-};
-
-
-/**
- * Context state for vertex programs.
- */
-struct gl_vertex_program_state
-{
- GLboolean Enabled; /**< User-set GL_VERTEX_PROGRAM_ARB/NV flag */
- GLboolean _Enabled; /**< Enabled and _valid_ user program? */
- GLboolean PointSizeEnabled; /**< GL_VERTEX_PROGRAM_POINT_SIZE_ARB/NV */
- GLboolean TwoSideEnabled; /**< GL_VERTEX_PROGRAM_TWO_SIDE_ARB/NV */
- struct gl_vertex_program *Current; /**< User-bound vertex program */
-
- /** Currently enabled and valid vertex program (including internal
- * programs, user-defined vertex programs and GLSL vertex shaders).
- * This is the program we must use when rendering.
- */
- struct gl_vertex_program *_Current;
-
- GLfloat Parameters[MAX_PROGRAM_ENV_PARAMS][4]; /**< Env params */
-
- /* For GL_NV_vertex_program only: */
- GLenum TrackMatrix[MAX_PROGRAM_ENV_PARAMS / 4];
- GLenum TrackMatrixTransform[MAX_PROGRAM_ENV_PARAMS / 4];
-
- /** Should fixed-function T&L be implemented with a vertex prog? */
- GLboolean _MaintainTnlProgram;
-
- /** Program to emulate fixed-function T&L (see above) */
- struct gl_vertex_program *_TnlProgram;
-
- /** Cache of fixed-function programs */
- struct gl_program_cache *Cache;
-
- GLboolean _Overriden;
-};
-
-
-/**
- * Context state for geometry programs.
- */
-struct gl_geometry_program_state
-{
- GLboolean Enabled; /**< GL_ARB_GEOMETRY_SHADER4 */
- GLboolean _Enabled; /**< Enabled and valid program? */
- struct gl_geometry_program *Current; /**< user-bound geometry program */
-
- /** Currently enabled and valid program (including internal programs
- * and compiled shader programs).
- */
- struct gl_geometry_program *_Current;
-
- GLfloat Parameters[MAX_PROGRAM_ENV_PARAMS][4]; /**< Env params */
-
- /** Cache of fixed-function programs */
- struct gl_program_cache *Cache;
-};
-
-/**
- * Context state for fragment programs.
- */
-struct gl_fragment_program_state
-{
- GLboolean Enabled; /**< User-set fragment program enable flag */
- GLboolean _Enabled; /**< Enabled and _valid_ user program? */
- struct gl_fragment_program *Current; /**< User-bound fragment program */
-
- /** Currently enabled and valid fragment program (including internal
- * programs, user-defined fragment programs and GLSL fragment shaders).
- * This is the program we must use when rendering.
- */
- struct gl_fragment_program *_Current;
-
- GLfloat Parameters[MAX_PROGRAM_ENV_PARAMS][4]; /**< Env params */
-
- /** Should fixed-function texturing be implemented with a fragment prog? */
- GLboolean _MaintainTexEnvProgram;
-
- /** Program to emulate fixed-function texture env/combine (see above) */
- struct gl_fragment_program *_TexEnvProgram;
-
- /** Cache of fixed-function programs */
- struct gl_program_cache *Cache;
-};
-
-
-/**
- * ATI_fragment_shader runtime state
- */
-#define ATI_FS_INPUT_PRIMARY 0
-#define ATI_FS_INPUT_SECONDARY 1
-
-struct atifs_instruction;
-struct atifs_setupinst;
-
-/**
- * ATI fragment shader
- */
-struct ati_fragment_shader
-{
- GLuint Id;
- GLint RefCount;
- struct atifs_instruction *Instructions[2];
- struct atifs_setupinst *SetupInst[2];
- GLfloat Constants[8][4];
- GLbitfield LocalConstDef; /**< Indicates which constants have been set */
- GLubyte numArithInstr[2];
- GLubyte regsAssigned[2];
- GLubyte NumPasses; /**< 1 or 2 */
- GLubyte cur_pass;
- GLubyte last_optype;
- GLboolean interpinp1;
- GLboolean isValid;
- GLuint swizzlerq;
-};
-
-/**
- * Context state for GL_ATI_fragment_shader
- */
-struct gl_ati_fragment_shader_state
-{
- GLboolean Enabled;
- GLboolean _Enabled; /**< enabled and valid shader? */
- GLboolean Compiling;
- GLfloat GlobalConstants[8][4];
- struct ati_fragment_shader *Current;
-};
-
-
-/**
- * Occlusion/timer query object.
- */
-struct gl_query_object
-{
- GLenum Target; /**< The query target, when active */
- GLuint Id; /**< hash table ID/name */
- GLuint64EXT Result; /**< the counter */
- GLboolean Active; /**< inside Begin/EndQuery */
- GLboolean Ready; /**< result is ready? */
-};
-
-
-/**
- * Context state for query objects.
- */
-struct gl_query_state
-{
- struct _mesa_HashTable *QueryObjects;
- struct gl_query_object *CurrentOcclusionObject; /* GL_ARB_occlusion_query */
- struct gl_query_object *CurrentTimerObject; /* GL_EXT_timer_query */
-
- /** GL_NV_conditional_render */
- struct gl_query_object *CondRenderQuery;
-
- /** GL_EXT_transform_feedback */
- struct gl_query_object *PrimitivesGenerated;
- struct gl_query_object *PrimitivesWritten;
-
- /** GL_ARB_timer_query */
- struct gl_query_object *TimeElapsed;
-
- GLenum CondRenderMode;
-};
-
-
-/** Sync object state */
-struct gl_sync_object {
- struct simple_node link;
- GLenum Type; /**< GL_SYNC_FENCE */
- GLuint Name; /**< Fence name */
- GLint RefCount; /**< Reference count */
- GLboolean DeletePending; /**< Object was deleted while there were still
- * live references (e.g., sync not yet finished)
- */
- GLenum SyncCondition;
- GLbitfield Flags; /**< Flags passed to glFenceSync */
- GLuint StatusFlag:1; /**< Has the sync object been signaled? */
-};
-
-
-/** Set by #pragma directives */
-struct gl_sl_pragmas
-{
- GLboolean IgnoreOptimize; /**< ignore #pragma optimize(on/off) ? */
- GLboolean IgnoreDebug; /**< ignore #pragma debug(on/off) ? */
- GLboolean Optimize; /**< defaults on */
- GLboolean Debug; /**< defaults off */
-};
-
-
-/**
- * A GLSL vertex or fragment shader object.
- */
-struct gl_shader
-{
- GLenum Type; /**< GL_FRAGMENT_SHADER || GL_VERTEX_SHADER || GL_GEOMETRY_SHADER_ARB (first field!) */
- GLuint Name; /**< AKA the handle */
- 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 */
- GLchar *InfoLog;
- struct gl_sl_pragmas Pragmas;
-
- unsigned Version; /**< GLSL version used for linking */
-
- struct exec_list *ir;
- struct glsl_symbol_table *symbols;
-
- /** Shaders containing built-in functions that are used for linking. */
- struct gl_shader *builtins_to_link[16];
- unsigned num_builtins_to_link;
-};
-
-
-/**
- * A GLSL program object.
- * Basically a linked collection of vertex and fragment shaders.
- */
-struct gl_shader_program
-{
- GLenum Type; /**< Always GL_SHADER_PROGRAM (internal token) */
- GLuint Name; /**< aka handle or ID */
- GLint RefCount; /**< Reference count */
- GLboolean DeletePending;
-
- GLuint NumShaders; /**< number of attached shaders */
- struct gl_shader **Shaders; /**< List of attached the shaders */
-
- /** User-defined attribute bindings (glBindAttribLocation) */
- struct gl_program_parameter_list *Attributes;
-
- /** Transform feedback varyings */
- struct {
- GLenum BufferMode;
- GLuint NumVarying;
- GLchar **VaryingNames; /**< Array [NumVarying] of char * */
- } TransformFeedback;
-
- /** Geometry shader state - copied into gl_geometry_program at link time */
- struct {
- GLint VerticesOut;
- GLenum InputType; /**< GL_POINTS, GL_LINES, GL_LINES_ADJACENCY_ARB,
- GL_TRIANGLES, or GL_TRIANGLES_ADJACENCY_ARB */
- GLenum OutputType; /**< GL_POINTS, GL_LINE_STRIP or GL_TRIANGLE_STRIP */
- } Geom;
-
- /* post-link info: */
- struct gl_vertex_program *VertexProgram; /**< Linked vertex program */
- struct gl_fragment_program *FragmentProgram; /**< Linked fragment prog */
- struct gl_geometry_program *GeometryProgram; /**< Linked geometry prog */
- struct gl_uniform_list *Uniforms;
- struct gl_program_parameter_list *Varying;
- GLboolean LinkStatus; /**< GL_LINK_STATUS */
- GLboolean Validated;
- GLboolean _Used; /**< Ever used for drawing? */
- GLchar *InfoLog;
-
- unsigned Version; /**< GLSL version used for linking */
-
- /**
- * Per-stage shaders resulting from the first stage of linking.
- *
- * Set of linked shaders for this program. The array is accessed using the
- * \c MESA_SHADER_* defines. Entries for non-existent stages will be
- * \c NULL.
- */
- struct gl_shader *_LinkedShaders[MESA_SHADER_TYPES];
-};
-
-
-#define GLSL_DUMP 0x1 /**< Dump shaders to stdout */
-#define GLSL_LOG 0x2 /**< Write shaders to files */
-#define GLSL_OPT 0x4 /**< Force optimizations (override pragmas) */
-#define GLSL_NO_OPT 0x8 /**< Force no optimizations (override pragmas) */
-#define GLSL_UNIFORMS 0x10 /**< Print glUniform calls */
-#define GLSL_NOP_VERT 0x20 /**< Force no-op vertex shaders */
-#define GLSL_NOP_FRAG 0x40 /**< Force no-op fragment shaders */
-#define GLSL_USE_PROG 0x80 /**< Log glUseProgram calls */
-
-
-/**
- * Context state for GLSL vertex/fragment shaders.
- */
-struct gl_shader_state
-{
- /**
- * Programs used for rendering
- *
- * There is a separate program set for each shader stage. If
- * GL_EXT_separate_shader_objects is not supported, each of these must point
- * to \c NULL or to the same program.
- */
- struct gl_shader_program *CurrentVertexProgram;
- struct gl_shader_program *CurrentGeometryProgram;
- struct gl_shader_program *CurrentFragmentProgram;
-
- /**
- * Program used by glUniform calls.
- *
- * Explicitly set by \c glUseProgram and \c glActiveProgramEXT.
- */
- struct gl_shader_program *ActiveProgram;
-
- void *MemPool;
-
- GLbitfield Flags; /**< Mask of GLSL_x flags */
-};
-
-/**
- * Compiler options for a single GLSL shaders type
- */
-struct gl_shader_compiler_options
-{
- /** Driver-selectable options: */
- GLboolean EmitCondCodes; /**< Use condition codes? */
- GLboolean EmitNVTempInitialization; /**< 0-fill NV temp registers */
- /**
- * Attempts to flatten all ir_if (OPCODE_IF) for GPUs that can't
- * support control flow.
- */
- GLboolean EmitNoIfs;
- GLboolean EmitNoLoops;
- GLboolean EmitNoFunctions;
- GLboolean EmitNoCont; /**< Emit CONT opcode? */
- GLboolean EmitNoMainReturn; /**< Emit CONT/RET opcodes? */
- GLboolean EmitNoNoise; /**< Emit NOISE opcodes? */
- GLboolean EmitNoPow; /**< Emit POW opcodes? */
-
- /**
- * \name Forms of indirect addressing the driver cannot do.
- */
- /*@{*/
- GLboolean EmitNoIndirectInput; /**< No indirect addressing of inputs */
- GLboolean EmitNoIndirectOutput; /**< No indirect addressing of outputs */
- GLboolean EmitNoIndirectTemp; /**< No indirect addressing of temps */
- GLboolean EmitNoIndirectUniform; /**< No indirect addressing of constants */
- /*@}*/
-
- GLuint MaxUnrollIterations;
-
- struct gl_sl_pragmas DefaultPragmas; /**< Default #pragma settings */
-};
-
-/**
- * Transform feedback object state
- */
-struct gl_transform_feedback_object
-{
- GLuint Name; /**< AKA the object ID */
- GLint RefCount;
- GLboolean Active; /**< Is transform feedback enabled? */
- GLboolean Paused; /**< Is transform feedback paused? */
-
- /** The feedback buffers */
- GLuint BufferNames[MAX_FEEDBACK_ATTRIBS];
- struct gl_buffer_object *Buffers[MAX_FEEDBACK_ATTRIBS];
-
- /** Start of feedback data in dest buffer */
- GLintptr Offset[MAX_FEEDBACK_ATTRIBS];
- /** Max data to put into dest buffer (in bytes) */
- GLsizeiptr Size[MAX_FEEDBACK_ATTRIBS];
-};
-
-
-/**
- * Context state for transform feedback.
- */
-struct gl_transform_feedback
-{
- GLenum Mode; /**< GL_POINTS, GL_LINES or GL_TRIANGLES */
-
- GLboolean RasterDiscard; /**< GL_RASTERIZER_DISCARD */
-
- /** The general binding point (GL_TRANSFORM_FEEDBACK_BUFFER) */
- struct gl_buffer_object *CurrentBuffer;
-
- /** The table of all transform feedback objects */
- struct _mesa_HashTable *Objects;
-
- /** The current xform-fb object (GL_TRANSFORM_FEEDBACK_BINDING) */
- struct gl_transform_feedback_object *CurrentObject;
-
- /** The default xform-fb object (Name==0) */
- struct gl_transform_feedback_object *DefaultObject;
-};
-
-
-
-/**
- * State which can be shared by multiple contexts:
- */
-struct gl_shared_state
-{
- _glthread_Mutex Mutex; /**< for thread safety */
- GLint RefCount; /**< Reference count */
- struct _mesa_HashTable *DisplayList; /**< Display lists hash table */
- struct _mesa_HashTable *TexObjects; /**< Texture objects hash table */
-
- /** Default texture objects (shared by all texture units) */
- struct gl_texture_object *DefaultTex[NUM_TEXTURE_TARGETS];
-
- /** Fallback texture used when a bound texture is incomplete */
- struct gl_texture_object *FallbackTex;
-
- /**
- * \name Thread safety and statechange notification for texture
- * objects.
- *
- * \todo Improve the granularity of locking.
- */
- /*@{*/
- _glthread_Mutex TexMutex; /**< texobj thread safety */
- GLuint TextureStateStamp; /**< state notification for shared tex */
- /*@}*/
-
- /** Default buffer object for vertex arrays that aren't in VBOs */
- struct gl_buffer_object *NullBufferObj;
-
- /**
- * \name Vertex/geometry/fragment programs
- */
- /*@{*/
- struct _mesa_HashTable *Programs; /**< All vertex/fragment programs */
- struct gl_vertex_program *DefaultVertexProgram;
- struct gl_fragment_program *DefaultFragmentProgram;
- struct gl_geometry_program *DefaultGeometryProgram;
- /*@}*/
-
- /* GL_ATI_fragment_shader */
- struct _mesa_HashTable *ATIShaders;
- struct ati_fragment_shader *DefaultFragmentShader;
-
- struct _mesa_HashTable *BufferObjects;
-
- /** Table of both gl_shader and gl_shader_program objects */
- struct _mesa_HashTable *ShaderObjects;
-
- /* GL_EXT_framebuffer_object */
- struct _mesa_HashTable *RenderBuffers;
- struct _mesa_HashTable *FrameBuffers;
-
- /* GL_ARB_sync */
- struct simple_node SyncObjects;
-
- void *DriverData; /**< Device driver shared state */
-};
-
-
-
-
-/**
- * A renderbuffer stores colors or depth values or stencil values.
- * A framebuffer object will have a collection of these.
- * Data are read/written to the buffer with a handful of Get/Put functions.
- *
- * Instances of this object are allocated with the Driver's NewRenderbuffer
- * hook. Drivers will likely wrap this class inside a driver-specific
- * class to simulate inheritance.
- */
-struct gl_renderbuffer
-{
-#define RB_MAGIC 0xaabbccdd
- int Magic; /** XXX TEMPORARY DEBUG INFO */
- _glthread_Mutex Mutex; /**< for thread safety */
- GLuint ClassID; /**< Useful for drivers */
- GLuint Name;
- GLint RefCount;
- GLuint Width, Height;
- GLboolean Purgeable; /**< Is the buffer purgeable under memory pressure? */
-
- 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 */
-
- GLubyte NumSamples;
-
- GLenum DataType; /**< Type of values passed to the Get/Put functions */
- GLvoid *Data; /**< This may not be used by some kinds of RBs */
-
- /* Used to wrap one renderbuffer around another: */
- struct gl_renderbuffer *Wrapped;
-
- /* Delete this renderbuffer */
- void (*Delete)(struct gl_renderbuffer *rb);
-
- /* Allocate new storage for this renderbuffer */
- GLboolean (*AllocStorage)(struct gl_context *ctx, struct gl_renderbuffer *rb,
- GLenum internalFormat,
- GLuint width, GLuint height);
-
- /* Lock/Unlock are called before/after calling the Get/Put functions.
- * Not sure this is the right place for these yet.
- void (*Lock)(struct gl_context *ctx, struct gl_renderbuffer *rb);
- void (*Unlock)(struct gl_context *ctx, struct gl_renderbuffer *rb);
- */
-
- /* Return a pointer to the element/pixel at (x,y).
- * Should return NULL if the buffer memory can't be directly addressed.
- */
- void *(*GetPointer)(struct gl_context *ctx, struct gl_renderbuffer *rb,
- GLint x, GLint y);
-
- /* Get/Read a row of values.
- * The values will be of format _BaseFormat and type DataType.
- */
- void (*GetRow)(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
- GLint x, GLint y, void *values);
-
- /* Get/Read values at arbitrary locations.
- * The values will be of format _BaseFormat and type DataType.
- */
- void (*GetValues)(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
- const GLint x[], const GLint y[], void *values);
-
- /* Put/Write a row of values.
- * The values will be of format _BaseFormat and type DataType.
- */
- void (*PutRow)(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
- GLint x, GLint y, const void *values, const GLubyte *mask);
-
- /* Put/Write a row of RGB values. This is a special-case routine that's
- * only used for RGBA renderbuffers when the source data is GL_RGB. That's
- * a common case for glDrawPixels and some triangle routines.
- * The values will be of format GL_RGB and type DataType.
- */
- void (*PutRowRGB)(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
- GLint x, GLint y, const void *values, const GLubyte *mask);
-
-
- /* Put/Write a row of identical values.
- * The values will be of format _BaseFormat and type DataType.
- */
- void (*PutMonoRow)(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
- GLint x, GLint y, const void *value, const GLubyte *mask);
-
- /* Put/Write values at arbitrary locations.
- * The values will be of format _BaseFormat and type DataType.
- */
- void (*PutValues)(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
- const GLint x[], const GLint y[], const void *values,
- const GLubyte *mask);
- /* Put/Write identical values at arbitrary locations.
- * The values will be of format _BaseFormat and type DataType.
- */
- void (*PutMonoValues)(struct gl_context *ctx, struct gl_renderbuffer *rb,
- GLuint count, const GLint x[], const GLint y[],
- const void *value, const GLubyte *mask);
-};
-
-
-/**
- * A renderbuffer attachment points to either a texture object (and specifies
- * a mipmap level, cube face or 3D texture slice) or points to a renderbuffer.
- */
-struct gl_renderbuffer_attachment
-{
- GLenum Type; /**< \c GL_NONE or \c GL_TEXTURE or \c GL_RENDERBUFFER_EXT */
- GLboolean Complete;
-
- /**
- * If \c Type is \c GL_RENDERBUFFER_EXT, this stores a pointer to the
- * application supplied renderbuffer object.
- */
- struct gl_renderbuffer *Renderbuffer;
-
- /**
- * If \c Type is \c GL_TEXTURE, this stores a pointer to the application
- * supplied texture object.
- */
- struct gl_texture_object *Texture;
- GLuint TextureLevel; /**< Attached mipmap level. */
- GLuint CubeMapFace; /**< 0 .. 5, for cube map textures. */
- GLuint Zoffset; /**< Slice for 3D textures, or layer for both 1D
- * and 2D array textures */
-};
-
-
-/**
- * A framebuffer is a collection of renderbuffers (color, depth, stencil, etc).
- * In C++ terms, think of this as a base class from which device drivers
- * will make derived classes.
- */
-struct gl_framebuffer
-{
- _glthread_Mutex Mutex; /**< for thread safety */
- /**
- * If zero, this is a window system framebuffer. If non-zero, this
- * is a FBO framebuffer; note that for some devices (i.e. those with
- * a natural pixel coordinate system for FBOs that differs from the
- * OpenGL/Mesa coordinate system), this means that the viewport,
- * polygon face orientation, and polygon stipple will have to be inverted.
- */
- GLuint Name;
-
- GLint RefCount;
- GLboolean DeletePending;
-
- /**
- * The framebuffer's visual. Immutable if this is a window system buffer.
- * Computed from attachments if user-made FBO.
- */
- struct gl_config Visual;
-
- GLboolean Initialized;
-
- GLuint Width, Height; /**< size of frame buffer in pixels */
-
- /** \name Drawing bounds (Intersection of buffer size and scissor box) */
- /*@{*/
- GLint _Xmin, _Xmax; /**< inclusive */
- GLint _Ymin, _Ymax; /**< exclusive */
- /*@}*/
-
- /** \name Derived Z buffer stuff */
- /*@{*/
- GLuint _DepthMax; /**< Max depth buffer value */
- GLfloat _DepthMaxF; /**< Float max depth buffer value */
- GLfloat _MRD; /**< minimum resolvable difference in Z values */
- /*@}*/
-
- /** One of the GL_FRAMEBUFFER_(IN)COMPLETE_* tokens */
- GLenum _Status;
-
- /** Integer color values */
- GLboolean _IntegerColor;
-
- /** Array of all renderbuffer attachments, indexed by BUFFER_* tokens. */
- struct gl_renderbuffer_attachment Attachment[BUFFER_COUNT];
-
- /* In unextended OpenGL these vars are part of the GL_COLOR_BUFFER
- * attribute group and GL_PIXEL attribute group, respectively.
- */
- GLenum ColorDrawBuffer[MAX_DRAW_BUFFERS];
- GLenum ColorReadBuffer;
-
- /** Computed from ColorDraw/ReadBuffer above */
- GLuint _NumColorDrawBuffers;
- GLint _ColorDrawBufferIndexes[MAX_DRAW_BUFFERS]; /**< BUFFER_x or -1 */
- GLint _ColorReadBufferIndex; /* -1 = None */
- struct gl_renderbuffer *_ColorDrawBuffers[MAX_DRAW_BUFFERS];
- struct gl_renderbuffer *_ColorReadBuffer;
-
- /** The Actual depth/stencil buffers to use. May be wrappers around the
- * depth/stencil buffers attached above. */
- struct gl_renderbuffer *_DepthBuffer;
- struct gl_renderbuffer *_StencilBuffer;
-
- /** Delete this framebuffer */
- void (*Delete)(struct gl_framebuffer *fb);
-};
-
-
-/**
- * Precision info for shader datatypes. See glGetShaderPrecisionFormat().
- */
-struct gl_precision
-{
- GLushort RangeMin; /**< min value exponent */
- GLushort RangeMax; /**< max value exponent */
- GLushort Precision; /**< number of mantissa bits */
-};
-
-
-/**
- * Limits for vertex and fragment programs/shaders.
- */
-struct gl_program_constants
-{
- /* logical limits */
- GLuint MaxInstructions;
- GLuint MaxAluInstructions;
- GLuint MaxTexInstructions;
- GLuint MaxTexIndirections;
- GLuint MaxAttribs;
- GLuint MaxTemps;
- GLuint MaxAddressRegs;
- GLuint MaxParameters;
- GLuint MaxLocalParams;
- GLuint MaxEnvParams;
- /* native/hardware limits */
- GLuint MaxNativeInstructions;
- GLuint MaxNativeAluInstructions;
- GLuint MaxNativeTexInstructions;
- GLuint MaxNativeTexIndirections;
- GLuint MaxNativeAttribs;
- GLuint MaxNativeTemps;
- GLuint MaxNativeAddressRegs;
- GLuint MaxNativeParameters;
- /* For shaders */
- GLuint MaxUniformComponents;
- /* GL_ARB_geometry_shader4 */
- GLuint MaxGeometryTextureImageUnits;
- GLuint MaxGeometryVaryingComponents;
- GLuint MaxVertexVaryingComponents;
- GLuint MaxGeometryUniformComponents;
- GLuint MaxGeometryOutputVertices;
- GLuint MaxGeometryTotalOutputComponents;
- /* ES 2.0 and GL_ARB_ES2_compatibility */
- struct gl_precision LowFloat, MediumFloat, HighFloat;
- struct gl_precision LowInt, MediumInt, HighInt;
-};
-
-
-/**
- * Constants which may be overridden by device driver during context creation
- * but are never changed after that.
- */
-struct gl_constants
-{
- GLint MaxTextureMbytes; /**< Max memory per image, in MB */
- GLint MaxTextureLevels; /**< Max mipmap levels. */
- GLint Max3DTextureLevels; /**< Max mipmap levels for 3D textures */
- GLint MaxCubeTextureLevels; /**< Max mipmap levels for cube textures */
- GLint MaxArrayTextureLayers; /**< Max layers in array textures */
- GLint MaxTextureRectSize; /**< Max rectangle texture size, in pixes */
- GLuint MaxTextureCoordUnits;
- GLuint MaxTextureImageUnits;
- GLuint MaxVertexTextureImageUnits;
- GLuint MaxCombinedTextureImageUnits;
- GLuint MaxTextureUnits; /**< = MIN(CoordUnits, ImageUnits) */
- GLfloat MaxTextureMaxAnisotropy; /**< GL_EXT_texture_filter_anisotropic */
- GLfloat MaxTextureLodBias; /**< GL_EXT_texture_lod_bias */
-
- GLuint MaxArrayLockSize;
-
- GLint SubPixelBits;
-
- GLfloat MinPointSize, MaxPointSize; /**< aliased */
- GLfloat MinPointSizeAA, MaxPointSizeAA; /**< antialiased */
- GLfloat PointSizeGranularity;
- GLfloat MinLineWidth, MaxLineWidth; /**< aliased */
- GLfloat MinLineWidthAA, MaxLineWidthAA; /**< antialiased */
- GLfloat LineWidthGranularity;
-
- GLuint MaxColorTableSize;
-
- GLuint MaxClipPlanes;
- GLuint MaxLights;
- GLfloat MaxShininess; /**< GL_NV_light_max_exponent */
- GLfloat MaxSpotExponent; /**< GL_NV_light_max_exponent */
-
- GLuint MaxViewportWidth, MaxViewportHeight;
-
- struct gl_program_constants VertexProgram; /**< GL_ARB_vertex_program */
- struct gl_program_constants FragmentProgram; /**< GL_ARB_fragment_program */
- struct gl_program_constants GeometryProgram; /**< GL_ARB_geometry_shader4 */
- GLuint MaxProgramMatrices;
- GLuint MaxProgramMatrixStackDepth;
-
- /** vertex array / buffer object bounds checking */
- GLboolean CheckArrayBounds;
-
- GLuint MaxDrawBuffers; /**< GL_ARB_draw_buffers */
-
- GLuint MaxColorAttachments; /**< GL_EXT_framebuffer_object */
- GLuint MaxRenderbufferSize; /**< GL_EXT_framebuffer_object */
- GLuint MaxSamples; /**< GL_ARB_framebuffer_object */
-
- GLuint MaxVarying; /**< Number of float[4] varying parameters */
-
- GLuint GLSLVersion; /**< GLSL version supported (ex: 120 = 1.20) */
-
- /** Which texture units support GL_ATI_envmap_bumpmap as targets */
- GLbitfield SupportedBumpUnits;
-
- /**
- * Maximum amount of time, measured in nanseconds, that the server can wait.
- */
- GLuint64 MaxServerWaitTimeout;
-
- /** GL_EXT_provoking_vertex */
- GLboolean QuadsFollowProvokingVertexConvention;
-
- /** OpenGL version 3.0 */
- GLbitfield ContextFlags; /**< Ex: GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT */
-
- /** OpenGL version 3.2 */
- GLbitfield ProfileMask; /**< Mask of CONTEXT_x_PROFILE_BIT */
-
- /** GL_EXT_transform_feedback */
- GLuint MaxTransformFeedbackSeparateAttribs;
- GLuint MaxTransformFeedbackSeparateComponents;
- GLuint MaxTransformFeedbackInterleavedComponents;
-
- /** GL_EXT_gpu_shader4 */
- GLint MinProgramTexelOffset, MaxProgramTexelOffset;
-
- /* GL_EXT_framebuffer_sRGB */
- GLboolean sRGBCapable; /* can enable sRGB blend/update on FBOs */
-};
-
-
-/**
- * Enable flag for each OpenGL extension. Different device drivers will
- * enable different extensions at runtime.
- */
-struct gl_extensions
-{
- GLboolean dummy; /* don't remove this! */
- GLboolean dummy_true; /* Set true by _mesa_init_extensions(). */
- GLboolean dummy_false; /* Set false by _mesa_init_extensions(). */
- GLboolean ARB_ES2_compatibility;
- GLboolean ARB_blend_func_extended;
- GLboolean ARB_copy_buffer;
- GLboolean ARB_depth_buffer_float;
- GLboolean ARB_depth_clamp;
- GLboolean ARB_depth_texture;
- GLboolean ARB_draw_buffers;
- GLboolean ARB_draw_buffers_blend;
- GLboolean ARB_draw_elements_base_vertex;
- GLboolean ARB_draw_instanced;
- GLboolean ARB_fragment_coord_conventions;
- GLboolean ARB_fragment_program;
- GLboolean ARB_fragment_program_shadow;
- GLboolean ARB_fragment_shader;
- GLboolean ARB_framebuffer_object;
- GLboolean ARB_explicit_attrib_location;
- GLboolean ARB_geometry_shader4;
- GLboolean ARB_half_float_pixel;
- GLboolean ARB_half_float_vertex;
- GLboolean ARB_instanced_arrays;
- GLboolean ARB_map_buffer_range;
- GLboolean ARB_multisample;
- GLboolean ARB_multitexture;
- GLboolean ARB_occlusion_query;
- GLboolean ARB_occlusion_query2;
- GLboolean ARB_point_sprite;
- GLboolean ARB_sampler_objects;
- GLboolean ARB_seamless_cube_map;
- GLboolean ARB_shader_objects;
- GLboolean ARB_shader_stencil_export;
- GLboolean ARB_shading_language_100;
- GLboolean ARB_shadow;
- GLboolean ARB_shadow_ambient;
- GLboolean ARB_sync;
- GLboolean ARB_texture_border_clamp;
- GLboolean ARB_texture_buffer_object;
- GLboolean ARB_texture_compression;
- GLboolean ARB_texture_compression_rgtc;
- GLboolean ARB_texture_cube_map;
- GLboolean ARB_texture_env_combine;
- GLboolean ARB_texture_env_crossbar;
- GLboolean ARB_texture_env_dot3;
- GLboolean ARB_texture_float;
- GLboolean ARB_texture_mirrored_repeat;
- GLboolean ARB_texture_multisample;
- GLboolean ARB_texture_non_power_of_two;
- GLboolean ARB_texture_rg;
- GLboolean ARB_texture_rgb10_a2ui;
- GLboolean ARB_timer_query;
- GLboolean ARB_transform_feedback2;
- GLboolean ARB_transpose_matrix;
- GLboolean ARB_uniform_buffer_object;
- GLboolean ARB_vertex_array_object;
- GLboolean ARB_vertex_buffer_object;
- GLboolean ARB_vertex_program;
- GLboolean ARB_vertex_shader;
- GLboolean ARB_vertex_type_2_10_10_10_rev;
- GLboolean ARB_window_pos;
- GLboolean EXT_abgr;
- GLboolean EXT_bgra;
- GLboolean EXT_blend_color;
- GLboolean EXT_blend_equation_separate;
- GLboolean EXT_blend_func_separate;
- GLboolean EXT_blend_logic_op;
- GLboolean EXT_blend_minmax;
- GLboolean EXT_blend_subtract;
- GLboolean EXT_clip_volume_hint;
- GLboolean EXT_compiled_vertex_array;
- GLboolean EXT_copy_texture;
- GLboolean EXT_depth_bounds_test;
- GLboolean EXT_draw_buffers2;
- GLboolean EXT_draw_range_elements;
- GLboolean EXT_fog_coord;
- GLboolean EXT_framebuffer_blit;
- GLboolean EXT_framebuffer_multisample;
- GLboolean EXT_framebuffer_object;
- GLboolean EXT_framebuffer_sRGB;
- GLboolean EXT_gpu_program_parameters;
- GLboolean EXT_gpu_shader4;
- GLboolean EXT_multi_draw_arrays;
- GLboolean EXT_paletted_texture;
- GLboolean EXT_packed_depth_stencil;
- GLboolean EXT_packed_float;
- GLboolean EXT_packed_pixels;
- GLboolean EXT_pixel_buffer_object;
- GLboolean EXT_point_parameters;
- GLboolean EXT_polygon_offset;
- GLboolean EXT_provoking_vertex;
- GLboolean EXT_rescale_normal;
- GLboolean EXT_shadow_funcs;
- GLboolean EXT_secondary_color;
- GLboolean EXT_separate_shader_objects;
- GLboolean EXT_separate_specular_color;
- GLboolean EXT_shared_texture_palette;
- GLboolean EXT_stencil_wrap;
- GLboolean EXT_stencil_two_side;
- GLboolean EXT_subtexture;
- GLboolean EXT_texture;
- GLboolean EXT_texture_object;
- GLboolean EXT_texture3D;
- GLboolean EXT_texture_array;
- GLboolean EXT_texture_compression_s3tc;
- GLboolean EXT_texture_env_add;
- GLboolean EXT_texture_env_combine;
- GLboolean EXT_texture_env_dot3;
- GLboolean EXT_texture_filter_anisotropic;
- GLboolean EXT_texture_integer;
- GLboolean EXT_texture_lod_bias;
- GLboolean EXT_texture_mirror_clamp;
- GLboolean EXT_texture_shared_exponent;
- GLboolean EXT_texture_sRGB;
- GLboolean EXT_texture_sRGB_decode;
- GLboolean EXT_texture_swizzle;
- GLboolean EXT_transform_feedback;
- GLboolean EXT_timer_query;
- GLboolean EXT_vertex_array;
- GLboolean EXT_vertex_array_bgra;
- 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;
- GLboolean APPLE_object_purgeable;
- GLboolean ATI_envmap_bumpmap;
- GLboolean ATI_texture_mirror_once;
- GLboolean ATI_texture_env_combine3;
- GLboolean ATI_fragment_shader;
- GLboolean ATI_separate_stencil;
- GLboolean IBM_rasterpos_clip;
- GLboolean IBM_multimode_draw_arrays;
- GLboolean MESA_pack_invert;
- GLboolean MESA_resize_buffers;
- GLboolean MESA_ycbcr_texture;
- GLboolean MESA_texture_array;
- GLboolean MESA_texture_signed_rgba;
- GLboolean NV_blend_square;
- GLboolean NV_conditional_render;
- GLboolean NV_fragment_program;
- GLboolean NV_fragment_program_option;
- GLboolean NV_light_max_exponent;
- GLboolean NV_point_sprite;
- GLboolean NV_primitive_restart;
- GLboolean NV_texgen_reflection;
- GLboolean NV_texture_env_combine4;
- GLboolean NV_texture_rectangle;
- GLboolean NV_vertex_program;
- GLboolean NV_vertex_program1_1;
- GLboolean OES_read_format;
- GLboolean SGI_texture_color_table;
- GLboolean SGIS_generate_mipmap;
- GLboolean SGIS_texture_edge_clamp;
- GLboolean SGIS_texture_lod;
- GLboolean TDFX_texture_compression_FXT1;
- GLboolean S3_s3tc;
- GLboolean OES_EGL_image;
- GLboolean OES_draw_texture;
- GLboolean EXT_texture_format_BGRA8888;
- GLboolean extension_sentinel;
- /** The extension string */
- const GLubyte *String;
- /** Number of supported extensions */
- GLuint Count;
-};
-
-
-/**
- * A stack of matrices (projection, modelview, color, texture, etc).
- */
-struct gl_matrix_stack
-{
- GLmatrix *Top; /**< points into Stack */
- GLmatrix *Stack; /**< array [MaxDepth] of GLmatrix */
- GLuint Depth; /**< 0 <= Depth < MaxDepth */
- GLuint MaxDepth; /**< size of Stack[] array */
- GLuint DirtyFlag; /**< _NEW_MODELVIEW or _NEW_PROJECTION, for example */
-};
-
-
-/**
- * \name Bits for image transfer operations
- * \sa __struct gl_contextRec::ImageTransferState.
- */
-/*@{*/
-#define IMAGE_SCALE_BIAS_BIT 0x1
-#define IMAGE_SHIFT_OFFSET_BIT 0x2
-#define IMAGE_MAP_COLOR_BIT 0x4
-#define IMAGE_CLAMP_BIT 0x800
-
-
-/** Pixel Transfer ops */
-#define IMAGE_BITS (IMAGE_SCALE_BIAS_BIT | \
- IMAGE_SHIFT_OFFSET_BIT | \
- IMAGE_MAP_COLOR_BIT)
-
-/**
- * \name Bits to indicate what state has changed.
- */
-/*@{*/
-#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
-/*@}*/
-
-
-/**
- * \name Bits to track array state changes
- *
- * Also used to summarize array enabled.
- */
-/*@{*/
-#define _NEW_ARRAY_VERTEX VERT_BIT_POS
-#define _NEW_ARRAY_WEIGHT VERT_BIT_WEIGHT
-#define _NEW_ARRAY_NORMAL VERT_BIT_NORMAL
-#define _NEW_ARRAY_COLOR0 VERT_BIT_COLOR0
-#define _NEW_ARRAY_COLOR1 VERT_BIT_COLOR1
-#define _NEW_ARRAY_FOGCOORD VERT_BIT_FOG
-#define _NEW_ARRAY_INDEX VERT_BIT_COLOR_INDEX
-#define _NEW_ARRAY_EDGEFLAG VERT_BIT_EDGEFLAG
-#define _NEW_ARRAY_POINT_SIZE VERT_BIT_COLOR_INDEX /* aliased */
-#define _NEW_ARRAY_TEXCOORD_0 VERT_BIT_TEX0
-#define _NEW_ARRAY_TEXCOORD_1 VERT_BIT_TEX1
-#define _NEW_ARRAY_TEXCOORD_2 VERT_BIT_TEX2
-#define _NEW_ARRAY_TEXCOORD_3 VERT_BIT_TEX3
-#define _NEW_ARRAY_TEXCOORD_4 VERT_BIT_TEX4
-#define _NEW_ARRAY_TEXCOORD_5 VERT_BIT_TEX5
-#define _NEW_ARRAY_TEXCOORD_6 VERT_BIT_TEX6
-#define _NEW_ARRAY_TEXCOORD_7 VERT_BIT_TEX7
-#define _NEW_ARRAY_ATTRIB_0 VERT_BIT_GENERIC0 /* start at bit 16 */
-#define _NEW_ARRAY_ALL 0xffffffff
-
-
-#define _NEW_ARRAY_TEXCOORD(i) (_NEW_ARRAY_TEXCOORD_0 << (i))
-#define _NEW_ARRAY_ATTRIB(i) (_NEW_ARRAY_ATTRIB_0 << (i))
-/*@}*/
-
-
-
-/**
- * \name A bunch of flags that we think might be useful to drivers.
- *
- * Set in the __struct gl_contextRec::_TriangleCaps bitfield.
- */
-/*@{*/
-#define DD_FLATSHADE 0x1
-#define DD_SEPARATE_SPECULAR 0x2
-#define DD_TRI_CULL_FRONT_BACK 0x4 /* special case on some hw */
-#define DD_TRI_LIGHT_TWOSIDE 0x8
-#define DD_TRI_UNFILLED 0x10
-#define DD_TRI_SMOOTH 0x20
-#define DD_TRI_STIPPLE 0x40
-#define DD_TRI_OFFSET 0x80
-#define DD_LINE_SMOOTH 0x100
-#define DD_LINE_STIPPLE 0x200
-#define DD_POINT_SMOOTH 0x400
-#define DD_POINT_ATTEN 0x800
-#define DD_TRI_TWOSTENCIL 0x1000
-/*@}*/
-
-
-/**
- * \name Define the state changes under which each of these bits might change
- */
-/*@{*/
-#define _DD_NEW_FLATSHADE _NEW_LIGHT
-#define _DD_NEW_SEPARATE_SPECULAR (_NEW_LIGHT | _NEW_FOG | _NEW_PROGRAM)
-#define _DD_NEW_TRI_CULL_FRONT_BACK _NEW_POLYGON
-#define _DD_NEW_TRI_LIGHT_TWOSIDE _NEW_LIGHT
-#define _DD_NEW_TRI_UNFILLED _NEW_POLYGON
-#define _DD_NEW_TRI_SMOOTH _NEW_POLYGON
-#define _DD_NEW_TRI_STIPPLE _NEW_POLYGON
-#define _DD_NEW_TRI_OFFSET _NEW_POLYGON
-#define _DD_NEW_LINE_SMOOTH _NEW_LINE
-#define _DD_NEW_LINE_STIPPLE _NEW_LINE
-#define _DD_NEW_LINE_WIDTH _NEW_LINE
-#define _DD_NEW_POINT_SMOOTH _NEW_POINT
-#define _DD_NEW_POINT_SIZE _NEW_POINT
-#define _DD_NEW_POINT_ATTEN _NEW_POINT
-/*@}*/
-
-
-/**
- * Composite state flags
- */
-/*@{*/
-#define _MESA_NEW_NEED_EYE_COORDS (_NEW_LIGHT | \
- _NEW_TEXTURE | \
- _NEW_POINT | \
- _NEW_PROGRAM | \
- _NEW_MODELVIEW)
-
-#define _MESA_NEW_NEED_NORMALS (_NEW_LIGHT | \
- _NEW_TEXTURE)
-
-#define _MESA_NEW_TRANSFER_STATE (_NEW_PIXEL)
-/*@}*/
-
-
-
-
-/* This has to be included here. */
-#include "dd.h"
-
-
-/**
- * Display list flags.
- * Strictly this is a tnl-private concept, but it doesn't seem
- * worthwhile adding a tnl private structure just to hold this one bit
- * of information:
- */
-#define DLIST_DANGLING_REFS 0x1
-
-
-/** Opaque declaration of display list payload data type */
-union gl_dlist_node;
-
-
-/**
- * Provide a location where information about a display list can be
- * collected. Could be extended with driverPrivate structures,
- * etc. in the future.
- */
-struct gl_display_list
-{
- GLuint Name;
- GLbitfield Flags; /**< DLIST_x flags */
- /** The dlist commands are in a linked list of nodes */
- union gl_dlist_node *Head;
-};
-
-
-/**
- * State used during display list compilation and execution.
- */
-struct gl_dlist_state
-{
- GLuint CallDepth; /**< Current recursion calling depth */
-
- struct gl_display_list *CurrentList; /**< List currently being compiled */
- union gl_dlist_node *CurrentBlock; /**< Pointer to current block of nodes */
- GLuint CurrentPos; /**< Index into current block of nodes */
-
- GLvertexformat ListVtxfmt;
-
- GLubyte ActiveAttribSize[VERT_ATTRIB_MAX];
- GLfloat CurrentAttrib[VERT_ATTRIB_MAX][4];
-
- GLubyte ActiveMaterialSize[MAT_ATTRIB_MAX];
- GLfloat CurrentMaterial[MAT_ATTRIB_MAX][4];
-
- GLubyte ActiveIndex;
- GLfloat CurrentIndex;
-
- GLubyte ActiveEdgeFlag;
- GLboolean CurrentEdgeFlag;
-
- struct {
- /* State known to have been set by the currently-compiling display
- * list. Used to eliminate some redundant state changes.
- */
- GLenum ShadeModel;
- } Current;
-};
-
-
-/**
- * Enum for the OpenGL APIs we know about and may support.
- */
-typedef enum
-{
- API_OPENGL,
- API_OPENGLES,
- API_OPENGLES2
-} gl_api;
-
-
-/**
- * Mesa rendering context.
- *
- * This is the central context data structure for Mesa. Almost all
- * OpenGL state is contained in this structure.
- * Think of this as a base class from which device drivers will derive
- * sub classes.
- *
- * The struct gl_context typedef names this structure.
- */
-struct gl_context
-{
- /** State possibly shared with other contexts in the address space */
- struct gl_shared_state *Shared;
-
- /** \name API function pointer tables */
- /*@{*/
- gl_api API;
- struct _glapi_table *Save; /**< Display list save functions */
- struct _glapi_table *Exec; /**< Execute functions */
- struct _glapi_table *CurrentDispatch; /**< == Save or Exec !! */
- /*@}*/
-
- struct gl_config Visual;
- struct gl_framebuffer *DrawBuffer; /**< buffer for writing */
- struct gl_framebuffer *ReadBuffer; /**< buffer for reading */
- struct gl_framebuffer *WinSysDrawBuffer; /**< set with MakeCurrent */
- struct gl_framebuffer *WinSysReadBuffer; /**< set with MakeCurrent */
-
- /**
- * Device driver function pointer table
- */
- struct dd_function_table Driver;
-
- void *DriverCtx; /**< Points to device driver context/state */
-
- /** Core/Driver constants */
- struct gl_constants Const;
-
- /** \name The various 4x4 matrix stacks */
- /*@{*/
- struct gl_matrix_stack ModelviewMatrixStack;
- struct gl_matrix_stack ProjectionMatrixStack;
- struct gl_matrix_stack TextureMatrixStack[MAX_TEXTURE_UNITS];
- struct gl_matrix_stack ProgramMatrixStack[MAX_PROGRAM_MATRICES];
- struct gl_matrix_stack *CurrentStack; /**< Points to one of the above stacks */
- /*@}*/
-
- /** Combined modelview and projection matrix */
- GLmatrix _ModelProjectMatrix;
-
- /** \name Display lists */
- struct gl_dlist_state ListState;
-
- GLboolean ExecuteFlag; /**< Execute GL commands? */
- GLboolean CompileFlag; /**< Compile GL commands into display list? */
-
- /** Extension information */
- struct gl_extensions Extensions;
-
- /** Version info */
- GLuint VersionMajor, VersionMinor;
- char *VersionString;
-
- /** \name State attribute stack (for glPush/PopAttrib) */
- /*@{*/
- GLuint AttribStackDepth;
- struct gl_attrib_node *AttribStack[MAX_ATTRIB_STACK_DEPTH];
- /*@}*/
-
- /** \name Renderer attribute groups
- *
- * We define a struct for each attribute group to make pushing and popping
- * attributes easy. Also it's a good organization.
- */
- /*@{*/
- struct gl_accum_attrib Accum; /**< Accum buffer attributes */
- struct gl_colorbuffer_attrib Color; /**< Color buffer attributes */
- struct gl_current_attrib Current; /**< Current attributes */
- struct gl_depthbuffer_attrib Depth; /**< Depth buffer attributes */
- struct gl_eval_attrib Eval; /**< Eval attributes */
- struct gl_fog_attrib Fog; /**< Fog attributes */
- struct gl_hint_attrib Hint; /**< Hint attributes */
- struct gl_light_attrib Light; /**< Light attributes */
- struct gl_line_attrib Line; /**< Line attributes */
- struct gl_list_attrib List; /**< List attributes */
- struct gl_multisample_attrib Multisample;
- struct gl_pixel_attrib Pixel; /**< Pixel attributes */
- struct gl_point_attrib Point; /**< Point attributes */
- struct gl_polygon_attrib Polygon; /**< Polygon attributes */
- GLuint PolygonStipple[32]; /**< Polygon stipple */
- struct gl_scissor_attrib Scissor; /**< Scissor attributes */
- struct gl_stencil_attrib Stencil; /**< Stencil buffer attributes */
- struct gl_texture_attrib Texture; /**< Texture attributes */
- struct gl_transform_attrib Transform; /**< Transformation attributes */
- struct gl_viewport_attrib Viewport; /**< Viewport attributes */
- /*@}*/
-
- /** \name Client attribute stack */
- /*@{*/
- GLuint ClientAttribStackDepth;
- struct gl_attrib_node *ClientAttribStack[MAX_CLIENT_ATTRIB_STACK_DEPTH];
- /*@}*/
-
- /** \name Client attribute groups */
- /*@{*/
- struct gl_array_attrib Array; /**< Vertex arrays */
- struct gl_pixelstore_attrib Pack; /**< Pixel packing */
- struct gl_pixelstore_attrib Unpack; /**< Pixel unpacking */
- struct gl_pixelstore_attrib DefaultPacking; /**< Default params */
- /*@}*/
-
- /** \name Other assorted state (not pushed/popped on attribute stack) */
- /*@{*/
- struct gl_pixelmaps PixelMaps;
-
- struct gl_evaluators EvalMap; /**< All evaluators */
- struct gl_feedback Feedback; /**< Feedback */
- struct gl_selection Select; /**< Selection */
-
- struct gl_program_state Program; /**< general program state */
- struct gl_vertex_program_state VertexProgram;
- struct gl_fragment_program_state FragmentProgram;
- struct gl_geometry_program_state GeometryProgram;
- struct gl_ati_fragment_shader_state ATIFragmentShader;
-
- struct gl_shader_state Shader; /**< GLSL shader object state */
- struct gl_shader_compiler_options ShaderCompilerOptions[MESA_SHADER_TYPES];
-
- struct gl_query_state Query; /**< occlusion, timer queries */
-
- struct gl_transform_feedback TransformFeedback;
-
- struct gl_buffer_object *CopyReadBuffer; /**< GL_ARB_copy_buffer */
- struct gl_buffer_object *CopyWriteBuffer; /**< GL_ARB_copy_buffer */
- /*@}*/
-
- struct gl_meta_state *Meta; /**< for "meta" operations */
-
- /* GL_EXT_framebuffer_object */
- struct gl_renderbuffer *CurrentRenderbuffer;
-
- GLenum ErrorValue; /**< Last error code */
-
- /**
- * Recognize and silence repeated error debug messages in buggy apps.
- */
- const char *ErrorDebugFmtString;
- GLuint ErrorDebugCount;
-
- GLenum RenderMode; /**< either GL_RENDER, GL_SELECT, GL_FEEDBACK */
- GLbitfield NewState; /**< bitwise-or of _NEW_* flags */
-
- GLboolean ViewportInitialized; /**< has viewport size been initialized? */
-
- GLbitfield varying_vp_inputs; /**< mask of VERT_BIT_* flags */
-
- /** \name Derived state */
- /*@{*/
- /** Bitwise-or of DD_* flags. Note that this bitfield may be used before
- * state validation so they need to always be current.
- */
- GLbitfield _TriangleCaps;
- GLbitfield _ImageTransferState;/**< bitwise-or of IMAGE_*_BIT flags */
- GLfloat _EyeZDir[3];
- GLfloat _ModelViewInvScale;
- GLboolean _NeedEyeCoords;
- GLboolean _ForceEyeCoords;
-
- GLuint TextureStateTimestamp; /**< detect changes to shared state */
-
- struct gl_shine_tab *_ShineTable[2]; /**< Active shine tables */
- struct gl_shine_tab *_ShineTabList; /**< MRU list of inactive shine tables */
- /**@}*/
-
- struct gl_list_extensions *ListExt; /**< driver dlist extensions */
-
- /** \name For debugging/development only */
- /*@{*/
- GLboolean FirstTimeCurrent;
- /*@}*/
-
- /** Dither disable via MESA_NO_DITHER env var */
- GLboolean NoDither;
-
- /** software compression/decompression supported or not */
- GLboolean Mesa_DXTn;
-
- GLboolean TextureFormatSupported[MESA_FORMAT_COUNT];
-
- /**
- * Use dp4 (rather than mul/mad) instructions for position
- * transformation?
- */
- GLboolean mvp_with_dp4;
-
- /**
- * \name Hooks for module contexts.
- *
- * These will eventually live in the driver or elsewhere.
- */
- /*@{*/
- void *swrast_context;
- void *swsetup_context;
- void *swtnl_context;
- void *swtnl_im;
- struct st_context *st;
- void *aelt_context;
- /*@}*/
-};
-
-
-#ifdef DEBUG
-extern int MESA_VERBOSE;
-extern int MESA_DEBUG_FLAGS;
-# define MESA_FUNCTION __FUNCTION__
-#else
-# define MESA_VERBOSE 0
-# define MESA_DEBUG_FLAGS 0
-# define MESA_FUNCTION "a function"
-# ifndef NDEBUG
-# define NDEBUG
-# endif
-#endif
-
-
-/** The MESA_VERBOSE var is a bitmask of these flags */
-enum _verbose
-{
- VERBOSE_VARRAY = 0x0001,
- VERBOSE_TEXTURE = 0x0002,
- VERBOSE_MATERIAL = 0x0004,
- VERBOSE_PIPELINE = 0x0008,
- VERBOSE_DRIVER = 0x0010,
- VERBOSE_STATE = 0x0020,
- VERBOSE_API = 0x0040,
- VERBOSE_DISPLAY_LIST = 0x0100,
- VERBOSE_LIGHTING = 0x0200,
- VERBOSE_PRIMS = 0x0400,
- VERBOSE_VERTS = 0x0800,
- VERBOSE_DISASSEM = 0x1000,
- VERBOSE_DRAW = 0x2000,
- VERBOSE_SWAPBUFFERS = 0x4000
-};
-
-
-/** The MESA_DEBUG_FLAGS var is a bitmask of these flags */
-enum _debug
-{
- DEBUG_ALWAYS_FLUSH = 0x1
-};
-
-
-
-#endif /* MTYPES_H */
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.7
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 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, 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.
+ */
+
+/**
+ * \file mtypes.h
+ * Main Mesa data structures.
+ *
+ * Please try to mark derived values with a leading underscore ('_').
+ */
+
+#ifndef MTYPES_H
+#define MTYPES_H
+
+
+#include "main/glheader.h"
+#include "main/config.h"
+#include "main/mfeatures.h"
+#include "glapi/glapi.h"
+#include "math/m_matrix.h" /* GLmatrix */
+#include "main/simple_list.h" /* struct simple_node */
+#include "main/formats.h" /* MESA_FORMAT_COUNT */
+
+
+/**
+ * Color channel data type.
+ */
+#if CHAN_BITS == 8
+ typedef GLubyte GLchan;
+#define CHAN_MAX 255
+#define CHAN_MAXF 255.0F
+#define CHAN_TYPE GL_UNSIGNED_BYTE
+#elif CHAN_BITS == 16
+ typedef GLushort GLchan;
+#define CHAN_MAX 65535
+#define CHAN_MAXF 65535.0F
+#define CHAN_TYPE GL_UNSIGNED_SHORT
+#elif CHAN_BITS == 32
+ typedef GLfloat GLchan;
+#define CHAN_MAX 1.0
+#define CHAN_MAXF 1.0F
+#define CHAN_TYPE GL_FLOAT
+#else
+#error "illegal number of color channel bits"
+#endif
+
+
+/**
+ * Stencil buffer data type.
+ */
+#if STENCIL_BITS==8
+ typedef GLubyte GLstencil;
+#elif STENCIL_BITS==16
+ typedef GLushort GLstencil;
+#else
+# error "illegal number of stencil bits"
+#endif
+
+
+/**
+ * \name 64-bit extension of GLbitfield.
+ */
+/*@{*/
+typedef GLuint64 GLbitfield64;
+
+/** Set a single bit */
+#define BITFIELD64_BIT(b) (1ULL << (b))
+
+
+/**
+ * \name Some forward type declarations
+ */
+/*@{*/
+struct _mesa_HashTable;
+struct gl_attrib_node;
+struct gl_list_extensions;
+struct gl_meta_state;
+struct gl_pixelstore_attrib;
+struct gl_program_cache;
+struct gl_texture_format;
+struct gl_texture_image;
+struct gl_texture_object;
+struct gl_context;
+struct st_context;
+/*@}*/
+
+
+/** Extra draw modes beyond GL_POINTS, GL_TRIANGLE_FAN, etc */
+#define PRIM_OUTSIDE_BEGIN_END (GL_POLYGON+1)
+#define PRIM_INSIDE_UNKNOWN_PRIM (GL_POLYGON+2)
+#define PRIM_UNKNOWN (GL_POLYGON+3)
+
+
+/**
+ * Shader stages. Note that these will become 5 with tessellation.
+ * These MUST have the same values as gallium's PIPE_SHADER_*
+ */
+typedef enum
+{
+ MESA_SHADER_VERTEX = 0,
+ MESA_SHADER_FRAGMENT = 1,
+ MESA_SHADER_GEOMETRY = 2,
+ MESA_SHADER_TYPES = 3
+} gl_shader_type;
+
+
+
+/**
+ * Indexes for vertex program attributes.
+ * GL_NV_vertex_program aliases generic attributes over the conventional
+ * attributes. In GL_ARB_vertex_program shader the aliasing is optional.
+ * In GL_ARB_vertex_shader / OpenGL 2.0 the aliasing is disallowed (the
+ * generic attributes are distinct/separate).
+ */
+typedef enum
+{
+ VERT_ATTRIB_POS = 0,
+ VERT_ATTRIB_WEIGHT = 1,
+ VERT_ATTRIB_NORMAL = 2,
+ VERT_ATTRIB_COLOR0 = 3,
+ VERT_ATTRIB_COLOR1 = 4,
+ VERT_ATTRIB_FOG = 5,
+ VERT_ATTRIB_COLOR_INDEX = 6,
+ VERT_ATTRIB_POINT_SIZE = 6, /*alias*/
+ VERT_ATTRIB_EDGEFLAG = 7,
+ VERT_ATTRIB_TEX0 = 8,
+ VERT_ATTRIB_TEX1 = 9,
+ VERT_ATTRIB_TEX2 = 10,
+ VERT_ATTRIB_TEX3 = 11,
+ VERT_ATTRIB_TEX4 = 12,
+ VERT_ATTRIB_TEX5 = 13,
+ VERT_ATTRIB_TEX6 = 14,
+ VERT_ATTRIB_TEX7 = 15,
+ VERT_ATTRIB_GENERIC0 = 16,
+ VERT_ATTRIB_GENERIC1 = 17,
+ VERT_ATTRIB_GENERIC2 = 18,
+ VERT_ATTRIB_GENERIC3 = 19,
+ VERT_ATTRIB_GENERIC4 = 20,
+ VERT_ATTRIB_GENERIC5 = 21,
+ VERT_ATTRIB_GENERIC6 = 22,
+ VERT_ATTRIB_GENERIC7 = 23,
+ VERT_ATTRIB_GENERIC8 = 24,
+ VERT_ATTRIB_GENERIC9 = 25,
+ VERT_ATTRIB_GENERIC10 = 26,
+ VERT_ATTRIB_GENERIC11 = 27,
+ VERT_ATTRIB_GENERIC12 = 28,
+ VERT_ATTRIB_GENERIC13 = 29,
+ VERT_ATTRIB_GENERIC14 = 30,
+ VERT_ATTRIB_GENERIC15 = 31,
+ VERT_ATTRIB_MAX = 32
+} gl_vert_attrib;
+
+/**
+ * Bitflags for vertex attributes.
+ * These are used in bitfields in many places.
+ */
+/*@{*/
+#define VERT_BIT_POS (1 << VERT_ATTRIB_POS)
+#define VERT_BIT_WEIGHT (1 << VERT_ATTRIB_WEIGHT)
+#define VERT_BIT_NORMAL (1 << VERT_ATTRIB_NORMAL)
+#define VERT_BIT_COLOR0 (1 << VERT_ATTRIB_COLOR0)
+#define VERT_BIT_COLOR1 (1 << VERT_ATTRIB_COLOR1)
+#define VERT_BIT_FOG (1 << VERT_ATTRIB_FOG)
+#define VERT_BIT_COLOR_INDEX (1 << VERT_ATTRIB_COLOR_INDEX)
+#define VERT_BIT_EDGEFLAG (1 << VERT_ATTRIB_EDGEFLAG)
+#define VERT_BIT_TEX0 (1 << VERT_ATTRIB_TEX0)
+#define VERT_BIT_TEX1 (1 << VERT_ATTRIB_TEX1)
+#define VERT_BIT_TEX2 (1 << VERT_ATTRIB_TEX2)
+#define VERT_BIT_TEX3 (1 << VERT_ATTRIB_TEX3)
+#define VERT_BIT_TEX4 (1 << VERT_ATTRIB_TEX4)
+#define VERT_BIT_TEX5 (1 << VERT_ATTRIB_TEX5)
+#define VERT_BIT_TEX6 (1 << VERT_ATTRIB_TEX6)
+#define VERT_BIT_TEX7 (1 << VERT_ATTRIB_TEX7)
+#define VERT_BIT_GENERIC0 (1 << VERT_ATTRIB_GENERIC0)
+#define VERT_BIT_GENERIC1 (1 << VERT_ATTRIB_GENERIC1)
+#define VERT_BIT_GENERIC2 (1 << VERT_ATTRIB_GENERIC2)
+#define VERT_BIT_GENERIC3 (1 << VERT_ATTRIB_GENERIC3)
+#define VERT_BIT_GENERIC4 (1 << VERT_ATTRIB_GENERIC4)
+#define VERT_BIT_GENERIC5 (1 << VERT_ATTRIB_GENERIC5)
+#define VERT_BIT_GENERIC6 (1 << VERT_ATTRIB_GENERIC6)
+#define VERT_BIT_GENERIC7 (1 << VERT_ATTRIB_GENERIC7)
+#define VERT_BIT_GENERIC8 (1 << VERT_ATTRIB_GENERIC8)
+#define VERT_BIT_GENERIC9 (1 << VERT_ATTRIB_GENERIC9)
+#define VERT_BIT_GENERIC10 (1 << VERT_ATTRIB_GENERIC10)
+#define VERT_BIT_GENERIC11 (1 << VERT_ATTRIB_GENERIC11)
+#define VERT_BIT_GENERIC12 (1 << VERT_ATTRIB_GENERIC12)
+#define VERT_BIT_GENERIC13 (1 << VERT_ATTRIB_GENERIC13)
+#define VERT_BIT_GENERIC14 (1 << VERT_ATTRIB_GENERIC14)
+#define VERT_BIT_GENERIC15 (1 << VERT_ATTRIB_GENERIC15)
+
+#define VERT_BIT_TEX(u) (1 << (VERT_ATTRIB_TEX0 + (u)))
+#define VERT_BIT_GENERIC(g) (1 << (VERT_ATTRIB_GENERIC0 + (g)))
+/*@}*/
+
+
+/**
+ * Indexes for vertex program result attributes
+ */
+typedef enum
+{
+ VERT_RESULT_HPOS = 0,
+ VERT_RESULT_COL0 = 1,
+ VERT_RESULT_COL1 = 2,
+ VERT_RESULT_FOGC = 3,
+ VERT_RESULT_TEX0 = 4,
+ VERT_RESULT_TEX1 = 5,
+ VERT_RESULT_TEX2 = 6,
+ VERT_RESULT_TEX3 = 7,
+ VERT_RESULT_TEX4 = 8,
+ VERT_RESULT_TEX5 = 9,
+ VERT_RESULT_TEX6 = 10,
+ VERT_RESULT_TEX7 = 11,
+ VERT_RESULT_PSIZ = 12,
+ VERT_RESULT_BFC0 = 13,
+ VERT_RESULT_BFC1 = 14,
+ VERT_RESULT_EDGE = 15,
+ VERT_RESULT_VAR0 = 16, /**< shader varying */
+ VERT_RESULT_MAX = (VERT_RESULT_VAR0 + MAX_VARYING)
+} gl_vert_result;
+
+
+/*********************************************/
+
+/**
+ * Indexes for geometry program attributes.
+ */
+typedef enum
+{
+ GEOM_ATTRIB_POSITION = 0,
+ GEOM_ATTRIB_COLOR0 = 1,
+ GEOM_ATTRIB_COLOR1 = 2,
+ GEOM_ATTRIB_SECONDARY_COLOR0 = 3,
+ GEOM_ATTRIB_SECONDARY_COLOR1 = 4,
+ GEOM_ATTRIB_FOG_FRAG_COORD = 5,
+ GEOM_ATTRIB_POINT_SIZE = 6,
+ GEOM_ATTRIB_CLIP_VERTEX = 7,
+ GEOM_ATTRIB_PRIMITIVE_ID = 8,
+ GEOM_ATTRIB_TEX_COORD = 9,
+
+ GEOM_ATTRIB_VAR0 = 16,
+ GEOM_ATTRIB_MAX = (GEOM_ATTRIB_VAR0 + MAX_VARYING)
+} gl_geom_attrib;
+
+/**
+ * Bitflags for geometry attributes.
+ * These are used in bitfields in many places.
+ */
+/*@{*/
+#define GEOM_BIT_COLOR0 (1 << GEOM_ATTRIB_COLOR0)
+#define GEOM_BIT_COLOR1 (1 << GEOM_ATTRIB_COLOR1)
+#define GEOM_BIT_SCOLOR0 (1 << GEOM_ATTRIB_SECONDARY_COLOR0)
+#define GEOM_BIT_SCOLOR1 (1 << GEOM_ATTRIB_SECONDARY_COLOR1)
+#define GEOM_BIT_TEX_COORD (1 << GEOM_ATTRIB_TEX_COORD)
+#define GEOM_BIT_FOG_COORD (1 << GEOM_ATTRIB_FOG_FRAG_COORD)
+#define GEOM_BIT_POSITION (1 << GEOM_ATTRIB_POSITION)
+#define GEOM_BIT_POINT_SIDE (1 << GEOM_ATTRIB_POINT_SIZE)
+#define GEOM_BIT_CLIP_VERTEX (1 << GEOM_ATTRIB_CLIP_VERTEX)
+#define GEOM_BIT_PRIM_ID (1 << GEOM_ATTRIB_PRIMITIVE_ID)
+#define GEOM_BIT_VAR0 (1 << GEOM_ATTRIB_VAR0)
+
+#define GEOM_BIT_VAR(g) (1 << (GEOM_BIT_VAR0 + (g)))
+/*@}*/
+
+
+/**
+ * Indexes for geometry program result attributes
+ */
+typedef enum
+{
+ GEOM_RESULT_POS = 0,
+ GEOM_RESULT_COL0 = 1,
+ GEOM_RESULT_COL1 = 2,
+ GEOM_RESULT_SCOL0 = 3,
+ GEOM_RESULT_SCOL1 = 4,
+ GEOM_RESULT_FOGC = 5,
+ GEOM_RESULT_TEX0 = 6,
+ GEOM_RESULT_TEX1 = 7,
+ GEOM_RESULT_TEX2 = 8,
+ GEOM_RESULT_TEX3 = 9,
+ GEOM_RESULT_TEX4 = 10,
+ GEOM_RESULT_TEX5 = 11,
+ GEOM_RESULT_TEX6 = 12,
+ GEOM_RESULT_TEX7 = 13,
+ GEOM_RESULT_PSIZ = 14,
+ GEOM_RESULT_CLPV = 15,
+ GEOM_RESULT_PRID = 16,
+ GEOM_RESULT_LAYR = 17,
+ GEOM_RESULT_VAR0 = 18, /**< shader varying, should really be 16 */
+ /* ### we need to -2 because var0 is 18 instead 16 like in the others */
+ GEOM_RESULT_MAX = (GEOM_RESULT_VAR0 + MAX_VARYING - 2)
+} gl_geom_result;
+
+
+/**
+ * Indexes for fragment program input attributes.
+ */
+typedef enum
+{
+ FRAG_ATTRIB_WPOS = 0,
+ FRAG_ATTRIB_COL0 = 1,
+ FRAG_ATTRIB_COL1 = 2,
+ FRAG_ATTRIB_FOGC = 3,
+ FRAG_ATTRIB_TEX0 = 4,
+ FRAG_ATTRIB_TEX1 = 5,
+ FRAG_ATTRIB_TEX2 = 6,
+ FRAG_ATTRIB_TEX3 = 7,
+ FRAG_ATTRIB_TEX4 = 8,
+ FRAG_ATTRIB_TEX5 = 9,
+ FRAG_ATTRIB_TEX6 = 10,
+ FRAG_ATTRIB_TEX7 = 11,
+ FRAG_ATTRIB_FACE = 12, /**< front/back face */
+ FRAG_ATTRIB_PNTC = 13, /**< sprite/point coord */
+ FRAG_ATTRIB_VAR0 = 14, /**< shader varying */
+ FRAG_ATTRIB_MAX = (FRAG_ATTRIB_VAR0 + MAX_VARYING)
+} gl_frag_attrib;
+
+/**
+ * Bitflags for fragment program input attributes.
+ */
+/*@{*/
+#define FRAG_BIT_WPOS (1 << FRAG_ATTRIB_WPOS)
+#define FRAG_BIT_COL0 (1 << FRAG_ATTRIB_COL0)
+#define FRAG_BIT_COL1 (1 << FRAG_ATTRIB_COL1)
+#define FRAG_BIT_FOGC (1 << FRAG_ATTRIB_FOGC)
+#define FRAG_BIT_FACE (1 << FRAG_ATTRIB_FACE)
+#define FRAG_BIT_PNTC (1 << FRAG_ATTRIB_PNTC)
+#define FRAG_BIT_TEX0 (1 << FRAG_ATTRIB_TEX0)
+#define FRAG_BIT_TEX1 (1 << FRAG_ATTRIB_TEX1)
+#define FRAG_BIT_TEX2 (1 << FRAG_ATTRIB_TEX2)
+#define FRAG_BIT_TEX3 (1 << FRAG_ATTRIB_TEX3)
+#define FRAG_BIT_TEX4 (1 << FRAG_ATTRIB_TEX4)
+#define FRAG_BIT_TEX5 (1 << FRAG_ATTRIB_TEX5)
+#define FRAG_BIT_TEX6 (1 << FRAG_ATTRIB_TEX6)
+#define FRAG_BIT_TEX7 (1 << FRAG_ATTRIB_TEX7)
+#define FRAG_BIT_VAR0 (1 << FRAG_ATTRIB_VAR0)
+
+#define FRAG_BIT_TEX(U) (FRAG_BIT_TEX0 << (U))
+#define FRAG_BIT_VAR(V) (FRAG_BIT_VAR0 << (V))
+
+#define FRAG_BITS_TEX_ANY (FRAG_BIT_TEX0| \
+ FRAG_BIT_TEX1| \
+ FRAG_BIT_TEX2| \
+ FRAG_BIT_TEX3| \
+ FRAG_BIT_TEX4| \
+ FRAG_BIT_TEX5| \
+ FRAG_BIT_TEX6| \
+ FRAG_BIT_TEX7)
+/*@}*/
+
+
+/**
+ * Fragment program results
+ */
+typedef enum
+{
+ FRAG_RESULT_DEPTH = 0,
+ FRAG_RESULT_STENCIL = 1,
+ FRAG_RESULT_COLOR = 2,
+ FRAG_RESULT_DATA0 = 3,
+ FRAG_RESULT_MAX = (FRAG_RESULT_DATA0 + MAX_DRAW_BUFFERS)
+} gl_frag_result;
+
+
+/**
+ * Indexes for all renderbuffers
+ */
+typedef enum
+{
+ /* the four standard color buffers */
+ BUFFER_FRONT_LEFT,
+ BUFFER_BACK_LEFT,
+ BUFFER_FRONT_RIGHT,
+ BUFFER_BACK_RIGHT,
+ BUFFER_DEPTH,
+ BUFFER_STENCIL,
+ BUFFER_ACCUM,
+ /* optional aux buffer */
+ BUFFER_AUX0,
+ /* generic renderbuffers */
+ BUFFER_COLOR0,
+ BUFFER_COLOR1,
+ BUFFER_COLOR2,
+ BUFFER_COLOR3,
+ BUFFER_COLOR4,
+ BUFFER_COLOR5,
+ BUFFER_COLOR6,
+ BUFFER_COLOR7,
+ BUFFER_COUNT
+} gl_buffer_index;
+
+/**
+ * Bit flags for all renderbuffers
+ */
+#define BUFFER_BIT_FRONT_LEFT (1 << BUFFER_FRONT_LEFT)
+#define BUFFER_BIT_BACK_LEFT (1 << BUFFER_BACK_LEFT)
+#define BUFFER_BIT_FRONT_RIGHT (1 << BUFFER_FRONT_RIGHT)
+#define BUFFER_BIT_BACK_RIGHT (1 << BUFFER_BACK_RIGHT)
+#define BUFFER_BIT_AUX0 (1 << BUFFER_AUX0)
+#define BUFFER_BIT_AUX1 (1 << BUFFER_AUX1)
+#define BUFFER_BIT_AUX2 (1 << BUFFER_AUX2)
+#define BUFFER_BIT_AUX3 (1 << BUFFER_AUX3)
+#define BUFFER_BIT_DEPTH (1 << BUFFER_DEPTH)
+#define BUFFER_BIT_STENCIL (1 << BUFFER_STENCIL)
+#define BUFFER_BIT_ACCUM (1 << BUFFER_ACCUM)
+#define BUFFER_BIT_COLOR0 (1 << BUFFER_COLOR0)
+#define BUFFER_BIT_COLOR1 (1 << BUFFER_COLOR1)
+#define BUFFER_BIT_COLOR2 (1 << BUFFER_COLOR2)
+#define BUFFER_BIT_COLOR3 (1 << BUFFER_COLOR3)
+#define BUFFER_BIT_COLOR4 (1 << BUFFER_COLOR4)
+#define BUFFER_BIT_COLOR5 (1 << BUFFER_COLOR5)
+#define BUFFER_BIT_COLOR6 (1 << BUFFER_COLOR6)
+#define BUFFER_BIT_COLOR7 (1 << BUFFER_COLOR7)
+
+/**
+ * Mask of all the color buffer bits (but not accum).
+ */
+#define BUFFER_BITS_COLOR (BUFFER_BIT_FRONT_LEFT | \
+ BUFFER_BIT_BACK_LEFT | \
+ BUFFER_BIT_FRONT_RIGHT | \
+ BUFFER_BIT_BACK_RIGHT | \
+ BUFFER_BIT_AUX0 | \
+ BUFFER_BIT_COLOR0 | \
+ BUFFER_BIT_COLOR1 | \
+ BUFFER_BIT_COLOR2 | \
+ BUFFER_BIT_COLOR3 | \
+ BUFFER_BIT_COLOR4 | \
+ BUFFER_BIT_COLOR5 | \
+ BUFFER_BIT_COLOR6 | \
+ BUFFER_BIT_COLOR7)
+
+
+/**
+ * Framebuffer configuration (aka visual / pixelformat)
+ * Note: some of these fields should be boolean, but it appears that
+ * code in drivers/dri/common/util.c requires int-sized fields.
+ */
+struct gl_config
+{
+ GLboolean rgbMode;
+ GLboolean floatMode;
+ GLboolean colorIndexMode; /* XXX is this used anywhere? */
+ GLuint doubleBufferMode;
+ GLuint stereoMode;
+
+ GLboolean haveAccumBuffer;
+ GLboolean haveDepthBuffer;
+ GLboolean haveStencilBuffer;
+
+ GLint redBits, greenBits, blueBits, alphaBits; /* bits per comp */
+ GLuint redMask, greenMask, blueMask, alphaMask;
+ GLint rgbBits; /* total bits for rgb */
+ GLint indexBits; /* total bits for colorindex */
+
+ GLint accumRedBits, accumGreenBits, accumBlueBits, accumAlphaBits;
+ GLint depthBits;
+ GLint stencilBits;
+
+ GLint numAuxBuffers;
+
+ GLint level;
+
+ /* EXT_visual_rating / GLX 1.2 */
+ GLint visualRating;
+
+ /* EXT_visual_info / GLX 1.2 */
+ GLint transparentPixel;
+ /* colors are floats scaled to ints */
+ GLint transparentRed, transparentGreen, transparentBlue, transparentAlpha;
+ GLint transparentIndex;
+
+ /* ARB_multisample / SGIS_multisample */
+ GLint sampleBuffers;
+ GLint samples;
+
+ /* SGIX_pbuffer / GLX 1.3 */
+ GLint maxPbufferWidth;
+ GLint maxPbufferHeight;
+ GLint maxPbufferPixels;
+ GLint optimalPbufferWidth; /* Only for SGIX_pbuffer. */
+ GLint optimalPbufferHeight; /* Only for SGIX_pbuffer. */
+
+ /* OML_swap_method */
+ GLint swapMethod;
+
+ /* EXT_texture_from_pixmap */
+ GLint bindToTextureRgb;
+ GLint bindToTextureRgba;
+ GLint bindToMipmapTexture;
+ GLint bindToTextureTargets;
+ GLint yInverted;
+
+ /* EXT_framebuffer_sRGB */
+ GLint sRGBCapable;
+};
+
+
+/**
+ * Data structure for color tables
+ */
+struct gl_color_table
+{
+ GLenum InternalFormat; /**< The user-specified format */
+ GLenum _BaseFormat; /**< GL_ALPHA, GL_RGBA, GL_RGB, etc */
+ GLuint Size; /**< number of entries in table */
+ GLfloat *TableF; /**< Color table, floating point values */
+ GLubyte *TableUB; /**< Color table, ubyte values */
+ GLubyte RedSize;
+ GLubyte GreenSize;
+ GLubyte BlueSize;
+ GLubyte AlphaSize;
+ GLubyte LuminanceSize;
+ GLubyte IntensitySize;
+};
+
+
+/**
+ * \name Bit flags used for updating material values.
+ */
+/*@{*/
+#define MAT_ATTRIB_FRONT_AMBIENT 0
+#define MAT_ATTRIB_BACK_AMBIENT 1
+#define MAT_ATTRIB_FRONT_DIFFUSE 2
+#define MAT_ATTRIB_BACK_DIFFUSE 3
+#define MAT_ATTRIB_FRONT_SPECULAR 4
+#define MAT_ATTRIB_BACK_SPECULAR 5
+#define MAT_ATTRIB_FRONT_EMISSION 6
+#define MAT_ATTRIB_BACK_EMISSION 7
+#define MAT_ATTRIB_FRONT_SHININESS 8
+#define MAT_ATTRIB_BACK_SHININESS 9
+#define MAT_ATTRIB_FRONT_INDEXES 10
+#define MAT_ATTRIB_BACK_INDEXES 11
+#define MAT_ATTRIB_MAX 12
+
+#define MAT_ATTRIB_AMBIENT(f) (MAT_ATTRIB_FRONT_AMBIENT+(f))
+#define MAT_ATTRIB_DIFFUSE(f) (MAT_ATTRIB_FRONT_DIFFUSE+(f))
+#define MAT_ATTRIB_SPECULAR(f) (MAT_ATTRIB_FRONT_SPECULAR+(f))
+#define MAT_ATTRIB_EMISSION(f) (MAT_ATTRIB_FRONT_EMISSION+(f))
+#define MAT_ATTRIB_SHININESS(f)(MAT_ATTRIB_FRONT_SHININESS+(f))
+#define MAT_ATTRIB_INDEXES(f) (MAT_ATTRIB_FRONT_INDEXES+(f))
+
+#define MAT_INDEX_AMBIENT 0
+#define MAT_INDEX_DIFFUSE 1
+#define MAT_INDEX_SPECULAR 2
+
+#define MAT_BIT_FRONT_AMBIENT (1<<MAT_ATTRIB_FRONT_AMBIENT)
+#define MAT_BIT_BACK_AMBIENT (1<<MAT_ATTRIB_BACK_AMBIENT)
+#define MAT_BIT_FRONT_DIFFUSE (1<<MAT_ATTRIB_FRONT_DIFFUSE)
+#define MAT_BIT_BACK_DIFFUSE (1<<MAT_ATTRIB_BACK_DIFFUSE)
+#define MAT_BIT_FRONT_SPECULAR (1<<MAT_ATTRIB_FRONT_SPECULAR)
+#define MAT_BIT_BACK_SPECULAR (1<<MAT_ATTRIB_BACK_SPECULAR)
+#define MAT_BIT_FRONT_EMISSION (1<<MAT_ATTRIB_FRONT_EMISSION)
+#define MAT_BIT_BACK_EMISSION (1<<MAT_ATTRIB_BACK_EMISSION)
+#define MAT_BIT_FRONT_SHININESS (1<<MAT_ATTRIB_FRONT_SHININESS)
+#define MAT_BIT_BACK_SHININESS (1<<MAT_ATTRIB_BACK_SHININESS)
+#define MAT_BIT_FRONT_INDEXES (1<<MAT_ATTRIB_FRONT_INDEXES)
+#define MAT_BIT_BACK_INDEXES (1<<MAT_ATTRIB_BACK_INDEXES)
+
+
+#define FRONT_MATERIAL_BITS (MAT_BIT_FRONT_EMISSION | \
+ MAT_BIT_FRONT_AMBIENT | \
+ MAT_BIT_FRONT_DIFFUSE | \
+ MAT_BIT_FRONT_SPECULAR | \
+ MAT_BIT_FRONT_SHININESS | \
+ MAT_BIT_FRONT_INDEXES)
+
+#define BACK_MATERIAL_BITS (MAT_BIT_BACK_EMISSION | \
+ MAT_BIT_BACK_AMBIENT | \
+ MAT_BIT_BACK_DIFFUSE | \
+ MAT_BIT_BACK_SPECULAR | \
+ MAT_BIT_BACK_SHININESS | \
+ MAT_BIT_BACK_INDEXES)
+
+#define ALL_MATERIAL_BITS (FRONT_MATERIAL_BITS | BACK_MATERIAL_BITS)
+/*@}*/
+
+
+#define EXP_TABLE_SIZE 512 /**< Specular exponent lookup table sizes */
+#define SHINE_TABLE_SIZE 256 /**< Material shininess lookup table sizes */
+
+/**
+ * Material shininess lookup table.
+ */
+struct gl_shine_tab
+{
+ struct gl_shine_tab *next, *prev;
+ GLfloat tab[SHINE_TABLE_SIZE+1];
+ GLfloat shininess;
+ GLuint refcount;
+};
+
+
+/**
+ * Light source state.
+ */
+struct gl_light
+{
+ struct gl_light *next; /**< double linked list with sentinel */
+ struct gl_light *prev;
+
+ GLfloat Ambient[4]; /**< ambient color */
+ GLfloat Diffuse[4]; /**< diffuse color */
+ GLfloat Specular[4]; /**< specular color */
+ GLfloat EyePosition[4]; /**< position in eye coordinates */
+ GLfloat SpotDirection[4]; /**< spotlight direction in eye coordinates */
+ GLfloat SpotExponent;
+ GLfloat SpotCutoff; /**< in degrees */
+ GLfloat _CosCutoffNeg; /**< = cos(SpotCutoff) */
+ GLfloat _CosCutoff; /**< = MAX(0, cos(SpotCutoff)) */
+ GLfloat ConstantAttenuation;
+ GLfloat LinearAttenuation;
+ GLfloat QuadraticAttenuation;
+ GLboolean Enabled; /**< On/off flag */
+
+ /**
+ * \name Derived fields
+ */
+ /*@{*/
+ GLbitfield _Flags; /**< State */
+
+ GLfloat _Position[4]; /**< position in eye/obj coordinates */
+ GLfloat _VP_inf_norm[3]; /**< Norm direction to infinite light */
+ GLfloat _h_inf_norm[3]; /**< Norm( _VP_inf_norm + <0,0,1> ) */
+ GLfloat _NormSpotDirection[4]; /**< normalized spotlight direction */
+ GLfloat _VP_inf_spot_attenuation;
+
+ GLfloat _SpotExpTable[EXP_TABLE_SIZE][2]; /**< to replace a pow() call */
+ GLfloat _MatAmbient[2][3]; /**< material ambient * light ambient */
+ GLfloat _MatDiffuse[2][3]; /**< material diffuse * light diffuse */
+ GLfloat _MatSpecular[2][3]; /**< material spec * light specular */
+ GLfloat _dli; /**< CI diffuse light intensity */
+ GLfloat _sli; /**< CI specular light intensity */
+ /*@}*/
+};
+
+
+/**
+ * Light model state.
+ */
+struct gl_lightmodel
+{
+ GLfloat Ambient[4]; /**< ambient color */
+ GLboolean LocalViewer; /**< Local (or infinite) view point? */
+ GLboolean TwoSide; /**< Two (or one) sided lighting? */
+ GLenum ColorControl; /**< either GL_SINGLE_COLOR
+ * or GL_SEPARATE_SPECULAR_COLOR */
+};
+
+
+/**
+ * Material state.
+ */
+struct gl_material
+{
+ GLfloat Attrib[MAT_ATTRIB_MAX][4];
+};
+
+
+/**
+ * Accumulation buffer attribute group (GL_ACCUM_BUFFER_BIT)
+ */
+struct gl_accum_attrib
+{
+ GLfloat ClearColor[4]; /**< Accumulation buffer clear color */
+};
+
+
+/**
+ * Color buffer attribute group (GL_COLOR_BUFFER_BIT).
+ */
+struct gl_colorbuffer_attrib
+{
+ GLuint ClearIndex; /**< Index to use for glClear */
+ GLclampf ClearColor[4]; /**< Color to use for glClear */
+
+ GLuint IndexMask; /**< Color index write mask */
+ GLubyte ColorMask[MAX_DRAW_BUFFERS][4];/**< Each flag is 0xff or 0x0 */
+
+ GLenum DrawBuffer[MAX_DRAW_BUFFERS]; /**< Which buffer to draw into */
+
+ /**
+ * \name alpha testing
+ */
+ /*@{*/
+ GLboolean AlphaEnabled; /**< Alpha test enabled flag */
+ GLenum AlphaFunc; /**< Alpha test function */
+ GLclampf AlphaRef; /**< Alpha reference value */
+ /*@}*/
+
+ /**
+ * \name Blending
+ */
+ /*@{*/
+ GLbitfield BlendEnabled; /**< Per-buffer blend enable flags */
+ GLfloat BlendColor[4]; /**< Blending color */
+ struct
+ {
+ GLenum SrcRGB; /**< RGB blend source term */
+ GLenum DstRGB; /**< RGB blend dest term */
+ GLenum SrcA; /**< Alpha blend source term */
+ GLenum DstA; /**< Alpha blend dest term */
+ GLenum EquationRGB; /**< GL_ADD, GL_SUBTRACT, etc. */
+ GLenum EquationA; /**< GL_ADD, GL_SUBTRACT, etc. */
+ } Blend[MAX_DRAW_BUFFERS];
+ /** Are the blend func terms currently different for each buffer/target? */
+ GLboolean _BlendFuncPerBuffer;
+ /** Are the blend equations currently different for each buffer/target? */
+ GLboolean _BlendEquationPerBuffer;
+ /*@}*/
+
+ /**
+ * \name Logic op
+ */
+ /*@{*/
+ GLenum LogicOp; /**< Logic operator */
+ GLboolean IndexLogicOpEnabled; /**< Color index logic op enabled flag */
+ GLboolean ColorLogicOpEnabled; /**< RGBA logic op enabled flag */
+ GLboolean _LogicOpEnabled; /**< RGBA logic op + EXT_blend_logic_op enabled flag */
+ /*@}*/
+
+ GLboolean DitherFlag; /**< Dither enable flag */
+
+ GLenum ClampFragmentColor; /**< GL_TRUE, GL_FALSE or GL_FIXED_ONLY_ARB */
+ GLenum ClampReadColor; /**< GL_TRUE, GL_FALSE or GL_FIXED_ONLY_ARB */
+
+ GLboolean sRGBEnabled; /**< Framebuffer sRGB blending/updating requested */
+};
+
+
+/**
+ * Current attribute group (GL_CURRENT_BIT).
+ */
+struct gl_current_attrib
+{
+ /**
+ * \name Current vertex attributes.
+ * \note Values are valid only after FLUSH_VERTICES has been called.
+ * \note Index and Edgeflag current values are stored as floats in the
+ * SIX and SEVEN attribute slots.
+ */
+ GLfloat Attrib[VERT_ATTRIB_MAX][4]; /**< Position, color, texcoords, etc */
+
+ /**
+ * \name Current raster position attributes (always valid).
+ * \note This set of attributes is very similar to the SWvertex struct.
+ */
+ /*@{*/
+ GLfloat RasterPos[4];
+ GLfloat RasterDistance;
+ GLfloat RasterColor[4];
+ GLfloat RasterSecondaryColor[4];
+ GLfloat RasterTexCoords[MAX_TEXTURE_COORD_UNITS][4];
+ GLboolean RasterPosValid;
+ /*@}*/
+};
+
+
+/**
+ * Depth buffer attribute group (GL_DEPTH_BUFFER_BIT).
+ */
+struct gl_depthbuffer_attrib
+{
+ GLenum Func; /**< Function for depth buffer compare */
+ GLclampd Clear; /**< Value to clear depth buffer to */
+ GLboolean Test; /**< Depth buffering enabled flag */
+ GLboolean Mask; /**< Depth buffer writable? */
+ GLboolean BoundsTest; /**< GL_EXT_depth_bounds_test */
+ GLfloat BoundsMin, BoundsMax;/**< GL_EXT_depth_bounds_test */
+};
+
+
+/**
+ * Evaluator attribute group (GL_EVAL_BIT).
+ */
+struct gl_eval_attrib
+{
+ /**
+ * \name Enable bits
+ */
+ /*@{*/
+ GLboolean Map1Color4;
+ GLboolean Map1Index;
+ GLboolean Map1Normal;
+ GLboolean Map1TextureCoord1;
+ GLboolean Map1TextureCoord2;
+ GLboolean Map1TextureCoord3;
+ GLboolean Map1TextureCoord4;
+ GLboolean Map1Vertex3;
+ GLboolean Map1Vertex4;
+ GLboolean Map1Attrib[16]; /* GL_NV_vertex_program */
+ GLboolean Map2Color4;
+ GLboolean Map2Index;
+ GLboolean Map2Normal;
+ GLboolean Map2TextureCoord1;
+ GLboolean Map2TextureCoord2;
+ GLboolean Map2TextureCoord3;
+ GLboolean Map2TextureCoord4;
+ GLboolean Map2Vertex3;
+ GLboolean Map2Vertex4;
+ GLboolean Map2Attrib[16]; /* GL_NV_vertex_program */
+ GLboolean AutoNormal;
+ /*@}*/
+
+ /**
+ * \name Map Grid endpoints and divisions and calculated du values
+ */
+ /*@{*/
+ GLint MapGrid1un;
+ GLfloat MapGrid1u1, MapGrid1u2, MapGrid1du;
+ GLint MapGrid2un, MapGrid2vn;
+ GLfloat MapGrid2u1, MapGrid2u2, MapGrid2du;
+ GLfloat MapGrid2v1, MapGrid2v2, MapGrid2dv;
+ /*@}*/
+};
+
+
+/**
+ * Fog attribute group (GL_FOG_BIT).
+ */
+struct gl_fog_attrib
+{
+ GLboolean Enabled; /**< Fog enabled flag */
+ GLfloat Color[4]; /**< Fog color */
+ GLfloat Density; /**< Density >= 0.0 */
+ GLfloat Start; /**< Start distance in eye coords */
+ GLfloat End; /**< End distance in eye coords */
+ GLfloat Index; /**< Fog index */
+ GLenum Mode; /**< Fog mode */
+ GLboolean ColorSumEnabled;
+ GLenum FogCoordinateSource; /**< GL_EXT_fog_coord */
+ GLfloat _Scale; /**< (End == Start) ? 1.0 : 1.0 / (End - Start) */
+};
+
+
+/**
+ * \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).
+ *
+ * Values are always one of GL_FASTEST, GL_NICEST, or GL_DONT_CARE.
+ */
+struct gl_hint_attrib
+{
+ GLenum PerspectiveCorrection;
+ GLenum PointSmooth;
+ GLenum LineSmooth;
+ GLenum PolygonSmooth;
+ GLenum Fog;
+ GLenum ClipVolumeClipping; /**< GL_EXT_clip_volume_hint */
+ GLenum TextureCompression; /**< GL_ARB_texture_compression */
+ GLenum GenerateMipmap; /**< GL_SGIS_generate_mipmap */
+ GLenum FragmentShaderDerivative; /**< GL_ARB_fragment_shader */
+};
+
+/**
+ * Light state flags.
+ */
+/*@{*/
+#define LIGHT_SPOT 0x1
+#define LIGHT_LOCAL_VIEWER 0x2
+#define LIGHT_POSITIONAL 0x4
+#define LIGHT_NEED_VERTICES (LIGHT_POSITIONAL|LIGHT_LOCAL_VIEWER)
+/*@}*/
+
+
+/**
+ * Lighting attribute group (GL_LIGHT_BIT).
+ */
+struct gl_light_attrib
+{
+ struct gl_light Light[MAX_LIGHTS]; /**< Array of light sources */
+ struct gl_lightmodel Model; /**< Lighting model */
+
+ /**
+ * Must flush FLUSH_VERTICES before referencing:
+ */
+ /*@{*/
+ struct gl_material Material; /**< Includes front & back values */
+ /*@}*/
+
+ GLboolean Enabled; /**< Lighting enabled flag */
+ GLenum ShadeModel; /**< GL_FLAT or GL_SMOOTH */
+ GLenum ProvokingVertex; /**< GL_EXT_provoking_vertex */
+ GLenum ColorMaterialFace; /**< GL_FRONT, BACK or FRONT_AND_BACK */
+ GLenum ColorMaterialMode; /**< GL_AMBIENT, GL_DIFFUSE, etc */
+ GLbitfield ColorMaterialBitmask; /**< bitmask formed from Face and Mode */
+ GLboolean ColorMaterialEnabled;
+ GLenum ClampVertexColor;
+
+ struct gl_light EnabledList; /**< List sentinel */
+
+ /**
+ * Derived state for optimizations:
+ */
+ /*@{*/
+ GLboolean _NeedEyeCoords;
+ GLboolean _NeedVertices; /**< Use fast shader? */
+ GLbitfield _Flags; /**< LIGHT_* flags, see above */
+ GLfloat _BaseColor[2][3];
+ /*@}*/
+};
+
+
+/**
+ * Line attribute group (GL_LINE_BIT).
+ */
+struct gl_line_attrib
+{
+ GLboolean SmoothFlag; /**< GL_LINE_SMOOTH enabled? */
+ GLboolean StippleFlag; /**< GL_LINE_STIPPLE enabled? */
+ GLushort StipplePattern; /**< Stipple pattern */
+ GLint StippleFactor; /**< Stipple repeat factor */
+ GLfloat Width; /**< Line width */
+};
+
+
+/**
+ * Display list attribute group (GL_LIST_BIT).
+ */
+struct gl_list_attrib
+{
+ GLuint ListBase;
+};
+
+
+/**
+ * Multisample attribute group (GL_MULTISAMPLE_BIT).
+ */
+struct gl_multisample_attrib
+{
+ GLboolean Enabled;
+ GLboolean _Enabled; /**< true if Enabled and multisample buffer */
+ GLboolean SampleAlphaToCoverage;
+ GLboolean SampleAlphaToOne;
+ GLboolean SampleCoverage;
+ GLfloat SampleCoverageValue;
+ GLboolean SampleCoverageInvert;
+};
+
+
+/**
+ * A pixelmap (see glPixelMap)
+ */
+struct gl_pixelmap
+{
+ GLint Size;
+ GLfloat Map[MAX_PIXEL_MAP_TABLE];
+ GLubyte Map8[MAX_PIXEL_MAP_TABLE]; /**< converted to 8-bit color */
+};
+
+
+/**
+ * Collection of all pixelmaps
+ */
+struct gl_pixelmaps
+{
+ struct gl_pixelmap RtoR; /**< i.e. GL_PIXEL_MAP_R_TO_R */
+ struct gl_pixelmap GtoG;
+ struct gl_pixelmap BtoB;
+ struct gl_pixelmap AtoA;
+ struct gl_pixelmap ItoR;
+ struct gl_pixelmap ItoG;
+ struct gl_pixelmap ItoB;
+ struct gl_pixelmap ItoA;
+ struct gl_pixelmap ItoI;
+ struct gl_pixelmap StoS;
+};
+
+
+/**
+ * Pixel attribute group (GL_PIXEL_MODE_BIT).
+ */
+struct gl_pixel_attrib
+{
+ GLenum ReadBuffer; /**< source buffer for glRead/CopyPixels() */
+
+ /*--- Begin Pixel Transfer State ---*/
+ /* Fields are in the order in which they're applied... */
+
+ /** Scale & Bias (index shift, offset) */
+ /*@{*/
+ GLfloat RedBias, RedScale;
+ GLfloat GreenBias, GreenScale;
+ GLfloat BlueBias, BlueScale;
+ GLfloat AlphaBias, AlphaScale;
+ GLfloat DepthBias, DepthScale;
+ GLint IndexShift, IndexOffset;
+ /*@}*/
+
+ /* Pixel Maps */
+ /* Note: actual pixel maps are not part of this attrib group */
+ GLboolean MapColorFlag;
+ GLboolean MapStencilFlag;
+
+ /*--- End Pixel Transfer State ---*/
+
+ /** glPixelZoom */
+ GLfloat ZoomX, ZoomY;
+
+ /** GL_SGI_texture_color_table */
+ GLfloat TextureColorTableScale[4]; /**< RGBA */
+ GLfloat TextureColorTableBias[4]; /**< RGBA */
+};
+
+
+/**
+ * Point attribute group (GL_POINT_BIT).
+ */
+struct gl_point_attrib
+{
+ GLboolean SmoothFlag; /**< True if GL_POINT_SMOOTH is enabled */
+ GLfloat Size; /**< User-specified point size */
+ GLfloat Params[3]; /**< GL_EXT_point_parameters */
+ GLfloat MinSize, MaxSize; /**< GL_EXT_point_parameters */
+ GLfloat Threshold; /**< GL_EXT_point_parameters */
+ GLboolean _Attenuated; /**< True if Params != [1, 0, 0] */
+ GLboolean PointSprite; /**< GL_NV/ARB_point_sprite */
+ GLboolean CoordReplace[MAX_TEXTURE_COORD_UNITS]; /**< GL_ARB_point_sprite*/
+ GLenum SpriteRMode; /**< GL_NV_point_sprite (only!) */
+ GLenum SpriteOrigin; /**< GL_ARB_point_sprite */
+};
+
+
+/**
+ * Polygon attribute group (GL_POLYGON_BIT).
+ */
+struct gl_polygon_attrib
+{
+ GLenum FrontFace; /**< Either GL_CW or GL_CCW */
+ GLenum FrontMode; /**< Either GL_POINT, GL_LINE or GL_FILL */
+ GLenum BackMode; /**< Either GL_POINT, GL_LINE or GL_FILL */
+ GLboolean _FrontBit; /**< 0=GL_CCW, 1=GL_CW */
+ GLboolean CullFlag; /**< Culling on/off flag */
+ GLboolean SmoothFlag; /**< True if GL_POLYGON_SMOOTH is enabled */
+ GLboolean StippleFlag; /**< True if GL_POLYGON_STIPPLE is enabled */
+ GLenum CullFaceMode; /**< Culling mode GL_FRONT or GL_BACK */
+ GLfloat OffsetFactor; /**< Polygon offset factor, from user */
+ GLfloat OffsetUnits; /**< Polygon offset units, from user */
+ GLboolean OffsetPoint; /**< Offset in GL_POINT mode */
+ GLboolean OffsetLine; /**< Offset in GL_LINE mode */
+ GLboolean OffsetFill; /**< Offset in GL_FILL mode */
+};
+
+
+/**
+ * Scissor attributes (GL_SCISSOR_BIT).
+ */
+struct gl_scissor_attrib
+{
+ GLboolean Enabled; /**< Scissor test enabled? */
+ GLint X, Y; /**< Lower left corner of box */
+ GLsizei Width, Height; /**< Size of box */
+};
+
+
+/**
+ * Stencil attribute group (GL_STENCIL_BUFFER_BIT).
+ *
+ * Three sets of stencil data are tracked so that OpenGL 2.0,
+ * GL_EXT_stencil_two_side, and GL_ATI_separate_stencil can all be supported
+ * simultaneously. In each of the stencil state arrays, element 0 corresponds
+ * to GL_FRONT. Element 1 corresponds to the OpenGL 2.0 /
+ * GL_ATI_separate_stencil GL_BACK state. Element 2 corresponds to the
+ * GL_EXT_stencil_two_side GL_BACK state.
+ *
+ * The derived value \c _BackFace is either 1 or 2 depending on whether or
+ * not GL_STENCIL_TEST_TWO_SIDE_EXT is enabled.
+ *
+ * The derived value \c _TestTwoSide is set when the front-face and back-face
+ * stencil state are different.
+ */
+struct gl_stencil_attrib
+{
+ GLboolean Enabled; /**< Enabled flag */
+ GLboolean TestTwoSide; /**< GL_EXT_stencil_two_side */
+ GLubyte ActiveFace; /**< GL_EXT_stencil_two_side (0 or 2) */
+ GLboolean _Enabled; /**< Enabled and stencil buffer present */
+ GLboolean _TestTwoSide;
+ GLubyte _BackFace; /**< Current back stencil state (1 or 2) */
+ GLenum Function[3]; /**< Stencil function */
+ GLenum FailFunc[3]; /**< Fail function */
+ GLenum ZPassFunc[3]; /**< Depth buffer pass function */
+ GLenum ZFailFunc[3]; /**< Depth buffer fail function */
+ GLint Ref[3]; /**< Reference value */
+ GLuint ValueMask[3]; /**< Value mask */
+ GLuint WriteMask[3]; /**< Write mask */
+ GLuint Clear; /**< Clear value */
+};
+
+
+/**
+ * An index for each type of texture object. These correspond to the GL
+ * texture target enums, such as GL_TEXTURE_2D, GL_TEXTURE_CUBE_MAP, etc.
+ * Note: the order is from highest priority to lowest priority.
+ */
+typedef enum
+{
+ TEXTURE_2D_ARRAY_INDEX,
+ TEXTURE_1D_ARRAY_INDEX,
+ TEXTURE_CUBE_INDEX,
+ TEXTURE_3D_INDEX,
+ TEXTURE_RECT_INDEX,
+ TEXTURE_2D_INDEX,
+ TEXTURE_1D_INDEX,
+ NUM_TEXTURE_TARGETS
+} gl_texture_index;
+
+
+/**
+ * Bit flags for each type of texture object
+ * Used for Texture.Unit[]._ReallyEnabled flags.
+ */
+/*@{*/
+#define TEXTURE_2D_ARRAY_BIT (1 << TEXTURE_2D_ARRAY_INDEX)
+#define TEXTURE_1D_ARRAY_BIT (1 << TEXTURE_1D_ARRAY_INDEX)
+#define TEXTURE_CUBE_BIT (1 << TEXTURE_CUBE_INDEX)
+#define TEXTURE_3D_BIT (1 << TEXTURE_3D_INDEX)
+#define TEXTURE_RECT_BIT (1 << TEXTURE_RECT_INDEX)
+#define TEXTURE_2D_BIT (1 << TEXTURE_2D_INDEX)
+#define TEXTURE_1D_BIT (1 << TEXTURE_1D_INDEX)
+/*@}*/
+
+
+/**
+ * TexGenEnabled flags.
+ */
+/*@{*/
+#define S_BIT 1
+#define T_BIT 2
+#define R_BIT 4
+#define Q_BIT 8
+#define STR_BITS (S_BIT | T_BIT | R_BIT)
+/*@}*/
+
+
+/**
+ * Bit flag versions of the corresponding GL_ constants.
+ */
+/*@{*/
+#define TEXGEN_SPHERE_MAP 0x1
+#define TEXGEN_OBJ_LINEAR 0x2
+#define TEXGEN_EYE_LINEAR 0x4
+#define TEXGEN_REFLECTION_MAP_NV 0x8
+#define TEXGEN_NORMAL_MAP_NV 0x10
+
+#define TEXGEN_NEED_NORMALS (TEXGEN_SPHERE_MAP | \
+ TEXGEN_REFLECTION_MAP_NV | \
+ TEXGEN_NORMAL_MAP_NV)
+#define TEXGEN_NEED_EYE_COORD (TEXGEN_SPHERE_MAP | \
+ TEXGEN_REFLECTION_MAP_NV | \
+ TEXGEN_NORMAL_MAP_NV | \
+ TEXGEN_EYE_LINEAR)
+/*@}*/
+
+
+
+/** Tex-gen enabled for texture unit? */
+#define ENABLE_TEXGEN(unit) (1 << (unit))
+
+/** Non-identity texture matrix for texture unit? */
+#define ENABLE_TEXMAT(unit) (1 << (unit))
+
+
+/**
+ * Texel fetch function prototype. We use texel fetch functions to
+ * extract RGBA, color indexes and depth components out of 1D, 2D and 3D
+ * texture images. These functions help to isolate us from the gritty
+ * details of all the various texture image encodings.
+ *
+ * \param texImage texture image.
+ * \param col texel column.
+ * \param row texel row.
+ * \param img texel image level/layer.
+ * \param texelOut output texel (up to 4 GLchans)
+ */
+typedef void (*FetchTexelFuncC)( const struct gl_texture_image *texImage,
+ GLint col, GLint row, GLint img,
+ GLchan *texelOut );
+
+/**
+ * As above, but returns floats.
+ * Used for depth component images and for upcoming signed/float
+ * texture images.
+ */
+typedef void (*FetchTexelFuncF)( const struct gl_texture_image *texImage,
+ GLint col, GLint row, GLint img,
+ GLfloat *texelOut );
+
+
+typedef void (*StoreTexelFunc)(struct gl_texture_image *texImage,
+ GLint col, GLint row, GLint img,
+ const void *texel);
+
+
+/**
+ * Texture image state. Describes the dimensions of a texture image,
+ * the texel format and pointers to Texel Fetch functions.
+ */
+struct gl_texture_image
+{
+ GLint InternalFormat; /**< Internal format as given by the user */
+ GLenum _BaseFormat; /**< Either GL_RGB, GL_RGBA, GL_ALPHA,
+ * GL_LUMINANCE, GL_LUMINANCE_ALPHA,
+ * GL_INTENSITY, GL_COLOR_INDEX,
+ * GL_DEPTH_COMPONENT or GL_DEPTH_STENCIL_EXT
+ * only. Used for choosing TexEnv arithmetic.
+ */
+ GLuint TexFormat; /**< The actual format: MESA_FORMAT_x */
+
+ GLuint Border; /**< 0 or 1 */
+ GLuint Width; /**< = 2^WidthLog2 + 2*Border */
+ GLuint Height; /**< = 2^HeightLog2 + 2*Border */
+ GLuint Depth; /**< = 2^DepthLog2 + 2*Border */
+ GLuint Width2; /**< = Width - 2*Border */
+ GLuint Height2; /**< = Height - 2*Border */
+ GLuint Depth2; /**< = Depth - 2*Border */
+ GLuint WidthLog2; /**< = log2(Width2) */
+ GLuint HeightLog2; /**< = log2(Height2) */
+ GLuint DepthLog2; /**< = log2(Depth2) */
+ GLuint MaxLog2; /**< = MAX(WidthLog2, HeightLog2) */
+ GLfloat WidthScale; /**< used for mipmap LOD computation */
+ GLfloat HeightScale; /**< used for mipmap LOD computation */
+ GLfloat DepthScale; /**< used for mipmap LOD computation */
+ GLboolean IsClientData; /**< Data owned by client? */
+ GLboolean _IsPowerOfTwo; /**< Are all dimensions powers of two? */
+
+ struct gl_texture_object *TexObject; /**< Pointer back to parent object */
+
+ FetchTexelFuncC FetchTexelc; /**< GLchan texel fetch function pointer */
+ FetchTexelFuncF FetchTexelf; /**< Float texel fetch function pointer */
+
+ GLuint RowStride; /**< Padded width in units of texels */
+ GLuint *ImageOffsets; /**< if 3D texture: array [Depth] of offsets to
+ each 2D slice in 'Data', in texels */
+ GLvoid *Data; /**< Image data, accessed via FetchTexel() */
+
+ /**
+ * \name For device driver:
+ */
+ /*@{*/
+ void *DriverData; /**< Arbitrary device driver data */
+ /*@}*/
+};
+
+
+/**
+ * Indexes for cube map faces.
+ */
+typedef enum
+{
+ FACE_POS_X = 0,
+ FACE_NEG_X = 1,
+ FACE_POS_Y = 2,
+ FACE_NEG_Y = 3,
+ FACE_POS_Z = 4,
+ FACE_NEG_Z = 5,
+ MAX_FACES = 6
+} gl_face_index;
+
+
+/**
+ * Texture object state. Contains the array of mipmap images, border color,
+ * wrap modes, filter modes, shadow/texcompare state, and the per-texture
+ * color palette.
+ */
+struct gl_texture_object
+{
+ _glthread_Mutex Mutex; /**< for thread safety */
+ GLint RefCount; /**< reference count */
+ GLuint Name; /**< the user-visible texture object ID */
+ GLenum Target; /**< GL_TEXTURE_1D, GL_TEXTURE_2D, etc. */
+ GLfloat Priority; /**< in [0,1] */
+ union {
+ GLfloat f[4];
+ GLuint ui[4];
+ GLint i[4];
+ } BorderColor; /**< Interpreted according to texture format */
+ GLenum WrapS; /**< S-axis texture image wrap mode */
+ GLenum WrapT; /**< T-axis texture image wrap mode */
+ GLenum WrapR; /**< R-axis texture image wrap mode */
+ GLenum MinFilter; /**< minification filter */
+ GLenum MagFilter; /**< magnification filter */
+ GLfloat MinLod; /**< min lambda, OpenGL 1.2 */
+ GLfloat MaxLod; /**< max lambda, OpenGL 1.2 */
+ GLfloat LodBias; /**< OpenGL 1.4 */
+ GLint BaseLevel; /**< min mipmap level, OpenGL 1.2 */
+ GLint MaxLevel; /**< max mipmap level, OpenGL 1.2 */
+ GLfloat MaxAnisotropy; /**< GL_EXT_texture_filter_anisotropic */
+ GLenum CompareMode; /**< GL_ARB_shadow */
+ GLenum CompareFunc; /**< GL_ARB_shadow */
+ GLfloat CompareFailValue; /**< GL_ARB_shadow_ambient */
+ GLenum DepthMode; /**< GL_ARB_depth_texture */
+ GLint _MaxLevel; /**< actual max mipmap level (q in the spec) */
+ GLfloat _MaxLambda; /**< = _MaxLevel - BaseLevel (q - b in spec) */
+ GLint CropRect[4]; /**< GL_OES_draw_texture */
+ GLenum Swizzle[4]; /**< GL_EXT_texture_swizzle */
+ GLuint _Swizzle; /**< same as Swizzle, but SWIZZLE_* format */
+ GLboolean GenerateMipmap; /**< GL_SGIS_generate_mipmap */
+ GLboolean _Complete; /**< Is texture object complete? */
+ GLboolean _RenderToTexture; /**< Any rendering to this texture? */
+ GLboolean Purgeable; /**< Is the buffer purgeable under memory pressure? */
+ GLenum sRGBDecode; /**< GL_DECODE_EXT or GL_SKIP_DECODE_EXT */
+
+ /** Actual texture images, indexed by [cube face] and [mipmap level] */
+ struct gl_texture_image *Image[MAX_FACES][MAX_TEXTURE_LEVELS];
+
+ /** GL_EXT_paletted_texture */
+ struct gl_color_table Palette;
+
+ /**
+ * \name For device driver.
+ * Note: instead of attaching driver data to this pointer, it's preferable
+ * to instead use this struct as a base class for your own texture object
+ * class. Driver->NewTextureObject() can be used to implement the
+ * allocation.
+ */
+ void *DriverData; /**< Arbitrary device driver data */
+};
+
+
+/** Up to four combiner sources are possible with GL_NV_texture_env_combine4 */
+#define MAX_COMBINER_TERMS 4
+
+
+/**
+ * Texture combine environment state.
+ */
+struct gl_tex_env_combine_state
+{
+ GLenum ModeRGB; /**< GL_REPLACE, GL_DECAL, GL_ADD, etc. */
+ GLenum ModeA; /**< GL_REPLACE, GL_DECAL, GL_ADD, etc. */
+ /** Source terms: GL_PRIMARY_COLOR, GL_TEXTURE, etc */
+ GLenum SourceRGB[MAX_COMBINER_TERMS];
+ GLenum SourceA[MAX_COMBINER_TERMS];
+ /** Source operands: GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, etc */
+ GLenum OperandRGB[MAX_COMBINER_TERMS];
+ GLenum OperandA[MAX_COMBINER_TERMS];
+ GLuint ScaleShiftRGB; /**< 0, 1 or 2 */
+ GLuint ScaleShiftA; /**< 0, 1 or 2 */
+ GLuint _NumArgsRGB; /**< Number of inputs used for the RGB combiner */
+ GLuint _NumArgsA; /**< Number of inputs used for the A combiner */
+};
+
+
+/**
+ * Texture coord generation state.
+ */
+struct gl_texgen
+{
+ GLenum Mode; /**< GL_EYE_LINEAR, GL_SPHERE_MAP, etc */
+ GLbitfield _ModeBit; /**< TEXGEN_x bit corresponding to Mode */
+ GLfloat ObjectPlane[4];
+ GLfloat EyePlane[4];
+};
+
+
+/**
+ * Texture unit state. Contains enable flags, texture environment/function/
+ * combiners, texgen state, pointers to current texture objects and
+ * post-filter color tables.
+ */
+struct gl_texture_unit
+{
+ GLbitfield Enabled; /**< bitmask of TEXTURE_*_BIT flags */
+ GLbitfield _ReallyEnabled; /**< 0 or exactly one of TEXTURE_*_BIT flags */
+
+ GLenum EnvMode; /**< GL_MODULATE, GL_DECAL, GL_BLEND, etc. */
+ GLfloat EnvColor[4];
+
+ struct gl_texgen GenS;
+ struct gl_texgen GenT;
+ struct gl_texgen GenR;
+ struct gl_texgen GenQ;
+ GLbitfield TexGenEnabled; /**< Bitwise-OR of [STRQ]_BIT values */
+ GLbitfield _GenFlags; /**< Bitwise-OR of Gen[STRQ]._ModeBit */
+
+ GLfloat LodBias; /**< for biasing mipmap levels */
+ GLenum BumpTarget;
+ GLfloat RotMatrix[4]; /* 2x2 matrix */
+
+ /**
+ * \name GL_EXT_texture_env_combine
+ */
+ struct gl_tex_env_combine_state Combine;
+
+ /**
+ * Derived state based on \c EnvMode and the \c BaseFormat of the
+ * currently enabled texture.
+ */
+ struct gl_tex_env_combine_state _EnvMode;
+
+ /**
+ * Currently enabled combiner state. This will point to either
+ * \c Combine or \c _EnvMode.
+ */
+ struct gl_tex_env_combine_state *_CurrentCombine;
+
+ /** Current texture object pointers */
+ struct gl_texture_object *CurrentTex[NUM_TEXTURE_TARGETS];
+
+ /** Points to highest priority, complete and enabled texture object */
+ struct gl_texture_object *_Current;
+
+ /** GL_SGI_texture_color_table */
+ /*@{*/
+ struct gl_color_table ColorTable;
+ struct gl_color_table ProxyColorTable;
+ GLboolean ColorTableEnabled;
+ /*@}*/
+};
+
+
+/**
+ * Texture attribute group (GL_TEXTURE_BIT).
+ */
+struct gl_texture_attrib
+{
+ GLuint CurrentUnit; /**< GL_ACTIVE_TEXTURE */
+ struct gl_texture_unit Unit[MAX_COMBINED_TEXTURE_IMAGE_UNITS];
+
+ struct gl_texture_object *ProxyTex[NUM_TEXTURE_TARGETS];
+
+ /** GL_ARB_seamless_cubemap */
+ GLboolean CubeMapSeamless;
+
+ /** GL_EXT_shared_texture_palette */
+ GLboolean SharedPalette;
+ struct gl_color_table Palette;
+
+ /** Texture units/samplers used by vertex or fragment texturing */
+ GLbitfield _EnabledUnits;
+
+ /** Texture coord units/sets used for fragment texturing */
+ GLbitfield _EnabledCoordUnits;
+
+ /** Texture coord units that have texgen enabled */
+ GLbitfield _TexGenEnabled;
+
+ /** Texture coord units that have non-identity matrices */
+ GLbitfield _TexMatEnabled;
+
+ /** Bitwise-OR of all Texture.Unit[i]._GenFlags */
+ GLbitfield _GenFlags;
+};
+
+
+/**
+ * Transformation attribute group (GL_TRANSFORM_BIT).
+ */
+struct gl_transform_attrib
+{
+ GLenum MatrixMode; /**< Matrix mode */
+ GLfloat EyeUserPlane[MAX_CLIP_PLANES][4]; /**< User clip planes */
+ GLfloat _ClipUserPlane[MAX_CLIP_PLANES][4]; /**< derived */
+ GLbitfield ClipPlanesEnabled; /**< on/off bitmask */
+ GLboolean Normalize; /**< Normalize all normals? */
+ GLboolean RescaleNormals; /**< GL_EXT_rescale_normal */
+ GLboolean RasterPositionUnclipped; /**< GL_IBM_rasterpos_clip */
+ GLboolean DepthClamp; /**< GL_ARB_depth_clamp */
+
+ GLfloat CullEyePos[4];
+ GLfloat CullObjPos[4];
+};
+
+
+/**
+ * Viewport attribute group (GL_VIEWPORT_BIT).
+ */
+struct gl_viewport_attrib
+{
+ GLint X, Y; /**< position */
+ GLsizei Width, Height; /**< size */
+ GLfloat Near, Far; /**< Depth buffer range */
+ GLmatrix _WindowMap; /**< Mapping transformation as a matrix. */
+};
+
+
+/**
+ * GL_ARB_vertex/pixel_buffer_object buffer object
+ */
+struct gl_buffer_object
+{
+ _glthread_Mutex Mutex;
+ GLint RefCount;
+ GLuint Name;
+ GLenum Usage; /**< GL_STREAM_DRAW_ARB, GL_STREAM_READ_ARB, etc. */
+ GLsizeiptrARB Size; /**< Size of buffer storage in bytes */
+ GLubyte *Data; /**< Location of storage either in RAM or VRAM. */
+ /** Fields describing a mapped buffer */
+ /*@{*/
+ GLbitfield AccessFlags; /**< Mask of GL_MAP_x_BIT flags */
+ GLvoid *Pointer; /**< User-space address of mapping */
+ GLintptr Offset; /**< Mapped offset */
+ GLsizeiptr Length; /**< Mapped length */
+ /*@}*/
+ GLboolean Written; /**< Ever written to? (for debugging) */
+ GLboolean Purgeable; /**< Is the buffer purgeable under memory pressure? */
+};
+
+
+/**
+ * Client pixel packing/unpacking attributes
+ */
+struct gl_pixelstore_attrib
+{
+ GLint Alignment;
+ GLint RowLength;
+ GLint SkipPixels;
+ GLint SkipRows;
+ GLint ImageHeight;
+ GLint SkipImages;
+ GLboolean SwapBytes;
+ GLboolean LsbFirst;
+ GLboolean ClientStorage; /**< GL_APPLE_client_storage */
+ GLboolean Invert; /**< GL_MESA_pack_invert */
+ struct gl_buffer_object *BufferObj; /**< GL_ARB_pixel_buffer_object */
+};
+
+
+/**
+ * Client vertex array attributes
+ */
+struct gl_client_array
+{
+ GLint Size; /**< components per element (1,2,3,4) */
+ GLenum Type; /**< datatype: GL_FLOAT, GL_INT, etc */
+ GLenum Format; /**< default: GL_RGBA, but may be GL_BGRA */
+ GLsizei Stride; /**< user-specified stride */
+ GLsizei StrideB; /**< actual stride in bytes */
+ const GLubyte *Ptr; /**< Points to array data */
+ GLboolean Enabled; /**< Enabled flag is a boolean */
+ GLboolean Normalized; /**< GL_ARB_vertex_program */
+ GLboolean Integer; /**< Integer-valued? */
+ GLuint InstanceDivisor; /**< GL_ARB_instanced_arrays */
+ GLuint _ElementSize; /**< size of each element in bytes */
+
+ struct gl_buffer_object *BufferObj;/**< GL_ARB_vertex_buffer_object */
+ GLuint _MaxElement; /**< max element index into array buffer + 1 */
+};
+
+
+/**
+ * Collection of vertex arrays. Defined by the GL_APPLE_vertex_array_object
+ * extension, but a nice encapsulation in any case.
+ */
+struct gl_array_object
+{
+ /** Name of the array object as received from glGenVertexArrayAPPLE. */
+ GLuint Name;
+
+ GLint RefCount;
+ _glthread_Mutex Mutex;
+ GLboolean VBOonly; /**< require all arrays to live in VBOs? */
+
+ /** Conventional vertex arrays */
+ /*@{*/
+ struct gl_client_array Vertex;
+ struct gl_client_array Weight;
+ struct gl_client_array Normal;
+ struct gl_client_array Color;
+ struct gl_client_array SecondaryColor;
+ struct gl_client_array FogCoord;
+ struct gl_client_array Index;
+ struct gl_client_array EdgeFlag;
+ struct gl_client_array TexCoord[MAX_TEXTURE_COORD_UNITS];
+ struct gl_client_array PointSize;
+ /*@}*/
+
+ /**
+ * Generic arrays for vertex programs/shaders.
+ * For NV vertex programs, these attributes alias and take priority
+ * over the conventional attribs above. For ARB vertex programs and
+ * GLSL vertex shaders, these attributes are separate.
+ */
+ struct gl_client_array VertexAttrib[MAX_VERTEX_GENERIC_ATTRIBS];
+
+ /** Mask of _NEW_ARRAY_* values indicating which arrays are enabled */
+ GLbitfield _Enabled;
+
+ /**
+ * Min of all enabled arrays' _MaxElement. When arrays reside inside VBOs
+ * we can determine the max legal (in bounds) glDrawElements array index.
+ */
+ GLuint _MaxElement;
+};
+
+
+/**
+ * Vertex array state
+ */
+struct gl_array_attrib
+{
+ /** Currently bound array object. See _mesa_BindVertexArrayAPPLE() */
+ struct gl_array_object *ArrayObj;
+
+ /** The default vertex array object */
+ struct gl_array_object *DefaultArrayObj;
+
+ /** Array objects (GL_ARB/APPLE_vertex_array_object) */
+ struct _mesa_HashTable *Objects;
+
+ GLint ActiveTexture; /**< Client Active Texture */
+ GLuint LockFirst; /**< GL_EXT_compiled_vertex_array */
+ GLuint LockCount; /**< GL_EXT_compiled_vertex_array */
+
+ /** GL 3.1 (slightly different from GL_NV_primitive_restart) */
+ GLboolean PrimitiveRestart;
+ GLuint RestartIndex;
+
+ GLbitfield NewState; /**< mask of _NEW_ARRAY_* values */
+
+ /* GL_ARB_vertex_buffer_object */
+ struct gl_buffer_object *ArrayBufferObj;
+ struct gl_buffer_object *ElementArrayBufferObj;
+};
+
+
+/**
+ * Feedback buffer state
+ */
+struct gl_feedback
+{
+ GLenum Type;
+ GLbitfield _Mask; /**< FB_* bits */
+ GLfloat *Buffer;
+ GLuint BufferSize;
+ GLuint Count;
+};
+
+
+/**
+ * Selection buffer state
+ */
+struct gl_selection
+{
+ GLuint *Buffer; /**< selection buffer */
+ GLuint BufferSize; /**< size of the selection buffer */
+ GLuint BufferCount; /**< number of values in the selection buffer */
+ GLuint Hits; /**< number of records in the selection buffer */
+ GLuint NameStackDepth; /**< name stack depth */
+ GLuint NameStack[MAX_NAME_STACK_DEPTH]; /**< name stack */
+ GLboolean HitFlag; /**< hit flag */
+ GLfloat HitMinZ; /**< minimum hit depth */
+ GLfloat HitMaxZ; /**< maximum hit depth */
+};
+
+
+/**
+ * 1-D Evaluator control points
+ */
+struct gl_1d_map
+{
+ GLuint Order; /**< Number of control points */
+ GLfloat u1, u2, du; /**< u1, u2, 1.0/(u2-u1) */
+ GLfloat *Points; /**< Points to contiguous control points */
+};
+
+
+/**
+ * 2-D Evaluator control points
+ */
+struct gl_2d_map
+{
+ GLuint Uorder; /**< Number of control points in U dimension */
+ GLuint Vorder; /**< Number of control points in V dimension */
+ GLfloat u1, u2, du;
+ GLfloat v1, v2, dv;
+ GLfloat *Points; /**< Points to contiguous control points */
+};
+
+
+/**
+ * All evaluator control point state
+ */
+struct gl_evaluators
+{
+ /**
+ * \name 1-D maps
+ */
+ /*@{*/
+ struct gl_1d_map Map1Vertex3;
+ struct gl_1d_map Map1Vertex4;
+ struct gl_1d_map Map1Index;
+ struct gl_1d_map Map1Color4;
+ struct gl_1d_map Map1Normal;
+ struct gl_1d_map Map1Texture1;
+ struct gl_1d_map Map1Texture2;
+ struct gl_1d_map Map1Texture3;
+ struct gl_1d_map Map1Texture4;
+ struct gl_1d_map Map1Attrib[16]; /**< GL_NV_vertex_program */
+ /*@}*/
+
+ /**
+ * \name 2-D maps
+ */
+ /*@{*/
+ struct gl_2d_map Map2Vertex3;
+ struct gl_2d_map Map2Vertex4;
+ struct gl_2d_map Map2Index;
+ struct gl_2d_map Map2Color4;
+ struct gl_2d_map Map2Normal;
+ struct gl_2d_map Map2Texture1;
+ struct gl_2d_map Map2Texture2;
+ struct gl_2d_map Map2Texture3;
+ struct gl_2d_map Map2Texture4;
+ struct gl_2d_map Map2Attrib[16]; /**< GL_NV_vertex_program */
+ /*@}*/
+};
+
+
+/**
+ * Names of the various vertex/fragment program register files, etc.
+ *
+ * NOTE: first four tokens must fit into 2 bits (see t_vb_arbprogram.c)
+ * All values should fit in a 4-bit field.
+ *
+ * NOTE: PROGRAM_ENV_PARAM, PROGRAM_STATE_VAR, PROGRAM_NAMED_PARAM,
+ * PROGRAM_CONSTANT, and PROGRAM_UNIFORM can all be considered to
+ * be "uniform" variables since they can only be set outside glBegin/End.
+ * They're also all stored in the same Parameters array.
+ */
+typedef enum
+{
+ PROGRAM_TEMPORARY, /**< machine->Temporary[] */
+ PROGRAM_INPUT, /**< machine->Inputs[] */
+ PROGRAM_OUTPUT, /**< machine->Outputs[] */
+ PROGRAM_VARYING, /**< machine->Inputs[]/Outputs[] */
+ PROGRAM_LOCAL_PARAM, /**< gl_program->LocalParams[] */
+ PROGRAM_ENV_PARAM, /**< gl_program->Parameters[] */
+ PROGRAM_STATE_VAR, /**< gl_program->Parameters[] */
+ PROGRAM_NAMED_PARAM, /**< gl_program->Parameters[] */
+ PROGRAM_CONSTANT, /**< gl_program->Parameters[] */
+ PROGRAM_UNIFORM, /**< gl_program->Parameters[] */
+ PROGRAM_WRITE_ONLY, /**< A dummy, write-only register */
+ PROGRAM_ADDRESS, /**< machine->AddressReg */
+ PROGRAM_SAMPLER, /**< for shader samplers, compile-time only */
+ PROGRAM_SYSTEM_VALUE,/**< InstanceId, PrimitiveID, etc. */
+ PROGRAM_UNDEFINED, /**< Invalid/TBD value */
+ PROGRAM_FILE_MAX
+} gl_register_file;
+
+
+/**
+ * If the register file is PROGRAM_SYSTEM_VALUE, the register index will be
+ * one of these values.
+ */
+typedef enum
+{
+ SYSTEM_VALUE_FRONT_FACE, /**< Fragment shader only (not done yet) */
+ SYSTEM_VALUE_INSTANCE_ID, /**< Vertex shader only */
+ SYSTEM_VALUE_MAX /**< Number of values */
+} gl_system_value;
+
+
+/** Vertex and fragment instructions */
+struct prog_instruction;
+struct gl_program_parameter_list;
+struct gl_uniform_list;
+
+
+/**
+ * Base class for any kind of program object
+ */
+struct gl_program
+{
+ GLuint Id;
+ GLubyte *String; /**< Null-terminated program text */
+ GLint RefCount;
+ GLenum Target; /**< GL_VERTEX/FRAGMENT_PROGRAM_ARB, GL_FRAGMENT_PROGRAM_NV */
+ GLenum Format; /**< String encoding format */
+ GLboolean Resident;
+
+ struct prog_instruction *Instructions;
+
+ GLbitfield InputsRead; /**< Bitmask of which input regs are read */
+ GLbitfield64 OutputsWritten; /**< Bitmask of which output regs are written */
+ GLbitfield SystemValuesRead; /**< Bitmask of SYSTEM_VALUE_x inputs used */
+ GLbitfield InputFlags[MAX_PROGRAM_INPUTS]; /**< PROG_PARAM_BIT_x flags */
+ GLbitfield OutputFlags[MAX_PROGRAM_OUTPUTS]; /**< PROG_PARAM_BIT_x flags */
+ GLbitfield TexturesUsed[MAX_TEXTURE_UNITS]; /**< TEXTURE_x_BIT bitmask */
+ GLbitfield SamplersUsed; /**< Bitfield of which samplers are used */
+ GLbitfield ShadowSamplers; /**< Texture units used for shadow sampling. */
+
+
+ /** Named parameters, constants, etc. from program text */
+ struct gl_program_parameter_list *Parameters;
+ /** Numbered local parameters */
+ GLfloat LocalParams[MAX_PROGRAM_LOCAL_PARAMS][4];
+
+ /** Vertex/fragment shader varying vars */
+ struct gl_program_parameter_list *Varying;
+ /** Vertex program user-defined attributes */
+ struct gl_program_parameter_list *Attributes;
+
+ /** Map from sampler unit to texture unit (set by glUniform1i()) */
+ GLubyte SamplerUnits[MAX_SAMPLERS];
+ /** Which texture target is being sampled (TEXTURE_1D/2D/3D/etc_INDEX) */
+ gl_texture_index SamplerTargets[MAX_SAMPLERS];
+
+ /** Bitmask of which register files are read/written with indirect
+ * addressing. Mask of (1 << PROGRAM_x) bits.
+ */
+ GLbitfield IndirectRegisterFiles;
+
+ /** Logical counts */
+ /*@{*/
+ GLuint NumInstructions;
+ GLuint NumTemporaries;
+ GLuint NumParameters;
+ GLuint NumAttributes;
+ GLuint NumAddressRegs;
+ GLuint NumAluInstructions;
+ GLuint NumTexInstructions;
+ GLuint NumTexIndirections;
+ /*@}*/
+ /** Native, actual h/w counts */
+ /*@{*/
+ GLuint NumNativeInstructions;
+ GLuint NumNativeTemporaries;
+ GLuint NumNativeParameters;
+ GLuint NumNativeAttributes;
+ GLuint NumNativeAddressRegs;
+ GLuint NumNativeAluInstructions;
+ GLuint NumNativeTexInstructions;
+ GLuint NumNativeTexIndirections;
+ /*@}*/
+};
+
+
+/** Vertex program object */
+struct gl_vertex_program
+{
+ struct gl_program Base; /**< base class */
+ GLboolean IsNVProgram; /**< is this a GL_NV_vertex_program program? */
+ GLboolean IsPositionInvariant;
+};
+
+
+/** Geometry program object */
+struct gl_geometry_program
+{
+ struct gl_program Base; /**< base class */
+
+ GLint VerticesOut;
+ GLenum InputType; /**< GL_POINTS, GL_LINES, GL_LINES_ADJACENCY_ARB,
+ GL_TRIANGLES, or GL_TRIANGLES_ADJACENCY_ARB */
+ GLenum OutputType; /**< GL_POINTS, GL_LINE_STRIP or GL_TRIANGLE_STRIP */
+};
+
+
+/** Fragment program object */
+struct gl_fragment_program
+{
+ struct gl_program Base; /**< base class */
+ GLenum FogOption;
+ GLboolean UsesKill; /**< shader uses KIL instruction */
+ GLboolean OriginUpperLeft;
+ GLboolean PixelCenterInteger;
+ enum gl_frag_depth_layout FragDepthLayout;
+};
+
+
+/**
+ * State common to vertex and fragment programs.
+ */
+struct gl_program_state
+{
+ GLint ErrorPos; /* GL_PROGRAM_ERROR_POSITION_ARB/NV */
+ const char *ErrorString; /* GL_PROGRAM_ERROR_STRING_ARB/NV */
+};
+
+
+/**
+ * Context state for vertex programs.
+ */
+struct gl_vertex_program_state
+{
+ GLboolean Enabled; /**< User-set GL_VERTEX_PROGRAM_ARB/NV flag */
+ GLboolean _Enabled; /**< Enabled and _valid_ user program? */
+ GLboolean PointSizeEnabled; /**< GL_VERTEX_PROGRAM_POINT_SIZE_ARB/NV */
+ GLboolean TwoSideEnabled; /**< GL_VERTEX_PROGRAM_TWO_SIDE_ARB/NV */
+ struct gl_vertex_program *Current; /**< User-bound vertex program */
+
+ /** Currently enabled and valid vertex program (including internal
+ * programs, user-defined vertex programs and GLSL vertex shaders).
+ * This is the program we must use when rendering.
+ */
+ struct gl_vertex_program *_Current;
+
+ GLfloat Parameters[MAX_PROGRAM_ENV_PARAMS][4]; /**< Env params */
+
+ /* For GL_NV_vertex_program only: */
+ GLenum TrackMatrix[MAX_PROGRAM_ENV_PARAMS / 4];
+ GLenum TrackMatrixTransform[MAX_PROGRAM_ENV_PARAMS / 4];
+
+ /** Should fixed-function T&L be implemented with a vertex prog? */
+ GLboolean _MaintainTnlProgram;
+
+ /** Program to emulate fixed-function T&L (see above) */
+ struct gl_vertex_program *_TnlProgram;
+
+ /** Cache of fixed-function programs */
+ struct gl_program_cache *Cache;
+
+ GLboolean _Overriden;
+};
+
+
+/**
+ * Context state for geometry programs.
+ */
+struct gl_geometry_program_state
+{
+ GLboolean Enabled; /**< GL_ARB_GEOMETRY_SHADER4 */
+ GLboolean _Enabled; /**< Enabled and valid program? */
+ struct gl_geometry_program *Current; /**< user-bound geometry program */
+
+ /** Currently enabled and valid program (including internal programs
+ * and compiled shader programs).
+ */
+ struct gl_geometry_program *_Current;
+
+ GLfloat Parameters[MAX_PROGRAM_ENV_PARAMS][4]; /**< Env params */
+
+ /** Cache of fixed-function programs */
+ struct gl_program_cache *Cache;
+};
+
+/**
+ * Context state for fragment programs.
+ */
+struct gl_fragment_program_state
+{
+ GLboolean Enabled; /**< User-set fragment program enable flag */
+ GLboolean _Enabled; /**< Enabled and _valid_ user program? */
+ struct gl_fragment_program *Current; /**< User-bound fragment program */
+
+ /** Currently enabled and valid fragment program (including internal
+ * programs, user-defined fragment programs and GLSL fragment shaders).
+ * This is the program we must use when rendering.
+ */
+ struct gl_fragment_program *_Current;
+
+ GLfloat Parameters[MAX_PROGRAM_ENV_PARAMS][4]; /**< Env params */
+
+ /** Should fixed-function texturing be implemented with a fragment prog? */
+ GLboolean _MaintainTexEnvProgram;
+
+ /** Program to emulate fixed-function texture env/combine (see above) */
+ struct gl_fragment_program *_TexEnvProgram;
+
+ /** Cache of fixed-function programs */
+ struct gl_program_cache *Cache;
+};
+
+
+/**
+ * ATI_fragment_shader runtime state
+ */
+#define ATI_FS_INPUT_PRIMARY 0
+#define ATI_FS_INPUT_SECONDARY 1
+
+struct atifs_instruction;
+struct atifs_setupinst;
+
+/**
+ * ATI fragment shader
+ */
+struct ati_fragment_shader
+{
+ GLuint Id;
+ GLint RefCount;
+ struct atifs_instruction *Instructions[2];
+ struct atifs_setupinst *SetupInst[2];
+ GLfloat Constants[8][4];
+ GLbitfield LocalConstDef; /**< Indicates which constants have been set */
+ GLubyte numArithInstr[2];
+ GLubyte regsAssigned[2];
+ GLubyte NumPasses; /**< 1 or 2 */
+ GLubyte cur_pass;
+ GLubyte last_optype;
+ GLboolean interpinp1;
+ GLboolean isValid;
+ GLuint swizzlerq;
+};
+
+/**
+ * Context state for GL_ATI_fragment_shader
+ */
+struct gl_ati_fragment_shader_state
+{
+ GLboolean Enabled;
+ GLboolean _Enabled; /**< enabled and valid shader? */
+ GLboolean Compiling;
+ GLfloat GlobalConstants[8][4];
+ struct ati_fragment_shader *Current;
+};
+
+
+/**
+ * Occlusion/timer query object.
+ */
+struct gl_query_object
+{
+ GLenum Target; /**< The query target, when active */
+ GLuint Id; /**< hash table ID/name */
+ GLuint64EXT Result; /**< the counter */
+ GLboolean Active; /**< inside Begin/EndQuery */
+ GLboolean Ready; /**< result is ready? */
+};
+
+
+/**
+ * Context state for query objects.
+ */
+struct gl_query_state
+{
+ struct _mesa_HashTable *QueryObjects;
+ struct gl_query_object *CurrentOcclusionObject; /* GL_ARB_occlusion_query */
+ struct gl_query_object *CurrentTimerObject; /* GL_EXT_timer_query */
+
+ /** GL_NV_conditional_render */
+ struct gl_query_object *CondRenderQuery;
+
+ /** GL_EXT_transform_feedback */
+ struct gl_query_object *PrimitivesGenerated;
+ struct gl_query_object *PrimitivesWritten;
+
+ /** GL_ARB_timer_query */
+ struct gl_query_object *TimeElapsed;
+
+ GLenum CondRenderMode;
+};
+
+
+/** Sync object state */
+struct gl_sync_object {
+ struct simple_node link;
+ GLenum Type; /**< GL_SYNC_FENCE */
+ GLuint Name; /**< Fence name */
+ GLint RefCount; /**< Reference count */
+ GLboolean DeletePending; /**< Object was deleted while there were still
+ * live references (e.g., sync not yet finished)
+ */
+ GLenum SyncCondition;
+ GLbitfield Flags; /**< Flags passed to glFenceSync */
+ GLuint StatusFlag:1; /**< Has the sync object been signaled? */
+};
+
+
+/** Set by #pragma directives */
+struct gl_sl_pragmas
+{
+ GLboolean IgnoreOptimize; /**< ignore #pragma optimize(on/off) ? */
+ GLboolean IgnoreDebug; /**< ignore #pragma debug(on/off) ? */
+ GLboolean Optimize; /**< defaults on */
+ GLboolean Debug; /**< defaults off */
+};
+
+
+/**
+ * A GLSL vertex or fragment shader object.
+ */
+struct gl_shader
+{
+ GLenum Type; /**< GL_FRAGMENT_SHADER || GL_VERTEX_SHADER || GL_GEOMETRY_SHADER_ARB (first field!) */
+ GLuint Name; /**< AKA the handle */
+ GLint RefCount; /**< Reference count */
+ GLboolean DeletePending;
+ GLboolean CompileStatus;
+ const GLchar *Source; /**< Source code string */
+ GLuint SourceChecksum; /**< for debug/logging purposes */
+ struct gl_program *Program; /**< Post-compile assembly code */
+ GLchar *InfoLog;
+ struct gl_sl_pragmas Pragmas;
+
+ unsigned Version; /**< GLSL version used for linking */
+
+ struct exec_list *ir;
+ struct glsl_symbol_table *symbols;
+
+ /** Shaders containing built-in functions that are used for linking. */
+ struct gl_shader *builtins_to_link[16];
+ unsigned num_builtins_to_link;
+};
+
+
+/**
+ * A GLSL program object.
+ * Basically a linked collection of vertex and fragment shaders.
+ */
+struct gl_shader_program
+{
+ GLenum Type; /**< Always GL_SHADER_PROGRAM (internal token) */
+ GLuint Name; /**< aka handle or ID */
+ GLint RefCount; /**< Reference count */
+ GLboolean DeletePending;
+
+ GLuint NumShaders; /**< number of attached shaders */
+ struct gl_shader **Shaders; /**< List of attached the shaders */
+
+ /** User-defined attribute bindings (glBindAttribLocation) */
+ struct gl_program_parameter_list *Attributes;
+
+ /** Transform feedback varyings */
+ struct {
+ GLenum BufferMode;
+ GLuint NumVarying;
+ GLchar **VaryingNames; /**< Array [NumVarying] of char * */
+ } TransformFeedback;
+
+ /** Geometry shader state - copied into gl_geometry_program at link time */
+ struct {
+ GLint VerticesOut;
+ GLenum InputType; /**< GL_POINTS, GL_LINES, GL_LINES_ADJACENCY_ARB,
+ GL_TRIANGLES, or GL_TRIANGLES_ADJACENCY_ARB */
+ GLenum OutputType; /**< GL_POINTS, GL_LINE_STRIP or GL_TRIANGLE_STRIP */
+ } Geom;
+
+ /* post-link info: */
+ struct gl_vertex_program *VertexProgram; /**< Linked vertex program */
+ struct gl_fragment_program *FragmentProgram; /**< Linked fragment prog */
+ struct gl_geometry_program *GeometryProgram; /**< Linked geometry prog */
+ struct gl_uniform_list *Uniforms;
+ struct gl_program_parameter_list *Varying;
+ GLboolean LinkStatus; /**< GL_LINK_STATUS */
+ GLboolean Validated;
+ GLboolean _Used; /**< Ever used for drawing? */
+ GLchar *InfoLog;
+
+ unsigned Version; /**< GLSL version used for linking */
+
+ /**
+ * Per-stage shaders resulting from the first stage of linking.
+ *
+ * Set of linked shaders for this program. The array is accessed using the
+ * \c MESA_SHADER_* defines. Entries for non-existent stages will be
+ * \c NULL.
+ */
+ struct gl_shader *_LinkedShaders[MESA_SHADER_TYPES];
+};
+
+
+#define GLSL_DUMP 0x1 /**< Dump shaders to stdout */
+#define GLSL_LOG 0x2 /**< Write shaders to files */
+#define GLSL_OPT 0x4 /**< Force optimizations (override pragmas) */
+#define GLSL_NO_OPT 0x8 /**< Force no optimizations (override pragmas) */
+#define GLSL_UNIFORMS 0x10 /**< Print glUniform calls */
+#define GLSL_NOP_VERT 0x20 /**< Force no-op vertex shaders */
+#define GLSL_NOP_FRAG 0x40 /**< Force no-op fragment shaders */
+#define GLSL_USE_PROG 0x80 /**< Log glUseProgram calls */
+
+
+/**
+ * Context state for GLSL vertex/fragment shaders.
+ */
+struct gl_shader_state
+{
+ /**
+ * Programs used for rendering
+ *
+ * There is a separate program set for each shader stage. If
+ * GL_EXT_separate_shader_objects is not supported, each of these must point
+ * to \c NULL or to the same program.
+ */
+ struct gl_shader_program *CurrentVertexProgram;
+ struct gl_shader_program *CurrentGeometryProgram;
+ struct gl_shader_program *CurrentFragmentProgram;
+
+ /**
+ * Program used by glUniform calls.
+ *
+ * Explicitly set by \c glUseProgram and \c glActiveProgramEXT.
+ */
+ struct gl_shader_program *ActiveProgram;
+
+ void *MemPool;
+
+ GLbitfield Flags; /**< Mask of GLSL_x flags */
+};
+
+/**
+ * Compiler options for a single GLSL shaders type
+ */
+struct gl_shader_compiler_options
+{
+ /** Driver-selectable options: */
+ GLboolean EmitCondCodes; /**< Use condition codes? */
+ GLboolean EmitNVTempInitialization; /**< 0-fill NV temp registers */
+ /**
+ * Attempts to flatten all ir_if (OPCODE_IF) for GPUs that can't
+ * support control flow.
+ */
+ GLboolean EmitNoIfs;
+ GLboolean EmitNoLoops;
+ GLboolean EmitNoFunctions;
+ GLboolean EmitNoCont; /**< Emit CONT opcode? */
+ GLboolean EmitNoMainReturn; /**< Emit CONT/RET opcodes? */
+ GLboolean EmitNoNoise; /**< Emit NOISE opcodes? */
+ GLboolean EmitNoPow; /**< Emit POW opcodes? */
+
+ /**
+ * \name Forms of indirect addressing the driver cannot do.
+ */
+ /*@{*/
+ GLboolean EmitNoIndirectInput; /**< No indirect addressing of inputs */
+ GLboolean EmitNoIndirectOutput; /**< No indirect addressing of outputs */
+ GLboolean EmitNoIndirectTemp; /**< No indirect addressing of temps */
+ GLboolean EmitNoIndirectUniform; /**< No indirect addressing of constants */
+ /*@}*/
+
+ GLuint MaxUnrollIterations;
+
+ struct gl_sl_pragmas DefaultPragmas; /**< Default #pragma settings */
+};
+
+/**
+ * Transform feedback object state
+ */
+struct gl_transform_feedback_object
+{
+ GLuint Name; /**< AKA the object ID */
+ GLint RefCount;
+ GLboolean Active; /**< Is transform feedback enabled? */
+ GLboolean Paused; /**< Is transform feedback paused? */
+
+ /** The feedback buffers */
+ GLuint BufferNames[MAX_FEEDBACK_ATTRIBS];
+ struct gl_buffer_object *Buffers[MAX_FEEDBACK_ATTRIBS];
+
+ /** Start of feedback data in dest buffer */
+ GLintptr Offset[MAX_FEEDBACK_ATTRIBS];
+ /** Max data to put into dest buffer (in bytes) */
+ GLsizeiptr Size[MAX_FEEDBACK_ATTRIBS];
+};
+
+
+/**
+ * Context state for transform feedback.
+ */
+struct gl_transform_feedback
+{
+ GLenum Mode; /**< GL_POINTS, GL_LINES or GL_TRIANGLES */
+
+ GLboolean RasterDiscard; /**< GL_RASTERIZER_DISCARD */
+
+ /** The general binding point (GL_TRANSFORM_FEEDBACK_BUFFER) */
+ struct gl_buffer_object *CurrentBuffer;
+
+ /** The table of all transform feedback objects */
+ struct _mesa_HashTable *Objects;
+
+ /** The current xform-fb object (GL_TRANSFORM_FEEDBACK_BINDING) */
+ struct gl_transform_feedback_object *CurrentObject;
+
+ /** The default xform-fb object (Name==0) */
+ struct gl_transform_feedback_object *DefaultObject;
+};
+
+
+
+/**
+ * State which can be shared by multiple contexts:
+ */
+struct gl_shared_state
+{
+ _glthread_Mutex Mutex; /**< for thread safety */
+ GLint RefCount; /**< Reference count */
+ struct _mesa_HashTable *DisplayList; /**< Display lists hash table */
+ struct _mesa_HashTable *TexObjects; /**< Texture objects hash table */
+
+ /** Default texture objects (shared by all texture units) */
+ struct gl_texture_object *DefaultTex[NUM_TEXTURE_TARGETS];
+
+ /** Fallback texture used when a bound texture is incomplete */
+ struct gl_texture_object *FallbackTex;
+
+ /**
+ * \name Thread safety and statechange notification for texture
+ * objects.
+ *
+ * \todo Improve the granularity of locking.
+ */
+ /*@{*/
+ _glthread_Mutex TexMutex; /**< texobj thread safety */
+ GLuint TextureStateStamp; /**< state notification for shared tex */
+ /*@}*/
+
+ /** Default buffer object for vertex arrays that aren't in VBOs */
+ struct gl_buffer_object *NullBufferObj;
+
+ /**
+ * \name Vertex/geometry/fragment programs
+ */
+ /*@{*/
+ struct _mesa_HashTable *Programs; /**< All vertex/fragment programs */
+ struct gl_vertex_program *DefaultVertexProgram;
+ struct gl_fragment_program *DefaultFragmentProgram;
+ struct gl_geometry_program *DefaultGeometryProgram;
+ /*@}*/
+
+ /* GL_ATI_fragment_shader */
+ struct _mesa_HashTable *ATIShaders;
+ struct ati_fragment_shader *DefaultFragmentShader;
+
+ struct _mesa_HashTable *BufferObjects;
+
+ /** Table of both gl_shader and gl_shader_program objects */
+ struct _mesa_HashTable *ShaderObjects;
+
+ /* GL_EXT_framebuffer_object */
+ struct _mesa_HashTable *RenderBuffers;
+ struct _mesa_HashTable *FrameBuffers;
+
+ /* GL_ARB_sync */
+ struct simple_node SyncObjects;
+
+ void *DriverData; /**< Device driver shared state */
+};
+
+
+
+
+/**
+ * A renderbuffer stores colors or depth values or stencil values.
+ * A framebuffer object will have a collection of these.
+ * Data are read/written to the buffer with a handful of Get/Put functions.
+ *
+ * Instances of this object are allocated with the Driver's NewRenderbuffer
+ * hook. Drivers will likely wrap this class inside a driver-specific
+ * class to simulate inheritance.
+ */
+struct gl_renderbuffer
+{
+#define RB_MAGIC 0xaabbccdd
+ int Magic; /** XXX TEMPORARY DEBUG INFO */
+ _glthread_Mutex Mutex; /**< for thread safety */
+ GLuint ClassID; /**< Useful for drivers */
+ GLuint Name;
+ GLint RefCount;
+ GLuint Width, Height;
+ GLboolean Purgeable; /**< Is the buffer purgeable under memory pressure? */
+
+ 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 */
+
+ GLubyte NumSamples;
+
+ GLenum DataType; /**< Type of values passed to the Get/Put functions */
+ GLvoid *Data; /**< This may not be used by some kinds of RBs */
+
+ /* Used to wrap one renderbuffer around another: */
+ struct gl_renderbuffer *Wrapped;
+
+ /* Delete this renderbuffer */
+ void (*Delete)(struct gl_renderbuffer *rb);
+
+ /* Allocate new storage for this renderbuffer */
+ GLboolean (*AllocStorage)(struct gl_context *ctx, struct gl_renderbuffer *rb,
+ GLenum internalFormat,
+ GLuint width, GLuint height);
+
+ /* Lock/Unlock are called before/after calling the Get/Put functions.
+ * Not sure this is the right place for these yet.
+ void (*Lock)(struct gl_context *ctx, struct gl_renderbuffer *rb);
+ void (*Unlock)(struct gl_context *ctx, struct gl_renderbuffer *rb);
+ */
+
+ /* Return a pointer to the element/pixel at (x,y).
+ * Should return NULL if the buffer memory can't be directly addressed.
+ */
+ void *(*GetPointer)(struct gl_context *ctx, struct gl_renderbuffer *rb,
+ GLint x, GLint y);
+
+ /* Get/Read a row of values.
+ * The values will be of format _BaseFormat and type DataType.
+ */
+ void (*GetRow)(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, void *values);
+
+ /* Get/Read values at arbitrary locations.
+ * The values will be of format _BaseFormat and type DataType.
+ */
+ void (*GetValues)(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
+ const GLint x[], const GLint y[], void *values);
+
+ /* Put/Write a row of values.
+ * The values will be of format _BaseFormat and type DataType.
+ */
+ void (*PutRow)(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, const void *values, const GLubyte *mask);
+
+ /* Put/Write a row of RGB values. This is a special-case routine that's
+ * only used for RGBA renderbuffers when the source data is GL_RGB. That's
+ * a common case for glDrawPixels and some triangle routines.
+ * The values will be of format GL_RGB and type DataType.
+ */
+ void (*PutRowRGB)(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, const void *values, const GLubyte *mask);
+
+
+ /* Put/Write a row of identical values.
+ * The values will be of format _BaseFormat and type DataType.
+ */
+ void (*PutMonoRow)(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, const void *value, const GLubyte *mask);
+
+ /* Put/Write values at arbitrary locations.
+ * The values will be of format _BaseFormat and type DataType.
+ */
+ void (*PutValues)(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
+ const GLint x[], const GLint y[], const void *values,
+ const GLubyte *mask);
+ /* Put/Write identical values at arbitrary locations.
+ * The values will be of format _BaseFormat and type DataType.
+ */
+ void (*PutMonoValues)(struct gl_context *ctx, struct gl_renderbuffer *rb,
+ GLuint count, const GLint x[], const GLint y[],
+ const void *value, const GLubyte *mask);
+};
+
+
+/**
+ * A renderbuffer attachment points to either a texture object (and specifies
+ * a mipmap level, cube face or 3D texture slice) or points to a renderbuffer.
+ */
+struct gl_renderbuffer_attachment
+{
+ GLenum Type; /**< \c GL_NONE or \c GL_TEXTURE or \c GL_RENDERBUFFER_EXT */
+ GLboolean Complete;
+
+ /**
+ * If \c Type is \c GL_RENDERBUFFER_EXT, this stores a pointer to the
+ * application supplied renderbuffer object.
+ */
+ struct gl_renderbuffer *Renderbuffer;
+
+ /**
+ * If \c Type is \c GL_TEXTURE, this stores a pointer to the application
+ * supplied texture object.
+ */
+ struct gl_texture_object *Texture;
+ GLuint TextureLevel; /**< Attached mipmap level. */
+ GLuint CubeMapFace; /**< 0 .. 5, for cube map textures. */
+ GLuint Zoffset; /**< Slice for 3D textures, or layer for both 1D
+ * and 2D array textures */
+};
+
+
+/**
+ * A framebuffer is a collection of renderbuffers (color, depth, stencil, etc).
+ * In C++ terms, think of this as a base class from which device drivers
+ * will make derived classes.
+ */
+struct gl_framebuffer
+{
+ _glthread_Mutex Mutex; /**< for thread safety */
+ /**
+ * If zero, this is a window system framebuffer. If non-zero, this
+ * is a FBO framebuffer; note that for some devices (i.e. those with
+ * a natural pixel coordinate system for FBOs that differs from the
+ * OpenGL/Mesa coordinate system), this means that the viewport,
+ * polygon face orientation, and polygon stipple will have to be inverted.
+ */
+ GLuint Name;
+
+ GLint RefCount;
+ GLboolean DeletePending;
+
+ /**
+ * The framebuffer's visual. Immutable if this is a window system buffer.
+ * Computed from attachments if user-made FBO.
+ */
+ struct gl_config Visual;
+
+ GLboolean Initialized;
+
+ GLuint Width, Height; /**< size of frame buffer in pixels */
+
+ /** \name Drawing bounds (Intersection of buffer size and scissor box) */
+ /*@{*/
+ GLint _Xmin, _Xmax; /**< inclusive */
+ GLint _Ymin, _Ymax; /**< exclusive */
+ /*@}*/
+
+ /** \name Derived Z buffer stuff */
+ /*@{*/
+ GLuint _DepthMax; /**< Max depth buffer value */
+ GLfloat _DepthMaxF; /**< Float max depth buffer value */
+ GLfloat _MRD; /**< minimum resolvable difference in Z values */
+ /*@}*/
+
+ /** One of the GL_FRAMEBUFFER_(IN)COMPLETE_* tokens */
+ GLenum _Status;
+
+ /** Integer color values */
+ GLboolean _IntegerColor;
+
+ /** Array of all renderbuffer attachments, indexed by BUFFER_* tokens. */
+ struct gl_renderbuffer_attachment Attachment[BUFFER_COUNT];
+
+ /* In unextended OpenGL these vars are part of the GL_COLOR_BUFFER
+ * attribute group and GL_PIXEL attribute group, respectively.
+ */
+ GLenum ColorDrawBuffer[MAX_DRAW_BUFFERS];
+ GLenum ColorReadBuffer;
+
+ /** Computed from ColorDraw/ReadBuffer above */
+ GLuint _NumColorDrawBuffers;
+ GLint _ColorDrawBufferIndexes[MAX_DRAW_BUFFERS]; /**< BUFFER_x or -1 */
+ GLint _ColorReadBufferIndex; /* -1 = None */
+ struct gl_renderbuffer *_ColorDrawBuffers[MAX_DRAW_BUFFERS];
+ struct gl_renderbuffer *_ColorReadBuffer;
+
+ /** The Actual depth/stencil buffers to use. May be wrappers around the
+ * depth/stencil buffers attached above. */
+ struct gl_renderbuffer *_DepthBuffer;
+ struct gl_renderbuffer *_StencilBuffer;
+
+ /** Delete this framebuffer */
+ void (*Delete)(struct gl_framebuffer *fb);
+};
+
+
+/**
+ * Precision info for shader datatypes. See glGetShaderPrecisionFormat().
+ */
+struct gl_precision
+{
+ GLushort RangeMin; /**< min value exponent */
+ GLushort RangeMax; /**< max value exponent */
+ GLushort Precision; /**< number of mantissa bits */
+};
+
+
+/**
+ * Limits for vertex and fragment programs/shaders.
+ */
+struct gl_program_constants
+{
+ /* logical limits */
+ GLuint MaxInstructions;
+ GLuint MaxAluInstructions;
+ GLuint MaxTexInstructions;
+ GLuint MaxTexIndirections;
+ GLuint MaxAttribs;
+ GLuint MaxTemps;
+ GLuint MaxAddressRegs;
+ GLuint MaxParameters;
+ GLuint MaxLocalParams;
+ GLuint MaxEnvParams;
+ /* native/hardware limits */
+ GLuint MaxNativeInstructions;
+ GLuint MaxNativeAluInstructions;
+ GLuint MaxNativeTexInstructions;
+ GLuint MaxNativeTexIndirections;
+ GLuint MaxNativeAttribs;
+ GLuint MaxNativeTemps;
+ GLuint MaxNativeAddressRegs;
+ GLuint MaxNativeParameters;
+ /* For shaders */
+ GLuint MaxUniformComponents;
+ /* GL_ARB_geometry_shader4 */
+ GLuint MaxGeometryTextureImageUnits;
+ GLuint MaxGeometryVaryingComponents;
+ GLuint MaxVertexVaryingComponents;
+ GLuint MaxGeometryUniformComponents;
+ GLuint MaxGeometryOutputVertices;
+ GLuint MaxGeometryTotalOutputComponents;
+ /* ES 2.0 and GL_ARB_ES2_compatibility */
+ struct gl_precision LowFloat, MediumFloat, HighFloat;
+ struct gl_precision LowInt, MediumInt, HighInt;
+};
+
+
+/**
+ * Constants which may be overridden by device driver during context creation
+ * but are never changed after that.
+ */
+struct gl_constants
+{
+ GLint MaxTextureMbytes; /**< Max memory per image, in MB */
+ GLint MaxTextureLevels; /**< Max mipmap levels. */
+ GLint Max3DTextureLevels; /**< Max mipmap levels for 3D textures */
+ GLint MaxCubeTextureLevels; /**< Max mipmap levels for cube textures */
+ GLint MaxArrayTextureLayers; /**< Max layers in array textures */
+ GLint MaxTextureRectSize; /**< Max rectangle texture size, in pixes */
+ GLuint MaxTextureCoordUnits;
+ GLuint MaxTextureImageUnits;
+ GLuint MaxVertexTextureImageUnits;
+ GLuint MaxCombinedTextureImageUnits;
+ GLuint MaxTextureUnits; /**< = MIN(CoordUnits, ImageUnits) */
+ GLfloat MaxTextureMaxAnisotropy; /**< GL_EXT_texture_filter_anisotropic */
+ GLfloat MaxTextureLodBias; /**< GL_EXT_texture_lod_bias */
+
+ GLuint MaxArrayLockSize;
+
+ GLint SubPixelBits;
+
+ GLfloat MinPointSize, MaxPointSize; /**< aliased */
+ GLfloat MinPointSizeAA, MaxPointSizeAA; /**< antialiased */
+ GLfloat PointSizeGranularity;
+ GLfloat MinLineWidth, MaxLineWidth; /**< aliased */
+ GLfloat MinLineWidthAA, MaxLineWidthAA; /**< antialiased */
+ GLfloat LineWidthGranularity;
+
+ GLuint MaxColorTableSize;
+
+ GLuint MaxClipPlanes;
+ GLuint MaxLights;
+ GLfloat MaxShininess; /**< GL_NV_light_max_exponent */
+ GLfloat MaxSpotExponent; /**< GL_NV_light_max_exponent */
+
+ GLuint MaxViewportWidth, MaxViewportHeight;
+
+ struct gl_program_constants VertexProgram; /**< GL_ARB_vertex_program */
+ struct gl_program_constants FragmentProgram; /**< GL_ARB_fragment_program */
+ struct gl_program_constants GeometryProgram; /**< GL_ARB_geometry_shader4 */
+ GLuint MaxProgramMatrices;
+ GLuint MaxProgramMatrixStackDepth;
+
+ /** vertex array / buffer object bounds checking */
+ GLboolean CheckArrayBounds;
+
+ GLuint MaxDrawBuffers; /**< GL_ARB_draw_buffers */
+
+ GLuint MaxColorAttachments; /**< GL_EXT_framebuffer_object */
+ GLuint MaxRenderbufferSize; /**< GL_EXT_framebuffer_object */
+ GLuint MaxSamples; /**< GL_ARB_framebuffer_object */
+
+ GLuint MaxVarying; /**< Number of float[4] varying parameters */
+
+ GLuint GLSLVersion; /**< GLSL version supported (ex: 120 = 1.20) */
+
+ /** Which texture units support GL_ATI_envmap_bumpmap as targets */
+ GLbitfield SupportedBumpUnits;
+
+ /**
+ * Maximum amount of time, measured in nanseconds, that the server can wait.
+ */
+ GLuint64 MaxServerWaitTimeout;
+
+ /** GL_EXT_provoking_vertex */
+ GLboolean QuadsFollowProvokingVertexConvention;
+
+ /** OpenGL version 3.0 */
+ GLbitfield ContextFlags; /**< Ex: GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT */
+
+ /** OpenGL version 3.2 */
+ GLbitfield ProfileMask; /**< Mask of CONTEXT_x_PROFILE_BIT */
+
+ /** GL_EXT_transform_feedback */
+ GLuint MaxTransformFeedbackSeparateAttribs;
+ GLuint MaxTransformFeedbackSeparateComponents;
+ GLuint MaxTransformFeedbackInterleavedComponents;
+
+ /** GL_EXT_gpu_shader4 */
+ GLint MinProgramTexelOffset, MaxProgramTexelOffset;
+
+ /* GL_EXT_framebuffer_sRGB */
+ GLboolean sRGBCapable; /* can enable sRGB blend/update on FBOs */
+};
+
+
+/**
+ * Enable flag for each OpenGL extension. Different device drivers will
+ * enable different extensions at runtime.
+ */
+struct gl_extensions
+{
+ GLboolean dummy; /* don't remove this! */
+ GLboolean dummy_true; /* Set true by _mesa_init_extensions(). */
+ GLboolean dummy_false; /* Set false by _mesa_init_extensions(). */
+ GLboolean ARB_ES2_compatibility;
+ GLboolean ARB_blend_func_extended;
+ GLboolean ARB_copy_buffer;
+ GLboolean ARB_depth_buffer_float;
+ GLboolean ARB_depth_clamp;
+ GLboolean ARB_depth_texture;
+ GLboolean ARB_draw_buffers;
+ GLboolean ARB_draw_buffers_blend;
+ GLboolean ARB_draw_elements_base_vertex;
+ GLboolean ARB_draw_instanced;
+ GLboolean ARB_fragment_coord_conventions;
+ GLboolean ARB_fragment_program;
+ GLboolean ARB_fragment_program_shadow;
+ GLboolean ARB_fragment_shader;
+ GLboolean ARB_framebuffer_object;
+ GLboolean ARB_explicit_attrib_location;
+ GLboolean ARB_geometry_shader4;
+ GLboolean ARB_half_float_pixel;
+ GLboolean ARB_half_float_vertex;
+ GLboolean ARB_instanced_arrays;
+ GLboolean ARB_map_buffer_range;
+ GLboolean ARB_multisample;
+ GLboolean ARB_multitexture;
+ GLboolean ARB_occlusion_query;
+ GLboolean ARB_occlusion_query2;
+ GLboolean ARB_point_sprite;
+ GLboolean ARB_sampler_objects;
+ GLboolean ARB_seamless_cube_map;
+ GLboolean ARB_shader_objects;
+ GLboolean ARB_shader_stencil_export;
+ GLboolean ARB_shading_language_100;
+ GLboolean ARB_shadow;
+ GLboolean ARB_shadow_ambient;
+ GLboolean ARB_sync;
+ GLboolean ARB_texture_border_clamp;
+ GLboolean ARB_texture_buffer_object;
+ GLboolean ARB_texture_compression;
+ GLboolean ARB_texture_compression_rgtc;
+ GLboolean ARB_texture_cube_map;
+ GLboolean ARB_texture_env_combine;
+ GLboolean ARB_texture_env_crossbar;
+ GLboolean ARB_texture_env_dot3;
+ GLboolean ARB_texture_float;
+ GLboolean ARB_texture_mirrored_repeat;
+ GLboolean ARB_texture_multisample;
+ GLboolean ARB_texture_non_power_of_two;
+ GLboolean ARB_texture_rg;
+ GLboolean ARB_texture_rgb10_a2ui;
+ GLboolean ARB_timer_query;
+ GLboolean ARB_transform_feedback2;
+ GLboolean ARB_transpose_matrix;
+ GLboolean ARB_uniform_buffer_object;
+ GLboolean ARB_vertex_array_object;
+ GLboolean ARB_vertex_buffer_object;
+ GLboolean ARB_vertex_program;
+ GLboolean ARB_vertex_shader;
+ GLboolean ARB_vertex_type_2_10_10_10_rev;
+ GLboolean ARB_window_pos;
+ GLboolean EXT_abgr;
+ GLboolean EXT_bgra;
+ GLboolean EXT_blend_color;
+ GLboolean EXT_blend_equation_separate;
+ GLboolean EXT_blend_func_separate;
+ GLboolean EXT_blend_logic_op;
+ GLboolean EXT_blend_minmax;
+ GLboolean EXT_blend_subtract;
+ GLboolean EXT_clip_volume_hint;
+ GLboolean EXT_compiled_vertex_array;
+ GLboolean EXT_copy_texture;
+ GLboolean EXT_depth_bounds_test;
+ GLboolean EXT_draw_buffers2;
+ GLboolean EXT_draw_range_elements;
+ GLboolean EXT_fog_coord;
+ GLboolean EXT_framebuffer_blit;
+ GLboolean EXT_framebuffer_multisample;
+ GLboolean EXT_framebuffer_object;
+ GLboolean EXT_framebuffer_sRGB;
+ GLboolean EXT_gpu_program_parameters;
+ GLboolean EXT_gpu_shader4;
+ GLboolean EXT_multi_draw_arrays;
+ GLboolean EXT_paletted_texture;
+ GLboolean EXT_packed_depth_stencil;
+ GLboolean EXT_packed_float;
+ GLboolean EXT_packed_pixels;
+ GLboolean EXT_pixel_buffer_object;
+ GLboolean EXT_point_parameters;
+ GLboolean EXT_polygon_offset;
+ GLboolean EXT_provoking_vertex;
+ GLboolean EXT_rescale_normal;
+ GLboolean EXT_shadow_funcs;
+ GLboolean EXT_secondary_color;
+ GLboolean EXT_separate_shader_objects;
+ GLboolean EXT_separate_specular_color;
+ GLboolean EXT_shared_texture_palette;
+ GLboolean EXT_stencil_wrap;
+ GLboolean EXT_stencil_two_side;
+ GLboolean EXT_subtexture;
+ GLboolean EXT_texture;
+ GLboolean EXT_texture_object;
+ GLboolean EXT_texture3D;
+ GLboolean EXT_texture_array;
+ GLboolean EXT_texture_compression_s3tc;
+ GLboolean EXT_texture_env_add;
+ GLboolean EXT_texture_env_combine;
+ GLboolean EXT_texture_env_dot3;
+ GLboolean EXT_texture_filter_anisotropic;
+ GLboolean EXT_texture_integer;
+ GLboolean EXT_texture_lod_bias;
+ GLboolean EXT_texture_mirror_clamp;
+ GLboolean EXT_texture_shared_exponent;
+ GLboolean EXT_texture_sRGB;
+ GLboolean EXT_texture_sRGB_decode;
+ GLboolean EXT_texture_swizzle;
+ GLboolean EXT_transform_feedback;
+ GLboolean EXT_timer_query;
+ GLboolean EXT_vertex_array;
+ GLboolean EXT_vertex_array_bgra;
+ 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;
+ GLboolean APPLE_object_purgeable;
+ GLboolean ATI_envmap_bumpmap;
+ GLboolean ATI_texture_mirror_once;
+ GLboolean ATI_texture_env_combine3;
+ GLboolean ATI_fragment_shader;
+ GLboolean ATI_separate_stencil;
+ GLboolean IBM_rasterpos_clip;
+ GLboolean IBM_multimode_draw_arrays;
+ GLboolean MESA_pack_invert;
+ GLboolean MESA_resize_buffers;
+ GLboolean MESA_ycbcr_texture;
+ GLboolean MESA_texture_array;
+ GLboolean MESA_texture_signed_rgba;
+ GLboolean NV_blend_square;
+ GLboolean NV_conditional_render;
+ GLboolean NV_fragment_program;
+ GLboolean NV_fragment_program_option;
+ GLboolean NV_light_max_exponent;
+ GLboolean NV_point_sprite;
+ GLboolean NV_primitive_restart;
+ GLboolean NV_texgen_reflection;
+ GLboolean NV_texture_env_combine4;
+ GLboolean NV_texture_rectangle;
+ GLboolean NV_vertex_program;
+ GLboolean NV_vertex_program1_1;
+ GLboolean OES_read_format;
+ GLboolean SGI_texture_color_table;
+ GLboolean SGIS_generate_mipmap;
+ GLboolean SGIS_texture_edge_clamp;
+ GLboolean SGIS_texture_lod;
+ GLboolean TDFX_texture_compression_FXT1;
+ GLboolean S3_s3tc;
+ GLboolean OES_EGL_image;
+ GLboolean OES_draw_texture;
+ GLboolean EXT_texture_format_BGRA8888;
+ GLboolean extension_sentinel;
+ /** The extension string */
+ const GLubyte *String;
+ /** Number of supported extensions */
+ GLuint Count;
+};
+
+
+/**
+ * A stack of matrices (projection, modelview, color, texture, etc).
+ */
+struct gl_matrix_stack
+{
+ GLmatrix *Top; /**< points into Stack */
+ GLmatrix *Stack; /**< array [MaxDepth] of GLmatrix */
+ GLuint Depth; /**< 0 <= Depth < MaxDepth */
+ GLuint MaxDepth; /**< size of Stack[] array */
+ GLuint DirtyFlag; /**< _NEW_MODELVIEW or _NEW_PROJECTION, for example */
+};
+
+
+/**
+ * \name Bits for image transfer operations
+ * \sa __struct gl_contextRec::ImageTransferState.
+ */
+/*@{*/
+#define IMAGE_SCALE_BIAS_BIT 0x1
+#define IMAGE_SHIFT_OFFSET_BIT 0x2
+#define IMAGE_MAP_COLOR_BIT 0x4
+#define IMAGE_CLAMP_BIT 0x800
+
+
+/** Pixel Transfer ops */
+#define IMAGE_BITS (IMAGE_SCALE_BIAS_BIT | \
+ IMAGE_SHIFT_OFFSET_BIT | \
+ IMAGE_MAP_COLOR_BIT)
+
+/**
+ * \name Bits to indicate what state has changed.
+ */
+/*@{*/
+#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
+/*@}*/
+
+
+/**
+ * \name Bits to track array state changes
+ *
+ * Also used to summarize array enabled.
+ */
+/*@{*/
+#define _NEW_ARRAY_VERTEX VERT_BIT_POS
+#define _NEW_ARRAY_WEIGHT VERT_BIT_WEIGHT
+#define _NEW_ARRAY_NORMAL VERT_BIT_NORMAL
+#define _NEW_ARRAY_COLOR0 VERT_BIT_COLOR0
+#define _NEW_ARRAY_COLOR1 VERT_BIT_COLOR1
+#define _NEW_ARRAY_FOGCOORD VERT_BIT_FOG
+#define _NEW_ARRAY_INDEX VERT_BIT_COLOR_INDEX
+#define _NEW_ARRAY_EDGEFLAG VERT_BIT_EDGEFLAG
+#define _NEW_ARRAY_POINT_SIZE VERT_BIT_COLOR_INDEX /* aliased */
+#define _NEW_ARRAY_TEXCOORD_0 VERT_BIT_TEX0
+#define _NEW_ARRAY_TEXCOORD_1 VERT_BIT_TEX1
+#define _NEW_ARRAY_TEXCOORD_2 VERT_BIT_TEX2
+#define _NEW_ARRAY_TEXCOORD_3 VERT_BIT_TEX3
+#define _NEW_ARRAY_TEXCOORD_4 VERT_BIT_TEX4
+#define _NEW_ARRAY_TEXCOORD_5 VERT_BIT_TEX5
+#define _NEW_ARRAY_TEXCOORD_6 VERT_BIT_TEX6
+#define _NEW_ARRAY_TEXCOORD_7 VERT_BIT_TEX7
+#define _NEW_ARRAY_ATTRIB_0 VERT_BIT_GENERIC0 /* start at bit 16 */
+#define _NEW_ARRAY_ALL 0xffffffff
+
+
+#define _NEW_ARRAY_TEXCOORD(i) (_NEW_ARRAY_TEXCOORD_0 << (i))
+#define _NEW_ARRAY_ATTRIB(i) (_NEW_ARRAY_ATTRIB_0 << (i))
+/*@}*/
+
+
+
+/**
+ * \name A bunch of flags that we think might be useful to drivers.
+ *
+ * Set in the __struct gl_contextRec::_TriangleCaps bitfield.
+ */
+/*@{*/
+#define DD_FLATSHADE 0x1
+#define DD_SEPARATE_SPECULAR 0x2
+#define DD_TRI_CULL_FRONT_BACK 0x4 /* special case on some hw */
+#define DD_TRI_LIGHT_TWOSIDE 0x8
+#define DD_TRI_UNFILLED 0x10
+#define DD_TRI_SMOOTH 0x20
+#define DD_TRI_STIPPLE 0x40
+#define DD_TRI_OFFSET 0x80
+#define DD_LINE_SMOOTH 0x100
+#define DD_LINE_STIPPLE 0x200
+#define DD_POINT_SMOOTH 0x400
+#define DD_POINT_ATTEN 0x800
+#define DD_TRI_TWOSTENCIL 0x1000
+/*@}*/
+
+
+/**
+ * \name Define the state changes under which each of these bits might change
+ */
+/*@{*/
+#define _DD_NEW_FLATSHADE _NEW_LIGHT
+#define _DD_NEW_SEPARATE_SPECULAR (_NEW_LIGHT | _NEW_FOG | _NEW_PROGRAM)
+#define _DD_NEW_TRI_CULL_FRONT_BACK _NEW_POLYGON
+#define _DD_NEW_TRI_LIGHT_TWOSIDE _NEW_LIGHT
+#define _DD_NEW_TRI_UNFILLED _NEW_POLYGON
+#define _DD_NEW_TRI_SMOOTH _NEW_POLYGON
+#define _DD_NEW_TRI_STIPPLE _NEW_POLYGON
+#define _DD_NEW_TRI_OFFSET _NEW_POLYGON
+#define _DD_NEW_LINE_SMOOTH _NEW_LINE
+#define _DD_NEW_LINE_STIPPLE _NEW_LINE
+#define _DD_NEW_LINE_WIDTH _NEW_LINE
+#define _DD_NEW_POINT_SMOOTH _NEW_POINT
+#define _DD_NEW_POINT_SIZE _NEW_POINT
+#define _DD_NEW_POINT_ATTEN _NEW_POINT
+/*@}*/
+
+
+/**
+ * Composite state flags
+ */
+/*@{*/
+#define _MESA_NEW_NEED_EYE_COORDS (_NEW_LIGHT | \
+ _NEW_TEXTURE | \
+ _NEW_POINT | \
+ _NEW_PROGRAM | \
+ _NEW_MODELVIEW)
+
+#define _MESA_NEW_NEED_NORMALS (_NEW_LIGHT | \
+ _NEW_TEXTURE)
+
+#define _MESA_NEW_TRANSFER_STATE (_NEW_PIXEL)
+/*@}*/
+
+
+
+
+/* This has to be included here. */
+#include "dd.h"
+
+
+/**
+ * Display list flags.
+ * Strictly this is a tnl-private concept, but it doesn't seem
+ * worthwhile adding a tnl private structure just to hold this one bit
+ * of information:
+ */
+#define DLIST_DANGLING_REFS 0x1
+
+
+/** Opaque declaration of display list payload data type */
+union gl_dlist_node;
+
+
+/**
+ * Provide a location where information about a display list can be
+ * collected. Could be extended with driverPrivate structures,
+ * etc. in the future.
+ */
+struct gl_display_list
+{
+ GLuint Name;
+ GLbitfield Flags; /**< DLIST_x flags */
+ /** The dlist commands are in a linked list of nodes */
+ union gl_dlist_node *Head;
+};
+
+
+/**
+ * State used during display list compilation and execution.
+ */
+struct gl_dlist_state
+{
+ GLuint CallDepth; /**< Current recursion calling depth */
+
+ struct gl_display_list *CurrentList; /**< List currently being compiled */
+ union gl_dlist_node *CurrentBlock; /**< Pointer to current block of nodes */
+ GLuint CurrentPos; /**< Index into current block of nodes */
+
+ GLvertexformat ListVtxfmt;
+
+ GLubyte ActiveAttribSize[VERT_ATTRIB_MAX];
+ GLfloat CurrentAttrib[VERT_ATTRIB_MAX][4];
+
+ GLubyte ActiveMaterialSize[MAT_ATTRIB_MAX];
+ GLfloat CurrentMaterial[MAT_ATTRIB_MAX][4];
+
+ GLubyte ActiveIndex;
+ GLfloat CurrentIndex;
+
+ GLubyte ActiveEdgeFlag;
+ GLboolean CurrentEdgeFlag;
+
+ struct {
+ /* State known to have been set by the currently-compiling display
+ * list. Used to eliminate some redundant state changes.
+ */
+ GLenum ShadeModel;
+ } Current;
+};
+
+
+/**
+ * Enum for the OpenGL APIs we know about and may support.
+ */
+typedef enum
+{
+ API_OPENGL,
+ API_OPENGLES,
+ API_OPENGLES2
+} gl_api;
+
+
+/**
+ * Mesa rendering context.
+ *
+ * This is the central context data structure for Mesa. Almost all
+ * OpenGL state is contained in this structure.
+ * Think of this as a base class from which device drivers will derive
+ * sub classes.
+ *
+ * The struct gl_context typedef names this structure.
+ */
+struct gl_context
+{
+ /** State possibly shared with other contexts in the address space */
+ struct gl_shared_state *Shared;
+
+ /** \name API function pointer tables */
+ /*@{*/
+ gl_api API;
+ struct _glapi_table *Save; /**< Display list save functions */
+ struct _glapi_table *Exec; /**< Execute functions */
+ struct _glapi_table *CurrentDispatch; /**< == Save or Exec !! */
+ /*@}*/
+
+ struct gl_config Visual;
+ struct gl_framebuffer *DrawBuffer; /**< buffer for writing */
+ struct gl_framebuffer *ReadBuffer; /**< buffer for reading */
+ struct gl_framebuffer *WinSysDrawBuffer; /**< set with MakeCurrent */
+ struct gl_framebuffer *WinSysReadBuffer; /**< set with MakeCurrent */
+
+ /**
+ * Device driver function pointer table
+ */
+ struct dd_function_table Driver;
+
+ void *DriverCtx; /**< Points to device driver context/state */
+
+ /** Core/Driver constants */
+ struct gl_constants Const;
+
+ /** \name The various 4x4 matrix stacks */
+ /*@{*/
+ struct gl_matrix_stack ModelviewMatrixStack;
+ struct gl_matrix_stack ProjectionMatrixStack;
+ struct gl_matrix_stack TextureMatrixStack[MAX_TEXTURE_UNITS];
+ struct gl_matrix_stack ProgramMatrixStack[MAX_PROGRAM_MATRICES];
+ struct gl_matrix_stack *CurrentStack; /**< Points to one of the above stacks */
+ /*@}*/
+
+ /** Combined modelview and projection matrix */
+ GLmatrix _ModelProjectMatrix;
+
+ /** \name Display lists */
+ struct gl_dlist_state ListState;
+
+ GLboolean ExecuteFlag; /**< Execute GL commands? */
+ GLboolean CompileFlag; /**< Compile GL commands into display list? */
+
+ /** Extension information */
+ struct gl_extensions Extensions;
+
+ /** Version info */
+ GLuint VersionMajor, VersionMinor;
+ char *VersionString;
+
+ /** \name State attribute stack (for glPush/PopAttrib) */
+ /*@{*/
+ GLuint AttribStackDepth;
+ struct gl_attrib_node *AttribStack[MAX_ATTRIB_STACK_DEPTH];
+ /*@}*/
+
+ /** \name Renderer attribute groups
+ *
+ * We define a struct for each attribute group to make pushing and popping
+ * attributes easy. Also it's a good organization.
+ */
+ /*@{*/
+ struct gl_accum_attrib Accum; /**< Accum buffer attributes */
+ struct gl_colorbuffer_attrib Color; /**< Color buffer attributes */
+ struct gl_current_attrib Current; /**< Current attributes */
+ struct gl_depthbuffer_attrib Depth; /**< Depth buffer attributes */
+ struct gl_eval_attrib Eval; /**< Eval attributes */
+ struct gl_fog_attrib Fog; /**< Fog attributes */
+ struct gl_hint_attrib Hint; /**< Hint attributes */
+ struct gl_light_attrib Light; /**< Light attributes */
+ struct gl_line_attrib Line; /**< Line attributes */
+ struct gl_list_attrib List; /**< List attributes */
+ struct gl_multisample_attrib Multisample;
+ struct gl_pixel_attrib Pixel; /**< Pixel attributes */
+ struct gl_point_attrib Point; /**< Point attributes */
+ struct gl_polygon_attrib Polygon; /**< Polygon attributes */
+ GLuint PolygonStipple[32]; /**< Polygon stipple */
+ struct gl_scissor_attrib Scissor; /**< Scissor attributes */
+ struct gl_stencil_attrib Stencil; /**< Stencil buffer attributes */
+ struct gl_texture_attrib Texture; /**< Texture attributes */
+ struct gl_transform_attrib Transform; /**< Transformation attributes */
+ struct gl_viewport_attrib Viewport; /**< Viewport attributes */
+ /*@}*/
+
+ /** \name Client attribute stack */
+ /*@{*/
+ GLuint ClientAttribStackDepth;
+ struct gl_attrib_node *ClientAttribStack[MAX_CLIENT_ATTRIB_STACK_DEPTH];
+ /*@}*/
+
+ /** \name Client attribute groups */
+ /*@{*/
+ struct gl_array_attrib Array; /**< Vertex arrays */
+ struct gl_pixelstore_attrib Pack; /**< Pixel packing */
+ struct gl_pixelstore_attrib Unpack; /**< Pixel unpacking */
+ struct gl_pixelstore_attrib DefaultPacking; /**< Default params */
+ /*@}*/
+
+ /** \name Other assorted state (not pushed/popped on attribute stack) */
+ /*@{*/
+ struct gl_pixelmaps PixelMaps;
+
+ struct gl_evaluators EvalMap; /**< All evaluators */
+ struct gl_feedback Feedback; /**< Feedback */
+ struct gl_selection Select; /**< Selection */
+
+ struct gl_program_state Program; /**< general program state */
+ struct gl_vertex_program_state VertexProgram;
+ struct gl_fragment_program_state FragmentProgram;
+ struct gl_geometry_program_state GeometryProgram;
+ struct gl_ati_fragment_shader_state ATIFragmentShader;
+
+ struct gl_shader_state Shader; /**< GLSL shader object state */
+ struct gl_shader_compiler_options ShaderCompilerOptions[MESA_SHADER_TYPES];
+
+ struct gl_query_state Query; /**< occlusion, timer queries */
+
+ struct gl_transform_feedback TransformFeedback;
+
+ struct gl_buffer_object *CopyReadBuffer; /**< GL_ARB_copy_buffer */
+ struct gl_buffer_object *CopyWriteBuffer; /**< GL_ARB_copy_buffer */
+ /*@}*/
+
+ struct gl_meta_state *Meta; /**< for "meta" operations */
+
+ /* GL_EXT_framebuffer_object */
+ struct gl_renderbuffer *CurrentRenderbuffer;
+
+ GLenum ErrorValue; /**< Last error code */
+
+ /**
+ * Recognize and silence repeated error debug messages in buggy apps.
+ */
+ const char *ErrorDebugFmtString;
+ GLuint ErrorDebugCount;
+
+ GLenum RenderMode; /**< either GL_RENDER, GL_SELECT, GL_FEEDBACK */
+ GLbitfield NewState; /**< bitwise-or of _NEW_* flags */
+
+ GLboolean ViewportInitialized; /**< has viewport size been initialized? */
+
+ GLbitfield varying_vp_inputs; /**< mask of VERT_BIT_* flags */
+
+ /** \name Derived state */
+ /*@{*/
+ /** Bitwise-or of DD_* flags. Note that this bitfield may be used before
+ * state validation so they need to always be current.
+ */
+ GLbitfield _TriangleCaps;
+ GLbitfield _ImageTransferState;/**< bitwise-or of IMAGE_*_BIT flags */
+ GLfloat _EyeZDir[3];
+ GLfloat _ModelViewInvScale;
+ GLboolean _NeedEyeCoords;
+ GLboolean _ForceEyeCoords;
+
+ GLuint TextureStateTimestamp; /**< detect changes to shared state */
+
+ struct gl_shine_tab *_ShineTable[2]; /**< Active shine tables */
+ struct gl_shine_tab *_ShineTabList; /**< MRU list of inactive shine tables */
+ /**@}*/
+
+ struct gl_list_extensions *ListExt; /**< driver dlist extensions */
+
+ /** \name For debugging/development only */
+ /*@{*/
+ GLboolean FirstTimeCurrent;
+ /*@}*/
+
+ /** Dither disable via MESA_NO_DITHER env var */
+ GLboolean NoDither;
+
+ /** software compression/decompression supported or not */
+ GLboolean Mesa_DXTn;
+
+ GLboolean TextureFormatSupported[MESA_FORMAT_COUNT];
+
+ /**
+ * Use dp4 (rather than mul/mad) instructions for position
+ * transformation?
+ */
+ GLboolean mvp_with_dp4;
+
+ /**
+ * \name Hooks for module contexts.
+ *
+ * These will eventually live in the driver or elsewhere.
+ */
+ /*@{*/
+ void *swrast_context;
+ void *swsetup_context;
+ void *swtnl_context;
+ void *swtnl_im;
+ struct st_context *st;
+ void *aelt_context;
+ /*@}*/
+};
+
+
+#ifdef DEBUG
+extern int MESA_VERBOSE;
+extern int MESA_DEBUG_FLAGS;
+# define MESA_FUNCTION __FUNCTION__
+#else
+# define MESA_VERBOSE 0
+# define MESA_DEBUG_FLAGS 0
+# define MESA_FUNCTION "a function"
+# ifndef NDEBUG
+# define NDEBUG
+# endif
+#endif
+
+
+/** The MESA_VERBOSE var is a bitmask of these flags */
+enum _verbose
+{
+ VERBOSE_VARRAY = 0x0001,
+ VERBOSE_TEXTURE = 0x0002,
+ VERBOSE_MATERIAL = 0x0004,
+ VERBOSE_PIPELINE = 0x0008,
+ VERBOSE_DRIVER = 0x0010,
+ VERBOSE_STATE = 0x0020,
+ VERBOSE_API = 0x0040,
+ VERBOSE_DISPLAY_LIST = 0x0100,
+ VERBOSE_LIGHTING = 0x0200,
+ VERBOSE_PRIMS = 0x0400,
+ VERBOSE_VERTS = 0x0800,
+ VERBOSE_DISASSEM = 0x1000,
+ VERBOSE_DRAW = 0x2000,
+ VERBOSE_SWAPBUFFERS = 0x4000
+};
+
+
+/** The MESA_DEBUG_FLAGS var is a bitmask of these flags */
+enum _debug
+{
+ DEBUG_ALWAYS_FLUSH = 0x1
+};
+
+
+
+#endif /* MTYPES_H */
diff --git a/mesalib/src/mesa/program/ir_to_mesa.cpp b/mesalib/src/mesa/program/ir_to_mesa.cpp
index d0ec23fc8..aa5f007e9 100644
--- a/mesalib/src/mesa/program/ir_to_mesa.cpp
+++ b/mesalib/src/mesa/program/ir_to_mesa.cpp
@@ -1,3267 +1,3270 @@
-/*
- * Copyright (C) 2005-2007 Brian Paul All Rights Reserved.
- * Copyright (C) 2008 VMware, Inc. All Rights Reserved.
- * 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 ir_to_mesa.cpp
- *
- * Translate GLSL IR to Mesa's gl_program representation.
- */
-
-#include <stdio.h>
-#include "main/compiler.h"
-#include "ir.h"
-#include "ir_visitor.h"
-#include "ir_print_visitor.h"
-#include "ir_expression_flattening.h"
-#include "glsl_types.h"
-#include "glsl_parser_extras.h"
-#include "../glsl/program.h"
-#include "ir_optimization.h"
-#include "ast.h"
-
-extern "C" {
-#include "main/mtypes.h"
-#include "main/shaderapi.h"
-#include "main/shaderobj.h"
-#include "main/uniforms.h"
-#include "program/hash_table.h"
-#include "program/prog_instruction.h"
-#include "program/prog_optimize.h"
-#include "program/prog_print.h"
-#include "program/program.h"
-#include "program/prog_uniform.h"
-#include "program/prog_parameter.h"
-#include "program/sampler.h"
-}
-
-static int swizzle_for_size(int size);
-
-/**
- * This struct is a corresponding struct to Mesa prog_src_register, with
- * wider fields.
- */
-typedef struct ir_to_mesa_src_reg {
- ir_to_mesa_src_reg(int file, int index, const glsl_type *type)
- {
- this->file = (gl_register_file) file;
- this->index = index;
- if (type && (type->is_scalar() || type->is_vector() || type->is_matrix()))
- this->swizzle = swizzle_for_size(type->vector_elements);
- else
- this->swizzle = SWIZZLE_XYZW;
- this->negate = 0;
- this->reladdr = NULL;
- }
-
- ir_to_mesa_src_reg()
- {
- this->file = PROGRAM_UNDEFINED;
- this->index = 0;
- this->swizzle = 0;
- this->negate = 0;
- this->reladdr = NULL;
- }
-
- gl_register_file file; /**< PROGRAM_* from Mesa */
- int index; /**< temporary index, VERT_ATTRIB_*, FRAG_ATTRIB_*, etc. */
- GLuint swizzle; /**< SWIZZLE_XYZWONEZERO swizzles from Mesa. */
- int negate; /**< NEGATE_XYZW mask from mesa */
- /** Register index should be offset by the integer in this reg. */
- ir_to_mesa_src_reg *reladdr;
-} ir_to_mesa_src_reg;
-
-typedef struct ir_to_mesa_dst_reg {
- int file; /**< PROGRAM_* from Mesa */
- int index; /**< temporary index, VERT_ATTRIB_*, FRAG_ATTRIB_*, etc. */
- int writemask; /**< Bitfield of WRITEMASK_[XYZW] */
- GLuint cond_mask:4;
- /** Register index should be offset by the integer in this reg. */
- ir_to_mesa_src_reg *reladdr;
-} ir_to_mesa_dst_reg;
-
-extern ir_to_mesa_src_reg ir_to_mesa_undef;
-
-class ir_to_mesa_instruction : public exec_node {
-public:
- /* 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 = rzalloc_size(ctx, size);
- assert(node != NULL);
-
- return node;
- }
-
- enum prog_opcode op;
- ir_to_mesa_dst_reg dst_reg;
- ir_to_mesa_src_reg src_reg[3];
- /** Pointer to the ir source this tree came from for debugging */
- ir_instruction *ir;
- GLboolean cond_update;
- bool saturate;
- int sampler; /**< sampler index */
- int tex_target; /**< One of TEXTURE_*_INDEX */
- GLboolean tex_shadow;
-
- class function_entry *function; /* Set on OPCODE_CAL or OPCODE_BGNSUB */
-};
-
-class variable_storage : public exec_node {
-public:
- variable_storage(ir_variable *var, gl_register_file file, int index)
- : file(file), index(index), var(var)
- {
- /* empty */
- }
-
- gl_register_file file;
- int index;
- ir_variable *var; /* variable that maps to this, if any */
-};
-
-class function_entry : public exec_node {
-public:
- ir_function_signature *sig;
-
- /**
- * identifier of this function signature used by the program.
- *
- * At the point that Mesa instructions for function calls are
- * generated, we don't know the address of the first instruction of
- * the function body. So we make the BranchTarget that is called a
- * small integer and rewrite them during set_branchtargets().
- */
- int sig_id;
-
- /**
- * Pointer to first instruction of the function body.
- *
- * Set during function body emits after main() is processed.
- */
- ir_to_mesa_instruction *bgn_inst;
-
- /**
- * Index of the first instruction of the function body in actual
- * Mesa IR.
- *
- * Set after convertion from ir_to_mesa_instruction to prog_instruction.
- */
- int inst;
-
- /** Storage for the return value. */
- ir_to_mesa_src_reg return_reg;
-};
-
-class ir_to_mesa_visitor : public ir_visitor {
-public:
- ir_to_mesa_visitor();
- ~ir_to_mesa_visitor();
-
- function_entry *current_function;
-
- struct gl_context *ctx;
- struct gl_program *prog;
- struct gl_shader_program *shader_program;
- struct gl_shader_compiler_options *options;
-
- int next_temp;
-
- variable_storage *find_variable_storage(ir_variable *var);
-
- function_entry *get_function_signature(ir_function_signature *sig);
-
- ir_to_mesa_src_reg get_temp(const glsl_type *type);
- void reladdr_to_temp(ir_instruction *ir,
- ir_to_mesa_src_reg *reg, int *num_reladdr);
-
- struct ir_to_mesa_src_reg src_reg_for_float(float val);
-
- /**
- * \name Visit methods
- *
- * As typical for the visitor pattern, there must be one \c visit method for
- * each concrete subclass of \c ir_instruction. Virtual base classes within
- * the hierarchy should not have \c visit methods.
- */
- /*@{*/
- virtual void visit(ir_variable *);
- virtual void visit(ir_loop *);
- virtual void visit(ir_loop_jump *);
- virtual void visit(ir_function_signature *);
- virtual void visit(ir_function *);
- virtual void visit(ir_expression *);
- virtual void visit(ir_swizzle *);
- virtual void visit(ir_dereference_variable *);
- virtual void visit(ir_dereference_array *);
- virtual void visit(ir_dereference_record *);
- virtual void visit(ir_assignment *);
- virtual void visit(ir_constant *);
- virtual void visit(ir_call *);
- virtual void visit(ir_return *);
- virtual void visit(ir_discard *);
- virtual void visit(ir_texture *);
- virtual void visit(ir_if *);
- /*@}*/
-
- struct ir_to_mesa_src_reg result;
-
- /** List of variable_storage */
- exec_list variables;
-
- /** List of function_entry */
- exec_list function_signatures;
- int next_signature_id;
-
- /** List of ir_to_mesa_instruction */
- exec_list instructions;
-
- ir_to_mesa_instruction *ir_to_mesa_emit_op0(ir_instruction *ir,
- enum prog_opcode op);
-
- ir_to_mesa_instruction *ir_to_mesa_emit_op1(ir_instruction *ir,
- enum prog_opcode op,
- ir_to_mesa_dst_reg dst,
- ir_to_mesa_src_reg src0);
-
- ir_to_mesa_instruction *ir_to_mesa_emit_op2(ir_instruction *ir,
- enum prog_opcode op,
- ir_to_mesa_dst_reg dst,
- ir_to_mesa_src_reg src0,
- ir_to_mesa_src_reg src1);
-
- ir_to_mesa_instruction *ir_to_mesa_emit_op3(ir_instruction *ir,
- enum prog_opcode op,
- ir_to_mesa_dst_reg dst,
- ir_to_mesa_src_reg src0,
- ir_to_mesa_src_reg src1,
- ir_to_mesa_src_reg src2);
-
- /**
- * Emit the correct dot-product instruction for the type of arguments
- *
- * \sa ir_to_mesa_emit_op2
- */
- void ir_to_mesa_emit_dp(ir_instruction *ir,
- ir_to_mesa_dst_reg dst,
- ir_to_mesa_src_reg src0,
- ir_to_mesa_src_reg src1,
- unsigned elements);
-
- void ir_to_mesa_emit_scalar_op1(ir_instruction *ir,
- enum prog_opcode op,
- ir_to_mesa_dst_reg dst,
- ir_to_mesa_src_reg src0);
-
- void ir_to_mesa_emit_scalar_op2(ir_instruction *ir,
- enum prog_opcode op,
- ir_to_mesa_dst_reg dst,
- ir_to_mesa_src_reg src0,
- ir_to_mesa_src_reg src1);
-
- void emit_scs(ir_instruction *ir, enum prog_opcode op,
- ir_to_mesa_dst_reg dst,
- const ir_to_mesa_src_reg &src);
-
- GLboolean try_emit_mad(ir_expression *ir,
- int mul_operand);
- GLboolean try_emit_sat(ir_expression *ir);
-
- void emit_swz(ir_expression *ir);
-
- bool process_move_condition(ir_rvalue *ir);
-
- void copy_propagate(void);
-
- void *mem_ctx;
-};
-
-ir_to_mesa_src_reg ir_to_mesa_undef = ir_to_mesa_src_reg(PROGRAM_UNDEFINED, 0, NULL);
-
-ir_to_mesa_dst_reg ir_to_mesa_undef_dst = {
- PROGRAM_UNDEFINED, 0, SWIZZLE_NOOP, COND_TR, NULL,
-};
-
-ir_to_mesa_dst_reg ir_to_mesa_address_reg = {
- PROGRAM_ADDRESS, 0, WRITEMASK_X, COND_TR, NULL
-};
-
-static void
-fail_link(struct gl_shader_program *prog, const char *fmt, ...) PRINTFLIKE(2, 3);
-
-static void
-fail_link(struct gl_shader_program *prog, const char *fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
- ralloc_vasprintf_append(&prog->InfoLog, fmt, args);
- va_end(args);
-
- prog->LinkStatus = GL_FALSE;
-}
-
-static int
-swizzle_for_size(int size)
-{
- int size_swizzles[4] = {
- MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X),
- MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y),
- MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_Z),
- MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W),
- };
-
- assert((size >= 1) && (size <= 4));
- return size_swizzles[size - 1];
-}
-
-ir_to_mesa_instruction *
-ir_to_mesa_visitor::ir_to_mesa_emit_op3(ir_instruction *ir,
- enum prog_opcode op,
- ir_to_mesa_dst_reg dst,
- ir_to_mesa_src_reg src0,
- ir_to_mesa_src_reg src1,
- ir_to_mesa_src_reg src2)
-{
- ir_to_mesa_instruction *inst = new(mem_ctx) ir_to_mesa_instruction();
- int num_reladdr = 0;
-
- /* If we have to do relative addressing, we want to load the ARL
- * reg directly for one of the regs, and preload the other reladdr
- * sources into temps.
- */
- num_reladdr += dst.reladdr != NULL;
- num_reladdr += src0.reladdr != NULL;
- num_reladdr += src1.reladdr != NULL;
- num_reladdr += src2.reladdr != NULL;
-
- reladdr_to_temp(ir, &src2, &num_reladdr);
- reladdr_to_temp(ir, &src1, &num_reladdr);
- reladdr_to_temp(ir, &src0, &num_reladdr);
-
- if (dst.reladdr) {
- ir_to_mesa_emit_op1(ir, OPCODE_ARL, ir_to_mesa_address_reg,
- *dst.reladdr);
-
- num_reladdr--;
- }
- assert(num_reladdr == 0);
-
- inst->op = op;
- inst->dst_reg = dst;
- inst->src_reg[0] = src0;
- inst->src_reg[1] = src1;
- inst->src_reg[2] = src2;
- inst->ir = ir;
-
- inst->function = NULL;
-
- this->instructions.push_tail(inst);
-
- return inst;
-}
-
-
-ir_to_mesa_instruction *
-ir_to_mesa_visitor::ir_to_mesa_emit_op2(ir_instruction *ir,
- enum prog_opcode op,
- ir_to_mesa_dst_reg dst,
- ir_to_mesa_src_reg src0,
- ir_to_mesa_src_reg src1)
-{
- return ir_to_mesa_emit_op3(ir, op, dst, src0, src1, ir_to_mesa_undef);
-}
-
-ir_to_mesa_instruction *
-ir_to_mesa_visitor::ir_to_mesa_emit_op1(ir_instruction *ir,
- enum prog_opcode op,
- ir_to_mesa_dst_reg dst,
- ir_to_mesa_src_reg src0)
-{
- assert(dst.writemask != 0);
- return ir_to_mesa_emit_op3(ir, op, dst,
- src0, ir_to_mesa_undef, ir_to_mesa_undef);
-}
-
-ir_to_mesa_instruction *
-ir_to_mesa_visitor::ir_to_mesa_emit_op0(ir_instruction *ir,
- enum prog_opcode op)
-{
- return ir_to_mesa_emit_op3(ir, op, ir_to_mesa_undef_dst,
- ir_to_mesa_undef,
- ir_to_mesa_undef,
- ir_to_mesa_undef);
-}
-
-void
-ir_to_mesa_visitor::ir_to_mesa_emit_dp(ir_instruction *ir,
- ir_to_mesa_dst_reg dst,
- ir_to_mesa_src_reg src0,
- ir_to_mesa_src_reg src1,
- unsigned elements)
-{
- static const gl_inst_opcode dot_opcodes[] = {
- OPCODE_DP2, OPCODE_DP3, OPCODE_DP4
- };
-
- ir_to_mesa_emit_op3(ir, dot_opcodes[elements - 2],
- dst, src0, src1, ir_to_mesa_undef);
-}
-
-inline ir_to_mesa_dst_reg
-ir_to_mesa_dst_reg_from_src(ir_to_mesa_src_reg reg)
-{
- ir_to_mesa_dst_reg dst_reg;
-
- dst_reg.file = reg.file;
- dst_reg.index = reg.index;
- dst_reg.writemask = WRITEMASK_XYZW;
- dst_reg.cond_mask = COND_TR;
- dst_reg.reladdr = reg.reladdr;
-
- return dst_reg;
-}
-
-inline ir_to_mesa_src_reg
-ir_to_mesa_src_reg_from_dst(ir_to_mesa_dst_reg reg)
-{
- return ir_to_mesa_src_reg(reg.file, reg.index, NULL);
-}
-
-/**
- * Emits Mesa scalar opcodes to produce unique answers across channels.
- *
- * Some Mesa opcodes are scalar-only, like ARB_fp/vp. The src X
- * channel determines the result across all channels. So to do a vec4
- * of this operation, we want to emit a scalar per source channel used
- * to produce dest channels.
- */
-void
-ir_to_mesa_visitor::ir_to_mesa_emit_scalar_op2(ir_instruction *ir,
- enum prog_opcode op,
- ir_to_mesa_dst_reg dst,
- ir_to_mesa_src_reg orig_src0,
- ir_to_mesa_src_reg orig_src1)
-{
- int i, j;
- int done_mask = ~dst.writemask;
-
- /* Mesa RCP is a scalar operation splatting results to all channels,
- * like ARB_fp/vp. So emit as many RCPs as necessary to cover our
- * dst channels.
- */
- for (i = 0; i < 4; i++) {
- GLuint this_mask = (1 << i);
- ir_to_mesa_instruction *inst;
- ir_to_mesa_src_reg src0 = orig_src0;
- ir_to_mesa_src_reg src1 = orig_src1;
-
- if (done_mask & this_mask)
- continue;
-
- GLuint src0_swiz = GET_SWZ(src0.swizzle, i);
- GLuint src1_swiz = GET_SWZ(src1.swizzle, i);
- for (j = i + 1; j < 4; j++) {
- /* If there is another enabled component in the destination that is
- * derived from the same inputs, generate its value on this pass as
- * well.
- */
- if (!(done_mask & (1 << j)) &&
- GET_SWZ(src0.swizzle, j) == src0_swiz &&
- GET_SWZ(src1.swizzle, j) == src1_swiz) {
- this_mask |= (1 << j);
- }
- }
- src0.swizzle = MAKE_SWIZZLE4(src0_swiz, src0_swiz,
- src0_swiz, src0_swiz);
- src1.swizzle = MAKE_SWIZZLE4(src1_swiz, src1_swiz,
- src1_swiz, src1_swiz);
-
- inst = ir_to_mesa_emit_op2(ir, op,
- dst,
- src0,
- src1);
- inst->dst_reg.writemask = this_mask;
- done_mask |= this_mask;
- }
-}
-
-void
-ir_to_mesa_visitor::ir_to_mesa_emit_scalar_op1(ir_instruction *ir,
- enum prog_opcode op,
- ir_to_mesa_dst_reg dst,
- ir_to_mesa_src_reg src0)
-{
- ir_to_mesa_src_reg undef = ir_to_mesa_undef;
-
- undef.swizzle = SWIZZLE_XXXX;
-
- ir_to_mesa_emit_scalar_op2(ir, op, dst, src0, undef);
-}
-
-/**
- * Emit an OPCODE_SCS instruction
- *
- * The \c SCS opcode functions a bit differently than the other Mesa (or
- * ARB_fragment_program) opcodes. Instead of splatting its result across all
- * four components of the destination, it writes one value to the \c x
- * component and another value to the \c y component.
- *
- * \param ir IR instruction being processed
- * \param op Either \c OPCODE_SIN or \c OPCODE_COS depending on which
- * value is desired.
- * \param dst Destination register
- * \param src Source register
- */
-void
-ir_to_mesa_visitor::emit_scs(ir_instruction *ir, enum prog_opcode op,
- ir_to_mesa_dst_reg dst,
- const ir_to_mesa_src_reg &src)
-{
- /* Vertex programs cannot use the SCS opcode.
- */
- if (this->prog->Target == GL_VERTEX_PROGRAM_ARB) {
- ir_to_mesa_emit_scalar_op1(ir, op, dst, src);
- return;
- }
-
- const unsigned component = (op == OPCODE_SIN) ? 0 : 1;
- const unsigned scs_mask = (1U << component);
- int done_mask = ~dst.writemask;
- ir_to_mesa_src_reg tmp;
-
- assert(op == OPCODE_SIN || op == OPCODE_COS);
-
- /* If there are compnents in the destination that differ from the component
- * that will be written by the SCS instrution, we'll need a temporary.
- */
- if (scs_mask != unsigned(dst.writemask)) {
- tmp = get_temp(glsl_type::vec4_type);
- }
-
- for (unsigned i = 0; i < 4; i++) {
- unsigned this_mask = (1U << i);
- ir_to_mesa_src_reg src0 = src;
-
- if ((done_mask & this_mask) != 0)
- continue;
-
- /* The source swizzle specified which component of the source generates
- * sine / cosine for the current component in the destination. The SCS
- * instruction requires that this value be swizzle to the X component.
- * Replace the current swizzle with a swizzle that puts the source in
- * the X component.
- */
- unsigned src0_swiz = GET_SWZ(src.swizzle, i);
-
- src0.swizzle = MAKE_SWIZZLE4(src0_swiz, src0_swiz,
- src0_swiz, src0_swiz);
- for (unsigned j = i + 1; j < 4; j++) {
- /* If there is another enabled component in the destination that is
- * derived from the same inputs, generate its value on this pass as
- * well.
- */
- if (!(done_mask & (1 << j)) &&
- GET_SWZ(src0.swizzle, j) == src0_swiz) {
- this_mask |= (1 << j);
- }
- }
-
- if (this_mask != scs_mask) {
- ir_to_mesa_instruction *inst;
- ir_to_mesa_dst_reg tmp_dst = ir_to_mesa_dst_reg_from_src(tmp);
-
- /* Emit the SCS instruction.
- */
- inst = ir_to_mesa_emit_op1(ir, OPCODE_SCS, tmp_dst, src0);
- inst->dst_reg.writemask = scs_mask;
-
- /* Move the result of the SCS instruction to the desired location in
- * the destination.
- */
- tmp.swizzle = MAKE_SWIZZLE4(component, component,
- component, component);
- inst = ir_to_mesa_emit_op1(ir, OPCODE_SCS, dst, tmp);
- inst->dst_reg.writemask = this_mask;
- } else {
- /* Emit the SCS instruction to write directly to the destination.
- */
- ir_to_mesa_instruction *inst =
- ir_to_mesa_emit_op1(ir, OPCODE_SCS, dst, src0);
- inst->dst_reg.writemask = scs_mask;
- }
-
- done_mask |= this_mask;
- }
-}
-
-struct ir_to_mesa_src_reg
-ir_to_mesa_visitor::src_reg_for_float(float val)
-{
- ir_to_mesa_src_reg src_reg(PROGRAM_CONSTANT, -1, NULL);
-
- src_reg.index = _mesa_add_unnamed_constant(this->prog->Parameters,
- &val, 1, &src_reg.swizzle);
-
- return src_reg;
-}
-
-static int
-type_size(const struct glsl_type *type)
-{
- unsigned int i;
- int size;
-
- switch (type->base_type) {
- case GLSL_TYPE_UINT:
- case GLSL_TYPE_INT:
- case GLSL_TYPE_FLOAT:
- case GLSL_TYPE_BOOL:
- if (type->is_matrix()) {
- return type->matrix_columns;
- } else {
- /* Regardless of size of vector, it gets a vec4. This is bad
- * packing for things like floats, but otherwise arrays become a
- * mess. Hopefully a later pass over the code can pack scalars
- * down if appropriate.
- */
- return 1;
- }
- case GLSL_TYPE_ARRAY:
- assert(type->length > 0);
- return type_size(type->fields.array) * type->length;
- case GLSL_TYPE_STRUCT:
- size = 0;
- for (i = 0; i < type->length; i++) {
- size += type_size(type->fields.structure[i].type);
- }
- return size;
- case GLSL_TYPE_SAMPLER:
- /* Samplers take up one slot in UNIFORMS[], but they're baked in
- * at link time.
- */
- return 1;
- default:
- assert(0);
- return 0;
- }
-}
-
-/**
- * In the initial pass of codegen, we assign temporary numbers to
- * intermediate results. (not SSA -- variable assignments will reuse
- * storage). Actual register allocation for the Mesa VM occurs in a
- * pass over the Mesa IR later.
- */
-ir_to_mesa_src_reg
-ir_to_mesa_visitor::get_temp(const glsl_type *type)
-{
- ir_to_mesa_src_reg src_reg;
- int swizzle[4];
- int i;
-
- src_reg.file = PROGRAM_TEMPORARY;
- src_reg.index = next_temp;
- src_reg.reladdr = NULL;
- next_temp += type_size(type);
-
- if (type->is_array() || type->is_record()) {
- src_reg.swizzle = SWIZZLE_NOOP;
- } else {
- for (i = 0; i < type->vector_elements; i++)
- swizzle[i] = i;
- for (; i < 4; i++)
- swizzle[i] = type->vector_elements - 1;
- src_reg.swizzle = MAKE_SWIZZLE4(swizzle[0], swizzle[1],
- swizzle[2], swizzle[3]);
- }
- src_reg.negate = 0;
-
- return src_reg;
-}
-
-variable_storage *
-ir_to_mesa_visitor::find_variable_storage(ir_variable *var)
-{
-
- variable_storage *entry;
-
- foreach_iter(exec_list_iterator, iter, this->variables) {
- entry = (variable_storage *)iter.get();
-
- if (entry->var == var)
- return entry;
- }
-
- return NULL;
-}
-
-void
-ir_to_mesa_visitor::visit(ir_variable *ir)
-{
- if (strcmp(ir->name, "gl_FragCoord") == 0) {
- struct gl_fragment_program *fp = (struct gl_fragment_program *)this->prog;
-
- 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) {
- unsigned int i;
- const struct gl_builtin_uniform_desc *statevar;
-
- for (i = 0; _mesa_builtin_uniform_desc[i].name; i++) {
- if (strcmp(ir->name, _mesa_builtin_uniform_desc[i].name) == 0)
- break;
- }
-
- if (!_mesa_builtin_uniform_desc[i].name) {
- fail_link(this->shader_program,
- "Failed to find builtin uniform `%s'\n", ir->name);
- return;
- }
-
- statevar = &_mesa_builtin_uniform_desc[i];
-
- int array_count;
- if (ir->type->is_array()) {
- array_count = ir->type->length;
- } else {
- array_count = 1;
- }
-
- /* Check if this statevar's setup in the STATE file exactly
- * matches how we'll want to reference it as a
- * struct/array/whatever. If not, then we need to move it into
- * temporary storage and hope that it'll get copy-propagated
- * out.
- */
- for (i = 0; i < statevar->num_elements; i++) {
- if (statevar->elements[i].swizzle != SWIZZLE_XYZW) {
- break;
- }
- }
-
- struct variable_storage *storage;
- ir_to_mesa_dst_reg dst;
- if (i == statevar->num_elements) {
- /* We'll set the index later. */
- storage = new(mem_ctx) variable_storage(ir, PROGRAM_STATE_VAR, -1);
- this->variables.push_tail(storage);
-
- dst = ir_to_mesa_undef_dst;
- } else {
- storage = new(mem_ctx) variable_storage(ir, PROGRAM_TEMPORARY,
- this->next_temp);
- this->variables.push_tail(storage);
- this->next_temp += type_size(ir->type);
-
- dst = ir_to_mesa_dst_reg_from_src(ir_to_mesa_src_reg(PROGRAM_TEMPORARY,
- storage->index,
- NULL));
- }
-
-
- for (int a = 0; a < array_count; a++) {
- for (unsigned int i = 0; i < statevar->num_elements; i++) {
- struct gl_builtin_uniform_element *element = &statevar->elements[i];
- int tokens[STATE_LENGTH];
-
- memcpy(tokens, element->tokens, sizeof(element->tokens));
- if (ir->type->is_array()) {
- tokens[1] = a;
- }
-
- int index = _mesa_add_state_reference(this->prog->Parameters,
- (gl_state_index *)tokens);
-
- if (storage->file == PROGRAM_STATE_VAR) {
- if (storage->index == -1) {
- storage->index = index;
- } else {
- assert(index ==
- (int)(storage->index + a * statevar->num_elements + i));
- }
- } else {
- ir_to_mesa_src_reg src(PROGRAM_STATE_VAR, index, NULL);
- src.swizzle = element->swizzle;
- ir_to_mesa_emit_op1(ir, OPCODE_MOV, dst, src);
- /* even a float takes up a whole vec4 reg in a struct/array. */
- dst.index++;
- }
- }
- }
- if (storage->file == PROGRAM_TEMPORARY &&
- dst.index != storage->index + type_size(ir->type)) {
- fail_link(this->shader_program,
- "failed to load builtin uniform `%s' (%d/%d regs loaded)\n",
- ir->name, dst.index - storage->index,
- type_size(ir->type));
- }
- }
-}
-
-void
-ir_to_mesa_visitor::visit(ir_loop *ir)
-{
- ir_dereference_variable *counter = NULL;
-
- if (ir->counter != NULL)
- counter = new(ir) ir_dereference_variable(ir->counter);
-
- if (ir->from != NULL) {
- assert(ir->counter != NULL);
-
- ir_assignment *a = new(ir) ir_assignment(counter, ir->from, NULL);
-
- a->accept(this);
- delete a;
- }
-
- ir_to_mesa_emit_op0(NULL, OPCODE_BGNLOOP);
-
- if (ir->to) {
- ir_expression *e =
- new(ir) ir_expression(ir->cmp, glsl_type::bool_type,
- counter, ir->to);
- ir_if *if_stmt = new(ir) ir_if(e);
-
- ir_loop_jump *brk = new(ir) ir_loop_jump(ir_loop_jump::jump_break);
-
- if_stmt->then_instructions.push_tail(brk);
-
- if_stmt->accept(this);
-
- delete if_stmt;
- delete e;
- delete brk;
- }
-
- visit_exec_list(&ir->body_instructions, this);
-
- if (ir->increment) {
- ir_expression *e =
- new(ir) ir_expression(ir_binop_add, counter->type,
- counter, ir->increment);
-
- ir_assignment *a = new(ir) ir_assignment(counter, e, NULL);
-
- a->accept(this);
- delete a;
- delete e;
- }
-
- ir_to_mesa_emit_op0(NULL, OPCODE_ENDLOOP);
-}
-
-void
-ir_to_mesa_visitor::visit(ir_loop_jump *ir)
-{
- switch (ir->mode) {
- case ir_loop_jump::jump_break:
- ir_to_mesa_emit_op0(NULL, OPCODE_BRK);
- break;
- case ir_loop_jump::jump_continue:
- ir_to_mesa_emit_op0(NULL, OPCODE_CONT);
- break;
- }
-}
-
-
-void
-ir_to_mesa_visitor::visit(ir_function_signature *ir)
-{
- assert(0);
- (void)ir;
-}
-
-void
-ir_to_mesa_visitor::visit(ir_function *ir)
-{
- /* Ignore function bodies other than main() -- we shouldn't see calls to
- * them since they should all be inlined before we get to ir_to_mesa.
- */
- if (strcmp(ir->name, "main") == 0) {
- const ir_function_signature *sig;
- exec_list empty;
-
- sig = ir->matching_signature(&empty);
-
- assert(sig);
-
- foreach_iter(exec_list_iterator, iter, sig->body) {
- ir_instruction *ir = (ir_instruction *)iter.get();
-
- ir->accept(this);
- }
- }
-}
-
-GLboolean
-ir_to_mesa_visitor::try_emit_mad(ir_expression *ir, int mul_operand)
-{
- int nonmul_operand = 1 - mul_operand;
- ir_to_mesa_src_reg a, b, c;
-
- ir_expression *expr = ir->operands[mul_operand]->as_expression();
- if (!expr || expr->operation != ir_binop_mul)
- return false;
-
- expr->operands[0]->accept(this);
- a = this->result;
- expr->operands[1]->accept(this);
- b = this->result;
- ir->operands[nonmul_operand]->accept(this);
- c = this->result;
-
- this->result = get_temp(ir->type);
- ir_to_mesa_emit_op3(ir, OPCODE_MAD,
- ir_to_mesa_dst_reg_from_src(this->result), a, b, c);
-
- return true;
-}
-
-GLboolean
-ir_to_mesa_visitor::try_emit_sat(ir_expression *ir)
-{
- /* Saturates were only introduced to vertex programs in
- * NV_vertex_program3, so don't give them to drivers in the VP.
- */
- if (this->prog->Target == GL_VERTEX_PROGRAM_ARB)
- return false;
-
- ir_rvalue *sat_src = ir->as_rvalue_to_saturate();
- if (!sat_src)
- return false;
-
- sat_src->accept(this);
- ir_to_mesa_src_reg src = this->result;
-
- this->result = get_temp(ir->type);
- ir_to_mesa_instruction *inst;
- inst = ir_to_mesa_emit_op1(ir, OPCODE_MOV,
- ir_to_mesa_dst_reg_from_src(this->result),
- src);
- inst->saturate = true;
-
- return true;
-}
-
-void
-ir_to_mesa_visitor::reladdr_to_temp(ir_instruction *ir,
- ir_to_mesa_src_reg *reg, int *num_reladdr)
-{
- if (!reg->reladdr)
- return;
-
- ir_to_mesa_emit_op1(ir, OPCODE_ARL, ir_to_mesa_address_reg, *reg->reladdr);
-
- if (*num_reladdr != 1) {
- ir_to_mesa_src_reg temp = get_temp(glsl_type::vec4_type);
-
- ir_to_mesa_emit_op1(ir, OPCODE_MOV,
- ir_to_mesa_dst_reg_from_src(temp), *reg);
- *reg = temp;
- }
-
- (*num_reladdr)--;
-}
-
-void
-ir_to_mesa_visitor::emit_swz(ir_expression *ir)
-{
- /* Assume that the vector operator is in a form compatible with OPCODE_SWZ.
- * This means that each of the operands is either an immediate value of -1,
- * 0, or 1, or is a component from one source register (possibly with
- * negation).
- */
- uint8_t components[4] = { 0 };
- bool negate[4] = { false };
- ir_variable *var = NULL;
-
- for (unsigned i = 0; i < ir->type->vector_elements; i++) {
- ir_rvalue *op = ir->operands[i];
-
- assert(op->type->is_scalar());
-
- while (op != NULL) {
- switch (op->ir_type) {
- case ir_type_constant: {
-
- assert(op->type->is_scalar());
-
- const ir_constant *const c = op->as_constant();
- if (c->is_one()) {
- components[i] = SWIZZLE_ONE;
- } else if (c->is_zero()) {
- components[i] = SWIZZLE_ZERO;
- } else if (c->is_negative_one()) {
- components[i] = SWIZZLE_ONE;
- negate[i] = true;
- } else {
- assert(!"SWZ constant must be 0.0 or 1.0.");
- }
-
- op = NULL;
- break;
- }
-
- case ir_type_dereference_variable: {
- ir_dereference_variable *const deref =
- (ir_dereference_variable *) op;
-
- assert((var == NULL) || (deref->var == var));
- components[i] = SWIZZLE_X;
- var = deref->var;
- op = NULL;
- break;
- }
-
- case ir_type_expression: {
- ir_expression *const expr = (ir_expression *) op;
-
- assert(expr->operation == ir_unop_neg);
- negate[i] = true;
-
- op = expr->operands[0];
- break;
- }
-
- case ir_type_swizzle: {
- ir_swizzle *const swiz = (ir_swizzle *) op;
-
- components[i] = swiz->mask.x;
- op = swiz->val;
- break;
- }
-
- default:
- assert(!"Should not get here.");
- return;
- }
- }
- }
-
- assert(var != NULL);
-
- ir_dereference_variable *const deref =
- new(mem_ctx) ir_dereference_variable(var);
-
- this->result.file = PROGRAM_UNDEFINED;
- deref->accept(this);
- if (this->result.file == PROGRAM_UNDEFINED) {
- ir_print_visitor v;
- printf("Failed to get tree for expression operand:\n");
- deref->accept(&v);
- exit(1);
- }
-
- ir_to_mesa_src_reg src;
-
- src = this->result;
- src.swizzle = MAKE_SWIZZLE4(components[0],
- components[1],
- components[2],
- components[3]);
- src.negate = ((unsigned(negate[0]) << 0)
- | (unsigned(negate[1]) << 1)
- | (unsigned(negate[2]) << 2)
- | (unsigned(negate[3]) << 3));
-
- /* Storage for our result. Ideally for an assignment we'd be using the
- * actual storage for the result here, instead.
- */
- const ir_to_mesa_src_reg result_src = get_temp(ir->type);
- ir_to_mesa_dst_reg result_dst = ir_to_mesa_dst_reg_from_src(result_src);
-
- /* Limit writes to the channels that will be used by result_src later.
- * This does limit this temp's use as a temporary for multi-instruction
- * sequences.
- */
- result_dst.writemask = (1 << ir->type->vector_elements) - 1;
-
- ir_to_mesa_emit_op1(ir, OPCODE_SWZ, result_dst, src);
- this->result = result_src;
-}
-
-void
-ir_to_mesa_visitor::visit(ir_expression *ir)
-{
- unsigned int operand;
- struct ir_to_mesa_src_reg op[Elements(ir->operands)];
- struct ir_to_mesa_src_reg result_src;
- struct ir_to_mesa_dst_reg result_dst;
-
- /* Quick peephole: Emit OPCODE_MAD(a, b, c) instead of ADD(MUL(a, b), c)
- */
- if (ir->operation == ir_binop_add) {
- if (try_emit_mad(ir, 1))
- return;
- if (try_emit_mad(ir, 0))
- return;
- }
- if (try_emit_sat(ir))
- return;
-
- if (ir->operation == ir_quadop_vector) {
- this->emit_swz(ir);
- return;
- }
-
- for (operand = 0; operand < ir->get_num_operands(); operand++) {
- this->result.file = PROGRAM_UNDEFINED;
- ir->operands[operand]->accept(this);
- if (this->result.file == PROGRAM_UNDEFINED) {
- ir_print_visitor v;
- printf("Failed to get tree for expression operand:\n");
- ir->operands[operand]->accept(&v);
- exit(1);
- }
- op[operand] = this->result;
-
- /* Matrix expression operands should have been broken down to vector
- * operations already.
- */
- assert(!ir->operands[operand]->type->is_matrix());
- }
-
- int vector_elements = ir->operands[0]->type->vector_elements;
- if (ir->operands[1]) {
- vector_elements = MAX2(vector_elements,
- ir->operands[1]->type->vector_elements);
- }
-
- this->result.file = PROGRAM_UNDEFINED;
-
- /* Storage for our result. Ideally for an assignment we'd be using
- * the actual storage for the result here, instead.
- */
- result_src = get_temp(ir->type);
- /* convenience for the emit functions below. */
- result_dst = ir_to_mesa_dst_reg_from_src(result_src);
- /* Limit writes to the channels that will be used by result_src later.
- * This does limit this temp's use as a temporary for multi-instruction
- * sequences.
- */
- result_dst.writemask = (1 << ir->type->vector_elements) - 1;
-
- switch (ir->operation) {
- case ir_unop_logic_not:
- ir_to_mesa_emit_op2(ir, OPCODE_SEQ, result_dst,
- op[0], src_reg_for_float(0.0));
- break;
- case ir_unop_neg:
- op[0].negate = ~op[0].negate;
- result_src = op[0];
- break;
- case ir_unop_abs:
- ir_to_mesa_emit_op1(ir, OPCODE_ABS, result_dst, op[0]);
- break;
- case ir_unop_sign:
- ir_to_mesa_emit_op1(ir, OPCODE_SSG, result_dst, op[0]);
- break;
- case ir_unop_rcp:
- ir_to_mesa_emit_scalar_op1(ir, OPCODE_RCP, result_dst, op[0]);
- break;
-
- case ir_unop_exp2:
- ir_to_mesa_emit_scalar_op1(ir, OPCODE_EX2, result_dst, op[0]);
- break;
- case ir_unop_exp:
- case ir_unop_log:
- assert(!"not reached: should be handled by ir_explog_to_explog2");
- break;
- case ir_unop_log2:
- ir_to_mesa_emit_scalar_op1(ir, OPCODE_LG2, result_dst, op[0]);
- break;
- case ir_unop_sin:
- ir_to_mesa_emit_scalar_op1(ir, OPCODE_SIN, result_dst, op[0]);
- break;
- case ir_unop_cos:
- ir_to_mesa_emit_scalar_op1(ir, OPCODE_COS, result_dst, op[0]);
- break;
- case ir_unop_sin_reduced:
- emit_scs(ir, OPCODE_SIN, result_dst, op[0]);
- break;
- case ir_unop_cos_reduced:
- emit_scs(ir, OPCODE_COS, result_dst, op[0]);
- break;
-
- case ir_unop_dFdx:
- ir_to_mesa_emit_op1(ir, OPCODE_DDX, result_dst, op[0]);
- break;
- case ir_unop_dFdy:
- ir_to_mesa_emit_op1(ir, OPCODE_DDY, result_dst, op[0]);
- break;
-
- case ir_unop_noise: {
- const enum prog_opcode opcode =
- prog_opcode(OPCODE_NOISE1
- + (ir->operands[0]->type->vector_elements) - 1);
- assert((opcode >= OPCODE_NOISE1) && (opcode <= OPCODE_NOISE4));
-
- ir_to_mesa_emit_op1(ir, opcode, result_dst, op[0]);
- break;
- }
-
- case ir_binop_add:
- ir_to_mesa_emit_op2(ir, OPCODE_ADD, result_dst, op[0], op[1]);
- break;
- case ir_binop_sub:
- ir_to_mesa_emit_op2(ir, OPCODE_SUB, result_dst, op[0], op[1]);
- break;
-
- case ir_binop_mul:
- ir_to_mesa_emit_op2(ir, OPCODE_MUL, result_dst, op[0], op[1]);
- break;
- case ir_binop_div:
- assert(!"not reached: should be handled by ir_div_to_mul_rcp");
- case ir_binop_mod:
- assert(!"ir_binop_mod should have been converted to b * fract(a/b)");
- break;
-
- case ir_binop_less:
- ir_to_mesa_emit_op2(ir, OPCODE_SLT, result_dst, op[0], op[1]);
- break;
- case ir_binop_greater:
- ir_to_mesa_emit_op2(ir, OPCODE_SGT, result_dst, op[0], op[1]);
- break;
- case ir_binop_lequal:
- ir_to_mesa_emit_op2(ir, OPCODE_SLE, result_dst, op[0], op[1]);
- break;
- case ir_binop_gequal:
- ir_to_mesa_emit_op2(ir, OPCODE_SGE, result_dst, op[0], op[1]);
- break;
- case ir_binop_equal:
- ir_to_mesa_emit_op2(ir, OPCODE_SEQ, result_dst, op[0], op[1]);
- break;
- case ir_binop_nequal:
- ir_to_mesa_emit_op2(ir, OPCODE_SNE, result_dst, op[0], op[1]);
- break;
- case ir_binop_all_equal:
- /* "==" operator producing a scalar boolean. */
- if (ir->operands[0]->type->is_vector() ||
- ir->operands[1]->type->is_vector()) {
- ir_to_mesa_src_reg temp = get_temp(glsl_type::vec4_type);
- ir_to_mesa_emit_op2(ir, OPCODE_SNE,
- ir_to_mesa_dst_reg_from_src(temp), op[0], op[1]);
- ir_to_mesa_emit_dp(ir, result_dst, temp, temp, vector_elements);
- ir_to_mesa_emit_op2(ir, OPCODE_SEQ,
- result_dst, result_src, src_reg_for_float(0.0));
- } else {
- ir_to_mesa_emit_op2(ir, OPCODE_SEQ, result_dst, op[0], op[1]);
- }
- break;
- case ir_binop_any_nequal:
- /* "!=" operator producing a scalar boolean. */
- if (ir->operands[0]->type->is_vector() ||
- ir->operands[1]->type->is_vector()) {
- ir_to_mesa_src_reg temp = get_temp(glsl_type::vec4_type);
- ir_to_mesa_emit_op2(ir, OPCODE_SNE,
- ir_to_mesa_dst_reg_from_src(temp), op[0], op[1]);
- ir_to_mesa_emit_dp(ir, result_dst, temp, temp, vector_elements);
- ir_to_mesa_emit_op2(ir, OPCODE_SNE,
- result_dst, result_src, src_reg_for_float(0.0));
- } else {
- ir_to_mesa_emit_op2(ir, OPCODE_SNE, result_dst, op[0], op[1]);
- }
- break;
-
- case ir_unop_any:
- assert(ir->operands[0]->type->is_vector());
- ir_to_mesa_emit_dp(ir, result_dst, op[0], op[0],
- ir->operands[0]->type->vector_elements);
- ir_to_mesa_emit_op2(ir, OPCODE_SNE,
- result_dst, result_src, src_reg_for_float(0.0));
- break;
-
- case ir_binop_logic_xor:
- ir_to_mesa_emit_op2(ir, OPCODE_SNE, result_dst, op[0], op[1]);
- break;
-
- case ir_binop_logic_or:
- /* This could be a saturated add and skip the SNE. */
- ir_to_mesa_emit_op2(ir, OPCODE_ADD,
- result_dst,
- op[0], op[1]);
-
- ir_to_mesa_emit_op2(ir, OPCODE_SNE,
- result_dst,
- result_src, src_reg_for_float(0.0));
- break;
-
- case ir_binop_logic_and:
- /* the bool args are stored as float 0.0 or 1.0, so "mul" gives us "and". */
- ir_to_mesa_emit_op2(ir, OPCODE_MUL,
- result_dst,
- op[0], op[1]);
- break;
-
- case ir_binop_dot:
- assert(ir->operands[0]->type->is_vector());
- assert(ir->operands[0]->type == ir->operands[1]->type);
- ir_to_mesa_emit_dp(ir, result_dst, op[0], op[1],
- ir->operands[0]->type->vector_elements);
- break;
-
- case ir_unop_sqrt:
- /* sqrt(x) = x * rsq(x). */
- ir_to_mesa_emit_scalar_op1(ir, OPCODE_RSQ, result_dst, op[0]);
- ir_to_mesa_emit_op2(ir, OPCODE_MUL, result_dst, result_src, op[0]);
- /* For incoming channels <= 0, set the result to 0. */
- op[0].negate = ~op[0].negate;
- ir_to_mesa_emit_op3(ir, OPCODE_CMP, result_dst,
- op[0], result_src, src_reg_for_float(0.0));
- break;
- case ir_unop_rsq:
- ir_to_mesa_emit_scalar_op1(ir, OPCODE_RSQ, result_dst, op[0]);
- break;
- case ir_unop_i2f:
- case ir_unop_b2f:
- case ir_unop_b2i:
- /* Mesa IR lacks types, ints are stored as truncated floats. */
- result_src = op[0];
- break;
- case ir_unop_f2i:
- ir_to_mesa_emit_op1(ir, OPCODE_TRUNC, result_dst, op[0]);
- break;
- case ir_unop_f2b:
- case ir_unop_i2b:
- ir_to_mesa_emit_op2(ir, OPCODE_SNE, result_dst,
- op[0], src_reg_for_float(0.0));
- break;
- case ir_unop_trunc:
- ir_to_mesa_emit_op1(ir, OPCODE_TRUNC, result_dst, op[0]);
- break;
- case ir_unop_ceil:
- op[0].negate = ~op[0].negate;
- ir_to_mesa_emit_op1(ir, OPCODE_FLR, result_dst, op[0]);
- result_src.negate = ~result_src.negate;
- break;
- case ir_unop_floor:
- ir_to_mesa_emit_op1(ir, OPCODE_FLR, result_dst, op[0]);
- break;
- case ir_unop_fract:
- ir_to_mesa_emit_op1(ir, OPCODE_FRC, result_dst, op[0]);
- break;
-
- case ir_binop_min:
- ir_to_mesa_emit_op2(ir, OPCODE_MIN, result_dst, op[0], op[1]);
- break;
- case ir_binop_max:
- ir_to_mesa_emit_op2(ir, OPCODE_MAX, result_dst, op[0], op[1]);
- break;
- case ir_binop_pow:
- ir_to_mesa_emit_scalar_op2(ir, OPCODE_POW, result_dst, op[0], op[1]);
- break;
-
- case ir_unop_bit_not:
- case ir_unop_u2f:
- case ir_binop_lshift:
- case ir_binop_rshift:
- case ir_binop_bit_and:
- case ir_binop_bit_xor:
- case ir_binop_bit_or:
- case ir_unop_round_even:
- assert(!"GLSL 1.30 features unsupported");
- break;
-
- case ir_quadop_vector:
- /* This operation should have already been handled.
- */
- assert(!"Should not get here.");
- break;
- }
-
- this->result = result_src;
-}
-
-
-void
-ir_to_mesa_visitor::visit(ir_swizzle *ir)
-{
- ir_to_mesa_src_reg src_reg;
- int i;
- int swizzle[4];
-
- /* Note that this is only swizzles in expressions, not those on the left
- * hand side of an assignment, which do write masking. See ir_assignment
- * for that.
- */
-
- ir->val->accept(this);
- src_reg = this->result;
- assert(src_reg.file != PROGRAM_UNDEFINED);
-
- for (i = 0; i < 4; i++) {
- if (i < ir->type->vector_elements) {
- switch (i) {
- case 0:
- swizzle[i] = GET_SWZ(src_reg.swizzle, ir->mask.x);
- break;
- case 1:
- swizzle[i] = GET_SWZ(src_reg.swizzle, ir->mask.y);
- break;
- case 2:
- swizzle[i] = GET_SWZ(src_reg.swizzle, ir->mask.z);
- break;
- case 3:
- swizzle[i] = GET_SWZ(src_reg.swizzle, ir->mask.w);
- break;
- }
- } else {
- /* If the type is smaller than a vec4, replicate the last
- * channel out.
- */
- swizzle[i] = swizzle[ir->type->vector_elements - 1];
- }
- }
-
- src_reg.swizzle = MAKE_SWIZZLE4(swizzle[0],
- swizzle[1],
- swizzle[2],
- swizzle[3]);
-
- this->result = src_reg;
-}
-
-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 (var->mode) {
- case ir_var_uniform:
- entry = new(mem_ctx) variable_storage(var, PROGRAM_UNIFORM,
- var->location);
- this->variables.push_tail(entry);
- break;
- case ir_var_in:
- case ir_var_inout:
- /* The linker assigns locations for varyings and attributes,
- * including deprecated builtins (like gl_Color), user-assign
- * generic attributes (glBindVertexLocation), and
- * user-defined varyings.
- *
- * FINISHME: We would hit this path for function arguments. Fix!
- */
- 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(var, PROGRAM_TEMPORARY,
- this->next_temp);
- this->variables.push_tail(entry);
-
- next_temp += type_size(var->type);
- break;
- }
-
- if (!entry) {
- printf("Failed to make storage for %s\n", var->name);
- exit(1);
- }
- }
-
- this->result = ir_to_mesa_src_reg(entry->file, entry->index, var->type);
-}
-
-void
-ir_to_mesa_visitor::visit(ir_dereference_array *ir)
-{
- ir_constant *index;
- ir_to_mesa_src_reg src_reg;
- int element_size = type_size(ir->type);
-
- index = ir->array_index->constant_expression_value();
-
- ir->array->accept(this);
- src_reg = this->result;
-
- if (index) {
- src_reg.index += index->value.i[0] * element_size;
- } else {
- ir_to_mesa_src_reg array_base = this->result;
- /* Variable index array dereference. It eats the "vec4" of the
- * base of the array and an index that offsets the Mesa register
- * index.
- */
- ir->array_index->accept(this);
-
- ir_to_mesa_src_reg index_reg;
-
- if (element_size == 1) {
- index_reg = this->result;
- } else {
- index_reg = get_temp(glsl_type::float_type);
-
- ir_to_mesa_emit_op2(ir, OPCODE_MUL,
- ir_to_mesa_dst_reg_from_src(index_reg),
- this->result, src_reg_for_float(element_size));
- }
-
- src_reg.reladdr = ralloc(mem_ctx, ir_to_mesa_src_reg);
- memcpy(src_reg.reladdr, &index_reg, sizeof(index_reg));
- }
-
- /* If the type is smaller than a vec4, replicate the last channel out. */
- if (ir->type->is_scalar() || ir->type->is_vector())
- src_reg.swizzle = swizzle_for_size(ir->type->vector_elements);
- else
- src_reg.swizzle = SWIZZLE_NOOP;
-
- this->result = src_reg;
-}
-
-void
-ir_to_mesa_visitor::visit(ir_dereference_record *ir)
-{
- unsigned int i;
- const glsl_type *struct_type = ir->record->type;
- int offset = 0;
-
- ir->record->accept(this);
-
- for (i = 0; i < struct_type->length; i++) {
- if (strcmp(struct_type->fields.structure[i].name, ir->field) == 0)
- break;
- offset += type_size(struct_type->fields.structure[i].type);
- }
-
- /* If the type is smaller than a vec4, replicate the last channel out. */
- if (ir->type->is_scalar() || ir->type->is_vector())
- this->result.swizzle = swizzle_for_size(ir->type->vector_elements);
- else
- this->result.swizzle = SWIZZLE_NOOP;
-
- this->result.index += offset;
-}
-
-/**
- * We want to be careful in assignment setup to hit the actual storage
- * instead of potentially using a temporary like we might with the
- * ir_dereference handler.
- */
-static struct ir_to_mesa_dst_reg
-get_assignment_lhs(ir_dereference *ir, ir_to_mesa_visitor *v)
-{
- /* The LHS must be a dereference. If the LHS is a variable indexed array
- * access of a vector, it must be separated into a series conditional moves
- * before reaching this point (see ir_vec_index_to_cond_assign).
- */
- assert(ir->as_dereference());
- ir_dereference_array *deref_array = ir->as_dereference_array();
- if (deref_array) {
- assert(!deref_array->array->type->is_vector());
- }
-
- /* Use the rvalue deref handler for the most part. We'll ignore
- * swizzles in it and write swizzles using writemask, though.
- */
- ir->accept(v);
- return ir_to_mesa_dst_reg_from_src(v->result);
-}
-
-/**
- * Process the condition of a conditional assignment
- *
- * Examines the condition of a conditional assignment to generate the optimal
- * first operand of a \c CMP instruction. If the condition is a relational
- * operator with 0 (e.g., \c ir_binop_less), the value being compared will be
- * used as the source for the \c CMP instruction. Otherwise the comparison
- * is processed to a boolean result, and the boolean result is used as the
- * operand to the CMP instruction.
- */
-bool
-ir_to_mesa_visitor::process_move_condition(ir_rvalue *ir)
-{
- ir_rvalue *src_ir = ir;
- bool negate = true;
- bool switch_order = false;
-
- ir_expression *const expr = ir->as_expression();
- if ((expr != NULL) && (expr->get_num_operands() == 2)) {
- bool zero_on_left = false;
-
- if (expr->operands[0]->is_zero()) {
- src_ir = expr->operands[1];
- zero_on_left = true;
- } else if (expr->operands[1]->is_zero()) {
- src_ir = expr->operands[0];
- zero_on_left = false;
- }
-
- /* a is - 0 + - 0 +
- * (a < 0) T F F ( a < 0) T F F
- * (0 < a) F F T (-a < 0) F F T
- * (a <= 0) T T F (-a < 0) F F T (swap order of other operands)
- * (0 <= a) F T T ( a < 0) T F F (swap order of other operands)
- * (a > 0) F F T (-a < 0) F F T
- * (0 > a) T F F ( a < 0) T F F
- * (a >= 0) F T T ( a < 0) T F F (swap order of other operands)
- * (0 >= a) T T F (-a < 0) F F T (swap order of other operands)
- *
- * Note that exchanging the order of 0 and 'a' in the comparison simply
- * means that the value of 'a' should be negated.
- */
- if (src_ir != ir) {
- switch (expr->operation) {
- case ir_binop_less:
- switch_order = false;
- negate = zero_on_left;
- break;
-
- case ir_binop_greater:
- switch_order = false;
- negate = !zero_on_left;
- break;
-
- case ir_binop_lequal:
- switch_order = true;
- negate = !zero_on_left;
- break;
-
- case ir_binop_gequal:
- switch_order = true;
- negate = zero_on_left;
- break;
-
- default:
- /* This isn't the right kind of comparison afterall, so make sure
- * the whole condition is visited.
- */
- src_ir = ir;
- break;
- }
- }
- }
-
- src_ir->accept(this);
-
- /* We use the OPCODE_CMP (a < 0 ? b : c) for conditional moves, and the
- * condition we produced is 0.0 or 1.0. By flipping the sign, we can
- * choose which value OPCODE_CMP produces without an extra instruction
- * computing the condition.
- */
- if (negate)
- this->result.negate = ~this->result.negate;
-
- return switch_order;
-}
-
-void
-ir_to_mesa_visitor::visit(ir_assignment *ir)
-{
- struct ir_to_mesa_dst_reg l;
- struct ir_to_mesa_src_reg r;
- int i;
-
- ir->rhs->accept(this);
- r = this->result;
-
- l = get_assignment_lhs(ir->lhs, this);
-
- /* FINISHME: This should really set to the correct maximal writemask for each
- * FINISHME: component written (in the loops below). This case can only
- * FINISHME: occur for matrices, arrays, and structures.
- */
- if (ir->write_mask == 0) {
- assert(!ir->lhs->type->is_scalar() && !ir->lhs->type->is_vector());
- l.writemask = WRITEMASK_XYZW;
- } else if (ir->lhs->type->is_scalar()) {
- /* FINISHME: This hack makes writing to gl_FragDepth, which lives in the
- * FINISHME: W component of fragment shader output zero, work correctly.
- */
- l.writemask = WRITEMASK_XYZW;
- } else {
- int swizzles[4];
- int first_enabled_chan = 0;
- int rhs_chan = 0;
-
- assert(ir->lhs->type->is_vector());
- l.writemask = ir->write_mask;
-
- for (int i = 0; i < 4; i++) {
- if (l.writemask & (1 << i)) {
- first_enabled_chan = GET_SWZ(r.swizzle, i);
- break;
- }
- }
-
- /* Swizzle a small RHS vector into the channels being written.
- *
- * glsl ir treats write_mask as dictating how many channels are
- * present on the RHS while Mesa IR treats write_mask as just
- * showing which channels of the vec4 RHS get written.
- */
- for (int i = 0; i < 4; i++) {
- if (l.writemask & (1 << i))
- swizzles[i] = GET_SWZ(r.swizzle, rhs_chan++);
- else
- swizzles[i] = first_enabled_chan;
- }
- r.swizzle = MAKE_SWIZZLE4(swizzles[0], swizzles[1],
- swizzles[2], swizzles[3]);
- }
-
- assert(l.file != PROGRAM_UNDEFINED);
- assert(r.file != PROGRAM_UNDEFINED);
-
- if (ir->condition) {
- const bool switch_order = this->process_move_condition(ir->condition);
- ir_to_mesa_src_reg condition = this->result;
-
- for (i = 0; i < type_size(ir->lhs->type); i++) {
- if (switch_order) {
- ir_to_mesa_emit_op3(ir, OPCODE_CMP, l,
- condition, ir_to_mesa_src_reg_from_dst(l), r);
- } else {
- ir_to_mesa_emit_op3(ir, OPCODE_CMP, l,
- condition, r, ir_to_mesa_src_reg_from_dst(l));
- }
-
- l.index++;
- r.index++;
- }
- } else {
- for (i = 0; i < type_size(ir->lhs->type); i++) {
- ir_to_mesa_emit_op1(ir, OPCODE_MOV, l, r);
- l.index++;
- r.index++;
- }
- }
-}
-
-
-void
-ir_to_mesa_visitor::visit(ir_constant *ir)
-{
- ir_to_mesa_src_reg src_reg;
- GLfloat stack_vals[4] = { 0 };
- GLfloat *values = stack_vals;
- unsigned int i;
-
- /* Unfortunately, 4 floats is all we can get into
- * _mesa_add_unnamed_constant. So, make a temp to store an
- * aggregate constant and move each constant value into it. If we
- * get lucky, copy propagation will eliminate the extra moves.
- */
-
- if (ir->type->base_type == GLSL_TYPE_STRUCT) {
- ir_to_mesa_src_reg temp_base = get_temp(ir->type);
- ir_to_mesa_dst_reg temp = ir_to_mesa_dst_reg_from_src(temp_base);
-
- foreach_iter(exec_list_iterator, iter, ir->components) {
- ir_constant *field_value = (ir_constant *)iter.get();
- int size = type_size(field_value->type);
-
- assert(size > 0);
-
- field_value->accept(this);
- src_reg = this->result;
-
- for (i = 0; i < (unsigned int)size; i++) {
- ir_to_mesa_emit_op1(ir, OPCODE_MOV, temp, src_reg);
-
- src_reg.index++;
- temp.index++;
- }
- }
- this->result = temp_base;
- return;
- }
-
- if (ir->type->is_array()) {
- ir_to_mesa_src_reg temp_base = get_temp(ir->type);
- ir_to_mesa_dst_reg temp = ir_to_mesa_dst_reg_from_src(temp_base);
- int size = type_size(ir->type->fields.array);
-
- assert(size > 0);
-
- for (i = 0; i < ir->type->length; i++) {
- ir->array_elements[i]->accept(this);
- src_reg = this->result;
- for (int j = 0; j < size; j++) {
- ir_to_mesa_emit_op1(ir, OPCODE_MOV, temp, src_reg);
-
- src_reg.index++;
- temp.index++;
- }
- }
- this->result = temp_base;
- return;
- }
-
- if (ir->type->is_matrix()) {
- ir_to_mesa_src_reg mat = get_temp(ir->type);
- ir_to_mesa_dst_reg mat_column = ir_to_mesa_dst_reg_from_src(mat);
-
- for (i = 0; i < ir->type->matrix_columns; i++) {
- assert(ir->type->base_type == GLSL_TYPE_FLOAT);
- values = &ir->value.f[i * ir->type->vector_elements];
-
- src_reg = ir_to_mesa_src_reg(PROGRAM_CONSTANT, -1, NULL);
- src_reg.index = _mesa_add_unnamed_constant(this->prog->Parameters,
- values,
- ir->type->vector_elements,
- &src_reg.swizzle);
- ir_to_mesa_emit_op1(ir, OPCODE_MOV, mat_column, src_reg);
-
- mat_column.index++;
- }
-
- this->result = mat;
- return;
- }
-
- src_reg.file = PROGRAM_CONSTANT;
- switch (ir->type->base_type) {
- case GLSL_TYPE_FLOAT:
- values = &ir->value.f[0];
- break;
- case GLSL_TYPE_UINT:
- for (i = 0; i < ir->type->vector_elements; i++) {
- values[i] = ir->value.u[i];
- }
- break;
- case GLSL_TYPE_INT:
- for (i = 0; i < ir->type->vector_elements; i++) {
- values[i] = ir->value.i[i];
- }
- break;
- case GLSL_TYPE_BOOL:
- for (i = 0; i < ir->type->vector_elements; i++) {
- values[i] = ir->value.b[i];
- }
- break;
- default:
- assert(!"Non-float/uint/int/bool constant");
- }
-
- this->result = ir_to_mesa_src_reg(PROGRAM_CONSTANT, -1, ir->type);
- this->result.index = _mesa_add_unnamed_constant(this->prog->Parameters,
- values,
- ir->type->vector_elements,
- &this->result.swizzle);
-}
-
-function_entry *
-ir_to_mesa_visitor::get_function_signature(ir_function_signature *sig)
-{
- function_entry *entry;
-
- foreach_iter(exec_list_iterator, iter, this->function_signatures) {
- entry = (function_entry *)iter.get();
-
- if (entry->sig == sig)
- return entry;
- }
-
- entry = ralloc(mem_ctx, function_entry);
- entry->sig = sig;
- entry->sig_id = this->next_signature_id++;
- entry->bgn_inst = NULL;
-
- /* Allocate storage for all the parameters. */
- foreach_iter(exec_list_iterator, iter, sig->parameters) {
- ir_variable *param = (ir_variable *)iter.get();
- variable_storage *storage;
-
- storage = find_variable_storage(param);
- assert(!storage);
-
- storage = new(mem_ctx) variable_storage(param, PROGRAM_TEMPORARY,
- this->next_temp);
- this->variables.push_tail(storage);
-
- this->next_temp += type_size(param->type);
- }
-
- if (!sig->return_type->is_void()) {
- entry->return_reg = get_temp(sig->return_type);
- } else {
- entry->return_reg = ir_to_mesa_undef;
- }
-
- this->function_signatures.push_tail(entry);
- return entry;
-}
-
-void
-ir_to_mesa_visitor::visit(ir_call *ir)
-{
- ir_to_mesa_instruction *call_inst;
- ir_function_signature *sig = ir->get_callee();
- function_entry *entry = get_function_signature(sig);
- int i;
-
- /* Process in parameters. */
- exec_list_iterator sig_iter = sig->parameters.iterator();
- foreach_iter(exec_list_iterator, iter, *ir) {
- ir_rvalue *param_rval = (ir_rvalue *)iter.get();
- ir_variable *param = (ir_variable *)sig_iter.get();
-
- if (param->mode == ir_var_in ||
- param->mode == ir_var_inout) {
- variable_storage *storage = find_variable_storage(param);
- assert(storage);
-
- param_rval->accept(this);
- ir_to_mesa_src_reg r = this->result;
-
- ir_to_mesa_dst_reg l;
- l.file = storage->file;
- l.index = storage->index;
- l.reladdr = NULL;
- l.writemask = WRITEMASK_XYZW;
- l.cond_mask = COND_TR;
-
- for (i = 0; i < type_size(param->type); i++) {
- ir_to_mesa_emit_op1(ir, OPCODE_MOV, l, r);
- l.index++;
- r.index++;
- }
- }
-
- sig_iter.next();
- }
- assert(!sig_iter.has_next());
-
- /* Emit call instruction */
- call_inst = ir_to_mesa_emit_op1(ir, OPCODE_CAL,
- ir_to_mesa_undef_dst, ir_to_mesa_undef);
- call_inst->function = entry;
-
- /* Process out parameters. */
- sig_iter = sig->parameters.iterator();
- foreach_iter(exec_list_iterator, iter, *ir) {
- ir_rvalue *param_rval = (ir_rvalue *)iter.get();
- ir_variable *param = (ir_variable *)sig_iter.get();
-
- if (param->mode == ir_var_out ||
- param->mode == ir_var_inout) {
- variable_storage *storage = find_variable_storage(param);
- assert(storage);
-
- ir_to_mesa_src_reg r;
- r.file = storage->file;
- r.index = storage->index;
- r.reladdr = NULL;
- r.swizzle = SWIZZLE_NOOP;
- r.negate = 0;
-
- param_rval->accept(this);
- ir_to_mesa_dst_reg l = ir_to_mesa_dst_reg_from_src(this->result);
-
- for (i = 0; i < type_size(param->type); i++) {
- ir_to_mesa_emit_op1(ir, OPCODE_MOV, l, r);
- l.index++;
- r.index++;
- }
- }
-
- sig_iter.next();
- }
- assert(!sig_iter.has_next());
-
- /* Process return value. */
- this->result = entry->return_reg;
-}
-
-void
-ir_to_mesa_visitor::visit(ir_texture *ir)
-{
- ir_to_mesa_src_reg result_src, coord, lod_info, projector;
- ir_to_mesa_dst_reg result_dst, coord_dst;
- ir_to_mesa_instruction *inst = NULL;
- prog_opcode opcode = OPCODE_NOP;
-
- ir->coordinate->accept(this);
-
- /* Put our coords in a temp. We'll need to modify them for shadow,
- * projection, or LOD, so the only case we'd use it as is is if
- * we're doing plain old texturing. Mesa IR optimization should
- * handle cleaning up our mess in that case.
- */
- coord = get_temp(glsl_type::vec4_type);
- coord_dst = ir_to_mesa_dst_reg_from_src(coord);
- ir_to_mesa_emit_op1(ir, OPCODE_MOV, coord_dst,
- this->result);
-
- if (ir->projector) {
- ir->projector->accept(this);
- projector = this->result;
- }
-
- /* Storage for our result. Ideally for an assignment we'd be using
- * the actual storage for the result here, instead.
- */
- result_src = get_temp(glsl_type::vec4_type);
- result_dst = ir_to_mesa_dst_reg_from_src(result_src);
-
- switch (ir->op) {
- case ir_tex:
- opcode = OPCODE_TEX;
- break;
- case ir_txb:
- opcode = OPCODE_TXB;
- ir->lod_info.bias->accept(this);
- lod_info = this->result;
- break;
- case ir_txl:
- opcode = OPCODE_TXL;
- ir->lod_info.lod->accept(this);
- lod_info = this->result;
- break;
- case ir_txd:
- case ir_txf:
- assert(!"GLSL 1.30 features unsupported");
- break;
- }
-
- if (ir->projector) {
- if (opcode == OPCODE_TEX) {
- /* Slot the projector in as the last component of the coord. */
- coord_dst.writemask = WRITEMASK_W;
- ir_to_mesa_emit_op1(ir, OPCODE_MOV, coord_dst, projector);
- coord_dst.writemask = WRITEMASK_XYZW;
- opcode = OPCODE_TXP;
- } else {
- ir_to_mesa_src_reg coord_w = coord;
- coord_w.swizzle = SWIZZLE_WWWW;
-
- /* For the other TEX opcodes there's no projective version
- * since the last slot is taken up by lod info. Do the
- * projective divide now.
- */
- coord_dst.writemask = WRITEMASK_W;
- ir_to_mesa_emit_op1(ir, OPCODE_RCP, coord_dst, projector);
-
- coord_dst.writemask = WRITEMASK_XYZ;
- ir_to_mesa_emit_op2(ir, OPCODE_MUL, coord_dst, coord, coord_w);
-
- coord_dst.writemask = WRITEMASK_XYZW;
- coord.swizzle = SWIZZLE_XYZW;
- }
- }
-
- if (ir->shadow_comparitor) {
- /* Slot the shadow value in as the second to last component of the
- * coord.
- */
- ir->shadow_comparitor->accept(this);
- coord_dst.writemask = WRITEMASK_Z;
- ir_to_mesa_emit_op1(ir, OPCODE_MOV, coord_dst, this->result);
- coord_dst.writemask = WRITEMASK_XYZW;
- }
-
- if (opcode == OPCODE_TXL || opcode == OPCODE_TXB) {
- /* Mesa IR stores lod or lod bias in the last channel of the coords. */
- coord_dst.writemask = WRITEMASK_W;
- ir_to_mesa_emit_op1(ir, OPCODE_MOV, coord_dst, lod_info);
- coord_dst.writemask = WRITEMASK_XYZW;
- }
-
- inst = ir_to_mesa_emit_op1(ir, opcode, result_dst, coord);
-
- if (ir->shadow_comparitor)
- inst->tex_shadow = GL_TRUE;
-
- inst->sampler = _mesa_get_sampler_uniform_value(ir->sampler,
- this->shader_program,
- this->prog);
-
- const glsl_type *sampler_type = ir->sampler->type;
-
- switch (sampler_type->sampler_dimensionality) {
- case GLSL_SAMPLER_DIM_1D:
- inst->tex_target = (sampler_type->sampler_array)
- ? TEXTURE_1D_ARRAY_INDEX : TEXTURE_1D_INDEX;
- break;
- case GLSL_SAMPLER_DIM_2D:
- inst->tex_target = (sampler_type->sampler_array)
- ? TEXTURE_2D_ARRAY_INDEX : TEXTURE_2D_INDEX;
- break;
- case GLSL_SAMPLER_DIM_3D:
- inst->tex_target = TEXTURE_3D_INDEX;
- break;
- case GLSL_SAMPLER_DIM_CUBE:
- inst->tex_target = TEXTURE_CUBE_INDEX;
- break;
- case GLSL_SAMPLER_DIM_RECT:
- inst->tex_target = TEXTURE_RECT_INDEX;
- break;
- case GLSL_SAMPLER_DIM_BUF:
- assert(!"FINISHME: Implement ARB_texture_buffer_object");
- break;
- default:
- assert(!"Should not get here.");
- }
-
- this->result = result_src;
-}
-
-void
-ir_to_mesa_visitor::visit(ir_return *ir)
-{
- if (ir->get_value()) {
- ir_to_mesa_dst_reg l;
- int i;
-
- assert(current_function);
-
- ir->get_value()->accept(this);
- ir_to_mesa_src_reg r = this->result;
-
- l = ir_to_mesa_dst_reg_from_src(current_function->return_reg);
-
- for (i = 0; i < type_size(current_function->sig->return_type); i++) {
- ir_to_mesa_emit_op1(ir, OPCODE_MOV, l, r);
- l.index++;
- r.index++;
- }
- }
-
- ir_to_mesa_emit_op0(ir, OPCODE_RET);
-}
-
-void
-ir_to_mesa_visitor::visit(ir_discard *ir)
-{
- struct gl_fragment_program *fp = (struct gl_fragment_program *)this->prog;
-
- if (ir->condition) {
- ir->condition->accept(this);
- this->result.negate = ~this->result.negate;
- ir_to_mesa_emit_op1(ir, OPCODE_KIL, ir_to_mesa_undef_dst, this->result);
- } else {
- ir_to_mesa_emit_op0(ir, OPCODE_KIL_NV);
- }
-
- fp->UsesKill = GL_TRUE;
-}
-
-void
-ir_to_mesa_visitor::visit(ir_if *ir)
-{
- ir_to_mesa_instruction *cond_inst, *if_inst, *else_inst = NULL;
- ir_to_mesa_instruction *prev_inst;
-
- prev_inst = (ir_to_mesa_instruction *)this->instructions.get_tail();
-
- ir->condition->accept(this);
- assert(this->result.file != PROGRAM_UNDEFINED);
-
- if (this->options->EmitCondCodes) {
- cond_inst = (ir_to_mesa_instruction *)this->instructions.get_tail();
-
- /* See if we actually generated any instruction for generating
- * the condition. If not, then cook up a move to a temp so we
- * have something to set cond_update on.
- */
- if (cond_inst == prev_inst) {
- ir_to_mesa_src_reg temp = get_temp(glsl_type::bool_type);
- cond_inst = ir_to_mesa_emit_op1(ir->condition, OPCODE_MOV,
- ir_to_mesa_dst_reg_from_src(temp),
- result);
- }
- cond_inst->cond_update = GL_TRUE;
-
- if_inst = ir_to_mesa_emit_op0(ir->condition, OPCODE_IF);
- if_inst->dst_reg.cond_mask = COND_NE;
- } else {
- if_inst = ir_to_mesa_emit_op1(ir->condition,
- OPCODE_IF, ir_to_mesa_undef_dst,
- this->result);
- }
-
- this->instructions.push_tail(if_inst);
-
- visit_exec_list(&ir->then_instructions, this);
-
- if (!ir->else_instructions.is_empty()) {
- else_inst = ir_to_mesa_emit_op0(ir->condition, OPCODE_ELSE);
- visit_exec_list(&ir->else_instructions, this);
- }
-
- if_inst = ir_to_mesa_emit_op1(ir->condition, OPCODE_ENDIF,
- ir_to_mesa_undef_dst, ir_to_mesa_undef);
-}
-
-ir_to_mesa_visitor::ir_to_mesa_visitor()
-{
- result.file = PROGRAM_UNDEFINED;
- next_temp = 1;
- next_signature_id = 1;
- current_function = NULL;
- mem_ctx = ralloc_context(NULL);
-}
-
-ir_to_mesa_visitor::~ir_to_mesa_visitor()
-{
- ralloc_free(mem_ctx);
-}
-
-static struct prog_src_register
-mesa_src_reg_from_ir_src_reg(ir_to_mesa_src_reg reg)
-{
- struct prog_src_register mesa_reg;
-
- mesa_reg.File = reg.file;
- assert(reg.index < (1 << INST_INDEX_BITS));
- mesa_reg.Index = reg.index;
- mesa_reg.Swizzle = reg.swizzle;
- mesa_reg.RelAddr = reg.reladdr != NULL;
- mesa_reg.Negate = reg.negate;
- mesa_reg.Abs = 0;
- mesa_reg.HasIndex2 = GL_FALSE;
- mesa_reg.RelAddr2 = 0;
- mesa_reg.Index2 = 0;
-
- return mesa_reg;
-}
-
-static void
-set_branchtargets(ir_to_mesa_visitor *v,
- struct prog_instruction *mesa_instructions,
- int num_instructions)
-{
- int if_count = 0, loop_count = 0;
- int *if_stack, *loop_stack;
- int if_stack_pos = 0, loop_stack_pos = 0;
- int i, j;
-
- for (i = 0; i < num_instructions; i++) {
- switch (mesa_instructions[i].Opcode) {
- case OPCODE_IF:
- if_count++;
- break;
- case OPCODE_BGNLOOP:
- loop_count++;
- break;
- case OPCODE_BRK:
- case OPCODE_CONT:
- mesa_instructions[i].BranchTarget = -1;
- break;
- default:
- break;
- }
- }
-
- 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) {
- case OPCODE_IF:
- if_stack[if_stack_pos] = i;
- if_stack_pos++;
- break;
- case OPCODE_ELSE:
- mesa_instructions[if_stack[if_stack_pos - 1]].BranchTarget = i;
- if_stack[if_stack_pos - 1] = i;
- break;
- case OPCODE_ENDIF:
- mesa_instructions[if_stack[if_stack_pos - 1]].BranchTarget = i;
- if_stack_pos--;
- break;
- case OPCODE_BGNLOOP:
- loop_stack[loop_stack_pos] = i;
- loop_stack_pos++;
- break;
- case OPCODE_ENDLOOP:
- loop_stack_pos--;
- /* Rewrite any breaks/conts at this nesting level (haven't
- * already had a BranchTarget assigned) to point to the end
- * of the loop.
- */
- for (j = loop_stack[loop_stack_pos]; j < i; j++) {
- if (mesa_instructions[j].Opcode == OPCODE_BRK ||
- mesa_instructions[j].Opcode == OPCODE_CONT) {
- if (mesa_instructions[j].BranchTarget == -1) {
- mesa_instructions[j].BranchTarget = i;
- }
- }
- }
- /* The loop ends point at each other. */
- mesa_instructions[i].BranchTarget = loop_stack[loop_stack_pos];
- mesa_instructions[loop_stack[loop_stack_pos]].BranchTarget = i;
- break;
- case OPCODE_CAL:
- foreach_iter(exec_list_iterator, iter, v->function_signatures) {
- function_entry *entry = (function_entry *)iter.get();
-
- if (entry->sig_id == mesa_instructions[i].BranchTarget) {
- mesa_instructions[i].BranchTarget = entry->inst;
- break;
- }
- }
- break;
- default:
- break;
- }
- }
-}
-
-static void
-print_program(struct prog_instruction *mesa_instructions,
- ir_instruction **mesa_instruction_annotation,
- int num_instructions)
-{
- ir_instruction *last_ir = NULL;
- int i;
- int indent = 0;
-
- for (i = 0; i < num_instructions; i++) {
- struct prog_instruction *mesa_inst = mesa_instructions + i;
- ir_instruction *ir = mesa_instruction_annotation[i];
-
- fprintf(stdout, "%3d: ", i);
-
- if (last_ir != ir && ir) {
- int j;
-
- for (j = 0; j < indent; j++) {
- fprintf(stdout, " ");
- }
- ir->print();
- printf("\n");
- last_ir = ir;
-
- fprintf(stdout, " "); /* line number spacing. */
- }
-
- indent = _mesa_fprint_instruction_opt(stdout, mesa_inst, indent,
- PROG_PRINT_DEBUG, NULL);
- }
-}
-
-static void
-count_resources(struct gl_program *prog)
-{
- unsigned int i;
-
- prog->SamplersUsed = 0;
-
- for (i = 0; i < prog->NumInstructions; i++) {
- struct prog_instruction *inst = &prog->Instructions[i];
-
- if (_mesa_is_tex_instruction(inst->Opcode)) {
- prog->SamplerTargets[inst->TexSrcUnit] =
- (gl_texture_index)inst->TexSrcTarget;
- prog->SamplersUsed |= 1 << inst->TexSrcUnit;
- if (inst->TexShadow) {
- prog->ShadowSamplers |= 1 << inst->TexSrcUnit;
- }
- }
- }
-
- _mesa_update_shader_textures_used(prog);
-}
-
-struct uniform_sort {
- struct gl_uniform *u;
- int pos;
-};
-
-/* The shader_program->Uniforms list is almost sorted in increasing
- * uniform->{Frag,Vert}Pos locations, but not quite when there are
- * uniforms shared between targets. We need to add parameters in
- * increasing order for the targets.
- */
-static int
-sort_uniforms(const void *a, const void *b)
-{
- struct uniform_sort *u1 = (struct uniform_sort *)a;
- struct uniform_sort *u2 = (struct uniform_sort *)b;
-
- return u1->pos - u2->pos;
-}
-
-/* Add the uniforms to the parameters. The linker chose locations
- * in our parameters lists (which weren't created yet), which the
- * uniforms code will use to poke values into our parameters list
- * when uniforms are updated.
- */
-static void
-add_uniforms_to_parameters_list(struct gl_shader_program *shader_program,
- struct gl_shader *shader,
- struct gl_program *prog)
-{
- unsigned int i;
- unsigned int next_sampler = 0, num_uniforms = 0;
- struct uniform_sort *sorted_uniforms;
-
- sorted_uniforms = ralloc_array(NULL, struct uniform_sort,
- shader_program->Uniforms->NumUniforms);
-
- for (i = 0; i < shader_program->Uniforms->NumUniforms; i++) {
- struct gl_uniform *uniform = shader_program->Uniforms->Uniforms + i;
- int parameter_index = -1;
-
- switch (shader->Type) {
- case GL_VERTEX_SHADER:
- parameter_index = uniform->VertPos;
- break;
- case GL_FRAGMENT_SHADER:
- parameter_index = uniform->FragPos;
- break;
- case GL_GEOMETRY_SHADER:
- parameter_index = uniform->GeomPos;
- break;
- }
-
- /* Only add uniforms used in our target. */
- if (parameter_index != -1) {
- sorted_uniforms[num_uniforms].pos = parameter_index;
- sorted_uniforms[num_uniforms].u = uniform;
- num_uniforms++;
- }
- }
-
- qsort(sorted_uniforms, num_uniforms, sizeof(struct uniform_sort),
- sort_uniforms);
-
- for (i = 0; i < num_uniforms; i++) {
- struct gl_uniform *uniform = sorted_uniforms[i].u;
- int parameter_index = sorted_uniforms[i].pos;
- const glsl_type *type = uniform->Type;
- unsigned int size;
-
- if (type->is_vector() ||
- type->is_scalar()) {
- size = type->vector_elements;
- } else {
- size = type_size(type) * 4;
- }
-
- gl_register_file file;
- if (type->is_sampler() ||
- (type->is_array() && type->fields.array->is_sampler())) {
- file = PROGRAM_SAMPLER;
- } else {
- file = PROGRAM_UNIFORM;
- }
-
- GLint index = _mesa_lookup_parameter_index(prog->Parameters, -1,
- uniform->Name);
-
- if (index < 0) {
- index = _mesa_add_parameter(prog->Parameters, file,
- uniform->Name, size, type->gl_type,
- NULL, NULL, 0x0);
-
- /* Sampler uniform values are stored in prog->SamplerUnits,
- * and the entry in that array is selected by this index we
- * store in ParameterValues[].
- */
- if (file == PROGRAM_SAMPLER) {
- for (unsigned int j = 0; j < size / 4; j++)
- prog->Parameters->ParameterValues[index + j][0] = next_sampler++;
- }
-
- /* The location chosen in the Parameters list here (returned
- * from _mesa_add_uniform) has to match what the linker chose.
- */
- if (index != parameter_index) {
- fail_link(shader_program, "Allocation of uniform `%s' to target "
- "failed (%d vs %d)\n",
- uniform->Name, index, parameter_index);
- }
- }
- }
-
- ralloc_free(sorted_uniforms);
-}
-
-static void
-set_uniform_initializer(struct gl_context *ctx, void *mem_ctx,
- struct gl_shader_program *shader_program,
- const char *name, const glsl_type *type,
- ir_constant *val)
-{
- if (type->is_record()) {
- ir_constant *field_constant;
-
- field_constant = (ir_constant *)val->components.get_head();
-
- for (unsigned int i = 0; i < type->length; i++) {
- const glsl_type *field_type = type->fields.structure[i].type;
- 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);
- field_constant = (ir_constant *)field_constant->next;
- }
- return;
- }
-
- int loc = _mesa_get_uniform_location(ctx, shader_program, name);
-
- if (loc == -1) {
- fail_link(shader_program,
- "Couldn't find uniform for initializer %s\n", name);
- return;
- }
-
- for (unsigned int i = 0; i < (type->is_array() ? type->length : 1); i++) {
- ir_constant *element;
- const glsl_type *element_type;
- if (type->is_array()) {
- element = val->array_elements[i];
- element_type = type->fields.array;
- } else {
- element = val;
- element_type = type;
- }
-
- void *values;
-
- if (element_type->base_type == GLSL_TYPE_BOOL) {
- 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];
- }
- values = (void *)conv;
- element_type = glsl_type::get_instance(GLSL_TYPE_INT,
- element_type->vector_elements,
- 1);
- } else {
- values = &element->value;
- }
-
- if (element_type->is_matrix()) {
- _mesa_uniform_matrix(ctx, shader_program,
- element_type->matrix_columns,
- element_type->vector_elements,
- loc, 1, GL_FALSE, (GLfloat *)values);
- loc += element_type->matrix_columns;
- } else {
- _mesa_uniform(ctx, shader_program, loc, element_type->matrix_columns,
- values, element_type->gl_type);
- loc += type_size(element_type);
- }
- }
-}
-
-static void
-set_uniform_initializers(struct gl_context *ctx,
- struct gl_shader_program *shader_program)
-{
- void *mem_ctx = NULL;
-
- for (unsigned int i = 0; i < MESA_SHADER_TYPES; i++) {
- struct gl_shader *shader = shader_program->_LinkedShaders[i];
-
- if (shader == NULL)
- continue;
-
- foreach_iter(exec_list_iterator, iter, *shader->ir) {
- ir_instruction *ir = (ir_instruction *)iter.get();
- ir_variable *var = ir->as_variable();
-
- if (!var || var->mode != ir_var_uniform || !var->constant_value)
- continue;
-
- if (!mem_ctx)
- mem_ctx = ralloc_context(NULL);
-
- set_uniform_initializer(ctx, mem_ctx, shader_program, var->name,
- var->type, var->constant_value);
- }
- }
-
- ralloc_free(mem_ctx);
-}
-
-/*
- * On a basic block basis, tracks available PROGRAM_TEMPORARY register
- * channels for copy propagation and updates following instructions to
- * use the original versions.
- *
- * The ir_to_mesa_visitor lazily produces code assuming that this pass
- * will occur. As an example, a TXP production before this pass:
- *
- * 0: MOV TEMP[1], INPUT[4].xyyy;
- * 1: MOV TEMP[1].w, INPUT[4].wwww;
- * 2: TXP TEMP[2], TEMP[1], texture[0], 2D;
- *
- * and after:
- *
- * 0: MOV TEMP[1], INPUT[4].xyyy;
- * 1: MOV TEMP[1].w, INPUT[4].wwww;
- * 2: TXP TEMP[2], INPUT[4].xyyw, texture[0], 2D;
- *
- * which allows for dead code elimination on TEMP[1]'s writes.
- */
-void
-ir_to_mesa_visitor::copy_propagate(void)
-{
- ir_to_mesa_instruction **acp = rzalloc_array(mem_ctx,
- ir_to_mesa_instruction *,
- this->next_temp * 4);
-
- 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;
- bool good = true;
- int acp_base = inst->src_reg[r].index * 4;
-
- if (inst->src_reg[r].file != PROGRAM_TEMPORARY ||
- inst->src_reg[r].reladdr)
- continue;
-
- /* See if we can find entries in the ACP consisting of MOVs
- * from the same src register for all the swizzled channels
- * of this src register reference.
- */
- for (int i = 0; i < 4; i++) {
- int src_chan = GET_SWZ(inst->src_reg[r].swizzle, i);
- ir_to_mesa_instruction *copy_chan = acp[acp_base + src_chan];
-
- if (!copy_chan) {
- good = false;
- break;
- }
-
- if (!first) {
- first = copy_chan;
- } else {
- if (first->src_reg[0].file != copy_chan->src_reg[0].file ||
- first->src_reg[0].index != copy_chan->src_reg[0].index) {
- good = false;
- break;
- }
- }
- }
-
- if (good) {
- /* We've now validated that we can copy-propagate to
- * replace this src register reference. Do it.
- */
- inst->src_reg[r].file = first->src_reg[0].file;
- inst->src_reg[r].index = first->src_reg[0].index;
-
- int swizzle = 0;
- for (int i = 0; i < 4; i++) {
- int src_chan = GET_SWZ(inst->src_reg[r].swizzle, i);
- ir_to_mesa_instruction *copy_inst = acp[acp_base + src_chan];
- swizzle |= (GET_SWZ(copy_inst->src_reg[0].swizzle, src_chan) <<
- (3 * i));
- }
- inst->src_reg[r].swizzle = swizzle;
- }
- }
-
- 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;
-
- default:
- /* Continuing the block, clear any written channels from
- * the ACP.
- */
- 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]->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;
- }
- }
- }
- }
- break;
- }
-
- /* If this is a copy, add it to the ACP. */
- if (inst->op == OPCODE_MOV &&
- inst->dst_reg.file == PROGRAM_TEMPORARY &&
- !inst->dst_reg.reladdr &&
- !inst->saturate &&
- !inst->src_reg[0].reladdr &&
- !inst->src_reg[0].negate) {
- for (int i = 0; i < 4; i++) {
- if (inst->dst_reg.writemask & (1 << i)) {
- acp[4 * inst->dst_reg.index + i] = inst;
- }
- }
- }
- }
-
- ralloc_free(acp);
-}
-
-
-/**
- * Convert a shader's GLSL IR into a Mesa gl_program.
- */
-static struct gl_program *
-get_mesa_program(struct gl_context *ctx,
- struct gl_shader_program *shader_program,
- struct gl_shader *shader)
-{
- ir_to_mesa_visitor v;
- struct prog_instruction *mesa_instructions, *mesa_inst;
- ir_instruction **mesa_instruction_annotation;
- int i;
- struct gl_program *prog;
- GLenum target;
- const char *target_string;
- GLboolean progress;
- struct gl_shader_compiler_options *options =
- &ctx->ShaderCompilerOptions[_mesa_shader_type_to_index(shader->Type)];
-
- switch (shader->Type) {
- case GL_VERTEX_SHADER:
- target = GL_VERTEX_PROGRAM_ARB;
- target_string = "vertex";
- break;
- case GL_FRAGMENT_SHADER:
- target = GL_FRAGMENT_PROGRAM_ARB;
- target_string = "fragment";
- break;
- case GL_GEOMETRY_SHADER:
- target = GL_GEOMETRY_PROGRAM_NV;
- target_string = "geometry";
- break;
- default:
- assert(!"should not be reached");
- return NULL;
- }
-
- validate_ir_tree(shader->ir);
-
- prog = ctx->Driver.NewProgram(ctx, target, shader_program->Name);
- if (!prog)
- return NULL;
- prog->Parameters = _mesa_new_parameter_list();
- prog->Varying = _mesa_new_parameter_list();
- prog->Attributes = _mesa_new_parameter_list();
- v.ctx = ctx;
- v.prog = prog;
- v.shader_program = shader_program;
- v.options = options;
-
- add_uniforms_to_parameters_list(shader_program, shader, prog);
-
- /* Emit Mesa IR for main(). */
- visit_exec_list(shader->ir, &v);
- v.ir_to_mesa_emit_op0(NULL, OPCODE_END);
-
- /* Now emit bodies for any functions that were used. */
- do {
- progress = GL_FALSE;
-
- foreach_iter(exec_list_iterator, iter, v.function_signatures) {
- function_entry *entry = (function_entry *)iter.get();
-
- if (!entry->bgn_inst) {
- v.current_function = entry;
-
- entry->bgn_inst = v.ir_to_mesa_emit_op0(NULL, OPCODE_BGNSUB);
- entry->bgn_inst->function = entry;
-
- visit_exec_list(&entry->sig->body, &v);
-
- ir_to_mesa_instruction *last;
- last = (ir_to_mesa_instruction *)v.instructions.get_tail();
- if (last->op != OPCODE_RET)
- v.ir_to_mesa_emit_op0(NULL, OPCODE_RET);
-
- ir_to_mesa_instruction *end;
- end = v.ir_to_mesa_emit_op0(NULL, OPCODE_ENDSUB);
- end->function = entry;
-
- progress = GL_TRUE;
- }
- }
- } while (progress);
-
- prog->NumTemporaries = v.next_temp;
-
- int num_instructions = 0;
- foreach_iter(exec_list_iterator, iter, v.instructions) {
- num_instructions++;
- }
-
- mesa_instructions =
- (struct prog_instruction *)calloc(num_instructions,
- sizeof(*mesa_instructions));
- mesa_instruction_annotation = ralloc_array(v.mem_ctx, ir_instruction *,
- num_instructions);
-
- v.copy_propagate();
-
- /* Convert ir_mesa_instructions into prog_instructions.
- */
- mesa_inst = mesa_instructions;
- i = 0;
- foreach_iter(exec_list_iterator, iter, v.instructions) {
- const ir_to_mesa_instruction *inst = (ir_to_mesa_instruction *)iter.get();
-
- mesa_inst->Opcode = inst->op;
- mesa_inst->CondUpdate = inst->cond_update;
- if (inst->saturate)
- mesa_inst->SaturateMode = SATURATE_ZERO_ONE;
- mesa_inst->DstReg.File = inst->dst_reg.file;
- mesa_inst->DstReg.Index = inst->dst_reg.index;
- mesa_inst->DstReg.CondMask = inst->dst_reg.cond_mask;
- mesa_inst->DstReg.WriteMask = inst->dst_reg.writemask;
- mesa_inst->DstReg.RelAddr = inst->dst_reg.reladdr != NULL;
- mesa_inst->SrcReg[0] = mesa_src_reg_from_ir_src_reg(inst->src_reg[0]);
- mesa_inst->SrcReg[1] = mesa_src_reg_from_ir_src_reg(inst->src_reg[1]);
- mesa_inst->SrcReg[2] = mesa_src_reg_from_ir_src_reg(inst->src_reg[2]);
- mesa_inst->TexSrcUnit = inst->sampler;
- mesa_inst->TexSrcTarget = inst->tex_target;
- mesa_inst->TexShadow = inst->tex_shadow;
- mesa_instruction_annotation[i] = inst->ir;
-
- /* Set IndirectRegisterFiles. */
- if (mesa_inst->DstReg.RelAddr)
- prog->IndirectRegisterFiles |= 1 << mesa_inst->DstReg.File;
-
- /* Update program's bitmask of indirectly accessed register files */
- for (unsigned src = 0; src < 3; src++)
- if (mesa_inst->SrcReg[src].RelAddr)
- prog->IndirectRegisterFiles |= 1 << mesa_inst->SrcReg[src].File;
-
- if (options->EmitNoIfs && mesa_inst->Opcode == OPCODE_IF) {
- fail_link(shader_program, "Couldn't flatten if statement\n");
- }
-
- switch (mesa_inst->Opcode) {
- case OPCODE_BGNSUB:
- inst->function->inst = i;
- mesa_inst->Comment = strdup(inst->function->sig->function_name());
- break;
- case OPCODE_ENDSUB:
- mesa_inst->Comment = strdup(inst->function->sig->function_name());
- break;
- case OPCODE_CAL:
- mesa_inst->BranchTarget = inst->function->sig_id; /* rewritten later */
- break;
- case OPCODE_ARL:
- prog->NumAddressRegs = 1;
- break;
- default:
- break;
- }
-
- mesa_inst++;
- i++;
-
- if (!shader_program->LinkStatus)
- break;
- }
-
- if (!shader_program->LinkStatus) {
- free(mesa_instructions);
- _mesa_reference_program(ctx, &shader->Program, NULL);
- return NULL;
- }
-
- set_branchtargets(&v, mesa_instructions, num_instructions);
-
- if (ctx->Shader.Flags & GLSL_DUMP) {
- printf("\n");
- printf("GLSL IR for linked %s program %d:\n", target_string,
- shader_program->Name);
- _mesa_print_ir(shader->ir, NULL);
- printf("\n");
- printf("\n");
- printf("Mesa IR for linked %s program %d:\n", target_string,
- shader_program->Name);
- print_program(mesa_instructions, mesa_instruction_annotation,
- num_instructions);
- }
-
- prog->Instructions = mesa_instructions;
- prog->NumInstructions = num_instructions;
-
- do_set_program_inouts(shader->ir, prog);
- count_resources(prog);
-
- _mesa_reference_program(ctx, &shader->Program, prog);
-
- if ((ctx->Shader.Flags & GLSL_NO_OPT) == 0) {
- _mesa_optimize_program(ctx, prog);
- }
-
- return prog;
-}
-
-extern "C" {
-
-/**
- * Called via ctx->Driver.CompilerShader().
- * This is a no-op.
- * XXX can we remove the ctx->Driver.CompileShader() hook?
- */
-GLboolean
-_mesa_ir_compile_shader(struct gl_context *ctx, struct gl_shader *shader)
-{
- assert(shader->CompileStatus);
- (void) ctx;
-
- return GL_TRUE;
-}
-
-
-/**
- * Link a shader.
- * Called via ctx->Driver.LinkShader()
- * This actually involves converting GLSL IR into Mesa gl_programs with
- * code lowering and other optimizations.
- */
-GLboolean
-_mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
-{
- assert(prog->LinkStatus);
-
- for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
- if (prog->_LinkedShaders[i] == NULL)
- continue;
-
- bool progress;
- exec_list *ir = prog->_LinkedShaders[i]->ir;
- const struct gl_shader_compiler_options *options =
- &ctx->ShaderCompilerOptions[_mesa_shader_type_to_index(prog->_LinkedShaders[i]->Type)];
-
- do {
- progress = false;
-
- /* Lowering */
- do_mat_op_to_vec(ir);
- lower_instructions(ir, (MOD_TO_FRACT | DIV_TO_MUL_RCP | EXP_TO_EXP2
- | LOG_TO_LOG2
- | ((options->EmitNoPow) ? POW_TO_EXP2 : 0)));
-
- progress = do_lower_jumps(ir, true, true, options->EmitNoMainReturn, options->EmitNoCont, options->EmitNoLoops) || progress;
-
- progress = do_common_optimization(ir, true, options->MaxUnrollIterations) || progress;
-
- progress = lower_quadop_vector(ir, true) || progress;
-
- if (options->EmitNoIfs) {
- progress = lower_discard(ir) || progress;
- progress = lower_if_to_cond_assign(ir) || progress;
- }
-
- if (options->EmitNoNoise)
- progress = lower_noise(ir) || progress;
-
- /* If there are forms of indirect addressing that the driver
- * cannot handle, perform the lowering pass.
- */
- if (options->EmitNoIndirectInput || options->EmitNoIndirectOutput
- || options->EmitNoIndirectTemp || options->EmitNoIndirectUniform)
- progress =
- lower_variable_index_to_cond_assign(ir,
- options->EmitNoIndirectInput,
- options->EmitNoIndirectOutput,
- options->EmitNoIndirectTemp,
- options->EmitNoIndirectUniform)
- || progress;
-
- progress = do_vec_index_to_cond_assign(ir) || progress;
- } while (progress);
-
- validate_ir_tree(ir);
- }
-
- for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
- struct gl_program *linked_prog;
-
- if (prog->_LinkedShaders[i] == NULL)
- continue;
-
- linked_prog = get_mesa_program(ctx, prog, prog->_LinkedShaders[i]);
-
- if (linked_prog) {
- bool ok = true;
-
- switch (prog->_LinkedShaders[i]->Type) {
- case GL_VERTEX_SHADER:
- _mesa_reference_vertprog(ctx, &prog->VertexProgram,
- (struct gl_vertex_program *)linked_prog);
- ok = ctx->Driver.ProgramStringNotify(ctx, GL_VERTEX_PROGRAM_ARB,
- linked_prog);
- break;
- case GL_FRAGMENT_SHADER:
- _mesa_reference_fragprog(ctx, &prog->FragmentProgram,
- (struct gl_fragment_program *)linked_prog);
- ok = ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_PROGRAM_ARB,
- linked_prog);
- break;
- case GL_GEOMETRY_SHADER:
- _mesa_reference_geomprog(ctx, &prog->GeometryProgram,
- (struct gl_geometry_program *)linked_prog);
- ok = ctx->Driver.ProgramStringNotify(ctx, GL_GEOMETRY_PROGRAM_NV,
- linked_prog);
- break;
- }
- if (!ok) {
- return GL_FALSE;
- }
- }
-
- _mesa_reference_program(ctx, &linked_prog, NULL);
- }
-
- return GL_TRUE;
-}
-
-
-/**
- * Compile a GLSL shader. Called via glCompileShader().
- */
-void
-_mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader)
-{
- struct _mesa_glsl_parse_state *state =
- new(shader) _mesa_glsl_parse_state(ctx, shader->Type, shader);
-
- const char *source = shader->Source;
- /* Check if the user called glCompileShader without first calling
- * glShaderSource. This should fail to compile, but not raise a GL_ERROR.
- */
- if (source == NULL) {
- shader->CompileStatus = GL_FALSE;
- return;
- }
-
- state->error = preprocess(state, &source, &state->info_log,
- &ctx->Extensions, ctx->API);
-
- if (ctx->Shader.Flags & GLSL_DUMP) {
- printf("GLSL source for shader %d:\n", shader->Name);
- printf("%s\n", shader->Source);
- }
-
- if (!state->error) {
- _mesa_glsl_lexer_ctor(state, source);
- _mesa_glsl_parse(state);
- _mesa_glsl_lexer_dtor(state);
- }
-
- 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);
-
- if (!state->error && !shader->ir->is_empty()) {
- validate_ir_tree(shader->ir);
-
- /* Do some optimization at compile time to reduce shader IR size
- * and reduce later work if the same shader is linked multiple times
- */
- while (do_common_optimization(shader->ir, false, 32))
- ;
-
- validate_ir_tree(shader->ir);
- }
-
- shader->symbols = state->symbols;
-
- shader->CompileStatus = !state->error;
- shader->InfoLog = state->info_log;
- shader->Version = state->language_version;
- memcpy(shader->builtins_to_link, state->builtins_to_link,
- sizeof(shader->builtins_to_link[0]) * state->num_builtins_to_link);
- shader->num_builtins_to_link = state->num_builtins_to_link;
-
- if (ctx->Shader.Flags & GLSL_LOG) {
- _mesa_write_shader_to_file(shader);
- }
-
- if (ctx->Shader.Flags & GLSL_DUMP) {
- if (shader->CompileStatus) {
- printf("GLSL IR for shader %d:\n", shader->Name);
- _mesa_print_ir(shader->ir, NULL);
- printf("\n\n");
- } else {
- printf("GLSL shader %d failed to compile.\n", shader->Name);
- }
- if (shader->InfoLog && shader->InfoLog[0] != 0) {
- printf("GLSL shader %d info log:\n", shader->Name);
- printf("%s\n", shader->InfoLog);
- }
- }
-
- /* Retain any live IR, but trash the rest. */
- reparent_ir(shader->ir, shader->ir);
-
- ralloc_free(state);
-
- if (shader->CompileStatus) {
- if (!ctx->Driver.CompileShader(ctx, shader))
- shader->CompileStatus = GL_FALSE;
- }
-}
-
-
-/**
- * Link a GLSL shader program. Called via glLinkProgram().
- */
-void
-_mesa_glsl_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
-{
- unsigned int i;
-
- _mesa_clear_shader_program_data(ctx, prog);
-
- prog->LinkStatus = GL_TRUE;
-
- for (i = 0; i < prog->NumShaders; i++) {
- if (!prog->Shaders[i]->CompileStatus) {
- fail_link(prog, "linking with uncompiled shader");
- prog->LinkStatus = GL_FALSE;
- }
- }
-
- prog->Varying = _mesa_new_parameter_list();
- _mesa_reference_vertprog(ctx, &prog->VertexProgram, NULL);
- _mesa_reference_fragprog(ctx, &prog->FragmentProgram, NULL);
- _mesa_reference_geomprog(ctx, &prog->GeometryProgram, NULL);
-
- if (prog->LinkStatus) {
- link_shaders(ctx, prog);
- }
-
- if (prog->LinkStatus) {
- if (!ctx->Driver.LinkShader(ctx, prog)) {
- prog->LinkStatus = GL_FALSE;
- }
- }
-
- set_uniform_initializers(ctx, prog);
-
- if (ctx->Shader.Flags & GLSL_DUMP) {
- if (!prog->LinkStatus) {
- printf("GLSL shader program %d failed to link\n", prog->Name);
- }
-
- if (prog->InfoLog && prog->InfoLog[0] != 0) {
- printf("GLSL shader program %d info log:\n", prog->Name);
- printf("%s\n", prog->InfoLog);
- }
- }
-}
-
-} /* extern "C" */
+/*
+ * Copyright (C) 2005-2007 Brian Paul All Rights Reserved.
+ * Copyright (C) 2008 VMware, Inc. All Rights Reserved.
+ * 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 ir_to_mesa.cpp
+ *
+ * Translate GLSL IR to Mesa's gl_program representation.
+ */
+
+#include <stdio.h>
+#include "main/compiler.h"
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_print_visitor.h"
+#include "ir_expression_flattening.h"
+#include "glsl_types.h"
+#include "glsl_parser_extras.h"
+#include "../glsl/program.h"
+#include "ir_optimization.h"
+#include "ast.h"
+
+extern "C" {
+#include "main/mtypes.h"
+#include "main/shaderapi.h"
+#include "main/shaderobj.h"
+#include "main/uniforms.h"
+#include "program/hash_table.h"
+#include "program/prog_instruction.h"
+#include "program/prog_optimize.h"
+#include "program/prog_print.h"
+#include "program/program.h"
+#include "program/prog_uniform.h"
+#include "program/prog_parameter.h"
+#include "program/sampler.h"
+}
+
+static int swizzle_for_size(int size);
+
+/**
+ * This struct is a corresponding struct to Mesa prog_src_register, with
+ * wider fields.
+ */
+typedef struct ir_to_mesa_src_reg {
+ ir_to_mesa_src_reg(int file, int index, const glsl_type *type)
+ {
+ this->file = (gl_register_file) file;
+ this->index = index;
+ if (type && (type->is_scalar() || type->is_vector() || type->is_matrix()))
+ this->swizzle = swizzle_for_size(type->vector_elements);
+ else
+ this->swizzle = SWIZZLE_XYZW;
+ this->negate = 0;
+ this->reladdr = NULL;
+ }
+
+ ir_to_mesa_src_reg()
+ {
+ this->file = PROGRAM_UNDEFINED;
+ this->index = 0;
+ this->swizzle = 0;
+ this->negate = 0;
+ this->reladdr = NULL;
+ }
+
+ gl_register_file file; /**< PROGRAM_* from Mesa */
+ int index; /**< temporary index, VERT_ATTRIB_*, FRAG_ATTRIB_*, etc. */
+ GLuint swizzle; /**< SWIZZLE_XYZWONEZERO swizzles from Mesa. */
+ int negate; /**< NEGATE_XYZW mask from mesa */
+ /** Register index should be offset by the integer in this reg. */
+ ir_to_mesa_src_reg *reladdr;
+} ir_to_mesa_src_reg;
+
+typedef struct ir_to_mesa_dst_reg {
+ int file; /**< PROGRAM_* from Mesa */
+ int index; /**< temporary index, VERT_ATTRIB_*, FRAG_ATTRIB_*, etc. */
+ int writemask; /**< Bitfield of WRITEMASK_[XYZW] */
+ GLuint cond_mask:4;
+ /** Register index should be offset by the integer in this reg. */
+ ir_to_mesa_src_reg *reladdr;
+} ir_to_mesa_dst_reg;
+
+extern ir_to_mesa_src_reg ir_to_mesa_undef;
+
+class ir_to_mesa_instruction : public exec_node {
+public:
+ /* 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 = rzalloc_size(ctx, size);
+ assert(node != NULL);
+
+ return node;
+ }
+
+ enum prog_opcode op;
+ ir_to_mesa_dst_reg dst_reg;
+ ir_to_mesa_src_reg src_reg[3];
+ /** Pointer to the ir source this tree came from for debugging */
+ ir_instruction *ir;
+ GLboolean cond_update;
+ bool saturate;
+ int sampler; /**< sampler index */
+ int tex_target; /**< One of TEXTURE_*_INDEX */
+ GLboolean tex_shadow;
+
+ class function_entry *function; /* Set on OPCODE_CAL or OPCODE_BGNSUB */
+};
+
+class variable_storage : public exec_node {
+public:
+ variable_storage(ir_variable *var, gl_register_file file, int index)
+ : file(file), index(index), var(var)
+ {
+ /* empty */
+ }
+
+ gl_register_file file;
+ int index;
+ ir_variable *var; /* variable that maps to this, if any */
+};
+
+class function_entry : public exec_node {
+public:
+ ir_function_signature *sig;
+
+ /**
+ * identifier of this function signature used by the program.
+ *
+ * At the point that Mesa instructions for function calls are
+ * generated, we don't know the address of the first instruction of
+ * the function body. So we make the BranchTarget that is called a
+ * small integer and rewrite them during set_branchtargets().
+ */
+ int sig_id;
+
+ /**
+ * Pointer to first instruction of the function body.
+ *
+ * Set during function body emits after main() is processed.
+ */
+ ir_to_mesa_instruction *bgn_inst;
+
+ /**
+ * Index of the first instruction of the function body in actual
+ * Mesa IR.
+ *
+ * Set after convertion from ir_to_mesa_instruction to prog_instruction.
+ */
+ int inst;
+
+ /** Storage for the return value. */
+ ir_to_mesa_src_reg return_reg;
+};
+
+class ir_to_mesa_visitor : public ir_visitor {
+public:
+ ir_to_mesa_visitor();
+ ~ir_to_mesa_visitor();
+
+ function_entry *current_function;
+
+ struct gl_context *ctx;
+ struct gl_program *prog;
+ struct gl_shader_program *shader_program;
+ struct gl_shader_compiler_options *options;
+
+ int next_temp;
+
+ variable_storage *find_variable_storage(ir_variable *var);
+
+ function_entry *get_function_signature(ir_function_signature *sig);
+
+ ir_to_mesa_src_reg get_temp(const glsl_type *type);
+ void reladdr_to_temp(ir_instruction *ir,
+ ir_to_mesa_src_reg *reg, int *num_reladdr);
+
+ struct ir_to_mesa_src_reg src_reg_for_float(float val);
+
+ /**
+ * \name Visit methods
+ *
+ * As typical for the visitor pattern, there must be one \c visit method for
+ * each concrete subclass of \c ir_instruction. Virtual base classes within
+ * the hierarchy should not have \c visit methods.
+ */
+ /*@{*/
+ virtual void visit(ir_variable *);
+ virtual void visit(ir_loop *);
+ virtual void visit(ir_loop_jump *);
+ virtual void visit(ir_function_signature *);
+ virtual void visit(ir_function *);
+ virtual void visit(ir_expression *);
+ virtual void visit(ir_swizzle *);
+ virtual void visit(ir_dereference_variable *);
+ virtual void visit(ir_dereference_array *);
+ virtual void visit(ir_dereference_record *);
+ virtual void visit(ir_assignment *);
+ virtual void visit(ir_constant *);
+ virtual void visit(ir_call *);
+ virtual void visit(ir_return *);
+ virtual void visit(ir_discard *);
+ virtual void visit(ir_texture *);
+ virtual void visit(ir_if *);
+ /*@}*/
+
+ struct ir_to_mesa_src_reg result;
+
+ /** List of variable_storage */
+ exec_list variables;
+
+ /** List of function_entry */
+ exec_list function_signatures;
+ int next_signature_id;
+
+ /** List of ir_to_mesa_instruction */
+ exec_list instructions;
+
+ ir_to_mesa_instruction *ir_to_mesa_emit_op0(ir_instruction *ir,
+ enum prog_opcode op);
+
+ ir_to_mesa_instruction *ir_to_mesa_emit_op1(ir_instruction *ir,
+ enum prog_opcode op,
+ ir_to_mesa_dst_reg dst,
+ ir_to_mesa_src_reg src0);
+
+ ir_to_mesa_instruction *ir_to_mesa_emit_op2(ir_instruction *ir,
+ enum prog_opcode op,
+ ir_to_mesa_dst_reg dst,
+ ir_to_mesa_src_reg src0,
+ ir_to_mesa_src_reg src1);
+
+ ir_to_mesa_instruction *ir_to_mesa_emit_op3(ir_instruction *ir,
+ enum prog_opcode op,
+ ir_to_mesa_dst_reg dst,
+ ir_to_mesa_src_reg src0,
+ ir_to_mesa_src_reg src1,
+ ir_to_mesa_src_reg src2);
+
+ /**
+ * Emit the correct dot-product instruction for the type of arguments
+ *
+ * \sa ir_to_mesa_emit_op2
+ */
+ void ir_to_mesa_emit_dp(ir_instruction *ir,
+ ir_to_mesa_dst_reg dst,
+ ir_to_mesa_src_reg src0,
+ ir_to_mesa_src_reg src1,
+ unsigned elements);
+
+ void ir_to_mesa_emit_scalar_op1(ir_instruction *ir,
+ enum prog_opcode op,
+ ir_to_mesa_dst_reg dst,
+ ir_to_mesa_src_reg src0);
+
+ void ir_to_mesa_emit_scalar_op2(ir_instruction *ir,
+ enum prog_opcode op,
+ ir_to_mesa_dst_reg dst,
+ ir_to_mesa_src_reg src0,
+ ir_to_mesa_src_reg src1);
+
+ void emit_scs(ir_instruction *ir, enum prog_opcode op,
+ ir_to_mesa_dst_reg dst,
+ const ir_to_mesa_src_reg &src);
+
+ GLboolean try_emit_mad(ir_expression *ir,
+ int mul_operand);
+ GLboolean try_emit_sat(ir_expression *ir);
+
+ void emit_swz(ir_expression *ir);
+
+ bool process_move_condition(ir_rvalue *ir);
+
+ void copy_propagate(void);
+
+ void *mem_ctx;
+};
+
+ir_to_mesa_src_reg ir_to_mesa_undef = ir_to_mesa_src_reg(PROGRAM_UNDEFINED, 0, NULL);
+
+ir_to_mesa_dst_reg ir_to_mesa_undef_dst = {
+ PROGRAM_UNDEFINED, 0, SWIZZLE_NOOP, COND_TR, NULL,
+};
+
+ir_to_mesa_dst_reg ir_to_mesa_address_reg = {
+ PROGRAM_ADDRESS, 0, WRITEMASK_X, COND_TR, NULL
+};
+
+static void
+fail_link(struct gl_shader_program *prog, const char *fmt, ...) PRINTFLIKE(2, 3);
+
+static void
+fail_link(struct gl_shader_program *prog, const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ ralloc_vasprintf_append(&prog->InfoLog, fmt, args);
+ va_end(args);
+
+ prog->LinkStatus = GL_FALSE;
+}
+
+static int
+swizzle_for_size(int size)
+{
+ int size_swizzles[4] = {
+ MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X),
+ MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y),
+ MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_Z),
+ MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W),
+ };
+
+ assert((size >= 1) && (size <= 4));
+ return size_swizzles[size - 1];
+}
+
+ir_to_mesa_instruction *
+ir_to_mesa_visitor::ir_to_mesa_emit_op3(ir_instruction *ir,
+ enum prog_opcode op,
+ ir_to_mesa_dst_reg dst,
+ ir_to_mesa_src_reg src0,
+ ir_to_mesa_src_reg src1,
+ ir_to_mesa_src_reg src2)
+{
+ ir_to_mesa_instruction *inst = new(mem_ctx) ir_to_mesa_instruction();
+ int num_reladdr = 0;
+
+ /* If we have to do relative addressing, we want to load the ARL
+ * reg directly for one of the regs, and preload the other reladdr
+ * sources into temps.
+ */
+ num_reladdr += dst.reladdr != NULL;
+ num_reladdr += src0.reladdr != NULL;
+ num_reladdr += src1.reladdr != NULL;
+ num_reladdr += src2.reladdr != NULL;
+
+ reladdr_to_temp(ir, &src2, &num_reladdr);
+ reladdr_to_temp(ir, &src1, &num_reladdr);
+ reladdr_to_temp(ir, &src0, &num_reladdr);
+
+ if (dst.reladdr) {
+ ir_to_mesa_emit_op1(ir, OPCODE_ARL, ir_to_mesa_address_reg,
+ *dst.reladdr);
+
+ num_reladdr--;
+ }
+ assert(num_reladdr == 0);
+
+ inst->op = op;
+ inst->dst_reg = dst;
+ inst->src_reg[0] = src0;
+ inst->src_reg[1] = src1;
+ inst->src_reg[2] = src2;
+ inst->ir = ir;
+
+ inst->function = NULL;
+
+ this->instructions.push_tail(inst);
+
+ return inst;
+}
+
+
+ir_to_mesa_instruction *
+ir_to_mesa_visitor::ir_to_mesa_emit_op2(ir_instruction *ir,
+ enum prog_opcode op,
+ ir_to_mesa_dst_reg dst,
+ ir_to_mesa_src_reg src0,
+ ir_to_mesa_src_reg src1)
+{
+ return ir_to_mesa_emit_op3(ir, op, dst, src0, src1, ir_to_mesa_undef);
+}
+
+ir_to_mesa_instruction *
+ir_to_mesa_visitor::ir_to_mesa_emit_op1(ir_instruction *ir,
+ enum prog_opcode op,
+ ir_to_mesa_dst_reg dst,
+ ir_to_mesa_src_reg src0)
+{
+ assert(dst.writemask != 0);
+ return ir_to_mesa_emit_op3(ir, op, dst,
+ src0, ir_to_mesa_undef, ir_to_mesa_undef);
+}
+
+ir_to_mesa_instruction *
+ir_to_mesa_visitor::ir_to_mesa_emit_op0(ir_instruction *ir,
+ enum prog_opcode op)
+{
+ return ir_to_mesa_emit_op3(ir, op, ir_to_mesa_undef_dst,
+ ir_to_mesa_undef,
+ ir_to_mesa_undef,
+ ir_to_mesa_undef);
+}
+
+void
+ir_to_mesa_visitor::ir_to_mesa_emit_dp(ir_instruction *ir,
+ ir_to_mesa_dst_reg dst,
+ ir_to_mesa_src_reg src0,
+ ir_to_mesa_src_reg src1,
+ unsigned elements)
+{
+ static const gl_inst_opcode dot_opcodes[] = {
+ OPCODE_DP2, OPCODE_DP3, OPCODE_DP4
+ };
+
+ ir_to_mesa_emit_op3(ir, dot_opcodes[elements - 2],
+ dst, src0, src1, ir_to_mesa_undef);
+}
+
+inline ir_to_mesa_dst_reg
+ir_to_mesa_dst_reg_from_src(ir_to_mesa_src_reg reg)
+{
+ ir_to_mesa_dst_reg dst_reg;
+
+ dst_reg.file = reg.file;
+ dst_reg.index = reg.index;
+ dst_reg.writemask = WRITEMASK_XYZW;
+ dst_reg.cond_mask = COND_TR;
+ dst_reg.reladdr = reg.reladdr;
+
+ return dst_reg;
+}
+
+inline ir_to_mesa_src_reg
+ir_to_mesa_src_reg_from_dst(ir_to_mesa_dst_reg reg)
+{
+ return ir_to_mesa_src_reg(reg.file, reg.index, NULL);
+}
+
+/**
+ * Emits Mesa scalar opcodes to produce unique answers across channels.
+ *
+ * Some Mesa opcodes are scalar-only, like ARB_fp/vp. The src X
+ * channel determines the result across all channels. So to do a vec4
+ * of this operation, we want to emit a scalar per source channel used
+ * to produce dest channels.
+ */
+void
+ir_to_mesa_visitor::ir_to_mesa_emit_scalar_op2(ir_instruction *ir,
+ enum prog_opcode op,
+ ir_to_mesa_dst_reg dst,
+ ir_to_mesa_src_reg orig_src0,
+ ir_to_mesa_src_reg orig_src1)
+{
+ int i, j;
+ int done_mask = ~dst.writemask;
+
+ /* Mesa RCP is a scalar operation splatting results to all channels,
+ * like ARB_fp/vp. So emit as many RCPs as necessary to cover our
+ * dst channels.
+ */
+ for (i = 0; i < 4; i++) {
+ GLuint this_mask = (1 << i);
+ ir_to_mesa_instruction *inst;
+ ir_to_mesa_src_reg src0 = orig_src0;
+ ir_to_mesa_src_reg src1 = orig_src1;
+
+ if (done_mask & this_mask)
+ continue;
+
+ GLuint src0_swiz = GET_SWZ(src0.swizzle, i);
+ GLuint src1_swiz = GET_SWZ(src1.swizzle, i);
+ for (j = i + 1; j < 4; j++) {
+ /* If there is another enabled component in the destination that is
+ * derived from the same inputs, generate its value on this pass as
+ * well.
+ */
+ if (!(done_mask & (1 << j)) &&
+ GET_SWZ(src0.swizzle, j) == src0_swiz &&
+ GET_SWZ(src1.swizzle, j) == src1_swiz) {
+ this_mask |= (1 << j);
+ }
+ }
+ src0.swizzle = MAKE_SWIZZLE4(src0_swiz, src0_swiz,
+ src0_swiz, src0_swiz);
+ src1.swizzle = MAKE_SWIZZLE4(src1_swiz, src1_swiz,
+ src1_swiz, src1_swiz);
+
+ inst = ir_to_mesa_emit_op2(ir, op,
+ dst,
+ src0,
+ src1);
+ inst->dst_reg.writemask = this_mask;
+ done_mask |= this_mask;
+ }
+}
+
+void
+ir_to_mesa_visitor::ir_to_mesa_emit_scalar_op1(ir_instruction *ir,
+ enum prog_opcode op,
+ ir_to_mesa_dst_reg dst,
+ ir_to_mesa_src_reg src0)
+{
+ ir_to_mesa_src_reg undef = ir_to_mesa_undef;
+
+ undef.swizzle = SWIZZLE_XXXX;
+
+ ir_to_mesa_emit_scalar_op2(ir, op, dst, src0, undef);
+}
+
+/**
+ * Emit an OPCODE_SCS instruction
+ *
+ * The \c SCS opcode functions a bit differently than the other Mesa (or
+ * ARB_fragment_program) opcodes. Instead of splatting its result across all
+ * four components of the destination, it writes one value to the \c x
+ * component and another value to the \c y component.
+ *
+ * \param ir IR instruction being processed
+ * \param op Either \c OPCODE_SIN or \c OPCODE_COS depending on which
+ * value is desired.
+ * \param dst Destination register
+ * \param src Source register
+ */
+void
+ir_to_mesa_visitor::emit_scs(ir_instruction *ir, enum prog_opcode op,
+ ir_to_mesa_dst_reg dst,
+ const ir_to_mesa_src_reg &src)
+{
+ /* Vertex programs cannot use the SCS opcode.
+ */
+ if (this->prog->Target == GL_VERTEX_PROGRAM_ARB) {
+ ir_to_mesa_emit_scalar_op1(ir, op, dst, src);
+ return;
+ }
+
+ const unsigned component = (op == OPCODE_SIN) ? 0 : 1;
+ const unsigned scs_mask = (1U << component);
+ int done_mask = ~dst.writemask;
+ ir_to_mesa_src_reg tmp;
+
+ assert(op == OPCODE_SIN || op == OPCODE_COS);
+
+ /* If there are compnents in the destination that differ from the component
+ * that will be written by the SCS instrution, we'll need a temporary.
+ */
+ if (scs_mask != unsigned(dst.writemask)) {
+ tmp = get_temp(glsl_type::vec4_type);
+ }
+
+ for (unsigned i = 0; i < 4; i++) {
+ unsigned this_mask = (1U << i);
+ ir_to_mesa_src_reg src0 = src;
+
+ if ((done_mask & this_mask) != 0)
+ continue;
+
+ /* The source swizzle specified which component of the source generates
+ * sine / cosine for the current component in the destination. The SCS
+ * instruction requires that this value be swizzle to the X component.
+ * Replace the current swizzle with a swizzle that puts the source in
+ * the X component.
+ */
+ unsigned src0_swiz = GET_SWZ(src.swizzle, i);
+
+ src0.swizzle = MAKE_SWIZZLE4(src0_swiz, src0_swiz,
+ src0_swiz, src0_swiz);
+ for (unsigned j = i + 1; j < 4; j++) {
+ /* If there is another enabled component in the destination that is
+ * derived from the same inputs, generate its value on this pass as
+ * well.
+ */
+ if (!(done_mask & (1 << j)) &&
+ GET_SWZ(src0.swizzle, j) == src0_swiz) {
+ this_mask |= (1 << j);
+ }
+ }
+
+ if (this_mask != scs_mask) {
+ ir_to_mesa_instruction *inst;
+ ir_to_mesa_dst_reg tmp_dst = ir_to_mesa_dst_reg_from_src(tmp);
+
+ /* Emit the SCS instruction.
+ */
+ inst = ir_to_mesa_emit_op1(ir, OPCODE_SCS, tmp_dst, src0);
+ inst->dst_reg.writemask = scs_mask;
+
+ /* Move the result of the SCS instruction to the desired location in
+ * the destination.
+ */
+ tmp.swizzle = MAKE_SWIZZLE4(component, component,
+ component, component);
+ inst = ir_to_mesa_emit_op1(ir, OPCODE_SCS, dst, tmp);
+ inst->dst_reg.writemask = this_mask;
+ } else {
+ /* Emit the SCS instruction to write directly to the destination.
+ */
+ ir_to_mesa_instruction *inst =
+ ir_to_mesa_emit_op1(ir, OPCODE_SCS, dst, src0);
+ inst->dst_reg.writemask = scs_mask;
+ }
+
+ done_mask |= this_mask;
+ }
+}
+
+struct ir_to_mesa_src_reg
+ir_to_mesa_visitor::src_reg_for_float(float val)
+{
+ ir_to_mesa_src_reg src_reg(PROGRAM_CONSTANT, -1, NULL);
+
+ src_reg.index = _mesa_add_unnamed_constant(this->prog->Parameters,
+ &val, 1, &src_reg.swizzle);
+
+ return src_reg;
+}
+
+static int
+type_size(const struct glsl_type *type)
+{
+ unsigned int i;
+ int size;
+
+ switch (type->base_type) {
+ case GLSL_TYPE_UINT:
+ case GLSL_TYPE_INT:
+ case GLSL_TYPE_FLOAT:
+ case GLSL_TYPE_BOOL:
+ if (type->is_matrix()) {
+ return type->matrix_columns;
+ } else {
+ /* Regardless of size of vector, it gets a vec4. This is bad
+ * packing for things like floats, but otherwise arrays become a
+ * mess. Hopefully a later pass over the code can pack scalars
+ * down if appropriate.
+ */
+ return 1;
+ }
+ case GLSL_TYPE_ARRAY:
+ assert(type->length > 0);
+ return type_size(type->fields.array) * type->length;
+ case GLSL_TYPE_STRUCT:
+ size = 0;
+ for (i = 0; i < type->length; i++) {
+ size += type_size(type->fields.structure[i].type);
+ }
+ return size;
+ case GLSL_TYPE_SAMPLER:
+ /* Samplers take up one slot in UNIFORMS[], but they're baked in
+ * at link time.
+ */
+ return 1;
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+/**
+ * In the initial pass of codegen, we assign temporary numbers to
+ * intermediate results. (not SSA -- variable assignments will reuse
+ * storage). Actual register allocation for the Mesa VM occurs in a
+ * pass over the Mesa IR later.
+ */
+ir_to_mesa_src_reg
+ir_to_mesa_visitor::get_temp(const glsl_type *type)
+{
+ ir_to_mesa_src_reg src_reg;
+ int swizzle[4];
+ int i;
+
+ src_reg.file = PROGRAM_TEMPORARY;
+ src_reg.index = next_temp;
+ src_reg.reladdr = NULL;
+ next_temp += type_size(type);
+
+ if (type->is_array() || type->is_record()) {
+ src_reg.swizzle = SWIZZLE_NOOP;
+ } else {
+ for (i = 0; i < type->vector_elements; i++)
+ swizzle[i] = i;
+ for (; i < 4; i++)
+ swizzle[i] = type->vector_elements - 1;
+ src_reg.swizzle = MAKE_SWIZZLE4(swizzle[0], swizzle[1],
+ swizzle[2], swizzle[3]);
+ }
+ src_reg.negate = 0;
+
+ return src_reg;
+}
+
+variable_storage *
+ir_to_mesa_visitor::find_variable_storage(ir_variable *var)
+{
+
+ variable_storage *entry;
+
+ foreach_iter(exec_list_iterator, iter, this->variables) {
+ entry = (variable_storage *)iter.get();
+
+ if (entry->var == var)
+ return entry;
+ }
+
+ return NULL;
+}
+
+void
+ir_to_mesa_visitor::visit(ir_variable *ir)
+{
+ if (strcmp(ir->name, "gl_FragCoord") == 0) {
+ struct gl_fragment_program *fp = (struct gl_fragment_program *)this->prog;
+
+ 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) {
+ unsigned int i;
+ const struct gl_builtin_uniform_desc *statevar;
+
+ for (i = 0; _mesa_builtin_uniform_desc[i].name; i++) {
+ if (strcmp(ir->name, _mesa_builtin_uniform_desc[i].name) == 0)
+ break;
+ }
+
+ if (!_mesa_builtin_uniform_desc[i].name) {
+ fail_link(this->shader_program,
+ "Failed to find builtin uniform `%s'\n", ir->name);
+ return;
+ }
+
+ statevar = &_mesa_builtin_uniform_desc[i];
+
+ int array_count;
+ if (ir->type->is_array()) {
+ array_count = ir->type->length;
+ } else {
+ array_count = 1;
+ }
+
+ /* Check if this statevar's setup in the STATE file exactly
+ * matches how we'll want to reference it as a
+ * struct/array/whatever. If not, then we need to move it into
+ * temporary storage and hope that it'll get copy-propagated
+ * out.
+ */
+ for (i = 0; i < statevar->num_elements; i++) {
+ if (statevar->elements[i].swizzle != SWIZZLE_XYZW) {
+ break;
+ }
+ }
+
+ struct variable_storage *storage;
+ ir_to_mesa_dst_reg dst;
+ if (i == statevar->num_elements) {
+ /* We'll set the index later. */
+ storage = new(mem_ctx) variable_storage(ir, PROGRAM_STATE_VAR, -1);
+ this->variables.push_tail(storage);
+
+ dst = ir_to_mesa_undef_dst;
+ } else {
+ storage = new(mem_ctx) variable_storage(ir, PROGRAM_TEMPORARY,
+ this->next_temp);
+ this->variables.push_tail(storage);
+ this->next_temp += type_size(ir->type);
+
+ dst = ir_to_mesa_dst_reg_from_src(ir_to_mesa_src_reg(PROGRAM_TEMPORARY,
+ storage->index,
+ NULL));
+ }
+
+
+ for (int a = 0; a < array_count; a++) {
+ for (unsigned int i = 0; i < statevar->num_elements; i++) {
+ struct gl_builtin_uniform_element *element = &statevar->elements[i];
+ int tokens[STATE_LENGTH];
+
+ memcpy(tokens, element->tokens, sizeof(element->tokens));
+ if (ir->type->is_array()) {
+ tokens[1] = a;
+ }
+
+ int index = _mesa_add_state_reference(this->prog->Parameters,
+ (gl_state_index *)tokens);
+
+ if (storage->file == PROGRAM_STATE_VAR) {
+ if (storage->index == -1) {
+ storage->index = index;
+ } else {
+ assert(index ==
+ (int)(storage->index + a * statevar->num_elements + i));
+ }
+ } else {
+ ir_to_mesa_src_reg src(PROGRAM_STATE_VAR, index, NULL);
+ src.swizzle = element->swizzle;
+ ir_to_mesa_emit_op1(ir, OPCODE_MOV, dst, src);
+ /* even a float takes up a whole vec4 reg in a struct/array. */
+ dst.index++;
+ }
+ }
+ }
+ if (storage->file == PROGRAM_TEMPORARY &&
+ dst.index != storage->index + type_size(ir->type)) {
+ fail_link(this->shader_program,
+ "failed to load builtin uniform `%s' (%d/%d regs loaded)\n",
+ ir->name, dst.index - storage->index,
+ type_size(ir->type));
+ }
+ }
+}
+
+void
+ir_to_mesa_visitor::visit(ir_loop *ir)
+{
+ ir_dereference_variable *counter = NULL;
+
+ if (ir->counter != NULL)
+ counter = new(ir) ir_dereference_variable(ir->counter);
+
+ if (ir->from != NULL) {
+ assert(ir->counter != NULL);
+
+ ir_assignment *a = new(ir) ir_assignment(counter, ir->from, NULL);
+
+ a->accept(this);
+ delete a;
+ }
+
+ ir_to_mesa_emit_op0(NULL, OPCODE_BGNLOOP);
+
+ if (ir->to) {
+ ir_expression *e =
+ new(ir) ir_expression(ir->cmp, glsl_type::bool_type,
+ counter, ir->to);
+ ir_if *if_stmt = new(ir) ir_if(e);
+
+ ir_loop_jump *brk = new(ir) ir_loop_jump(ir_loop_jump::jump_break);
+
+ if_stmt->then_instructions.push_tail(brk);
+
+ if_stmt->accept(this);
+
+ delete if_stmt;
+ delete e;
+ delete brk;
+ }
+
+ visit_exec_list(&ir->body_instructions, this);
+
+ if (ir->increment) {
+ ir_expression *e =
+ new(ir) ir_expression(ir_binop_add, counter->type,
+ counter, ir->increment);
+
+ ir_assignment *a = new(ir) ir_assignment(counter, e, NULL);
+
+ a->accept(this);
+ delete a;
+ delete e;
+ }
+
+ ir_to_mesa_emit_op0(NULL, OPCODE_ENDLOOP);
+}
+
+void
+ir_to_mesa_visitor::visit(ir_loop_jump *ir)
+{
+ switch (ir->mode) {
+ case ir_loop_jump::jump_break:
+ ir_to_mesa_emit_op0(NULL, OPCODE_BRK);
+ break;
+ case ir_loop_jump::jump_continue:
+ ir_to_mesa_emit_op0(NULL, OPCODE_CONT);
+ break;
+ }
+}
+
+
+void
+ir_to_mesa_visitor::visit(ir_function_signature *ir)
+{
+ assert(0);
+ (void)ir;
+}
+
+void
+ir_to_mesa_visitor::visit(ir_function *ir)
+{
+ /* Ignore function bodies other than main() -- we shouldn't see calls to
+ * them since they should all be inlined before we get to ir_to_mesa.
+ */
+ if (strcmp(ir->name, "main") == 0) {
+ const ir_function_signature *sig;
+ exec_list empty;
+
+ sig = ir->matching_signature(&empty);
+
+ assert(sig);
+
+ foreach_iter(exec_list_iterator, iter, sig->body) {
+ ir_instruction *ir = (ir_instruction *)iter.get();
+
+ ir->accept(this);
+ }
+ }
+}
+
+GLboolean
+ir_to_mesa_visitor::try_emit_mad(ir_expression *ir, int mul_operand)
+{
+ int nonmul_operand = 1 - mul_operand;
+ ir_to_mesa_src_reg a, b, c;
+
+ ir_expression *expr = ir->operands[mul_operand]->as_expression();
+ if (!expr || expr->operation != ir_binop_mul)
+ return false;
+
+ expr->operands[0]->accept(this);
+ a = this->result;
+ expr->operands[1]->accept(this);
+ b = this->result;
+ ir->operands[nonmul_operand]->accept(this);
+ c = this->result;
+
+ this->result = get_temp(ir->type);
+ ir_to_mesa_emit_op3(ir, OPCODE_MAD,
+ ir_to_mesa_dst_reg_from_src(this->result), a, b, c);
+
+ return true;
+}
+
+GLboolean
+ir_to_mesa_visitor::try_emit_sat(ir_expression *ir)
+{
+ /* Saturates were only introduced to vertex programs in
+ * NV_vertex_program3, so don't give them to drivers in the VP.
+ */
+ if (this->prog->Target == GL_VERTEX_PROGRAM_ARB)
+ return false;
+
+ ir_rvalue *sat_src = ir->as_rvalue_to_saturate();
+ if (!sat_src)
+ return false;
+
+ sat_src->accept(this);
+ ir_to_mesa_src_reg src = this->result;
+
+ this->result = get_temp(ir->type);
+ ir_to_mesa_instruction *inst;
+ inst = ir_to_mesa_emit_op1(ir, OPCODE_MOV,
+ ir_to_mesa_dst_reg_from_src(this->result),
+ src);
+ inst->saturate = true;
+
+ return true;
+}
+
+void
+ir_to_mesa_visitor::reladdr_to_temp(ir_instruction *ir,
+ ir_to_mesa_src_reg *reg, int *num_reladdr)
+{
+ if (!reg->reladdr)
+ return;
+
+ ir_to_mesa_emit_op1(ir, OPCODE_ARL, ir_to_mesa_address_reg, *reg->reladdr);
+
+ if (*num_reladdr != 1) {
+ ir_to_mesa_src_reg temp = get_temp(glsl_type::vec4_type);
+
+ ir_to_mesa_emit_op1(ir, OPCODE_MOV,
+ ir_to_mesa_dst_reg_from_src(temp), *reg);
+ *reg = temp;
+ }
+
+ (*num_reladdr)--;
+}
+
+void
+ir_to_mesa_visitor::emit_swz(ir_expression *ir)
+{
+ /* Assume that the vector operator is in a form compatible with OPCODE_SWZ.
+ * This means that each of the operands is either an immediate value of -1,
+ * 0, or 1, or is a component from one source register (possibly with
+ * negation).
+ */
+ uint8_t components[4] = { 0 };
+ bool negate[4] = { false };
+ ir_variable *var = NULL;
+
+ for (unsigned i = 0; i < ir->type->vector_elements; i++) {
+ ir_rvalue *op = ir->operands[i];
+
+ assert(op->type->is_scalar());
+
+ while (op != NULL) {
+ switch (op->ir_type) {
+ case ir_type_constant: {
+
+ assert(op->type->is_scalar());
+
+ const ir_constant *const c = op->as_constant();
+ if (c->is_one()) {
+ components[i] = SWIZZLE_ONE;
+ } else if (c->is_zero()) {
+ components[i] = SWIZZLE_ZERO;
+ } else if (c->is_negative_one()) {
+ components[i] = SWIZZLE_ONE;
+ negate[i] = true;
+ } else {
+ assert(!"SWZ constant must be 0.0 or 1.0.");
+ }
+
+ op = NULL;
+ break;
+ }
+
+ case ir_type_dereference_variable: {
+ ir_dereference_variable *const deref =
+ (ir_dereference_variable *) op;
+
+ assert((var == NULL) || (deref->var == var));
+ components[i] = SWIZZLE_X;
+ var = deref->var;
+ op = NULL;
+ break;
+ }
+
+ case ir_type_expression: {
+ ir_expression *const expr = (ir_expression *) op;
+
+ assert(expr->operation == ir_unop_neg);
+ negate[i] = true;
+
+ op = expr->operands[0];
+ break;
+ }
+
+ case ir_type_swizzle: {
+ ir_swizzle *const swiz = (ir_swizzle *) op;
+
+ components[i] = swiz->mask.x;
+ op = swiz->val;
+ break;
+ }
+
+ default:
+ assert(!"Should not get here.");
+ return;
+ }
+ }
+ }
+
+ assert(var != NULL);
+
+ ir_dereference_variable *const deref =
+ new(mem_ctx) ir_dereference_variable(var);
+
+ this->result.file = PROGRAM_UNDEFINED;
+ deref->accept(this);
+ if (this->result.file == PROGRAM_UNDEFINED) {
+ ir_print_visitor v;
+ printf("Failed to get tree for expression operand:\n");
+ deref->accept(&v);
+ exit(1);
+ }
+
+ ir_to_mesa_src_reg src;
+
+ src = this->result;
+ src.swizzle = MAKE_SWIZZLE4(components[0],
+ components[1],
+ components[2],
+ components[3]);
+ src.negate = ((unsigned(negate[0]) << 0)
+ | (unsigned(negate[1]) << 1)
+ | (unsigned(negate[2]) << 2)
+ | (unsigned(negate[3]) << 3));
+
+ /* Storage for our result. Ideally for an assignment we'd be using the
+ * actual storage for the result here, instead.
+ */
+ const ir_to_mesa_src_reg result_src = get_temp(ir->type);
+ ir_to_mesa_dst_reg result_dst = ir_to_mesa_dst_reg_from_src(result_src);
+
+ /* Limit writes to the channels that will be used by result_src later.
+ * This does limit this temp's use as a temporary for multi-instruction
+ * sequences.
+ */
+ result_dst.writemask = (1 << ir->type->vector_elements) - 1;
+
+ ir_to_mesa_emit_op1(ir, OPCODE_SWZ, result_dst, src);
+ this->result = result_src;
+}
+
+void
+ir_to_mesa_visitor::visit(ir_expression *ir)
+{
+ unsigned int operand;
+ struct ir_to_mesa_src_reg op[Elements(ir->operands)];
+ struct ir_to_mesa_src_reg result_src;
+ struct ir_to_mesa_dst_reg result_dst;
+
+ /* Quick peephole: Emit OPCODE_MAD(a, b, c) instead of ADD(MUL(a, b), c)
+ */
+ if (ir->operation == ir_binop_add) {
+ if (try_emit_mad(ir, 1))
+ return;
+ if (try_emit_mad(ir, 0))
+ return;
+ }
+ if (try_emit_sat(ir))
+ return;
+
+ if (ir->operation == ir_quadop_vector) {
+ this->emit_swz(ir);
+ return;
+ }
+
+ for (operand = 0; operand < ir->get_num_operands(); operand++) {
+ this->result.file = PROGRAM_UNDEFINED;
+ ir->operands[operand]->accept(this);
+ if (this->result.file == PROGRAM_UNDEFINED) {
+ ir_print_visitor v;
+ printf("Failed to get tree for expression operand:\n");
+ ir->operands[operand]->accept(&v);
+ exit(1);
+ }
+ op[operand] = this->result;
+
+ /* Matrix expression operands should have been broken down to vector
+ * operations already.
+ */
+ assert(!ir->operands[operand]->type->is_matrix());
+ }
+
+ int vector_elements = ir->operands[0]->type->vector_elements;
+ if (ir->operands[1]) {
+ vector_elements = MAX2(vector_elements,
+ ir->operands[1]->type->vector_elements);
+ }
+
+ this->result.file = PROGRAM_UNDEFINED;
+
+ /* Storage for our result. Ideally for an assignment we'd be using
+ * the actual storage for the result here, instead.
+ */
+ result_src = get_temp(ir->type);
+ /* convenience for the emit functions below. */
+ result_dst = ir_to_mesa_dst_reg_from_src(result_src);
+ /* Limit writes to the channels that will be used by result_src later.
+ * This does limit this temp's use as a temporary for multi-instruction
+ * sequences.
+ */
+ result_dst.writemask = (1 << ir->type->vector_elements) - 1;
+
+ switch (ir->operation) {
+ case ir_unop_logic_not:
+ ir_to_mesa_emit_op2(ir, OPCODE_SEQ, result_dst,
+ op[0], src_reg_for_float(0.0));
+ break;
+ case ir_unop_neg:
+ op[0].negate = ~op[0].negate;
+ result_src = op[0];
+ break;
+ case ir_unop_abs:
+ ir_to_mesa_emit_op1(ir, OPCODE_ABS, result_dst, op[0]);
+ break;
+ case ir_unop_sign:
+ ir_to_mesa_emit_op1(ir, OPCODE_SSG, result_dst, op[0]);
+ break;
+ case ir_unop_rcp:
+ ir_to_mesa_emit_scalar_op1(ir, OPCODE_RCP, result_dst, op[0]);
+ break;
+
+ case ir_unop_exp2:
+ ir_to_mesa_emit_scalar_op1(ir, OPCODE_EX2, result_dst, op[0]);
+ break;
+ case ir_unop_exp:
+ case ir_unop_log:
+ assert(!"not reached: should be handled by ir_explog_to_explog2");
+ break;
+ case ir_unop_log2:
+ ir_to_mesa_emit_scalar_op1(ir, OPCODE_LG2, result_dst, op[0]);
+ break;
+ case ir_unop_sin:
+ ir_to_mesa_emit_scalar_op1(ir, OPCODE_SIN, result_dst, op[0]);
+ break;
+ case ir_unop_cos:
+ ir_to_mesa_emit_scalar_op1(ir, OPCODE_COS, result_dst, op[0]);
+ break;
+ case ir_unop_sin_reduced:
+ emit_scs(ir, OPCODE_SIN, result_dst, op[0]);
+ break;
+ case ir_unop_cos_reduced:
+ emit_scs(ir, OPCODE_COS, result_dst, op[0]);
+ break;
+
+ case ir_unop_dFdx:
+ ir_to_mesa_emit_op1(ir, OPCODE_DDX, result_dst, op[0]);
+ break;
+ case ir_unop_dFdy:
+ ir_to_mesa_emit_op1(ir, OPCODE_DDY, result_dst, op[0]);
+ break;
+
+ case ir_unop_noise: {
+ const enum prog_opcode opcode =
+ prog_opcode(OPCODE_NOISE1
+ + (ir->operands[0]->type->vector_elements) - 1);
+ assert((opcode >= OPCODE_NOISE1) && (opcode <= OPCODE_NOISE4));
+
+ ir_to_mesa_emit_op1(ir, opcode, result_dst, op[0]);
+ break;
+ }
+
+ case ir_binop_add:
+ ir_to_mesa_emit_op2(ir, OPCODE_ADD, result_dst, op[0], op[1]);
+ break;
+ case ir_binop_sub:
+ ir_to_mesa_emit_op2(ir, OPCODE_SUB, result_dst, op[0], op[1]);
+ break;
+
+ case ir_binop_mul:
+ ir_to_mesa_emit_op2(ir, OPCODE_MUL, result_dst, op[0], op[1]);
+ break;
+ case ir_binop_div:
+ assert(!"not reached: should be handled by ir_div_to_mul_rcp");
+ case ir_binop_mod:
+ assert(!"ir_binop_mod should have been converted to b * fract(a/b)");
+ break;
+
+ case ir_binop_less:
+ ir_to_mesa_emit_op2(ir, OPCODE_SLT, result_dst, op[0], op[1]);
+ break;
+ case ir_binop_greater:
+ ir_to_mesa_emit_op2(ir, OPCODE_SGT, result_dst, op[0], op[1]);
+ break;
+ case ir_binop_lequal:
+ ir_to_mesa_emit_op2(ir, OPCODE_SLE, result_dst, op[0], op[1]);
+ break;
+ case ir_binop_gequal:
+ ir_to_mesa_emit_op2(ir, OPCODE_SGE, result_dst, op[0], op[1]);
+ break;
+ case ir_binop_equal:
+ ir_to_mesa_emit_op2(ir, OPCODE_SEQ, result_dst, op[0], op[1]);
+ break;
+ case ir_binop_nequal:
+ ir_to_mesa_emit_op2(ir, OPCODE_SNE, result_dst, op[0], op[1]);
+ break;
+ case ir_binop_all_equal:
+ /* "==" operator producing a scalar boolean. */
+ if (ir->operands[0]->type->is_vector() ||
+ ir->operands[1]->type->is_vector()) {
+ ir_to_mesa_src_reg temp = get_temp(glsl_type::vec4_type);
+ ir_to_mesa_emit_op2(ir, OPCODE_SNE,
+ ir_to_mesa_dst_reg_from_src(temp), op[0], op[1]);
+ ir_to_mesa_emit_dp(ir, result_dst, temp, temp, vector_elements);
+ ir_to_mesa_emit_op2(ir, OPCODE_SEQ,
+ result_dst, result_src, src_reg_for_float(0.0));
+ } else {
+ ir_to_mesa_emit_op2(ir, OPCODE_SEQ, result_dst, op[0], op[1]);
+ }
+ break;
+ case ir_binop_any_nequal:
+ /* "!=" operator producing a scalar boolean. */
+ if (ir->operands[0]->type->is_vector() ||
+ ir->operands[1]->type->is_vector()) {
+ ir_to_mesa_src_reg temp = get_temp(glsl_type::vec4_type);
+ ir_to_mesa_emit_op2(ir, OPCODE_SNE,
+ ir_to_mesa_dst_reg_from_src(temp), op[0], op[1]);
+ ir_to_mesa_emit_dp(ir, result_dst, temp, temp, vector_elements);
+ ir_to_mesa_emit_op2(ir, OPCODE_SNE,
+ result_dst, result_src, src_reg_for_float(0.0));
+ } else {
+ ir_to_mesa_emit_op2(ir, OPCODE_SNE, result_dst, op[0], op[1]);
+ }
+ break;
+
+ case ir_unop_any:
+ assert(ir->operands[0]->type->is_vector());
+ ir_to_mesa_emit_dp(ir, result_dst, op[0], op[0],
+ ir->operands[0]->type->vector_elements);
+ ir_to_mesa_emit_op2(ir, OPCODE_SNE,
+ result_dst, result_src, src_reg_for_float(0.0));
+ break;
+
+ case ir_binop_logic_xor:
+ ir_to_mesa_emit_op2(ir, OPCODE_SNE, result_dst, op[0], op[1]);
+ break;
+
+ case ir_binop_logic_or:
+ /* This could be a saturated add and skip the SNE. */
+ ir_to_mesa_emit_op2(ir, OPCODE_ADD,
+ result_dst,
+ op[0], op[1]);
+
+ ir_to_mesa_emit_op2(ir, OPCODE_SNE,
+ result_dst,
+ result_src, src_reg_for_float(0.0));
+ break;
+
+ case ir_binop_logic_and:
+ /* the bool args are stored as float 0.0 or 1.0, so "mul" gives us "and". */
+ ir_to_mesa_emit_op2(ir, OPCODE_MUL,
+ result_dst,
+ op[0], op[1]);
+ break;
+
+ case ir_binop_dot:
+ assert(ir->operands[0]->type->is_vector());
+ assert(ir->operands[0]->type == ir->operands[1]->type);
+ ir_to_mesa_emit_dp(ir, result_dst, op[0], op[1],
+ ir->operands[0]->type->vector_elements);
+ break;
+
+ case ir_unop_sqrt:
+ /* sqrt(x) = x * rsq(x). */
+ ir_to_mesa_emit_scalar_op1(ir, OPCODE_RSQ, result_dst, op[0]);
+ ir_to_mesa_emit_op2(ir, OPCODE_MUL, result_dst, result_src, op[0]);
+ /* For incoming channels <= 0, set the result to 0. */
+ op[0].negate = ~op[0].negate;
+ ir_to_mesa_emit_op3(ir, OPCODE_CMP, result_dst,
+ op[0], result_src, src_reg_for_float(0.0));
+ break;
+ case ir_unop_rsq:
+ ir_to_mesa_emit_scalar_op1(ir, OPCODE_RSQ, result_dst, op[0]);
+ break;
+ case ir_unop_i2f:
+ case ir_unop_b2f:
+ case ir_unop_b2i:
+ /* Mesa IR lacks types, ints are stored as truncated floats. */
+ result_src = op[0];
+ break;
+ case ir_unop_f2i:
+ ir_to_mesa_emit_op1(ir, OPCODE_TRUNC, result_dst, op[0]);
+ break;
+ case ir_unop_f2b:
+ case ir_unop_i2b:
+ ir_to_mesa_emit_op2(ir, OPCODE_SNE, result_dst,
+ op[0], src_reg_for_float(0.0));
+ break;
+ case ir_unop_trunc:
+ ir_to_mesa_emit_op1(ir, OPCODE_TRUNC, result_dst, op[0]);
+ break;
+ case ir_unop_ceil:
+ op[0].negate = ~op[0].negate;
+ ir_to_mesa_emit_op1(ir, OPCODE_FLR, result_dst, op[0]);
+ result_src.negate = ~result_src.negate;
+ break;
+ case ir_unop_floor:
+ ir_to_mesa_emit_op1(ir, OPCODE_FLR, result_dst, op[0]);
+ break;
+ case ir_unop_fract:
+ ir_to_mesa_emit_op1(ir, OPCODE_FRC, result_dst, op[0]);
+ break;
+
+ case ir_binop_min:
+ ir_to_mesa_emit_op2(ir, OPCODE_MIN, result_dst, op[0], op[1]);
+ break;
+ case ir_binop_max:
+ ir_to_mesa_emit_op2(ir, OPCODE_MAX, result_dst, op[0], op[1]);
+ break;
+ case ir_binop_pow:
+ ir_to_mesa_emit_scalar_op2(ir, OPCODE_POW, result_dst, op[0], op[1]);
+ break;
+
+ case ir_unop_bit_not:
+ case ir_unop_u2f:
+ case ir_binop_lshift:
+ case ir_binop_rshift:
+ case ir_binop_bit_and:
+ case ir_binop_bit_xor:
+ case ir_binop_bit_or:
+ case ir_unop_round_even:
+ assert(!"GLSL 1.30 features unsupported");
+ break;
+
+ case ir_quadop_vector:
+ /* This operation should have already been handled.
+ */
+ assert(!"Should not get here.");
+ break;
+ }
+
+ this->result = result_src;
+}
+
+
+void
+ir_to_mesa_visitor::visit(ir_swizzle *ir)
+{
+ ir_to_mesa_src_reg src_reg;
+ int i;
+ int swizzle[4];
+
+ /* Note that this is only swizzles in expressions, not those on the left
+ * hand side of an assignment, which do write masking. See ir_assignment
+ * for that.
+ */
+
+ ir->val->accept(this);
+ src_reg = this->result;
+ assert(src_reg.file != PROGRAM_UNDEFINED);
+
+ for (i = 0; i < 4; i++) {
+ if (i < ir->type->vector_elements) {
+ switch (i) {
+ case 0:
+ swizzle[i] = GET_SWZ(src_reg.swizzle, ir->mask.x);
+ break;
+ case 1:
+ swizzle[i] = GET_SWZ(src_reg.swizzle, ir->mask.y);
+ break;
+ case 2:
+ swizzle[i] = GET_SWZ(src_reg.swizzle, ir->mask.z);
+ break;
+ case 3:
+ swizzle[i] = GET_SWZ(src_reg.swizzle, ir->mask.w);
+ break;
+ }
+ } else {
+ /* If the type is smaller than a vec4, replicate the last
+ * channel out.
+ */
+ swizzle[i] = swizzle[ir->type->vector_elements - 1];
+ }
+ }
+
+ src_reg.swizzle = MAKE_SWIZZLE4(swizzle[0],
+ swizzle[1],
+ swizzle[2],
+ swizzle[3]);
+
+ this->result = src_reg;
+}
+
+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 (var->mode) {
+ case ir_var_uniform:
+ entry = new(mem_ctx) variable_storage(var, PROGRAM_UNIFORM,
+ var->location);
+ this->variables.push_tail(entry);
+ break;
+ case ir_var_in:
+ case ir_var_inout:
+ /* The linker assigns locations for varyings and attributes,
+ * including deprecated builtins (like gl_Color), user-assign
+ * generic attributes (glBindVertexLocation), and
+ * user-defined varyings.
+ *
+ * FINISHME: We would hit this path for function arguments. Fix!
+ */
+ 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(var, PROGRAM_TEMPORARY,
+ this->next_temp);
+ this->variables.push_tail(entry);
+
+ next_temp += type_size(var->type);
+ break;
+ }
+
+ if (!entry) {
+ printf("Failed to make storage for %s\n", var->name);
+ exit(1);
+ }
+ }
+
+ this->result = ir_to_mesa_src_reg(entry->file, entry->index, var->type);
+}
+
+void
+ir_to_mesa_visitor::visit(ir_dereference_array *ir)
+{
+ ir_constant *index;
+ ir_to_mesa_src_reg src_reg;
+ int element_size = type_size(ir->type);
+
+ index = ir->array_index->constant_expression_value();
+
+ ir->array->accept(this);
+ src_reg = this->result;
+
+ if (index) {
+ src_reg.index += index->value.i[0] * element_size;
+ } else {
+ ir_to_mesa_src_reg array_base = this->result;
+ /* Variable index array dereference. It eats the "vec4" of the
+ * base of the array and an index that offsets the Mesa register
+ * index.
+ */
+ ir->array_index->accept(this);
+
+ ir_to_mesa_src_reg index_reg;
+
+ if (element_size == 1) {
+ index_reg = this->result;
+ } else {
+ index_reg = get_temp(glsl_type::float_type);
+
+ ir_to_mesa_emit_op2(ir, OPCODE_MUL,
+ ir_to_mesa_dst_reg_from_src(index_reg),
+ this->result, src_reg_for_float(element_size));
+ }
+
+ src_reg.reladdr = ralloc(mem_ctx, ir_to_mesa_src_reg);
+ memcpy(src_reg.reladdr, &index_reg, sizeof(index_reg));
+ }
+
+ /* If the type is smaller than a vec4, replicate the last channel out. */
+ if (ir->type->is_scalar() || ir->type->is_vector())
+ src_reg.swizzle = swizzle_for_size(ir->type->vector_elements);
+ else
+ src_reg.swizzle = SWIZZLE_NOOP;
+
+ this->result = src_reg;
+}
+
+void
+ir_to_mesa_visitor::visit(ir_dereference_record *ir)
+{
+ unsigned int i;
+ const glsl_type *struct_type = ir->record->type;
+ int offset = 0;
+
+ ir->record->accept(this);
+
+ for (i = 0; i < struct_type->length; i++) {
+ if (strcmp(struct_type->fields.structure[i].name, ir->field) == 0)
+ break;
+ offset += type_size(struct_type->fields.structure[i].type);
+ }
+
+ /* If the type is smaller than a vec4, replicate the last channel out. */
+ if (ir->type->is_scalar() || ir->type->is_vector())
+ this->result.swizzle = swizzle_for_size(ir->type->vector_elements);
+ else
+ this->result.swizzle = SWIZZLE_NOOP;
+
+ this->result.index += offset;
+}
+
+/**
+ * We want to be careful in assignment setup to hit the actual storage
+ * instead of potentially using a temporary like we might with the
+ * ir_dereference handler.
+ */
+static struct ir_to_mesa_dst_reg
+get_assignment_lhs(ir_dereference *ir, ir_to_mesa_visitor *v)
+{
+ /* The LHS must be a dereference. If the LHS is a variable indexed array
+ * access of a vector, it must be separated into a series conditional moves
+ * before reaching this point (see ir_vec_index_to_cond_assign).
+ */
+ assert(ir->as_dereference());
+ ir_dereference_array *deref_array = ir->as_dereference_array();
+ if (deref_array) {
+ assert(!deref_array->array->type->is_vector());
+ }
+
+ /* Use the rvalue deref handler for the most part. We'll ignore
+ * swizzles in it and write swizzles using writemask, though.
+ */
+ ir->accept(v);
+ return ir_to_mesa_dst_reg_from_src(v->result);
+}
+
+/**
+ * Process the condition of a conditional assignment
+ *
+ * Examines the condition of a conditional assignment to generate the optimal
+ * first operand of a \c CMP instruction. If the condition is a relational
+ * operator with 0 (e.g., \c ir_binop_less), the value being compared will be
+ * used as the source for the \c CMP instruction. Otherwise the comparison
+ * is processed to a boolean result, and the boolean result is used as the
+ * operand to the CMP instruction.
+ */
+bool
+ir_to_mesa_visitor::process_move_condition(ir_rvalue *ir)
+{
+ ir_rvalue *src_ir = ir;
+ bool negate = true;
+ bool switch_order = false;
+
+ ir_expression *const expr = ir->as_expression();
+ if ((expr != NULL) && (expr->get_num_operands() == 2)) {
+ bool zero_on_left = false;
+
+ if (expr->operands[0]->is_zero()) {
+ src_ir = expr->operands[1];
+ zero_on_left = true;
+ } else if (expr->operands[1]->is_zero()) {
+ src_ir = expr->operands[0];
+ zero_on_left = false;
+ }
+
+ /* a is - 0 + - 0 +
+ * (a < 0) T F F ( a < 0) T F F
+ * (0 < a) F F T (-a < 0) F F T
+ * (a <= 0) T T F (-a < 0) F F T (swap order of other operands)
+ * (0 <= a) F T T ( a < 0) T F F (swap order of other operands)
+ * (a > 0) F F T (-a < 0) F F T
+ * (0 > a) T F F ( a < 0) T F F
+ * (a >= 0) F T T ( a < 0) T F F (swap order of other operands)
+ * (0 >= a) T T F (-a < 0) F F T (swap order of other operands)
+ *
+ * Note that exchanging the order of 0 and 'a' in the comparison simply
+ * means that the value of 'a' should be negated.
+ */
+ if (src_ir != ir) {
+ switch (expr->operation) {
+ case ir_binop_less:
+ switch_order = false;
+ negate = zero_on_left;
+ break;
+
+ case ir_binop_greater:
+ switch_order = false;
+ negate = !zero_on_left;
+ break;
+
+ case ir_binop_lequal:
+ switch_order = true;
+ negate = !zero_on_left;
+ break;
+
+ case ir_binop_gequal:
+ switch_order = true;
+ negate = zero_on_left;
+ break;
+
+ default:
+ /* This isn't the right kind of comparison afterall, so make sure
+ * the whole condition is visited.
+ */
+ src_ir = ir;
+ break;
+ }
+ }
+ }
+
+ src_ir->accept(this);
+
+ /* We use the OPCODE_CMP (a < 0 ? b : c) for conditional moves, and the
+ * condition we produced is 0.0 or 1.0. By flipping the sign, we can
+ * choose which value OPCODE_CMP produces without an extra instruction
+ * computing the condition.
+ */
+ if (negate)
+ this->result.negate = ~this->result.negate;
+
+ return switch_order;
+}
+
+void
+ir_to_mesa_visitor::visit(ir_assignment *ir)
+{
+ struct ir_to_mesa_dst_reg l;
+ struct ir_to_mesa_src_reg r;
+ int i;
+
+ ir->rhs->accept(this);
+ r = this->result;
+
+ l = get_assignment_lhs(ir->lhs, this);
+
+ /* FINISHME: This should really set to the correct maximal writemask for each
+ * FINISHME: component written (in the loops below). This case can only
+ * FINISHME: occur for matrices, arrays, and structures.
+ */
+ if (ir->write_mask == 0) {
+ assert(!ir->lhs->type->is_scalar() && !ir->lhs->type->is_vector());
+ l.writemask = WRITEMASK_XYZW;
+ } else if (ir->lhs->type->is_scalar()) {
+ /* FINISHME: This hack makes writing to gl_FragDepth, which lives in the
+ * FINISHME: W component of fragment shader output zero, work correctly.
+ */
+ l.writemask = WRITEMASK_XYZW;
+ } else {
+ int swizzles[4];
+ int first_enabled_chan = 0;
+ int rhs_chan = 0;
+
+ assert(ir->lhs->type->is_vector());
+ l.writemask = ir->write_mask;
+
+ for (int i = 0; i < 4; i++) {
+ if (l.writemask & (1 << i)) {
+ first_enabled_chan = GET_SWZ(r.swizzle, i);
+ break;
+ }
+ }
+
+ /* Swizzle a small RHS vector into the channels being written.
+ *
+ * glsl ir treats write_mask as dictating how many channels are
+ * present on the RHS while Mesa IR treats write_mask as just
+ * showing which channels of the vec4 RHS get written.
+ */
+ for (int i = 0; i < 4; i++) {
+ if (l.writemask & (1 << i))
+ swizzles[i] = GET_SWZ(r.swizzle, rhs_chan++);
+ else
+ swizzles[i] = first_enabled_chan;
+ }
+ r.swizzle = MAKE_SWIZZLE4(swizzles[0], swizzles[1],
+ swizzles[2], swizzles[3]);
+ }
+
+ assert(l.file != PROGRAM_UNDEFINED);
+ assert(r.file != PROGRAM_UNDEFINED);
+
+ if (ir->condition) {
+ const bool switch_order = this->process_move_condition(ir->condition);
+ ir_to_mesa_src_reg condition = this->result;
+
+ for (i = 0; i < type_size(ir->lhs->type); i++) {
+ if (switch_order) {
+ ir_to_mesa_emit_op3(ir, OPCODE_CMP, l,
+ condition, ir_to_mesa_src_reg_from_dst(l), r);
+ } else {
+ ir_to_mesa_emit_op3(ir, OPCODE_CMP, l,
+ condition, r, ir_to_mesa_src_reg_from_dst(l));
+ }
+
+ l.index++;
+ r.index++;
+ }
+ } else {
+ for (i = 0; i < type_size(ir->lhs->type); i++) {
+ ir_to_mesa_emit_op1(ir, OPCODE_MOV, l, r);
+ l.index++;
+ r.index++;
+ }
+ }
+}
+
+
+void
+ir_to_mesa_visitor::visit(ir_constant *ir)
+{
+ ir_to_mesa_src_reg src_reg;
+ GLfloat stack_vals[4] = { 0 };
+ GLfloat *values = stack_vals;
+ unsigned int i;
+
+ /* Unfortunately, 4 floats is all we can get into
+ * _mesa_add_unnamed_constant. So, make a temp to store an
+ * aggregate constant and move each constant value into it. If we
+ * get lucky, copy propagation will eliminate the extra moves.
+ */
+
+ if (ir->type->base_type == GLSL_TYPE_STRUCT) {
+ ir_to_mesa_src_reg temp_base = get_temp(ir->type);
+ ir_to_mesa_dst_reg temp = ir_to_mesa_dst_reg_from_src(temp_base);
+
+ foreach_iter(exec_list_iterator, iter, ir->components) {
+ ir_constant *field_value = (ir_constant *)iter.get();
+ int size = type_size(field_value->type);
+
+ assert(size > 0);
+
+ field_value->accept(this);
+ src_reg = this->result;
+
+ for (i = 0; i < (unsigned int)size; i++) {
+ ir_to_mesa_emit_op1(ir, OPCODE_MOV, temp, src_reg);
+
+ src_reg.index++;
+ temp.index++;
+ }
+ }
+ this->result = temp_base;
+ return;
+ }
+
+ if (ir->type->is_array()) {
+ ir_to_mesa_src_reg temp_base = get_temp(ir->type);
+ ir_to_mesa_dst_reg temp = ir_to_mesa_dst_reg_from_src(temp_base);
+ int size = type_size(ir->type->fields.array);
+
+ assert(size > 0);
+
+ for (i = 0; i < ir->type->length; i++) {
+ ir->array_elements[i]->accept(this);
+ src_reg = this->result;
+ for (int j = 0; j < size; j++) {
+ ir_to_mesa_emit_op1(ir, OPCODE_MOV, temp, src_reg);
+
+ src_reg.index++;
+ temp.index++;
+ }
+ }
+ this->result = temp_base;
+ return;
+ }
+
+ if (ir->type->is_matrix()) {
+ ir_to_mesa_src_reg mat = get_temp(ir->type);
+ ir_to_mesa_dst_reg mat_column = ir_to_mesa_dst_reg_from_src(mat);
+
+ for (i = 0; i < ir->type->matrix_columns; i++) {
+ assert(ir->type->base_type == GLSL_TYPE_FLOAT);
+ values = &ir->value.f[i * ir->type->vector_elements];
+
+ src_reg = ir_to_mesa_src_reg(PROGRAM_CONSTANT, -1, NULL);
+ src_reg.index = _mesa_add_unnamed_constant(this->prog->Parameters,
+ values,
+ ir->type->vector_elements,
+ &src_reg.swizzle);
+ ir_to_mesa_emit_op1(ir, OPCODE_MOV, mat_column, src_reg);
+
+ mat_column.index++;
+ }
+
+ this->result = mat;
+ return;
+ }
+
+ src_reg.file = PROGRAM_CONSTANT;
+ switch (ir->type->base_type) {
+ case GLSL_TYPE_FLOAT:
+ values = &ir->value.f[0];
+ break;
+ case GLSL_TYPE_UINT:
+ for (i = 0; i < ir->type->vector_elements; i++) {
+ values[i] = ir->value.u[i];
+ }
+ break;
+ case GLSL_TYPE_INT:
+ for (i = 0; i < ir->type->vector_elements; i++) {
+ values[i] = ir->value.i[i];
+ }
+ break;
+ case GLSL_TYPE_BOOL:
+ for (i = 0; i < ir->type->vector_elements; i++) {
+ values[i] = ir->value.b[i];
+ }
+ break;
+ default:
+ assert(!"Non-float/uint/int/bool constant");
+ }
+
+ this->result = ir_to_mesa_src_reg(PROGRAM_CONSTANT, -1, ir->type);
+ this->result.index = _mesa_add_unnamed_constant(this->prog->Parameters,
+ values,
+ ir->type->vector_elements,
+ &this->result.swizzle);
+}
+
+function_entry *
+ir_to_mesa_visitor::get_function_signature(ir_function_signature *sig)
+{
+ function_entry *entry;
+
+ foreach_iter(exec_list_iterator, iter, this->function_signatures) {
+ entry = (function_entry *)iter.get();
+
+ if (entry->sig == sig)
+ return entry;
+ }
+
+ entry = ralloc(mem_ctx, function_entry);
+ entry->sig = sig;
+ entry->sig_id = this->next_signature_id++;
+ entry->bgn_inst = NULL;
+
+ /* Allocate storage for all the parameters. */
+ foreach_iter(exec_list_iterator, iter, sig->parameters) {
+ ir_variable *param = (ir_variable *)iter.get();
+ variable_storage *storage;
+
+ storage = find_variable_storage(param);
+ assert(!storage);
+
+ storage = new(mem_ctx) variable_storage(param, PROGRAM_TEMPORARY,
+ this->next_temp);
+ this->variables.push_tail(storage);
+
+ this->next_temp += type_size(param->type);
+ }
+
+ if (!sig->return_type->is_void()) {
+ entry->return_reg = get_temp(sig->return_type);
+ } else {
+ entry->return_reg = ir_to_mesa_undef;
+ }
+
+ this->function_signatures.push_tail(entry);
+ return entry;
+}
+
+void
+ir_to_mesa_visitor::visit(ir_call *ir)
+{
+ ir_to_mesa_instruction *call_inst;
+ ir_function_signature *sig = ir->get_callee();
+ function_entry *entry = get_function_signature(sig);
+ int i;
+
+ /* Process in parameters. */
+ exec_list_iterator sig_iter = sig->parameters.iterator();
+ foreach_iter(exec_list_iterator, iter, *ir) {
+ ir_rvalue *param_rval = (ir_rvalue *)iter.get();
+ ir_variable *param = (ir_variable *)sig_iter.get();
+
+ if (param->mode == ir_var_in ||
+ param->mode == ir_var_inout) {
+ variable_storage *storage = find_variable_storage(param);
+ assert(storage);
+
+ param_rval->accept(this);
+ ir_to_mesa_src_reg r = this->result;
+
+ ir_to_mesa_dst_reg l;
+ l.file = storage->file;
+ l.index = storage->index;
+ l.reladdr = NULL;
+ l.writemask = WRITEMASK_XYZW;
+ l.cond_mask = COND_TR;
+
+ for (i = 0; i < type_size(param->type); i++) {
+ ir_to_mesa_emit_op1(ir, OPCODE_MOV, l, r);
+ l.index++;
+ r.index++;
+ }
+ }
+
+ sig_iter.next();
+ }
+ assert(!sig_iter.has_next());
+
+ /* Emit call instruction */
+ call_inst = ir_to_mesa_emit_op1(ir, OPCODE_CAL,
+ ir_to_mesa_undef_dst, ir_to_mesa_undef);
+ call_inst->function = entry;
+
+ /* Process out parameters. */
+ sig_iter = sig->parameters.iterator();
+ foreach_iter(exec_list_iterator, iter, *ir) {
+ ir_rvalue *param_rval = (ir_rvalue *)iter.get();
+ ir_variable *param = (ir_variable *)sig_iter.get();
+
+ if (param->mode == ir_var_out ||
+ param->mode == ir_var_inout) {
+ variable_storage *storage = find_variable_storage(param);
+ assert(storage);
+
+ ir_to_mesa_src_reg r;
+ r.file = storage->file;
+ r.index = storage->index;
+ r.reladdr = NULL;
+ r.swizzle = SWIZZLE_NOOP;
+ r.negate = 0;
+
+ param_rval->accept(this);
+ ir_to_mesa_dst_reg l = ir_to_mesa_dst_reg_from_src(this->result);
+
+ for (i = 0; i < type_size(param->type); i++) {
+ ir_to_mesa_emit_op1(ir, OPCODE_MOV, l, r);
+ l.index++;
+ r.index++;
+ }
+ }
+
+ sig_iter.next();
+ }
+ assert(!sig_iter.has_next());
+
+ /* Process return value. */
+ this->result = entry->return_reg;
+}
+
+void
+ir_to_mesa_visitor::visit(ir_texture *ir)
+{
+ ir_to_mesa_src_reg result_src, coord, lod_info, projector;
+ ir_to_mesa_dst_reg result_dst, coord_dst;
+ ir_to_mesa_instruction *inst = NULL;
+ prog_opcode opcode = OPCODE_NOP;
+
+ ir->coordinate->accept(this);
+
+ /* Put our coords in a temp. We'll need to modify them for shadow,
+ * projection, or LOD, so the only case we'd use it as is is if
+ * we're doing plain old texturing. Mesa IR optimization should
+ * handle cleaning up our mess in that case.
+ */
+ coord = get_temp(glsl_type::vec4_type);
+ coord_dst = ir_to_mesa_dst_reg_from_src(coord);
+ ir_to_mesa_emit_op1(ir, OPCODE_MOV, coord_dst,
+ this->result);
+
+ if (ir->projector) {
+ ir->projector->accept(this);
+ projector = this->result;
+ }
+
+ /* Storage for our result. Ideally for an assignment we'd be using
+ * the actual storage for the result here, instead.
+ */
+ result_src = get_temp(glsl_type::vec4_type);
+ result_dst = ir_to_mesa_dst_reg_from_src(result_src);
+
+ switch (ir->op) {
+ case ir_tex:
+ opcode = OPCODE_TEX;
+ break;
+ case ir_txb:
+ opcode = OPCODE_TXB;
+ ir->lod_info.bias->accept(this);
+ lod_info = this->result;
+ break;
+ case ir_txl:
+ opcode = OPCODE_TXL;
+ ir->lod_info.lod->accept(this);
+ lod_info = this->result;
+ break;
+ case ir_txd:
+ case ir_txf:
+ assert(!"GLSL 1.30 features unsupported");
+ break;
+ }
+
+ if (ir->projector) {
+ if (opcode == OPCODE_TEX) {
+ /* Slot the projector in as the last component of the coord. */
+ coord_dst.writemask = WRITEMASK_W;
+ ir_to_mesa_emit_op1(ir, OPCODE_MOV, coord_dst, projector);
+ coord_dst.writemask = WRITEMASK_XYZW;
+ opcode = OPCODE_TXP;
+ } else {
+ ir_to_mesa_src_reg coord_w = coord;
+ coord_w.swizzle = SWIZZLE_WWWW;
+
+ /* For the other TEX opcodes there's no projective version
+ * since the last slot is taken up by lod info. Do the
+ * projective divide now.
+ */
+ coord_dst.writemask = WRITEMASK_W;
+ ir_to_mesa_emit_op1(ir, OPCODE_RCP, coord_dst, projector);
+
+ coord_dst.writemask = WRITEMASK_XYZ;
+ ir_to_mesa_emit_op2(ir, OPCODE_MUL, coord_dst, coord, coord_w);
+
+ coord_dst.writemask = WRITEMASK_XYZW;
+ coord.swizzle = SWIZZLE_XYZW;
+ }
+ }
+
+ if (ir->shadow_comparitor) {
+ /* Slot the shadow value in as the second to last component of the
+ * coord.
+ */
+ ir->shadow_comparitor->accept(this);
+ coord_dst.writemask = WRITEMASK_Z;
+ ir_to_mesa_emit_op1(ir, OPCODE_MOV, coord_dst, this->result);
+ coord_dst.writemask = WRITEMASK_XYZW;
+ }
+
+ if (opcode == OPCODE_TXL || opcode == OPCODE_TXB) {
+ /* Mesa IR stores lod or lod bias in the last channel of the coords. */
+ coord_dst.writemask = WRITEMASK_W;
+ ir_to_mesa_emit_op1(ir, OPCODE_MOV, coord_dst, lod_info);
+ coord_dst.writemask = WRITEMASK_XYZW;
+ }
+
+ inst = ir_to_mesa_emit_op1(ir, opcode, result_dst, coord);
+
+ if (ir->shadow_comparitor)
+ inst->tex_shadow = GL_TRUE;
+
+ inst->sampler = _mesa_get_sampler_uniform_value(ir->sampler,
+ this->shader_program,
+ this->prog);
+
+ const glsl_type *sampler_type = ir->sampler->type;
+
+ switch (sampler_type->sampler_dimensionality) {
+ case GLSL_SAMPLER_DIM_1D:
+ inst->tex_target = (sampler_type->sampler_array)
+ ? TEXTURE_1D_ARRAY_INDEX : TEXTURE_1D_INDEX;
+ break;
+ case GLSL_SAMPLER_DIM_2D:
+ inst->tex_target = (sampler_type->sampler_array)
+ ? TEXTURE_2D_ARRAY_INDEX : TEXTURE_2D_INDEX;
+ break;
+ case GLSL_SAMPLER_DIM_3D:
+ inst->tex_target = TEXTURE_3D_INDEX;
+ break;
+ case GLSL_SAMPLER_DIM_CUBE:
+ inst->tex_target = TEXTURE_CUBE_INDEX;
+ break;
+ case GLSL_SAMPLER_DIM_RECT:
+ inst->tex_target = TEXTURE_RECT_INDEX;
+ break;
+ case GLSL_SAMPLER_DIM_BUF:
+ assert(!"FINISHME: Implement ARB_texture_buffer_object");
+ break;
+ default:
+ assert(!"Should not get here.");
+ }
+
+ this->result = result_src;
+}
+
+void
+ir_to_mesa_visitor::visit(ir_return *ir)
+{
+ if (ir->get_value()) {
+ ir_to_mesa_dst_reg l;
+ int i;
+
+ assert(current_function);
+
+ ir->get_value()->accept(this);
+ ir_to_mesa_src_reg r = this->result;
+
+ l = ir_to_mesa_dst_reg_from_src(current_function->return_reg);
+
+ for (i = 0; i < type_size(current_function->sig->return_type); i++) {
+ ir_to_mesa_emit_op1(ir, OPCODE_MOV, l, r);
+ l.index++;
+ r.index++;
+ }
+ }
+
+ ir_to_mesa_emit_op0(ir, OPCODE_RET);
+}
+
+void
+ir_to_mesa_visitor::visit(ir_discard *ir)
+{
+ struct gl_fragment_program *fp = (struct gl_fragment_program *)this->prog;
+
+ if (ir->condition) {
+ ir->condition->accept(this);
+ this->result.negate = ~this->result.negate;
+ ir_to_mesa_emit_op1(ir, OPCODE_KIL, ir_to_mesa_undef_dst, this->result);
+ } else {
+ ir_to_mesa_emit_op0(ir, OPCODE_KIL_NV);
+ }
+
+ fp->UsesKill = GL_TRUE;
+}
+
+void
+ir_to_mesa_visitor::visit(ir_if *ir)
+{
+ ir_to_mesa_instruction *cond_inst, *if_inst, *else_inst = NULL;
+ ir_to_mesa_instruction *prev_inst;
+
+ prev_inst = (ir_to_mesa_instruction *)this->instructions.get_tail();
+
+ ir->condition->accept(this);
+ assert(this->result.file != PROGRAM_UNDEFINED);
+
+ if (this->options->EmitCondCodes) {
+ cond_inst = (ir_to_mesa_instruction *)this->instructions.get_tail();
+
+ /* See if we actually generated any instruction for generating
+ * the condition. If not, then cook up a move to a temp so we
+ * have something to set cond_update on.
+ */
+ if (cond_inst == prev_inst) {
+ ir_to_mesa_src_reg temp = get_temp(glsl_type::bool_type);
+ cond_inst = ir_to_mesa_emit_op1(ir->condition, OPCODE_MOV,
+ ir_to_mesa_dst_reg_from_src(temp),
+ result);
+ }
+ cond_inst->cond_update = GL_TRUE;
+
+ if_inst = ir_to_mesa_emit_op0(ir->condition, OPCODE_IF);
+ if_inst->dst_reg.cond_mask = COND_NE;
+ } else {
+ if_inst = ir_to_mesa_emit_op1(ir->condition,
+ OPCODE_IF, ir_to_mesa_undef_dst,
+ this->result);
+ }
+
+ this->instructions.push_tail(if_inst);
+
+ visit_exec_list(&ir->then_instructions, this);
+
+ if (!ir->else_instructions.is_empty()) {
+ else_inst = ir_to_mesa_emit_op0(ir->condition, OPCODE_ELSE);
+ visit_exec_list(&ir->else_instructions, this);
+ }
+
+ if_inst = ir_to_mesa_emit_op1(ir->condition, OPCODE_ENDIF,
+ ir_to_mesa_undef_dst, ir_to_mesa_undef);
+}
+
+ir_to_mesa_visitor::ir_to_mesa_visitor()
+{
+ result.file = PROGRAM_UNDEFINED;
+ next_temp = 1;
+ next_signature_id = 1;
+ current_function = NULL;
+ mem_ctx = ralloc_context(NULL);
+}
+
+ir_to_mesa_visitor::~ir_to_mesa_visitor()
+{
+ ralloc_free(mem_ctx);
+}
+
+static struct prog_src_register
+mesa_src_reg_from_ir_src_reg(ir_to_mesa_src_reg reg)
+{
+ struct prog_src_register mesa_reg;
+
+ mesa_reg.File = reg.file;
+ assert(reg.index < (1 << INST_INDEX_BITS));
+ mesa_reg.Index = reg.index;
+ mesa_reg.Swizzle = reg.swizzle;
+ mesa_reg.RelAddr = reg.reladdr != NULL;
+ mesa_reg.Negate = reg.negate;
+ mesa_reg.Abs = 0;
+ mesa_reg.HasIndex2 = GL_FALSE;
+ mesa_reg.RelAddr2 = 0;
+ mesa_reg.Index2 = 0;
+
+ return mesa_reg;
+}
+
+static void
+set_branchtargets(ir_to_mesa_visitor *v,
+ struct prog_instruction *mesa_instructions,
+ int num_instructions)
+{
+ int if_count = 0, loop_count = 0;
+ int *if_stack, *loop_stack;
+ int if_stack_pos = 0, loop_stack_pos = 0;
+ int i, j;
+
+ for (i = 0; i < num_instructions; i++) {
+ switch (mesa_instructions[i].Opcode) {
+ case OPCODE_IF:
+ if_count++;
+ break;
+ case OPCODE_BGNLOOP:
+ loop_count++;
+ break;
+ case OPCODE_BRK:
+ case OPCODE_CONT:
+ mesa_instructions[i].BranchTarget = -1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ 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) {
+ case OPCODE_IF:
+ if_stack[if_stack_pos] = i;
+ if_stack_pos++;
+ break;
+ case OPCODE_ELSE:
+ mesa_instructions[if_stack[if_stack_pos - 1]].BranchTarget = i;
+ if_stack[if_stack_pos - 1] = i;
+ break;
+ case OPCODE_ENDIF:
+ mesa_instructions[if_stack[if_stack_pos - 1]].BranchTarget = i;
+ if_stack_pos--;
+ break;
+ case OPCODE_BGNLOOP:
+ loop_stack[loop_stack_pos] = i;
+ loop_stack_pos++;
+ break;
+ case OPCODE_ENDLOOP:
+ loop_stack_pos--;
+ /* Rewrite any breaks/conts at this nesting level (haven't
+ * already had a BranchTarget assigned) to point to the end
+ * of the loop.
+ */
+ for (j = loop_stack[loop_stack_pos]; j < i; j++) {
+ if (mesa_instructions[j].Opcode == OPCODE_BRK ||
+ mesa_instructions[j].Opcode == OPCODE_CONT) {
+ if (mesa_instructions[j].BranchTarget == -1) {
+ mesa_instructions[j].BranchTarget = i;
+ }
+ }
+ }
+ /* The loop ends point at each other. */
+ mesa_instructions[i].BranchTarget = loop_stack[loop_stack_pos];
+ mesa_instructions[loop_stack[loop_stack_pos]].BranchTarget = i;
+ break;
+ case OPCODE_CAL:
+ foreach_iter(exec_list_iterator, iter, v->function_signatures) {
+ function_entry *entry = (function_entry *)iter.get();
+
+ if (entry->sig_id == mesa_instructions[i].BranchTarget) {
+ mesa_instructions[i].BranchTarget = entry->inst;
+ break;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static void
+print_program(struct prog_instruction *mesa_instructions,
+ ir_instruction **mesa_instruction_annotation,
+ int num_instructions)
+{
+ ir_instruction *last_ir = NULL;
+ int i;
+ int indent = 0;
+
+ for (i = 0; i < num_instructions; i++) {
+ struct prog_instruction *mesa_inst = mesa_instructions + i;
+ ir_instruction *ir = mesa_instruction_annotation[i];
+
+ fprintf(stdout, "%3d: ", i);
+
+ if (last_ir != ir && ir) {
+ int j;
+
+ for (j = 0; j < indent; j++) {
+ fprintf(stdout, " ");
+ }
+ ir->print();
+ printf("\n");
+ last_ir = ir;
+
+ fprintf(stdout, " "); /* line number spacing. */
+ }
+
+ indent = _mesa_fprint_instruction_opt(stdout, mesa_inst, indent,
+ PROG_PRINT_DEBUG, NULL);
+ }
+}
+
+static void
+count_resources(struct gl_program *prog)
+{
+ unsigned int i;
+
+ prog->SamplersUsed = 0;
+
+ for (i = 0; i < prog->NumInstructions; i++) {
+ struct prog_instruction *inst = &prog->Instructions[i];
+
+ if (_mesa_is_tex_instruction(inst->Opcode)) {
+ prog->SamplerTargets[inst->TexSrcUnit] =
+ (gl_texture_index)inst->TexSrcTarget;
+ prog->SamplersUsed |= 1 << inst->TexSrcUnit;
+ if (inst->TexShadow) {
+ prog->ShadowSamplers |= 1 << inst->TexSrcUnit;
+ }
+ }
+ }
+
+ _mesa_update_shader_textures_used(prog);
+}
+
+struct uniform_sort {
+ struct gl_uniform *u;
+ int pos;
+};
+
+/* The shader_program->Uniforms list is almost sorted in increasing
+ * uniform->{Frag,Vert}Pos locations, but not quite when there are
+ * uniforms shared between targets. We need to add parameters in
+ * increasing order for the targets.
+ */
+static int
+sort_uniforms(const void *a, const void *b)
+{
+ struct uniform_sort *u1 = (struct uniform_sort *)a;
+ struct uniform_sort *u2 = (struct uniform_sort *)b;
+
+ return u1->pos - u2->pos;
+}
+
+/* Add the uniforms to the parameters. The linker chose locations
+ * in our parameters lists (which weren't created yet), which the
+ * uniforms code will use to poke values into our parameters list
+ * when uniforms are updated.
+ */
+static void
+add_uniforms_to_parameters_list(struct gl_shader_program *shader_program,
+ struct gl_shader *shader,
+ struct gl_program *prog)
+{
+ unsigned int i;
+ unsigned int next_sampler = 0, num_uniforms = 0;
+ struct uniform_sort *sorted_uniforms;
+
+ sorted_uniforms = ralloc_array(NULL, struct uniform_sort,
+ shader_program->Uniforms->NumUniforms);
+
+ for (i = 0; i < shader_program->Uniforms->NumUniforms; i++) {
+ struct gl_uniform *uniform = shader_program->Uniforms->Uniforms + i;
+ int parameter_index = -1;
+
+ switch (shader->Type) {
+ case GL_VERTEX_SHADER:
+ parameter_index = uniform->VertPos;
+ break;
+ case GL_FRAGMENT_SHADER:
+ parameter_index = uniform->FragPos;
+ break;
+ case GL_GEOMETRY_SHADER:
+ parameter_index = uniform->GeomPos;
+ break;
+ }
+
+ /* Only add uniforms used in our target. */
+ if (parameter_index != -1) {
+ sorted_uniforms[num_uniforms].pos = parameter_index;
+ sorted_uniforms[num_uniforms].u = uniform;
+ num_uniforms++;
+ }
+ }
+
+ qsort(sorted_uniforms, num_uniforms, sizeof(struct uniform_sort),
+ sort_uniforms);
+
+ for (i = 0; i < num_uniforms; i++) {
+ struct gl_uniform *uniform = sorted_uniforms[i].u;
+ int parameter_index = sorted_uniforms[i].pos;
+ const glsl_type *type = uniform->Type;
+ unsigned int size;
+
+ if (type->is_vector() ||
+ type->is_scalar()) {
+ size = type->vector_elements;
+ } else {
+ size = type_size(type) * 4;
+ }
+
+ gl_register_file file;
+ if (type->is_sampler() ||
+ (type->is_array() && type->fields.array->is_sampler())) {
+ file = PROGRAM_SAMPLER;
+ } else {
+ file = PROGRAM_UNIFORM;
+ }
+
+ GLint index = _mesa_lookup_parameter_index(prog->Parameters, -1,
+ uniform->Name);
+
+ if (index < 0) {
+ index = _mesa_add_parameter(prog->Parameters, file,
+ uniform->Name, size, type->gl_type,
+ NULL, NULL, 0x0);
+
+ /* Sampler uniform values are stored in prog->SamplerUnits,
+ * and the entry in that array is selected by this index we
+ * store in ParameterValues[].
+ */
+ if (file == PROGRAM_SAMPLER) {
+ for (unsigned int j = 0; j < size / 4; j++)
+ prog->Parameters->ParameterValues[index + j][0] = next_sampler++;
+ }
+
+ /* The location chosen in the Parameters list here (returned
+ * from _mesa_add_uniform) has to match what the linker chose.
+ */
+ if (index != parameter_index) {
+ fail_link(shader_program, "Allocation of uniform `%s' to target "
+ "failed (%d vs %d)\n",
+ uniform->Name, index, parameter_index);
+ }
+ }
+ }
+
+ ralloc_free(sorted_uniforms);
+}
+
+static void
+set_uniform_initializer(struct gl_context *ctx, void *mem_ctx,
+ struct gl_shader_program *shader_program,
+ const char *name, const glsl_type *type,
+ ir_constant *val)
+{
+ if (type->is_record()) {
+ ir_constant *field_constant;
+
+ field_constant = (ir_constant *)val->components.get_head();
+
+ for (unsigned int i = 0; i < type->length; i++) {
+ const glsl_type *field_type = type->fields.structure[i].type;
+ 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);
+ field_constant = (ir_constant *)field_constant->next;
+ }
+ return;
+ }
+
+ int loc = _mesa_get_uniform_location(ctx, shader_program, name);
+
+ if (loc == -1) {
+ fail_link(shader_program,
+ "Couldn't find uniform for initializer %s\n", name);
+ return;
+ }
+
+ for (unsigned int i = 0; i < (type->is_array() ? type->length : 1); i++) {
+ ir_constant *element;
+ const glsl_type *element_type;
+ if (type->is_array()) {
+ element = val->array_elements[i];
+ element_type = type->fields.array;
+ } else {
+ element = val;
+ element_type = type;
+ }
+
+ void *values;
+
+ if (element_type->base_type == GLSL_TYPE_BOOL) {
+ 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];
+ }
+ values = (void *)conv;
+ element_type = glsl_type::get_instance(GLSL_TYPE_INT,
+ element_type->vector_elements,
+ 1);
+ } else {
+ values = &element->value;
+ }
+
+ if (element_type->is_matrix()) {
+ _mesa_uniform_matrix(ctx, shader_program,
+ element_type->matrix_columns,
+ element_type->vector_elements,
+ loc, 1, GL_FALSE, (GLfloat *)values);
+ loc += element_type->matrix_columns;
+ } else {
+ _mesa_uniform(ctx, shader_program, loc, element_type->matrix_columns,
+ values, element_type->gl_type);
+ loc += type_size(element_type);
+ }
+ }
+}
+
+static void
+set_uniform_initializers(struct gl_context *ctx,
+ struct gl_shader_program *shader_program)
+{
+ void *mem_ctx = NULL;
+
+ for (unsigned int i = 0; i < MESA_SHADER_TYPES; i++) {
+ struct gl_shader *shader = shader_program->_LinkedShaders[i];
+
+ if (shader == NULL)
+ continue;
+
+ foreach_iter(exec_list_iterator, iter, *shader->ir) {
+ ir_instruction *ir = (ir_instruction *)iter.get();
+ ir_variable *var = ir->as_variable();
+
+ if (!var || var->mode != ir_var_uniform || !var->constant_value)
+ continue;
+
+ if (!mem_ctx)
+ mem_ctx = ralloc_context(NULL);
+
+ set_uniform_initializer(ctx, mem_ctx, shader_program, var->name,
+ var->type, var->constant_value);
+ }
+ }
+
+ ralloc_free(mem_ctx);
+}
+
+/*
+ * On a basic block basis, tracks available PROGRAM_TEMPORARY register
+ * channels for copy propagation and updates following instructions to
+ * use the original versions.
+ *
+ * The ir_to_mesa_visitor lazily produces code assuming that this pass
+ * will occur. As an example, a TXP production before this pass:
+ *
+ * 0: MOV TEMP[1], INPUT[4].xyyy;
+ * 1: MOV TEMP[1].w, INPUT[4].wwww;
+ * 2: TXP TEMP[2], TEMP[1], texture[0], 2D;
+ *
+ * and after:
+ *
+ * 0: MOV TEMP[1], INPUT[4].xyyy;
+ * 1: MOV TEMP[1].w, INPUT[4].wwww;
+ * 2: TXP TEMP[2], INPUT[4].xyyw, texture[0], 2D;
+ *
+ * which allows for dead code elimination on TEMP[1]'s writes.
+ */
+void
+ir_to_mesa_visitor::copy_propagate(void)
+{
+ ir_to_mesa_instruction **acp = rzalloc_array(mem_ctx,
+ ir_to_mesa_instruction *,
+ this->next_temp * 4);
+
+ 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;
+ bool good = true;
+ int acp_base = inst->src_reg[r].index * 4;
+
+ if (inst->src_reg[r].file != PROGRAM_TEMPORARY ||
+ inst->src_reg[r].reladdr)
+ continue;
+
+ /* See if we can find entries in the ACP consisting of MOVs
+ * from the same src register for all the swizzled channels
+ * of this src register reference.
+ */
+ for (int i = 0; i < 4; i++) {
+ int src_chan = GET_SWZ(inst->src_reg[r].swizzle, i);
+ ir_to_mesa_instruction *copy_chan = acp[acp_base + src_chan];
+
+ if (!copy_chan) {
+ good = false;
+ break;
+ }
+
+ if (!first) {
+ first = copy_chan;
+ } else {
+ if (first->src_reg[0].file != copy_chan->src_reg[0].file ||
+ first->src_reg[0].index != copy_chan->src_reg[0].index) {
+ good = false;
+ break;
+ }
+ }
+ }
+
+ if (good) {
+ /* We've now validated that we can copy-propagate to
+ * replace this src register reference. Do it.
+ */
+ inst->src_reg[r].file = first->src_reg[0].file;
+ inst->src_reg[r].index = first->src_reg[0].index;
+
+ int swizzle = 0;
+ for (int i = 0; i < 4; i++) {
+ int src_chan = GET_SWZ(inst->src_reg[r].swizzle, i);
+ ir_to_mesa_instruction *copy_inst = acp[acp_base + src_chan];
+ swizzle |= (GET_SWZ(copy_inst->src_reg[0].swizzle, src_chan) <<
+ (3 * i));
+ }
+ inst->src_reg[r].swizzle = swizzle;
+ }
+ }
+
+ 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;
+
+ default:
+ /* Continuing the block, clear any written channels from
+ * the ACP.
+ */
+ 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;
+ }
+ }
+ }
+ }
+ break;
+ }
+
+ /* If this is a copy, add it to the ACP. */
+ if (inst->op == OPCODE_MOV &&
+ inst->dst_reg.file == PROGRAM_TEMPORARY &&
+ !inst->dst_reg.reladdr &&
+ !inst->saturate &&
+ !inst->src_reg[0].reladdr &&
+ !inst->src_reg[0].negate) {
+ for (int i = 0; i < 4; i++) {
+ if (inst->dst_reg.writemask & (1 << i)) {
+ acp[4 * inst->dst_reg.index + i] = inst;
+ }
+ }
+ }
+ }
+
+ ralloc_free(acp);
+}
+
+
+/**
+ * Convert a shader's GLSL IR into a Mesa gl_program.
+ */
+static struct gl_program *
+get_mesa_program(struct gl_context *ctx,
+ struct gl_shader_program *shader_program,
+ struct gl_shader *shader)
+{
+ ir_to_mesa_visitor v;
+ struct prog_instruction *mesa_instructions, *mesa_inst;
+ ir_instruction **mesa_instruction_annotation;
+ int i;
+ struct gl_program *prog;
+ GLenum target;
+ const char *target_string;
+ GLboolean progress;
+ struct gl_shader_compiler_options *options =
+ &ctx->ShaderCompilerOptions[_mesa_shader_type_to_index(shader->Type)];
+
+ switch (shader->Type) {
+ case GL_VERTEX_SHADER:
+ target = GL_VERTEX_PROGRAM_ARB;
+ target_string = "vertex";
+ break;
+ case GL_FRAGMENT_SHADER:
+ target = GL_FRAGMENT_PROGRAM_ARB;
+ target_string = "fragment";
+ break;
+ case GL_GEOMETRY_SHADER:
+ target = GL_GEOMETRY_PROGRAM_NV;
+ target_string = "geometry";
+ break;
+ default:
+ assert(!"should not be reached");
+ return NULL;
+ }
+
+ validate_ir_tree(shader->ir);
+
+ prog = ctx->Driver.NewProgram(ctx, target, shader_program->Name);
+ if (!prog)
+ return NULL;
+ prog->Parameters = _mesa_new_parameter_list();
+ prog->Varying = _mesa_new_parameter_list();
+ prog->Attributes = _mesa_new_parameter_list();
+ v.ctx = ctx;
+ v.prog = prog;
+ v.shader_program = shader_program;
+ v.options = options;
+
+ add_uniforms_to_parameters_list(shader_program, shader, prog);
+
+ /* Emit Mesa IR for main(). */
+ visit_exec_list(shader->ir, &v);
+ v.ir_to_mesa_emit_op0(NULL, OPCODE_END);
+
+ /* Now emit bodies for any functions that were used. */
+ do {
+ progress = GL_FALSE;
+
+ foreach_iter(exec_list_iterator, iter, v.function_signatures) {
+ function_entry *entry = (function_entry *)iter.get();
+
+ if (!entry->bgn_inst) {
+ v.current_function = entry;
+
+ entry->bgn_inst = v.ir_to_mesa_emit_op0(NULL, OPCODE_BGNSUB);
+ entry->bgn_inst->function = entry;
+
+ visit_exec_list(&entry->sig->body, &v);
+
+ ir_to_mesa_instruction *last;
+ last = (ir_to_mesa_instruction *)v.instructions.get_tail();
+ if (last->op != OPCODE_RET)
+ v.ir_to_mesa_emit_op0(NULL, OPCODE_RET);
+
+ ir_to_mesa_instruction *end;
+ end = v.ir_to_mesa_emit_op0(NULL, OPCODE_ENDSUB);
+ end->function = entry;
+
+ progress = GL_TRUE;
+ }
+ }
+ } while (progress);
+
+ prog->NumTemporaries = v.next_temp;
+
+ int num_instructions = 0;
+ foreach_iter(exec_list_iterator, iter, v.instructions) {
+ num_instructions++;
+ }
+
+ mesa_instructions =
+ (struct prog_instruction *)calloc(num_instructions,
+ sizeof(*mesa_instructions));
+ mesa_instruction_annotation = ralloc_array(v.mem_ctx, ir_instruction *,
+ num_instructions);
+
+ v.copy_propagate();
+
+ /* Convert ir_mesa_instructions into prog_instructions.
+ */
+ mesa_inst = mesa_instructions;
+ i = 0;
+ foreach_iter(exec_list_iterator, iter, v.instructions) {
+ const ir_to_mesa_instruction *inst = (ir_to_mesa_instruction *)iter.get();
+
+ mesa_inst->Opcode = inst->op;
+ mesa_inst->CondUpdate = inst->cond_update;
+ if (inst->saturate)
+ mesa_inst->SaturateMode = SATURATE_ZERO_ONE;
+ mesa_inst->DstReg.File = inst->dst_reg.file;
+ mesa_inst->DstReg.Index = inst->dst_reg.index;
+ mesa_inst->DstReg.CondMask = inst->dst_reg.cond_mask;
+ mesa_inst->DstReg.WriteMask = inst->dst_reg.writemask;
+ mesa_inst->DstReg.RelAddr = inst->dst_reg.reladdr != NULL;
+ mesa_inst->SrcReg[0] = mesa_src_reg_from_ir_src_reg(inst->src_reg[0]);
+ mesa_inst->SrcReg[1] = mesa_src_reg_from_ir_src_reg(inst->src_reg[1]);
+ mesa_inst->SrcReg[2] = mesa_src_reg_from_ir_src_reg(inst->src_reg[2]);
+ mesa_inst->TexSrcUnit = inst->sampler;
+ mesa_inst->TexSrcTarget = inst->tex_target;
+ mesa_inst->TexShadow = inst->tex_shadow;
+ mesa_instruction_annotation[i] = inst->ir;
+
+ /* Set IndirectRegisterFiles. */
+ if (mesa_inst->DstReg.RelAddr)
+ prog->IndirectRegisterFiles |= 1 << mesa_inst->DstReg.File;
+
+ /* Update program's bitmask of indirectly accessed register files */
+ for (unsigned src = 0; src < 3; src++)
+ if (mesa_inst->SrcReg[src].RelAddr)
+ prog->IndirectRegisterFiles |= 1 << mesa_inst->SrcReg[src].File;
+
+ if (options->EmitNoIfs && mesa_inst->Opcode == OPCODE_IF) {
+ fail_link(shader_program, "Couldn't flatten if statement\n");
+ }
+
+ switch (mesa_inst->Opcode) {
+ case OPCODE_BGNSUB:
+ inst->function->inst = i;
+ mesa_inst->Comment = strdup(inst->function->sig->function_name());
+ break;
+ case OPCODE_ENDSUB:
+ mesa_inst->Comment = strdup(inst->function->sig->function_name());
+ break;
+ case OPCODE_CAL:
+ mesa_inst->BranchTarget = inst->function->sig_id; /* rewritten later */
+ break;
+ case OPCODE_ARL:
+ prog->NumAddressRegs = 1;
+ break;
+ default:
+ break;
+ }
+
+ mesa_inst++;
+ i++;
+
+ if (!shader_program->LinkStatus)
+ break;
+ }
+
+ if (!shader_program->LinkStatus) {
+ free(mesa_instructions);
+ _mesa_reference_program(ctx, &shader->Program, NULL);
+ return NULL;
+ }
+
+ set_branchtargets(&v, mesa_instructions, num_instructions);
+
+ if (ctx->Shader.Flags & GLSL_DUMP) {
+ printf("\n");
+ printf("GLSL IR for linked %s program %d:\n", target_string,
+ shader_program->Name);
+ _mesa_print_ir(shader->ir, NULL);
+ printf("\n");
+ printf("\n");
+ printf("Mesa IR for linked %s program %d:\n", target_string,
+ shader_program->Name);
+ print_program(mesa_instructions, mesa_instruction_annotation,
+ num_instructions);
+ }
+
+ prog->Instructions = mesa_instructions;
+ prog->NumInstructions = num_instructions;
+
+ do_set_program_inouts(shader->ir, prog);
+ count_resources(prog);
+
+ _mesa_reference_program(ctx, &shader->Program, prog);
+
+ if ((ctx->Shader.Flags & GLSL_NO_OPT) == 0) {
+ _mesa_optimize_program(ctx, prog);
+ }
+
+ return prog;
+}
+
+extern "C" {
+
+/**
+ * Called via ctx->Driver.CompilerShader().
+ * This is a no-op.
+ * XXX can we remove the ctx->Driver.CompileShader() hook?
+ */
+GLboolean
+_mesa_ir_compile_shader(struct gl_context *ctx, struct gl_shader *shader)
+{
+ assert(shader->CompileStatus);
+ (void) ctx;
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Link a shader.
+ * Called via ctx->Driver.LinkShader()
+ * This actually involves converting GLSL IR into Mesa gl_programs with
+ * code lowering and other optimizations.
+ */
+GLboolean
+_mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
+{
+ assert(prog->LinkStatus);
+
+ for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
+ if (prog->_LinkedShaders[i] == NULL)
+ continue;
+
+ bool progress;
+ exec_list *ir = prog->_LinkedShaders[i]->ir;
+ const struct gl_shader_compiler_options *options =
+ &ctx->ShaderCompilerOptions[_mesa_shader_type_to_index(prog->_LinkedShaders[i]->Type)];
+
+ do {
+ progress = false;
+
+ /* Lowering */
+ do_mat_op_to_vec(ir);
+ lower_instructions(ir, (MOD_TO_FRACT | DIV_TO_MUL_RCP | EXP_TO_EXP2
+ | LOG_TO_LOG2
+ | ((options->EmitNoPow) ? POW_TO_EXP2 : 0)));
+
+ progress = do_lower_jumps(ir, true, true, options->EmitNoMainReturn, options->EmitNoCont, options->EmitNoLoops) || progress;
+
+ progress = do_common_optimization(ir, true, options->MaxUnrollIterations) || progress;
+
+ progress = lower_quadop_vector(ir, true) || progress;
+
+ if (options->EmitNoIfs) {
+ progress = lower_discard(ir) || progress;
+ progress = lower_if_to_cond_assign(ir) || progress;
+ }
+
+ if (options->EmitNoNoise)
+ progress = lower_noise(ir) || progress;
+
+ /* If there are forms of indirect addressing that the driver
+ * cannot handle, perform the lowering pass.
+ */
+ if (options->EmitNoIndirectInput || options->EmitNoIndirectOutput
+ || options->EmitNoIndirectTemp || options->EmitNoIndirectUniform)
+ progress =
+ lower_variable_index_to_cond_assign(ir,
+ options->EmitNoIndirectInput,
+ options->EmitNoIndirectOutput,
+ options->EmitNoIndirectTemp,
+ options->EmitNoIndirectUniform)
+ || progress;
+
+ progress = do_vec_index_to_cond_assign(ir) || progress;
+ } while (progress);
+
+ validate_ir_tree(ir);
+ }
+
+ for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
+ struct gl_program *linked_prog;
+
+ if (prog->_LinkedShaders[i] == NULL)
+ continue;
+
+ linked_prog = get_mesa_program(ctx, prog, prog->_LinkedShaders[i]);
+
+ if (linked_prog) {
+ bool ok = true;
+
+ switch (prog->_LinkedShaders[i]->Type) {
+ case GL_VERTEX_SHADER:
+ _mesa_reference_vertprog(ctx, &prog->VertexProgram,
+ (struct gl_vertex_program *)linked_prog);
+ ok = ctx->Driver.ProgramStringNotify(ctx, GL_VERTEX_PROGRAM_ARB,
+ linked_prog);
+ break;
+ case GL_FRAGMENT_SHADER:
+ _mesa_reference_fragprog(ctx, &prog->FragmentProgram,
+ (struct gl_fragment_program *)linked_prog);
+ ok = ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_PROGRAM_ARB,
+ linked_prog);
+ break;
+ case GL_GEOMETRY_SHADER:
+ _mesa_reference_geomprog(ctx, &prog->GeometryProgram,
+ (struct gl_geometry_program *)linked_prog);
+ ok = ctx->Driver.ProgramStringNotify(ctx, GL_GEOMETRY_PROGRAM_NV,
+ linked_prog);
+ break;
+ }
+ if (!ok) {
+ return GL_FALSE;
+ }
+ }
+
+ _mesa_reference_program(ctx, &linked_prog, NULL);
+ }
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Compile a GLSL shader. Called via glCompileShader().
+ */
+void
+_mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader)
+{
+ struct _mesa_glsl_parse_state *state =
+ new(shader) _mesa_glsl_parse_state(ctx, shader->Type, shader);
+
+ const char *source = shader->Source;
+ /* Check if the user called glCompileShader without first calling
+ * glShaderSource. This should fail to compile, but not raise a GL_ERROR.
+ */
+ if (source == NULL) {
+ shader->CompileStatus = GL_FALSE;
+ return;
+ }
+
+ state->error = preprocess(state, &source, &state->info_log,
+ &ctx->Extensions, ctx->API);
+
+ if (ctx->Shader.Flags & GLSL_DUMP) {
+ printf("GLSL source for shader %d:\n", shader->Name);
+ printf("%s\n", shader->Source);
+ }
+
+ if (!state->error) {
+ _mesa_glsl_lexer_ctor(state, source);
+ _mesa_glsl_parse(state);
+ _mesa_glsl_lexer_dtor(state);
+ }
+
+ 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);
+
+ if (!state->error && !shader->ir->is_empty()) {
+ validate_ir_tree(shader->ir);
+
+ /* Do some optimization at compile time to reduce shader IR size
+ * and reduce later work if the same shader is linked multiple times
+ */
+ while (do_common_optimization(shader->ir, false, 32))
+ ;
+
+ validate_ir_tree(shader->ir);
+ }
+
+ shader->symbols = state->symbols;
+
+ shader->CompileStatus = !state->error;
+ shader->InfoLog = state->info_log;
+ shader->Version = state->language_version;
+ memcpy(shader->builtins_to_link, state->builtins_to_link,
+ sizeof(shader->builtins_to_link[0]) * state->num_builtins_to_link);
+ shader->num_builtins_to_link = state->num_builtins_to_link;
+
+ if (ctx->Shader.Flags & GLSL_LOG) {
+ _mesa_write_shader_to_file(shader);
+ }
+
+ if (ctx->Shader.Flags & GLSL_DUMP) {
+ if (shader->CompileStatus) {
+ printf("GLSL IR for shader %d:\n", shader->Name);
+ _mesa_print_ir(shader->ir, NULL);
+ printf("\n\n");
+ } else {
+ printf("GLSL shader %d failed to compile.\n", shader->Name);
+ }
+ if (shader->InfoLog && shader->InfoLog[0] != 0) {
+ printf("GLSL shader %d info log:\n", shader->Name);
+ printf("%s\n", shader->InfoLog);
+ }
+ }
+
+ /* Retain any live IR, but trash the rest. */
+ reparent_ir(shader->ir, shader->ir);
+
+ ralloc_free(state);
+
+ if (shader->CompileStatus) {
+ if (!ctx->Driver.CompileShader(ctx, shader))
+ shader->CompileStatus = GL_FALSE;
+ }
+}
+
+
+/**
+ * Link a GLSL shader program. Called via glLinkProgram().
+ */
+void
+_mesa_glsl_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
+{
+ unsigned int i;
+
+ _mesa_clear_shader_program_data(ctx, prog);
+
+ prog->LinkStatus = GL_TRUE;
+
+ for (i = 0; i < prog->NumShaders; i++) {
+ if (!prog->Shaders[i]->CompileStatus) {
+ fail_link(prog, "linking with uncompiled shader");
+ prog->LinkStatus = GL_FALSE;
+ }
+ }
+
+ prog->Varying = _mesa_new_parameter_list();
+ _mesa_reference_vertprog(ctx, &prog->VertexProgram, NULL);
+ _mesa_reference_fragprog(ctx, &prog->FragmentProgram, NULL);
+ _mesa_reference_geomprog(ctx, &prog->GeometryProgram, NULL);
+
+ if (prog->LinkStatus) {
+ link_shaders(ctx, prog);
+ }
+
+ if (prog->LinkStatus) {
+ if (!ctx->Driver.LinkShader(ctx, prog)) {
+ prog->LinkStatus = GL_FALSE;
+ }
+ }
+
+ set_uniform_initializers(ctx, prog);
+
+ if (ctx->Shader.Flags & GLSL_DUMP) {
+ if (!prog->LinkStatus) {
+ printf("GLSL shader program %d failed to link\n", prog->Name);
+ }
+
+ if (prog->InfoLog && prog->InfoLog[0] != 0) {
+ printf("GLSL shader program %d info log:\n", prog->Name);
+ printf("%s\n", prog->InfoLog);
+ }
+ }
+}
+
+} /* extern "C" */
diff --git a/mesalib/src/mesa/state_tracker/st_cb_fbo.c b/mesalib/src/mesa/state_tracker/st_cb_fbo.c
index 398e32a34..2934f9ffb 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_fbo.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_fbo.c
@@ -1,620 +1,639 @@
-/**************************************************************************
- *
- * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
- * 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.
- *
- **************************************************************************/
-
-
-/**
- * Framebuffer/renderbuffer functions.
- *
- * \author Brian Paul
- */
-
-
-#include "main/imports.h"
-#include "main/context.h"
-#include "main/fbobject.h"
-#include "main/framebuffer.h"
-#include "main/macros.h"
-#include "main/mfeatures.h"
-#include "main/renderbuffer.h"
-
-#include "pipe/p_context.h"
-#include "pipe/p_defines.h"
-#include "pipe/p_screen.h"
-#include "st_context.h"
-#include "st_cb_fbo.h"
-#include "st_cb_flush.h"
-#include "st_format.h"
-#include "st_texture.h"
-#include "st_manager.h"
-
-#include "util/u_format.h"
-#include "util/u_inlines.h"
-#include "util/u_surface.h"
-
-
-/**
- * gl_renderbuffer::AllocStorage()
- * This is called to allocate the original drawing surface, and
- * during window resize.
- */
-static GLboolean
-st_renderbuffer_alloc_storage(struct gl_context * ctx,
- struct gl_renderbuffer *rb,
- GLenum internalFormat,
- GLuint width, GLuint height)
-{
- struct st_context *st = st_context(ctx);
- struct pipe_context *pipe = st->pipe;
- struct pipe_screen *screen = st->pipe->screen;
- struct st_renderbuffer *strb = st_renderbuffer(rb);
- enum pipe_format format;
- struct pipe_surface surf_tmpl;
-
- if (strb->format != PIPE_FORMAT_NONE)
- format = strb->format;
- else
- format = st_choose_renderbuffer_format(screen, internalFormat,
- rb->NumSamples);
-
- /* init renderbuffer fields */
- strb->Base.Width = width;
- strb->Base.Height = height;
- strb->Base.Format = st_pipe_format_to_mesa_format(format);
- strb->Base.DataType = st_format_datatype(format);
-
- strb->defined = GL_FALSE; /* undefined contents now */
-
- if (strb->software) {
- size_t size;
-
- free(strb->data);
-
- assert(strb->format != PIPE_FORMAT_NONE);
-
- strb->stride = util_format_get_stride(strb->format, width);
- size = util_format_get_2d_size(strb->format, strb->stride, height);
-
- strb->data = malloc(size);
-
- return strb->data != NULL;
- }
- else {
- struct pipe_resource template;
-
- /* Free the old surface and texture
- */
- pipe_surface_reference( &strb->surface, NULL );
- pipe_resource_reference( &strb->texture, NULL );
- pipe_sampler_view_reference(&strb->sampler_view, NULL);
-
- /* Setup new texture template.
- */
- memset(&template, 0, sizeof(template));
- template.target = st->internal_target;
- template.format = format;
- template.width0 = width;
- template.height0 = height;
- template.depth0 = 1;
- template.array_size = 1;
- template.last_level = 0;
- template.nr_samples = rb->NumSamples;
- if (util_format_is_depth_or_stencil(format)) {
- template.bind = PIPE_BIND_DEPTH_STENCIL;
- }
- else {
- template.bind = (PIPE_BIND_DISPLAY_TARGET |
- PIPE_BIND_RENDER_TARGET);
- }
-
- strb->texture = screen->resource_create(screen, &template);
-
- if (!strb->texture)
- return FALSE;
-
- memset(&surf_tmpl, 0, sizeof(surf_tmpl));
- u_surface_default_template(&surf_tmpl, strb->texture, template.bind);
- strb->surface = pipe->create_surface(pipe,
- strb->texture,
- &surf_tmpl);
- if (strb->surface) {
- assert(strb->surface->texture);
- assert(strb->surface->format);
- assert(strb->surface->width == width);
- assert(strb->surface->height == height);
- }
-
- return strb->surface != NULL;
- }
-}
-
-
-/**
- * gl_renderbuffer::Delete()
- */
-static void
-st_renderbuffer_delete(struct gl_renderbuffer *rb)
-{
- struct st_renderbuffer *strb = st_renderbuffer(rb);
- ASSERT(strb);
- pipe_surface_reference(&strb->surface, NULL);
- pipe_resource_reference(&strb->texture, NULL);
- pipe_sampler_view_reference(&strb->sampler_view, NULL);
- free(strb->data);
- free(strb);
-}
-
-
-/**
- * gl_renderbuffer::GetPointer()
- */
-static void *
-null_get_pointer(struct gl_context * ctx, struct gl_renderbuffer *rb,
- GLint x, GLint y)
-{
- /* By returning NULL we force all software rendering to go through
- * the span routines.
- */
-#if 0
- assert(0); /* Should never get called with softpipe */
-#endif
- return NULL;
-}
-
-
-/**
- * Called via ctx->Driver.NewFramebuffer()
- */
-static struct gl_framebuffer *
-st_new_framebuffer(struct gl_context *ctx, GLuint name)
-{
- /* XXX not sure we need to subclass gl_framebuffer for pipe */
- return _mesa_new_framebuffer(ctx, name);
-}
-
-
-/**
- * Called via ctx->Driver.NewRenderbuffer()
- */
-static struct gl_renderbuffer *
-st_new_renderbuffer(struct gl_context *ctx, GLuint name)
-{
- struct st_renderbuffer *strb = ST_CALLOC_STRUCT(st_renderbuffer);
- if (strb) {
- _mesa_init_renderbuffer(&strb->Base, name);
- strb->Base.Delete = st_renderbuffer_delete;
- strb->Base.AllocStorage = st_renderbuffer_alloc_storage;
- strb->Base.GetPointer = null_get_pointer;
- strb->format = PIPE_FORMAT_NONE;
- return &strb->Base;
- }
- return NULL;
-}
-
-
-/**
- * Allocate a renderbuffer for a an on-screen window (not a user-created
- * renderbuffer). The window system code determines the format.
- */
-struct gl_renderbuffer *
-st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw)
-{
- struct st_renderbuffer *strb;
-
- strb = ST_CALLOC_STRUCT(st_renderbuffer);
- if (!strb) {
- _mesa_error(NULL, GL_OUT_OF_MEMORY, "creating renderbuffer");
- return NULL;
- }
-
- _mesa_init_renderbuffer(&strb->Base, 0);
- strb->Base.ClassID = 0x4242; /* just a unique value */
- strb->Base.NumSamples = samples;
- strb->Base.Format = st_pipe_format_to_mesa_format(format);
- strb->Base.DataType = st_format_datatype(format);
- strb->format = format;
- strb->software = sw;
-
- switch (format) {
- case PIPE_FORMAT_R8G8B8A8_UNORM:
- case PIPE_FORMAT_B8G8R8A8_UNORM:
- case PIPE_FORMAT_A8R8G8B8_UNORM:
- case PIPE_FORMAT_R8G8B8X8_UNORM:
- case PIPE_FORMAT_B8G8R8X8_UNORM:
- case PIPE_FORMAT_X8R8G8B8_UNORM:
- case PIPE_FORMAT_B5G5R5A1_UNORM:
- case PIPE_FORMAT_B4G4R4A4_UNORM:
- case PIPE_FORMAT_B5G6R5_UNORM:
- strb->Base.InternalFormat = GL_RGBA;
- break;
- case PIPE_FORMAT_Z16_UNORM:
- strb->Base.InternalFormat = GL_DEPTH_COMPONENT16;
- break;
- case PIPE_FORMAT_Z32_UNORM:
- strb->Base.InternalFormat = GL_DEPTH_COMPONENT32;
- break;
- case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
- case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
- case PIPE_FORMAT_Z24X8_UNORM:
- case PIPE_FORMAT_X8Z24_UNORM:
- strb->Base.InternalFormat = GL_DEPTH24_STENCIL8_EXT;
- break;
- case PIPE_FORMAT_S8_USCALED:
- strb->Base.InternalFormat = GL_STENCIL_INDEX8_EXT;
- break;
- case PIPE_FORMAT_R16G16B16A16_SNORM:
- strb->Base.InternalFormat = GL_RGBA16;
- break;
- case PIPE_FORMAT_R8_UNORM:
- strb->Base.InternalFormat = GL_R8;
- break;
- case PIPE_FORMAT_R8G8_UNORM:
- strb->Base.InternalFormat = GL_RG8;
- break;
- case PIPE_FORMAT_R16_UNORM:
- strb->Base.InternalFormat = GL_R16;
- break;
- case PIPE_FORMAT_R16G16_UNORM:
- strb->Base.InternalFormat = GL_RG16;
- break;
- default:
- _mesa_problem(NULL,
- "Unexpected format in st_new_renderbuffer_fb");
- free(strb);
- return NULL;
- }
-
- /* st-specific methods */
- strb->Base.Delete = st_renderbuffer_delete;
- strb->Base.AllocStorage = st_renderbuffer_alloc_storage;
- strb->Base.GetPointer = null_get_pointer;
-
- /* surface is allocated in st_renderbuffer_alloc_storage() */
- strb->surface = NULL;
-
- return &strb->Base;
-}
-
-
-
-
-/**
- * Called via ctx->Driver.BindFramebufferEXT().
- */
-static void
-st_bind_framebuffer(struct gl_context *ctx, GLenum target,
- struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
-{
-
-}
-
-/**
- * Called by ctx->Driver.FramebufferRenderbuffer
- */
-static void
-st_framebuffer_renderbuffer(struct gl_context *ctx,
- struct gl_framebuffer *fb,
- GLenum attachment,
- struct gl_renderbuffer *rb)
-{
- /* XXX no need for derivation? */
- _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
-}
-
-
-/**
- * Called by ctx->Driver.RenderTexture
- */
-static void
-st_render_texture(struct gl_context *ctx,
- struct gl_framebuffer *fb,
- struct gl_renderbuffer_attachment *att)
-{
- struct st_context *st = st_context(ctx);
- struct pipe_context *pipe = st->pipe;
- struct st_renderbuffer *strb;
- struct gl_renderbuffer *rb;
- struct pipe_resource *pt = st_get_texobj_resource(att->Texture);
- struct st_texture_object *stObj;
- const struct gl_texture_image *texImage;
- struct pipe_surface surf_tmpl;
-
- /* When would this fail? Perhaps assert? */
- if (!pt)
- return;
-
- /* get pointer to texture image we're rendeing to */
- texImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
-
- /* create new renderbuffer which wraps the texture image */
- rb = st_new_renderbuffer(ctx, 0);
- if (!rb) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture()");
- return;
- }
-
- _mesa_reference_renderbuffer(&att->Renderbuffer, rb);
- assert(rb->RefCount == 1);
- rb->AllocStorage = NULL; /* should not get called */
- strb = st_renderbuffer(rb);
-
- assert(strb->Base.RefCount > 0);
-
- /* get the texture for the texture object */
- stObj = st_texture_object(att->Texture);
-
- /* point renderbuffer at texobject */
- strb->rtt = stObj;
- strb->rtt_level = att->TextureLevel;
- strb->rtt_face = att->CubeMapFace;
- strb->rtt_slice = att->Zoffset;
-
- rb->Width = texImage->Width2;
- rb->Height = texImage->Height2;
- rb->_BaseFormat = texImage->_BaseFormat;
- /*printf("***** render to texture level %d: %d x %d\n", att->TextureLevel, rb->Width, rb->Height);*/
-
- /*printf("***** pipe texture %d x %d\n", pt->width0, pt->height0);*/
-
- pipe_resource_reference( &strb->texture, pt );
-
- pipe_surface_reference(&strb->surface, NULL);
-
- pipe_sampler_view_reference(&strb->sampler_view,
- st_get_texture_sampler_view(stObj, pipe));
-
- assert(strb->rtt_level <= strb->texture->last_level);
-
- /* new surface for rendering into the texture */
- memset(&surf_tmpl, 0, sizeof(surf_tmpl));
- 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;
- surf_tmpl.u.tex.last_layer = strb->rtt_face + strb->rtt_slice;
- strb->surface = pipe->create_surface(pipe,
- strb->texture,
- &surf_tmpl);
-
- strb->format = pt->format;
-
- strb->Base.Format = st_pipe_format_to_mesa_format(pt->format);
- strb->Base.DataType = st_format_datatype(pt->format);
-
- /*
- printf("RENDER TO TEXTURE obj=%p pt=%p surf=%p %d x %d\n",
- att->Texture, pt, strb->surface, rb->Width, rb->Height);
- */
-
- /* Invalidate buffer state so that the pipe's framebuffer state
- * gets updated.
- * That's where the new renderbuffer (which we just created) gets
- * passed to the pipe as a (color/depth) render target.
- */
- st_invalidate_state(ctx, _NEW_BUFFERS);
-}
-
-
-/**
- * Called via ctx->Driver.FinishRenderTexture.
- */
-static void
-st_finish_render_texture(struct gl_context *ctx,
- struct gl_renderbuffer_attachment *att)
-{
- struct st_context *st = st_context(ctx);
- struct st_renderbuffer *strb = st_renderbuffer(att->Renderbuffer);
-
- if (!strb)
- return;
-
- st_flush(st, PIPE_FLUSH_RENDER_CACHE, NULL);
-
- strb->rtt = NULL;
-
- /*
- printf("FINISH RENDER TO TEXTURE surf=%p\n", strb->surface);
- */
-
- /* restore previous framebuffer state */
- st_invalidate_state(ctx, _NEW_BUFFERS);
-}
-
-
-/**
- * Validate a renderbuffer attachment for a particular set of bindings.
- */
-static GLboolean
-st_validate_attachment(struct pipe_screen *screen,
- const struct gl_renderbuffer_attachment *att,
- unsigned bindings)
-{
- const struct st_texture_object *stObj = st_texture_object(att->Texture);
-
- /* Only validate texture attachments for now, since
- * st_renderbuffer_alloc_storage makes sure that
- * the format is supported.
- */
- if (att->Type != GL_TEXTURE)
- return GL_TRUE;
-
- if (!stObj)
- return GL_FALSE;
-
- return screen->is_format_supported(screen, stObj->pt->format,
- PIPE_TEXTURE_2D,
- stObj->pt->nr_samples, bindings, 0);
-}
-
-
-/**
- * Check if two renderbuffer attachments name a combined depth/stencil
- * renderbuffer.
- */
-GLboolean
-st_is_depth_stencil_combined(const struct gl_renderbuffer_attachment *depth,
- const struct gl_renderbuffer_attachment *stencil)
-{
- assert(depth && stencil);
-
- if (depth->Type == stencil->Type) {
- if (depth->Type == GL_RENDERBUFFER_EXT &&
- depth->Renderbuffer == stencil->Renderbuffer)
- return GL_TRUE;
-
- if (depth->Type == GL_TEXTURE &&
- depth->Texture == stencil->Texture)
- return GL_TRUE;
- }
-
- return GL_FALSE;
-}
-
-
-/**
- * Check that the framebuffer configuration is valid in terms of what
- * the driver can support.
- *
- * For Gallium we only supports combined Z+stencil, not separate buffers.
- */
-static void
-st_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
-{
- struct st_context *st = st_context(ctx);
- struct pipe_screen *screen = st->pipe->screen;
- const struct gl_renderbuffer_attachment *depth =
- &fb->Attachment[BUFFER_DEPTH];
- const struct gl_renderbuffer_attachment *stencil =
- &fb->Attachment[BUFFER_STENCIL];
- GLuint i;
-
- if (depth->Type && stencil->Type && depth->Type != stencil->Type) {
- fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
- return;
- }
- if (depth->Type == GL_RENDERBUFFER_EXT &&
- stencil->Type == GL_RENDERBUFFER_EXT &&
- depth->Renderbuffer != stencil->Renderbuffer) {
- fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
- return;
- }
- if (depth->Type == GL_TEXTURE &&
- stencil->Type == GL_TEXTURE &&
- depth->Texture != stencil->Texture) {
- fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
- return;
- }
-
- if (!st_validate_attachment(screen,
- depth,
- PIPE_BIND_DEPTH_STENCIL)) {
- fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
- return;
- }
- if (!st_validate_attachment(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,
- &fb->Attachment[BUFFER_COLOR0 + i],
- PIPE_BIND_RENDER_TARGET)) {
- fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
- return;
- }
- }
-}
-
-
-/**
- * Called via glDrawBuffer.
- */
-static void
-st_DrawBuffers(struct gl_context *ctx, GLsizei count, const GLenum *buffers)
-{
- struct st_context *st = st_context(ctx);
- struct gl_framebuffer *fb = ctx->DrawBuffer;
- GLuint i;
-
- (void) count;
- (void) buffers;
-
- /* add the renderbuffers on demand */
- for (i = 0; i < fb->_NumColorDrawBuffers; i++) {
- gl_buffer_index idx = fb->_ColorDrawBufferIndexes[i];
- st_manager_add_color_renderbuffer(st, fb, idx);
- }
-}
-
-
-/**
- * Called via glReadBuffer.
- */
-static void
-st_ReadBuffer(struct gl_context *ctx, GLenum buffer)
-{
- struct st_context *st = st_context(ctx);
- struct gl_framebuffer *fb = ctx->ReadBuffer;
-
- (void) buffer;
-
- /* add the renderbuffer on demand */
- st_manager_add_color_renderbuffer(st, fb, fb->_ColorReadBufferIndex);
-}
-
-
-void st_init_fbo_functions(struct dd_function_table *functions)
-{
-#if FEATURE_EXT_framebuffer_object
- functions->NewFramebuffer = st_new_framebuffer;
- functions->NewRenderbuffer = st_new_renderbuffer;
- functions->BindFramebuffer = st_bind_framebuffer;
- functions->FramebufferRenderbuffer = st_framebuffer_renderbuffer;
- functions->RenderTexture = st_render_texture;
- functions->FinishRenderTexture = st_finish_render_texture;
- functions->ValidateFramebuffer = st_validate_framebuffer;
-#endif
- /* no longer needed by core Mesa, drivers handle resizes...
- functions->ResizeBuffers = st_resize_buffers;
- */
-
- functions->DrawBuffers = st_DrawBuffers;
- functions->ReadBuffer = st_ReadBuffer;
-}
-
-/* XXX unused ? */
-struct pipe_sampler_view *
-st_get_renderbuffer_sampler_view(struct st_renderbuffer *rb,
- struct pipe_context *pipe)
-{
- if (!rb->sampler_view) {
- rb->sampler_view = st_create_texture_sampler_view(pipe, rb->texture);
- }
-
- return rb->sampler_view;
-}
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * 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.
+ *
+ **************************************************************************/
+
+
+/**
+ * Framebuffer/renderbuffer functions.
+ *
+ * \author Brian Paul
+ */
+
+
+#include "main/imports.h"
+#include "main/context.h"
+#include "main/fbobject.h"
+#include "main/framebuffer.h"
+#include "main/macros.h"
+#include "main/mfeatures.h"
+#include "main/renderbuffer.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_screen.h"
+#include "st_context.h"
+#include "st_cb_fbo.h"
+#include "st_cb_flush.h"
+#include "st_format.h"
+#include "st_texture.h"
+#include "st_manager.h"
+
+#include "util/u_format.h"
+#include "util/u_inlines.h"
+#include "util/u_surface.h"
+
+
+/**
+ * gl_renderbuffer::AllocStorage()
+ * This is called to allocate the original drawing surface, and
+ * during window resize.
+ */
+static GLboolean
+st_renderbuffer_alloc_storage(struct gl_context * ctx,
+ struct gl_renderbuffer *rb,
+ GLenum internalFormat,
+ GLuint width, GLuint height)
+{
+ struct st_context *st = st_context(ctx);
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_screen *screen = st->pipe->screen;
+ struct st_renderbuffer *strb = st_renderbuffer(rb);
+ enum pipe_format format;
+ struct pipe_surface surf_tmpl;
+
+ if (strb->format != PIPE_FORMAT_NONE)
+ format = strb->format;
+ else
+ format = st_choose_renderbuffer_format(screen, internalFormat,
+ rb->NumSamples);
+
+ /* init renderbuffer fields */
+ strb->Base.Width = width;
+ strb->Base.Height = height;
+ strb->Base.Format = st_pipe_format_to_mesa_format(format);
+ strb->Base.DataType = st_format_datatype(format);
+
+ strb->defined = GL_FALSE; /* undefined contents now */
+
+ if (strb->software) {
+ size_t size;
+
+ free(strb->data);
+
+ assert(strb->format != PIPE_FORMAT_NONE);
+
+ strb->stride = util_format_get_stride(strb->format, width);
+ size = util_format_get_2d_size(strb->format, strb->stride, height);
+
+ strb->data = malloc(size);
+
+ return strb->data != NULL;
+ }
+ else {
+ struct pipe_resource template;
+
+ /* Free the old surface and texture
+ */
+ pipe_surface_reference( &strb->surface, NULL );
+ pipe_resource_reference( &strb->texture, NULL );
+ pipe_sampler_view_reference(&strb->sampler_view, NULL);
+
+ /* Setup new texture template.
+ */
+ memset(&template, 0, sizeof(template));
+ template.target = st->internal_target;
+ template.format = format;
+ template.width0 = width;
+ template.height0 = height;
+ template.depth0 = 1;
+ template.array_size = 1;
+ template.last_level = 0;
+ template.nr_samples = rb->NumSamples;
+ if (util_format_is_depth_or_stencil(format)) {
+ template.bind = PIPE_BIND_DEPTH_STENCIL;
+ }
+ else {
+ template.bind = (PIPE_BIND_DISPLAY_TARGET |
+ PIPE_BIND_RENDER_TARGET);
+ }
+
+ strb->texture = screen->resource_create(screen, &template);
+
+ if (!strb->texture)
+ return FALSE;
+
+ memset(&surf_tmpl, 0, sizeof(surf_tmpl));
+ u_surface_default_template(&surf_tmpl, strb->texture, template.bind);
+ strb->surface = pipe->create_surface(pipe,
+ strb->texture,
+ &surf_tmpl);
+ if (strb->surface) {
+ assert(strb->surface->texture);
+ assert(strb->surface->format);
+ assert(strb->surface->width == width);
+ assert(strb->surface->height == height);
+ }
+
+ return strb->surface != NULL;
+ }
+}
+
+
+/**
+ * gl_renderbuffer::Delete()
+ */
+static void
+st_renderbuffer_delete(struct gl_renderbuffer *rb)
+{
+ struct st_renderbuffer *strb = st_renderbuffer(rb);
+ ASSERT(strb);
+ pipe_surface_reference(&strb->surface, NULL);
+ pipe_resource_reference(&strb->texture, NULL);
+ pipe_sampler_view_reference(&strb->sampler_view, NULL);
+ free(strb->data);
+ free(strb);
+}
+
+
+/**
+ * gl_renderbuffer::GetPointer()
+ */
+static void *
+null_get_pointer(struct gl_context * ctx, struct gl_renderbuffer *rb,
+ GLint x, GLint y)
+{
+ /* By returning NULL we force all software rendering to go through
+ * the span routines.
+ */
+#if 0
+ assert(0); /* Should never get called with softpipe */
+#endif
+ return NULL;
+}
+
+
+/**
+ * Called via ctx->Driver.NewFramebuffer()
+ */
+static struct gl_framebuffer *
+st_new_framebuffer(struct gl_context *ctx, GLuint name)
+{
+ /* XXX not sure we need to subclass gl_framebuffer for pipe */
+ return _mesa_new_framebuffer(ctx, name);
+}
+
+
+/**
+ * Called via ctx->Driver.NewRenderbuffer()
+ */
+static struct gl_renderbuffer *
+st_new_renderbuffer(struct gl_context *ctx, GLuint name)
+{
+ struct st_renderbuffer *strb = ST_CALLOC_STRUCT(st_renderbuffer);
+ if (strb) {
+ _mesa_init_renderbuffer(&strb->Base, name);
+ strb->Base.Delete = st_renderbuffer_delete;
+ strb->Base.AllocStorage = st_renderbuffer_alloc_storage;
+ strb->Base.GetPointer = null_get_pointer;
+ strb->format = PIPE_FORMAT_NONE;
+ return &strb->Base;
+ }
+ return NULL;
+}
+
+
+/**
+ * Allocate a renderbuffer for a an on-screen window (not a user-created
+ * renderbuffer). The window system code determines the format.
+ */
+struct gl_renderbuffer *
+st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw)
+{
+ struct st_renderbuffer *strb;
+
+ strb = ST_CALLOC_STRUCT(st_renderbuffer);
+ if (!strb) {
+ _mesa_error(NULL, GL_OUT_OF_MEMORY, "creating renderbuffer");
+ return NULL;
+ }
+
+ _mesa_init_renderbuffer(&strb->Base, 0);
+ strb->Base.ClassID = 0x4242; /* just a unique value */
+ strb->Base.NumSamples = samples;
+ strb->Base.Format = st_pipe_format_to_mesa_format(format);
+ strb->Base.DataType = st_format_datatype(format);
+ strb->format = format;
+ strb->software = sw;
+
+ switch (format) {
+ case PIPE_FORMAT_R8G8B8A8_UNORM:
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_R8G8B8X8_UNORM:
+ case PIPE_FORMAT_B8G8R8X8_UNORM:
+ case PIPE_FORMAT_X8R8G8B8_UNORM:
+ case PIPE_FORMAT_B5G5R5A1_UNORM:
+ case PIPE_FORMAT_B4G4R4A4_UNORM:
+ case PIPE_FORMAT_B5G6R5_UNORM:
+ strb->Base.InternalFormat = GL_RGBA;
+ break;
+ case PIPE_FORMAT_Z16_UNORM:
+ strb->Base.InternalFormat = GL_DEPTH_COMPONENT16;
+ break;
+ case PIPE_FORMAT_Z32_UNORM:
+ strb->Base.InternalFormat = GL_DEPTH_COMPONENT32;
+ break;
+ case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
+ case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
+ case PIPE_FORMAT_Z24X8_UNORM:
+ case PIPE_FORMAT_X8Z24_UNORM:
+ strb->Base.InternalFormat = GL_DEPTH24_STENCIL8_EXT;
+ break;
+ case PIPE_FORMAT_S8_USCALED:
+ strb->Base.InternalFormat = GL_STENCIL_INDEX8_EXT;
+ break;
+ case PIPE_FORMAT_R16G16B16A16_SNORM:
+ strb->Base.InternalFormat = GL_RGBA16;
+ break;
+ case PIPE_FORMAT_R8_UNORM:
+ strb->Base.InternalFormat = GL_R8;
+ break;
+ case PIPE_FORMAT_R8G8_UNORM:
+ strb->Base.InternalFormat = GL_RG8;
+ break;
+ case PIPE_FORMAT_R16_UNORM:
+ strb->Base.InternalFormat = GL_R16;
+ break;
+ case PIPE_FORMAT_R16G16_UNORM:
+ strb->Base.InternalFormat = GL_RG16;
+ break;
+ default:
+ _mesa_problem(NULL,
+ "Unexpected format in st_new_renderbuffer_fb");
+ free(strb);
+ return NULL;
+ }
+
+ /* st-specific methods */
+ strb->Base.Delete = st_renderbuffer_delete;
+ strb->Base.AllocStorage = st_renderbuffer_alloc_storage;
+ strb->Base.GetPointer = null_get_pointer;
+
+ /* surface is allocated in st_renderbuffer_alloc_storage() */
+ strb->surface = NULL;
+
+ return &strb->Base;
+}
+
+
+
+
+/**
+ * Called via ctx->Driver.BindFramebufferEXT().
+ */
+static void
+st_bind_framebuffer(struct gl_context *ctx, GLenum target,
+ struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
+{
+
+}
+
+/**
+ * Called by ctx->Driver.FramebufferRenderbuffer
+ */
+static void
+st_framebuffer_renderbuffer(struct gl_context *ctx,
+ struct gl_framebuffer *fb,
+ GLenum attachment,
+ struct gl_renderbuffer *rb)
+{
+ /* XXX no need for derivation? */
+ _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
+}
+
+
+/**
+ * Called by ctx->Driver.RenderTexture
+ */
+static void
+st_render_texture(struct gl_context *ctx,
+ struct gl_framebuffer *fb,
+ struct gl_renderbuffer_attachment *att)
+{
+ struct st_context *st = st_context(ctx);
+ struct pipe_context *pipe = st->pipe;
+ struct st_renderbuffer *strb;
+ struct gl_renderbuffer *rb;
+ struct pipe_resource *pt = st_get_texobj_resource(att->Texture);
+ struct st_texture_object *stObj;
+ const struct gl_texture_image *texImage;
+ struct pipe_surface surf_tmpl;
+
+ /* When would this fail? Perhaps assert? */
+ if (!pt)
+ return;
+
+ /* get pointer to texture image we're rendeing to */
+ texImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
+
+ /* create new renderbuffer which wraps the texture image */
+ rb = st_new_renderbuffer(ctx, 0);
+ if (!rb) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture()");
+ return;
+ }
+
+ _mesa_reference_renderbuffer(&att->Renderbuffer, rb);
+ assert(rb->RefCount == 1);
+ rb->AllocStorage = NULL; /* should not get called */
+ strb = st_renderbuffer(rb);
+
+ assert(strb->Base.RefCount > 0);
+
+ /* get the texture for the texture object */
+ stObj = st_texture_object(att->Texture);
+
+ /* point renderbuffer at texobject */
+ strb->rtt = stObj;
+ strb->rtt_level = att->TextureLevel;
+ strb->rtt_face = att->CubeMapFace;
+ strb->rtt_slice = att->Zoffset;
+
+ rb->Width = texImage->Width2;
+ rb->Height = texImage->Height2;
+ rb->_BaseFormat = texImage->_BaseFormat;
+ /*printf("***** render to texture level %d: %d x %d\n", att->TextureLevel, rb->Width, rb->Height);*/
+
+ /*printf("***** pipe texture %d x %d\n", pt->width0, pt->height0);*/
+
+ pipe_resource_reference( &strb->texture, pt );
+
+ pipe_surface_reference(&strb->surface, NULL);
+
+ pipe_sampler_view_reference(&strb->sampler_view,
+ st_get_texture_sampler_view(stObj, pipe));
+
+ assert(strb->rtt_level <= strb->texture->last_level);
+
+ /* new surface for rendering into the texture */
+ memset(&surf_tmpl, 0, sizeof(surf_tmpl));
+ 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;
+ surf_tmpl.u.tex.last_layer = strb->rtt_face + strb->rtt_slice;
+ strb->surface = pipe->create_surface(pipe,
+ strb->texture,
+ &surf_tmpl);
+
+ strb->format = pt->format;
+
+ strb->Base.Format = st_pipe_format_to_mesa_format(pt->format);
+ strb->Base.DataType = st_format_datatype(pt->format);
+
+ /*
+ printf("RENDER TO TEXTURE obj=%p pt=%p surf=%p %d x %d\n",
+ att->Texture, pt, strb->surface, rb->Width, rb->Height);
+ */
+
+ /* Invalidate buffer state so that the pipe's framebuffer state
+ * gets updated.
+ * That's where the new renderbuffer (which we just created) gets
+ * passed to the pipe as a (color/depth) render target.
+ */
+ st_invalidate_state(ctx, _NEW_BUFFERS);
+}
+
+
+/**
+ * Called via ctx->Driver.FinishRenderTexture.
+ */
+static void
+st_finish_render_texture(struct gl_context *ctx,
+ struct gl_renderbuffer_attachment *att)
+{
+ struct st_context *st = st_context(ctx);
+ struct st_renderbuffer *strb = st_renderbuffer(att->Renderbuffer);
+
+ if (!strb)
+ return;
+
+ st_flush(st, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+ strb->rtt = NULL;
+
+ /*
+ printf("FINISH RENDER TO TEXTURE surf=%p\n", strb->surface);
+ */
+
+ /* restore previous framebuffer state */
+ st_invalidate_state(ctx, _NEW_BUFFERS);
+}
+
+
+/**
+ * Validate a renderbuffer attachment for a particular set of bindings.
+ */
+static GLboolean
+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
+ * the format is supported.
+ */
+ if (att->Type != GL_TEXTURE)
+ return GL_TRUE;
+
+ if (!stObj)
+ return GL_FALSE;
+
+ 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);
+}
+
+
+/**
+ * Check if two renderbuffer attachments name a combined depth/stencil
+ * renderbuffer.
+ */
+GLboolean
+st_is_depth_stencil_combined(const struct gl_renderbuffer_attachment *depth,
+ const struct gl_renderbuffer_attachment *stencil)
+{
+ assert(depth && stencil);
+
+ if (depth->Type == stencil->Type) {
+ if (depth->Type == GL_RENDERBUFFER_EXT &&
+ depth->Renderbuffer == stencil->Renderbuffer)
+ return GL_TRUE;
+
+ if (depth->Type == GL_TEXTURE &&
+ depth->Texture == stencil->Texture)
+ return GL_TRUE;
+ }
+
+ return GL_FALSE;
+}
+
+
+/**
+ * Check that the framebuffer configuration is valid in terms of what
+ * the driver can support.
+ *
+ * For Gallium we only supports combined Z+stencil, not separate buffers.
+ */
+static void
+st_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
+{
+ struct st_context *st = st_context(ctx);
+ struct pipe_screen *screen = st->pipe->screen;
+ const struct gl_renderbuffer_attachment *depth =
+ &fb->Attachment[BUFFER_DEPTH];
+ const struct gl_renderbuffer_attachment *stencil =
+ &fb->Attachment[BUFFER_STENCIL];
+ GLuint i;
+
+ if (depth->Type && stencil->Type && depth->Type != stencil->Type) {
+ fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
+ return;
+ }
+ if (depth->Type == GL_RENDERBUFFER_EXT &&
+ stencil->Type == GL_RENDERBUFFER_EXT &&
+ depth->Renderbuffer != stencil->Renderbuffer) {
+ fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
+ return;
+ }
+ if (depth->Type == GL_TEXTURE &&
+ stencil->Type == GL_TEXTURE &&
+ depth->Texture != stencil->Texture) {
+ fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
+ return;
+ }
+
+ if (!st_validate_attachment(ctx,
+ screen,
+ depth,
+ PIPE_BIND_DEPTH_STENCIL)) {
+ fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
+ return;
+ }
+ 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(ctx,
+ screen,
+ &fb->Attachment[BUFFER_COLOR0 + i],
+ PIPE_BIND_RENDER_TARGET)) {
+ fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
+ return;
+ }
+ }
+}
+
+
+/**
+ * Called via glDrawBuffer.
+ */
+static void
+st_DrawBuffers(struct gl_context *ctx, GLsizei count, const GLenum *buffers)
+{
+ struct st_context *st = st_context(ctx);
+ struct gl_framebuffer *fb = ctx->DrawBuffer;
+ GLuint i;
+
+ (void) count;
+ (void) buffers;
+
+ /* add the renderbuffers on demand */
+ for (i = 0; i < fb->_NumColorDrawBuffers; i++) {
+ gl_buffer_index idx = fb->_ColorDrawBufferIndexes[i];
+ st_manager_add_color_renderbuffer(st, fb, idx);
+ }
+}
+
+
+/**
+ * Called via glReadBuffer.
+ */
+static void
+st_ReadBuffer(struct gl_context *ctx, GLenum buffer)
+{
+ struct st_context *st = st_context(ctx);
+ struct gl_framebuffer *fb = ctx->ReadBuffer;
+
+ (void) buffer;
+
+ /* add the renderbuffer on demand */
+ st_manager_add_color_renderbuffer(st, fb, fb->_ColorReadBufferIndex);
+}
+
+
+void st_init_fbo_functions(struct dd_function_table *functions)
+{
+#if FEATURE_EXT_framebuffer_object
+ functions->NewFramebuffer = st_new_framebuffer;
+ functions->NewRenderbuffer = st_new_renderbuffer;
+ functions->BindFramebuffer = st_bind_framebuffer;
+ functions->FramebufferRenderbuffer = st_framebuffer_renderbuffer;
+ functions->RenderTexture = st_render_texture;
+ functions->FinishRenderTexture = st_finish_render_texture;
+ functions->ValidateFramebuffer = st_validate_framebuffer;
+#endif
+ /* no longer needed by core Mesa, drivers handle resizes...
+ functions->ResizeBuffers = st_resize_buffers;
+ */
+
+ functions->DrawBuffers = st_DrawBuffers;
+ functions->ReadBuffer = st_ReadBuffer;
+}
+
+/* XXX unused ? */
+struct pipe_sampler_view *
+st_get_renderbuffer_sampler_view(struct st_renderbuffer *rb,
+ struct pipe_context *pipe)
+{
+ if (!rb->sampler_view) {
+ rb->sampler_view = st_create_texture_sampler_view(pipe, rb->texture);
+ }
+
+ return rb->sampler_view;
+}
diff --git a/mesalib/src/mesa/state_tracker/st_manager.c b/mesalib/src/mesa/state_tracker/st_manager.c
index 3b54eb7b8..5684e9768 100644
--- a/mesalib/src/mesa/state_tracker/st_manager.c
+++ b/mesalib/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/mesalib/src/mesa/swrast/s_trispan.h b/mesalib/src/mesa/swrast/s_trispan.h
deleted file mode 100644
index 15207e863..000000000
--- a/mesalib/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/mesalib/src/mesa/x86/read_rgba_span_x86.S b/mesalib/src/mesa/x86/read_rgba_span_x86.S
index 817729973..04571afb7 100644
--- a/mesalib/src/mesa/x86/read_rgba_span_x86.S
+++ b/mesalib/src/mesa/x86/read_rgba_span_x86.S
@@ -1,678 +1,686 @@
-/*
- * (C) Copyright IBM Corporation 2004
- * 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
- * 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
- * IBM 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.
- */
-
-/**
- * \file read_rgba_span_x86.S
- * Optimized routines to transfer pixel data from the framebuffer to a
- * buffer in main memory.
- *
- * \author Ian Romanick <idr@us.ibm.com>
- */
-
- .file "read_rgba_span_x86.S"
-#if !defined(__DJGPP__) && !defined(__MINGW32__) && !defined(__APPLE__) /* this one cries for assyntax.h */
-/* Kevin F. Quinn 2nd July 2006
- * Replaced data segment constants with text-segment instructions.
- */
-#define LOAD_MASK(mvins,m1,m2) \
- pushl $0xff00ff00 ;\
- pushl $0xff00ff00 ;\
- pushl $0xff00ff00 ;\
- pushl $0xff00ff00 ;\
- mvins (%esp), m1 ;\
- pushl $0x00ff0000 ;\
- pushl $0x00ff0000 ;\
- pushl $0x00ff0000 ;\
- pushl $0x00ff0000 ;\
- mvins (%esp), m2 ;\
- addl $32, %esp
-
-/* I implemented these as macros because they appear in several places,
- * and I've tweaked them a number of times. I got tired of changing every
- * place they appear. :)
- */
-
-#define DO_ONE_PIXEL() \
- movl (%ebx), %eax ; \
- addl $4, %ebx ; \
- bswap %eax /* ARGB -> BGRA */ ; \
- rorl $8, %eax /* BGRA -> ABGR */ ; \
- movl %eax, (%ecx) /* ABGR -> R, G, B, A */ ; \
- addl $4, %ecx
-
-#define DO_ONE_LAST_PIXEL() \
- movl (%ebx), %eax ; \
- bswap %eax /* ARGB -> BGRA */ ; \
- rorl $8, %eax /* BGRA -> ABGR */ ; \
- movl %eax, (%ecx) /* ABGR -> R, G, B, A */ ; \
-
-
-/**
- * MMX optimized version of the BGRA8888_REV to RGBA copy routine.
- *
- * \warning
- * This function assumes that the caller will issue the EMMS instruction
- * at the correct places.
- */
-
-.globl _generic_read_RGBA_span_BGRA8888_REV_MMX
-.hidden _generic_read_RGBA_span_BGRA8888_REV_MMX
- .type _generic_read_RGBA_span_BGRA8888_REV_MMX, @function
-_generic_read_RGBA_span_BGRA8888_REV_MMX:
- pushl %ebx
-
-#ifdef USE_INNER_EMMS
- emms
-#endif
- LOAD_MASK(movq,%mm1,%mm2)
-
- movl 8(%esp), %ebx /* source pointer */
- movl 16(%esp), %edx /* number of pixels to copy */
- movl 12(%esp), %ecx /* destination pointer */
-
- testl %edx, %edx
- jle .L20 /* Bail if there's nothing to do. */
-
- movl %ebx, %eax
-
- negl %eax
- sarl $2, %eax
- andl $1, %eax
- je .L17
-
- subl %eax, %edx
- DO_ONE_PIXEL()
-.L17:
-
- /* Would it be faster to unroll this loop once and process 4 pixels
- * per pass, instead of just two?
- */
-
- movl %edx, %eax
- shrl %eax
- jmp .L18
-.L19:
- movq (%ebx), %mm0
- addl $8, %ebx
-
- /* These 9 instructions do what PSHUFB (if there were such an
- * instruction) could do in 1. :(
- */
-
- movq %mm0, %mm3
- movq %mm0, %mm4
-
- pand %mm2, %mm3
- psllq $16, %mm4
- psrlq $16, %mm3
- pand %mm2, %mm4
-
- pand %mm1, %mm0
- por %mm4, %mm3
- por %mm3, %mm0
-
- movq %mm0, (%ecx)
- addl $8, %ecx
- subl $1, %eax
-.L18:
- jne .L19
-
-#ifdef USE_INNER_EMMS
- emms
-#endif
-
- /* At this point there are either 1 or 0 pixels remaining to be
- * converted. Convert the last pixel, if needed.
- */
-
- testl $1, %edx
- je .L20
-
- DO_ONE_LAST_PIXEL()
-
-.L20:
- popl %ebx
- ret
- .size _generic_read_RGBA_span_BGRA8888_REV_MMX, .-_generic_read_RGBA_span_BGRA8888_REV_MMX
-
-
-/**
- * SSE optimized version of the BGRA8888_REV to RGBA copy routine. SSE
- * instructions are only actually used to read data from the framebuffer.
- * In practice, the speed-up is pretty small.
- *
- * \todo
- * Do some more testing and determine if there's any reason to have this
- * function in addition to the MMX version.
- *
- * \warning
- * This function assumes that the caller will issue the EMMS instruction
- * at the correct places.
- */
-
-.globl _generic_read_RGBA_span_BGRA8888_REV_SSE
-.hidden _generic_read_RGBA_span_BGRA8888_REV_SSE
- .type _generic_read_RGBA_span_BGRA8888_REV_SSE, @function
-_generic_read_RGBA_span_BGRA8888_REV_SSE:
- pushl %esi
- pushl %ebx
- pushl %ebp
-
-#ifdef USE_INNER_EMMS
- emms
-#endif
-
- LOAD_MASK(movq,%mm1,%mm2)
-
- movl 16(%esp), %ebx /* source pointer */
- movl 24(%esp), %edx /* number of pixels to copy */
- movl 20(%esp), %ecx /* destination pointer */
-
- testl %edx, %edx
- jle .L35 /* Bail if there's nothing to do. */
-
- movl %esp, %ebp
- subl $16, %esp
- andl $0xfffffff0, %esp
-
- movl %ebx, %eax
- movl %edx, %esi
-
- negl %eax
- andl $15, %eax
- sarl $2, %eax
- cmpl %edx, %eax
- cmovle %eax, %esi
-
- subl %esi, %edx
-
- testl $1, %esi
- je .L32
-
- DO_ONE_PIXEL()
-.L32:
-
- testl $2, %esi
- je .L31
-
- movq (%ebx), %mm0
- addl $8, %ebx
-
- movq %mm0, %mm3
- movq %mm0, %mm4
-
- pand %mm2, %mm3
- psllq $16, %mm4
- psrlq $16, %mm3
- pand %mm2, %mm4
-
- pand %mm1, %mm0
- por %mm4, %mm3
- por %mm3, %mm0
-
- movq %mm0, (%ecx)
- addl $8, %ecx
-.L31:
-
- movl %edx, %eax
- shrl $2, %eax
- jmp .L33
-.L34:
- movaps (%ebx), %xmm0
- addl $16, %ebx
-
- /* This would be so much better if we could just move directly from
- * an SSE register to an MMX register. Unfortunately, that
- * functionality wasn't introduced until SSE2 with the MOVDQ2Q
- * instruction.
- */
-
- movaps %xmm0, (%esp)
- movq (%esp), %mm0
- movq 8(%esp), %mm5
-
- movq %mm0, %mm3
- movq %mm0, %mm4
- movq %mm5, %mm6
- movq %mm5, %mm7
-
- pand %mm2, %mm3
- pand %mm2, %mm6
-
- psllq $16, %mm4
- psllq $16, %mm7
-
- psrlq $16, %mm3
- psrlq $16, %mm6
-
- pand %mm2, %mm4
- pand %mm2, %mm7
-
- pand %mm1, %mm0
- pand %mm1, %mm5
-
- por %mm4, %mm3
- por %mm7, %mm6
-
- por %mm3, %mm0
- por %mm6, %mm5
-
- movq %mm0, (%ecx)
- movq %mm5, 8(%ecx)
- addl $16, %ecx
-
- subl $1, %eax
-.L33:
- jne .L34
-
-#ifdef USE_INNER_EMMS
- emms
-#endif
- movl %ebp, %esp
-
- /* At this point there are either [0, 3] pixels remaining to be
- * converted.
- */
-
- testl $2, %edx
- je .L36
-
- movq (%ebx), %mm0
- addl $8, %ebx
-
- movq %mm0, %mm3
- movq %mm0, %mm4
-
- pand %mm2, %mm3
- psllq $16, %mm4
- psrlq $16, %mm3
- pand %mm2, %mm4
-
- pand %mm1, %mm0
- por %mm4, %mm3
- por %mm3, %mm0
-
- movq %mm0, (%ecx)
- addl $8, %ecx
-.L36:
-
- testl $1, %edx
- je .L35
-
- DO_ONE_LAST_PIXEL()
-.L35:
- popl %ebp
- popl %ebx
- popl %esi
- ret
- .size _generic_read_RGBA_span_BGRA8888_REV_SSE, .-_generic_read_RGBA_span_BGRA8888_REV_SSE
-
-
-/**
- * SSE2 optimized version of the BGRA8888_REV to RGBA copy routine.
- */
-
- .text
-.globl _generic_read_RGBA_span_BGRA8888_REV_SSE2
-.hidden _generic_read_RGBA_span_BGRA8888_REV_SSE2
- .type _generic_read_RGBA_span_BGRA8888_REV_SSE2, @function
-_generic_read_RGBA_span_BGRA8888_REV_SSE2:
- pushl %esi
- pushl %ebx
-
- LOAD_MASK(movdqu,%xmm1,%xmm2)
-
- movl 12(%esp), %ebx /* source pointer */
- movl 20(%esp), %edx /* number of pixels to copy */
- movl 16(%esp), %ecx /* destination pointer */
-
- movl %ebx, %eax
- movl %edx, %esi
-
- testl %edx, %edx
- jle .L46 /* Bail if there's nothing to do. */
-
- /* If the source pointer isn't a multiple of 16 we have to process
- * a few pixels the "slow" way to get the address aligned for
- * the SSE fetch intsructions.
- */
-
- negl %eax
- andl $15, %eax
- sarl $2, %eax
-
- cmpl %edx, %eax
- cmovbe %eax, %esi
- subl %esi, %edx
-
- testl $1, %esi
- je .L41
-
- DO_ONE_PIXEL()
-.L41:
- testl $2, %esi
- je .L40
-
- movq (%ebx), %xmm0
- addl $8, %ebx
-
- movdqa %xmm0, %xmm3
- movdqa %xmm0, %xmm4
- andps %xmm1, %xmm0
-
- andps %xmm2, %xmm3
- pslldq $2, %xmm4
- psrldq $2, %xmm3
- andps %xmm2, %xmm4
-
- orps %xmm4, %xmm3
- orps %xmm3, %xmm0
-
- movq %xmm0, (%ecx)
- addl $8, %ecx
-.L40:
-
- /* Would it be worth having a specialized version of this loop for
- * the case where the destination is 16-byte aligned? That version
- * would be identical except that it could use movedqa instead of
- * movdqu.
- */
-
- movl %edx, %eax
- shrl $2, %eax
- jmp .L42
-.L43:
- movdqa (%ebx), %xmm0
- addl $16, %ebx
-
- movdqa %xmm0, %xmm3
- movdqa %xmm0, %xmm4
- andps %xmm1, %xmm0
-
- andps %xmm2, %xmm3
- pslldq $2, %xmm4
- psrldq $2, %xmm3
- andps %xmm2, %xmm4
-
- orps %xmm4, %xmm3
- orps %xmm3, %xmm0
-
- movdqu %xmm0, (%ecx)
- addl $16, %ecx
- subl $1, %eax
-.L42:
- jne .L43
-
-
- /* There may be upto 3 pixels remaining to be copied. Take care
- * of them now. We do the 2 pixel case first because the data
- * will be aligned.
- */
-
- testl $2, %edx
- je .L47
-
- movq (%ebx), %xmm0
- addl $8, %ebx
-
- movdqa %xmm0, %xmm3
- movdqa %xmm0, %xmm4
- andps %xmm1, %xmm0
-
- andps %xmm2, %xmm3
- pslldq $2, %xmm4
- psrldq $2, %xmm3
- andps %xmm2, %xmm4
-
- orps %xmm4, %xmm3
- orps %xmm3, %xmm0
-
- movq %xmm0, (%ecx)
- addl $8, %ecx
-.L47:
-
- testl $1, %edx
- je .L46
-
- DO_ONE_LAST_PIXEL()
-.L46:
-
- popl %ebx
- popl %esi
- ret
- .size _generic_read_RGBA_span_BGRA8888_REV_SSE2, .-_generic_read_RGBA_span_BGRA8888_REV_SSE2
-
-
-
-#define MASK_565_L 0x07e0f800
-#define MASK_565_H 0x0000001f
-/* Setting SCALE_ADJUST to 5 gives a perfect match with the
- * classic C implementation in Mesa. Setting SCALE_ADJUST
- * to 0 is slightly faster but at a small cost to accuracy.
- */
-#define SCALE_ADJUST 5
-#if SCALE_ADJUST == 5
-#define PRESCALE_L 0x00100001
-#define PRESCALE_H 0x00000200
-#define SCALE_L 0x40C620E8
-#define SCALE_H 0x0000839d
-#elif SCALE_ADJUST == 0
-#define PRESCALE_L 0x00200001
-#define PRESCALE_H 0x00000800
-#define SCALE_L 0x01040108
-#define SCALE_H 0x00000108
-#else
-#error SCALE_ADJUST must either be 5 or 0.
-#endif
-#define ALPHA_L 0x00000000
-#define ALPHA_H 0x00ff0000
-
-/**
- * MMX optimized version of the RGB565 to RGBA copy routine.
- */
-
- .text
- .globl _generic_read_RGBA_span_RGB565_MMX
- .hidden _generic_read_RGBA_span_RGB565_MMX
- .type _generic_read_RGBA_span_RGB565_MMX, @function
-
-_generic_read_RGBA_span_RGB565_MMX:
-
-#ifdef USE_INNER_EMMS
- emms
-#endif
-
- movl 4(%esp), %eax /* source pointer */
- movl 8(%esp), %edx /* destination pointer */
- movl 12(%esp), %ecx /* number of pixels to copy */
-
- pushl $MASK_565_H
- pushl $MASK_565_L
- movq (%esp), %mm5
- pushl $PRESCALE_H
- pushl $PRESCALE_L
- movq (%esp), %mm6
- pushl $SCALE_H
- pushl $SCALE_L
- movq (%esp), %mm7
- pushl $ALPHA_H
- pushl $ALPHA_L
- movq (%esp), %mm3
- addl $32,%esp
-
- sarl $2, %ecx
- jl .L01 /* Bail early if the count is negative. */
- jmp .L02
-
-.L03:
- /* Fetch 4 RGB565 pixels into %mm4. Distribute the first and
- * second pixels into the four words of %mm0 and %mm2.
- */
-
- movq (%eax), %mm4
- addl $8, %eax
-
- pshufw $0x00, %mm4, %mm0
- pshufw $0x55, %mm4, %mm2
-
-
- /* Mask the pixels so that each word of each register contains only
- * one color component.
- */
-
- pand %mm5, %mm0
- pand %mm5, %mm2
-
-
- /* Adjust the component values so that they are as small as possible,
- * but large enough so that we can multiply them by an unsigned 16-bit
- * number and get a value as large as 0x00ff0000.
- */
-
- pmullw %mm6, %mm0
- pmullw %mm6, %mm2
-#if SCALE_ADJUST > 0
- psrlw $SCALE_ADJUST, %mm0
- psrlw $SCALE_ADJUST, %mm2
-#endif
-
- /* Scale the input component values to be on the range
- * [0, 0x00ff0000]. This it the real magic of the whole routine.
- */
-
- pmulhuw %mm7, %mm0
- pmulhuw %mm7, %mm2
-
-
- /* Always set the alpha value to 0xff.
- */
-
- por %mm3, %mm0
- por %mm3, %mm2
-
-
- /* Pack the 16-bit values to 8-bit values and store the converted
- * pixel data.
- */
-
- packuswb %mm2, %mm0
- movq %mm0, (%edx)
- addl $8, %edx
-
- pshufw $0xaa, %mm4, %mm0
- pshufw $0xff, %mm4, %mm2
-
- pand %mm5, %mm0
- pand %mm5, %mm2
- pmullw %mm6, %mm0
- pmullw %mm6, %mm2
-#if SCALE_ADJUST > 0
- psrlw $SCALE_ADJUST, %mm0
- psrlw $SCALE_ADJUST, %mm2
-#endif
- pmulhuw %mm7, %mm0
- pmulhuw %mm7, %mm2
-
- por %mm3, %mm0
- por %mm3, %mm2
-
- packuswb %mm2, %mm0
-
- movq %mm0, (%edx)
- addl $8, %edx
-
- subl $1, %ecx
-.L02:
- jne .L03
-
-
- /* At this point there can be at most 3 pixels left to process. If
- * there is either 2 or 3 left, process 2.
- */
-
- movl 12(%esp), %ecx
- testl $0x02, %ecx
- je .L04
-
- movd (%eax), %mm4
- addl $4, %eax
-
- pshufw $0x00, %mm4, %mm0
- pshufw $0x55, %mm4, %mm2
-
- pand %mm5, %mm0
- pand %mm5, %mm2
- pmullw %mm6, %mm0
- pmullw %mm6, %mm2
-#if SCALE_ADJUST > 0
- psrlw $SCALE_ADJUST, %mm0
- psrlw $SCALE_ADJUST, %mm2
-#endif
- pmulhuw %mm7, %mm0
- pmulhuw %mm7, %mm2
-
- por %mm3, %mm0
- por %mm3, %mm2
-
- packuswb %mm2, %mm0
-
- movq %mm0, (%edx)
- addl $8, %edx
-
-.L04:
- /* At this point there can be at most 1 pixel left to process.
- * Process it if needed.
- */
-
- testl $0x01, %ecx
- je .L01
-
- movzwl (%eax), %ecx
- movd %ecx, %mm4
-
- pshufw $0x00, %mm4, %mm0
-
- pand %mm5, %mm0
- pmullw %mm6, %mm0
-#if SCALE_ADJUST > 0
- psrlw $SCALE_ADJUST, %mm0
-#endif
- pmulhuw %mm7, %mm0
-
- por %mm3, %mm0
-
- packuswb %mm0, %mm0
-
- movd %mm0, (%edx)
-
-.L01:
-#ifdef USE_INNER_EMMS
- emms
-#endif
- ret
-#endif /* !defined(__DJGPP__) && !defined(__MINGW32__) && !defined(__APPLE__) */
-
-#if defined (__ELF__) && defined (__linux__)
- .section .note.GNU-stack,"",%progbits
-#endif
+/*
+ * (C) Copyright IBM Corporation 2004
+ * 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
+ * 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
+ * IBM 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.
+ */
+
+/**
+ * \file read_rgba_span_x86.S
+ * Optimized routines to transfer pixel data from the framebuffer to a
+ * buffer in main memory.
+ *
+ * \author Ian Romanick <idr@us.ibm.com>
+ */
+
+ .file "read_rgba_span_x86.S"
+#if !defined(__DJGPP__) && !defined(__MINGW32__) && !defined(__APPLE__) /* this one cries for assyntax.h */
+/* Kevin F. Quinn 2nd July 2006
+ * Replaced data segment constants with text-segment instructions.
+ */
+#define LOAD_MASK(mvins,m1,m2) \
+ pushl $0xff00ff00 ;\
+ pushl $0xff00ff00 ;\
+ pushl $0xff00ff00 ;\
+ pushl $0xff00ff00 ;\
+ mvins (%esp), m1 ;\
+ pushl $0x00ff0000 ;\
+ pushl $0x00ff0000 ;\
+ pushl $0x00ff0000 ;\
+ pushl $0x00ff0000 ;\
+ mvins (%esp), m2 ;\
+ addl $32, %esp
+
+/* I implemented these as macros because they appear in several places,
+ * and I've tweaked them a number of times. I got tired of changing every
+ * place they appear. :)
+ */
+
+#define DO_ONE_PIXEL() \
+ movl (%ebx), %eax ; \
+ addl $4, %ebx ; \
+ bswap %eax /* ARGB -> BGRA */ ; \
+ rorl $8, %eax /* BGRA -> ABGR */ ; \
+ movl %eax, (%ecx) /* ABGR -> R, G, B, A */ ; \
+ addl $4, %ecx
+
+#define DO_ONE_LAST_PIXEL() \
+ movl (%ebx), %eax ; \
+ bswap %eax /* ARGB -> BGRA */ ; \
+ rorl $8, %eax /* BGRA -> ABGR */ ; \
+ movl %eax, (%ecx) /* ABGR -> R, G, B, A */ ; \
+
+
+/**
+ * MMX optimized version of the BGRA8888_REV to RGBA copy routine.
+ *
+ * \warning
+ * This function assumes that the caller will issue the EMMS instruction
+ * at the correct places.
+ */
+
+.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
+
+#ifdef USE_INNER_EMMS
+ emms
+#endif
+ LOAD_MASK(movq,%mm1,%mm2)
+
+ movl 8(%esp), %ebx /* source pointer */
+ movl 16(%esp), %edx /* number of pixels to copy */
+ movl 12(%esp), %ecx /* destination pointer */
+
+ testl %edx, %edx
+ jle .L20 /* Bail if there's nothing to do. */
+
+ movl %ebx, %eax
+
+ negl %eax
+ sarl $2, %eax
+ andl $1, %eax
+ je .L17
+
+ subl %eax, %edx
+ DO_ONE_PIXEL()
+.L17:
+
+ /* Would it be faster to unroll this loop once and process 4 pixels
+ * per pass, instead of just two?
+ */
+
+ movl %edx, %eax
+ shrl %eax
+ jmp .L18
+.L19:
+ movq (%ebx), %mm0
+ addl $8, %ebx
+
+ /* These 9 instructions do what PSHUFB (if there were such an
+ * instruction) could do in 1. :(
+ */
+
+ movq %mm0, %mm3
+ movq %mm0, %mm4
+
+ pand %mm2, %mm3
+ psllq $16, %mm4
+ psrlq $16, %mm3
+ pand %mm2, %mm4
+
+ pand %mm1, %mm0
+ por %mm4, %mm3
+ por %mm3, %mm0
+
+ movq %mm0, (%ecx)
+ addl $8, %ecx
+ subl $1, %eax
+.L18:
+ jne .L19
+
+#ifdef USE_INNER_EMMS
+ emms
+#endif
+
+ /* At this point there are either 1 or 0 pixels remaining to be
+ * converted. Convert the last pixel, if needed.
+ */
+
+ testl $1, %edx
+ je .L20
+
+ DO_ONE_LAST_PIXEL()
+
+.L20:
+ popl %ebx
+ ret
+ .size _generic_read_RGBA_span_BGRA8888_REV_MMX, .-_generic_read_RGBA_span_BGRA8888_REV_MMX
+
+
+/**
+ * SSE optimized version of the BGRA8888_REV to RGBA copy routine. SSE
+ * instructions are only actually used to read data from the framebuffer.
+ * In practice, the speed-up is pretty small.
+ *
+ * \todo
+ * Do some more testing and determine if there's any reason to have this
+ * function in addition to the MMX version.
+ *
+ * \warning
+ * This function assumes that the caller will issue the EMMS instruction
+ * at the correct places.
+ */
+
+.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
+ pushl %ebx
+ pushl %ebp
+
+#ifdef USE_INNER_EMMS
+ emms
+#endif
+
+ LOAD_MASK(movq,%mm1,%mm2)
+
+ movl 16(%esp), %ebx /* source pointer */
+ movl 24(%esp), %edx /* number of pixels to copy */
+ movl 20(%esp), %ecx /* destination pointer */
+
+ testl %edx, %edx
+ jle .L35 /* Bail if there's nothing to do. */
+
+ movl %esp, %ebp
+ subl $16, %esp
+ andl $0xfffffff0, %esp
+
+ movl %ebx, %eax
+ movl %edx, %esi
+
+ negl %eax
+ andl $15, %eax
+ sarl $2, %eax
+ cmpl %edx, %eax
+ cmovle %eax, %esi
+
+ subl %esi, %edx
+
+ testl $1, %esi
+ je .L32
+
+ DO_ONE_PIXEL()
+.L32:
+
+ testl $2, %esi
+ je .L31
+
+ movq (%ebx), %mm0
+ addl $8, %ebx
+
+ movq %mm0, %mm3
+ movq %mm0, %mm4
+
+ pand %mm2, %mm3
+ psllq $16, %mm4
+ psrlq $16, %mm3
+ pand %mm2, %mm4
+
+ pand %mm1, %mm0
+ por %mm4, %mm3
+ por %mm3, %mm0
+
+ movq %mm0, (%ecx)
+ addl $8, %ecx
+.L31:
+
+ movl %edx, %eax
+ shrl $2, %eax
+ jmp .L33
+.L34:
+ movaps (%ebx), %xmm0
+ addl $16, %ebx
+
+ /* This would be so much better if we could just move directly from
+ * an SSE register to an MMX register. Unfortunately, that
+ * functionality wasn't introduced until SSE2 with the MOVDQ2Q
+ * instruction.
+ */
+
+ movaps %xmm0, (%esp)
+ movq (%esp), %mm0
+ movq 8(%esp), %mm5
+
+ movq %mm0, %mm3
+ movq %mm0, %mm4
+ movq %mm5, %mm6
+ movq %mm5, %mm7
+
+ pand %mm2, %mm3
+ pand %mm2, %mm6
+
+ psllq $16, %mm4
+ psllq $16, %mm7
+
+ psrlq $16, %mm3
+ psrlq $16, %mm6
+
+ pand %mm2, %mm4
+ pand %mm2, %mm7
+
+ pand %mm1, %mm0
+ pand %mm1, %mm5
+
+ por %mm4, %mm3
+ por %mm7, %mm6
+
+ por %mm3, %mm0
+ por %mm6, %mm5
+
+ movq %mm0, (%ecx)
+ movq %mm5, 8(%ecx)
+ addl $16, %ecx
+
+ subl $1, %eax
+.L33:
+ jne .L34
+
+#ifdef USE_INNER_EMMS
+ emms
+#endif
+ movl %ebp, %esp
+
+ /* At this point there are either [0, 3] pixels remaining to be
+ * converted.
+ */
+
+ testl $2, %edx
+ je .L36
+
+ movq (%ebx), %mm0
+ addl $8, %ebx
+
+ movq %mm0, %mm3
+ movq %mm0, %mm4
+
+ pand %mm2, %mm3
+ psllq $16, %mm4
+ psrlq $16, %mm3
+ pand %mm2, %mm4
+
+ pand %mm1, %mm0
+ por %mm4, %mm3
+ por %mm3, %mm0
+
+ movq %mm0, (%ecx)
+ addl $8, %ecx
+.L36:
+
+ testl $1, %edx
+ je .L35
+
+ DO_ONE_LAST_PIXEL()
+.L35:
+ popl %ebp
+ popl %ebx
+ popl %esi
+ ret
+ .size _generic_read_RGBA_span_BGRA8888_REV_SSE, .-_generic_read_RGBA_span_BGRA8888_REV_SSE
+
+
+/**
+ * SSE2 optimized version of the BGRA8888_REV to RGBA copy routine.
+ */
+
+ .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
+ pushl %ebx
+
+ LOAD_MASK(movdqu,%xmm1,%xmm2)
+
+ movl 12(%esp), %ebx /* source pointer */
+ movl 20(%esp), %edx /* number of pixels to copy */
+ movl 16(%esp), %ecx /* destination pointer */
+
+ movl %ebx, %eax
+ movl %edx, %esi
+
+ testl %edx, %edx
+ jle .L46 /* Bail if there's nothing to do. */
+
+ /* If the source pointer isn't a multiple of 16 we have to process
+ * a few pixels the "slow" way to get the address aligned for
+ * the SSE fetch intsructions.
+ */
+
+ negl %eax
+ andl $15, %eax
+ sarl $2, %eax
+
+ cmpl %edx, %eax
+ cmovbe %eax, %esi
+ subl %esi, %edx
+
+ testl $1, %esi
+ je .L41
+
+ DO_ONE_PIXEL()
+.L41:
+ testl $2, %esi
+ je .L40
+
+ movq (%ebx), %xmm0
+ addl $8, %ebx
+
+ movdqa %xmm0, %xmm3
+ movdqa %xmm0, %xmm4
+ andps %xmm1, %xmm0
+
+ andps %xmm2, %xmm3
+ pslldq $2, %xmm4
+ psrldq $2, %xmm3
+ andps %xmm2, %xmm4
+
+ orps %xmm4, %xmm3
+ orps %xmm3, %xmm0
+
+ movq %xmm0, (%ecx)
+ addl $8, %ecx
+.L40:
+
+ /* Would it be worth having a specialized version of this loop for
+ * the case where the destination is 16-byte aligned? That version
+ * would be identical except that it could use movedqa instead of
+ * movdqu.
+ */
+
+ movl %edx, %eax
+ shrl $2, %eax
+ jmp .L42
+.L43:
+ movdqa (%ebx), %xmm0
+ addl $16, %ebx
+
+ movdqa %xmm0, %xmm3
+ movdqa %xmm0, %xmm4
+ andps %xmm1, %xmm0
+
+ andps %xmm2, %xmm3
+ pslldq $2, %xmm4
+ psrldq $2, %xmm3
+ andps %xmm2, %xmm4
+
+ orps %xmm4, %xmm3
+ orps %xmm3, %xmm0
+
+ movdqu %xmm0, (%ecx)
+ addl $16, %ecx
+ subl $1, %eax
+.L42:
+ jne .L43
+
+
+ /* There may be upto 3 pixels remaining to be copied. Take care
+ * of them now. We do the 2 pixel case first because the data
+ * will be aligned.
+ */
+
+ testl $2, %edx
+ je .L47
+
+ movq (%ebx), %xmm0
+ addl $8, %ebx
+
+ movdqa %xmm0, %xmm3
+ movdqa %xmm0, %xmm4
+ andps %xmm1, %xmm0
+
+ andps %xmm2, %xmm3
+ pslldq $2, %xmm4
+ psrldq $2, %xmm3
+ andps %xmm2, %xmm4
+
+ orps %xmm4, %xmm3
+ orps %xmm3, %xmm0
+
+ movq %xmm0, (%ecx)
+ addl $8, %ecx
+.L47:
+
+ testl $1, %edx
+ je .L46
+
+ DO_ONE_LAST_PIXEL()
+.L46:
+
+ popl %ebx
+ popl %esi
+ ret
+ .size _generic_read_RGBA_span_BGRA8888_REV_SSE2, .-_generic_read_RGBA_span_BGRA8888_REV_SSE2
+
+
+
+#define MASK_565_L 0x07e0f800
+#define MASK_565_H 0x0000001f
+/* Setting SCALE_ADJUST to 5 gives a perfect match with the
+ * classic C implementation in Mesa. Setting SCALE_ADJUST
+ * to 0 is slightly faster but at a small cost to accuracy.
+ */
+#define SCALE_ADJUST 5
+#if SCALE_ADJUST == 5
+#define PRESCALE_L 0x00100001
+#define PRESCALE_H 0x00000200
+#define SCALE_L 0x40C620E8
+#define SCALE_H 0x0000839d
+#elif SCALE_ADJUST == 0
+#define PRESCALE_L 0x00200001
+#define PRESCALE_H 0x00000800
+#define SCALE_L 0x01040108
+#define SCALE_H 0x00000108
+#else
+#error SCALE_ADJUST must either be 5 or 0.
+#endif
+#define ALPHA_L 0x00000000
+#define ALPHA_H 0x00ff0000
+
+/**
+ * MMX optimized version of the RGB565 to RGBA copy routine.
+ */
+
+ .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:
+
+#ifdef USE_INNER_EMMS
+ emms
+#endif
+
+ movl 4(%esp), %eax /* source pointer */
+ movl 8(%esp), %edx /* destination pointer */
+ movl 12(%esp), %ecx /* number of pixels to copy */
+
+ pushl $MASK_565_H
+ pushl $MASK_565_L
+ movq (%esp), %mm5
+ pushl $PRESCALE_H
+ pushl $PRESCALE_L
+ movq (%esp), %mm6
+ pushl $SCALE_H
+ pushl $SCALE_L
+ movq (%esp), %mm7
+ pushl $ALPHA_H
+ pushl $ALPHA_L
+ movq (%esp), %mm3
+ addl $32,%esp
+
+ sarl $2, %ecx
+ jl .L01 /* Bail early if the count is negative. */
+ jmp .L02
+
+.L03:
+ /* Fetch 4 RGB565 pixels into %mm4. Distribute the first and
+ * second pixels into the four words of %mm0 and %mm2.
+ */
+
+ movq (%eax), %mm4
+ addl $8, %eax
+
+ pshufw $0x00, %mm4, %mm0
+ pshufw $0x55, %mm4, %mm2
+
+
+ /* Mask the pixels so that each word of each register contains only
+ * one color component.
+ */
+
+ pand %mm5, %mm0
+ pand %mm5, %mm2
+
+
+ /* Adjust the component values so that they are as small as possible,
+ * but large enough so that we can multiply them by an unsigned 16-bit
+ * number and get a value as large as 0x00ff0000.
+ */
+
+ pmullw %mm6, %mm0
+ pmullw %mm6, %mm2
+#if SCALE_ADJUST > 0
+ psrlw $SCALE_ADJUST, %mm0
+ psrlw $SCALE_ADJUST, %mm2
+#endif
+
+ /* Scale the input component values to be on the range
+ * [0, 0x00ff0000]. This it the real magic of the whole routine.
+ */
+
+ pmulhuw %mm7, %mm0
+ pmulhuw %mm7, %mm2
+
+
+ /* Always set the alpha value to 0xff.
+ */
+
+ por %mm3, %mm0
+ por %mm3, %mm2
+
+
+ /* Pack the 16-bit values to 8-bit values and store the converted
+ * pixel data.
+ */
+
+ packuswb %mm2, %mm0
+ movq %mm0, (%edx)
+ addl $8, %edx
+
+ pshufw $0xaa, %mm4, %mm0
+ pshufw $0xff, %mm4, %mm2
+
+ pand %mm5, %mm0
+ pand %mm5, %mm2
+ pmullw %mm6, %mm0
+ pmullw %mm6, %mm2
+#if SCALE_ADJUST > 0
+ psrlw $SCALE_ADJUST, %mm0
+ psrlw $SCALE_ADJUST, %mm2
+#endif
+ pmulhuw %mm7, %mm0
+ pmulhuw %mm7, %mm2
+
+ por %mm3, %mm0
+ por %mm3, %mm2
+
+ packuswb %mm2, %mm0
+
+ movq %mm0, (%edx)
+ addl $8, %edx
+
+ subl $1, %ecx
+.L02:
+ jne .L03
+
+
+ /* At this point there can be at most 3 pixels left to process. If
+ * there is either 2 or 3 left, process 2.
+ */
+
+ movl 12(%esp), %ecx
+ testl $0x02, %ecx
+ je .L04
+
+ movd (%eax), %mm4
+ addl $4, %eax
+
+ pshufw $0x00, %mm4, %mm0
+ pshufw $0x55, %mm4, %mm2
+
+ pand %mm5, %mm0
+ pand %mm5, %mm2
+ pmullw %mm6, %mm0
+ pmullw %mm6, %mm2
+#if SCALE_ADJUST > 0
+ psrlw $SCALE_ADJUST, %mm0
+ psrlw $SCALE_ADJUST, %mm2
+#endif
+ pmulhuw %mm7, %mm0
+ pmulhuw %mm7, %mm2
+
+ por %mm3, %mm0
+ por %mm3, %mm2
+
+ packuswb %mm2, %mm0
+
+ movq %mm0, (%edx)
+ addl $8, %edx
+
+.L04:
+ /* At this point there can be at most 1 pixel left to process.
+ * Process it if needed.
+ */
+
+ testl $0x01, %ecx
+ je .L01
+
+ movzwl (%eax), %ecx
+ movd %ecx, %mm4
+
+ pshufw $0x00, %mm4, %mm0
+
+ pand %mm5, %mm0
+ pmullw %mm6, %mm0
+#if SCALE_ADJUST > 0
+ psrlw $SCALE_ADJUST, %mm0
+#endif
+ pmulhuw %mm7, %mm0
+
+ por %mm3, %mm0
+
+ packuswb %mm0, %mm0
+
+ movd %mm0, (%edx)
+
+.L01:
+#ifdef USE_INNER_EMMS
+ emms
+#endif
+ ret
+#endif /* !defined(__DJGPP__) && !defined(__MINGW32__) && !defined(__APPLE__) */
+
+#if defined (__ELF__) && defined (__linux__)
+ .section .note.GNU-stack,"",%progbits
+#endif