summaryrefslogtreecommitdiffstats
path: root/src/mesa
diff options
context:
space:
mode:
authorBrian Paul <[email protected]>2009-02-09 09:22:22 -0700
committerBrian Paul <[email protected]>2009-02-09 09:22:22 -0700
commite97681c7f551a2a2a6bd5eff0f4192a870c816c0 (patch)
treedff2bf0e6d22efb92af131f64be0621ed316977c /src/mesa
parent1a46c8a062aea59de5cf55881104489db5d609e5 (diff)
parentb907d4cd8fafe719b4f87d877562829548937485 (diff)
mesa: merge gallium-0.2 into gallium-master-merge
Merge commit 'origin/gallium-0.2' into gallium-master-merge Conflicts: Makefile docs/relnotes-7.4.html docs/relnotes.html src/mesa/drivers/dri/i965/brw_wm.h src/mesa/main/imports.c src/mesa/main/mtypes.h src/mesa/main/texcompress.c src/mesa/main/texenvprogram.c src/mesa/main/version.h src/mesa/vbo/vbo_exec_api.c src/mesa/vbo/vbo_save_draw.c
Diffstat (limited to 'src/mesa')
-rw-r--r--src/mesa/Makefile11
-rw-r--r--src/mesa/Makefile.DJ166
-rw-r--r--src/mesa/Makefile.mgw2
-rw-r--r--src/mesa/SConscript343
-rw-r--r--src/mesa/drivers/dri/Makefile.template16
-rw-r--r--src/mesa/drivers/dri/common/dri_util.h42
-rw-r--r--src/mesa/drivers/dri/common/drirenderbuffer.c2
-rw-r--r--src/mesa/drivers/dri/common/utils.c134
-rw-r--r--src/mesa/drivers/dri/common/utils.h3
-rw-r--r--src/mesa/drivers/dri/glcore/Makefile84
-rw-r--r--src/mesa/glapi/descrip.mms39
-rw-r--r--src/mesa/glapi/glapi.c4
-rw-r--r--src/mesa/glapi/glthread.c6
-rw-r--r--src/mesa/glapi/glthread.h48
-rw-r--r--src/mesa/main/api_validate.c6
-rw-r--r--src/mesa/main/bufferobj.c15
-rw-r--r--src/mesa/main/bufferobj.h5
-rw-r--r--src/mesa/main/buffers.c3
-rw-r--r--src/mesa/main/config.h4
-rw-r--r--src/mesa/main/context.c86
-rw-r--r--src/mesa/main/dlopen.c2
-rw-r--r--src/mesa/main/drawpix.c4
-rw-r--r--src/mesa/main/enable.c5
-rw-r--r--src/mesa/main/extensions.c2
-rw-r--r--src/mesa/main/fbobject.c2
-rw-r--r--src/mesa/main/ffvertex_prog.c74
-rw-r--r--src/mesa/main/glheader.h39
-rw-r--r--src/mesa/main/imports.c16
-rw-r--r--src/mesa/main/imports.h8
-rw-r--r--src/mesa/main/light.c1
-rw-r--r--src/mesa/main/mtypes.h10
-rw-r--r--src/mesa/main/renderbuffer.c3
-rw-r--r--src/mesa/main/sources1
-rw-r--r--src/mesa/main/state.c69
-rw-r--r--src/mesa/main/state.h14
-rw-r--r--src/mesa/main/texcompress.c56
-rw-r--r--src/mesa/main/texcompress_fxt1.c8
-rw-r--r--src/mesa/main/texcompress_s3tc.c184
-rw-r--r--src/mesa/main/texenvprogram.c185
-rw-r--r--src/mesa/main/texformat.c76
-rw-r--r--src/mesa/main/texformat.h21
-rw-r--r--src/mesa/main/texformat_tmp.h26
-rw-r--r--src/mesa/main/teximage.c23
-rw-r--r--src/mesa/main/texstore.c55
-rw-r--r--src/mesa/main/texstore.h2
-rw-r--r--src/mesa/main/varray.h14
-rw-r--r--src/mesa/main/version.h4
-rw-r--r--src/mesa/math/m_debug_xform.c3
-rw-r--r--src/mesa/ppc/common_ppc.c2
-rw-r--r--src/mesa/shader/arbprogparse.c68
-rw-r--r--src/mesa/shader/atifragshader.h2
-rw-r--r--src/mesa/shader/grammar/descrip.mms42
-rw-r--r--src/mesa/shader/prog_cache.c29
-rw-r--r--src/mesa/shader/prog_cache.h2
-rw-r--r--src/mesa/shader/prog_instruction.h2
-rw-r--r--src/mesa/shader/prog_parameter.c4
-rw-r--r--src/mesa/shader/prog_print.c17
-rw-r--r--src/mesa/shader/prog_print.h3
-rw-r--r--src/mesa/shader/prog_statevars.c29
-rw-r--r--src/mesa/shader/prog_statevars.h3
-rw-r--r--src/mesa/shader/prog_uniform.c4
-rw-r--r--src/mesa/shader/program.c42
-rw-r--r--src/mesa/shader/shader_api.c25
-rw-r--r--src/mesa/shader/slang/library/slang_version_syn.h64
-rw-r--r--src/mesa/shader/slang/slang_link.c1
-rw-r--r--src/mesa/sources10
-rw-r--r--src/mesa/sources.mak350
-rw-r--r--src/mesa/state_tracker/Makefile2
-rw-r--r--src/mesa/state_tracker/st_api.c33
-rw-r--r--src/mesa/state_tracker/st_atom.c218
-rw-r--r--src/mesa/state_tracker/st_atom.h66
-rw-r--r--src/mesa/state_tracker/st_atom_blend.c232
-rw-r--r--src/mesa/state_tracker/st_atom_clip.c71
-rw-r--r--src/mesa/state_tracker/st_atom_constbuf.c140
-rw-r--r--src/mesa/state_tracker/st_atom_constbuf.h38
-rw-r--r--src/mesa/state_tracker/st_atom_depth.c151
-rw-r--r--src/mesa/state_tracker/st_atom_framebuffer.c176
-rw-r--r--src/mesa/state_tracker/st_atom_pixeltransfer.c474
-rw-r--r--src/mesa/state_tracker/st_atom_rasterizer.c289
-rw-r--r--src/mesa/state_tracker/st_atom_sampler.c217
-rw-r--r--src/mesa/state_tracker/st_atom_scissor.c92
-rw-r--r--src/mesa/state_tracker/st_atom_shader.c369
-rw-r--r--src/mesa/state_tracker/st_atom_shader.h38
-rw-r--r--src/mesa/state_tracker/st_atom_stipple.c63
-rw-r--r--src/mesa/state_tracker/st_atom_texture.c162
-rw-r--r--src/mesa/state_tracker/st_atom_viewport.c91
-rw-r--r--src/mesa/state_tracker/st_cache.h68
-rw-r--r--src/mesa/state_tracker/st_cb_accum.c362
-rw-r--r--src/mesa/state_tracker/st_cb_accum.h39
-rw-r--r--src/mesa/state_tracker/st_cb_bitmap.c833
-rw-r--r--src/mesa/state_tracker/st_cb_bitmap.h52
-rw-r--r--src/mesa/state_tracker/st_cb_blit.c111
-rw-r--r--src/mesa/state_tracker/st_cb_blit.h46
-rw-r--r--src/mesa/state_tracker/st_cb_bufferobjects.c240
-rw-r--r--src/mesa/state_tracker/st_cb_bufferobjects.h66
-rw-r--r--src/mesa/state_tracker/st_cb_clear.c602
-rw-r--r--src/mesa/state_tracker/st_cb_clear.h49
-rw-r--r--src/mesa/state_tracker/st_cb_drawpixels.c1104
-rw-r--r--src/mesa/state_tracker/st_cb_drawpixels.h39
-rw-r--r--src/mesa/state_tracker/st_cb_fbo.c458
-rw-r--r--src/mesa/state_tracker/st_cb_fbo.h71
-rw-r--r--src/mesa/state_tracker/st_cb_feedback.c309
-rw-r--r--src/mesa/state_tracker/st_cb_feedback.h37
-rw-r--r--src/mesa/state_tracker/st_cb_flush.c149
-rw-r--r--src/mesa/state_tracker/st_cb_flush.h38
-rw-r--r--src/mesa/state_tracker/st_cb_get.c97
-rw-r--r--src/mesa/state_tracker/st_cb_get.h37
-rw-r--r--src/mesa/state_tracker/st_cb_program.c266
-rw-r--r--src/mesa/state_tracker/st_cb_program.h39
-rw-r--r--src/mesa/state_tracker/st_cb_queryobj.c171
-rw-r--r--src/mesa/state_tracker/st_cb_queryobj.h36
-rw-r--r--src/mesa/state_tracker/st_cb_rasterpos.c261
-rw-r--r--src/mesa/state_tracker/st_cb_rasterpos.h33
-rw-r--r--src/mesa/state_tracker/st_cb_readpixels.c464
-rw-r--r--src/mesa/state_tracker/st_cb_readpixels.h45
-rw-r--r--src/mesa/state_tracker/st_cb_strings.c84
-rw-r--r--src/mesa/state_tracker/st_cb_strings.h38
-rw-r--r--src/mesa/state_tracker/st_cb_texture.c1551
-rw-r--r--src/mesa/state_tracker/st_cb_texture.h48
-rw-r--r--src/mesa/state_tracker/st_context.c325
-rw-r--r--src/mesa/state_tracker/st_context.h249
-rw-r--r--src/mesa/state_tracker/st_debug.c70
-rw-r--r--src/mesa/state_tracker/st_debug.h36
-rw-r--r--src/mesa/state_tracker/st_draw.c699
-rw-r--r--src/mesa/state_tracker/st_draw.h67
-rw-r--r--src/mesa/state_tracker/st_draw_feedback.c262
-rw-r--r--src/mesa/state_tracker/st_extensions.c279
-rw-r--r--src/mesa/state_tracker/st_extensions.h38
-rw-r--r--src/mesa/state_tracker/st_format.c718
-rw-r--r--src/mesa/state_tracker/st_format.h79
-rw-r--r--src/mesa/state_tracker/st_framebuffer.c333
-rw-r--r--src/mesa/state_tracker/st_gen_mipmap.c209
-rw-r--r--src/mesa/state_tracker/st_gen_mipmap.h46
-rw-r--r--src/mesa/state_tracker/st_mesa_to_tgsi.c1041
-rw-r--r--src/mesa/state_tracker/st_mesa_to_tgsi.h67
-rw-r--r--src/mesa/state_tracker/st_program.c556
-rw-r--r--src/mesa/state_tracker/st_program.h158
-rw-r--r--src/mesa/state_tracker/st_public.h122
-rw-r--r--src/mesa/state_tracker/st_texture.c488
-rw-r--r--src/mesa/state_tracker/st_texture.h179
-rw-r--r--src/mesa/swrast/s_context.c3
-rw-r--r--src/mesa/tnl/t_context.c3
-rw-r--r--src/mesa/tnl/t_vp_build.h7
-rw-r--r--src/mesa/tnl/tnl.h2
-rw-r--r--src/mesa/vbo/vbo.h18
-rw-r--r--src/mesa/vbo/vbo_context.c22
-rw-r--r--src/mesa/vbo/vbo_exec_api.c86
-rw-r--r--src/mesa/vbo/vbo_exec_array.c69
-rw-r--r--src/mesa/vbo/vbo_exec_draw.c7
-rw-r--r--src/mesa/vbo/vbo_save_draw.c33
-rw-r--r--src/mesa/vf/vf.c372
-rw-r--r--src/mesa/vf/vf.h234
-rw-r--r--src/mesa/vf/vf_generic.c981
-rw-r--r--src/mesa/vf/vf_sse.c662
-rw-r--r--src/mesa/x86/Makefile2
-rw-r--r--src/mesa/x86/rtasm/x86sse.c9
156 files changed, 21212 insertions, 709 deletions
diff --git a/src/mesa/Makefile b/src/mesa/Makefile
index 6b4057030ef..552c20e0b9b 100644
--- a/src/mesa/Makefile
+++ b/src/mesa/Makefile
@@ -3,8 +3,7 @@
TOP = ../..
include $(TOP)/configs/current
-include sources
-
+include sources.mak
.SUFFIXES : .cpp
@@ -19,6 +18,7 @@ include sources
+
# Default: build dependencies, then asm_subdirs, then convenience
# libs (.a) and finally the device drivers:
default: depend asm_subdirs libmesa.a libglapi.a driver_subdirs
@@ -34,8 +34,11 @@ libmesa.a: $(MESA_OBJECTS)
# Make archive of gl* API dispatcher functions only
libglapi.a: $(GLAPI_OBJECTS)
- @ $(MKLIB) -o glapi -static $(GLAPI_OBJECTS)
-
+ @if [ "${WINDOW_SYSTEM}" = "dri" ] ; then \
+ touch libglapi.a ; \
+ else \
+ $(MKLIB) -o glapi -static $(GLAPI_OBJECTS) ; \
+ fi
######################################################################
# Device drivers
diff --git a/src/mesa/Makefile.DJ b/src/mesa/Makefile.DJ
deleted file mode 100644
index 06a13fb1abd..00000000000
--- a/src/mesa/Makefile.DJ
+++ /dev/null
@@ -1,166 +0,0 @@
-# Mesa 3-D graphics library
-# Version: 5.1
-#
-# Copyright (C) 1999-2003 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.
-
-# DOS/DJGPP core makefile v1.7 for Mesa
-#
-# Copyright (C) 2002 - Daniel Borca
-# Web : http://www.geocities.com/dborca
-
-
-#
-# Available options:
-#
-# Environment variables:
-# CFLAGS
-#
-# GLIDE path to Glide3 SDK; used with FX.
-# default = $(TOP)/glide3
-# FX=1 build for 3dfx Glide3. Note that this disables
-# compilation of most DMesa code and requires fxMesa.
-# As a consequence, you'll need the DJGPP Glide3
-# library to build any application.
-# default = no
-# X86=1 optimize for x86 (if possible, use MMX, SSE, 3DNow).
-# default = no
-#
-# Targets:
-# all: build GL
-# clean: remove object files
-#
-
-
-
-.PHONY: all clean
-.INTERMEDIATE: x86/gen_matypes.exe
-
-TOP = ../..
-GLIDE ?= $(TOP)/glide3
-LIBDIR = $(TOP)/lib
-GL_LIB = libgl.a
-GL_DXE = gl.dxe
-GL_IMP = libigl.a
-
-export LD_LIBRARY_PATH := $(LD_LIBRARY_PATH);$(LIBDIR);$(GLIDE)/lib
-
-CC = gcc
-CFLAGS += $(INCLUDE_DIRS)
-CFLAGS += -DUSE_EXTERNAL_DXTN_LIB=1
-ifeq ($(FX),1)
-CFLAGS += -D__DOS__
-CFLAGS += -I$(GLIDE)/include -DFX
-LIBNAME = "Mesa/FX DJGPP"
-else
-LIBNAME = "Mesa DJGPP"
-endif
-
-AR = ar
-ARFLAGS = crus
-
-HAVEDXE3 = $(wildcard $(DJDIR)/bin/dxe3gen.exe)
-
-ifeq ($(wildcard $(addsuffix /rm.exe,$(subst ;, ,$(PATH)))),)
-UNLINK = del $(subst /,\,$(1))
-else
-UNLINK = $(RM) $(1)
-endif
-
-include sources
-
-ifeq ($(X86),1)
-CFLAGS += -DUSE_X86_ASM
-CFLAGS += -DUSE_MMX_ASM
-CFLAGS += -DUSE_SSE_ASM
-CFLAGS += -DUSE_3DNOW_ASM
-X86_SOURCES += $(X86_API)
-else
-X86_SOURCES =
-endif
-
-DRIVER_SOURCES = \
- drivers/dos/dmesa.c
-ifeq ($(FX),1)
-DRIVER_SOURCES += \
- $(GLIDE_DRIVER_SOURCES)
-else
-DRIVER_SOURCES += \
- $(OSMESA_DRIVER_SOURCES) \
- drivers/dos/video.c \
- drivers/dos/vesa.c \
- drivers/dos/blit.S \
- drivers/dos/vga.c \
- drivers/dos/null.c \
- drivers/dos/dpmi.c
-endif
-
-SOURCES = $(CORE_SOURCES) $(X86_SOURCES) $(COMMON_DRIVER_SOURCES) $(DRIVER_SOURCES)
-
-OBJECTS = $(addsuffix .o,$(basename $(SOURCES)))
-
-X86_OBJECTS = $(addsuffix .o,$(basename $(X86_SOURCES)))
-
-.c.o:
- $(CC) -o $@ $(CFLAGS) -c $<
-.S.o:
- $(CC) -o $@ $(CFLAGS) -c $<
-.s.o:
- $(CC) -o $@ $(CFLAGS) -x assembler-with-cpp -c $<
-
-all: $(LIBDIR)/$(GL_LIB) $(LIBDIR)/$(GL_DXE) $(LIBDIR)/$(GL_IMP)
-
-$(LIBDIR)/$(GL_LIB): $(OBJECTS)
- $(AR) $(ARFLAGS) $@ $^
-
-$(LIBDIR)/$(GL_DXE) $(LIBDIR)/$(GL_IMP): $(OBJECTS)
-ifeq ($(HAVEDXE3),)
- $(warning Missing DXE3 package... Skipping $(GL_DXE))
-else
-ifeq ($(FX),1)
- -dxe3gen -o $(LIBDIR)/$(GL_DXE) -Y $(LIBDIR)/$(GL_IMP) -D $(LIBNAME) -E _gl -E _DMesa -P glide3x.dxe -U $^
-else
- -dxe3gen -o $(LIBDIR)/$(GL_DXE) -Y $(LIBDIR)/$(GL_IMP) -D $(LIBNAME) -E _gl -E _DMesa -U $^
-endif
-endif
-
-$(X86_OBJECTS): x86/matypes.h
-
-x86/matypes.h: x86/gen_matypes.exe
- $< > $@
-
-x86/gen_matypes.exe: x86/gen_matypes.c
- $(CC) -o $@ $(CFLAGS) -s $<
-
-clean:
- -$(call UNLINK,array_cache/*.o)
- -$(call UNLINK,glapi/*.o)
- -$(call UNLINK,main/*.o)
- -$(call UNLINK,math/*.o)
- -$(call UNLINK,shader/*.o)
- -$(call UNLINK,sparc/*.o)
- -$(call UNLINK,ppc/*.o)
- -$(call UNLINK,swrast/*.o)
- -$(call UNLINK,swrast_setup/*.o)
- -$(call UNLINK,tnl/*.o)
- -$(call UNLINK,x86/*.o)
- -$(call UNLINK,drivers/common/*.o)
- -$(call UNLINK,drivers/dos/*.o)
- -$(call UNLINK,drivers/glide/*.o)
diff --git a/src/mesa/Makefile.mgw b/src/mesa/Makefile.mgw
index 886b344ec9b..097c390a83e 100644
--- a/src/mesa/Makefile.mgw
+++ b/src/mesa/Makefile.mgw
@@ -124,7 +124,7 @@ ifneq ($(wildcard $(addsuffix /rm,$(subst :, ,$(PATH)))),)
UNLINK = $(RM) $(1)
endif
-include sources
+include sources.mak
CFLAGS += $(INCLUDE_DIRS)
diff --git a/src/mesa/SConscript b/src/mesa/SConscript
new file mode 100644
index 00000000000..a878d31dbb5
--- /dev/null
+++ b/src/mesa/SConscript
@@ -0,0 +1,343 @@
+#######################################################################
+# SConscript for Mesa
+
+
+Import('*')
+
+if env['platform'] != 'winddk':
+
+ env = env.Clone()
+
+ env.Append(CPPPATH = [
+ '#/src/mesa',
+ ])
+
+ if env['platform'] == 'windows':
+ env.Append(CPPDEFINES = [
+ '_GDI32_', # prevent gl* being declared __declspec(dllimport) in MS headers
+ 'BUILD_GL32', # declare gl* as __declspec(dllexport) in Mesa headers
+ ])
+
+ #
+ # Source files
+ #
+
+ main_sources = [
+ 'main/api_arrayelt.c',
+ 'main/api_exec.c',
+ 'main/api_loopback.c',
+ 'main/api_noop.c',
+ 'main/api_validate.c',
+ 'main/accum.c',
+ 'main/attrib.c',
+ 'main/arrayobj.c',
+ 'main/blend.c',
+ 'main/bufferobj.c',
+ 'main/buffers.c',
+ 'main/clear.c',
+ 'main/clip.c',
+ 'main/colortab.c',
+ 'main/context.c',
+ 'main/convolve.c',
+ 'main/debug.c',
+ 'main/depth.c',
+ 'main/depthstencil.c',
+ 'main/dlist.c',
+ 'main/dlopen.c',
+ 'main/drawpix.c',
+ 'main/enable.c',
+ 'main/enums.c',
+ 'main/eval.c',
+ 'main/execmem.c',
+ 'main/extensions.c',
+ 'main/fbobject.c',
+ 'main/feedback.c',
+ 'main/ffvertex_prog.c',
+ 'main/fog.c',
+ 'main/framebuffer.c',
+ 'main/get.c',
+ 'main/getstring.c',
+ 'main/hash.c',
+ 'main/hint.c',
+ 'main/histogram.c',
+ 'main/image.c',
+ 'main/imports.c',
+ 'main/light.c',
+ 'main/lines.c',
+ 'main/matrix.c',
+ 'main/mipmap.c',
+ 'main/mm.c',
+ 'main/multisample.c',
+ 'main/pixel.c',
+ 'main/pixelstore.c',
+ 'main/points.c',
+ 'main/polygon.c',
+ 'main/queryobj.c',
+ 'main/rastpos.c',
+ 'main/rbadaptors.c',
+ 'main/readpix.c',
+ 'main/renderbuffer.c',
+ 'main/scissor.c',
+ 'main/shaders.c',
+ 'main/state.c',
+ 'main/stencil.c',
+ 'main/texcompress.c',
+ 'main/texcompress_s3tc.c',
+ 'main/texcompress_fxt1.c',
+ 'main/texenv.c',
+ 'main/texenvprogram.c',
+ 'main/texformat.c',
+ 'main/texgen.c',
+ 'main/teximage.c',
+ 'main/texobj.c',
+ 'main/texparam.c',
+ 'main/texrender.c',
+ 'main/texstate.c',
+ 'main/texstore.c',
+ 'main/varray.c',
+ 'main/vtxfmt.c',
+ ]
+
+ math_sources = [
+ 'math/m_debug_clip.c',
+ 'math/m_debug_norm.c',
+ 'math/m_debug_xform.c',
+ 'math/m_eval.c',
+ 'math/m_matrix.c',
+ 'math/m_translate.c',
+ 'math/m_vector.c',
+ 'math/m_xform.c',
+ ]
+
+ vbo_sources = [
+ 'vbo/vbo_context.c',
+ 'vbo/vbo_exec.c',
+ 'vbo/vbo_exec_api.c',
+ 'vbo/vbo_exec_array.c',
+ 'vbo/vbo_exec_draw.c',
+ 'vbo/vbo_exec_eval.c',
+ 'vbo/vbo_rebase.c',
+ 'vbo/vbo_split.c',
+ 'vbo/vbo_split_copy.c',
+ 'vbo/vbo_split_inplace.c',
+ 'vbo/vbo_save.c',
+ 'vbo/vbo_save_api.c',
+ 'vbo/vbo_save_draw.c',
+ 'vbo/vbo_save_loopback.c',
+ ]
+
+ vf_sources = [
+ 'vf/vf.c',
+ 'vf/vf_generic.c',
+ 'vf/vf_sse.c',
+ ]
+
+ statetracker_sources = [
+ 'state_tracker/st_atom.c',
+ 'state_tracker/st_atom_blend.c',
+ 'state_tracker/st_atom_clip.c',
+ 'state_tracker/st_atom_constbuf.c',
+ 'state_tracker/st_atom_depth.c',
+ 'state_tracker/st_atom_framebuffer.c',
+ 'state_tracker/st_atom_pixeltransfer.c',
+ 'state_tracker/st_atom_sampler.c',
+ 'state_tracker/st_atom_scissor.c',
+ 'state_tracker/st_atom_shader.c',
+ 'state_tracker/st_atom_rasterizer.c',
+ 'state_tracker/st_atom_stipple.c',
+ 'state_tracker/st_atom_texture.c',
+ 'state_tracker/st_atom_viewport.c',
+ 'state_tracker/st_cb_accum.c',
+ 'state_tracker/st_cb_bitmap.c',
+ 'state_tracker/st_cb_blit.c',
+ 'state_tracker/st_cb_bufferobjects.c',
+ 'state_tracker/st_cb_clear.c',
+ 'state_tracker/st_cb_flush.c',
+ 'state_tracker/st_cb_drawpixels.c',
+ 'state_tracker/st_cb_fbo.c',
+ 'state_tracker/st_cb_get.c',
+ 'state_tracker/st_cb_feedback.c',
+ 'state_tracker/st_cb_program.c',
+ 'state_tracker/st_cb_queryobj.c',
+ 'state_tracker/st_cb_rasterpos.c',
+ 'state_tracker/st_cb_readpixels.c',
+ 'state_tracker/st_cb_strings.c',
+ 'state_tracker/st_cb_texture.c',
+ 'state_tracker/st_context.c',
+ 'state_tracker/st_debug.c',
+ 'state_tracker/st_draw.c',
+ 'state_tracker/st_draw_feedback.c',
+ 'state_tracker/st_extensions.c',
+ 'state_tracker/st_format.c',
+ 'state_tracker/st_framebuffer.c',
+ 'state_tracker/st_gen_mipmap.c',
+ 'state_tracker/st_mesa_to_tgsi.c',
+ 'state_tracker/st_program.c',
+ 'state_tracker/st_texture.c',
+ ]
+
+ shader_sources = [
+ 'shader/arbprogparse.c',
+ 'shader/arbprogram.c',
+ 'shader/atifragshader.c',
+ 'shader/grammar/grammar_mesa.c',
+ 'shader/nvfragparse.c',
+ 'shader/nvprogram.c',
+ 'shader/nvvertparse.c',
+ 'shader/program.c',
+ 'shader/prog_cache.c',
+ 'shader/prog_debug.c',
+ 'shader/prog_execute.c',
+ 'shader/prog_instruction.c',
+ 'shader/prog_noise.c',
+ 'shader/prog_parameter.c',
+ 'shader/prog_print.c',
+ 'shader/prog_statevars.c',
+ 'shader/prog_uniform.c',
+ 'shader/programopt.c',
+ 'shader/shader_api.c',
+ ]
+
+ slang_sources = [
+ 'shader/slang/slang_builtin.c',
+ 'shader/slang/slang_codegen.c',
+ 'shader/slang/slang_compile.c',
+ 'shader/slang/slang_compile_function.c',
+ 'shader/slang/slang_compile_operation.c',
+ 'shader/slang/slang_compile_struct.c',
+ 'shader/slang/slang_compile_variable.c',
+ 'shader/slang/slang_emit.c',
+ 'shader/slang/slang_ir.c',
+ 'shader/slang/slang_label.c',
+ 'shader/slang/slang_link.c',
+ 'shader/slang/slang_log.c',
+ 'shader/slang/slang_mem.c',
+ 'shader/slang/slang_preprocess.c',
+ 'shader/slang/slang_print.c',
+ 'shader/slang/slang_simplify.c',
+ 'shader/slang/slang_storage.c',
+ 'shader/slang/slang_typeinfo.c',
+ 'shader/slang/slang_vartable.c',
+ 'shader/slang/slang_utility.c',
+ ]
+
+ mesa_sources = (
+ main_sources +
+ math_sources +
+ vbo_sources +
+ vf_sources +
+ statetracker_sources +
+ shader_sources +
+ slang_sources
+ )
+
+ glapi_sources = [
+ 'main/dispatch.c',
+ 'glapi/glapi.c',
+ 'glapi/glapi_getproc.c',
+ 'glapi/glthread.c',
+ ]
+
+ #
+ # Assembly sources
+ #
+ if gcc and env['machine'] == 'x86':
+ env.Append(CPPDEFINES = [
+ 'USE_X86_ASM',
+ 'USE_MMX_ASM',
+ 'USE_3DNOW_ASM',
+ 'USE_SSE_ASM',
+ ])
+ mesa_sources += [
+ 'x86/common_x86.c',
+ 'x86/x86.c',
+ 'x86/3dnow.c',
+ 'x86/sse.c',
+ 'x86/common_x86_asm.S',
+ 'x86/x86_xform2.S',
+ 'x86/x86_xform3.S',
+ 'x86/x86_xform4.S',
+ 'x86/x86_cliptest.S',
+ 'x86/mmx_blend.S',
+ 'x86/3dnow_xform1.S',
+ 'x86/3dnow_xform2.S',
+ 'x86/3dnow_xform3.S',
+ 'x86/3dnow_xform4.S',
+ 'x86/3dnow_normal.S',
+ 'x86/sse_xform1.S',
+ 'x86/sse_xform2.S',
+ 'x86/sse_xform3.S',
+ 'x86/sse_xform4.S',
+ 'x86/sse_normal.S',
+ 'x86/read_rgba_span_x86.S',
+ ]
+ glapi_sources += [
+ 'x86/glapi_x86.S',
+ ]
+ elif gcc and env['machine'] == 'x86_64':
+ env.Append(CPPDEFINES = [
+ 'USE_X86_64_ASM',
+ ])
+ mesa_sources += [
+ 'x86-64/x86-64.c',
+ 'x86-64/xform4.S',
+ ]
+ glapi_sources += [
+ 'x86-64/glapi_x86-64.S'
+ ]
+ elif gcc and env['machine'] == 'ppc':
+ env.Append(CPPDEFINES = [
+ 'USE_PPC_ASM',
+ 'USE_VMX_ASM',
+ ])
+ mesa_sources += [
+ 'ppc/common_ppc.c',
+ ]
+ glapi_sources += [
+ ]
+ elif gcc and env['machine'] == 'sparc':
+ mesa_sources += [
+ 'sparc/sparc.c',
+ 'sparc/clip.S',
+ 'sparc/norm.S',
+ 'sparc/xform.S',
+ ]
+ glapi_sources += [
+ 'sparc/glapi_sparc.S'
+ ]
+ else:
+ pass
+
+ # Generate matypes.h
+ if gcc and env['machine'] in ('x86', 'x86_64'):
+ # See http://www.scons.org/wiki/UsingCodeGenerators
+ gen_matypes = env.Program(
+ target = 'gen_matypes',
+ source = 'x86/gen_matypes.c',
+ )
+ matypes = env.Command(
+ 'matypes.h',
+ gen_matypes,
+ gen_matypes[0].abspath + ' > $TARGET',
+ )
+ # Add the dir containing the generated header (somewhere inside the
+ # build dir) to the include path
+ env.Append(CPPPATH = [matypes[0].dir])
+
+ #
+ # Libraries
+ #
+
+ mesa = env.ConvenienceLibrary(
+ target = 'mesa',
+ source = mesa_sources,
+ )
+ Export('mesa')
+
+ if not dri:
+ glapi = env.ConvenienceLibrary(
+ target = 'glapi',
+ source = glapi_sources,
+ )
+ Export('glapi')
+
diff --git a/src/mesa/drivers/dri/Makefile.template b/src/mesa/drivers/dri/Makefile.template
index 2dc3664cc6a..2fa36bab3f9 100644
--- a/src/mesa/drivers/dri/Makefile.template
+++ b/src/mesa/drivers/dri/Makefile.template
@@ -2,13 +2,16 @@
MESA_MODULES = $(TOP)/src/mesa/libmesa.a
-COMMON_SOURCES = \
+COMMON_GALLIUM_SOURCES = \
../common/utils.c \
- ../common/texmem.c \
../common/vblank.c \
../common/dri_util.c \
- ../common/xmlconfig.c \
- ../common/drirenderbuffer.c
+ ../common/xmlconfig.c
+
+COMMON_SOURCES = $(COMMON_GALLIUM_SOURCES) \
+ ../../common/driverfuncs.c \
+ ../common/texmem.c \
+ ../common/drirenderbuffer.c
ifeq ($(WINDOW_SYSTEM),dri)
WINOBJ=
@@ -59,9 +62,9 @@ SHARED_INCLUDES = \
default: symlinks depend $(LIBNAME) $(TOP)/$(LIB_DIR)/$(LIBNAME)
-$(LIBNAME): $(OBJECTS) $(MESA_MODULES) $(WINOBJ) Makefile $(TOP)/src/mesa/drivers/dri/Makefile.template
+$(LIBNAME): $(OBJECTS) $(MESA_MODULES) $(PIPE_DRIVERS) $(WINOBJ) Makefile $(TOP)/src/mesa/drivers/dri/Makefile.template
$(MKLIB) -o $@ -noprefix -linker '$(CC)' -ldflags '$(LDFLAGS)' \
- $(OBJECTS) $(MESA_MODULES) $(WINOBJ) $(DRI_LIB_DEPS)
+ $(OBJECTS) $(PIPE_DRIVERS) $(MESA_MODULES) $(WINOBJ) $(DRI_LIB_DEPS)
$(TOP)/$(LIB_DIR)/$(LIBNAME): $(LIBNAME)
@@ -69,6 +72,7 @@ $(TOP)/$(LIB_DIR)/$(LIBNAME): $(LIBNAME)
depend: $(C_SOURCES) $(ASM_SOURCES) $(SYMLINKS)
+ rm -f depend
touch depend
$(MKDEP) $(MKDEP_OPTIONS) $(DRIVER_DEFINES) $(INCLUDES) $(C_SOURCES) \
$(ASM_SOURCES)
diff --git a/src/mesa/drivers/dri/common/dri_util.h b/src/mesa/drivers/dri/common/dri_util.h
index c6781f1c7ab..c95a5c8299a 100644
--- a/src/mesa/drivers/dri/common/dri_util.h
+++ b/src/mesa/drivers/dri/common/dri_util.h
@@ -1,25 +1,3 @@
-/* $XFree86: xc/lib/GL/dri/dri_util.h,v 1.1 2002/02/22 21:32:52 dawes Exp $ */
-/**
- * \file dri_util.h
- * DRI utility functions definitions.
- *
- * This module acts as glue between GLX and the actual hardware driver. A DRI
- * driver doesn't really \e have to use any of this - it's optional. But, some
- * useful stuff is done here that otherwise would have to be duplicated in most
- * drivers.
- *
- * Basically, these utility functions take care of some of the dirty details of
- * screen initialization, context creation, context binding, DRM setup, etc.
- *
- * These functions are compiled into each DRI driver so libGL.so knows nothing
- * about them.
- *
- * \sa dri_util.c.
- *
- * \author Kevin E. Martin <[email protected]>
- * \author Brian Paul <[email protected]>
- */
-
/*
* Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
* All Rights Reserved.
@@ -45,6 +23,26 @@
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
+/**
+ * \file dri_util.h
+ * DRI utility functions definitions.
+ *
+ * This module acts as glue between GLX and the actual hardware driver. A DRI
+ * driver doesn't really \e have to use any of this - it's optional. But, some
+ * useful stuff is done here that otherwise would have to be duplicated in most
+ * drivers.
+ *
+ * Basically, these utility functions take care of some of the dirty details of
+ * screen initialization, context creation, context binding, DRM setup, etc.
+ *
+ * These functions are compiled into each DRI driver so libGL.so knows nothing
+ * about them.
+ *
+ * \sa dri_util.c.
+ *
+ * \author Kevin E. Martin <[email protected]>
+ * \author Brian Paul <[email protected]>
+ */
#ifndef _DRI_UTIL_H_
#define _DRI_UTIL_H_
diff --git a/src/mesa/drivers/dri/common/drirenderbuffer.c b/src/mesa/drivers/dri/common/drirenderbuffer.c
index b99bf2033b2..15af99136cd 100644
--- a/src/mesa/drivers/dri/common/drirenderbuffer.c
+++ b/src/mesa/drivers/dri/common/drirenderbuffer.c
@@ -209,6 +209,8 @@ driUpdateFramebufferSize(GLcontext *ctx, const __DRIdrawablePrivate *dPriv)
struct gl_framebuffer *fb = (struct gl_framebuffer *) dPriv->driverPrivate;
if (fb && (dPriv->w != fb->Width || dPriv->h != fb->Height)) {
ctx->Driver.ResizeBuffers(ctx, fb, dPriv->w, dPriv->h);
+ /* if the driver needs the hw lock for ResizeBuffers, the drawable
+ might have changed again by now */
assert(fb->Width == dPriv->w);
assert(fb->Height == dPriv->h);
}
diff --git a/src/mesa/drivers/dri/common/utils.c b/src/mesa/drivers/dri/common/utils.c
index d6de1c0e9bb..5175ab0abbf 100644
--- a/src/mesa/drivers/dri/common/utils.c
+++ b/src/mesa/drivers/dri/common/utils.c
@@ -320,8 +320,10 @@ void driInitSingleExtension( GLcontext * ctx,
*/
offset = _glapi_add_dispatch( functions, parameter_signature );
if (offset == -1) {
+#if 0 /* this causes noise with egl */
fprintf(stderr, "DISPATCH ERROR! _glapi_add_dispatch failed "
"to add %s!\n", functions[0]);
+#endif
}
else if (ext->functions[i].remap_index != -1) {
driDispatchRemapTable[ ext->functions[i].remap_index ] =
@@ -514,6 +516,9 @@ GLboolean driClipRectToFramebuffer( const GLframebuffer *buffer,
* \c GLX_SWAP_UNDEFINED_OML. See the
* GLX_OML_swap_method extension spec for more details.
* \param num_db_modes Number of entries in \c db_modes.
+ * \param msaa_samples Array of msaa sample count. 0 represents a visual
+ * without a multisample buffer.
+ * \param num_msaa_modes Number of entries in \c msaa_samples.
* \param visType GLX visual type. Usually either \c GLX_TRUE_COLOR or
* \c GLX_DIRECT_COLOR.
*
@@ -533,7 +538,8 @@ __DRIconfig **
driCreateConfigs(GLenum fb_format, GLenum fb_type,
const uint8_t * depth_bits, const uint8_t * stencil_bits,
unsigned num_depth_stencil_bits,
- const GLenum * db_modes, unsigned num_db_modes)
+ const GLenum * db_modes, unsigned num_db_modes,
+ const u_int8_t * msaa_samples, unsigned num_msaa_modes)
{
static const uint8_t bits_table[4][4] = {
/* R G B A */
@@ -593,9 +599,7 @@ driCreateConfigs(GLenum fb_format, GLenum fb_type,
int index;
__DRIconfig **configs, **c;
__GLcontextModes *modes;
- unsigned i;
- unsigned j;
- unsigned k;
+ unsigned i, j, k, h;
unsigned num_modes;
unsigned num_accum_bits = 2;
@@ -668,7 +672,7 @@ driCreateConfigs(GLenum fb_format, GLenum fb_type,
break;
}
- num_modes = num_depth_stencil_bits * num_db_modes * num_accum_bits;
+ num_modes = num_depth_stencil_bits * num_db_modes * num_accum_bits * num_msaa_modes;
configs = _mesa_calloc((num_modes + 1) * sizeof *configs);
if (configs == NULL)
return NULL;
@@ -676,66 +680,72 @@ driCreateConfigs(GLenum fb_format, GLenum fb_type,
c = configs;
for ( k = 0 ; k < num_depth_stencil_bits ; k++ ) {
for ( i = 0 ; i < num_db_modes ; i++ ) {
- for ( j = 0 ; j < num_accum_bits ; j++ ) {
- *c = _mesa_malloc (sizeof **c);
- modes = &(*c)->modes;
- c++;
-
- memset(modes, 0, sizeof *modes);
- modes->redBits = bits[0];
- modes->greenBits = bits[1];
- modes->blueBits = bits[2];
- modes->alphaBits = bits[3];
- modes->redMask = masks[0];
- modes->greenMask = masks[1];
- modes->blueMask = masks[2];
- modes->alphaMask = masks[3];
- modes->rgbBits = modes->redBits + modes->greenBits
- + modes->blueBits + modes->alphaBits;
-
- modes->accumRedBits = 16 * j;
- modes->accumGreenBits = 16 * j;
- modes->accumBlueBits = 16 * j;
- modes->accumAlphaBits = (masks[3] != 0) ? 16 * j : 0;
- modes->visualRating = (j == 0) ? GLX_NONE : GLX_SLOW_CONFIG;
-
- modes->stencilBits = stencil_bits[k];
- modes->depthBits = depth_bits[k];
-
- modes->transparentPixel = GLX_NONE;
- modes->transparentRed = GLX_DONT_CARE;
- modes->transparentGreen = GLX_DONT_CARE;
- modes->transparentBlue = GLX_DONT_CARE;
- modes->transparentAlpha = GLX_DONT_CARE;
- modes->transparentIndex = GLX_DONT_CARE;
- modes->visualType = GLX_DONT_CARE;
- modes->renderType = GLX_RGBA_BIT;
- modes->drawableType = GLX_WINDOW_BIT;
- modes->rgbMode = GL_TRUE;
-
- if ( db_modes[i] == GLX_NONE ) {
- modes->doubleBufferMode = GL_FALSE;
- }
- else {
- modes->doubleBufferMode = GL_TRUE;
- modes->swapMethod = db_modes[i];
- }
-
- modes->haveAccumBuffer = ((modes->accumRedBits +
+ for ( h = 0 ; h < num_msaa_modes; h++ ) {
+ for ( j = 0 ; j < num_accum_bits ; j++ ) {
+ *c = _mesa_malloc (sizeof **c);
+ modes = &(*c)->modes;
+ c++;
+
+ memset(modes, 0, sizeof *modes);
+ modes->redBits = bits[0];
+ modes->greenBits = bits[1];
+ modes->blueBits = bits[2];
+ modes->alphaBits = bits[3];
+ modes->redMask = masks[0];
+ modes->greenMask = masks[1];
+ modes->blueMask = masks[2];
+ modes->alphaMask = masks[3];
+ modes->rgbBits = modes->redBits + modes->greenBits
+ + modes->blueBits + modes->alphaBits;
+
+ modes->accumRedBits = 16 * j;
+ modes->accumGreenBits = 16 * j;
+ modes->accumBlueBits = 16 * j;
+ modes->accumAlphaBits = (masks[3] != 0) ? 16 * j : 0;
+ modes->visualRating = (j == 0) ? GLX_NONE : GLX_SLOW_CONFIG;
+
+ modes->stencilBits = stencil_bits[k];
+ modes->depthBits = depth_bits[k];
+
+ modes->transparentPixel = GLX_NONE;
+ modes->transparentRed = GLX_DONT_CARE;
+ modes->transparentGreen = GLX_DONT_CARE;
+ modes->transparentBlue = GLX_DONT_CARE;
+ modes->transparentAlpha = GLX_DONT_CARE;
+ modes->transparentIndex = GLX_DONT_CARE;
+ modes->visualType = GLX_DONT_CARE;
+ modes->renderType = GLX_RGBA_BIT;
+ modes->drawableType = GLX_WINDOW_BIT;
+ modes->rgbMode = GL_TRUE;
+
+ if ( db_modes[i] == GLX_NONE ) {
+ modes->doubleBufferMode = GL_FALSE;
+ }
+ else {
+ modes->doubleBufferMode = GL_TRUE;
+ modes->swapMethod = db_modes[i];
+ }
+
+ modes->samples = msaa_samples[h];
+ modes->sampleBuffers = modes->samples ? 1 : 0;
+
+
+ modes->haveAccumBuffer = ((modes->accumRedBits +
modes->accumGreenBits +
modes->accumBlueBits +
modes->accumAlphaBits) > 0);
- modes->haveDepthBuffer = (modes->depthBits > 0);
- modes->haveStencilBuffer = (modes->stencilBits > 0);
-
- modes->bindToTextureRgb = GL_TRUE;
- modes->bindToTextureRgba = GL_TRUE;
- modes->bindToMipmapTexture = GL_FALSE;
- modes->bindToTextureTargets = modes->rgbMode ?
- __DRI_ATTRIB_TEXTURE_1D_BIT |
- __DRI_ATTRIB_TEXTURE_2D_BIT |
- __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT :
- 0;
+ modes->haveDepthBuffer = (modes->depthBits > 0);
+ modes->haveStencilBuffer = (modes->stencilBits > 0);
+
+ modes->bindToTextureRgb = GL_TRUE;
+ modes->bindToTextureRgba = GL_TRUE;
+ modes->bindToMipmapTexture = GL_FALSE;
+ modes->bindToTextureTargets = modes->rgbMode ?
+ __DRI_ATTRIB_TEXTURE_1D_BIT |
+ __DRI_ATTRIB_TEXTURE_2D_BIT |
+ __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT :
+ 0;
+ }
}
}
}
diff --git a/src/mesa/drivers/dri/common/utils.h b/src/mesa/drivers/dri/common/utils.h
index b0908e530a5..a4ef5092478 100644
--- a/src/mesa/drivers/dri/common/utils.h
+++ b/src/mesa/drivers/dri/common/utils.h
@@ -131,7 +131,8 @@ extern __DRIconfig **
driCreateConfigs(GLenum fb_format, GLenum fb_type,
const uint8_t * depth_bits, const uint8_t * stencil_bits,
unsigned num_depth_stencil_bits,
- const GLenum * db_modes, unsigned num_db_modes);
+ const GLenum * db_modes, unsigned num_db_modes,
+ const uint8_t * msaa_samples, unsigned num_msaa_modes);
const __DRIconfig **driConcatConfigs(const __DRIconfig **a,
const __DRIconfig **b);
diff --git a/src/mesa/drivers/dri/glcore/Makefile b/src/mesa/drivers/dri/glcore/Makefile
new file mode 100644
index 00000000000..ac7e1de9285
--- /dev/null
+++ b/src/mesa/drivers/dri/glcore/Makefile
@@ -0,0 +1,84 @@
+# src/mesa/drivers/dri/glcore/Makefile
+
+TOP = ../../../../..
+include $(TOP)/configs/current
+
+LIBNAME = glcore_dri.so
+
+DRIVER_SOURCES = glcore_driver.c \
+ $(TOP)/src/mesa/drivers/common/driverfuncs.c \
+ ../common/dri_util.c
+
+C_SOURCES = \
+ $(DRIVER_SOURCES) \
+ $(DRI_SOURCES)
+
+
+# Include directories
+INCLUDE_DIRS = \
+ -I. \
+ -I../common \
+ -I../dri_client \
+ -I../dri_client/imports \
+ -Iserver \
+ -I$(TOP)/include \
+ -I$(DRM_SOURCE_PATH)/shared-core \
+ -I$(TOP)/src/mesa \
+ -I$(TOP)/src/mesa/main \
+ -I$(TOP)/src/mesa/glapi \
+ -I$(TOP)/src/mesa/math \
+ -I$(TOP)/src/mesa/transform \
+ -I$(TOP)/src/mesa/shader \
+ -I$(TOP)/src/mesa/swrast \
+ -I$(TOP)/src/mesa/swrast_setup
+
+# Core Mesa objects
+MESA_MODULES = $(TOP)/src/mesa/libmesa.a
+
+# Libraries that the driver shared lib depends on
+LIB_DEPS = -lm -lpthread -lc
+# LIB_DEPS = -lGL -lm -lpthread -lc
+
+
+ASM_SOURCES =
+
+OBJECTS = $(C_SOURCES:.c=.o) \
+ $(ASM_SOURCES:.S=.o)
+
+
+##### RULES #####
+
+.c.o:
+ $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $(DEFINES) $< -o $@
+
+.S.o:
+ $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $(DEFINES) $< -o $@
+
+
+##### TARGETS #####
+
+default: depend $(TOP)/$(LIB_DIR)/$(LIBNAME)
+
+
+$(TOP)/$(LIB_DIR)/$(LIBNAME): $(OBJECTS) $(MESA_MODULES) $(WINOBJ) Makefile
+ CC="$(CC)" CXX="$(CXX)" $(TOP)/bin/mklib -o $(LIBNAME) -noprefix -install $(TOP)/$(LIB_DIR) \
+ $(OBJECTS) $(WINLIB) $(LIB_DEPS) $(WINOBJ) $(MESA_MODULES)
+
+
+depend: $(C_SOURCES) $(ASM_SOURCES)
+ rm -f depend
+ touch depend
+ $(MKDEP) $(MKDEP_OPTIONS) $(INCLUDE_DIRS) $(C_SOURCES) $(ASM_SOURCES) \
+ > /dev/null
+
+
+# Emacs tags
+tags:
+ etags `find . -name \*.[ch]` `find ../include`
+
+
+clean:
+ -rm -f *.o server/*.o
+
+
+include depend
diff --git a/src/mesa/glapi/descrip.mms b/src/mesa/glapi/descrip.mms
deleted file mode 100644
index ee96baa6fcc..00000000000
--- a/src/mesa/glapi/descrip.mms
+++ /dev/null
@@ -1,39 +0,0 @@
-# Makefile for core library for VMS
-# contributed by Jouk Jansen [email protected]
-# Last revision : 29 September 2008
-
-.first
- define gl [---.include.gl]
- define main [-.main]
-
-.include [---]mms-config.
-
-##### MACROS #####
-
-VPATH = RCS
-
-INCDIR = [---.include],[-.main]
-LIBDIR = [---.lib]
-CFLAGS = /include=($(INCDIR),[])/define=(PTHREADS=1)/name=(as_is,short)/float=ieee/ieee=denorm
-
-SOURCES = glapi.c glthread.c glapi_getproc.c
-
-OBJECTS = glapi.obj,glthread.obj,glapi_getproc.obj
-
-##### RULES #####
-
-VERSION=Mesa V3.4
-
-##### TARGETS #####
-# Make the library
-$(LIBDIR)$(GL_LIB) : $(OBJECTS)
- @ library $(LIBDIR)$(GL_LIB) $(OBJECTS)
-
-clean :
- purge
- delete *.obj;*
-
-glapi.obj : glapi.c
-
-glthread.obj : glthread.c
-glapi_getproc.obj : glapi_getproc.c
diff --git a/src/mesa/glapi/glapi.c b/src/mesa/glapi/glapi.c
index c3ebf60719f..9b5144a88b6 100644
--- a/src/mesa/glapi/glapi.c
+++ b/src/mesa/glapi/glapi.c
@@ -98,6 +98,7 @@ _glapi_set_warning_func( _glapi_warning_func func )
static GLboolean
warn(void)
{
+#if !defined(_WIN32_WCE)
if ((WarnFlag || getenv("MESA_DEBUG") || getenv("LIBGL_DEBUG"))
&& warning_func) {
return GL_TRUE;
@@ -105,6 +106,9 @@ warn(void)
else {
return GL_FALSE;
}
+#else
+ return GL_FALSE;
+#endif
}
diff --git a/src/mesa/glapi/glthread.c b/src/mesa/glapi/glthread.c
index b818f4e26eb..56ddf7c25ac 100644
--- a/src/mesa/glapi/glthread.c
+++ b/src/mesa/glapi/glthread.c
@@ -25,16 +25,14 @@
/*
* XXX There's probably some work to do in order to make this file
- * truly reusable outside of Mesa.
+ * truly reusable outside of Mesa. First, the glheader.h include must go.
*/
-
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
-#include <stdlib.h>
-#include <stdio.h>
+#include "main/glheader.h"
#include "glthread.h"
diff --git a/src/mesa/glapi/glthread.h b/src/mesa/glapi/glthread.h
index 27ccd2e2e7b..ae2f79f37dd 100644
--- a/src/mesa/glapi/glthread.h
+++ b/src/mesa/glapi/glthread.h
@@ -116,9 +116,49 @@ typedef pthread_mutex_t _glthread_Mutex;
#define _glthread_UNLOCK_MUTEX(name) \
(void) pthread_mutex_unlock(&(name))
-#endif /* PTHREADS */
+typedef pthread_cond_t _glthread_Cond;
+#define _glthread_DECLARE_STATIC_COND(name) \
+ static _glthread_Cond name = PTHREAD_COND_INITIALIZER
+#define _glthread_INIT_COND(cond) \
+ pthread_cond_init(&(cond), NULL)
+
+#define _glthread_DESTROY_COND(name) \
+ pthread_cond_destroy(&(name))
+
+#define _glthread_COND_WAIT(cond, mutex) \
+ pthread_cond_wait(&(cond), &(mutex))
+
+#define _glthread_COND_SIGNAL(cond) \
+ pthread_cond_signal(&(cond))
+
+#define _glthread_COND_BROADCAST(cond) \
+ pthread_cond_broadcast(&(cond))
+
+
+#else /* PTHREADS */
+
+typedef unsigned int _glthread_Cond;
+#define _glthread_DECLARE_STATIC_COND(name) \
+// #warning Condition variables not implemented.
+
+#define _glthread_INIT_COND(cond) \
+ ASSERT(0);
+
+#define _glthread_DESTROY_COND(name) \
+ ASSERT(0);
+
+#define _glthread_COND_WAIT(cond, mutex) \
+ ASSERT(0);
+
+#define _glthread_COND_SIGNAL(cond) \
+ ASSERT(0);
+
+#define _glthread_COND_BROADCAST(cond) \
+ ASSERT(0);
+
+#endif
/*
@@ -259,11 +299,11 @@ typedef benaphore _glthread_Mutex;
* THREADS not defined
*/
-typedef int _glthread_TSD;
+typedef GLuint _glthread_TSD;
-typedef int _glthread_Thread;
+typedef GLuint _glthread_Thread;
-typedef int _glthread_Mutex;
+typedef GLuint _glthread_Mutex;
#define _glthread_DECLARE_STATIC_MUTEX(name) static _glthread_Mutex name = 0
diff --git a/src/mesa/main/api_validate.c b/src/mesa/main/api_validate.c
index 59c2debb229..5c8955d7c8d 100644
--- a/src/mesa/main/api_validate.c
+++ b/src/mesa/main/api_validate.c
@@ -133,6 +133,12 @@ _mesa_validate_DrawElements(GLcontext *ctx,
/* use indices in the buffer object */
GLuint indexBytes;
+ if (!ctx->Array.ElementArrayBufferObj->Size) {
+ _mesa_warning(ctx,
+ "glDrawElements called with empty array elements buffer");
+ return GL_FALSE;
+ }
+
if (type == GL_UNSIGNED_INT) {
indexBytes = count * sizeof(GLuint);
}
diff --git a/src/mesa/main/bufferobj.c b/src/mesa/main/bufferobj.c
index 59fe8e25def..016543da01f 100644
--- a/src/mesa/main/bufferobj.c
+++ b/src/mesa/main/bufferobj.c
@@ -38,6 +38,13 @@
#include "bufferobj.h"
+#ifdef FEATURE_OES_mapbuffer
+#define DEFAULT_ACCESS GL_WRITE_ONLY;
+#else
+#define DEFAULT_ACCESS GL_READ_WRITE;
+#endif
+
+
/**
* Get the buffer object bound to the specified target in a GL context.
*
@@ -255,7 +262,7 @@ _mesa_initialize_buffer_object( struct gl_buffer_object *obj,
obj->RefCount = 1;
obj->Name = name;
obj->Usage = GL_STATIC_DRAW_ARB;
- obj->Access = GL_READ_WRITE_ARB;
+ obj->Access = DEFAULT_ACCESS;
}
@@ -664,8 +671,8 @@ _mesa_map_drawpix_pbo(GLcontext *ctx,
* \sa _mesa_unmap_bitmap_pbo
*/
void
-_mesa_unmap_drapix_pbo(GLcontext *ctx,
- const struct gl_pixelstore_attrib *unpack)
+_mesa_unmap_drawpix_pbo(GLcontext *ctx,
+ const struct gl_pixelstore_attrib *unpack)
{
if (unpack->BufferObj->Name) {
ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
@@ -1065,7 +1072,7 @@ _mesa_UnmapBufferARB(GLenum target)
status = ctx->Driver.UnmapBuffer( ctx, target, bufObj );
}
- bufObj->Access = GL_READ_WRITE_ARB; /* initial value, OK? */
+ bufObj->Access = DEFAULT_ACCESS;
bufObj->Pointer = NULL;
return status;
diff --git a/src/mesa/main/bufferobj.h b/src/mesa/main/bufferobj.h
index 163fe241aab..3c08f0083cf 100644
--- a/src/mesa/main/bufferobj.h
+++ b/src/mesa/main/bufferobj.h
@@ -103,9 +103,8 @@ _mesa_map_drawpix_pbo(GLcontext *ctx,
const GLvoid *pixels);
extern void
-_mesa_unmap_drapix_pbo(GLcontext *ctx,
- const struct gl_pixelstore_attrib *unpack);
-
+_mesa_unmap_drawpix_pbo(GLcontext *ctx,
+ const struct gl_pixelstore_attrib *unpack);
extern void *
_mesa_map_readpix_pbo(GLcontext *ctx,
diff --git a/src/mesa/main/buffers.c b/src/mesa/main/buffers.c
index 7877ee00451..818d068a12b 100644
--- a/src/mesa/main/buffers.c
+++ b/src/mesa/main/buffers.c
@@ -416,7 +416,7 @@ _mesa_drawbuffers(GLcontext *ctx, GLuint n, const GLenum *buffers,
}
}
- ctx->NewState |= _NEW_COLOR;
+ ctx->NewState |= _NEW_BUFFERS;
}
@@ -491,6 +491,7 @@ _mesa_ReadBuffer(GLenum buffer)
/* OK, all error checking has been completed now */
_mesa_readbuffer(ctx, buffer, srcBuffer);
+ ctx->NewState |= _NEW_BUFFERS;
/*
* Call device driver function.
diff --git a/src/mesa/main/config.h b/src/mesa/main/config.h
index cf1198cd0d5..c3feffda986 100644
--- a/src/mesa/main/config.h
+++ b/src/mesa/main/config.h
@@ -177,13 +177,11 @@
/** For GL_ARB_fragment_program */
/*@{*/
#define MAX_FRAGMENT_PROGRAM_ADDRESS_REGS 0
-#define MAX_FRAGMENT_PROGRAM_ALU_INSTRUCTIONS 48
-#define MAX_FRAGMENT_PROGRAM_TEX_INSTRUCTIONS 24
-#define MAX_FRAGMENT_PROGRAM_TEX_INDIRECTIONS 4
/*@}*/
/** For any program target/extension */
/*@{*/
+#define MAX_PROGRAM_INSTRUCTIONS (16 * 1024)
#define MAX_PROGRAM_LOCAL_PARAMS 256 /**< per-program constants (power of two) */
#define MAX_PROGRAM_ENV_PARAMS 128
#define MAX_PROGRAM_MATRICES 8
diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c
index 608942979f4..a315091a20d 100644
--- a/src/mesa/main/context.c
+++ b/src/mesa/main/context.c
@@ -145,9 +145,7 @@
#include "glapi/glthread.h"
#include "glapi/glapioffsets.h"
#include "glapi/glapitable.h"
-#if FEATURE_NV_vertex_program || FEATURE_NV_fragment_program
#include "shader/program.h"
-#endif
#include "shader/shader_api.h"
#if FEATURE_ATI_fragment_shader
#include "shader/atifragshader.h"
@@ -186,9 +184,11 @@ GLfloat _mesa_ubyte_to_float_color_tab[256];
* We have to finish any pending rendering.
*/
void
-_mesa_notifySwapBuffers(__GLcontext *gc)
+_mesa_notifySwapBuffers(__GLcontext *ctx)
{
- FLUSH_VERTICES( gc, 0 );
+ if (ctx->Driver.Flush) {
+ ctx->Driver.Flush(ctx);
+ }
}
@@ -611,6 +611,7 @@ delete_program_cb(GLuint id, void *data, void *userData)
ctx->Driver.DeleteProgram(ctx, prog);
}
+#if FEATURE_ATI_fragment_shader
/**
* Callback for deleting an ATI fragment shader object.
* Called by _mesa_HashDeleteAll().
@@ -622,6 +623,7 @@ delete_fragshader_cb(GLuint id, void *data, void *userData)
GLcontext *ctx = (GLcontext *) userData;
_mesa_delete_ati_fragment_shader(ctx, shader);
}
+#endif
/**
* Callback for deleting a buffer object. Called by _mesa_HashDeleteAll().
@@ -712,7 +714,6 @@ delete_renderbuffer_cb(GLuint id, void *data, void *userData)
}
-
/**
* Deallocate a shared state object and all children structures.
*
@@ -818,11 +819,33 @@ _mesa_init_current(GLcontext *ctx)
/**
- * Init vertex/fragment program native limits from logical limits.
+ * Init vertex/fragment program limits.
+ * Important: drivers should override these with actual limits.
*/
static void
-init_natives(struct gl_program_constants *prog)
+init_program_limits(GLenum type, struct gl_program_constants *prog)
{
+ prog->MaxInstructions = MAX_PROGRAM_INSTRUCTIONS;
+ prog->MaxAluInstructions = MAX_PROGRAM_INSTRUCTIONS;
+ prog->MaxTexInstructions = MAX_PROGRAM_INSTRUCTIONS;
+ prog->MaxTexIndirections = MAX_PROGRAM_INSTRUCTIONS;
+ prog->MaxTemps = MAX_PROGRAM_TEMPS;
+ prog->MaxEnvParams = MAX_PROGRAM_ENV_PARAMS;
+ prog->MaxLocalParams = MAX_PROGRAM_LOCAL_PARAMS;
+ prog->MaxUniformComponents = 4 * MAX_UNIFORMS;
+
+ if (type == GL_VERTEX_PROGRAM_ARB) {
+ prog->MaxParameters = MAX_NV_VERTEX_PROGRAM_PARAMS;
+ prog->MaxAttribs = MAX_NV_VERTEX_PROGRAM_INPUTS;
+ prog->MaxAddressRegs = MAX_VERTEX_PROGRAM_ADDRESS_REGS;
+ }
+ else {
+ prog->MaxParameters = MAX_NV_FRAGMENT_PROGRAM_PARAMS;
+ prog->MaxAttribs = MAX_NV_FRAGMENT_PROGRAM_INPUTS;
+ prog->MaxAddressRegs = MAX_FRAGMENT_PROGRAM_ADDRESS_REGS;
+ }
+
+ /* copy the above limits to init native limits */
prog->MaxNativeInstructions = prog->MaxInstructions;
prog->MaxNativeAluInstructions = prog->MaxAluInstructions;
prog->MaxNativeTexInstructions = prog->MaxTexInstructions;
@@ -881,33 +904,10 @@ _mesa_init_constants(GLcontext *ctx)
ctx->Const.MaxViewportWidth = MAX_WIDTH;
ctx->Const.MaxViewportHeight = MAX_HEIGHT;
#if FEATURE_ARB_vertex_program
- ctx->Const.VertexProgram.MaxInstructions = MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS;
- ctx->Const.VertexProgram.MaxAluInstructions = 0;
- ctx->Const.VertexProgram.MaxTexInstructions = 0;
- ctx->Const.VertexProgram.MaxTexIndirections = 0;
- ctx->Const.VertexProgram.MaxAttribs = MAX_NV_VERTEX_PROGRAM_INPUTS;
- ctx->Const.VertexProgram.MaxTemps = MAX_PROGRAM_TEMPS;
- ctx->Const.VertexProgram.MaxParameters = MAX_NV_VERTEX_PROGRAM_PARAMS;
- ctx->Const.VertexProgram.MaxLocalParams = MAX_PROGRAM_LOCAL_PARAMS;
- ctx->Const.VertexProgram.MaxEnvParams = MAX_PROGRAM_ENV_PARAMS;
- ctx->Const.VertexProgram.MaxAddressRegs = MAX_VERTEX_PROGRAM_ADDRESS_REGS;
- ctx->Const.VertexProgram.MaxUniformComponents = 4 * MAX_UNIFORMS;
- init_natives(&ctx->Const.VertexProgram);
+ init_program_limits(GL_VERTEX_PROGRAM_ARB, &ctx->Const.VertexProgram);
#endif
-
#if FEATURE_ARB_fragment_program
- ctx->Const.FragmentProgram.MaxInstructions = MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS;
- ctx->Const.FragmentProgram.MaxAluInstructions = MAX_FRAGMENT_PROGRAM_ALU_INSTRUCTIONS;
- ctx->Const.FragmentProgram.MaxTexInstructions = MAX_FRAGMENT_PROGRAM_TEX_INSTRUCTIONS;
- ctx->Const.FragmentProgram.MaxTexIndirections = MAX_FRAGMENT_PROGRAM_TEX_INDIRECTIONS;
- ctx->Const.FragmentProgram.MaxAttribs = MAX_NV_FRAGMENT_PROGRAM_INPUTS;
- ctx->Const.FragmentProgram.MaxTemps = MAX_PROGRAM_TEMPS;
- ctx->Const.FragmentProgram.MaxParameters = MAX_NV_FRAGMENT_PROGRAM_PARAMS;
- ctx->Const.FragmentProgram.MaxLocalParams = MAX_PROGRAM_LOCAL_PARAMS;
- ctx->Const.FragmentProgram.MaxEnvParams = MAX_PROGRAM_ENV_PARAMS;
- ctx->Const.FragmentProgram.MaxAddressRegs = MAX_FRAGMENT_PROGRAM_ADDRESS_REGS;
- ctx->Const.FragmentProgram.MaxUniformComponents = 4 * MAX_UNIFORMS;
- init_natives(&ctx->Const.FragmentProgram);
+ init_program_limits(GL_FRAGMENT_PROGRAM_ARB, &ctx->Const.FragmentProgram);
#endif
ctx->Const.MaxProgramMatrices = MAX_PROGRAM_MATRICES;
ctx->Const.MaxProgramMatrixStackDepth = MAX_PROGRAM_MATRIX_STACK_DEPTH;
@@ -1066,6 +1066,7 @@ init_attrib_groups(GLcontext *ctx)
/* Miscellaneous */
ctx->NewState = _NEW_ALL;
ctx->ErrorValue = (GLenum) GL_NO_ERROR;
+ ctx->varying_vp_inputs = ~0;
return GL_TRUE;
}
@@ -1165,7 +1166,7 @@ _mesa_initialize_context(GLcontext *ctx,
const struct dd_function_table *driverFunctions,
void *driverContext)
{
- ASSERT(driverContext);
+ /*ASSERT(driverContext);*/
assert(driverFunctions->NewTextureObject);
assert(driverFunctions->FreeTexImageData);
@@ -1269,7 +1270,7 @@ _mesa_create_context(const GLvisual *visual,
GLcontext *ctx;
ASSERT(visual);
- ASSERT(driverContext);
+ /*ASSERT(driverContext);*/
ctx = (GLcontext *) _mesa_calloc(sizeof(GLcontext));
if (!ctx)
@@ -1317,7 +1318,9 @@ _mesa_free_context_data( GLcontext *ctx )
_mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, NULL);
_mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, NULL);
+#if FEATURE_attrib_stack
_mesa_free_attrib_data(ctx);
+#endif
_mesa_free_lighting_data( ctx );
#if FEATURE_evaluators
_mesa_free_eval_data( ctx );
@@ -1634,7 +1637,22 @@ _mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer,
* or not bound to a user-created FBO.
*/
if (!newCtx->DrawBuffer || newCtx->DrawBuffer->Name == 0) {
+ /* KW: merge conflict here, revisit.
+ */
+ /* fix up the fb fields - these will end up wrong otherwise
+ * if the DRIdrawable changes, and everything relies on them.
+ * This is a bit messy (same as needed in _mesa_BindFramebufferEXT)
+ */
+ unsigned int i;
+ GLenum buffers[MAX_DRAW_BUFFERS];
+
_mesa_reference_framebuffer(&newCtx->DrawBuffer, drawBuffer);
+
+ for(i = 0; i < newCtx->Const.MaxDrawBuffers; i++) {
+ buffers[i] = newCtx->Color.DrawBuffer[i];
+ }
+
+ _mesa_drawbuffers(newCtx, newCtx->Const.MaxDrawBuffers, buffers, NULL);
}
if (!newCtx->ReadBuffer || newCtx->ReadBuffer->Name == 0) {
_mesa_reference_framebuffer(&newCtx->ReadBuffer, readBuffer);
diff --git a/src/mesa/main/dlopen.c b/src/mesa/main/dlopen.c
index becef8173ef..8bc83c094fd 100644
--- a/src/mesa/main/dlopen.c
+++ b/src/mesa/main/dlopen.c
@@ -48,7 +48,7 @@ _mesa_dlopen(const char *libname, int flags)
flags = RTLD_LAZY | RTLD_GLOBAL; /* Overriding flags at this time */
return dlopen(libname, flags);
#elif defined(__MINGW32__)
- return LoadLibrary(libname);
+ return LoadLibraryA(libname);
#else
return NULL;
#endif
diff --git a/src/mesa/main/drawpix.c b/src/mesa/main/drawpix.c
index ac97bc1ff9e..13cfa0e756e 100644
--- a/src/mesa/main/drawpix.c
+++ b/src/mesa/main/drawpix.c
@@ -153,7 +153,7 @@ _mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height,
return;
}
- if (!ctx->Current.RasterPosValid) {
+ if (!ctx->Current.RasterPosValid || width ==0 || height == 0) {
return;
}
@@ -218,7 +218,7 @@ _mesa_Bitmap( GLsizei width, GLsizei height,
if (ctx->RenderMode == GL_RENDER) {
/* Truncate, to satisfy conformance tests (matches SGI's OpenGL). */
- const GLfloat epsilon = (const GLfloat)0.0001;
+ const GLfloat epsilon = 0.0001F;
GLint x = IFLOOR(ctx->Current.RasterPos[0] + epsilon - xorig);
GLint y = IFLOOR(ctx->Current.RasterPos[1] + epsilon - yorig);
diff --git a/src/mesa/main/enable.c b/src/mesa/main/enable.c
index 1b034105356..2b54fac6949 100644
--- a/src/mesa/main/enable.c
+++ b/src/mesa/main/enable.c
@@ -951,6 +951,7 @@ _mesa_set_enable(GLcontext *ctx, GLenum cap, GLboolean state)
break;
/* GL_MESA_program_debug */
+#if FEATURE_MESA_program_debug
case GL_FRAGMENT_PROGRAM_CALLBACK_MESA:
CHECK_EXTENSION(MESA_program_debug, cap);
ctx->FragmentProgram.CallbackEnabled = state;
@@ -959,6 +960,7 @@ _mesa_set_enable(GLcontext *ctx, GLenum cap, GLboolean state)
CHECK_EXTENSION(MESA_program_debug, cap);
ctx->VertexProgram.CallbackEnabled = state;
break;
+#endif
#if FEATURE_ATI_fragment_shader
case GL_FRAGMENT_SHADER_ATI:
@@ -1403,12 +1405,15 @@ _mesa_IsEnabled( GLenum cap )
return ctx->Depth.BoundsTest;
/* GL_MESA_program_debug */
+#if FEATURE_MESA_program_debug
case GL_FRAGMENT_PROGRAM_CALLBACK_MESA:
CHECK_EXTENSION(MESA_program_debug);
return ctx->FragmentProgram.CallbackEnabled;
case GL_VERTEX_PROGRAM_CALLBACK_MESA:
CHECK_EXTENSION(MESA_program_debug);
return ctx->VertexProgram.CallbackEnabled;
+#endif
+
#if FEATURE_ATI_fragment_shader
case GL_FRAGMENT_SHADER_ATI:
CHECK_EXTENSION(ATI_fragment_shader);
diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c
index e38e72dbbe0..1b31e283cd3 100644
--- a/src/mesa/main/extensions.c
+++ b/src/mesa/main/extensions.c
@@ -87,7 +87,7 @@ static const struct {
{ OFF, "GL_EXT_blend_logic_op", F(EXT_blend_logic_op) },
{ OFF, "GL_EXT_blend_minmax", F(EXT_blend_minmax) },
{ OFF, "GL_EXT_blend_subtract", F(EXT_blend_subtract) },
- { ON, "GL_EXT_clip_volume_hint", F(EXT_clip_volume_hint) },
+ { OFF, "GL_EXT_clip_volume_hint", F(EXT_clip_volume_hint) },
{ OFF, "GL_EXT_cull_vertex", F(EXT_cull_vertex) },
{ ON, "GL_EXT_compiled_vertex_array", F(EXT_compiled_vertex_array) },
{ OFF, "GL_EXT_convolution", F(EXT_convolution) },
diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c
index d08ad339026..ae823262a28 100644
--- a/src/mesa/main/fbobject.c
+++ b/src/mesa/main/fbobject.c
@@ -193,7 +193,7 @@ _mesa_remove_attachment(GLcontext *ctx, struct gl_renderbuffer_attachment *att)
if (att->Type == GL_TEXTURE) {
ASSERT(att->Texture);
if (ctx->Driver.FinishRenderTexture) {
- /* tell driver we're done rendering to this texobj */
+ /* tell driver that we're done rendering to this texture. */
ctx->Driver.FinishRenderTexture(ctx, att);
}
_mesa_reference_texobj(&att->Texture, NULL); /* unbind */
diff --git a/src/mesa/main/ffvertex_prog.c b/src/mesa/main/ffvertex_prog.c
index cc1b44de642..d70b78f2586 100644
--- a/src/mesa/main/ffvertex_prog.c
+++ b/src/mesa/main/ffvertex_prog.c
@@ -47,17 +47,17 @@
struct state_key {
+ unsigned light_color_material_mask:12;
+ unsigned light_material_mask:12;
unsigned light_global_enabled:1;
unsigned light_local_viewer:1;
unsigned light_twoside:1;
unsigned light_color_material:1;
- unsigned light_color_material_mask:12;
- unsigned light_material_mask:12;
unsigned material_shininess_is_zero:1;
-
unsigned need_eye_coords:1;
unsigned normalize:1;
unsigned rescale_normals:1;
+
unsigned fog_source_is_depth:1;
unsigned tnl_do_vertex_fog:1;
unsigned separate_specular:1;
@@ -67,6 +67,8 @@ struct state_key {
unsigned texture_enabled_global:1;
unsigned fragprog_inputs_read:12;
+ unsigned varying_vp_inputs;
+
struct {
unsigned light_enabled:1;
unsigned light_eyepos3_is_zero:1;
@@ -194,6 +196,7 @@ static void make_state_key( GLcontext *ctx, struct state_key *key )
key->need_eye_coords = ctx->_NeedEyeCoords;
key->fragprog_inputs_read = fp->Base.InputsRead;
+ key->varying_vp_inputs = ctx->varying_vp_inputs;
if (ctx->RenderMode == GL_FEEDBACK) {
/* make sure the vertprog emits color and tex0 */
@@ -447,20 +450,52 @@ static void release_temp( struct tnl_program *p, struct ureg reg )
}
}
-
static void release_temps( struct tnl_program *p )
{
p->temp_in_use = p->temp_reserved;
}
+static struct ureg register_param5(struct tnl_program *p,
+ GLint s0,
+ GLint s1,
+ GLint s2,
+ GLint s3,
+ GLint s4)
+{
+ gl_state_index tokens[STATE_LENGTH];
+ GLint idx;
+ tokens[0] = s0;
+ tokens[1] = s1;
+ tokens[2] = s2;
+ tokens[3] = s3;
+ tokens[4] = s4;
+ idx = _mesa_add_state_reference( p->program->Base.Parameters, tokens );
+ return make_ureg(PROGRAM_STATE_VAR, idx);
+}
+
+
+#define register_param1(p,s0) register_param5(p,s0,0,0,0,0)
+#define register_param2(p,s0,s1) register_param5(p,s0,s1,0,0,0)
+#define register_param3(p,s0,s1,s2) register_param5(p,s0,s1,s2,0,0)
+#define register_param4(p,s0,s1,s2,s3) register_param5(p,s0,s1,s2,s3,0)
+
+
+
/**
* \param input one of VERT_ATTRIB_x tokens.
*/
static struct ureg register_input( struct tnl_program *p, GLuint input )
{
- p->program->Base.InputsRead |= (1<<input);
- return make_ureg(PROGRAM_INPUT, input);
+ /* Material attribs are passed here as inputs >= 32
+ */
+ if (input >= 32 || (p->state->varying_vp_inputs & (1<<input))) {
+ p->program->Base.InputsRead |= (1<<input);
+ return make_ureg(PROGRAM_INPUT, input);
+ }
+ else {
+ return register_param3( p, STATE_INTERNAL, STATE_CURRENT_ATTRIB, input );
+ }
}
@@ -493,7 +528,6 @@ static struct ureg register_const4f( struct tnl_program *p,
return make_ureg(PROGRAM_CONSTANT, idx);
}
-
#define register_const1f(p, s0) register_const4f(p, s0, 0, 0, 1)
#define register_scalar_const(p, s0) register_const4f(p, s0, s0, s0, s0)
#define register_const2f(p, s0, s1) register_const4f(p, s0, s1, 0, 1)
@@ -513,32 +547,6 @@ static struct ureg get_identity_param( struct tnl_program *p )
return p->identity;
}
-
-static struct ureg register_param5(struct tnl_program *p,
- GLint s0,
- GLint s1,
- GLint s2,
- GLint s3,
- GLint s4)
-{
- gl_state_index tokens[STATE_LENGTH];
- GLint idx;
- tokens[0] = s0;
- tokens[1] = s1;
- tokens[2] = s2;
- tokens[3] = s3;
- tokens[4] = s4;
- idx = _mesa_add_state_reference( p->program->Base.Parameters, tokens );
- return make_ureg(PROGRAM_STATE_VAR, idx);
-}
-
-
-#define register_param1(p,s0) register_param5(p,s0,0,0,0,0)
-#define register_param2(p,s0,s1) register_param5(p,s0,s1,0,0,0)
-#define register_param3(p,s0,s1,s2) register_param5(p,s0,s1,s2,0,0)
-#define register_param4(p,s0,s1,s2,s3) register_param5(p,s0,s1,s2,s3,0)
-
-
static void register_matrix_param5( struct tnl_program *p,
GLint s0, /* modelview, projection, etc */
GLint s1, /* texture matrix number */
diff --git a/src/mesa/main/glheader.h b/src/mesa/main/glheader.h
index 626806d35f6..5657976711e 100644
--- a/src/mesa/main/glheader.h
+++ b/src/mesa/main/glheader.h
@@ -64,22 +64,33 @@
#include <stdarg.h>
-/* Get typedefs for uintptr_t and friends */
-#if defined(__MINGW32__) || defined(__NetBSD__)
-# include <stdint.h>
-#elif defined(_WIN32)
-# include <BaseTsd.h>
-# if _MSC_VER == 1200
- typedef UINT_PTR uintptr_t;
-# endif
-#elif defined(__INTERIX)
-/* Interix 3.x has a gcc that shadows this. */
-# ifndef _UINTPTR_T_DEFINED
- typedef unsigned long uintptr_t;
-# define _UINTPTR_T_DEFINED
+/* Get standard integer types */
+#if defined(_MSC_VER)
+
+ typedef __int8 int8_t;
+ typedef unsigned __int8 uint8_t;
+ typedef __int16 int16_t;
+ typedef unsigned __int16 uint16_t;
+# ifndef __eglplatform_h_
+ typedef __int32 int32_t;
+# endif
+ typedef unsigned __int32 uint32_t;
+ typedef __int64 int64_t;
+ typedef unsigned __int64 uint64_t;
+
+# if defined(_WIN64)
+ typedef __int64 intptr_t;
+ typedef unsigned __int64 uintptr_t;
+# else
+ typedef __int32 intptr_t;
+ typedef unsigned __int32 uintptr_t;
# endif
+
+# define INT64_C(__val) __val##i64
+# define UINT64_C(__val) __val##ui64
+
#else
-# include <inttypes.h>
+# include <stdint.h>
#endif
diff --git a/src/mesa/main/imports.c b/src/mesa/main/imports.c
index 0c2c894eef0..cb04594c1fd 100644
--- a/src/mesa/main/imports.c
+++ b/src/mesa/main/imports.c
@@ -557,7 +557,7 @@ _mesa_pow(double x, double y)
* Find the first bit set in a word.
*/
int
-_mesa_ffs(int i)
+_mesa_ffs(int32_t i)
{
#if (defined(_WIN32) ) || defined(__IBMC__) || defined(__IBMCPP__)
register int bit = 0;
@@ -594,11 +594,7 @@ _mesa_ffs(int i)
* if no bits set.
*/
int
-#ifdef __MINGW32__
-_mesa_ffsll(long val)
-#else
-_mesa_ffsll(long long val)
-#endif
+_mesa_ffsll(int64_t val)
{
#ifdef ffsll
return ffsll(val);
@@ -607,11 +603,11 @@ _mesa_ffsll(long long val)
assert(sizeof(val) == 8);
- bit = _mesa_ffs(val);
+ bit = _mesa_ffs((int32_t)val);
if (bit != 0)
return bit;
- bit = _mesa_ffs(val >> 32);
+ bit = _mesa_ffs((int32_t)(val >> 32));
if (bit != 0)
return 32 + bit;
@@ -950,12 +946,10 @@ _mesa_snprintf( char *str, size_t size, const char *fmt, ... )
void
_mesa_printf( const char *fmtString, ... )
{
- char s[MAXSTRING];
va_list args;
va_start( args, fmtString );
- vsnprintf(s, MAXSTRING, fmtString, args);
+ vfprintf(stderr, fmtString, args);
va_end( args );
- fprintf(stderr, "%s", s);
}
/** Wrapper around fprintf(), using vsprintf() for the formatting. */
diff --git a/src/mesa/main/imports.h b/src/mesa/main/imports.h
index ec270a0cb30..a421eb5e755 100644
--- a/src/mesa/main/imports.h
+++ b/src/mesa/main/imports.h
@@ -708,14 +708,10 @@ extern double
_mesa_pow(double x, double y);
extern int
-_mesa_ffs(int i);
+_mesa_ffs(int32_t i);
extern int
-#ifdef __MINGW32__
-_mesa_ffsll(long i);
-#else
-_mesa_ffsll(long long i);
-#endif
+_mesa_ffsll(int64_t i);
extern unsigned int
_mesa_bitcount(unsigned int n);
diff --git a/src/mesa/main/light.c b/src/mesa/main/light.c
index ce50224d30a..a15c1f0be05 100644
--- a/src/mesa/main/light.c
+++ b/src/mesa/main/light.c
@@ -1368,6 +1368,7 @@ _mesa_init_lighting( GLcontext *ctx )
/* Miscellaneous */
ctx->Light._NeedEyeCoords = GL_FALSE;
ctx->_NeedEyeCoords = GL_FALSE;
+ ctx->_ForceEyeCoords = GL_FALSE;
ctx->_ModelViewInvScale = 1.0;
}
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 509da06d092..67f7d463098 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -125,6 +125,8 @@ struct gl_program_cache;
struct gl_texture_format;
struct gl_texture_image;
struct gl_texture_object;
+struct st_context;
+struct pipe_surface;
typedef struct __GLcontextRec GLcontext;
typedef struct __GLcontextModesRec GLvisual;
typedef struct gl_framebuffer GLframebuffer;
@@ -1579,7 +1581,6 @@ struct gl_texture_attrib
struct gl_texture_unit Unit[MAX_TEXTURE_UNITS];
- /** Proxy texture objects */
struct gl_texture_object *ProxyTex[NUM_TEXTURE_TARGETS];
/** GL_EXT_shared_texture_palette */
@@ -2003,6 +2004,8 @@ struct gl_vertex_program_state
GLboolean CallbackEnabled;
GLuint CurrentPosition;
#endif
+
+ GLboolean _Overriden;
};
@@ -2760,6 +2763,7 @@ struct gl_matrix_stack
#define _NEW_MULTISAMPLE 0x2000000 /**< __GLcontextRec::Multisample */
#define _NEW_TRACK_MATRIX 0x4000000 /**< __GLcontextRec::VertexProgram */
#define _NEW_PROGRAM 0x8000000 /**< __GLcontextRec::VertexProgram */
+#define _NEW_CURRENT_ATTRIB 0x10000000 /**< __GLcontextRec::Current */
#define _NEW_ALL ~0
/*@}*/
@@ -3088,6 +3092,8 @@ struct __GLcontextRec
GLenum RenderMode; /**< either GL_RENDER, GL_SELECT, GL_FEEDBACK */
GLbitfield NewState; /**< bitwise-or of _NEW_* flags */
+ 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
@@ -3133,7 +3139,7 @@ struct __GLcontextRec
void *swsetup_context;
void *swtnl_context;
void *swtnl_im;
- void *acache_context;
+ struct st_context *st;
void *aelt_context;
/*@}*/
};
diff --git a/src/mesa/main/renderbuffer.c b/src/mesa/main/renderbuffer.c
index 6047ebac4af..38be8266e05 100644
--- a/src/mesa/main/renderbuffer.c
+++ b/src/mesa/main/renderbuffer.c
@@ -1199,7 +1199,8 @@ _mesa_soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
if (width > 0 && height > 0) {
/* allocate new buffer storage */
- rb->Data = _mesa_malloc(width * height * pixelSize);
+ rb->Data = malloc(width * height * pixelSize);
+
if (rb->Data == NULL) {
rb->Width = 0;
rb->Height = 0;
diff --git a/src/mesa/main/sources b/src/mesa/main/sources
index 1b43e7e00f0..4e58702c746 100644
--- a/src/mesa/main/sources
+++ b/src/mesa/main/sources
@@ -79,7 +79,6 @@ vsnprintf.c
MESA_MAIN_HEADERS = \
accum.h \
api_arrayelt.h \
-api_eval.h \
api_exec.h \
api_loopback.h \
api_noop.h \
diff --git a/src/mesa/main/state.c b/src/mesa/main/state.c
index 6fe54c753f4..718cd998476 100644
--- a/src/mesa/main/state.c
+++ b/src/mesa/main/state.c
@@ -1,6 +1,6 @@
/*
* Mesa 3-D graphics library
- * Version: 7.1
+ * Version: 7.3
*
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
*
@@ -426,6 +426,9 @@ _mesa_update_state_locked( GLcontext *ctx )
GLbitfield new_state = ctx->NewState;
GLbitfield prog_flags = _NEW_PROGRAM;
+ if (new_state == _NEW_CURRENT_ATTRIB)
+ goto out;
+
if (MESA_VERBOSE & VERBOSE_STATE)
_mesa_print_state("_mesa_update_state", new_state);
@@ -435,7 +438,7 @@ _mesa_update_state_locked( GLcontext *ctx )
if (new_state & (_NEW_PROGRAM|_NEW_TEXTURE|_NEW_TEXTURE_MATRIX))
_mesa_update_texture( ctx, new_state );
- if (new_state & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL))
+ if (new_state & _NEW_BUFFERS)
_mesa_update_framebuffer(ctx);
if (new_state & (_NEW_SCISSOR | _NEW_BUFFERS | _NEW_VIEWPORT))
@@ -489,10 +492,13 @@ _mesa_update_state_locked( GLcontext *ctx )
_mesa_update_tnl_spaces( ctx, new_state );
if (ctx->FragmentProgram._MaintainTexEnvProgram) {
- prog_flags |= (_NEW_TEXTURE | _NEW_FOG | _DD_NEW_SEPARATE_SPECULAR);
+ prog_flags |= (_NEW_ARRAY | _NEW_TEXTURE_MATRIX | _NEW_LIGHT |
+ _NEW_RENDERMODE |
+ _NEW_TEXTURE | _NEW_FOG | _DD_NEW_SEPARATE_SPECULAR);
}
if (ctx->VertexProgram._MaintainTnlProgram) {
prog_flags |= (_NEW_ARRAY | _NEW_TEXTURE | _NEW_TEXTURE_MATRIX |
+ _NEW_RENDERMODE |
_NEW_TRANSFORM | _NEW_POINT |
_NEW_FOG | _NEW_LIGHT |
_MESA_NEW_NEED_EYE_COORDS);
@@ -511,6 +517,7 @@ _mesa_update_state_locked( GLcontext *ctx )
* Set ctx->NewState to zero to avoid recursion if
* Driver.UpdateState() has to call FLUSH_VERTICES(). (fixed?)
*/
+ out:
new_state = ctx->NewState;
ctx->NewState = 0;
ctx->Driver.UpdateState(ctx, new_state);
@@ -527,3 +534,59 @@ _mesa_update_state( GLcontext *ctx )
_mesa_update_state_locked(ctx);
_mesa_unlock_context_textures(ctx);
}
+
+
+
+
+/**
+ * Want to figure out which fragment program inputs are actually
+ * constant/current values from ctx->Current. These should be
+ * referenced as a tracked state variable rather than a fragment
+ * program input, to save the overhead of putting a constant value in
+ * every submitted vertex, transferring it to hardware, interpolating
+ * it across the triangle, etc...
+ *
+ * When there is a VP bound, just use vp->outputs. But when we're
+ * generating vp from fixed function state, basically want to
+ * calculate:
+ *
+ * vp_out_2_fp_in( vp_in_2_vp_out( varying_inputs ) |
+ * potential_vp_outputs )
+ *
+ * Where potential_vp_outputs is calculated by looking at enabled
+ * texgen, etc.
+ *
+ * The generated fragment program should then only declare inputs that
+ * may vary or otherwise differ from the ctx->Current values.
+ * Otherwise, the fp should track them as state values instead.
+ */
+void
+_mesa_set_varying_vp_inputs( GLcontext *ctx,
+ GLbitfield varying_inputs )
+{
+ if (ctx->varying_vp_inputs != varying_inputs) {
+ ctx->varying_vp_inputs = varying_inputs;
+ ctx->NewState |= _NEW_ARRAY;
+ /*_mesa_printf("%s %x\n", __FUNCTION__, varying_inputs);*/
+ }
+}
+
+
+/**
+ * Used by drivers to tell core Mesa that the driver is going to
+ * install/ use its own vertex program. In particular, this will
+ * prevent generated fragment programs from using state vars instead
+ * of ordinary varyings/inputs.
+ */
+void
+_mesa_set_vp_override(GLcontext *ctx, GLboolean flag)
+{
+ if (ctx->VertexProgram._Overriden != flag) {
+ ctx->VertexProgram._Overriden = flag;
+
+ /* Set one of the bits which will trigger fragment program
+ * regeneration:
+ */
+ ctx->NewState |= _NEW_ARRAY;
+ }
+}
diff --git a/src/mesa/main/state.h b/src/mesa/main/state.h
index bb7cb8f32a3..29db08a0b95 100644
--- a/src/mesa/main/state.h
+++ b/src/mesa/main/state.h
@@ -1,6 +1,6 @@
/*
* Mesa 3-D graphics library
- * Version: 7.1
+ * Version: 7.3
*
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
*
@@ -29,13 +29,21 @@
#include "mtypes.h"
extern void
-_mesa_update_state( GLcontext *ctx );
+_mesa_update_state(GLcontext *ctx);
/* As above but can only be called between _mesa_lock_context_textures() and
* _mesa_unlock_context_textures().
*/
extern void
-_mesa_update_state_locked( GLcontext *ctx );
+_mesa_update_state_locked(GLcontext *ctx);
+
+
+extern void
+_mesa_set_varying_vp_inputs(GLcontext *ctx, GLbitfield varying_inputs);
+
+
+extern void
+_mesa_set_vp_override(GLcontext *ctx, GLboolean flag);
#endif
diff --git a/src/mesa/main/texcompress.c b/src/mesa/main/texcompress.c
index 09eba151c06..c1b8c7675a2 100644
--- a/src/mesa/main/texcompress.c
+++ b/src/mesa/main/texcompress.c
@@ -3,6 +3,7 @@
* Version: 6.5.1
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ * Copyright (c) 2008 VMware, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -135,8 +136,10 @@ _mesa_compressed_texture_size( GLcontext *ctx,
ASSERT(depth == 1);
(void) depth;
+ (void) size;
switch (mesaFormat) {
+#if FEATURE_texture_fxt1
case MESA_FORMAT_RGB_FXT1:
case MESA_FORMAT_RGBA_FXT1:
/* round up width to next multiple of 8, height to next multiple of 4 */
@@ -148,8 +151,14 @@ _mesa_compressed_texture_size( GLcontext *ctx,
* take 16 bytes.
*/
return size;
+#endif
+#if FEATURE_texture_s3tc
case MESA_FORMAT_RGB_DXT1:
case MESA_FORMAT_RGBA_DXT1:
+#if FEATURE_EXT_texture_sRGB
+ case MESA_FORMAT_SRGB_DXT1:
+ case MESA_FORMAT_SRGBA_DXT1:
+#endif
/* round up width, height to next multiple of 4 */
width = (width + 3) & ~3;
height = (height + 3) & ~3;
@@ -161,6 +170,10 @@ _mesa_compressed_texture_size( GLcontext *ctx,
return size;
case MESA_FORMAT_RGBA_DXT3:
case MESA_FORMAT_RGBA_DXT5:
+#if FEATURE_EXT_texture_sRGB
+ case MESA_FORMAT_SRGBA_DXT3:
+ case MESA_FORMAT_SRGBA_DXT5:
+#endif
/* round up width, height to next multiple of 4 */
width = (width + 3) & ~3;
height = (height + 3) & ~3;
@@ -170,6 +183,7 @@ _mesa_compressed_texture_size( GLcontext *ctx,
* take 16 bytes.
*/
return size;
+#endif
default:
_mesa_problem(ctx, "bad mesaFormat in _mesa_compressed_texture_size");
return 0;
@@ -194,12 +208,15 @@ _mesa_compressed_texture_size_glenum(GLcontext *ctx,
GLuint mesaFormat;
switch (glformat) {
+#if FEATURE_texture_fxt1
case GL_COMPRESSED_RGB_FXT1_3DFX:
mesaFormat = MESA_FORMAT_RGB_FXT1;
break;
case GL_COMPRESSED_RGBA_FXT1_3DFX:
mesaFormat = MESA_FORMAT_RGBA_FXT1;
break;
+#endif
+#if FEATURE_texture_s3tc
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
case GL_RGB_S3TC:
mesaFormat = MESA_FORMAT_RGB_DXT1;
@@ -216,6 +233,21 @@ _mesa_compressed_texture_size_glenum(GLcontext *ctx,
case GL_RGBA4_S3TC:
mesaFormat = MESA_FORMAT_RGBA_DXT5;
break;
+#if FEATURE_EXT_texture_sRGB
+ case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+ mesaFormat = MESA_FORMAT_SRGB_DXT1;
+ break;
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+ mesaFormat = MESA_FORMAT_SRGBA_DXT1;
+ break;
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+ mesaFormat = MESA_FORMAT_SRGBA_DXT3;
+ break;
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+ mesaFormat = MESA_FORMAT_SRGBA_DXT5;
+ break;
+#endif
+#endif
default:
return 0;
}
@@ -237,18 +269,30 @@ _mesa_compressed_row_stride(GLuint mesaFormat, GLsizei width)
GLint stride;
switch (mesaFormat) {
+#if FEATURE_texture_fxt1
case MESA_FORMAT_RGB_FXT1:
case MESA_FORMAT_RGBA_FXT1:
stride = ((width + 7) / 8) * 16; /* 16 bytes per 8x4 tile */
break;
+#endif
+#if FEATURE_texture_s3tc
case MESA_FORMAT_RGB_DXT1:
case MESA_FORMAT_RGBA_DXT1:
+#if FEATURE_EXT_texture_sRGB
+ case MESA_FORMAT_SRGB_DXT1:
+ case MESA_FORMAT_SRGBA_DXT1:
+#endif
stride = ((width + 3) / 4) * 8; /* 8 bytes per 4x4 tile */
break;
case MESA_FORMAT_RGBA_DXT3:
case MESA_FORMAT_RGBA_DXT5:
+#if FEATURE_EXT_texture_sRGB
+ case MESA_FORMAT_SRGBA_DXT3:
+ case MESA_FORMAT_SRGBA_DXT5:
+#endif
stride = ((width + 3) / 4) * 16; /* 16 bytes per 4x4 tile */
break;
+#endif
default:
_mesa_problem(NULL, "bad mesaFormat in _mesa_compressed_row_stride");
return 0;
@@ -285,18 +329,30 @@ _mesa_compressed_image_address(GLint col, GLint row, GLint img,
*/
switch (mesaFormat) {
+#if FEATURE_texture_fxt1
case MESA_FORMAT_RGB_FXT1:
case MESA_FORMAT_RGBA_FXT1:
addr = (GLubyte *) image + 16 * (((width + 7) / 8) * (row / 4) + col / 8);
break;
+#endif
+#if FEATURE_texture_s3tc
case MESA_FORMAT_RGB_DXT1:
case MESA_FORMAT_RGBA_DXT1:
+#if FEATURE_EXT_texture_sRGB
+ case MESA_FORMAT_SRGB_DXT1:
+ case MESA_FORMAT_SRGBA_DXT1:
+#endif
addr = (GLubyte *) image + 8 * (((width + 3) / 4) * (row / 4) + col / 4);
break;
case MESA_FORMAT_RGBA_DXT3:
case MESA_FORMAT_RGBA_DXT5:
+#if FEATURE_EXT_texture_sRGB
+ case MESA_FORMAT_SRGBA_DXT3:
+ case MESA_FORMAT_SRGBA_DXT5:
+#endif
addr = (GLubyte *) image + 16 * (((width + 3) / 4) * (row / 4) + col / 4);
break;
+#endif
default:
_mesa_problem(NULL, "bad mesaFormat in _mesa_compressed_image_address");
addr = NULL;
diff --git a/src/mesa/main/texcompress_fxt1.c b/src/mesa/main/texcompress_fxt1.c
index 45f344b0c52..fc151605c9e 100644
--- a/src/mesa/main/texcompress_fxt1.c
+++ b/src/mesa/main/texcompress_fxt1.c
@@ -298,17 +298,17 @@ const struct gl_texture_format _mesa_texformat_rgba_fxt1 = {
/*
* Define a 64-bit unsigned integer type and macros
*/
-#ifdef GL_EXT_timer_query /* this extensions defines the GLuint64EXT type */
+#if 1
#define FX64_NATIVE 1
-typedef GLuint64EXT Fx64;
+typedef uint64_t Fx64;
#define FX64_MOV32(a, b) a = b
#define FX64_OR32(a, b) a |= b
#define FX64_SHL(a, c) a <<= c
-#else /* !GL_EXT_timer_query */
+#else
#define FX64_NATIVE 0
@@ -330,7 +330,7 @@ typedef struct {
} \
} while (0)
-#endif /* !GL_EXT_timer_query */
+#endif
#define F(i) (GLfloat)1 /* can be used to obtain an oblong metric: 0.30 / 0.59 / 0.11 */
diff --git a/src/mesa/main/texcompress_s3tc.c b/src/mesa/main/texcompress_s3tc.c
index a19c161b2c0..d17e18da6b5 100644
--- a/src/mesa/main/texcompress_s3tc.c
+++ b/src/mesa/main/texcompress_s3tc.c
@@ -3,6 +3,7 @@
* Version: 6.5.3
*
* Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
+ * Copyright (c) 2008 VMware, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -53,6 +54,34 @@
#define DXTN_LIBNAME "libtxc_dxtn.so"
#endif
+#if FEATURE_EXT_texture_sRGB
+/**
+ * Convert an 8-bit sRGB value from non-linear space to a
+ * linear RGB value in [0, 1].
+ * Implemented with a 256-entry lookup table.
+ */
+static INLINE GLfloat
+nonlinear_to_linear(GLubyte cs8)
+{
+ static GLfloat table[256];
+ static GLboolean tableReady = GL_FALSE;
+ if (!tableReady) {
+ /* compute lookup table now */
+ GLuint i;
+ for (i = 0; i < 256; i++) {
+ const GLfloat cs = UBYTE_TO_FLOAT(i);
+ if (cs <= 0.04045) {
+ table[i] = cs / 12.92f;
+ }
+ else {
+ table[i] = (GLfloat) _mesa_pow((cs + 0.055) / 1.055, 2.4);
+ }
+ }
+ tableReady = GL_TRUE;
+ }
+ return table[cs8];
+}
+#endif /* FEATURE_EXT_texture_sRGB */
typedef void (*dxtFetchTexelFuncExt)( GLint srcRowstride, GLubyte *pixdata, GLint col, GLint row, GLvoid *texelOut );
@@ -483,6 +512,59 @@ fetch_texel_2d_f_rgba_dxt5( const struct gl_texture_image *texImage,
texel[ACOMP] = CHAN_TO_FLOAT(rgba[ACOMP]);
}
+#if FEATURE_EXT_texture_sRGB
+static void
+fetch_texel_2d_f_srgb_dxt1( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ /* just sample as GLchan and convert to float here */
+ GLchan rgba[4];
+ fetch_texel_2d_rgb_dxt1(texImage, i, j, k, rgba);
+ texel[RCOMP] = nonlinear_to_linear(rgba[RCOMP]);
+ texel[GCOMP] = nonlinear_to_linear(rgba[GCOMP]);
+ texel[BCOMP] = nonlinear_to_linear(rgba[BCOMP]);
+ texel[ACOMP] = CHAN_TO_FLOAT(rgba[ACOMP]);
+}
+
+static void
+fetch_texel_2d_f_srgba_dxt1( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ /* just sample as GLchan and convert to float here */
+ GLchan rgba[4];
+ fetch_texel_2d_rgba_dxt1(texImage, i, j, k, rgba);
+ texel[RCOMP] = nonlinear_to_linear(rgba[RCOMP]);
+ texel[GCOMP] = nonlinear_to_linear(rgba[GCOMP]);
+ texel[BCOMP] = nonlinear_to_linear(rgba[BCOMP]);
+ texel[ACOMP] = CHAN_TO_FLOAT(rgba[ACOMP]);
+}
+
+static void
+fetch_texel_2d_f_srgba_dxt3( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ /* just sample as GLchan and convert to float here */
+ GLchan rgba[4];
+ fetch_texel_2d_rgba_dxt3(texImage, i, j, k, rgba);
+ texel[RCOMP] = nonlinear_to_linear(rgba[RCOMP]);
+ texel[GCOMP] = nonlinear_to_linear(rgba[GCOMP]);
+ texel[BCOMP] = nonlinear_to_linear(rgba[BCOMP]);
+ texel[ACOMP] = CHAN_TO_FLOAT(rgba[ACOMP]);
+}
+
+static void
+fetch_texel_2d_f_srgba_dxt5( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ /* just sample as GLchan and convert to float here */
+ GLchan rgba[4];
+ fetch_texel_2d_rgba_dxt5(texImage, i, j, k, rgba);
+ texel[RCOMP] = nonlinear_to_linear(rgba[RCOMP]);
+ texel[GCOMP] = nonlinear_to_linear(rgba[GCOMP]);
+ texel[BCOMP] = nonlinear_to_linear(rgba[BCOMP]);
+ texel[ACOMP] = CHAN_TO_FLOAT(rgba[ACOMP]);
+}
+#endif
const struct gl_texture_format _mesa_texformat_rgb_dxt1 = {
MESA_FORMAT_RGB_DXT1, /* MesaFormat */
@@ -508,6 +590,78 @@ const struct gl_texture_format _mesa_texformat_rgb_dxt1 = {
NULL /* StoreTexel */
};
+const struct gl_texture_format _mesa_texformat_rgba_dxt1 = {
+ MESA_FORMAT_RGBA_DXT1, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 4, /*approx*/ /* RedBits */
+ 4, /*approx*/ /* GreenBits */
+ 4, /*approx*/ /* BlueBits */
+ 1, /*approx*/ /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 0, /* TexelBytes */
+ texstore_rgba_dxt1, /* StoreTexImageFunc */
+ NULL, /*impossible*/ /* FetchTexel1D */
+ fetch_texel_2d_rgba_dxt1, /* FetchTexel2D */
+ NULL, /*impossible*/ /* FetchTexel3D */
+ NULL, /*impossible*/ /* FetchTexel1Df */
+ fetch_texel_2d_f_rgba_dxt1, /* FetchTexel2Df */
+ NULL, /*impossible*/ /* FetchTexel3Df */
+ NULL /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_rgba_dxt3 = {
+ MESA_FORMAT_RGBA_DXT3, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 4, /*approx*/ /* RedBits */
+ 4, /*approx*/ /* GreenBits */
+ 4, /*approx*/ /* BlueBits */
+ 4, /*approx*/ /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 0, /* TexelBytes */
+ texstore_rgba_dxt3, /* StoreTexImageFunc */
+ NULL, /*impossible*/ /* FetchTexel1D */
+ fetch_texel_2d_rgba_dxt3, /* FetchTexel2D */
+ NULL, /*impossible*/ /* FetchTexel3D */
+ NULL, /*impossible*/ /* FetchTexel1Df */
+ fetch_texel_2d_f_rgba_dxt3, /* FetchTexel2Df */
+ NULL, /*impossible*/ /* FetchTexel3Df */
+ NULL /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_rgba_dxt5 = {
+ MESA_FORMAT_RGBA_DXT5, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 4,/*approx*/ /* RedBits */
+ 4,/*approx*/ /* GreenBits */
+ 4,/*approx*/ /* BlueBits */
+ 4,/*approx*/ /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 0, /* TexelBytes */
+ texstore_rgba_dxt5, /* StoreTexImageFunc */
+ NULL, /*impossible*/ /* FetchTexel1D */
+ fetch_texel_2d_rgba_dxt5, /* FetchTexel2D */
+ NULL, /*impossible*/ /* FetchTexel3D */
+ NULL, /*impossible*/ /* FetchTexel1Df */
+ fetch_texel_2d_f_rgba_dxt5, /* FetchTexel2Df */
+ NULL, /*impossible*/ /* FetchTexel3Df */
+ NULL /* StoreTexel */
+};
+
#if FEATURE_EXT_texture_sRGB
const struct gl_texture_format _mesa_texformat_srgb_dxt1 = {
MESA_FORMAT_SRGB_DXT1, /* MesaFormat */
@@ -525,17 +679,16 @@ const struct gl_texture_format _mesa_texformat_srgb_dxt1 = {
0, /* TexelBytes */
texstore_rgb_dxt1, /* StoreTexImageFunc */
NULL, /*impossible*/ /* FetchTexel1D */
- fetch_texel_2d_rgb_dxt1, /* FetchTexel2D */
+ NULL, /* FetchTexel2D */
NULL, /*impossible*/ /* FetchTexel3D */
NULL, /*impossible*/ /* FetchTexel1Df */
- fetch_texel_2d_f_rgb_dxt1, /* FetchTexel2Df */
+ fetch_texel_2d_f_srgb_dxt1, /* FetchTexel2Df */
NULL, /*impossible*/ /* FetchTexel3Df */
NULL /* StoreTexel */
};
-#endif
-const struct gl_texture_format _mesa_texformat_rgba_dxt1 = {
- MESA_FORMAT_RGBA_DXT1, /* MesaFormat */
+const struct gl_texture_format _mesa_texformat_srgba_dxt1 = {
+ MESA_FORMAT_SRGBA_DXT1, /* MesaFormat */
GL_RGBA, /* BaseFormat */
GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
4, /*approx*/ /* RedBits */
@@ -550,16 +703,16 @@ const struct gl_texture_format _mesa_texformat_rgba_dxt1 = {
0, /* TexelBytes */
texstore_rgba_dxt1, /* StoreTexImageFunc */
NULL, /*impossible*/ /* FetchTexel1D */
- fetch_texel_2d_rgba_dxt1, /* FetchTexel2D */
+ NULL, /* FetchTexel2D */
NULL, /*impossible*/ /* FetchTexel3D */
NULL, /*impossible*/ /* FetchTexel1Df */
- fetch_texel_2d_f_rgba_dxt1, /* FetchTexel2Df */
+ fetch_texel_2d_f_srgba_dxt1, /* FetchTexel2Df */
NULL, /*impossible*/ /* FetchTexel3Df */
NULL /* StoreTexel */
};
-const struct gl_texture_format _mesa_texformat_rgba_dxt3 = {
- MESA_FORMAT_RGBA_DXT3, /* MesaFormat */
+const struct gl_texture_format _mesa_texformat_srgba_dxt3 = {
+ MESA_FORMAT_SRGBA_DXT3, /* MesaFormat */
GL_RGBA, /* BaseFormat */
GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
4, /*approx*/ /* RedBits */
@@ -574,16 +727,16 @@ const struct gl_texture_format _mesa_texformat_rgba_dxt3 = {
0, /* TexelBytes */
texstore_rgba_dxt3, /* StoreTexImageFunc */
NULL, /*impossible*/ /* FetchTexel1D */
- fetch_texel_2d_rgba_dxt3, /* FetchTexel2D */
+ NULL, /* FetchTexel2D */
NULL, /*impossible*/ /* FetchTexel3D */
NULL, /*impossible*/ /* FetchTexel1Df */
- fetch_texel_2d_f_rgba_dxt3, /* FetchTexel2Df */
+ fetch_texel_2d_f_srgba_dxt3, /* FetchTexel2Df */
NULL, /*impossible*/ /* FetchTexel3Df */
NULL /* StoreTexel */
};
-const struct gl_texture_format _mesa_texformat_rgba_dxt5 = {
- MESA_FORMAT_RGBA_DXT5, /* MesaFormat */
+const struct gl_texture_format _mesa_texformat_srgba_dxt5 = {
+ MESA_FORMAT_SRGBA_DXT5, /* MesaFormat */
GL_RGBA, /* BaseFormat */
GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
4,/*approx*/ /* RedBits */
@@ -598,10 +751,11 @@ const struct gl_texture_format _mesa_texformat_rgba_dxt5 = {
0, /* TexelBytes */
texstore_rgba_dxt5, /* StoreTexImageFunc */
NULL, /*impossible*/ /* FetchTexel1D */
- fetch_texel_2d_rgba_dxt5, /* FetchTexel2D */
+ NULL, /* FetchTexel2D */
NULL, /*impossible*/ /* FetchTexel3D */
NULL, /*impossible*/ /* FetchTexel1Df */
- fetch_texel_2d_f_rgba_dxt5, /* FetchTexel2Df */
+ fetch_texel_2d_f_srgba_dxt5, /* FetchTexel2Df */
NULL, /*impossible*/ /* FetchTexel3Df */
NULL /* StoreTexel */
};
+#endif
diff --git a/src/mesa/main/texenvprogram.c b/src/mesa/main/texenvprogram.c
index 066f3bd0bec..10edfc8fb80 100644
--- a/src/mesa/main/texenvprogram.c
+++ b/src/mesa/main/texenvprogram.c
@@ -67,11 +67,9 @@ struct texenvprog_cache_item
/**
- * This MAX is probably a bit generous, but that's OK. There can be
- * up to four instructions per texture unit (TEX + 3 for combine),
- * then there's fog and specular add.
+ * Up to nine instructions per tex unit, plus fog, specular color.
*/
-#define MAX_INSTRUCTIONS ((MAX_TEXTURE_COORD_UNITS * 4) + 12)
+#define MAX_INSTRUCTIONS ((MAX_TEXTURE_COORD_UNITS * 9) + 12)
#define DISASSEM (MESA_VERBOSE & VERBOSE_DISASSEM)
@@ -81,10 +79,12 @@ struct mode_opt {
};
struct state_key {
- GLbitfield enabled_units;
+ GLuint nr_enabled_units:8;
+ GLuint enabled_units:8;
GLuint separate_specular:1;
GLuint fog_enabled:1;
GLuint fog_mode:2;
+ GLuint inputs_available:12;
struct {
GLuint enabled:1;
@@ -232,6 +232,8 @@ static GLuint translate_mode( GLenum envMode, GLenum mode )
#define TEXTURE_UNKNOWN_INDEX 7
static GLuint translate_tex_src_bit( GLbitfield bit )
{
+ /* make sure number of switch cases is correct */
+ assert(NUM_TEXTURE_TARGETS == 7);
switch (bit) {
case TEXTURE_1D_BIT: return TEXTURE_1D_INDEX;
case TEXTURE_2D_BIT: return TEXTURE_2D_INDEX;
@@ -246,6 +248,102 @@ static GLuint translate_tex_src_bit( GLbitfield bit )
}
}
+#define VERT_BIT_TEX_ANY (0xff << VERT_ATTRIB_TEX0)
+#define VERT_RESULT_TEX_ANY (0xff << VERT_RESULT_TEX0)
+
+/**
+ * Identify all possible varying inputs. The fragment program will
+ * never reference non-varying inputs, but will track them via state
+ * constants instead.
+ *
+ * This function figures out all the inputs that the fragment program
+ * has access to. The bitmask is later reduced to just those which
+ * are actually referenced.
+ */
+static GLbitfield get_fp_input_mask( GLcontext *ctx )
+{
+ const GLboolean vertexShader = (ctx->Shader.CurrentProgram &&
+ ctx->Shader.CurrentProgram->VertexProgram);
+ const GLboolean vertexProgram = ctx->VertexProgram._Enabled;
+ GLbitfield fp_inputs = 0x0;
+
+ if (ctx->VertexProgram._Overriden) {
+ /* Somebody's messing with the vertex program and we don't have
+ * a clue what's happening. Assume that it could be producing
+ * all possible outputs.
+ */
+ fp_inputs = ~0;
+ }
+ else if (ctx->RenderMode == GL_FEEDBACK) {
+ fp_inputs = (FRAG_BIT_COL0 | FRAG_BIT_TEX0);
+ }
+ else if (!(vertexProgram || vertexShader) ||
+ !ctx->VertexProgram._Current) {
+ /* Fixed function vertex logic */
+ GLbitfield varying_inputs = ctx->varying_vp_inputs;
+
+ /* These get generated in the setup routine regardless of the
+ * vertex program:
+ */
+ if (ctx->Point.PointSprite)
+ varying_inputs |= FRAG_BITS_TEX_ANY;
+
+ /* First look at what values may be computed by the generated
+ * vertex program:
+ */
+ if (ctx->Light.Enabled) {
+ fp_inputs |= FRAG_BIT_COL0;
+
+ if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)
+ fp_inputs |= FRAG_BIT_COL1;
+ }
+
+ fp_inputs |= (ctx->Texture._TexGenEnabled |
+ ctx->Texture._TexMatEnabled) << FRAG_ATTRIB_TEX0;
+
+ /* Then look at what might be varying as a result of enabled
+ * arrays, etc:
+ */
+ if (varying_inputs & VERT_BIT_COLOR0) fp_inputs |= FRAG_BIT_COL0;
+ if (varying_inputs & VERT_BIT_COLOR1) fp_inputs |= FRAG_BIT_COL1;
+
+ fp_inputs |= (((varying_inputs & VERT_BIT_TEX_ANY) >> VERT_ATTRIB_TEX0)
+ << FRAG_ATTRIB_TEX0);
+
+ }
+ else {
+ /* calculate from vp->outputs */
+ struct gl_vertex_program *vprog;
+ GLbitfield vp_outputs;
+
+ /* Choose GLSL vertex shader over ARB vertex program. Need this
+ * since vertex shader state validation comes after fragment state
+ * validation (see additional comments in state.c).
+ */
+ if (vertexShader)
+ vprog = ctx->Shader.CurrentProgram->VertexProgram;
+ else
+ vprog = ctx->VertexProgram._Current;
+
+ vp_outputs = vprog->Base.OutputsWritten;
+
+ /* These get generated in the setup routine regardless of the
+ * vertex program:
+ */
+ if (ctx->Point.PointSprite)
+ vp_outputs |= FRAG_BITS_TEX_ANY;
+
+ if (vp_outputs & (1 << VERT_RESULT_COL0)) fp_inputs |= FRAG_BIT_COL0;
+ if (vp_outputs & (1 << VERT_RESULT_COL1)) fp_inputs |= FRAG_BIT_COL1;
+
+ fp_inputs |= (((vp_outputs & VERT_RESULT_TEX_ANY) >> VERT_RESULT_TEX0)
+ << FRAG_ATTRIB_TEX0);
+ }
+
+ return fp_inputs;
+}
+
+
/**
* Examine current texture environment state and generate a unique
* key to identify it.
@@ -253,7 +351,9 @@ static GLuint translate_tex_src_bit( GLbitfield bit )
static void make_state_key( GLcontext *ctx, struct state_key *key )
{
GLuint i, j;
-
+ GLbitfield inputs_referenced = FRAG_BIT_COL0;
+ GLbitfield inputs_available = get_fp_input_mask( ctx );
+
memset(key, 0, sizeof(*key));
for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
@@ -267,6 +367,8 @@ static void make_state_key( GLcontext *ctx, struct state_key *key )
key->unit[i].enabled = 1;
key->enabled_units |= (1<<i);
+ key->nr_enabled_units = i+1;
+ inputs_referenced |= FRAG_BIT_TEX(i);
key->unit[i].source_index =
translate_tex_src_bit(texUnit->_ReallyEnabled);
@@ -297,16 +399,22 @@ static void make_state_key( GLcontext *ctx, struct state_key *key )
}
}
- if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)
+ if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) {
key->separate_specular = 1;
+ inputs_referenced |= FRAG_BIT_COL1;
+ }
if (ctx->Fog.Enabled) {
key->fog_enabled = 1;
key->fog_mode = translate_fog_mode(ctx->Fog.Mode);
+ inputs_referenced |= FRAG_BIT_FOGC; /* maybe */
}
+
+ key->inputs_available = (inputs_available & inputs_referenced);
}
-/* Use uregs to represent registers internally, translate to Mesa's
+/**
+ * Use uregs to represent registers internally, translate to Mesa's
* expected formats on emit.
*
* NOTE: These are passed by value extensively in this file rather
@@ -339,16 +447,16 @@ static const struct ureg undef = {
};
-/* State used to build the fragment program:
+/** State used to build the fragment program:
*/
struct texenv_fragment_program {
struct gl_fragment_program *program;
GLcontext *ctx;
struct state_key *state;
- GLbitfield alu_temps; /* Track texture indirections, see spec. */
- GLbitfield temps_output; /* Track texture indirections, see spec. */
- GLbitfield temp_in_use; /* Tracks temporary regs which are in use. */
+ GLbitfield alu_temps; /**< Track texture indirections, see spec. */
+ GLbitfield temps_output; /**< Track texture indirections, see spec. */
+ GLbitfield temp_in_use; /**< Tracks temporary regs which are in use. */
GLboolean error;
struct ureg src_texture[MAX_TEXTURE_COORD_UNITS];
@@ -356,11 +464,11 @@ struct texenv_fragment_program {
* else undef.
*/
- struct ureg src_previous; /* Reg containing color from previous
+ struct ureg src_previous; /**< Reg containing color from previous
* stage. May need to be decl'd.
*/
- GLuint last_tex_stage; /* Number of last enabled texture unit */
+ GLuint last_tex_stage; /**< Number of last enabled texture unit */
struct ureg half;
struct ureg one;
@@ -438,7 +546,7 @@ static struct ureg get_tex_temp( struct texenv_fragment_program *p )
{
int bit;
- /* First try to find availble temp not previously used (to avoid
+ /* First try to find available temp not previously used (to avoid
* starting a new texture indirection). According to the spec, the
* ~p->temps_output isn't necessary, but will keep it there for
* now:
@@ -463,6 +571,14 @@ static struct ureg get_tex_temp( struct texenv_fragment_program *p )
}
+/** Mark a temp reg as being no longer allocatable. */
+static void reserve_temp( struct texenv_fragment_program *p, struct ureg r )
+{
+ if (r.file == PROGRAM_TEMPORARY)
+ p->temps_output |= (1 << r.idx);
+}
+
+
static void release_temps(GLcontext *ctx, struct texenv_fragment_program *p )
{
GLuint max_temp = ctx->Const.FragmentProgram.MaxTemps;
@@ -501,11 +617,29 @@ static struct ureg register_param5( struct texenv_fragment_program *p,
#define register_param3(p,s0,s1,s2) register_param5(p,s0,s1,s2,0,0)
#define register_param4(p,s0,s1,s2,s3) register_param5(p,s0,s1,s2,s3,0)
+static GLuint frag_to_vert_attrib( GLuint attrib )
+{
+ switch (attrib) {
+ case FRAG_ATTRIB_COL0: return VERT_ATTRIB_COLOR0;
+ case FRAG_ATTRIB_COL1: return VERT_ATTRIB_COLOR1;
+ default:
+ assert(attrib >= FRAG_ATTRIB_TEX0);
+ assert(attrib <= FRAG_ATTRIB_TEX7);
+ return attrib - FRAG_ATTRIB_TEX0 + VERT_ATTRIB_TEX0;
+ }
+}
+
static struct ureg register_input( struct texenv_fragment_program *p, GLuint input )
{
- p->program->Base.InputsRead |= (1 << input);
- return make_ureg(PROGRAM_INPUT, input);
+ if (p->state->inputs_available & (1<<input)) {
+ p->program->Base.InputsRead |= (1 << input);
+ return make_ureg(PROGRAM_INPUT, input);
+ }
+ else {
+ GLuint idx = frag_to_vert_attrib( input );
+ return register_param3( p, STATE_INTERNAL, STATE_CURRENT_ATTRIB, idx );
+ }
}
@@ -556,10 +690,12 @@ emit_op(struct texenv_fragment_program *p,
emit_dst( &inst->DstReg, dest, mask );
+#if 0
/* Accounting for indirection tracking:
*/
if (dest.file == PROGRAM_TEMPORARY)
p->temps_output |= 1 << dest.idx;
+#endif
return inst;
}
@@ -614,6 +750,10 @@ static struct ureg emit_texld( struct texenv_fragment_program *p,
p->program->Base.NumTexInstructions++;
+ /* Accounting for indirection tracking:
+ */
+ reserve_temp(p, dest);
+
/* Is this a texture indirection?
*/
if ((coord.file == PROGRAM_TEMPORARY &&
@@ -638,14 +778,16 @@ static struct ureg register_const4f( struct texenv_fragment_program *p,
{
GLfloat values[4];
GLuint idx, swizzle;
+ struct ureg r;
values[0] = s0;
values[1] = s1;
values[2] = s2;
values[3] = s3;
idx = _mesa_add_unnamed_constant( p->program->Base.Parameters, values, 4,
&swizzle );
- ASSERT(swizzle == SWIZZLE_NOOP);
- return make_ureg(PROGRAM_CONSTANT, idx);
+ r = make_ureg(PROGRAM_CONSTANT, idx);
+ r.swz = swizzle;
+ return r;
}
#define register_scalar_const(p, s0) register_const4f(p, s0, s0, s0, s0)
@@ -1031,6 +1173,7 @@ static void load_texture( struct texenv_fragment_program *p, GLuint unit )
p->src_texture[unit] = emit_texld( p, OPCODE_TXP,
tmp, WRITEMASK_XYZW,
unit, dim, texcoord );
+
if (p->state->unit[unit].shadow)
p->program->Base.ShadowSamplers |= 1 << unit;
@@ -1157,6 +1300,7 @@ create_new_program(GLcontext *ctx, struct state_key *key,
for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++)
if (key->enabled_units & (1<<unit)) {
p.src_previous = emit_texenv( &p, unit );
+ reserve_temp(&p, p.src_previous); /* don't re-use this temp reg */
release_temps(ctx, &p); /* release all temps */
}
}
@@ -1268,6 +1412,9 @@ _mesa_get_fixed_func_fragment_program(GLcontext *ctx)
* If _MaintainTexEnvProgram is set we'll generate a fragment program that
* implements the current texture env/combine mode.
* This function generates that program and puts it into effect.
+ *
+ * XXX: remove this function. currently only called by some drivers,
+ * not by mesa core. We now handle this properly from inside mesa.
*/
void
_mesa_UpdateTexEnvProgram( GLcontext *ctx )
diff --git a/src/mesa/main/texformat.c b/src/mesa/main/texformat.c
index ffbb7fb19dc..16d05cc7d07 100644
--- a/src/mesa/main/texformat.c
+++ b/src/mesa/main/texformat.c
@@ -3,6 +3,7 @@
* Version: 6.5.1
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ * Copyright (c) 2008 VMware, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -333,6 +334,30 @@ const struct gl_texture_format _mesa_texformat_srgba8 = {
store_texel_srgba8 /* StoreTexel */
};
+const struct gl_texture_format _mesa_texformat_sargb8 = {
+ MESA_FORMAT_SARGB8, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 8, /* RedBits */
+ 8, /* GreenBits */
+ 8, /* BlueBits */
+ 8, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 4, /* TexelBytes */
+ _mesa_texstore_sargb8, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_sargb8, /* FetchTexel1Df */
+ fetch_texel_2d_sargb8, /* FetchTexel2Df */
+ fetch_texel_3d_sargb8, /* FetchTexel3Df */
+ store_texel_sargb8 /* StoreTexel */
+};
+
const struct gl_texture_format _mesa_texformat_sl8 = {
MESA_FORMAT_SL8, /* MesaFormat */
GL_LUMINANCE, /* BaseFormat */
@@ -1624,21 +1649,40 @@ _mesa_choose_tex_format( GLcontext *ctx, GLint internalFormat,
case GL_SLUMINANCE_ALPHA_EXT:
case GL_SLUMINANCE8_ALPHA8_EXT:
return &_mesa_texformat_sla8;
- /* NOTE: not supporting any compression of sRGB at this time */
- case GL_COMPRESSED_SRGB_EXT:
- return &_mesa_texformat_srgb8;
- case GL_COMPRESSED_SRGB_ALPHA_EXT:
- return &_mesa_texformat_srgba8;
case GL_COMPRESSED_SLUMINANCE_EXT:
return &_mesa_texformat_sl8;
case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT:
return &_mesa_texformat_sla8;
- case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_SRGB_EXT:
+#if FEATURE_texture_s3tc
+ if (ctx->Extensions.EXT_texture_compression_s3tc)
+ return &_mesa_texformat_srgb_dxt1;
+#endif
return &_mesa_texformat_srgb8;
+ case GL_COMPRESSED_SRGB_ALPHA_EXT:
+#if FEATURE_texture_s3tc
+ if (ctx->Extensions.EXT_texture_compression_s3tc)
+ return &_mesa_texformat_srgba_dxt3; /* Not srgba_dxt1, see spec */
+#endif
+ return &_mesa_texformat_srgba8;
+#if FEATURE_texture_s3tc
+ case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+ if (ctx->Extensions.EXT_texture_compression_s3tc)
+ return &_mesa_texformat_srgb_dxt1;
+ break;
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+ if (ctx->Extensions.EXT_texture_compression_s3tc)
+ return &_mesa_texformat_srgba_dxt1;
+ break;
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+ if (ctx->Extensions.EXT_texture_compression_s3tc)
+ return &_mesa_texformat_srgba_dxt3;
+ break;
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
- return &_mesa_texformat_srgba8;
+ if (ctx->Extensions.EXT_texture_compression_s3tc)
+ return &_mesa_texformat_srgba_dxt5;
+ break;
+#endif
default:
; /* fallthrough */
}
@@ -1719,6 +1763,11 @@ _mesa_format_to_type_and_comps(const struct gl_texture_format *format,
*comps = 1; /* XXX OK? */
return;
+ case MESA_FORMAT_S8_Z24:
+ *datatype = GL_UNSIGNED_INT;
+ *comps = 1; /* XXX OK? */
+ return;
+
case MESA_FORMAT_Z16:
*datatype = GL_UNSIGNED_SHORT;
*comps = 1;
@@ -1729,11 +1778,13 @@ _mesa_format_to_type_and_comps(const struct gl_texture_format *format,
*comps = 1;
return;
+#if FEATURE_EXT_texture_sRGB
case MESA_FORMAT_SRGB8:
*datatype = GL_UNSIGNED_BYTE;
*comps = 3;
return;
case MESA_FORMAT_SRGBA8:
+ case MESA_FORMAT_SARGB8:
*datatype = GL_UNSIGNED_BYTE;
*comps = 4;
return;
@@ -1745,17 +1796,28 @@ _mesa_format_to_type_and_comps(const struct gl_texture_format *format,
*datatype = GL_UNSIGNED_BYTE;
*comps = 2;
return;
+#endif
+#if FEATURE_texture_fxt1
case MESA_FORMAT_RGB_FXT1:
case MESA_FORMAT_RGBA_FXT1:
+#endif
+#if FEATURE_texture_s3tc
case MESA_FORMAT_RGB_DXT1:
case MESA_FORMAT_RGBA_DXT1:
case MESA_FORMAT_RGBA_DXT3:
case MESA_FORMAT_RGBA_DXT5:
+#if FEATURE_EXT_texture_sRGB
+ case MESA_FORMAT_SRGB_DXT1:
+ case MESA_FORMAT_SRGBA_DXT1:
+ case MESA_FORMAT_SRGBA_DXT3:
+ case MESA_FORMAT_SRGBA_DXT5:
+#endif
/* XXX generate error instead? */
*datatype = GL_UNSIGNED_BYTE;
*comps = 0;
return;
+#endif
case MESA_FORMAT_RGBA:
*datatype = CHAN_TYPE;
diff --git a/src/mesa/main/texformat.h b/src/mesa/main/texformat.h
index b1604d4a494..31364c36b1a 100644
--- a/src/mesa/main/texformat.h
+++ b/src/mesa/main/texformat.h
@@ -3,6 +3,7 @@
* Version: 6.5.1
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ * Copyright (c) 2008 VMware, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -98,9 +99,15 @@ enum _format {
/*@{*/
MESA_FORMAT_SRGB8,
MESA_FORMAT_SRGBA8,
+ MESA_FORMAT_SARGB8,
MESA_FORMAT_SL8,
MESA_FORMAT_SLA8,
+#if FEATURE_texture_s3tc
MESA_FORMAT_SRGB_DXT1,
+ MESA_FORMAT_SRGBA_DXT1,
+ MESA_FORMAT_SRGBA_DXT3,
+ MESA_FORMAT_SRGBA_DXT5,
+#endif
/*@}*/
#endif
@@ -108,12 +115,16 @@ enum _format {
* \name Compressed texture formats.
*/
/*@{*/
+#if FEATURE_texture_fxt1
MESA_FORMAT_RGB_FXT1,
MESA_FORMAT_RGBA_FXT1,
+#endif
+#if FEATURE_texture_s3tc
MESA_FORMAT_RGB_DXT1,
MESA_FORMAT_RGBA_DXT1,
MESA_FORMAT_RGBA_DXT3,
MESA_FORMAT_RGBA_DXT5,
+#endif
/*@}*/
/**
@@ -170,9 +181,15 @@ extern const struct gl_texture_format _mesa_texformat_intensity;
/*@{*/
extern const struct gl_texture_format _mesa_texformat_srgb8;
extern const struct gl_texture_format _mesa_texformat_srgba8;
+extern const struct gl_texture_format _mesa_texformat_sargb8;
extern const struct gl_texture_format _mesa_texformat_sl8;
extern const struct gl_texture_format _mesa_texformat_sla8;
+#if FEATURE_texture_s3tc
extern const struct gl_texture_format _mesa_texformat_srgb_dxt1;
+extern const struct gl_texture_format _mesa_texformat_srgba_dxt1;
+extern const struct gl_texture_format _mesa_texformat_srgba_dxt3;
+extern const struct gl_texture_format _mesa_texformat_srgba_dxt5;
+#endif
/*@}*/
#endif
@@ -229,12 +246,16 @@ extern const struct gl_texture_format _mesa_texformat_ycbcr_rev;
/** \name Compressed formats */
/*@{*/
+#if FEATURE_texture_fxt1
extern const struct gl_texture_format _mesa_texformat_rgb_fxt1;
extern const struct gl_texture_format _mesa_texformat_rgba_fxt1;
+#endif
+#if FEATURE_texture_s3tc
extern const struct gl_texture_format _mesa_texformat_rgb_dxt1;
extern const struct gl_texture_format _mesa_texformat_rgba_dxt1;
extern const struct gl_texture_format _mesa_texformat_rgba_dxt3;
extern const struct gl_texture_format _mesa_texformat_rgba_dxt5;
+#endif
/*@}*/
/** \name The null format */
diff --git a/src/mesa/main/texformat_tmp.h b/src/mesa/main/texformat_tmp.h
index 5f0c674d4fb..08b6d8f12fb 100644
--- a/src/mesa/main/texformat_tmp.h
+++ b/src/mesa/main/texformat_tmp.h
@@ -3,6 +3,7 @@
* Version: 6.5.1
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ * Copyright (c) 2008 VMware, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -1238,6 +1239,31 @@ static void store_texel_srgba8(struct gl_texture_image *texImage,
dst[0] = rgba[RCOMP];
dst[1] = rgba[GCOMP];
dst[2] = rgba[BCOMP];
+ dst[3] = rgba[ACOMP];
+}
+#endif
+
+/* Fetch texel from 1D, 2D or 3D sargb8 texture, return 4 GLfloats */
+static void FETCH(sargb8)(const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 4);
+ texel[RCOMP] = nonlinear_to_linear(src[1]);
+ texel[GCOMP] = nonlinear_to_linear(src[2]);
+ texel[BCOMP] = nonlinear_to_linear(src[3]);
+ texel[ACOMP] = UBYTE_TO_FLOAT(src[0]); /* linear! */
+}
+
+#if DIM == 3
+static void store_texel_sargb8(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLubyte *rgba = (const GLubyte *) texel;
+ GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 4);
+ dst[0] = rgba[ACOMP];
+ dst[1] = rgba[RCOMP];
+ dst[2] = rgba[GCOMP];
+ dst[3] = rgba[BCOMP];
}
#endif
diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c
index 9519d89e4a0..fdc72ed8436 100644
--- a/src/mesa/main/teximage.c
+++ b/src/mesa/main/teximage.c
@@ -1161,19 +1161,30 @@ _mesa_init_teximage_fields(GLcontext *ctx, GLenum target,
img->Width = width;
img->Height = height;
img->Depth = depth;
+
img->Width2 = width - 2 * border; /* == 1 << img->WidthLog2; */
- img->Height2 = height - 2 * border; /* == 1 << img->HeightLog2; */
- img->Depth2 = depth - 2 * border; /* == 1 << img->DepthLog2; */
img->WidthLog2 = logbase2(img->Width2);
- if (height == 1) /* 1-D texture */
+
+ if (height == 1) { /* 1-D texture */
+ img->Height2 = 1;
img->HeightLog2 = 0;
- else
+ }
+ else {
+ img->Height2 = height - 2 * border; /* == 1 << img->HeightLog2; */
img->HeightLog2 = logbase2(img->Height2);
- if (depth == 1) /* 2-D texture */
+ }
+
+ if (depth == 1) { /* 2-D texture */
+ img->Depth2 = 1;
img->DepthLog2 = 0;
- else
+ }
+ else {
+ img->Depth2 = depth - 2 * border; /* == 1 << img->DepthLog2; */
img->DepthLog2 = logbase2(img->Depth2);
+ }
+
img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2);
+
img->IsCompressed = GL_FALSE;
img->CompressedSize = 0;
diff --git a/src/mesa/main/texstore.c b/src/mesa/main/texstore.c
index 67cfca25651..2b06796abab 100644
--- a/src/mesa/main/texstore.c
+++ b/src/mesa/main/texstore.c
@@ -3,6 +3,7 @@
* Version: 7.3
*
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (c) 2008 VMware, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -885,8 +886,8 @@ _mesa_swizzle_ubyte_image(GLcontext *ctx,
/* _mesa_printf("map %d %d %d %d\n", map[0], map[1], map[2], map[3]); */
- if (srcRowStride == dstRowStride &&
- srcComponents == dstComponents &&
+ if (srcComponents == dstComponents &&
+ srcRowStride == dstRowStride &&
srcRowStride == srcWidth * srcComponents &&
dimensions < 3) {
/* 1 and 2D images only */
@@ -2769,7 +2770,6 @@ _mesa_texstore_rgba_float16(TEXSTORE_PARAMS)
GLboolean
_mesa_texstore_srgb8(TEXSTORE_PARAMS)
{
- const GLboolean littleEndian = _mesa_little_endian();
const struct gl_texture_format *newDstFormat;
StoreTexImageFunc store;
GLboolean k;
@@ -2777,14 +2777,8 @@ _mesa_texstore_srgb8(TEXSTORE_PARAMS)
ASSERT(dstFormat == &_mesa_texformat_srgb8);
/* reuse normal rgb texstore code */
- if (littleEndian) {
- newDstFormat = &_mesa_texformat_bgr888;
- store = _mesa_texstore_bgr888;
- }
- else {
- newDstFormat = &_mesa_texformat_rgb888;
- store = _mesa_texstore_rgb888;
- }
+ newDstFormat = &_mesa_texformat_rgb888;
+ store = _mesa_texstore_rgb888;
k = store(ctx, dims, baseInternalFormat,
newDstFormat, dstAddr,
@@ -2800,17 +2794,13 @@ _mesa_texstore_srgb8(TEXSTORE_PARAMS)
GLboolean
_mesa_texstore_srgba8(TEXSTORE_PARAMS)
{
- const GLboolean littleEndian = _mesa_little_endian();
const struct gl_texture_format *newDstFormat;
GLboolean k;
ASSERT(dstFormat == &_mesa_texformat_srgba8);
/* reuse normal rgba texstore code */
- if (littleEndian)
- newDstFormat = &_mesa_texformat_rgba8888_rev;
- else
- newDstFormat = &_mesa_texformat_rgba8888;
+ newDstFormat = &_mesa_texformat_rgba8888;
k = _mesa_texstore_rgba8888(ctx, dims, baseInternalFormat,
newDstFormat, dstAddr,
@@ -2824,6 +2814,28 @@ _mesa_texstore_srgba8(TEXSTORE_PARAMS)
GLboolean
+_mesa_texstore_sargb8(TEXSTORE_PARAMS)
+{
+ const struct gl_texture_format *newDstFormat;
+ GLboolean k;
+
+ ASSERT(dstFormat == &_mesa_texformat_sargb8);
+
+ /* reuse normal rgba texstore code */
+ newDstFormat = &_mesa_texformat_argb8888;
+
+ k = _mesa_texstore_argb8888(ctx, dims, baseInternalFormat,
+ newDstFormat, dstAddr,
+ dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride, dstImageOffsets,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType,
+ srcAddr, srcPacking);
+ return k;
+}
+
+
+GLboolean
_mesa_texstore_sl8(TEXSTORE_PARAMS)
{
const struct gl_texture_format *newDstFormat;
@@ -2848,17 +2860,13 @@ _mesa_texstore_sl8(TEXSTORE_PARAMS)
GLboolean
_mesa_texstore_sla8(TEXSTORE_PARAMS)
{
- const GLboolean littleEndian = _mesa_little_endian();
const struct gl_texture_format *newDstFormat;
GLboolean k;
ASSERT(dstFormat == &_mesa_texformat_sla8);
/* reuse normal luminance/alpha texstore code */
- if (littleEndian)
- newDstFormat = &_mesa_texformat_al88;
- else
- newDstFormat = &_mesa_texformat_al88_rev;
+ newDstFormat = &_mesa_texformat_al88;
k = _mesa_texstore_al88(ctx, dims, baseInternalFormat,
newDstFormat, dstAddr,
@@ -3688,6 +3696,7 @@ is_srgb_teximage(const struct gl_texture_image *texImage)
switch (texImage->TexFormat->MesaFormat) {
case MESA_FORMAT_SRGB8:
case MESA_FORMAT_SRGBA8:
+ case MESA_FORMAT_SARGB8:
case MESA_FORMAT_SL8:
case MESA_FORMAT_SLA8:
return GL_TRUE;
@@ -3820,6 +3829,10 @@ _mesa_get_teximage(GLcontext *ctx, GLenum target, GLint level,
MEMCPY(dest,
(const GLubyte *) texImage->Data + row * rowstride,
comps * width * sizeof(GLubyte));
+ /* FIXME: isn't it necessary to still do component assigning
+ according to format/type? */
+ /* FIXME: need to do something else for compressed srgb textures
+ (currently will return values converted to linear) */
}
#endif /* FEATURE_EXT_texture_sRGB */
else {
diff --git a/src/mesa/main/texstore.h b/src/mesa/main/texstore.h
index 951d0a112bb..b03386b2acc 100644
--- a/src/mesa/main/texstore.h
+++ b/src/mesa/main/texstore.h
@@ -3,6 +3,7 @@
* Version: 6.5.1
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ * Copyright (c) 2008 VMware, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -73,6 +74,7 @@ extern GLboolean _mesa_texstore_rgba_dxt5(TEXSTORE_PARAMS);
#if FEATURE_EXT_texture_sRGB
extern GLboolean _mesa_texstore_srgb8(TEXSTORE_PARAMS);
extern GLboolean _mesa_texstore_srgba8(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_sargb8(TEXSTORE_PARAMS);
extern GLboolean _mesa_texstore_sl8(TEXSTORE_PARAMS);
extern GLboolean _mesa_texstore_sla8(TEXSTORE_PARAMS);
#endif
diff --git a/src/mesa/main/varray.h b/src/mesa/main/varray.h
index 6385689fcc9..97d5c8219d0 100644
--- a/src/mesa/main/varray.h
+++ b/src/mesa/main/varray.h
@@ -156,6 +156,20 @@ _mesa_LockArraysEXT(GLint first, GLsizei count);
extern void GLAPIENTRY
_mesa_UnlockArraysEXT( void );
+
+extern void GLAPIENTRY
+_mesa_DrawArrays(GLenum mode, GLint first, GLsizei count);
+
+extern void GLAPIENTRY
+_mesa_DrawElements(GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices);
+
+extern void GLAPIENTRY
+_mesa_DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count,
+ GLenum type, const GLvoid *indices);
+
+
+
extern void
_mesa_init_varray( GLcontext * ctx );
diff --git a/src/mesa/main/version.h b/src/mesa/main/version.h
index f5bf6e2c855..9287e8515cc 100644
--- a/src/mesa/main/version.h
+++ b/src/mesa/main/version.h
@@ -1,6 +1,10 @@
/*
* Mesa 3-D graphics library
+<<<<<<< HEAD:src/mesa/main/version.h
* Version: 7.5
+=======
+ * Version: 7.4
+>>>>>>> origin/gallium-0.2:src/mesa/main/version.h
*
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
*
diff --git a/src/mesa/math/m_debug_xform.c b/src/mesa/math/m_debug_xform.c
index ec22c7052db..df8cc066b6e 100644
--- a/src/mesa/math/m_debug_xform.c
+++ b/src/mesa/math/m_debug_xform.c
@@ -206,7 +206,8 @@ static int test_transform_function( transform_func func, int psize,
case VAR:
break;
default:
- abort();
+ ASSERT(0);
+ return 0;
}
}
}
diff --git a/src/mesa/ppc/common_ppc.c b/src/mesa/ppc/common_ppc.c
index 786e1817acf..c7cec96e5d5 100644
--- a/src/mesa/ppc/common_ppc.c
+++ b/src/mesa/ppc/common_ppc.c
@@ -85,7 +85,7 @@ void _mesa_init_all_ppc_transform_asm( void )
}
# ifndef USE_VMX_ASM
- _mesa_ppc_cpu_features &= ~PPC_FEATURES_HAS_ALTIVEC;
+ _mesa_ppc_cpu_features &= ~PPC_FEATURE_HAS_ALTIVEC;
# endif
#endif
}
diff --git a/src/mesa/shader/arbprogparse.c b/src/mesa/shader/arbprogparse.c
index c65d886a91d..2e0fc3694a4 100644
--- a/src/mesa/shader/arbprogparse.c
+++ b/src/mesa/shader/arbprogparse.c
@@ -30,6 +30,27 @@
* \author Karl Rasche
*/
+/**
+Notes on program parameters, etc.
+
+The instructions we emit will use six kinds of source registers:
+
+ PROGRAM_INPUT - input registers
+ PROGRAM_TEMPORARY - temp registers
+ PROGRAM_ADDRESS - address/indirect register
+ PROGRAM_SAMPLER - texture sampler
+ PROGRAM_CONSTANT - indexes into program->Parameters, a known constant/literal
+ PROGRAM_STATE_VAR - indexes into program->Parameters, and may actually be:
+ + a state variable, like "state.fog.color", or
+ + a pointer to a "program.local[k]" parameter, or
+ + a pointer to a "program.env[k]" parameter
+
+Basically, all the program.local[] and program.env[] values will get mapped
+into the unified gl_program->Parameters array. This solves the problem of
+having three separate program parameter arrays.
+*/
+
+
#include "main/glheader.h"
#include "main/imports.h"
#include "main/context.h"
@@ -38,16 +59,11 @@
#include "shader/grammar/grammar_mesa.h"
#include "arbprogparse.h"
#include "program.h"
+#include "programopt.h"
#include "prog_parameter.h"
#include "prog_statevars.h"
#include "prog_instruction.h"
-
-/* For ARB programs, use the NV instruction limits */
-#define MAX_INSTRUCTIONS MAX2(MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS, \
- MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS)
-
-
/**
* This is basically a union of the vertex_program and fragment_program
* structs that we can use to parse the program into
@@ -1895,7 +1911,11 @@ parse_param_elements (GLcontext * ctx, const GLubyte ** inst,
const_values, 4);
if (param_var->param_binding_begin == ~0U)
param_var->param_binding_begin = idx;
- param_var->param_binding_type = PROGRAM_CONSTANT;
+ param_var->param_binding_type = PROGRAM_STATE_VAR;
+ /* Note: when we reference this parameter in an instruction later,
+ * we'll check if it's really a constant/immediate and set the
+ * instruction register type appropriately.
+ */
param_var->param_binding_length++;
Program->Base.NumParameters++;
break;
@@ -2602,6 +2622,18 @@ parse_src_reg (GLcontext * ctx, const GLubyte ** inst,
return 1;
}
+ if (*File == PROGRAM_STATE_VAR) {
+ enum register_file file;
+
+ /* If we're referencing the Program->Parameters[] array, check if the
+ * parameter is really a constant/literal. If so, set File to CONSTANT.
+ */
+ assert(*Index < (GLint) Program->Base.Parameters->NumParameters);
+ file = Program->Base.Parameters->Parameters[*Index].Type;
+ if (file == PROGRAM_CONSTANT)
+ *File = PROGRAM_CONSTANT;
+ }
+
/* Add attributes to InputsRead only if they are used the program.
* This avoids the handling of unused ATTRIB declarations in the drivers. */
if (*File == PROGRAM_INPUT)
@@ -3378,11 +3410,11 @@ debug_variables (GLcontext * ctx, struct var_cache *vc_head,
fprintf (stderr, "%s\n",
Program->Base.Parameters->Parameters[a + b].Name);
if (Program->Base.Parameters->Parameters[a + b].Type == PROGRAM_STATE_VAR) {
- const char *s;
+ char *s;
s = _mesa_program_state_string(Program->Base.Parameters->Parameters
[a + b].StateIndexes);
fprintf(stderr, "%s\n", s);
- _mesa_free((char *) s);
+ _mesa_free(s);
}
else
fprintf (stderr, "%f %f %f %f\n",
@@ -3430,7 +3462,7 @@ parse_instructions(GLcontext * ctx, const GLubyte * inst,
: ctx->Const.VertexProgram.MaxInstructions;
GLint err = 0;
- ASSERT(MAX_INSTRUCTIONS >= maxInst);
+ ASSERT(MAX_PROGRAM_INSTRUCTIONS >= maxInst);
Program->MajorVersion = (GLuint) * inst++;
Program->MinorVersion = (GLuint) * inst++;
@@ -3784,7 +3816,7 @@ _mesa_parse_arb_program(GLcontext *ctx, GLenum target,
/* Initialize the arb_program struct */
program->Base.String = strz;
- program->Base.Instructions = _mesa_alloc_instructions(MAX_INSTRUCTIONS);
+ program->Base.Instructions = _mesa_alloc_instructions(MAX_PROGRAM_INSTRUCTIONS);
program->Base.NumInstructions =
program->Base.NumTemporaries =
program->Base.NumParameters =
@@ -3829,12 +3861,12 @@ _mesa_parse_arb_program(GLcontext *ctx, GLenum target,
_mesa_free (parsed);
- /* Reallocate the instruction array from size [MAX_INSTRUCTIONS]
+ /* Reallocate the instruction array from size [MAX_PROGRAM_INSTRUCTIONS]
* to size [ap.Base.NumInstructions].
*/
program->Base.Instructions
= _mesa_realloc_instructions(program->Base.Instructions,
- MAX_INSTRUCTIONS,
+ MAX_PROGRAM_INSTRUCTIONS,
program->Base.NumInstructions);
return !err;
@@ -3898,6 +3930,16 @@ _mesa_parse_arb_fragment_program(GLcontext* ctx, GLenum target,
_mesa_free_parameter_list(program->Base.Parameters);
program->Base.Parameters = ap.Base.Parameters;
+ /* Append fog instructions now if the program has "OPTION ARB_fog_exp"
+ * or similar. We used to leave this up to drivers, but it appears
+ * there's no hardware that wants to do fog in a discrete stage separate
+ * from the fragment shader.
+ */
+ if (program->FogOption != GL_NONE) {
+ _mesa_append_fog_code(ctx, program);
+ program->FogOption = GL_NONE;
+ }
+
#if DEBUG_FP
_mesa_printf("____________Fragment program %u ________\n", program->Base.Id);
_mesa_print_program(&program->Base);
diff --git a/src/mesa/shader/atifragshader.h b/src/mesa/shader/atifragshader.h
index 32fb3a80190..e1dc20e6065 100644
--- a/src/mesa/shader/atifragshader.h
+++ b/src/mesa/shader/atifragshader.h
@@ -8,6 +8,8 @@
#ifndef ATIFRAGSHADER_H
#define ATIFRAGSHADER_H
+#include "main/mtypes.h"
+
#define MAX_NUM_INSTRUCTIONS_PER_PASS_ATI 8
#define MAX_NUM_PASSES_ATI 2
#define MAX_NUM_FRAGMENT_REGISTERS_ATI 6
diff --git a/src/mesa/shader/grammar/descrip.mms b/src/mesa/shader/grammar/descrip.mms
deleted file mode 100644
index 6976b70d6ac..00000000000
--- a/src/mesa/shader/grammar/descrip.mms
+++ /dev/null
@@ -1,42 +0,0 @@
-# Makefile for core library for VMS
-# contributed by Jouk Jansen [email protected]
-# Last revision : 29 September 2008
-
-.first
- define gl [----.include.gl]
- define math [--.math]
- define swrast [--.swrast]
- define array_cache [--.array_cache]
- define main [--.main]
-
-.include [----]mms-config.
-
-##### MACROS #####
-
-VPATH = RCS
-
-INCDIR = [----.include],[],[--.main],[--.glapi],[-.slang]
-LIBDIR = [----.lib]
-CFLAGS = /include=($(INCDIR),[])/define=(PTHREADS=1)/name=(as_is,short)/float=ieee/ieee=denorm
-
-SOURCES = grammar_mesa.c
-
-OBJECTS = grammar_mesa.obj
-
-##### RULES #####
-
-VERSION=Mesa V3.4
-
-##### TARGETS #####
-all :
- $(MMS)$(MMSQUALIFIERS) $(LIBDIR)$(GL_LIB)
-
-# Make the library
-$(LIBDIR)$(GL_LIB) : $(OBJECTS)
- @ library $(LIBDIR)$(GL_LIB) $(OBJECTS)
-
-clean :
- purge
- delete *.obj;*
-
-grammar_mesa.obj : grammar_mesa.c grammar.c
diff --git a/src/mesa/shader/prog_cache.c b/src/mesa/shader/prog_cache.c
index 36a25377c55..9437e596138 100644
--- a/src/mesa/shader/prog_cache.c
+++ b/src/mesa/shader/prog_cache.c
@@ -44,6 +44,7 @@ struct cache_item
struct gl_program_cache
{
struct cache_item **items;
+ struct cache_item *last;
GLuint size, n_items;
};
@@ -83,6 +84,8 @@ rehash(struct gl_program_cache *cache)
struct cache_item *c, *next;
GLuint size, i;
+ cache->last = NULL;
+
size = cache->size * 3;
items = (struct cache_item**) _mesa_malloc(size * sizeof(*items));
_mesa_memset(items, 0, size * sizeof(*items));
@@ -105,6 +108,8 @@ clear_cache(GLcontext *ctx, struct gl_program_cache *cache)
{
struct cache_item *c, *next;
GLuint i;
+
+ cache->last = NULL;
for (i = 0; i < cache->size; i++) {
for (c = cache->items[i]; c; c = next) {
@@ -149,18 +154,26 @@ _mesa_delete_program_cache(GLcontext *ctx, struct gl_program_cache *cache)
struct gl_program *
-_mesa_search_program_cache(const struct gl_program_cache *cache,
+_mesa_search_program_cache(struct gl_program_cache *cache,
const void *key, GLuint keysize)
{
- const GLuint hash = hash_key(key, keysize);
- struct cache_item *c;
-
- for (c = cache->items[hash % cache->size]; c; c = c->next) {
- if (c->hash == hash && memcmp(c->key, key, keysize) == 0)
- return c->program;
+ if (cache->last &&
+ memcmp(cache->last->key, key, keysize) == 0) {
+ return cache->last->program;
}
+ else {
+ const GLuint hash = hash_key(key, keysize);
+ struct cache_item *c;
+
+ for (c = cache->items[hash % cache->size]; c; c = c->next) {
+ if (c->hash == hash && memcmp(c->key, key, keysize) == 0) {
+ cache->last = c;
+ return c->program;
+ }
+ }
- return NULL;
+ return NULL;
+ }
}
diff --git a/src/mesa/shader/prog_cache.h b/src/mesa/shader/prog_cache.h
index a8c91fba011..4e1ccac03ff 100644
--- a/src/mesa/shader/prog_cache.h
+++ b/src/mesa/shader/prog_cache.h
@@ -42,7 +42,7 @@ _mesa_delete_program_cache(GLcontext *ctx, struct gl_program_cache *pc);
extern struct gl_program *
-_mesa_search_program_cache(const struct gl_program_cache *cache,
+_mesa_search_program_cache(struct gl_program_cache *cache,
const void *key, GLuint keysize);
extern void
diff --git a/src/mesa/shader/prog_instruction.h b/src/mesa/shader/prog_instruction.h
index 268afc528c4..f978334ab22 100644
--- a/src/mesa/shader/prog_instruction.h
+++ b/src/mesa/shader/prog_instruction.h
@@ -418,11 +418,13 @@ struct prog_instruction
*/
GLint BranchTarget;
+#if 0
/**
* For TEX instructions in shaders, the sampler to use for the
* texture lookup.
*/
GLint Sampler;
+#endif
const char *Comment;
};
diff --git a/src/mesa/shader/prog_parameter.c b/src/mesa/shader/prog_parameter.c
index dc48e84ab29..8ae961241f6 100644
--- a/src/mesa/shader/prog_parameter.c
+++ b/src/mesa/shader/prog_parameter.c
@@ -424,7 +424,7 @@ _mesa_add_state_reference(struct gl_program_parameter_list *paramList,
const gl_state_index stateTokens[STATE_LENGTH])
{
const GLuint size = 4; /* XXX fix */
- const char *name;
+ char *name;
GLint index;
/* Check if the state reference is already in the list */
@@ -451,7 +451,7 @@ _mesa_add_state_reference(struct gl_program_parameter_list *paramList,
paramList->StateFlags |= _mesa_program_state_flags(stateTokens);
/* free name string here since we duplicated it in add_parameter() */
- _mesa_free((void *) name);
+ _mesa_free(name);
return index;
}
diff --git a/src/mesa/shader/prog_print.c b/src/mesa/shader/prog_print.c
index 8b0f16e688f..d0ed22e98e1 100644
--- a/src/mesa/shader/prog_print.c
+++ b/src/mesa/shader/prog_print.c
@@ -253,7 +253,9 @@ reg_string(enum register_file f, GLint index, gl_prog_print_mode mode,
{
struct gl_program_parameter *param
= prog->Parameters->Parameters + index;
- sprintf(str, _mesa_program_state_string(param->StateIndexes));
+ char *state = _mesa_program_state_string(param->StateIndexes);
+ sprintf(str, state);
+ _mesa_free(state);
}
break;
case PROGRAM_ADDRESS:
@@ -359,6 +361,19 @@ _mesa_swizzle_string(GLuint swizzle, GLuint negateBase, GLboolean extended)
}
+void
+_mesa_print_swizzle(GLuint swizzle)
+{
+ if (swizzle == SWIZZLE_XYZW) {
+ _mesa_printf(".xyzw\n");
+ }
+ else {
+ const char *s = _mesa_swizzle_string(swizzle, 0, 0);
+ _mesa_printf("%s\n", s);
+ }
+}
+
+
const char *
_mesa_writemask_string(GLuint writeMask)
{
diff --git a/src/mesa/shader/prog_print.h b/src/mesa/shader/prog_print.h
index aa7f902feeb..d55661cebb8 100644
--- a/src/mesa/shader/prog_print.h
+++ b/src/mesa/shader/prog_print.h
@@ -47,6 +47,9 @@ const char *
_mesa_writemask_string(GLuint writeMask);
extern void
+_mesa_print_swizzle(GLuint swizzle);
+
+extern void
_mesa_print_alu_instruction(const struct prog_instruction *inst,
const char *opcode_string, GLuint numRegs);
diff --git a/src/mesa/shader/prog_statevars.c b/src/mesa/shader/prog_statevars.c
index 3ce60427bf4..e1db30b78f4 100644
--- a/src/mesa/shader/prog_statevars.c
+++ b/src/mesa/shader/prog_statevars.c
@@ -395,6 +395,12 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[],
case STATE_INTERNAL:
switch (state[1]) {
+ case STATE_CURRENT_ATTRIB: {
+ const GLuint idx = (GLuint) state[2];
+ COPY_4V(value, ctx->Current.Attrib[idx]);
+ return;
+ }
+
case STATE_NORMAL_SCALE:
ASSIGN_4V(value,
ctx->_ModelViewInvScale,
@@ -501,6 +507,9 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[],
}
return;
+ /* XXX: make sure new tokens added here are also handled in the
+ * _mesa_program_state_flags() switch, below.
+ */
default:
/* unknown state indexes are silently ignored
* should be handled by the driver.
@@ -574,11 +583,29 @@ _mesa_program_state_flags(const gl_state_index state[STATE_LENGTH])
case STATE_INTERNAL:
switch (state[1]) {
+ case STATE_CURRENT_ATTRIB:
+ return _NEW_CURRENT_ATTRIB;
+
+ case STATE_NORMAL_SCALE:
+ return _NEW_MODELVIEW;
+
case STATE_TEXRECT_SCALE:
case STATE_SHADOW_AMBIENT:
return _NEW_TEXTURE;
case STATE_FOG_PARAMS_OPTIMIZED:
return _NEW_FOG;
+ case STATE_LIGHT_SPOT_DIR_NORMALIZED:
+ case STATE_LIGHT_POSITION:
+ case STATE_LIGHT_POSITION_NORMALIZED:
+ case STATE_LIGHT_HALF_VECTOR:
+ return _NEW_LIGHT;
+
+ case STATE_PT_SCALE:
+ case STATE_PT_BIAS:
+ case STATE_PCM_SCALE:
+ case STATE_PCM_BIAS:
+ return _NEW_PIXEL;
+
default:
/* unknown state indexes are silently ignored and
* no flag set, since it is handled by the driver.
@@ -807,7 +834,7 @@ append_index(char *dst, GLint index)
* For example, return "state.matrix.texture[2].inverse".
* Use _mesa_free() to deallocate the string.
*/
-const char *
+char *
_mesa_program_state_string(const gl_state_index state[STATE_LENGTH])
{
char str[1000] = "";
diff --git a/src/mesa/shader/prog_statevars.h b/src/mesa/shader/prog_statevars.h
index 909bce0a4f3..d5358a1d042 100644
--- a/src/mesa/shader/prog_statevars.h
+++ b/src/mesa/shader/prog_statevars.h
@@ -104,6 +104,7 @@ typedef enum gl_state_index_ {
STATE_LOCAL,
STATE_INTERNAL, /* Mesa additions */
+ STATE_CURRENT_ATTRIB, /* ctx->Current vertex attrib value */
STATE_NORMAL_SCALE,
STATE_TEXRECT_SCALE,
STATE_FOG_PARAMS_OPTIMIZED, /* for faster fog calc */
@@ -130,7 +131,7 @@ extern GLbitfield
_mesa_program_state_flags(const gl_state_index state[STATE_LENGTH]);
-extern const char *
+extern char *
_mesa_program_state_string(const gl_state_index state[STATE_LENGTH]);
diff --git a/src/mesa/shader/prog_uniform.c b/src/mesa/shader/prog_uniform.c
index dc76be8e46c..0642713148c 100644
--- a/src/mesa/shader/prog_uniform.c
+++ b/src/mesa/shader/prog_uniform.c
@@ -142,8 +142,8 @@ _mesa_longest_uniform_name(const struct gl_uniform_list *list)
GLint max = 0;
GLuint i;
for (i = 0; list && i < list->NumUniforms; i++) {
- GLuint len = _mesa_strlen(list->Uniforms[i].Name);
- if (len > (GLuint)max)
+ GLint len = (GLint)_mesa_strlen(list->Uniforms[i].Name);
+ if (len > max)
max = len;
}
return max;
diff --git a/src/mesa/shader/program.c b/src/mesa/shader/program.c
index d114828ec6a..7a3b827352a 100644
--- a/src/mesa/shader/program.c
+++ b/src/mesa/shader/program.c
@@ -554,7 +554,6 @@ _mesa_insert_instructions(struct gl_program *prog, GLuint start, GLuint count)
return GL_TRUE;
}
-
/**
* Delete 'count' instructions at 'start' in the given program.
* Adjust branch targets accordingly.
@@ -691,17 +690,47 @@ _mesa_combine_programs(GLcontext *ctx,
if (newProg->Target == GL_FRAGMENT_PROGRAM_ARB) {
struct gl_fragment_program *fprogA, *fprogB, *newFprog;
+ GLbitfield progB_inputsRead = progB->InputsRead;
+ GLint progB_colorFile, progB_colorIndex;
+
fprogA = (struct gl_fragment_program *) progA;
fprogB = (struct gl_fragment_program *) progB;
newFprog = (struct gl_fragment_program *) newProg;
newFprog->UsesKill = fprogA->UsesKill || fprogB->UsesKill;
+ /* We'll do a search and replace for instances
+ * of progB_colorFile/progB_colorIndex below...
+ */
+ progB_colorFile = PROGRAM_INPUT;
+ progB_colorIndex = FRAG_ATTRIB_COL0;
+
+ /*
+ * The fragment program may get color from a state var rather than
+ * a fragment input (vertex output) if it's constant.
+ * See the texenvprogram.c code.
+ * So, search the program's parameter list now to see if the program
+ * gets color from a state var instead of a conventional fragment
+ * input register.
+ */
+ for (i = 0; i < progB->Parameters->NumParameters; i++) {
+ struct gl_program_parameter *p = &progB->Parameters->Parameters[i];
+ if (p->Type == PROGRAM_STATE_VAR &&
+ p->StateIndexes[0] == STATE_INTERNAL &&
+ p->StateIndexes[1] == STATE_CURRENT_ATTRIB &&
+ p->StateIndexes[2] == VERT_ATTRIB_COLOR0) {
+ progB_inputsRead |= FRAG_BIT_COL0;
+ progB_colorFile = PROGRAM_STATE_VAR;
+ progB_colorIndex = i;
+ break;
+ }
+ }
+
/* Connect color outputs of fprogA to color inputs of fprogB, via a
* new temporary register.
*/
if ((progA->OutputsWritten & (1 << FRAG_RESULT_COLR)) &&
- (progB->InputsRead & (1 << FRAG_ATTRIB_COL0))) {
+ (progB_inputsRead & FRAG_BIT_COL0)) {
GLint tempReg = _mesa_find_free_register(newProg, PROGRAM_TEMPORARY);
if (tempReg < 0) {
_mesa_problem(ctx, "No free temp regs found in "
@@ -712,13 +741,14 @@ _mesa_combine_programs(GLcontext *ctx,
replace_registers(newInst, lenA,
PROGRAM_OUTPUT, FRAG_RESULT_COLR,
PROGRAM_TEMPORARY, tempReg);
- /* replace reads from input.color[0] with tempReg */
+ /* replace reads from the input color with tempReg */
replace_registers(newInst + lenA, lenB,
- PROGRAM_INPUT, FRAG_ATTRIB_COL0,
- PROGRAM_TEMPORARY, tempReg);
+ progB_colorFile, progB_colorIndex, /* search for */
+ PROGRAM_TEMPORARY, tempReg /* replace with */ );
}
- inputsB = progB->InputsRead;
+ /* compute combined program's InputsRead */
+ inputsB = progB_inputsRead;
if (progA->OutputsWritten & (1 << FRAG_RESULT_COLR)) {
inputsB &= ~(1 << FRAG_ATTRIB_COL0);
}
diff --git a/src/mesa/shader/shader_api.c b/src/mesa/shader/shader_api.c
index fb2a7e54fe6..a5cf1ca1d44 100644
--- a/src/mesa/shader/shader_api.c
+++ b/src/mesa/shader/shader_api.c
@@ -406,7 +406,7 @@ _mesa_init_shader_state(GLcontext * ctx)
* are generated by the GLSL compiler.
*/
ctx->Shader.EmitHighLevelInstructions = GL_TRUE;
- ctx->Shader.EmitCondCodes = GL_TRUE; /* XXX probably want GL_FALSE... */
+ ctx->Shader.EmitCondCodes = GL_FALSE;/*GL_TRUE;*/ /* XXX probably want GL_FALSE... */
ctx->Shader.EmitComments = GL_FALSE;
ctx->Shader.Flags = get_shader_flags();
}
@@ -1143,7 +1143,8 @@ get_matrix_dims(GLenum type, GLint *rows, GLint *cols)
/**
* Determine the number of rows and columns occupied by a uniform
- * according to its datatype.
+ * according to its datatype. For non-matrix types (such as GL_FLOAT_VEC4),
+ * the number of rows = 1 and cols = number of elements in the vector.
*/
static void
get_uniform_rows_cols(const struct gl_program_parameter *p,
@@ -1152,11 +1153,17 @@ get_uniform_rows_cols(const struct gl_program_parameter *p,
get_matrix_dims(p->DataType, rows, cols);
if (*rows == 0 && *cols == 0) {
/* not a matrix type, probably a float or vector */
- *rows = p->Size / 4 + 1;
- if (p->Size % 4 == 0)
- *cols = 4;
- else
- *cols = p->Size % 4;
+ if (p->Size <= 4) {
+ *rows = 1;
+ *cols = p->Size;
+ }
+ else {
+ *rows = p->Size / 4 + 1;
+ if (p->Size % 4 == 0)
+ *cols = 4;
+ else
+ *cols = p->Size % 4;
+ }
}
}
@@ -1556,7 +1563,7 @@ set_program_uniform(GLcontext *ctx, struct gl_program *program,
return;
}
- if (index + offset > program->Parameters->Size) {
+ if (index + offset > (GLint) program->Parameters->Size) {
/* out of bounds! */
return;
}
@@ -1621,7 +1628,7 @@ set_program_uniform(GLcontext *ctx, struct gl_program *program,
/* if the uniform is bool-valued, convert to 1.0 or 0.0 */
if (is_boolean_type(param->DataType)) {
for (i = 0; i < elems; i++) {
- uniformVal[i] = uniformVal[i] ? 1.0 : 0.0;
+ uniformVal[i] = uniformVal[i] ? 1.0f : 0.0f;
}
}
}
diff --git a/src/mesa/shader/slang/library/slang_version_syn.h b/src/mesa/shader/slang/library/slang_version_syn.h
deleted file mode 100644
index 3b94d85927a..00000000000
--- a/src/mesa/shader/slang/library/slang_version_syn.h
+++ /dev/null
@@ -1,64 +0,0 @@
-".syntax version_directive;\n"
-"version_directive\n"
-" version_directive_1 .and .loop version_directive_2;\n"
-"version_directive_1\n"
-" prior_optional_spaces .and optional_version_directive .and .true .emit $;\n"
-"version_directive_2\n"
-" prior_optional_spaces .and version_directive_body .and .true .emit $;\n"
-"optional_version_directive\n"
-" version_directive_body .or .true .emit 10 .emit 1;\n"
-"version_directive_body\n"
-" '#' .and optional_space .and \"version\" .and space .and version_number .and optional_space .and\n"
-" new_line;\n"
-"version_number\n"
-" version_number_110;\n"
-"version_number_110\n"
-" leading_zeroes .and \"110\" .emit 10 .emit 1;\n"
-"leading_zeroes\n"
-" .loop zero;\n"
-"zero\n"
-" '0';\n"
-"space\n"
-" single_space .and .loop single_space;\n"
-"optional_space\n"
-" .loop single_space;\n"
-"single_space\n"
-" ' ' .or '\\t';\n"
-"prior_optional_spaces\n"
-" .loop prior_space;\n"
-"prior_space\n"
-" c_style_comment_block .or cpp_style_comment_block .or space .or new_line;\n"
-"c_style_comment_block\n"
-" '/' .and '*' .and c_style_comment_rest;\n"
-"c_style_comment_rest\n"
-" .loop c_style_comment_char_no_star .and c_style_comment_rest_1;\n"
-"c_style_comment_rest_1\n"
-" c_style_comment_end .or c_style_comment_rest_2;\n"
-"c_style_comment_rest_2\n"
-" '*' .and c_style_comment_rest;\n"
-"c_style_comment_char_no_star\n"
-" '\\x2B'-'\\xFF' .or '\\x01'-'\\x29';\n"
-"c_style_comment_end\n"
-" '*' .and '/';\n"
-"cpp_style_comment_block\n"
-" '/' .and '/' .and cpp_style_comment_block_1;\n"
-"cpp_style_comment_block_1\n"
-" cpp_style_comment_block_2 .or cpp_style_comment_block_3;\n"
-"cpp_style_comment_block_2\n"
-" .loop cpp_style_comment_char .and new_line;\n"
-"cpp_style_comment_block_3\n"
-" .loop cpp_style_comment_char;\n"
-"cpp_style_comment_char\n"
-" '\\x0E'-'\\xFF' .or '\\x01'-'\\x09' .or '\\x0B'-'\\x0C';\n"
-"new_line\n"
-" cr_lf .or lf_cr .or '\\n' .or '\\r';\n"
-"cr_lf\n"
-" '\\r' .and '\\n';\n"
-"lf_cr\n"
-" '\\n' .and '\\r';\n"
-".string __string_filter;\n"
-"__string_filter\n"
-" .loop __identifier_char;\n"
-"__identifier_char\n"
-" 'a'-'z' .or 'A'-'Z' .or '_' .or '0'-'9';\n"
-""
diff --git a/src/mesa/shader/slang/slang_link.c b/src/mesa/shader/slang/slang_link.c
index 848a64f932a..99f2cbdcc05 100644
--- a/src/mesa/shader/slang/slang_link.c
+++ b/src/mesa/shader/slang/slang_link.c
@@ -502,7 +502,6 @@ _slang_update_inputs_outputs(struct gl_program *prog)
maxAddrReg = MAX2(maxAddrReg, inst->DstReg.Index + 1);
}
}
-
prog->NumAddressRegs = maxAddrReg;
}
diff --git a/src/mesa/sources b/src/mesa/sources
index 01a3fb89e61..643c625b5bf 100644
--- a/src/mesa/sources
+++ b/src/mesa/sources
@@ -274,20 +274,19 @@ MESA_SOURCES = \
ALL_SOURCES = \
$(MESA_SOURCES) \
$(GLAPI_SOURCES) \
- $(ASM_SOURCES) \
+ $(MESA_ASM_SOURCES) \
$(COMMON_DRIVER_SOURCES)
-
### Object files
MESA_OBJECTS = \
$(MESA_SOURCES:.c=.o) \
- $(ASM_SOURCES:.S=.o)
+ $(MESA_ASM_SOURCES:.S=.o)
GLAPI_OBJECTS = \
$(GLAPI_SOURCES:.c=.o) \
- $(ASM_API:.S=.o)
+ $(GLAPI_ASM_SOURCES:.S=.o)
COMMON_DRIVER_OBJECTS = $(COMMON_DRIVER_SOURCES:.c=.o)
@@ -301,5 +300,4 @@ COMMON_DRIVER_OBJECTS = $(COMMON_DRIVER_SOURCES:.c=.o)
INCLUDE_DIRS = \
-I$(TOP)/include \
- -I$(TOP)/src/mesa \
- -I$(TOP)/src/mesa/main
+ -I$(TOP)/src/mesa
diff --git a/src/mesa/sources.mak b/src/mesa/sources.mak
new file mode 100644
index 00000000000..8940670d5ba
--- /dev/null
+++ b/src/mesa/sources.mak
@@ -0,0 +1,350 @@
+### Lists of source files, included by Makefiles
+
+MAIN_SOURCES = \
+ main/api_arrayelt.c \
+ main/api_exec.c \
+ main/api_loopback.c \
+ main/api_noop.c \
+ main/api_validate.c \
+ main/accum.c \
+ main/attrib.c \
+ main/arrayobj.c \
+ main/blend.c \
+ main/bufferobj.c \
+ main/buffers.c \
+ main/clear.c \
+ main/clip.c \
+ main/colortab.c \
+ main/context.c \
+ main/convolve.c \
+ main/debug.c \
+ main/depth.c \
+ main/depthstencil.c \
+ main/dlist.c \
+ main/dlopen.c \
+ main/drawpix.c \
+ main/enable.c \
+ main/enums.c \
+ main/eval.c \
+ main/execmem.c \
+ main/extensions.c \
+ main/fbobject.c \
+ main/feedback.c \
+ main/ffvertex_prog.c \
+ main/fog.c \
+ main/framebuffer.c \
+ main/get.c \
+ main/getstring.c \
+ main/hash.c \
+ main/hint.c \
+ main/histogram.c \
+ main/image.c \
+ main/imports.c \
+ main/light.c \
+ main/lines.c \
+ main/matrix.c \
+ main/mipmap.c \
+ main/mm.c \
+ main/multisample.c \
+ main/pixel.c \
+ main/pixelstore.c \
+ main/points.c \
+ main/polygon.c \
+ main/queryobj.c \
+ main/rastpos.c \
+ main/rbadaptors.c \
+ main/readpix.c \
+ main/renderbuffer.c \
+ main/scissor.c \
+ main/shaders.c \
+ main/state.c \
+ main/stencil.c \
+ main/texcompress.c \
+ main/texcompress_s3tc.c \
+ main/texcompress_fxt1.c \
+ main/texenv.c \
+ main/texenvprogram.c \
+ main/texformat.c \
+ main/texgen.c \
+ main/teximage.c \
+ main/texobj.c \
+ main/texparam.c \
+ main/texrender.c \
+ main/texstate.c \
+ main/texstore.c \
+ main/varray.c \
+ main/vtxfmt.c
+
+GLAPI_SOURCES = \
+ main/dispatch.c \
+ glapi/glapi.c \
+ glapi/glapi_getproc.c \
+ glapi/glthread.c
+
+MATH_SOURCES = \
+ math/m_debug_clip.c \
+ math/m_debug_norm.c \
+ math/m_debug_xform.c \
+ math/m_eval.c \
+ math/m_matrix.c \
+ math/m_translate.c \
+ math/m_vector.c \
+ math/m_xform.c
+
+__SWRAST_SOURCES = \
+ swrast/s_aaline.c \
+ swrast/s_aatriangle.c \
+ swrast/s_accum.c \
+ swrast/s_alpha.c \
+ swrast/s_atifragshader.c \
+ swrast/s_bitmap.c \
+ swrast/s_blend.c \
+ swrast/s_blit.c \
+ swrast/s_buffers.c \
+ swrast/s_copypix.c \
+ swrast/s_context.c \
+ swrast/s_depth.c \
+ swrast/s_drawpix.c \
+ swrast/s_feedback.c \
+ swrast/s_fog.c \
+ swrast/s_fragprog.c \
+ swrast/s_imaging.c \
+ swrast/s_lines.c \
+ swrast/s_logic.c \
+ swrast/s_masking.c \
+ swrast/s_points.c \
+ swrast/s_readpix.c \
+ swrast/s_span.c \
+ swrast/s_stencil.c \
+ swrast/s_texcombine.c \
+ swrast/s_texfilter.c \
+ swrast/s_texstore.c \
+ swrast/s_triangle.c \
+ swrast/s_zoom.c
+
+__SWRAST_SETUP_SOURCES = \
+ swrast_setup/ss_context.c \
+ swrast_setup/ss_triangle.c
+
+__TNL_SOURCES = \
+ tnl/t_context.c \
+ tnl/t_pipeline.c \
+ tnl/t_draw.c \
+ tnl/t_rasterpos.c \
+ tnl/t_vb_program.c \
+ tnl/t_vb_render.c \
+ tnl/t_vb_texgen.c \
+ tnl/t_vb_texmat.c \
+ tnl/t_vb_vertex.c \
+ tnl/t_vb_cull.c \
+ tnl/t_vb_fog.c \
+ tnl/t_vb_light.c \
+ tnl/t_vb_normals.c \
+ tnl/t_vb_points.c \
+ tnl/t_vp_build.c \
+ tnl/t_vertex.c \
+ tnl/t_vertex_sse.c \
+ tnl/t_vertex_generic.c
+
+VBO_SOURCES = \
+ vbo/vbo_context.c \
+ vbo/vbo_exec.c \
+ vbo/vbo_exec_api.c \
+ vbo/vbo_exec_array.c \
+ vbo/vbo_exec_draw.c \
+ vbo/vbo_exec_eval.c \
+ vbo/vbo_rebase.c \
+ vbo/vbo_split.c \
+ vbo/vbo_split_copy.c \
+ vbo/vbo_split_inplace.c \
+ vbo/vbo_save.c \
+ vbo/vbo_save_api.c \
+ vbo/vbo_save_draw.c \
+ vbo/vbo_save_loopback.c
+
+__VF_SOURCES = \
+ vf/vf.c \
+ vf/vf_generic.c \
+ vf/vf_sse.c
+
+STATETRACKER_SOURCES = \
+ state_tracker/st_atom.c \
+ state_tracker/st_atom_blend.c \
+ state_tracker/st_atom_clip.c \
+ state_tracker/st_atom_constbuf.c \
+ state_tracker/st_atom_depth.c \
+ state_tracker/st_atom_framebuffer.c \
+ state_tracker/st_atom_pixeltransfer.c \
+ state_tracker/st_atom_sampler.c \
+ state_tracker/st_atom_scissor.c \
+ state_tracker/st_atom_shader.c \
+ state_tracker/st_atom_rasterizer.c \
+ state_tracker/st_atom_stipple.c \
+ state_tracker/st_atom_texture.c \
+ state_tracker/st_atom_viewport.c \
+ state_tracker/st_cb_accum.c \
+ state_tracker/st_cb_bitmap.c \
+ state_tracker/st_cb_blit.c \
+ state_tracker/st_cb_bufferobjects.c \
+ state_tracker/st_cb_clear.c \
+ state_tracker/st_cb_flush.c \
+ state_tracker/st_cb_get.c \
+ state_tracker/st_cb_drawpixels.c \
+ state_tracker/st_cb_fbo.c \
+ state_tracker/st_cb_feedback.c \
+ state_tracker/st_cb_program.c \
+ state_tracker/st_cb_queryobj.c \
+ state_tracker/st_cb_rasterpos.c \
+ state_tracker/st_cb_readpixels.c \
+ state_tracker/st_cb_strings.c \
+ state_tracker/st_cb_texture.c \
+ state_tracker/st_api.c \
+ state_tracker/st_context.c \
+ state_tracker/st_debug.c \
+ state_tracker/st_draw.c \
+ state_tracker/st_draw_feedback.c \
+ state_tracker/st_extensions.c \
+ state_tracker/st_format.c \
+ state_tracker/st_framebuffer.c \
+ state_tracker/st_gen_mipmap.c \
+ state_tracker/st_mesa_to_tgsi.c \
+ state_tracker/st_program.c \
+ state_tracker/st_texture.c
+
+SHADER_SOURCES = \
+ shader/arbprogparse.c \
+ shader/arbprogram.c \
+ shader/atifragshader.c \
+ shader/grammar/grammar_mesa.c \
+ shader/nvfragparse.c \
+ shader/nvprogram.c \
+ shader/nvvertparse.c \
+ shader/program.c \
+ shader/prog_cache.c \
+ shader/prog_debug.c \
+ shader/prog_execute.c \
+ shader/prog_instruction.c \
+ shader/prog_noise.c \
+ shader/prog_parameter.c \
+ shader/prog_print.c \
+ shader/prog_statevars.c \
+ shader/prog_uniform.c \
+ shader/programopt.c \
+ shader/shader_api.c \
+
+SLANG_SOURCES = \
+ shader/slang/slang_builtin.c \
+ shader/slang/slang_codegen.c \
+ shader/slang/slang_compile.c \
+ shader/slang/slang_compile_function.c \
+ shader/slang/slang_compile_operation.c \
+ shader/slang/slang_compile_struct.c \
+ shader/slang/slang_compile_variable.c \
+ shader/slang/slang_emit.c \
+ shader/slang/slang_ir.c \
+ shader/slang/slang_label.c \
+ shader/slang/slang_link.c \
+ shader/slang/slang_log.c \
+ shader/slang/slang_mem.c \
+ shader/slang/slang_preprocess.c \
+ shader/slang/slang_print.c \
+ shader/slang/slang_simplify.c \
+ shader/slang/slang_storage.c \
+ shader/slang/slang_typeinfo.c \
+ shader/slang/slang_vartable.c \
+ shader/slang/slang_utility.c
+
+ASM_C_SOURCES = \
+ x86/common_x86.c \
+ x86/x86.c \
+ x86/3dnow.c \
+ x86/sse.c \
+ sparc/sparc.c \
+ ppc/common_ppc.c \
+ x86-64/x86-64.c
+
+X86_SOURCES = \
+ x86/common_x86_asm.S \
+ x86/x86_xform2.S \
+ x86/x86_xform3.S \
+ x86/x86_xform4.S \
+ x86/x86_cliptest.S \
+ x86/mmx_blend.S \
+ x86/3dnow_xform1.S \
+ x86/3dnow_xform2.S \
+ x86/3dnow_xform3.S \
+ x86/3dnow_xform4.S \
+ x86/3dnow_normal.S \
+ x86/sse_xform1.S \
+ x86/sse_xform2.S \
+ x86/sse_xform3.S \
+ x86/sse_xform4.S \
+ x86/sse_normal.S \
+ x86/read_rgba_span_x86.S
+
+X86_API = \
+ x86/glapi_x86.S
+
+X86-64_SOURCES = \
+ x86-64/xform4.S
+
+X86-64_API = \
+ x86-64/glapi_x86-64.S
+
+SPARC_SOURCES = \
+ sparc/clip.S \
+ sparc/norm.S \
+ sparc/xform.S
+
+SPARC_API = \
+ sparc/glapi_sparc.S
+
+__COMMON_DRIVER_SOURCES = \
+ drivers/common/driverfuncs.c
+
+
+
+### All the core C sources
+
+MESA_SOURCES = \
+ $(MAIN_SOURCES) \
+ $(MATH_SOURCES) \
+ $(VBO_SOURCES) \
+ $(STATETRACKER_SOURCES) \
+ $(TNL_SOURCES) \
+ $(SHADER_SOURCES) \
+ $(SWRAST_SOURCES) \
+ $(SWRAST_SETUP_SOURCES) \
+ $(ASM_C_SOURCES) \
+ $(SLANG_SOURCES)
+
+ALL_SOURCES = \
+ $(MESA_SOURCES) \
+ $(GLAPI_SOURCES) \
+ $(MESA_ASM_SOURCES) \
+ $(COMMON_DRIVER_SOURCES)
+
+
+### Object files
+
+MESA_OBJECTS = \
+ $(MESA_SOURCES:.c=.o) \
+ $(MESA_ASM_SOURCES:.S=.o)
+
+GLAPI_OBJECTS = \
+ $(GLAPI_SOURCES:.c=.o) \
+ $(GLAPI_ASM_SOURCES:.S=.o)
+
+
+COMMON_DRIVER_OBJECTS = $(COMMON_DRIVER_SOURCES:.c=.o)
+
+
+
+### Include directories
+
+INCLUDE_DIRS = \
+ -I$(TOP)/include \
+ -I$(TOP)/src/mesa \
+ -I$(TOP)/src/gallium/include \
+ -I$(TOP)/src/gallium/drivers \
+ -I$(TOP)/src/gallium/auxiliary
diff --git a/src/mesa/state_tracker/Makefile b/src/mesa/state_tracker/Makefile
new file mode 100644
index 00000000000..0ab1dc6e6bd
--- /dev/null
+++ b/src/mesa/state_tracker/Makefile
@@ -0,0 +1,2 @@
+default:
+ cd ../.. ; make \ No newline at end of file
diff --git a/src/mesa/state_tracker/st_api.c b/src/mesa/state_tracker/st_api.c
new file mode 100644
index 00000000000..fc0e9a23164
--- /dev/null
+++ b/src/mesa/state_tracker/st_api.c
@@ -0,0 +1,33 @@
+/**************************************************************************
+ *
+ * Copyright 2008 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.
+ *
+ **************************************************************************/
+
+
+/**
+ * Just a global symbol for EGL to look for to identify the supported
+ * graphics API.
+ */
+int st_api_OpenGL = 1;
diff --git a/src/mesa/state_tracker/st_atom.c b/src/mesa/state_tracker/st_atom.c
new file mode 100644
index 00000000000..fc8587f4598
--- /dev/null
+++ b/src/mesa/state_tracker/st_atom.c
@@ -0,0 +1,218 @@
+/**************************************************************************
+ *
+ * Copyright 2003 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.
+ *
+ **************************************************************************/
+
+
+#include "main/glheader.h"
+#include "main/context.h"
+
+#include "pipe/p_defines.h"
+#include "st_context.h"
+#include "st_atom.h"
+#include "st_cb_bitmap.h"
+#include "st_program.h"
+
+
+
+/* This is used to initialize st->atoms[]. We could use this list
+ * directly except for a single atom, st_update_constants, which has a
+ * .dirty value which changes according to the parameters of the
+ * current fragment and vertex programs, and so cannot be a static
+ * value.
+ */
+static const struct st_tracked_state *atoms[] =
+{
+ &st_update_depth_stencil_alpha,
+ &st_update_clip,
+
+ &st_finalize_textures,
+ &st_update_shader,
+
+ &st_update_rasterizer,
+ &st_update_polygon_stipple,
+ &st_update_viewport,
+ &st_update_scissor,
+ &st_update_blend,
+ &st_update_sampler,
+ &st_update_texture,
+ &st_update_framebuffer,
+ &st_update_vs_constants,
+ &st_update_fs_constants,
+ &st_update_pixel_transfer
+};
+
+
+void st_init_atoms( struct st_context *st )
+{
+ GLuint i;
+
+ st->atoms = malloc(sizeof(atoms));
+ st->nr_atoms = sizeof(atoms)/sizeof(*atoms);
+ memcpy(st->atoms, atoms, sizeof(atoms));
+
+ /* Patch in a pointer to the dynamic state atom:
+ */
+ for (i = 0; i < st->nr_atoms; i++) {
+ if (st->atoms[i] == &st_update_vs_constants) {
+ st->atoms[i] = &st->constants.tracked_state[PIPE_SHADER_VERTEX];
+ st->atoms[i][0] = st_update_vs_constants;
+ }
+
+ if (st->atoms[i] == &st_update_fs_constants) {
+ st->atoms[i] = &st->constants.tracked_state[PIPE_SHADER_FRAGMENT];
+ st->atoms[i][0] = st_update_fs_constants;
+ }
+ }
+}
+
+
+void st_destroy_atoms( struct st_context *st )
+{
+ if (st->atoms) {
+ free(st->atoms);
+ st->atoms = NULL;
+ }
+}
+
+
+/***********************************************************************
+ */
+
+static GLboolean check_state( const struct st_state_flags *a,
+ const struct st_state_flags *b )
+{
+ return ((a->mesa & b->mesa) ||
+ (a->st & b->st));
+}
+
+static void accumulate_state( struct st_state_flags *a,
+ const struct st_state_flags *b )
+{
+ a->mesa |= b->mesa;
+ a->st |= b->st;
+}
+
+
+static void xor_states( struct st_state_flags *result,
+ const struct st_state_flags *a,
+ const struct st_state_flags *b )
+{
+ result->mesa = a->mesa ^ b->mesa;
+ result->st = a->st ^ b->st;
+}
+
+
+/* Too complex to figure out, just check every time:
+ */
+static void check_program_state( struct st_context *st )
+{
+ GLcontext *ctx = st->ctx;
+
+ if (ctx->VertexProgram._Current != &st->vp->Base)
+ st->dirty.st |= ST_NEW_VERTEX_PROGRAM;
+
+ if (ctx->FragmentProgram._Current != &st->fp->Base)
+ st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
+
+}
+
+
+/***********************************************************************
+ * Update all derived state:
+ */
+
+void st_validate_state( struct st_context *st )
+{
+ struct st_state_flags *state = &st->dirty;
+ GLuint i;
+
+ /* The bitmap cache is immune to pixel unpack changes.
+ * Note that GLUT makes several calls to glPixelStore for each
+ * bitmap char it draws so this is an important check.
+ */
+ if (state->mesa & ~_NEW_PACKUNPACK)
+ st_flush_bitmap_cache(st);
+
+ check_program_state( st );
+
+ if (state->st == 0)
+ return;
+
+// _mesa_printf("%s %x/%x\n", __FUNCTION__, state->mesa, state->st);
+
+ if (1) {
+ /* Debug version which enforces various sanity checks on the
+ * state flags which are generated and checked to help ensure
+ * state atoms are ordered correctly in the list.
+ */
+ struct st_state_flags examined, prev;
+ memset(&examined, 0, sizeof(examined));
+ prev = *state;
+
+ for (i = 0; i < st->nr_atoms; i++) {
+ const struct st_tracked_state *atom = st->atoms[i];
+ struct st_state_flags generated;
+
+// _mesa_printf("atom %s %x/%x\n", atom->name, atom->dirty.mesa, atom->dirty.st);
+
+ if (!(atom->dirty.mesa || atom->dirty.st) ||
+ !atom->update) {
+ _mesa_printf("malformed atom %s\n", atom->name);
+ assert(0);
+ }
+
+ if (check_state(state, &atom->dirty)) {
+ st->atoms[i]->update( st );
+// _mesa_printf("after: %x\n", atom->dirty.mesa);
+ }
+
+ accumulate_state(&examined, &atom->dirty);
+
+ /* generated = (prev ^ state)
+ * if (examined & generated)
+ * fail;
+ */
+ xor_states(&generated, &prev, state);
+ assert(!check_state(&examined, &generated));
+ prev = *state;
+ }
+// _mesa_printf("\n");
+
+ }
+ else {
+ const GLuint nr = st->nr_atoms;
+
+ for (i = 0; i < nr; i++) {
+ if (check_state(state, &st->atoms[i]->dirty))
+ st->atoms[i]->update( st );
+ }
+ }
+
+ memset(state, 0, sizeof(*state));
+}
+
+
+
diff --git a/src/mesa/state_tracker/st_atom.h b/src/mesa/state_tracker/st_atom.h
new file mode 100644
index 00000000000..c7cffd85c8a
--- /dev/null
+++ b/src/mesa/state_tracker/st_atom.h
@@ -0,0 +1,66 @@
+/**************************************************************************
+ *
+ * Copyright 2003 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.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <[email protected]>
+ */
+
+
+#ifndef ST_ATOM_H
+#define ST_ATOM_H
+
+struct st_context;
+struct st_tracked_state;
+
+void st_init_atoms( struct st_context *st );
+void st_destroy_atoms( struct st_context *st );
+
+
+void st_validate_state( struct st_context *st );
+
+
+extern const struct st_tracked_state st_update_framebuffer;
+extern const struct st_tracked_state st_update_clip;
+extern const struct st_tracked_state st_update_depth_stencil_alpha;
+extern const struct st_tracked_state st_update_shader;
+extern const struct st_tracked_state st_update_rasterizer;
+extern const struct st_tracked_state st_update_polygon_stipple;
+extern const struct st_tracked_state st_update_viewport;
+extern const struct st_tracked_state st_update_scissor;
+extern const struct st_tracked_state st_update_blend;
+extern const struct st_tracked_state st_update_sampler;
+extern const struct st_tracked_state st_update_texture;
+extern const struct st_tracked_state st_finalize_textures;
+extern const struct st_tracked_state st_update_fs_constants;
+extern const struct st_tracked_state st_update_vs_constants;
+extern const struct st_tracked_state st_update_pixel_transfer;
+
+
+uint st_compare_func_to_pipe(GLenum func);
+
+#endif
diff --git a/src/mesa/state_tracker/st_atom_blend.c b/src/mesa/state_tracker/st_atom_blend.c
new file mode 100644
index 00000000000..35c09c3e08f
--- /dev/null
+++ b/src/mesa/state_tracker/st_atom_blend.c
@@ -0,0 +1,232 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <[email protected]>
+ * Brian Paul
+ */
+
+
+#include "st_context.h"
+#include "st_atom.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "cso_cache/cso_context.h"
+
+#include "main/macros.h"
+
+/**
+ * Convert GLenum blend tokens to pipe tokens.
+ * Both blend factors and blend funcs are accepted.
+ */
+static GLuint
+translate_blend(GLenum blend)
+{
+ switch (blend) {
+ /* blend functions */
+ case GL_FUNC_ADD:
+ return PIPE_BLEND_ADD;
+ case GL_FUNC_SUBTRACT:
+ return PIPE_BLEND_SUBTRACT;
+ case GL_FUNC_REVERSE_SUBTRACT:
+ return PIPE_BLEND_REVERSE_SUBTRACT;
+ case GL_MIN:
+ return PIPE_BLEND_MIN;
+ case GL_MAX:
+ return PIPE_BLEND_MAX;
+
+ /* blend factors */
+ case GL_ONE:
+ return PIPE_BLENDFACTOR_ONE;
+ case GL_SRC_COLOR:
+ return PIPE_BLENDFACTOR_SRC_COLOR;
+ case GL_SRC_ALPHA:
+ return PIPE_BLENDFACTOR_SRC_ALPHA;
+ case GL_DST_ALPHA:
+ return PIPE_BLENDFACTOR_DST_ALPHA;
+ case GL_DST_COLOR:
+ return PIPE_BLENDFACTOR_DST_COLOR;
+ case GL_SRC_ALPHA_SATURATE:
+ return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE;
+ case GL_CONSTANT_COLOR:
+ return PIPE_BLENDFACTOR_CONST_COLOR;
+ case GL_CONSTANT_ALPHA:
+ return PIPE_BLENDFACTOR_CONST_ALPHA;
+ /*
+ return PIPE_BLENDFACTOR_SRC1_COLOR;
+ return PIPE_BLENDFACTOR_SRC1_ALPHA;
+ */
+ case GL_ZERO:
+ return PIPE_BLENDFACTOR_ZERO;
+ case GL_ONE_MINUS_SRC_COLOR:
+ return PIPE_BLENDFACTOR_INV_SRC_COLOR;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ return PIPE_BLENDFACTOR_INV_SRC_ALPHA;
+ case GL_ONE_MINUS_DST_COLOR:
+ return PIPE_BLENDFACTOR_INV_DST_COLOR;
+ case GL_ONE_MINUS_DST_ALPHA:
+ return PIPE_BLENDFACTOR_INV_DST_ALPHA;
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ return PIPE_BLENDFACTOR_INV_CONST_COLOR;
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ return PIPE_BLENDFACTOR_INV_CONST_ALPHA;
+ /*
+ return PIPE_BLENDFACTOR_INV_SRC1_COLOR;
+ return PIPE_BLENDFACTOR_INV_SRC1_ALPHA;
+ */
+ default:
+ assert("invalid GL token in translate_blend()" == NULL);
+ return 0;
+ }
+}
+
+
+/**
+ * Convert GLenum logicop tokens to pipe tokens.
+ */
+static GLuint
+translate_logicop(GLenum logicop)
+{
+ switch (logicop) {
+ case GL_CLEAR:
+ return PIPE_LOGICOP_CLEAR;
+ case GL_NOR:
+ return PIPE_LOGICOP_NOR;
+ case GL_AND_INVERTED:
+ return PIPE_LOGICOP_AND_INVERTED;
+ case GL_COPY_INVERTED:
+ return PIPE_LOGICOP_COPY_INVERTED;
+ case GL_AND_REVERSE:
+ return PIPE_LOGICOP_AND_REVERSE;
+ case GL_INVERT:
+ return PIPE_LOGICOP_INVERT;
+ case GL_XOR:
+ return PIPE_LOGICOP_XOR;
+ case GL_NAND:
+ return PIPE_LOGICOP_NAND;
+ case GL_AND:
+ return PIPE_LOGICOP_AND;
+ case GL_EQUIV:
+ return PIPE_LOGICOP_EQUIV;
+ case GL_NOOP:
+ return PIPE_LOGICOP_NOOP;
+ case GL_OR_INVERTED:
+ return PIPE_LOGICOP_OR_INVERTED;
+ case GL_COPY:
+ return PIPE_LOGICOP_COPY;
+ case GL_OR_REVERSE:
+ return PIPE_LOGICOP_OR_REVERSE;
+ case GL_OR:
+ return PIPE_LOGICOP_OR;
+ case GL_SET:
+ return PIPE_LOGICOP_SET;
+ default:
+ assert("invalid GL token in translate_logicop()" == NULL);
+ return 0;
+ }
+}
+
+
+static void
+update_blend( struct st_context *st )
+{
+ struct pipe_blend_state *blend = &st->state.blend;
+
+ memset(blend, 0, sizeof(*blend));
+
+ if (st->ctx->Color.ColorLogicOpEnabled ||
+ (st->ctx->Color.BlendEnabled &&
+ st->ctx->Color.BlendEquationRGB == GL_LOGIC_OP)) {
+ /* logicop enabled */
+ blend->logicop_enable = 1;
+ blend->logicop_func = translate_logicop(st->ctx->Color.LogicOp);
+ }
+ else if (st->ctx->Color.BlendEnabled) {
+ /* blending enabled */
+ blend->blend_enable = 1;
+
+ blend->rgb_func = translate_blend(st->ctx->Color.BlendEquationRGB);
+ if (st->ctx->Color.BlendEquationRGB == GL_MIN ||
+ st->ctx->Color.BlendEquationRGB == GL_MAX) {
+ /* Min/max are special */
+ blend->rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend->rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
+ }
+ else {
+ blend->rgb_src_factor = translate_blend(st->ctx->Color.BlendSrcRGB);
+ blend->rgb_dst_factor = translate_blend(st->ctx->Color.BlendDstRGB);
+ }
+
+ blend->alpha_func = translate_blend(st->ctx->Color.BlendEquationA);
+ if (st->ctx->Color.BlendEquationA == GL_MIN ||
+ st->ctx->Color.BlendEquationA == GL_MAX) {
+ /* Min/max are special */
+ blend->alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend->alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
+ }
+ else {
+ blend->alpha_src_factor = translate_blend(st->ctx->Color.BlendSrcA);
+ blend->alpha_dst_factor = translate_blend(st->ctx->Color.BlendDstA);
+ }
+ }
+ else {
+ /* no blending / logicop */
+ }
+
+ /* Colormask - maybe reverse these bits? */
+ if (st->ctx->Color.ColorMask[0])
+ blend->colormask |= PIPE_MASK_R;
+ if (st->ctx->Color.ColorMask[1])
+ blend->colormask |= PIPE_MASK_G;
+ if (st->ctx->Color.ColorMask[2])
+ blend->colormask |= PIPE_MASK_B;
+ if (st->ctx->Color.ColorMask[3])
+ blend->colormask |= PIPE_MASK_A;
+
+ if (st->ctx->Color.DitherFlag)
+ blend->dither = 1;
+
+ cso_set_blend(st->cso_context, blend);
+
+ {
+ struct pipe_blend_color bc;
+ COPY_4FV(bc.color, st->ctx->Color.BlendColor);
+ cso_set_blend_color(st->cso_context, &bc);
+ }
+}
+
+
+const struct st_tracked_state st_update_blend = {
+ "st_update_blend", /* name */
+ { /* dirty */
+ (_NEW_COLOR), /* XXX _NEW_BLEND someday? */ /* mesa */
+ 0, /* st */
+ },
+ update_blend, /* update */
+};
diff --git a/src/mesa/state_tracker/st_atom_clip.c b/src/mesa/state_tracker/st_atom_clip.c
new file mode 100644
index 00000000000..23d709b814c
--- /dev/null
+++ b/src/mesa/state_tracker/st_atom_clip.c
@@ -0,0 +1,71 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <[email protected]>
+ */
+
+
+#include "st_context.h"
+#include "pipe/p_context.h"
+#include "st_atom.h"
+
+
+/* Second state atom for user clip planes:
+ */
+static void update_clip( struct st_context *st )
+{
+ struct pipe_clip_state clip;
+ GLuint i;
+
+ memset(&clip, 0, sizeof(clip));
+
+ for (i = 0; i < PIPE_MAX_CLIP_PLANES; i++) {
+ if (st->ctx->Transform.ClipPlanesEnabled & (1 << i)) {
+ memcpy(clip.ucp[clip.nr],
+ st->ctx->Transform._ClipUserPlane[i],
+ sizeof(clip.ucp[0]));
+ clip.nr++;
+ }
+ }
+
+ if (memcmp(&clip, &st->state.clip, sizeof(clip)) != 0) {
+ st->state.clip = clip;
+ st->pipe->set_clip_state(st->pipe, &clip);
+ }
+}
+
+
+const struct st_tracked_state st_update_clip = {
+ "st_update_clip", /* name */
+ { /* dirty */
+ (_NEW_TRANSFORM), /* mesa */
+ 0, /* st */
+ },
+ update_clip /* update */
+};
diff --git a/src/mesa/state_tracker/st_atom_constbuf.c b/src/mesa/state_tracker/st_atom_constbuf.c
new file mode 100644
index 00000000000..514b10cd022
--- /dev/null
+++ b/src/mesa/state_tracker/st_atom_constbuf.c
@@ -0,0 +1,140 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <[email protected]>
+ * Brian Paul
+ */
+
+#include "main/imports.h"
+#include "shader/prog_parameter.h"
+#include "shader/prog_print.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "st_atom_constbuf.h"
+#include "st_program.h"
+
+
+/**
+ * Pass the given program parameters to the graphics pipe as a
+ * constant buffer.
+ * \param id either PIPE_SHADER_VERTEX or PIPE_SHADER_FRAGMENT
+ */
+void st_upload_constants( struct st_context *st,
+ struct gl_program_parameter_list *params,
+ unsigned id)
+{
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_constant_buffer *cbuf = &st->state.constants[id];
+
+ assert(id == PIPE_SHADER_VERTEX || id == PIPE_SHADER_FRAGMENT);
+
+ /* update constants */
+ if (params && params->NumParameters) {
+ const uint paramBytes = params->NumParameters * sizeof(GLfloat) * 4;
+
+ /* Update our own dependency flags. This works because this
+ * function will also be called whenever the program changes.
+ */
+ st->constants.tracked_state[id].dirty.mesa =
+ (params->StateFlags | _NEW_PROGRAM);
+
+ _mesa_load_state_parameters(st->ctx, params);
+
+ /* We always need to get a new buffer, to keep the drivers simple and
+ * avoid gratuitous rendering synchronization.
+ */
+ pipe_buffer_reference(pipe->screen, &cbuf->buffer, NULL );
+ cbuf->buffer = pipe_buffer_create(pipe->screen, 16, PIPE_BUFFER_USAGE_CONSTANT,
+ paramBytes );
+
+ if (0)
+ {
+ printf("%s(shader=%d, numParams=%d, stateFlags=0x%x)\n",
+ __FUNCTION__, id, params->NumParameters, params->StateFlags);
+ _mesa_print_parameter_list(params);
+ }
+
+ /* load Mesa constants into the constant buffer */
+ if (cbuf->buffer) {
+ void *map = pipe_buffer_map(pipe->screen, cbuf->buffer,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+ memcpy(map, params->ParameterValues, paramBytes);
+ pipe_buffer_unmap(pipe->screen, cbuf->buffer);
+ }
+
+ st->pipe->set_constant_buffer(st->pipe, id, 0, cbuf);
+ }
+ else {
+ st->constants.tracked_state[id].dirty.mesa = 0;
+ // st->pipe->set_constant_buffer(st->pipe, id, 0, NULL);
+ }
+}
+
+/* Vertex shader:
+ */
+static void update_vs_constants(struct st_context *st )
+{
+ struct st_vertex_program *vp = st->vp;
+ struct gl_program_parameter_list *params = vp->Base.Base.Parameters;
+
+ st_upload_constants( st, params, PIPE_SHADER_VERTEX );
+}
+
+const struct st_tracked_state st_update_vs_constants = {
+ "st_update_vs_constants", /* name */
+ { /* dirty */
+ 0, /* set dynamically above */ /* mesa */
+ ST_NEW_VERTEX_PROGRAM, /* st */
+ },
+ update_vs_constants /* update */
+};
+
+/* Fragment shader:
+ */
+static void update_fs_constants(struct st_context *st )
+{
+ struct st_fragment_program *fp = st->fp;
+ struct gl_program_parameter_list *params = fp->Base.Base.Parameters;
+
+ st_upload_constants( st, params, PIPE_SHADER_FRAGMENT );
+}
+
+const struct st_tracked_state st_update_fs_constants = {
+ "st_update_fs_constants", /* name */
+ { /* dirty */
+ 0, /* set dynamically above */ /* mesa */
+ ST_NEW_FRAGMENT_PROGRAM, /* st */
+ },
+ update_fs_constants /* update */
+};
+
diff --git a/src/mesa/state_tracker/st_atom_constbuf.h b/src/mesa/state_tracker/st_atom_constbuf.h
new file mode 100644
index 00000000000..f707534e2cf
--- /dev/null
+++ b/src/mesa/state_tracker/st_atom_constbuf.h
@@ -0,0 +1,38 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_ATOM_CONSTBUF_H
+#define ST_ATOM_CONSTBUF_H
+
+
+void st_upload_constants( struct st_context *st,
+ struct gl_program_parameter_list *params,
+ unsigned id);
+
+
+#endif /* ST_ATOM_CONSTBUF_H */
diff --git a/src/mesa/state_tracker/st_atom_depth.c b/src/mesa/state_tracker/st_atom_depth.c
new file mode 100644
index 00000000000..2d617bd95dc
--- /dev/null
+++ b/src/mesa/state_tracker/st_atom_depth.c
@@ -0,0 +1,151 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <[email protected]>
+ * Brian Paul
+ * Zack Rusin
+ */
+
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "cso_cache/cso_context.h"
+
+
+/**
+ * Convert an OpenGL compare mode to a pipe tokens.
+ */
+GLuint
+st_compare_func_to_pipe(GLenum func)
+{
+ /* Same values, just biased */
+ assert(PIPE_FUNC_NEVER == GL_NEVER - GL_NEVER);
+ assert(PIPE_FUNC_LESS == GL_LESS - GL_NEVER);
+ assert(PIPE_FUNC_EQUAL == GL_EQUAL - GL_NEVER);
+ assert(PIPE_FUNC_LEQUAL == GL_LEQUAL - GL_NEVER);
+ assert(PIPE_FUNC_GREATER == GL_GREATER - GL_NEVER);
+ assert(PIPE_FUNC_NOTEQUAL == GL_NOTEQUAL - GL_NEVER);
+ assert(PIPE_FUNC_GEQUAL == GL_GEQUAL - GL_NEVER);
+ assert(PIPE_FUNC_ALWAYS == GL_ALWAYS - GL_NEVER);
+ assert(func >= GL_NEVER);
+ assert(func <= GL_ALWAYS);
+ return func - GL_NEVER;
+}
+
+
+/**
+ * Convert GLenum stencil op tokens to pipe tokens.
+ */
+static GLuint
+gl_stencil_op_to_pipe(GLenum func)
+{
+ switch (func) {
+ case GL_KEEP:
+ return PIPE_STENCIL_OP_KEEP;
+ case GL_ZERO:
+ return PIPE_STENCIL_OP_ZERO;
+ case GL_REPLACE:
+ return PIPE_STENCIL_OP_REPLACE;
+ case GL_INCR:
+ return PIPE_STENCIL_OP_INCR;
+ case GL_DECR:
+ return PIPE_STENCIL_OP_DECR;
+ case GL_INCR_WRAP:
+ return PIPE_STENCIL_OP_INCR_WRAP;
+ case GL_DECR_WRAP:
+ return PIPE_STENCIL_OP_DECR_WRAP;
+ case GL_INVERT:
+ return PIPE_STENCIL_OP_INVERT;
+ default:
+ assert("invalid GL token in gl_stencil_op_to_pipe()" == NULL);
+ return 0;
+ }
+}
+
+static void
+update_depth_stencil_alpha(struct st_context *st)
+{
+ struct pipe_depth_stencil_alpha_state *dsa = &st->state.depth_stencil;
+
+ memset(dsa, 0, sizeof(*dsa));
+
+ dsa->depth.enabled = st->ctx->Depth.Test;
+ dsa->depth.writemask = st->ctx->Depth.Mask;
+ dsa->depth.func = st_compare_func_to_pipe(st->ctx->Depth.Func);
+
+ if (st->ctx->Query.CurrentOcclusionObject &&
+ st->ctx->Query.CurrentOcclusionObject->Active)
+ dsa->depth.occlusion_count = 1;
+
+ if (st->ctx->Stencil.Enabled && st->ctx->Visual.stencilBits > 0) {
+ dsa->stencil[0].enabled = 1;
+ dsa->stencil[0].func = st_compare_func_to_pipe(st->ctx->Stencil.Function[0]);
+ dsa->stencil[0].fail_op = gl_stencil_op_to_pipe(st->ctx->Stencil.FailFunc[0]);
+ dsa->stencil[0].zfail_op = gl_stencil_op_to_pipe(st->ctx->Stencil.ZFailFunc[0]);
+ dsa->stencil[0].zpass_op = gl_stencil_op_to_pipe(st->ctx->Stencil.ZPassFunc[0]);
+ dsa->stencil[0].ref_value = st->ctx->Stencil.Ref[0] & 0xff;
+ dsa->stencil[0].valuemask = st->ctx->Stencil.ValueMask[0] & 0xff;
+ dsa->stencil[0].writemask = st->ctx->Stencil.WriteMask[0] & 0xff;
+
+ if (st->ctx->Stencil._TestTwoSide) {
+ dsa->stencil[1].enabled = 1;
+ dsa->stencil[1].func = st_compare_func_to_pipe(st->ctx->Stencil.Function[1]);
+ dsa->stencil[1].fail_op = gl_stencil_op_to_pipe(st->ctx->Stencil.FailFunc[1]);
+ dsa->stencil[1].zfail_op = gl_stencil_op_to_pipe(st->ctx->Stencil.ZFailFunc[1]);
+ dsa->stencil[1].zpass_op = gl_stencil_op_to_pipe(st->ctx->Stencil.ZPassFunc[1]);
+ dsa->stencil[1].ref_value = st->ctx->Stencil.Ref[1] & 0xff;
+ dsa->stencil[1].valuemask = st->ctx->Stencil.ValueMask[1] & 0xff;
+ dsa->stencil[1].writemask = st->ctx->Stencil.WriteMask[1] & 0xff;
+ }
+ else {
+ dsa->stencil[1] = dsa->stencil[0];
+ dsa->stencil[1].enabled = 0;
+ }
+ }
+
+ if (st->ctx->Color.AlphaEnabled) {
+ dsa->alpha.enabled = 1;
+ dsa->alpha.func = st_compare_func_to_pipe(st->ctx->Color.AlphaFunc);
+ dsa->alpha.ref_value = st->ctx->Color.AlphaRef;
+ }
+
+ cso_set_depth_stencil_alpha(st->cso_context, dsa);
+}
+
+
+const struct st_tracked_state st_update_depth_stencil_alpha = {
+ "st_update_depth_stencil", /* name */
+ { /* dirty */
+ (_NEW_DEPTH|_NEW_STENCIL|_NEW_COLOR), /* mesa */
+ 0, /* st */
+ },
+ update_depth_stencil_alpha /* update */
+};
diff --git a/src/mesa/state_tracker/st_atom_framebuffer.c b/src/mesa/state_tracker/st_atom_framebuffer.c
new file mode 100644
index 00000000000..625efdd66b5
--- /dev/null
+++ b/src/mesa/state_tracker/st_atom_framebuffer.c
@@ -0,0 +1,176 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <[email protected]>
+ * Brian Paul
+ */
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "st_cb_fbo.h"
+#include "st_public.h"
+#include "st_texture.h"
+#include "pipe/p_context.h"
+#include "pipe/p_inlines.h"
+#include "cso_cache/cso_context.h"
+
+
+
+/**
+ * When doing GL render to texture, we have to be sure that finalize_texture()
+ * didn't yank out the pipe_texture that we earlier created a surface for.
+ * Check for that here and create a new surface if needed.
+ */
+static void
+update_renderbuffer_surface(struct st_context *st,
+ struct st_renderbuffer *strb)
+{
+ struct pipe_screen *screen = st->pipe->screen;
+ struct pipe_texture *texture = strb->rtt->pt;
+ int rtt_width = strb->Base.Width;
+ int rtt_height = strb->Base.Height;
+
+ if (!strb->surface ||
+ strb->surface->texture != texture ||
+ strb->surface->width != rtt_width ||
+ strb->surface->height != rtt_height) {
+ GLuint level;
+ /* find matching mipmap level size */
+ for (level = 0; level <= texture->last_level; level++) {
+ if (texture->width[level] == rtt_width &&
+ texture->height[level] == rtt_height) {
+
+ pipe_surface_reference(&strb->surface, NULL);
+
+ strb->surface = screen->get_tex_surface(screen,
+ texture,
+ strb->rtt_face,
+ level,
+ strb->rtt_slice,
+ PIPE_BUFFER_USAGE_GPU_READ |
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+#if 0
+ printf("-- alloc new surface %d x %d into tex %p\n",
+ strb->surface->width, strb->surface->height,
+ texture);
+#endif
+ break;
+ }
+ }
+ }
+}
+
+
+/**
+ * Update framebuffer state (color, depth, stencil, etc. buffers)
+ */
+static void
+update_framebuffer_state( struct st_context *st )
+{
+ struct pipe_framebuffer_state *framebuffer = &st->state.framebuffer;
+ struct gl_framebuffer *fb = st->ctx->DrawBuffer;
+ struct st_renderbuffer *strb;
+ GLuint i;
+
+ memset(framebuffer, 0, sizeof(*framebuffer));
+
+ framebuffer->width = fb->Width;
+ framebuffer->height = fb->Height;
+
+ /*printf("------ fb size %d x %d\n", fb->Width, fb->Height);*/
+
+ /* Examine Mesa's ctx->DrawBuffer->_ColorDrawBuffers state
+ * to determine which surfaces to draw to
+ */
+ framebuffer->nr_cbufs = 0;
+ for (i = 0; i < fb->_NumColorDrawBuffers; i++) {
+ strb = st_renderbuffer(fb->_ColorDrawBuffers[i]);
+
+ /*printf("--------- framebuffer surface rtt %p\n", strb->rtt);*/
+ if (strb->rtt) {
+ /* rendering to a GL texture, may have to update surface */
+ update_renderbuffer_surface(st, strb);
+ }
+
+ if (strb->surface) {
+ framebuffer->cbufs[framebuffer->nr_cbufs] = strb->surface;
+ framebuffer->nr_cbufs++;
+ }
+ }
+
+ strb = st_renderbuffer(fb->Attachment[BUFFER_DEPTH].Renderbuffer);
+ if (strb) {
+ strb = st_renderbuffer(strb->Base.Wrapped);
+ if (strb->rtt) {
+ /* rendering to a GL texture, may have to update surface */
+ update_renderbuffer_surface(st, strb);
+ }
+
+ framebuffer->zsbuf = strb->surface;
+ }
+ else {
+ strb = st_renderbuffer(fb->Attachment[BUFFER_STENCIL].Renderbuffer);
+ if (strb) {
+ strb = st_renderbuffer(strb->Base.Wrapped);
+ assert(strb->surface);
+ framebuffer->zsbuf = strb->surface;
+ }
+ }
+
+ cso_set_framebuffer(st->cso_context, framebuffer);
+
+ if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) {
+ if (st->frontbuffer_status == FRONT_STATUS_COPY_OF_BACK) {
+ /* copy back color buffer to front color buffer */
+ struct st_framebuffer *stfb = (struct st_framebuffer *) fb;
+ struct pipe_surface *surf_front, *surf_back;
+ (void) st_get_framebuffer_surface(stfb, ST_SURFACE_FRONT_LEFT, &surf_front);
+ (void) st_get_framebuffer_surface(stfb, ST_SURFACE_BACK_LEFT, &surf_back);
+
+ st->pipe->surface_copy(st->pipe,
+ FALSE,
+ surf_front, 0, 0, /* dest */
+ surf_back, 0, 0, /* src */
+ fb->Width, fb->Height);
+ }
+ /* we're assuming we'll really draw to the front buffer */
+ st->frontbuffer_status = FRONT_STATUS_DIRTY;
+ }
+}
+
+
+const struct st_tracked_state st_update_framebuffer = {
+ "st_update_framebuffer", /* name */
+ { /* dirty */
+ _NEW_BUFFERS, /* mesa */
+ ST_NEW_FRAMEBUFFER, /* st */
+ },
+ update_framebuffer_state /* update */
+};
+
diff --git a/src/mesa/state_tracker/st_atom_pixeltransfer.c b/src/mesa/state_tracker/st_atom_pixeltransfer.c
new file mode 100644
index 00000000000..a357b716771
--- /dev/null
+++ b/src/mesa/state_tracker/st_atom_pixeltransfer.c
@@ -0,0 +1,474 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+/*
+ * Generate fragment programs to implement pixel transfer ops, such as
+ * scale/bias, colormatrix, colortable, convolution...
+ *
+ * Authors:
+ * Brian Paul
+ */
+
+#include "main/imports.h"
+#include "main/image.h"
+#include "main/macros.h"
+#include "shader/program.h"
+#include "shader/prog_instruction.h"
+#include "shader/prog_parameter.h"
+#include "shader/prog_print.h"
+
+#include "st_context.h"
+#include "st_format.h"
+#include "st_program.h"
+#include "st_texture.h"
+
+#include "pipe/p_screen.h"
+#include "pipe/p_context.h"
+#include "pipe/p_inlines.h"
+#include "util/u_pack_color.h"
+
+
+struct state_key
+{
+ GLuint scaleAndBias:1;
+ GLuint colorMatrix:1;
+ GLuint colorMatrixPostScaleBias:1;
+ GLuint pixelMaps:1;
+
+#if 0
+ GLfloat Maps[3][256][4];
+ int NumMaps;
+ GLint NumStages;
+ pipeline_stage Stages[STAGE_MAX];
+ GLboolean StagesUsed[STAGE_MAX];
+ GLfloat Scale1[4], Bias1[4];
+ GLfloat Scale2[4], Bias2[4];
+#endif
+};
+
+
+static GLboolean
+is_identity(const GLfloat m[16])
+{
+ GLuint i;
+ for (i = 0; i < 16; i++) {
+ const int row = i % 4, col = i / 4;
+ const float val = (GLfloat)(row == col);
+ if (m[i] != val)
+ return GL_FALSE;
+ }
+ return GL_TRUE;
+}
+
+
+static void
+make_state_key(GLcontext *ctx, struct state_key *key)
+{
+ static const GLfloat zero[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
+ static const GLfloat one[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
+
+ memset(key, 0, sizeof(*key));
+
+ if (ctx->Pixel.RedBias != 0.0 || ctx->Pixel.RedScale != 1.0 ||
+ ctx->Pixel.GreenBias != 0.0 || ctx->Pixel.GreenScale != 1.0 ||
+ ctx->Pixel.BlueBias != 0.0 || ctx->Pixel.BlueScale != 1.0 ||
+ ctx->Pixel.AlphaBias != 0.0 || ctx->Pixel.AlphaScale != 1.0) {
+ key->scaleAndBias = 1;
+ }
+
+ if (!is_identity(ctx->ColorMatrixStack.Top->m)) {
+ key->colorMatrix = 1;
+ }
+
+ if (!TEST_EQ_4V(ctx->Pixel.PostColorMatrixScale, one) ||
+ !TEST_EQ_4V(ctx->Pixel.PostColorMatrixBias, zero)) {
+ key->colorMatrixPostScaleBias = 1;
+ }
+
+ key->pixelMaps = ctx->Pixel.MapColorFlag;
+}
+
+
+static struct pipe_texture *
+create_color_map_texture(GLcontext *ctx)
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct pipe_texture *pt;
+ enum pipe_format format;
+ const uint texSize = 256; /* simple, and usually perfect */
+
+ /* find an RGBA texture format */
+ format = st_choose_format(pipe, GL_RGBA, PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_SAMPLER);
+
+ /* create texture for color map/table */
+ pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, format, 0,
+ texSize, texSize, 1, 0,
+ PIPE_TEXTURE_USAGE_SAMPLER);
+ return pt;
+}
+
+
+/**
+ * Update the pixelmap texture with the contents of the R/G/B/A pixel maps.
+ */
+static void
+load_color_map_texture(GLcontext *ctx, struct pipe_texture *pt)
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_surface *surface;
+ const GLuint rSize = ctx->PixelMaps.RtoR.Size;
+ const GLuint gSize = ctx->PixelMaps.GtoG.Size;
+ const GLuint bSize = ctx->PixelMaps.BtoB.Size;
+ const GLuint aSize = ctx->PixelMaps.AtoA.Size;
+ const uint texSize = pt->width[0];
+ uint *dest;
+ uint i, j;
+
+ surface = screen->get_tex_surface(screen, pt, 0, 0, 0,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+ dest = (uint *) screen->surface_map(screen, surface,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+
+ /* Pack four 1D maps into a 2D texture:
+ * R map is placed horizontally, indexed by S, in channel 0
+ * G map is placed vertically, indexed by T, in channel 1
+ * B map is placed horizontally, indexed by S, in channel 2
+ * A map is placed vertically, indexed by T, in channel 3
+ */
+ for (i = 0; i < texSize; i++) {
+ for (j = 0; j < texSize; j++) {
+ int k = (i * texSize + j);
+ ubyte r = ctx->PixelMaps.RtoR.Map8[j * rSize / texSize];
+ ubyte g = ctx->PixelMaps.GtoG.Map8[i * gSize / texSize];
+ ubyte b = ctx->PixelMaps.BtoB.Map8[j * bSize / texSize];
+ ubyte a = ctx->PixelMaps.AtoA.Map8[i * aSize / texSize];
+ util_pack_color_ub(r, g, b, a, pt->format, dest + k);
+ }
+ }
+
+ screen->surface_unmap(screen, surface);
+ pipe_surface_reference(&surface, NULL);
+}
+
+
+
+#define MAX_INST 100
+
+/**
+ * Returns a fragment program which implements the current pixel transfer ops.
+ */
+static struct gl_fragment_program *
+get_pixel_transfer_program(GLcontext *ctx, const struct state_key *key)
+{
+ struct st_context *st = ctx->st;
+ struct prog_instruction inst[MAX_INST];
+ struct gl_program_parameter_list *params;
+ struct gl_fragment_program *fp;
+ GLuint ic = 0;
+ const GLuint colorTemp = 0;
+
+ fp = (struct gl_fragment_program *)
+ ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
+ if (!fp)
+ return NULL;
+
+ params = _mesa_new_parameter_list();
+
+ /*
+ * Get initial pixel color from the texture.
+ * TEX colorTemp, fragment.texcoord[0], texture[0], 2D;
+ */
+ _mesa_init_instructions(inst + ic, 1);
+ inst[ic].Opcode = OPCODE_TEX;
+ inst[ic].DstReg.File = PROGRAM_TEMPORARY;
+ inst[ic].DstReg.Index = colorTemp;
+ inst[ic].SrcReg[0].File = PROGRAM_INPUT;
+ inst[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0;
+ inst[ic].TexSrcUnit = 0;
+ inst[ic].TexSrcTarget = TEXTURE_2D_INDEX;
+ ic++;
+ fp->Base.InputsRead = (1 << FRAG_ATTRIB_TEX0);
+ fp->Base.OutputsWritten = (1 << FRAG_RESULT_COLR);
+ fp->Base.SamplersUsed = 0x1; /* sampler 0 (bit 0) is used */
+
+ if (key->scaleAndBias) {
+ static const gl_state_index scale_state[STATE_LENGTH] =
+ { STATE_INTERNAL, STATE_PT_SCALE, 0, 0, 0 };
+ static const gl_state_index bias_state[STATE_LENGTH] =
+ { STATE_INTERNAL, STATE_PT_BIAS, 0, 0, 0 };
+ GLfloat scale[4], bias[4];
+ GLint scale_p, bias_p;
+
+ scale[0] = ctx->Pixel.RedScale;
+ scale[1] = ctx->Pixel.GreenScale;
+ scale[2] = ctx->Pixel.BlueScale;
+ scale[3] = ctx->Pixel.AlphaScale;
+ bias[0] = ctx->Pixel.RedBias;
+ bias[1] = ctx->Pixel.GreenBias;
+ bias[2] = ctx->Pixel.BlueBias;
+ bias[3] = ctx->Pixel.AlphaBias;
+
+ scale_p = _mesa_add_state_reference(params, scale_state);
+ bias_p = _mesa_add_state_reference(params, bias_state);
+
+ /* MAD colorTemp, colorTemp, scale, bias; */
+ _mesa_init_instructions(inst + ic, 1);
+ inst[ic].Opcode = OPCODE_MAD;
+ inst[ic].DstReg.File = PROGRAM_TEMPORARY;
+ inst[ic].DstReg.Index = colorTemp;
+ inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst[ic].SrcReg[0].Index = colorTemp;
+ inst[ic].SrcReg[1].File = PROGRAM_STATE_VAR;
+ inst[ic].SrcReg[1].Index = scale_p;
+ inst[ic].SrcReg[2].File = PROGRAM_STATE_VAR;
+ inst[ic].SrcReg[2].Index = bias_p;
+ ic++;
+ }
+
+ if (key->pixelMaps) {
+ const GLuint temp = 1;
+
+ /* create the colormap/texture now if not already done */
+ if (!st->pixel_xfer.pixelmap_texture) {
+ st->pixel_xfer.pixelmap_texture = create_color_map_texture(ctx);
+ }
+
+ /* with a little effort, we can do four pixel map look-ups with
+ * two TEX instructions:
+ */
+
+ /* TEX temp.rg, colorTemp.rgba, texture[1], 2D; */
+ _mesa_init_instructions(inst + ic, 1);
+ inst[ic].Opcode = OPCODE_TEX;
+ inst[ic].DstReg.File = PROGRAM_TEMPORARY;
+ inst[ic].DstReg.Index = temp;
+ inst[ic].DstReg.WriteMask = WRITEMASK_XY; /* write R,G */
+ inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst[ic].SrcReg[0].Index = colorTemp;
+ inst[ic].TexSrcUnit = 1;
+ inst[ic].TexSrcTarget = TEXTURE_2D_INDEX;
+ ic++;
+
+ /* TEX temp.ba, colorTemp.baba, texture[1], 2D; */
+ _mesa_init_instructions(inst + ic, 1);
+ inst[ic].Opcode = OPCODE_TEX;
+ inst[ic].DstReg.File = PROGRAM_TEMPORARY;
+ inst[ic].DstReg.Index = temp;
+ inst[ic].DstReg.WriteMask = WRITEMASK_ZW; /* write B,A */
+ inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst[ic].SrcReg[0].Index = colorTemp;
+ inst[ic].SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_W,
+ SWIZZLE_Z, SWIZZLE_W);
+ inst[ic].TexSrcUnit = 1;
+ inst[ic].TexSrcTarget = TEXTURE_2D_INDEX;
+ ic++;
+
+ /* MOV colorTemp, temp; */
+ _mesa_init_instructions(inst + ic, 1);
+ inst[ic].Opcode = OPCODE_MOV;
+ inst[ic].DstReg.File = PROGRAM_TEMPORARY;
+ inst[ic].DstReg.Index = colorTemp;
+ inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst[ic].SrcReg[0].Index = temp;
+ ic++;
+
+ fp->Base.SamplersUsed |= (1 << 1); /* sampler 1 is used */
+ }
+
+ if (key->colorMatrix) {
+ static const gl_state_index row0_state[STATE_LENGTH] =
+ { STATE_COLOR_MATRIX, 0, 0, 0, 0 };
+ static const gl_state_index row1_state[STATE_LENGTH] =
+ { STATE_COLOR_MATRIX, 0, 1, 1, 0 };
+ static const gl_state_index row2_state[STATE_LENGTH] =
+ { STATE_COLOR_MATRIX, 0, 2, 2, 0 };
+ static const gl_state_index row3_state[STATE_LENGTH] =
+ { STATE_COLOR_MATRIX, 0, 3, 3, 0 };
+
+ GLint row0_p = _mesa_add_state_reference(params, row0_state);
+ GLint row1_p = _mesa_add_state_reference(params, row1_state);
+ GLint row2_p = _mesa_add_state_reference(params, row2_state);
+ GLint row3_p = _mesa_add_state_reference(params, row3_state);
+ const GLuint temp = 1;
+
+ /* DP4 temp.x, colorTemp, matrow0; */
+ _mesa_init_instructions(inst + ic, 1);
+ inst[ic].Opcode = OPCODE_DP4;
+ inst[ic].DstReg.File = PROGRAM_TEMPORARY;
+ inst[ic].DstReg.Index = temp;
+ inst[ic].DstReg.WriteMask = WRITEMASK_X;
+ inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst[ic].SrcReg[0].Index = colorTemp;
+ inst[ic].SrcReg[1].File = PROGRAM_STATE_VAR;
+ inst[ic].SrcReg[1].Index = row0_p;
+ ic++;
+
+ /* DP4 temp.y, colorTemp, matrow1; */
+ _mesa_init_instructions(inst + ic, 1);
+ inst[ic].Opcode = OPCODE_DP4;
+ inst[ic].DstReg.File = PROGRAM_TEMPORARY;
+ inst[ic].DstReg.Index = temp;
+ inst[ic].DstReg.WriteMask = WRITEMASK_Y;
+ inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst[ic].SrcReg[0].Index = colorTemp;
+ inst[ic].SrcReg[1].File = PROGRAM_STATE_VAR;
+ inst[ic].SrcReg[1].Index = row1_p;
+ ic++;
+
+ /* DP4 temp.z, colorTemp, matrow2; */
+ _mesa_init_instructions(inst + ic, 1);
+ inst[ic].Opcode = OPCODE_DP4;
+ inst[ic].DstReg.File = PROGRAM_TEMPORARY;
+ inst[ic].DstReg.Index = temp;
+ inst[ic].DstReg.WriteMask = WRITEMASK_Z;
+ inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst[ic].SrcReg[0].Index = colorTemp;
+ inst[ic].SrcReg[1].File = PROGRAM_STATE_VAR;
+ inst[ic].SrcReg[1].Index = row2_p;
+ ic++;
+
+ /* DP4 temp.w, colorTemp, matrow3; */
+ _mesa_init_instructions(inst + ic, 1);
+ inst[ic].Opcode = OPCODE_DP4;
+ inst[ic].DstReg.File = PROGRAM_TEMPORARY;
+ inst[ic].DstReg.Index = temp;
+ inst[ic].DstReg.WriteMask = WRITEMASK_W;
+ inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst[ic].SrcReg[0].Index = colorTemp;
+ inst[ic].SrcReg[1].File = PROGRAM_STATE_VAR;
+ inst[ic].SrcReg[1].Index = row3_p;
+ ic++;
+
+ /* MOV colorTemp, temp; */
+ _mesa_init_instructions(inst + ic, 1);
+ inst[ic].Opcode = OPCODE_MOV;
+ inst[ic].DstReg.File = PROGRAM_TEMPORARY;
+ inst[ic].DstReg.Index = colorTemp;
+ inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst[ic].SrcReg[0].Index = temp;
+ ic++;
+ }
+
+ if (key->colorMatrixPostScaleBias) {
+ static const gl_state_index scale_state[STATE_LENGTH] =
+ { STATE_INTERNAL, STATE_PT_SCALE, 0, 0, 0 };
+ static const gl_state_index bias_state[STATE_LENGTH] =
+ { STATE_INTERNAL, STATE_PT_BIAS, 0, 0, 0 };
+ GLint scale_param, bias_param;
+
+ scale_param = _mesa_add_state_reference(params, scale_state);
+ bias_param = _mesa_add_state_reference(params, bias_state);
+
+ _mesa_init_instructions(inst + ic, 1);
+ inst[ic].Opcode = OPCODE_MAD;
+ inst[ic].DstReg.File = PROGRAM_TEMPORARY;
+ inst[ic].DstReg.Index = colorTemp;
+ inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst[ic].SrcReg[0].Index = colorTemp;
+ inst[ic].SrcReg[1].File = PROGRAM_STATE_VAR;
+ inst[ic].SrcReg[1].Index = scale_param;
+ inst[ic].SrcReg[2].File = PROGRAM_STATE_VAR;
+ inst[ic].SrcReg[2].Index = bias_param;
+ ic++;
+ }
+
+ /* Modify last instruction's dst reg to write to result.color */
+ {
+ struct prog_instruction *last = &inst[ic - 1];
+ last->DstReg.File = PROGRAM_OUTPUT;
+ last->DstReg.Index = FRAG_RESULT_COLR;
+ }
+
+ /* END; */
+ _mesa_init_instructions(inst + ic, 1);
+ inst[ic].Opcode = OPCODE_END;
+ ic++;
+
+ assert(ic <= MAX_INST);
+
+
+ fp->Base.Instructions = _mesa_alloc_instructions(ic);
+ if (!fp->Base.Instructions) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY,
+ "generating pixel transfer program");
+ return NULL;
+ }
+
+ _mesa_copy_instructions(fp->Base.Instructions, inst, ic);
+ fp->Base.NumInstructions = ic;
+ fp->Base.Parameters = params;
+
+#if 0
+ printf("========= pixel transfer prog\n");
+ _mesa_print_program(&fp->Base);
+ _mesa_print_parameter_list(fp->Base.Parameters);
+#endif
+
+ return fp;
+}
+
+
+
+/**
+ * Update st->pixel_xfer.program in response to new pixel-transfer state.
+ */
+static void
+update_pixel_transfer(struct st_context *st)
+{
+ GLcontext *ctx = st->ctx;
+ struct state_key key;
+ struct gl_fragment_program *fp;
+
+ make_state_key(st->ctx, &key);
+
+ fp = (struct gl_fragment_program *)
+ _mesa_search_program_cache(st->pixel_xfer.cache, &key, sizeof(key));
+ if (!fp) {
+ fp = get_pixel_transfer_program(st->ctx, &key);
+ _mesa_program_cache_insert(st->ctx, st->pixel_xfer.cache,
+ &key, sizeof(key), &fp->Base);
+ }
+
+ if (ctx->Pixel.MapColorFlag) {
+ load_color_map_texture(ctx, st->pixel_xfer.pixelmap_texture);
+ }
+ st->pixel_xfer.pixelmap_enabled = ctx->Pixel.MapColorFlag;
+
+ st->pixel_xfer.program = (struct st_fragment_program *) fp;
+}
+
+
+
+const struct st_tracked_state st_update_pixel_transfer = {
+ "st_update_pixel_transfer", /* name */
+ { /* dirty */
+ _NEW_PIXEL | _NEW_COLOR_MATRIX, /* mesa */
+ 0, /* st */
+ },
+ update_pixel_transfer /* update */
+};
diff --git a/src/mesa/state_tracker/st_atom_rasterizer.c b/src/mesa/state_tracker/st_atom_rasterizer.c
new file mode 100644
index 00000000000..ea76487bcfc
--- /dev/null
+++ b/src/mesa/state_tracker/st_atom_rasterizer.c
@@ -0,0 +1,289 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <[email protected]>
+ */
+
+#include "main/macros.h"
+#include "st_context.h"
+#include "st_atom.h"
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "cso_cache/cso_context.h"
+
+
+static GLuint translate_fill( GLenum mode )
+{
+ switch (mode) {
+ case GL_POINT:
+ return PIPE_POLYGON_MODE_POINT;
+ case GL_LINE:
+ return PIPE_POLYGON_MODE_LINE;
+ case GL_FILL:
+ return PIPE_POLYGON_MODE_FILL;
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+static GLboolean get_offset_flag( GLuint fill_mode,
+ const struct gl_polygon_attrib *p )
+{
+ switch (fill_mode) {
+ case PIPE_POLYGON_MODE_POINT:
+ return p->OffsetPoint;
+ case PIPE_POLYGON_MODE_LINE:
+ return p->OffsetLine;
+ case PIPE_POLYGON_MODE_FILL:
+ return p->OffsetFill;
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+
+static void update_raster_state( struct st_context *st )
+{
+ GLcontext *ctx = st->ctx;
+ struct pipe_rasterizer_state *raster = &st->state.rasterizer;
+ const struct gl_vertex_program *vertProg = ctx->VertexProgram._Current;
+ uint i;
+
+ memset(raster, 0, sizeof(*raster));
+
+ raster->origin_lower_left = 1; /* Always true for OpenGL */
+
+ /* _NEW_POLYGON, _NEW_BUFFERS
+ */
+ {
+ if (ctx->Polygon.FrontFace == GL_CCW)
+ raster->front_winding = PIPE_WINDING_CCW;
+ else
+ raster->front_winding = PIPE_WINDING_CW;
+
+ /* XXX
+ * I think the intention here is that user-created framebuffer objects
+ * use Y=0=TOP layout instead of OpenGL's normal Y=0=bottom layout.
+ * Flipping Y changes CW to CCW and vice-versa.
+ * But this is an implementation/driver-specific artifact - remove...
+ */
+ if (ctx->DrawBuffer && ctx->DrawBuffer->Name != 0)
+ raster->front_winding ^= PIPE_WINDING_BOTH;
+ }
+
+ /* _NEW_LIGHT
+ */
+ if (ctx->Light.ShadeModel == GL_FLAT)
+ raster->flatshade = 1;
+
+ /* _NEW_LIGHT | _NEW_PROGRAM
+ *
+ * Back-face colors can come from traditional lighting (when
+ * GL_LIGHT_MODEL_TWO_SIDE is set) or from vertex programs/shaders (when
+ * GL_VERTEX_PROGRAM_TWO_SIDE is set). Note the logic here.
+ */
+ if (ctx->VertexProgram._Current) {
+ if (ctx->VertexProgram._Enabled ||
+ (ctx->Shader.CurrentProgram &&
+ ctx->Shader.CurrentProgram->VertexProgram &&
+ ctx->Shader.CurrentProgram->LinkStatus)) {
+ /* user-defined vertex program or shader */
+ raster->light_twoside = ctx->VertexProgram.TwoSideEnabled;
+ }
+ else {
+ /* TNL-generated program */
+ raster->light_twoside = ctx->Light.Enabled && ctx->Light.Model.TwoSide;
+ }
+ }
+ else if (ctx->Light.Enabled && ctx->Light.Model.TwoSide) {
+ raster->light_twoside = 1;
+ }
+
+ /* _NEW_POLYGON
+ */
+ if (ctx->Polygon.CullFlag) {
+ if (ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) {
+ raster->cull_mode = PIPE_WINDING_BOTH;
+ }
+ else if (ctx->Polygon.CullFaceMode == GL_FRONT) {
+ raster->cull_mode = raster->front_winding;
+ }
+ else {
+ raster->cull_mode = raster->front_winding ^ PIPE_WINDING_BOTH;
+ }
+ }
+
+ /* _NEW_POLYGON
+ */
+ {
+ GLuint fill_front = translate_fill( ctx->Polygon.FrontMode );
+ GLuint fill_back = translate_fill( ctx->Polygon.BackMode );
+
+ if (raster->front_winding == PIPE_WINDING_CW) {
+ raster->fill_cw = fill_front;
+ raster->fill_ccw = fill_back;
+ }
+ else {
+ raster->fill_cw = fill_back;
+ raster->fill_ccw = fill_front;
+ }
+
+ /* Simplify when culling is active:
+ */
+ if (raster->cull_mode & PIPE_WINDING_CW) {
+ raster->fill_cw = raster->fill_ccw;
+ }
+
+ if (raster->cull_mode & PIPE_WINDING_CCW) {
+ raster->fill_ccw = raster->fill_cw;
+ }
+ }
+
+ /* _NEW_POLYGON
+ */
+ if (ctx->Polygon.OffsetUnits != 0.0 ||
+ ctx->Polygon.OffsetFactor != 0.0) {
+ raster->offset_cw = get_offset_flag( raster->fill_cw, &ctx->Polygon );
+ raster->offset_ccw = get_offset_flag( raster->fill_ccw, &ctx->Polygon );
+ raster->offset_units = ctx->Polygon.OffsetUnits;
+ raster->offset_scale = ctx->Polygon.OffsetFactor;
+ }
+
+ if (ctx->Polygon.SmoothFlag)
+ raster->poly_smooth = 1;
+
+ if (ctx->Polygon.StippleFlag)
+ raster->poly_stipple_enable = 1;
+
+
+ /* _NEW_BUFFERS, _NEW_POLYGON
+ */
+ if (raster->fill_cw != PIPE_POLYGON_MODE_FILL ||
+ raster->fill_ccw != PIPE_POLYGON_MODE_FILL)
+ {
+ GLfloat mrd = (ctx->DrawBuffer ?
+ ctx->DrawBuffer->_MRD :
+ 1.0f);
+
+ raster->offset_units = ctx->Polygon.OffsetFactor * mrd;
+ raster->offset_scale = (ctx->Polygon.OffsetUnits * mrd *
+ st->polygon_offset_scale);
+ }
+
+ /* _NEW_POINT
+ */
+ raster->point_size = ctx->Point.Size;
+
+ raster->point_size_min = 0; /* temporary, will go away */
+ raster->point_size_max = 1000; /* temporary, will go away */
+
+ raster->point_smooth = ctx->Point.SmoothFlag;
+ raster->point_sprite = ctx->Point.PointSprite;
+ for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) {
+ if (ctx->Point.CoordReplace[i]) {
+ if (ctx->Point.SpriteOrigin == GL_UPPER_LEFT)
+ raster->sprite_coord_mode[i] = PIPE_SPRITE_COORD_UPPER_LEFT;
+ else
+ raster->sprite_coord_mode[i] = PIPE_SPRITE_COORD_LOWER_LEFT;
+ }
+ else {
+ raster->sprite_coord_mode[i] = PIPE_SPRITE_COORD_NONE;
+ }
+ }
+
+ /* ST_NEW_VERTEX_PROGRAM
+ */
+ if (vertProg) {
+ if (vertProg->Base.Id == 0) {
+ if (vertProg->Base.OutputsWritten & (1 << VERT_RESULT_PSIZ)) {
+ /* generated program which emits point size */
+ raster->point_size_per_vertex = TRUE;
+ }
+ }
+ else if (ctx->VertexProgram.PointSizeEnabled) {
+ /* user-defined program and GL_VERTEX_PROGRAM_POINT_SIZE set */
+ raster->point_size_per_vertex = ctx->VertexProgram.PointSizeEnabled;
+ }
+ }
+ if (!raster->point_size_per_vertex) {
+ /* clamp size now */
+ raster->point_size = CLAMP(ctx->Point.Size,
+ ctx->Point.MinSize,
+ ctx->Point.MaxSize);
+ }
+
+ /* _NEW_LINE
+ */
+ raster->line_smooth = ctx->Line.SmoothFlag;
+ if (ctx->Line.SmoothFlag) {
+ raster->line_width = CLAMP(ctx->Line.Width,
+ ctx->Const.MinLineWidthAA,
+ ctx->Const.MaxLineWidthAA);
+ }
+ else {
+ raster->line_width = CLAMP(ctx->Line.Width,
+ ctx->Const.MinLineWidth,
+ ctx->Const.MaxLineWidth);
+ }
+
+ raster->line_stipple_enable = ctx->Line.StippleFlag;
+ raster->line_stipple_pattern = ctx->Line.StipplePattern;
+ /* GL stipple factor is in [1,256], remap to [0, 255] here */
+ raster->line_stipple_factor = ctx->Line.StippleFactor - 1;
+
+ /* _NEW_MULTISAMPLE */
+ if (ctx->Multisample._Enabled || st->force_msaa)
+ raster->multisample = 1;
+
+ /* _NEW_SCISSOR */
+ if (ctx->Scissor.Enabled)
+ raster->scissor = 1;
+
+ raster->gl_rasterization_rules = 1;
+
+ cso_set_rasterizer(st->cso_context, raster);
+}
+
+const struct st_tracked_state st_update_rasterizer = {
+ "st_update_rasterizer", /* name */
+ {
+ (_NEW_BUFFERS |
+ _NEW_LIGHT |
+ _NEW_LINE |
+ _NEW_MULTISAMPLE |
+ _NEW_POINT |
+ _NEW_POLYGON |
+ _NEW_PROGRAM |
+ _NEW_SCISSOR), /* mesa state dependencies*/
+ ST_NEW_VERTEX_PROGRAM, /* state tracker dependencies */
+ },
+ update_raster_state /* update function */
+};
diff --git a/src/mesa/state_tracker/st_atom_sampler.c b/src/mesa/state_tracker/st_atom_sampler.c
new file mode 100644
index 00000000000..d7b904354f2
--- /dev/null
+++ b/src/mesa/state_tracker/st_atom_sampler.c
@@ -0,0 +1,217 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <[email protected]>
+ * Brian Paul
+ */
+
+
+#include "main/macros.h"
+
+#include "st_context.h"
+#include "st_cb_texture.h"
+#include "st_atom.h"
+#include "st_program.h"
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+
+#include "cso_cache/cso_context.h"
+
+
+/**
+ * Convert GLenum texcoord wrap tokens to pipe tokens.
+ */
+static GLuint
+gl_wrap_to_sp(GLenum wrap)
+{
+ switch (wrap) {
+ case GL_REPEAT:
+ return PIPE_TEX_WRAP_REPEAT;
+ case GL_CLAMP:
+ return PIPE_TEX_WRAP_CLAMP;
+ case GL_CLAMP_TO_EDGE:
+ return PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ case GL_CLAMP_TO_BORDER:
+ return PIPE_TEX_WRAP_CLAMP_TO_BORDER;
+ case GL_MIRRORED_REPEAT:
+ return PIPE_TEX_WRAP_MIRROR_REPEAT;
+ case GL_MIRROR_CLAMP_EXT:
+ return PIPE_TEX_WRAP_MIRROR_CLAMP;
+ case GL_MIRROR_CLAMP_TO_EDGE_EXT:
+ return PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE;
+ case GL_MIRROR_CLAMP_TO_BORDER_EXT:
+ return PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER;
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+
+static GLuint
+gl_filter_to_mip_filter(GLenum filter)
+{
+ switch (filter) {
+ case GL_NEAREST:
+ case GL_LINEAR:
+ return PIPE_TEX_MIPFILTER_NONE;
+
+ case GL_NEAREST_MIPMAP_NEAREST:
+ case GL_LINEAR_MIPMAP_NEAREST:
+ return PIPE_TEX_MIPFILTER_NEAREST;
+
+ case GL_NEAREST_MIPMAP_LINEAR:
+ case GL_LINEAR_MIPMAP_LINEAR:
+ return PIPE_TEX_MIPFILTER_LINEAR;
+
+ default:
+ assert(0);
+ return PIPE_TEX_MIPFILTER_NONE;
+ }
+}
+
+
+static GLuint
+gl_filter_to_img_filter(GLenum filter)
+{
+ switch (filter) {
+ case GL_NEAREST:
+ case GL_NEAREST_MIPMAP_NEAREST:
+ case GL_NEAREST_MIPMAP_LINEAR:
+ return PIPE_TEX_FILTER_NEAREST;
+
+ case GL_LINEAR:
+ case GL_LINEAR_MIPMAP_NEAREST:
+ case GL_LINEAR_MIPMAP_LINEAR:
+ return PIPE_TEX_FILTER_LINEAR;
+
+ default:
+ assert(0);
+ return PIPE_TEX_FILTER_NEAREST;
+ }
+}
+
+
+static void
+update_samplers(struct st_context *st)
+{
+ struct gl_vertex_program *vprog = st->ctx->VertexProgram._Current;
+ struct gl_fragment_program *fprog = st->ctx->FragmentProgram._Current;
+ const GLbitfield samplersUsed = (vprog->Base.SamplersUsed |
+ fprog->Base.SamplersUsed);
+ GLuint su;
+
+ st->state.num_samplers = 0;
+
+ /* loop over sampler units (aka tex image units) */
+ for (su = 0; su < st->ctx->Const.MaxTextureImageUnits; su++) {
+ struct pipe_sampler_state *sampler = st->state.samplers + su;
+
+ memset(sampler, 0, sizeof(*sampler));
+
+ if (samplersUsed & (1 << su)) {
+ struct gl_texture_object *texobj;
+ GLuint texUnit;
+
+ if (fprog->Base.SamplersUsed & (1 << su))
+ texUnit = fprog->Base.SamplerUnits[su];
+ else
+ texUnit = vprog->Base.SamplerUnits[su];
+
+ texobj = st->ctx->Texture.Unit[texUnit]._Current;
+ if (!texobj) {
+ texobj = st_get_default_texture(st);
+ }
+
+ sampler->wrap_s = gl_wrap_to_sp(texobj->WrapS);
+ sampler->wrap_t = gl_wrap_to_sp(texobj->WrapT);
+ sampler->wrap_r = gl_wrap_to_sp(texobj->WrapR);
+
+ sampler->min_img_filter = gl_filter_to_img_filter(texobj->MinFilter);
+ sampler->min_mip_filter = gl_filter_to_mip_filter(texobj->MinFilter);
+ sampler->mag_img_filter = gl_filter_to_img_filter(texobj->MagFilter);
+
+ if (texobj->Target != GL_TEXTURE_RECTANGLE_ARB)
+ sampler->normalized_coords = 1;
+
+ sampler->lod_bias = st->ctx->Texture.Unit[su].LodBias;
+ sampler->min_lod = MAX2(0.0f, texobj->MinLod);
+ sampler->max_lod = MIN2(texobj->MaxLevel - texobj->BaseLevel,
+ texobj->MaxLod);
+ if (sampler->max_lod < sampler->min_lod) {
+ /* The GL spec doesn't seem to specify what to do in this case.
+ * Swap the values.
+ */
+ float tmp = sampler->max_lod;
+ sampler->max_lod = sampler->min_lod;
+ sampler->min_lod = tmp;
+ assert(sampler->min_lod <= sampler->max_lod);
+ }
+
+ sampler->border_color[0] = texobj->BorderColor[RCOMP];
+ sampler->border_color[1] = texobj->BorderColor[GCOMP];
+ sampler->border_color[2] = texobj->BorderColor[BCOMP];
+ sampler->border_color[3] = texobj->BorderColor[ACOMP];
+
+ sampler->max_anisotropy = texobj->MaxAnisotropy;
+ if (sampler->max_anisotropy > 1.0) {
+ sampler->min_img_filter = PIPE_TEX_FILTER_ANISO;
+ sampler->mag_img_filter = PIPE_TEX_FILTER_ANISO;
+ }
+
+ /* only care about ARB_shadow, not SGI shadow */
+ if (texobj->CompareMode == GL_COMPARE_R_TO_TEXTURE) {
+ sampler->compare_mode = PIPE_TEX_COMPARE_R_TO_TEXTURE;
+ sampler->compare_func
+ = st_compare_func_to_pipe(texobj->CompareFunc);
+ }
+
+ st->state.num_samplers = su + 1;
+
+ /*printf("%s su=%u non-null\n", __FUNCTION__, su);*/
+ cso_single_sampler(st->cso_context, su, sampler);
+ }
+ else {
+ /*printf("%s su=%u null\n", __FUNCTION__, su);*/
+ cso_single_sampler(st->cso_context, su, NULL);
+ }
+ }
+
+ cso_single_sampler_done(st->cso_context);
+}
+
+
+const struct st_tracked_state st_update_sampler = {
+ "st_update_sampler", /* name */
+ { /* dirty */
+ _NEW_TEXTURE, /* mesa */
+ 0, /* st */
+ },
+ update_samplers /* update */
+};
diff --git a/src/mesa/state_tracker/st_atom_scissor.c b/src/mesa/state_tracker/st_atom_scissor.c
new file mode 100644
index 00000000000..3fd59e1945c
--- /dev/null
+++ b/src/mesa/state_tracker/st_atom_scissor.c
@@ -0,0 +1,92 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <[email protected]>
+ */
+
+
+#include "st_context.h"
+#include "pipe/p_context.h"
+#include "st_atom.h"
+
+
+/**
+ * Scissor depends on the scissor box, and the framebuffer dimensions.
+ */
+static void
+update_scissor( struct st_context *st )
+{
+ struct pipe_scissor_state scissor;
+ const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
+ GLint miny, maxy;
+
+ scissor.minx = 0;
+ scissor.miny = 0;
+ scissor.maxx = fb->Width;
+ scissor.maxy = fb->Height;
+
+ if (st->ctx->Scissor.Enabled) {
+ if ((GLuint)st->ctx->Scissor.X > scissor.minx)
+ scissor.minx = st->ctx->Scissor.X;
+ if ((GLuint)st->ctx->Scissor.Y > scissor.miny)
+ scissor.miny = st->ctx->Scissor.Y;
+
+ if ((GLuint)st->ctx->Scissor.X + st->ctx->Scissor.Width < scissor.maxx)
+ scissor.maxx = st->ctx->Scissor.X + st->ctx->Scissor.Width;
+ if ((GLuint)st->ctx->Scissor.Y + st->ctx->Scissor.Height < scissor.maxy)
+ scissor.maxy = st->ctx->Scissor.Y + st->ctx->Scissor.Height;
+
+ /* check for null space */
+ if (scissor.minx >= scissor.maxx || scissor.miny >= scissor.maxy)
+ scissor.minx = scissor.miny = scissor.maxx = scissor.maxy = 0;
+ }
+
+ /* Now invert Y. Pipe drivers use the convention Y=0=top for surfaces
+ */
+ miny = fb->Height - scissor.maxy;
+ maxy = fb->Height - scissor.miny;
+ scissor.miny = miny;
+ scissor.maxy = maxy;
+
+ if (memcmp(&scissor, &st->state.scissor, sizeof(scissor)) != 0) {
+ /* state has changed */
+ st->state.scissor = scissor; /* struct copy */
+ st->pipe->set_scissor_state(st->pipe, &scissor); /* activate */
+ }
+}
+
+
+const struct st_tracked_state st_update_scissor = {
+ "st_update_scissor", /* name */
+ { /* dirty */
+ (_NEW_SCISSOR | _NEW_BUFFERS), /* mesa */
+ 0, /* st */
+ },
+ update_scissor /* update */
+};
diff --git a/src/mesa/state_tracker/st_atom_shader.c b/src/mesa/state_tracker/st_atom_shader.c
new file mode 100644
index 00000000000..cbd414e2d3b
--- /dev/null
+++ b/src/mesa/state_tracker/st_atom_shader.c
@@ -0,0 +1,369 @@
+/**************************************************************************
+ *
+ * Copyright 2003 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.
+ *
+ **************************************************************************/
+
+/**
+ * State validation for vertex/fragment shaders.
+ * Note that we have to delay most vertex/fragment shader translation
+ * until rendering time since the linkage between the vertex outputs and
+ * fragment inputs can vary depending on the pairing of shaders.
+ *
+ * Authors:
+ * Brian Paul
+ */
+
+
+
+#include "main/imports.h"
+#include "main/mtypes.h"
+#include "main/macros.h"
+#include "shader/program.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_shader_tokens.h"
+
+#include "util/u_simple_shaders.h"
+
+#include "cso_cache/cso_context.h"
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "st_program.h"
+#include "st_atom_shader.h"
+#include "st_mesa_to_tgsi.h"
+
+
+/**
+ * This represents a vertex program, especially translated to match
+ * the inputs of a particular fragment shader.
+ */
+struct translated_vertex_program
+{
+ struct st_vertex_program *master;
+
+ /** The fragment shader "signature" this vertex shader is meant for: */
+ GLbitfield frag_inputs;
+
+ /** Compared against master vertex program's serialNo: */
+ GLuint serialNo;
+
+ /** Maps VERT_RESULT_x to slot */
+ GLuint output_to_slot[VERT_RESULT_MAX];
+ ubyte output_to_semantic_name[VERT_RESULT_MAX];
+ ubyte output_to_semantic_index[VERT_RESULT_MAX];
+
+ /** Pointer to the translated vertex program */
+ struct st_vertex_program *vp;
+
+ struct translated_vertex_program *next; /**< next in linked list */
+};
+
+
+
+/**
+ * Given a vertex program output attribute, return the corresponding
+ * fragment program input attribute.
+ * \return -1 for vertex outputs that have no corresponding fragment input
+ */
+static GLint
+vp_out_to_fp_in(GLuint vertResult)
+{
+ if (vertResult >= VERT_RESULT_TEX0 &&
+ vertResult < VERT_RESULT_TEX0 + MAX_TEXTURE_COORD_UNITS)
+ return FRAG_ATTRIB_TEX0 + (vertResult - VERT_RESULT_TEX0);
+
+ if (vertResult >= VERT_RESULT_VAR0 &&
+ vertResult < VERT_RESULT_VAR0 + MAX_VARYING)
+ return FRAG_ATTRIB_VAR0 + (vertResult - VERT_RESULT_VAR0);
+
+ switch (vertResult) {
+ case VERT_RESULT_HPOS:
+ return FRAG_ATTRIB_WPOS;
+ case VERT_RESULT_COL0:
+ return FRAG_ATTRIB_COL0;
+ case VERT_RESULT_COL1:
+ return FRAG_ATTRIB_COL1;
+ case VERT_RESULT_FOGC:
+ return FRAG_ATTRIB_FOGC;
+ default:
+ /* Back-face colors, edge flags, etc */
+ return -1;
+ }
+}
+
+
+/**
+ * Find a translated vertex program that corresponds to stvp and
+ * has outputs matched to stfp's inputs.
+ * This performs vertex and fragment translation (to TGSI) when needed.
+ */
+static struct translated_vertex_program *
+find_translated_vp(struct st_context *st,
+ struct st_vertex_program *stvp,
+ struct st_fragment_program *stfp)
+{
+ static const GLuint UNUSED = ~0;
+ struct translated_vertex_program *xvp;
+ const GLbitfield fragInputsRead = stfp->Base.Base.InputsRead;
+
+ /*
+ * Translate fragment program if needed.
+ */
+ if (!stfp->state.tokens) {
+ GLuint inAttr, numIn = 0;
+
+ for (inAttr = 0; inAttr < FRAG_ATTRIB_MAX; inAttr++) {
+ if (fragInputsRead & (1 << inAttr)) {
+ stfp->input_to_slot[inAttr] = numIn;
+ numIn++;
+ }
+ else {
+ stfp->input_to_slot[inAttr] = UNUSED;
+ }
+ }
+
+ stfp->num_input_slots = numIn;
+
+ assert(stfp->Base.Base.NumInstructions > 1);
+
+ st_translate_fragment_program(st, stfp, stfp->input_to_slot);
+ }
+
+
+ /* See if we've got a translated vertex program whose outputs match
+ * the fragment program's inputs.
+ * XXX This could be a hash lookup, using InputsRead as the key.
+ */
+ for (xvp = stfp->vertex_programs; xvp; xvp = xvp->next) {
+ if (xvp->master == stvp && xvp->frag_inputs == fragInputsRead) {
+ break;
+ }
+ }
+
+ /* No? Allocate translated vp object now */
+ if (!xvp) {
+ xvp = CALLOC_STRUCT(translated_vertex_program);
+ xvp->frag_inputs = fragInputsRead;
+ xvp->master = stvp;
+
+ xvp->next = stfp->vertex_programs;
+ stfp->vertex_programs = xvp;
+ }
+
+ /* See if we need to translate vertex program to TGSI form */
+ if (xvp->serialNo != stvp->serialNo) {
+ GLuint outAttr, dummySlot;
+ const GLbitfield outputsWritten = stvp->Base.Base.OutputsWritten;
+ GLuint numVpOuts = 0;
+ GLboolean emitPntSize = GL_FALSE, emitBFC0 = GL_FALSE, emitBFC1 = GL_FALSE;
+ GLint maxGeneric;
+
+ /* Compute mapping of vertex program outputs to slots, which depends
+ * on the fragment program's input->slot mapping.
+ */
+ for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
+ /* set defaults: */
+ xvp->output_to_slot[outAttr] = UNUSED;
+ xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_COUNT;
+ xvp->output_to_semantic_index[outAttr] = 99;
+
+ if (outAttr == VERT_RESULT_HPOS) {
+ /* always put xformed position into slot zero */
+ xvp->output_to_slot[VERT_RESULT_HPOS] = 0;
+ xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_POSITION;
+ xvp->output_to_semantic_index[outAttr] = 0;
+ numVpOuts++;
+ }
+ else if (outputsWritten & (1 << outAttr)) {
+ /* see if the frag prog wants this vert output */
+ GLint fpInAttrib = vp_out_to_fp_in(outAttr);
+ if (fpInAttrib >= 0) {
+ GLuint fpInSlot = stfp->input_to_slot[fpInAttrib];
+ if (fpInSlot != ~0) {
+ /* match this vp output to the fp input */
+ GLuint vpOutSlot = stfp->input_map[fpInSlot];
+ xvp->output_to_slot[outAttr] = vpOutSlot;
+ xvp->output_to_semantic_name[outAttr] = stfp->input_semantic_name[fpInSlot];
+ xvp->output_to_semantic_index[outAttr] = stfp->input_semantic_index[fpInSlot];
+ numVpOuts++;
+ }
+ }
+ else if (outAttr == VERT_RESULT_PSIZ)
+ emitPntSize = GL_TRUE;
+ else if (outAttr == VERT_RESULT_BFC0)
+ emitBFC0 = GL_TRUE;
+ else if (outAttr == VERT_RESULT_BFC1)
+ emitBFC1 = GL_TRUE;
+ }
+#if 0 /*debug*/
+ printf("assign vp output_to_slot[%d] = %d\n", outAttr,
+ xvp->output_to_slot[outAttr]);
+#endif
+ }
+
+ /* must do these last */
+ if (emitPntSize) {
+ xvp->output_to_slot[VERT_RESULT_PSIZ] = numVpOuts++;
+ xvp->output_to_semantic_name[VERT_RESULT_PSIZ] = TGSI_SEMANTIC_PSIZE;
+ xvp->output_to_semantic_index[VERT_RESULT_PSIZ] = 0;
+ }
+ if (emitBFC0) {
+ xvp->output_to_slot[VERT_RESULT_BFC0] = numVpOuts++;
+ xvp->output_to_semantic_name[VERT_RESULT_BFC0] = TGSI_SEMANTIC_COLOR;
+ xvp->output_to_semantic_index[VERT_RESULT_BFC0] = 0;
+ }
+ if (emitBFC1) {
+ xvp->output_to_slot[VERT_RESULT_BFC1] = numVpOuts++;
+ xvp->output_to_semantic_name[VERT_RESULT_BFC0] = TGSI_SEMANTIC_COLOR;
+ xvp->output_to_semantic_index[VERT_RESULT_BFC0] = 1;
+ }
+
+ /* Unneeded vertex program outputs will go to this slot.
+ * We could use this info to do dead code elimination in the
+ * vertex program.
+ */
+ dummySlot = numVpOuts;
+
+ /* find max GENERIC slot index */
+ maxGeneric = -1;
+ for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
+ if (xvp->output_to_semantic_name[outAttr] == TGSI_SEMANTIC_GENERIC) {
+ maxGeneric = MAX2(maxGeneric,
+ xvp->output_to_semantic_index[outAttr]);
+ }
+ }
+
+ /* Map vert program outputs that aren't used to the dummy slot
+ * (and an unused generic attribute slot).
+ */
+ for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
+ if (outputsWritten & (1 << outAttr)) {
+ if (xvp->output_to_slot[outAttr] == UNUSED) {
+ xvp->output_to_slot[outAttr] = dummySlot;
+ xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_GENERIC;
+ xvp->output_to_semantic_index[outAttr] = maxGeneric + 1;
+ }
+ }
+
+#if 0 /*debug*/
+ printf("vp output_to_slot[%d] = %d\n", outAttr,
+ xvp->output_to_slot[outAttr]);
+#endif
+ }
+
+ assert(stvp->Base.Base.NumInstructions > 1);
+
+ st_translate_vertex_program(st, stvp, xvp->output_to_slot,
+ xvp->output_to_semantic_name,
+ xvp->output_to_semantic_index);
+
+ xvp->vp = stvp;
+
+ /* translated VP is up to date now */
+ xvp->serialNo = stvp->serialNo;
+ }
+
+ return xvp;
+}
+
+
+void
+st_free_translated_vertex_programs(struct st_context *st,
+ struct translated_vertex_program *xvp)
+{
+ struct translated_vertex_program *next;
+
+ while (xvp) {
+ next = xvp->next;
+ free(xvp);
+ xvp = next;
+ }
+}
+
+
+static void *
+get_passthrough_fs(struct st_context *st)
+{
+ struct pipe_shader_state shader;
+
+ if (!st->passthrough_fs) {
+ st->passthrough_fs =
+ util_make_fragment_passthrough_shader(st->pipe, &shader);
+#if 0 /* We actually need to keep the tokens around at this time */
+ free((void *) shader.tokens);
+#endif
+ }
+
+ return st->passthrough_fs;
+}
+
+
+static void
+update_linkage( struct st_context *st )
+{
+ struct st_vertex_program *stvp;
+ struct st_fragment_program *stfp;
+ struct translated_vertex_program *xvp;
+
+ /* find active shader and params -- Should be covered by
+ * ST_NEW_VERTEX_PROGRAM
+ */
+ assert(st->ctx->VertexProgram._Current);
+ stvp = st_vertex_program(st->ctx->VertexProgram._Current);
+ assert(stvp->Base.Base.Target == GL_VERTEX_PROGRAM_ARB);
+
+ assert(st->ctx->FragmentProgram._Current);
+ stfp = st_fragment_program(st->ctx->FragmentProgram._Current);
+ assert(stfp->Base.Base.Target == GL_FRAGMENT_PROGRAM_ARB);
+
+ xvp = find_translated_vp(st, stvp, stfp);
+
+ st_reference_vertprog(st, &st->vp, stvp);
+ st_reference_fragprog(st, &st->fp, stfp);
+
+ cso_set_vertex_shader_handle(st->cso_context, stvp->driver_shader);
+
+ if (st->missing_textures) {
+ /* use a pass-through frag shader that uses no textures */
+ void *fs = get_passthrough_fs(st);
+ cso_set_fragment_shader_handle(st->cso_context, fs);
+ }
+ else {
+ cso_set_fragment_shader_handle(st->cso_context, stfp->driver_shader);
+ }
+
+ st->vertex_result_to_slot = xvp->output_to_slot;
+}
+
+
+const struct st_tracked_state st_update_shader = {
+ "st_update_shader", /* name */
+ { /* dirty */
+ 0, /* mesa */
+ ST_NEW_VERTEX_PROGRAM | ST_NEW_FRAGMENT_PROGRAM /* st */
+ },
+ update_linkage /* update */
+};
diff --git a/src/mesa/state_tracker/st_atom_shader.h b/src/mesa/state_tracker/st_atom_shader.h
new file mode 100644
index 00000000000..8403bc66c92
--- /dev/null
+++ b/src/mesa/state_tracker/st_atom_shader.h
@@ -0,0 +1,38 @@
+/**************************************************************************
+ *
+ * Copyright 2007-2008 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.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_ATOM_SHADER_H
+#define ST_ATOM_SHADER_H
+
+
+extern void
+st_free_translated_vertex_programs(struct st_context *st,
+ struct translated_vertex_program *xvp);
+
+
+#endif /* ST_ATOM_SHADER_H */
diff --git a/src/mesa/state_tracker/st_atom_stipple.c b/src/mesa/state_tracker/st_atom_stipple.c
new file mode 100644
index 00000000000..f395930ab40
--- /dev/null
+++ b/src/mesa/state_tracker/st_atom_stipple.c
@@ -0,0 +1,63 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+ /*
+ * \brief polygon stipple state
+ *
+ * Authors:
+ * Brian Paul
+ */
+
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+
+
+static void
+update_stipple( struct st_context *st )
+{
+ const GLuint sz = sizeof(st->state.poly_stipple.stipple);
+ assert(sz == sizeof(st->ctx->PolygonStipple));
+
+ if (memcmp(&st->state.poly_stipple.stipple, st->ctx->PolygonStipple, sz)) {
+ /* state has changed */
+ memcpy(st->state.poly_stipple.stipple, st->ctx->PolygonStipple, sz);
+ st->pipe->set_polygon_stipple(st->pipe, &st->state.poly_stipple);
+ }
+}
+
+
+const struct st_tracked_state st_update_polygon_stipple = {
+ "st_update_polygon_stipple", /* name */
+ { /* dirty */
+ (_NEW_POLYGONSTIPPLE), /* mesa */
+ 0, /* st */
+ },
+ update_stipple /* update */
+};
diff --git a/src/mesa/state_tracker/st_atom_texture.c b/src/mesa/state_tracker/st_atom_texture.c
new file mode 100644
index 00000000000..21f7321f97a
--- /dev/null
+++ b/src/mesa/state_tracker/st_atom_texture.c
@@ -0,0 +1,162 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <[email protected]>
+ * Brian Paul
+ */
+
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "st_texture.h"
+#include "st_cb_texture.h"
+#include "pipe/p_context.h"
+#include "pipe/p_inlines.h"
+#include "cso_cache/cso_context.h"
+
+
+static void
+update_textures(struct st_context *st)
+{
+ struct gl_vertex_program *vprog = st->ctx->VertexProgram._Current;
+ struct gl_fragment_program *fprog = st->ctx->FragmentProgram._Current;
+ const GLbitfield samplersUsed = (vprog->Base.SamplersUsed |
+ fprog->Base.SamplersUsed);
+ GLuint su;
+
+ st->state.num_textures = 0;
+
+ /* loop over sampler units (aka tex image units) */
+ for (su = 0; su < st->ctx->Const.MaxTextureImageUnits; su++) {
+ struct pipe_texture *pt = NULL;
+
+ if (samplersUsed & (1 << su)) {
+ struct gl_texture_object *texObj;
+ struct st_texture_object *stObj;
+ GLboolean flush, retval;
+ GLuint texUnit;
+
+ if (fprog->Base.SamplersUsed & (1 << su))
+ texUnit = fprog->Base.SamplerUnits[su];
+ else
+ texUnit = vprog->Base.SamplerUnits[su];
+
+ texObj = st->ctx->Texture.Unit[texUnit]._Current;
+
+ if (!texObj) {
+ texObj = st_get_default_texture(st);
+ }
+ stObj = st_texture_object(texObj);
+
+ retval = st_finalize_texture(st->ctx, st->pipe, texObj, &flush);
+ if (!retval) {
+ /* out of mem */
+ continue;
+ }
+
+ st->state.num_textures = su + 1;
+
+ pt = st_get_stobj_texture(stObj);
+ }
+
+ /*
+ if (pt) {
+ printf("%s su=%u non-null\n", __FUNCTION__, su);
+ }
+ else {
+ printf("%s su=%u null\n", __FUNCTION__, su);
+ }
+ */
+
+ pipe_texture_reference(&st->state.sampler_texture[su], pt);
+ }
+
+ cso_set_sampler_textures(st->cso_context,
+ st->state.num_textures,
+ st->state.sampler_texture);
+}
+
+
+const struct st_tracked_state st_update_texture = {
+ "st_update_texture", /* name */
+ { /* dirty */
+ _NEW_TEXTURE, /* mesa */
+ ST_NEW_FRAGMENT_PROGRAM, /* st */
+ },
+ update_textures /* update */
+};
+
+
+
+
+static void
+finalize_textures(struct st_context *st)
+{
+ struct gl_fragment_program *fprog = st->ctx->FragmentProgram._Current;
+ const GLboolean prev_missing_textures = st->missing_textures;
+ GLuint su;
+
+ st->missing_textures = GL_FALSE;
+
+ for (su = 0; su < st->ctx->Const.MaxTextureCoordUnits; su++) {
+ if (fprog->Base.SamplersUsed & (1 << su)) {
+ const GLuint texUnit = fprog->Base.SamplerUnits[su];
+ struct gl_texture_object *texObj
+ = st->ctx->Texture.Unit[texUnit]._Current;
+ struct st_texture_object *stObj = st_texture_object(texObj);
+
+ if (texObj) {
+ GLboolean flush, retval;
+
+ retval = st_finalize_texture(st->ctx, st->pipe, texObj, &flush);
+ if (!retval) {
+ /* out of mem */
+ st->missing_textures = GL_TRUE;
+ continue;
+ }
+
+ stObj->teximage_realloc = TRUE;
+ }
+ }
+ }
+
+ if (prev_missing_textures != st->missing_textures)
+ st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
+}
+
+
+
+const struct st_tracked_state st_finalize_textures = {
+ "st_finalize_textures", /* name */
+ { /* dirty */
+ _NEW_TEXTURE, /* mesa */
+ 0, /* st */
+ },
+ finalize_textures /* update */
+};
diff --git a/src/mesa/state_tracker/st_atom_viewport.c b/src/mesa/state_tracker/st_atom_viewport.c
new file mode 100644
index 00000000000..27ec2eb0331
--- /dev/null
+++ b/src/mesa/state_tracker/st_atom_viewport.c
@@ -0,0 +1,91 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+
+#include "main/context.h"
+#include "main/colormac.h"
+#include "st_context.h"
+#include "st_atom.h"
+#include "pipe/p_context.h"
+#include "cso_cache/cso_context.h"
+
+/**
+ * Update the viewport transformation matrix. Depends on:
+ * - viewport pos/size
+ * - depthrange
+ * - window pos/size or FBO size
+ */
+static void
+update_viewport( struct st_context *st )
+{
+ GLcontext *ctx = st->ctx;
+ GLfloat yScale, yBias;
+
+ /* _NEW_BUFFERS
+ */
+ if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
+ yScale = -1;
+ yBias = (GLfloat)ctx->DrawBuffer->Height;
+ }
+ else {
+ yScale = 1.0;
+ yBias = 0.0;
+ }
+
+ /* _NEW_VIEWPORT
+ */
+ {
+ GLfloat x = (GLfloat)ctx->Viewport.X;
+ GLfloat y = (GLfloat)ctx->Viewport.Y;
+ GLfloat z = ctx->Viewport.Near;
+ GLfloat half_width = (GLfloat)ctx->Viewport.Width / 2.0f;
+ GLfloat half_height = (GLfloat)ctx->Viewport.Height / 2.0f;
+ GLfloat half_depth = (GLfloat)(ctx->Viewport.Far - ctx->Viewport.Near) / 2.0f;
+
+ st->state.viewport.scale[0] = half_width;
+ st->state.viewport.scale[1] = half_height * yScale;
+ st->state.viewport.scale[2] = half_depth;
+ st->state.viewport.scale[3] = 1.0;
+
+ st->state.viewport.translate[0] = half_width + x;
+ st->state.viewport.translate[1] = (half_height + y) * yScale + yBias;
+ st->state.viewport.translate[2] = half_depth + z;
+ st->state.viewport.translate[3] = 0.0;
+
+ cso_set_viewport(st->cso_context, &st->state.viewport);
+ }
+}
+
+
+const struct st_tracked_state st_update_viewport = {
+ "st_update_viewport", /* name */
+ { /* dirty */
+ _NEW_BUFFERS | _NEW_VIEWPORT, /* mesa */
+ 0, /* st */
+ },
+ update_viewport /* update */
+};
diff --git a/src/mesa/state_tracker/st_cache.h b/src/mesa/state_tracker/st_cache.h
new file mode 100644
index 00000000000..b81de316ec9
--- /dev/null
+++ b/src/mesa/state_tracker/st_cache.h
@@ -0,0 +1,68 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Zack Rusin <[email protected]>
+ */
+
+#ifndef ST_CACHE_H
+#define ST_CACHE_H
+
+#include "cso_cache/cso_cache.h"
+
+struct pipe_blend_state;
+struct pipe_sampler_state;
+struct st_context;
+
+
+const struct cso_blend *
+st_cached_blend_state(struct st_context *st,
+ const struct pipe_blend_state *blend);
+
+const struct cso_sampler *
+st_cached_sampler_state(struct st_context *st,
+ const struct pipe_sampler_state *sampler);
+
+const struct cso_depth_stencil_alpha *
+st_cached_depth_stencil_alpha_state(struct st_context *st,
+ const struct pipe_depth_stencil_alpha_state *depth_stencil);
+
+const struct cso_rasterizer *
+st_cached_rasterizer_state(struct st_context *st,
+ const struct pipe_rasterizer_state *raster);
+
+const struct cso_fragment_shader *
+st_cached_fs_state(struct st_context *st,
+ const struct pipe_shader_state *templ);
+
+
+const struct cso_vertex_shader *
+st_cached_vs_state(struct st_context *st,
+ const struct pipe_shader_state *templ);
+
+#endif
diff --git a/src/mesa/state_tracker/st_cb_accum.c b/src/mesa/state_tracker/st_cb_accum.c
new file mode 100644
index 00000000000..a4e72b48ed4
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_accum.c
@@ -0,0 +1,362 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Brian Paul
+ */
+
+#include "main/imports.h"
+#include "main/image.h"
+#include "main/macros.h"
+
+#include "st_context.h"
+#include "st_cb_accum.h"
+#include "st_cb_fbo.h"
+#include "st_draw.h"
+#include "st_public.h"
+#include "st_format.h"
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "util/u_tile.h"
+
+
+#define UNCLAMPED_FLOAT_TO_SHORT(us, f) \
+ us = ( (short) ( CLAMP((f), -1.0, 1.0) * 32767.0F) )
+
+
+/**
+ * For hardware that supports deep color buffers, we could accelerate
+ * most/all the accum operations with blending/texturing.
+ * For now, just use the get/put_tile() functions and do things in software.
+ */
+
+
+/**
+ * Wrapper for pipe_get_tile_rgba(). Do format/cpp override to make the
+ * tile util function think the surface is 16bit/channel, even if it's not.
+ * See also: st_renderbuffer_alloc_storage()
+ */
+static void
+acc_get_tile_rgba(struct pipe_context *pipe, struct pipe_surface *acc_ps,
+ uint x, uint y, uint w, uint h, float *p)
+{
+ const enum pipe_format f = acc_ps->format;
+ const struct pipe_format_block b = acc_ps->block;
+
+ acc_ps->format = DEFAULT_ACCUM_PIPE_FORMAT;
+ acc_ps->block.size = 8;
+ acc_ps->block.width = 1;
+ acc_ps->block.height = 1;
+
+ pipe_get_tile_rgba(acc_ps, x, y, w, h, p);
+
+ acc_ps->format = f;
+ acc_ps->block = b;
+}
+
+
+/**
+ * Wrapper for pipe_put_tile_rgba(). Do format/cpp override to make the
+ * tile util function think the surface is 16bit/channel, even if it's not.
+ * See also: st_renderbuffer_alloc_storage()
+ */
+static void
+acc_put_tile_rgba(struct pipe_context *pipe, struct pipe_surface *acc_ps,
+ uint x, uint y, uint w, uint h, const float *p)
+{
+ enum pipe_format f = acc_ps->format;
+ const struct pipe_format_block b = acc_ps->block;
+
+ acc_ps->format = DEFAULT_ACCUM_PIPE_FORMAT;
+ acc_ps->block.size = 8;
+ acc_ps->block.width = 1;
+ acc_ps->block.height = 1;
+
+ pipe_put_tile_rgba(acc_ps, x, y, w, h, p);
+
+ acc_ps->format = f;
+ acc_ps->block = b;
+}
+
+
+
+void
+st_clear_accum_buffer(GLcontext *ctx, struct gl_renderbuffer *rb)
+{
+ struct st_renderbuffer *acc_strb = st_renderbuffer(rb);
+ struct pipe_surface *acc_ps;
+ struct pipe_screen *screen = ctx->st->pipe->screen;
+ const GLint xpos = ctx->DrawBuffer->_Xmin;
+ const GLint ypos = ctx->DrawBuffer->_Ymin;
+ const GLint width = ctx->DrawBuffer->_Xmax - xpos;
+ const GLint height = ctx->DrawBuffer->_Ymax - ypos;
+ GLubyte *map;
+
+ acc_ps = screen->get_tex_surface(screen, acc_strb->texture, 0, 0, 0,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+ map = screen->surface_map(screen, acc_ps,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+
+ /* note acc_strb->format might not equal acc_ps->format */
+ switch (acc_strb->format) {
+ case PIPE_FORMAT_R16G16B16A16_SNORM:
+ {
+ GLshort r = FLOAT_TO_SHORT(ctx->Accum.ClearColor[0]);
+ GLshort g = FLOAT_TO_SHORT(ctx->Accum.ClearColor[1]);
+ GLshort b = FLOAT_TO_SHORT(ctx->Accum.ClearColor[2]);
+ GLshort a = FLOAT_TO_SHORT(ctx->Accum.ClearColor[3]);
+ int i, j;
+ for (i = 0; i < height; i++) {
+ GLshort *dst = (GLshort *) (map + (ypos + i) * acc_ps->stride + xpos * 8);
+ for (j = 0; j < width; j++) {
+ dst[0] = r;
+ dst[1] = g;
+ dst[2] = b;
+ dst[3] = a;
+ dst += 4;
+ }
+ }
+ }
+ break;
+ default:
+ _mesa_problem(ctx, "unexpected format in st_clear_accum_buffer()");
+ }
+
+ screen->surface_unmap(screen, acc_ps);
+ pipe_surface_reference(&acc_ps, NULL);
+}
+
+
+/** For ADD/MULT */
+static void
+accum_mad(GLcontext *ctx, GLfloat scale, GLfloat bias,
+ GLint xpos, GLint ypos, GLint width, GLint height,
+ struct st_renderbuffer *acc_strb)
+{
+ struct pipe_screen *screen = ctx->st->pipe->screen;
+ struct pipe_surface *acc_ps = acc_strb->surface;
+ GLubyte *map;
+
+ map = screen->surface_map(screen, acc_ps,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+
+ /* note acc_strb->format might not equal acc_ps->format */
+ switch (acc_strb->format) {
+ case PIPE_FORMAT_R16G16B16A16_SNORM:
+ {
+ int i, j;
+ for (i = 0; i < height; i++) {
+ GLshort *acc = (GLshort *) (map + (ypos + i) * acc_ps->stride + xpos * 8);
+ for (j = 0; j < width * 4; j++) {
+ float val = SHORT_TO_FLOAT(acc[j]) * scale + bias;
+ acc[j] = FLOAT_TO_SHORT(val);
+ }
+ }
+ }
+ break;
+ default:
+ _mesa_problem(NULL, "unexpected format in st_clear_accum_buffer()");
+ }
+
+ screen->surface_unmap(screen, acc_ps);
+}
+
+
+static void
+accum_accum(struct pipe_context *pipe, GLfloat value,
+ GLint xpos, GLint ypos, GLint width, GLint height,
+ struct st_renderbuffer *acc_strb,
+ struct st_renderbuffer *color_strb)
+{
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_surface *acc_surf, *color_surf;
+ GLfloat *colorBuf, *accBuf;
+ GLint i;
+
+ acc_surf = screen->get_tex_surface(screen, acc_strb->texture, 0, 0, 0,
+ (PIPE_BUFFER_USAGE_CPU_WRITE |
+ PIPE_BUFFER_USAGE_CPU_READ));
+
+ color_surf = screen->get_tex_surface(screen, color_strb->texture, 0, 0, 0,
+ PIPE_BUFFER_USAGE_CPU_READ);
+
+ colorBuf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
+ accBuf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
+
+ pipe_get_tile_rgba(color_surf, xpos, ypos, width, height, colorBuf);
+ acc_get_tile_rgba(pipe, acc_surf, xpos, ypos, width, height, accBuf);
+
+ for (i = 0; i < 4 * width * height; i++) {
+ accBuf[i] = accBuf[i] + colorBuf[i] * value;
+ }
+
+ acc_put_tile_rgba(pipe, acc_surf, xpos, ypos, width, height, accBuf);
+
+ free(colorBuf);
+ free(accBuf);
+ pipe_surface_reference(&acc_surf, NULL);
+ pipe_surface_reference(&color_surf, NULL);
+}
+
+
+static void
+accum_load(struct pipe_context *pipe, GLfloat value,
+ GLint xpos, GLint ypos, GLint width, GLint height,
+ struct st_renderbuffer *acc_strb,
+ struct st_renderbuffer *color_strb)
+{
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_surface *acc_surf, *color_surf;
+ GLfloat *buf;
+ GLint i;
+
+ acc_surf = screen->get_tex_surface(screen, acc_strb->texture, 0, 0, 0,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+
+ color_surf = screen->get_tex_surface(screen, color_strb->texture, 0, 0, 0,
+ PIPE_BUFFER_USAGE_CPU_READ);
+
+ buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
+
+ pipe_get_tile_rgba(color_surf, xpos, ypos, width, height, buf);
+
+ for (i = 0; i < 4 * width * height; i++) {
+ buf[i] = buf[i] * value;
+ }
+
+ acc_put_tile_rgba(pipe, acc_surf, xpos, ypos, width, height, buf);
+
+ free(buf);
+ pipe_surface_reference(&acc_surf, NULL);
+ pipe_surface_reference(&color_surf, NULL);
+}
+
+
+static void
+accum_return(GLcontext *ctx, GLfloat value,
+ GLint xpos, GLint ypos, GLint width, GLint height,
+ struct st_renderbuffer *acc_strb,
+ struct st_renderbuffer *color_strb)
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ const GLubyte *colormask = ctx->Color.ColorMask;
+ struct pipe_surface *acc_surf, *color_surf;
+ GLfloat *abuf, *cbuf = NULL;
+ GLint i, ch;
+
+ abuf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
+
+ acc_surf = screen->get_tex_surface(screen, acc_strb->texture, 0, 0, 0,
+ PIPE_BUFFER_USAGE_CPU_READ);
+
+ color_surf = screen->get_tex_surface(screen, color_strb->texture, 0, 0, 0,
+ (PIPE_BUFFER_USAGE_CPU_READ |
+ PIPE_BUFFER_USAGE_CPU_WRITE));
+
+ acc_get_tile_rgba(pipe, acc_surf, xpos, ypos, width, height, abuf);
+
+ if (!colormask[0] || !colormask[1] || !colormask[2] || !colormask[3]) {
+ cbuf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
+ pipe_get_tile_rgba(color_surf, xpos, ypos, width, height, cbuf);
+ }
+
+ for (i = 0; i < width * height; i++) {
+ for (ch = 0; ch < 4; ch++) {
+ if (colormask[ch]) {
+ GLfloat val = abuf[i * 4 + ch] * value;
+ abuf[i * 4 + ch] = CLAMP(val, 0.0f, 1.0f);
+ }
+ else {
+ abuf[i * 4 + ch] = cbuf[i * 4 + ch];
+ }
+ }
+ }
+
+ pipe_put_tile_rgba(color_surf, xpos, ypos, width, height, abuf);
+
+ free(abuf);
+ if (cbuf)
+ free(cbuf);
+ pipe_surface_reference(&acc_surf, NULL);
+ pipe_surface_reference(&color_surf, NULL);
+}
+
+
+static void
+st_Accum(GLcontext *ctx, GLenum op, GLfloat value)
+{
+ struct st_context *st = ctx->st;
+ struct pipe_context *pipe = st->pipe;
+ struct st_renderbuffer *acc_strb
+ = st_renderbuffer(ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer);
+ struct st_renderbuffer *color_strb
+ = st_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer);
+
+ const GLint xpos = ctx->DrawBuffer->_Xmin;
+ const GLint ypos = ctx->DrawBuffer->_Ymin;
+ const GLint width = ctx->DrawBuffer->_Xmax - xpos;
+ const GLint height = ctx->DrawBuffer->_Ymax - ypos;
+
+ /* make sure color bufs aren't cached */
+ st_flush( st, PIPE_FLUSH_RENDER_CACHE, NULL );
+
+ switch (op) {
+ case GL_ADD:
+ if (value != 0.0F) {
+ accum_mad(ctx, 1.0, value, xpos, ypos, width, height, acc_strb);
+ }
+ break;
+ case GL_MULT:
+ if (value != 1.0F) {
+ accum_mad(ctx, value, 0.0, xpos, ypos, width, height, acc_strb);
+ }
+ break;
+ case GL_ACCUM:
+ if (value != 0.0F) {
+ accum_accum(pipe, value, xpos, ypos, width, height, acc_strb, color_strb);
+ }
+ break;
+ case GL_LOAD:
+ accum_load(pipe, value, xpos, ypos, width, height, acc_strb, color_strb);
+ break;
+ case GL_RETURN:
+ accum_return(ctx, value, xpos, ypos, width, height, acc_strb, color_strb);
+ break;
+ default:
+ assert(0);
+ }
+}
+
+
+
+void st_init_accum_functions(struct dd_function_table *functions)
+{
+ functions->Accum = st_Accum;
+}
diff --git a/src/mesa/state_tracker/st_cb_accum.h b/src/mesa/state_tracker/st_cb_accum.h
new file mode 100644
index 00000000000..ed9b7dab943
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_accum.h
@@ -0,0 +1,39 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_CB_ACCUM_H
+#define ST_CB_ACCUM_H
+
+
+extern void
+st_clear_accum_buffer(GLcontext *ctx, struct gl_renderbuffer *rb);
+
+extern void st_init_accum_functions(struct dd_function_table *functions);
+
+
+#endif /* ST_CB_ACCUM_H */
diff --git a/src/mesa/state_tracker/st_cb_bitmap.c b/src/mesa/state_tracker/st_cb_bitmap.c
new file mode 100644
index 00000000000..f14e562400b
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_bitmap.c
@@ -0,0 +1,833 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Brian Paul
+ */
+
+#include "main/imports.h"
+#include "main/image.h"
+#include "main/bufferobj.h"
+#include "main/macros.h"
+#include "main/texformat.h"
+#include "shader/program.h"
+#include "shader/prog_parameter.h"
+#include "shader/prog_print.h"
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "st_atom_constbuf.h"
+#include "st_program.h"
+#include "st_cb_bitmap.h"
+#include "st_cb_program.h"
+#include "st_mesa_to_tgsi.h"
+#include "st_texture.h"
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "util/u_tile.h"
+#include "util/u_draw_quad.h"
+#include "util/u_simple_shaders.h"
+#include "shader/prog_instruction.h"
+#include "cso_cache/cso_context.h"
+
+
+
+/**
+ * glBitmaps are drawn as textured quads. The user's bitmap pattern
+ * is stored in a texture image. An alpha8 texture format is used.
+ * The fragment shader samples a bit (texel) from the texture, then
+ * discards the fragment if the bit is off.
+ *
+ * Note that we actually store the inverse image of the bitmap to
+ * simplify the fragment program. An "on" bit gets stored as texel=0x0
+ * and an "off" bit is stored as texel=0xff. Then we kill the
+ * fragment if the negated texel value is less than zero.
+ */
+
+
+/**
+ * The bitmap cache attempts to accumulate multiple glBitmap calls in a
+ * buffer which is then rendered en mass upon a flush, state change, etc.
+ * A wide, short buffer is used to target the common case of a series
+ * of glBitmap calls being used to draw text.
+ */
+static GLboolean UseBitmapCache = GL_TRUE;
+
+
+#define BITMAP_CACHE_WIDTH 512
+#define BITMAP_CACHE_HEIGHT 32
+
+struct bitmap_cache
+{
+ /** Window pos to render the cached image */
+ GLint xpos, ypos;
+ /** Bounds of region used in window coords */
+ GLint xmin, ymin, xmax, ymax;
+
+ GLfloat color[4];
+
+ struct pipe_texture *texture;
+ struct pipe_surface *surf;
+
+ GLboolean empty;
+
+ /** An I8 texture image: */
+ ubyte *buffer;
+};
+
+
+
+
+/**
+ * Make fragment program for glBitmap:
+ * Sample the texture and kill the fragment if the bit is 0.
+ * This program will be combined with the user's fragment program.
+ */
+static struct st_fragment_program *
+make_bitmap_fragment_program(GLcontext *ctx, GLuint samplerIndex)
+{
+ struct st_fragment_program *stfp;
+ struct gl_program *p;
+ GLuint ic = 0;
+
+ p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
+ if (!p)
+ return NULL;
+
+ p->NumInstructions = 3;
+
+ p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
+ if (!p->Instructions) {
+ ctx->Driver.DeleteProgram(ctx, p);
+ return NULL;
+ }
+ _mesa_init_instructions(p->Instructions, p->NumInstructions);
+
+ /* TEX tmp0, fragment.texcoord[0], texture[0], 2D; */
+ p->Instructions[ic].Opcode = OPCODE_TEX;
+ p->Instructions[ic].DstReg.File = PROGRAM_TEMPORARY;
+ p->Instructions[ic].DstReg.Index = 0;
+ p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
+ p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0;
+ p->Instructions[ic].TexSrcUnit = samplerIndex;
+ p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX;
+ ic++;
+
+ /* KIL if -tmp0 < 0 # texel=0 -> keep / texel=0 -> discard */
+ p->Instructions[ic].Opcode = OPCODE_KIL;
+ p->Instructions[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
+ p->Instructions[ic].SrcReg[0].Index = 0;
+ p->Instructions[ic].SrcReg[0].NegateBase = NEGATE_XYZW;
+ ic++;
+
+ /* END; */
+ p->Instructions[ic++].Opcode = OPCODE_END;
+
+ assert(ic == p->NumInstructions);
+
+ p->InputsRead = FRAG_BIT_TEX0;
+ p->OutputsWritten = 0x0;
+ p->SamplersUsed = (1 << samplerIndex);
+
+ stfp = (struct st_fragment_program *) p;
+ stfp->Base.UsesKill = GL_TRUE;
+ st_translate_fragment_program(ctx->st, stfp, NULL);
+
+ return stfp;
+}
+
+
+static int
+find_free_bit(uint bitfield)
+{
+ int i;
+ for (i = 0; i < 32; i++) {
+ if ((bitfield & (1 << i)) == 0) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+
+/**
+ * Combine basic bitmap fragment program with the user-defined program.
+ */
+static struct st_fragment_program *
+combined_bitmap_fragment_program(GLcontext *ctx)
+{
+ struct st_context *st = ctx->st;
+ struct st_fragment_program *stfp = st->fp;
+
+ if (!stfp->bitmap_program) {
+ /*
+ * Generate new program which is the user-defined program prefixed
+ * with the bitmap sampler/kill instructions.
+ */
+ struct st_fragment_program *bitmap_prog;
+ uint sampler;
+
+ sampler = find_free_bit(st->fp->Base.Base.SamplersUsed);
+ bitmap_prog = make_bitmap_fragment_program(ctx, sampler);
+
+ stfp->bitmap_program = (struct st_fragment_program *)
+ _mesa_combine_programs(ctx,
+ &bitmap_prog->Base.Base, &stfp->Base.Base);
+ stfp->bitmap_program->bitmap_sampler = sampler;
+
+ /* done with this after combining */
+ st_reference_fragprog(st, &bitmap_prog, NULL);
+
+#if 0
+ {
+ struct gl_program *p = &stfp->bitmap_program->Base.Base;
+ printf("Combined bitmap program:\n");
+ _mesa_print_program(p);
+ printf("InputsRead: 0x%x\n", p->InputsRead);
+ printf("OutputsWritten: 0x%x\n", p->OutputsWritten);
+ _mesa_print_parameter_list(p->Parameters);
+ }
+#endif
+
+ /* translate to TGSI tokens */
+ st_translate_fragment_program(st, stfp->bitmap_program, NULL);
+ }
+
+ return stfp->bitmap_program;
+}
+
+
+/**
+ * Copy user-provide bitmap bits into texture buffer, expanding
+ * bits into texels.
+ * "On" bits will set texels to 0xff.
+ * "Off" bits will not modify texels.
+ * Note that the image is actually going to be upside down in
+ * the texture. We deal with that with texcoords.
+ */
+static void
+unpack_bitmap(struct st_context *st,
+ GLint px, GLint py, GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap,
+ ubyte *destBuffer, uint destStride)
+{
+ GLint row, col;
+
+#define SET_PIXEL(COL, ROW) \
+ destBuffer[(py + (ROW)) * destStride + px + (COL)] = 0x0;
+
+ for (row = 0; row < height; row++) {
+ const GLubyte *src = (const GLubyte *) _mesa_image_address2d(unpack,
+ bitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, row, 0);
+
+ if (unpack->LsbFirst) {
+ /* Lsb first */
+ GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
+ for (col = 0; col < width; col++) {
+
+ if (*src & mask) {
+ SET_PIXEL(col, row);
+ }
+
+ if (mask == 128U) {
+ src++;
+ mask = 1U;
+ }
+ else {
+ mask = mask << 1;
+ }
+ }
+
+ /* get ready for next row */
+ if (mask != 1)
+ src++;
+ }
+ else {
+ /* Msb first */
+ GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
+ for (col = 0; col < width; col++) {
+
+ if (*src & mask) {
+ SET_PIXEL(col, row);
+ }
+
+ if (mask == 1U) {
+ src++;
+ mask = 128U;
+ }
+ else {
+ mask = mask >> 1;
+ }
+ }
+
+ /* get ready for next row */
+ if (mask != 128)
+ src++;
+ }
+
+ } /* row */
+
+#undef SET_PIXEL
+}
+
+
+/**
+ * Create a texture which represents a bitmap image.
+ */
+static struct pipe_texture *
+make_bitmap_texture(GLcontext *ctx, GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap)
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_surface *surface;
+ ubyte *dest;
+ struct pipe_texture *pt;
+
+ /* PBO source... */
+ bitmap = _mesa_map_bitmap_pbo(ctx, unpack, bitmap);
+ if (!bitmap) {
+ return NULL;
+ }
+
+ /**
+ * Create texture to hold bitmap pattern.
+ */
+ pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, ctx->st->bitmap.tex_format,
+ 0, width, height, 1, 0,
+ PIPE_TEXTURE_USAGE_SAMPLER);
+ if (!pt) {
+ _mesa_unmap_bitmap_pbo(ctx, unpack);
+ return NULL;
+ }
+
+ surface = screen->get_tex_surface(screen, pt, 0, 0, 0,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+
+ /* map texture surface */
+ dest = screen->surface_map(screen, surface, PIPE_BUFFER_USAGE_CPU_WRITE);
+
+ /* Put image into texture surface */
+ memset(dest, 0xff, height * surface->stride);
+ unpack_bitmap(ctx->st, 0, 0, width, height, unpack, bitmap,
+ dest, surface->stride);
+
+ _mesa_unmap_bitmap_pbo(ctx, unpack);
+
+ /* Release surface */
+ screen->surface_unmap(screen, surface);
+ pipe_surface_reference(&surface, NULL);
+
+ return pt;
+}
+
+static GLuint
+setup_bitmap_vertex_data(struct st_context *st,
+ int x, int y, int width, int height,
+ float z, const float color[4])
+{
+ struct pipe_context *pipe = st->pipe;
+ const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
+ const GLfloat fb_width = (GLfloat)fb->Width;
+ const GLfloat fb_height = (GLfloat)fb->Height;
+ const GLfloat x0 = (GLfloat)x;
+ const GLfloat x1 = (GLfloat)(x + width);
+ const GLfloat y0 = (GLfloat)y;
+ const GLfloat y1 = (GLfloat)(y + height);
+ const GLfloat sLeft = (GLfloat)0.0, sRight = (GLfloat)1.0;
+ const GLfloat tTop = (GLfloat)0.0, tBot = (GLfloat)1.0 - tTop;
+ const GLfloat clip_x0 = (GLfloat)(x0 / fb_width * 2.0 - 1.0);
+ const GLfloat clip_y0 = (GLfloat)(y0 / fb_height * 2.0 - 1.0);
+ const GLfloat clip_x1 = (GLfloat)(x1 / fb_width * 2.0 - 1.0);
+ const GLfloat clip_y1 = (GLfloat)(y1 / fb_height * 2.0 - 1.0);
+ const GLuint max_slots = 4096 / sizeof(st->bitmap.vertices);
+ GLuint i;
+
+ if (st->bitmap.vbuf_slot >= max_slots) {
+ pipe_buffer_reference(pipe->screen, &st->bitmap.vbuf, NULL);
+ st->bitmap.vbuf_slot = 0;
+ }
+
+ if (!st->bitmap.vbuf) {
+ st->bitmap.vbuf = pipe_buffer_create(pipe->screen, 32,
+ PIPE_BUFFER_USAGE_VERTEX,
+ max_slots * sizeof(st->bitmap.vertices));
+ }
+
+ /* Positions are in clip coords since we need to do clipping in case
+ * the bitmap quad goes beyond the window bounds.
+ */
+ st->bitmap.vertices[0][0][0] = clip_x0;
+ st->bitmap.vertices[0][0][1] = clip_y0;
+ st->bitmap.vertices[0][2][0] = sLeft;
+ st->bitmap.vertices[0][2][1] = tTop;
+
+ st->bitmap.vertices[1][0][0] = clip_x1;
+ st->bitmap.vertices[1][0][1] = clip_y0;
+ st->bitmap.vertices[1][2][0] = sRight;
+ st->bitmap.vertices[1][2][1] = tTop;
+
+ st->bitmap.vertices[2][0][0] = clip_x1;
+ st->bitmap.vertices[2][0][1] = clip_y1;
+ st->bitmap.vertices[2][2][0] = sRight;
+ st->bitmap.vertices[2][2][1] = tBot;
+
+ st->bitmap.vertices[3][0][0] = clip_x0;
+ st->bitmap.vertices[3][0][1] = clip_y1;
+ st->bitmap.vertices[3][2][0] = sLeft;
+ st->bitmap.vertices[3][2][1] = tBot;
+
+ /* same for all verts: */
+ for (i = 0; i < 4; i++) {
+ st->bitmap.vertices[i][0][2] = z;
+ st->bitmap.vertices[i][0][3] = 1.0;
+ st->bitmap.vertices[i][1][0] = color[0];
+ st->bitmap.vertices[i][1][1] = color[1];
+ st->bitmap.vertices[i][1][2] = color[2];
+ st->bitmap.vertices[i][1][3] = color[3];
+ st->bitmap.vertices[i][2][2] = 0.0; /*R*/
+ st->bitmap.vertices[i][2][3] = 1.0; /*Q*/
+ }
+
+ /* put vertex data into vbuf */
+ {
+ char *buf = pipe_buffer_map(pipe->screen,
+ st->bitmap.vbuf,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+
+ memcpy(buf + st->bitmap.vbuf_slot * sizeof st->bitmap.vertices,
+ st->bitmap.vertices,
+ sizeof st->bitmap.vertices);
+
+ pipe_buffer_unmap(pipe->screen, st->bitmap.vbuf);
+ }
+
+ return st->bitmap.vbuf_slot++ * sizeof st->bitmap.vertices;
+}
+
+
+
+/**
+ * Render a glBitmap by drawing a textured quad
+ */
+static void
+draw_bitmap_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
+ GLsizei width, GLsizei height,
+ struct pipe_texture *pt,
+ const GLfloat *color)
+{
+ struct st_context *st = ctx->st;
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct cso_context *cso = ctx->st->cso_context;
+ struct st_fragment_program *stfp;
+ GLuint maxSize;
+ GLuint offset;
+
+ stfp = combined_bitmap_fragment_program(ctx);
+
+ /* As an optimization, Mesa's fragment programs will sometimes get the
+ * primary color from a statevar/constant rather than a varying variable.
+ * when that's the case, we need to ensure that we use the 'color'
+ * parameter and not the current attribute color (which may have changed
+ * through glRasterPos and state validation.
+ * So, we force the proper color here. Not elegant, but it works.
+ */
+ {
+ GLfloat colorSave[4];
+ COPY_4V(colorSave, ctx->Current.Attrib[VERT_ATTRIB_COLOR0]);
+ COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], color);
+ st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT);
+ COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], colorSave);
+ }
+
+
+ /* limit checks */
+ /* XXX if the bitmap is larger than the max texture size, break
+ * it up into chunks.
+ */
+ maxSize = 1 << (pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1);
+ assert(width <= (GLsizei)maxSize);
+ assert(height <= (GLsizei)maxSize);
+
+ cso_save_rasterizer(cso);
+ cso_save_samplers(cso);
+ cso_save_sampler_textures(cso);
+ cso_save_viewport(cso);
+ cso_save_fragment_shader(cso);
+ cso_save_vertex_shader(cso);
+
+ /* rasterizer state: just scissor */
+ st->bitmap.rasterizer.scissor = ctx->Scissor.Enabled;
+ cso_set_rasterizer(cso, &st->bitmap.rasterizer);
+
+ /* fragment shader state: TEX lookup program */
+ cso_set_fragment_shader_handle(cso, stfp->driver_shader);
+
+ /* vertex shader state: position + texcoord pass-through */
+ cso_set_vertex_shader_handle(cso, st->bitmap.vs);
+
+ /* user samplers, plus our bitmap sampler */
+ {
+ struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
+ uint num = MAX2(stfp->bitmap_sampler + 1, st->state.num_samplers);
+ uint i;
+ for (i = 0; i < st->state.num_samplers; i++) {
+ samplers[i] = &st->state.samplers[i];
+ }
+ samplers[stfp->bitmap_sampler] = &st->bitmap.sampler;
+ cso_set_samplers(cso, num, (const struct pipe_sampler_state **) samplers);
+ }
+
+ /* user textures, plus the bitmap texture */
+ {
+ struct pipe_texture *textures[PIPE_MAX_SAMPLERS];
+ uint num = MAX2(stfp->bitmap_sampler + 1, st->state.num_textures);
+ memcpy(textures, st->state.sampler_texture, sizeof(textures));
+ textures[stfp->bitmap_sampler] = pt;
+ cso_set_sampler_textures(cso, num, textures);
+ }
+
+ /* viewport state: viewport matching window dims */
+ {
+ const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
+ const GLboolean invert = (st_fb_orientation(fb) == Y_0_TOP);
+ const GLfloat width = (GLfloat)fb->Width;
+ const GLfloat height = (GLfloat)fb->Height;
+ struct pipe_viewport_state vp;
+ vp.scale[0] = 0.5f * width;
+ vp.scale[1] = height * (invert ? -0.5f : 0.5f);
+ vp.scale[2] = 1.0f;
+ vp.scale[3] = 1.0f;
+ vp.translate[0] = 0.5f * width;
+ vp.translate[1] = 0.5f * height;
+ vp.translate[2] = 0.0f;
+ vp.translate[3] = 0.0f;
+ cso_set_viewport(cso, &vp);
+ }
+
+ /* draw textured quad */
+ offset = setup_bitmap_vertex_data(st, x, y, width, height,
+ ctx->Current.RasterPos[2],
+ color);
+
+ util_draw_vertex_buffer(pipe, st->bitmap.vbuf, offset,
+ PIPE_PRIM_TRIANGLE_FAN,
+ 4, /* verts */
+ 3); /* attribs/vert */
+
+
+ /* restore state */
+ cso_restore_rasterizer(cso);
+ cso_restore_samplers(cso);
+ cso_restore_sampler_textures(cso);
+ cso_restore_viewport(cso);
+ cso_restore_fragment_shader(cso);
+ cso_restore_vertex_shader(cso);
+}
+
+
+static void
+reset_cache(struct st_context *st)
+{
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct bitmap_cache *cache = st->bitmap.cache;
+
+ //memset(cache->buffer, 0xff, sizeof(cache->buffer));
+ cache->empty = GL_TRUE;
+
+ cache->xmin = 1000000;
+ cache->xmax = -1000000;
+ cache->ymin = 1000000;
+ cache->ymax = -1000000;
+
+ if (cache->surf)
+ screen->tex_surface_release(screen, &cache->surf);
+
+ assert(!cache->texture);
+
+ /* allocate a new texture */
+ cache->texture = st_texture_create(st, PIPE_TEXTURE_2D,
+ st->bitmap.tex_format, 0,
+ BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT,
+ 1, 0,
+ PIPE_TEXTURE_USAGE_SAMPLER);
+
+ /* Map the texture surface.
+ * Subsequent glBitmap calls will write into the texture image.
+ */
+ cache->surf = screen->get_tex_surface(screen, cache->texture, 0, 0, 0,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+ cache->buffer = screen->surface_map(screen, cache->surf,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+
+ /* init image to all 0xff */
+ memset(cache->buffer, 0xff, BITMAP_CACHE_WIDTH * BITMAP_CACHE_HEIGHT);
+}
+
+
+/**
+ * If there's anything in the bitmap cache, draw/flush it now.
+ */
+void
+st_flush_bitmap_cache(struct st_context *st)
+{
+ if (!st->bitmap.cache->empty) {
+ struct bitmap_cache *cache = st->bitmap.cache;
+
+ if (st->ctx->DrawBuffer) {
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+
+ assert(cache->xmin <= cache->xmax);
+
+/* printf("flush size %d x %d at %d, %d\n",
+ cache->xmax - cache->xmin,
+ cache->ymax - cache->ymin,
+ cache->xpos, cache->ypos);
+*/
+
+ /* The texture surface has been mapped until now.
+ * So unmap and release the texture surface before drawing.
+ */
+ screen->surface_unmap(screen, cache->surf);
+ cache->buffer = NULL;
+
+ screen->tex_surface_release(screen, &cache->surf);
+
+ draw_bitmap_quad(st->ctx,
+ cache->xpos,
+ cache->ypos,
+ st->ctx->Current.RasterPos[2],
+ BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT,
+ cache->texture,
+ cache->color);
+ }
+
+ /* release/free the texture */
+ pipe_texture_reference(&cache->texture, NULL);
+
+ reset_cache(st);
+ }
+}
+
+/* Flush bitmap cache and release vertex buffer.
+ */
+void
+st_flush_bitmap( struct st_context *st )
+{
+ st_flush_bitmap_cache(st);
+
+ /* Release vertex buffer to avoid synchronous rendering if we were
+ * to map it in the next frame.
+ */
+ pipe_buffer_reference(st->pipe->screen, &st->bitmap.vbuf, NULL);
+ st->bitmap.vbuf_slot = 0;
+}
+
+
+/**
+ * Try to accumulate this glBitmap call in the bitmap cache.
+ * \return GL_TRUE for success, GL_FALSE if bitmap is too large, etc.
+ */
+static GLboolean
+accum_bitmap(struct st_context *st,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap )
+{
+ struct bitmap_cache *cache = st->bitmap.cache;
+ int px = -999, py;
+
+ if (width > BITMAP_CACHE_WIDTH ||
+ height > BITMAP_CACHE_HEIGHT)
+ return GL_FALSE; /* too big to cache */
+
+ if (!cache->empty) {
+ px = x - cache->xpos; /* pos in buffer */
+ py = y - cache->ypos;
+ if (px < 0 || px + width > BITMAP_CACHE_WIDTH ||
+ py < 0 || py + height > BITMAP_CACHE_HEIGHT ||
+ !TEST_EQ_4V(st->ctx->Current.RasterColor, cache->color)) {
+ /* This bitmap would extend beyond cache bounds, or the bitmap
+ * color is changing
+ * so flush and continue.
+ */
+ st_flush_bitmap_cache(st);
+ }
+ }
+
+ if (cache->empty) {
+ /* Initialize. Center bitmap vertically in the buffer. */
+ px = 0;
+ py = (BITMAP_CACHE_HEIGHT - height) / 2;
+ cache->xpos = x;
+ cache->ypos = y - py;
+ cache->empty = GL_FALSE;
+ COPY_4FV(cache->color, st->ctx->Current.RasterColor);
+ }
+
+ assert(px != -999);
+
+ if (x < cache->xmin)
+ cache->xmin = x;
+ if (y < cache->ymin)
+ cache->ymin = y;
+ if (x + width > cache->xmax)
+ cache->xmax = x + width;
+ if (y + height > cache->ymax)
+ cache->ymax = y + height;
+
+ unpack_bitmap(st, px, py, width, height, unpack, bitmap,
+ cache->buffer, BITMAP_CACHE_WIDTH);
+
+ return GL_TRUE; /* accumulated */
+}
+
+
+
+/**
+ * Called via ctx->Driver.Bitmap()
+ */
+static void
+st_Bitmap(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap )
+{
+ struct st_context *st = ctx->st;
+ struct pipe_texture *pt;
+
+ if (width == 0 || height == 0)
+ return;
+
+ st_validate_state(st);
+
+ if (!st->bitmap.vs) {
+ /* create pass-through vertex shader now */
+ const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
+ TGSI_SEMANTIC_COLOR,
+ TGSI_SEMANTIC_GENERIC };
+ const uint semantic_indexes[] = { 0, 0, 0 };
+ st->bitmap.vs = util_make_vertex_passthrough_shader(st->pipe, 3,
+ semantic_names,
+ semantic_indexes,
+ &st->bitmap.vert_shader);
+ }
+
+ if (UseBitmapCache && accum_bitmap(st, x, y, width, height, unpack, bitmap))
+ return;
+
+ pt = make_bitmap_texture(ctx, width, height, unpack, bitmap);
+ if (pt) {
+ assert(pt->target == PIPE_TEXTURE_2D);
+ draw_bitmap_quad(ctx, x, y, ctx->Current.RasterPos[2],
+ width, height, pt,
+ st->ctx->Current.RasterColor);
+ /* release/free the texture */
+ pipe_texture_reference(&pt, NULL);
+ }
+}
+
+
+/** Per-context init */
+void
+st_init_bitmap_functions(struct dd_function_table *functions)
+{
+ functions->Bitmap = st_Bitmap;
+}
+
+
+/** Per-context init */
+void
+st_init_bitmap(struct st_context *st)
+{
+ struct pipe_sampler_state *sampler = &st->bitmap.sampler;
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+
+ /* init sampler state once */
+ memset(sampler, 0, sizeof(*sampler));
+ sampler->wrap_s = PIPE_TEX_WRAP_CLAMP;
+ sampler->wrap_t = PIPE_TEX_WRAP_CLAMP;
+ sampler->wrap_r = PIPE_TEX_WRAP_CLAMP;
+ sampler->min_img_filter = PIPE_TEX_FILTER_NEAREST;
+ sampler->min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+ sampler->mag_img_filter = PIPE_TEX_FILTER_NEAREST;
+ sampler->normalized_coords = 1;
+
+ /* init baseline rasterizer state once */
+ memset(&st->bitmap.rasterizer, 0, sizeof(st->bitmap.rasterizer));
+ st->bitmap.rasterizer.gl_rasterization_rules = 1;
+ st->bitmap.rasterizer.bypass_vs = 1;
+
+ /* find a usable texture format */
+ if (screen->is_format_supported(screen, PIPE_FORMAT_I8_UNORM, PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_SAMPLER, 0)) {
+ st->bitmap.tex_format = PIPE_FORMAT_I8_UNORM;
+ }
+ else {
+ /* XXX support more formats */
+ assert(0);
+ }
+
+ /* alloc bitmap cache object */
+ st->bitmap.cache = CALLOC_STRUCT(bitmap_cache);
+
+ reset_cache(st);
+}
+
+
+/** Per-context tear-down */
+void
+st_destroy_bitmap(struct st_context *st)
+{
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct bitmap_cache *cache = st->bitmap.cache;
+
+ screen->surface_unmap(screen, cache->surf);
+ screen->tex_surface_release(screen, &cache->surf);
+
+ if (st->bitmap.vs) {
+ cso_delete_vertex_shader(st->cso_context, st->bitmap.vs);
+ st->bitmap.vs = NULL;
+ }
+
+ if (st->bitmap.vbuf) {
+ pipe_buffer_reference(pipe->screen, &st->bitmap.vbuf, NULL);
+ st->bitmap.vbuf = NULL;
+ }
+
+ if (st->bitmap.cache) {
+ pipe_texture_release(&st->bitmap.cache->texture);
+ FREE(st->bitmap.cache);
+ st->bitmap.cache = NULL;
+ }
+}
diff --git a/src/mesa/state_tracker/st_cb_bitmap.h b/src/mesa/state_tracker/st_cb_bitmap.h
new file mode 100644
index 00000000000..81cf61981dc
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_bitmap.h
@@ -0,0 +1,52 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_CB_BITMAP_H
+#define ST_CB_BITMAP_H
+
+
+extern void
+st_init_bitmap_functions(struct dd_function_table *functions);
+
+extern void
+st_init_bitmap(struct st_context *st);
+
+extern void
+st_destroy_bitmap(struct st_context *st);
+
+extern void
+st_flush_bitmap_cache(struct st_context *st);
+
+/* Flush bitmap cache and release vertex buffer. Needed at end of
+ * frame to avoid synchronous rendering.
+ */
+extern void
+st_flush_bitmap(struct st_context *st);
+
+
+#endif /* ST_CB_BITMAP_H */
diff --git a/src/mesa/state_tracker/st_cb_blit.c b/src/mesa/state_tracker/st_cb_blit.c
new file mode 100644
index 00000000000..28526234720
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_blit.c
@@ -0,0 +1,111 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Brian Paul
+ */
+
+#include "main/imports.h"
+#include "main/image.h"
+#include "main/macros.h"
+#include "main/texformat.h"
+#include "shader/program.h"
+#include "shader/prog_parameter.h"
+#include "shader/prog_print.h"
+
+#include "st_context.h"
+#include "st_program.h"
+#include "st_cb_blit.h"
+#include "st_cb_fbo.h"
+
+#include "util/u_blit.h"
+
+#include "cso_cache/cso_context.h"
+
+
+void
+st_init_blit(struct st_context *st)
+{
+ st->blit = util_create_blit(st->pipe, st->cso_context);
+}
+
+
+void
+st_destroy_blit(struct st_context *st)
+{
+ util_destroy_blit(st->blit);
+ st->blit = NULL;
+}
+
+
+static void
+st_BlitFramebuffer(GLcontext *ctx,
+ GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter)
+{
+ struct st_context *st = ctx->st;
+
+ const uint pFilter = ((filter == GL_NEAREST)
+ ? PIPE_TEX_MIPFILTER_NEAREST
+ : PIPE_TEX_MIPFILTER_LINEAR);
+
+ if (mask & GL_COLOR_BUFFER_BIT) {
+ struct st_renderbuffer *srcRb =
+ st_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer);
+ struct st_renderbuffer *dstRb =
+ st_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0]);
+ struct pipe_surface *srcSurf = srcRb->surface;
+ struct pipe_surface *dstSurf = dstRb->surface;
+
+ if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
+ /* invert Y */
+ srcY0 = srcRb->Base.Height - srcY0;
+ srcY1 = srcRb->Base.Height - srcY1;
+
+ dstY0 = dstRb->Base.Height - dstY0;
+ dstY1 = dstRb->Base.Height - dstY1;
+ }
+
+ util_blit_pixels(st->blit,
+ srcSurf, srcX0, srcY0, srcX1, srcY1,
+ dstSurf, dstX0, dstY0, dstX1, dstY1,
+ 0.0, pFilter);
+
+ }
+}
+
+
+
+void
+st_init_blit_functions(struct dd_function_table *functions)
+{
+#if FEATURE_EXT_framebuffer_blit
+ functions->BlitFramebuffer = st_BlitFramebuffer;
+#endif
+}
diff --git a/src/mesa/state_tracker/st_cb_blit.h b/src/mesa/state_tracker/st_cb_blit.h
new file mode 100644
index 00000000000..ed22986b531
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_blit.h
@@ -0,0 +1,46 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+#ifndef ST_CB_BLIT_H
+#define ST_CB_BLIT_H
+
+
+#include "st_context.h"
+
+
+
+extern void
+st_init_blit(struct st_context *st);
+
+extern void
+st_destroy_blit(struct st_context *st);
+
+extern void
+st_init_blit_functions(struct dd_function_table *functions);
+
+
+#endif /* ST_CB_BLIT_H */
diff --git a/src/mesa/state_tracker/st_cb_bufferobjects.c b/src/mesa/state_tracker/st_cb_bufferobjects.c
new file mode 100644
index 00000000000..07fa2afce05
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_bufferobjects.c
@@ -0,0 +1,240 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+
+#include "main/imports.h"
+#include "main/mtypes.h"
+#include "main/bufferobj.h"
+
+#include "st_context.h"
+#include "st_cb_bufferobjects.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+
+
+
+/* Pixel buffers and Vertex/index buffers are handled through these
+ * mesa callbacks. Framebuffer/Renderbuffer objects are
+ * created/managed elsewhere.
+ */
+
+
+
+/**
+ * There is some duplication between mesa's bufferobjects and our
+ * bufmgr buffers. Both have an integer handle and a hashtable to
+ * lookup an opaque structure. It would be nice if the handles and
+ * internal structure where somehow shared.
+ */
+static struct gl_buffer_object *
+st_bufferobj_alloc(GLcontext *ctx, GLuint name, GLenum target)
+{
+ struct st_buffer_object *st_obj = CALLOC_STRUCT(st_buffer_object);
+
+ if (!st_obj)
+ return NULL;
+
+ _mesa_initialize_buffer_object(&st_obj->Base, name, target);
+
+ return &st_obj->Base;
+}
+
+
+
+/**
+ * Deallocate/free a vertex/pixel buffer object.
+ * Called via glDeleteBuffersARB().
+ */
+static void
+st_bufferobj_free(GLcontext *ctx, struct gl_buffer_object *obj)
+{
+ struct pipe_context *pipe = st_context(ctx)->pipe;
+ struct st_buffer_object *st_obj = st_buffer_object(obj);
+
+ if (st_obj->buffer)
+ pipe_buffer_reference(pipe->screen, &st_obj->buffer, NULL);
+
+ free(st_obj);
+}
+
+
+
+/**
+ * Replace data in a subrange of buffer object. If the data range
+ * specified by size + offset extends beyond the end of the buffer or
+ * if data is NULL, no copy is performed.
+ * Called via glBufferSubDataARB().
+ */
+static void
+st_bufferobj_subdata(GLcontext *ctx,
+ GLenum target,
+ GLintptrARB offset,
+ GLsizeiptrARB size,
+ const GLvoid * data, struct gl_buffer_object *obj)
+{
+ struct pipe_context *pipe = st_context(ctx)->pipe;
+ struct st_buffer_object *st_obj = st_buffer_object(obj);
+ char *map;
+
+ if (offset >= st_obj->size || size > (st_obj->size - offset))
+ return;
+
+ map = pipe_buffer_map(pipe->screen, st_obj->buffer, PIPE_BUFFER_USAGE_CPU_WRITE);
+ memcpy(map + offset, data, size);
+ pipe_buffer_unmap(pipe->screen, st_obj->buffer);
+}
+
+
+/**
+ * Called via glGetBufferSubDataARB().
+ */
+static void
+st_bufferobj_get_subdata(GLcontext *ctx,
+ GLenum target,
+ GLintptrARB offset,
+ GLsizeiptrARB size,
+ GLvoid * data, struct gl_buffer_object *obj)
+{
+ struct pipe_context *pipe = st_context(ctx)->pipe;
+ struct st_buffer_object *st_obj = st_buffer_object(obj);
+ char *map;
+
+ if (offset >= st_obj->size || size > (st_obj->size - offset))
+ return;
+
+ map = pipe_buffer_map(pipe->screen, st_obj->buffer, PIPE_BUFFER_USAGE_CPU_READ);
+ memcpy(data, map + offset, size);
+ pipe_buffer_unmap(pipe->screen, st_obj->buffer);
+}
+
+
+/**
+ * Allocate space for and store data in a buffer object. Any data that was
+ * previously stored in the buffer object is lost. If data is NULL,
+ * memory will be allocated, but no copy will occur.
+ * Called via glBufferDataARB().
+ */
+static void
+st_bufferobj_data(GLcontext *ctx,
+ GLenum target,
+ GLsizeiptrARB size,
+ const GLvoid * data,
+ GLenum usage,
+ struct gl_buffer_object *obj)
+{
+ struct st_context *st = st_context(ctx);
+ struct pipe_context *pipe = st->pipe;
+ struct st_buffer_object *st_obj = st_buffer_object(obj);
+ unsigned buffer_usage;
+
+ st_obj->Base.Size = size;
+ st_obj->Base.Usage = usage;
+
+ switch(target) {
+ case GL_PIXEL_PACK_BUFFER_ARB:
+ case GL_PIXEL_UNPACK_BUFFER_ARB:
+ buffer_usage = PIPE_BUFFER_USAGE_PIXEL;
+ break;
+ case GL_ARRAY_BUFFER_ARB:
+ buffer_usage = PIPE_BUFFER_USAGE_VERTEX;
+ break;
+ case GL_ELEMENT_ARRAY_BUFFER_ARB:
+ buffer_usage = PIPE_BUFFER_USAGE_INDEX;
+ break;
+ default:
+ buffer_usage = 0;
+ }
+
+ pipe_buffer_reference( pipe->screen, &st_obj->buffer, NULL );
+
+ st_obj->buffer = pipe_buffer_create( pipe->screen, 32, buffer_usage, size );
+
+ st_obj->size = size;
+
+ if (data)
+ st_bufferobj_subdata(ctx, target, 0, size, data, obj);
+}
+
+
+/**
+ * Called via glMapBufferARB().
+ */
+static void *
+st_bufferobj_map(GLcontext *ctx, GLenum target, GLenum access,
+ struct gl_buffer_object *obj)
+{
+ struct pipe_context *pipe = st_context(ctx)->pipe;
+ struct st_buffer_object *st_obj = st_buffer_object(obj);
+ GLuint flags;
+
+ switch (access) {
+ case GL_WRITE_ONLY:
+ flags = PIPE_BUFFER_USAGE_CPU_WRITE;
+ break;
+ case GL_READ_ONLY:
+ flags = PIPE_BUFFER_USAGE_CPU_READ;
+ break;
+ case GL_READ_WRITE:
+ /* fall-through */
+ default:
+ flags = PIPE_BUFFER_USAGE_CPU_READ | PIPE_BUFFER_USAGE_CPU_WRITE;
+ break;
+ }
+
+ obj->Pointer = pipe_buffer_map(pipe->screen, st_obj->buffer, flags);
+ return obj->Pointer;
+}
+
+
+/**
+ * Called via glMapBufferARB().
+ */
+static GLboolean
+st_bufferobj_unmap(GLcontext *ctx, GLenum target, struct gl_buffer_object *obj)
+{
+ struct pipe_context *pipe = st_context(ctx)->pipe;
+ struct st_buffer_object *st_obj = st_buffer_object(obj);
+
+ pipe_buffer_unmap(pipe->screen, st_obj->buffer);
+ obj->Pointer = NULL;
+ return GL_TRUE;
+}
+
+
+void
+st_init_bufferobject_functions(struct dd_function_table *functions)
+{
+ functions->NewBufferObject = st_bufferobj_alloc;
+ functions->DeleteBuffer = st_bufferobj_free;
+ functions->BufferData = st_bufferobj_data;
+ functions->BufferSubData = st_bufferobj_subdata;
+ functions->GetBufferSubData = st_bufferobj_get_subdata;
+ functions->MapBuffer = st_bufferobj_map;
+ functions->UnmapBuffer = st_bufferobj_unmap;
+}
diff --git a/src/mesa/state_tracker/st_cb_bufferobjects.h b/src/mesa/state_tracker/st_cb_bufferobjects.h
new file mode 100644
index 00000000000..dcbb5a52336
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_bufferobjects.h
@@ -0,0 +1,66 @@
+/**************************************************************************
+ *
+ * Copyright 2005 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.
+ *
+ **************************************************************************/
+
+#ifndef ST_CB_BUFFEROBJECTS_H
+#define ST_CB_BUFFEROBJECTS_H
+
+struct st_context;
+struct gl_buffer_object;
+struct pipe_buffer;
+
+/**
+ * State_tracker vertex/pixel buffer object, derived from Mesa's
+ * gl_buffer_object.
+ */
+struct st_buffer_object
+{
+ struct gl_buffer_object Base;
+ struct pipe_buffer *buffer;
+ GLsizeiptrARB size;
+};
+
+
+/* Are the obj->Name tests necessary? Unfortunately yes, mesa
+ * allocates a couple of gl_buffer_object structs statically, and the
+ * Name == 0 test is the only way to identify them and avoid casting
+ * them erroneously to our structs.
+ */
+static INLINE struct st_buffer_object *
+st_buffer_object(struct gl_buffer_object *obj)
+{
+ if (obj->Name)
+ return (struct st_buffer_object *) obj;
+ else
+ return NULL;
+}
+
+
+extern void
+st_init_bufferobject_functions(struct dd_function_table *functions);
+
+
+#endif
diff --git a/src/mesa/state_tracker/st_cb_clear.c b/src/mesa/state_tracker/st_cb_clear.c
new file mode 100644
index 00000000000..668c3f9ebf4
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_clear.c
@@ -0,0 +1,602 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <[email protected]>
+ * Brian Paul
+ */
+
+#include "main/glheader.h"
+#include "main/macros.h"
+#include "shader/prog_instruction.h"
+#include "st_context.h"
+#include "st_atom.h"
+#include "st_cb_accum.h"
+#include "st_cb_clear.h"
+#include "st_cb_fbo.h"
+#include "st_draw.h"
+#include "st_program.h"
+#include "st_public.h"
+#include "st_mesa_to_tgsi.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "util/u_pack_color.h"
+#include "util/u_simple_shaders.h"
+#include "util/u_draw_quad.h"
+
+#include "cso_cache/cso_context.h"
+
+
+void
+st_init_clear(struct st_context *st)
+{
+ struct pipe_context *pipe = st->pipe;
+
+ /* rasterizer state: bypass clipping */
+ memset(&st->clear.raster, 0, sizeof(st->clear.raster));
+ st->clear.raster.gl_rasterization_rules = 1;
+ st->clear.raster.bypass_clipping = 1;
+
+ /* viewport state: identity since we're drawing in window coords */
+ st->clear.viewport.scale[0] = 1.0;
+ st->clear.viewport.scale[1] = 1.0;
+ st->clear.viewport.scale[2] = 1.0;
+ st->clear.viewport.scale[3] = 1.0;
+ st->clear.viewport.translate[0] = 0.0;
+ st->clear.viewport.translate[1] = 0.0;
+ st->clear.viewport.translate[2] = 0.0;
+ st->clear.viewport.translate[3] = 0.0;
+
+ /* fragment shader state: color pass-through program */
+ st->clear.fs =
+ util_make_fragment_passthrough_shader(pipe, &st->clear.frag_shader);
+
+ /* vertex shader state: color/position pass-through */
+ {
+ const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
+ TGSI_SEMANTIC_COLOR };
+ const uint semantic_indexes[] = { 0, 0 };
+ st->clear.vs = util_make_vertex_passthrough_shader(pipe, 2,
+ semantic_names,
+ semantic_indexes,
+ &st->clear.vert_shader);
+ }
+}
+
+
+void
+st_destroy_clear(struct st_context *st)
+{
+ struct pipe_context *pipe = st->pipe;
+
+ if (st->clear.vert_shader.tokens) {
+ FREE((void *) st->clear.vert_shader.tokens);
+ st->clear.vert_shader.tokens = NULL;
+ }
+
+ if (st->clear.frag_shader.tokens) {
+ FREE((void *) st->clear.frag_shader.tokens);
+ st->clear.frag_shader.tokens = NULL;
+ }
+
+ if (st->clear.fs) {
+ cso_delete_fragment_shader(st->cso_context, st->clear.fs);
+ st->clear.fs = NULL;
+ }
+ if (st->clear.vs) {
+ cso_delete_vertex_shader(st->cso_context, st->clear.vs);
+ st->clear.vs = NULL;
+ }
+ if (st->clear.vbuf) {
+ pipe_buffer_reference(pipe->screen, &st->clear.vbuf, NULL);
+ st->clear.vbuf = NULL;
+ }
+}
+
+
+static GLboolean
+is_depth_stencil_format(enum pipe_format pipeFormat)
+{
+ switch (pipeFormat) {
+ case PIPE_FORMAT_S8Z24_UNORM:
+ case PIPE_FORMAT_Z24S8_UNORM:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+
+/**
+ * Draw a screen-aligned quadrilateral.
+ * Coords are window coords with y=0=bottom. These coords will be transformed
+ * by the vertex shader and viewport transform (which will flip Y if needed).
+ */
+static void
+draw_quad(GLcontext *ctx,
+ float x0, float y0, float x1, float y1, GLfloat z,
+ const GLfloat color[4])
+{
+ struct st_context *st = ctx->st;
+ struct pipe_context *pipe = st->pipe;
+ const GLuint max_slots = 1024 / sizeof(st->clear.vertices);
+ GLuint i;
+ void *buf;
+
+ if (st->clear.vbuf_slot >= max_slots) {
+ pipe_buffer_reference(pipe->screen, &st->clear.vbuf, NULL);
+ st->clear.vbuf_slot = 0;
+ }
+
+ if (!st->clear.vbuf) {
+ st->clear.vbuf = pipe_buffer_create(pipe->screen, 32, PIPE_BUFFER_USAGE_VERTEX,
+ max_slots * sizeof(st->clear.vertices));
+ }
+
+ /* positions */
+ st->clear.vertices[0][0][0] = x0;
+ st->clear.vertices[0][0][1] = y0;
+
+ st->clear.vertices[1][0][0] = x1;
+ st->clear.vertices[1][0][1] = y0;
+
+ st->clear.vertices[2][0][0] = x1;
+ st->clear.vertices[2][0][1] = y1;
+
+ st->clear.vertices[3][0][0] = x0;
+ st->clear.vertices[3][0][1] = y1;
+
+ /* same for all verts: */
+ for (i = 0; i < 4; i++) {
+ st->clear.vertices[i][0][2] = z;
+ st->clear.vertices[i][0][3] = 1.0;
+ st->clear.vertices[i][1][0] = color[0];
+ st->clear.vertices[i][1][1] = color[1];
+ st->clear.vertices[i][1][2] = color[2];
+ st->clear.vertices[i][1][3] = color[3];
+ }
+
+ /* put vertex data into vbuf */
+ buf = pipe_buffer_map(pipe->screen, st->clear.vbuf, PIPE_BUFFER_USAGE_CPU_WRITE);
+
+ memcpy((char *)buf + st->clear.vbuf_slot * sizeof(st->clear.vertices),
+ st->clear.vertices,
+ sizeof(st->clear.vertices));
+
+ pipe_buffer_unmap(pipe->screen, st->clear.vbuf);
+
+ /* draw */
+ util_draw_vertex_buffer(pipe,
+ st->clear.vbuf,
+ st->clear.vbuf_slot * sizeof(st->clear.vertices),
+ PIPE_PRIM_TRIANGLE_FAN,
+ 4, /* verts */
+ 2); /* attribs/vert */
+
+ /* Increment slot */
+ st->clear.vbuf_slot++;
+}
+
+
+
+/**
+ * Do glClear by drawing a quadrilateral.
+ * The vertices of the quad will be computed from the
+ * ctx->DrawBuffer->_X/Ymin/max fields.
+ */
+static void
+clear_with_quad(GLcontext *ctx,
+ GLboolean color, GLboolean depth, GLboolean stencil)
+{
+ struct st_context *st = ctx->st;
+ const GLfloat x0 = (GLfloat) ctx->DrawBuffer->_Xmin;
+ const GLfloat x1 = (GLfloat) ctx->DrawBuffer->_Xmax;
+ GLfloat y0, y1;
+
+ if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
+ y0 = (GLfloat) (ctx->DrawBuffer->Height - ctx->DrawBuffer->_Ymax);
+ y1 = (GLfloat) (ctx->DrawBuffer->Height - ctx->DrawBuffer->_Ymin);
+ }
+ else {
+ y0 = (GLfloat) ctx->DrawBuffer->_Ymin;
+ y1 = (GLfloat) ctx->DrawBuffer->_Ymax;
+ }
+
+ /*
+ printf("%s %s%s%s %f,%f %f,%f\n", __FUNCTION__,
+ color ? "color, " : "",
+ depth ? "depth, " : "",
+ stencil ? "stencil" : "",
+ x0, y0,
+ x1, y1);
+ */
+
+ cso_save_blend(st->cso_context);
+ cso_save_depth_stencil_alpha(st->cso_context);
+ cso_save_rasterizer(st->cso_context);
+ cso_save_viewport(st->cso_context);
+ cso_save_fragment_shader(st->cso_context);
+ cso_save_vertex_shader(st->cso_context);
+
+ /* blend state: RGBA masking */
+ {
+ struct pipe_blend_state blend;
+ memset(&blend, 0, sizeof(blend));
+ blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ if (color) {
+ if (ctx->Color.ColorMask[0])
+ blend.colormask |= PIPE_MASK_R;
+ if (ctx->Color.ColorMask[1])
+ blend.colormask |= PIPE_MASK_G;
+ if (ctx->Color.ColorMask[2])
+ blend.colormask |= PIPE_MASK_B;
+ if (ctx->Color.ColorMask[3])
+ blend.colormask |= PIPE_MASK_A;
+ if (st->ctx->Color.DitherFlag)
+ blend.dither = 1;
+ }
+ cso_set_blend(st->cso_context, &blend);
+ }
+
+ /* depth_stencil state: always pass/set to ref value */
+ {
+ struct pipe_depth_stencil_alpha_state depth_stencil;
+ memset(&depth_stencil, 0, sizeof(depth_stencil));
+ if (depth) {
+ depth_stencil.depth.enabled = 1;
+ depth_stencil.depth.writemask = 1;
+ depth_stencil.depth.func = PIPE_FUNC_ALWAYS;
+ }
+
+ if (stencil) {
+ depth_stencil.stencil[0].enabled = 1;
+ depth_stencil.stencil[0].func = PIPE_FUNC_ALWAYS;
+ depth_stencil.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
+ depth_stencil.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
+ depth_stencil.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
+ depth_stencil.stencil[0].ref_value = ctx->Stencil.Clear;
+ depth_stencil.stencil[0].valuemask = 0xff;
+ depth_stencil.stencil[0].writemask = ctx->Stencil.WriteMask[0] & 0xff;
+ }
+
+ cso_set_depth_stencil_alpha(st->cso_context, &depth_stencil);
+ }
+
+ cso_set_rasterizer(st->cso_context, &st->clear.raster);
+ cso_set_viewport(st->cso_context, &st->clear.viewport);
+
+ cso_set_fragment_shader_handle(st->cso_context, st->clear.fs);
+ cso_set_vertex_shader_handle(st->cso_context, st->clear.vs);
+
+ /* draw quad matching scissor rect (XXX verify coord round-off) */
+ draw_quad(ctx, x0, y0, x1, y1, (GLfloat) ctx->Depth.Clear, ctx->Color.ClearColor);
+
+ /* Restore pipe state */
+ cso_restore_blend(st->cso_context);
+ cso_restore_depth_stencil_alpha(st->cso_context);
+ cso_restore_rasterizer(st->cso_context);
+ cso_restore_viewport(st->cso_context);
+ cso_restore_fragment_shader(st->cso_context);
+ cso_restore_vertex_shader(st->cso_context);
+}
+
+
+/**
+ * Determine if we need to clear the depth buffer by drawing a quad.
+ */
+static INLINE GLboolean
+check_clear_color_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb)
+{
+ const struct st_renderbuffer *strb = st_renderbuffer(rb);
+
+ if (strb->surface->status == PIPE_SURFACE_STATUS_UNDEFINED)
+ return FALSE;
+
+ if (ctx->Scissor.Enabled)
+ return TRUE;
+
+ if (!ctx->Color.ColorMask[0] ||
+ !ctx->Color.ColorMask[1] ||
+ !ctx->Color.ColorMask[2] ||
+ !ctx->Color.ColorMask[3])
+ return TRUE;
+
+ return FALSE;
+}
+
+
+static INLINE GLboolean
+check_clear_depth_stencil_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb)
+{
+ const struct st_renderbuffer *strb = st_renderbuffer(rb);
+ const GLuint stencilMax = (1 << rb->StencilBits) - 1;
+ GLboolean maskStencil
+ = (ctx->Stencil.WriteMask[0] & stencilMax) != stencilMax;
+
+ if (strb->surface->status == PIPE_SURFACE_STATUS_UNDEFINED)
+ return FALSE;
+
+ if (ctx->Scissor.Enabled)
+ return TRUE;
+
+ if (maskStencil)
+ return TRUE;
+
+ return FALSE;
+}
+
+
+/**
+ * Determine if we need to clear the depth buffer by drawing a quad.
+ */
+static INLINE GLboolean
+check_clear_depth_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb)
+{
+ const struct st_renderbuffer *strb = st_renderbuffer(rb);
+ const GLboolean isDS = is_depth_stencil_format(strb->surface->format);
+
+ if (strb->surface->status == PIPE_SURFACE_STATUS_UNDEFINED)
+ return FALSE;
+
+ if (ctx->Scissor.Enabled)
+ return TRUE;
+
+ if (isDS &&
+ strb->surface->status == PIPE_SURFACE_STATUS_DEFINED &&
+ ctx->DrawBuffer->Visual.stencilBits > 0)
+ return TRUE;
+
+ return FALSE;
+}
+
+
+/**
+ * Determine if we need to clear the stencil buffer by drawing a quad.
+ */
+static INLINE GLboolean
+check_clear_stencil_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb)
+{
+ const struct st_renderbuffer *strb = st_renderbuffer(rb);
+ const GLboolean isDS = is_depth_stencil_format(strb->surface->format);
+ const GLuint stencilMax = (1 << rb->StencilBits) - 1;
+ const GLboolean maskStencil
+ = (ctx->Stencil.WriteMask[0] & stencilMax) != stencilMax;
+
+ if (strb->surface->status == PIPE_SURFACE_STATUS_UNDEFINED)
+ return FALSE;
+
+ if (maskStencil)
+ return TRUE;
+
+ if (ctx->Scissor.Enabled)
+ return TRUE;
+
+ /* This is correct, but it is necessary to look at the depth clear
+ * value held in the surface when it comes time to issue the clear,
+ * rather than taking depth and stencil clear values from the
+ * current state.
+ */
+ if (isDS &&
+ strb->surface->status == PIPE_SURFACE_STATUS_DEFINED &&
+ ctx->DrawBuffer->Visual.depthBits > 0)
+ return TRUE;
+
+ return FALSE;
+}
+
+
+
+static void
+clear_color_buffer(GLcontext *ctx, struct gl_renderbuffer *rb)
+{
+ struct st_renderbuffer *strb = st_renderbuffer(rb);
+
+ if (!strb->surface)
+ return;
+
+ if (check_clear_color_with_quad( ctx, rb )) {
+ /* masking or scissoring */
+ clear_with_quad(ctx, GL_TRUE, GL_FALSE, GL_FALSE);
+ }
+ else {
+ /* clear whole buffer w/out masking */
+ uint clearValue;
+ /* NOTE: we always pass the clear color as PIPE_FORMAT_A8R8G8B8_UNORM
+ * at this time!
+ */
+ util_pack_color(ctx->Color.ClearColor, PIPE_FORMAT_A8R8G8B8_UNORM, &clearValue);
+ ctx->st->pipe->clear(ctx->st->pipe, strb->surface, clearValue);
+ }
+}
+
+
+static void
+clear_depth_buffer(GLcontext *ctx, struct gl_renderbuffer *rb)
+{
+ struct st_renderbuffer *strb = st_renderbuffer(rb);
+
+ if (!strb->surface)
+ return;
+
+ if (check_clear_depth_with_quad(ctx, rb)) {
+ /* scissoring or we have a combined depth/stencil buffer */
+ clear_with_quad(ctx, GL_FALSE, GL_TRUE, GL_FALSE);
+ }
+ else {
+ /* simple clear of whole buffer */
+ uint clearValue = util_pack_z(strb->surface->format, ctx->Depth.Clear);
+ ctx->st->pipe->clear(ctx->st->pipe, strb->surface, clearValue);
+ }
+}
+
+
+static void
+clear_stencil_buffer(GLcontext *ctx, struct gl_renderbuffer *rb)
+{
+ struct st_renderbuffer *strb = st_renderbuffer(rb);
+
+ if (!strb->surface)
+ return;
+
+ if (check_clear_stencil_with_quad(ctx, rb)) {
+ /* masking or scissoring or combined depth/stencil buffer */
+ clear_with_quad(ctx, GL_FALSE, GL_FALSE, GL_TRUE);
+ }
+ else {
+ /* simple clear of whole buffer */
+ GLuint clearValue = ctx->Stencil.Clear;
+
+ switch (strb->surface->format) {
+ case PIPE_FORMAT_S8Z24_UNORM:
+ clearValue <<= 24;
+ break;
+ default:
+ ; /* no-op, stencil value is in least significant bits */
+ }
+
+ ctx->st->pipe->clear(ctx->st->pipe, strb->surface, clearValue);
+ }
+}
+
+
+static void
+clear_depth_stencil_buffer(GLcontext *ctx, struct gl_renderbuffer *rb)
+{
+ struct st_renderbuffer *strb = st_renderbuffer(rb);
+
+ if (!strb->surface)
+ return;
+
+ if (check_clear_depth_stencil_with_quad(ctx, rb)) {
+ /* masking or scissoring */
+ clear_with_quad(ctx, GL_FALSE, GL_TRUE, GL_TRUE);
+ }
+ else {
+ /* clear whole buffer w/out masking */
+ GLuint clearValue = util_pack_z(strb->surface->format, ctx->Depth.Clear);
+
+ switch (strb->surface->format) {
+ case PIPE_FORMAT_S8Z24_UNORM:
+ clearValue |= ctx->Stencil.Clear << 24;
+ break;
+ case PIPE_FORMAT_Z24S8_UNORM:
+ clearValue |= ctx->Stencil.Clear;
+ break;
+ default:
+ assert(0);
+ }
+
+ ctx->st->pipe->clear(ctx->st->pipe, strb->surface, clearValue);
+ }
+}
+
+
+void st_flush_clear( struct st_context *st )
+{
+ /* Release vertex buffer to avoid synchronous rendering if we were
+ * to map it in the next frame.
+ */
+ pipe_buffer_reference(st->pipe->screen, &st->clear.vbuf, NULL);
+ st->clear.vbuf_slot = 0;
+}
+
+
+
+/**
+ * Called via ctx->Driver.Clear()
+ * XXX: doesn't pick up the differences between front/back/left/right
+ * clears. Need to sort that out...
+ */
+static void st_clear(GLcontext *ctx, GLbitfield mask)
+{
+ static const GLbitfield BUFFER_BITS_DS
+ = (BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL);
+ struct st_context *st = ctx->st;
+ struct gl_renderbuffer *depthRb
+ = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
+ struct gl_renderbuffer *stencilRb
+ = ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
+ GLbitfield cmask = mask & BUFFER_BITS_COLOR;
+
+ /* This makes sure the softpipe has the latest scissor, etc values */
+ st_validate_state( st );
+
+ /*
+ * XXX TO-DO:
+ * If we're going to use clear_with_quad() for any reason, use it to
+ * clear as many other buffers as possible.
+ * As it is now, we sometimes call clear_with_quad() three times to clear
+ * color/depth/stencil individually...
+ */
+
+ if (cmask) {
+ GLuint b;
+ for (b = 0; cmask; b++) {
+ if (cmask & (1 << b)) {
+ struct gl_renderbuffer *rb
+ = ctx->DrawBuffer->Attachment[b].Renderbuffer;
+ assert(rb);
+ clear_color_buffer(ctx, rb);
+ cmask &= ~(1 << b); /* turn off bit */
+ }
+ assert(b < BUFFER_COUNT);
+ }
+ }
+
+ if (mask & BUFFER_BIT_ACCUM) {
+ st_clear_accum_buffer(ctx,
+ ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer);
+ }
+
+ if ((mask & BUFFER_BITS_DS) == BUFFER_BITS_DS && depthRb == stencilRb) {
+ /* clearing combined depth + stencil */
+ clear_depth_stencil_buffer(ctx, depthRb);
+ }
+ else {
+ /* separate depth/stencil clears */
+ if (mask & BUFFER_BIT_DEPTH) {
+ clear_depth_buffer(ctx, depthRb);
+ }
+ if (mask & BUFFER_BIT_STENCIL) {
+ clear_stencil_buffer(ctx, stencilRb);
+ }
+ }
+}
+
+
+void st_init_clear_functions(struct dd_function_table *functions)
+{
+ functions->Clear = st_clear;
+}
diff --git a/src/mesa/state_tracker/st_cb_clear.h b/src/mesa/state_tracker/st_cb_clear.h
new file mode 100644
index 00000000000..bc035ac25ca
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_clear.h
@@ -0,0 +1,49 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_CB_CLEAR_H
+#define ST_CB_CLEAR_H
+
+
+extern void
+st_init_clear(struct st_context *st);
+
+
+extern void
+st_destroy_clear(struct st_context *st);
+
+extern void
+st_flush_clear(struct st_context *st);
+
+
+extern void
+st_init_clear_functions(struct dd_function_table *functions);
+
+
+#endif /* ST_CB_CLEAR_H */
+
diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c
new file mode 100644
index 00000000000..32bf21411da
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_drawpixels.c
@@ -0,0 +1,1104 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Brian Paul
+ */
+
+#include "main/imports.h"
+#include "main/image.h"
+#include "main/bufferobj.h"
+#include "main/macros.h"
+#include "main/texformat.h"
+#include "main/state.h"
+#include "shader/program.h"
+#include "shader/prog_parameter.h"
+#include "shader/prog_print.h"
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "st_atom_constbuf.h"
+#include "st_draw.h"
+#include "st_program.h"
+#include "st_cb_drawpixels.h"
+#include "st_cb_readpixels.h"
+#include "st_cb_fbo.h"
+#include "st_cb_texture.h"
+#include "st_draw.h"
+#include "st_format.h"
+#include "st_mesa_to_tgsi.h"
+#include "st_texture.h"
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "util/u_tile.h"
+#include "util/u_draw_quad.h"
+#include "shader/prog_instruction.h"
+#include "cso_cache/cso_context.h"
+
+
+/**
+ * Check if the given program is:
+ * 0: MOVE result.color, fragment.color;
+ * 1: END;
+ */
+static GLboolean
+is_passthrough_program(const struct gl_fragment_program *prog)
+{
+ if (prog->Base.NumInstructions == 2) {
+ const struct prog_instruction *inst = prog->Base.Instructions;
+ if (inst[0].Opcode == OPCODE_MOV &&
+ inst[1].Opcode == OPCODE_END &&
+ inst[0].DstReg.File == PROGRAM_OUTPUT &&
+ inst[0].DstReg.Index == FRAG_RESULT_COLR &&
+ inst[0].DstReg.WriteMask == WRITEMASK_XYZW &&
+ inst[0].SrcReg[0].File == PROGRAM_INPUT &&
+ inst[0].SrcReg[0].Index == FRAG_ATTRIB_COL0 &&
+ inst[0].SrcReg[0].Swizzle == SWIZZLE_XYZW) {
+ return GL_TRUE;
+ }
+ }
+ return GL_FALSE;
+}
+
+
+
+/**
+ * Make fragment shader for glDraw/CopyPixels. This shader is made
+ * by combining the pixel transfer shader with the user-defined shader.
+ */
+static struct st_fragment_program *
+combined_drawpix_fragment_program(GLcontext *ctx)
+{
+ struct st_context *st = ctx->st;
+ struct st_fragment_program *stfp;
+
+ if (st->pixel_xfer.program->serialNo == st->pixel_xfer.xfer_prog_sn
+ && st->fp->serialNo == st->pixel_xfer.user_prog_sn) {
+ /* the pixel tranfer program has not changed and the user-defined
+ * program has not changed, so re-use the combined program.
+ */
+ stfp = st->pixel_xfer.combined_prog;
+ }
+ else {
+ /* Concatenate the pixel transfer program with the current user-
+ * defined program.
+ */
+ if (is_passthrough_program(&st->fp->Base)) {
+ stfp = (struct st_fragment_program *)
+ _mesa_clone_program(ctx, &st->pixel_xfer.program->Base.Base);
+ }
+ else {
+#if 0
+ printf("Base program:\n");
+ _mesa_print_program(&st->fp->Base.Base);
+ printf("DrawPix program:\n");
+ _mesa_print_program(&st->pixel_xfer.program->Base.Base);
+#endif
+ stfp = (struct st_fragment_program *)
+ _mesa_combine_programs(ctx,
+ &st->pixel_xfer.program->Base.Base,
+ &st->fp->Base.Base);
+ }
+
+#if 0
+ {
+ struct gl_program *p = &stfp->Base.Base;
+ printf("Combined DrawPixels program:\n");
+ _mesa_print_program(p);
+ printf("InputsRead: 0x%x\n", p->InputsRead);
+ printf("OutputsWritten: 0x%x\n", p->OutputsWritten);
+ _mesa_print_parameter_list(p->Parameters);
+ }
+#endif
+
+ /* translate to TGSI tokens */
+ st_translate_fragment_program(st, stfp, NULL);
+
+ /* save new program, update serial numbers */
+ st->pixel_xfer.xfer_prog_sn = st->pixel_xfer.program->serialNo;
+ st->pixel_xfer.user_prog_sn = st->fp->serialNo;
+ st->pixel_xfer.combined_prog_sn = stfp->serialNo;
+ st->pixel_xfer.combined_prog = stfp;
+ }
+
+ /* Ideally we'd have updated the pipe constants during the normal
+ * st/atom mechanism. But we can't since this is specific to glDrawPixels.
+ */
+ st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT);
+
+ return stfp;
+}
+
+
+/**
+ * Create fragment shader that does a TEX() instruction to get a Z
+ * value, then writes to FRAG_RESULT_DEPR.
+ * Pass fragment color through as-is.
+ */
+static struct st_fragment_program *
+make_fragment_shader_z(struct st_context *st)
+{
+ GLcontext *ctx = st->ctx;
+ struct gl_program *p;
+ GLuint ic = 0;
+
+ if (st->drawpix.z_shader) {
+ return st->drawpix.z_shader;
+ }
+
+ /*
+ * Create shader now
+ */
+ p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
+ if (!p)
+ return NULL;
+
+ p->NumInstructions = 3;
+
+ p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
+ if (!p->Instructions) {
+ ctx->Driver.DeleteProgram(ctx, p);
+ return NULL;
+ }
+ _mesa_init_instructions(p->Instructions, p->NumInstructions);
+
+ /* TEX result.depth, fragment.texcoord[0], texture[0], 2D; */
+ p->Instructions[ic].Opcode = OPCODE_TEX;
+ p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
+ p->Instructions[ic].DstReg.Index = FRAG_RESULT_DEPR;
+ p->Instructions[ic].DstReg.WriteMask = WRITEMASK_Z;
+ p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
+ p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0;
+ p->Instructions[ic].TexSrcUnit = 0;
+ p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX;
+ ic++;
+
+ /* MOV result.color, fragment.color */
+ p->Instructions[ic].Opcode = OPCODE_MOV;
+ p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
+ p->Instructions[ic].DstReg.Index = FRAG_RESULT_COLR;
+ p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
+ p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_COL0;
+ ic++;
+
+ /* END; */
+ p->Instructions[ic++].Opcode = OPCODE_END;
+
+ assert(ic == p->NumInstructions);
+
+ p->InputsRead = FRAG_BIT_TEX0 | FRAG_BIT_COL0;
+ p->OutputsWritten = (1 << FRAG_RESULT_COLR) | (1 << FRAG_RESULT_DEPR);
+ p->SamplersUsed = 0x1; /* sampler 0 (bit 0) is used */
+
+ st->drawpix.z_shader = (struct st_fragment_program *) p;
+ st_translate_fragment_program(st, st->drawpix.z_shader, NULL);
+
+ return st->drawpix.z_shader;
+}
+
+
+
+/**
+ * Create a simple vertex shader that just passes through the
+ * vertex position and texcoord (and optionally, color).
+ */
+static struct st_vertex_program *
+st_make_passthrough_vertex_shader(struct st_context *st, GLboolean passColor)
+{
+ GLcontext *ctx = st->ctx;
+ struct st_vertex_program *stvp;
+ struct gl_program *p;
+ GLuint ic = 0;
+
+ if (st->drawpix.vert_shaders[passColor])
+ return st->drawpix.vert_shaders[passColor];
+
+ /*
+ * Create shader now
+ */
+ p = ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0);
+ if (!p)
+ return NULL;
+
+ if (passColor)
+ p->NumInstructions = 4;
+ else
+ p->NumInstructions = 3;
+
+ p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
+ if (!p->Instructions) {
+ ctx->Driver.DeleteProgram(ctx, p);
+ return NULL;
+ }
+ _mesa_init_instructions(p->Instructions, p->NumInstructions);
+ /* MOV result.pos, vertex.pos; */
+ p->Instructions[0].Opcode = OPCODE_MOV;
+ p->Instructions[0].DstReg.File = PROGRAM_OUTPUT;
+ p->Instructions[0].DstReg.Index = VERT_RESULT_HPOS;
+ p->Instructions[0].SrcReg[0].File = PROGRAM_INPUT;
+ p->Instructions[0].SrcReg[0].Index = VERT_ATTRIB_POS;
+ /* MOV result.texcoord0, vertex.texcoord0; */
+ p->Instructions[1].Opcode = OPCODE_MOV;
+ p->Instructions[1].DstReg.File = PROGRAM_OUTPUT;
+ p->Instructions[1].DstReg.Index = VERT_RESULT_TEX0;
+ p->Instructions[1].SrcReg[0].File = PROGRAM_INPUT;
+ p->Instructions[1].SrcReg[0].Index = VERT_ATTRIB_TEX0;
+ ic = 2;
+ if (passColor) {
+ /* MOV result.color0, vertex.color0; */
+ p->Instructions[ic].Opcode = OPCODE_MOV;
+ p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
+ p->Instructions[ic].DstReg.Index = VERT_RESULT_COL0;
+ p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
+ p->Instructions[ic].SrcReg[0].Index = VERT_ATTRIB_COLOR0;
+ ic++;
+ }
+
+ /* END; */
+ p->Instructions[ic].Opcode = OPCODE_END;
+ ic++;
+
+ assert(ic == p->NumInstructions);
+
+ p->InputsRead = VERT_BIT_POS | VERT_BIT_TEX0;
+ p->OutputsWritten = ((1 << VERT_RESULT_TEX0) |
+ (1 << VERT_RESULT_HPOS));
+ if (passColor) {
+ p->InputsRead |= VERT_BIT_COLOR0;
+ p->OutputsWritten |= (1 << VERT_RESULT_COL0);
+ }
+
+ stvp = (struct st_vertex_program *) p;
+ st_translate_vertex_program(st, stvp, NULL, NULL, NULL);
+
+ st->drawpix.vert_shaders[passColor] = stvp;
+
+ return stvp;
+}
+
+
+static GLenum
+_mesa_base_format(GLenum format)
+{
+ switch (format) {
+ case GL_DEPTH_COMPONENT:
+ return GL_DEPTH_COMPONENT;
+ case GL_STENCIL_INDEX:
+ return GL_STENCIL_INDEX;
+ default:
+ return GL_RGBA;
+ }
+}
+
+
+/**
+ * Make texture containing an image for glDrawPixels image.
+ * If 'pixels' is NULL, leave the texture image data undefined.
+ */
+static struct pipe_texture *
+make_texture(struct st_context *st,
+ GLsizei width, GLsizei height, GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels)
+{
+ GLcontext *ctx = st->ctx;
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ const struct gl_texture_format *mformat;
+ struct pipe_texture *pt;
+ enum pipe_format pipeFormat;
+ GLuint cpp;
+ GLenum baseFormat;
+
+ baseFormat = _mesa_base_format(format);
+
+ mformat = st_ChooseTextureFormat(ctx, baseFormat, format, type);
+ assert(mformat);
+
+ pipeFormat = st_mesa_format_to_pipe_format(mformat->MesaFormat);
+ assert(pipeFormat);
+ cpp = st_sizeof_format(pipeFormat);
+
+ pixels = _mesa_map_drawpix_pbo(ctx, unpack, pixels);
+ if (!pixels)
+ return NULL;
+
+ pt = st_texture_create(st, PIPE_TEXTURE_2D, pipeFormat, 0, width, height,
+ 1, 0,
+ PIPE_TEXTURE_USAGE_SAMPLER);
+ if (!pt) {
+ _mesa_unmap_drawpix_pbo(ctx, unpack);
+ return NULL;
+ }
+
+ {
+ struct pipe_surface *surface;
+ static const GLuint dstImageOffsets = 0;
+ GLboolean success;
+ GLubyte *dest;
+ const GLbitfield imageTransferStateSave = ctx->_ImageTransferState;
+
+ /* we'll do pixel transfer in a fragment shader */
+ ctx->_ImageTransferState = 0x0;
+
+ surface = screen->get_tex_surface(screen, pt, 0, 0, 0,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+
+ /* map texture surface */
+ dest = screen->surface_map(screen, surface,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+
+ /* Put image into texture surface.
+ * Note that the image is actually going to be upside down in
+ * the texture. We deal with that with texcoords.
+ */
+ success = mformat->StoreImage(ctx, 2, /* dims */
+ baseFormat, /* baseInternalFormat */
+ mformat, /* gl_texture_format */
+ dest, /* dest */
+ 0, 0, 0, /* dstX/Y/Zoffset */
+ surface->stride, /* dstRowStride, bytes */
+ &dstImageOffsets, /* dstImageOffsets */
+ width, height, 1, /* size */
+ format, type, /* src format/type */
+ pixels, /* data source */
+ unpack);
+
+ /* unmap */
+ screen->surface_unmap(screen, surface);
+ pipe_surface_reference(&surface, NULL);
+
+ assert(success);
+
+ /* restore */
+ ctx->_ImageTransferState = imageTransferStateSave;
+ }
+
+ _mesa_unmap_drawpix_pbo(ctx, unpack);
+
+ return pt;
+}
+
+
+/**
+ * Draw quad with texcoords and optional color.
+ * Coords are window coords with y=0=bottom.
+ * \param color may be null
+ * \param invertTex if true, flip texcoords vertically
+ */
+static void
+draw_quad(GLcontext *ctx, GLfloat x0, GLfloat y0, GLfloat z,
+ GLfloat x1, GLfloat y1, const GLfloat *color,
+ GLboolean invertTex)
+{
+ struct st_context *st = ctx->st;
+ struct pipe_context *pipe = ctx->st->pipe;
+ GLfloat verts[4][3][4]; /* four verts, three attribs, XYZW */
+
+ /* setup vertex data */
+ {
+ const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
+ const GLfloat fb_width = (GLfloat) fb->Width;
+ const GLfloat fb_height = (GLfloat) fb->Height;
+ const GLfloat clip_x0 = x0 / fb_width * 2.0f - 1.0f;
+ const GLfloat clip_y0 = y0 / fb_height * 2.0f - 1.0f;
+ const GLfloat clip_x1 = x1 / fb_width * 2.0f - 1.0f;
+ const GLfloat clip_y1 = y1 / fb_height * 2.0f - 1.0f;
+ const GLfloat sLeft = 0.0f, sRight = 1.0f;
+ const GLfloat tTop = invertTex, tBot = 1.0f - tTop;
+ GLuint tex, i;
+
+ /* upper-left */
+ verts[0][0][0] = clip_x0; /* v[0].attr[0].x */
+ verts[0][0][1] = clip_y0; /* v[0].attr[0].y */
+
+ /* upper-right */
+ verts[1][0][0] = clip_x1;
+ verts[1][0][1] = clip_y0;
+
+ /* lower-right */
+ verts[2][0][0] = clip_x1;
+ verts[2][0][1] = clip_y1;
+
+ /* lower-left */
+ verts[3][0][0] = clip_x0;
+ verts[3][0][1] = clip_y1;
+
+ tex = color ? 2 : 1;
+ verts[0][tex][0] = sLeft; /* v[0].attr[tex].s */
+ verts[0][tex][1] = tTop; /* v[0].attr[tex].t */
+ verts[1][tex][0] = sRight;
+ verts[1][tex][1] = tTop;
+ verts[2][tex][0] = sRight;
+ verts[2][tex][1] = tBot;
+ verts[3][tex][0] = sLeft;
+ verts[3][tex][1] = tBot;
+
+ /* same for all verts: */
+ if (color) {
+ for (i = 0; i < 4; i++) {
+ verts[i][0][2] = z; /*Z*/
+ verts[i][0][3] = 1.0f; /*W*/
+ verts[i][1][0] = color[0];
+ verts[i][1][1] = color[1];
+ verts[i][1][2] = color[2];
+ verts[i][1][3] = color[3];
+ verts[i][2][2] = 0.0f; /*R*/
+ verts[i][2][3] = 1.0f; /*Q*/
+ }
+ }
+ else {
+ for (i = 0; i < 4; i++) {
+ verts[i][0][2] = z; /*Z*/
+ verts[i][0][3] = 1.0f; /*W*/
+ verts[i][1][2] = 0.0f; /*R*/
+ verts[i][1][3] = 1.0f; /*Q*/
+ }
+ }
+ }
+
+ {
+ struct pipe_buffer *buf;
+ ubyte *map;
+
+ /* allocate/load buffer object with vertex data */
+ buf = pipe_buffer_create(pipe->screen, 32, PIPE_BUFFER_USAGE_VERTEX,
+ sizeof(verts));
+ map = pipe_buffer_map(pipe->screen, buf, PIPE_BUFFER_USAGE_CPU_WRITE);
+ memcpy(map, verts, sizeof(verts));
+ pipe_buffer_unmap(pipe->screen, buf);
+
+ util_draw_vertex_buffer(pipe, buf, 0,
+ PIPE_PRIM_QUADS,
+ 4, /* verts */
+ 3); /* attribs/vert */
+ pipe_buffer_reference(pipe->screen, &buf, NULL);
+ }
+}
+
+
+
+static void
+draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
+ GLsizei width, GLsizei height,
+ GLfloat zoomX, GLfloat zoomY,
+ struct pipe_texture *pt,
+ struct st_vertex_program *stvp,
+ struct st_fragment_program *stfp,
+ const GLfloat *color,
+ GLboolean invertTex)
+{
+ struct st_context *st = ctx->st;
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct cso_context *cso = ctx->st->cso_context;
+ GLfloat x0, y0, x1, y1;
+ GLsizei maxSize;
+
+ /* limit checks */
+ /* XXX if DrawPixels image is larger than max texture size, break
+ * it up into chunks.
+ */
+ maxSize = 1 << (pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1);
+ assert(width <= maxSize);
+ assert(height <= maxSize);
+
+ cso_save_rasterizer(cso);
+ cso_save_viewport(cso);
+ cso_save_samplers(cso);
+ cso_save_sampler_textures(cso);
+ cso_save_fragment_shader(cso);
+ cso_save_vertex_shader(cso);
+
+ /* rasterizer state: just scissor */
+ {
+ struct pipe_rasterizer_state rasterizer;
+ memset(&rasterizer, 0, sizeof(rasterizer));
+ rasterizer.gl_rasterization_rules = 1;
+ rasterizer.scissor = ctx->Scissor.Enabled;
+ cso_set_rasterizer(cso, &rasterizer);
+ }
+
+ /* fragment shader state: TEX lookup program */
+ cso_set_fragment_shader_handle(cso, stfp->driver_shader);
+
+ /* vertex shader state: position + texcoord pass-through */
+ cso_set_vertex_shader_handle(cso, stvp->driver_shader);
+
+
+ /* texture sampling state: */
+ {
+ struct pipe_sampler_state sampler;
+ memset(&sampler, 0, sizeof(sampler));
+ sampler.wrap_s = PIPE_TEX_WRAP_CLAMP;
+ sampler.wrap_t = PIPE_TEX_WRAP_CLAMP;
+ sampler.wrap_r = PIPE_TEX_WRAP_CLAMP;
+ sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
+ sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+ sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
+ sampler.normalized_coords = 1;
+
+ cso_single_sampler(cso, 0, &sampler);
+ if (st->pixel_xfer.pixelmap_enabled) {
+ cso_single_sampler(cso, 1, &sampler);
+ }
+ cso_single_sampler_done(cso);
+ }
+
+ /* viewport state: viewport matching window dims */
+ {
+ const float width = (float) ctx->DrawBuffer->Width;
+ const float height = (float) ctx->DrawBuffer->Height;
+ struct pipe_viewport_state vp;
+ vp.scale[0] = 0.5f * width;
+ vp.scale[1] = -0.5f * height;
+ vp.scale[2] = 1.0f;
+ vp.scale[3] = 1.0f;
+ vp.translate[0] = 0.5f * width;
+ vp.translate[1] = 0.5f * height;
+ vp.translate[2] = 0.0f;
+ vp.translate[3] = 0.0f;
+ cso_set_viewport(cso, &vp);
+ }
+
+ /* texture state: */
+ if (st->pixel_xfer.pixelmap_enabled) {
+ struct pipe_texture *textures[2];
+ textures[0] = pt;
+ textures[1] = st->pixel_xfer.pixelmap_texture;
+ pipe->set_sampler_textures(pipe, 2, textures);
+ }
+ else {
+ pipe->set_sampler_textures(pipe, 1, &pt);
+ }
+
+ /* Compute window coords (y=0=bottom) with pixel zoom.
+ * Recall that these coords are transformed by the current
+ * vertex shader and viewport transformation.
+ */
+ x0 = (GLfloat) x;
+ x1 = x + width * ctx->Pixel.ZoomX;
+ y0 = (GLfloat) y;
+ y1 = y + height * ctx->Pixel.ZoomY;
+ //if(!color)
+ draw_quad(ctx, x0, y0, z, x1, y1, color, invertTex);
+ //else
+ //printf("skip draw quad\n");
+ /* restore state */
+ cso_restore_rasterizer(cso);
+ cso_restore_viewport(cso);
+ cso_restore_samplers(cso);
+ cso_restore_sampler_textures(cso);
+ cso_restore_fragment_shader(cso);
+ cso_restore_vertex_shader(cso);
+}
+
+
+/**
+ * Check if a GL format/type combination is a match to the given pipe format.
+ * XXX probably move this to a re-usable place.
+ */
+static GLboolean
+compatible_formats(GLenum format, GLenum type, enum pipe_format pipeFormat)
+{
+ static const GLuint one = 1;
+ GLubyte littleEndian = *((GLubyte *) &one);
+
+ if (pipeFormat == PIPE_FORMAT_R8G8B8A8_UNORM &&
+ format == GL_RGBA &&
+ type == GL_UNSIGNED_BYTE &&
+ !littleEndian) {
+ return GL_TRUE;
+ }
+ else if (pipeFormat == PIPE_FORMAT_R8G8B8A8_UNORM &&
+ format == GL_ABGR_EXT &&
+ type == GL_UNSIGNED_BYTE &&
+ littleEndian) {
+ return GL_TRUE;
+ }
+ else if (pipeFormat == PIPE_FORMAT_A8R8G8B8_UNORM &&
+ format == GL_BGRA &&
+ type == GL_UNSIGNED_BYTE &&
+ littleEndian) {
+ return GL_TRUE;
+ }
+ else if (pipeFormat == PIPE_FORMAT_R5G6B5_UNORM &&
+ format == GL_RGB &&
+ type == GL_UNSIGNED_SHORT_5_6_5) {
+ /* endian don't care */
+ return GL_TRUE;
+ }
+ else if (pipeFormat == PIPE_FORMAT_R5G6B5_UNORM &&
+ format == GL_BGR &&
+ type == GL_UNSIGNED_SHORT_5_6_5_REV) {
+ /* endian don't care */
+ return GL_TRUE;
+ }
+ else if (pipeFormat == PIPE_FORMAT_S8_UNORM &&
+ format == GL_STENCIL_INDEX &&
+ type == GL_UNSIGNED_BYTE) {
+ return GL_TRUE;
+ }
+ else if (pipeFormat == PIPE_FORMAT_Z32_UNORM &&
+ format == GL_DEPTH_COMPONENT &&
+ type == GL_UNSIGNED_INT) {
+ return GL_TRUE;
+ }
+ /* XXX add more cases */
+ else {
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Check if any per-fragment ops are enabled.
+ * XXX probably move this to a re-usable place.
+ */
+static GLboolean
+any_fragment_ops(const struct st_context *st)
+{
+ if (st->state.depth_stencil.alpha.enabled ||
+ st->state.depth_stencil.depth.enabled ||
+ st->state.blend.blend_enable ||
+ st->state.blend.logicop_enable)
+ /* XXX more checks */
+ return GL_TRUE;
+ else
+ return GL_FALSE;
+}
+
+
+/**
+ * Check if any pixel transfer ops are enabled.
+ * XXX probably move this to a re-usable place.
+ */
+static GLboolean
+any_pixel_transfer_ops(const struct st_context *st)
+{
+ if (st->ctx->Pixel.RedScale != 1.0 ||
+ st->ctx->Pixel.RedBias != 0.0 ||
+ st->ctx->Pixel.GreenScale != 1.0 ||
+ st->ctx->Pixel.GreenBias != 0.0 ||
+ st->ctx->Pixel.BlueScale != 1.0 ||
+ st->ctx->Pixel.BlueBias != 0.0 ||
+ st->ctx->Pixel.AlphaScale != 1.0 ||
+ st->ctx->Pixel.AlphaBias != 0.0 ||
+ st->ctx->Pixel.MapColorFlag)
+ /* XXX more checks */
+ return GL_TRUE;
+ else
+ return GL_FALSE;
+}
+
+
+/**
+ * Draw image with a blit, or other non-textured quad method.
+ */
+static void
+draw_blit(struct st_context *st,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type, const GLvoid *pixels)
+{
+
+
+}
+
+
+static void
+draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
+ GLsizei width, GLsizei height, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels)
+{
+ struct st_context *st = ctx->st;
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct st_renderbuffer *strb;
+ struct pipe_surface *ps;
+ const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0;
+ GLint skipPixels;
+ ubyte *stmap;
+
+ pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+ strb = st_renderbuffer(ctx->DrawBuffer->
+ Attachment[BUFFER_STENCIL].Renderbuffer);
+ ps = screen->get_tex_surface(screen, strb->texture, 0, 0, 0,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+
+ /* map the stencil buffer */
+ stmap = screen->surface_map(screen, ps,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+
+ /* if width > MAX_WIDTH, have to process image in chunks */
+ skipPixels = 0;
+ while (skipPixels < width) {
+ const GLint spanX = x + skipPixels;
+ const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH);
+ GLint row;
+ for (row = 0; row < height; row++) {
+ GLint spanY = y + row;
+ GLubyte values[MAX_WIDTH];
+ GLenum destType = GL_UNSIGNED_BYTE;
+ const GLvoid *source = _mesa_image_address2d(unpack, pixels,
+ width, height,
+ GL_COLOR_INDEX, type,
+ row, skipPixels);
+ _mesa_unpack_stencil_span(ctx, spanWidth, destType, values,
+ type, source, unpack,
+ ctx->_ImageTransferState);
+ if (zoom) {
+ /*
+ _swrast_write_zoomed_stencil_span(ctx, x, y, spanWidth,
+ spanX, spanY, values);
+ */
+ }
+ else {
+ if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
+ spanY = ctx->DrawBuffer->Height - spanY - 1;
+ }
+
+ switch (ps->format) {
+ case PIPE_FORMAT_S8_UNORM:
+ {
+ ubyte *dest = stmap + spanY * ps->stride + spanX;
+ memcpy(dest, values, spanWidth);
+ }
+ break;
+ case PIPE_FORMAT_S8Z24_UNORM:
+ {
+ uint *dest = (uint *) (stmap + spanY * ps->stride + spanX*4);
+ GLint k;
+ for (k = 0; k < spanWidth; k++) {
+ uint p = dest[k];
+ p = (p & 0xffffff) | (values[k] << 24);
+ dest[k] = p;
+ }
+ }
+ break;
+ default:
+ assert(0);
+ }
+ }
+ }
+ skipPixels += spanWidth;
+ }
+
+ /* unmap the stencil buffer */
+ screen->surface_unmap(screen, ps);
+ pipe_surface_reference(&ps, NULL);
+}
+
+
+/**
+ * Called via ctx->Driver.DrawPixels()
+ */
+static void
+st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels)
+{
+ struct st_fragment_program *stfp;
+ struct st_vertex_program *stvp;
+ struct st_context *st = ctx->st;
+ struct pipe_surface *ps;
+ GLuint bufferFormat;
+ const GLfloat *color;
+
+ if (format == GL_STENCIL_INDEX) {
+ draw_stencil_pixels(ctx, x, y, width, height, type, unpack, pixels);
+ return;
+ }
+
+ _mesa_set_vp_override( ctx, TRUE );
+ _mesa_update_state( ctx );
+
+ st_validate_state(st);
+
+ if (format == GL_DEPTH_COMPONENT) {
+ ps = st->state.framebuffer.zsbuf;
+ stfp = make_fragment_shader_z(ctx->st);
+ stvp = st_make_passthrough_vertex_shader(ctx->st, GL_TRUE);
+ color = ctx->Current.RasterColor;
+ }
+ else if (format == GL_STENCIL_INDEX) {
+ ps = st->state.framebuffer.zsbuf;
+ /* XXX special case - can't use texture map */
+ color = NULL;
+ }
+ else {
+ ps = st->state.framebuffer.cbufs[0];
+ stfp = combined_drawpix_fragment_program(ctx);
+ stvp = st_make_passthrough_vertex_shader(ctx->st, GL_FALSE);
+ color = NULL;
+ }
+
+ bufferFormat = ps->format;
+
+ if (1/*any_fragment_ops(st) ||
+ any_pixel_transfer_ops(st) ||
+ !compatible_formats(format, type, ps->format)*/) {
+ /* textured quad */
+ struct pipe_texture *pt
+ = make_texture(ctx->st, width, height, format, type, unpack, pixels);
+ if (pt) {
+ draw_textured_quad(ctx, x, y, ctx->Current.RasterPos[2],
+ width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY,
+ pt, stvp, stfp, color, GL_FALSE);
+ pipe_texture_reference(&pt, NULL);
+ }
+ }
+ else {
+ /* blit */
+ draw_blit(st, width, height, format, type, pixels);
+ }
+
+ _mesa_set_vp_override( ctx, FALSE );
+}
+
+
+
+static void
+copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
+ GLsizei width, GLsizei height,
+ GLint dstx, GLint dsty)
+{
+ struct st_renderbuffer *rbDraw = st_renderbuffer(ctx->DrawBuffer->_StencilBuffer);
+ struct pipe_screen *screen = ctx->st->pipe->screen;
+ struct pipe_surface *psDraw;
+ ubyte *drawMap;
+ ubyte *buffer;
+ int i;
+
+ buffer = malloc(width * height * sizeof(ubyte));
+ if (!buffer) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels(stencil)");
+ return;
+ }
+
+ /* this will do stencil pixel transfer ops */
+ st_read_stencil_pixels(ctx, srcx, srcy, width, height, GL_UNSIGNED_BYTE,
+ &ctx->DefaultPacking, buffer);
+
+ psDraw = screen->get_tex_surface(screen, rbDraw->texture, 0, 0, 0,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+
+ assert(psDraw->block.width == 1);
+ assert(psDraw->block.height == 1);
+
+ /* map the stencil buffer */
+ drawMap = screen->surface_map(screen, psDraw, PIPE_BUFFER_USAGE_CPU_WRITE);
+
+ /* draw */
+ /* XXX PixelZoom not handled yet */
+ for (i = 0; i < height; i++) {
+ ubyte *dst;
+ const ubyte *src;
+ int y;
+
+ y = dsty + i;
+
+ if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
+ y = ctx->DrawBuffer->Height - y - 1;
+ }
+
+ dst = drawMap + y * psDraw->stride + dstx * psDraw->block.size;
+ src = buffer + i * width;
+
+ switch (psDraw->format) {
+ case PIPE_FORMAT_S8Z24_UNORM:
+ {
+ uint *dst4 = (uint *) dst;
+ int j;
+ for (j = 0; j < width; j++) {
+ *dst4 = (*dst4 & 0xffffff) | (src[j] << 24);
+ dst4++;
+ }
+ }
+ break;
+ case PIPE_FORMAT_S8_UNORM:
+ memcpy(dst, src, width);
+ break;
+ default:
+ assert(0);
+ }
+ }
+
+ free(buffer);
+
+ /* unmap the stencil buffer */
+ screen->surface_unmap(screen, psDraw);
+ pipe_surface_reference(&psDraw, NULL);
+}
+
+
+static void
+st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,
+ GLsizei width, GLsizei height,
+ GLint dstx, GLint dsty, GLenum type)
+{
+ struct st_context *st = ctx->st;
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct st_renderbuffer *rbRead;
+ struct st_vertex_program *stvp;
+ struct st_fragment_program *stfp;
+ struct pipe_surface *psTex;
+ struct pipe_texture *pt;
+ GLfloat *color;
+ enum pipe_format srcFormat, texFormat;
+
+ /* make sure rendering has completed */
+ pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+ st_validate_state(st);
+
+ if (type == GL_STENCIL) {
+ /* can't use texturing to do stencil */
+ copy_stencil_pixels(ctx, srcx, srcy, width, height, dstx, dsty);
+ return;
+ }
+
+ if (type == GL_COLOR) {
+ rbRead = st_get_color_read_renderbuffer(ctx);
+ color = NULL;
+ stfp = combined_drawpix_fragment_program(ctx);
+ stvp = st_make_passthrough_vertex_shader(ctx->st, GL_FALSE);
+ }
+ else {
+ assert(type == GL_DEPTH);
+ rbRead = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer);
+ color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
+ stfp = make_fragment_shader_z(ctx->st);
+ stvp = st_make_passthrough_vertex_shader(ctx->st, GL_TRUE);
+ }
+
+ srcFormat = rbRead->texture->format;
+
+ if (screen->is_format_supported(screen, srcFormat, PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_SAMPLER, 0)) {
+ texFormat = srcFormat;
+ }
+ else {
+ /* srcFormat can't be used as a texture format */
+ if (type == GL_DEPTH) {
+ texFormat = st_choose_format(pipe, GL_DEPTH_COMPONENT, PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_DEPTH_STENCIL);
+ assert(texFormat != PIPE_FORMAT_NONE); /* XXX no depth texture formats??? */
+ }
+ else {
+ /* default color format */
+ texFormat = st_choose_format(pipe, GL_RGBA, PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_SAMPLER);
+ assert(texFormat != PIPE_FORMAT_NONE);
+ }
+ }
+
+ pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, texFormat, 0,
+ width, height, 1, 0,
+ PIPE_TEXTURE_USAGE_SAMPLER);
+ if (!pt)
+ return;
+
+ if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
+ srcy = ctx->DrawBuffer->Height - srcy - height;
+ }
+
+ if (srcFormat == texFormat) {
+ /* copy source framebuffer surface into mipmap/texture */
+ struct pipe_surface *psRead = screen->get_tex_surface(screen,
+ rbRead->texture, 0, 0, 0,
+ PIPE_BUFFER_USAGE_GPU_READ);
+ psTex = screen->get_tex_surface(screen, pt, 0, 0, 0,
+ PIPE_BUFFER_USAGE_GPU_WRITE );
+ pipe->surface_copy(pipe,
+ FALSE,
+ psTex, /* dest */
+ 0, 0, /* destx/y */
+ psRead,
+ srcx, srcy, width, height);
+ pipe_surface_reference(&psRead, NULL);
+ }
+ else {
+ /* CPU-based fallback/conversion */
+ struct pipe_surface *psRead = screen->get_tex_surface(screen,
+ rbRead->texture, 0, 0, 0,
+ PIPE_BUFFER_USAGE_CPU_READ);
+
+ psTex = screen->get_tex_surface(screen, pt, 0, 0, 0,
+ PIPE_BUFFER_USAGE_CPU_WRITE );
+
+ if (type == GL_COLOR) {
+ /* alternate path using get/put_tile() */
+ GLfloat *buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
+
+ pipe_get_tile_rgba(psRead, srcx, srcy, width, height, buf);
+ pipe_put_tile_rgba(psTex, 0, 0, width, height, buf);
+
+ free(buf);
+ }
+ else {
+ /* GL_DEPTH */
+ GLuint *buf = (GLuint *) malloc(width * height * sizeof(GLuint));
+ pipe_get_tile_z(psRead, srcx, srcy, width, height, buf);
+ pipe_put_tile_z(psTex, 0, 0, width, height, buf);
+ free(buf);
+ }
+ pipe_surface_reference(&psRead, NULL);
+ }
+
+ pipe_surface_reference(&psTex, NULL);
+
+ /* draw textured quad */
+ draw_textured_quad(ctx, dstx, dsty, ctx->Current.RasterPos[2],
+ width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY,
+ pt, stvp, stfp, color, GL_TRUE);
+
+ pipe_texture_reference(&pt, NULL);
+}
+
+
+
+void st_init_drawpixels_functions(struct dd_function_table *functions)
+{
+ functions->DrawPixels = st_DrawPixels;
+ functions->CopyPixels = st_CopyPixels;
+}
+
+
+void
+st_destroy_drawpix(struct st_context *st)
+{
+ st_reference_fragprog(st, &st->drawpix.z_shader, NULL);
+ st_reference_fragprog(st, &st->pixel_xfer.combined_prog, NULL);
+ st_reference_vertprog(st, &st->drawpix.vert_shaders[0], NULL);
+ st_reference_vertprog(st, &st->drawpix.vert_shaders[1], NULL);
+}
+
+
diff --git a/src/mesa/state_tracker/st_cb_drawpixels.h b/src/mesa/state_tracker/st_cb_drawpixels.h
new file mode 100644
index 00000000000..26fe864d185
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_drawpixels.h
@@ -0,0 +1,39 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_CB_DRAWPIXELS_H
+#define ST_CB_DRAWPIXELS_H
+
+
+extern void st_init_drawpixels_functions(struct dd_function_table *functions);
+
+extern void
+st_destroy_drawpix(struct st_context *st);
+
+
+#endif /* ST_CB_DRAWPIXELS_H */
diff --git a/src/mesa/state_tracker/st_cb_fbo.c b/src/mesa/state_tracker/st_cb_fbo.c
new file mode 100644
index 00000000000..9af648b8d0f
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_fbo.c
@@ -0,0 +1,458 @@
+/**************************************************************************
+ *
+ * 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/renderbuffer.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_screen.h"
+#include "st_context.h"
+#include "st_cb_fbo.h"
+#include "st_cb_texture.h"
+#include "st_format.h"
+#include "st_public.h"
+#include "st_texture.h"
+
+
+
+/**
+ * Compute the renderbuffer's Red/Green/EtcBit fields from the pipe format.
+ */
+static int
+init_renderbuffer_bits(struct st_renderbuffer *strb,
+ enum pipe_format pipeFormat)
+{
+ struct pipe_format_info info;
+
+ if (!st_get_format_info( pipeFormat, &info )) {
+ assert( 0 );
+ }
+
+ strb->Base._ActualFormat = info.base_format;
+ strb->Base.RedBits = info.red_bits;
+ strb->Base.GreenBits = info.green_bits;
+ strb->Base.BlueBits = info.blue_bits;
+ strb->Base.AlphaBits = info.alpha_bits;
+ strb->Base.DepthBits = info.depth_bits;
+ strb->Base.StencilBits = info.stencil_bits;
+ strb->Base.DataType = st_format_datatype(pipeFormat);
+
+ return info.size;
+}
+
+/**
+ * gl_renderbuffer::AllocStorage()
+ * This is called to allocate the original drawing surface, and
+ * during window resize.
+ */
+static GLboolean
+st_renderbuffer_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
+ GLenum internalFormat,
+ GLuint width, GLuint height)
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct st_renderbuffer *strb = st_renderbuffer(rb);
+ struct pipe_texture template;
+ unsigned surface_usage;
+
+ /* Free the old surface and texture
+ */
+ pipe_surface_reference( &strb->surface, NULL );
+ pipe_texture_reference( &strb->texture, NULL );
+
+
+ memset(&template, 0, sizeof(template));
+
+ if (strb->format != PIPE_FORMAT_NONE) {
+ template.format = strb->format;
+ }
+ else {
+ template.format = st_choose_renderbuffer_format(pipe, internalFormat);
+ }
+
+ strb->Base.Width = width;
+ strb->Base.Height = height;
+ init_renderbuffer_bits(strb, template.format);
+
+ template.target = PIPE_TEXTURE_2D;
+ template.compressed = 0;
+ pf_get_block(template.format, &template.block);
+ template.width[0] = width;
+ template.height[0] = height;
+ template.depth[0] = 1;
+ template.last_level = 0;
+ template.nr_samples = rb->NumSamples;
+
+ if (pf_is_depth_stencil(template.format)) {
+ template.tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL;
+ }
+ else {
+ template.tex_usage = (PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
+ PIPE_TEXTURE_USAGE_RENDER_TARGET);
+ }
+
+
+ /* Probably need dedicated flags for surface usage too:
+ */
+ surface_usage = (PIPE_BUFFER_USAGE_GPU_READ |
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+#if 0
+ PIPE_BUFFER_USAGE_CPU_READ |
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+#endif
+
+ strb->texture = pipe->screen->texture_create( pipe->screen,
+ &template );
+
+ /* Special path for accum buffers.
+ *
+ * Try a different surface format. Since accum buffers are s/w
+ * only for now, the surface pixel format doesn't really matter,
+ * only that the buffer is large enough.
+ */
+ if (!strb->texture && template.format == DEFAULT_ACCUM_PIPE_FORMAT)
+ {
+ /* Actually, just setting this usage value should be sufficient
+ * to tell the driver to go ahead and allocate the buffer, even
+ * if HW doesn't support the format.
+ */
+ template.tex_usage = 0;
+ surface_usage = (PIPE_BUFFER_USAGE_CPU_READ |
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+
+ strb->texture = pipe->screen->texture_create( pipe->screen,
+ &template );
+
+ }
+
+ if (!strb->texture)
+ return FALSE;
+
+ strb->surface = pipe->screen->get_tex_surface( pipe->screen,
+ strb->texture,
+ 0, 0, 0,
+ surface_usage );
+
+ assert(strb->surface->texture);
+ assert(strb->surface->format);
+ assert(strb->surface->block.size);
+ assert(strb->surface->block.width);
+ assert(strb->surface->block.height);
+ assert(strb->surface->width == width);
+ assert(strb->surface->height == height);
+ assert(strb->surface->stride);
+
+
+ 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_texture_reference(&strb->texture, NULL);
+ free(strb);
+}
+
+
+/**
+ * gl_renderbuffer::GetPointer()
+ */
+static void *
+null_get_pointer(GLcontext * 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(GLcontext *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(GLcontext *ctx, GLuint name)
+{
+ struct st_renderbuffer *strb = 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)
+{
+ struct st_renderbuffer *strb;
+
+ strb = 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->format = format;
+
+ switch (format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ case PIPE_FORMAT_X8R8G8B8_UNORM:
+ case PIPE_FORMAT_B8G8R8X8_UNORM:
+ case PIPE_FORMAT_A1R5G5B5_UNORM:
+ case PIPE_FORMAT_A4R4G4B4_UNORM:
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ strb->Base.InternalFormat = GL_RGBA;
+ strb->Base._BaseFormat = GL_RGBA;
+ break;
+ case PIPE_FORMAT_Z16_UNORM:
+ strb->Base.InternalFormat = GL_DEPTH_COMPONENT16;
+ strb->Base._BaseFormat = GL_DEPTH_COMPONENT;
+ break;
+ case PIPE_FORMAT_Z32_UNORM:
+ strb->Base.InternalFormat = GL_DEPTH_COMPONENT32;
+ strb->Base._BaseFormat = GL_DEPTH_COMPONENT;
+ break;
+ case PIPE_FORMAT_S8Z24_UNORM:
+ case PIPE_FORMAT_Z24S8_UNORM:
+ case PIPE_FORMAT_X8Z24_UNORM:
+ case PIPE_FORMAT_Z24X8_UNORM:
+ strb->Base.InternalFormat = GL_DEPTH24_STENCIL8_EXT;
+ strb->Base._BaseFormat = GL_DEPTH_STENCIL_EXT;
+ break;
+ case PIPE_FORMAT_S8_UNORM:
+ strb->Base.InternalFormat = GL_STENCIL_INDEX8_EXT;
+ strb->Base._BaseFormat = GL_STENCIL_INDEX;
+ break;
+ case DEFAULT_ACCUM_PIPE_FORMAT: /*PIPE_FORMAT_R16G16B16A16_SNORM*/
+ strb->Base.InternalFormat = GL_RGBA16;
+ strb->Base._BaseFormat = GL_RGBA;
+ break;
+ default:
+ _mesa_problem(NULL,
+ "Unexpected format in st_new_renderbuffer_fb");
+ 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(GLcontext *ctx, GLenum target,
+ struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
+{
+
+}
+
+/**
+ * Called by ctx->Driver.FramebufferRenderbuffer
+ */
+static void
+st_framebuffer_renderbuffer(GLcontext *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(GLcontext *ctx,
+ struct gl_framebuffer *fb,
+ struct gl_renderbuffer_attachment *att)
+{
+ struct st_renderbuffer *strb;
+ struct gl_renderbuffer *rb;
+ struct pipe_texture *pt = st_get_texobj_texture(att->Texture);
+ struct st_texture_object *stObj;
+ const struct gl_texture_image *texImage =
+ att->Texture->Image[att->CubeMapFace][att->TextureLevel];
+
+ if (!pt)
+ return;
+
+ assert(!att->Renderbuffer);
+
+ /* 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);
+
+ /* 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;
+ /*printf("***** render to texture level %d: %d x %d\n", att->TextureLevel, rb->Width, rb->Height);*/
+
+ /*printf("***** pipe texture %d x %d\n", pt->width[0], pt->height[0]);*/
+
+ pipe_texture_reference( &strb->texture, pt );
+
+ pipe_surface_reference(&strb->surface, NULL);
+
+ /* the new surface will be created during framebuffer validation */
+
+ init_renderbuffer_bits(strb, 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(GLcontext *ctx,
+ struct gl_renderbuffer_attachment *att)
+{
+ struct pipe_screen *screen = ctx->st->pipe->screen;
+ struct st_renderbuffer *strb = st_renderbuffer(att->Renderbuffer);
+
+ if (!strb)
+ return;
+
+ st_flush( ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL );
+
+ if (strb->surface)
+ screen->tex_surface_release( screen, &strb->surface );
+
+ strb->rtt = NULL;
+
+ /*
+ printf("FINISH RENDER TO TEXTURE surf=%p\n", strb->surface);
+ */
+
+ _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
+
+ /* restore previous framebuffer state */
+ st_invalidate_state(ctx, _NEW_BUFFERS);
+}
+
+
+
+void st_init_fbo_functions(struct dd_function_table *functions)
+{
+ 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;
+ /* no longer needed by core Mesa, drivers handle resizes...
+ functions->ResizeBuffers = st_resize_buffers;
+ */
+}
diff --git a/src/mesa/state_tracker/st_cb_fbo.h b/src/mesa/state_tracker/st_cb_fbo.h
new file mode 100644
index 00000000000..44fa9fe9a4f
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_fbo.h
@@ -0,0 +1,71 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_CB_FBO_H
+#define ST_CB_FBO_H
+
+
+#define DEFAULT_ACCUM_PIPE_FORMAT PIPE_FORMAT_R16G16B16A16_SNORM
+
+
+
+/**
+ * Derived renderbuffer class. Just need to add a pointer to the
+ * pipe surface.
+ */
+struct st_renderbuffer
+{
+ struct gl_renderbuffer Base;
+ struct pipe_texture *texture;
+ struct pipe_surface *surface; /* temporary view into texture */
+ enum pipe_format format; /** preferred format, or PIPE_FORMAT_NONE */
+
+ struct st_texture_object *rtt; /**< GL render to texture's texture */
+ int rtt_level, rtt_face, rtt_slice;
+
+ /** Render to texture state */
+ struct pipe_texture *texture_save;
+ struct pipe_surface *surface_save;
+};
+
+
+static INLINE struct st_renderbuffer *
+st_renderbuffer(struct gl_renderbuffer *rb)
+{
+ return (struct st_renderbuffer *) rb;
+}
+
+
+extern struct gl_renderbuffer *
+st_new_renderbuffer_fb(enum pipe_format format, int samples);
+
+extern void
+st_init_fbo_functions(struct dd_function_table *functions);
+
+
+#endif /* ST_CB_FBO_H */
diff --git a/src/mesa/state_tracker/st_cb_feedback.c b/src/mesa/state_tracker/st_cb_feedback.c
new file mode 100644
index 00000000000..c7e8aa7cc56
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_feedback.c
@@ -0,0 +1,309 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+/**
+ * GL_SELECT and GL_FEEDBACK render modes.
+ * Basically, we use a private instance of the 'draw' module for doing
+ * selection/feedback. It would be nice to use the transform_feedback
+ * hardware feature, but it's defined as happening pre-clip and we want
+ * post-clipped primitives. Also, there's concerns about the efficiency
+ * of using the hardware for this anyway.
+ *
+ * Authors:
+ * Brian Paul
+ */
+
+#include "main/imports.h"
+#include "main/context.h"
+#include "main/feedback.h"
+#include "main/macros.h"
+
+#include "vbo/vbo.h"
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "st_draw.h"
+#include "st_cb_feedback.h"
+#include "st_cb_bufferobjects.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "cso_cache/cso_cache.h"
+
+#include "draw/draw_context.h"
+#include "draw/draw_pipe.h"
+
+
+/**
+ * This is actually used for both feedback and selection.
+ */
+struct feedback_stage
+{
+ struct draw_stage stage; /**< Base class */
+ GLcontext *ctx; /**< Rendering context */
+ GLboolean reset_stipple_counter;
+};
+
+
+/**********************************************************************
+ * GL Feedback functions
+ **********************************************************************/
+
+static INLINE struct feedback_stage *
+feedback_stage( struct draw_stage *stage )
+{
+ return (struct feedback_stage *)stage;
+}
+
+
+static void
+feedback_vertex(GLcontext *ctx, const struct draw_context *draw,
+ const struct vertex_header *v)
+{
+ const struct st_context *st = ctx->st;
+ GLfloat win[4];
+ const GLfloat *color, *texcoord;
+ const GLfloat ci = 0;
+ GLuint slot;
+
+ /* Recall that Y=0=Top of window for Gallium wincoords */
+ win[0] = v->data[0][0];
+ win[1] = ctx->DrawBuffer->Height - v->data[0][1];
+ win[2] = v->data[0][2];
+ win[3] = 1.0F / v->data[0][3];
+
+ /* XXX
+ * When we compute vertex layout, save info about position of the
+ * color and texcoord attribs to use here.
+ */
+
+ slot = st->vertex_result_to_slot[VERT_RESULT_COL0];
+ if (slot != ~0U)
+ color = v->data[slot];
+ else
+ color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
+
+ slot = st->vertex_result_to_slot[VERT_RESULT_TEX0];
+ if (slot != ~0U)
+ texcoord = v->data[slot];
+ else
+ texcoord = ctx->Current.Attrib[VERT_ATTRIB_TEX0];
+
+ _mesa_feedback_vertex(ctx, win, color, ci, texcoord);
+}
+
+
+static void
+feedback_tri( struct draw_stage *stage, struct prim_header *prim )
+{
+ struct feedback_stage *fs = feedback_stage(stage);
+ struct draw_context *draw = stage->draw;
+ FEEDBACK_TOKEN(fs->ctx, (GLfloat) GL_POLYGON_TOKEN);
+ FEEDBACK_TOKEN(fs->ctx, (GLfloat) 3); /* three vertices */
+ feedback_vertex(fs->ctx, draw, prim->v[0]);
+ feedback_vertex(fs->ctx, draw, prim->v[1]);
+ feedback_vertex(fs->ctx, draw, prim->v[2]);
+}
+
+
+static void
+feedback_line( struct draw_stage *stage, struct prim_header *prim )
+{
+ struct feedback_stage *fs = feedback_stage(stage);
+ struct draw_context *draw = stage->draw;
+ if (fs->reset_stipple_counter) {
+ FEEDBACK_TOKEN(fs->ctx, (GLfloat) GL_LINE_RESET_TOKEN);
+ fs->reset_stipple_counter = GL_FALSE;
+ }
+ else {
+ FEEDBACK_TOKEN(fs->ctx, (GLfloat) GL_LINE_TOKEN);
+ }
+ feedback_vertex(fs->ctx, draw, prim->v[0]);
+ feedback_vertex(fs->ctx, draw, prim->v[1]);
+}
+
+
+static void
+feedback_point( struct draw_stage *stage, struct prim_header *prim )
+{
+ struct feedback_stage *fs = feedback_stage(stage);
+ struct draw_context *draw = stage->draw;
+ FEEDBACK_TOKEN(fs->ctx, (GLfloat) GL_POINT_TOKEN);
+ feedback_vertex(fs->ctx, draw, prim->v[0]);
+}
+
+
+static void
+feedback_flush( struct draw_stage *stage, unsigned flags )
+{
+ /* no-op */
+}
+
+
+static void
+feedback_reset_stipple_counter( struct draw_stage *stage )
+{
+ struct feedback_stage *fs = feedback_stage(stage);
+ fs->reset_stipple_counter = GL_TRUE;
+}
+
+
+static void
+feedback_destroy( struct draw_stage *stage )
+{
+ /* no-op */
+}
+
+/**
+ * Create GL feedback drawing stage.
+ */
+static struct draw_stage *
+draw_glfeedback_stage(GLcontext *ctx, struct draw_context *draw)
+{
+ struct feedback_stage *fs = CALLOC_STRUCT(feedback_stage);
+
+ fs->stage.draw = draw;
+ fs->stage.next = NULL;
+ fs->stage.point = feedback_point;
+ fs->stage.line = feedback_line;
+ fs->stage.tri = feedback_tri;
+ fs->stage.flush = feedback_flush;
+ fs->stage.reset_stipple_counter = feedback_reset_stipple_counter;
+ fs->stage.destroy = feedback_destroy;
+ fs->ctx = ctx;
+
+ return &fs->stage;
+}
+
+
+
+/**********************************************************************
+ * GL Selection functions
+ **********************************************************************/
+
+static void
+select_tri( struct draw_stage *stage, struct prim_header *prim )
+{
+ struct feedback_stage *fs = feedback_stage(stage);
+ _mesa_update_hitflag( fs->ctx, prim->v[0]->data[0][2] );
+ _mesa_update_hitflag( fs->ctx, prim->v[1]->data[0][2] );
+ _mesa_update_hitflag( fs->ctx, prim->v[2]->data[0][2] );
+}
+
+static void
+select_line( struct draw_stage *stage, struct prim_header *prim )
+{
+ struct feedback_stage *fs = feedback_stage(stage);
+ _mesa_update_hitflag( fs->ctx, prim->v[0]->data[0][2] );
+ _mesa_update_hitflag( fs->ctx, prim->v[1]->data[0][2] );
+}
+
+
+static void
+select_point( struct draw_stage *stage, struct prim_header *prim )
+{
+ struct feedback_stage *fs = feedback_stage(stage);
+ _mesa_update_hitflag( fs->ctx, prim->v[0]->data[0][2] );
+}
+
+
+static void
+select_flush( struct draw_stage *stage, unsigned flags )
+{
+ /* no-op */
+}
+
+
+static void
+select_reset_stipple_counter( struct draw_stage *stage )
+{
+ /* no-op */
+}
+
+static void
+select_destroy( struct draw_stage *stage )
+{
+ /* no-op */
+}
+
+
+/**
+ * Create GL selection mode drawing stage.
+ */
+static struct draw_stage *
+draw_glselect_stage(GLcontext *ctx, struct draw_context *draw)
+{
+ struct feedback_stage *fs = CALLOC_STRUCT(feedback_stage);
+
+ fs->stage.draw = draw;
+ fs->stage.next = NULL;
+ fs->stage.point = select_point;
+ fs->stage.line = select_line;
+ fs->stage.tri = select_tri;
+ fs->stage.flush = select_flush;
+ fs->stage.reset_stipple_counter = select_reset_stipple_counter;
+ fs->stage.destroy = select_destroy;
+ fs->ctx = ctx;
+
+ return &fs->stage;
+}
+
+
+static void
+st_RenderMode(GLcontext *ctx, GLenum newMode )
+{
+ struct st_context *st = ctx->st;
+ struct draw_context *draw = st->draw;
+
+ if (newMode == GL_RENDER) {
+ /* restore normal VBO draw function */
+ vbo_set_draw_func(ctx, st_draw_vbo);
+ }
+ else if (newMode == GL_SELECT) {
+ if (!st->selection_stage)
+ st->selection_stage = draw_glselect_stage(ctx, draw);
+ draw_set_rasterize_stage(draw, st->selection_stage);
+ /* Plug in new vbo draw function */
+ vbo_set_draw_func(ctx, st_feedback_draw_vbo);
+ }
+ else {
+ if (!st->feedback_stage)
+ st->feedback_stage = draw_glfeedback_stage(ctx, draw);
+ draw_set_rasterize_stage(draw, st->feedback_stage);
+ /* Plug in new vbo draw function */
+ vbo_set_draw_func(ctx, st_feedback_draw_vbo);
+ /* need to generate/use a vertex program that emits pos/color/tex */
+ st->dirty.st |= ST_NEW_VERTEX_PROGRAM;
+ }
+}
+
+
+
+void st_init_feedback_functions(struct dd_function_table *functions)
+{
+ functions->RenderMode = st_RenderMode;
+}
diff --git a/src/mesa/state_tracker/st_cb_feedback.h b/src/mesa/state_tracker/st_cb_feedback.h
new file mode 100644
index 00000000000..2559ba3817b
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_feedback.h
@@ -0,0 +1,37 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_CB_FEEDBACK_H
+#define ST_CB_FEEDBACK_H
+
+
+extern void
+st_init_feedback_functions(struct dd_function_table *functions);
+
+
+#endif /* ST_CB_FEEDBACK_H */
diff --git a/src/mesa/state_tracker/st_cb_flush.c b/src/mesa/state_tracker/st_cb_flush.c
new file mode 100644
index 00000000000..f8621ab125f
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_flush.c
@@ -0,0 +1,149 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <[email protected]>
+ * Brian Paul
+ */
+
+#include "main/glheader.h"
+#include "main/macros.h"
+#include "main/context.h"
+#include "st_context.h"
+#include "st_cb_bitmap.h"
+#include "st_cb_flush.h"
+#include "st_cb_clear.h"
+#include "st_cb_fbo.h"
+#include "st_public.h"
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_screen.h"
+#include "util/u_gen_mipmap.h"
+#include "util/u_blit.h"
+
+
+static INLINE GLboolean
+is_front_buffer_dirty(struct st_context *st)
+{
+ return st->frontbuffer_status == FRONT_STATUS_DIRTY;
+}
+
+
+/**
+ * Tell the screen to display the front color buffer on-screen.
+ */
+static void
+display_front_buffer(struct st_context *st)
+{
+ GLframebuffer *fb = st->ctx->DrawBuffer;
+ struct st_renderbuffer *strb
+ = st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
+ struct pipe_surface *front_surf = strb->surface;
+
+ /* Hook for copying "fake" frontbuffer if necessary:
+ */
+ st->pipe->screen->flush_frontbuffer( st->pipe->screen, front_surf,
+ st->pipe->priv );
+
+ /*
+ st->frontbuffer_status = FRONT_STATUS_UNDEFINED;
+ */
+}
+
+
+void st_flush( struct st_context *st, uint pipeFlushFlags,
+ struct pipe_fence_handle **fence )
+{
+ FLUSH_VERTICES(st->ctx, 0);
+
+ /* Release any vertex buffers that might potentially be accessed in
+ * successive frames:
+ */
+ st_flush_bitmap(st);
+ st_flush_clear(st);
+ util_blit_flush(st->blit);
+ util_gen_mipmap_flush(st->gen_mipmap);
+
+ st->pipe->flush( st->pipe, pipeFlushFlags, fence );
+}
+
+
+/**
+ * Flush, and wait for completion.
+ */
+void st_finish( struct st_context *st )
+{
+ struct pipe_fence_handle *fence = NULL;
+
+ st_flush(st, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, &fence);
+
+ if(fence) {
+ st->pipe->screen->fence_finish(st->pipe->screen, fence, 0);
+ st->pipe->screen->fence_reference(st->pipe->screen, &fence, NULL);
+ }
+}
+
+
+
+/**
+ * Called via ctx->Driver.Flush()
+ */
+static void st_glFlush(GLcontext *ctx)
+{
+ struct st_context *st = ctx->st;
+
+ if (is_front_buffer_dirty(st)) {
+ st_finish(st);
+ display_front_buffer(st);
+ }
+ else {
+ st_flush(st, PIPE_FLUSH_RENDER_CACHE, NULL);
+ }
+}
+
+
+/**
+ * Called via ctx->Driver.Finish()
+ */
+static void st_glFinish(GLcontext *ctx)
+{
+ struct st_context *st = ctx->st;
+
+ st_finish(st);
+
+ if (is_front_buffer_dirty(st)) {
+ display_front_buffer(st);
+ }
+}
+
+
+void st_init_flush_functions(struct dd_function_table *functions)
+{
+ functions->Flush = st_glFlush;
+ functions->Finish = st_glFinish;
+}
diff --git a/src/mesa/state_tracker/st_cb_flush.h b/src/mesa/state_tracker/st_cb_flush.h
new file mode 100644
index 00000000000..c26f7792259
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_flush.h
@@ -0,0 +1,38 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_CB_FLUSH_H
+#define ST_CB_FLUSH_H
+
+
+extern void
+st_init_flush_functions(struct dd_function_table *functions);
+
+
+#endif /* ST_CB_FLUSH_H */
+
diff --git a/src/mesa/state_tracker/st_cb_get.c b/src/mesa/state_tracker/st_cb_get.c
new file mode 100644
index 00000000000..e7d7f03bc9b
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_get.c
@@ -0,0 +1,97 @@
+/**************************************************************************
+ *
+ * Copyright 2008 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.
+ *
+ **************************************************************************/
+
+
+/**
+ * glGet functions
+ *
+ * \author Brian Paul
+ */
+
+#include "main/imports.h"
+#include "main/context.h"
+
+#include "pipe/p_defines.h"
+
+#include "st_cb_fbo.h"
+#include "st_cb_get.h"
+
+
+
+/**
+ * Examine the current color read buffer format to determine
+ * which GL pixel format/type combo is the best match.
+ */
+static void
+get_preferred_read_format_type(GLcontext *ctx, GLint *format, GLint *type)
+{
+ struct gl_framebuffer *fb = ctx->ReadBuffer;
+ struct st_renderbuffer *strb = st_renderbuffer(fb->_ColorReadBuffer);
+
+ /* defaults */
+ *format = ctx->Const.ColorReadFormat;
+ *type = ctx->Const.ColorReadType;
+
+ if (strb) {
+ /* XXX could add more cases here... */
+ if (strb->format == PIPE_FORMAT_A8R8G8B8_UNORM) {
+ *format = GL_BGRA;
+ if (_mesa_little_endian())
+ *type = GL_UNSIGNED_INT_8_8_8_8_REV;
+ else
+ *type = GL_UNSIGNED_INT_8_8_8_8;
+ }
+ }
+}
+
+
+/**
+ * We only intercept the OES preferred ReadPixels format/type.
+ * Everything else goes to the default _mesa_GetIntegerv.
+ */
+static GLboolean
+st_GetIntegerv(GLcontext *ctx, GLenum pname, GLint *params)
+{
+ GLint dummy;
+
+ switch (pname) {
+ case GL_IMPLEMENTATION_COLOR_READ_TYPE_OES:
+ get_preferred_read_format_type(ctx, &dummy, params);
+ return GL_TRUE;
+ case GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES:
+ get_preferred_read_format_type(ctx, params, &dummy);
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+void st_init_get_functions(struct dd_function_table *functions)
+{
+ functions->GetIntegerv = st_GetIntegerv;
+}
diff --git a/src/mesa/state_tracker/st_cb_get.h b/src/mesa/state_tracker/st_cb_get.h
new file mode 100644
index 00000000000..8e9f3e93060
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_get.h
@@ -0,0 +1,37 @@
+/**************************************************************************
+ *
+ * Copyright 2008 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.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_CB_GET_H
+#define ST_CB_GET_H
+
+
+extern void
+st_init_get_functions(struct dd_function_table *functions);
+
+
+#endif
diff --git a/src/mesa/state_tracker/st_cb_program.c b/src/mesa/state_tracker/st_cb_program.c
new file mode 100644
index 00000000000..ea0fa20012e
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_program.c
@@ -0,0 +1,266 @@
+/**************************************************************************
+ *
+ * Copyright 2003 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.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <[email protected]>
+ */
+
+#include "main/glheader.h"
+#include "main/macros.h"
+#include "main/enums.h"
+#include "shader/prog_instruction.h"
+#include "shader/prog_parameter.h"
+#include "shader/program.h"
+#include "shader/programopt.h"
+#include "shader/shader_api.h"
+
+#include "cso_cache/cso_context.h"
+#include "draw/draw_context.h"
+
+#include "st_context.h"
+#include "st_program.h"
+#include "st_atom_shader.h"
+#include "st_cb_program.h"
+
+
+static GLuint SerialNo = 1;
+
+
+/**
+ * Called via ctx->Driver.BindProgram() to bind an ARB vertex or
+ * fragment program.
+ */
+static void st_bind_program( GLcontext *ctx,
+ GLenum target,
+ struct gl_program *prog )
+{
+ struct st_context *st = st_context(ctx);
+
+ switch (target) {
+ case GL_VERTEX_PROGRAM_ARB:
+ st->dirty.st |= ST_NEW_VERTEX_PROGRAM;
+ break;
+ case GL_FRAGMENT_PROGRAM_ARB:
+ st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
+ break;
+ }
+}
+
+
+/**
+ * Called via ctx->Driver.UseProgram() to bind a linked GLSL program
+ * (vertex shader + fragment shader).
+ */
+static void st_use_program( GLcontext *ctx,
+ GLuint program )
+{
+ struct st_context *st = st_context(ctx);
+
+ st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
+ st->dirty.st |= ST_NEW_VERTEX_PROGRAM;
+
+ _mesa_use_program(ctx, program);
+}
+
+
+
+/**
+ * Called via ctx->Driver.NewProgram() to allocate a new vertex or
+ * fragment program.
+ */
+static struct gl_program *st_new_program( GLcontext *ctx,
+ GLenum target,
+ GLuint id )
+{
+ switch (target) {
+ case GL_VERTEX_PROGRAM_ARB: {
+ struct st_vertex_program *prog = CALLOC_STRUCT(st_vertex_program);
+
+ prog->serialNo = SerialNo++;
+
+ return _mesa_init_vertex_program( ctx,
+ &prog->Base,
+ target,
+ id );
+ }
+
+ case GL_FRAGMENT_PROGRAM_ARB:
+ case GL_FRAGMENT_PROGRAM_NV: {
+ struct st_fragment_program *prog = CALLOC_STRUCT(st_fragment_program);
+
+ prog->serialNo = SerialNo++;
+
+ return _mesa_init_fragment_program( ctx,
+ &prog->Base,
+ target,
+ id );
+ }
+
+ default:
+ assert(0);
+ return NULL;
+ }
+}
+
+
+void
+st_delete_program(GLcontext *ctx, struct gl_program *prog)
+{
+ struct st_context *st = st_context(ctx);
+
+ switch( prog->Target ) {
+ case GL_VERTEX_PROGRAM_ARB:
+ {
+ struct st_vertex_program *stvp = (struct st_vertex_program *) prog;
+
+ if (stvp->driver_shader) {
+ cso_delete_vertex_shader(st->cso_context, stvp->driver_shader);
+ stvp->driver_shader = NULL;
+ }
+
+ if (stvp->draw_shader) {
+#if FEATURE_feedback || FEATURE_drawpix
+ /* this would only have been allocated for the RasterPos path */
+ draw_delete_vertex_shader(st->draw, stvp->draw_shader);
+ stvp->draw_shader = NULL;
+#endif
+ }
+
+ if (stvp->state.tokens) {
+ FREE((void *) stvp->state.tokens);
+ stvp->state.tokens = NULL;
+ }
+ }
+ break;
+ case GL_FRAGMENT_PROGRAM_ARB:
+ {
+ struct st_fragment_program *stfp = (struct st_fragment_program *) prog;
+
+ if (stfp->driver_shader) {
+ cso_delete_fragment_shader(st->cso_context, stfp->driver_shader);
+ stfp->driver_shader = NULL;
+ }
+
+ if (stfp->state.tokens) {
+ FREE((void *) stfp->state.tokens);
+ stfp->state.tokens = NULL;
+ }
+
+ if (stfp->bitmap_program) {
+ struct gl_program *prg = &stfp->bitmap_program->Base.Base;
+ _mesa_reference_program(ctx, &prg, NULL);
+ stfp->bitmap_program = NULL;
+ }
+
+ st_free_translated_vertex_programs(st, stfp->vertex_programs);
+ }
+ break;
+ default:
+ assert(0); /* problem */
+ }
+
+ /* delete base class */
+ _mesa_delete_program( ctx, prog );
+}
+
+
+static GLboolean st_is_program_native( GLcontext *ctx,
+ GLenum target,
+ struct gl_program *prog )
+{
+ return GL_TRUE;
+}
+
+
+static void st_program_string_notify( GLcontext *ctx,
+ GLenum target,
+ struct gl_program *prog )
+{
+ struct st_context *st = st_context(ctx);
+
+ if (target == GL_FRAGMENT_PROGRAM_ARB) {
+ struct st_fragment_program *stfp = (struct st_fragment_program *) prog;
+
+ stfp->serialNo++;
+
+ if (stfp->driver_shader) {
+ cso_delete_fragment_shader(st->cso_context, stfp->driver_shader);
+ stfp->driver_shader = NULL;
+ }
+
+ if (stfp->state.tokens) {
+ FREE((void *) stfp->state.tokens);
+ stfp->state.tokens = NULL;
+ }
+
+ stfp->param_state = stfp->Base.Base.Parameters->StateFlags;
+
+ if (st->fp == stfp)
+ st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
+ }
+ else if (target == GL_VERTEX_PROGRAM_ARB) {
+ struct st_vertex_program *stvp = (struct st_vertex_program *) prog;
+
+ stvp->serialNo++;
+
+ if (stvp->driver_shader) {
+ cso_delete_vertex_shader(st->cso_context, stvp->driver_shader);
+ stvp->driver_shader = NULL;
+ }
+
+ if (stvp->draw_shader) {
+#if FEATURE_feedback || FEATURE_drawpix
+ /* this would only have been allocated for the RasterPos path */
+ draw_delete_vertex_shader(st->draw, stvp->draw_shader);
+ stvp->draw_shader = NULL;
+#endif
+ }
+
+ if (stvp->state.tokens) {
+ FREE((void *) stvp->state.tokens);
+ stvp->state.tokens = NULL;
+ }
+
+ stvp->param_state = stvp->Base.Base.Parameters->StateFlags;
+
+ if (st->vp == stvp)
+ st->dirty.st |= ST_NEW_VERTEX_PROGRAM;
+ }
+}
+
+
+
+void st_init_program_functions(struct dd_function_table *functions)
+{
+ functions->BindProgram = st_bind_program;
+ functions->UseProgram = st_use_program;
+ functions->NewProgram = st_new_program;
+ functions->DeleteProgram = st_delete_program;
+ functions->IsProgramNative = st_is_program_native;
+ functions->ProgramStringNotify = st_program_string_notify;
+}
diff --git a/src/mesa/state_tracker/st_cb_program.h b/src/mesa/state_tracker/st_cb_program.h
new file mode 100644
index 00000000000..0de96f2fd22
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_program.h
@@ -0,0 +1,39 @@
+/**************************************************************************
+ *
+ * Copyright 2008 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.
+ *
+ **************************************************************************/
+
+#ifndef ST_CB_PROGRAM_H
+#define ST_CB_PROGRAM_H
+
+
+extern void
+st_init_program_functions(struct dd_function_table *functions);
+
+extern void
+st_delete_program(GLcontext *ctx, struct gl_program *prog);
+
+
+#endif
diff --git a/src/mesa/state_tracker/st_cb_queryobj.c b/src/mesa/state_tracker/st_cb_queryobj.c
new file mode 100644
index 00000000000..21c2c7dd9ff
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_queryobj.c
@@ -0,0 +1,171 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+
+/**
+ * glBegin/EndQuery interface to pipe
+ *
+ * \author Brian Paul
+ */
+
+
+#include "main/imports.h"
+#include "main/context.h"
+#include "main/image.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "st_context.h"
+#include "st_cb_queryobj.h"
+#include "st_public.h"
+
+
+struct st_query_object
+{
+ struct gl_query_object base;
+ struct pipe_query *pq;
+};
+
+
+/**
+ * Cast wrapper
+ */
+static struct st_query_object *
+st_query_object(struct gl_query_object *q)
+{
+ return (struct st_query_object *) q;
+}
+
+
+static struct gl_query_object *
+st_NewQueryObject(GLcontext *ctx, GLuint id)
+{
+ struct st_query_object *stq = CALLOC_STRUCT(st_query_object);
+ if (stq) {
+ stq->base.Id = id;
+ stq->base.Ready = GL_TRUE;
+ stq->pq = NULL;
+ return &stq->base;
+ }
+ return NULL;
+}
+
+
+
+static void
+st_DeleteQuery(GLcontext *ctx, struct gl_query_object *q)
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct st_query_object *stq = st_query_object(q);
+
+ if (stq->pq) {
+ pipe->destroy_query(pipe, stq->pq);
+ stq->pq = NULL;
+ }
+
+ FREE(stq);
+}
+
+
+static void
+st_BeginQuery(GLcontext *ctx, struct gl_query_object *q)
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct st_query_object *stq = st_query_object(q);
+
+ switch (q->Target) {
+ case GL_SAMPLES_PASSED_ARB:
+ if (!stq->pq)
+ stq->pq = pipe->create_query( pipe, PIPE_QUERY_OCCLUSION_COUNTER );
+ break;
+ default:
+ assert(0);
+ return;
+ }
+
+ pipe->begin_query(pipe, stq->pq);
+}
+
+
+static void
+st_EndQuery(GLcontext *ctx, struct gl_query_object *q)
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct st_query_object *stq = st_query_object(q);
+
+ pipe->end_query(pipe, stq->pq);
+}
+
+
+static void
+st_WaitQuery(GLcontext *ctx, struct gl_query_object *q)
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct st_query_object *stq = st_query_object(q);
+
+ /* this function should only be called if we don't have a ready result */
+ assert(!stq->base.Ready);
+
+ while (!stq->base.Ready &&
+ !pipe->get_query_result(pipe,
+ stq->pq,
+ TRUE,
+ &q->Result))
+ {
+ /* nothing */
+ }
+
+ q->Ready = GL_TRUE;
+}
+
+
+static void
+st_CheckQuery(GLcontext *ctx, struct gl_query_object *q)
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct st_query_object *stq = st_query_object(q);
+
+ if (!q->Ready) {
+ q->Ready = pipe->get_query_result(pipe,
+ stq->pq,
+ FALSE,
+ &q->Result);
+ }
+}
+
+
+
+
+void st_init_query_functions(struct dd_function_table *functions)
+{
+ functions->NewQueryObject = st_NewQueryObject;
+ functions->DeleteQuery = st_DeleteQuery;
+ functions->BeginQuery = st_BeginQuery;
+ functions->EndQuery = st_EndQuery;
+ functions->WaitQuery = st_WaitQuery;
+ functions->CheckQuery = st_CheckQuery;
+}
diff --git a/src/mesa/state_tracker/st_cb_queryobj.h b/src/mesa/state_tracker/st_cb_queryobj.h
new file mode 100644
index 00000000000..9220a212b60
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_queryobj.h
@@ -0,0 +1,36 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+#ifndef ST_CB_QUERYOBJ_H
+#define ST_CB_QUERYOBJ_H
+
+
+extern void
+st_init_query_functions(struct dd_function_table *functions);
+
+
+#endif
diff --git a/src/mesa/state_tracker/st_cb_rasterpos.c b/src/mesa/state_tracker/st_cb_rasterpos.c
new file mode 100644
index 00000000000..8867ca5652e
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_rasterpos.c
@@ -0,0 +1,261 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+/**
+ * glRasterPos implementation. Basically render a GL_POINT with our
+ * private draw module. Plug in a special "rasterpos" stage at the end
+ * of the 'draw' pipeline to capture the results and update the current
+ * raster pos attributes.
+ *
+ * Authors:
+ * Brian Paul
+ */
+
+
+#include "main/imports.h"
+#include "main/macros.h"
+#include "main/feedback.h"
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "st_draw.h"
+#include "st_cb_rasterpos.h"
+#include "st_draw.h"
+#include "draw/draw_context.h"
+#include "draw/draw_pipe.h"
+#include "shader/prog_instruction.h"
+#include "vbo/vbo.h"
+
+
+
+/**
+ * Our special drawing pipeline stage (replaces rasterization).
+ */
+struct rastpos_stage
+{
+ struct draw_stage stage; /**< Base class */
+ GLcontext *ctx; /**< Rendering context */
+
+ /* vertex attrib info we can setup once and re-use */
+ struct gl_client_array array[VERT_ATTRIB_MAX];
+ const struct gl_client_array *arrays[VERT_ATTRIB_MAX];
+ struct _mesa_prim prim;
+};
+
+
+static INLINE struct rastpos_stage *
+rastpos_stage( struct draw_stage *stage )
+{
+ return (struct rastpos_stage *) stage;
+}
+
+static void
+rastpos_flush( struct draw_stage *stage, unsigned flags )
+{
+ /* no-op */
+}
+
+static void
+rastpos_reset_stipple_counter( struct draw_stage *stage )
+{
+ /* no-op */
+}
+
+static void
+rastpos_tri( struct draw_stage *stage, struct prim_header *prim )
+{
+ /* should never get here */
+ assert(0);
+}
+
+static void
+rastpos_line( struct draw_stage *stage, struct prim_header *prim )
+{
+ /* should never get here */
+ assert(0);
+}
+
+static void
+rastpos_destroy(struct draw_stage *stage)
+{
+ free(stage);
+}
+
+
+/**
+ * Update a raster pos attribute from the vertex result if it's present,
+ * else copy the current attrib.
+ */
+static void
+update_attrib(GLcontext *ctx, const GLuint *outputMapping,
+ const struct vertex_header *vert,
+ GLfloat *dest,
+ GLuint result, GLuint defaultAttrib)
+{
+ const GLfloat *src;
+ const GLuint k = outputMapping[result];
+ if (k != ~0U)
+ src = vert->data[k];
+ else
+ src = ctx->Current.Attrib[defaultAttrib];
+ COPY_4V(dest, src);
+}
+
+
+/**
+ * Normally, this function would render a GL_POINT.
+ */
+static void
+rastpos_point(struct draw_stage *stage, struct prim_header *prim)
+{
+ struct rastpos_stage *rs = rastpos_stage(stage);
+ GLcontext *ctx = rs->ctx;
+ struct st_context *st = ctx->st;
+ const GLfloat height = (GLfloat) ctx->DrawBuffer->Height;
+ const GLuint *outputMapping = st->vertex_result_to_slot;
+ const GLfloat *pos;
+ GLuint i;
+
+ /* if we get here, we didn't get clipped */
+ ctx->Current.RasterPosValid = GL_TRUE;
+
+ /* update raster pos */
+ pos = prim->v[0]->data[0];
+ ctx->Current.RasterPos[0] = pos[0];
+ if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP)
+ ctx->Current.RasterPos[1] = height - pos[1]; /* invert Y */
+ else
+ ctx->Current.RasterPos[1] = pos[1];
+ ctx->Current.RasterPos[2] = pos[2];
+ ctx->Current.RasterPos[3] = pos[3];
+
+ /* update other raster attribs */
+ update_attrib(ctx, outputMapping, prim->v[0],
+ ctx->Current.RasterColor,
+ VERT_RESULT_COL0, VERT_ATTRIB_COLOR0);
+
+ update_attrib(ctx, outputMapping, prim->v[0],
+ ctx->Current.RasterSecondaryColor,
+ VERT_RESULT_COL1, VERT_ATTRIB_COLOR1);
+
+ for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
+ update_attrib(ctx, outputMapping, prim->v[0],
+ ctx->Current.RasterTexCoords[i],
+ VERT_RESULT_TEX0 + i, VERT_ATTRIB_TEX0 + i);
+ }
+
+ if (ctx->RenderMode == GL_SELECT) {
+ _mesa_update_hitflag( ctx, ctx->Current.RasterPos[2] );
+ }
+}
+
+
+/**
+ * Create rasterpos "drawing" stage.
+ */
+static struct rastpos_stage *
+new_draw_rastpos_stage(GLcontext *ctx, struct draw_context *draw)
+{
+ struct rastpos_stage *rs = CALLOC_STRUCT(rastpos_stage);
+ GLuint i;
+
+ rs->stage.draw = draw;
+ rs->stage.next = NULL;
+ rs->stage.point = rastpos_point;
+ rs->stage.line = rastpos_line;
+ rs->stage.tri = rastpos_tri;
+ rs->stage.flush = rastpos_flush;
+ rs->stage.destroy = rastpos_destroy;
+ rs->stage.reset_stipple_counter = rastpos_reset_stipple_counter;
+ rs->stage.destroy = rastpos_destroy;
+ rs->ctx = ctx;
+
+ for (i = 0; i < VERT_ATTRIB_MAX; i++) {
+ rs->array[i].Size = 4;
+ rs->array[i].Type = GL_FLOAT;
+ rs->array[i].Stride = 0;
+ rs->array[i].StrideB = 0;
+ rs->array[i].Ptr = (GLubyte *) ctx->Current.Attrib[i];
+ rs->array[i].Enabled = GL_TRUE;
+ rs->array[i].Normalized = GL_TRUE;
+ rs->array[i].BufferObj = NULL;
+ rs->arrays[i] = &rs->array[i];
+ }
+
+ rs->prim.mode = GL_POINTS;
+ rs->prim.indexed = 0;
+ rs->prim.begin = 1;
+ rs->prim.end = 1;
+ rs->prim.weak = 0;
+ rs->prim.start = 0;
+ rs->prim.count = 1;
+
+ return rs;
+}
+
+
+static void
+st_RasterPos(GLcontext *ctx, const GLfloat v[4])
+{
+ struct st_context *st = ctx->st;
+ struct draw_context *draw = st->draw;
+ struct rastpos_stage *rs;
+
+ if (st->rastpos_stage) {
+ /* get rastpos stage info */
+ rs = rastpos_stage(st->rastpos_stage);
+ }
+ else {
+ /* create rastpos draw stage */
+ rs = new_draw_rastpos_stage(ctx, draw);
+ st->rastpos_stage = &rs->stage;
+ }
+
+ /* plug our rastpos stage into the draw module */
+ draw_set_rasterize_stage(st->draw, st->rastpos_stage);
+
+ /* make sure everything's up to date */
+ st_validate_state(ctx->st);
+
+ /* This will get set only if rastpos_point(), above, gets called */
+ ctx->Current.RasterPosValid = GL_FALSE;
+
+ /* All vertex attribs but position were previously initialized above.
+ * Just plug in position pointer now.
+ */
+ rs->array[0].Ptr = (GLubyte *) v;
+
+ /* draw the point */
+ st_feedback_draw_vbo(ctx, rs->arrays, &rs->prim, 1, NULL, 0, 1);
+}
+
+
+
+void st_init_rasterpos_functions(struct dd_function_table *functions)
+{
+ functions->RasterPos = st_RasterPos;
+}
diff --git a/src/mesa/state_tracker/st_cb_rasterpos.h b/src/mesa/state_tracker/st_cb_rasterpos.h
new file mode 100644
index 00000000000..2b992e1405e
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_rasterpos.h
@@ -0,0 +1,33 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+#ifndef ST_CB_RASTERPOS_H
+#define ST_CB_RASTERPOS_H
+
+extern void st_init_rasterpos_functions(struct dd_function_table *functions);
+
+#endif
diff --git a/src/mesa/state_tracker/st_cb_readpixels.c b/src/mesa/state_tracker/st_cb_readpixels.c
new file mode 100644
index 00000000000..646eaff1903
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_readpixels.c
@@ -0,0 +1,464 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+
+/**
+ * glReadPixels interface to pipe
+ *
+ * \author Brian Paul
+ */
+
+
+#include "main/imports.h"
+#include "main/bufferobj.h"
+#include "main/context.h"
+#include "main/image.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "util/u_tile.h"
+#include "st_context.h"
+#include "st_cb_bitmap.h"
+#include "st_cb_readpixels.h"
+#include "st_cb_fbo.h"
+#include "st_format.h"
+#include "st_public.h"
+
+
+/**
+ * Special case for reading stencil buffer.
+ * For color/depth we use get_tile(). For stencil, map the stencil buffer.
+ */
+void
+st_read_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
+ GLsizei width, GLsizei height, GLenum type,
+ const struct gl_pixelstore_attrib *packing,
+ GLvoid *pixels)
+{
+ struct gl_framebuffer *fb = ctx->ReadBuffer;
+ struct pipe_screen *screen = ctx->st->pipe->screen;
+ struct st_renderbuffer *strb = st_renderbuffer(fb->_StencilBuffer);
+ struct pipe_surface *ps;
+ ubyte *stmap;
+ GLint j;
+
+ /* Create a CPU-READ surface/view into the renderbuffer's texture */
+ ps = screen->get_tex_surface(screen, strb->texture, 0, 0, 0,
+ PIPE_BUFFER_USAGE_CPU_READ);
+
+ /* map the stencil buffer */
+ stmap = screen->surface_map(screen, ps, PIPE_BUFFER_USAGE_CPU_READ);
+
+ /* width should never be > MAX_WIDTH since we did clipping earlier */
+ ASSERT(width <= MAX_WIDTH);
+
+ /* process image row by row */
+ for (j = 0; j < height; j++, y++) {
+ GLvoid *dest;
+ GLstencil values[MAX_WIDTH];
+ GLint srcY;
+
+ if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
+ srcY = ctx->DrawBuffer->Height - y - 1;
+ }
+ else {
+ srcY = y;
+ }
+
+ /* get stencil values */
+ switch (ps->format) {
+ case PIPE_FORMAT_S8_UNORM:
+ {
+ const ubyte *src = stmap + srcY * ps->stride + x;
+ memcpy(values, src, width);
+ }
+ break;
+ case PIPE_FORMAT_S8Z24_UNORM:
+ {
+ const uint *src = (uint *) (stmap + srcY * ps->stride + x*4);
+ GLint k;
+ for (k = 0; k < width; k++) {
+ values[k] = src[k] >> 24;
+ }
+ }
+ break;
+ case PIPE_FORMAT_Z24S8_UNORM:
+ {
+ const uint *src = (uint *) (stmap + srcY * ps->stride + x*4);
+ GLint k;
+ for (k = 0; k < width; k++) {
+ values[k] = src[k] & 0xff;
+ }
+ }
+ break;
+ default:
+ assert(0);
+ }
+
+ /* store */
+ dest = _mesa_image_address2d(packing, pixels, width, height,
+ GL_STENCIL_INDEX, type, j, 0);
+
+ _mesa_pack_stencil_span(ctx, width, type, dest, values, packing);
+ }
+
+
+ /* unmap the stencil buffer */
+ screen->surface_unmap(screen, ps);
+ pipe_surface_reference(&ps, NULL);
+}
+
+
+/**
+ * Return renderbuffer to use for reading color pixels for glRead/CopyPixel
+ * commands.
+ * Special care is needed for the front buffer.
+ */
+struct st_renderbuffer *
+st_get_color_read_renderbuffer(GLcontext *ctx)
+{
+ struct gl_framebuffer *fb = ctx->ReadBuffer;
+ struct st_renderbuffer *strb =
+ st_renderbuffer(fb->_ColorReadBuffer);
+ struct st_renderbuffer *front =
+ st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
+
+ if (strb == front
+ && ctx->st->frontbuffer_status == FRONT_STATUS_COPY_OF_BACK) {
+ /* reading from front color buffer, which is a logical copy of the
+ * back color buffer.
+ */
+ struct st_renderbuffer *back =
+ st_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
+ strb = back;
+ }
+
+ return strb;
+}
+
+
+/**
+ * Try to do glReadPixels in a fast manner for common cases.
+ * \return GL_TRUE for success, GL_FALSE for failure
+ */
+static GLboolean
+st_fast_readpixels(GLcontext *ctx, struct st_renderbuffer *strb,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *pack,
+ GLvoid *dest)
+{
+ enum combination {
+ A8R8G8B8_UNORM_TO_RGBA_UBYTE,
+ A8R8G8B8_UNORM_TO_RGB_UBYTE,
+ A8R8G8B8_UNORM_TO_BGRA_UINT
+ } combo;
+
+ if (ctx->_ImageTransferState)
+ return GL_FALSE;
+
+ if (strb->format == PIPE_FORMAT_A8R8G8B8_UNORM &&
+ format == GL_RGBA && type == GL_UNSIGNED_BYTE) {
+ combo = A8R8G8B8_UNORM_TO_RGBA_UBYTE;
+ }
+ else if (strb->format == PIPE_FORMAT_A8R8G8B8_UNORM &&
+ format == GL_RGB && type == GL_UNSIGNED_BYTE) {
+ combo = A8R8G8B8_UNORM_TO_RGB_UBYTE;
+ }
+ else if (strb->format == PIPE_FORMAT_A8R8G8B8_UNORM &&
+ format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8_REV) {
+ combo = A8R8G8B8_UNORM_TO_BGRA_UINT;
+ }
+ else {
+ return GL_FALSE;
+ }
+
+ /*printf("st_fast_readpixels combo %d\n", (GLint) combo);*/
+
+ {
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_surface *surf;
+ const GLubyte *map;
+ GLubyte *dst;
+ GLint row, col, dy, dstStride;
+
+ surf = screen->get_tex_surface(screen, strb->texture, 0, 0, 0,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ if (!surf) {
+ return GL_FALSE;
+ }
+
+ map = screen->surface_map(screen, surf, PIPE_BUFFER_USAGE_CPU_READ);
+ if (!map) {
+ pipe_surface_reference(&surf, NULL);
+ return GL_FALSE;
+ }
+
+ if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
+ y = surf->height - y - 1;
+ dy = -1;
+ }
+ else {
+ dy = 1;
+ }
+
+ dst = _mesa_image_address2d(pack, dest, width, height,
+ format, type, 0, 0);
+ dstStride = _mesa_image_row_stride(pack, width, format, type);
+
+ switch (combo) {
+ case A8R8G8B8_UNORM_TO_RGBA_UBYTE:
+ for (row = 0; row < height; row++) {
+ const GLubyte *src = map + y * surf->stride + x * 4;
+ for (col = 0; col < width; col++) {
+ GLuint pixel = ((GLuint *) src)[col];
+ dst[col*4+0] = (pixel >> 16) & 0xff;
+ dst[col*4+1] = (pixel >> 8) & 0xff;
+ dst[col*4+2] = (pixel >> 0) & 0xff;
+ dst[col*4+3] = (pixel >> 24) & 0xff;
+ }
+ dst += dstStride;
+ y += dy;
+ }
+ break;
+ case A8R8G8B8_UNORM_TO_RGB_UBYTE:
+ for (row = 0; row < height; row++) {
+ const GLubyte *src = map + y * surf->stride + x * 4;
+ for (col = 0; col < width; col++) {
+ GLuint pixel = ((GLuint *) src)[col];
+ dst[col*3+0] = (pixel >> 16) & 0xff;
+ dst[col*3+1] = (pixel >> 8) & 0xff;
+ dst[col*3+2] = (pixel >> 0) & 0xff;
+ }
+ dst += dstStride;
+ y += dy;
+ }
+ break;
+ case A8R8G8B8_UNORM_TO_BGRA_UINT:
+ for (row = 0; row < height; row++) {
+ const GLubyte *src = map + y * surf->stride + x * 4;
+ memcpy(dst, src, 4 * width);
+ dst += dstStride;
+ y += dy;
+ }
+ break;
+ default:
+ ; /* nothing */
+ }
+
+ screen->surface_unmap(screen, surf);
+ pipe_surface_reference(&surf, NULL);
+ }
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Do glReadPixels by getting rows from the framebuffer surface with
+ * get_tile(). Convert to requested format/type with Mesa image routines.
+ * Image transfer ops are done in software too.
+ */
+static void
+st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *pack,
+ GLvoid *dest)
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ GLfloat temp[MAX_WIDTH][4];
+ const GLbitfield transferOps = ctx->_ImageTransferState;
+ GLsizei i, j;
+ GLint yStep, dfStride;
+ GLfloat *df;
+ struct st_renderbuffer *strb;
+ struct gl_pixelstore_attrib clippedPacking = *pack;
+ struct pipe_surface *surf;
+
+ assert(ctx->ReadBuffer->Width > 0);
+
+ /* XXX convolution not done yet */
+ assert((transferOps & IMAGE_CONVOLUTION_BIT) == 0);
+
+ /* Do all needed clipping here, so that we can forget about it later */
+ if (!_mesa_clip_readpixels(ctx, &x, &y, &width, &height, &clippedPacking)) {
+ /* The ReadPixels surface is totally outside the window bounds */
+ return;
+ }
+
+ dest = _mesa_map_readpix_pbo(ctx, &clippedPacking, dest);
+ if (!dest)
+ return;
+
+ /* make sure rendering has completed */
+ st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+ if (format == GL_STENCIL_INDEX) {
+ st_read_stencil_pixels(ctx, x, y, width, height, type, pack, dest);
+ return;
+ }
+ else if (format == GL_DEPTH_COMPONENT) {
+ strb = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer);
+ }
+ else {
+ /* Read color buffer */
+ strb = st_get_color_read_renderbuffer(ctx);
+ }
+
+ if (!strb)
+ return;
+
+ /* try a fast-path readpixels before anything else */
+ if (st_fast_readpixels(ctx, strb, x, y, width, height,
+ format, type, pack, dest)) {
+ /* success! */
+ _mesa_unmap_readpix_pbo(ctx, &clippedPacking);
+ return;
+ }
+
+ if (format == GL_RGBA && type == GL_FLOAT) {
+ /* write tile(row) directly into user's buffer */
+ df = (GLfloat *) _mesa_image_address2d(&clippedPacking, dest, width,
+ height, format, type, 0, 0);
+ dfStride = width * 4;
+ }
+ else {
+ /* write tile(row) into temp row buffer */
+ df = (GLfloat *) temp;
+ dfStride = 0;
+ }
+
+ /* determine bottom-to-top vs. top-to-bottom order */
+ if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
+ y = strb->Base.Height - 1 - y;
+ yStep = -1;
+ }
+ else {
+ yStep = 1;
+ }
+
+ /* Create a CPU-READ surface/view into the renderbuffer's texture */
+ surf = screen->get_tex_surface(screen, strb->texture, 0, 0, 0,
+ PIPE_BUFFER_USAGE_CPU_READ);
+
+ /*
+ * Copy pixels from pipe_surface to user memory
+ */
+ {
+ /* dest of first pixel in client memory */
+ GLubyte *dst = _mesa_image_address2d(&clippedPacking, dest, width,
+ height, format, type, 0, 0);
+ /* dest row stride */
+ const GLint dstStride = _mesa_image_row_stride(&clippedPacking, width,
+ format, type);
+
+ if (surf->format == PIPE_FORMAT_S8Z24_UNORM ||
+ surf->format == PIPE_FORMAT_X8Z24_UNORM) {
+ if (format == GL_DEPTH_COMPONENT) {
+ for (i = 0; i < height; i++) {
+ GLuint ztemp[MAX_WIDTH];
+ GLfloat zfloat[MAX_WIDTH];
+ const double scale = 1.0 / ((1 << 24) - 1);
+ pipe_get_tile_raw(surf, x, y, width, 1, ztemp, 0);
+ y += yStep;
+ for (j = 0; j < width; j++) {
+ zfloat[j] = (float) (scale * (ztemp[j] & 0xffffff));
+ }
+ _mesa_pack_depth_span(ctx, width, dst, type,
+ zfloat, &clippedPacking);
+ dst += dstStride;
+ }
+ }
+ else {
+ /* untested, but simple: */
+ assert(format == GL_DEPTH_STENCIL_EXT);
+ for (i = 0; i < height; i++) {
+ pipe_get_tile_raw(surf, x, y, width, 1, dst, 0);
+ y += yStep;
+ dst += dstStride;
+ }
+ }
+ }
+ else if (surf->format == PIPE_FORMAT_Z16_UNORM) {
+ for (i = 0; i < height; i++) {
+ GLushort ztemp[MAX_WIDTH];
+ GLfloat zfloat[MAX_WIDTH];
+ const double scale = 1.0 / 0xffff;
+ pipe_get_tile_raw(surf, x, y, width, 1, ztemp, 0);
+ y += yStep;
+ for (j = 0; j < width; j++) {
+ zfloat[j] = (float) (scale * ztemp[j]);
+ }
+ _mesa_pack_depth_span(ctx, width, dst, type,
+ zfloat, &clippedPacking);
+ dst += dstStride;
+ }
+ }
+ else if (surf->format == PIPE_FORMAT_Z32_UNORM) {
+ for (i = 0; i < height; i++) {
+ GLuint ztemp[MAX_WIDTH];
+ GLfloat zfloat[MAX_WIDTH];
+ const double scale = 1.0 / 0xffffffff;
+ pipe_get_tile_raw(surf, x, y, width, 1, ztemp, 0);
+ y += yStep;
+ for (j = 0; j < width; j++) {
+ zfloat[j] = (float) (scale * ztemp[j]);
+ }
+ _mesa_pack_depth_span(ctx, width, dst, type,
+ zfloat, &clippedPacking);
+ dst += dstStride;
+ }
+ }
+ else {
+ /* RGBA format */
+ /* Do a row at a time to flip image data vertically */
+ for (i = 0; i < height; i++) {
+ pipe_get_tile_rgba(surf, x, y, width, 1, df);
+ y += yStep;
+ df += dfStride;
+ if (!dfStride) {
+ _mesa_pack_rgba_span_float(ctx, width, temp, format, type, dst,
+ &clippedPacking, transferOps);
+ dst += dstStride;
+ }
+ }
+ }
+ }
+
+ pipe_surface_reference(&surf, NULL);
+
+ _mesa_unmap_readpix_pbo(ctx, &clippedPacking);
+}
+
+
+void st_init_readpixels_functions(struct dd_function_table *functions)
+{
+ functions->ReadPixels = st_readpixels;
+}
diff --git a/src/mesa/state_tracker/st_cb_readpixels.h b/src/mesa/state_tracker/st_cb_readpixels.h
new file mode 100644
index 00000000000..9e151be51fb
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_readpixels.h
@@ -0,0 +1,45 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_CB_READPIXELS_H
+#define ST_CB_READPIXELS_H
+
+extern struct st_renderbuffer *
+st_get_color_read_renderbuffer(GLcontext *ctx);
+
+extern void
+st_read_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
+ GLsizei width, GLsizei height, GLenum type,
+ const struct gl_pixelstore_attrib *packing,
+ GLvoid *pixels);
+
+extern void
+st_init_readpixels_functions(struct dd_function_table *functions);
+
+
+#endif /* ST_CB_READPIXELS_H */
diff --git a/src/mesa/state_tracker/st_cb_strings.c b/src/mesa/state_tracker/st_cb_strings.c
new file mode 100644
index 00000000000..2036ccafbfb
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_strings.c
@@ -0,0 +1,84 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <[email protected]>
+ * Brian Paul
+ */
+
+#include "main/glheader.h"
+#include "main/macros.h"
+#include "main/version.h"
+#include "pipe/p_context.h"
+#include "pipe/p_screen.h"
+#include "st_context.h"
+#include "st_cb_strings.h"
+
+#define ST_VERSION_STRING "0.2"
+
+static const GLubyte *
+st_get_string(GLcontext * ctx, GLenum name)
+{
+ struct st_context *st = st_context(ctx);
+ struct pipe_screen *screen = st->pipe->screen;
+
+ switch (name) {
+ case GL_VENDOR: {
+ const char *vendor = screen->get_vendor( screen );
+ const char *tungsten = "Tungsten Graphics, Inc.";
+
+ /* Tungsten Graphics, Inc. developed the state_tracker module
+ * (and much of Mesa), but the driver itself may come from elsewhere.
+ * The additional string allows "and XyzCorp" to reflect this.
+ */
+ if (vendor && strcmp(vendor, tungsten) != 0)
+ util_snprintf(st->vendor, sizeof(st->vendor),
+ "%s and %s", tungsten, vendor);
+ else
+ util_snprintf(st->vendor, sizeof(st->vendor), "%s", tungsten);
+
+ return (GLubyte *) st->vendor;
+ }
+
+ case GL_RENDERER:
+ util_snprintf(st->renderer, sizeof(st->renderer), "Gallium %s on %s",
+ ST_VERSION_STRING,
+ screen->get_name( screen ));
+
+ return (GLubyte *) st->renderer;
+
+ default:
+ return NULL;
+ }
+}
+
+
+void st_init_string_functions(struct dd_function_table *functions)
+{
+ functions->GetString = st_get_string;
+}
diff --git a/src/mesa/state_tracker/st_cb_strings.h b/src/mesa/state_tracker/st_cb_strings.h
new file mode 100644
index 00000000000..3b765aaa592
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_strings.h
@@ -0,0 +1,38 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_CB_STRINGS_H
+#define ST_CB_STRINGS_H
+
+
+extern void
+st_init_string_functions(struct dd_function_table *functions);
+
+
+#endif /* ST_CB_CLEAR_H */
+
diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c
new file mode 100644
index 00000000000..d08229b57a3
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_texture.c
@@ -0,0 +1,1551 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+#include "main/imports.h"
+#if FEATURE_convolve
+#include "main/convolve.h"
+#endif
+#include "main/enums.h"
+#include "main/image.h"
+#include "main/macros.h"
+#include "main/mipmap.h"
+#include "main/pixel.h"
+#include "main/texcompress.h"
+#include "main/texformat.h"
+#include "main/teximage.h"
+#include "main/texobj.h"
+#include "main/texstore.h"
+
+#include "state_tracker/st_context.h"
+#include "state_tracker/st_cb_fbo.h"
+#include "state_tracker/st_cb_texture.h"
+#include "state_tracker/st_format.h"
+#include "state_tracker/st_public.h"
+#include "state_tracker/st_texture.h"
+#include "state_tracker/st_gen_mipmap.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "util/u_tile.h"
+#include "util/u_blit.h"
+
+
+#define DBG if (0) printf
+
+
+static enum pipe_texture_target
+gl_target_to_pipe(GLenum target)
+{
+ switch (target) {
+ case GL_TEXTURE_1D:
+ return PIPE_TEXTURE_1D;
+
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_RECTANGLE_NV:
+ return PIPE_TEXTURE_2D;
+
+ case GL_TEXTURE_3D:
+ return PIPE_TEXTURE_3D;
+
+ case GL_TEXTURE_CUBE_MAP_ARB:
+ return PIPE_TEXTURE_CUBE;
+
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+
+/**
+ * Return nominal bytes per texel for a compressed format, 0 for non-compressed
+ * format.
+ */
+static int
+compressed_num_bytes(GLuint mesaFormat)
+{
+ switch(mesaFormat) {
+#if FEATURE_texture_fxt1
+ case MESA_FORMAT_RGB_FXT1:
+ case MESA_FORMAT_RGBA_FXT1:
+#endif
+#if FEATURE_texture_s3tc
+ case MESA_FORMAT_RGB_DXT1:
+ case MESA_FORMAT_RGBA_DXT1:
+ return 2;
+ case MESA_FORMAT_RGBA_DXT3:
+ case MESA_FORMAT_RGBA_DXT5:
+ return 4;
+#endif
+ default:
+ return 0;
+ }
+}
+
+
+/** called via ctx->Driver.NewTextureImage() */
+static struct gl_texture_image *
+st_NewTextureImage(GLcontext * ctx)
+{
+ DBG("%s\n", __FUNCTION__);
+ (void) ctx;
+ return (struct gl_texture_image *) CALLOC_STRUCT(st_texture_image);
+}
+
+
+/** called via ctx->Driver.NewTextureObject() */
+static struct gl_texture_object *
+st_NewTextureObject(GLcontext * ctx, GLuint name, GLenum target)
+{
+ struct st_texture_object *obj = CALLOC_STRUCT(st_texture_object);
+
+ DBG("%s\n", __FUNCTION__);
+ _mesa_initialize_texture_object(&obj->base, name, target);
+
+ return &obj->base;
+}
+
+/** called via ctx->Driver.DeleteTextureImage() */
+static void
+st_DeleteTextureObject(GLcontext *ctx,
+ struct gl_texture_object *texObj)
+{
+ struct st_texture_object *stObj = st_texture_object(texObj);
+ if (stObj->pt)
+ pipe_texture_reference(&stObj->pt, NULL);
+
+ _mesa_delete_texture_object(ctx, texObj);
+}
+
+
+/** called via ctx->Driver.FreeTexImageData() */
+static void
+st_FreeTextureImageData(GLcontext * ctx, struct gl_texture_image *texImage)
+{
+ struct st_texture_image *stImage = st_texture_image(texImage);
+
+ DBG("%s\n", __FUNCTION__);
+
+ if (stImage->pt) {
+ pipe_texture_reference(&stImage->pt, NULL);
+ }
+
+ if (texImage->Data) {
+ _mesa_align_free(texImage->Data);
+ texImage->Data = NULL;
+ }
+}
+
+
+/**
+ * From linux kernel i386 header files, copes with odd sizes better
+ * than COPY_DWORDS would:
+ * XXX Put this in src/mesa/main/imports.h ???
+ */
+#if defined(i386) || defined(__i386__)
+static INLINE void *
+__memcpy(void *to, const void *from, size_t n)
+{
+ int d0, d1, d2;
+ __asm__ __volatile__("rep ; movsl\n\t"
+ "testb $2,%b4\n\t"
+ "je 1f\n\t"
+ "movsw\n"
+ "1:\ttestb $1,%b4\n\t"
+ "je 2f\n\t"
+ "movsb\n" "2:":"=&c"(d0), "=&D"(d1), "=&S"(d2)
+ :"0"(n / 4), "q"(n), "1"((long) to), "2"((long) from)
+ :"memory");
+ return (to);
+}
+#else
+#define __memcpy(a,b,c) memcpy(a,b,c)
+#endif
+
+
+/**
+ * The system memcpy (at least on ubuntu 5.10) has problems copying
+ * to agp (writecombined) memory from a source which isn't 64-byte
+ * aligned - there is a 4x performance falloff.
+ *
+ * The x86 __memcpy is immune to this but is slightly slower
+ * (10%-ish) than the system memcpy.
+ *
+ * The sse_memcpy seems to have a slight cliff at 64/32 bytes, but
+ * isn't much faster than x86_memcpy for agp copies.
+ *
+ * TODO: switch dynamically.
+ */
+static void *
+do_memcpy(void *dest, const void *src, size_t n)
+{
+ if ((((unsigned) src) & 63) || (((unsigned) dest) & 63)) {
+ return __memcpy(dest, src, n);
+ }
+ else
+ return memcpy(dest, src, n);
+}
+
+
+static int
+logbase2(int n)
+{
+ GLint i = 1, log2 = 0;
+ while (n > i) {
+ i *= 2;
+ log2++;
+ }
+ return log2;
+}
+
+
+/**
+ * Allocate a pipe_texture object for the given st_texture_object using
+ * the given st_texture_image to guess the mipmap size/levels.
+ *
+ * [comments...]
+ * Otherwise, store it in memory if (Border != 0) or (any dimension ==
+ * 1).
+ *
+ * Otherwise, if max_level >= level >= min_level, create texture with
+ * space for images from min_level down to max_level.
+ *
+ * Otherwise, create texture with space for images from (level 0)..(1x1).
+ * Consider pruning this texture at a validation if the saving is worth it.
+ */
+static void
+guess_and_alloc_texture(struct st_context *st,
+ struct st_texture_object *stObj,
+ const struct st_texture_image *stImage)
+{
+ GLuint firstLevel;
+ GLuint lastLevel;
+ GLuint width = stImage->base.Width2; /* size w/out border */
+ GLuint height = stImage->base.Height2;
+ GLuint depth = stImage->base.Depth2;
+ GLuint i, comp_byte = 0;
+ enum pipe_format fmt;
+
+ DBG("%s\n", __FUNCTION__);
+
+ assert(!stObj->pt);
+
+ if (stObj->pt &&
+ (GLint) stImage->level > stObj->base.BaseLevel &&
+ (stImage->base.Width == 1 ||
+ (stObj->base.Target != GL_TEXTURE_1D &&
+ stImage->base.Height == 1) ||
+ (stObj->base.Target == GL_TEXTURE_3D &&
+ stImage->base.Depth == 1)))
+ return;
+
+ /* If this image disrespects BaseLevel, allocate from level zero.
+ * Usually BaseLevel == 0, so it's unlikely to happen.
+ */
+ if ((GLint) stImage->level < stObj->base.BaseLevel)
+ firstLevel = 0;
+ else
+ firstLevel = stObj->base.BaseLevel;
+
+
+ /* Figure out image dimensions at start level.
+ */
+ for (i = stImage->level; i > firstLevel; i--) {
+ if (width != 1)
+ width <<= 1;
+ if (height != 1)
+ height <<= 1;
+ if (depth != 1)
+ depth <<= 1;
+ }
+
+ if (width == 0 || height == 0 || depth == 0) {
+ /* no texture needed */
+ return;
+ }
+
+ /* Guess a reasonable value for lastLevel. This is probably going
+ * to be wrong fairly often and might mean that we have to look at
+ * resizable buffers, or require that buffers implement lazy
+ * pagetable arrangements.
+ */
+ if ((stObj->base.MinFilter == GL_NEAREST ||
+ stObj->base.MinFilter == GL_LINEAR) &&
+ stImage->level == firstLevel) {
+ lastLevel = firstLevel;
+ }
+ else {
+ GLuint l2width = logbase2(width);
+ GLuint l2height = logbase2(height);
+ GLuint l2depth = logbase2(depth);
+ lastLevel = firstLevel + MAX2(MAX2(l2width, l2height), l2depth);
+ }
+
+ if (stImage->base.IsCompressed)
+ comp_byte = compressed_num_bytes(stImage->base.TexFormat->MesaFormat);
+
+ fmt = st_mesa_format_to_pipe_format(stImage->base.TexFormat->MesaFormat);
+ stObj->pt = st_texture_create(st,
+ gl_target_to_pipe(stObj->base.Target),
+ fmt,
+ lastLevel,
+ width,
+ height,
+ depth,
+ comp_byte,
+ ( (pf_is_depth_stencil(fmt) ?
+ PIPE_TEXTURE_USAGE_DEPTH_STENCIL :
+ PIPE_TEXTURE_USAGE_RENDER_TARGET) |
+ PIPE_TEXTURE_USAGE_SAMPLER ));
+
+ DBG("%s - success\n", __FUNCTION__);
+}
+
+
+/**
+ * Adjust pixel unpack params and image dimensions to strip off the
+ * texture border.
+ * Gallium doesn't support texture borders. They've seldem been used
+ * and seldom been implemented correctly anyway.
+ * \param unpackNew returns the new pixel unpack parameters
+ */
+static void
+strip_texture_border(GLint border,
+ GLint *width, GLint *height, GLint *depth,
+ const struct gl_pixelstore_attrib *unpack,
+ struct gl_pixelstore_attrib *unpackNew)
+{
+ assert(border > 0); /* sanity check */
+
+ *unpackNew = *unpack;
+
+ if (unpackNew->RowLength == 0)
+ unpackNew->RowLength = *width;
+
+ if (depth && unpackNew->ImageHeight == 0)
+ unpackNew->ImageHeight = *height;
+
+ unpackNew->SkipPixels += border;
+ if (height)
+ unpackNew->SkipRows += border;
+ if (depth)
+ unpackNew->SkipImages += border;
+
+ assert(*width >= 3);
+ *width = *width - 2 * border;
+ if (height && *height >= 3)
+ *height = *height - 2 * border;
+ if (depth && *depth >= 3)
+ *depth = *depth - 2 * border;
+}
+
+
+/**
+ * Do glTexImage1/2/3D().
+ */
+static void
+st_TexImage(GLcontext * ctx,
+ GLint dims,
+ GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint height, GLint depth,
+ GLint border,
+ GLenum format, GLenum type, const void *pixels,
+ const struct gl_pixelstore_attrib *unpack,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage,
+ GLsizei imageSize, int compressed)
+{
+ struct st_texture_object *stObj = st_texture_object(texObj);
+ struct st_texture_image *stImage = st_texture_image(texImage);
+ GLint postConvWidth, postConvHeight;
+ GLint texelBytes, sizeInBytes;
+ GLuint dstRowStride;
+ struct gl_pixelstore_attrib unpackNB;
+
+ DBG("%s target %s level %d %dx%dx%d border %d\n", __FUNCTION__,
+ _mesa_lookup_enum_by_nr(target), level, width, height, depth, border);
+
+ /* gallium does not support texture borders, strip it off */
+ if (border) {
+ strip_texture_border(border, &width, &height, &depth,
+ unpack, &unpackNB);
+ unpack = &unpackNB;
+ texImage->Width = width;
+ texImage->Height = height;
+ texImage->Depth = depth;
+ texImage->Border = 0;
+ border = 0;
+ }
+
+ postConvWidth = width;
+ postConvHeight = height;
+
+ stImage->face = _mesa_tex_target_to_face(target);
+ stImage->level = level;
+
+#if FEATURE_convolve
+ if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
+ _mesa_adjust_image_for_convolution(ctx, dims, &postConvWidth,
+ &postConvHeight);
+ }
+#endif
+
+ /* choose the texture format */
+ texImage->TexFormat = st_ChooseTextureFormat(ctx, internalFormat,
+ format, type);
+
+ _mesa_set_fetch_functions(texImage, dims);
+
+ if (texImage->TexFormat->TexelBytes == 0) {
+ /* must be a compressed format */
+ texelBytes = 0;
+ texImage->IsCompressed = GL_TRUE;
+ texImage->CompressedSize =
+ ctx->Driver.CompressedTextureSize(ctx, texImage->Width,
+ texImage->Height, texImage->Depth,
+ texImage->TexFormat->MesaFormat);
+ }
+ else {
+ texelBytes = texImage->TexFormat->TexelBytes;
+
+ /* Minimum pitch of 32 bytes */
+ if (postConvWidth * texelBytes < 32) {
+ postConvWidth = 32 / texelBytes;
+ texImage->RowStride = postConvWidth;
+ }
+
+ /* we'll set RowStride elsewhere when the texture is a "mapped" state */
+ /*assert(texImage->RowStride == postConvWidth);*/
+ }
+
+ /* Release the reference to a potentially orphaned buffer.
+ * Release any old malloced memory.
+ */
+ if (stImage->pt) {
+ pipe_texture_reference(&stImage->pt, NULL);
+ assert(!texImage->Data);
+ }
+ else if (texImage->Data) {
+ _mesa_align_free(texImage->Data);
+ }
+
+ if (width == 0 || height == 0 || depth == 0) {
+ /* stop after freeing old image */
+ return;
+ }
+
+ /* If this is the only mipmap level in the texture, could call
+ * bmBufferData with NULL data to free the old block and avoid
+ * waiting on any outstanding fences.
+ */
+ if (stObj->pt &&
+ (stObj->teximage_realloc ||
+ (/*stObj->pt->first_level == level &&*/
+ stObj->pt->last_level == level &&
+ stObj->pt->target != PIPE_TEXTURE_CUBE &&
+ !st_texture_match_image(stObj->pt, &stImage->base,
+ stImage->face, stImage->level)))) {
+
+ DBG("release it\n");
+ pipe_texture_reference(&stObj->pt, NULL);
+ assert(!stObj->pt);
+ stObj->teximage_realloc = FALSE;
+ }
+
+ if (!stObj->pt) {
+ guess_and_alloc_texture(ctx->st, stObj, stImage);
+ if (!stObj->pt) {
+ /* Probably out of memory.
+ * Try flushing any pending rendering, then retry.
+ */
+ st_finish(ctx->st);
+ guess_and_alloc_texture(ctx->st, stObj, stImage);
+ if (!stObj->pt) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
+ return;
+ }
+ }
+ }
+
+ assert(!stImage->pt);
+
+ if (stObj->pt &&
+ st_texture_match_image(stObj->pt, &stImage->base,
+ stImage->face, stImage->level)) {
+
+ pipe_texture_reference(&stImage->pt, stObj->pt);
+ assert(stImage->pt);
+ }
+
+ if (!stImage->pt)
+ DBG("XXX: Image did not fit into texture - storing in local memory!\n");
+
+ /* st_CopyTexImage calls this function with pixels == NULL, with
+ * the expectation that the texture will be set up but nothing
+ * more will be done. This is where those calls return:
+ */
+ if (compressed) {
+ pixels = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, pixels,
+ unpack,
+ "glCompressedTexImage");
+ } else {
+ pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, 1,
+ format, type,
+ pixels, unpack, "glTexImage");
+ }
+ if (!pixels)
+ return;
+
+ if (stImage->pt) {
+ texImage->Data = st_texture_image_map(ctx->st, stImage, 0,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+ if (stImage->surface)
+ dstRowStride = stImage->surface->stride;
+ }
+ else {
+ /* Allocate regular memory and store the image there temporarily. */
+ if (texImage->IsCompressed) {
+ sizeInBytes = texImage->CompressedSize;
+ dstRowStride =
+ _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, width);
+ assert(dims != 3);
+ }
+ else {
+ dstRowStride = postConvWidth * texelBytes;
+ sizeInBytes = depth * dstRowStride * postConvHeight;
+ }
+
+ texImage->Data = _mesa_align_malloc(sizeInBytes, 16);
+ }
+
+ if (!texImage->Data) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
+ return;
+ }
+
+ DBG("Upload image %dx%dx%d row_len %x pitch %x\n",
+ width, height, depth, width * texelBytes, dstRowStride);
+
+ /* Copy data. Would like to know when it's ok for us to eg. use
+ * the blitter to copy. Or, use the hardware to do the format
+ * conversion and copy:
+ */
+ if (compressed) {
+ memcpy(texImage->Data, pixels, imageSize);
+ }
+ else {
+ GLuint srcImageStride = _mesa_image_image_stride(unpack, width, height,
+ format, type);
+ int i;
+ const GLubyte *src = (const GLubyte *) pixels;
+
+ for (i = 0; i++ < depth;) {
+ if (!texImage->TexFormat->StoreImage(ctx, dims,
+ texImage->_BaseFormat,
+ texImage->TexFormat,
+ texImage->Data,
+ 0, 0, 0, /* dstX/Y/Zoffset */
+ dstRowStride,
+ texImage->ImageOffsets,
+ width, height, 1,
+ format, type, src, unpack)) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
+ }
+
+ if (stImage->pt && i < depth) {
+ st_texture_image_unmap(ctx->st, stImage);
+ texImage->Data = st_texture_image_map(ctx->st, stImage, i,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+ src += srcImageStride;
+ }
+ }
+ }
+
+ _mesa_unmap_teximage_pbo(ctx, unpack);
+
+ if (stImage->pt) {
+ st_texture_image_unmap(ctx->st, stImage);
+ texImage->Data = NULL;
+ }
+
+ if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+ ctx->Driver.GenerateMipmap(ctx, target, texObj);
+ }
+}
+
+
+static void
+st_TexImage3D(GLcontext * ctx,
+ GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint height, GLint depth,
+ GLint border,
+ GLenum format, GLenum type, const void *pixels,
+ const struct gl_pixelstore_attrib *unpack,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ st_TexImage(ctx, 3, target, level,
+ internalFormat, width, height, depth, border,
+ format, type, pixels, unpack, texObj, texImage, 0, 0);
+}
+
+
+static void
+st_TexImage2D(GLcontext * ctx,
+ GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint height, GLint border,
+ GLenum format, GLenum type, const void *pixels,
+ const struct gl_pixelstore_attrib *unpack,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ st_TexImage(ctx, 2, target, level,
+ internalFormat, width, height, 1, border,
+ format, type, pixels, unpack, texObj, texImage, 0, 0);
+}
+
+
+static void
+st_TexImage1D(GLcontext * ctx,
+ GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint border,
+ GLenum format, GLenum type, const void *pixels,
+ const struct gl_pixelstore_attrib *unpack,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ st_TexImage(ctx, 1, target, level,
+ internalFormat, width, 1, 1, border,
+ format, type, pixels, unpack, texObj, texImage, 0, 0);
+}
+
+
+static void
+st_CompressedTexImage2D(GLcontext *ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint height, GLint border,
+ GLsizei imageSize, const GLvoid *data,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ st_TexImage(ctx, 2, target, level,
+ internalFormat, width, height, 1, border,
+ 0, 0, data, &ctx->Unpack, texObj, texImage, imageSize, 1);
+}
+
+
+/**
+ * Need to map texture image into memory before copying image data,
+ * then unmap it.
+ */
+static void
+st_get_tex_image(GLcontext * ctx, GLenum target, GLint level,
+ GLenum format, GLenum type, GLvoid * pixels,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage, int compressed)
+{
+ struct st_texture_image *stImage = st_texture_image(texImage);
+ GLuint dstImageStride = _mesa_image_image_stride(&ctx->Pack,
+ texImage->Width,
+ texImage->Height,
+ format, type);
+ GLuint depth;
+ GLuint i;
+ GLubyte *dest;
+
+ /* Map */
+ if (stImage->pt) {
+ /* Image is stored in hardware format in a buffer managed by the
+ * kernel. Need to explicitly map and unmap it.
+ */
+ texImage->Data = st_texture_image_map(ctx->st, stImage, 0,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ texImage->RowStride = stImage->surface->stride / stImage->pt->block.size;
+ }
+ else {
+ /* Otherwise, the image should actually be stored in
+ * texImage->Data. This is pretty confusing for
+ * everybody, I'd much prefer to separate the two functions of
+ * texImage->Data - storage for texture images in main memory
+ * and access (ie mappings) of images. In other words, we'd
+ * create a new texImage->Map field and leave Data simply for
+ * storage.
+ */
+ assert(texImage->Data);
+ }
+
+ depth = texImage->Depth;
+ texImage->Depth = 1;
+
+ dest = (GLubyte *) pixels;
+
+ for (i = 0; i++ < depth;) {
+ if (compressed) {
+ _mesa_get_compressed_teximage(ctx, target, level, dest,
+ texObj, texImage);
+ } else {
+ _mesa_get_teximage(ctx, target, level, format, type, dest,
+ texObj, texImage);
+ }
+
+ if (stImage->pt && i < depth) {
+ st_texture_image_unmap(ctx->st, stImage);
+ texImage->Data = st_texture_image_map(ctx->st, stImage, i,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ dest += dstImageStride;
+ }
+ }
+
+ texImage->Depth = depth;
+
+ /* Unmap */
+ if (stImage->pt) {
+ st_texture_image_unmap(ctx->st, stImage);
+ texImage->Data = NULL;
+ }
+}
+
+
+static void
+st_GetTexImage(GLcontext * ctx, GLenum target, GLint level,
+ GLenum format, GLenum type, GLvoid * pixels,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ st_get_tex_image(ctx, target, level, format, type, pixels,
+ texObj, texImage, 0);
+}
+
+
+static void
+st_GetCompressedTexImage(GLcontext *ctx, GLenum target, GLint level,
+ GLvoid *pixels,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ st_get_tex_image(ctx, target, level, 0, 0, pixels,
+ (struct gl_texture_object *) texObj,
+ (struct gl_texture_image *) texImage, 1);
+}
+
+
+
+static void
+st_TexSubimage(GLcontext * ctx,
+ GLint dims,
+ GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLint width, GLint height, GLint depth,
+ GLenum format, GLenum type, const void *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ struct st_texture_image *stImage = st_texture_image(texImage);
+ GLuint dstRowStride;
+ GLuint srcImageStride = _mesa_image_image_stride(packing, width, height,
+ format, type);
+ int i;
+ const GLubyte *src;
+
+ DBG("%s target %s level %d offset %d,%d %dx%d\n", __FUNCTION__,
+ _mesa_lookup_enum_by_nr(target),
+ level, xoffset, yoffset, width, height);
+
+ pixels =
+ _mesa_validate_pbo_teximage(ctx, dims, width, height, depth, format,
+ type, pixels, packing, "glTexSubImage2D");
+ if (!pixels)
+ return;
+
+ /* Map buffer if necessary. Need to lock to prevent other contexts
+ * from uploading the buffer under us.
+ */
+ if (stImage->pt) {
+ texImage->Data = st_texture_image_map(ctx->st, stImage, zoffset,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+ if (stImage->surface)
+ dstRowStride = stImage->surface->stride;
+ }
+
+ if (!texImage->Data) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage");
+ return;
+ }
+
+ src = (const GLubyte *) pixels;
+
+ for (i = 0; i++ < depth;) {
+ if (!texImage->TexFormat->StoreImage(ctx, dims, texImage->_BaseFormat,
+ texImage->TexFormat,
+ texImage->Data,
+ xoffset, yoffset, 0,
+ dstRowStride,
+ texImage->ImageOffsets,
+ width, height, 1,
+ format, type, src, packing)) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage");
+ }
+
+ if (stImage->pt && i < depth) {
+ /* map next slice of 3D texture */
+ st_texture_image_unmap(ctx->st, stImage);
+ texImage->Data = st_texture_image_map(ctx->st, stImage, zoffset + i,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+ src += srcImageStride;
+ }
+ }
+
+ if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+ ctx->Driver.GenerateMipmap(ctx, target, texObj);
+ }
+
+ _mesa_unmap_teximage_pbo(ctx, packing);
+
+ if (stImage->pt) {
+ st_texture_image_unmap(ctx->st, stImage);
+ texImage->Data = NULL;
+ }
+}
+
+
+
+static void
+st_TexSubImage3D(GLcontext * ctx,
+ GLenum target,
+ GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type,
+ const GLvoid * pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ st_TexSubimage(ctx, 3, target, level,
+ xoffset, yoffset, zoffset,
+ width, height, depth,
+ format, type, pixels, packing, texObj, texImage);
+}
+
+
+static void
+st_TexSubImage2D(GLcontext * ctx,
+ GLenum target,
+ GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const GLvoid * pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ st_TexSubimage(ctx, 2, target, level,
+ xoffset, yoffset, 0,
+ width, height, 1,
+ format, type, pixels, packing, texObj, texImage);
+}
+
+
+static void
+st_TexSubImage1D(GLcontext * ctx,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLsizei width,
+ GLenum format, GLenum type,
+ const GLvoid * pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ st_TexSubimage(ctx, 1, target, level,
+ xoffset, 0, 0,
+ width, 1, 1,
+ format, type, pixels, packing, texObj, texImage);
+}
+
+
+
+/**
+ * Return 0 for GL_TEXTURE_CUBE_MAP_POSITIVE_X,
+ * 1 for GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
+ * etc.
+ * XXX duplicated from main/teximage.c
+ */
+static uint
+texture_face(GLenum target)
+{
+ if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
+ target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)
+ return (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
+ else
+ return 0;
+}
+
+
+
+/**
+ * Do a CopyTexSubImage operation by mapping the source surface and
+ * dest surface and using get_tile()/put_tile() to access the pixels/texels.
+ *
+ * Note: srcY=0=TOP of renderbuffer
+ */
+static void
+fallback_copy_texsubimage(GLcontext *ctx,
+ GLenum target,
+ GLint level,
+ struct st_renderbuffer *strb,
+ struct st_texture_image *stImage,
+ GLenum baseFormat,
+ GLint destX, GLint destY, GLint destZ,
+ GLint srcX, GLint srcY,
+ GLsizei width, GLsizei height)
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ const uint face = texture_face(target);
+ struct pipe_texture *pt = stImage->pt;
+ struct pipe_surface *src_surf, *dest_surf;
+
+ /* We'd use strb->surface, here but it's created for GPU read/write only */
+ src_surf = pipe->screen->get_tex_surface( pipe->screen,
+ strb->texture,
+ 0, 0, 0,
+ PIPE_BUFFER_USAGE_CPU_READ);
+
+ dest_surf = screen->get_tex_surface(screen, pt, face, level, destZ,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+
+ assert(width <= MAX_WIDTH);
+
+ if (baseFormat == GL_DEPTH_COMPONENT) {
+ const GLboolean scaleOrBias = (ctx->Pixel.DepthScale != 1.0F ||
+ ctx->Pixel.DepthBias != 0.0F);
+ GLint row, yStep;
+
+ /* determine bottom-to-top vs. top-to-bottom order for src buffer */
+ if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
+ srcY = strb->Base.Height - 1 - srcY;
+ yStep = -1;
+ }
+ else {
+ yStep = 1;
+ }
+
+ /* To avoid a large temp memory allocation, do copy row by row */
+ for (row = 0; row < height; row++, srcY += yStep, destY++) {
+ uint data[MAX_WIDTH];
+ pipe_get_tile_z(src_surf, srcX, srcY, width, 1, data);
+ if (scaleOrBias) {
+ _mesa_scale_and_bias_depth_uint(ctx, width, data);
+ }
+ pipe_put_tile_z(dest_surf, destX, destY, width, 1, data);
+ }
+ }
+ else {
+ /* RGBA format */
+ GLfloat *tempSrc =
+ (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));
+ GLvoid *texDest =
+ st_texture_image_map(ctx->st, stImage, 0,PIPE_BUFFER_USAGE_CPU_WRITE);
+
+ if (tempSrc && texDest) {
+ const GLint dims = 2;
+ struct gl_texture_image *texImage = &stImage->base;
+ GLint dstRowStride = stImage->surface->stride;
+ struct gl_pixelstore_attrib unpack = ctx->DefaultPacking;
+
+ if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
+ /* need to invert src */
+ srcY = strb->Base.Height - srcY - height;
+ unpack.Invert = GL_TRUE;
+ }
+
+ /* get float/RGBA image from framebuffer */
+ /* XXX this usually involves a lot of int/float conversion.
+ * try to avoid that someday.
+ */
+ pipe_get_tile_rgba(src_surf, srcX, srcY, width, height, tempSrc);
+
+ /* Store into texture memory.
+ * Note that this does some special things such as pixel transfer
+ * ops and format conversion. In particular, if the dest tex format
+ * is actually RGBA but the user created the texture as GL_RGB we
+ * need to fill-in/override the alpha channel with 1.0.
+ */
+ texImage->TexFormat->StoreImage(ctx, dims,
+ texImage->_BaseFormat,
+ texImage->TexFormat,
+ texDest,
+ destX, destY, destZ,
+ dstRowStride,
+ texImage->ImageOffsets,
+ width, height, 1,
+ GL_RGBA, GL_FLOAT, tempSrc, /* src */
+ &unpack);
+ }
+ else {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage");
+ }
+
+ if (tempSrc)
+ _mesa_free(tempSrc);
+ if (texDest)
+ st_texture_image_unmap(ctx->st, stImage);
+ }
+
+ screen->tex_surface_release(screen, &dest_surf);
+ screen->tex_surface_release(screen, &src_surf);
+}
+
+
+/**
+ * Do a CopyTex[Sub]Image1/2/3D() using a hardware (blit) path if possible.
+ * Note that the region to copy has already been clipped so we know we
+ * won't read from outside the source renderbuffer's bounds.
+ *
+ * Note: srcY=0=Bottom of renderbuffer (GL convention)
+ */
+static void
+st_copy_texsubimage(GLcontext *ctx,
+ GLenum target, GLint level,
+ GLint destX, GLint destY, GLint destZ,
+ GLint srcX, GLint srcY,
+ GLsizei width, GLsizei height)
+{
+ struct gl_texture_unit *texUnit =
+ &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ struct gl_texture_object *texObj =
+ _mesa_select_tex_object(ctx, texUnit, target);
+ struct gl_texture_image *texImage =
+ _mesa_select_tex_image(ctx, texObj, target, level);
+ struct st_texture_image *stImage = st_texture_image(texImage);
+ const GLenum texBaseFormat = texImage->InternalFormat;
+ struct gl_framebuffer *fb = ctx->ReadBuffer;
+ struct st_renderbuffer *strb;
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ enum pipe_format dest_format, src_format;
+ GLboolean use_fallback = GL_TRUE;
+ GLboolean matching_base_formats;
+
+ /* any rendering in progress must complete before we grab the fb image */
+ st_finish(ctx->st);
+
+ /* determine if copying depth or color data */
+ if (texBaseFormat == GL_DEPTH_COMPONENT) {
+ strb = st_renderbuffer(fb->_DepthBuffer);
+ }
+ else if (texBaseFormat == GL_DEPTH_STENCIL_EXT) {
+ strb = st_renderbuffer(fb->_StencilBuffer);
+ }
+ else {
+ /* texBaseFormat == GL_RGB, GL_RGBA, GL_ALPHA, etc */
+ strb = st_renderbuffer(fb->_ColorReadBuffer);
+ }
+
+ assert(strb);
+ assert(strb->surface);
+ assert(stImage->pt);
+
+ src_format = strb->surface->format;
+ dest_format = stImage->pt->format;
+
+ /*
+ * Determine if the src framebuffer and dest texture have the same
+ * base format. We need this to detect a case such as the framebuffer
+ * being GL_RGBA but the texture being GL_RGB. If the actual hardware
+ * texture format stores RGBA we need to set A=1 (overriding the
+ * framebuffer's alpha values). We can't do that with the blit or
+ * textured-quad paths.
+ */
+ matching_base_formats = (strb->Base._BaseFormat == texImage->_BaseFormat);
+
+ if (matching_base_formats && ctx->_ImageTransferState == 0x0) {
+ /* try potential hardware path */
+ struct pipe_surface *dest_surface = NULL;
+
+ if (src_format == dest_format) {
+ /* use surface_copy() / blit */
+ boolean do_flip = (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP);
+
+ dest_surface = screen->get_tex_surface(screen, stImage->pt,
+ stImage->face, stImage->level,
+ destZ,
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+ if (do_flip)
+ srcY = strb->surface->height - srcY - height;
+
+ /* for surface_copy(), y=0=top, always */
+ pipe->surface_copy(pipe,
+ do_flip,
+ /* dest */
+ dest_surface,
+ destX, destY,
+ /* src */
+ strb->surface,
+ srcX, srcY,
+ /* size */
+ width, height);
+ use_fallback = GL_FALSE;
+ }
+ else if (screen->is_format_supported(screen, src_format,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_SAMPLER,
+ 0) &&
+ screen->is_format_supported(screen, dest_format,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_RENDER_TARGET,
+ 0)) {
+ /* draw textured quad to do the copy */
+ boolean do_flip = (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP);
+ int srcY0, srcY1;
+
+ dest_surface = screen->get_tex_surface(screen, stImage->pt,
+ stImage->face, stImage->level,
+ destZ,
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+
+ if (do_flip) {
+ srcY1 = strb->Base.Height - srcY - height;
+ srcY0 = srcY1 + height;
+ }
+ else {
+ srcY0 = srcY;
+ srcY1 = srcY0 + height;
+ }
+ util_blit_pixels(ctx->st->blit,
+ strb->surface,
+ srcX, srcY0,
+ srcX + width, srcY1,
+ dest_surface,
+ destX, destY,
+ destX + width, destY + height,
+ 0.0, PIPE_TEX_MIPFILTER_NEAREST);
+ use_fallback = GL_FALSE;
+ }
+
+ if (dest_surface)
+ pipe_surface_reference(&dest_surface, NULL);
+ }
+
+ if (use_fallback) {
+ /* software fallback */
+ fallback_copy_texsubimage(ctx, target, level,
+ strb, stImage, texBaseFormat,
+ destX, destY, destZ,
+ srcX, srcY, width, height);
+ }
+
+ if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+ ctx->Driver.GenerateMipmap(ctx, target, texObj);
+ }
+}
+
+
+
+static void
+st_CopyTexImage1D(GLcontext * ctx, GLenum target, GLint level,
+ GLenum internalFormat,
+ GLint x, GLint y, GLsizei width, GLint border)
+{
+ struct gl_texture_unit *texUnit =
+ &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ struct gl_texture_object *texObj =
+ _mesa_select_tex_object(ctx, texUnit, target);
+ struct gl_texture_image *texImage =
+ _mesa_select_tex_image(ctx, texObj, target, level);
+
+#if 0
+ if (border)
+ goto fail;
+#endif
+
+ /* Setup or redefine the texture object, texture and texture
+ * image. Don't populate yet.
+ */
+ ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
+ width, border,
+ GL_RGBA, CHAN_TYPE, NULL,
+ &ctx->DefaultPacking, texObj, texImage);
+
+ st_copy_texsubimage(ctx, target, level,
+ 0, 0, 0, /* destX,Y,Z */
+ x, y, width, 1); /* src X, Y, size */
+}
+
+
+static void
+st_CopyTexImage2D(GLcontext * ctx, GLenum target, GLint level,
+ GLenum internalFormat,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLint border)
+{
+ struct gl_texture_unit *texUnit =
+ &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ struct gl_texture_object *texObj =
+ _mesa_select_tex_object(ctx, texUnit, target);
+ struct gl_texture_image *texImage =
+ _mesa_select_tex_image(ctx, texObj, target, level);
+
+ /* Setup or redefine the texture object, texture and texture
+ * image. Don't populate yet.
+ */
+ ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
+ width, height, border,
+ GL_RGBA, CHAN_TYPE, NULL,
+ &ctx->DefaultPacking, texObj, texImage);
+
+ st_copy_texsubimage(ctx, target, level,
+ 0, 0, 0, /* destX,Y,Z */
+ x, y, width, height); /* src X, Y, size */
+}
+
+
+static void
+st_CopyTexSubImage1D(GLcontext * ctx, GLenum target, GLint level,
+ GLint xoffset, GLint x, GLint y, GLsizei width)
+{
+ const GLint yoffset = 0, zoffset = 0;
+ const GLsizei height = 1;
+ st_copy_texsubimage(ctx, target, level,
+ xoffset, yoffset, zoffset, /* destX,Y,Z */
+ x, y, width, height); /* src X, Y, size */
+}
+
+
+static void
+st_CopyTexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ const GLint zoffset = 0;
+ st_copy_texsubimage(ctx, target, level,
+ xoffset, yoffset, zoffset, /* destX,Y,Z */
+ x, y, width, height); /* src X, Y, size */
+}
+
+
+static void
+st_CopyTexSubImage3D(GLcontext * ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ st_copy_texsubimage(ctx, target, level,
+ xoffset, yoffset, zoffset, /* destX,Y,Z */
+ x, y, width, height); /* src X, Y, size */
+}
+
+
+/**
+ * Compute which mipmap levels that really need to be sent to the hardware.
+ * This depends on the base image size, GL_TEXTURE_MIN_LOD,
+ * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
+ */
+static void
+calculate_first_last_level(struct st_texture_object *stObj)
+{
+ struct gl_texture_object *tObj = &stObj->base;
+
+ /* These must be signed values. MinLod and MaxLod can be negative numbers,
+ * and having firstLevel and lastLevel as signed prevents the need for
+ * extra sign checks.
+ */
+ int firstLevel;
+ int lastLevel;
+
+ /* Yes, this looks overly complicated, but it's all needed.
+ */
+ switch (tObj->Target) {
+ case GL_TEXTURE_1D:
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_3D:
+ case GL_TEXTURE_CUBE_MAP:
+ if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) {
+ /* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL.
+ */
+ firstLevel = lastLevel = tObj->BaseLevel;
+ }
+ else {
+ firstLevel = 0;
+ lastLevel = MIN2(tObj->MaxLevel,
+ (int) tObj->Image[0][tObj->BaseLevel]->WidthLog2);
+ }
+ break;
+ case GL_TEXTURE_RECTANGLE_NV:
+ case GL_TEXTURE_4D_SGIS:
+ firstLevel = lastLevel = 0;
+ break;
+ default:
+ return;
+ }
+
+ stObj->lastLevel = lastLevel;
+}
+
+
+static void
+copy_image_data_to_texture(struct st_context *st,
+ struct st_texture_object *stObj,
+ GLuint dstLevel,
+ struct st_texture_image *stImage)
+{
+ if (stImage->pt) {
+ /* Copy potentially with the blitter:
+ */
+ st_texture_image_copy(st->pipe,
+ stObj->pt, dstLevel, /* dest texture, level */
+ stImage->pt, /* src texture */
+ stImage->face
+ );
+
+ pipe_texture_reference(&stImage->pt, NULL);
+ }
+ else if (stImage->base.Data) {
+ assert(stImage->base.Data != NULL);
+
+ /* More straightforward upload.
+ */
+ st_texture_image_data(st->pipe,
+ stObj->pt,
+ stImage->face,
+ dstLevel,
+ stImage->base.Data,
+ stImage->base.RowStride *
+ stObj->pt->block.size,
+ stImage->base.RowStride *
+ stImage->base.Height *
+ stObj->pt->block.size);
+ _mesa_align_free(stImage->base.Data);
+ stImage->base.Data = NULL;
+ }
+
+ pipe_texture_reference(&stImage->pt, stObj->pt);
+}
+
+
+/**
+ * Called during state validation. When this function is finished,
+ * the texture object should be ready for rendering.
+ * \return GL_TRUE for success, GL_FALSE for failure (out of mem)
+ */
+GLboolean
+st_finalize_texture(GLcontext *ctx,
+ struct pipe_context *pipe,
+ struct gl_texture_object *tObj,
+ GLboolean *needFlush)
+{
+ struct st_texture_object *stObj = st_texture_object(tObj);
+ const GLuint nr_faces = (stObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
+ int comp_byte = 0;
+ int cpp;
+ GLuint face;
+ struct st_texture_image *firstImage;
+
+ *needFlush = GL_FALSE;
+
+ /* We know/require this is true by now:
+ */
+ assert(stObj->base._Complete);
+
+ /* What levels must the texture include at a minimum?
+ */
+ calculate_first_last_level(stObj);
+ firstImage = st_texture_image(stObj->base.Image[0][stObj->base.BaseLevel]);
+
+ /* If both firstImage and stObj point to a texture which can contain
+ * all active images, favour firstImage. Note that because of the
+ * completeness requirement, we know that the image dimensions
+ * will match.
+ */
+ if (firstImage->pt &&
+ firstImage->pt != stObj->pt &&
+ firstImage->pt->last_level >= stObj->lastLevel) {
+
+ pipe_texture_reference(&stObj->pt, firstImage->pt);
+ }
+
+ /* FIXME: determine format block instead of cpp */
+ if (firstImage->base.IsCompressed) {
+ comp_byte = compressed_num_bytes(firstImage->base.TexFormat->MesaFormat);
+ cpp = comp_byte;
+ }
+ else {
+ cpp = firstImage->base.TexFormat->TexelBytes;
+ }
+
+ /* If we already have a gallium texture, check that it matches the texture
+ * object's format, target, size, num_levels, etc.
+ */
+ if (stObj->pt) {
+ const enum pipe_format fmt =
+ st_mesa_format_to_pipe_format(firstImage->base.TexFormat->MesaFormat);
+ if (stObj->pt->target != gl_target_to_pipe(stObj->base.Target) ||
+ stObj->pt->format != fmt ||
+ stObj->pt->last_level < stObj->lastLevel ||
+ stObj->pt->width[0] != firstImage->base.Width2 ||
+ stObj->pt->height[0] != firstImage->base.Height2 ||
+ stObj->pt->depth[0] != firstImage->base.Depth2 ||
+ stObj->pt->block.size != cpp ||
+ stObj->pt->block.width != 1 ||
+ stObj->pt->block.height != 1 ||
+ stObj->pt->compressed != firstImage->base.IsCompressed) {
+ pipe_texture_release(&stObj->pt);
+ ctx->st->dirty.st |= ST_NEW_FRAMEBUFFER;
+ }
+ }
+
+ /* May need to create a new gallium texture:
+ */
+ if (!stObj->pt) {
+ const enum pipe_format fmt =
+ st_mesa_format_to_pipe_format(firstImage->base.TexFormat->MesaFormat);
+ stObj->pt = st_texture_create(ctx->st,
+ gl_target_to_pipe(stObj->base.Target),
+ fmt,
+ stObj->lastLevel,
+ firstImage->base.Width2,
+ firstImage->base.Height2,
+ firstImage->base.Depth2,
+ comp_byte,
+ ( (pf_is_depth_stencil(fmt) ?
+ PIPE_TEXTURE_USAGE_DEPTH_STENCIL :
+ PIPE_TEXTURE_USAGE_RENDER_TARGET) |
+ PIPE_TEXTURE_USAGE_SAMPLER ));
+
+ if (!stObj->pt) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
+ return GL_FALSE;
+ }
+ }
+
+ /* Pull in any images not in the object's texture:
+ */
+ for (face = 0; face < nr_faces; face++) {
+ GLuint level;
+ for (level = 0; level <= stObj->lastLevel; level++) {
+ struct st_texture_image *stImage =
+ st_texture_image(stObj->base.Image[face][stObj->base.BaseLevel + level]);
+
+ /* Need to import images in main memory or held in other textures.
+ */
+ if (stImage && stObj->pt != stImage->pt) {
+ copy_image_data_to_texture(ctx->st, stObj, level, stImage);
+ *needFlush = GL_TRUE;
+ }
+ }
+ }
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Returns pointer to a default/dummy texture.
+ * This is typically used when the current shader has tex/sample instructions
+ * but the user has not provided a (any) texture(s).
+ */
+struct gl_texture_object *
+st_get_default_texture(struct st_context *st)
+{
+ if (!st->default_texture) {
+ static const GLenum target = GL_TEXTURE_2D;
+ GLubyte pixels[16][16][4];
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImg;
+
+ /* init image to gray */
+ memset(pixels, 127, sizeof(pixels));
+
+ texObj = st->ctx->Driver.NewTextureObject(st->ctx, 0, target);
+
+ texImg = _mesa_get_tex_image(st->ctx, texObj, target, 0);
+
+ _mesa_init_teximage_fields(st->ctx, target, texImg,
+ 16, 16, 1, 0, /* w, h, d, border */
+ GL_RGBA);
+
+ st_TexImage(st->ctx, 2, target,
+ 0, GL_RGBA, /* level, intformat */
+ 16, 16, 1, 0, /* w, h, d, border */
+ GL_RGBA, GL_UNSIGNED_BYTE, pixels,
+ &st->ctx->DefaultPacking,
+ texObj, texImg,
+ 0, 0);
+
+ texObj->MinFilter = GL_NEAREST;
+ texObj->MagFilter = GL_NEAREST;
+ texObj->_Complete = GL_TRUE;
+
+ st->default_texture = texObj;
+ }
+ return st->default_texture;
+}
+
+
+void
+st_init_texture_functions(struct dd_function_table *functions)
+{
+ functions->ChooseTextureFormat = st_ChooseTextureFormat;
+ functions->TexImage1D = st_TexImage1D;
+ functions->TexImage2D = st_TexImage2D;
+ functions->TexImage3D = st_TexImage3D;
+ functions->TexSubImage1D = st_TexSubImage1D;
+ functions->TexSubImage2D = st_TexSubImage2D;
+ functions->TexSubImage3D = st_TexSubImage3D;
+ functions->CopyTexImage1D = st_CopyTexImage1D;
+ functions->CopyTexImage2D = st_CopyTexImage2D;
+ functions->CopyTexSubImage1D = st_CopyTexSubImage1D;
+ functions->CopyTexSubImage2D = st_CopyTexSubImage2D;
+ functions->CopyTexSubImage3D = st_CopyTexSubImage3D;
+ functions->GenerateMipmap = st_generate_mipmap;
+
+ functions->GetTexImage = st_GetTexImage;
+
+ /* compressed texture functions */
+ functions->CompressedTexImage2D = st_CompressedTexImage2D;
+ functions->GetCompressedTexImage = st_GetCompressedTexImage;
+ functions->CompressedTextureSize = _mesa_compressed_texture_size;
+
+ functions->NewTextureObject = st_NewTextureObject;
+ functions->NewTextureImage = st_NewTextureImage;
+ functions->DeleteTexture = st_DeleteTextureObject;
+ functions->FreeTexImageData = st_FreeTextureImageData;
+ functions->UpdateTexturePalette = 0;
+
+ functions->TextureMemCpy = do_memcpy;
+
+ /* XXX Temporary until we can query pipe's texture sizes */
+ functions->TestProxyTexImage = _mesa_test_proxy_teximage;
+}
diff --git a/src/mesa/state_tracker/st_cb_texture.h b/src/mesa/state_tracker/st_cb_texture.h
new file mode 100644
index 00000000000..f1fe0339cdd
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_texture.h
@@ -0,0 +1,48 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_CB_TEXTURE_H
+#define ST_CB_TEXTURE_H
+
+
+extern GLboolean
+st_finalize_texture(GLcontext *ctx,
+ struct pipe_context *pipe,
+ struct gl_texture_object *tObj,
+ GLboolean *needFlush);
+
+
+extern struct gl_texture_object *
+st_get_default_texture(struct st_context *st);
+
+
+extern void
+st_init_texture_functions(struct dd_function_table *functions);
+
+
+#endif /* ST_CB_TEXTURE_H */
diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c
new file mode 100644
index 00000000000..e584a6ceeac
--- /dev/null
+++ b/src/mesa/state_tracker/st_context.c
@@ -0,0 +1,325 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+#include "main/imports.h"
+#include "main/context.h"
+#include "main/extensions.h"
+#include "main/matrix.h"
+#include "main/buffers.h"
+#include "main/scissor.h"
+#include "vbo/vbo.h"
+#include "shader/shader_api.h"
+#include "glapi/glapi.h"
+#include "st_public.h"
+#include "st_context.h"
+#include "st_cb_accum.h"
+#include "st_cb_bitmap.h"
+#include "st_cb_blit.h"
+#include "st_cb_bufferobjects.h"
+#include "st_cb_clear.h"
+#if FEATURE_drawpix
+#include "st_cb_drawpixels.h"
+#include "st_cb_rasterpos.h"
+#endif
+#ifdef FEATURE_OES_draw_texture
+#include "st_cb_drawtex.h"
+#endif
+#include "st_cb_fbo.h"
+#include "st_cb_get.h"
+#if FEATURE_feedback
+#include "st_cb_feedback.h"
+#endif
+#include "st_cb_program.h"
+#include "st_cb_queryobj.h"
+#include "st_cb_readpixels.h"
+#include "st_cb_texture.h"
+#include "st_cb_flush.h"
+#include "st_cb_strings.h"
+#include "st_atom.h"
+#include "st_draw.h"
+#include "st_extensions.h"
+#include "st_gen_mipmap.h"
+#include "st_program.h"
+#include "pipe/p_context.h"
+#include "pipe/p_inlines.h"
+#include "draw/draw_context.h"
+#include "cso_cache/cso_cache.h"
+#include "cso_cache/cso_context.h"
+
+
+/**
+ * Called via ctx->Driver.UpdateState()
+ */
+void st_invalidate_state(GLcontext * ctx, GLuint new_state)
+{
+ struct st_context *st = st_context(ctx);
+
+ st->dirty.mesa |= new_state;
+ st->dirty.st |= ST_NEW_MESA;
+
+ /* This is the only core Mesa module we depend upon.
+ * No longer use swrast, swsetup, tnl.
+ */
+ _vbo_InvalidateState(ctx, new_state);
+}
+
+
+/**
+ * Check for multisample env var override.
+ */
+int
+st_get_msaa(void)
+{
+ const char *msaa = _mesa_getenv("__GL_FSAA_MODE");
+ if (msaa)
+ return atoi(msaa);
+ return 0;
+}
+
+
+static struct st_context *
+st_create_context_priv( GLcontext *ctx, struct pipe_context *pipe )
+{
+ uint i;
+ struct st_context *st = CALLOC_STRUCT( st_context );
+
+ ctx->st = st;
+
+ st->ctx = ctx;
+ st->pipe = pipe;
+
+ /* state tracker needs the VBO module */
+ _vbo_CreateContext(ctx);
+
+#if FEATURE_feedback || FEATURE_drawpix
+ st->draw = draw_create(); /* for selection/feedback */
+
+ /* Disable draw options that might convert points/lines to tris, etc.
+ * as that would foul-up feedback/selection mode.
+ */
+ draw_wide_line_threshold(st->draw, 1000.0f);
+ draw_wide_point_threshold(st->draw, 1000.0f);
+ draw_enable_line_stipple(st->draw, FALSE);
+ draw_enable_point_sprites(st->draw, FALSE);
+#endif
+
+ st->dirty.mesa = ~0;
+ st->dirty.st = ~0;
+
+ st->cso_context = cso_create_context(pipe);
+
+ st_init_atoms( st );
+ st_init_bitmap(st);
+ st_init_clear(st);
+ st_init_draw( st );
+ st_init_generate_mipmap(st);
+ st_init_blit(st);
+
+ for (i = 0; i < PIPE_MAX_SAMPLERS; i++)
+ st->state.sampler_list[i] = &st->state.samplers[i];
+
+ /* we want all vertex data to be placed in buffer objects */
+ vbo_use_buffer_objects(ctx);
+
+ /* Need these flags:
+ */
+ st->ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE;
+
+ st->ctx->VertexProgram._MaintainTnlProgram = GL_TRUE;
+
+ st->pixel_xfer.cache = _mesa_new_program_cache();
+
+ st->force_msaa = st_get_msaa();
+
+ /* GL limits and extensions */
+ st_init_limits(st);
+ st_init_extensions(st);
+
+ return st;
+}
+
+
+struct st_context *st_create_context(struct pipe_context *pipe,
+ const __GLcontextModes *visual,
+ struct st_context *share)
+{
+ GLcontext *ctx;
+ GLcontext *shareCtx = share ? share->ctx : NULL;
+ struct dd_function_table funcs;
+
+ memset(&funcs, 0, sizeof(funcs));
+ st_init_driver_functions(&funcs);
+
+ ctx = _mesa_create_context(visual, shareCtx, &funcs, NULL);
+
+ return st_create_context_priv(ctx, pipe);
+}
+
+
+static void st_destroy_context_priv( struct st_context *st )
+{
+ uint i;
+
+#if FEATURE_feedback || FEATURE_drawpix
+ draw_destroy(st->draw);
+#endif
+ st_destroy_atoms( st );
+ st_destroy_draw( st );
+ st_destroy_generate_mipmap(st);
+#if FEATURE_EXT_framebuffer_blit
+ st_destroy_blit(st);
+#endif
+ st_destroy_clear(st);
+#if FEATURE_drawpix
+ st_destroy_bitmap(st);
+ st_destroy_drawpix(st);
+#endif
+#ifdef FEATURE_OES_draw_texture
+ st_destroy_drawtex(st);
+#endif
+
+ for (i = 0; i < Elements(st->state.sampler_texture); i++) {
+ pipe_texture_reference(&st->state.sampler_texture[i], NULL);
+ }
+
+ for (i = 0; i < Elements(st->state.constants); i++) {
+ if (st->state.constants[i].buffer) {
+ pipe_buffer_reference(st->pipe->screen, &st->state.constants[i].buffer, NULL);
+ }
+ }
+
+ if (st->default_texture) {
+ st->ctx->Driver.DeleteTexture(st->ctx, st->default_texture);
+ st->default_texture = NULL;
+ }
+
+ free( st );
+}
+
+
+void st_destroy_context( struct st_context *st )
+{
+ struct pipe_context *pipe = st->pipe;
+ struct cso_context *cso = st->cso_context;
+ GLcontext *ctx = st->ctx;
+
+ /* need to unbind and destroy CSO objects before anything else */
+ cso_release_all(st->cso_context);
+
+ st_reference_fragprog(st, &st->fp, NULL);
+ st_reference_vertprog(st, &st->vp, NULL);
+
+ _mesa_delete_program_cache(st->ctx, st->pixel_xfer.cache);
+
+ _vbo_DestroyContext(st->ctx);
+
+ _mesa_free_context_data(ctx);
+
+ st_destroy_context_priv(st);
+
+ cso_destroy_context(cso);
+
+ pipe->destroy( pipe );
+
+ free(ctx);
+}
+
+
+void st_make_current(struct st_context *st,
+ struct st_framebuffer *draw,
+ struct st_framebuffer *read)
+{
+ if (st) {
+ GLboolean firstTime = st->ctx->FirstTimeCurrent;
+ _mesa_make_current(st->ctx, &draw->Base, &read->Base);
+ /* Need to initialize viewport here since draw->Base->Width/Height
+ * will still be zero at this point.
+ * This could be improved, but would require rather extensive work
+ * elsewhere (allocate rb surface storage sooner)
+ */
+ if (firstTime) {
+ GLuint w = draw->InitWidth, h = draw->InitHeight;
+ _mesa_set_viewport(st->ctx, 0, 0, w, h);
+ _mesa_set_scissor(st->ctx, 0, 0, w, h);
+
+ }
+ }
+ else {
+ _mesa_make_current(NULL, NULL, NULL);
+ }
+}
+
+
+void st_copy_context_state(struct st_context *dst,
+ struct st_context *src,
+ uint mask)
+{
+ _mesa_copy_context(dst->ctx, src->ctx, mask);
+}
+
+
+
+st_proc st_get_proc_address(const char *procname)
+{
+ return (st_proc) _glapi_get_proc_address(procname);
+}
+
+
+
+void st_init_driver_functions(struct dd_function_table *functions)
+{
+ _mesa_init_glsl_driver_functions(functions);
+
+#if FEATURE_accum
+ st_init_accum_functions(functions);
+#endif
+#if FEATURE_EXT_framebuffer_blit
+ st_init_blit_functions(functions);
+#endif
+ st_init_bufferobject_functions(functions);
+ st_init_clear_functions(functions);
+#if FEATURE_drawpix
+ st_init_bitmap_functions(functions);
+ st_init_drawpixels_functions(functions);
+ st_init_rasterpos_functions(functions);
+#endif
+ st_init_fbo_functions(functions);
+ st_init_get_functions(functions);
+#if FEATURE_feedback
+ st_init_feedback_functions(functions);
+#endif
+ st_init_program_functions(functions);
+#if FEATURE_ARB_occlusion_query
+ st_init_query_functions(functions);
+#endif
+ st_init_readpixels_functions(functions);
+ st_init_texture_functions(functions);
+ st_init_flush_functions(functions);
+ st_init_string_functions(functions);
+
+ functions->UpdateState = st_invalidate_state;
+}
diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h
new file mode 100644
index 00000000000..695ac4a96f4
--- /dev/null
+++ b/src/mesa/state_tracker/st_context.h
@@ -0,0 +1,249 @@
+/**************************************************************************
+ *
+ * Copyright 2003 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.
+ *
+ **************************************************************************/
+
+#ifndef ST_CONTEXT_H
+#define ST_CONTEXT_H
+
+#include "main/mtypes.h"
+#include "shader/prog_cache.h"
+#include "pipe/p_state.h"
+
+
+struct st_context;
+struct st_texture_object;
+struct st_fragment_program;
+struct draw_context;
+struct draw_stage;
+struct cso_cache;
+struct cso_blend;
+struct gen_mipmap_state;
+struct blit_state;
+struct bitmap_cache;
+
+
+#define FRONT_STATUS_UNDEFINED 0
+#define FRONT_STATUS_DIRTY 1
+#define FRONT_STATUS_COPY_OF_BACK 2
+
+
+#define ST_NEW_MESA 0x1 /* Mesa state has changed */
+#define ST_NEW_FRAGMENT_PROGRAM 0x2
+#define ST_NEW_VERTEX_PROGRAM 0x4
+#define ST_NEW_FRAMEBUFFER 0x8
+
+
+struct st_state_flags {
+ GLuint mesa;
+ GLuint st;
+};
+
+struct st_tracked_state {
+ const char *name;
+ struct st_state_flags dirty;
+ void (*update)( struct st_context *st );
+};
+
+
+
+struct st_context
+{
+ GLcontext *ctx;
+
+ struct pipe_context *pipe;
+
+ struct draw_context *draw; /**< For selection/feedback/rastpos only */
+ struct draw_stage *feedback_stage; /**< For GL_FEEDBACK rendermode */
+ struct draw_stage *selection_stage; /**< For GL_SELECT rendermode */
+ struct draw_stage *rastpos_stage; /**< For glRasterPos */
+
+ /* Some state is contained in constant objects.
+ * Other state is just parameter values.
+ */
+ struct {
+ struct pipe_blend_state blend;
+ struct pipe_depth_stencil_alpha_state depth_stencil;
+ struct pipe_rasterizer_state rasterizer;
+ struct pipe_sampler_state samplers[PIPE_MAX_SAMPLERS];
+ struct pipe_sampler_state *sampler_list[PIPE_MAX_SAMPLERS];
+ struct pipe_clip_state clip;
+ struct pipe_constant_buffer constants[2];
+ struct pipe_framebuffer_state framebuffer;
+ struct pipe_texture *sampler_texture[PIPE_MAX_SAMPLERS];
+ struct pipe_poly_stipple poly_stipple;
+ struct pipe_scissor_state scissor;
+ struct pipe_viewport_state viewport;
+
+ GLuint num_samplers;
+ GLuint num_textures;
+ } state;
+
+ struct {
+ struct st_tracked_state tracked_state[PIPE_SHADER_TYPES];
+ } constants;
+
+ /* XXX unused: */
+ struct {
+ struct gl_fragment_program *fragment_program;
+ } cb;
+
+ GLuint frontbuffer_status; /**< one of FRONT_STATUS_ */
+
+ char vendor[100];
+ char renderer[100];
+
+ /* State to be validated:
+ */
+ struct st_tracked_state **atoms;
+ GLuint nr_atoms;
+
+ struct st_state_flags dirty;
+
+ GLboolean missing_textures;
+
+ GLfloat polygon_offset_scale; /* ?? */
+
+ /** Mapping from VERT_RESULT_x to post-transformed vertex slot */
+ const GLuint *vertex_result_to_slot;
+
+ struct st_vertex_program *vp; /**< Currently bound vertex program */
+ struct st_fragment_program *fp; /**< Currently bound fragment program */
+
+ struct gl_texture_object *default_texture;
+
+ struct {
+ struct gl_program_cache *cache;
+ struct st_fragment_program *program; /**< cur pixel transfer prog */
+ GLuint xfer_prog_sn; /**< pixel xfer program serial no. */
+ GLuint user_prog_sn; /**< user fragment program serial no. */
+ struct st_fragment_program *combined_prog;
+ GLuint combined_prog_sn;
+ struct pipe_texture *pixelmap_texture;
+ boolean pixelmap_enabled; /**< use the pixelmap texture? */
+ } pixel_xfer;
+
+ /** for glBitmap */
+ struct {
+ struct pipe_rasterizer_state rasterizer;
+ struct pipe_sampler_state sampler;
+ struct pipe_shader_state vert_shader;
+ enum pipe_format tex_format;
+ void *vs;
+ float vertices[4][3][4]; /**< vertex pos + color + texcoord */
+ struct pipe_buffer *vbuf;
+ unsigned vbuf_slot; /* next free slot in vbuf */
+ struct bitmap_cache *cache;
+ } bitmap;
+
+ /** for glDraw/CopyPixels */
+ struct {
+ struct st_fragment_program *z_shader;
+ struct st_vertex_program *vert_shaders[2];
+ } drawpix;
+
+ /** for glClear */
+ struct {
+ struct pipe_shader_state vert_shader;
+ struct pipe_shader_state frag_shader;
+ struct pipe_rasterizer_state raster;
+ struct pipe_viewport_state viewport;
+ void *vs;
+ void *fs;
+ float vertices[4][2][4]; /**< vertex pos + color */
+ struct pipe_buffer *vbuf;
+ unsigned vbuf_slot;
+ } clear;
+
+ void *passthrough_fs; /**< simple pass-through frag shader */
+
+ struct gen_mipmap_state *gen_mipmap;
+ struct blit_state *blit;
+
+ struct cso_context *cso_context;
+
+ int force_msaa;
+};
+
+
+/* Need this so that we can implement Mesa callbacks in this module.
+ */
+static INLINE struct st_context *st_context(GLcontext *ctx)
+{
+ return ctx->st;
+}
+
+
+/**
+ * Wrapper for GLframebuffer.
+ * This is an opaque type to the outside world.
+ */
+struct st_framebuffer
+{
+ GLframebuffer Base;
+ void *Private;
+ GLuint InitWidth, InitHeight;
+};
+
+
+extern void st_init_driver_functions(struct dd_function_table *functions);
+
+void st_invalidate_state(GLcontext * ctx, GLuint new_state);
+
+
+
+#define Y_0_TOP 1
+#define Y_0_BOTTOM 2
+
+static INLINE GLuint
+st_fb_orientation(const struct gl_framebuffer *fb)
+{
+ if (fb && fb->Name == 0) {
+ /* Drawing into a window (on-screen buffer).
+ *
+ * Negate Y scale to flip image vertically.
+ * The NDC Y coords prior to viewport transformation are in the range
+ * [y=-1=bottom, y=1=top]
+ * Hardware window coords are in the range [y=0=top, y=H-1=bottom] where
+ * H is the window height.
+ * Use the viewport transformation to invert Y.
+ */
+ return Y_0_TOP;
+ }
+ else {
+ /* Drawing into user-created FBO (very likely a texture).
+ *
+ * For textures, T=0=Bottom, so by extension Y=0=Bottom for rendering.
+ */
+ return Y_0_BOTTOM;
+ }
+}
+
+
+extern int
+st_get_msaa(void);
+
+
+#endif
diff --git a/src/mesa/state_tracker/st_debug.c b/src/mesa/state_tracker/st_debug.c
new file mode 100644
index 00000000000..c7d26ce33cf
--- /dev/null
+++ b/src/mesa/state_tracker/st_debug.c
@@ -0,0 +1,70 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+
+#include "main/context.h"
+#include "shader/prog_print.h"
+
+#include "pipe/p_state.h"
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_dump.h"
+
+#include "cso_cache/cso_cache.h"
+
+#include "st_context.h"
+#include "st_debug.h"
+#include "st_program.h"
+
+
+
+/**
+ * Print current state. May be called from inside gdb to see currently
+ * bound vertex/fragment shaders and associated constants.
+ */
+void
+st_print_current(void)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct st_context *st = ctx->st;
+
+#if 0
+ int i;
+
+ printf("Vertex Transform Inputs:\n");
+ for (i = 0; i < st->vp->state.num_inputs; i++) {
+ printf(" Slot %d: VERT_ATTRIB_%d\n", i, st->vp->index_to_input[i]);
+ }
+#endif
+
+ tgsi_dump( st->vp->state.tokens, 0 );
+ if (st->vp->Base.Base.Parameters)
+ _mesa_print_parameter_list(st->vp->Base.Base.Parameters);
+
+ tgsi_dump( st->fp->state.tokens, 0 );
+ if (st->fp->Base.Base.Parameters)
+ _mesa_print_parameter_list(st->fp->Base.Base.Parameters);
+}
diff --git a/src/mesa/state_tracker/st_debug.h b/src/mesa/state_tracker/st_debug.h
new file mode 100644
index 00000000000..49d752e1b23
--- /dev/null
+++ b/src/mesa/state_tracker/st_debug.h
@@ -0,0 +1,36 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_DEBUG_H
+#define ST_DEBUG_H
+
+extern void
+st_print_current(void);
+
+
+#endif /* ST_DEBUG_H */
diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c
new file mode 100644
index 00000000000..ae71d586c2f
--- /dev/null
+++ b/src/mesa/state_tracker/st_draw.c
@@ -0,0 +1,699 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <[email protected]>
+ */
+
+#include "main/imports.h"
+#include "main/image.h"
+#include "main/macros.h"
+#include "shader/prog_uniform.h"
+
+#include "vbo/vbo.h"
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "st_cb_bufferobjects.h"
+#include "st_draw.h"
+#include "st_program.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+
+
+static GLuint double_types[4] = {
+ PIPE_FORMAT_R64_FLOAT,
+ PIPE_FORMAT_R64G64_FLOAT,
+ PIPE_FORMAT_R64G64B64_FLOAT,
+ PIPE_FORMAT_R64G64B64A64_FLOAT
+};
+
+static GLuint float_types[4] = {
+ PIPE_FORMAT_R32_FLOAT,
+ PIPE_FORMAT_R32G32_FLOAT,
+ PIPE_FORMAT_R32G32B32_FLOAT,
+ PIPE_FORMAT_R32G32B32A32_FLOAT
+};
+
+static GLuint uint_types_norm[4] = {
+ PIPE_FORMAT_R32_UNORM,
+ PIPE_FORMAT_R32G32_UNORM,
+ PIPE_FORMAT_R32G32B32_UNORM,
+ PIPE_FORMAT_R32G32B32A32_UNORM
+};
+
+static GLuint uint_types_scale[4] = {
+ PIPE_FORMAT_R32_USCALED,
+ PIPE_FORMAT_R32G32_USCALED,
+ PIPE_FORMAT_R32G32B32_USCALED,
+ PIPE_FORMAT_R32G32B32A32_USCALED
+};
+
+static GLuint int_types_norm[4] = {
+ PIPE_FORMAT_R32_SNORM,
+ PIPE_FORMAT_R32G32_SNORM,
+ PIPE_FORMAT_R32G32B32_SNORM,
+ PIPE_FORMAT_R32G32B32A32_SNORM
+};
+
+static GLuint int_types_scale[4] = {
+ PIPE_FORMAT_R32_SSCALED,
+ PIPE_FORMAT_R32G32_SSCALED,
+ PIPE_FORMAT_R32G32B32_SSCALED,
+ PIPE_FORMAT_R32G32B32A32_SSCALED
+};
+
+static GLuint ushort_types_norm[4] = {
+ PIPE_FORMAT_R16_UNORM,
+ PIPE_FORMAT_R16G16_UNORM,
+ PIPE_FORMAT_R16G16B16_UNORM,
+ PIPE_FORMAT_R16G16B16A16_UNORM
+};
+
+static GLuint ushort_types_scale[4] = {
+ PIPE_FORMAT_R16_USCALED,
+ PIPE_FORMAT_R16G16_USCALED,
+ PIPE_FORMAT_R16G16B16_USCALED,
+ PIPE_FORMAT_R16G16B16A16_USCALED
+};
+
+static GLuint short_types_norm[4] = {
+ PIPE_FORMAT_R16_SNORM,
+ PIPE_FORMAT_R16G16_SNORM,
+ PIPE_FORMAT_R16G16B16_SNORM,
+ PIPE_FORMAT_R16G16B16A16_SNORM
+};
+
+static GLuint short_types_scale[4] = {
+ PIPE_FORMAT_R16_SSCALED,
+ PIPE_FORMAT_R16G16_SSCALED,
+ PIPE_FORMAT_R16G16B16_SSCALED,
+ PIPE_FORMAT_R16G16B16A16_SSCALED
+};
+
+static GLuint ubyte_types_norm[4] = {
+ PIPE_FORMAT_R8_UNORM,
+ PIPE_FORMAT_R8G8_UNORM,
+ PIPE_FORMAT_R8G8B8_UNORM,
+ PIPE_FORMAT_R8G8B8A8_UNORM
+};
+
+static GLuint ubyte_types_scale[4] = {
+ PIPE_FORMAT_R8_USCALED,
+ PIPE_FORMAT_R8G8_USCALED,
+ PIPE_FORMAT_R8G8B8_USCALED,
+ PIPE_FORMAT_R8G8B8A8_USCALED
+};
+
+static GLuint byte_types_norm[4] = {
+ PIPE_FORMAT_R8_SNORM,
+ PIPE_FORMAT_R8G8_SNORM,
+ PIPE_FORMAT_R8G8B8_SNORM,
+ PIPE_FORMAT_R8G8B8A8_SNORM
+};
+
+static GLuint byte_types_scale[4] = {
+ PIPE_FORMAT_R8_SSCALED,
+ PIPE_FORMAT_R8G8_SSCALED,
+ PIPE_FORMAT_R8G8B8_SSCALED,
+ PIPE_FORMAT_R8G8B8A8_SSCALED
+};
+
+static GLuint fixed_types[4] = {
+ PIPE_FORMAT_R32_FIXED,
+ PIPE_FORMAT_R32G32_FIXED,
+ PIPE_FORMAT_R32G32B32_FIXED,
+ PIPE_FORMAT_R32G32B32A32_FIXED
+};
+
+
+
+/**
+ * Return a PIPE_FORMAT_x for the given GL datatype and size.
+ */
+GLuint
+st_pipe_vertex_format(GLenum type, GLuint size, GLboolean normalized)
+{
+ assert((type >= GL_BYTE && type <= GL_DOUBLE) ||
+ type == GL_FIXED);
+ assert(size >= 1);
+ assert(size <= 4);
+
+ if (normalized) {
+ switch (type) {
+ case GL_DOUBLE: return double_types[size-1];
+ case GL_FLOAT: return float_types[size-1];
+ case GL_INT: return int_types_norm[size-1];
+ case GL_SHORT: return short_types_norm[size-1];
+ case GL_BYTE: return byte_types_norm[size-1];
+ case GL_UNSIGNED_INT: return uint_types_norm[size-1];
+ case GL_UNSIGNED_SHORT: return ushort_types_norm[size-1];
+ case GL_UNSIGNED_BYTE: return ubyte_types_norm[size-1];
+ case GL_FIXED: return fixed_types[size-1];
+ default: assert(0); return 0;
+ }
+ }
+ else {
+ switch (type) {
+ case GL_DOUBLE: return double_types[size-1];
+ case GL_FLOAT: return float_types[size-1];
+ case GL_INT: return int_types_scale[size-1];
+ case GL_SHORT: return short_types_scale[size-1];
+ case GL_BYTE: return byte_types_scale[size-1];
+ case GL_UNSIGNED_INT: return uint_types_scale[size-1];
+ case GL_UNSIGNED_SHORT: return ushort_types_scale[size-1];
+ case GL_UNSIGNED_BYTE: return ubyte_types_scale[size-1];
+ case GL_FIXED: return fixed_types[size-1];
+ default: assert(0); return 0;
+ }
+ }
+ return 0; /* silence compiler warning */
+}
+
+
+/*
+ * If edge flags are needed, setup an bitvector of flags and call
+ * pipe->set_edgeflags().
+ * XXX memleak: need to free the returned pointer at some point
+ */
+static void *
+setup_edgeflags(GLcontext *ctx, GLenum primMode, GLint start, GLint count,
+ const struct gl_client_array *array)
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+
+ if ((primMode == GL_TRIANGLES ||
+ primMode == GL_QUADS ||
+ primMode == GL_POLYGON) &&
+ (ctx->Polygon.FrontMode != GL_FILL ||
+ ctx->Polygon.BackMode != GL_FILL)) {
+ /* need edge flags */
+ GLint i;
+ unsigned *vec;
+ struct st_buffer_object *stobj = st_buffer_object(array->BufferObj);
+ ubyte *map;
+
+ if (!stobj)
+ return NULL;
+
+ vec = (unsigned *) calloc(sizeof(unsigned), (count + 31) / 32);
+ if (!vec)
+ return NULL;
+
+ map = pipe_buffer_map(pipe->screen, stobj->buffer, PIPE_BUFFER_USAGE_CPU_READ);
+ map = ADD_POINTERS(map, array->Ptr);
+
+ for (i = 0; i < count; i++) {
+ if (*((float *) map))
+ vec[i/32] |= 1 << (i % 32);
+
+ map += array->StrideB;
+ }
+
+ pipe_buffer_unmap(pipe->screen, stobj->buffer);
+
+ pipe->set_edgeflags(pipe, vec);
+
+ return vec;
+ }
+ else {
+ /* edge flags not needed */
+ pipe->set_edgeflags(pipe, NULL);
+ return NULL;
+ }
+}
+
+
+/**
+ * Examine the active arrays to determine if we have interleaved
+ * vertex arrays all living in one VBO, or all living in user space.
+ * \param userSpace returns whether the arrays are in user space.
+ */
+static GLboolean
+is_interleaved_arrays(const struct st_vertex_program *vp,
+ const struct gl_client_array **arrays,
+ GLboolean *userSpace)
+{
+ GLuint attr;
+ const struct gl_buffer_object *firstBufObj = NULL;
+ GLint firstStride = -1;
+ GLuint num_client_arrays = 0;
+ const GLubyte *client_addr = NULL;
+
+ for (attr = 0; attr < vp->num_inputs; attr++) {
+ const GLuint mesaAttr = vp->index_to_input[attr];
+ const struct gl_buffer_object *bufObj = arrays[mesaAttr]->BufferObj;
+ const GLsizei stride = arrays[mesaAttr]->StrideB; /* in bytes */
+
+ if (firstStride < 0) {
+ firstStride = stride;
+ }
+ else if (firstStride != stride) {
+ return GL_FALSE;
+ }
+
+ if (!bufObj || !bufObj->Name) {
+ num_client_arrays++;
+ /* Try to detect if the client-space arrays are
+ * "close" to each other.
+ */
+ if (!client_addr) {
+ client_addr = arrays[mesaAttr]->Ptr;
+ }
+ else if (abs(arrays[mesaAttr]->Ptr - client_addr) > firstStride) {
+ /* arrays start too far apart */
+ return GL_FALSE;
+ }
+ }
+ else if (!firstBufObj) {
+ firstBufObj = bufObj;
+ }
+ else if (bufObj != firstBufObj) {
+ return GL_FALSE;
+ }
+ }
+
+ *userSpace = (num_client_arrays == vp->num_inputs);
+ /* printf("user space: %d (%d %d)\n", (int) *userSpace,num_client_arrays,vp->num_inputs); */
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Compute the memory range occupied by the arrays.
+ */
+static void
+get_arrays_bounds(const struct st_vertex_program *vp,
+ const struct gl_client_array **arrays,
+ GLuint max_index,
+ const GLubyte **low, const GLubyte **high)
+{
+ const GLubyte *low_addr = NULL;
+ GLuint attr;
+ GLint stride;
+
+ for (attr = 0; attr < vp->num_inputs; attr++) {
+ const GLuint mesaAttr = vp->index_to_input[attr];
+ const GLubyte *start = arrays[mesaAttr]->Ptr;
+ stride = arrays[mesaAttr]->StrideB;
+ if (attr == 0) {
+ low_addr = start;
+ }
+ else {
+ low_addr = MIN2(low_addr, start);
+ }
+ }
+
+ *low = low_addr;
+ *high = low_addr + (max_index + 1) * stride;
+}
+
+
+/**
+ * Set up for drawing interleaved arrays that all live in one VBO
+ * or all live in user space.
+ * \param vbuffer returns vertex buffer info
+ * \param velements returns vertex element info
+ */
+static void
+setup_interleaved_attribs(GLcontext *ctx,
+ const struct st_vertex_program *vp,
+ const struct gl_client_array **arrays,
+ GLuint max_index,
+ GLboolean userSpace,
+ struct pipe_vertex_buffer *vbuffer,
+ struct pipe_vertex_element velements[])
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+ GLuint attr;
+ const GLubyte *offset0;
+
+ for (attr = 0; attr < vp->num_inputs; attr++) {
+ const GLuint mesaAttr = vp->index_to_input[attr];
+ struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj;
+ struct st_buffer_object *stobj = st_buffer_object(bufobj);
+ GLsizei stride = arrays[mesaAttr]->StrideB;
+
+ /*printf("stobj %u = %p\n", attr, (void*)stobj);*/
+
+ if (attr == 0) {
+ const GLubyte *low, *high;
+
+ get_arrays_bounds(vp, arrays, max_index, &low, &high);
+ /*printf("buffer range: %p %p %d\n", low, high, high-low);*/
+
+ offset0 = low;
+ if (userSpace) {
+ vbuffer->buffer =
+ pipe_user_buffer_create(pipe->screen, (void *) low, high - low);
+ vbuffer->buffer_offset = 0;
+ }
+ else {
+ vbuffer->buffer = NULL;
+ pipe_buffer_reference(pipe->screen, &vbuffer->buffer, stobj->buffer);
+ vbuffer->buffer_offset = (unsigned) low;
+ }
+ vbuffer->stride = stride; /* in bytes */
+ vbuffer->max_index = max_index;
+ }
+
+ velements[attr].src_offset =
+ (unsigned) (arrays[mesaAttr]->Ptr - offset0);
+ velements[attr].vertex_buffer_index = 0;
+ velements[attr].nr_components = arrays[mesaAttr]->Size;
+ velements[attr].src_format =
+ st_pipe_vertex_format(arrays[mesaAttr]->Type,
+ arrays[mesaAttr]->Size,
+ arrays[mesaAttr]->Normalized);
+ assert(velements[attr].src_format);
+ }
+}
+
+
+/**
+ * Set up a separate pipe_vertex_buffer and pipe_vertex_element for each
+ * vertex attribute.
+ * \param vbuffer returns vertex buffer info
+ * \param velements returns vertex element info
+ */
+static void
+setup_non_interleaved_attribs(GLcontext *ctx,
+ const struct st_vertex_program *vp,
+ const struct gl_client_array **arrays,
+ GLuint max_index,
+ GLboolean *userSpace,
+ struct pipe_vertex_buffer vbuffer[],
+ struct pipe_vertex_element velements[])
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+ GLuint attr;
+
+ for (attr = 0; attr < vp->num_inputs; attr++) {
+ const GLuint mesaAttr = vp->index_to_input[attr];
+ struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj;
+ GLsizei stride = arrays[mesaAttr]->StrideB;
+
+ *userSpace = GL_FALSE;
+
+ if (bufobj && bufobj->Name) {
+ /* Attribute data is in a VBO.
+ * Recall that for VBOs, the gl_client_array->Ptr field is
+ * really an offset from the start of the VBO, not a pointer.
+ */
+ struct st_buffer_object *stobj = st_buffer_object(bufobj);
+ assert(stobj->buffer);
+ /*printf("stobj %u = %p\n", attr, (void*) stobj);*/
+
+ vbuffer[attr].buffer = NULL;
+ pipe_buffer_reference(pipe->screen, &vbuffer[attr].buffer, stobj->buffer);
+ vbuffer[attr].buffer_offset = (unsigned) arrays[mesaAttr]->Ptr;
+ velements[attr].src_offset = 0;
+ }
+ else {
+ /* attribute data is in user-space memory, not a VBO */
+ uint bytes;
+ /*printf("user-space array %d stride %d\n", attr, stride);*/
+
+ *userSpace = GL_TRUE;
+
+ /* wrap user data */
+ if (arrays[mesaAttr]->Ptr) {
+ /* user's vertex array */
+ if (arrays[mesaAttr]->StrideB) {
+ bytes = arrays[mesaAttr]->StrideB * (max_index + 1);
+ }
+ else {
+ bytes = arrays[mesaAttr]->Size
+ * _mesa_sizeof_type(arrays[mesaAttr]->Type);
+ }
+ vbuffer[attr].buffer = pipe_user_buffer_create(pipe->screen,
+ (void *) arrays[mesaAttr]->Ptr, bytes);
+ }
+ else {
+ /* no array, use ctx->Current.Attrib[] value */
+ bytes = sizeof(ctx->Current.Attrib[0]);
+ vbuffer[attr].buffer = pipe_user_buffer_create(pipe->screen,
+ (void *) ctx->Current.Attrib[mesaAttr], bytes);
+ stride = 0;
+ }
+
+ vbuffer[attr].buffer_offset = 0;
+ velements[attr].src_offset = 0;
+ }
+
+ assert(velements[attr].src_offset <= 2048); /* 11-bit field */
+
+ /* common-case setup */
+ vbuffer[attr].stride = stride; /* in bytes */
+ vbuffer[attr].max_index = max_index;
+ velements[attr].vertex_buffer_index = attr;
+ velements[attr].nr_components = arrays[mesaAttr]->Size;
+ velements[attr].src_format
+ = st_pipe_vertex_format(arrays[mesaAttr]->Type,
+ arrays[mesaAttr]->Size,
+ arrays[mesaAttr]->Normalized);
+ assert(velements[attr].src_format);
+ }
+}
+
+
+
+/**
+ * Prior to drawing, check that any uniforms referenced by the
+ * current shader have been set. If a uniform has not been set,
+ * issue a warning.
+ */
+static void
+check_uniforms(GLcontext *ctx)
+{
+ const struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
+ if (shProg && shProg->LinkStatus) {
+ GLuint i;
+ for (i = 0; i < shProg->Uniforms->NumUniforms; i++) {
+ const struct gl_uniform *u = &shProg->Uniforms->Uniforms[i];
+ if (!u->Initialized) {
+ _mesa_warning(ctx,
+ "Using shader with uninitialized uniform: %s",
+ u->Name);
+ }
+ }
+ }
+}
+
+
+/**
+ * This function gets plugged into the VBO module and is called when
+ * we have something to render.
+ * Basically, translate the information into the format expected by gallium.
+ */
+void
+st_draw_vbo(GLcontext *ctx,
+ const struct gl_client_array **arrays,
+ const struct _mesa_prim *prims,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLuint min_index,
+ GLuint max_index)
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+ const struct st_vertex_program *vp;
+ const struct pipe_shader_state *vs;
+ struct pipe_vertex_buffer vbuffer[PIPE_MAX_SHADER_INPUTS];
+ GLuint attr;
+ struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS];
+ unsigned num_vbuffers, num_velements;
+ GLboolean userSpace;
+
+ /* sanity check for pointer arithmetic below */
+ assert(sizeof(arrays[0]->Ptr[0]) == 1);
+
+ st_validate_state(ctx->st);
+
+ /* must get these after state validation! */
+ vp = ctx->st->vp;
+ vs = &ctx->st->vp->state;
+
+#if 0
+ if (MESA_VERBOSE & VERBOSE_GLSL) {
+ check_uniforms(ctx);
+ }
+#endif
+
+ /*
+ * Setup the vbuffer[] and velements[] arrays.
+ */
+ if (is_interleaved_arrays(vp, arrays, &userSpace)) {
+ /*printf("Draw interleaved\n");*/
+ setup_interleaved_attribs(ctx, vp, arrays, max_index, userSpace,
+ vbuffer, velements);
+ num_vbuffers = 1;
+ num_velements = vp->num_inputs;
+ if (num_velements == 0)
+ num_vbuffers = 0;
+ }
+ else {
+ /*printf("Draw non-interleaved\n");*/
+ setup_non_interleaved_attribs(ctx, vp, arrays, max_index,
+ &userSpace, vbuffer, velements);
+ num_vbuffers = vp->num_inputs;
+ num_velements = vp->num_inputs;
+ }
+
+#if 0
+ {
+ GLuint i;
+ for (i = 0; i < num_vbuffers; i++) {
+ printf("buffers[%d].stride = %u\n", i, vbuffer[i].stride);
+ printf("buffers[%d].max_index = %u\n", i, vbuffer[i].max_index);
+ printf("buffers[%d].buffer_offset = %u\n", i, vbuffer[i].buffer_offset);
+ printf("buffers[%d].buffer = %p\n", i, (void*) vbuffer[i].buffer);
+ }
+ for (i = 0; i < num_velements; i++) {
+ printf("vlements[%d].vbuffer_index = %u\n", i, velements[i].vertex_buffer_index);
+ printf("vlements[%d].src_offset = %u\n", i, velements[i].src_offset);
+ printf("vlements[%d].nr_comps = %u\n", i, velements[i].nr_components);
+ printf("vlements[%d].format = %s\n", i, pf_name(velements[i].src_format));
+ }
+ }
+#endif
+
+ pipe->set_vertex_buffers(pipe, num_vbuffers, vbuffer);
+ pipe->set_vertex_elements(pipe, num_velements, velements);
+
+ if (num_vbuffers == 0 || num_velements == 0)
+ return;
+
+ /* do actual drawing */
+ if (ib) {
+ /* indexed primitive */
+ struct gl_buffer_object *bufobj = ib->obj;
+ struct pipe_buffer *indexBuf = NULL;
+ unsigned indexSize, indexOffset, i;
+
+ switch (ib->type) {
+ case GL_UNSIGNED_INT:
+ indexSize = 4;
+ break;
+ case GL_UNSIGNED_SHORT:
+ indexSize = 2;
+ break;
+ case GL_UNSIGNED_BYTE:
+ indexSize = 1;
+ break;
+ default:
+ assert(0);
+ return;
+ }
+
+ /* get/create the index buffer object */
+ if (bufobj && bufobj->Name) {
+ /* elements/indexes are in a real VBO */
+ struct st_buffer_object *stobj = st_buffer_object(bufobj);
+ pipe_buffer_reference(pipe->screen, &indexBuf, stobj->buffer);
+ indexOffset = (unsigned) ib->ptr / indexSize;
+ }
+ else {
+ /* element/indicies are in user space memory */
+ indexBuf = pipe_user_buffer_create(pipe->screen, (void *) ib->ptr,
+ ib->count * indexSize);
+ indexOffset = 0;
+ }
+
+ /* draw */
+ if (nr_prims == 1 && pipe->draw_range_elements != NULL) {
+ i = 0;
+
+ /* XXX: exercise temporary path to pass min/max directly
+ * through to driver & draw module. These interfaces still
+ * need a bit of work...
+ */
+ setup_edgeflags(ctx, prims[i].mode,
+ prims[i].start + indexOffset, prims[i].count,
+ arrays[VERT_ATTRIB_EDGEFLAG]);
+
+ pipe->draw_range_elements(pipe, indexBuf, indexSize,
+ min_index,
+ max_index,
+ prims[i].mode,
+ prims[i].start + indexOffset, prims[i].count);
+ }
+ else {
+ for (i = 0; i < nr_prims; i++) {
+ setup_edgeflags(ctx, prims[i].mode,
+ prims[i].start + indexOffset, prims[i].count,
+ arrays[VERT_ATTRIB_EDGEFLAG]);
+
+ pipe->draw_elements(pipe, indexBuf, indexSize,
+ prims[i].mode,
+ prims[i].start + indexOffset, prims[i].count);
+ }
+ }
+
+ pipe_buffer_reference(pipe->screen, &indexBuf, NULL);
+ }
+ else {
+ /* non-indexed */
+ GLuint i;
+ for (i = 0; i < nr_prims; i++) {
+ setup_edgeflags(ctx, prims[i].mode,
+ prims[i].start, prims[i].count,
+ arrays[VERT_ATTRIB_EDGEFLAG]);
+
+ pipe->draw_arrays(pipe, prims[i].mode, prims[i].start, prims[i].count);
+ }
+ }
+
+ /* unreference buffers (frees wrapped user-space buffer objects) */
+ for (attr = 0; attr < num_vbuffers; attr++) {
+ pipe_buffer_reference(pipe->screen, &vbuffer[attr].buffer, NULL);
+ assert(!vbuffer[attr].buffer);
+ }
+
+ if (userSpace)
+ {
+ pipe->set_vertex_buffers(pipe, 0, NULL);
+ }
+}
+
+
+void st_init_draw( struct st_context *st )
+{
+ GLcontext *ctx = st->ctx;
+
+ vbo_set_draw_func(ctx, st_draw_vbo);
+}
+
+
+void st_destroy_draw( struct st_context *st )
+{
+}
+
+
diff --git a/src/mesa/state_tracker/st_draw.h b/src/mesa/state_tracker/st_draw.h
new file mode 100644
index 00000000000..659c3ac834f
--- /dev/null
+++ b/src/mesa/state_tracker/st_draw.h
@@ -0,0 +1,67 @@
+/**************************************************************************
+ *
+ * Copyright 2004 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.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <[email protected]>
+ */
+
+
+#ifndef ST_DRAW_H
+#define ST_DRAW_H
+
+struct _mesa_prim;
+struct _mesa_index_buffer;
+
+void st_init_draw( struct st_context *st );
+
+void st_destroy_draw( struct st_context *st );
+
+extern void
+st_draw_vbo(GLcontext *ctx,
+ const struct gl_client_array **arrays,
+ const struct _mesa_prim *prims,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLuint min_index,
+ GLuint max_index);
+
+extern void
+st_feedback_draw_vbo(GLcontext *ctx,
+ const struct gl_client_array **arrays,
+ const struct _mesa_prim *prims,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLuint min_index,
+ GLuint max_index);
+
+/* Internal function:
+ */
+extern GLuint
+st_pipe_vertex_format(GLenum type, GLuint size, GLboolean normalized);
+
+#endif
diff --git a/src/mesa/state_tracker/st_draw_feedback.c b/src/mesa/state_tracker/st_draw_feedback.c
new file mode 100644
index 00000000000..5c9c4506c22
--- /dev/null
+++ b/src/mesa/state_tracker/st_draw_feedback.c
@@ -0,0 +1,262 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+#include "main/imports.h"
+#include "main/image.h"
+#include "main/macros.h"
+#include "shader/prog_uniform.h"
+
+#include "vbo/vbo.h"
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "st_cb_bufferobjects.h"
+#include "st_draw.h"
+#include "st_program.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+
+#include "draw/draw_private.h"
+#include "draw/draw_context.h"
+
+
+#if FEATURE_feedback || FEATURE_drawpix
+
+/**
+ * Set the (private) draw module's post-transformed vertex format when in
+ * GL_SELECT or GL_FEEDBACK mode or for glRasterPos.
+ */
+static void
+set_feedback_vertex_format(GLcontext *ctx)
+{
+#if 0
+ struct st_context *st = ctx->st;
+ struct vertex_info vinfo;
+ GLuint i;
+
+ memset(&vinfo, 0, sizeof(vinfo));
+
+ if (ctx->RenderMode == GL_SELECT) {
+ assert(ctx->RenderMode == GL_SELECT);
+ vinfo.num_attribs = 1;
+ vinfo.format[0] = FORMAT_4F;
+ vinfo.interp_mode[0] = INTERP_LINEAR;
+ }
+ else {
+ /* GL_FEEDBACK, or glRasterPos */
+ /* emit all attribs (pos, color, texcoord) as GLfloat[4] */
+ vinfo.num_attribs = st->state.vs->cso->state.num_outputs;
+ for (i = 0; i < vinfo.num_attribs; i++) {
+ vinfo.format[i] = FORMAT_4F;
+ vinfo.interp_mode[i] = INTERP_LINEAR;
+ }
+ }
+
+ draw_set_vertex_info(st->draw, &vinfo);
+#endif
+}
+
+
+/**
+ * Called by VBO to draw arrays when in selection or feedback mode and
+ * to implement glRasterPos.
+ * This is very much like the normal draw_vbo() function above.
+ * Look at code refactoring some day.
+ * Might move this into the failover module some day.
+ */
+void
+st_feedback_draw_vbo(GLcontext *ctx,
+ const struct gl_client_array **arrays,
+ const struct _mesa_prim *prims,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLuint min_index,
+ GLuint max_index)
+{
+ struct st_context *st = ctx->st;
+ struct pipe_context *pipe = st->pipe;
+ struct draw_context *draw = st->draw;
+ const struct st_vertex_program *vp;
+ const struct pipe_shader_state *vs;
+ struct pipe_buffer *index_buffer_handle = 0;
+ struct pipe_vertex_buffer vbuffers[PIPE_MAX_SHADER_INPUTS];
+ struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS];
+ GLuint attr, i;
+ ubyte *mapped_constants;
+
+ assert(draw);
+
+ st_validate_state(ctx->st);
+
+ /* must get these after state validation! */
+ vp = ctx->st->vp;
+ vs = &st->vp->state;
+
+ if (!st->vp->draw_shader) {
+ st->vp->draw_shader = draw_create_vertex_shader(draw, vs);
+ }
+
+ /*
+ * Set up the draw module's state.
+ *
+ * We'd like to do this less frequently, but the normal state-update
+ * code sends state updates to the pipe, not to our private draw module.
+ */
+ assert(draw);
+ draw_set_viewport_state(draw, &st->state.viewport);
+ draw_set_clip_state(draw, &st->state.clip);
+ draw_set_rasterizer_state(draw, &st->state.rasterizer);
+ draw_bind_vertex_shader(draw, st->vp->draw_shader);
+ set_feedback_vertex_format(ctx);
+
+ /* loop over TGSI shader inputs to determine vertex buffer
+ * and attribute info
+ */
+ for (attr = 0; attr < vp->num_inputs; attr++) {
+ const GLuint mesaAttr = vp->index_to_input[attr];
+ struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj;
+ void *map;
+
+ if (bufobj && bufobj->Name) {
+ /* Attribute data is in a VBO.
+ * Recall that for VBOs, the gl_client_array->Ptr field is
+ * really an offset from the start of the VBO, not a pointer.
+ */
+ struct st_buffer_object *stobj = st_buffer_object(bufobj);
+ assert(stobj->buffer);
+
+ vbuffers[attr].buffer = NULL;
+ pipe_buffer_reference(pipe->screen, &vbuffers[attr].buffer, stobj->buffer);
+ vbuffers[attr].buffer_offset = (unsigned) arrays[0]->Ptr;/* in bytes */
+ velements[attr].src_offset = arrays[mesaAttr]->Ptr - arrays[0]->Ptr;
+ }
+ else {
+ /* attribute data is in user-space memory, not a VBO */
+ uint bytes = (arrays[mesaAttr]->Size
+ * _mesa_sizeof_type(arrays[mesaAttr]->Type)
+ * (max_index + 1));
+
+ /* wrap user data */
+ vbuffers[attr].buffer
+ = pipe_user_buffer_create(pipe->screen, (void *) arrays[mesaAttr]->Ptr,
+ bytes);
+ vbuffers[attr].buffer_offset = 0;
+ velements[attr].src_offset = 0;
+ }
+
+ /* common-case setup */
+ vbuffers[attr].stride = arrays[mesaAttr]->StrideB; /* in bytes */
+ vbuffers[attr].max_index = max_index;
+ velements[attr].vertex_buffer_index = attr;
+ velements[attr].nr_components = arrays[mesaAttr]->Size;
+ velements[attr].src_format =
+ st_pipe_vertex_format(arrays[mesaAttr]->Type,
+ arrays[mesaAttr]->Size,
+ arrays[mesaAttr]->Normalized);
+ assert(velements[attr].src_format);
+
+ /* tell draw about this attribute */
+#if 0
+ draw_set_vertex_buffer(draw, attr, &vbuffer[attr]);
+#endif
+
+ /* map the attrib buffer */
+ map = pipe_buffer_map(pipe->screen, vbuffers[attr].buffer,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ draw_set_mapped_vertex_buffer(draw, attr, map);
+ }
+
+ draw_set_vertex_buffers(draw, vp->num_inputs, vbuffers);
+ draw_set_vertex_elements(draw, vp->num_inputs, velements);
+
+ if (ib) {
+ unsigned indexSize;
+ struct gl_buffer_object *bufobj = ib->obj;
+ struct st_buffer_object *stobj = st_buffer_object(bufobj);
+ void *map;
+
+ index_buffer_handle = stobj->buffer;
+
+ switch (ib->type) {
+ case GL_UNSIGNED_INT:
+ indexSize = 4;
+ break;
+ case GL_UNSIGNED_SHORT:
+ indexSize = 2;
+ break;
+ default:
+ assert(0);
+ return;
+ }
+
+ map = pipe_buffer_map(pipe->screen, index_buffer_handle,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ draw_set_mapped_element_buffer(draw, indexSize, map);
+ }
+ else {
+ /* no index/element buffer */
+ draw_set_mapped_element_buffer(draw, 0, NULL);
+ }
+
+
+ /* map constant buffers */
+ mapped_constants = pipe_buffer_map(pipe->screen,
+ st->state.constants[PIPE_SHADER_VERTEX].buffer,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ draw_set_mapped_constant_buffer(st->draw, mapped_constants,
+ st->state.constants[PIPE_SHADER_VERTEX].buffer->size);
+
+
+ /* draw here */
+ for (i = 0; i < nr_prims; i++) {
+ draw_arrays(draw, prims[i].mode, prims[i].start, prims[i].count);
+ }
+
+
+ /* unmap constant buffers */
+ pipe_buffer_unmap(pipe->screen, st->state.constants[PIPE_SHADER_VERTEX].buffer);
+
+ /*
+ * unmap vertex/index buffers
+ */
+ for (i = 0; i < PIPE_MAX_ATTRIBS; i++) {
+ if (draw->pt.vertex_buffer[i].buffer) {
+ pipe_buffer_unmap(pipe->screen, draw->pt.vertex_buffer[i].buffer);
+ pipe_buffer_reference(pipe->screen, &draw->pt.vertex_buffer[i].buffer, NULL);
+ draw_set_mapped_vertex_buffer(draw, i, NULL);
+ }
+ }
+ if (ib) {
+ pipe_buffer_unmap(pipe->screen, index_buffer_handle);
+ draw_set_mapped_element_buffer(draw, 0, NULL);
+ }
+}
+
+#endif /* FEATURE_feedback || FEATURE_drawpix */
+
diff --git a/src/mesa/state_tracker/st_extensions.c b/src/mesa/state_tracker/st_extensions.c
new file mode 100644
index 00000000000..cd34529d385
--- /dev/null
+++ b/src/mesa/state_tracker/st_extensions.c
@@ -0,0 +1,279 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright (c) 2008 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "main/imports.h"
+#include "main/context.h"
+#include "main/extensions.h"
+#include "main/macros.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_screen.h"
+
+#include "st_context.h"
+#include "st_extensions.h"
+
+
+static int _min(int a, int b)
+{
+ return (a < b) ? a : b;
+}
+
+static float _maxf(float a, float b)
+{
+ return (a > b) ? a : b;
+}
+
+static int _clamp(int a, int min, int max)
+{
+ if (a < min)
+ return min;
+ else if (a > max)
+ return max;
+ else
+ return a;
+}
+
+
+/**
+ * Query driver to get implementation limits.
+ * Note that we have to limit/clamp against Mesa's internal limits too.
+ */
+void st_init_limits(struct st_context *st)
+{
+ struct pipe_screen *screen = st->pipe->screen;
+ struct gl_constants *c = &st->ctx->Const;
+
+ c->MaxTextureLevels
+ = _min(screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS),
+ MAX_TEXTURE_LEVELS);
+
+ c->Max3DTextureLevels
+ = _min(screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_3D_LEVELS),
+ MAX_3D_TEXTURE_LEVELS);
+
+ c->MaxCubeTextureLevels
+ = _min(screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS),
+ MAX_CUBE_TEXTURE_LEVELS);
+
+ c->MaxTextureRectSize
+ = _min(1 << (c->MaxTextureLevels - 1), MAX_TEXTURE_RECT_SIZE);
+
+ c->MaxTextureImageUnits
+ = _min(screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS),
+ MAX_TEXTURE_IMAGE_UNITS);
+
+ c->MaxVertexTextureImageUnits
+ = _min(screen->get_param(screen, PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS),
+ MAX_VERTEX_TEXTURE_IMAGE_UNITS);
+
+ c->MaxTextureCoordUnits
+ = _min(c->MaxTextureImageUnits, MAX_TEXTURE_COORD_UNITS);
+
+ c->MaxTextureUnits = _min(c->MaxTextureImageUnits, c->MaxTextureCoordUnits);
+
+ c->MaxDrawBuffers
+ = _clamp(screen->get_param(screen, PIPE_CAP_MAX_RENDER_TARGETS),
+ 1, MAX_DRAW_BUFFERS);
+
+ c->MaxLineWidth
+ = _maxf(1.0f, screen->get_paramf(screen, PIPE_CAP_MAX_LINE_WIDTH));
+ c->MaxLineWidthAA
+ = _maxf(1.0f, screen->get_paramf(screen, PIPE_CAP_MAX_LINE_WIDTH_AA));
+
+ c->MaxPointSize
+ = _maxf(1.0f, screen->get_paramf(screen, PIPE_CAP_MAX_POINT_WIDTH));
+ c->MaxPointSizeAA
+ = _maxf(1.0f, screen->get_paramf(screen, PIPE_CAP_MAX_POINT_WIDTH_AA));
+
+ c->MaxTextureMaxAnisotropy
+ = _maxf(2.0f, screen->get_paramf(screen, PIPE_CAP_MAX_TEXTURE_ANISOTROPY));
+
+ c->MaxTextureLodBias
+ = screen->get_paramf(screen, PIPE_CAP_MAX_TEXTURE_LOD_BIAS);
+
+ c->MaxDrawBuffers
+ = CLAMP(screen->get_param(screen, PIPE_CAP_MAX_RENDER_TARGETS),
+ 1, MAX_DRAW_BUFFERS);
+}
+
+
+/**
+ * Use pipe_screen::get_param() to query PIPE_CAP_ values to determine
+ * which GL extensions are supported.
+ * Quite a few extensions are always supported because they are standard
+ * features or can be built on top of other gallium features.
+ * Some fine tuning may still be needed.
+ */
+void st_init_extensions(struct st_context *st)
+{
+ struct pipe_screen *screen = st->pipe->screen;
+ GLcontext *ctx = st->ctx;
+
+ /*
+ * Extensions that are supported by all Gallium drivers:
+ */
+ ctx->Extensions.ARB_multisample = GL_TRUE;
+ ctx->Extensions.ARB_fragment_program = GL_TRUE;
+ ctx->Extensions.ARB_texture_border_clamp = GL_TRUE; /* XXX temp */
+ ctx->Extensions.ARB_texture_compression = GL_TRUE;
+ ctx->Extensions.ARB_texture_cube_map = GL_TRUE;
+ ctx->Extensions.ARB_texture_env_combine = GL_TRUE;
+ ctx->Extensions.ARB_texture_env_crossbar = GL_TRUE;
+ ctx->Extensions.ARB_texture_env_dot3 = GL_TRUE;
+ ctx->Extensions.ARB_vertex_program = GL_TRUE;
+ ctx->Extensions.ARB_vertex_buffer_object = GL_TRUE;
+
+ ctx->Extensions.EXT_blend_color = GL_TRUE;
+ ctx->Extensions.EXT_blend_equation_separate = GL_TRUE;
+ ctx->Extensions.EXT_blend_func_separate = GL_TRUE;
+ ctx->Extensions.EXT_blend_logic_op = GL_TRUE;
+ ctx->Extensions.EXT_blend_minmax = GL_TRUE;
+ ctx->Extensions.EXT_blend_subtract = GL_TRUE;
+ ctx->Extensions.EXT_framebuffer_blit = GL_TRUE;
+ ctx->Extensions.EXT_framebuffer_object = GL_TRUE;
+ ctx->Extensions.EXT_fog_coord = GL_TRUE;
+ ctx->Extensions.EXT_multi_draw_arrays = GL_TRUE;
+ ctx->Extensions.EXT_pixel_buffer_object = GL_TRUE;
+ ctx->Extensions.EXT_point_parameters = GL_TRUE;
+ ctx->Extensions.EXT_secondary_color = GL_TRUE;
+ ctx->Extensions.EXT_stencil_wrap = GL_TRUE;
+ ctx->Extensions.EXT_texture_env_add = GL_TRUE;
+ ctx->Extensions.EXT_texture_env_combine = GL_TRUE;
+ ctx->Extensions.EXT_texture_env_dot3 = GL_TRUE;
+ ctx->Extensions.EXT_texture_lod_bias = GL_TRUE;
+
+ ctx->Extensions.NV_blend_square = GL_TRUE;
+ ctx->Extensions.NV_texgen_reflection = GL_TRUE;
+
+ ctx->Extensions.SGI_color_matrix = GL_TRUE;
+ ctx->Extensions.SGIS_generate_mipmap = GL_TRUE;
+
+ /*
+ * Extensions that depend on the driver/hardware:
+ */
+ if (screen->get_param(screen, PIPE_CAP_MAX_RENDER_TARGETS) > 0) {
+ ctx->Extensions.ARB_draw_buffers = GL_TRUE;
+ }
+
+ if (screen->get_param(screen, PIPE_CAP_GLSL)) {
+ ctx->Extensions.ARB_fragment_shader = GL_TRUE;
+ ctx->Extensions.ARB_vertex_shader = GL_TRUE;
+ ctx->Extensions.ARB_shader_objects = GL_TRUE;
+ ctx->Extensions.ARB_shading_language_100 = GL_TRUE;
+ ctx->Extensions.ARB_shading_language_120 = GL_TRUE;
+ }
+
+ if (screen->get_param(screen, PIPE_CAP_TEXTURE_MIRROR_REPEAT) > 0) {
+ ctx->Extensions.ARB_texture_mirrored_repeat = GL_TRUE;
+ }
+
+ if (screen->get_param(screen, PIPE_CAP_TEXTURE_MIRROR_CLAMP) > 0) {
+ ctx->Extensions.EXT_texture_mirror_clamp = GL_TRUE;
+ }
+
+ if (screen->get_param(screen, PIPE_CAP_NPOT_TEXTURES)) {
+ ctx->Extensions.ARB_texture_non_power_of_two = GL_TRUE;
+ ctx->Extensions.NV_texture_rectangle = GL_TRUE;
+ }
+
+ if (screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS) > 1) {
+ ctx->Extensions.ARB_multitexture = GL_TRUE;
+ }
+
+ if (screen->get_param(screen, PIPE_CAP_TWO_SIDED_STENCIL)) {
+ ctx->Extensions.ATI_separate_stencil = GL_TRUE;
+ }
+
+ if (screen->get_param(screen, PIPE_CAP_ANISOTROPIC_FILTER)) {
+ ctx->Extensions.EXT_texture_filter_anisotropic = GL_TRUE;
+ }
+
+ if (screen->get_param(screen, PIPE_CAP_POINT_SPRITE)) {
+ ctx->Extensions.ARB_point_sprite = GL_TRUE;
+ ctx->Extensions.NV_point_sprite = GL_TRUE;
+ }
+
+ if (screen->get_param(screen, PIPE_CAP_OCCLUSION_QUERY)) {
+ ctx->Extensions.ARB_occlusion_query = GL_TRUE;
+ }
+
+ if (screen->get_param(screen, PIPE_CAP_TEXTURE_SHADOW_MAP)) {
+ ctx->Extensions.ARB_depth_texture = GL_TRUE;
+ ctx->Extensions.ARB_shadow = GL_TRUE;
+ ctx->Extensions.EXT_shadow_funcs = GL_TRUE;
+ /*ctx->Extensions.ARB_shadow_ambient = GL_TRUE;*/
+ }
+
+ /* GL_EXT_packed_depth_stencil requires both the ability to render to
+ * a depth/stencil buffer and texture from depth/stencil source.
+ */
+ if (screen->is_format_supported(screen, PIPE_FORMAT_Z24S8_UNORM,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0) &&
+ screen->is_format_supported(screen, PIPE_FORMAT_Z24S8_UNORM,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_SAMPLER, 0)) {
+ ctx->Extensions.EXT_packed_depth_stencil = GL_TRUE;
+ }
+ else if (screen->is_format_supported(screen, PIPE_FORMAT_S8Z24_UNORM,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0) &&
+ screen->is_format_supported(screen, PIPE_FORMAT_S8Z24_UNORM,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_SAMPLER, 0)) {
+ ctx->Extensions.EXT_packed_depth_stencil = GL_TRUE;
+ }
+
+ /* sRGB support */
+ if (screen->is_format_supported(screen, PIPE_FORMAT_R8G8B8A8_SRGB,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_SAMPLER, 0) ||
+ screen->is_format_supported(screen, PIPE_FORMAT_A8R8G8B8_SRGB,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_SAMPLER, 0)) {
+ ctx->Extensions.EXT_texture_sRGB = GL_TRUE;
+ }
+
+ /* s3tc support */
+ if (screen->is_format_supported(screen, PIPE_FORMAT_DXT5_RGBA,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_SAMPLER, 0)) {
+ ctx->Extensions.EXT_texture_compression_s3tc = GL_TRUE;
+ }
+
+ /* ycbcr support */
+ if (screen->is_format_supported(screen, PIPE_FORMAT_YCBCR,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_SAMPLER, 0) ||
+ screen->is_format_supported(screen, PIPE_FORMAT_YCBCR_REV,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_SAMPLER, 0)) {
+ ctx->Extensions.MESA_ycbcr_texture = GL_TRUE;
+ }
+}
diff --git a/src/mesa/state_tracker/st_extensions.h b/src/mesa/state_tracker/st_extensions.h
new file mode 100644
index 00000000000..2994f16dd33
--- /dev/null
+++ b/src/mesa/state_tracker/st_extensions.h
@@ -0,0 +1,38 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_EXTENSIONS_H
+#define ST_EXTENSIONS_H
+
+
+extern void st_init_limits(struct st_context *st);
+
+extern void st_init_extensions(struct st_context *st);
+
+
+#endif /* ST_EXTENSIONS_H */
diff --git a/src/mesa/state_tracker/st_format.c b/src/mesa/state_tracker/st_format.c
new file mode 100644
index 00000000000..9e2d60c9269
--- /dev/null
+++ b/src/mesa/state_tracker/st_format.c
@@ -0,0 +1,718 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright (c) 2008 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL 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.
+ *
+ **************************************************************************/
+
+
+/**
+ * Texture Image-related functions.
+ * \author Brian Paul
+ */
+
+#include "main/imports.h"
+#include "main/context.h"
+#include "main/texstore.h"
+#include "main/texformat.h"
+#include "main/enums.h"
+#include "main/macros.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_screen.h"
+#include "st_context.h"
+#include "st_format.h"
+
+static GLuint
+format_bits(
+ pipe_format_rgbazs_t info,
+ GLuint comp )
+{
+ return pf_get_component_bits( (enum pipe_format) info, comp );
+}
+
+static GLuint
+format_max_bits(
+ pipe_format_rgbazs_t info )
+{
+ GLuint size = format_bits( info, PIPE_FORMAT_COMP_R );
+
+ size = MAX2( size, format_bits( info, PIPE_FORMAT_COMP_G ) );
+ size = MAX2( size, format_bits( info, PIPE_FORMAT_COMP_B ) );
+ size = MAX2( size, format_bits( info, PIPE_FORMAT_COMP_A ) );
+ size = MAX2( size, format_bits( info, PIPE_FORMAT_COMP_Z ) );
+ size = MAX2( size, format_bits( info, PIPE_FORMAT_COMP_S ) );
+ return size;
+}
+
+static GLuint
+format_size(
+ pipe_format_rgbazs_t info )
+{
+ return
+ format_bits( info, PIPE_FORMAT_COMP_R ) +
+ format_bits( info, PIPE_FORMAT_COMP_G ) +
+ format_bits( info, PIPE_FORMAT_COMP_B ) +
+ format_bits( info, PIPE_FORMAT_COMP_A ) +
+ format_bits( info, PIPE_FORMAT_COMP_Z ) +
+ format_bits( info, PIPE_FORMAT_COMP_S );
+}
+
+/*
+ * XXX temporary here
+ */
+GLboolean
+st_get_format_info(enum pipe_format format, struct pipe_format_info *pinfo)
+{
+ if (pf_layout(format) == PIPE_FORMAT_LAYOUT_RGBAZS) {
+ pipe_format_rgbazs_t info;
+
+ info = format;
+
+#if 0
+ printf("%s\n", pf_name( format ) );
+#endif
+
+ /* Data type */
+ if (format == PIPE_FORMAT_A1R5G5B5_UNORM || format == PIPE_FORMAT_R5G6B5_UNORM) {
+ pinfo->datatype = GL_UNSIGNED_SHORT;
+ }
+ else {
+ GLuint size;
+
+ size = format_max_bits( info );
+ if (size == 8) {
+ if (pf_type(info) == PIPE_FORMAT_TYPE_UNORM)
+ pinfo->datatype = GL_UNSIGNED_BYTE;
+ else
+ pinfo->datatype = GL_BYTE;
+ }
+ else if (size == 16) {
+ if (pf_type(info) == PIPE_FORMAT_TYPE_UNORM)
+ pinfo->datatype = GL_UNSIGNED_SHORT;
+ else
+ pinfo->datatype = GL_SHORT;
+ }
+ else {
+ assert( size <= 32 );
+ if (pf_type(info) == PIPE_FORMAT_TYPE_UNORM)
+ pinfo->datatype = GL_UNSIGNED_INT;
+ else
+ pinfo->datatype = GL_INT;
+ }
+ }
+
+ /* Component bits */
+ pinfo->red_bits = format_bits( info, PIPE_FORMAT_COMP_R );
+ pinfo->green_bits = format_bits( info, PIPE_FORMAT_COMP_G );
+ pinfo->blue_bits = format_bits( info, PIPE_FORMAT_COMP_B );
+ pinfo->alpha_bits = format_bits( info, PIPE_FORMAT_COMP_A );
+ pinfo->depth_bits = format_bits( info, PIPE_FORMAT_COMP_Z );
+ pinfo->stencil_bits = format_bits( info, PIPE_FORMAT_COMP_S );
+ pinfo->luminance_bits = 0;
+ pinfo->intensity_bits = 0;
+
+ /* Format size */
+ pinfo->size = format_size( info ) / 8;
+
+ /* Luminance & Intensity bits */
+ if( pf_swizzle_x(info) == PIPE_FORMAT_COMP_R &&
+ pf_swizzle_y(info) == PIPE_FORMAT_COMP_R &&
+ pf_swizzle_z(info) == PIPE_FORMAT_COMP_R ) {
+ if( pf_swizzle_w(info) == PIPE_FORMAT_COMP_R ) {
+ pinfo->intensity_bits = pinfo->red_bits;
+ }
+ else {
+ pinfo->luminance_bits = pinfo->red_bits;
+ }
+ pinfo->red_bits = 0;
+ }
+
+ /* Base format */
+ if (pinfo->depth_bits) {
+ if (pinfo->stencil_bits) {
+ pinfo->base_format = GL_DEPTH_STENCIL_EXT;
+ }
+ else {
+ pinfo->base_format = GL_DEPTH_COMPONENT;
+ }
+ }
+ else if (pinfo->stencil_bits) {
+ pinfo->base_format = GL_STENCIL_INDEX;
+ }
+ else {
+ pinfo->base_format = GL_RGBA;
+ }
+ }
+ else if (pf_layout(format) == PIPE_FORMAT_LAYOUT_YCBCR) {
+ pinfo->base_format = GL_YCBCR_MESA;
+ pinfo->datatype = GL_UNSIGNED_SHORT;
+ pinfo->size = 2; /* two bytes per "texel" */
+ }
+ else {
+ /* compressed format? */
+ assert(0);
+ }
+
+#if 0
+ printf(
+ "ST_FORMAT: R(%u), G(%u), B(%u), A(%u), Z(%u), S(%u)\n",
+ pinfo->red_bits,
+ pinfo->green_bits,
+ pinfo->blue_bits,
+ pinfo->alpha_bits,
+ pinfo->depth_bits,
+ pinfo->stencil_bits );
+#endif
+
+ pinfo->format = format;
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Return bytes per pixel for the given format.
+ */
+GLuint
+st_sizeof_format(enum pipe_format format)
+{
+ struct pipe_format_info info;
+ if (!st_get_format_info( format, &info )) {
+ assert( 0 );
+ return 0;
+ }
+ return info.size;
+}
+
+
+/**
+ * Return bytes per pixel for the given format.
+ */
+GLenum
+st_format_datatype(enum pipe_format format)
+{
+ struct pipe_format_info info;
+ if (!st_get_format_info( format, &info )) {
+ assert( 0 );
+ return 0;
+ }
+ return info.datatype;
+}
+
+
+enum pipe_format
+st_mesa_format_to_pipe_format(GLuint mesaFormat)
+{
+ switch (mesaFormat) {
+ /* fix this */
+ case MESA_FORMAT_ARGB8888_REV:
+ case MESA_FORMAT_ARGB8888:
+ return PIPE_FORMAT_A8R8G8B8_UNORM;
+ case MESA_FORMAT_ARGB1555:
+ return PIPE_FORMAT_A1R5G5B5_UNORM;
+ case MESA_FORMAT_ARGB4444:
+ return PIPE_FORMAT_A4R4G4B4_UNORM;
+ case MESA_FORMAT_RGB565:
+ return PIPE_FORMAT_R5G6B5_UNORM;
+ case MESA_FORMAT_AL88:
+ return PIPE_FORMAT_A8L8_UNORM;
+ case MESA_FORMAT_A8:
+ return PIPE_FORMAT_A8_UNORM;
+ case MESA_FORMAT_L8:
+ return PIPE_FORMAT_L8_UNORM;
+ case MESA_FORMAT_I8:
+ return PIPE_FORMAT_I8_UNORM;
+ case MESA_FORMAT_Z16:
+ return PIPE_FORMAT_Z16_UNORM;
+ case MESA_FORMAT_Z32:
+ return PIPE_FORMAT_Z32_UNORM;
+ case MESA_FORMAT_Z24_S8:
+ return PIPE_FORMAT_Z24S8_UNORM;
+ case MESA_FORMAT_S8_Z24:
+ return PIPE_FORMAT_S8Z24_UNORM;
+ case MESA_FORMAT_YCBCR:
+ return PIPE_FORMAT_YCBCR;
+#if FEATURE_texture_s3tc
+ case MESA_FORMAT_RGB_DXT1:
+ return PIPE_FORMAT_DXT1_RGB;
+ case MESA_FORMAT_RGBA_DXT1:
+ return PIPE_FORMAT_DXT1_RGBA;
+ case MESA_FORMAT_RGBA_DXT3:
+ return PIPE_FORMAT_DXT3_RGBA;
+ case MESA_FORMAT_RGBA_DXT5:
+ return PIPE_FORMAT_DXT5_RGBA;
+#if FEATURE_EXT_texture_sRGB
+ case MESA_FORMAT_SRGB_DXT1:
+ return PIPE_FORMAT_DXT1_SRGB;
+ case MESA_FORMAT_SRGBA_DXT1:
+ return PIPE_FORMAT_DXT1_SRGBA;
+ case MESA_FORMAT_SRGBA_DXT3:
+ return PIPE_FORMAT_DXT3_SRGBA;
+ case MESA_FORMAT_SRGBA_DXT5:
+ return PIPE_FORMAT_DXT5_SRGBA;
+#endif
+#endif
+#if FEATURE_EXT_texture_sRGB
+ case MESA_FORMAT_SLA8:
+ return PIPE_FORMAT_A8L8_SRGB;
+ case MESA_FORMAT_SL8:
+ return PIPE_FORMAT_L8_SRGB;
+ case MESA_FORMAT_SRGB8:
+ return PIPE_FORMAT_R8G8B8_SRGB;
+ case MESA_FORMAT_SRGBA8:
+ return PIPE_FORMAT_R8G8B8A8_SRGB;
+ case MESA_FORMAT_SARGB8:
+ return PIPE_FORMAT_A8R8G8B8_SRGB;
+#endif
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+/**
+ * Find an RGBA format supported by the context/winsys.
+ */
+static enum pipe_format
+default_rgba_format(struct pipe_screen *screen,
+ enum pipe_texture_target target,
+ unsigned tex_usage,
+ unsigned geom_flags)
+{
+ static const enum pipe_format colorFormats[] = {
+ PIPE_FORMAT_A8R8G8B8_UNORM,
+ PIPE_FORMAT_B8G8R8A8_UNORM,
+ PIPE_FORMAT_R8G8B8A8_UNORM,
+ PIPE_FORMAT_R5G6B5_UNORM
+ };
+ uint i;
+ for (i = 0; i < Elements(colorFormats); i++) {
+ if (screen->is_format_supported( screen, colorFormats[i], target, tex_usage, geom_flags )) {
+ return colorFormats[i];
+ }
+ }
+ return PIPE_FORMAT_NONE;
+}
+
+/**
+ * Find an sRGBA format supported by the context/winsys.
+ */
+static enum pipe_format
+default_srgba_format(struct pipe_screen *screen,
+ enum pipe_texture_target target,
+ unsigned tex_usage,
+ unsigned geom_flags)
+{
+ static const enum pipe_format colorFormats[] = {
+ PIPE_FORMAT_A8R8G8B8_SRGB,
+ PIPE_FORMAT_B8G8R8A8_SRGB,
+ PIPE_FORMAT_R8G8B8A8_SRGB,
+ };
+ uint i;
+ for (i = 0; i < Elements(colorFormats); i++) {
+ if (screen->is_format_supported( screen, colorFormats[i], target, tex_usage, geom_flags )) {
+ return colorFormats[i];
+ }
+ }
+ return PIPE_FORMAT_NONE;
+}
+
+/**
+ * Search list of formats for first RGBA format with >8 bits/channel.
+ */
+static enum pipe_format
+default_deep_rgba_format(struct pipe_screen *screen,
+ enum pipe_texture_target target,
+ unsigned tex_usage,
+ unsigned geom_flags)
+{
+ if (screen->is_format_supported(screen, PIPE_FORMAT_R16G16B16A16_SNORM, target, tex_usage, geom_flags)) {
+ return PIPE_FORMAT_R16G16B16A16_SNORM;
+ }
+ if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET)
+ return default_rgba_format(screen, target, tex_usage, geom_flags);
+ else
+ return PIPE_FORMAT_NONE;
+}
+
+
+/**
+ * Find an Z format supported by the context/winsys.
+ */
+static enum pipe_format
+default_depth_format(struct pipe_screen *screen,
+ enum pipe_texture_target target,
+ unsigned tex_usage,
+ unsigned geom_flags)
+{
+ static const enum pipe_format zFormats[] = {
+ PIPE_FORMAT_Z16_UNORM,
+ PIPE_FORMAT_Z32_UNORM,
+ PIPE_FORMAT_S8Z24_UNORM,
+ PIPE_FORMAT_Z24S8_UNORM
+ };
+ uint i;
+ for (i = 0; i < Elements(zFormats); i++) {
+ if (screen->is_format_supported( screen, zFormats[i], target, tex_usage, geom_flags )) {
+ return zFormats[i];
+ }
+ }
+ return PIPE_FORMAT_NONE;
+}
+
+
+/**
+ * Given an OpenGL internalFormat value for a texture or surface, return
+ * the best matching PIPE_FORMAT_x, or PIPE_FORMAT_NONE if there's no match.
+ * \param target one of PIPE_TEXTURE_x
+ * \param tex_usage either PIPE_TEXTURE_USAGE_RENDER_TARGET
+ * or PIPE_TEXTURE_USAGE_SAMPLER
+ */
+enum pipe_format
+st_choose_format(struct pipe_context *pipe, GLint internalFormat,
+ enum pipe_texture_target target, unsigned tex_usage)
+{
+ struct pipe_screen *screen = pipe->screen;
+ unsigned geom_flags = 0;
+
+ switch (internalFormat) {
+ case 4:
+ case GL_RGBA:
+ case GL_COMPRESSED_RGBA:
+ case 3:
+ case GL_RGB:
+ case GL_COMPRESSED_RGB:
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ return default_rgba_format( screen, target, tex_usage, geom_flags );
+ case GL_RGBA16:
+ if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET)
+ return default_deep_rgba_format( screen, target, tex_usage, geom_flags );
+ else
+ return default_rgba_format( screen, target, tex_usage, geom_flags );
+
+ case GL_RGBA4:
+ case GL_RGBA2:
+ if (screen->is_format_supported( screen, PIPE_FORMAT_A4R4G4B4_UNORM, target, tex_usage, geom_flags ))
+ return PIPE_FORMAT_A4R4G4B4_UNORM;
+ return default_rgba_format( screen, target, tex_usage, geom_flags );
+
+ case GL_RGB5_A1:
+ if (screen->is_format_supported( screen, PIPE_FORMAT_A1R5G5B5_UNORM, target, tex_usage, geom_flags ))
+ return PIPE_FORMAT_A1R5G5B5_UNORM;
+ return default_rgba_format( screen, target, tex_usage, geom_flags );
+
+ case GL_RGB8:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ return default_rgba_format( screen, target, tex_usage, geom_flags );
+
+ case GL_RGB5:
+ case GL_RGB4:
+ case GL_R3_G3_B2:
+ if (screen->is_format_supported( screen, PIPE_FORMAT_A1R5G5B5_UNORM, target, tex_usage, geom_flags ))
+ return PIPE_FORMAT_A1R5G5B5_UNORM;
+ if (screen->is_format_supported( screen, PIPE_FORMAT_R5G6B5_UNORM, target, tex_usage, geom_flags ))
+ return PIPE_FORMAT_R5G6B5_UNORM;
+ return default_rgba_format( screen, target, tex_usage, geom_flags );
+
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ case GL_COMPRESSED_ALPHA:
+ if (screen->is_format_supported( screen, PIPE_FORMAT_A8_UNORM, target, tex_usage, geom_flags ))
+ return PIPE_FORMAT_A8_UNORM;
+ return default_rgba_format( screen, target, tex_usage, geom_flags );
+
+ case 1:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ case GL_COMPRESSED_LUMINANCE:
+ if (screen->is_format_supported( screen, PIPE_FORMAT_L8_UNORM, target, tex_usage, geom_flags ))
+ return PIPE_FORMAT_L8_UNORM;
+ return default_rgba_format( screen, target, tex_usage, geom_flags );
+
+ case 2:
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE4_ALPHA4:
+ case GL_LUMINANCE6_ALPHA2:
+ case GL_LUMINANCE8_ALPHA8:
+ case GL_LUMINANCE12_ALPHA4:
+ case GL_LUMINANCE12_ALPHA12:
+ case GL_LUMINANCE16_ALPHA16:
+ case GL_COMPRESSED_LUMINANCE_ALPHA:
+ if (screen->is_format_supported( screen, PIPE_FORMAT_A8L8_UNORM, target, tex_usage, geom_flags ))
+ return PIPE_FORMAT_A8L8_UNORM;
+ return default_rgba_format( screen, target, tex_usage, geom_flags );
+
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ case GL_COMPRESSED_INTENSITY:
+ if (screen->is_format_supported( screen, PIPE_FORMAT_I8_UNORM, target, tex_usage, geom_flags ))
+ return PIPE_FORMAT_I8_UNORM;
+ return default_rgba_format( screen, target, tex_usage, geom_flags );
+
+ case GL_YCBCR_MESA:
+ if (screen->is_format_supported(screen, PIPE_FORMAT_YCBCR,
+ target, tex_usage, geom_flags)) {
+ return PIPE_FORMAT_YCBCR;
+ }
+ if (screen->is_format_supported(screen, PIPE_FORMAT_YCBCR_REV,
+ target, tex_usage, geom_flags)) {
+ return PIPE_FORMAT_YCBCR_REV;
+ }
+ return PIPE_FORMAT_NONE;
+
+ case GL_RGB_S3TC:
+ case GL_RGB4_S3TC:
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ return PIPE_FORMAT_DXT1_RGB;
+
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ return PIPE_FORMAT_DXT1_RGBA;
+
+ case GL_RGBA_S3TC:
+ case GL_RGBA4_S3TC:
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+ return PIPE_FORMAT_DXT3_RGBA;
+
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ return PIPE_FORMAT_DXT5_RGBA;
+
+#if 0
+ case GL_COMPRESSED_RGB_FXT1_3DFX:
+ return PIPE_FORMAT_RGB_FXT1;
+ case GL_COMPRESSED_RGBA_FXT1_3DFX:
+ return PIPE_FORMAT_RGB_FXT1;
+#endif
+
+ case GL_DEPTH_COMPONENT16:
+ if (screen->is_format_supported( screen, PIPE_FORMAT_Z16_UNORM, target, tex_usage, geom_flags ))
+ return PIPE_FORMAT_Z16_UNORM;
+ /* fall-through */
+ case GL_DEPTH_COMPONENT24:
+ if (screen->is_format_supported( screen, PIPE_FORMAT_S8Z24_UNORM, target, tex_usage, geom_flags ))
+ return PIPE_FORMAT_S8Z24_UNORM;
+ if (screen->is_format_supported( screen, PIPE_FORMAT_Z24S8_UNORM, target, tex_usage, geom_flags ))
+ return PIPE_FORMAT_Z24S8_UNORM;
+ /* fall-through */
+ case GL_DEPTH_COMPONENT32:
+ if (screen->is_format_supported( screen, PIPE_FORMAT_Z32_UNORM, target, tex_usage, geom_flags ))
+ return PIPE_FORMAT_Z32_UNORM;
+ /* fall-through */
+ case GL_DEPTH_COMPONENT:
+ return default_depth_format( screen, target, tex_usage, geom_flags );
+
+ case GL_STENCIL_INDEX:
+ case GL_STENCIL_INDEX1_EXT:
+ case GL_STENCIL_INDEX4_EXT:
+ case GL_STENCIL_INDEX8_EXT:
+ case GL_STENCIL_INDEX16_EXT:
+ if (screen->is_format_supported( screen, PIPE_FORMAT_S8_UNORM, target, tex_usage, geom_flags ))
+ return PIPE_FORMAT_S8_UNORM;
+ if (screen->is_format_supported( screen, PIPE_FORMAT_S8Z24_UNORM, target, tex_usage, geom_flags ))
+ return PIPE_FORMAT_S8Z24_UNORM;
+ if (screen->is_format_supported( screen, PIPE_FORMAT_Z24S8_UNORM, target, tex_usage, geom_flags ))
+ return PIPE_FORMAT_Z24S8_UNORM;
+ return PIPE_FORMAT_NONE;
+
+ case GL_DEPTH_STENCIL_EXT:
+ case GL_DEPTH24_STENCIL8_EXT:
+ if (screen->is_format_supported( screen, PIPE_FORMAT_S8Z24_UNORM, target, tex_usage, geom_flags ))
+ return PIPE_FORMAT_S8Z24_UNORM;
+ if (screen->is_format_supported( screen, PIPE_FORMAT_Z24S8_UNORM, target, tex_usage, geom_flags ))
+ return PIPE_FORMAT_Z24S8_UNORM;
+ return PIPE_FORMAT_NONE;
+
+ case GL_SRGB_EXT:
+ case GL_SRGB8_EXT:
+ case GL_COMPRESSED_SRGB_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_EXT:
+ case GL_SRGB_ALPHA_EXT:
+ case GL_SRGB8_ALPHA8_EXT:
+ return default_srgba_format( screen, target, tex_usage, geom_flags );
+ case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+ return PIPE_FORMAT_DXT1_SRGB;
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+ return PIPE_FORMAT_DXT1_SRGBA;
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+ return PIPE_FORMAT_DXT3_SRGBA;
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+ return PIPE_FORMAT_DXT5_SRGBA;
+
+ case GL_SLUMINANCE_ALPHA_EXT:
+ case GL_SLUMINANCE8_ALPHA8_EXT:
+ case GL_COMPRESSED_SLUMINANCE_EXT:
+ case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT:
+ if (screen->is_format_supported( screen, PIPE_FORMAT_A8L8_SRGB, target, tex_usage, geom_flags ))
+ return PIPE_FORMAT_A8L8_SRGB;
+ return default_srgba_format( screen, target, tex_usage, geom_flags );
+
+ case GL_SLUMINANCE_EXT:
+ case GL_SLUMINANCE8_EXT:
+ if (screen->is_format_supported( screen, PIPE_FORMAT_L8_SRGB, target, tex_usage, geom_flags ))
+ return PIPE_FORMAT_L8_SRGB;
+ return default_srgba_format( screen, target, tex_usage, geom_flags );
+
+ default:
+ return PIPE_FORMAT_NONE;
+ }
+}
+
+
+static GLboolean
+is_stencil_format(GLenum format)
+{
+ switch (format) {
+ case GL_STENCIL_INDEX:
+ case GL_STENCIL_INDEX1_EXT:
+ case GL_STENCIL_INDEX4_EXT:
+ case GL_STENCIL_INDEX8_EXT:
+ case GL_STENCIL_INDEX16_EXT:
+ case GL_DEPTH_STENCIL_EXT:
+ case GL_DEPTH24_STENCIL8_EXT:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+/**
+ * Called by FBO code to choose a PIPE_FORMAT_ for drawing surfaces.
+ */
+enum pipe_format
+st_choose_renderbuffer_format(struct pipe_context *pipe, GLint internalFormat)
+{
+ uint usage;
+ if (is_stencil_format(internalFormat))
+ usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL;
+ else
+ usage = PIPE_TEXTURE_USAGE_RENDER_TARGET;
+ return st_choose_format(pipe, internalFormat, PIPE_TEXTURE_2D, usage);
+}
+
+
+static const struct gl_texture_format *
+translate_gallium_format_to_mesa_format(enum pipe_format format)
+{
+ switch (format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ return &_mesa_texformat_argb8888;
+ case PIPE_FORMAT_A1R5G5B5_UNORM:
+ return &_mesa_texformat_argb1555;
+ case PIPE_FORMAT_A4R4G4B4_UNORM:
+ return &_mesa_texformat_argb4444;
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ return &_mesa_texformat_rgb565;
+ case PIPE_FORMAT_A8L8_UNORM:
+ return &_mesa_texformat_al88;
+ case PIPE_FORMAT_A8_UNORM:
+ return &_mesa_texformat_a8;
+ case PIPE_FORMAT_L8_UNORM:
+ return &_mesa_texformat_l8;
+ case PIPE_FORMAT_I8_UNORM:
+ return &_mesa_texformat_i8;
+ case PIPE_FORMAT_Z16_UNORM:
+ return &_mesa_texformat_z16;
+ case PIPE_FORMAT_Z32_UNORM:
+ return &_mesa_texformat_z32;
+ case PIPE_FORMAT_Z24S8_UNORM:
+ return &_mesa_texformat_z24_s8;
+ case PIPE_FORMAT_S8Z24_UNORM:
+ return &_mesa_texformat_s8_z24;
+ case PIPE_FORMAT_YCBCR:
+ return &_mesa_texformat_ycbcr;
+ case PIPE_FORMAT_YCBCR_REV:
+ return &_mesa_texformat_ycbcr_rev;
+#if FEATURE_texture_s3tc
+ case PIPE_FORMAT_DXT1_RGB:
+ return &_mesa_texformat_rgb_dxt1;
+ case PIPE_FORMAT_DXT1_RGBA:
+ return &_mesa_texformat_rgba_dxt1;
+ case PIPE_FORMAT_DXT3_RGBA:
+ return &_mesa_texformat_rgba_dxt3;
+ case PIPE_FORMAT_DXT5_RGBA:
+ return &_mesa_texformat_rgba_dxt5;
+#if FEATURE_EXT_texture_sRGB
+ case PIPE_FORMAT_DXT1_SRGB:
+ return &_mesa_texformat_srgb_dxt1;
+ case PIPE_FORMAT_DXT1_SRGBA:
+ return &_mesa_texformat_srgba_dxt1;
+ case PIPE_FORMAT_DXT3_SRGBA:
+ return &_mesa_texformat_srgba_dxt3;
+ case PIPE_FORMAT_DXT5_SRGBA:
+ return &_mesa_texformat_srgba_dxt5;
+#endif
+#endif
+#if FEATURE_EXT_texture_sRGB
+ case PIPE_FORMAT_A8L8_SRGB:
+ return &_mesa_texformat_sla8;
+ case PIPE_FORMAT_L8_SRGB:
+ return &_mesa_texformat_sl8;
+ case PIPE_FORMAT_R8G8B8_SRGB:
+ return &_mesa_texformat_srgb8;
+ case PIPE_FORMAT_R8G8B8A8_SRGB:
+ return &_mesa_texformat_srgba8;
+ case PIPE_FORMAT_A8R8G8B8_SRGB:
+ return &_mesa_texformat_sargb8;
+#endif
+ /* XXX add additional cases */
+ default:
+ assert(0);
+ return NULL;
+ }
+}
+
+
+/**
+ * Called via ctx->Driver.chooseTextureFormat().
+ */
+const struct gl_texture_format *
+st_ChooseTextureFormat(GLcontext *ctx, GLint internalFormat,
+ GLenum format, GLenum type)
+{
+ enum pipe_format pFormat;
+
+ (void) format;
+ (void) type;
+
+ pFormat = st_choose_format(ctx->st->pipe, internalFormat, PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_SAMPLER);
+ if (pFormat == PIPE_FORMAT_NONE)
+ return NULL;
+
+ return translate_gallium_format_to_mesa_format(pFormat);
+}
diff --git a/src/mesa/state_tracker/st_format.h b/src/mesa/state_tracker/st_format.h
new file mode 100644
index 00000000000..3f5ac3201b1
--- /dev/null
+++ b/src/mesa/state_tracker/st_format.h
@@ -0,0 +1,79 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_FORMAT_H
+#define ST_FORMAT_H
+
+
+struct pipe_format_info
+{
+ enum pipe_format format;
+ GLenum base_format;
+ GLenum datatype;
+ GLubyte red_bits;
+ GLubyte green_bits;
+ GLubyte blue_bits;
+ GLubyte alpha_bits;
+ GLubyte luminance_bits;
+ GLubyte intensity_bits;
+ GLubyte depth_bits;
+ GLubyte stencil_bits;
+ GLubyte size; /**< in bytes */
+};
+
+
+GLboolean
+st_get_format_info(enum pipe_format format, struct pipe_format_info *pinfo);
+
+
+extern GLuint
+st_sizeof_format(enum pipe_format format);
+
+
+extern GLenum
+st_format_datatype(enum pipe_format format);
+
+
+extern enum pipe_format
+st_mesa_format_to_pipe_format(GLuint mesaFormat);
+
+
+extern enum pipe_format
+st_choose_format(struct pipe_context *pipe, GLint internalFormat,
+ enum pipe_texture_target target, unsigned tex_usage);
+
+extern enum pipe_format
+st_choose_renderbuffer_format(struct pipe_context *pipe, GLint internalFormat);
+
+
+extern const struct gl_texture_format *
+st_ChooseTextureFormat(GLcontext * ctx, GLint internalFormat,
+ GLenum format, GLenum type);
+
+
+#endif /* ST_CB_TEXIMAGE_H */
diff --git a/src/mesa/state_tracker/st_framebuffer.c b/src/mesa/state_tracker/st_framebuffer.c
new file mode 100644
index 00000000000..0d9c7b97e3d
--- /dev/null
+++ b/src/mesa/state_tracker/st_framebuffer.c
@@ -0,0 +1,333 @@
+/**************************************************************************
+ *
+ * Copyright 2003 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.
+ *
+ **************************************************************************/
+
+
+#include "main/imports.h"
+#include "main/buffers.h"
+#include "main/context.h"
+#include "main/framebuffer.h"
+#include "main/matrix.h"
+#include "main/renderbuffer.h"
+#include "main/scissor.h"
+#include "st_context.h"
+#include "st_cb_fbo.h"
+#include "st_public.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_context.h"
+#include "pipe/p_inlines.h"
+
+
+struct st_framebuffer *
+st_create_framebuffer( const __GLcontextModes *visual,
+ enum pipe_format colorFormat,
+ enum pipe_format depthFormat,
+ enum pipe_format stencilFormat,
+ uint width, uint height,
+ void *private)
+{
+ struct st_framebuffer *stfb = CALLOC_STRUCT(st_framebuffer);
+ if (stfb) {
+ int samples = st_get_msaa();
+
+ if (visual->sampleBuffers)
+ samples = visual->samples;
+
+ _mesa_initialize_framebuffer(&stfb->Base, visual);
+
+ {
+ /* fake frontbuffer */
+ /* XXX allocation should only happen in the unusual case
+ it's actually needed */
+ struct gl_renderbuffer *rb
+ = st_new_renderbuffer_fb(colorFormat, samples);
+ _mesa_add_renderbuffer(&stfb->Base, BUFFER_FRONT_LEFT, rb);
+ }
+
+ if (visual->doubleBufferMode) {
+ struct gl_renderbuffer *rb
+ = st_new_renderbuffer_fb(colorFormat, samples);
+ _mesa_add_renderbuffer(&stfb->Base, BUFFER_BACK_LEFT, rb);
+ }
+
+ if (depthFormat == stencilFormat && depthFormat != PIPE_FORMAT_NONE) {
+ /* combined depth/stencil buffer */
+ struct gl_renderbuffer *depthStencilRb
+ = st_new_renderbuffer_fb(depthFormat, samples);
+ /* note: bind RB to two attachment points */
+ _mesa_add_renderbuffer(&stfb->Base, BUFFER_DEPTH, depthStencilRb);
+ _mesa_add_renderbuffer(&stfb->Base, BUFFER_STENCIL, depthStencilRb);
+ }
+ else {
+ /* separate depth and/or stencil */
+
+ if (visual->depthBits == 32) {
+ /* 32-bit depth buffer */
+ struct gl_renderbuffer *depthRb
+ = st_new_renderbuffer_fb(depthFormat, samples);
+ _mesa_add_renderbuffer(&stfb->Base, BUFFER_DEPTH, depthRb);
+ }
+ else if (visual->depthBits == 24) {
+ /* 24-bit depth buffer, ignore stencil bits */
+ struct gl_renderbuffer *depthRb
+ = st_new_renderbuffer_fb(depthFormat, samples);
+ _mesa_add_renderbuffer(&stfb->Base, BUFFER_DEPTH, depthRb);
+ }
+ else if (visual->depthBits > 0) {
+ /* 16-bit depth buffer */
+ struct gl_renderbuffer *depthRb
+ = st_new_renderbuffer_fb(depthFormat, samples);
+ _mesa_add_renderbuffer(&stfb->Base, BUFFER_DEPTH, depthRb);
+ }
+
+ if (visual->stencilBits > 0) {
+ /* 8-bit stencil */
+ struct gl_renderbuffer *stencilRb
+ = st_new_renderbuffer_fb(stencilFormat, samples);
+ _mesa_add_renderbuffer(&stfb->Base, BUFFER_STENCIL, stencilRb);
+ }
+ }
+
+ if (visual->accumRedBits > 0) {
+ /* 16-bit/channel accum */
+ struct gl_renderbuffer *accumRb
+ = st_new_renderbuffer_fb(DEFAULT_ACCUM_PIPE_FORMAT, 0); /* XXX accum isn't multisampled right? */
+ _mesa_add_renderbuffer(&stfb->Base, BUFFER_ACCUM, accumRb);
+ }
+
+ stfb->Base.Initialized = GL_TRUE;
+ stfb->InitWidth = width;
+ stfb->InitHeight = height;
+ stfb->Private = private;
+ }
+ return stfb;
+}
+
+
+void st_resize_framebuffer( struct st_framebuffer *stfb,
+ uint width, uint height )
+{
+ if (stfb->Base.Width != width || stfb->Base.Height != height) {
+ GET_CURRENT_CONTEXT(ctx);
+ if (ctx) {
+ if (stfb->InitWidth == 0 && stfb->InitHeight == 0) {
+ /* didn't have a valid size until now */
+ stfb->InitWidth = width;
+ stfb->InitHeight = height;
+ if (ctx->Viewport.Width <= 1) {
+ /* set context's initial viewport/scissor size */
+ _mesa_set_viewport(ctx, 0, 0, width, height);
+ _mesa_set_scissor(ctx, 0, 0, width, height);
+ }
+ }
+
+ _mesa_resize_framebuffer(ctx, &stfb->Base, width, height);
+
+ assert(stfb->Base.Width == width);
+ assert(stfb->Base.Height == height);
+ }
+ }
+}
+
+
+void st_unreference_framebuffer( struct st_framebuffer *stfb )
+{
+ _mesa_unreference_framebuffer((struct gl_framebuffer **) &stfb);
+}
+
+
+
+/**
+ * Set/replace a framebuffer surface.
+ * The user of the state tracker can use this instead of
+ * st_resize_framebuffer() to provide new surfaces when a window is resized.
+ */
+void
+st_set_framebuffer_surface(struct st_framebuffer *stfb,
+ uint surfIndex, struct pipe_surface *surf)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ static const GLuint invalid_size = 9999999;
+ struct st_renderbuffer *strb;
+ GLuint width, height, i;
+
+ assert(surfIndex < BUFFER_COUNT);
+
+ strb = st_renderbuffer(stfb->Base.Attachment[surfIndex].Renderbuffer);
+
+ /* fail */
+ if (!strb) return;
+
+ /* replace the renderbuffer's surface/texture pointers */
+ pipe_surface_reference( &strb->surface, surf );
+ pipe_texture_reference( &strb->texture, surf->texture );
+
+ if (ctx) {
+ /* If ctx isn't set, we've likely not made current yet.
+ * But when we do, we need to start setting this dirty bit
+ * to ensure the renderbuffer attachements are up-to-date
+ * via update_framebuffer.
+ */
+ ctx->st->dirty.st |= ST_NEW_FRAMEBUFFER;
+ }
+
+ /* update renderbuffer's width/height */
+ strb->Base.Width = surf->width;
+ strb->Base.Height = surf->height;
+
+ /* Try to update the framebuffer's width/height from the renderbuffer
+ * sizes. Before we start drawing, all the rbs _should_ be the same size.
+ */
+ width = height = invalid_size;
+ for (i = 0; i < BUFFER_COUNT; i++) {
+ if (stfb->Base.Attachment[i].Renderbuffer) {
+ if (width == invalid_size) {
+ width = stfb->Base.Attachment[i].Renderbuffer->Width;
+ height = stfb->Base.Attachment[i].Renderbuffer->Height;
+ }
+ else if (width != stfb->Base.Attachment[i].Renderbuffer->Width ||
+ height != stfb->Base.Attachment[i].Renderbuffer->Height) {
+ /* inconsistant renderbuffer sizes, bail out */
+ return;
+ }
+ }
+ }
+
+ if (width != invalid_size) {
+ /* OK, the renderbuffers are of a consistant size, so update the
+ * parent framebuffer's size.
+ */
+ stfb->Base.Width = width;
+ stfb->Base.Height = height;
+ }
+}
+
+
+
+/**
+ * Return the pipe_surface for the given renderbuffer.
+ */
+int
+st_get_framebuffer_surface(struct st_framebuffer *stfb, uint surfIndex, struct pipe_surface **surface)
+{
+ struct st_renderbuffer *strb;
+
+ assert(surfIndex <= ST_SURFACE_DEPTH);
+
+ /* sanity checks, ST tokens should match Mesa tokens */
+ assert(ST_SURFACE_FRONT_LEFT == BUFFER_FRONT_LEFT);
+ assert(ST_SURFACE_BACK_RIGHT == BUFFER_BACK_RIGHT);
+
+ strb = st_renderbuffer(stfb->Base.Attachment[surfIndex].Renderbuffer);
+ if (strb) {
+ *surface = strb->surface;
+ return GL_TRUE;
+ }
+
+ *surface = NULL;
+ return GL_FALSE;
+}
+
+int
+st_get_framebuffer_texture(struct st_framebuffer *stfb, uint surfIndex, struct pipe_texture **texture)
+{
+ struct st_renderbuffer *strb;
+
+ assert(surfIndex <= ST_SURFACE_DEPTH);
+
+ /* sanity checks, ST tokens should match Mesa tokens */
+ assert(ST_SURFACE_FRONT_LEFT == BUFFER_FRONT_LEFT);
+ assert(ST_SURFACE_BACK_RIGHT == BUFFER_BACK_RIGHT);
+
+ strb = st_renderbuffer(stfb->Base.Attachment[surfIndex].Renderbuffer);
+ if (strb) {
+ *texture = strb->texture;
+ return GL_TRUE;
+ }
+
+ *texture = NULL;
+ return GL_FALSE;
+}
+
+/**
+ * This function is to be called prior to SwapBuffers on the given
+ * framebuffer. It checks if the current context is bound to the framebuffer
+ * and flushes rendering if needed.
+ */
+void
+st_notify_swapbuffers(struct st_framebuffer *stfb)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (ctx && ctx->DrawBuffer == &stfb->Base) {
+ st_flush( ctx->st,
+ PIPE_FLUSH_RENDER_CACHE |
+ PIPE_FLUSH_SWAPBUFFERS |
+ PIPE_FLUSH_FRAME,
+ NULL );
+ ctx->st->frontbuffer_status = FRONT_STATUS_COPY_OF_BACK;
+ }
+}
+
+
+/**
+ * Quick hack - allows the winsys to inform the driver that surface
+ * states are now undefined after a glXSwapBuffers or similar.
+ */
+void
+st_notify_swapbuffers_complete(struct st_framebuffer *stfb)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (ctx && ctx->DrawBuffer == &stfb->Base) {
+ struct st_renderbuffer *strb;
+
+ /* Mark back color buffers as undefined */
+ strb = st_renderbuffer(stfb->Base.Attachment[BUFFER_BACK_LEFT].
+ Renderbuffer);
+ if (strb && strb->surface)
+ strb->surface->status = PIPE_SURFACE_STATUS_UNDEFINED;
+
+ strb = st_renderbuffer(stfb->Base.Attachment[BUFFER_BACK_RIGHT].
+ Renderbuffer);
+ if (strb && strb->surface)
+ strb->surface->status = PIPE_SURFACE_STATUS_UNDEFINED;
+ }
+}
+
+
+void *st_framebuffer_private( struct st_framebuffer *stfb )
+{
+ return stfb->Private;
+}
+
+void st_get_framebuffer_dimensions( struct st_framebuffer *stfb,
+ uint *width,
+ uint *height)
+{
+ *width = stfb->Base.Width;
+ *height = stfb->Base.Height;
+}
diff --git a/src/mesa/state_tracker/st_gen_mipmap.c b/src/mesa/state_tracker/st_gen_mipmap.c
new file mode 100644
index 00000000000..6a3455aaba2
--- /dev/null
+++ b/src/mesa/state_tracker/st_gen_mipmap.c
@@ -0,0 +1,209 @@
+/**************************************************************************
+ *
+ * Copyright 2008 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.
+ *
+ **************************************************************************/
+
+
+#include "main/imports.h"
+#include "main/mipmap.h"
+#include "main/teximage.h"
+#include "main/texformat.h"
+
+#include "shader/prog_instruction.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "util/u_gen_mipmap.h"
+
+#include "cso_cache/cso_cache.h"
+#include "cso_cache/cso_context.h"
+
+#include "st_context.h"
+#include "st_draw.h"
+#include "st_gen_mipmap.h"
+#include "st_program.h"
+#include "st_texture.h"
+#include "st_cb_texture.h"
+
+
+/**
+ * one-time init for generate mipmap
+ * XXX Note: there may be other times we need no-op/simple state like this.
+ * In that case, some code refactoring would be good.
+ */
+void
+st_init_generate_mipmap(struct st_context *st)
+{
+ st->gen_mipmap = util_create_gen_mipmap(st->pipe, st->cso_context);
+}
+
+
+void
+st_destroy_generate_mipmap(struct st_context *st)
+{
+ util_destroy_gen_mipmap(st->gen_mipmap);
+ st->gen_mipmap = NULL;
+}
+
+
+/**
+ * Generate mipmap levels using hardware rendering.
+ * \return TRUE if successful, FALSE if not possible
+ */
+static boolean
+st_render_mipmap(struct st_context *st,
+ GLenum target,
+ struct pipe_texture *pt,
+ uint baseLevel, uint lastLevel)
+{
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ const uint face = _mesa_tex_target_to_face(target);
+
+ assert(target != GL_TEXTURE_3D); /* not done yet */
+
+ /* check if we can render in the texture's format */
+ if (!screen->is_format_supported(screen, pt->format, target,
+ PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) {
+ return FALSE;
+ }
+
+ util_gen_mipmap(st->gen_mipmap, pt, face, baseLevel, lastLevel,
+ PIPE_TEX_FILTER_LINEAR);
+
+ return TRUE;
+}
+
+
+static void
+fallback_generate_mipmap(GLcontext *ctx, GLenum target,
+ struct gl_texture_object *texObj)
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_texture *pt = st_get_texobj_texture(texObj);
+ const uint baseLevel = texObj->BaseLevel;
+ const uint lastLevel = pt->last_level;
+ const uint face = _mesa_tex_target_to_face(target), zslice = 0;
+ uint dstLevel;
+ GLenum datatype;
+ GLuint comps;
+
+ assert(target != GL_TEXTURE_3D); /* not done yet */
+
+ _mesa_format_to_type_and_comps(texObj->Image[face][baseLevel]->TexFormat,
+ &datatype, &comps);
+
+ for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
+ const uint srcLevel = dstLevel - 1;
+ struct pipe_surface *srcSurf, *dstSurf;
+ const ubyte *srcData;
+ ubyte *dstData;
+
+ srcSurf = screen->get_tex_surface(screen, pt, face, srcLevel, zslice,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ dstSurf = screen->get_tex_surface(screen, pt, face, dstLevel, zslice,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+
+ srcData = (ubyte *) pipe_surface_map(srcSurf,
+ PIPE_BUFFER_USAGE_CPU_READ)
+ + srcSurf->offset;
+ dstData = (ubyte *) pipe_surface_map(dstSurf,
+ PIPE_BUFFER_USAGE_CPU_WRITE)
+ + dstSurf->offset;
+
+ _mesa_generate_mipmap_level(target, datatype, comps,
+ 0 /*border*/,
+ pt->width[srcLevel], pt->height[srcLevel], pt->depth[srcLevel],
+ srcData,
+ srcSurf->stride, /* stride in bytes */
+ pt->width[dstLevel], pt->height[dstLevel], pt->depth[dstLevel],
+ dstData,
+ dstSurf->stride); /* stride in bytes */
+
+ pipe_surface_unmap(srcSurf);
+ pipe_surface_unmap(dstSurf);
+
+ pipe_surface_reference(&srcSurf, NULL);
+ pipe_surface_reference(&dstSurf, NULL);
+ }
+}
+
+
+void
+st_generate_mipmap(GLcontext *ctx, GLenum target,
+ struct gl_texture_object *texObj)
+{
+ struct st_context *st = ctx->st;
+ struct pipe_texture *pt = st_get_texobj_texture(texObj);
+ const uint baseLevel = texObj->BaseLevel;
+ uint lastLevel;
+ uint dstLevel;
+
+ if (!pt)
+ return;
+
+ lastLevel = pt->last_level;
+
+ if (!st_render_mipmap(st, target, pt, baseLevel, lastLevel)) {
+ fallback_generate_mipmap(ctx, target, texObj);
+ }
+
+ /* Fill in the Mesa gl_texture_image fields */
+ for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
+ const uint srcLevel = dstLevel - 1;
+ const struct gl_texture_image *srcImage
+ = _mesa_get_tex_image(ctx, texObj, target, srcLevel);
+ struct gl_texture_image *dstImage;
+ struct st_texture_image *stImage;
+ uint dstWidth = pt->width[dstLevel];
+ uint dstHeight = pt->height[dstLevel];
+ uint dstDepth = pt->depth[dstLevel];
+ uint border = srcImage->Border;
+
+ dstImage = _mesa_get_tex_image(ctx, texObj, target, dstLevel);
+ if (!dstImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
+ return;
+ }
+
+ if (dstImage->ImageOffsets)
+ _mesa_free(dstImage->ImageOffsets);
+
+ /* Free old image data */
+ if (dstImage->Data)
+ ctx->Driver.FreeTexImageData(ctx, dstImage);
+
+ /* initialize new image */
+ _mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight,
+ dstDepth, border, srcImage->InternalFormat);
+
+ dstImage->TexFormat = srcImage->TexFormat;
+
+ stImage = (struct st_texture_image *) dstImage;
+ pipe_texture_reference(&stImage->pt, pt);
+ }
+}
diff --git a/src/mesa/state_tracker/st_gen_mipmap.h b/src/mesa/state_tracker/st_gen_mipmap.h
new file mode 100644
index 00000000000..00fbae93026
--- /dev/null
+++ b/src/mesa/state_tracker/st_gen_mipmap.h
@@ -0,0 +1,46 @@
+/**************************************************************************
+ *
+ * Copyright 2008 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.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_GEN_MIPMAP_H
+#define ST_GEN_MIPMAP_H
+
+
+extern void
+st_init_generate_mipmap(struct st_context *st);
+
+
+extern void
+st_destroy_generate_mipmap(struct st_context *st);
+
+
+extern void
+st_generate_mipmap(GLcontext *ctx, GLenum target,
+ struct gl_texture_object *texObj);
+
+
+#endif /* ST_GEN_MIPMAP_H */
diff --git a/src/mesa/state_tracker/st_mesa_to_tgsi.c b/src/mesa/state_tracker/st_mesa_to_tgsi.c
new file mode 100644
index 00000000000..5b5707fa1c5
--- /dev/null
+++ b/src/mesa/state_tracker/st_mesa_to_tgsi.c
@@ -0,0 +1,1041 @@
+/**************************************************************************
+ *
+ * Copyright 2007-2008 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.
+ *
+ **************************************************************************/
+
+/*
+ * \author
+ * Michal Krol
+ */
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_build.h"
+#include "tgsi/tgsi_util.h"
+#include "tgsi/tgsi_dump.h"
+#include "tgsi/tgsi_sanity.h"
+#include "st_mesa_to_tgsi.h"
+#include "shader/prog_instruction.h"
+#include "shader/prog_parameter.h"
+#include "shader/prog_print.h"
+#include "pipe/p_debug.h"
+
+/*
+ * Map mesa register file to TGSI register file.
+ */
+static GLuint
+map_register_file(
+ enum register_file file,
+ GLuint index,
+ const GLuint immediateMapping[],
+ GLboolean indirectAccess )
+{
+ switch( file ) {
+ case PROGRAM_UNDEFINED:
+ return TGSI_FILE_NULL;
+ case PROGRAM_TEMPORARY:
+ return TGSI_FILE_TEMPORARY;
+ /*case PROGRAM_LOCAL_PARAM:*/
+ /*case PROGRAM_ENV_PARAM:*/
+
+ /* Because of the longstanding problem with mesa arb shaders
+ * where constants, immediates and state variables are all
+ * bundled together as PROGRAM_STATE_VAR, we can't tell from the
+ * mesa register file whether this is a CONSTANT or an
+ * IMMEDIATE, hence we need all the other information.
+ */
+ case PROGRAM_STATE_VAR:
+ case PROGRAM_NAMED_PARAM:
+ case PROGRAM_UNIFORM:
+ if (!indirectAccess && immediateMapping && immediateMapping[index] != ~0)
+ return TGSI_FILE_IMMEDIATE;
+ else
+ return TGSI_FILE_CONSTANT;
+ case PROGRAM_CONSTANT:
+ if (indirectAccess)
+ return TGSI_FILE_CONSTANT;
+ assert(immediateMapping[index] != ~0);
+ return TGSI_FILE_IMMEDIATE;
+ case PROGRAM_INPUT:
+ return TGSI_FILE_INPUT;
+ case PROGRAM_OUTPUT:
+ return TGSI_FILE_OUTPUT;
+ case PROGRAM_ADDRESS:
+ return TGSI_FILE_ADDRESS;
+ default:
+ assert( 0 );
+ return TGSI_FILE_NULL;
+ }
+}
+
+/**
+ * Map mesa register file index to TGSI index.
+ * Take special care when processing input and output indices.
+ * \param file one of TGSI_FILE_x
+ * \param index the mesa register file index
+ * \param inputMapping maps Mesa input indexes to TGSI input indexes
+ * \param outputMapping maps Mesa output indexes to TGSI output indexes
+ */
+static GLuint
+map_register_file_index(
+ GLuint file,
+ GLuint index,
+ const GLuint inputMapping[],
+ const GLuint outputMapping[],
+ const GLuint immediateMapping[],
+ GLboolean indirectAccess )
+{
+ switch( file ) {
+ case TGSI_FILE_INPUT:
+ /* inputs are mapped according to the user-defined map */
+ return inputMapping[index];
+
+ case TGSI_FILE_OUTPUT:
+ return outputMapping[index];
+
+ case TGSI_FILE_IMMEDIATE:
+ if (indirectAccess)
+ return index;
+ assert(immediateMapping[index] != ~0);
+ return immediateMapping[index];
+
+ default:
+ return index;
+ }
+}
+
+/*
+ * Map mesa texture target to TGSI texture target.
+ */
+static GLuint
+map_texture_target(
+ GLuint textarget )
+{
+ switch( textarget ) {
+ case TEXTURE_1D_INDEX:
+ return TGSI_TEXTURE_1D;
+ case TEXTURE_2D_INDEX:
+ return TGSI_TEXTURE_2D;
+ case TEXTURE_3D_INDEX:
+ return TGSI_TEXTURE_3D;
+ case TEXTURE_CUBE_INDEX:
+ return TGSI_TEXTURE_CUBE;
+ case TEXTURE_RECT_INDEX:
+ return TGSI_TEXTURE_RECT;
+ default:
+ assert( 0 );
+ }
+
+ return TGSI_TEXTURE_1D;
+}
+
+static GLuint
+convert_sat(
+ GLuint sat )
+{
+ switch( sat ) {
+ case SATURATE_OFF:
+ return TGSI_SAT_NONE;
+ case SATURATE_ZERO_ONE:
+ return TGSI_SAT_ZERO_ONE;
+ case SATURATE_PLUS_MINUS_ONE:
+ return TGSI_SAT_MINUS_PLUS_ONE;
+ default:
+ assert( 0 );
+ return TGSI_SAT_NONE;
+ }
+}
+
+static GLuint
+convert_writemask(
+ GLuint writemask )
+{
+ assert( WRITEMASK_X == TGSI_WRITEMASK_X );
+ assert( WRITEMASK_Y == TGSI_WRITEMASK_Y );
+ assert( WRITEMASK_Z == TGSI_WRITEMASK_Z );
+ assert( WRITEMASK_W == TGSI_WRITEMASK_W );
+ assert( (writemask & ~TGSI_WRITEMASK_XYZW) == 0 );
+
+ return writemask;
+}
+
+static struct tgsi_full_immediate
+make_immediate(const float *value, uint size)
+{
+ struct tgsi_full_immediate imm;
+
+ imm = tgsi_default_full_immediate();
+ imm.Immediate.Size += size;
+ imm.Immediate.DataType = TGSI_IMM_FLOAT32;
+ imm.u.Pointer = value;
+ return imm;
+}
+
+static void
+compile_instruction(
+ const struct prog_instruction *inst,
+ struct tgsi_full_instruction *fullinst,
+ const GLuint inputMapping[],
+ const GLuint outputMapping[],
+ const GLuint immediateMapping[],
+ GLboolean indirectAccess,
+ GLuint preamble_size,
+ GLuint processor,
+ GLboolean *insideSubroutine)
+{
+ GLuint i;
+ struct tgsi_full_dst_register *fulldst;
+ struct tgsi_full_src_register *fullsrc;
+
+ *fullinst = tgsi_default_full_instruction();
+
+ fullinst->Instruction.Saturate = convert_sat( inst->SaturateMode );
+ fullinst->Instruction.NumDstRegs = _mesa_num_inst_dst_regs( inst->Opcode );
+ fullinst->Instruction.NumSrcRegs = _mesa_num_inst_src_regs( inst->Opcode );
+
+ fulldst = &fullinst->FullDstRegisters[0];
+ fulldst->DstRegister.File = map_register_file( inst->DstReg.File, 0, NULL, GL_FALSE );
+ fulldst->DstRegister.Index = map_register_file_index(
+ fulldst->DstRegister.File,
+ inst->DstReg.Index,
+ inputMapping,
+ outputMapping,
+ NULL,
+ GL_FALSE );
+ fulldst->DstRegister.WriteMask = convert_writemask( inst->DstReg.WriteMask );
+
+ for (i = 0; i < fullinst->Instruction.NumSrcRegs; i++) {
+ GLuint j;
+
+ fullsrc = &fullinst->FullSrcRegisters[i];
+ fullsrc->SrcRegister.File = map_register_file(
+ inst->SrcReg[i].File,
+ inst->SrcReg[i].Index,
+ immediateMapping,
+ indirectAccess );
+ fullsrc->SrcRegister.Index = map_register_file_index(
+ fullsrc->SrcRegister.File,
+ inst->SrcReg[i].Index,
+ inputMapping,
+ outputMapping,
+ immediateMapping,
+ indirectAccess );
+
+
+ /* swizzle (ext swizzle also depends on negation) */
+ {
+ GLuint swz[4];
+ GLboolean extended = (inst->SrcReg[i].NegateBase != NEGATE_NONE &&
+ inst->SrcReg[i].NegateBase != NEGATE_XYZW);
+ for( j = 0; j < 4; j++ ) {
+ swz[j] = GET_SWZ( inst->SrcReg[i].Swizzle, j );
+ if (swz[j] > SWIZZLE_W)
+ extended = GL_TRUE;
+ }
+ if (extended) {
+ for (j = 0; j < 4; j++) {
+ tgsi_util_set_src_register_extswizzle(&fullsrc->SrcRegisterExtSwz,
+ swz[j], j);
+ }
+ }
+ else {
+ for (j = 0; j < 4; j++) {
+ tgsi_util_set_src_register_swizzle(&fullsrc->SrcRegister,
+ swz[j], j);
+ }
+ }
+ }
+
+ if( inst->SrcReg[i].NegateBase == NEGATE_XYZW ) {
+ fullsrc->SrcRegister.Negate = 1;
+ }
+ else if( inst->SrcReg[i].NegateBase != NEGATE_NONE ) {
+ if( inst->SrcReg[i].NegateBase & NEGATE_X ) {
+ fullsrc->SrcRegisterExtSwz.NegateX = 1;
+ }
+ if( inst->SrcReg[i].NegateBase & NEGATE_Y ) {
+ fullsrc->SrcRegisterExtSwz.NegateY = 1;
+ }
+ if( inst->SrcReg[i].NegateBase & NEGATE_Z ) {
+ fullsrc->SrcRegisterExtSwz.NegateZ = 1;
+ }
+ if( inst->SrcReg[i].NegateBase & NEGATE_W ) {
+ fullsrc->SrcRegisterExtSwz.NegateW = 1;
+ }
+ }
+
+ if( inst->SrcReg[i].Abs ) {
+ fullsrc->SrcRegisterExtMod.Absolute = 1;
+ }
+
+ if( inst->SrcReg[i].NegateAbs ) {
+ fullsrc->SrcRegisterExtMod.Negate = 1;
+ }
+
+ if( inst->SrcReg[i].RelAddr ) {
+ fullsrc->SrcRegister.Indirect = 1;
+
+ fullsrc->SrcRegisterInd.File = TGSI_FILE_ADDRESS;
+ fullsrc->SrcRegisterInd.Index = 0;
+ }
+ }
+
+ switch( inst->Opcode ) {
+ case OPCODE_ARL:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_ARL;
+ break;
+ case OPCODE_ABS:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_ABS;
+ break;
+ case OPCODE_ADD:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_ADD;
+ break;
+ case OPCODE_BGNLOOP:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_BGNLOOP2;
+ fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size;
+ break;
+ case OPCODE_BGNSUB:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_BGNSUB;
+ *insideSubroutine = GL_TRUE;
+ break;
+ case OPCODE_BRA:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_BRA;
+ break;
+ case OPCODE_BRK:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_BRK;
+ break;
+ case OPCODE_CAL:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_CAL;
+ fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size;
+ break;
+ case OPCODE_CMP:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_CMP;
+ break;
+ case OPCODE_CONT:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_CONT;
+ break;
+ case OPCODE_COS:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_COS;
+ break;
+ case OPCODE_DDX:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_DDX;
+ break;
+ case OPCODE_DDY:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_DDY;
+ break;
+ case OPCODE_DP2:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_DP2;
+ break;
+ case OPCODE_DP2A:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_DP2A;
+ break;
+ case OPCODE_DP3:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_DP3;
+ break;
+ case OPCODE_DP4:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_DP4;
+ break;
+ case OPCODE_DPH:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_DPH;
+ break;
+ case OPCODE_DST:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_DST;
+ break;
+ case OPCODE_ELSE:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_ELSE;
+ fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size;
+ break;
+ case OPCODE_ENDIF:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_ENDIF;
+ break;
+ case OPCODE_ENDLOOP:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_ENDLOOP2;
+ fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size;
+ break;
+ case OPCODE_ENDSUB:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_ENDSUB;
+ *insideSubroutine = GL_FALSE;
+ break;
+ case OPCODE_EX2:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_EX2;
+ break;
+ case OPCODE_EXP:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_EXP;
+ break;
+ case OPCODE_FLR:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_FLR;
+ break;
+ case OPCODE_FRC:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_FRC;
+ break;
+ case OPCODE_IF:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_IF;
+ fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size;
+ break;
+ case OPCODE_TRUNC:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_TRUNC;
+ break;
+ case OPCODE_KIL:
+ /* conditional */
+ fullinst->Instruction.Opcode = TGSI_OPCODE_KIL;
+ break;
+ case OPCODE_KIL_NV:
+ /* predicated */
+ assert(inst->DstReg.CondMask == COND_TR);
+ fullinst->Instruction.Opcode = TGSI_OPCODE_KILP;
+ break;
+ case OPCODE_LG2:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_LG2;
+ break;
+ case OPCODE_LOG:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_LOG;
+ break;
+ case OPCODE_LIT:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_LIT;
+ break;
+ case OPCODE_LRP:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_LRP;
+ break;
+ case OPCODE_MAD:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_MAD;
+ break;
+ case OPCODE_MAX:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_MAX;
+ break;
+ case OPCODE_MIN:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_MIN;
+ break;
+ case OPCODE_MOV:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_MOV;
+ break;
+ case OPCODE_MUL:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_MUL;
+ break;
+ case OPCODE_NOISE1:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE1;
+ break;
+ case OPCODE_NOISE2:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE2;
+ break;
+ case OPCODE_NOISE3:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE3;
+ break;
+ case OPCODE_NOISE4:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE4;
+ break;
+ case OPCODE_NOP:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_NOP;
+ break;
+ case OPCODE_NRM3:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_NRM;
+ break;
+ case OPCODE_NRM4:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_NRM4;
+ break;
+ case OPCODE_POW:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_POW;
+ break;
+ case OPCODE_RCP:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_RCP;
+ break;
+ case OPCODE_RET:
+ /* If RET is used inside main (not a real subroutine) we may want
+ * to execute END instead of RET. TBD...
+ */
+ if (1 /* *insideSubroutine */) {
+ fullinst->Instruction.Opcode = TGSI_OPCODE_RET;
+ }
+ else {
+ /* inside main() pseudo-function */
+ fullinst->Instruction.Opcode = TGSI_OPCODE_END;
+ }
+ break;
+ case OPCODE_RSQ:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_RSQ;
+
+ /* KW: Don't do this here. If particular hardware needs to do
+ * this, can do so in the driver..
+ */
+#if 0
+ tgsi_util_set_full_src_register_sign_mode(
+ &fullinst->FullSrcRegisters[0],
+ TGSI_UTIL_SIGN_CLEAR );
+#endif
+ break;
+ case OPCODE_SCS:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_SCS;
+ fulldst->DstRegister.WriteMask &= TGSI_WRITEMASK_XY;
+ break;
+ case OPCODE_SEQ:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_SEQ;
+ break;
+ case OPCODE_SGE:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_SGE;
+ break;
+ case OPCODE_SGT:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_SGT;
+ break;
+ case OPCODE_SIN:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_SIN;
+ break;
+ case OPCODE_SLE:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_SLE;
+ break;
+ case OPCODE_SLT:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_SLT;
+ break;
+ case OPCODE_SNE:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_SNE;
+ break;
+ case OPCODE_SSG:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_SSG;
+ break;
+ case OPCODE_SUB:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_SUB;
+ break;
+ case OPCODE_SWZ:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_SWZ;
+ break;
+ case OPCODE_TEX:
+ /* ordinary texture lookup */
+ fullinst->Instruction.Opcode = TGSI_OPCODE_TEX;
+ fullinst->Instruction.NumSrcRegs = 2;
+ fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
+ fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
+ fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
+ break;
+ case OPCODE_TXB:
+ /* texture lookup with LOD bias */
+ fullinst->Instruction.Opcode = TGSI_OPCODE_TXB;
+ fullinst->Instruction.NumSrcRegs = 2;
+ fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
+ fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
+ fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
+ break;
+ case OPCODE_TXD:
+ /* texture lookup with explicit partial derivatives */
+ fullinst->Instruction.Opcode = TGSI_OPCODE_TXD;
+ fullinst->Instruction.NumSrcRegs = 4;
+ fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
+ /* src[0] = coord, src[1] = d[strq]/dx, src[2] = d[strq]/dy */
+ fullinst->FullSrcRegisters[3].SrcRegister.File = TGSI_FILE_SAMPLER;
+ fullinst->FullSrcRegisters[3].SrcRegister.Index = inst->TexSrcUnit;
+ break;
+ case OPCODE_TXL:
+ /* texture lookup with explicit LOD */
+ fullinst->Instruction.Opcode = TGSI_OPCODE_TXL;
+ fullinst->Instruction.NumSrcRegs = 2;
+ fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
+ fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
+ fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
+ break;
+ case OPCODE_TXP:
+ /* texture lookup with divide by Q component */
+ /* convert to TEX w/ special flag for division */
+ fullinst->Instruction.Opcode = TGSI_OPCODE_TXP;
+ fullinst->Instruction.NumSrcRegs = 2;
+ fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
+ fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
+ fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
+ break;
+ case OPCODE_XPD:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_XPD;
+ fulldst->DstRegister.WriteMask &= TGSI_WRITEMASK_XYZ;
+ break;
+ case OPCODE_END:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_END;
+ break;
+ default:
+ assert( 0 );
+ }
+}
+
+/**
+ * \param usage_mask bitfield of TGSI_WRITEMASK_{XYZW} tokens
+ */
+static struct tgsi_full_declaration
+make_input_decl(
+ GLuint index,
+ GLboolean interpolate_info,
+ GLuint interpolate,
+ GLuint usage_mask,
+ GLboolean semantic_info,
+ GLuint semantic_name,
+ GLbitfield semantic_index,
+ GLbitfield input_flags)
+{
+ struct tgsi_full_declaration decl;
+
+ assert(semantic_name < TGSI_SEMANTIC_COUNT);
+
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_INPUT;
+ decl.Declaration.UsageMask = usage_mask;
+ decl.Declaration.Semantic = semantic_info;
+ decl.DeclarationRange.First = index;
+ decl.DeclarationRange.Last = index;
+ if (semantic_info) {
+ decl.Semantic.SemanticName = semantic_name;
+ decl.Semantic.SemanticIndex = semantic_index;
+ }
+ if (interpolate_info) {
+ decl.Declaration.Interpolate = interpolate;
+ }
+ if (input_flags & PROG_PARAM_BIT_CENTROID)
+ decl.Declaration.Centroid = 1;
+ if (input_flags & PROG_PARAM_BIT_INVARIANT)
+ decl.Declaration.Invariant = 1;
+
+ return decl;
+}
+
+/**
+ * \param usage_mask bitfield of TGSI_WRITEMASK_{XYZW} tokens
+ */
+static struct tgsi_full_declaration
+make_output_decl(
+ GLuint index,
+ GLuint semantic_name,
+ GLuint semantic_index,
+ GLuint usage_mask,
+ GLbitfield output_flags)
+{
+ struct tgsi_full_declaration decl;
+
+ assert(semantic_name < TGSI_SEMANTIC_COUNT);
+
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_OUTPUT;
+ decl.Declaration.UsageMask = usage_mask;
+ decl.Declaration.Semantic = 1;
+ decl.DeclarationRange.First = index;
+ decl.DeclarationRange.Last = index;
+ decl.Semantic.SemanticName = semantic_name;
+ decl.Semantic.SemanticIndex = semantic_index;
+ if (output_flags & PROG_PARAM_BIT_CENTROID)
+ decl.Declaration.Centroid = 1;
+ if (output_flags & PROG_PARAM_BIT_INVARIANT)
+ decl.Declaration.Invariant = 1;
+
+ return decl;
+}
+
+
+static struct tgsi_full_declaration
+make_temp_decl(
+ GLuint start_index,
+ GLuint end_index )
+{
+ struct tgsi_full_declaration decl;
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_TEMPORARY;
+ decl.DeclarationRange.First = start_index;
+ decl.DeclarationRange.Last = end_index;
+ return decl;
+}
+
+static struct tgsi_full_declaration
+make_addr_decl(
+ GLuint start_index,
+ GLuint end_index )
+{
+ struct tgsi_full_declaration decl;
+
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_ADDRESS;
+ decl.DeclarationRange.First = start_index;
+ decl.DeclarationRange.Last = end_index;
+ return decl;
+}
+
+static struct tgsi_full_declaration
+make_sampler_decl(GLuint index)
+{
+ struct tgsi_full_declaration decl;
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_SAMPLER;
+ decl.DeclarationRange.First = index;
+ decl.DeclarationRange.Last = index;
+ return decl;
+}
+
+/** Reference into a constant buffer */
+static struct tgsi_full_declaration
+make_constant_decl(GLuint first, GLuint last)
+{
+ struct tgsi_full_declaration decl;
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_CONSTANT;
+ decl.DeclarationRange.First = first;
+ decl.DeclarationRange.Last = last;
+ return decl;
+}
+
+
+
+/**
+ * Find the temporaries which are used in the given program.
+ */
+static void
+find_temporaries(const struct gl_program *program,
+ GLboolean tempsUsed[MAX_PROGRAM_TEMPS])
+{
+ GLuint i, j;
+
+ for (i = 0; i < MAX_PROGRAM_TEMPS; i++)
+ tempsUsed[i] = GL_FALSE;
+
+ for (i = 0; i < program->NumInstructions; i++) {
+ const struct prog_instruction *inst = program->Instructions + i;
+ const GLuint n = _mesa_num_inst_src_regs( inst->Opcode );
+ for (j = 0; j < n; j++) {
+ if (inst->SrcReg[j].File == PROGRAM_TEMPORARY)
+ tempsUsed[inst->SrcReg[j].Index] = GL_TRUE;
+ if (inst->DstReg.File == PROGRAM_TEMPORARY)
+ tempsUsed[inst->DstReg.Index] = GL_TRUE;
+ }
+ }
+}
+
+
+
+
+/**
+ * Translate Mesa program to TGSI format.
+ * \param program the program to translate
+ * \param numInputs number of input registers used
+ * \param inputMapping maps Mesa fragment program inputs to TGSI generic
+ * input indexes
+ * \param inputSemanticName the TGSI_SEMANTIC flag for each input
+ * \param inputSemanticIndex the semantic index (ex: which texcoord) for each input
+ * \param interpMode the TGSI_INTERPOLATE_LINEAR/PERSP mode for each input
+
+ * \param numOutputs number of output registers used
+ * \param outputMapping maps Mesa fragment program outputs to TGSI
+ * generic outputs
+ * \param outputSemanticName the TGSI_SEMANTIC flag for each output
+ * \param outputSemanticIndex the semantic index (ex: which texcoord) for each output
+ * \param tokens array to store translated tokens in
+ * \param maxTokens size of the tokens array
+ *
+ * \return number of tokens placed in 'tokens' buffer, or zero if error
+ */
+GLuint
+st_translate_mesa_program(
+ GLcontext *ctx,
+ uint procType,
+ const struct gl_program *program,
+ GLuint numInputs,
+ const GLuint inputMapping[],
+ const ubyte inputSemanticName[],
+ const ubyte inputSemanticIndex[],
+ const GLuint interpMode[],
+ const GLbitfield inputFlags[],
+ GLuint numOutputs,
+ const GLuint outputMapping[],
+ const ubyte outputSemanticName[],
+ const ubyte outputSemanticIndex[],
+ const GLbitfield outputFlags[],
+ struct tgsi_token *tokens,
+ GLuint maxTokens )
+{
+ GLuint i;
+ GLuint ti; /* token index */
+ struct tgsi_header *header;
+ struct tgsi_processor *processor;
+ struct tgsi_full_instruction fullinst;
+ GLuint preamble_size = 0;
+ GLuint immediates[1000];
+ GLuint numImmediates = 0;
+ GLboolean insideSubroutine = GL_FALSE;
+ GLboolean indirectAccess = GL_FALSE;
+
+ assert(procType == TGSI_PROCESSOR_FRAGMENT ||
+ procType == TGSI_PROCESSOR_VERTEX);
+
+ *(struct tgsi_version *) &tokens[0] = tgsi_build_version();
+
+ header = (struct tgsi_header *) &tokens[1];
+ *header = tgsi_build_header();
+
+ processor = (struct tgsi_processor *) &tokens[2];
+ *processor = tgsi_build_processor( procType, header );
+
+ ti = 3;
+
+ /*
+ * Declare input attributes.
+ */
+ if (procType == TGSI_PROCESSOR_FRAGMENT) {
+ for (i = 0; i < numInputs; i++) {
+ struct tgsi_full_declaration fulldecl;
+ fulldecl = make_input_decl(i,
+ GL_TRUE, interpMode[i],
+ TGSI_WRITEMASK_XYZW,
+ GL_TRUE, inputSemanticName[i],
+ inputSemanticIndex[i],
+ inputFlags[i]);
+ ti += tgsi_build_full_declaration(&fulldecl,
+ &tokens[ti],
+ header,
+ maxTokens - ti );
+ }
+ }
+ else {
+ /* vertex prog */
+ /* XXX: this could probaby be merged with the clause above.
+ * the only difference is the semantic tags.
+ */
+ for (i = 0; i < numInputs; i++) {
+ struct tgsi_full_declaration fulldecl;
+ fulldecl = make_input_decl(i,
+ GL_FALSE, 0,
+ TGSI_WRITEMASK_XYZW,
+ GL_FALSE, 0, 0,
+ inputFlags[i]);
+ ti += tgsi_build_full_declaration(&fulldecl,
+ &tokens[ti],
+ header,
+ maxTokens - ti );
+ }
+ }
+
+ /*
+ * Declare output attributes.
+ */
+ if (procType == TGSI_PROCESSOR_FRAGMENT) {
+ for (i = 0; i < numOutputs; i++) {
+ struct tgsi_full_declaration fulldecl;
+ switch (outputSemanticName[i]) {
+ case TGSI_SEMANTIC_POSITION:
+ fulldecl = make_output_decl(i,
+ TGSI_SEMANTIC_POSITION, /* Z / Depth */
+ outputSemanticIndex[i],
+ TGSI_WRITEMASK_Z,
+ outputFlags[i]);
+ break;
+ case TGSI_SEMANTIC_COLOR:
+ fulldecl = make_output_decl(i,
+ TGSI_SEMANTIC_COLOR,
+ outputSemanticIndex[i],
+ TGSI_WRITEMASK_XYZW,
+ outputFlags[i]);
+ break;
+ default:
+ assert(0);
+ return 0;
+ }
+ ti += tgsi_build_full_declaration(&fulldecl,
+ &tokens[ti],
+ header,
+ maxTokens - ti );
+ }
+ }
+ else {
+ /* vertex prog */
+ for (i = 0; i < numOutputs; i++) {
+ struct tgsi_full_declaration fulldecl;
+ fulldecl = make_output_decl(i,
+ outputSemanticName[i],
+ outputSemanticIndex[i],
+ TGSI_WRITEMASK_XYZW,
+ outputFlags[i]);
+ ti += tgsi_build_full_declaration(&fulldecl,
+ &tokens[ti],
+ header,
+ maxTokens - ti );
+ }
+ }
+
+ /* temporary decls */
+ {
+ GLboolean tempsUsed[MAX_PROGRAM_TEMPS + 1];
+ GLboolean inside_range = GL_FALSE;
+ GLuint start_range = 0;
+
+ find_temporaries(program, tempsUsed);
+ tempsUsed[MAX_PROGRAM_TEMPS] = GL_FALSE;
+ for (i = 0; i < MAX_PROGRAM_TEMPS + 1; i++) {
+ if (tempsUsed[i] && !inside_range) {
+ inside_range = GL_TRUE;
+ start_range = i;
+ }
+ else if (!tempsUsed[i] && inside_range) {
+ struct tgsi_full_declaration fulldecl;
+
+ inside_range = GL_FALSE;
+ fulldecl = make_temp_decl( start_range, i - 1 );
+ ti += tgsi_build_full_declaration(
+ &fulldecl,
+ &tokens[ti],
+ header,
+ maxTokens - ti );
+ }
+ }
+ }
+
+ /* Declare address register.
+ */
+ if (program->NumAddressRegs > 0) {
+ struct tgsi_full_declaration fulldecl;
+
+ assert( program->NumAddressRegs == 1 );
+
+ fulldecl = make_addr_decl( 0, 0 );
+ ti += tgsi_build_full_declaration(
+ &fulldecl,
+ &tokens[ti],
+ header,
+ maxTokens - ti );
+
+ indirectAccess = GL_TRUE;
+ }
+
+ /* immediates/literals */
+ memset(immediates, ~0, sizeof(immediates));
+
+ /* Emit immediates only when there is no address register in use.
+ * FIXME: Be smarter and recognize param arrays -- indirect addressing is
+ * only valid within the referenced array.
+ */
+ if (program->Parameters && !indirectAccess) {
+ for (i = 0; i < program->Parameters->NumParameters; i++) {
+ if (program->Parameters->Parameters[i].Type == PROGRAM_CONSTANT) {
+ struct tgsi_full_immediate fullimm;
+
+ fullimm = make_immediate( program->Parameters->ParameterValues[i], 4 );
+ ti += tgsi_build_full_immediate(
+ &fullimm,
+ &tokens[ti],
+ header,
+ maxTokens - ti );
+ immediates[i] = numImmediates;
+ numImmediates++;
+ }
+ }
+ }
+
+ /* constant buffer refs */
+ if (program->Parameters) {
+ GLint start = -1, end = -1;
+
+ for (i = 0; i < program->Parameters->NumParameters; i++) {
+ GLboolean emit = (i == program->Parameters->NumParameters - 1);
+ GLboolean matches;
+
+ switch (program->Parameters->Parameters[i].Type) {
+ case PROGRAM_ENV_PARAM:
+ case PROGRAM_STATE_VAR:
+ case PROGRAM_NAMED_PARAM:
+ case PROGRAM_UNIFORM:
+ matches = GL_TRUE;
+ break;
+ case PROGRAM_CONSTANT:
+ matches = indirectAccess;
+ break;
+ default:
+ matches = GL_FALSE;
+ }
+
+ if (matches) {
+ if (start == -1) {
+ /* begin a sequence */
+ start = i;
+ end = i;
+ }
+ else {
+ /* continue sequence */
+ end = i;
+ }
+ }
+ else {
+ if (start != -1) {
+ /* end of sequence */
+ emit = GL_TRUE;
+ }
+ }
+
+ if (emit && start >= 0) {
+ struct tgsi_full_declaration fulldecl;
+
+ fulldecl = make_constant_decl( start, end );
+ ti += tgsi_build_full_declaration(
+ &fulldecl,
+ &tokens[ti],
+ header,
+ maxTokens - ti );
+ start = end = -1;
+ }
+ }
+ }
+
+ /* texture samplers */
+ for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
+ if (program->SamplersUsed & (1 << i)) {
+ struct tgsi_full_declaration fulldecl;
+
+ fulldecl = make_sampler_decl( i );
+ ti += tgsi_build_full_declaration(
+ &fulldecl,
+ &tokens[ti],
+ header,
+ maxTokens - ti );
+ }
+ }
+
+ for (i = 0; i < program->NumInstructions; i++) {
+ compile_instruction(
+ &program->Instructions[i],
+ &fullinst,
+ inputMapping,
+ outputMapping,
+ immediates,
+ indirectAccess,
+ preamble_size,
+ procType,
+ &insideSubroutine );
+
+ ti += tgsi_build_full_instruction(
+ &fullinst,
+ &tokens[ti],
+ header,
+ maxTokens - ti );
+ }
+
+#if DEBUG
+ if(!tgsi_sanity_check(tokens)) {
+ debug_printf("Due to sanity check failure(s) above the following shader program is invalid:\n");
+ debug_printf("\nOriginal program:\n%s", program->String);
+ debug_printf("\nMesa program:\n");
+ _mesa_print_program(program);
+ debug_printf("\nTGSI program:\n");
+ tgsi_dump(tokens, 0);
+ assert(0);
+ }
+#endif
+
+ return ti;
+}
diff --git a/src/mesa/state_tracker/st_mesa_to_tgsi.h b/src/mesa/state_tracker/st_mesa_to_tgsi.h
new file mode 100644
index 00000000000..b465b3bddcf
--- /dev/null
+++ b/src/mesa/state_tracker/st_mesa_to_tgsi.h
@@ -0,0 +1,67 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_MESA_TO_TGSI_H
+#define ST_MESA_TO_TGSI_H
+
+#include "main/mtypes.h"
+
+
+#if defined __cplusplus
+extern "C" {
+#endif
+
+struct tgsi_token;
+struct gl_program;
+
+GLuint
+st_translate_mesa_program(
+ GLcontext *ctx,
+ uint procType,
+ const struct gl_program *program,
+ GLuint numInputs,
+ const GLuint inputMapping[],
+ const ubyte inputSemanticName[],
+ const ubyte inputSemanticIndex[],
+ const GLuint interpMode[],
+ const GLbitfield inputFlags[],
+ GLuint numOutputs,
+ const GLuint outputMapping[],
+ const ubyte outputSemanticName[],
+ const ubyte outputSemanticIndex[],
+ const GLbitfield outputFlags[],
+ struct tgsi_token *tokens,
+ GLuint maxTokens );
+
+
+#if defined __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* ST_MESA_TO_TGSI_H */
+
diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c
new file mode 100644
index 00000000000..442eeed1470
--- /dev/null
+++ b/src/mesa/state_tracker/st_program.c
@@ -0,0 +1,556 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <[email protected]>
+ * Brian Paul
+ */
+
+
+#include "main/imports.h"
+#include "main/mtypes.h"
+#include "shader/prog_print.h"
+#include "shader/programopt.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_shader_tokens.h"
+#include "draw/draw_context.h"
+#include "tgsi/tgsi_dump.h"
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "st_program.h"
+#include "st_mesa_to_tgsi.h"
+#include "cso_cache/cso_context.h"
+
+
+#define ST_MAX_SHADER_TOKENS 4096
+
+
+#define TGSI_DEBUG 0
+
+
+/** XXX we should use the version of this from u_memory.h but including
+ * that header causes symbol collisions.
+ */
+static INLINE void *
+mem_dup(const void *src, uint size)
+{
+ void *dup = MALLOC(size);
+ if (dup)
+ memcpy(dup, src, size);
+ return dup;
+}
+
+
+
+/**
+ * Translate a Mesa vertex shader into a TGSI shader.
+ * \param outputMapping to map vertex program output registers (VERT_RESULT_x)
+ * to TGSI output slots
+ * \param tokensOut destination for TGSI tokens
+ * \return pointer to cached pipe_shader object.
+ */
+void
+st_translate_vertex_program(struct st_context *st,
+ struct st_vertex_program *stvp,
+ const GLuint outputMapping[],
+ const ubyte *outputSemanticName,
+ const ubyte *outputSemanticIndex)
+{
+ struct pipe_context *pipe = st->pipe;
+ struct tgsi_token tokens[ST_MAX_SHADER_TOKENS];
+ GLuint defaultOutputMapping[VERT_RESULT_MAX];
+ struct pipe_shader_state vs;
+ GLuint attr, i;
+ GLuint num_generic = 0;
+ GLuint num_tokens;
+
+ ubyte vs_input_semantic_name[PIPE_MAX_SHADER_INPUTS];
+ ubyte vs_input_semantic_index[PIPE_MAX_SHADER_INPUTS];
+ uint vs_num_inputs = 0;
+
+ ubyte vs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS];
+ ubyte vs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS];
+ uint vs_num_outputs = 0;
+
+ GLbitfield input_flags[MAX_PROGRAM_INPUTS];
+ GLbitfield output_flags[MAX_PROGRAM_OUTPUTS];
+
+ memset(&vs, 0, sizeof(vs));
+ memset(input_flags, 0, sizeof(input_flags));
+ memset(output_flags, 0, sizeof(output_flags));
+
+ if (stvp->Base.IsPositionInvariant)
+ _mesa_insert_mvp_code(st->ctx, &stvp->Base);
+
+ /*
+ * Determine number of inputs, the mappings between VERT_ATTRIB_x
+ * and TGSI generic input indexes, plus input attrib semantic info.
+ */
+ for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
+ if (stvp->Base.Base.InputsRead & (1 << attr)) {
+ const GLuint slot = vs_num_inputs;
+
+ vs_num_inputs++;
+
+ stvp->input_to_index[attr] = slot;
+ stvp->index_to_input[slot] = attr;
+
+ switch (attr) {
+ case VERT_ATTRIB_POS:
+ vs_input_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
+ vs_input_semantic_index[slot] = 0;
+ break;
+ case VERT_ATTRIB_WEIGHT:
+ /* fall-through */
+ case VERT_ATTRIB_NORMAL:
+ /* just label as a generic */
+ vs_input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+ vs_input_semantic_index[slot] = 0;
+ break;
+ case VERT_ATTRIB_COLOR0:
+ vs_input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+ vs_input_semantic_index[slot] = 0;
+ break;
+ case VERT_ATTRIB_COLOR1:
+ vs_input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+ vs_input_semantic_index[slot] = 1;
+ break;
+ case VERT_ATTRIB_FOG:
+ vs_input_semantic_name[slot] = TGSI_SEMANTIC_FOG;
+ vs_input_semantic_index[slot] = 0;
+ break;
+ case VERT_ATTRIB_POINT_SIZE:
+ vs_input_semantic_name[slot] = TGSI_SEMANTIC_PSIZE;
+ vs_input_semantic_index[slot] = 0;
+ break;
+ case VERT_ATTRIB_TEX0:
+ case VERT_ATTRIB_TEX1:
+ case VERT_ATTRIB_TEX2:
+ case VERT_ATTRIB_TEX3:
+ case VERT_ATTRIB_TEX4:
+ case VERT_ATTRIB_TEX5:
+ case VERT_ATTRIB_TEX6:
+ case VERT_ATTRIB_TEX7:
+ vs_input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+ vs_input_semantic_index[slot] = num_generic++;
+ break;
+ case VERT_ATTRIB_GENERIC0:
+ case VERT_ATTRIB_GENERIC1:
+ case VERT_ATTRIB_GENERIC2:
+ case VERT_ATTRIB_GENERIC3:
+ case VERT_ATTRIB_GENERIC4:
+ case VERT_ATTRIB_GENERIC5:
+ case VERT_ATTRIB_GENERIC6:
+ case VERT_ATTRIB_GENERIC7:
+ assert(attr < VERT_ATTRIB_MAX);
+ vs_input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+ vs_input_semantic_index[slot] = num_generic++;
+ break;
+ default:
+ assert(0);
+ }
+
+ input_flags[slot] = stvp->Base.Base.InputFlags[attr];
+ }
+ }
+
+#if 0
+ if (outputMapping && outputSemanticName) {
+ printf("VERT_RESULT written out_slot semantic_name semantic_index\n");
+ for (attr = 0; attr < VERT_RESULT_MAX; attr++) {
+ printf(" %-2d %c %3d %2d %2d\n",
+ attr,
+ ((stvp->Base.Base.OutputsWritten & (1 << attr)) ? 'Y' : ' '),
+ outputMapping[attr],
+ outputSemanticName[attr],
+ outputSemanticIndex[attr]);
+ }
+ }
+#endif
+
+ /* initialize output semantics to defaults */
+ for (i = 0; i < PIPE_MAX_SHADER_OUTPUTS; i++) {
+ vs_output_semantic_name[i] = TGSI_SEMANTIC_GENERIC;
+ vs_output_semantic_index[i] = 0;
+ output_flags[i] = 0x0;
+ }
+
+ num_generic = 0;
+ /*
+ * Determine number of outputs, the (default) output register
+ * mapping and the semantic information for each output.
+ */
+ for (attr = 0; attr < VERT_RESULT_MAX; attr++) {
+ if (stvp->Base.Base.OutputsWritten & (1 << attr)) {
+ GLuint slot;
+
+ /* XXX
+ * Pass in the fragment program's input's semantic info.
+ * Use the generic semantic indexes from there, instead of
+ * guessing below.
+ */
+
+ if (outputMapping) {
+ slot = outputMapping[attr];
+ assert(slot != ~0);
+ }
+ else {
+ slot = vs_num_outputs;
+ vs_num_outputs++;
+ defaultOutputMapping[attr] = slot;
+ }
+
+ switch (attr) {
+ case VERT_RESULT_HPOS:
+ assert(slot == 0);
+ vs_output_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
+ vs_output_semantic_index[slot] = 0;
+ break;
+ case VERT_RESULT_COL0:
+ vs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+ vs_output_semantic_index[slot] = 0;
+ break;
+ case VERT_RESULT_COL1:
+ vs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+ vs_output_semantic_index[slot] = 1;
+ break;
+ case VERT_RESULT_BFC0:
+ vs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
+ vs_output_semantic_index[slot] = 0;
+ break;
+ case VERT_RESULT_BFC1:
+ vs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
+ vs_output_semantic_index[slot] = 1;
+ break;
+ case VERT_RESULT_FOGC:
+ vs_output_semantic_name[slot] = TGSI_SEMANTIC_FOG;
+ vs_output_semantic_index[slot] = 0;
+ break;
+ case VERT_RESULT_PSIZ:
+ vs_output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE;
+ vs_output_semantic_index[slot] = 0;
+ break;
+ case VERT_RESULT_EDGE:
+ assert(0);
+ break;
+ case VERT_RESULT_TEX0:
+ case VERT_RESULT_TEX1:
+ case VERT_RESULT_TEX2:
+ case VERT_RESULT_TEX3:
+ case VERT_RESULT_TEX4:
+ case VERT_RESULT_TEX5:
+ case VERT_RESULT_TEX6:
+ case VERT_RESULT_TEX7:
+ /* fall-through */
+ case VERT_RESULT_VAR0:
+ /* fall-through */
+ default:
+ if (outputSemanticName) {
+ /* use provided semantic into */
+ assert(outputSemanticName[attr] != TGSI_SEMANTIC_COUNT);
+ vs_output_semantic_name[slot] = outputSemanticName[attr];
+ vs_output_semantic_index[slot] = outputSemanticIndex[attr];
+ }
+ else {
+ /* use default semantic info */
+ vs_output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+ vs_output_semantic_index[slot] = num_generic++;
+ }
+ }
+
+ output_flags[slot] = stvp->Base.Base.OutputFlags[attr];
+ }
+ }
+
+ assert(vs_output_semantic_name[0] == TGSI_SEMANTIC_POSITION);
+
+
+ if (outputMapping) {
+ /* find max output slot referenced to compute vs_num_outputs */
+ GLuint maxSlot = 0;
+ for (attr = 0; attr < VERT_RESULT_MAX; attr++) {
+ if (outputMapping[attr] != ~0 && outputMapping[attr] > maxSlot)
+ maxSlot = outputMapping[attr];
+ }
+ vs_num_outputs = maxSlot + 1;
+ }
+ else {
+ outputMapping = defaultOutputMapping;
+ }
+
+ /* free old shader state, if any */
+ if (stvp->state.tokens) {
+ FREE((void *) stvp->state.tokens);
+ stvp->state.tokens = NULL;
+ }
+ if (stvp->driver_shader) {
+ cso_delete_vertex_shader(st->cso_context, stvp->driver_shader);
+ stvp->driver_shader = NULL;
+ }
+
+ /* XXX: fix static allocation of tokens:
+ */
+ num_tokens = st_translate_mesa_program(st->ctx,
+ TGSI_PROCESSOR_VERTEX,
+ &stvp->Base.Base,
+ /* inputs */
+ vs_num_inputs,
+ stvp->input_to_index,
+ vs_input_semantic_name,
+ vs_input_semantic_index,
+ NULL,
+ input_flags,
+ /* outputs */
+ vs_num_outputs,
+ outputMapping,
+ vs_output_semantic_name,
+ vs_output_semantic_index,
+ output_flags,
+ /* tokenized result */
+ tokens, ST_MAX_SHADER_TOKENS);
+
+ assert(num_tokens < ST_MAX_SHADER_TOKENS);
+
+ vs.tokens = (struct tgsi_token *)
+ mem_dup(tokens, num_tokens * sizeof(tokens[0]));
+
+ stvp->num_inputs = vs_num_inputs;
+ stvp->state = vs; /* struct copy */
+ stvp->driver_shader = pipe->create_vs_state(pipe, &vs);
+
+ if (0)
+ _mesa_print_program(&stvp->Base.Base);
+
+ if (TGSI_DEBUG)
+ tgsi_dump( vs.tokens, 0 );
+}
+
+
+
+/**
+ * Translate a Mesa fragment shader into a TGSI shader.
+ * \param inputMapping to map fragment program input registers to TGSI
+ * input slots
+ * \param tokensOut destination for TGSI tokens
+ * \return pointer to cached pipe_shader object.
+ */
+void
+st_translate_fragment_program(struct st_context *st,
+ struct st_fragment_program *stfp,
+ const GLuint inputMapping[])
+{
+ struct pipe_context *pipe = st->pipe;
+ struct tgsi_token tokens[ST_MAX_SHADER_TOKENS];
+ GLuint outputMapping[FRAG_RESULT_MAX];
+ GLuint defaultInputMapping[FRAG_ATTRIB_MAX];
+ struct pipe_shader_state fs;
+ GLuint interpMode[16]; /* XXX size? */
+ GLuint attr;
+ const GLbitfield inputsRead = stfp->Base.Base.InputsRead;
+ GLuint vslot = 0;
+ GLuint num_generic = 0;
+ GLuint num_tokens;
+
+ uint fs_num_inputs = 0;
+
+ ubyte fs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS];
+ ubyte fs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS];
+ uint fs_num_outputs = 0;
+
+ GLbitfield input_flags[MAX_PROGRAM_INPUTS];
+ GLbitfield output_flags[MAX_PROGRAM_OUTPUTS];
+
+ memset(&fs, 0, sizeof(fs));
+ memset(input_flags, 0, sizeof(input_flags));
+ memset(output_flags, 0, sizeof(output_flags));
+
+ /* which vertex output goes to the first fragment input: */
+ if (inputsRead & FRAG_BIT_WPOS)
+ vslot = 0;
+ else
+ vslot = 1;
+
+ /*
+ * Convert Mesa program inputs to TGSI input register semantics.
+ */
+ for (attr = 0; attr < FRAG_ATTRIB_MAX; attr++) {
+ if (inputsRead & (1 << attr)) {
+ const GLuint slot = fs_num_inputs;
+
+ defaultInputMapping[attr] = slot;
+
+ stfp->input_map[slot] = vslot++;
+
+ fs_num_inputs++;
+
+ switch (attr) {
+ case FRAG_ATTRIB_WPOS:
+ stfp->input_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
+ stfp->input_semantic_index[slot] = 0;
+ interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
+ break;
+ case FRAG_ATTRIB_COL0:
+ stfp->input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+ stfp->input_semantic_index[slot] = 0;
+ interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
+ break;
+ case FRAG_ATTRIB_COL1:
+ stfp->input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+ stfp->input_semantic_index[slot] = 1;
+ interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
+ break;
+ case FRAG_ATTRIB_FOGC:
+ if (stfp->Base.UsesPointCoord)
+ stfp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+ else
+ stfp->input_semantic_name[slot] = TGSI_SEMANTIC_FOG;
+ stfp->input_semantic_index[slot] = 0;
+ interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
+ break;
+ case FRAG_ATTRIB_TEX0:
+ case FRAG_ATTRIB_TEX1:
+ case FRAG_ATTRIB_TEX2:
+ case FRAG_ATTRIB_TEX3:
+ case FRAG_ATTRIB_TEX4:
+ case FRAG_ATTRIB_TEX5:
+ case FRAG_ATTRIB_TEX6:
+ case FRAG_ATTRIB_TEX7:
+ stfp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+ stfp->input_semantic_index[slot] = num_generic++;
+ interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
+ break;
+ case FRAG_ATTRIB_VAR0:
+ /* fall-through */
+ default:
+ stfp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+ stfp->input_semantic_index[slot] = num_generic++;
+ interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
+ }
+
+ input_flags[slot] = stfp->Base.Base.InputFlags[attr];
+ }
+ }
+
+ /*
+ * Semantics and mapping for outputs
+ */
+ {
+ uint numColors = 0;
+ GLbitfield outputsWritten = stfp->Base.Base.OutputsWritten;
+
+ /* if z is written, emit that first */
+ if (outputsWritten & (1 << FRAG_RESULT_DEPR)) {
+ fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_POSITION;
+ fs_output_semantic_index[fs_num_outputs] = 0;
+ outputMapping[FRAG_RESULT_DEPR] = fs_num_outputs;
+ fs_num_outputs++;
+ outputsWritten &= ~(1 << FRAG_RESULT_DEPR);
+ }
+
+ /* handle remaning outputs (color) */
+ for (attr = 0; attr < FRAG_RESULT_MAX; attr++) {
+ if (outputsWritten & (1 << attr)) {
+ switch (attr) {
+ case FRAG_RESULT_DEPR:
+ /* handled above */
+ assert(0);
+ break;
+ case FRAG_RESULT_COLR:
+ fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_COLOR;
+ fs_output_semantic_index[fs_num_outputs] = numColors;
+ outputMapping[attr] = fs_num_outputs;
+ numColors++;
+ break;
+ default:
+ assert(0);
+ }
+
+ output_flags[fs_num_outputs] = stfp->Base.Base.OutputFlags[attr];
+
+ fs_num_outputs++;
+ }
+ }
+ }
+
+ if (!inputMapping)
+ inputMapping = defaultInputMapping;
+
+ /* XXX: fix static allocation of tokens:
+ */
+ num_tokens = st_translate_mesa_program(st->ctx,
+ TGSI_PROCESSOR_FRAGMENT,
+ &stfp->Base.Base,
+ /* inputs */
+ fs_num_inputs,
+ inputMapping,
+ stfp->input_semantic_name,
+ stfp->input_semantic_index,
+ interpMode,
+ input_flags,
+ /* outputs */
+ fs_num_outputs,
+ outputMapping,
+ fs_output_semantic_name,
+ fs_output_semantic_index,
+ output_flags,
+ /* tokenized result */
+ tokens, ST_MAX_SHADER_TOKENS);
+
+ assert(num_tokens < ST_MAX_SHADER_TOKENS);
+
+ fs.tokens = (struct tgsi_token *)
+ mem_dup(tokens, num_tokens * sizeof(tokens[0]));
+
+ stfp->state = fs; /* struct copy */
+ stfp->driver_shader = pipe->create_fs_state(pipe, &fs);
+
+ if (0)
+ _mesa_print_program(&stfp->Base.Base);
+
+ if (TGSI_DEBUG)
+ tgsi_dump( fs.tokens, 0/*TGSI_DUMP_VERBOSE*/ );
+}
+
+
+/**
+ * Debug- print current shader text
+ */
+void
+st_print_shaders(GLcontext *ctx)
+{
+ struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
+ if (shProg) {
+ GLuint i;
+ for (i = 0; i < shProg->NumShaders; i++) {
+ printf("GLSL shader %u of %u:\n", i, shProg->NumShaders);
+ printf("%s\n", shProg->Shaders[i]->Source);
+ }
+ }
+}
diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h
new file mode 100644
index 00000000000..e2e5eddef22
--- /dev/null
+++ b/src/mesa/state_tracker/st_program.h
@@ -0,0 +1,158 @@
+/**************************************************************************
+ *
+ * Copyright 2003 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.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <[email protected]>
+ */
+
+
+#ifndef ST_PROGRAM_H
+#define ST_PROGRAM_H
+
+#include "main/mtypes.h"
+#include "shader/program.h"
+#include "pipe/p_shader_tokens.h"
+
+
+struct cso_fragment_shader;
+struct cso_vertex_shader;
+struct translated_vertex_program;
+
+
+/**
+ * Derived from Mesa gl_fragment_program:
+ */
+struct st_fragment_program
+{
+ struct gl_fragment_program Base;
+ GLuint serialNo;
+
+ GLuint input_to_slot[FRAG_ATTRIB_MAX]; /**< Maps FRAG_ATTRIB_x to slot */
+ GLuint num_input_slots;
+
+ /** map FP input back to VP output */
+ GLuint input_map[PIPE_MAX_SHADER_INPUTS];
+
+ ubyte input_semantic_name[PIPE_MAX_SHADER_INPUTS];
+ ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS];
+
+ struct pipe_shader_state state;
+ void *driver_shader;
+
+ GLuint param_state;
+
+ /** List of vertex programs which have been translated such that their
+ * outputs match this fragment program's inputs.
+ */
+ struct translated_vertex_program *vertex_programs;
+
+ /** Program prefixed with glBitmap prologue */
+ struct st_fragment_program *bitmap_program;
+ uint bitmap_sampler;
+};
+
+
+/**
+ * Derived from Mesa gl_fragment_program:
+ */
+struct st_vertex_program
+{
+ struct gl_vertex_program Base; /**< The Mesa vertex program */
+ GLuint serialNo;
+
+ /** maps a Mesa VERT_ATTRIB_x to a packed TGSI input index */
+ GLuint input_to_index[VERT_ATTRIB_MAX];
+ /** maps a TGSI input index back to a Mesa VERT_ATTRIB_x */
+ GLuint index_to_input[PIPE_MAX_SHADER_INPUTS];
+
+ GLuint num_inputs;
+
+ struct pipe_shader_state state;
+ void *driver_shader;
+
+ /** For using our private draw module (glRasterPos) */
+ struct draw_vertex_shader *draw_shader;
+
+ GLuint param_state;
+};
+
+
+static INLINE struct st_fragment_program *
+st_fragment_program( struct gl_fragment_program *fp )
+{
+ return (struct st_fragment_program *)fp;
+}
+
+
+static INLINE struct st_vertex_program *
+st_vertex_program( struct gl_vertex_program *vp )
+{
+ return (struct st_vertex_program *)vp;
+}
+
+
+static INLINE void
+st_reference_vertprog(struct st_context *st,
+ struct st_vertex_program **ptr,
+ struct st_vertex_program *prog)
+{
+ _mesa_reference_program(st->ctx,
+ (struct gl_program **) ptr,
+ (struct gl_program *) prog);
+}
+
+static INLINE void
+st_reference_fragprog(struct st_context *st,
+ struct st_fragment_program **ptr,
+ struct st_fragment_program *prog)
+{
+ _mesa_reference_program(st->ctx,
+ (struct gl_program **) ptr,
+ (struct gl_program *) prog);
+}
+
+
+extern void
+st_translate_fragment_program(struct st_context *st,
+ struct st_fragment_program *fp,
+ const GLuint inputMapping[]);
+
+
+extern void
+st_translate_vertex_program(struct st_context *st,
+ struct st_vertex_program *vp,
+ const GLuint vert_output_to_slot[],
+ const ubyte *fs_input_semantic_name,
+ const ubyte *fs_input_semantic_index);
+
+
+extern void
+st_print_shaders(GLcontext *ctx);
+
+
+#endif
diff --git a/src/mesa/state_tracker/st_public.h b/src/mesa/state_tracker/st_public.h
new file mode 100644
index 00000000000..414218bb589
--- /dev/null
+++ b/src/mesa/state_tracker/st_public.h
@@ -0,0 +1,122 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+#ifndef ST_PUBLIC_H
+#define ST_PUBLIC_H
+
+#include "GL/gl.h"
+#include "GL/internal/glcore.h" /* for __GLcontextModes */
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_format.h"
+
+
+#define ST_SURFACE_FRONT_LEFT 0
+#define ST_SURFACE_BACK_LEFT 1
+#define ST_SURFACE_FRONT_RIGHT 2
+#define ST_SURFACE_BACK_RIGHT 3
+#define ST_SURFACE_DEPTH 8
+
+#define ST_TEXTURE_2D 0x2
+#define ST_TEXTURE_RECT 0x4
+
+#define ST_TEXTURE_RGB 0x1
+#define ST_TEXTURE_RGBA 0x2
+
+
+struct st_context;
+struct st_framebuffer;
+struct pipe_context;
+struct pipe_fence_handle;
+struct pipe_surface;
+struct pipe_texture;
+
+
+struct st_context *st_create_context(struct pipe_context *pipe,
+ const __GLcontextModes *visual,
+ struct st_context *share);
+
+void st_destroy_context( struct st_context *st );
+
+void st_copy_context_state(struct st_context *dst, struct st_context *src,
+ uint mask);
+
+struct st_framebuffer *st_create_framebuffer( const __GLcontextModes *visual,
+ enum pipe_format colorFormat,
+ enum pipe_format depthFormat,
+ enum pipe_format stencilFormat,
+ uint width, uint height,
+ void *privateData);
+
+void st_resize_framebuffer( struct st_framebuffer *stfb,
+ uint width, uint height );
+
+void st_set_framebuffer_surface(struct st_framebuffer *stfb,
+ uint surfIndex, struct pipe_surface *surf);
+
+void st_get_framebuffer_dimensions( struct st_framebuffer *stfb,
+ uint *width, uint *height);
+
+int st_get_framebuffer_surface(struct st_framebuffer *stfb,
+ uint surfIndex, struct pipe_surface **surface);
+
+int st_get_framebuffer_texture(struct st_framebuffer *stfb,
+ uint surfIndex, struct pipe_texture **texture);
+
+void *st_framebuffer_private( struct st_framebuffer *stfb );
+
+void st_unreference_framebuffer( struct st_framebuffer *stfb );
+
+void st_make_current(struct st_context *st,
+ struct st_framebuffer *draw,
+ struct st_framebuffer *read);
+
+void st_flush( struct st_context *st, uint pipeFlushFlags,
+ struct pipe_fence_handle **fence );
+void st_finish( struct st_context *st );
+
+void st_notify_swapbuffers(struct st_framebuffer *stfb);
+void st_notify_swapbuffers_complete(struct st_framebuffer *stfb);
+
+int st_set_teximage(struct pipe_texture *pt, int target);
+
+/** Redirect rendering into stfb's surface to a texture image */
+int st_bind_teximage(struct st_framebuffer *stfb, uint surfIndex,
+ int target, int format, int level);
+
+/** Undo surface-to-texture binding */
+int st_release_teximage(struct st_framebuffer *stfb, uint surfIndex,
+ int target, int format, int level);
+
+
+/** Generic function type */
+typedef void (*st_proc)();
+
+st_proc st_get_proc_address(const char *procname);
+
+
+#endif
diff --git a/src/mesa/state_tracker/st_texture.c b/src/mesa/state_tracker/st_texture.c
new file mode 100644
index 00000000000..63cfe5fc163
--- /dev/null
+++ b/src/mesa/state_tracker/st_texture.c
@@ -0,0 +1,488 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+#include "st_context.h"
+#include "st_format.h"
+#include "st_public.h"
+#include "st_texture.h"
+#include "st_cb_fbo.h"
+#include "main/enums.h"
+#include "main/teximage.h"
+#include "main/texstore.h"
+
+#undef Elements /* fix re-defined macro warning */
+
+#include "pipe/p_state.h"
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_inlines.h"
+#include "util/u_rect.h"
+
+
+#define DBG if(0) printf
+
+#if 0
+static GLenum
+target_to_target(GLenum target)
+{
+ switch (target) {
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
+ return GL_TEXTURE_CUBE_MAP_ARB;
+ default:
+ return target;
+ }
+}
+#endif
+
+
+/**
+ * Allocate a new pipe_texture object
+ * width0, height0, depth0 are the dimensions of the level 0 image
+ * (the highest resolution). last_level indicates how many mipmap levels
+ * to allocate storage for. For non-mipmapped textures, this will be zero.
+ */
+struct pipe_texture *
+st_texture_create(struct st_context *st,
+ enum pipe_texture_target target,
+ enum pipe_format format,
+ GLuint last_level,
+ GLuint width0,
+ GLuint height0,
+ GLuint depth0,
+ GLuint compress_byte,
+ GLuint usage )
+{
+ struct pipe_texture pt, *newtex;
+ struct pipe_screen *screen = st->pipe->screen;
+
+ assert(target <= PIPE_TEXTURE_CUBE);
+
+ DBG("%s target %s format %s last_level %d\n", __FUNCTION__,
+ _mesa_lookup_enum_by_nr(target),
+ _mesa_lookup_enum_by_nr(format), last_level);
+
+ assert(format);
+ assert(screen->is_format_supported(screen, format, target,
+ PIPE_TEXTURE_USAGE_SAMPLER, 0));
+
+ memset(&pt, 0, sizeof(pt));
+ pt.target = target;
+ pt.format = format;
+ pt.last_level = last_level;
+ pt.width[0] = width0;
+ pt.height[0] = height0;
+ pt.depth[0] = depth0;
+ pt.compressed = compress_byte ? 1 : 0;
+ pf_get_block(format, &pt.block);
+ pt.tex_usage = usage;
+
+ newtex = screen->texture_create(screen, &pt);
+
+ assert(!newtex || newtex->refcount == 1);
+
+ return newtex;
+}
+
+
+/**
+ * Check if a texture image be pulled into a unified mipmap texture.
+ * This mirrors the completeness test in a lot of ways.
+ *
+ * Not sure whether I want to pass gl_texture_image here.
+ */
+GLboolean
+st_texture_match_image(const struct pipe_texture *pt,
+ const struct gl_texture_image *image,
+ GLuint face, GLuint level)
+{
+ /* Images with borders are never pulled into mipmap textures.
+ */
+ if (image->Border)
+ return GL_FALSE;
+
+ if (st_mesa_format_to_pipe_format(image->TexFormat->MesaFormat) != pt->format ||
+ image->IsCompressed != pt->compressed)
+ return GL_FALSE;
+
+ /* Test image dimensions against the base level image adjusted for
+ * minification. This will also catch images not present in the
+ * texture, changed targets, etc.
+ */
+ if (image->Width != pt->width[level] ||
+ image->Height != pt->height[level] ||
+ image->Depth != pt->depth[level])
+ return GL_FALSE;
+
+ return GL_TRUE;
+}
+
+
+#if 000
+/* Although we use the image_offset[] array to store relative offsets
+ * to cube faces, Mesa doesn't know anything about this and expects
+ * each cube face to be treated as a separate image.
+ *
+ * These functions present that view to mesa:
+ */
+const GLuint *
+st_texture_depth_offsets(struct pipe_texture *pt, GLuint level)
+{
+ static const GLuint zero = 0;
+
+ if (pt->target != PIPE_TEXTURE_3D || pt->level[level].nr_images == 1)
+ return &zero;
+ else
+ return pt->level[level].image_offset;
+}
+
+
+/**
+ * Return the offset to the given mipmap texture image within the
+ * texture memory buffer, in bytes.
+ */
+GLuint
+st_texture_image_offset(const struct pipe_texture * pt,
+ GLuint face, GLuint level)
+{
+ if (pt->target == PIPE_TEXTURE_CUBE)
+ return (pt->level[level].level_offset +
+ pt->level[level].image_offset[face] * pt->cpp);
+ else
+ return pt->level[level].level_offset;
+}
+#endif
+
+
+/**
+ * Map a teximage in a mipmap texture.
+ * \param row_stride returns row stride in bytes
+ * \param image_stride returns image stride in bytes (for 3D textures).
+ * \return address of mapping
+ */
+GLubyte *
+st_texture_image_map(struct st_context *st, struct st_texture_image *stImage,
+ GLuint zoffset,
+ GLuint flags )
+{
+ struct pipe_screen *screen = st->pipe->screen;
+ struct pipe_texture *pt = stImage->pt;
+ DBG("%s \n", __FUNCTION__);
+
+ stImage->surface = screen->get_tex_surface(screen, pt, stImage->face,
+ stImage->level, zoffset,
+ flags);
+
+ if (stImage->surface)
+ return screen->surface_map(screen, stImage->surface, flags);
+ else
+ return NULL;
+}
+
+
+void
+st_texture_image_unmap(struct st_context *st,
+ struct st_texture_image *stImage)
+{
+ struct pipe_screen *screen = st->pipe->screen;
+
+ DBG("%s\n", __FUNCTION__);
+
+ screen->surface_unmap(screen, stImage->surface);
+
+ pipe_surface_reference(&stImage->surface, NULL);
+}
+
+
+
+/**
+ * Upload data to a rectangular sub-region. Lots of choices how to do this:
+ *
+ * - memcpy by span to current destination
+ * - upload data as new buffer and blit
+ *
+ * Currently always memcpy.
+ */
+static void
+st_surface_data(struct pipe_context *pipe,
+ struct pipe_surface *dst,
+ unsigned dstx, unsigned dsty,
+ const void *src, unsigned src_stride,
+ unsigned srcx, unsigned srcy, unsigned width, unsigned height)
+{
+ struct pipe_screen *screen = pipe->screen;
+ void *map = screen->surface_map(screen, dst, PIPE_BUFFER_USAGE_CPU_WRITE);
+
+ pipe_copy_rect(map,
+ &dst->block,
+ dst->stride,
+ dstx, dsty,
+ width, height,
+ src, src_stride,
+ srcx, srcy);
+
+ screen->surface_unmap(screen, dst);
+}
+
+
+/* Upload data for a particular image.
+ */
+void
+st_texture_image_data(struct pipe_context *pipe,
+ struct pipe_texture *dst,
+ GLuint face,
+ GLuint level,
+ void *src,
+ GLuint src_row_stride, GLuint src_image_stride)
+{
+ struct pipe_screen *screen = pipe->screen;
+ GLuint depth = dst->depth[level];
+ GLuint i;
+ const GLubyte *srcUB = src;
+ struct pipe_surface *dst_surface;
+
+ DBG("%s\n", __FUNCTION__);
+ for (i = 0; i < depth; i++) {
+ dst_surface = screen->get_tex_surface(screen, dst, face, level, i,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+
+ st_surface_data(pipe, dst_surface,
+ 0, 0, /* dstx, dsty */
+ srcUB,
+ src_row_stride,
+ 0, 0, /* source x, y */
+ dst->width[level], dst->height[level]); /* width, height */
+
+ screen->tex_surface_release(screen, &dst_surface);
+
+ srcUB += src_image_stride;
+ }
+}
+
+
+/* Copy mipmap image between textures
+ */
+void
+st_texture_image_copy(struct pipe_context *pipe,
+ struct pipe_texture *dst, GLuint dstLevel,
+ struct pipe_texture *src,
+ GLuint face)
+{
+ struct pipe_screen *screen = pipe->screen;
+ GLuint width = dst->width[dstLevel];
+ GLuint height = dst->height[dstLevel];
+ GLuint depth = dst->depth[dstLevel];
+ struct pipe_surface *src_surface;
+ struct pipe_surface *dst_surface;
+ GLuint i;
+
+ for (i = 0; i < depth; i++) {
+ GLuint srcLevel;
+
+ /* find src texture level of needed size */
+ for (srcLevel = 0; srcLevel <= src->last_level; srcLevel++) {
+ if (src->width[srcLevel] == width &&
+ src->height[srcLevel] == height) {
+ break;
+ }
+ }
+ assert(src->width[srcLevel] == width);
+ assert(src->height[srcLevel] == height);
+
+#if 0
+ {
+ src_surface = screen->get_tex_surface(screen, src, face, srcLevel, i,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ ubyte *map = screen->surface_map(screen, src_surface, PIPE_BUFFER_USAGE_CPU_READ);
+ map += src_surface->width * src_surface->height * 4 / 2;
+ printf("%s center pixel: %d %d %d %d (pt %p[%d] -> %p[%d])\n",
+ __FUNCTION__,
+ map[0], map[1], map[2], map[3],
+ src, srcLevel, dst, dstLevel);
+
+ screen->surface_unmap(screen, src_surface);
+ pipe_surface_reference(&src_surface, NULL);
+ }
+#endif
+
+ dst_surface = screen->get_tex_surface(screen, dst, face, dstLevel, i,
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+
+ src_surface = screen->get_tex_surface(screen, src, face, srcLevel, i,
+ PIPE_BUFFER_USAGE_GPU_READ);
+
+ pipe->surface_copy(pipe,
+ FALSE,
+ dst_surface,
+ 0, 0, /* destX, Y */
+ src_surface,
+ 0, 0, /* srcX, Y */
+ width, height);
+
+ screen->tex_surface_release(screen, &src_surface);
+ screen->tex_surface_release(screen, &dst_surface);
+ }
+}
+
+/** Bind a pipe surface for use as a texture image */
+int
+st_set_teximage(struct pipe_texture *pt, int target)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ const GLuint unit = ctx->Texture.CurrentUnit;
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ struct st_texture_image *stImage;
+ int internalFormat;
+
+ switch (pt->format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ internalFormat = GL_RGBA8;
+ break;
+ default:
+ return 0;
+ };
+
+ switch (target) {
+ case ST_TEXTURE_2D:
+ target = GL_TEXTURE_2D;
+ break;
+ case ST_TEXTURE_RECT:
+ target = GL_TEXTURE_RECTANGLE_ARB;
+ break;
+ default:
+ return 0;
+ }
+
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
+ texImage = _mesa_get_tex_image(ctx, texObj, target, 0);
+ stImage = st_texture_image(texImage);
+
+ _mesa_init_teximage_fields(ctx, GL_TEXTURE_2D, texImage, pt->width[0],
+ pt->height[0], 1, 0, internalFormat);
+
+ texImage->TexFormat = st_ChooseTextureFormat(ctx, internalFormat, GL_RGBA,
+ GL_UNSIGNED_BYTE);
+ _mesa_set_fetch_functions(texImage, 2);
+
+ pipe_texture_reference(&stImage->pt, pt);
+
+ return 1;
+}
+
+/** Redirect rendering into stfb's surface to a texture image */
+int
+st_bind_teximage(struct st_framebuffer *stfb, uint surfIndex,
+ int target, int format, int level)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct st_context *st = ctx->st;
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ const GLuint unit = ctx->Texture.CurrentUnit;
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ struct st_texture_image *stImage;
+ struct st_renderbuffer *strb;
+ GLint face = 0, slice = 0;
+
+ assert(surfIndex <= ST_SURFACE_DEPTH);
+
+ strb = st_renderbuffer(stfb->Base.Attachment[surfIndex].Renderbuffer);
+
+ if (strb->texture_save || strb->surface_save) {
+ /* Error! */
+ return 0;
+ }
+
+ if (target == ST_TEXTURE_2D) {
+ texObj = texUnit->Current2D;
+ texImage = _mesa_get_tex_image(ctx, texObj, GL_TEXTURE_2D, level);
+ stImage = st_texture_image(texImage);
+ }
+ else {
+ /* unsupported target */
+ return 0;
+ }
+
+ st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+ /* save the renderbuffer's surface/texture info */
+ pipe_texture_reference(&strb->texture_save, strb->texture);
+ pipe_surface_reference(&strb->surface_save, strb->surface);
+
+ /* plug in new surface/texture info */
+ pipe_texture_reference(&strb->texture, stImage->pt);
+ strb->surface = screen->get_tex_surface(screen, strb->texture,
+ face, level, slice,
+ (PIPE_BUFFER_USAGE_GPU_READ |
+ PIPE_BUFFER_USAGE_GPU_WRITE));
+
+ st->dirty.st |= ST_NEW_FRAMEBUFFER;
+
+ return 1;
+}
+
+
+/** Undo surface-to-texture binding */
+int
+st_release_teximage(struct st_framebuffer *stfb, uint surfIndex,
+ int target, int format, int level)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct st_context *st = ctx->st;
+ struct st_renderbuffer *strb;
+
+ assert(surfIndex <= ST_SURFACE_DEPTH);
+
+ strb = st_renderbuffer(stfb->Base.Attachment[surfIndex].Renderbuffer);
+
+ if (!strb->texture_save || !strb->surface_save) {
+ /* Error! */
+ return 0;
+ }
+
+ st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+ /* free tex surface, restore original */
+ pipe_surface_reference(&strb->surface, strb->surface_save);
+ pipe_texture_reference(&strb->texture, strb->texture_save);
+
+ pipe_surface_reference(&strb->surface_save, NULL);
+ pipe_texture_reference(&strb->texture_save, NULL);
+
+ st->dirty.st |= ST_NEW_FRAMEBUFFER;
+
+ return 1;
+}
diff --git a/src/mesa/state_tracker/st_texture.h b/src/mesa/state_tracker/st_texture.h
new file mode 100644
index 00000000000..31f66ad52cf
--- /dev/null
+++ b/src/mesa/state_tracker/st_texture.h
@@ -0,0 +1,179 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+#ifndef ST_TEXTURE_H
+#define ST_TEXTURE_H
+
+
+#include "main/mtypes.h"
+
+struct pipe_context;
+struct pipe_texture;
+
+
+struct st_texture_image
+{
+ struct gl_texture_image base;
+
+ /* These aren't stored in gl_texture_image
+ */
+ GLuint level;
+ GLuint face;
+
+ /* If stImage->pt != NULL, image data is stored here.
+ * Else if stImage->base.Data != NULL, image is stored there.
+ * Else there is no image data.
+ */
+ struct pipe_texture *pt;
+
+ struct pipe_surface *surface;
+};
+
+
+
+struct st_texture_object
+{
+ struct gl_texture_object base; /* The "parent" object */
+
+ /* The texture must include at levels [0..lastLevel] once validated:
+ */
+ GLuint lastLevel;
+
+ /* On validation any active images held in main memory or in other
+ * textures will be copied to this texture and the old storage freed.
+ */
+ struct pipe_texture *pt;
+
+ GLboolean teximage_realloc;
+};
+
+
+static INLINE struct st_texture_image *
+st_texture_image(struct gl_texture_image *img)
+{
+ return (struct st_texture_image *) img;
+}
+
+static INLINE struct st_texture_object *
+st_texture_object(struct gl_texture_object *obj)
+{
+ return (struct st_texture_object *) obj;
+}
+
+
+static INLINE struct pipe_texture *
+st_get_texobj_texture(struct gl_texture_object *texObj)
+{
+ struct st_texture_object *stObj = st_texture_object(texObj);
+ return stObj ? stObj->pt : NULL;
+}
+
+
+static INLINE struct pipe_texture *
+st_get_stobj_texture(struct st_texture_object *stObj)
+{
+ return stObj ? stObj->pt : NULL;
+}
+
+static INLINE GLboolean pf_is_depth_stencil( enum pipe_format format )
+{
+ return (pf_get_component_bits( format, PIPE_FORMAT_COMP_Z ) +
+ pf_get_component_bits( format, PIPE_FORMAT_COMP_S )) != 0;
+}
+
+
+extern struct pipe_texture *
+st_texture_create(struct st_context *st,
+ enum pipe_texture_target target,
+ enum pipe_format format,
+ GLuint last_level,
+ GLuint width0,
+ GLuint height0,
+ GLuint depth0,
+ GLuint compress_byte,
+ GLuint tex_usage );
+
+
+/* Check if an image fits into an existing texture object.
+ */
+extern GLboolean
+st_texture_match_image(const struct pipe_texture *pt,
+ const struct gl_texture_image *image,
+ GLuint face, GLuint level);
+
+/* Return a pointer to an image within a texture. Return image stride as
+ * well.
+ */
+extern GLubyte *
+st_texture_image_map(struct st_context *st,
+ struct st_texture_image *stImage,
+ GLuint zoffset,
+ GLuint flags);
+
+extern void
+st_texture_image_unmap(struct st_context *st,
+ struct st_texture_image *stImage);
+
+
+/* Return pointers to each 2d slice within an image. Indexed by depth
+ * value.
+ */
+extern const GLuint *
+st_texture_depth_offsets(struct pipe_texture *pt, GLuint level);
+
+
+/* Return the linear offset of an image relative to the start of its region.
+ */
+extern GLuint
+st_texture_image_offset(const struct pipe_texture *pt,
+ GLuint face, GLuint level);
+
+extern GLuint
+st_texture_texel_offset(const struct pipe_texture * pt,
+ GLuint face, GLuint level,
+ GLuint col, GLuint row, GLuint img);
+
+
+/* Upload an image into a texture
+ */
+extern void
+st_texture_image_data(struct pipe_context *pipe,
+ struct pipe_texture *dst,
+ GLuint face, GLuint level, void *src,
+ GLuint src_row_pitch, GLuint src_image_pitch);
+
+
+/* Copy an image between two textures
+ */
+extern void
+st_texture_image_copy(struct pipe_context *pipe,
+ struct pipe_texture *dst, GLuint dstLevel,
+ struct pipe_texture *src,
+ GLuint face);
+
+
+#endif
diff --git a/src/mesa/swrast/s_context.c b/src/mesa/swrast/s_context.c
index 62857ddeb0d..297940adbd6 100644
--- a/src/mesa/swrast/s_context.c
+++ b/src/mesa/swrast/s_context.c
@@ -533,6 +533,9 @@ _swrast_update_texture_samplers(GLcontext *ctx)
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLuint u;
+ if (!swrast)
+ return; /* pipe hack */
+
for (u = 0; u < ctx->Const.MaxTextureImageUnits; u++) {
const struct gl_texture_object *tObj = ctx->Texture.Unit[u]._Current;
/* Note: If tObj is NULL, the sample function will be a simple
diff --git a/src/mesa/tnl/t_context.c b/src/mesa/tnl/t_context.c
index 19ec556dcd4..7bfc7b00610 100644
--- a/src/mesa/tnl/t_context.c
+++ b/src/mesa/tnl/t_context.c
@@ -78,6 +78,9 @@ _tnl_CreateContext( GLcontext *ctx )
tnl->nr_blocks = 0;
+ /* plug in the VBO drawing function */
+ vbo_set_draw_func(ctx, _tnl_draw_prims);
+
return GL_TRUE;
}
diff --git a/src/mesa/tnl/t_vp_build.h b/src/mesa/tnl/t_vp_build.h
index d1c147ff032..d6ebc66c045 100644
--- a/src/mesa/tnl/t_vp_build.h
+++ b/src/mesa/tnl/t_vp_build.h
@@ -29,6 +29,13 @@
#include "main/mtypes.h"
+#define TNL_FIXED_FUNCTION_STATE_FLAGS (_NEW_PROGRAM | \
+ _NEW_LIGHT | \
+ _NEW_TEXTURE | \
+ _NEW_TEXTURE_MATRIX | \
+ _NEW_TRANSFORM | \
+ _NEW_FOG | \
+ _NEW_POINT)
extern void _tnl_UpdateFixedFunctionProgram( GLcontext *ctx );
diff --git a/src/mesa/tnl/tnl.h b/src/mesa/tnl/tnl.h
index 9a1717bf898..4d628aa9a60 100644
--- a/src/mesa/tnl/tnl.h
+++ b/src/mesa/tnl/tnl.h
@@ -81,6 +81,8 @@ _tnl_draw_prims( GLcontext *ctx,
GLuint min_index,
GLuint max_index);
+extern void
+_mesa_load_tracked_matrices(GLcontext *ctx);
extern void
_tnl_RasterPos(GLcontext *ctx, const GLfloat vObj[4]);
diff --git a/src/mesa/vbo/vbo.h b/src/mesa/vbo/vbo.h
index 4c51b44cdad..5362226c2f9 100644
--- a/src/mesa/vbo/vbo.h
+++ b/src/mesa/vbo/vbo.h
@@ -117,4 +117,22 @@ void vbo_rebase_prims( GLcontext *ctx,
void vbo_use_buffer_objects(GLcontext *ctx);
+void vbo_set_draw_func(GLcontext *ctx, vbo_draw_func func);
+
+
+void GLAPIENTRY
+_vbo_Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
+
+void GLAPIENTRY
+_vbo_Normal3f(GLfloat x, GLfloat y, GLfloat z);
+
+void GLAPIENTRY
+_vbo_MultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+
+void GLAPIENTRY
+_vbo_Materialfv(GLenum face, GLenum pname, const GLfloat *params);
+
+void GLAPIENTRY
+_vbo_VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+
#endif
diff --git a/src/mesa/vbo/vbo_context.c b/src/mesa/vbo/vbo_context.c
index 274d23248f1..467ab4e3e55 100644
--- a/src/mesa/vbo/vbo_context.c
+++ b/src/mesa/vbo/vbo_context.c
@@ -31,6 +31,7 @@
#include "vbo.h"
#include "vbo_context.h"
+#if 0
/* Reach out and grab this to use as the default:
*/
extern void _tnl_draw_prims( GLcontext *ctx,
@@ -40,6 +41,7 @@ extern void _tnl_draw_prims( GLcontext *ctx,
const struct _mesa_index_buffer *ib,
GLuint min_index,
GLuint max_index );
+#endif
@@ -215,7 +217,9 @@ GLboolean _vbo_CreateContext( GLcontext *ctx )
/* By default:
*/
+#if 0 /* dead - see vbo_set_draw_func() */
vbo->draw_prims = _tnl_draw_prims;
+#endif
/* Hook our functions into exec and compile dispatch tables. These
* will pretty much be permanently installed, which means that the
@@ -243,10 +247,20 @@ void _vbo_DestroyContext( GLcontext *ctx )
ctx->aelt_context = NULL;
}
- vbo_exec_destroy(ctx);
+ if (vbo_context(ctx)) {
+ vbo_exec_destroy(ctx);
#if FEATURE_dlist
- vbo_save_destroy(ctx);
+ vbo_save_destroy(ctx);
#endif
- FREE(vbo_context(ctx));
- ctx->swtnl_im = NULL;
+ FREE(vbo_context(ctx));
+ ctx->swtnl_im = NULL;
+ }
+}
+
+
+void vbo_set_draw_func(GLcontext *ctx, vbo_draw_func func)
+{
+ struct vbo_context *vbo = vbo_context(ctx);
+ vbo->draw_prims = func;
}
+
diff --git a/src/mesa/vbo/vbo_exec_api.c b/src/mesa/vbo/vbo_exec_api.c
index f6daa253fdd..2743bf6b55c 100644
--- a/src/mesa/vbo/vbo_exec_api.c
+++ b/src/mesa/vbo/vbo_exec_api.c
@@ -143,32 +143,36 @@ static void vbo_exec_copy_to_current( struct vbo_exec_context *exec )
for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
if (exec->vtx.attrsz[i]) {
- GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
-
/* Note: the exec->vtx.current[i] pointers point into the
* ctx->Current.Attrib and ctx->Light.Material.Attrib arrays.
*/
- if (exec->vtx.attrptr[i]) {
-
- COPY_CLEAN_4V(current,
- exec->vtx.attrsz[i],
- exec->vtx.attrptr[i]);
-
- }
-
- /* Given that we explicitly state size here, there is no need
- * for the COPY_CLEAN above, could just copy 16 bytes and be
- * done. The only problem is when Mesa accesses ctx->Current
- * directly.
- */
- vbo->currval[i].Size = exec->vtx.attrsz[i];
-
- /* This triggers rather too much recalculation of Mesa state
- * that doesn't get used (eg light positions).
- */
- if (i >= VBO_ATTRIB_MAT_FRONT_AMBIENT &&
- i <= VBO_ATTRIB_MAT_BACK_INDEXES)
- ctx->NewState |= _NEW_LIGHT;
+ GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
+ GLfloat tmp[4];
+
+ COPY_CLEAN_4V(tmp,
+ exec->vtx.attrsz[i],
+ exec->vtx.attrptr[i]);
+
+ if (memcmp(current, tmp, sizeof(tmp)) != 0)
+ {
+ memcpy(current, tmp, sizeof(tmp));
+
+ /* Given that we explicitly state size here, there is no need
+ * for the COPY_CLEAN above, could just copy 16 bytes and be
+ * done. The only problem is when Mesa accesses ctx->Current
+ * directly.
+ */
+ vbo->currval[i].Size = exec->vtx.attrsz[i];
+
+ /* This triggers rather too much recalculation of Mesa state
+ * that doesn't get used (eg light positions).
+ */
+ if (i >= VBO_ATTRIB_MAT_FRONT_AMBIENT &&
+ i <= VBO_ATTRIB_MAT_BACK_INDEXES)
+ ctx->NewState |= _NEW_LIGHT;
+
+ ctx->NewState |= _NEW_CURRENT_ATTRIB;
+ }
}
}
@@ -696,7 +700,8 @@ void vbo_exec_vtx_init( struct vbo_exec_context *exec )
GLuint i;
/* Allocate a buffer object. Will just reuse this object
- * continuously.
+ * continuously, unless vbo_use_buffer_objects() is called to enable
+ * use of real VBOs.
*/
_mesa_reference_buffer_object(ctx,
&exec->vtx.bufferobj,
@@ -775,3 +780,36 @@ static void reset_attrfv( struct vbo_exec_context *exec )
exec->vtx.vertex_size = 0;
}
+
+void GLAPIENTRY
+_vbo_Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a)
+{
+ vbo_Color4f(r, g, b, a);
+}
+
+
+void GLAPIENTRY
+_vbo_Normal3f(GLfloat x, GLfloat y, GLfloat z)
+{
+ vbo_Normal3f(x, y, z);
+}
+
+
+void GLAPIENTRY
+_vbo_MultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
+{
+ vbo_MultiTexCoord4f(target, s, t, r, q);
+}
+
+void GLAPIENTRY
+_vbo_Materialfv(GLenum face, GLenum pname, const GLfloat *params)
+{
+ vbo_Materialfv(face, pname, params);
+}
+
+
+void GLAPIENTRY
+_vbo_VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ vbo_VertexAttrib4fARB(index, x, y, z, w);
+}
diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c
index 82f4db17d19..8871e10cf60 100644
--- a/src/mesa/vbo/vbo_exec_array.c
+++ b/src/mesa/vbo/vbo_exec_array.c
@@ -30,6 +30,8 @@
#include "main/state.h"
#include "main/api_validate.h"
#include "main/api_noop.h"
+#include "main/varray.h"
+#include "glapi/dispatch.h"
#include "vbo_context.h"
@@ -125,6 +127,7 @@ static void recalculate_input_bindings( GLcontext *ctx )
struct vbo_context *vbo = vbo_context(ctx);
struct vbo_exec_context *exec = &vbo->exec;
const struct gl_client_array **inputs = &exec->array.inputs[0];
+ GLbitfield const_inputs = 0x0;
GLuint i;
exec->array.program_mode = get_program_mode(ctx);
@@ -139,19 +142,24 @@ static void recalculate_input_bindings( GLcontext *ctx )
for (i = 0; i <= VERT_ATTRIB_TEX7; i++) {
if (exec->array.legacy_array[i]->Enabled)
inputs[i] = exec->array.legacy_array[i];
- else
+ else {
inputs[i] = &vbo->legacy_currval[i];
+ const_inputs |= 1 << i;
+ }
}
for (i = 0; i < MAT_ATTRIB_MAX; i++) {
inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->mat_currval[i];
+ const_inputs |= 1 << (VERT_ATTRIB_GENERIC0 + i);
}
/* Could use just about anything, just to fill in the empty
* slots:
*/
- for (i = MAT_ATTRIB_MAX; i < VERT_ATTRIB_MAX - VERT_ATTRIB_GENERIC0; i++)
+ for (i = MAT_ATTRIB_MAX; i < VERT_ATTRIB_MAX - VERT_ATTRIB_GENERIC0; i++) {
inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->generic_currval[i];
+ const_inputs |= 1 << (VERT_ATTRIB_GENERIC0 + i);
+ }
break;
case VP_NV:
@@ -164,15 +172,19 @@ static void recalculate_input_bindings( GLcontext *ctx )
inputs[i] = exec->array.generic_array[i];
else if (exec->array.legacy_array[i]->Enabled)
inputs[i] = exec->array.legacy_array[i];
- else
+ else {
inputs[i] = &vbo->legacy_currval[i];
+ const_inputs |= 1 << i;
+ }
}
/* Could use just about anything, just to fill in the empty
* slots:
*/
- for (i = VERT_ATTRIB_GENERIC0; i < VERT_ATTRIB_MAX; i++)
+ for (i = VERT_ATTRIB_GENERIC0; i < VERT_ATTRIB_MAX; i++) {
inputs[i] = &vbo->generic_currval[i - VERT_ATTRIB_GENERIC0];
+ const_inputs |= 1 << i;
+ }
break;
case VP_ARB:
@@ -187,25 +199,34 @@ static void recalculate_input_bindings( GLcontext *ctx )
inputs[0] = exec->array.generic_array[0];
else if (exec->array.legacy_array[0]->Enabled)
inputs[0] = exec->array.legacy_array[0];
- else
+ else {
inputs[0] = &vbo->legacy_currval[0];
+ const_inputs |= 1 << 0;
+ }
for (i = 1; i <= VERT_ATTRIB_TEX7; i++) {
if (exec->array.legacy_array[i]->Enabled)
inputs[i] = exec->array.legacy_array[i];
- else
+ else {
inputs[i] = &vbo->legacy_currval[i];
+ const_inputs |= 1 << i;
+ }
}
for (i = 0; i < 16; i++) {
if (exec->array.generic_array[i]->Enabled)
inputs[VERT_ATTRIB_GENERIC0 + i] = exec->array.generic_array[i];
- else
+ else {
inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->generic_currval[i];
+ const_inputs |= 1 << (VERT_ATTRIB_GENERIC0 + i);
+ }
+
}
break;
}
+
+ _mesa_set_varying_vp_inputs( ctx, ~const_inputs );
}
static void bind_arrays( GLcontext *ctx )
@@ -255,6 +276,11 @@ vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count)
bind_arrays( ctx );
+ /* Again...
+ */
+ if (ctx->NewState)
+ _mesa_update_state( ctx );
+
prim[0].begin = 1;
prim[0].end = 1;
prim[0].weak = 0;
@@ -295,6 +321,9 @@ vbo_exec_DrawRangeElements(GLenum mode,
bind_arrays( ctx );
+ if (ctx->NewState)
+ _mesa_update_state( ctx );
+
ib.count = count;
ib.type = type;
ib.obj = ctx->Array.ElementArrayBufferObj;
@@ -403,3 +432,29 @@ void vbo_exec_array_destroy( struct vbo_exec_context *exec )
{
/* nothing to do */
}
+
+
+/* This API entrypoint is not ordinarily used */
+void GLAPIENTRY
+_mesa_DrawArrays(GLenum mode, GLint first, GLsizei count)
+{
+ vbo_exec_DrawArrays(mode, first, count);
+}
+
+
+/* This API entrypoint is not ordinarily used */
+void GLAPIENTRY
+_mesa_DrawElements(GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices)
+{
+ vbo_exec_DrawElements(mode, count, type, indices);
+}
+
+
+/* This API entrypoint is not ordinarily used */
+void GLAPIENTRY
+_mesa_DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count,
+ GLenum type, const GLvoid *indices)
+{
+ vbo_exec_DrawRangeElements(mode, start, end, count, type, indices);
+}
diff --git a/src/mesa/vbo/vbo_exec_draw.c b/src/mesa/vbo/vbo_exec_draw.c
index 7204aec1dcb..45133fa4f32 100644
--- a/src/mesa/vbo/vbo_exec_draw.c
+++ b/src/mesa/vbo/vbo_exec_draw.c
@@ -150,6 +150,7 @@ static void vbo_exec_bind_arrays( GLcontext *ctx )
GLubyte *data = exec->vtx.buffer_map;
const GLuint *map;
GLuint attr;
+ GLbitfield varying_inputs = 0x0;
/* Install the default (ie Current) attributes first, then overlay
* all active ones.
@@ -225,8 +226,11 @@ static void vbo_exec_bind_arrays( GLcontext *ctx )
arrays[attr]._MaxElement = count; /* ??? */
data += exec->vtx.attrsz[src] * sizeof(GLfloat);
+ varying_inputs |= 1<<attr;
}
}
+
+ _mesa_set_varying_vp_inputs( ctx, varying_inputs );
}
@@ -256,6 +260,9 @@ void vbo_exec_vtx_flush( struct vbo_exec_context *exec )
*/
vbo_exec_bind_arrays( ctx );
+ if (ctx->NewState)
+ _mesa_update_state( ctx );
+
/* if using a real VBO, unmap it before drawing */
if (exec->vtx.bufferobj->Name) {
ctx->Driver.UnmapBuffer(ctx, target, exec->vtx.bufferobj);
diff --git a/src/mesa/vbo/vbo_save_draw.c b/src/mesa/vbo/vbo_save_draw.c
index 7ee0a9a33f4..617c5a77baf 100644
--- a/src/mesa/vbo/vbo_save_draw.c
+++ b/src/mesa/vbo/vbo_save_draw.c
@@ -64,18 +64,26 @@ static void _playback_copy_to_current( GLcontext *ctx,
for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
if (node->attrsz[i]) {
GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
+ GLfloat tmp[4];
- COPY_CLEAN_4V(current,
- node->attrsz[i],
- data);
+ COPY_CLEAN_4V(tmp,
+ node->attrsz[i],
+ data);
+
+ if (memcmp(current, tmp, 4 * sizeof(GLfloat)) != 0)
+ {
+ memcpy(current, tmp, 4 * sizeof(GLfloat));
- vbo->currval[i].Size = node->attrsz[i];
+ vbo->currval[i].Size = node->attrsz[i];
- data += node->attrsz[i];
+ if (i >= VBO_ATTRIB_FIRST_MATERIAL &&
+ i <= VBO_ATTRIB_LAST_MATERIAL)
+ ctx->NewState |= _NEW_LIGHT;
+
+ ctx->NewState |= _NEW_CURRENT_ATTRIB;
+ }
- if (i >= VBO_ATTRIB_FIRST_MATERIAL &&
- i <= VBO_ATTRIB_LAST_MATERIAL)
- ctx->NewState |= _NEW_LIGHT;
+ data += node->attrsz[i];
}
}
@@ -111,6 +119,7 @@ static void vbo_bind_vertex_list( GLcontext *ctx,
const GLuint *map;
GLuint attr;
GLubyte node_attrsz[VBO_ATTRIB_MAX]; /* copy of node->attrsz[] */
+ GLbitfield varying_inputs = 0x0;
memcpy(node_attrsz, node->attrsz, sizeof(node->attrsz));
@@ -176,8 +185,11 @@ static void vbo_bind_vertex_list( GLcontext *ctx,
assert(arrays[attr].BufferObj->Name);
data += node->attrsz[src] * sizeof(GLfloat);
+ varying_inputs |= 1<<attr;
}
}
+
+ _mesa_set_varying_vp_inputs( ctx, varying_inputs );
}
static void vbo_save_loopback_vertex_list( GLcontext *ctx,
@@ -246,6 +258,11 @@ void vbo_save_playback_vertex_list( GLcontext *ctx, void *data )
vbo_bind_vertex_list( ctx, node );
+ /* Again...
+ */
+ if (ctx->NewState)
+ _mesa_update_state( ctx );
+
vbo_context(ctx)->draw_prims( ctx,
save->inputs,
node->prim,
diff --git a/src/mesa/vf/vf.c b/src/mesa/vf/vf.c
new file mode 100644
index 00000000000..82f3d2b641d
--- /dev/null
+++ b/src/mesa/vf/vf.c
@@ -0,0 +1,372 @@
+/*
+ * Copyright 2003 Tungsten Graphics, 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
+ * 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
+ * TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <[email protected]>
+ */
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/colormac.h"
+
+#include "vf.h"
+
+#define DBG 0
+
+
+
+static GLboolean match_fastpath( struct vertex_fetch *vf,
+ const struct vf_fastpath *fp)
+{
+ GLuint j;
+
+ if (vf->attr_count != fp->attr_count)
+ return GL_FALSE;
+
+ for (j = 0; j < vf->attr_count; j++)
+ if (vf->attr[j].format != fp->attr[j].format ||
+ vf->attr[j].inputsize != fp->attr[j].size ||
+ vf->attr[j].vertoffset != fp->attr[j].offset)
+ return GL_FALSE;
+
+ if (fp->match_strides) {
+ if (vf->vertex_stride != fp->vertex_stride)
+ return GL_FALSE;
+
+ for (j = 0; j < vf->attr_count; j++)
+ if (vf->attr[j].inputstride != fp->attr[j].stride)
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+static GLboolean search_fastpath_emit( struct vertex_fetch *vf )
+{
+ struct vf_fastpath *fp = vf->fastpath;
+
+ for ( ; fp ; fp = fp->next) {
+ if (match_fastpath(vf, fp)) {
+ vf->emit = fp->func;
+ return GL_TRUE;
+ }
+ }
+
+ return GL_FALSE;
+}
+
+void vf_register_fastpath( struct vertex_fetch *vf,
+ GLboolean match_strides )
+{
+ struct vf_fastpath *fastpath = CALLOC_STRUCT(vf_fastpath);
+ GLuint i;
+
+ fastpath->vertex_stride = vf->vertex_stride;
+ fastpath->attr_count = vf->attr_count;
+ fastpath->match_strides = match_strides;
+ fastpath->func = vf->emit;
+ fastpath->attr = (struct vf_attr_type *)
+ _mesa_malloc(vf->attr_count * sizeof(fastpath->attr[0]));
+
+ for (i = 0; i < vf->attr_count; i++) {
+ fastpath->attr[i].format = vf->attr[i].format;
+ fastpath->attr[i].stride = vf->attr[i].inputstride;
+ fastpath->attr[i].size = vf->attr[i].inputsize;
+ fastpath->attr[i].offset = vf->attr[i].vertoffset;
+ }
+
+ fastpath->next = vf->fastpath;
+ vf->fastpath = fastpath;
+}
+
+
+
+
+/***********************************************************************
+ * Build codegen functions or return generic ones:
+ */
+static void choose_emit_func( struct vertex_fetch *vf,
+ GLuint count,
+ GLubyte *dest)
+{
+ vf->emit = NULL;
+
+ /* Does this match an existing (hardwired, codegen or known-bad)
+ * fastpath?
+ */
+ if (search_fastpath_emit(vf)) {
+ /* Use this result. If it is null, then it is already known
+ * that the current state will fail for codegen and there is no
+ * point trying again.
+ */
+ }
+ else if (vf->codegen_emit) {
+ vf->codegen_emit( vf );
+ }
+
+ if (!vf->emit) {
+ vf_generate_hardwired_emit(vf);
+ }
+
+ /* Otherwise use the generic version:
+ */
+ if (!vf->emit)
+ vf->emit = vf_generic_emit;
+
+ vf->emit( vf, count, dest );
+}
+
+
+
+
+
+/***********************************************************************
+ * Public entrypoints, mostly dispatch to the above:
+ */
+
+
+
+GLuint vf_set_vertex_attributes( struct vertex_fetch *vf,
+ const struct vf_attr_map *map,
+ GLuint nr,
+ GLuint vertex_stride )
+{
+ GLuint offset = 0;
+ GLuint i, j;
+
+ assert(nr < VF_ATTRIB_MAX);
+
+ memset(vf->lookup, 0, sizeof(vf->lookup));
+
+ for (j = 0, i = 0; i < nr; i++) {
+ const GLuint format = map[i].format;
+ if (format == EMIT_PAD) {
+ if (DBG)
+ _mesa_printf("%d: pad %d, offset %d\n", i,
+ map[i].offset, offset);
+
+ offset += map[i].offset;
+
+ }
+ else {
+ assert(vf->lookup[map[i].attrib] == 0);
+ vf->lookup[map[i].attrib] = &vf->attr[j];
+
+ vf->attr[j].attrib = map[i].attrib;
+ vf->attr[j].format = format;
+ vf->attr[j].insert = vf_format_info[format].insert;
+ vf->attr[j].extract = vf_format_info[format].extract;
+ vf->attr[j].vertattrsize = vf_format_info[format].attrsize;
+ vf->attr[j].vertoffset = offset;
+
+ if (DBG)
+ _mesa_printf("%d: %s, offset %d\n", i,
+ vf_format_info[format].name,
+ vf->attr[j].vertoffset);
+
+ offset += vf_format_info[format].attrsize;
+ j++;
+ }
+ }
+
+ vf->attr_count = j;
+ vf->vertex_stride = vertex_stride ? vertex_stride : offset;
+ vf->emit = choose_emit_func;
+
+ assert(vf->vertex_stride >= offset);
+ return vf->vertex_stride;
+}
+
+
+
+void vf_set_vp_matrix( struct vertex_fetch *vf,
+ const GLfloat *viewport )
+{
+ assert(vf->allow_viewport_emits);
+
+ /* scale */
+ vf->vp[0] = viewport[MAT_SX];
+ vf->vp[1] = viewport[MAT_SY];
+ vf->vp[2] = viewport[MAT_SZ];
+ vf->vp[3] = 1.0;
+
+ /* translate */
+ vf->vp[4] = viewport[MAT_TX];
+ vf->vp[5] = viewport[MAT_TY];
+ vf->vp[6] = viewport[MAT_TZ];
+ vf->vp[7] = 0.0;
+}
+
+void vf_set_vp_scale_translate( struct vertex_fetch *vf,
+ const GLfloat *scale,
+ const GLfloat *translate )
+{
+ assert(vf->allow_viewport_emits);
+
+ vf->vp[0] = scale[0];
+ vf->vp[1] = scale[1];
+ vf->vp[2] = scale[2];
+ vf->vp[3] = scale[3];
+
+ vf->vp[4] = translate[0];
+ vf->vp[5] = translate[1];
+ vf->vp[6] = translate[2];
+ vf->vp[7] = translate[3];
+}
+
+
+/* Set attribute pointers, adjusted for start position:
+ */
+void vf_set_sources( struct vertex_fetch *vf,
+ GLvector4f * const sources[],
+ GLuint start )
+{
+ struct vf_attr *a = vf->attr;
+ GLuint j;
+
+ for (j = 0; j < vf->attr_count; j++) {
+ const GLvector4f *vptr = sources[a[j].attrib];
+
+ if ((a[j].inputstride != vptr->stride) ||
+ (a[j].inputsize != vptr->size))
+ vf->emit = choose_emit_func;
+
+ a[j].inputstride = vptr->stride;
+ a[j].inputsize = vptr->size;
+ a[j].do_insert = a[j].insert[vptr->size - 1];
+ a[j].inputptr = ((GLubyte *)vptr->data) + start * vptr->stride;
+ }
+}
+
+
+
+/* Emit count VB vertices to dest.
+ */
+void vf_emit_vertices( struct vertex_fetch *vf,
+ GLuint count,
+ void *dest )
+{
+ vf->emit( vf, count, (GLubyte*) dest );
+}
+
+
+/* Extract a named attribute from a hardware vertex. Will have to
+ * reverse any viewport transformation, swizzling or other conversions
+ * which may have been applied.
+ *
+ * This is mainly required for on-the-fly vertex translations to
+ * swrast format.
+ */
+void vf_get_attr( struct vertex_fetch *vf,
+ const void *vertex,
+ GLenum attr,
+ const GLfloat *dflt,
+ GLfloat *dest )
+{
+ const struct vf_attr *a = vf->attr;
+ const GLuint attr_count = vf->attr_count;
+ GLuint j;
+
+ for (j = 0; j < attr_count; j++) {
+ if (a[j].attrib == attr) {
+ a[j].extract( &a[j], dest, (GLubyte *)vertex + a[j].vertoffset );
+ return;
+ }
+ }
+
+ /* Else return the value from ctx->Current.
+ */
+ _mesa_memcpy( dest, dflt, 4*sizeof(GLfloat));
+}
+
+
+
+
+struct vertex_fetch *vf_create( GLboolean allow_viewport_emits )
+{
+ struct vertex_fetch *vf = CALLOC_STRUCT(vertex_fetch);
+ GLuint i;
+
+ for (i = 0; i < VF_ATTRIB_MAX; i++)
+ vf->attr[i].vf = vf;
+
+ vf->allow_viewport_emits = allow_viewport_emits;
+
+ switch(CHAN_TYPE) {
+ case GL_UNSIGNED_BYTE:
+ vf->chan_scale[0] = 255.0;
+ vf->chan_scale[1] = 255.0;
+ vf->chan_scale[2] = 255.0;
+ vf->chan_scale[3] = 255.0;
+ break;
+ case GL_UNSIGNED_SHORT:
+ vf->chan_scale[0] = 65535.0;
+ vf->chan_scale[1] = 65535.0;
+ vf->chan_scale[2] = 65535.0;
+ vf->chan_scale[3] = 65535.0;
+ break;
+ default:
+ vf->chan_scale[0] = 1.0;
+ vf->chan_scale[1] = 1.0;
+ vf->chan_scale[2] = 1.0;
+ vf->chan_scale[3] = 1.0;
+ break;
+ }
+
+ vf->identity[0] = 0.0;
+ vf->identity[1] = 0.0;
+ vf->identity[2] = 0.0;
+ vf->identity[3] = 1.0;
+
+ vf->codegen_emit = NULL;
+
+#ifdef USE_SSE_ASM
+ if (!_mesa_getenv("MESA_NO_CODEGEN"))
+ vf->codegen_emit = vf_generate_sse_emit;
+#endif
+
+ return vf;
+}
+
+
+void vf_destroy( struct vertex_fetch *vf )
+{
+ struct vf_fastpath *fp, *tmp;
+
+ for (fp = vf->fastpath ; fp ; fp = tmp) {
+ tmp = fp->next;
+ FREE(fp->attr);
+
+ /* KW: At the moment, fp->func is constrained to be allocated by
+ * _mesa_exec_alloc(), as the hardwired fastpaths in
+ * t_vertex_generic.c are handled specially. It would be nice
+ * to unify them, but this probably won't change until this
+ * module gets another overhaul.
+ */
+ _mesa_exec_free((void *) fp->func);
+ FREE(fp);
+ }
+
+ vf->fastpath = NULL;
+ FREE(vf);
+}
diff --git a/src/mesa/vf/vf.h b/src/mesa/vf/vf.h
new file mode 100644
index 00000000000..83d7547619c
--- /dev/null
+++ b/src/mesa/vf/vf.h
@@ -0,0 +1,234 @@
+/*
+ * Copyright 2003 Tungsten Graphics, 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
+ * 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
+ * TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <[email protected]>
+ */
+
+#ifndef VF_VERTEX_H
+#define VF_VERTEX_H
+
+#include "main/mtypes.h"
+#include "math/m_vector.h"
+
+enum {
+ VF_ATTRIB_POS = 0,
+ VF_ATTRIB_WEIGHT = 1,
+ VF_ATTRIB_NORMAL = 2,
+ VF_ATTRIB_COLOR0 = 3,
+ VF_ATTRIB_COLOR1 = 4,
+ VF_ATTRIB_FOG = 5,
+ VF_ATTRIB_COLOR_INDEX = 6,
+ VF_ATTRIB_EDGEFLAG = 7,
+ VF_ATTRIB_TEX0 = 8,
+ VF_ATTRIB_TEX1 = 9,
+ VF_ATTRIB_TEX2 = 10,
+ VF_ATTRIB_TEX3 = 11,
+ VF_ATTRIB_TEX4 = 12,
+ VF_ATTRIB_TEX5 = 13,
+ VF_ATTRIB_TEX6 = 14,
+ VF_ATTRIB_TEX7 = 15,
+ VF_ATTRIB_VAR0 = 16,
+ VF_ATTRIB_VAR1 = 17,
+ VF_ATTRIB_VAR2 = 18,
+ VF_ATTRIB_VAR3 = 19,
+ VF_ATTRIB_VAR4 = 20,
+ VF_ATTRIB_VAR5 = 21,
+ VF_ATTRIB_VAR6 = 22,
+ VF_ATTRIB_VAR7 = 23,
+ VF_ATTRIB_POINTSIZE = 24,
+ VF_ATTRIB_BFC0 = 25,
+ VF_ATTRIB_BFC1 = 26,
+ VF_ATTRIB_CLIP_POS = 27,
+ VF_ATTRIB_VERTEX_HEADER = 28,
+ VF_ATTRIB_MAX = 29
+};
+
+
+enum vf_attr_format {
+ EMIT_1F,
+ EMIT_2F,
+ EMIT_3F,
+ EMIT_4F,
+ EMIT_2F_VIEWPORT, /* do viewport transform and emit */
+ EMIT_3F_VIEWPORT, /* do viewport transform and emit */
+ EMIT_4F_VIEWPORT, /* do viewport transform and emit */
+ EMIT_3F_XYW, /* for projective texture */
+ EMIT_1UB_1F, /* for fog coordinate */
+ EMIT_3UB_3F_RGB, /* for specular color */
+ EMIT_3UB_3F_BGR, /* for specular color */
+ EMIT_4UB_4F_RGBA, /* for color */
+ EMIT_4UB_4F_BGRA, /* for color */
+ EMIT_4UB_4F_ARGB, /* for color */
+ EMIT_4UB_4F_ABGR, /* for color */
+ EMIT_4CHAN_4F_RGBA, /* for swrast color */
+ EMIT_PAD, /* leave a hole of 'offset' bytes */
+ EMIT_MAX
+};
+
+struct vf_attr_map {
+ GLuint attrib;
+ enum vf_attr_format format;
+ GLuint offset;
+};
+
+struct vertex_fetch;
+
+void vf_set_vp_matrix( struct vertex_fetch *vf,
+ const GLfloat *viewport );
+
+void vf_set_vp_scale_translate( struct vertex_fetch *vf,
+ const GLfloat *scale,
+ const GLfloat *translate );
+
+GLuint vf_set_vertex_attributes( struct vertex_fetch *vf,
+ const struct vf_attr_map *map,
+ GLuint nr,
+ GLuint vertex_stride );
+
+void vf_set_sources( struct vertex_fetch *vf,
+ GLvector4f * const attrib[],
+ GLuint start );
+
+void vf_emit_vertices( struct vertex_fetch *vf,
+ GLuint count,
+ void *dest );
+
+void vf_get_attr( struct vertex_fetch *vf,
+ const void *vertex,
+ GLenum attr,
+ const GLfloat *dflt,
+ GLfloat *dest );
+
+struct vertex_fetch *vf_create( GLboolean allow_viewport_emits );
+
+void vf_destroy( struct vertex_fetch *vf );
+
+
+
+/***********************************************************************
+ * Internal functions and structs:
+ */
+
+struct vf_attr;
+
+typedef void (*vf_extract_func)( const struct vf_attr *a,
+ GLfloat *out,
+ const GLubyte *v );
+
+typedef void (*vf_insert_func)( const struct vf_attr *a,
+ GLubyte *v,
+ const GLfloat *in );
+
+typedef void (*vf_emit_func)( struct vertex_fetch *vf,
+ GLuint count,
+ GLubyte *dest );
+
+
+
+/* Describes how to convert/move a vertex attribute from a vertex
+ * array to a vertex structure.
+ */
+struct vf_attr
+{
+ struct vertex_fetch *vf;
+
+ GLuint format;
+ GLuint inputsize;
+ GLuint inputstride;
+ GLuint vertoffset; /* position of the attrib in the vertex struct */
+
+ GLuint attrib; /* which vertex attrib (0=position, etc) */
+ GLuint vertattrsize; /* size of the attribute in bytes */
+
+ GLubyte *inputptr;
+ const vf_insert_func *insert;
+ vf_insert_func do_insert;
+ vf_extract_func extract;
+};
+
+struct vertex_fetch
+{
+ struct vf_attr attr[VF_ATTRIB_MAX];
+ GLuint attr_count;
+ GLuint vertex_stride;
+
+ struct vf_attr *lookup[VF_ATTRIB_MAX];
+
+ vf_emit_func emit;
+
+ /* Parameters and constants for codegen:
+ */
+ GLboolean allow_viewport_emits;
+ GLfloat vp[8];
+ GLfloat chan_scale[4];
+ GLfloat identity[4];
+
+ struct vf_fastpath *fastpath;
+
+ void (*codegen_emit)( struct vertex_fetch *vf );
+};
+
+
+struct vf_attr_type {
+ GLuint format;
+ GLuint size;
+ GLuint stride;
+ GLuint offset;
+};
+
+struct vf_fastpath {
+ GLuint vertex_stride;
+ GLuint attr_count;
+ GLboolean match_strides;
+
+ struct vf_attr_type *attr;
+
+ vf_emit_func func;
+ struct vf_fastpath *next;
+};
+
+
+void vf_register_fastpath( struct vertex_fetch *vtx,
+ GLboolean match_strides );
+
+void vf_generic_emit( struct vertex_fetch *vf,
+ GLuint count,
+ GLubyte *v );
+
+void vf_generate_hardwired_emit( struct vertex_fetch *vf );
+
+void vf_generate_sse_emit( struct vertex_fetch *vf );
+
+
+struct vf_format_info {
+ const char *name;
+ vf_extract_func extract;
+ vf_insert_func insert[4];
+ const GLuint attrsize;
+};
+
+const struct vf_format_info vf_format_info[EMIT_MAX];
+
+
+#endif
diff --git a/src/mesa/vf/vf_generic.c b/src/mesa/vf/vf_generic.c
new file mode 100644
index 00000000000..baa00af29a6
--- /dev/null
+++ b/src/mesa/vf/vf_generic.c
@@ -0,0 +1,981 @@
+
+/*
+ * Copyright 2003 Tungsten Graphics, 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
+ * 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
+ * TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <[email protected]>
+ */
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/colormac.h"
+#include "main/simple_list.h"
+
+#include "vf/vf.h"
+
+
+/*
+ * These functions take the NDC coordinates pointed to by 'in', apply the
+ * NDC->Viewport mapping and store the results at 'v'.
+ */
+
+static INLINE void insert_4f_viewport_4( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)v;
+ const GLfloat *scale = a->vf->vp;
+ const GLfloat *trans = a->vf->vp + 4;
+
+ out[0] = scale[0] * in[0] + trans[0];
+ out[1] = scale[1] * in[1] + trans[1];
+ out[2] = scale[2] * in[2] + trans[2];
+ out[3] = in[3];
+}
+
+static INLINE void insert_4f_viewport_3( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)v;
+ const GLfloat *scale = a->vf->vp;
+ const GLfloat *trans = a->vf->vp + 4;
+
+ out[0] = scale[0] * in[0] + trans[0];
+ out[1] = scale[1] * in[1] + trans[1];
+ out[2] = scale[2] * in[2] + trans[2];
+ out[3] = 1;
+}
+
+static INLINE void insert_4f_viewport_2( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)v;
+ const GLfloat *scale = a->vf->vp;
+ const GLfloat *trans = a->vf->vp + 4;
+
+ out[0] = scale[0] * in[0] + trans[0];
+ out[1] = scale[1] * in[1] + trans[1];
+ out[2] = trans[2];
+ out[3] = 1;
+}
+
+static INLINE void insert_4f_viewport_1( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)v;
+ const GLfloat *scale = a->vf->vp;
+ const GLfloat *trans = a->vf->vp + 4;
+
+ out[0] = scale[0] * in[0] + trans[0];
+ out[1] = trans[1];
+ out[2] = trans[2];
+ out[3] = 1;
+}
+
+static INLINE void insert_3f_viewport_3( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)v;
+ const GLfloat *scale = a->vf->vp;
+ const GLfloat *trans = a->vf->vp + 4;
+
+ out[0] = scale[0] * in[0] + trans[0];
+ out[1] = scale[1] * in[1] + trans[1];
+ out[2] = scale[2] * in[2] + trans[2];
+}
+
+static INLINE void insert_3f_viewport_2( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)v;
+ const GLfloat *scale = a->vf->vp;
+ const GLfloat *trans = a->vf->vp + 4;
+
+ out[0] = scale[0] * in[0] + trans[0];
+ out[1] = scale[1] * in[1] + trans[1];
+ out[2] = scale[2] * in[2] + trans[2];
+}
+
+static INLINE void insert_3f_viewport_1( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)v;
+ const GLfloat *scale = a->vf->vp;
+ const GLfloat *trans = a->vf->vp + 4;
+
+ out[0] = scale[0] * in[0] + trans[0];
+ out[1] = trans[1];
+ out[2] = trans[2];
+}
+
+static INLINE void insert_2f_viewport_2( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)v;
+ const GLfloat *scale = a->vf->vp;
+ const GLfloat *trans = a->vf->vp + 4;
+
+ out[0] = scale[0] * in[0] + trans[0];
+ out[1] = scale[1] * in[1] + trans[1];
+}
+
+static INLINE void insert_2f_viewport_1( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)v;
+ const GLfloat *scale = a->vf->vp;
+ const GLfloat *trans = a->vf->vp + 4;
+
+ out[0] = scale[0] * in[0] + trans[0];
+ out[1] = trans[1];
+}
+
+
+/*
+ * These functions do the same as above, except for the viewport mapping.
+ */
+
+static INLINE void insert_4f_4( const struct vf_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = in[2];
+ out[3] = in[3];
+}
+
+static INLINE void insert_4f_3( const struct vf_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = in[2];
+ out[3] = 1;
+}
+
+static INLINE void insert_4f_2( const struct vf_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = 0;
+ out[3] = 1;
+}
+
+static INLINE void insert_4f_1( const struct vf_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+}
+
+static INLINE void insert_3f_xyw_4( const struct vf_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = in[3];
+}
+
+static INLINE void insert_3f_xyw_err( const struct vf_attr *a, GLubyte *v, const GLfloat *in )
+{
+ (void) a; (void) v; (void) in;
+ _mesa_exit(1);
+}
+
+static INLINE void insert_3f_3( const struct vf_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = in[2];
+}
+
+static INLINE void insert_3f_2( const struct vf_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = 0;
+}
+
+static INLINE void insert_3f_1( const struct vf_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = 0;
+ out[2] = 0;
+}
+
+
+static INLINE void insert_2f_2( const struct vf_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = in[1];
+}
+
+static INLINE void insert_2f_1( const struct vf_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = 0;
+}
+
+static INLINE void insert_1f_1( const struct vf_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+
+ out[0] = in[0];
+}
+
+static INLINE void insert_null( const struct vf_attr *a, GLubyte *v, const GLfloat *in )
+{
+ (void) a; (void) v; (void) in;
+}
+
+static INLINE void insert_4chan_4f_rgba_4( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLchan *c = (GLchan *)v;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]);
+ UNCLAMPED_FLOAT_TO_CHAN(c[1], in[1]);
+ UNCLAMPED_FLOAT_TO_CHAN(c[2], in[2]);
+ UNCLAMPED_FLOAT_TO_CHAN(c[3], in[3]);
+}
+
+static INLINE void insert_4chan_4f_rgba_3( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLchan *c = (GLchan *)v;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]);
+ UNCLAMPED_FLOAT_TO_CHAN(c[1], in[1]);
+ UNCLAMPED_FLOAT_TO_CHAN(c[2], in[2]);
+ c[3] = CHAN_MAX;
+}
+
+static INLINE void insert_4chan_4f_rgba_2( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLchan *c = (GLchan *)v;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]);
+ UNCLAMPED_FLOAT_TO_CHAN(c[1], in[1]);
+ c[2] = 0;
+ c[3] = CHAN_MAX;
+}
+
+static INLINE void insert_4chan_4f_rgba_1( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLchan *c = (GLchan *)v;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]);
+ c[1] = 0;
+ c[2] = 0;
+ c[3] = CHAN_MAX;
+}
+
+static INLINE void insert_4ub_4f_rgba_4( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[2]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[3]);
+}
+
+static INLINE void insert_4ub_4f_rgba_3( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[2]);
+ v[3] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_rgba_2( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ v[2] = 0;
+ v[3] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_rgba_1( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+ v[1] = 0;
+ v[2] = 0;
+ v[3] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_bgra_4( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[2]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[3]);
+}
+
+static INLINE void insert_4ub_4f_bgra_3( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[2]);
+ v[3] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_bgra_2( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ v[0] = 0;
+ v[3] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_bgra_1( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
+ v[1] = 0;
+ v[0] = 0;
+ v[3] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_argb_4( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[2]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[3]);
+}
+
+static INLINE void insert_4ub_4f_argb_3( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[2]);
+ v[0] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_argb_2( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
+ v[3] = 0x00;
+ v[0] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_argb_1( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]);
+ v[2] = 0x00;
+ v[3] = 0x00;
+ v[0] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_abgr_4( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[2]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[3]);
+}
+
+static INLINE void insert_4ub_4f_abgr_3( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[2]);
+ v[0] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_abgr_2( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
+ v[1] = 0x00;
+ v[0] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_abgr_1( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]);
+ v[2] = 0x00;
+ v[1] = 0x00;
+ v[0] = 0xff;
+}
+
+static INLINE void insert_3ub_3f_rgb_3( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[2]);
+}
+
+static INLINE void insert_3ub_3f_rgb_2( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ v[2] = 0;
+}
+
+static INLINE void insert_3ub_3f_rgb_1( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+ v[1] = 0;
+ v[2] = 0;
+}
+
+static INLINE void insert_3ub_3f_bgr_3( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[2]);
+}
+
+static INLINE void insert_3ub_3f_bgr_2( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ v[0] = 0;
+}
+
+static INLINE void insert_3ub_3f_bgr_1( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
+ v[1] = 0;
+ v[0] = 0;
+}
+
+
+static INLINE void insert_1ub_1f_1( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+}
+
+
+/***********************************************************************
+ * Functions to perform the reverse operations to the above, for
+ * swrast translation and clip-interpolation.
+ *
+ * Currently always extracts a full 4 floats.
+ */
+
+static void extract_4f_viewport( const struct vf_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ const GLfloat *in = (const GLfloat *)v;
+ const GLfloat *scale = a->vf->vp;
+ const GLfloat *trans = a->vf->vp + 4;
+
+ /* Although included for completeness, the position coordinate is
+ * usually handled differently during clipping.
+ */
+ out[0] = (in[0] - trans[0]) / scale[0];
+ out[1] = (in[1] - trans[1]) / scale[1];
+ out[2] = (in[2] - trans[2]) / scale[2];
+ out[3] = in[3];
+}
+
+static void extract_3f_viewport( const struct vf_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ const GLfloat *in = (const GLfloat *)v;
+ const GLfloat *scale = a->vf->vp;
+ const GLfloat *trans = a->vf->vp + 4;
+
+ out[0] = (in[0] - trans[0]) / scale[0];
+ out[1] = (in[1] - trans[1]) / scale[1];
+ out[2] = (in[2] - trans[2]) / scale[2];
+ out[3] = 1;
+}
+
+
+static void extract_2f_viewport( const struct vf_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ const GLfloat *in = (const GLfloat *)v;
+ const GLfloat *scale = a->vf->vp;
+ const GLfloat *trans = a->vf->vp + 4;
+
+ out[0] = (in[0] - trans[0]) / scale[0];
+ out[1] = (in[1] - trans[1]) / scale[1];
+ out[2] = 0;
+ out[3] = 1;
+}
+
+
+static void extract_4f( const struct vf_attr *a, GLfloat *out, const GLubyte *v )
+{
+ const GLfloat *in = (const GLfloat *)v;
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = in[2];
+ out[3] = in[3];
+}
+
+static void extract_3f_xyw( const struct vf_attr *a, GLfloat *out, const GLubyte *v )
+{
+ const GLfloat *in = (const GLfloat *)v;
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = 0;
+ out[3] = in[2];
+}
+
+
+static void extract_3f( const struct vf_attr *a, GLfloat *out, const GLubyte *v )
+{
+ const GLfloat *in = (const GLfloat *)v;
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = in[2];
+ out[3] = 1;
+}
+
+
+static void extract_2f( const struct vf_attr *a, GLfloat *out, const GLubyte *v )
+{
+ const GLfloat *in = (const GLfloat *)v;
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = 0;
+ out[3] = 1;
+}
+
+static void extract_1f( const struct vf_attr *a, GLfloat *out, const GLubyte *v )
+{
+ const GLfloat *in = (const GLfloat *)v;
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+}
+
+static void extract_4chan_4f_rgba( const struct vf_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ GLchan *c = (GLchan *)v;
+ (void) a;
+
+ out[0] = CHAN_TO_FLOAT(c[0]);
+ out[1] = CHAN_TO_FLOAT(c[1]);
+ out[2] = CHAN_TO_FLOAT(c[2]);
+ out[3] = CHAN_TO_FLOAT(c[3]);
+}
+
+static void extract_4ub_4f_rgba( const struct vf_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ (void) a;
+ out[0] = UBYTE_TO_FLOAT(v[0]);
+ out[1] = UBYTE_TO_FLOAT(v[1]);
+ out[2] = UBYTE_TO_FLOAT(v[2]);
+ out[3] = UBYTE_TO_FLOAT(v[3]);
+}
+
+static void extract_4ub_4f_bgra( const struct vf_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ (void) a;
+ out[2] = UBYTE_TO_FLOAT(v[0]);
+ out[1] = UBYTE_TO_FLOAT(v[1]);
+ out[0] = UBYTE_TO_FLOAT(v[2]);
+ out[3] = UBYTE_TO_FLOAT(v[3]);
+}
+
+static void extract_4ub_4f_argb( const struct vf_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ (void) a;
+ out[3] = UBYTE_TO_FLOAT(v[0]);
+ out[0] = UBYTE_TO_FLOAT(v[1]);
+ out[1] = UBYTE_TO_FLOAT(v[2]);
+ out[2] = UBYTE_TO_FLOAT(v[3]);
+}
+
+static void extract_4ub_4f_abgr( const struct vf_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ (void) a;
+ out[3] = UBYTE_TO_FLOAT(v[0]);
+ out[2] = UBYTE_TO_FLOAT(v[1]);
+ out[1] = UBYTE_TO_FLOAT(v[2]);
+ out[0] = UBYTE_TO_FLOAT(v[3]);
+}
+
+static void extract_3ub_3f_rgb( const struct vf_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ (void) a;
+ out[0] = UBYTE_TO_FLOAT(v[0]);
+ out[1] = UBYTE_TO_FLOAT(v[1]);
+ out[2] = UBYTE_TO_FLOAT(v[2]);
+ out[3] = 1;
+}
+
+static void extract_3ub_3f_bgr( const struct vf_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ (void) a;
+ out[2] = UBYTE_TO_FLOAT(v[0]);
+ out[1] = UBYTE_TO_FLOAT(v[1]);
+ out[0] = UBYTE_TO_FLOAT(v[2]);
+ out[3] = 1;
+}
+
+static void extract_1ub_1f( const struct vf_attr *a, GLfloat *out, const GLubyte *v )
+{
+ (void) a;
+ out[0] = UBYTE_TO_FLOAT(v[0]);
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+}
+
+
+const struct vf_format_info vf_format_info[EMIT_MAX] =
+{
+ { "1f",
+ extract_1f,
+ { insert_1f_1, insert_1f_1, insert_1f_1, insert_1f_1 },
+ sizeof(GLfloat) },
+
+ { "2f",
+ extract_2f,
+ { insert_2f_1, insert_2f_2, insert_2f_2, insert_2f_2 },
+ 2 * sizeof(GLfloat) },
+
+ { "3f",
+ extract_3f,
+ { insert_3f_1, insert_3f_2, insert_3f_3, insert_3f_3 },
+ 3 * sizeof(GLfloat) },
+
+ { "4f",
+ extract_4f,
+ { insert_4f_1, insert_4f_2, insert_4f_3, insert_4f_4 },
+ 4 * sizeof(GLfloat) },
+
+ { "2f_viewport",
+ extract_2f_viewport,
+ { insert_2f_viewport_1, insert_2f_viewport_2, insert_2f_viewport_2,
+ insert_2f_viewport_2 },
+ 2 * sizeof(GLfloat) },
+
+ { "3f_viewport",
+ extract_3f_viewport,
+ { insert_3f_viewport_1, insert_3f_viewport_2, insert_3f_viewport_3,
+ insert_3f_viewport_3 },
+ 3 * sizeof(GLfloat) },
+
+ { "4f_viewport",
+ extract_4f_viewport,
+ { insert_4f_viewport_1, insert_4f_viewport_2, insert_4f_viewport_3,
+ insert_4f_viewport_4 },
+ 4 * sizeof(GLfloat) },
+
+ { "3f_xyw",
+ extract_3f_xyw,
+ { insert_3f_xyw_err, insert_3f_xyw_err, insert_3f_xyw_err,
+ insert_3f_xyw_4 },
+ 3 * sizeof(GLfloat) },
+
+ { "1ub_1f",
+ extract_1ub_1f,
+ { insert_1ub_1f_1, insert_1ub_1f_1, insert_1ub_1f_1, insert_1ub_1f_1 },
+ sizeof(GLubyte) },
+
+ { "3ub_3f_rgb",
+ extract_3ub_3f_rgb,
+ { insert_3ub_3f_rgb_1, insert_3ub_3f_rgb_2, insert_3ub_3f_rgb_3,
+ insert_3ub_3f_rgb_3 },
+ 3 * sizeof(GLubyte) },
+
+ { "3ub_3f_bgr",
+ extract_3ub_3f_bgr,
+ { insert_3ub_3f_bgr_1, insert_3ub_3f_bgr_2, insert_3ub_3f_bgr_3,
+ insert_3ub_3f_bgr_3 },
+ 3 * sizeof(GLubyte) },
+
+ { "4ub_4f_rgba",
+ extract_4ub_4f_rgba,
+ { insert_4ub_4f_rgba_1, insert_4ub_4f_rgba_2, insert_4ub_4f_rgba_3,
+ insert_4ub_4f_rgba_4 },
+ 4 * sizeof(GLubyte) },
+
+ { "4ub_4f_bgra",
+ extract_4ub_4f_bgra,
+ { insert_4ub_4f_bgra_1, insert_4ub_4f_bgra_2, insert_4ub_4f_bgra_3,
+ insert_4ub_4f_bgra_4 },
+ 4 * sizeof(GLubyte) },
+
+ { "4ub_4f_argb",
+ extract_4ub_4f_argb,
+ { insert_4ub_4f_argb_1, insert_4ub_4f_argb_2, insert_4ub_4f_argb_3,
+ insert_4ub_4f_argb_4 },
+ 4 * sizeof(GLubyte) },
+
+ { "4ub_4f_abgr",
+ extract_4ub_4f_abgr,
+ { insert_4ub_4f_abgr_1, insert_4ub_4f_abgr_2, insert_4ub_4f_abgr_3,
+ insert_4ub_4f_abgr_4 },
+ 4 * sizeof(GLubyte) },
+
+ { "4chan_4f_rgba",
+ extract_4chan_4f_rgba,
+ { insert_4chan_4f_rgba_1, insert_4chan_4f_rgba_2, insert_4chan_4f_rgba_3,
+ insert_4chan_4f_rgba_4 },
+ 4 * sizeof(GLchan) },
+
+ { "pad",
+ NULL,
+ { NULL, NULL, NULL, NULL },
+ 0 }
+
+};
+
+
+
+
+/***********************************************************************
+ * Hardwired fastpaths for emitting whole vertices or groups of
+ * vertices
+ */
+#define EMIT5(NR, F0, F1, F2, F3, F4, NAME) \
+static void NAME( struct vertex_fetch *vf, \
+ GLuint count, \
+ GLubyte *v ) \
+{ \
+ struct vf_attr *a = vf->attr; \
+ GLuint i; \
+ \
+ for (i = 0 ; i < count ; i++, v += vf->vertex_stride) { \
+ if (NR > 0) { \
+ F0( &a[0], v + a[0].vertoffset, (GLfloat *)a[0].inputptr ); \
+ a[0].inputptr += a[0].inputstride; \
+ } \
+ \
+ if (NR > 1) { \
+ F1( &a[1], v + a[1].vertoffset, (GLfloat *)a[1].inputptr ); \
+ a[1].inputptr += a[1].inputstride; \
+ } \
+ \
+ if (NR > 2) { \
+ F2( &a[2], v + a[2].vertoffset, (GLfloat *)a[2].inputptr ); \
+ a[2].inputptr += a[2].inputstride; \
+ } \
+ \
+ if (NR > 3) { \
+ F3( &a[3], v + a[3].vertoffset, (GLfloat *)a[3].inputptr ); \
+ a[3].inputptr += a[3].inputstride; \
+ } \
+ \
+ if (NR > 4) { \
+ F4( &a[4], v + a[4].vertoffset, (GLfloat *)a[4].inputptr ); \
+ a[4].inputptr += a[4].inputstride; \
+ } \
+ } \
+}
+
+
+#define EMIT2(F0, F1, NAME) EMIT5(2, F0, F1, insert_null, \
+ insert_null, insert_null, NAME)
+
+#define EMIT3(F0, F1, F2, NAME) EMIT5(3, F0, F1, F2, insert_null, \
+ insert_null, NAME)
+
+#define EMIT4(F0, F1, F2, F3, NAME) EMIT5(4, F0, F1, F2, F3, \
+ insert_null, NAME)
+
+
+EMIT2(insert_3f_viewport_3, insert_4ub_4f_rgba_4, emit_viewport3_rgba4)
+EMIT2(insert_3f_viewport_3, insert_4ub_4f_bgra_4, emit_viewport3_bgra4)
+EMIT2(insert_3f_3, insert_4ub_4f_rgba_4, emit_xyz3_rgba4)
+
+EMIT3(insert_4f_viewport_4, insert_4ub_4f_rgba_4, insert_2f_2, emit_viewport4_rgba4_st2)
+EMIT3(insert_4f_viewport_4, insert_4ub_4f_bgra_4, insert_2f_2, emit_viewport4_bgra4_st2)
+EMIT3(insert_4f_4, insert_4ub_4f_rgba_4, insert_2f_2, emit_xyzw4_rgba4_st2)
+
+EMIT4(insert_4f_viewport_4, insert_4ub_4f_rgba_4, insert_2f_2, insert_2f_2, emit_viewport4_rgba4_st2_st2)
+EMIT4(insert_4f_viewport_4, insert_4ub_4f_bgra_4, insert_2f_2, insert_2f_2, emit_viewport4_bgra4_st2_st2)
+EMIT4(insert_4f_4, insert_4ub_4f_rgba_4, insert_2f_2, insert_2f_2, emit_xyzw4_rgba4_st2_st2)
+
+
+/* Use the codegen paths to select one of a number of hardwired
+ * fastpaths.
+ */
+void vf_generate_hardwired_emit( struct vertex_fetch *vf )
+{
+ vf_emit_func func = NULL;
+
+ /* Does it fit a hardwired fastpath? Help! this is growing out of
+ * control!
+ */
+ switch (vf->attr_count) {
+ case 2:
+ if (vf->attr[0].do_insert == insert_3f_viewport_3) {
+ if (vf->attr[1].do_insert == insert_4ub_4f_bgra_4)
+ func = emit_viewport3_bgra4;
+ else if (vf->attr[1].do_insert == insert_4ub_4f_rgba_4)
+ func = emit_viewport3_rgba4;
+ }
+ else if (vf->attr[0].do_insert == insert_3f_3 &&
+ vf->attr[1].do_insert == insert_4ub_4f_rgba_4) {
+ func = emit_xyz3_rgba4;
+ }
+ break;
+ case 3:
+ if (vf->attr[2].do_insert == insert_2f_2) {
+ if (vf->attr[1].do_insert == insert_4ub_4f_rgba_4) {
+ if (vf->attr[0].do_insert == insert_4f_viewport_4)
+ func = emit_viewport4_rgba4_st2;
+ else if (vf->attr[0].do_insert == insert_4f_4)
+ func = emit_xyzw4_rgba4_st2;
+ }
+ else if (vf->attr[1].do_insert == insert_4ub_4f_bgra_4 &&
+ vf->attr[0].do_insert == insert_4f_viewport_4)
+ func = emit_viewport4_bgra4_st2;
+ }
+ break;
+ case 4:
+ if (vf->attr[2].do_insert == insert_2f_2 &&
+ vf->attr[3].do_insert == insert_2f_2) {
+ if (vf->attr[1].do_insert == insert_4ub_4f_rgba_4) {
+ if (vf->attr[0].do_insert == insert_4f_viewport_4)
+ func = emit_viewport4_rgba4_st2_st2;
+ else if (vf->attr[0].do_insert == insert_4f_4)
+ func = emit_xyzw4_rgba4_st2_st2;
+ }
+ else if (vf->attr[1].do_insert == insert_4ub_4f_bgra_4 &&
+ vf->attr[0].do_insert == insert_4f_viewport_4)
+ func = emit_viewport4_bgra4_st2_st2;
+ }
+ break;
+ }
+
+ vf->emit = func;
+}
+
+/***********************************************************************
+ * Generic (non-codegen) functions for whole vertices or groups of
+ * vertices
+ */
+
+void vf_generic_emit( struct vertex_fetch *vf,
+ GLuint count,
+ GLubyte *v )
+{
+ struct vf_attr *a = vf->attr;
+ const GLuint attr_count = vf->attr_count;
+ const GLuint stride = vf->vertex_stride;
+ GLuint i, j;
+
+ for (i = 0 ; i < count ; i++, v += stride) {
+ for (j = 0; j < attr_count; j++) {
+ GLfloat *in = (GLfloat *)a[j].inputptr;
+ a[j].inputptr += a[j].inputstride;
+ a[j].do_insert( &a[j], v + a[j].vertoffset, in );
+ }
+ }
+}
+
+
diff --git a/src/mesa/vf/vf_sse.c b/src/mesa/vf/vf_sse.c
new file mode 100644
index 00000000000..4d70196ffed
--- /dev/null
+++ b/src/mesa/vf/vf_sse.c
@@ -0,0 +1,662 @@
+/*
+ * Copyright 2003 Tungsten Graphics, 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
+ * 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
+ * TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <[email protected]>
+ */
+
+#include "main/glheader.h"
+#include "main/colormac.h"
+#include "main/simple_list.h"
+#include "main/enums.h"
+
+#include "vf/vf.h"
+
+#if defined(USE_SSE_ASM)
+
+#include "x86/rtasm/x86sse.h"
+#include "x86/common_x86_asm.h"
+
+
+#define X 0
+#define Y 1
+#define Z 2
+#define W 3
+
+
+struct x86_program {
+ struct x86_function func;
+
+ struct vertex_fetch *vf;
+ GLboolean inputs_safe;
+ GLboolean outputs_safe;
+ GLboolean have_sse2;
+
+ struct x86_reg identity;
+ struct x86_reg chan0;
+};
+
+
+static struct x86_reg get_identity( struct x86_program *p )
+{
+ return p->identity;
+}
+
+static void emit_load4f_4( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ sse_movups(&p->func, dest, arg0);
+}
+
+static void emit_load4f_3( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ /* Have to jump through some hoops:
+ *
+ * c 0 0 0
+ * c 0 0 1
+ * 0 0 c 1
+ * a b c 1
+ */
+ sse_movss(&p->func, dest, x86_make_disp(arg0, 8));
+ sse_shufps(&p->func, dest, get_identity(p), SHUF(X,Y,Z,W) );
+ sse_shufps(&p->func, dest, dest, SHUF(Y,Z,X,W) );
+ sse_movlps(&p->func, dest, arg0);
+}
+
+static void emit_load4f_2( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ /* Initialize from identity, then pull in low two words:
+ */
+ sse_movups(&p->func, dest, get_identity(p));
+ sse_movlps(&p->func, dest, arg0);
+}
+
+static void emit_load4f_1( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ /* Pull in low word, then swizzle in identity */
+ sse_movss(&p->func, dest, arg0);
+ sse_shufps(&p->func, dest, get_identity(p), SHUF(X,Y,Z,W) );
+}
+
+
+
+static void emit_load3f_3( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ /* Over-reads by 1 dword - potential SEGV if input is a vertex
+ * array.
+ */
+ if (p->inputs_safe) {
+ sse_movups(&p->func, dest, arg0);
+ }
+ else {
+ /* c 0 0 0
+ * c c c c
+ * a b c c
+ */
+ sse_movss(&p->func, dest, x86_make_disp(arg0, 8));
+ sse_shufps(&p->func, dest, dest, SHUF(X,X,X,X));
+ sse_movlps(&p->func, dest, arg0);
+ }
+}
+
+static void emit_load3f_2( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ emit_load4f_2(p, dest, arg0);
+}
+
+static void emit_load3f_1( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ emit_load4f_1(p, dest, arg0);
+}
+
+static void emit_load2f_2( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ sse_movlps(&p->func, dest, arg0);
+}
+
+static void emit_load2f_1( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ emit_load4f_1(p, dest, arg0);
+}
+
+static void emit_load1f_1( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ sse_movss(&p->func, dest, arg0);
+}
+
+static void (*load[4][4])( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 ) = {
+ { emit_load1f_1,
+ emit_load1f_1,
+ emit_load1f_1,
+ emit_load1f_1 },
+
+ { emit_load2f_1,
+ emit_load2f_2,
+ emit_load2f_2,
+ emit_load2f_2 },
+
+ { emit_load3f_1,
+ emit_load3f_2,
+ emit_load3f_3,
+ emit_load3f_3 },
+
+ { emit_load4f_1,
+ emit_load4f_2,
+ emit_load4f_3,
+ emit_load4f_4 }
+};
+
+static void emit_load( struct x86_program *p,
+ struct x86_reg dest,
+ GLuint sz,
+ struct x86_reg src,
+ GLuint src_sz)
+{
+ load[sz-1][src_sz-1](p, dest, src);
+}
+
+static void emit_store4f( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ sse_movups(&p->func, dest, arg0);
+}
+
+static void emit_store3f( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ if (p->outputs_safe) {
+ /* Emit the extra dword anyway. This may hurt writecombining,
+ * may cause other problems.
+ */
+ sse_movups(&p->func, dest, arg0);
+ }
+ else {
+ /* Alternate strategy - emit two, shuffle, emit one.
+ */
+ sse_movlps(&p->func, dest, arg0);
+ sse_shufps(&p->func, arg0, arg0, SHUF(Z,Z,Z,Z) ); /* NOTE! destructive */
+ sse_movss(&p->func, x86_make_disp(dest,8), arg0);
+ }
+}
+
+static void emit_store2f( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ sse_movlps(&p->func, dest, arg0);
+}
+
+static void emit_store1f( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ sse_movss(&p->func, dest, arg0);
+}
+
+
+static void (*store[4])( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 ) =
+{
+ emit_store1f,
+ emit_store2f,
+ emit_store3f,
+ emit_store4f
+};
+
+static void emit_store( struct x86_program *p,
+ struct x86_reg dest,
+ GLuint sz,
+ struct x86_reg temp )
+
+{
+ store[sz-1](p, dest, temp);
+}
+
+static void emit_pack_store_4ub( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg temp )
+{
+ /* Scale by 255.0
+ */
+ sse_mulps(&p->func, temp, p->chan0);
+
+ if (p->have_sse2) {
+ sse2_cvtps2dq(&p->func, temp, temp);
+ sse2_packssdw(&p->func, temp, temp);
+ sse2_packuswb(&p->func, temp, temp);
+ sse_movss(&p->func, dest, temp);
+ }
+ else {
+ struct x86_reg mmx0 = x86_make_reg(file_MMX, 0);
+ struct x86_reg mmx1 = x86_make_reg(file_MMX, 1);
+ sse_cvtps2pi(&p->func, mmx0, temp);
+ sse_movhlps(&p->func, temp, temp);
+ sse_cvtps2pi(&p->func, mmx1, temp);
+ mmx_packssdw(&p->func, mmx0, mmx1);
+ mmx_packuswb(&p->func, mmx0, mmx0);
+ mmx_movd(&p->func, dest, mmx0);
+ }
+}
+
+static GLint get_offset( const void *a, const void *b )
+{
+ return (const char *)b - (const char *)a;
+}
+
+/* Not much happens here. Eventually use this function to try and
+ * avoid saving/reloading the source pointers each vertex (if some of
+ * them can fit in registers).
+ */
+static void get_src_ptr( struct x86_program *p,
+ struct x86_reg srcREG,
+ struct x86_reg vfREG,
+ struct vf_attr *a )
+{
+ struct vertex_fetch *vf = p->vf;
+ struct x86_reg ptr_to_src = x86_make_disp(vfREG, get_offset(vf, &a->inputptr));
+
+ /* Load current a[j].inputptr
+ */
+ x86_mov(&p->func, srcREG, ptr_to_src);
+}
+
+static void update_src_ptr( struct x86_program *p,
+ struct x86_reg srcREG,
+ struct x86_reg vfREG,
+ struct vf_attr *a )
+{
+ if (a->inputstride) {
+ struct vertex_fetch *vf = p->vf;
+ struct x86_reg ptr_to_src = x86_make_disp(vfREG, get_offset(vf, &a->inputptr));
+
+ /* add a[j].inputstride (hardcoded value - could just as easily
+ * pull the stride value from memory each time).
+ */
+ x86_lea(&p->func, srcREG, x86_make_disp(srcREG, a->inputstride));
+
+ /* save new value of a[j].inputptr
+ */
+ x86_mov(&p->func, ptr_to_src, srcREG);
+ }
+}
+
+
+/* Lots of hardcoding
+ *
+ * EAX -- pointer to current output vertex
+ * ECX -- pointer to current attribute
+ *
+ */
+static GLboolean build_vertex_emit( struct x86_program *p )
+{
+ struct vertex_fetch *vf = p->vf;
+ GLuint j = 0;
+
+ struct x86_reg vertexEAX = x86_make_reg(file_REG32, reg_AX);
+ struct x86_reg srcECX = x86_make_reg(file_REG32, reg_CX);
+ struct x86_reg countEBP = x86_make_reg(file_REG32, reg_BP);
+ struct x86_reg vfESI = x86_make_reg(file_REG32, reg_SI);
+ struct x86_reg temp = x86_make_reg(file_XMM, 0);
+ struct x86_reg vp0 = x86_make_reg(file_XMM, 1);
+ struct x86_reg vp1 = x86_make_reg(file_XMM, 2);
+ GLubyte *fixup, *label;
+
+ /* Push a few regs?
+ */
+ x86_push(&p->func, countEBP);
+ x86_push(&p->func, vfESI);
+
+
+ /* Get vertex count, compare to zero
+ */
+ x86_xor(&p->func, srcECX, srcECX);
+ x86_mov(&p->func, countEBP, x86_fn_arg(&p->func, 2));
+ x86_cmp(&p->func, countEBP, srcECX);
+ fixup = x86_jcc_forward(&p->func, cc_E);
+
+ /* Initialize destination register.
+ */
+ x86_mov(&p->func, vertexEAX, x86_fn_arg(&p->func, 3));
+
+ /* Move argument 1 (vf) into a reg:
+ */
+ x86_mov(&p->func, vfESI, x86_fn_arg(&p->func, 1));
+
+
+ /* Possibly load vp0, vp1 for viewport calcs:
+ */
+ if (vf->allow_viewport_emits) {
+ sse_movups(&p->func, vp0, x86_make_disp(vfESI, get_offset(vf, &vf->vp[0])));
+ sse_movups(&p->func, vp1, x86_make_disp(vfESI, get_offset(vf, &vf->vp[4])));
+ }
+
+ /* always load, needed or not:
+ */
+ sse_movups(&p->func, p->chan0, x86_make_disp(vfESI, get_offset(vf, &vf->chan_scale[0])));
+ sse_movups(&p->func, p->identity, x86_make_disp(vfESI, get_offset(vf, &vf->identity[0])));
+
+ /* Note address for loop jump */
+ label = x86_get_label(&p->func);
+
+ /* Emit code for each of the attributes. Currently routes
+ * everything through SSE registers, even when it might be more
+ * efficient to stick with regular old x86. No optimization or
+ * other tricks - enough new ground to cover here just getting
+ * things working.
+ */
+ while (j < vf->attr_count) {
+ struct vf_attr *a = &vf->attr[j];
+ struct x86_reg dest = x86_make_disp(vertexEAX, a->vertoffset);
+
+ /* Now, load an XMM reg from src, perhaps transform, then save.
+ * Could be shortcircuited in specific cases:
+ */
+ switch (a->format) {
+ case EMIT_1F:
+ get_src_ptr(p, srcECX, vfESI, a);
+ emit_load(p, temp, 1, x86_deref(srcECX), a->inputsize);
+ emit_store(p, dest, 1, temp);
+ update_src_ptr(p, srcECX, vfESI, a);
+ break;
+ case EMIT_2F:
+ get_src_ptr(p, srcECX, vfESI, a);
+ emit_load(p, temp, 2, x86_deref(srcECX), a->inputsize);
+ emit_store(p, dest, 2, temp);
+ update_src_ptr(p, srcECX, vfESI, a);
+ break;
+ case EMIT_3F:
+ /* Potentially the worst case - hardcode 2+1 copying:
+ */
+ if (0) {
+ get_src_ptr(p, srcECX, vfESI, a);
+ emit_load(p, temp, 3, x86_deref(srcECX), a->inputsize);
+ emit_store(p, dest, 3, temp);
+ update_src_ptr(p, srcECX, vfESI, a);
+ }
+ else {
+ get_src_ptr(p, srcECX, vfESI, a);
+ emit_load(p, temp, 2, x86_deref(srcECX), a->inputsize);
+ emit_store(p, dest, 2, temp);
+ if (a->inputsize > 2) {
+ emit_load(p, temp, 1, x86_make_disp(srcECX, 8), 1);
+ emit_store(p, x86_make_disp(dest,8), 1, temp);
+ }
+ else {
+ sse_movss(&p->func, x86_make_disp(dest,8), get_identity(p));
+ }
+ update_src_ptr(p, srcECX, vfESI, a);
+ }
+ break;
+ case EMIT_4F:
+ get_src_ptr(p, srcECX, vfESI, a);
+ emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+ emit_store(p, dest, 4, temp);
+ update_src_ptr(p, srcECX, vfESI, a);
+ break;
+ case EMIT_2F_VIEWPORT:
+ get_src_ptr(p, srcECX, vfESI, a);
+ emit_load(p, temp, 2, x86_deref(srcECX), a->inputsize);
+ sse_mulps(&p->func, temp, vp0);
+ sse_addps(&p->func, temp, vp1);
+ emit_store(p, dest, 2, temp);
+ update_src_ptr(p, srcECX, vfESI, a);
+ break;
+ case EMIT_3F_VIEWPORT:
+ get_src_ptr(p, srcECX, vfESI, a);
+ emit_load(p, temp, 3, x86_deref(srcECX), a->inputsize);
+ sse_mulps(&p->func, temp, vp0);
+ sse_addps(&p->func, temp, vp1);
+ emit_store(p, dest, 3, temp);
+ update_src_ptr(p, srcECX, vfESI, a);
+ break;
+ case EMIT_4F_VIEWPORT:
+ get_src_ptr(p, srcECX, vfESI, a);
+ emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+ sse_mulps(&p->func, temp, vp0);
+ sse_addps(&p->func, temp, vp1);
+ emit_store(p, dest, 4, temp);
+ update_src_ptr(p, srcECX, vfESI, a);
+ break;
+ case EMIT_3F_XYW:
+ get_src_ptr(p, srcECX, vfESI, a);
+ emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+ sse_shufps(&p->func, temp, temp, SHUF(X,Y,W,Z));
+ emit_store(p, dest, 3, temp);
+ update_src_ptr(p, srcECX, vfESI, a);
+ break;
+
+ case EMIT_1UB_1F:
+ /* Test for PAD3 + 1UB:
+ */
+ if (j > 0 &&
+ a[-1].vertoffset + a[-1].vertattrsize <= a->vertoffset - 3)
+ {
+ get_src_ptr(p, srcECX, vfESI, a);
+ emit_load(p, temp, 1, x86_deref(srcECX), a->inputsize);
+ sse_shufps(&p->func, temp, temp, SHUF(X,X,X,X));
+ emit_pack_store_4ub(p, x86_make_disp(dest, -3), temp); /* overkill! */
+ update_src_ptr(p, srcECX, vfESI, a);
+ }
+ else {
+ _mesa_printf("Can't emit 1ub %x %x %d\n", a->vertoffset, a[-1].vertoffset, a[-1].vertattrsize );
+ return GL_FALSE;
+ }
+ break;
+ case EMIT_3UB_3F_RGB:
+ case EMIT_3UB_3F_BGR:
+ /* Test for 3UB + PAD1:
+ */
+ if (j == vf->attr_count - 1 ||
+ a[1].vertoffset >= a->vertoffset + 4) {
+ get_src_ptr(p, srcECX, vfESI, a);
+ emit_load(p, temp, 3, x86_deref(srcECX), a->inputsize);
+ if (a->format == EMIT_3UB_3F_BGR)
+ sse_shufps(&p->func, temp, temp, SHUF(Z,Y,X,W));
+ emit_pack_store_4ub(p, dest, temp);
+ update_src_ptr(p, srcECX, vfESI, a);
+ }
+ /* Test for 3UB + 1UB:
+ */
+ else if (j < vf->attr_count - 1 &&
+ a[1].format == EMIT_1UB_1F &&
+ a[1].vertoffset == a->vertoffset + 3) {
+ get_src_ptr(p, srcECX, vfESI, a);
+ emit_load(p, temp, 3, x86_deref(srcECX), a->inputsize);
+ update_src_ptr(p, srcECX, vfESI, a);
+
+ /* Make room for incoming value:
+ */
+ sse_shufps(&p->func, temp, temp, SHUF(W,X,Y,Z));
+
+ get_src_ptr(p, srcECX, vfESI, &a[1]);
+ emit_load(p, temp, 1, x86_deref(srcECX), a[1].inputsize);
+ update_src_ptr(p, srcECX, vfESI, &a[1]);
+
+ /* Rearrange and possibly do BGR conversion:
+ */
+ if (a->format == EMIT_3UB_3F_BGR)
+ sse_shufps(&p->func, temp, temp, SHUF(W,Z,Y,X));
+ else
+ sse_shufps(&p->func, temp, temp, SHUF(Y,Z,W,X));
+
+ emit_pack_store_4ub(p, dest, temp);
+ j++; /* NOTE: two attrs consumed */
+ }
+ else {
+ _mesa_printf("Can't emit 3ub\n");
+ }
+ return GL_FALSE; /* add this later */
+ break;
+
+ case EMIT_4UB_4F_RGBA:
+ get_src_ptr(p, srcECX, vfESI, a);
+ emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+ emit_pack_store_4ub(p, dest, temp);
+ update_src_ptr(p, srcECX, vfESI, a);
+ break;
+ case EMIT_4UB_4F_BGRA:
+ get_src_ptr(p, srcECX, vfESI, a);
+ emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+ sse_shufps(&p->func, temp, temp, SHUF(Z,Y,X,W));
+ emit_pack_store_4ub(p, dest, temp);
+ update_src_ptr(p, srcECX, vfESI, a);
+ break;
+ case EMIT_4UB_4F_ARGB:
+ get_src_ptr(p, srcECX, vfESI, a);
+ emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+ sse_shufps(&p->func, temp, temp, SHUF(W,X,Y,Z));
+ emit_pack_store_4ub(p, dest, temp);
+ update_src_ptr(p, srcECX, vfESI, a);
+ break;
+ case EMIT_4UB_4F_ABGR:
+ get_src_ptr(p, srcECX, vfESI, a);
+ emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+ sse_shufps(&p->func, temp, temp, SHUF(W,Z,Y,X));
+ emit_pack_store_4ub(p, dest, temp);
+ update_src_ptr(p, srcECX, vfESI, a);
+ break;
+ case EMIT_4CHAN_4F_RGBA:
+ switch (CHAN_TYPE) {
+ case GL_UNSIGNED_BYTE:
+ get_src_ptr(p, srcECX, vfESI, a);
+ emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+ emit_pack_store_4ub(p, dest, temp);
+ update_src_ptr(p, srcECX, vfESI, a);
+ break;
+ case GL_FLOAT:
+ get_src_ptr(p, srcECX, vfESI, a);
+ emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+ emit_store(p, dest, 4, temp);
+ update_src_ptr(p, srcECX, vfESI, a);
+ break;
+ case GL_UNSIGNED_SHORT:
+ default:
+ _mesa_printf("unknown CHAN_TYPE %s\n", _mesa_lookup_enum_by_nr(CHAN_TYPE));
+ return GL_FALSE;
+ }
+ break;
+ default:
+ _mesa_printf("unknown a[%d].format %d\n", j, a->format);
+ return GL_FALSE; /* catch any new opcodes */
+ }
+
+ /* Increment j by at least 1 - may have been incremented above also:
+ */
+ j++;
+ }
+
+ /* Next vertex:
+ */
+ x86_lea(&p->func, vertexEAX, x86_make_disp(vertexEAX, vf->vertex_stride));
+
+ /* decr count, loop if not zero
+ */
+ x86_dec(&p->func, countEBP);
+ x86_test(&p->func, countEBP, countEBP);
+ x86_jcc(&p->func, cc_NZ, label);
+
+ /* Exit mmx state?
+ */
+ if (p->func.need_emms)
+ mmx_emms(&p->func);
+
+ /* Land forward jump here:
+ */
+ x86_fixup_fwd_jump(&p->func, fixup);
+
+ /* Pop regs and return
+ */
+ x86_pop(&p->func, x86_get_base_reg(vfESI));
+ x86_pop(&p->func, countEBP);
+ x86_ret(&p->func);
+
+ vf->emit = (vf_emit_func)x86_get_func(&p->func);
+ return GL_TRUE;
+}
+
+
+
+void vf_generate_sse_emit( struct vertex_fetch *vf )
+{
+ struct x86_program p;
+
+ if (!cpu_has_xmm) {
+ vf->codegen_emit = NULL;
+ return;
+ }
+
+ _mesa_memset(&p, 0, sizeof(p));
+
+ p.vf = vf;
+ p.inputs_safe = 0; /* for now */
+ p.outputs_safe = 0; /* for now */
+ p.have_sse2 = cpu_has_xmm2;
+ p.identity = x86_make_reg(file_XMM, 6);
+ p.chan0 = x86_make_reg(file_XMM, 7);
+
+ x86_init_func(&p.func);
+
+ if (build_vertex_emit(&p)) {
+ vf_register_fastpath( vf, GL_TRUE );
+ }
+ else {
+ /* Note the failure so that we don't keep trying to codegen an
+ * impossible state:
+ */
+ vf_register_fastpath( vf, GL_FALSE );
+ x86_release_func(&p.func);
+ }
+}
+
+#else
+
+void vf_generate_sse_emit( struct vertex_fetch *vf )
+{
+ /* Dummy version for when USE_SSE_ASM not defined */
+}
+
+#endif
diff --git a/src/mesa/x86/Makefile b/src/mesa/x86/Makefile
index dc8c7f355eb..aa49a9134aa 100644
--- a/src/mesa/x86/Makefile
+++ b/src/mesa/x86/Makefile
@@ -21,7 +21,7 @@ clean:
gen_matypes: gen_matypes.c
- $(CC) $(INCLUDE_DIRS) $(CFLAGS) gen_matypes.c -o gen_matypes
+ $(HOST_CC) $(INCLUDE_DIRS) $(HOST_CFLAGS) gen_matypes.c -o gen_matypes
# need some special rules here, unfortunately
matypes.h: ../main/mtypes.h ../tnl/t_context.h gen_matypes
diff --git a/src/mesa/x86/rtasm/x86sse.c b/src/mesa/x86/rtasm/x86sse.c
index e68f8dfec13..5aedf5b04be 100644
--- a/src/mesa/x86/rtasm/x86sse.c
+++ b/src/mesa/x86/rtasm/x86sse.c
@@ -1,3 +1,4 @@
+#ifdef USE_X86_ASM
#if defined(__i386__) || defined(__386__)
#include "main/imports.h"
@@ -290,7 +291,7 @@ void x86_call( struct x86_function *p, void (*label)())
void x86_call( struct x86_function *p, struct x86_reg reg)
{
emit_1ub(p, 0xff);
- emit_modrm(p, reg, reg);
+ emit_modrm_noreg(p, 2, reg);
}
#endif
@@ -1192,3 +1193,9 @@ void x86sse_dummy( void )
}
#endif
+
+#else /* USE_X86_ASM */
+
+int x86sse_c_dummy_var; /* silence warning */
+
+#endif /* USE_X86_ASM */