summaryrefslogtreecommitdiff
path: root/src/VBox/GuestHost/OpenGL
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2014-03-26 19:21:20 +0000
committer <>2014-05-08 15:03:54 +0000
commitfb123f93f9f5ce42c8e5785d2f8e0edaf951740e (patch)
treec2103d76aec5f1f10892cd1d3a38e24f665ae5db /src/VBox/GuestHost/OpenGL
parent58ed4748338f9466599adfc8a9171280ed99e23f (diff)
downloadVirtualBox-master.tar.gz
Imported from /home/lorry/working-area/delta_VirtualBox/VirtualBox-4.3.10.tar.bz2.HEADVirtualBox-4.3.10master
Diffstat (limited to 'src/VBox/GuestHost/OpenGL')
-rw-r--r--src/VBox/GuestHost/OpenGL/Makefile.kmk68
-rw-r--r--src/VBox/GuestHost/OpenGL/glapi_parser/APIspec.txt101
-rwxr-xr-xsrc/VBox/GuestHost/OpenGL/glapi_parser/apiutil.py53
-rw-r--r--src/VBox/GuestHost/OpenGL/include/GL/glext.h122
-rw-r--r--src/VBox/GuestHost/OpenGL/include/chromium.h45
-rw-r--r--src/VBox/GuestHost/OpenGL/include/cr_blitter.h323
-rw-r--r--src/VBox/GuestHost/OpenGL/include/cr_bmpscale.h25
-rw-r--r--src/VBox/GuestHost/OpenGL/include/cr_compositor.h233
-rw-r--r--src/VBox/GuestHost/OpenGL/include/cr_dump.h177
-rw-r--r--src/VBox/GuestHost/OpenGL/include/cr_error.h19
-rw-r--r--src/VBox/GuestHost/OpenGL/include/cr_extstring.h4
-rw-r--r--src/VBox/GuestHost/OpenGL/include/cr_glext.h34
-rw-r--r--src/VBox/GuestHost/OpenGL/include/cr_glstate.h65
-rw-r--r--src/VBox/GuestHost/OpenGL/include/cr_hash.h22
-rw-r--r--src/VBox/GuestHost/OpenGL/include/cr_htable.h120
-rw-r--r--src/VBox/GuestHost/OpenGL/include/cr_pack.h22
-rw-r--r--src/VBox/GuestHost/OpenGL/include/cr_pixeldata.h3
-rw-r--r--src/VBox/GuestHost/OpenGL/include/cr_protocol.h46
-rw-r--r--src/VBox/GuestHost/OpenGL/include/cr_server.h287
-rw-r--r--src/VBox/GuestHost/OpenGL/include/cr_string.h24
-rw-r--r--src/VBox/GuestHost/OpenGL/include/cr_version.h39
-rw-r--r--src/VBox/GuestHost/OpenGL/include/cr_vreg.h377
-rw-r--r--src/VBox/GuestHost/OpenGL/include/state/cr_attrib.h12
-rw-r--r--src/VBox/GuestHost/OpenGL/include/state/cr_bufferobject.h5
-rw-r--r--src/VBox/GuestHost/OpenGL/include/state/cr_client.h6
-rw-r--r--src/VBox/GuestHost/OpenGL/include/state/cr_framebuffer.h14
-rw-r--r--src/VBox/GuestHost/OpenGL/include/state/cr_glsl.h3
-rw-r--r--src/VBox/GuestHost/OpenGL/include/state/cr_point.h3
-rw-r--r--src/VBox/GuestHost/OpenGL/include/state/cr_stencil.h84
-rw-r--r--src/VBox/GuestHost/OpenGL/include/state/cr_texture.h4
-rw-r--r--src/VBox/GuestHost/OpenGL/packer/opcodes.py33
-rw-r--r--src/VBox/GuestHost/OpenGL/packer/pack_buffer.c25
-rw-r--r--src/VBox/GuestHost/OpenGL/packer/pack_extensions.c2
-rw-r--r--src/VBox/GuestHost/OpenGL/packer/pack_framebuffer.c2
-rw-r--r--src/VBox/GuestHost/OpenGL/packer/pack_misc.c84
-rw-r--r--src/VBox/GuestHost/OpenGL/packer/pack_pixels.c3
-rw-r--r--src/VBox/GuestHost/OpenGL/packer/pack_shaders.c24
-rw-r--r--src/VBox/GuestHost/OpenGL/packer/pack_visibleregion.c6
-rw-r--r--src/VBox/GuestHost/OpenGL/packer/packer.h4
-rw-r--r--src/VBox/GuestHost/OpenGL/packer/packer.py4
-rw-r--r--src/VBox/GuestHost/OpenGL/packer/packer_special4
-rw-r--r--src/VBox/GuestHost/OpenGL/spu_loader/glloader.py4
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/dump.cpp1741
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/dump_gen.py257
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/get_components.py144
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state.h21
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_attrib.c39
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_bits_globalop.h338
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_buffer.c2
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_bufferobject.c218
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_client.c218
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_diff.c332
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_enable.c7
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_error.c7
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_framebuffer.c620
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_get.py2
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_get.txt21
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_glsl.c60
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_init.c163
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_lists.c200
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_point.c259
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_point.txt1
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_polygon.c3
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_program.c17
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_snapshot.c837
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_special7
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_stencil.c1335
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_texdiff.c10
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_teximage.c67
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_texture.c111
-rw-r--r--src/VBox/GuestHost/OpenGL/util/blitter.cpp1751
-rw-r--r--src/VBox/GuestHost/OpenGL/util/bmpscale.cpp319
-rw-r--r--src/VBox/GuestHost/OpenGL/util/compositor.cpp1015
-rw-r--r--src/VBox/GuestHost/OpenGL/util/dll.c74
-rw-r--r--src/VBox/GuestHost/OpenGL/util/error.c27
-rw-r--r--src/VBox/GuestHost/OpenGL/util/hash.c492
-rw-r--r--src/VBox/GuestHost/OpenGL/util/htable.cpp195
-rw-r--r--src/VBox/GuestHost/OpenGL/util/net.c18
-rw-r--r--src/VBox/GuestHost/OpenGL/util/pixel.c20
-rw-r--r--src/VBox/GuestHost/OpenGL/util/string.c123
-rw-r--r--src/VBox/GuestHost/OpenGL/util/util.def4
-rw-r--r--src/VBox/GuestHost/OpenGL/util/vboxhgcm.c149
-rw-r--r--src/VBox/GuestHost/OpenGL/util/vboxhgsmi.c2
-rw-r--r--src/VBox/GuestHost/OpenGL/util/vreg.cpp1692
84 files changed, 13882 insertions, 1571 deletions
diff --git a/src/VBox/GuestHost/OpenGL/Makefile.kmk b/src/VBox/GuestHost/OpenGL/Makefile.kmk
index 2cbb0b84..2a1d1dac 100644
--- a/src/VBox/GuestHost/OpenGL/Makefile.kmk
+++ b/src/VBox/GuestHost/OpenGL/Makefile.kmk
@@ -4,7 +4,7 @@
#
#
-# Copyright (C) 2008-2012 Oracle Corporation
+# Copyright (C) 2008-2013 Oracle Corporation
#
# This file is part of VirtualBox Open Source Edition (OSE), as
# available from http://www.virtualbox.org. This file is free software;
@@ -27,6 +27,12 @@ BLDDIRS += \
$(VBOX_PATH_CROGL_GENFILES)/state/
ifdef VBOX_WITH_ADDITIONS
+ ifn1of ($(KBUILD_TARGET), darwin os2)
+ VBOX_WITH_CROGL_ADDITIONS = 1
+ endif
+endif
+
+ifdef VBOX_WITH_CROGL_ADDITIONS
DLLS += VBoxOGLcrutil VBoxOGLerrorspu
LIBRARIES += VBoxOGLcrpacker VBoxOGLspuload VBoxOGLcrstate
endif
@@ -76,6 +82,11 @@ VBoxOGLcrutil_SOURCES = \
util/timer.c \
util/url.c \
util/warp.c \
+ util/vreg.cpp \
+ util/blitter.cpp \
+ util/compositor.cpp \
+ util/htable.cpp \
+ util/bmpscale.cpp \
util/vboxhgcm.c \
$(VBOX_PATH_CROGL_GENFILES)/debug_opcodes.c
VBoxOGLcrutil_SOURCES.win.x86 = \
@@ -83,10 +94,16 @@ VBoxOGLcrutil_SOURCES.win.x86 = \
util/util.rc
VBoxOGLcrutil_LIBS.win = \
$(PATH_SDK_$(VBOX_WINDDK)_LIB)/ddraw.lib \
- $(PATH_SDK_$(VBOX_WINDDK)_LIB)/dxguid.lib
+ $(PATH_SDK_$(VBOX_WINDDK)_LIB)/dxguid.lib \
+ $(PATH_SDK_$(VBOX_WINDDK)_LIB)/shlwapi.lib
VBoxOGLcrutil_LIBS = \
$(VBOX_LIB_IPRT_GUEST_R3_SHARED) \
$(VBOX_LIB_VBGL_R3_SHARED)
+
+# Needed by GDEbuger
+ifdef CR_NO_GL_SYSTEM_PATH
+VBoxOGLcrutil_DEFS += CR_NO_GL_SYSTEM_PATH
+endif
ifdef VBOX_WITH_CRHGSMI
VBoxOGLcrutil_DEFS.win += VBOX_WITH_CRHGSMI
VBoxOGLcrutil_LIBS.win += $(VBOX_PATH_ADDITIONS_LIB)/VBoxCrHgsmi$(VBOX_SUFF_LIB)
@@ -104,7 +121,7 @@ VBoxOGLcrutil_CLEAN = \
VBoxOGLcrutil_pixel.c_CFLAGS.win.x86 += -Od
VBoxOGLhostcrutil_pixel.c_CFLAGS.win.x86 += -Od
-if defined(VBOX_WITH_WDDM) && defined(VBOX_WITH_ADDITIONS)
+if defined(VBOX_WITH_WDDM) && defined(VBOX_WITH_CROGL_ADDITIONS)
#
# VBoxOGLcrutil-x86 - x86 VBoxOGLcrutil version built for amd64 build
#
@@ -161,6 +178,12 @@ $(VBOX_PATH_CROGL_GENFILES)/debug_opcodes.c: $(PATH_SUB_CURRENT)/util/debug_opco
$(call MSG_GENERATE,python,$@,$<)
$(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI)
+ifdef VBOX_WITH_CRDUMPER
+$(VBOX_PATH_CROGL_GENFILES)/dump_gen.cpp: $(PATH_SUB_CURRENT)/state_tracker/dump_gen.py $(PATH_ROOT)/src/VBox/HostServices/SharedOpenGL/crserverlib/get_sizes.py $(addprefix $(PATH_SUB_CURRENT)/state_tracker/, state_isenabled.txt state_extensions_isenabled.txt) $(VBOX_CROGL_API_FILES) | $$(dir $$@)
+ $(call MSG_GENERATE,python,$@,$<)
+ $(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI) $(<D)
+endif
+
#
# VBoxOGLcrpacker
#
@@ -259,7 +282,7 @@ ifdef VBOX_WITH_WDDM
VBoxOGLcrpacker_DEFS.win += VBOX_WITH_WDDM
endif
-if defined(VBOX_WITH_WDDM) && defined(VBOX_WITH_ADDITIONS)
+if defined(VBOX_WITH_WDDM) && defined(VBOX_WITH_CROGL_ADDITIONS)
#
# VBoxOGLcrpacker-x86 - x86 VBoxOGLcrpacker version built for amd64 build
#
@@ -343,7 +366,7 @@ ifdef VBOX_WITH_WDDM
VBoxOGLspuload_DEFS.win += VBOX_WITH_WDDM
endif
-if defined(VBOX_WITH_WDDM) && defined(VBOX_WITH_ADDITIONS)
+if defined(VBOX_WITH_WDDM) && defined(VBOX_WITH_CROGL_ADDITIONS)
#
# VBoxOGLspuload-x86 - x86 VBoxOGLspuload version built for amd64 build
#
@@ -443,13 +466,16 @@ VBoxOGLcrstate_SOURCES = \
$(VBOX_PATH_CROGL_GENFILES)/state_lighting_gen.c \
$(VBOX_PATH_CROGL_GENFILES)/state_line_gen.c \
$(VBOX_PATH_CROGL_GENFILES)/state_multisample_gen.c \
- $(VBOX_PATH_CROGL_GENFILES)/state_point_gen.c \
$(VBOX_PATH_CROGL_GENFILES)/state_polygon_gen.c \
$(VBOX_PATH_CROGL_GENFILES)/state_regcombiner_gen.c \
- $(VBOX_PATH_CROGL_GENFILES)/state_stencil_gen.c \
$(VBOX_PATH_CROGL_GENFILES)/state_viewport_gen.c \
$(VBOX_PATH_CROGL_GENFILES)/state_get.c \
$(VBOX_PATH_CROGL_GENFILES)/state_isenabled.c
+ifdef VBOX_WITH_CRDUMPER
+VBoxOGLcrstate_SOURCES += state_tracker/dump.cpp \
+ $(VBOX_PATH_CROGL_GENFILES)/dump_gen.cpp
+endif
+
VBoxOGLcrstate_CLEAN = \
$(VBOX_PATH_CROGL_GENFILES)/state_buffer_gen.c \
$(VBOX_PATH_CROGL_GENFILES)/state_current_gen.c \
@@ -458,17 +484,21 @@ VBoxOGLcrstate_CLEAN = \
$(VBOX_PATH_CROGL_GENFILES)/state_lighting_gen.c \
$(VBOX_PATH_CROGL_GENFILES)/state_line_gen.c \
$(VBOX_PATH_CROGL_GENFILES)/state_multisample_gen.c \
- $(VBOX_PATH_CROGL_GENFILES)/state_point_gen.c \
$(VBOX_PATH_CROGL_GENFILES)/state_polygon_gen.c \
$(VBOX_PATH_CROGL_GENFILES)/state_regcombiner_gen.c \
- $(VBOX_PATH_CROGL_GENFILES)/state_stencil_gen.c \
$(VBOX_PATH_CROGL_GENFILES)/state_viewport_gen.c \
$(VBOX_PATH_CROGL_GENFILES)/state_get.c \
$(VBOX_PATH_CROGL_GENFILES)/state_isenabled.c \
$(VBOX_PATH_CROGL_GENFILES)/state/cr_statefuncs.h
+ifdef VBOX_WITH_CRDUMPER
+VBoxOGLcrstate_CLEAN += $(VBOX_PATH_CROGL_GENFILES)/dump_gen.cpp
+endif
+
ifneq ($(KBUILD_TARGET),win)
+ ifeq ($(VBOX_WITH_COMPATIBLE_LINUX_GUEST_PACKAGE),)
state_tracker/state_lists.c_CFLAGS += $(VBOX_GCC_Wno-pointer-sign)
VBoxOGLcrstate_CFLAGS +=
+ endif
endif
ifdef VBOX_WITH_CRHGSMI
VBoxOGLcrstate_DEFS.win += VBOX_WITH_CRHGSMI
@@ -476,8 +506,14 @@ endif
ifdef VBOX_WITH_WDDM
VBoxOGLcrstate_DEFS.win += VBOX_WITH_WDDM
endif
+ifdef VBOX_WITH_CRDUMPER
+VBoxOGLcrstate_DEFS += VBOX_WITH_CRDUMPER
+#VBoxOGLcrutil_LIBS += \
+ $(PATH_STAGE_LIB)/additions/VBoxOGLcrstate$(VBOX_SUFF_LIB) \
+ $(PATH_STAGE_LIB)/additions/VBoxOGLspuload$(VBOX_SUFF_LIB)
+endif
-if defined(VBOX_WITH_WDDM) && defined(VBOX_WITH_ADDITIONS)
+if defined(VBOX_WITH_WDDM) && defined(VBOX_WITH_CROGL_ADDITIONS)
#
# VBoxOGLcrstate-x86 - x86 VBoxOGLcrstate version built for amd64 build
#
@@ -535,10 +571,6 @@ $(VBOX_PATH_CROGL_GENFILES)/state_multisample_gen.c: $(addprefix $(PATH_SUB_CURR
$(call MSG_GENERATE,python,$@,$<)
$(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $(<D)/gendiffcode.py multisample Multisample $(<D)
-$(VBOX_PATH_CROGL_GENFILES)/state_point_gen.c: $(addprefix $(PATH_SUB_CURRENT)/state_tracker/, state_point.txt gendiffcode.py) | $$(dir $$@)
- $(call MSG_GENERATE,python,$@,$<)
- $(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $(<D)/gendiffcode.py point Point $(<D)
-
$(VBOX_PATH_CROGL_GENFILES)/state_polygon_gen.c: $(addprefix $(PATH_SUB_CURRENT)/state_tracker/, state_polygon.txt gendiffcode.py) | $$(dir $$@)
$(call MSG_GENERATE,python,$@,$<)
$(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $(<D)/gendiffcode.py polygon Polygon $(<D)
@@ -547,15 +579,11 @@ $(VBOX_PATH_CROGL_GENFILES)/state_regcombiner_gen.c: $(addprefix $(PATH_SUB_CURR
$(call MSG_GENERATE,python,$@,$<)
$(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $(<D)/gendiffcode.py regcombiner RegCombiner $(<D)
-$(VBOX_PATH_CROGL_GENFILES)/state_stencil_gen.c: $(addprefix $(PATH_SUB_CURRENT)/state_tracker/, state_stencil.txt gendiffcode.py) | $$(dir $$@)
- $(call MSG_GENERATE,python,$@,$<)
- $(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $(<D)/gendiffcode.py stencil Stencil $(<D)
-
$(VBOX_PATH_CROGL_GENFILES)/state_viewport_gen.c: $(addprefix $(PATH_SUB_CURRENT)/state_tracker/, state_viewport.txt gendiffcode.py) | $$(dir $$@)
$(call MSG_GENERATE,python,$@,$<)
$(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $(<D)/gendiffcode.py viewport Viewport $(<D)
-$(VBOX_PATH_CROGL_GENFILES)/state_get.c: $(addprefix $(PATH_SUB_CURRENT)/state_tracker/, state_get.py state_get.txt state_extensions_get.txt) $(VBOX_CROGL_API_FILES) | $$(dir $$@)
+$(VBOX_PATH_CROGL_GENFILES)/state_get.c: $(addprefix $(PATH_SUB_CURRENT)/state_tracker/, state_get.py state_get.txt state_extensions_get.txt get_components.py) $(VBOX_CROGL_API_FILES) | $$(dir $$@)
$(call MSG_GENERATE,python,$@,$<)
$(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $(<D)/state_get.py $(VBOX_PATH_CROGL_GLAPI) $(<D)
@@ -606,7 +634,7 @@ VBoxOGLerrorspu_DEFS.win += VBOX_WITH_WDDM
endif
-if defined(VBOX_WITH_WDDM) && defined(VBOX_WITH_ADDITIONS)
+if defined(VBOX_WITH_WDDM) && defined(VBOX_WITH_CROGL_ADDITIONS)
#
# VBoxOGLerrorspu-x86 - x86 VBoxOGLerrorspu version built for amd64 build
#
diff --git a/src/VBox/GuestHost/OpenGL/glapi_parser/APIspec.txt b/src/VBox/GuestHost/OpenGL/glapi_parser/APIspec.txt
index 560b2fed..3df1d92e 100644
--- a/src/VBox/GuestHost/OpenGL/glapi_parser/APIspec.txt
+++ b/src/VBox/GuestHost/OpenGL/glapi_parser/APIspec.txt
@@ -2579,7 +2579,7 @@ chromium pack
name GetBooleanv
return void
param pname GLenum
-paramprop pname GL_ACCUM_ALPHA_BITS GL_ACCUM_BLUE_BITS GL_ACCUM_CLEAR_VALUE GL_ACCUM_GREEN_BITS GL_ACCUM_RED_BITS GL_ACTIVE_TEXTURE_ARB GL_ALIASED_LINE_WIDTH_RANGE GL_ALIASED_POINT_SIZE_RANGE GL_ALPHA_BIAS GL_ALPHA_BITS GL_ALPHA_SCALE GL_ALPHA_TEST GL_ALPHA_TEST_FUNC GL_ALPHA_TEST_REF GL_ATTRIB_STACK_DEPTH GL_AUTO_NORMAL GL_AUX_BUFFERS GL_BLEND GL_BLEND_COLOR GL_BLEND_DST GL_BLEND_EQUATION GL_BLEND_SRC GL_BLUE_BIAS GL_BLUE_BITS GL_BLUE_SCALE GL_CLIENT_ACTIVE_TEXTURE_ARB GL_CLIENT_ATTRIB_STACK_DEPTH GL_COLOR_ARRAY GL_COLOR_ARRAY_SIZE GL_COLOR_ARRAY_STRIDE GL_COLOR_ARRAY_TYPE GL_COLOR_CLEAR_VALUE GL_COLOR_LOGIC_OP GL_COLOR_MATERIAL GL_COLOR_MATERIAL_FACE GL_COLOR_MATERIAL_PARAMETER GL_COLOR_MATRIX_STACK_DEPTH GL_COLOR_WRITEMASK GL_CULL_FACE GL_CULL_FACE_MODE GL_CURRENT_COLOR GL_CURRENT_INDEX GL_CURRENT_NORMAL GL_CURRENT_RASTER_COLOR GL_CURRENT_RASTER_DISTANCE GL_CURRENT_RASTER_INDEX GL_CURRENT_RASTER_POSITION GL_CURRENT_RASTER_POSITION_VALID GL_CURRENT_RASTER_TEXTURE_COORDS GL_CURRENT_TEXTURE_COORDS GL_DEPTH_BIAS GL_DEPTH_BITS GL_DEPTH_CLEAR_VALUE GL_DEPTH_FUNC GL_DEPTH_RANGE GL_DEPTH_SCALE GL_DEPTH_TEST GL_DEPTH_WRITEMASK GL_DITHER GL_DOUBLEBUFFER GL_DRAW_BUFFER GL_EDGE_FLAG GL_EDGE_FLAG_ARRAY GL_EDGE_FLAG_ARRAY_STRIDE GL_FEEDBACK_BUFFER_SIZE GL_FEEDBACK_BUFFER_TYPE GL_FOG GL_FOG_COLOR GL_FOG_DENSITY GL_FOG_END GL_FOG_HINT GL_FOG_INDEX GL_FOG_MODE GL_FOG_START GL_FRONT_FACE GL_GREEN_BIAS GL_GREEN_BITS GL_GREEN_SCALE GL_INDEX_ARRAY GL_INDEX_ARRAY_STRIDE GL_INDEX_ARRAY_TYPE GL_INDEX_BITS GL_INDEX_CLEAR_VALUE GL_INDEX_LOGIC_OP GL_INDEX_MODE GL_INDEX_OFFSET GL_INDEX_SHIFT GL_INDEX_WRITEMASK GL_LIGHTING GL_LIGHT_MODEL_AMBIENT GL_LIGHT_MODEL_COLOR_CONTROL GL_LIGHT_MODEL_LOCAL_VIEWER GL_LIGHT_MODEL_TWO_SIDE GL_LINE_SMOOTH GL_LINE_SMOOTH_HINT GL_LINE_STIPPLE GL_LINE_STIPPLE_PATTERN GL_LINE_STIPPLE_REPEAT GL_LINE_WIDTH GL_LINE_WIDTH_GRANULARITY GL_LINE_WIDTH_RANGE GL_LIST_BASE GL_LIST_INDEX GL_LIST_MODE GL_LOGIC_OP_MODE GL_MAP1_COLOR_4 GL_MAP1_GRID_DOMAIN GL_MAP1_GRID_SEGMENTS GL_MAP1_INDEX GL_MAP1_NORMAL GL_MAP1_TEXTURE_COORD_1 GL_MAP1_TEXTURE_COORD_2 GL_MAP1_TEXTURE_COORD_3 GL_MAP1_TEXTURE_COORD_4 GL_MAP1_VERTEX_3 GL_MAP1_VERTEX_4 GL_MAP2_COLOR_4 GL_MAP2_GRID_DOMAIN GL_MAP2_GRID_SEGMENTS GL_MAP2_INDEX GL_MAP2_NORMAL GL_MAP2_TEXTURE_COORD_1 GL_MAP2_TEXTURE_COORD_2 GL_MAP2_TEXTURE_COORD_3 GL_MAP2_TEXTURE_COORD_4 GL_MAP2_VERTEX_3 GL_MAP2_VERTEX_4 GL_MAP_COLOR GL_MAP_STENCIL GL_MATRIX_MODE GL_MAX_3D_TEXTURE_SIZE GL_MAX_ATTRIB_STACK_DEPTH GL_MAX_CLIENT_ATTRIB_STACK_DEPTH GL_MAX_CLIP_PLANES GL_MAX_COLOR_MATRIX_STACK_DEPTH GL_MAX_ELEMENTS_INDICES GL_MAX_ELEMENTS_VERTICES GL_MAX_EVAL_ORDER GL_MAX_LIGHTS GL_MAX_LIST_NESTING GL_MAX_MODELVIEW_STACK_DEPTH GL_MAX_NAME_STACK_DEPTH GL_MAX_PIXEL_MAP_TABLE GL_MAX_PROJECTION_STACK_DEPTH GL_MAX_TEXTURE_SIZE GL_MAX_TEXTURE_STACK_DEPTH GL_MAX_TEXTURE_UNITS_ARB GL_MAX_VIEWPORT_DIMS GL_MODELVIEW_MATRIX GL_MODELVIEW_STACK_DEPTH GL_NAME_STACK_DEPTH GL_NORMAL_ARRAY GL_NORMAL_ARRAY_STRIDE GL_NORMAL_ARRAY_TYPE GL_NORMALIZE GL_PACK_ALIGNMENT GL_PACK_IMAGE_HEIGHT GL_PACK_LSB_FIRST GL_PACK_ROW_LENGTH GL_PACK_SKIP_IMAGES GL_PACK_SKIP_PIXELS GL_PACK_SKIP_ROWS GL_PACK_SWAP_BYTES GL_PERSPECTIVE_CORRECTION_HINT GL_PIXEL_MAP_A_TO_A_SIZE GL_PIXEL_MAP_B_TO_B_SIZE GL_PIXEL_MAP_G_TO_G_SIZE GL_PIXEL_MAP_I_TO_A_SIZE GL_PIXEL_MAP_I_TO_B_SIZE GL_PIXEL_MAP_I_TO_G_SIZE GL_PIXEL_MAP_I_TO_I_SIZE GL_PIXEL_MAP_I_TO_R_SIZE GL_PIXEL_MAP_R_TO_R_SIZE GL_PIXEL_MAP_S_TO_S_SIZE GL_POINT_SIZE GL_POINT_SIZE_GRANULARITY GL_POINT_SIZE_RANGE GL_POINT_SMOOTH GL_POINT_SMOOTH_HINT GL_POLYGON_MODE GL_POLYGON_OFFSET_FACTOR GL_POLYGON_OFFSET_FILL GL_POLYGON_OFFSET_LINE GL_POLYGON_OFFSET_POINT GL_POLYGON_OFFSET_UNITS GL_POLYGON_SMOOTH GL_POLYGON_SMOOTH_HINT GL_POLYGON_STIPPLE GL_PROJECTION_MATRIX GL_PROJECTION_STACK_DEPTH GL_READ_BUFFER GL_RED_BIAS GL_RED_BITS GL_RED_SCALE GL_RENDER_MODE GL_RESCALE_NORMAL GL_RGBA_MODE GL_SCISSOR_BOX GL_SCISSOR_TEST GL_SELECTION_BUFFER_SIZE GL_SHADE_MODEL GL_SMOOTH_LINE_WIDTH_GRANULARITY GL_SMOOTH_LINE_WIDTH_RANGE GL_SMOOTH_POINT_SIZE_GRANULARITY GL_SMOOTH_POINT_SIZE_RANGE GL_STENCIL_BITS GL_STENCIL_CLEAR_VALUE GL_STENCIL_FAIL GL_STENCIL_FUNC GL_STENCIL_PASS_DEPTH_FAIL GL_STENCIL_PASS_DEPTH_PASS GL_STENCIL_REF GL_STENCIL_TEST GL_STENCIL_VALUE_MASK GL_STENCIL_WRITEMASK GL_STEREO GL_SUBPIXEL_BITS GL_TEXTURE_1D GL_TEXTURE_2D GL_TEXTURE_3D GL_TEXTURE_BINDING_1D GL_TEXTURE_BINDING_2D GL_TEXTURE_BINDING_3D GL_TEXTURE_COORD_ARRAY GL_TEXTURE_COORD_ARRAY_SIZE GL_TEXTURE_COORD_ARRAY_STRIDE GL_TEXTURE_COORD_ARRAY_TYPE GL_TEXTURE_GEN_Q GL_TEXTURE_GEN_R GL_TEXTURE_GEN_S GL_TEXTURE_GEN_T GL_TEXTURE_MATRIX GL_TEXTURE_STACK_DEPTH GL_UNPACK_ALIGNMENT GL_UNPACK_IMAGE_HEIGHT GL_UNPACK_LSB_FIRST GL_UNPACK_ROW_LENGTH GL_UNPACK_SKIP_IMAGES GL_UNPACK_SKIP_PIXELS GL_UNPACK_SKIP_ROWS GL_UNPACK_SWAP_BYTES GL_VERTEX_ARRAY GL_VERTEX_ARRAY_SIZE GL_VERTEX_ARRAY_STRIDE GL_VERTEX_ARRAY_TYPE GL_VIEWPORT GL_ZOOM_X GL_ZOOM_Y GL_CLIP_PLANE0 GL_CLIP_PLANE1 GL_CLIP_PLANE2 GL_CLIP_PLANE3 GL_CLIP_PLANE4 GL_CLIP_PLANE5 GL_LIGHT0 GL_LIGHT1 GL_LIGHT2 GL_LIGHT3 GL_LIGHT4 GL_LIGHT5 GL_LIGHT6 GL_LIGHT7 GL_MULTISAMPLE_ARB GL_SAMPLE_ALPHA_TO_COVERAGE_ARB GL_SAMPLE_ALPHA_TO_ONE_ARB GL_SAMPLE_COVERAGE_ARB GL_SAMPLE_BUFFERS_ARB GL_SAMPLES_ARB GL_SAMPLE_COVERAGE_VALUE_ARB GL_SAMPLE_COVERAGE_INVERT_ARB GL_POINT_SPRITE_ARB GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB GL_CLIP_VOLUME_CLIPPING_HINT_EXT GL_RASTER_POSITION_UNCLIPPED_IBM GL_GENERATE_MIPMAP_HINT_SGIS GL_FOG_DISTANCE_MODE_NV GL_TRANSPOSE_MODELVIEW_MATRIX_ARB GL_TRANSPOSE_PROJECTION_MATRIX_ARB GL_TRANSPOSE_TEXTURE_MATRIX_ARB GL_TRANSPOSE_COLOR_MATRIX_ARB GL_MAX_TEXTURE_LOD_BIAS_EXT GL_PER_STAGE_CONSTANTS_NV GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT GL_CURRENT_FOG_COORDINATE_EXT GL_FOG_COORDINATE_ARRAY_TYPE_EXT GL_FOG_COORDINATE_ARRAY_STRIDE_EXT GL_COLOR_SUM_EXT GL_CURRENT_SECONDARY_COLOR_EXT GL_SECONDARY_COLOR_ARRAY_SIZE_EXT GL_SECONDARY_COLOR_ARRAY_TYPE_EXT GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT GL_ARRAY_BUFFER_BINDING_ARB GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB GL_VERTEX_ARRAY_BUFFER_BINDING_ARB GL_NORMAL_ARRAY_BUFFER_BINDING_ARB GL_COLOR_ARRAY_BUFFER_BINDING_ARB GL_INDEX_ARRAY_BUFFER_BINDING_ARB GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB GL_TEXTURE_RECTANGLE_NV GL_TEXTURE_BINDING_RECTANGLE_NV GL_MAX_RECTANGLE_TEXTURE_SIZE_NV
+paramprop pname GL_ACCUM_ALPHA_BITS GL_ACCUM_BLUE_BITS GL_ACCUM_CLEAR_VALUE GL_ACCUM_GREEN_BITS GL_ACCUM_RED_BITS GL_ACTIVE_TEXTURE_ARB GL_ALIASED_LINE_WIDTH_RANGE GL_ALIASED_POINT_SIZE_RANGE GL_ALPHA_BIAS GL_ALPHA_BITS GL_ALPHA_SCALE GL_ALPHA_TEST GL_ALPHA_TEST_FUNC GL_ALPHA_TEST_REF GL_ATTRIB_STACK_DEPTH GL_AUTO_NORMAL GL_AUX_BUFFERS GL_BLEND GL_BLEND_COLOR GL_BLEND_DST GL_BLEND_EQUATION GL_BLEND_SRC GL_BLUE_BIAS GL_BLUE_BITS GL_BLUE_SCALE GL_CLIENT_ACTIVE_TEXTURE_ARB GL_CLIENT_ATTRIB_STACK_DEPTH GL_COLOR_ARRAY GL_COLOR_ARRAY_SIZE GL_COLOR_ARRAY_STRIDE GL_COLOR_ARRAY_TYPE GL_COLOR_CLEAR_VALUE GL_COLOR_LOGIC_OP GL_COLOR_MATERIAL GL_COLOR_MATERIAL_FACE GL_COLOR_MATERIAL_PARAMETER GL_COLOR_MATRIX_STACK_DEPTH GL_COLOR_WRITEMASK GL_CULL_FACE GL_CULL_FACE_MODE GL_CURRENT_COLOR GL_CURRENT_INDEX GL_CURRENT_NORMAL GL_CURRENT_RASTER_COLOR GL_CURRENT_RASTER_DISTANCE GL_CURRENT_RASTER_INDEX GL_CURRENT_RASTER_POSITION GL_CURRENT_RASTER_POSITION_VALID GL_CURRENT_RASTER_TEXTURE_COORDS GL_CURRENT_TEXTURE_COORDS GL_DEPTH_BIAS GL_DEPTH_BITS GL_DEPTH_CLEAR_VALUE GL_DEPTH_FUNC GL_DEPTH_RANGE GL_DEPTH_SCALE GL_DEPTH_TEST GL_DEPTH_WRITEMASK GL_DITHER GL_DOUBLEBUFFER GL_DRAW_BUFFER GL_EDGE_FLAG GL_EDGE_FLAG_ARRAY GL_EDGE_FLAG_ARRAY_STRIDE GL_FEEDBACK_BUFFER_SIZE GL_FEEDBACK_BUFFER_TYPE GL_FOG GL_FOG_COLOR GL_FOG_DENSITY GL_FOG_END GL_FOG_HINT GL_FOG_INDEX GL_FOG_MODE GL_FOG_START GL_FRONT_FACE GL_GREEN_BIAS GL_GREEN_BITS GL_GREEN_SCALE GL_INDEX_ARRAY GL_INDEX_ARRAY_STRIDE GL_INDEX_ARRAY_TYPE GL_INDEX_BITS GL_INDEX_CLEAR_VALUE GL_INDEX_LOGIC_OP GL_INDEX_MODE GL_INDEX_OFFSET GL_INDEX_SHIFT GL_INDEX_WRITEMASK GL_LIGHTING GL_LIGHT_MODEL_AMBIENT GL_LIGHT_MODEL_COLOR_CONTROL GL_LIGHT_MODEL_LOCAL_VIEWER GL_LIGHT_MODEL_TWO_SIDE GL_LINE_SMOOTH GL_LINE_SMOOTH_HINT GL_LINE_STIPPLE GL_LINE_STIPPLE_PATTERN GL_LINE_STIPPLE_REPEAT GL_LINE_WIDTH GL_LINE_WIDTH_GRANULARITY GL_LINE_WIDTH_RANGE GL_LIST_BASE GL_LIST_INDEX GL_LIST_MODE GL_LOGIC_OP_MODE GL_MAP1_COLOR_4 GL_MAP1_GRID_DOMAIN GL_MAP1_GRID_SEGMENTS GL_MAP1_INDEX GL_MAP1_NORMAL GL_MAP1_TEXTURE_COORD_1 GL_MAP1_TEXTURE_COORD_2 GL_MAP1_TEXTURE_COORD_3 GL_MAP1_TEXTURE_COORD_4 GL_MAP1_VERTEX_3 GL_MAP1_VERTEX_4 GL_MAP2_COLOR_4 GL_MAP2_GRID_DOMAIN GL_MAP2_GRID_SEGMENTS GL_MAP2_INDEX GL_MAP2_NORMAL GL_MAP2_TEXTURE_COORD_1 GL_MAP2_TEXTURE_COORD_2 GL_MAP2_TEXTURE_COORD_3 GL_MAP2_TEXTURE_COORD_4 GL_MAP2_VERTEX_3 GL_MAP2_VERTEX_4 GL_MAP_COLOR GL_MAP_STENCIL GL_MATRIX_MODE GL_MAX_3D_TEXTURE_SIZE GL_MAX_ATTRIB_STACK_DEPTH GL_MAX_CLIENT_ATTRIB_STACK_DEPTH GL_MAX_CLIP_PLANES GL_MAX_COLOR_MATRIX_STACK_DEPTH GL_MAX_ELEMENTS_INDICES GL_MAX_ELEMENTS_VERTICES GL_MAX_EVAL_ORDER GL_MAX_LIGHTS GL_MAX_LIST_NESTING GL_MAX_MODELVIEW_STACK_DEPTH GL_MAX_NAME_STACK_DEPTH GL_MAX_PIXEL_MAP_TABLE GL_MAX_PROJECTION_STACK_DEPTH GL_MAX_TEXTURE_SIZE GL_MAX_TEXTURE_STACK_DEPTH GL_MAX_TEXTURE_UNITS_ARB GL_MAX_VIEWPORT_DIMS GL_MODELVIEW_MATRIX GL_MODELVIEW_STACK_DEPTH GL_NAME_STACK_DEPTH GL_NORMAL_ARRAY GL_NORMAL_ARRAY_STRIDE GL_NORMAL_ARRAY_TYPE GL_NORMALIZE GL_PACK_ALIGNMENT GL_PACK_IMAGE_HEIGHT GL_PACK_LSB_FIRST GL_PACK_ROW_LENGTH GL_PACK_SKIP_IMAGES GL_PACK_SKIP_PIXELS GL_PACK_SKIP_ROWS GL_PACK_SWAP_BYTES GL_PERSPECTIVE_CORRECTION_HINT GL_PIXEL_MAP_A_TO_A_SIZE GL_PIXEL_MAP_B_TO_B_SIZE GL_PIXEL_MAP_G_TO_G_SIZE GL_PIXEL_MAP_I_TO_A_SIZE GL_PIXEL_MAP_I_TO_B_SIZE GL_PIXEL_MAP_I_TO_G_SIZE GL_PIXEL_MAP_I_TO_I_SIZE GL_PIXEL_MAP_I_TO_R_SIZE GL_PIXEL_MAP_R_TO_R_SIZE GL_PIXEL_MAP_S_TO_S_SIZE GL_POINT_SIZE GL_POINT_SIZE_GRANULARITY GL_POINT_SIZE_RANGE GL_POINT_SMOOTH GL_POINT_SMOOTH_HINT GL_POLYGON_MODE GL_POLYGON_OFFSET_FACTOR GL_POLYGON_OFFSET_FILL GL_POLYGON_OFFSET_LINE GL_POLYGON_OFFSET_POINT GL_POLYGON_OFFSET_UNITS GL_POLYGON_SMOOTH GL_POLYGON_SMOOTH_HINT GL_POLYGON_STIPPLE GL_PROJECTION_MATRIX GL_PROJECTION_STACK_DEPTH GL_READ_BUFFER GL_RED_BIAS GL_RED_BITS GL_RED_SCALE GL_RENDER_MODE GL_RESCALE_NORMAL GL_RGBA_MODE GL_SCISSOR_BOX GL_SCISSOR_TEST GL_SELECTION_BUFFER_SIZE GL_SHADE_MODEL GL_SMOOTH_LINE_WIDTH_GRANULARITY GL_SMOOTH_LINE_WIDTH_RANGE GL_SMOOTH_POINT_SIZE_GRANULARITY GL_SMOOTH_POINT_SIZE_RANGE GL_STENCIL_BITS GL_STENCIL_CLEAR_VALUE GL_STENCIL_FAIL GL_STENCIL_FUNC GL_STENCIL_PASS_DEPTH_FAIL GL_STENCIL_PASS_DEPTH_PASS GL_STENCIL_REF GL_STENCIL_TEST GL_STENCIL_VALUE_MASK GL_STENCIL_WRITEMASK GL_STEREO GL_SUBPIXEL_BITS GL_TEXTURE_1D GL_TEXTURE_2D GL_TEXTURE_3D GL_TEXTURE_BINDING_1D GL_TEXTURE_BINDING_2D GL_TEXTURE_BINDING_3D GL_TEXTURE_COORD_ARRAY GL_TEXTURE_COORD_ARRAY_SIZE GL_TEXTURE_COORD_ARRAY_STRIDE GL_TEXTURE_COORD_ARRAY_TYPE GL_TEXTURE_GEN_Q GL_TEXTURE_GEN_R GL_TEXTURE_GEN_S GL_TEXTURE_GEN_T GL_TEXTURE_MATRIX GL_TEXTURE_STACK_DEPTH GL_UNPACK_ALIGNMENT GL_UNPACK_IMAGE_HEIGHT GL_UNPACK_LSB_FIRST GL_UNPACK_ROW_LENGTH GL_UNPACK_SKIP_IMAGES GL_UNPACK_SKIP_PIXELS GL_UNPACK_SKIP_ROWS GL_UNPACK_SWAP_BYTES GL_VERTEX_ARRAY GL_VERTEX_ARRAY_SIZE GL_VERTEX_ARRAY_STRIDE GL_VERTEX_ARRAY_TYPE GL_VIEWPORT GL_ZOOM_X GL_ZOOM_Y GL_CLIP_PLANE0 GL_CLIP_PLANE1 GL_CLIP_PLANE2 GL_CLIP_PLANE3 GL_CLIP_PLANE4 GL_CLIP_PLANE5 GL_LIGHT0 GL_LIGHT1 GL_LIGHT2 GL_LIGHT3 GL_LIGHT4 GL_LIGHT5 GL_LIGHT6 GL_LIGHT7 GL_MULTISAMPLE_ARB GL_SAMPLE_ALPHA_TO_COVERAGE_ARB GL_SAMPLE_ALPHA_TO_ONE_ARB GL_SAMPLE_COVERAGE_ARB GL_SAMPLE_BUFFERS_ARB GL_SAMPLES_ARB GL_SAMPLE_COVERAGE_VALUE_ARB GL_SAMPLE_COVERAGE_INVERT_ARB GL_POINT_SPRITE_ARB GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB GL_CLIP_VOLUME_CLIPPING_HINT_EXT GL_RASTER_POSITION_UNCLIPPED_IBM GL_GENERATE_MIPMAP_HINT_SGIS GL_FOG_DISTANCE_MODE_NV GL_TRANSPOSE_MODELVIEW_MATRIX_ARB GL_TRANSPOSE_PROJECTION_MATRIX_ARB GL_TRANSPOSE_TEXTURE_MATRIX_ARB GL_TRANSPOSE_COLOR_MATRIX_ARB GL_MAX_TEXTURE_LOD_BIAS_EXT GL_PER_STAGE_CONSTANTS_NV GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT GL_CURRENT_FOG_COORDINATE_EXT GL_FOG_COORDINATE_ARRAY_TYPE_EXT GL_FOG_COORDINATE_ARRAY_STRIDE_EXT GL_COLOR_SUM_EXT GL_CURRENT_SECONDARY_COLOR_EXT GL_SECONDARY_COLOR_ARRAY_SIZE_EXT GL_SECONDARY_COLOR_ARRAY_TYPE_EXT GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT GL_ARRAY_BUFFER_BINDING_ARB GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB GL_VERTEX_ARRAY_BUFFER_BINDING_ARB GL_NORMAL_ARRAY_BUFFER_BINDING_ARB GL_COLOR_ARRAY_BUFFER_BINDING_ARB GL_INDEX_ARRAY_BUFFER_BINDING_ARB GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB GL_TEXTURE_RECTANGLE_NV GL_TEXTURE_BINDING_RECTANGLE_NV GL_MAX_RECTANGLE_TEXTURE_SIZE_NV GL_READ_FRAMEBUFFER_BINDING_EXT GL_DRAW_FRAMEBUFFER_BINDING_EXT GL_ACTIVE_STENCIL_FACE_EXT
param params GLboolean *
category 1.0
props get
@@ -2599,7 +2599,7 @@ chromium extpack
name GetDoublev
return void
param pname GLenum
-paramprop pname GL_ACCUM_ALPHA_BITS GL_ACCUM_BLUE_BITS GL_ACCUM_CLEAR_VALUE GL_ACCUM_GREEN_BITS GL_ACCUM_RED_BITS GL_ACTIVE_TEXTURE_ARB GL_ALIASED_LINE_WIDTH_RANGE GL_ALIASED_POINT_SIZE_RANGE GL_ALPHA_BIAS GL_ALPHA_BITS GL_ALPHA_SCALE GL_ALPHA_TEST GL_ALPHA_TEST_FUNC GL_ALPHA_TEST_REF GL_ATTRIB_STACK_DEPTH GL_AUTO_NORMAL GL_AUX_BUFFERS GL_BLEND GL_BLEND_COLOR GL_BLEND_DST GL_BLEND_EQUATION GL_BLEND_SRC GL_BLUE_BIAS GL_BLUE_BITS GL_BLUE_SCALE GL_CLIENT_ACTIVE_TEXTURE_ARB GL_CLIENT_ATTRIB_STACK_DEPTH GL_COLOR_ARRAY GL_COLOR_ARRAY_SIZE GL_COLOR_ARRAY_STRIDE GL_COLOR_ARRAY_TYPE GL_COLOR_CLEAR_VALUE GL_COLOR_LOGIC_OP GL_COLOR_MATERIAL GL_COLOR_MATERIAL_FACE GL_COLOR_MATERIAL_PARAMETER GL_COLOR_MATRIX_STACK_DEPTH GL_COLOR_WRITEMASK GL_CULL_FACE GL_CULL_FACE_MODE GL_CURRENT_COLOR GL_CURRENT_INDEX GL_CURRENT_NORMAL GL_CURRENT_RASTER_COLOR GL_CURRENT_RASTER_DISTANCE GL_CURRENT_RASTER_INDEX GL_CURRENT_RASTER_POSITION GL_CURRENT_RASTER_POSITION_VALID GL_CURRENT_RASTER_TEXTURE_COORDS GL_CURRENT_TEXTURE_COORDS GL_DEPTH_BIAS GL_DEPTH_BITS GL_DEPTH_CLEAR_VALUE GL_DEPTH_FUNC GL_DEPTH_RANGE GL_DEPTH_SCALE GL_DEPTH_TEST GL_DEPTH_WRITEMASK GL_DITHER GL_DOUBLEBUFFER GL_DRAW_BUFFER GL_EDGE_FLAG GL_EDGE_FLAG_ARRAY GL_EDGE_FLAG_ARRAY_STRIDE GL_FEEDBACK_BUFFER_SIZE GL_FEEDBACK_BUFFER_TYPE GL_FOG GL_FOG_COLOR GL_FOG_DENSITY GL_FOG_END GL_FOG_HINT GL_FOG_INDEX GL_FOG_MODE GL_FOG_START GL_FRONT_FACE GL_GREEN_BIAS GL_GREEN_BITS GL_GREEN_SCALE GL_INDEX_ARRAY GL_INDEX_ARRAY_STRIDE GL_INDEX_ARRAY_TYPE GL_INDEX_BITS GL_INDEX_CLEAR_VALUE GL_INDEX_LOGIC_OP GL_INDEX_MODE GL_INDEX_OFFSET GL_INDEX_SHIFT GL_INDEX_WRITEMASK GL_LIGHTING GL_LIGHT_MODEL_AMBIENT GL_LIGHT_MODEL_COLOR_CONTROL GL_LIGHT_MODEL_LOCAL_VIEWER GL_LIGHT_MODEL_TWO_SIDE GL_LINE_SMOOTH GL_LINE_SMOOTH_HINT GL_LINE_STIPPLE GL_LINE_STIPPLE_PATTERN GL_LINE_STIPPLE_REPEAT GL_LINE_WIDTH GL_LINE_WIDTH_GRANULARITY GL_LINE_WIDTH_RANGE GL_LIST_BASE GL_LIST_INDEX GL_LIST_MODE GL_LOGIC_OP_MODE GL_MAP1_COLOR_4 GL_MAP1_GRID_DOMAIN GL_MAP1_GRID_SEGMENTS GL_MAP1_INDEX GL_MAP1_NORMAL GL_MAP1_TEXTURE_COORD_1 GL_MAP1_TEXTURE_COORD_2 GL_MAP1_TEXTURE_COORD_3 GL_MAP1_TEXTURE_COORD_4 GL_MAP1_VERTEX_3 GL_MAP1_VERTEX_4 GL_MAP2_COLOR_4 GL_MAP2_GRID_DOMAIN GL_MAP2_GRID_SEGMENTS GL_MAP2_INDEX GL_MAP2_NORMAL GL_MAP2_TEXTURE_COORD_1 GL_MAP2_TEXTURE_COORD_2 GL_MAP2_TEXTURE_COORD_3 GL_MAP2_TEXTURE_COORD_4 GL_MAP2_VERTEX_3 GL_MAP2_VERTEX_4 GL_MAP_COLOR GL_MAP_STENCIL GL_MATRIX_MODE GL_MAX_3D_TEXTURE_SIZE GL_MAX_ATTRIB_STACK_DEPTH GL_MAX_CLIENT_ATTRIB_STACK_DEPTH GL_MAX_CLIP_PLANES GL_MAX_COLOR_MATRIX_STACK_DEPTH GL_MAX_ELEMENTS_INDICES GL_MAX_ELEMENTS_VERTICES GL_MAX_EVAL_ORDER GL_MAX_LIGHTS GL_MAX_LIST_NESTING GL_MAX_MODELVIEW_STACK_DEPTH GL_MAX_NAME_STACK_DEPTH GL_MAX_PIXEL_MAP_TABLE GL_MAX_PROJECTION_STACK_DEPTH GL_MAX_TEXTURE_SIZE GL_MAX_TEXTURE_STACK_DEPTH GL_MAX_TEXTURE_UNITS_ARB GL_MAX_VIEWPORT_DIMS GL_MODELVIEW_MATRIX GL_MODELVIEW_STACK_DEPTH GL_NAME_STACK_DEPTH GL_NORMAL_ARRAY GL_NORMAL_ARRAY_STRIDE GL_NORMAL_ARRAY_TYPE GL_NORMALIZE GL_PACK_ALIGNMENT GL_PACK_IMAGE_HEIGHT GL_PACK_LSB_FIRST GL_PACK_ROW_LENGTH GL_PACK_SKIP_IMAGES GL_PACK_SKIP_PIXELS GL_PACK_SKIP_ROWS GL_PACK_SWAP_BYTES GL_PERSPECTIVE_CORRECTION_HINT GL_PIXEL_MAP_A_TO_A_SIZE GL_PIXEL_MAP_B_TO_B_SIZE GL_PIXEL_MAP_G_TO_G_SIZE GL_PIXEL_MAP_I_TO_A_SIZE GL_PIXEL_MAP_I_TO_B_SIZE GL_PIXEL_MAP_I_TO_G_SIZE GL_PIXEL_MAP_I_TO_I_SIZE GL_PIXEL_MAP_I_TO_R_SIZE GL_PIXEL_MAP_R_TO_R_SIZE GL_PIXEL_MAP_S_TO_S_SIZE GL_POINT_SIZE GL_POINT_SIZE_GRANULARITY GL_POINT_SIZE_RANGE GL_POINT_SMOOTH GL_POINT_SMOOTH_HINT GL_POLYGON_MODE GL_POLYGON_OFFSET_FACTOR GL_POLYGON_OFFSET_FILL GL_POLYGON_OFFSET_LINE GL_POLYGON_OFFSET_POINT GL_POLYGON_OFFSET_UNITS GL_POLYGON_SMOOTH GL_POLYGON_SMOOTH_HINT GL_POLYGON_STIPPLE GL_PROJECTION_MATRIX GL_PROJECTION_STACK_DEPTH GL_READ_BUFFER GL_RED_BIAS GL_RED_BITS GL_RED_SCALE GL_RENDER_MODE GL_RESCALE_NORMAL GL_RGBA_MODE GL_SCISSOR_BOX GL_SCISSOR_TEST GL_SELECTION_BUFFER_SIZE GL_SHADE_MODEL GL_SMOOTH_LINE_WIDTH_GRANULARITY GL_SMOOTH_LINE_WIDTH_RANGE GL_SMOOTH_POINT_SIZE_GRANULARITY GL_SMOOTH_POINT_SIZE_RANGE GL_STENCIL_BITS GL_STENCIL_CLEAR_VALUE GL_STENCIL_FAIL GL_STENCIL_FUNC GL_STENCIL_PASS_DEPTH_FAIL GL_STENCIL_PASS_DEPTH_PASS GL_STENCIL_REF GL_STENCIL_TEST GL_STENCIL_VALUE_MASK GL_STENCIL_WRITEMASK GL_STEREO GL_SUBPIXEL_BITS GL_TEXTURE_1D GL_TEXTURE_2D GL_TEXTURE_3D GL_TEXTURE_BINDING_1D GL_TEXTURE_BINDING_2D GL_TEXTURE_BINDING_3D GL_TEXTURE_COORD_ARRAY GL_TEXTURE_COORD_ARRAY_SIZE GL_TEXTURE_COORD_ARRAY_STRIDE GL_TEXTURE_COORD_ARRAY_TYPE GL_TEXTURE_GEN_Q GL_TEXTURE_GEN_R GL_TEXTURE_GEN_S GL_TEXTURE_GEN_T GL_TEXTURE_MATRIX GL_TEXTURE_STACK_DEPTH GL_UNPACK_ALIGNMENT GL_UNPACK_IMAGE_HEIGHT GL_UNPACK_LSB_FIRST GL_UNPACK_ROW_LENGTH GL_UNPACK_SKIP_IMAGES GL_UNPACK_SKIP_PIXELS GL_UNPACK_SKIP_ROWS GL_UNPACK_SWAP_BYTES GL_VERTEX_ARRAY GL_VERTEX_ARRAY_SIZE GL_VERTEX_ARRAY_STRIDE GL_VERTEX_ARRAY_TYPE GL_VIEWPORT GL_ZOOM_X GL_ZOOM_Y GL_CLIP_PLANE0 GL_CLIP_PLANE1 GL_CLIP_PLANE2 GL_CLIP_PLANE3 GL_CLIP_PLANE4 GL_CLIP_PLANE5 GL_LIGHT0 GL_LIGHT1 GL_LIGHT2 GL_LIGHT3 GL_LIGHT4 GL_LIGHT5 GL_LIGHT6 GL_LIGHT7 GL_MULTISAMPLE_ARB GL_SAMPLE_ALPHA_TO_COVERAGE_ARB GL_SAMPLE_ALPHA_TO_ONE_ARB GL_SAMPLE_COVERAGE_ARB GL_SAMPLE_BUFFERS_ARB GL_SAMPLES_ARB GL_SAMPLE_COVERAGE_VALUE_ARB GL_SAMPLE_COVERAGE_INVERT_ARB GL_POINT_SPRITE_ARB GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB GL_CLIP_VOLUME_CLIPPING_HINT_EXT GL_RASTER_POSITION_UNCLIPPED_IBM GL_GENERATE_MIPMAP_HINT_SGIS GL_FOG_DISTANCE_MODE_NV GL_TRANSPOSE_MODELVIEW_MATRIX_ARB GL_TRANSPOSE_PROJECTION_MATRIX_ARB GL_TRANSPOSE_TEXTURE_MATRIX_ARB GL_TRANSPOSE_COLOR_MATRIX_ARB GL_TRANSPOSE_MODELVIEW_MATRIX_ARB GL_TRANSPOSE_PROJECTION_MATRIX_ARB GL_TRANSPOSE_TEXTURE_MATRIX_ARB GL_TRANSPOSE_COLOR_MATRIX_ARB GL_MAX_TEXTURE_LOD_BIAS_EXT GL_PER_STAGE_CONSTANTS_NV GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT GL_CURRENT_FOG_COORDINATE_EXT GL_FOG_COORDINATE_ARRAY_TYPE_EXT GL_FOG_COORDINATE_ARRAY_STRIDE_EXT GL_COLOR_SUM_EXT GL_CURRENT_SECONDARY_COLOR_EXT GL_SECONDARY_COLOR_ARRAY_SIZE_EXT GL_SECONDARY_COLOR_ARRAY_TYPE_EXT GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT GL_ARRAY_BUFFER_BINDING_ARB GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB GL_VERTEX_ARRAY_BUFFER_BINDING_ARB GL_NORMAL_ARRAY_BUFFER_BINDING_ARB GL_COLOR_ARRAY_BUFFER_BINDING_ARB GL_INDEX_ARRAY_BUFFER_BINDING_ARB GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB GL_TEXTURE_RECTANGLE_NV GL_TEXTURE_BINDING_RECTANGLE_NV GL_MAX_RECTANGLE_TEXTURE_SIZE_NV
+paramprop pname GL_ACCUM_ALPHA_BITS GL_ACCUM_BLUE_BITS GL_ACCUM_CLEAR_VALUE GL_ACCUM_GREEN_BITS GL_ACCUM_RED_BITS GL_ACTIVE_TEXTURE_ARB GL_ALIASED_LINE_WIDTH_RANGE GL_ALIASED_POINT_SIZE_RANGE GL_ALPHA_BIAS GL_ALPHA_BITS GL_ALPHA_SCALE GL_ALPHA_TEST GL_ALPHA_TEST_FUNC GL_ALPHA_TEST_REF GL_ATTRIB_STACK_DEPTH GL_AUTO_NORMAL GL_AUX_BUFFERS GL_BLEND GL_BLEND_COLOR GL_BLEND_DST GL_BLEND_EQUATION GL_BLEND_SRC GL_BLUE_BIAS GL_BLUE_BITS GL_BLUE_SCALE GL_CLIENT_ACTIVE_TEXTURE_ARB GL_CLIENT_ATTRIB_STACK_DEPTH GL_COLOR_ARRAY GL_COLOR_ARRAY_SIZE GL_COLOR_ARRAY_STRIDE GL_COLOR_ARRAY_TYPE GL_COLOR_CLEAR_VALUE GL_COLOR_LOGIC_OP GL_COLOR_MATERIAL GL_COLOR_MATERIAL_FACE GL_COLOR_MATERIAL_PARAMETER GL_COLOR_MATRIX_STACK_DEPTH GL_COLOR_WRITEMASK GL_CULL_FACE GL_CULL_FACE_MODE GL_CURRENT_COLOR GL_CURRENT_INDEX GL_CURRENT_NORMAL GL_CURRENT_RASTER_COLOR GL_CURRENT_RASTER_DISTANCE GL_CURRENT_RASTER_INDEX GL_CURRENT_RASTER_POSITION GL_CURRENT_RASTER_POSITION_VALID GL_CURRENT_RASTER_TEXTURE_COORDS GL_CURRENT_TEXTURE_COORDS GL_DEPTH_BIAS GL_DEPTH_BITS GL_DEPTH_CLEAR_VALUE GL_DEPTH_FUNC GL_DEPTH_RANGE GL_DEPTH_SCALE GL_DEPTH_TEST GL_DEPTH_WRITEMASK GL_DITHER GL_DOUBLEBUFFER GL_DRAW_BUFFER GL_EDGE_FLAG GL_EDGE_FLAG_ARRAY GL_EDGE_FLAG_ARRAY_STRIDE GL_FEEDBACK_BUFFER_SIZE GL_FEEDBACK_BUFFER_TYPE GL_FOG GL_FOG_COLOR GL_FOG_DENSITY GL_FOG_END GL_FOG_HINT GL_FOG_INDEX GL_FOG_MODE GL_FOG_START GL_FRONT_FACE GL_GREEN_BIAS GL_GREEN_BITS GL_GREEN_SCALE GL_INDEX_ARRAY GL_INDEX_ARRAY_STRIDE GL_INDEX_ARRAY_TYPE GL_INDEX_BITS GL_INDEX_CLEAR_VALUE GL_INDEX_LOGIC_OP GL_INDEX_MODE GL_INDEX_OFFSET GL_INDEX_SHIFT GL_INDEX_WRITEMASK GL_LIGHTING GL_LIGHT_MODEL_AMBIENT GL_LIGHT_MODEL_COLOR_CONTROL GL_LIGHT_MODEL_LOCAL_VIEWER GL_LIGHT_MODEL_TWO_SIDE GL_LINE_SMOOTH GL_LINE_SMOOTH_HINT GL_LINE_STIPPLE GL_LINE_STIPPLE_PATTERN GL_LINE_STIPPLE_REPEAT GL_LINE_WIDTH GL_LINE_WIDTH_GRANULARITY GL_LINE_WIDTH_RANGE GL_LIST_BASE GL_LIST_INDEX GL_LIST_MODE GL_LOGIC_OP_MODE GL_MAP1_COLOR_4 GL_MAP1_GRID_DOMAIN GL_MAP1_GRID_SEGMENTS GL_MAP1_INDEX GL_MAP1_NORMAL GL_MAP1_TEXTURE_COORD_1 GL_MAP1_TEXTURE_COORD_2 GL_MAP1_TEXTURE_COORD_3 GL_MAP1_TEXTURE_COORD_4 GL_MAP1_VERTEX_3 GL_MAP1_VERTEX_4 GL_MAP2_COLOR_4 GL_MAP2_GRID_DOMAIN GL_MAP2_GRID_SEGMENTS GL_MAP2_INDEX GL_MAP2_NORMAL GL_MAP2_TEXTURE_COORD_1 GL_MAP2_TEXTURE_COORD_2 GL_MAP2_TEXTURE_COORD_3 GL_MAP2_TEXTURE_COORD_4 GL_MAP2_VERTEX_3 GL_MAP2_VERTEX_4 GL_MAP_COLOR GL_MAP_STENCIL GL_MATRIX_MODE GL_MAX_3D_TEXTURE_SIZE GL_MAX_ATTRIB_STACK_DEPTH GL_MAX_CLIENT_ATTRIB_STACK_DEPTH GL_MAX_CLIP_PLANES GL_MAX_COLOR_MATRIX_STACK_DEPTH GL_MAX_ELEMENTS_INDICES GL_MAX_ELEMENTS_VERTICES GL_MAX_EVAL_ORDER GL_MAX_LIGHTS GL_MAX_LIST_NESTING GL_MAX_MODELVIEW_STACK_DEPTH GL_MAX_NAME_STACK_DEPTH GL_MAX_PIXEL_MAP_TABLE GL_MAX_PROJECTION_STACK_DEPTH GL_MAX_TEXTURE_SIZE GL_MAX_TEXTURE_STACK_DEPTH GL_MAX_TEXTURE_UNITS_ARB GL_MAX_VIEWPORT_DIMS GL_MODELVIEW_MATRIX GL_MODELVIEW_STACK_DEPTH GL_NAME_STACK_DEPTH GL_NORMAL_ARRAY GL_NORMAL_ARRAY_STRIDE GL_NORMAL_ARRAY_TYPE GL_NORMALIZE GL_PACK_ALIGNMENT GL_PACK_IMAGE_HEIGHT GL_PACK_LSB_FIRST GL_PACK_ROW_LENGTH GL_PACK_SKIP_IMAGES GL_PACK_SKIP_PIXELS GL_PACK_SKIP_ROWS GL_PACK_SWAP_BYTES GL_PERSPECTIVE_CORRECTION_HINT GL_PIXEL_MAP_A_TO_A_SIZE GL_PIXEL_MAP_B_TO_B_SIZE GL_PIXEL_MAP_G_TO_G_SIZE GL_PIXEL_MAP_I_TO_A_SIZE GL_PIXEL_MAP_I_TO_B_SIZE GL_PIXEL_MAP_I_TO_G_SIZE GL_PIXEL_MAP_I_TO_I_SIZE GL_PIXEL_MAP_I_TO_R_SIZE GL_PIXEL_MAP_R_TO_R_SIZE GL_PIXEL_MAP_S_TO_S_SIZE GL_POINT_SIZE GL_POINT_SIZE_GRANULARITY GL_POINT_SIZE_RANGE GL_POINT_SMOOTH GL_POINT_SMOOTH_HINT GL_POLYGON_MODE GL_POLYGON_OFFSET_FACTOR GL_POLYGON_OFFSET_FILL GL_POLYGON_OFFSET_LINE GL_POLYGON_OFFSET_POINT GL_POLYGON_OFFSET_UNITS GL_POLYGON_SMOOTH GL_POLYGON_SMOOTH_HINT GL_POLYGON_STIPPLE GL_PROJECTION_MATRIX GL_PROJECTION_STACK_DEPTH GL_READ_BUFFER GL_RED_BIAS GL_RED_BITS GL_RED_SCALE GL_RENDER_MODE GL_RESCALE_NORMAL GL_RGBA_MODE GL_SCISSOR_BOX GL_SCISSOR_TEST GL_SELECTION_BUFFER_SIZE GL_SHADE_MODEL GL_SMOOTH_LINE_WIDTH_GRANULARITY GL_SMOOTH_LINE_WIDTH_RANGE GL_SMOOTH_POINT_SIZE_GRANULARITY GL_SMOOTH_POINT_SIZE_RANGE GL_STENCIL_BITS GL_STENCIL_CLEAR_VALUE GL_STENCIL_FAIL GL_STENCIL_FUNC GL_STENCIL_PASS_DEPTH_FAIL GL_STENCIL_PASS_DEPTH_PASS GL_STENCIL_REF GL_STENCIL_TEST GL_STENCIL_VALUE_MASK GL_STENCIL_WRITEMASK GL_STEREO GL_SUBPIXEL_BITS GL_TEXTURE_1D GL_TEXTURE_2D GL_TEXTURE_3D GL_TEXTURE_BINDING_1D GL_TEXTURE_BINDING_2D GL_TEXTURE_BINDING_3D GL_TEXTURE_COORD_ARRAY GL_TEXTURE_COORD_ARRAY_SIZE GL_TEXTURE_COORD_ARRAY_STRIDE GL_TEXTURE_COORD_ARRAY_TYPE GL_TEXTURE_GEN_Q GL_TEXTURE_GEN_R GL_TEXTURE_GEN_S GL_TEXTURE_GEN_T GL_TEXTURE_MATRIX GL_TEXTURE_STACK_DEPTH GL_UNPACK_ALIGNMENT GL_UNPACK_IMAGE_HEIGHT GL_UNPACK_LSB_FIRST GL_UNPACK_ROW_LENGTH GL_UNPACK_SKIP_IMAGES GL_UNPACK_SKIP_PIXELS GL_UNPACK_SKIP_ROWS GL_UNPACK_SWAP_BYTES GL_VERTEX_ARRAY GL_VERTEX_ARRAY_SIZE GL_VERTEX_ARRAY_STRIDE GL_VERTEX_ARRAY_TYPE GL_VIEWPORT GL_ZOOM_X GL_ZOOM_Y GL_CLIP_PLANE0 GL_CLIP_PLANE1 GL_CLIP_PLANE2 GL_CLIP_PLANE3 GL_CLIP_PLANE4 GL_CLIP_PLANE5 GL_LIGHT0 GL_LIGHT1 GL_LIGHT2 GL_LIGHT3 GL_LIGHT4 GL_LIGHT5 GL_LIGHT6 GL_LIGHT7 GL_MULTISAMPLE_ARB GL_SAMPLE_ALPHA_TO_COVERAGE_ARB GL_SAMPLE_ALPHA_TO_ONE_ARB GL_SAMPLE_COVERAGE_ARB GL_SAMPLE_BUFFERS_ARB GL_SAMPLES_ARB GL_SAMPLE_COVERAGE_VALUE_ARB GL_SAMPLE_COVERAGE_INVERT_ARB GL_POINT_SPRITE_ARB GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB GL_CLIP_VOLUME_CLIPPING_HINT_EXT GL_RASTER_POSITION_UNCLIPPED_IBM GL_GENERATE_MIPMAP_HINT_SGIS GL_FOG_DISTANCE_MODE_NV GL_TRANSPOSE_MODELVIEW_MATRIX_ARB GL_TRANSPOSE_PROJECTION_MATRIX_ARB GL_TRANSPOSE_TEXTURE_MATRIX_ARB GL_TRANSPOSE_COLOR_MATRIX_ARB GL_TRANSPOSE_MODELVIEW_MATRIX_ARB GL_TRANSPOSE_PROJECTION_MATRIX_ARB GL_TRANSPOSE_TEXTURE_MATRIX_ARB GL_TRANSPOSE_COLOR_MATRIX_ARB GL_MAX_TEXTURE_LOD_BIAS_EXT GL_PER_STAGE_CONSTANTS_NV GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT GL_CURRENT_FOG_COORDINATE_EXT GL_FOG_COORDINATE_ARRAY_TYPE_EXT GL_FOG_COORDINATE_ARRAY_STRIDE_EXT GL_COLOR_SUM_EXT GL_CURRENT_SECONDARY_COLOR_EXT GL_SECONDARY_COLOR_ARRAY_SIZE_EXT GL_SECONDARY_COLOR_ARRAY_TYPE_EXT GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT GL_ARRAY_BUFFER_BINDING_ARB GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB GL_VERTEX_ARRAY_BUFFER_BINDING_ARB GL_NORMAL_ARRAY_BUFFER_BINDING_ARB GL_COLOR_ARRAY_BUFFER_BINDING_ARB GL_INDEX_ARRAY_BUFFER_BINDING_ARB GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB GL_TEXTURE_RECTANGLE_NV GL_TEXTURE_BINDING_RECTANGLE_NV GL_MAX_RECTANGLE_TEXTURE_SIZE_NV GL_READ_FRAMEBUFFER_BINDING_EXT GL_DRAW_FRAMEBUFFER_BINDING_EXT GL_READ_FRAMEBUFFER_BINDING_EXT GL_DRAW_FRAMEBUFFER_BINDING_EXT GL_ACTIVE_STENCIL_FACE_EXT
param params GLdouble *
category 1.0
props get
@@ -2614,7 +2614,7 @@ chromium extpack
name GetFloatv
return void
param pname GLenum
-paramprop pname GL_ACCUM_ALPHA_BITS GL_ACCUM_BLUE_BITS GL_ACCUM_CLEAR_VALUE GL_ACCUM_GREEN_BITS GL_ACCUM_RED_BITS GL_ACTIVE_TEXTURE_ARB GL_ALIASED_LINE_WIDTH_RANGE GL_ALIASED_POINT_SIZE_RANGE GL_ALPHA_BIAS GL_ALPHA_BITS GL_ALPHA_SCALE GL_ALPHA_TEST GL_ALPHA_TEST_FUNC GL_ALPHA_TEST_REF GL_ATTRIB_STACK_DEPTH GL_AUTO_NORMAL GL_AUX_BUFFERS GL_BLEND GL_BLEND_COLOR GL_BLEND_DST GL_BLEND_EQUATION GL_BLEND_SRC GL_BLUE_BIAS GL_BLUE_BITS GL_BLUE_SCALE GL_CLIENT_ACTIVE_TEXTURE_ARB GL_CLIENT_ATTRIB_STACK_DEPTH GL_COLOR_ARRAY GL_COLOR_ARRAY_SIZE GL_COLOR_ARRAY_STRIDE GL_COLOR_ARRAY_TYPE GL_COLOR_CLEAR_VALUE GL_COLOR_LOGIC_OP GL_COLOR_MATERIAL GL_COLOR_MATERIAL_FACE GL_COLOR_MATERIAL_PARAMETER GL_COLOR_MATRIX_STACK_DEPTH GL_COLOR_WRITEMASK GL_CULL_FACE GL_CULL_FACE_MODE GL_CURRENT_COLOR GL_CURRENT_INDEX GL_CURRENT_NORMAL GL_CURRENT_RASTER_COLOR GL_CURRENT_RASTER_DISTANCE GL_CURRENT_RASTER_INDEX GL_CURRENT_RASTER_POSITION GL_CURRENT_RASTER_POSITION_VALID GL_CURRENT_RASTER_TEXTURE_COORDS GL_CURRENT_TEXTURE_COORDS GL_DEPTH_BIAS GL_DEPTH_BITS GL_DEPTH_CLEAR_VALUE GL_DEPTH_FUNC GL_DEPTH_RANGE GL_DEPTH_SCALE GL_DEPTH_TEST GL_DEPTH_WRITEMASK GL_DITHER GL_DOUBLEBUFFER GL_DRAW_BUFFER GL_EDGE_FLAG GL_EDGE_FLAG_ARRAY GL_EDGE_FLAG_ARRAY_STRIDE GL_FEEDBACK_BUFFER_SIZE GL_FEEDBACK_BUFFER_TYPE GL_FOG GL_FOG_COLOR GL_FOG_DENSITY GL_FOG_END GL_FOG_HINT GL_FOG_INDEX GL_FOG_MODE GL_FOG_START GL_FRONT_FACE GL_GREEN_BIAS GL_GREEN_BITS GL_GREEN_SCALE GL_INDEX_ARRAY GL_INDEX_ARRAY_STRIDE GL_INDEX_ARRAY_TYPE GL_INDEX_BITS GL_INDEX_CLEAR_VALUE GL_INDEX_LOGIC_OP GL_INDEX_MODE GL_INDEX_OFFSET GL_INDEX_SHIFT GL_INDEX_WRITEMASK GL_LIGHTING GL_LIGHT_MODEL_AMBIENT GL_LIGHT_MODEL_COLOR_CONTROL GL_LIGHT_MODEL_LOCAL_VIEWER GL_LIGHT_MODEL_TWO_SIDE GL_LINE_SMOOTH GL_LINE_SMOOTH_HINT GL_LINE_STIPPLE GL_LINE_STIPPLE_PATTERN GL_LINE_STIPPLE_REPEAT GL_LINE_WIDTH GL_LINE_WIDTH_GRANULARITY GL_LINE_WIDTH_RANGE GL_LIST_BASE GL_LIST_INDEX GL_LIST_MODE GL_LOGIC_OP_MODE GL_MAP1_COLOR_4 GL_MAP1_GRID_DOMAIN GL_MAP1_GRID_SEGMENTS GL_MAP1_INDEX GL_MAP1_NORMAL GL_MAP1_TEXTURE_COORD_1 GL_MAP1_TEXTURE_COORD_2 GL_MAP1_TEXTURE_COORD_3 GL_MAP1_TEXTURE_COORD_4 GL_MAP1_VERTEX_3 GL_MAP1_VERTEX_4 GL_MAP2_COLOR_4 GL_MAP2_GRID_DOMAIN GL_MAP2_GRID_SEGMENTS GL_MAP2_INDEX GL_MAP2_NORMAL GL_MAP2_TEXTURE_COORD_1 GL_MAP2_TEXTURE_COORD_2 GL_MAP2_TEXTURE_COORD_3 GL_MAP2_TEXTURE_COORD_4 GL_MAP2_VERTEX_3 GL_MAP2_VERTEX_4 GL_MAP_COLOR GL_MAP_STENCIL GL_MATRIX_MODE GL_MAX_3D_TEXTURE_SIZE GL_MAX_ATTRIB_STACK_DEPTH GL_MAX_CLIENT_ATTRIB_STACK_DEPTH GL_MAX_CLIP_PLANES GL_MAX_COLOR_MATRIX_STACK_DEPTH GL_MAX_ELEMENTS_INDICES GL_MAX_ELEMENTS_VERTICES GL_MAX_EVAL_ORDER GL_MAX_LIGHTS GL_MAX_LIST_NESTING GL_MAX_MODELVIEW_STACK_DEPTH GL_MAX_NAME_STACK_DEPTH GL_MAX_PIXEL_MAP_TABLE GL_MAX_PROJECTION_STACK_DEPTH GL_MAX_TEXTURE_SIZE GL_MAX_TEXTURE_STACK_DEPTH GL_MAX_TEXTURE_UNITS_ARB GL_MAX_VIEWPORT_DIMS GL_MODELVIEW_MATRIX GL_MODELVIEW_STACK_DEPTH GL_NAME_STACK_DEPTH GL_NORMAL_ARRAY GL_NORMAL_ARRAY_STRIDE GL_NORMAL_ARRAY_TYPE GL_NORMALIZE GL_PACK_ALIGNMENT GL_PACK_IMAGE_HEIGHT GL_PACK_LSB_FIRST GL_PACK_ROW_LENGTH GL_PACK_SKIP_IMAGES GL_PACK_SKIP_PIXELS GL_PACK_SKIP_ROWS GL_PACK_SWAP_BYTES GL_PERSPECTIVE_CORRECTION_HINT GL_PIXEL_MAP_A_TO_A_SIZE GL_PIXEL_MAP_B_TO_B_SIZE GL_PIXEL_MAP_G_TO_G_SIZE GL_PIXEL_MAP_I_TO_A_SIZE GL_PIXEL_MAP_I_TO_B_SIZE GL_PIXEL_MAP_I_TO_G_SIZE GL_PIXEL_MAP_I_TO_I_SIZE GL_PIXEL_MAP_I_TO_R_SIZE GL_PIXEL_MAP_R_TO_R_SIZE GL_PIXEL_MAP_S_TO_S_SIZE GL_POINT_SIZE GL_POINT_SIZE_GRANULARITY GL_POINT_SIZE_RANGE GL_POINT_SMOOTH GL_POINT_SMOOTH_HINT GL_POLYGON_MODE GL_POLYGON_OFFSET_FACTOR GL_POLYGON_OFFSET_FILL GL_POLYGON_OFFSET_LINE GL_POLYGON_OFFSET_POINT GL_POLYGON_OFFSET_UNITS GL_POLYGON_SMOOTH GL_POLYGON_SMOOTH_HINT GL_POLYGON_STIPPLE GL_PROJECTION_MATRIX GL_PROJECTION_STACK_DEPTH GL_READ_BUFFER GL_RED_BIAS GL_RED_BITS GL_RED_SCALE GL_RENDER_MODE GL_RESCALE_NORMAL GL_RGBA_MODE GL_SCISSOR_BOX GL_SCISSOR_TEST GL_SELECTION_BUFFER_SIZE GL_SHADE_MODEL GL_SMOOTH_LINE_WIDTH_GRANULARITY GL_SMOOTH_LINE_WIDTH_RANGE GL_SMOOTH_POINT_SIZE_GRANULARITY GL_SMOOTH_POINT_SIZE_RANGE GL_STENCIL_BITS GL_STENCIL_CLEAR_VALUE GL_STENCIL_FAIL GL_STENCIL_FUNC GL_STENCIL_PASS_DEPTH_FAIL GL_STENCIL_PASS_DEPTH_PASS GL_STENCIL_REF GL_STENCIL_TEST GL_STENCIL_VALUE_MASK GL_STENCIL_WRITEMASK GL_STEREO GL_SUBPIXEL_BITS GL_TEXTURE_1D GL_TEXTURE_2D GL_TEXTURE_3D GL_TEXTURE_BINDING_1D GL_TEXTURE_BINDING_2D GL_TEXTURE_BINDING_3D GL_TEXTURE_COORD_ARRAY GL_TEXTURE_COORD_ARRAY_SIZE GL_TEXTURE_COORD_ARRAY_STRIDE GL_TEXTURE_COORD_ARRAY_TYPE GL_TEXTURE_GEN_Q GL_TEXTURE_GEN_R GL_TEXTURE_GEN_S GL_TEXTURE_GEN_T GL_TEXTURE_MATRIX GL_TEXTURE_STACK_DEPTH GL_UNPACK_ALIGNMENT GL_UNPACK_IMAGE_HEIGHT GL_UNPACK_LSB_FIRST GL_UNPACK_ROW_LENGTH GL_UNPACK_SKIP_IMAGES GL_UNPACK_SKIP_PIXELS GL_UNPACK_SKIP_ROWS GL_UNPACK_SWAP_BYTES GL_VERTEX_ARRAY GL_VERTEX_ARRAY_SIZE GL_VERTEX_ARRAY_STRIDE GL_VERTEX_ARRAY_TYPE GL_VIEWPORT GL_ZOOM_X GL_ZOOM_Y GL_CLIP_PLANE0 GL_CLIP_PLANE1 GL_CLIP_PLANE2 GL_CLIP_PLANE3 GL_CLIP_PLANE4 GL_CLIP_PLANE5 GL_LIGHT0 GL_LIGHT1 GL_LIGHT2 GL_LIGHT3 GL_LIGHT4 GL_LIGHT5 GL_LIGHT6 GL_LIGHT7 GL_MULTISAMPLE_ARB GL_SAMPLE_ALPHA_TO_COVERAGE_ARB GL_SAMPLE_ALPHA_TO_ONE_ARB GL_SAMPLE_COVERAGE_ARB GL_SAMPLE_BUFFERS_ARB GL_SAMPLES_ARB GL_SAMPLE_COVERAGE_VALUE_ARB GL_SAMPLE_COVERAGE_INVERT_ARB GL_POINT_SPRITE_ARB GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB GL_CLIP_VOLUME_CLIPPING_HINT_EXT GL_RASTER_POSITION_UNCLIPPED_IBM GL_GENERATE_MIPMAP_HINT_SGIS GL_FOG_DISTANCE_MODE_NV GL_TRANSPOSE_MODELVIEW_MATRIX_ARB GL_TRANSPOSE_PROJECTION_MATRIX_ARB GL_TRANSPOSE_TEXTURE_MATRIX_ARB GL_TRANSPOSE_COLOR_MATRIX_ARB GL_MAX_TEXTURE_LOD_BIAS_EXT GL_PER_STAGE_CONSTANTS_NV GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT GL_CURRENT_FOG_COORDINATE_EXT GL_FOG_COORDINATE_ARRAY_TYPE_EXT GL_FOG_COORDINATE_ARRAY_STRIDE_EXT GL_COLOR_SUM_EXT GL_CURRENT_SECONDARY_COLOR_EXT GL_SECONDARY_COLOR_ARRAY_SIZE_EXT GL_SECONDARY_COLOR_ARRAY_TYPE_EXT GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT GL_ARRAY_BUFFER_BINDING_ARB GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB GL_VERTEX_ARRAY_BUFFER_BINDING_ARB GL_NORMAL_ARRAY_BUFFER_BINDING_ARB GL_COLOR_ARRAY_BUFFER_BINDING_ARB GL_INDEX_ARRAY_BUFFER_BINDING_ARB GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB GL_TEXTURE_RECTANGLE_NV GL_TEXTURE_BINDING_RECTANGLE_NV GL_MAX_RECTANGLE_TEXTURE_SIZE_NV
+paramprop pname GL_ACCUM_ALPHA_BITS GL_ACCUM_BLUE_BITS GL_ACCUM_CLEAR_VALUE GL_ACCUM_GREEN_BITS GL_ACCUM_RED_BITS GL_ACTIVE_TEXTURE_ARB GL_ALIASED_LINE_WIDTH_RANGE GL_ALIASED_POINT_SIZE_RANGE GL_ALPHA_BIAS GL_ALPHA_BITS GL_ALPHA_SCALE GL_ALPHA_TEST GL_ALPHA_TEST_FUNC GL_ALPHA_TEST_REF GL_ATTRIB_STACK_DEPTH GL_AUTO_NORMAL GL_AUX_BUFFERS GL_BLEND GL_BLEND_COLOR GL_BLEND_DST GL_BLEND_EQUATION GL_BLEND_SRC GL_BLUE_BIAS GL_BLUE_BITS GL_BLUE_SCALE GL_CLIENT_ACTIVE_TEXTURE_ARB GL_CLIENT_ATTRIB_STACK_DEPTH GL_COLOR_ARRAY GL_COLOR_ARRAY_SIZE GL_COLOR_ARRAY_STRIDE GL_COLOR_ARRAY_TYPE GL_COLOR_CLEAR_VALUE GL_COLOR_LOGIC_OP GL_COLOR_MATERIAL GL_COLOR_MATERIAL_FACE GL_COLOR_MATERIAL_PARAMETER GL_COLOR_MATRIX_STACK_DEPTH GL_COLOR_WRITEMASK GL_CULL_FACE GL_CULL_FACE_MODE GL_CURRENT_COLOR GL_CURRENT_INDEX GL_CURRENT_NORMAL GL_CURRENT_RASTER_COLOR GL_CURRENT_RASTER_DISTANCE GL_CURRENT_RASTER_INDEX GL_CURRENT_RASTER_POSITION GL_CURRENT_RASTER_POSITION_VALID GL_CURRENT_RASTER_TEXTURE_COORDS GL_CURRENT_TEXTURE_COORDS GL_DEPTH_BIAS GL_DEPTH_BITS GL_DEPTH_CLEAR_VALUE GL_DEPTH_FUNC GL_DEPTH_RANGE GL_DEPTH_SCALE GL_DEPTH_TEST GL_DEPTH_WRITEMASK GL_DITHER GL_DOUBLEBUFFER GL_DRAW_BUFFER GL_EDGE_FLAG GL_EDGE_FLAG_ARRAY GL_EDGE_FLAG_ARRAY_STRIDE GL_FEEDBACK_BUFFER_SIZE GL_FEEDBACK_BUFFER_TYPE GL_FOG GL_FOG_COLOR GL_FOG_DENSITY GL_FOG_END GL_FOG_HINT GL_FOG_INDEX GL_FOG_MODE GL_FOG_START GL_FRONT_FACE GL_GREEN_BIAS GL_GREEN_BITS GL_GREEN_SCALE GL_INDEX_ARRAY GL_INDEX_ARRAY_STRIDE GL_INDEX_ARRAY_TYPE GL_INDEX_BITS GL_INDEX_CLEAR_VALUE GL_INDEX_LOGIC_OP GL_INDEX_MODE GL_INDEX_OFFSET GL_INDEX_SHIFT GL_INDEX_WRITEMASK GL_LIGHTING GL_LIGHT_MODEL_AMBIENT GL_LIGHT_MODEL_COLOR_CONTROL GL_LIGHT_MODEL_LOCAL_VIEWER GL_LIGHT_MODEL_TWO_SIDE GL_LINE_SMOOTH GL_LINE_SMOOTH_HINT GL_LINE_STIPPLE GL_LINE_STIPPLE_PATTERN GL_LINE_STIPPLE_REPEAT GL_LINE_WIDTH GL_LINE_WIDTH_GRANULARITY GL_LINE_WIDTH_RANGE GL_LIST_BASE GL_LIST_INDEX GL_LIST_MODE GL_LOGIC_OP_MODE GL_MAP1_COLOR_4 GL_MAP1_GRID_DOMAIN GL_MAP1_GRID_SEGMENTS GL_MAP1_INDEX GL_MAP1_NORMAL GL_MAP1_TEXTURE_COORD_1 GL_MAP1_TEXTURE_COORD_2 GL_MAP1_TEXTURE_COORD_3 GL_MAP1_TEXTURE_COORD_4 GL_MAP1_VERTEX_3 GL_MAP1_VERTEX_4 GL_MAP2_COLOR_4 GL_MAP2_GRID_DOMAIN GL_MAP2_GRID_SEGMENTS GL_MAP2_INDEX GL_MAP2_NORMAL GL_MAP2_TEXTURE_COORD_1 GL_MAP2_TEXTURE_COORD_2 GL_MAP2_TEXTURE_COORD_3 GL_MAP2_TEXTURE_COORD_4 GL_MAP2_VERTEX_3 GL_MAP2_VERTEX_4 GL_MAP_COLOR GL_MAP_STENCIL GL_MATRIX_MODE GL_MAX_3D_TEXTURE_SIZE GL_MAX_ATTRIB_STACK_DEPTH GL_MAX_CLIENT_ATTRIB_STACK_DEPTH GL_MAX_CLIP_PLANES GL_MAX_COLOR_MATRIX_STACK_DEPTH GL_MAX_ELEMENTS_INDICES GL_MAX_ELEMENTS_VERTICES GL_MAX_EVAL_ORDER GL_MAX_LIGHTS GL_MAX_LIST_NESTING GL_MAX_MODELVIEW_STACK_DEPTH GL_MAX_NAME_STACK_DEPTH GL_MAX_PIXEL_MAP_TABLE GL_MAX_PROJECTION_STACK_DEPTH GL_MAX_TEXTURE_SIZE GL_MAX_TEXTURE_STACK_DEPTH GL_MAX_TEXTURE_UNITS_ARB GL_MAX_VIEWPORT_DIMS GL_MODELVIEW_MATRIX GL_MODELVIEW_STACK_DEPTH GL_NAME_STACK_DEPTH GL_NORMAL_ARRAY GL_NORMAL_ARRAY_STRIDE GL_NORMAL_ARRAY_TYPE GL_NORMALIZE GL_PACK_ALIGNMENT GL_PACK_IMAGE_HEIGHT GL_PACK_LSB_FIRST GL_PACK_ROW_LENGTH GL_PACK_SKIP_IMAGES GL_PACK_SKIP_PIXELS GL_PACK_SKIP_ROWS GL_PACK_SWAP_BYTES GL_PERSPECTIVE_CORRECTION_HINT GL_PIXEL_MAP_A_TO_A_SIZE GL_PIXEL_MAP_B_TO_B_SIZE GL_PIXEL_MAP_G_TO_G_SIZE GL_PIXEL_MAP_I_TO_A_SIZE GL_PIXEL_MAP_I_TO_B_SIZE GL_PIXEL_MAP_I_TO_G_SIZE GL_PIXEL_MAP_I_TO_I_SIZE GL_PIXEL_MAP_I_TO_R_SIZE GL_PIXEL_MAP_R_TO_R_SIZE GL_PIXEL_MAP_S_TO_S_SIZE GL_POINT_SIZE GL_POINT_SIZE_GRANULARITY GL_POINT_SIZE_RANGE GL_POINT_SMOOTH GL_POINT_SMOOTH_HINT GL_POLYGON_MODE GL_POLYGON_OFFSET_FACTOR GL_POLYGON_OFFSET_FILL GL_POLYGON_OFFSET_LINE GL_POLYGON_OFFSET_POINT GL_POLYGON_OFFSET_UNITS GL_POLYGON_SMOOTH GL_POLYGON_SMOOTH_HINT GL_POLYGON_STIPPLE GL_PROJECTION_MATRIX GL_PROJECTION_STACK_DEPTH GL_READ_BUFFER GL_RED_BIAS GL_RED_BITS GL_RED_SCALE GL_RENDER_MODE GL_RESCALE_NORMAL GL_RGBA_MODE GL_SCISSOR_BOX GL_SCISSOR_TEST GL_SELECTION_BUFFER_SIZE GL_SHADE_MODEL GL_SMOOTH_LINE_WIDTH_GRANULARITY GL_SMOOTH_LINE_WIDTH_RANGE GL_SMOOTH_POINT_SIZE_GRANULARITY GL_SMOOTH_POINT_SIZE_RANGE GL_STENCIL_BITS GL_STENCIL_CLEAR_VALUE GL_STENCIL_FAIL GL_STENCIL_FUNC GL_STENCIL_PASS_DEPTH_FAIL GL_STENCIL_PASS_DEPTH_PASS GL_STENCIL_REF GL_STENCIL_TEST GL_STENCIL_VALUE_MASK GL_STENCIL_WRITEMASK GL_STEREO GL_SUBPIXEL_BITS GL_TEXTURE_1D GL_TEXTURE_2D GL_TEXTURE_3D GL_TEXTURE_BINDING_1D GL_TEXTURE_BINDING_2D GL_TEXTURE_BINDING_3D GL_TEXTURE_COORD_ARRAY GL_TEXTURE_COORD_ARRAY_SIZE GL_TEXTURE_COORD_ARRAY_STRIDE GL_TEXTURE_COORD_ARRAY_TYPE GL_TEXTURE_GEN_Q GL_TEXTURE_GEN_R GL_TEXTURE_GEN_S GL_TEXTURE_GEN_T GL_TEXTURE_MATRIX GL_TEXTURE_STACK_DEPTH GL_UNPACK_ALIGNMENT GL_UNPACK_IMAGE_HEIGHT GL_UNPACK_LSB_FIRST GL_UNPACK_ROW_LENGTH GL_UNPACK_SKIP_IMAGES GL_UNPACK_SKIP_PIXELS GL_UNPACK_SKIP_ROWS GL_UNPACK_SWAP_BYTES GL_VERTEX_ARRAY GL_VERTEX_ARRAY_SIZE GL_VERTEX_ARRAY_STRIDE GL_VERTEX_ARRAY_TYPE GL_VIEWPORT GL_ZOOM_X GL_ZOOM_Y GL_CLIP_PLANE0 GL_CLIP_PLANE1 GL_CLIP_PLANE2 GL_CLIP_PLANE3 GL_CLIP_PLANE4 GL_CLIP_PLANE5 GL_LIGHT0 GL_LIGHT1 GL_LIGHT2 GL_LIGHT3 GL_LIGHT4 GL_LIGHT5 GL_LIGHT6 GL_LIGHT7 GL_MULTISAMPLE_ARB GL_SAMPLE_ALPHA_TO_COVERAGE_ARB GL_SAMPLE_ALPHA_TO_ONE_ARB GL_SAMPLE_COVERAGE_ARB GL_SAMPLE_BUFFERS_ARB GL_SAMPLES_ARB GL_SAMPLE_COVERAGE_VALUE_ARB GL_SAMPLE_COVERAGE_INVERT_ARB GL_POINT_SPRITE_ARB GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB GL_CLIP_VOLUME_CLIPPING_HINT_EXT GL_RASTER_POSITION_UNCLIPPED_IBM GL_GENERATE_MIPMAP_HINT_SGIS GL_FOG_DISTANCE_MODE_NV GL_TRANSPOSE_MODELVIEW_MATRIX_ARB GL_TRANSPOSE_PROJECTION_MATRIX_ARB GL_TRANSPOSE_TEXTURE_MATRIX_ARB GL_TRANSPOSE_COLOR_MATRIX_ARB GL_MAX_TEXTURE_LOD_BIAS_EXT GL_PER_STAGE_CONSTANTS_NV GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT GL_CURRENT_FOG_COORDINATE_EXT GL_FOG_COORDINATE_ARRAY_TYPE_EXT GL_FOG_COORDINATE_ARRAY_STRIDE_EXT GL_COLOR_SUM_EXT GL_CURRENT_SECONDARY_COLOR_EXT GL_SECONDARY_COLOR_ARRAY_SIZE_EXT GL_SECONDARY_COLOR_ARRAY_TYPE_EXT GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT GL_ARRAY_BUFFER_BINDING_ARB GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB GL_VERTEX_ARRAY_BUFFER_BINDING_ARB GL_NORMAL_ARRAY_BUFFER_BINDING_ARB GL_COLOR_ARRAY_BUFFER_BINDING_ARB GL_INDEX_ARRAY_BUFFER_BINDING_ARB GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB GL_TEXTURE_RECTANGLE_NV GL_TEXTURE_BINDING_RECTANGLE_NV GL_MAX_RECTANGLE_TEXTURE_SIZE_NV GL_READ_FRAMEBUFFER_BINDING_EXT GL_DRAW_FRAMEBUFFER_BINDING_EXT GL_ACTIVE_STENCIL_FACE_EXT
param params GLfloat *
category 1.0
props get
@@ -2623,7 +2623,7 @@ chromium extpack
name GetIntegerv
return void
param pname GLenum
-paramprop pname GL_ACCUM_ALPHA_BITS GL_ACCUM_BLUE_BITS GL_ACCUM_CLEAR_VALUE GL_ACCUM_GREEN_BITS GL_ACCUM_RED_BITS GL_ACTIVE_TEXTURE_ARB GL_ALIASED_LINE_WIDTH_RANGE GL_ALIASED_POINT_SIZE_RANGE GL_ALPHA_BIAS GL_ALPHA_BITS GL_ALPHA_SCALE GL_ALPHA_TEST GL_ALPHA_TEST_FUNC GL_ALPHA_TEST_REF GL_ATTRIB_STACK_DEPTH GL_AUTO_NORMAL GL_AUX_BUFFERS GL_BLEND GL_BLEND_COLOR GL_BLEND_DST GL_BLEND_EQUATION GL_BLEND_SRC GL_BLUE_BIAS GL_BLUE_BITS GL_BLUE_SCALE GL_CLIENT_ACTIVE_TEXTURE_ARB GL_CLIENT_ATTRIB_STACK_DEPTH GL_COLOR_ARRAY GL_COLOR_ARRAY_SIZE GL_COLOR_ARRAY_STRIDE GL_COLOR_ARRAY_TYPE GL_COLOR_CLEAR_VALUE GL_COLOR_LOGIC_OP GL_COLOR_MATERIAL GL_COLOR_MATERIAL_FACE GL_COLOR_MATERIAL_PARAMETER GL_COLOR_MATRIX_STACK_DEPTH GL_COLOR_WRITEMASK GL_CULL_FACE GL_CULL_FACE_MODE GL_CURRENT_COLOR GL_CURRENT_INDEX GL_CURRENT_NORMAL GL_CURRENT_RASTER_COLOR GL_CURRENT_RASTER_DISTANCE GL_CURRENT_RASTER_INDEX GL_CURRENT_RASTER_POSITION GL_CURRENT_RASTER_POSITION_VALID GL_CURRENT_RASTER_TEXTURE_COORDS GL_CURRENT_TEXTURE_COORDS GL_DEPTH_BIAS GL_DEPTH_BITS GL_DEPTH_CLEAR_VALUE GL_DEPTH_FUNC GL_DEPTH_RANGE GL_DEPTH_SCALE GL_DEPTH_TEST GL_DEPTH_WRITEMASK GL_DITHER GL_DOUBLEBUFFER GL_DRAW_BUFFER GL_EDGE_FLAG GL_EDGE_FLAG_ARRAY GL_EDGE_FLAG_ARRAY_STRIDE GL_FEEDBACK_BUFFER_SIZE GL_FEEDBACK_BUFFER_TYPE GL_FOG GL_FOG_COLOR GL_FOG_DENSITY GL_FOG_END GL_FOG_HINT GL_FOG_INDEX GL_FOG_MODE GL_FOG_START GL_FRONT_FACE GL_GREEN_BIAS GL_GREEN_BITS GL_GREEN_SCALE GL_INDEX_ARRAY GL_INDEX_ARRAY_STRIDE GL_INDEX_ARRAY_TYPE GL_INDEX_BITS GL_INDEX_CLEAR_VALUE GL_INDEX_LOGIC_OP GL_INDEX_MODE GL_INDEX_OFFSET GL_INDEX_SHIFT GL_INDEX_WRITEMASK GL_LIGHTING GL_LIGHT_MODEL_AMBIENT GL_LIGHT_MODEL_COLOR_CONTROL GL_LIGHT_MODEL_LOCAL_VIEWER GL_LIGHT_MODEL_TWO_SIDE GL_LINE_SMOOTH GL_LINE_SMOOTH_HINT GL_LINE_STIPPLE GL_LINE_STIPPLE_PATTERN GL_LINE_STIPPLE_REPEAT GL_LINE_WIDTH GL_LINE_WIDTH_GRANULARITY GL_LINE_WIDTH_RANGE GL_LIST_BASE GL_LIST_INDEX GL_LIST_MODE GL_LOGIC_OP_MODE GL_MAP1_COLOR_4 GL_MAP1_GRID_DOMAIN GL_MAP1_GRID_SEGMENTS GL_MAP1_INDEX GL_MAP1_NORMAL GL_MAP1_TEXTURE_COORD_1 GL_MAP1_TEXTURE_COORD_2 GL_MAP1_TEXTURE_COORD_3 GL_MAP1_TEXTURE_COORD_4 GL_MAP1_VERTEX_3 GL_MAP1_VERTEX_4 GL_MAP2_COLOR_4 GL_MAP2_GRID_DOMAIN GL_MAP2_GRID_SEGMENTS GL_MAP2_INDEX GL_MAP2_NORMAL GL_MAP2_TEXTURE_COORD_1 GL_MAP2_TEXTURE_COORD_2 GL_MAP2_TEXTURE_COORD_3 GL_MAP2_TEXTURE_COORD_4 GL_MAP2_VERTEX_3 GL_MAP2_VERTEX_4 GL_MAP_COLOR GL_MAP_STENCIL GL_MATRIX_MODE GL_MAX_3D_TEXTURE_SIZE GL_MAX_ATTRIB_STACK_DEPTH GL_MAX_CLIENT_ATTRIB_STACK_DEPTH GL_MAX_CLIP_PLANES GL_MAX_COLOR_MATRIX_STACK_DEPTH GL_MAX_ELEMENTS_INDICES GL_MAX_ELEMENTS_VERTICES GL_MAX_EVAL_ORDER GL_MAX_LIGHTS GL_MAX_LIST_NESTING GL_MAX_MODELVIEW_STACK_DEPTH GL_MAX_NAME_STACK_DEPTH GL_MAX_PIXEL_MAP_TABLE GL_MAX_PROJECTION_STACK_DEPTH GL_MAX_TEXTURE_SIZE GL_MAX_TEXTURE_STACK_DEPTH GL_MAX_TEXTURE_UNITS_ARB GL_MAX_VIEWPORT_DIMS GL_MODELVIEW_MATRIX GL_MODELVIEW_STACK_DEPTH GL_NAME_STACK_DEPTH GL_NORMAL_ARRAY GL_NORMAL_ARRAY_STRIDE GL_NORMAL_ARRAY_TYPE GL_NORMALIZE GL_PACK_ALIGNMENT GL_PACK_IMAGE_HEIGHT GL_PACK_LSB_FIRST GL_PACK_ROW_LENGTH GL_PACK_SKIP_IMAGES GL_PACK_SKIP_PIXELS GL_PACK_SKIP_ROWS GL_PACK_SWAP_BYTES GL_PERSPECTIVE_CORRECTION_HINT GL_PIXEL_MAP_A_TO_A_SIZE GL_PIXEL_MAP_B_TO_B_SIZE GL_PIXEL_MAP_G_TO_G_SIZE GL_PIXEL_MAP_I_TO_A_SIZE GL_PIXEL_MAP_I_TO_B_SIZE GL_PIXEL_MAP_I_TO_G_SIZE GL_PIXEL_MAP_I_TO_I_SIZE GL_PIXEL_MAP_I_TO_R_SIZE GL_PIXEL_MAP_R_TO_R_SIZE GL_PIXEL_MAP_S_TO_S_SIZE GL_POINT_SIZE GL_POINT_SIZE_GRANULARITY GL_POINT_SIZE_RANGE GL_POINT_SMOOTH GL_POINT_SMOOTH_HINT GL_POLYGON_MODE GL_POLYGON_OFFSET_FACTOR GL_POLYGON_OFFSET_FILL GL_POLYGON_OFFSET_LINE GL_POLYGON_OFFSET_POINT GL_POLYGON_OFFSET_UNITS GL_POLYGON_SMOOTH GL_POLYGON_SMOOTH_HINT GL_POLYGON_STIPPLE GL_PROJECTION_MATRIX GL_PROJECTION_STACK_DEPTH GL_READ_BUFFER GL_RED_BIAS GL_RED_BITS GL_RED_SCALE GL_RENDER_MODE GL_RESCALE_NORMAL GL_RGBA_MODE GL_SCISSOR_BOX GL_SCISSOR_TEST GL_SELECTION_BUFFER_SIZE GL_SHADE_MODEL GL_SMOOTH_LINE_WIDTH_GRANULARITY GL_SMOOTH_LINE_WIDTH_RANGE GL_SMOOTH_POINT_SIZE_GRANULARITY GL_SMOOTH_POINT_SIZE_RANGE GL_STENCIL_BITS GL_STENCIL_CLEAR_VALUE GL_STENCIL_FAIL GL_STENCIL_FUNC GL_STENCIL_PASS_DEPTH_FAIL GL_STENCIL_PASS_DEPTH_PASS GL_STENCIL_REF GL_STENCIL_TEST GL_STENCIL_VALUE_MASK GL_STENCIL_WRITEMASK GL_STEREO GL_SUBPIXEL_BITS GL_TEXTURE_1D GL_TEXTURE_2D GL_TEXTURE_3D GL_TEXTURE_BINDING_1D GL_TEXTURE_BINDING_2D GL_TEXTURE_BINDING_3D GL_TEXTURE_COORD_ARRAY GL_TEXTURE_COORD_ARRAY_SIZE GL_TEXTURE_COORD_ARRAY_STRIDE GL_TEXTURE_COORD_ARRAY_TYPE GL_TEXTURE_GEN_Q GL_TEXTURE_GEN_R GL_TEXTURE_GEN_S GL_TEXTURE_GEN_T GL_TEXTURE_MATRIX GL_TEXTURE_STACK_DEPTH GL_UNPACK_ALIGNMENT GL_UNPACK_IMAGE_HEIGHT GL_UNPACK_LSB_FIRST GL_UNPACK_ROW_LENGTH GL_UNPACK_SKIP_IMAGES GL_UNPACK_SKIP_PIXELS GL_UNPACK_SKIP_ROWS GL_UNPACK_SWAP_BYTES GL_VERTEX_ARRAY GL_VERTEX_ARRAY_SIZE GL_VERTEX_ARRAY_STRIDE GL_VERTEX_ARRAY_TYPE GL_VIEWPORT GL_ZOOM_X GL_ZOOM_Y GL_CLIP_PLANE0 GL_CLIP_PLANE1 GL_CLIP_PLANE2 GL_CLIP_PLANE3 GL_CLIP_PLANE4 GL_CLIP_PLANE5 GL_LIGHT0 GL_LIGHT1 GL_LIGHT2 GL_LIGHT3 GL_LIGHT4 GL_LIGHT5 GL_LIGHT6 GL_LIGHT7 GL_MULTISAMPLE_ARB GL_SAMPLE_ALPHA_TO_COVERAGE_ARB GL_SAMPLE_ALPHA_TO_ONE_ARB GL_SAMPLE_COVERAGE_ARB GL_SAMPLE_BUFFERS_ARB GL_SAMPLES_ARB GL_SAMPLE_COVERAGE_VALUE_ARB GL_SAMPLE_COVERAGE_INVERT_ARB GL_POINT_SPRITE_ARB GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB GL_CLIP_VOLUME_CLIPPING_HINT_EXT GL_RASTER_POSITION_UNCLIPPED_IBM GL_GENERATE_MIPMAP_HINT_SGIS GL_FOG_DISTANCE_MODE_NV GL_TRANSPOSE_MODELVIEW_MATRIX_ARB GL_TRANSPOSE_PROJECTION_MATRIX_ARB GL_TRANSPOSE_TEXTURE_MATRIX_ARB GL_TRANSPOSE_COLOR_MATRIX_ARB GL_MAX_TEXTURE_LOD_BIAS_EXT GL_PER_STAGE_CONSTANTS_NV GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT GL_CURRENT_FOG_COORDINATE_EXT GL_FOG_COORDINATE_ARRAY_TYPE_EXT GL_FOG_COORDINATE_ARRAY_STRIDE_EXT GL_COLOR_SUM_EXT GL_CURRENT_SECONDARY_COLOR_EXT GL_SECONDARY_COLOR_ARRAY_SIZE_EXT GL_SECONDARY_COLOR_ARRAY_TYPE_EXT GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT GL_ARRAY_BUFFER_BINDING_ARB GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB GL_VERTEX_ARRAY_BUFFER_BINDING_ARB GL_NORMAL_ARRAY_BUFFER_BINDING_ARB GL_COLOR_ARRAY_BUFFER_BINDING_ARB GL_INDEX_ARRAY_BUFFER_BINDING_ARB GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB GL_TEXTURE_RECTANGLE_NV GL_TEXTURE_BINDING_RECTANGLE_NV GL_MAX_RECTANGLE_TEXTURE_SIZE_NV GL_FRAMEBUFFER_BINDING_EXT GL_RENDERBUFFER_BINDING_EXT GL_MAX_COLOR_ATTACHMENTS_EXT GL_MAX_RENDERBUFFER_SIZE_EXT
+paramprop pname GL_ACCUM_ALPHA_BITS GL_ACCUM_BLUE_BITS GL_ACCUM_CLEAR_VALUE GL_ACCUM_GREEN_BITS GL_ACCUM_RED_BITS GL_ACTIVE_TEXTURE_ARB GL_ALIASED_LINE_WIDTH_RANGE GL_ALIASED_POINT_SIZE_RANGE GL_ALPHA_BIAS GL_ALPHA_BITS GL_ALPHA_SCALE GL_ALPHA_TEST GL_ALPHA_TEST_FUNC GL_ALPHA_TEST_REF GL_ATTRIB_STACK_DEPTH GL_AUTO_NORMAL GL_AUX_BUFFERS GL_BLEND GL_BLEND_COLOR GL_BLEND_DST GL_BLEND_EQUATION GL_BLEND_SRC GL_BLUE_BIAS GL_BLUE_BITS GL_BLUE_SCALE GL_CLIENT_ACTIVE_TEXTURE_ARB GL_CLIENT_ATTRIB_STACK_DEPTH GL_COLOR_ARRAY GL_COLOR_ARRAY_SIZE GL_COLOR_ARRAY_STRIDE GL_COLOR_ARRAY_TYPE GL_COLOR_CLEAR_VALUE GL_COLOR_LOGIC_OP GL_COLOR_MATERIAL GL_COLOR_MATERIAL_FACE GL_COLOR_MATERIAL_PARAMETER GL_COLOR_MATRIX_STACK_DEPTH GL_COLOR_WRITEMASK GL_CULL_FACE GL_CULL_FACE_MODE GL_CURRENT_COLOR GL_CURRENT_INDEX GL_CURRENT_NORMAL GL_CURRENT_RASTER_COLOR GL_CURRENT_RASTER_DISTANCE GL_CURRENT_RASTER_INDEX GL_CURRENT_RASTER_POSITION GL_CURRENT_RASTER_POSITION_VALID GL_CURRENT_RASTER_TEXTURE_COORDS GL_CURRENT_TEXTURE_COORDS GL_DEPTH_BIAS GL_DEPTH_BITS GL_DEPTH_CLEAR_VALUE GL_DEPTH_FUNC GL_DEPTH_RANGE GL_DEPTH_SCALE GL_DEPTH_TEST GL_DEPTH_WRITEMASK GL_DITHER GL_DOUBLEBUFFER GL_DRAW_BUFFER GL_EDGE_FLAG GL_EDGE_FLAG_ARRAY GL_EDGE_FLAG_ARRAY_STRIDE GL_FEEDBACK_BUFFER_SIZE GL_FEEDBACK_BUFFER_TYPE GL_FOG GL_FOG_COLOR GL_FOG_DENSITY GL_FOG_END GL_FOG_HINT GL_FOG_INDEX GL_FOG_MODE GL_FOG_START GL_FRONT_FACE GL_GREEN_BIAS GL_GREEN_BITS GL_GREEN_SCALE GL_INDEX_ARRAY GL_INDEX_ARRAY_STRIDE GL_INDEX_ARRAY_TYPE GL_INDEX_BITS GL_INDEX_CLEAR_VALUE GL_INDEX_LOGIC_OP GL_INDEX_MODE GL_INDEX_OFFSET GL_INDEX_SHIFT GL_INDEX_WRITEMASK GL_LIGHTING GL_LIGHT_MODEL_AMBIENT GL_LIGHT_MODEL_COLOR_CONTROL GL_LIGHT_MODEL_LOCAL_VIEWER GL_LIGHT_MODEL_TWO_SIDE GL_LINE_SMOOTH GL_LINE_SMOOTH_HINT GL_LINE_STIPPLE GL_LINE_STIPPLE_PATTERN GL_LINE_STIPPLE_REPEAT GL_LINE_WIDTH GL_LINE_WIDTH_GRANULARITY GL_LINE_WIDTH_RANGE GL_LIST_BASE GL_LIST_INDEX GL_LIST_MODE GL_LOGIC_OP_MODE GL_MAP1_COLOR_4 GL_MAP1_GRID_DOMAIN GL_MAP1_GRID_SEGMENTS GL_MAP1_INDEX GL_MAP1_NORMAL GL_MAP1_TEXTURE_COORD_1 GL_MAP1_TEXTURE_COORD_2 GL_MAP1_TEXTURE_COORD_3 GL_MAP1_TEXTURE_COORD_4 GL_MAP1_VERTEX_3 GL_MAP1_VERTEX_4 GL_MAP2_COLOR_4 GL_MAP2_GRID_DOMAIN GL_MAP2_GRID_SEGMENTS GL_MAP2_INDEX GL_MAP2_NORMAL GL_MAP2_TEXTURE_COORD_1 GL_MAP2_TEXTURE_COORD_2 GL_MAP2_TEXTURE_COORD_3 GL_MAP2_TEXTURE_COORD_4 GL_MAP2_VERTEX_3 GL_MAP2_VERTEX_4 GL_MAP_COLOR GL_MAP_STENCIL GL_MATRIX_MODE GL_MAX_3D_TEXTURE_SIZE GL_MAX_ATTRIB_STACK_DEPTH GL_MAX_CLIENT_ATTRIB_STACK_DEPTH GL_MAX_CLIP_PLANES GL_MAX_COLOR_MATRIX_STACK_DEPTH GL_MAX_ELEMENTS_INDICES GL_MAX_ELEMENTS_VERTICES GL_MAX_EVAL_ORDER GL_MAX_LIGHTS GL_MAX_LIST_NESTING GL_MAX_MODELVIEW_STACK_DEPTH GL_MAX_NAME_STACK_DEPTH GL_MAX_PIXEL_MAP_TABLE GL_MAX_PROJECTION_STACK_DEPTH GL_MAX_TEXTURE_SIZE GL_MAX_TEXTURE_STACK_DEPTH GL_MAX_TEXTURE_UNITS_ARB GL_MAX_VIEWPORT_DIMS GL_MODELVIEW_MATRIX GL_MODELVIEW_STACK_DEPTH GL_NAME_STACK_DEPTH GL_NORMAL_ARRAY GL_NORMAL_ARRAY_STRIDE GL_NORMAL_ARRAY_TYPE GL_NORMALIZE GL_PACK_ALIGNMENT GL_PACK_IMAGE_HEIGHT GL_PACK_LSB_FIRST GL_PACK_ROW_LENGTH GL_PACK_SKIP_IMAGES GL_PACK_SKIP_PIXELS GL_PACK_SKIP_ROWS GL_PACK_SWAP_BYTES GL_PERSPECTIVE_CORRECTION_HINT GL_PIXEL_MAP_A_TO_A_SIZE GL_PIXEL_MAP_B_TO_B_SIZE GL_PIXEL_MAP_G_TO_G_SIZE GL_PIXEL_MAP_I_TO_A_SIZE GL_PIXEL_MAP_I_TO_B_SIZE GL_PIXEL_MAP_I_TO_G_SIZE GL_PIXEL_MAP_I_TO_I_SIZE GL_PIXEL_MAP_I_TO_R_SIZE GL_PIXEL_MAP_R_TO_R_SIZE GL_PIXEL_MAP_S_TO_S_SIZE GL_POINT_SIZE GL_POINT_SIZE_GRANULARITY GL_POINT_SIZE_RANGE GL_POINT_SMOOTH GL_POINT_SMOOTH_HINT GL_POLYGON_MODE GL_POLYGON_OFFSET_FACTOR GL_POLYGON_OFFSET_FILL GL_POLYGON_OFFSET_LINE GL_POLYGON_OFFSET_POINT GL_POLYGON_OFFSET_UNITS GL_POLYGON_SMOOTH GL_POLYGON_SMOOTH_HINT GL_POLYGON_STIPPLE GL_PROJECTION_MATRIX GL_PROJECTION_STACK_DEPTH GL_READ_BUFFER GL_RED_BIAS GL_RED_BITS GL_RED_SCALE GL_RENDER_MODE GL_RESCALE_NORMAL GL_RGBA_MODE GL_SCISSOR_BOX GL_SCISSOR_TEST GL_SELECTION_BUFFER_SIZE GL_SHADE_MODEL GL_SMOOTH_LINE_WIDTH_GRANULARITY GL_SMOOTH_LINE_WIDTH_RANGE GL_SMOOTH_POINT_SIZE_GRANULARITY GL_SMOOTH_POINT_SIZE_RANGE GL_STENCIL_BITS GL_STENCIL_CLEAR_VALUE GL_STENCIL_FAIL GL_STENCIL_FUNC GL_STENCIL_PASS_DEPTH_FAIL GL_STENCIL_PASS_DEPTH_PASS GL_STENCIL_REF GL_STENCIL_TEST GL_STENCIL_VALUE_MASK GL_STENCIL_WRITEMASK GL_STEREO GL_SUBPIXEL_BITS GL_TEXTURE_1D GL_TEXTURE_2D GL_TEXTURE_3D GL_TEXTURE_BINDING_1D GL_TEXTURE_BINDING_2D GL_TEXTURE_BINDING_3D GL_TEXTURE_COORD_ARRAY GL_TEXTURE_COORD_ARRAY_SIZE GL_TEXTURE_COORD_ARRAY_STRIDE GL_TEXTURE_COORD_ARRAY_TYPE GL_TEXTURE_GEN_Q GL_TEXTURE_GEN_R GL_TEXTURE_GEN_S GL_TEXTURE_GEN_T GL_TEXTURE_MATRIX GL_TEXTURE_STACK_DEPTH GL_UNPACK_ALIGNMENT GL_UNPACK_IMAGE_HEIGHT GL_UNPACK_LSB_FIRST GL_UNPACK_ROW_LENGTH GL_UNPACK_SKIP_IMAGES GL_UNPACK_SKIP_PIXELS GL_UNPACK_SKIP_ROWS GL_UNPACK_SWAP_BYTES GL_VERTEX_ARRAY GL_VERTEX_ARRAY_SIZE GL_VERTEX_ARRAY_STRIDE GL_VERTEX_ARRAY_TYPE GL_VIEWPORT GL_ZOOM_X GL_ZOOM_Y GL_CLIP_PLANE0 GL_CLIP_PLANE1 GL_CLIP_PLANE2 GL_CLIP_PLANE3 GL_CLIP_PLANE4 GL_CLIP_PLANE5 GL_LIGHT0 GL_LIGHT1 GL_LIGHT2 GL_LIGHT3 GL_LIGHT4 GL_LIGHT5 GL_LIGHT6 GL_LIGHT7 GL_MULTISAMPLE_ARB GL_SAMPLE_ALPHA_TO_COVERAGE_ARB GL_SAMPLE_ALPHA_TO_ONE_ARB GL_SAMPLE_COVERAGE_ARB GL_SAMPLE_BUFFERS_ARB GL_SAMPLES_ARB GL_SAMPLE_COVERAGE_VALUE_ARB GL_SAMPLE_COVERAGE_INVERT_ARB GL_POINT_SPRITE_ARB GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB GL_CLIP_VOLUME_CLIPPING_HINT_EXT GL_RASTER_POSITION_UNCLIPPED_IBM GL_GENERATE_MIPMAP_HINT_SGIS GL_FOG_DISTANCE_MODE_NV GL_TRANSPOSE_MODELVIEW_MATRIX_ARB GL_TRANSPOSE_PROJECTION_MATRIX_ARB GL_TRANSPOSE_TEXTURE_MATRIX_ARB GL_TRANSPOSE_COLOR_MATRIX_ARB GL_MAX_TEXTURE_LOD_BIAS_EXT GL_PER_STAGE_CONSTANTS_NV GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT GL_CURRENT_FOG_COORDINATE_EXT GL_FOG_COORDINATE_ARRAY_TYPE_EXT GL_FOG_COORDINATE_ARRAY_STRIDE_EXT GL_COLOR_SUM_EXT GL_CURRENT_SECONDARY_COLOR_EXT GL_SECONDARY_COLOR_ARRAY_SIZE_EXT GL_SECONDARY_COLOR_ARRAY_TYPE_EXT GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT GL_ARRAY_BUFFER_BINDING_ARB GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB GL_VERTEX_ARRAY_BUFFER_BINDING_ARB GL_NORMAL_ARRAY_BUFFER_BINDING_ARB GL_COLOR_ARRAY_BUFFER_BINDING_ARB GL_INDEX_ARRAY_BUFFER_BINDING_ARB GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB GL_TEXTURE_RECTANGLE_NV GL_TEXTURE_BINDING_RECTANGLE_NV GL_MAX_RECTANGLE_TEXTURE_SIZE_NV GL_FRAMEBUFFER_BINDING_EXT GL_RENDERBUFFER_BINDING_EXT GL_MAX_COLOR_ATTACHMENTS_EXT GL_MAX_RENDERBUFFER_SIZE_EXT GL_READ_FRAMEBUFFER_BINDING_EXT GL_DRAW_FRAMEBUFFER_BINDING_EXT GL_ACTIVE_STENCIL_FACE_EXT
param params GLint *
category 1.0
props get
@@ -8366,11 +8366,24 @@ name WindowVisibleRegion
return void
param window GLint
param cRects GLint
-param pRects GLint *
+param pRects const GLint *
category Chromium
props nolist
chromium extpack
+name VBoxTexPresent
+return void
+param texture GLuint
+param cfg GLuint
+param xPos GLint
+param yPos GLint
+param cRects GLint
+param pRects const GLint *
+category Chromium
+props nolist
+chromium extpack
+chrelopcode 0
+
name WindowShow
return void
param window GLint
@@ -8536,6 +8549,15 @@ param shareCtx GLint
category VBox
chromium nopack
+name VBoxConChromiumParameteriCR
+return void
+param con GLint
+param target GLenum
+paramprop target GL_CURSOR_POSITION_CR GL_DEFAULT_BBOX_CR GL_SCREEN_BBOX_CR GL_OBJECT_BBOX_CR GL_PRINT_STRING_CR GL_MURAL_SIZE_CR GL_NUM_SERVERS_CR GL_NUM_TILES_CR GL_TILE_BOUNDS_CR GL_VERTEX_COUNTS_CR GL_RESET_VERTEX_COUNTERS_CR GL_SET_MAX_VIEWPORT_CR GL_HEAD_SPU_NAME_CR GL_PERF_GET_FRAME_DATA_CR GL_PERF_GET_TIMER_DATA_CR GL_PERF_DUMP_COUNTERS_CR GL_PERF_SET_TOKEN_CR GL_PERF_SET_DUMP_ON_SWAP_CR GL_PERF_SET_DUMP_ON_FINISH_CR GL_PERF_SET_DUMP_ON_FLUSH_CR GL_PERF_START_TIMER_CR GL_PERF_STOP_TIMER_CR GL_WINDOW_SIZE_CR GL_TILE_INFO_CR GL_GATHER_DRAWPIXELS_CR GL_GATHER_PACK_CR GL_GATHER_CONNECT_CR GL_GATHER_POST_SWAPBUFFERS_CR GL_SAVEFRAME_ENABLED_CR GL_SAVEFRAME_FRAMENUM_CR GL_SAVEFRAME_STRIDE_CR GL_SAVEFRAME_SINGLE_CR GL_SAVEFRAME_FILESPEC_CR GL_READBACK_BARRIER_SIZE_CR
+param value GLint
+category VBox
+chromium nopack
+
name VBoxWindowCreate
return GLint
param con GLint
@@ -8569,6 +8591,15 @@ param con GLint
category VBox
chromium nopack
+name VBoxPresentComposition
+return void
+param win GLint
+param pCompositor const struct VBOXVR_SCR_COMPOSITOR *
+param pChangedEntry const struct VBOXVR_SCR_COMPOSITOR_ENTRY *
+category VBox
+chromium nopack
+
+
# OpenGL 1.5
name BindBuffer
@@ -9723,7 +9754,7 @@ chromium nopack
# GL_ARB_shader_objects
name GetHandleARB
-return GLhandleARB
+return VBoxGLhandleARB
param pname GLenum
paramprop pname GL_PROGRAM_OBJECT_ARB
category GL_ARB_shader_objects
@@ -9732,7 +9763,7 @@ chromium extpack serverdependent
name DeleteObjectARB
return void
-param obj GLhandleARB
+param obj VBoxGLhandleARB
category GL_ARB_shader_objects
props nolist
chromium extpack
@@ -9740,14 +9771,14 @@ chromium extpack
name DetachObjectARB
alias DetachShader
return void
-param containerObj GLhandleARB
-param attachedObj GLhandleARB
+param containerObj VBoxGLhandleARB
+param attachedObj VBoxGLhandleARB
category GL_ARB_shader_objects
chromium extpack
name CreateShaderObjectARB
alias CreateShader
-return GLhandleARB
+return VBoxGLhandleARB
param shaderType GLenum
paramprop shaderType GL_FRAGMENT_SHADER_ARB GL_VERTEX_SHADER_ARB
category GL_ARB_shader_objects
@@ -9757,7 +9788,7 @@ chromium nopack
name ShaderSourceARB
alias ShaderSource
return void
-param shaderObj GLhandleARB
+param shaderObj VBoxGLhandleARB
param count GLsizei
param string const GLcharARB **
param length const GLint *
@@ -9767,13 +9798,13 @@ chromium nopack
name CompileShaderARB
alias CompileShader
return void
-param shaderObj GLhandleARB
+param shaderObj VBoxGLhandleARB
category GL_ARB_shader_objects
chromium nopack
name CreateProgramObjectARB
alias CreateProgram
-return GLhandleARB
+return VBoxGLhandleARB
category GL_ARB_shader_objects
props get
chromium nopack
@@ -9781,29 +9812,29 @@ chromium nopack
name AttachObjectARB
alias AttachShader
return void
-param containerObj GLhandleARB
-param obj GLhandleARB
+param containerObj VBoxGLhandleARB
+param obj VBoxGLhandleARB
category GL_ARB_shader_objects
chromium extpack
name LinkProgramARB
alias LinkProgram
return void
-param programObj GLhandleARB
+param programObj VBoxGLhandleARB
category GL_ARB_shader_objects
chromium nopack
name UseProgramObjectARB
alias UseProgram
return void
-param programObj GLhandleARB
+param programObj VBoxGLhandleARB
category GL_ARB_shader_objects
chromium nopack
name ValidateProgramARB
alias ValidateProgram
return void
-param programObj GLhandleARB
+param programObj VBoxGLhandleARB
category GL_ARB_shader_objects
chromium nopack
@@ -9987,7 +10018,7 @@ chromium nopack
name GetObjectParameterfvARB
return void
-param obj GLhandleARB
+param obj VBoxGLhandleARB
param pname GLenum
paramprop pname GL_OBJECT_TYPE_ARB GL_OBJECT_SUBTYPE_ARB GL_OBJECT_DELETE_STATUS_ARB GL_OBJECT_COMPILE_STATUS_ARB GL_OBJECT_LINK_STATUS_ARB GL_OBJECT_VALIDATE_STATUS_ARB GL_OBJECT_INFO_LOG_LENGTH_ARB GL_OBJECT_ATTACHED_OBJECTS_ARB GL_OBJECT_ACTIVE_UNIFORMS_ARB GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB GL_OBJECT_SHADER_SOURCE_LENGTH_ARB
param params GLfloat *
@@ -9997,7 +10028,7 @@ chromium extpack
name GetObjectParameterivARB
return void
-param obj GLhandleARB
+param obj VBoxGLhandleARB
param pname GLenum
paramprop pname GL_OBJECT_TYPE_ARB GL_OBJECT_SUBTYPE_ARB GL_OBJECT_DELETE_STATUS_ARB GL_OBJECT_COMPILE_STATUS_ARB GL_OBJECT_LINK_STATUS_ARB GL_OBJECT_VALIDATE_STATUS_ARB GL_OBJECT_INFO_LOG_LENGTH_ARB GL_OBJECT_ATTACHED_OBJECTS_ARB GL_OBJECT_ACTIVE_UNIFORMS_ARB GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB GL_OBJECT_SHADER_SOURCE_LENGTH_ARB
param params GLint *
@@ -10007,7 +10038,7 @@ chromium extpack
name GetInfoLogARB
return void
-param obj GLhandleARB
+param obj VBoxGLhandleARB
param maxLength GLsizei
param length GLsizei *
param infoLog GLcharARB *
@@ -10017,10 +10048,10 @@ chromium extpack
name GetAttachedObjectsARB
return void
-param containerObj GLhandleARB
+param containerObj VBoxGLhandleARB
param maxCount GLsizei
param count GLsizei *
-param obj GLhandleARB *
+param obj VBoxGLhandleARB *
category GL_ARB_shader_objects
props get
chromium extpack
@@ -10028,7 +10059,7 @@ chromium extpack
name GetUniformLocationARB
alias GetUniformLocation
return GLint
-param programObj GLhandleARB
+param programObj VBoxGLhandleARB
param name const GLcharARB *
category GL_ARB_shader_objects
props get
@@ -10037,7 +10068,7 @@ chromium nopack
name GetActiveUniformARB
alias GetActiveUniform
return void
-param programObj GLhandleARB
+param programObj VBoxGLhandleARB
param index GLuint
param maxLength GLsizei
param length GLsizei *
@@ -10051,7 +10082,7 @@ chromium nopack
name GetShaderSourceARB
alias GetShaderSource
return void
-param obj GLhandleARB
+param obj VBoxGLhandleARB
param maxLength GLsizei
param length GLsizei *
param source GLcharARB *
@@ -10062,7 +10093,7 @@ chromium nopack
name GetUniformfvARB
alias GetUniformfv
return void
-param programObj GLhandleARB
+param programObj VBoxGLhandleARB
param location GLint
param params GLfloat *
category GL_ARB_shader_objects
@@ -10072,7 +10103,7 @@ chromium nopack
name GetUniformivARB
alias GetUniformiv
return void
-param programObj GLhandleARB
+param programObj VBoxGLhandleARB
param location GLint
param params GLint *
category GL_ARB_shader_objects
@@ -10084,7 +10115,7 @@ chromium nopack
name GetActiveAttribARB
alias GetActiveAttrib
return void
-param programObj GLhandleARB
+param programObj VBoxGLhandleARB
param index GLuint
param maxLength GLsizei
param length GLsizei *
@@ -10098,7 +10129,7 @@ chromium nopack
name GetAttribLocationARB
alias GetAttribLocation
return GLint
-param programObj GLhandleARB
+param programObj VBoxGLhandleARB
param name const GLcharARB *
category GL_ARB_vertex_shader
props get
@@ -10107,7 +10138,7 @@ chromium nopack
name BindAttribLocationARB
alias BindAttribLocation
return void
-param programObj GLhandleARB
+param programObj VBoxGLhandleARB
param index GLuint
param name const GLcharARB *
category GL_ARB_vertex_shader
@@ -10383,6 +10414,14 @@ paramprop modeAlpha GL_FUNC_ADD GL_FUNC_SUBTRACT GL_FUNC_REVERSE_SUBTRACT
category GL_EXT_blend_equation_separate
chromium nopack
+# GL_GREMEDY_string_marker
+name StringMarkerGREMEDY
+return void
+param len GLsizei
+param string const GLvoid*
+category GL_GREMEDY_string_marker
+chromium nopack
+
# end of file sentinel
name dummy
diff --git a/src/VBox/GuestHost/OpenGL/glapi_parser/apiutil.py b/src/VBox/GuestHost/OpenGL/glapi_parser/apiutil.py
index e7b7e30c..bce38f18 100755
--- a/src/VBox/GuestHost/OpenGL/glapi_parser/apiutil.py
+++ b/src/VBox/GuestHost/OpenGL/glapi_parser/apiutil.py
@@ -46,6 +46,7 @@ class APIFunction:
self.paramset = []
self.props = []
self.chromium = []
+ self.chrelopcode = -1
@@ -161,6 +162,9 @@ def ProcessSpecFile(filename, userFunc):
record.params[i] = (name, type, vecSize)
break
+ elif tokens[0] == 'chrelopcode':
+ record.chrelopcode = int(tokens[1])
+
else:
print 'Invalid token %s after function %s' % (tokens[0], record.name)
#endif
@@ -223,6 +227,17 @@ def GetAllFunctions(specFile = ""):
funcs.sort()
return funcs
+def GetAllFunctionsAndOmittedAliases(specFile = ""):
+ """Return sorted list of all functions known to Chromium."""
+ d = GetFunctionDict(specFile)
+ funcs = []
+ for func in d.keys():
+ rec = d[func]
+ if (not "omit" in rec.chromium or
+ rec.alias != ''):
+ funcs.append(func)
+ funcs.sort()
+ return funcs
def GetDispatchedFunctions(specFile = ""):
"""Return sorted list of all functions handled by SPU dispatch table."""
@@ -300,6 +315,12 @@ def ChromiumProps(funcName):
"""Return list of Chromium-specific properties of the named GL function."""
d = GetFunctionDict()
return d[funcName].chromium
+
+def ChromiumRelOpCode(funcName):
+ """Return list of Chromium-specific properties of the named GL function."""
+ d = GetFunctionDict()
+ return d[funcName].chrelopcode
+
def ParamProps(funcName):
"""Return list of Parameter-specific properties of the named GL function."""
@@ -356,10 +377,10 @@ def GetCategoryWrapper(func_name):
cat == "VBox"):
return ''
elif (cat == '1.3' or
- cat == '1.4' or
- cat == '1.5' or
- cat == '2.0' or
- cat == '2.1'):
+ cat == '1.4' or
+ cat == '1.5' or
+ cat == '2.0' or
+ cat == '2.1'):
# i.e. OpenGL 1.3 or 1.4 or 1.5
return "OPENGL_VERSION_" + string.replace(cat, ".", "_")
else:
@@ -568,16 +589,16 @@ def MakeDeclarationString(params):
#enddef
def MakeDeclarationStringWithContext(ctx_macro_prefix, params):
- """Same as MakeDeclarationString, but adds a context macro
- """
-
- n = len(params)
- if n == 0:
- return ctx_macro_prefix + '_ARGSINGLEDECL'
- else:
- result = MakeDeclarationString(params)
- return ctx_macro_prefix + '_ARGDECL ' + result
- #endif
+ """Same as MakeDeclarationString, but adds a context macro
+ """
+
+ n = len(params)
+ if n == 0:
+ return ctx_macro_prefix + '_ARGSINGLEDECL'
+ else:
+ result = MakeDeclarationString(params)
+ return ctx_macro_prefix + '_ARGDECL ' + result
+ #endif
#enddef
@@ -625,9 +646,9 @@ __lengths = {
'int': 4,
'GLintptrARB': 4, # XXX or 8 bytes?
'GLsizeiptrARB': 4, # XXX or 8 bytes?
- 'GLhandleARB': 4,
+ 'VBoxGLhandleARB': 4,
'GLcharARB': 1,
- 'uintptr_t': 4
+ 'uintptr_t': 4
}
def sizeof(type):
diff --git a/src/VBox/GuestHost/OpenGL/include/GL/glext.h b/src/VBox/GuestHost/OpenGL/include/GL/glext.h
index 90cd2c01..7f754544 100644
--- a/src/VBox/GuestHost/OpenGL/include/GL/glext.h
+++ b/src/VBox/GuestHost/OpenGL/include/GL/glext.h
@@ -3722,29 +3722,17 @@ typedef ptrdiff_t GLintptrARB;
typedef ptrdiff_t GLsizeiptrARB;
#endif
-/* VBox: HACK ALERT! When building the host side against Mac OS X 10.7 headers,
- /Developer/SDKs/MacOSX10.7.sdk/System/Library/Frameworks/OpenGL.framework/Headers/gltypes.h
- is included and it typedefs GLhandleARB differently. In 10.6 and earlier,
- gl.h was included instead of gltypes.h (new file) avoiding the conflicting
- typedef in Headers/glext.h.
-
- Since sizeof the gltypes.h typedef is 64-bit on 64-bit platforms, we're in
- trouble if the type is used for anything important. Fortunately, the
- conflict only occurs in three files: renderspu_config.c, renderspu_cocoa.c
- and renderspu_cocoa_helper.m. */
-#ifdef RT_OS_DARWIN
-# ifndef MAC_OS_X_VERSION_MIN_REQUIRED
-# error "MAC_OS_X_VERSION_MIN_REQUIRED is not defined"
-# endif
-# if MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 && defined(__gltypes_h_)
-# define GLhandleARB VBoxGLhandleARB
-# endif
-#endif
-
#ifndef GL_ARB_shader_objects
/* GL types for handling shader object handles and program/shader text */
typedef char GLcharARB; /* native character */
-typedef unsigned int GLhandleARB; /* shader object handle */
+typedef unsigned int VBoxGLhandleARB; /* shader object handle */
+# ifdef RT_OS_DARWIN
+typedef void* GLhandleARB; /* shader object handle */
+# else
+typedef unsigned int GLhandleARB; /* native shader object handle */
+# endif
+#else
+# error "GL_ARB_shader_objects should NOT be defined here!!"
#endif
/* GL types for "half" precision (s10e5) float data in host memory */
@@ -4770,17 +4758,17 @@ typedef void (APIENTRYP PFNGLGETQUERYOBJECTUIVARBPROC) (GLuint id, GLenum pname,
#ifndef GL_ARB_shader_objects
#define GL_ARB_shader_objects 1
#ifdef GL_GLEXT_PROTOTYPES
-GLAPI void APIENTRY glDeleteObjectARB (GLhandleARB);
-GLAPI GLhandleARB APIENTRY glGetHandleARB (GLenum);
-GLAPI void APIENTRY glDetachObjectARB (GLhandleARB, GLhandleARB);
-GLAPI GLhandleARB APIENTRY glCreateShaderObjectARB (GLenum);
-GLAPI void APIENTRY glShaderSourceARB (GLhandleARB, GLsizei, const GLcharARB* *, const GLint *);
-GLAPI void APIENTRY glCompileShaderARB (GLhandleARB);
-GLAPI GLhandleARB APIENTRY glCreateProgramObjectARB (void);
-GLAPI void APIENTRY glAttachObjectARB (GLhandleARB, GLhandleARB);
-GLAPI void APIENTRY glLinkProgramARB (GLhandleARB);
-GLAPI void APIENTRY glUseProgramObjectARB (GLhandleARB);
-GLAPI void APIENTRY glValidateProgramARB (GLhandleARB);
+GLAPI void APIENTRY glDeleteObjectARB (VBoxGLhandleARB);
+GLAPI VBoxGLhandleARB APIENTRY glGetHandleARB (GLenum);
+GLAPI void APIENTRY glDetachObjectARB (VBoxGLhandleARB, VBoxGLhandleARB);
+GLAPI VBoxGLhandleARB APIENTRY glCreateShaderObjectARB (GLenum);
+GLAPI void APIENTRY glShaderSourceARB (VBoxGLhandleARB, GLsizei, const GLcharARB* *, const GLint *);
+GLAPI void APIENTRY glCompileShaderARB (VBoxGLhandleARB);
+GLAPI VBoxGLhandleARB APIENTRY glCreateProgramObjectARB (void);
+GLAPI void APIENTRY glAttachObjectARB (VBoxGLhandleARB, VBoxGLhandleARB);
+GLAPI void APIENTRY glLinkProgramARB (VBoxGLhandleARB);
+GLAPI void APIENTRY glUseProgramObjectARB (VBoxGLhandleARB);
+GLAPI void APIENTRY glValidateProgramARB (VBoxGLhandleARB);
GLAPI void APIENTRY glUniform1fARB (GLint, GLfloat);
GLAPI void APIENTRY glUniform2fARB (GLint, GLfloat, GLfloat);
GLAPI void APIENTRY glUniform3fARB (GLint, GLfloat, GLfloat, GLfloat);
@@ -4800,27 +4788,27 @@ GLAPI void APIENTRY glUniform4ivARB (GLint, GLsizei, const GLint *);
GLAPI void APIENTRY glUniformMatrix2fvARB (GLint, GLsizei, GLboolean, const GLfloat *);
GLAPI void APIENTRY glUniformMatrix3fvARB (GLint, GLsizei, GLboolean, const GLfloat *);
GLAPI void APIENTRY glUniformMatrix4fvARB (GLint, GLsizei, GLboolean, const GLfloat *);
-GLAPI void APIENTRY glGetObjectParameterfvARB (GLhandleARB, GLenum, GLfloat *);
-GLAPI void APIENTRY glGetObjectParameterivARB (GLhandleARB, GLenum, GLint *);
-GLAPI void APIENTRY glGetInfoLogARB (GLhandleARB, GLsizei, GLsizei *, GLcharARB *);
-GLAPI void APIENTRY glGetAttachedObjectsARB (GLhandleARB, GLsizei, GLsizei *, GLhandleARB *);
-GLAPI GLint APIENTRY glGetUniformLocationARB (GLhandleARB, const GLcharARB *);
-GLAPI void APIENTRY glGetActiveUniformARB (GLhandleARB, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLcharARB *);
-GLAPI void APIENTRY glGetUniformfvARB (GLhandleARB, GLint, GLfloat *);
-GLAPI void APIENTRY glGetUniformivARB (GLhandleARB, GLint, GLint *);
-GLAPI void APIENTRY glGetShaderSourceARB (GLhandleARB, GLsizei, GLsizei *, GLcharARB *);
-#endif /* GL_GLEXT_PROTOTYPES */
-typedef void (APIENTRYP PFNGLDELETEOBJECTARBPROC) (GLhandleARB obj);
-typedef GLhandleARB (APIENTRYP PFNGLGETHANDLEARBPROC) (GLenum pname);
-typedef void (APIENTRYP PFNGLDETACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB attachedObj);
-typedef GLhandleARB (APIENTRYP PFNGLCREATESHADEROBJECTARBPROC) (GLenum shaderType);
-typedef void (APIENTRYP PFNGLSHADERSOURCEARBPROC) (GLhandleARB shaderObj, GLsizei count, const GLcharARB* *string, const GLint *length);
-typedef void (APIENTRYP PFNGLCOMPILESHADERARBPROC) (GLhandleARB shaderObj);
-typedef GLhandleARB (APIENTRYP PFNGLCREATEPROGRAMOBJECTARBPROC) (void);
-typedef void (APIENTRYP PFNGLATTACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB obj);
-typedef void (APIENTRYP PFNGLLINKPROGRAMARBPROC) (GLhandleARB programObj);
-typedef void (APIENTRYP PFNGLUSEPROGRAMOBJECTARBPROC) (GLhandleARB programObj);
-typedef void (APIENTRYP PFNGLVALIDATEPROGRAMARBPROC) (GLhandleARB programObj);
+GLAPI void APIENTRY glGetObjectParameterfvARB (VBoxGLhandleARB, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetObjectParameterivARB (VBoxGLhandleARB, GLenum, GLint *);
+GLAPI void APIENTRY glGetInfoLogARB (VBoxGLhandleARB, GLsizei, GLsizei *, GLcharARB *);
+GLAPI void APIENTRY glGetAttachedObjectsARB (VBoxGLhandleARB, GLsizei, GLsizei *, VBoxGLhandleARB *);
+GLAPI GLint APIENTRY glGetUniformLocationARB (VBoxGLhandleARB, const GLcharARB *);
+GLAPI void APIENTRY glGetActiveUniformARB (VBoxGLhandleARB, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLcharARB *);
+GLAPI void APIENTRY glGetUniformfvARB (VBoxGLhandleARB, GLint, GLfloat *);
+GLAPI void APIENTRY glGetUniformivARB (VBoxGLhandleARB, GLint, GLint *);
+GLAPI void APIENTRY glGetShaderSourceARB (VBoxGLhandleARB, GLsizei, GLsizei *, GLcharARB *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLDELETEOBJECTARBPROC) (VBoxGLhandleARB obj);
+typedef VBoxGLhandleARB (APIENTRYP PFNGLGETHANDLEARBPROC) (GLenum pname);
+typedef void (APIENTRYP PFNGLDETACHOBJECTARBPROC) (VBoxGLhandleARB containerObj, VBoxGLhandleARB attachedObj);
+typedef VBoxGLhandleARB (APIENTRYP PFNGLCREATESHADEROBJECTARBPROC) (GLenum shaderType);
+typedef void (APIENTRYP PFNGLSHADERSOURCEARBPROC) (VBoxGLhandleARB shaderObj, GLsizei count, const GLcharARB* *string, const GLint *length);
+typedef void (APIENTRYP PFNGLCOMPILESHADERARBPROC) (VBoxGLhandleARB shaderObj);
+typedef VBoxGLhandleARB (APIENTRYP PFNGLCREATEPROGRAMOBJECTARBPROC) (void);
+typedef void (APIENTRYP PFNGLATTACHOBJECTARBPROC) (VBoxGLhandleARB containerObj, VBoxGLhandleARB obj);
+typedef void (APIENTRYP PFNGLLINKPROGRAMARBPROC) (VBoxGLhandleARB programObj);
+typedef void (APIENTRYP PFNGLUSEPROGRAMOBJECTARBPROC) (VBoxGLhandleARB programObj);
+typedef void (APIENTRYP PFNGLVALIDATEPROGRAMARBPROC) (VBoxGLhandleARB programObj);
typedef void (APIENTRYP PFNGLUNIFORM1FARBPROC) (GLint location, GLfloat v0);
typedef void (APIENTRYP PFNGLUNIFORM2FARBPROC) (GLint location, GLfloat v0, GLfloat v1);
typedef void (APIENTRYP PFNGLUNIFORM3FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
@@ -4840,27 +4828,27 @@ typedef void (APIENTRYP PFNGLUNIFORM4IVARBPROC) (GLint location, GLsizei count,
typedef void (APIENTRYP PFNGLUNIFORMMATRIX2FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
typedef void (APIENTRYP PFNGLUNIFORMMATRIX3FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
-typedef void (APIENTRYP PFNGLGETOBJECTPARAMETERFVARBPROC) (GLhandleARB obj, GLenum pname, GLfloat *params);
-typedef void (APIENTRYP PFNGLGETOBJECTPARAMETERIVARBPROC) (GLhandleARB obj, GLenum pname, GLint *params);
-typedef void (APIENTRYP PFNGLGETINFOLOGARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog);
-typedef void (APIENTRYP PFNGLGETATTACHEDOBJECTSARBPROC) (GLhandleARB containerObj, GLsizei maxCount, GLsizei *count, GLhandleARB *obj);
-typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name);
-typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name);
-typedef void (APIENTRYP PFNGLGETUNIFORMFVARBPROC) (GLhandleARB programObj, GLint location, GLfloat *params);
-typedef void (APIENTRYP PFNGLGETUNIFORMIVARBPROC) (GLhandleARB programObj, GLint location, GLint *params);
-typedef void (APIENTRYP PFNGLGETSHADERSOURCEARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *source);
+typedef void (APIENTRYP PFNGLGETOBJECTPARAMETERFVARBPROC) (VBoxGLhandleARB obj, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETOBJECTPARAMETERIVARBPROC) (VBoxGLhandleARB obj, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETINFOLOGARBPROC) (VBoxGLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog);
+typedef void (APIENTRYP PFNGLGETATTACHEDOBJECTSARBPROC) (VBoxGLhandleARB containerObj, GLsizei maxCount, GLsizei *count, VBoxGLhandleARB *obj);
+typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONARBPROC) (VBoxGLhandleARB programObj, const GLcharARB *name);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMARBPROC) (VBoxGLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name);
+typedef void (APIENTRYP PFNGLGETUNIFORMFVARBPROC) (VBoxGLhandleARB programObj, GLint location, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETUNIFORMIVARBPROC) (VBoxGLhandleARB programObj, GLint location, GLint *params);
+typedef void (APIENTRYP PFNGLGETSHADERSOURCEARBPROC) (VBoxGLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *source);
#endif
#ifndef GL_ARB_vertex_shader
#define GL_ARB_vertex_shader 1
#ifdef GL_GLEXT_PROTOTYPES
-GLAPI void APIENTRY glBindAttribLocationARB (GLhandleARB, GLuint, const GLcharARB *);
-GLAPI void APIENTRY glGetActiveAttribARB (GLhandleARB, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLcharARB *);
-GLAPI GLint APIENTRY glGetAttribLocationARB (GLhandleARB, const GLcharARB *);
+GLAPI void APIENTRY glBindAttribLocationARB (VBoxGLhandleARB, GLuint, const GLcharARB *);
+GLAPI void APIENTRY glGetActiveAttribARB (VBoxGLhandleARB, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLcharARB *);
+GLAPI GLint APIENTRY glGetAttribLocationARB (VBoxGLhandleARB, const GLcharARB *);
#endif /* GL_GLEXT_PROTOTYPES */
-typedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONARBPROC) (GLhandleARB programObj, GLuint index, const GLcharARB *name);
-typedef void (APIENTRYP PFNGLGETACTIVEATTRIBARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name);
-typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name);
+typedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONARBPROC) (VBoxGLhandleARB programObj, GLuint index, const GLcharARB *name);
+typedef void (APIENTRYP PFNGLGETACTIVEATTRIBARBPROC) (VBoxGLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name);
+typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONARBPROC) (VBoxGLhandleARB programObj, const GLcharARB *name);
#endif
#ifndef GL_ARB_fragment_shader
diff --git a/src/VBox/GuestHost/OpenGL/include/chromium.h b/src/VBox/GuestHost/OpenGL/include/chromium.h
index f316e23a..4e1ed628 100644
--- a/src/VBox/GuestHost/OpenGL/include/chromium.h
+++ b/src/VBox/GuestHost/OpenGL/include/chromium.h
@@ -21,24 +21,24 @@
#include "cr_compiler.h"
#ifdef IN_RING0
-#include <common/VBoxMPUtils.h>
-#define WINGDIAPI
+# include <common/VBoxMPUtils.h>
+# define WINGDIAPI
#endif
/*
* We effectively wrap gl.h, glu.h, etc, just like GLUT
*/
#ifndef GL_GLEXT_PROTOTYPES
-#define GL_GLEXT_PROTOTYPES
+# define GL_GLEXT_PROTOTYPES
#endif
#if defined(WINDOWS)
# ifdef IN_RING0
# error "should not happen!"
# endif
-#define WIN32_LEAN_AND_MEAN
-#define WGL_APIENTRY __stdcall
-#include <windows.h>
+# define WIN32_LEAN_AND_MEAN
+# define WGL_APIENTRY __stdcall
+# include <windows.h>
#elif defined(DARWIN)
/* nothing */
#else
@@ -55,23 +55,23 @@
#ifdef GLX
-#ifndef GLX_GLXEXT_PROTOTYPES
-#define GLX_GLXEXT_PROTOTYPES
-#endif
-#include <GL/glx.h>
+# ifndef GLX_GLXEXT_PROTOTYPES
+# define GLX_GLXEXT_PROTOTYPES
+# endif
+# include <GL/glx.h>
#endif
#ifdef USE_OSMESA
-#include <GL/osmesa.h>
+# include <GL/osmesa.h>
#endif
#ifdef DARWIN
-#include <stddef.h>
+# include <stddef.h>
#elif !defined(FreeBSD)
-#include <malloc.h> /* to get ptrdiff_t used below */
+# include <malloc.h> /* to get ptrdiff_t used below */
#endif
-#include <GL/glext.h>
+#include "cr_glext.h"
#ifdef __cplusplus
extern "C" {
@@ -79,6 +79,11 @@ extern "C" {
/* to shut up gcc warning for struct VBOXUHGSMI * parameters */
struct VBOXUHGSMI;
+struct VBOXVR_SCR_COMPOSITOR;
+struct VBOXVR_SCR_COMPOSITOR_ENTRY;
+
+#define CR_RENDER_DEFAULT_CONTEXT_ID (INT32_MAX-1)
+#define CR_RENDER_DEFAULT_WINDOW_ID (INT32_MAX-1)
#if defined(IN_GUEST) && (WINDOWS) && defined(VBOX_WITH_WDDM)
# ifdef VBOX_WDDM_WOW64
@@ -607,6 +612,7 @@ extern void APIENTRY glGetChromiumParametervCR(GLenum target, GLuint index, GLen
#define GL_WINDOW_SIZE_CR 0x8B06
#define GL_MAX_WINDOW_SIZE_CR 0x8B24 /* new */
+#define GL_WINDOW_VISIBILITY_CR 0x8B25 /* new */
#endif /* GL_CR_window_size */
@@ -714,7 +720,13 @@ extern void APIENTRY glZPixCR(GLsizei width, GLsizei height, GLenum format,
/*report that the shared resource is no longer used by this context, the parameter value is a texture name*/
#define GL_RCUSAGE_TEXTURE_CLEAR_CR 0x8B2A
/*configures host to create windows initially hidden*/
-#define GL_HOST_WND_CREATED_HIDDEN 0x8B2B
+#define GL_HOST_WND_CREATED_HIDDEN_CR 0x8B2B
+/* guest requests host whether e debug break is needed*/
+#define GL_DBG_CHECK_BREAK_CR 0x8B2C
+/* Tells renderspu the default context id being used by the crserver */
+#define GL_HH_SET_DEFAULT_SHARED_CTX 0x8B2D
+
+#define GL_HH_SET_TMPCTX_MAKE_CURRENT 0x8B2E
/**********************************************************************/
/***** Chromium-specific API *****/
@@ -765,8 +777,9 @@ extern GLint APIENTRY crWindowCreate(const char *dpyName, GLint visBits);
extern void APIENTRY crWindowDestroy(GLint window);
extern void APIENTRY crWindowSize(GLint window, GLint w, GLint h);
extern void APIENTRY crWindowPosition(GLint window, GLint x, GLint y);
-extern void APIENTRY crWindowVisibleRegion( GLint window, GLint cRects, void *pRects );
+extern void APIENTRY crWindowVisibleRegion( GLint window, GLint cRects, const void *pRects );
extern void APIENTRY crWindowShow( GLint window, GLint flag );
+extern void APIENTRY crVBoxTexPresent(GLuint texture, GLuint cfg, GLint xPos, GLint yPos, GLint cRects, const GLint *pRects);
typedef int (CR_APIENTRY *CR_PROC)();
CR_PROC APIENTRY crGetProcAddress( const char *name );
diff --git a/src/VBox/GuestHost/OpenGL/include/cr_blitter.h b/src/VBox/GuestHost/OpenGL/include/cr_blitter.h
new file mode 100644
index 00000000..2a01d3b6
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/include/cr_blitter.h
@@ -0,0 +1,323 @@
+/* $Id$ */
+
+/** @file
+ * Blitter API
+ */
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+#ifndef ___cr_blitter_h__
+#define ___cr_blitter_h__
+
+#include <iprt/cdefs.h>
+#include <iprt/asm.h>
+#include "cr_spu.h"
+#include "cr_vreg.h"
+
+#ifndef IN_RING0
+# define VBOXBLITTERDECL(_type) DECLEXPORT(_type)
+#else
+# define VBOXBLITTERDECL(_type) RTDECL(_type)
+#endif
+
+RT_C_DECLS_BEGIN
+/* GLSL Cache */
+typedef struct CR_GLSL_CACHE
+{
+ int iGlVersion;
+ GLuint uNoAlpha2DProg;
+ GLuint uNoAlpha2DRectProg;
+ SPUDispatchTable *pDispatch;
+} CR_GLSL_CACHE;
+
+DECLINLINE(void) CrGlslInit(CR_GLSL_CACHE *pCache, SPUDispatchTable *pDispatch)
+{
+ memset(pCache, 0, sizeof (*pCache));
+ pCache->pDispatch = pDispatch;
+}
+
+DECLINLINE(bool) CrGlslIsInited(const CR_GLSL_CACHE *pCache)
+{
+ return !!pCache->pDispatch;
+}
+
+/* clients should set proper context before calling these funcs */
+VBOXBLITTERDECL(bool) CrGlslIsSupported(CR_GLSL_CACHE *pCache);
+VBOXBLITTERDECL(int) CrGlslProgGenAllNoAlpha(CR_GLSL_CACHE *pCache);
+VBOXBLITTERDECL(int) CrGlslProgGenNoAlpha(CR_GLSL_CACHE *pCache, GLenum enmTexTarget);
+VBOXBLITTERDECL(int) CrGlslProgUseGenNoAlpha(CR_GLSL_CACHE *pCache, GLenum enmTexTarget);
+VBOXBLITTERDECL(int) CrGlslProgUseNoAlpha(const CR_GLSL_CACHE *pCache, GLenum enmTexTarget);
+VBOXBLITTERDECL(void) CrGlslProgClear(const CR_GLSL_CACHE *pCache);
+VBOXBLITTERDECL(bool) CrGlslNeedsCleanup(const CR_GLSL_CACHE *pCache);
+VBOXBLITTERDECL(void) CrGlslCleanup(CR_GLSL_CACHE *pCache);
+VBOXBLITTERDECL(void) CrGlslTerm(CR_GLSL_CACHE *pCache);
+
+/* BLITTER */
+typedef struct CR_BLITTER_BUFFER
+{
+ GLuint cbBuffer;
+ GLvoid * pvBuffer;
+} CR_BLITTER_BUFFER, *PCR_BLITTER_BUFFER;
+
+typedef union CR_BLITTER_FLAGS
+{
+ struct
+ {
+ uint32_t Initialized : 1;
+ uint32_t CtxCreated : 1;
+ uint32_t SupportsFBO : 1;
+ uint32_t SupportsPBO : 1;
+ uint32_t CurrentMuralChanged : 1;
+ uint32_t LastWasFBODraw : 1;
+ uint32_t ForceDrawBlit : 1;
+ uint32_t ShadersGloal : 1;
+ uint32_t Reserved : 24;
+ };
+ uint32_t Value;
+} CR_BLITTER_FLAGS, *PCR_BLITTER_FLAGS;
+
+struct CR_BLITTER;
+
+typedef DECLCALLBACK(int) FNCRBLT_BLITTER(struct CR_BLITTER *pBlitter, const VBOXVR_TEXTURE *pSrc, const RTRECT *paSrcRect, const RTRECTSIZE *pDstSize, const RTRECT *paDstRect, uint32_t cRects, uint32_t fFlags);
+typedef FNCRBLT_BLITTER *PFNCRBLT_BLITTER;
+
+typedef struct CR_BLITTER_SPUITEM
+{
+ int id;
+ GLint visualBits;
+} CR_BLITTER_SPUITEM, *PCR_BLITTER_SPUITEM;
+
+typedef struct CR_BLITTER_CONTEXT
+{
+ CR_BLITTER_SPUITEM Base;
+} CR_BLITTER_CONTEXT, *PCR_BLITTER_CONTEXT;
+
+typedef struct CR_BLITTER_WINDOW
+{
+ CR_BLITTER_SPUITEM Base;
+ GLuint width, height;
+} CR_BLITTER_WINDOW, *PCR_BLITTER_WINDOW;
+
+typedef struct CR_BLITTER_IMG
+{
+ void *pvData;
+ GLuint cbData;
+ GLenum enmFormat;
+ GLuint width, height;
+ GLuint bpp;
+ GLuint pitch;
+} CR_BLITTER_IMG, *PCR_BLITTER_IMG;
+
+typedef struct CR_BLITTER
+{
+ GLuint idFBO;
+ CR_BLITTER_FLAGS Flags;
+ uint32_t cEnters;
+ PFNCRBLT_BLITTER pfnBlt;
+ CR_BLITTER_BUFFER Verticies;
+ CR_BLITTER_BUFFER Indicies;
+ RTRECTSIZE CurrentSetSize;
+ CR_BLITTER_WINDOW CurrentMural;
+ CR_BLITTER_CONTEXT CtxInfo;
+ int32_t i32MakeCurrentUserData;
+ SPUDispatchTable *pDispatch;
+ const CR_GLSL_CACHE *pGlslCache;
+ CR_GLSL_CACHE LocalGlslCache;
+} CR_BLITTER, *PCR_BLITTER;
+
+DECLINLINE(GLboolean) CrBltIsInitialized(PCR_BLITTER pBlitter)
+{
+ return !!pBlitter->pDispatch;
+}
+
+VBOXBLITTERDECL(int) CrBltInit(PCR_BLITTER pBlitter, const CR_BLITTER_CONTEXT *pCtxBase, bool fCreateNewCtx, bool fForceDrawBlt, const CR_GLSL_CACHE *pShaders, SPUDispatchTable *pDispatch);
+
+VBOXBLITTERDECL(void) CrBltTerm(PCR_BLITTER pBlitter);
+
+VBOXBLITTERDECL(int) CrBltCleanup(PCR_BLITTER pBlitter);
+
+DECLINLINE(GLboolean) CrBltSupportsTexTex(PCR_BLITTER pBlitter)
+{
+ return pBlitter->Flags.SupportsFBO;
+}
+
+DECLINLINE(GLboolean) CrBltIsEntered(PCR_BLITTER pBlitter)
+{
+ return !!pBlitter->cEnters;
+}
+
+DECLINLINE(GLint) CrBltGetVisBits(PCR_BLITTER pBlitter)
+{
+ return pBlitter->CtxInfo.Base.visualBits;
+}
+
+
+DECLINLINE(GLboolean) CrBltIsEverEntered(PCR_BLITTER pBlitter)
+{
+ return !!pBlitter->Flags.Initialized;
+}
+
+DECLINLINE(void) CrBltSetMakeCurrentUserData(PCR_BLITTER pBlitter, int32_t i32MakeCurrentUserData)
+{
+ pBlitter->i32MakeCurrentUserData = i32MakeCurrentUserData;
+}
+
+VBOXBLITTERDECL(int) CrBltMuralSetCurrentInfo(PCR_BLITTER pBlitter, const CR_BLITTER_WINDOW *pMural);
+DECLINLINE(const CR_BLITTER_WINDOW *) CrBltMuralGetCurrentInfo(PCR_BLITTER pBlitter)
+{
+ return &pBlitter->CurrentMural;
+}
+
+VBOXBLITTERDECL(void) CrBltCheckUpdateViewport(PCR_BLITTER pBlitter);
+
+VBOXBLITTERDECL(void) CrBltLeave(PCR_BLITTER pBlitter);
+VBOXBLITTERDECL(int) CrBltEnter(PCR_BLITTER pBlitter);
+VBOXBLITTERDECL(void) CrBltBlitTexMural(PCR_BLITTER pBlitter, bool fBb, const VBOXVR_TEXTURE *pSrc, const RTRECT *paSrcRects, const RTRECT *paDstRects, uint32_t cRects, uint32_t fFlags);
+VBOXBLITTERDECL(void) CrBltBlitTexTex(PCR_BLITTER pBlitter, const VBOXVR_TEXTURE *pSrc, const RTRECT *pSrcRect, const VBOXVR_TEXTURE *pDst, const RTRECT *pDstRect, uint32_t cRects, uint32_t fFlags);
+VBOXBLITTERDECL(int) CrBltImgGetTex(PCR_BLITTER pBlitter, const VBOXVR_TEXTURE *pSrc, GLenum enmFormat, CR_BLITTER_IMG *pDst);
+
+VBOXBLITTERDECL(int) CrBltImgGetMural(PCR_BLITTER pBlitter, bool fBb, CR_BLITTER_IMG *pDst);
+VBOXBLITTERDECL(void) CrBltImgFree(PCR_BLITTER pBlitter, CR_BLITTER_IMG *pDst);
+VBOXBLITTERDECL(void) CrBltPresent(PCR_BLITTER pBlitter);
+/* */
+struct CR_TEXDATA;
+
+typedef DECLCALLBACK(void) FNCRTEXDATA_RELEASED(struct CR_TEXDATA *pTexture);
+typedef FNCRTEXDATA_RELEASED *PFNCRTEXDATA_RELEASED;
+
+typedef union CR_TEXDATA_FLAGS
+{
+ struct
+ {
+ uint32_t DataValid : 1;
+ uint32_t DataAcquired : 1;
+ uint32_t DataInverted : 1;
+ uint32_t Entered : 1;
+ uint32_t Reserved : 28;
+ };
+ uint32_t Value;
+} CR_TEXDATA_FLAGS, *PCR_TEXDATA_FLAGS;
+
+
+typedef struct CR_TEXDATA
+{
+ VBOXVR_TEXTURE Tex;
+ volatile uint32_t cRefs;
+ /* fields specific to texture data download */
+ uint32_t idInvertTex;
+ uint32_t idPBO;
+ CR_TEXDATA_FLAGS Flags;
+ PCR_BLITTER pBlitter;
+ CR_BLITTER_IMG Img;
+ /*dtor*/
+ PFNCRTEXDATA_RELEASED pfnTextureReleased;
+ struct CR_TEXDATA *pScaledCache;
+} CR_TEXDATA, *PCR_TEXDATA;
+
+DECLINLINE(void) CrTdInit(PCR_TEXDATA pTex, const VBOXVR_TEXTURE *pVrTex, PCR_BLITTER pBlitter, PFNCRTEXDATA_RELEASED pfnTextureReleased)
+{
+ memset(pTex, 0, sizeof (*pTex));
+ pTex->Tex = *pVrTex;
+ pTex->cRefs = 1;
+ pTex->pBlitter = pBlitter;
+ pTex->pfnTextureReleased = pfnTextureReleased;
+}
+
+DECLINLINE(const VBOXVR_TEXTURE*) CrTdTexGet(const CR_TEXDATA *pTex)
+{
+ return &pTex->Tex;
+}
+
+DECLINLINE(PCR_BLITTER) CrTdBlitterGet(CR_TEXDATA *pTex)
+{
+ return pTex->pBlitter;
+}
+
+DECLINLINE(int) CrTdBltEnter(PCR_TEXDATA pTex)
+{
+ int rc;
+ if (pTex->Flags.Entered)
+ return VERR_INVALID_STATE;
+ rc = CrBltEnter(pTex->pBlitter);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("CrBltEnter failed rc %d", rc));
+ return rc;
+ }
+ pTex->Flags.Entered = 1;
+ return VINF_SUCCESS;
+}
+
+DECLINLINE(bool) CrTdBltIsEntered(PCR_TEXDATA pTex)
+{
+ return pTex->Flags.Entered;
+}
+
+DECLINLINE(void) CrTdBltLeave(PCR_TEXDATA pTex)
+{
+ if (!pTex->Flags.Entered)
+ {
+ WARN(("invalid Blt Leave"));
+ return;
+ }
+
+ CrBltLeave(pTex->pBlitter);
+
+ pTex->Flags.Entered = 0;
+}
+
+/* the CrTdBltXxx calls are done with the entered blitter */
+/* acquire the texture data, returns the cached data in case it is cached.
+ * the data remains cached in the CR_TEXDATA object until it is discarded with CrTdBltDataFree or CrTdBltDataCleanup.
+ * */
+VBOXBLITTERDECL(int) CrTdBltDataAcquire(PCR_TEXDATA pTex, GLenum enmFormat, bool fInverted, const CR_BLITTER_IMG**ppImg);
+
+VBOXBLITTERDECL(int) CrTdBltDataAcquireScaled(PCR_TEXDATA pTex, GLenum enmFormat, bool fInverted, uint32_t width, uint32_t height, const CR_BLITTER_IMG**ppImg);
+
+VBOXBLITTERDECL(int) CrTdBltDataReleaseScaled(PCR_TEXDATA pTex, const CR_BLITTER_IMG *pImg);
+
+VBOXBLITTERDECL(void) CrTdBltScaleCacheMoveTo(PCR_TEXDATA pTex, PCR_TEXDATA pDstTex);
+
+/* release the texture data, the data remains cached in the CR_TEXDATA object until it is discarded with CrTdBltDataFree or CrTdBltDataCleanup */
+VBOXBLITTERDECL(int) CrTdBltDataRelease(PCR_TEXDATA pTex);
+/* discard the texture data cached with previous CrTdBltDataAcquire.
+ * Must be called wit data released (CrTdBltDataRelease) */
+VBOXBLITTERDECL(int) CrTdBltDataFree(PCR_TEXDATA pTex);
+VBOXBLITTERDECL(int) CrTdBltDataFreeNe(PCR_TEXDATA pTex);
+VBOXBLITTERDECL(void) CrTdBltDataInvalidateNe(PCR_TEXDATA pTex);
+/* does same as CrTdBltDataFree, and in addition cleans up.
+ * this is kind of a texture destructor, which clients should call on texture object destruction, e.g. from the PFNCRTEXDATA_RELEASED callback */
+VBOXBLITTERDECL(int) CrTdBltDataCleanup(PCR_TEXDATA pTex);
+
+VBOXBLITTERDECL(int) CrTdBltDataCleanupNe(PCR_TEXDATA pTex);
+
+DECLINLINE(uint32_t) CrTdAddRef(PCR_TEXDATA pTex)
+{
+ return ASMAtomicIncU32(&pTex->cRefs);
+}
+
+DECLINLINE(uint32_t) CrTdRelease(PCR_TEXDATA pTex)
+{
+ uint32_t cRefs = ASMAtomicDecU32(&pTex->cRefs);
+ if (!cRefs)
+ {
+ if (pTex->pfnTextureReleased)
+ pTex->pfnTextureReleased(pTex);
+ else
+ CrTdBltDataCleanupNe(pTex);
+ }
+
+ return cRefs;
+}
+
+RT_C_DECLS_END
+
+#endif /* #ifndef ___cr_blitter_h__ */
diff --git a/src/VBox/GuestHost/OpenGL/include/cr_bmpscale.h b/src/VBox/GuestHost/OpenGL/include/cr_bmpscale.h
new file mode 100644
index 00000000..fda56bac
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/include/cr_bmpscale.h
@@ -0,0 +1,25 @@
+#ifndef ___cr_bmpscale_h__
+#define ___cr_bmpscale_h__
+
+#include <iprt/types.h>
+#include <iprt/cdefs.h>
+
+
+RT_C_DECLS_BEGIN
+
+#ifndef IN_RING0
+# define VBOXBMPSCALEDECL(_type) DECLEXPORT(_type)
+#else
+# define VBOXBLITTERDECL(_type) RTDECL(_type)
+#endif
+
+VBOXBMPSCALEDECL(void) CrBmpScale32 (uint8_t *dst,
+ int iDstDeltaLine,
+ int dstW, int dstH,
+ const uint8_t *src,
+ int iSrcDeltaLine,
+ int srcW, int srcH);
+
+RT_C_DECLS_END
+
+#endif /* #ifndef ___cr_bmpscale_h__ */
diff --git a/src/VBox/GuestHost/OpenGL/include/cr_compositor.h b/src/VBox/GuestHost/OpenGL/include/cr_compositor.h
new file mode 100644
index 00000000..4ad56936
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/include/cr_compositor.h
@@ -0,0 +1,233 @@
+/* $Id: cr_compositor.h $ */
+
+/** @file
+ * uint32_t compositor API
+ */
+
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+#ifndef ___cr_compositor_h_
+#define ___cr_compositor_h_
+#include <cr_vreg.h>
+#include <cr_blitter.h>
+
+/* Compositor with Stretching & Cached Rectangles info */
+
+RT_C_DECLS_BEGIN
+
+struct VBOXVR_SCR_COMPOSITOR_ENTRY;
+struct VBOXVR_SCR_COMPOSITOR;
+
+typedef DECLCALLBACK(void) FNVBOXVRSCRCOMPOSITOR_ENTRY_RELEASED(const struct VBOXVR_SCR_COMPOSITOR *pCompositor, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacingEntry);
+typedef FNVBOXVRSCRCOMPOSITOR_ENTRY_RELEASED *PFNVBOXVRSCRCOMPOSITOR_ENTRY_RELEASED;
+
+
+typedef struct VBOXVR_SCR_COMPOSITOR_ENTRY
+{
+ VBOXVR_COMPOSITOR_ENTRY Ce;
+ RTRECT Rect;
+ uint32_t fChanged;
+ uint32_t fFlags;
+ uint32_t cRects;
+ PRTRECT paSrcRects;
+ PRTRECT paDstRects;
+ PRTRECT paDstUnstretchedRects;
+ PFNVBOXVRSCRCOMPOSITOR_ENTRY_RELEASED pfnEntryReleased;
+ PCR_TEXDATA pTex;
+} VBOXVR_SCR_COMPOSITOR_ENTRY, *PVBOXVR_SCR_COMPOSITOR_ENTRY;
+
+typedef struct VBOXVR_SCR_COMPOSITOR
+{
+ VBOXVR_COMPOSITOR Compositor;
+ RTRECT Rect;
+#ifndef IN_RING0
+ float StretchX;
+ float StretchY;
+#endif
+ uint32_t fFlags;
+ uint32_t cRects;
+ uint32_t cRectsBuffer;
+ PRTRECT paSrcRects;
+ PRTRECT paDstRects;
+ PRTRECT paDstUnstretchedRects;
+} VBOXVR_SCR_COMPOSITOR, *PVBOXVR_SCR_COMPOSITOR;
+
+
+typedef DECLCALLBACK(bool) FNVBOXVRSCRCOMPOSITOR_VISITOR(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, void *pvVisitor);
+typedef FNVBOXVRSCRCOMPOSITOR_VISITOR *PFNVBOXVRSCRCOMPOSITOR_VISITOR;
+
+DECLINLINE(void) CrVrScrCompositorEntryInit(PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const RTRECT *pRect, CR_TEXDATA *pTex, PFNVBOXVRSCRCOMPOSITOR_ENTRY_RELEASED pfnEntryReleased)
+{
+ memset(pEntry, 0, sizeof (*pEntry));
+ VBoxVrCompositorEntryInit(&pEntry->Ce);
+ pEntry->Rect = *pRect;
+ pEntry->pfnEntryReleased = pfnEntryReleased;
+ if (pTex)
+ {
+ CrTdAddRef(pTex);
+ pEntry->pTex = pTex;
+ }
+}
+
+DECLINLINE(void) CrVrScrCompositorEntryCleanup(PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry)
+{
+ if (pEntry->pTex)
+ {
+ CrTdRelease(pEntry->pTex);
+ pEntry->pTex = NULL;
+ }
+}
+
+DECLINLINE(bool) CrVrScrCompositorEntryIsUsed(const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry)
+{
+ return VBoxVrCompositorEntryIsInList(&pEntry->Ce);
+}
+
+DECLINLINE(void) CrVrScrCompositorEntrySetChanged(PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, bool fChanged)
+{
+ pEntry->fChanged = !!fChanged;
+}
+
+DECLINLINE(void) CrVrScrCompositorEntryTexSet(PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, CR_TEXDATA *pTex)
+{
+ if (pEntry->pTex)
+ CrTdRelease(pEntry->pTex);
+
+ if (pTex)
+ CrTdAddRef(pTex);
+
+ pEntry->pTex = pTex;
+}
+
+DECLINLINE(CR_TEXDATA *) CrVrScrCompositorEntryTexGet(const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry)
+{
+ return pEntry->pTex;
+}
+
+DECLINLINE(bool) CrVrScrCompositorEntryIsChanged(const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry)
+{
+ return !!pEntry->fChanged;
+}
+
+DECLINLINE(bool) CrVrScrCompositorIsEmpty(const VBOXVR_SCR_COMPOSITOR *pCompositor)
+{
+ return VBoxVrCompositorIsEmpty(&pCompositor->Compositor);
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorEntryRectSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const RTRECT *pRect);
+VBOXVREGDECL(int) CrVrScrCompositorEntryTexAssign(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, CR_TEXDATA *pTex);
+VBOXVREGDECL(void) CrVrScrCompositorVisit(PVBOXVR_SCR_COMPOSITOR pCompositor, PFNVBOXVRSCRCOMPOSITOR_VISITOR pfnVisitor, void *pvVisitor);
+VBOXVREGDECL(void) CrVrScrCompositorEntrySetAllChanged(PVBOXVR_SCR_COMPOSITOR pCompositor, bool fChanged);
+DECLINLINE(bool) CrVrScrCompositorEntryIsInList(const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry)
+{
+ return VBoxVrCompositorEntryIsInList(&pEntry->Ce);
+}
+VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsAdd(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated, VBOXVR_SCR_COMPOSITOR_ENTRY **ppReplacedScrEntry, uint32_t *pfChangeFlags);
+VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated, bool *pfChanged);
+VBOXVREGDECL(int) CrVrScrCompositorEntryListIntersect(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const VBOXVR_LIST *pList2, bool *pfChanged);
+VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsIntersect(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, uint32_t cRegions, const RTRECT *paRegions, bool *pfChanged);
+VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsIntersectAll(PVBOXVR_SCR_COMPOSITOR pCompositor, uint32_t cRegions, const RTRECT *paRegions, bool *pfChanged);
+VBOXVREGDECL(int) CrVrScrCompositorEntryListIntersectAll(PVBOXVR_SCR_COMPOSITOR pCompositor, const VBOXVR_LIST *pList2, bool *pfChanged);
+VBOXVREGDECL(int) CrVrScrCompositorEntryPosSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const RTPOINT *pPos);
+DECLINLINE(const RTRECT*) CrVrScrCompositorEntryRectGet(const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry)
+{
+ return &pEntry->Rect;
+}
+
+/* regions are valid until the next CrVrScrCompositor call */
+VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsGet(const VBOXVR_SCR_COMPOSITOR *pCompositor, const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry, uint32_t *pcRegions, const RTRECT **ppaSrcRegions, const RTRECT **ppaDstRegions, const RTRECT **ppaDstUnstretchedRects);
+VBOXVREGDECL(int) CrVrScrCompositorEntryRemove(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry);
+VBOXVREGDECL(bool) CrVrScrCompositorEntryReplace(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, PVBOXVR_SCR_COMPOSITOR_ENTRY pNewEntry);
+VBOXVREGDECL(void) CrVrScrCompositorEntryFlagsSet(PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, uint32_t fFlags);
+VBOXVREGDECL(uint32_t) CrVrScrCompositorEntryFlagsCombinedGet(const VBOXVR_SCR_COMPOSITOR *pCompositor, const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry);
+DECLINLINE(uint32_t) CrVrScrCompositorEntryFlagsGet(const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry)
+{
+ return pEntry->fFlags;
+}
+
+VBOXVREGDECL(void) CrVrScrCompositorInit(PVBOXVR_SCR_COMPOSITOR pCompositor, const RTRECT *pRect);
+VBOXVREGDECL(int) CrVrScrCompositorRectSet(PVBOXVR_SCR_COMPOSITOR pCompositor, const RTRECT *pRect, bool *pfChanged);
+DECLINLINE(const RTRECT*) CrVrScrCompositorRectGet(const VBOXVR_SCR_COMPOSITOR *pCompositor)
+{
+ return &pCompositor->Rect;
+}
+
+VBOXVREGDECL(void) CrVrScrCompositorClear(PVBOXVR_SCR_COMPOSITOR pCompositor);
+VBOXVREGDECL(void) CrVrScrCompositorRegionsClear(PVBOXVR_SCR_COMPOSITOR pCompositor, bool *pfChanged);
+
+typedef DECLCALLBACK(VBOXVR_SCR_COMPOSITOR_ENTRY*) FNVBOXVR_SCR_COMPOSITOR_ENTRY_FOR(const VBOXVR_SCR_COMPOSITOR_ENTRY*pEntry, void *pvContext);
+typedef FNVBOXVR_SCR_COMPOSITOR_ENTRY_FOR *PFNVBOXVR_SCR_COMPOSITOR_ENTRY_FOR;
+
+VBOXVREGDECL(int) CrVrScrCompositorClone(const VBOXVR_SCR_COMPOSITOR *pCompositor, PVBOXVR_SCR_COMPOSITOR pDstCompositor, PFNVBOXVR_SCR_COMPOSITOR_ENTRY_FOR pfnEntryFor, void* pvEntryFor);
+VBOXVREGDECL(int) CrVrScrCompositorIntersectList(PVBOXVR_SCR_COMPOSITOR pCompositor, const VBOXVR_LIST *pVr, bool *pfChanged);
+VBOXVREGDECL(int) CrVrScrCompositorIntersectedList(const VBOXVR_SCR_COMPOSITOR *pCompositor, const VBOXVR_LIST *pVr, PVBOXVR_SCR_COMPOSITOR pDstCompositor, PFNVBOXVR_SCR_COMPOSITOR_ENTRY_FOR pfnEntryFor, void* pvEntryFor, bool *pfChanged);
+#ifndef IN_RING0
+VBOXVREGDECL(void) CrVrScrCompositorSetStretching(PVBOXVR_SCR_COMPOSITOR pCompositor, float StretchX, float StretchY);
+DECLINLINE(void) CrVrScrCompositorGetStretching(const VBOXVR_SCR_COMPOSITOR *pCompositor, float *pStretchX, float *pStretchY)
+{
+ if (pStretchX)
+ *pStretchX = pCompositor->StretchX;
+
+ if (pStretchY)
+ *pStretchY = pCompositor->StretchY;
+}
+#endif
+/* regions are valid until the next CrVrScrCompositor call */
+VBOXVREGDECL(int) CrVrScrCompositorRegionsGet(const VBOXVR_SCR_COMPOSITOR *pCompositor, uint32_t *pcRegions, const RTRECT **ppaSrcRegions, const RTRECT **ppaDstRegions, const RTRECT **ppaDstUnstretchedRects);
+
+#define VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(_p) ((PVBOXVR_SCR_COMPOSITOR_ENTRY)(((uint8_t*)(_p)) - RT_OFFSETOF(VBOXVR_SCR_COMPOSITOR_ENTRY, Ce)))
+#define VBOXVR_SCR_COMPOSITOR_CONST_ENTRY_FROM_ENTRY(_p) ((const VBOXVR_SCR_COMPOSITOR_ENTRY*)(((uint8_t*)(_p)) - RT_OFFSETOF(VBOXVR_SCR_COMPOSITOR_ENTRY, Ce)))
+#define VBOXVR_SCR_COMPOSITOR_FROM_COMPOSITOR(_p) ((PVBOXVR_SCR_COMPOSITOR)(((uint8_t*)(_p)) - RT_OFFSETOF(VBOXVR_SCR_COMPOSITOR, Compositor)))
+
+typedef struct VBOXVR_SCR_COMPOSITOR_ITERATOR
+{
+ VBOXVR_COMPOSITOR_ITERATOR Base;
+} VBOXVR_SCR_COMPOSITOR_ITERATOR ,*PVBOXVR_SCR_COMPOSITOR_ITERATOR;
+
+typedef struct VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR
+{
+ VBOXVR_COMPOSITOR_CONST_ITERATOR Base;
+} VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR ,*PVBOXVR_SCR_COMPOSITOR_CONST_ITERATOR;
+
+DECLINLINE(void) CrVrScrCompositorIterInit(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ITERATOR pIter)
+{
+ VBoxVrCompositorIterInit(&pCompositor->Compositor, &pIter->Base);
+}
+
+DECLINLINE(void) CrVrScrCompositorConstIterInit(const VBOXVR_SCR_COMPOSITOR *pCompositor, PVBOXVR_SCR_COMPOSITOR_CONST_ITERATOR pIter)
+{
+ VBoxVrCompositorConstIterInit(&pCompositor->Compositor, &pIter->Base);
+}
+
+DECLINLINE(PVBOXVR_SCR_COMPOSITOR_ENTRY) CrVrScrCompositorIterNext(PVBOXVR_SCR_COMPOSITOR_ITERATOR pIter)
+{
+ PVBOXVR_COMPOSITOR_ENTRY pCe = VBoxVrCompositorIterNext(&pIter->Base);
+ if (pCe)
+ {
+ return VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pCe);
+ }
+ return NULL;
+}
+
+DECLINLINE(const VBOXVR_SCR_COMPOSITOR_ENTRY*) CrVrScrCompositorConstIterNext(PVBOXVR_SCR_COMPOSITOR_CONST_ITERATOR pIter)
+{
+ const VBOXVR_COMPOSITOR_ENTRY *pCe = VBoxVrCompositorConstIterNext(&pIter->Base);
+ if (pCe)
+ {
+ return VBOXVR_SCR_COMPOSITOR_CONST_ENTRY_FROM_ENTRY(pCe);
+ }
+ return NULL;
+}
+
+RT_C_DECLS_END
+
+#endif /* ___cr_compositor_h_ */
diff --git a/src/VBox/GuestHost/OpenGL/include/cr_dump.h b/src/VBox/GuestHost/OpenGL/include/cr_dump.h
new file mode 100644
index 00000000..0946f56e
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/include/cr_dump.h
@@ -0,0 +1,177 @@
+/* $Id: cr_dump.h $ */
+
+/** @file
+ * Debugging: Dump API
+ */
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+#ifndef ___cr_dump_h__
+#define ___cr_dump_h__
+
+/* dump stuff */
+//#define VBOX_WITH_CRDUMPER
+#ifdef VBOX_WITH_CRDUMPER
+
+#include <iprt/cdefs.h>
+#include <iprt/string.h>
+#include <cr_spu.h>
+#include <cr_glstate.h>
+#include <cr_blitter.h>
+
+# define VBOXDUMPDECL(_type) DECLEXPORT(_type)
+
+RT_C_DECLS_BEGIN
+
+#ifdef RT_OS_WINDOWS
+DECLEXPORT(void) crDmpDumpImgDmlBreak(struct CR_DUMPER * pDumper, CR_BLITTER_IMG *pImg, const char*pszEntryDesc);
+
+DECLEXPORT(void) crDmpDumpStrDbgPrint(struct CR_DUMPER * pDumper, const char*pszStr);
+#endif
+
+struct CR_DUMPER;
+
+typedef DECLCALLBACKPTR(void, PFNCRDUMPIMG)(struct CR_DUMPER * pDumper, CR_BLITTER_IMG *pImg, const char*pszEntryDesc);
+typedef DECLCALLBACKPTR(void, PFNCRDUMPSTR)(struct CR_DUMPER * pDumper, const char*pszStr);
+
+typedef struct CR_DUMPER
+{
+ PFNCRDUMPIMG pfnDumpImg;
+ PFNCRDUMPSTR pfnDumpStr;
+} CR_DUMPER;
+
+#define crDmpImg(_pDumper, _pImg, _pDesc) do { \
+ (_pDumper)->pfnDumpImg((_pDumper), (_pImg), (_pDesc)); \
+ } while (0)
+
+#define crDmpStr(_pDumper, _pDesc) do { \
+ (_pDumper)->pfnDumpStr((_pDumper), (_pDesc)); \
+ } while (0)
+
+#ifndef RT_OS_WINDOWS
+# define vsprintf_s vsnprintf
+# define sprintf_s snprintf
+#endif
+
+DECLINLINE(void) crDmpStrV(CR_DUMPER *pDumper, const char *pszStr, va_list pArgList)
+{
+ char szBuffer[4096] = {0};
+ vsprintf_s(szBuffer, sizeof (szBuffer), pszStr, pArgList);
+ crDmpStr(pDumper, szBuffer);
+}
+
+DECLINLINE(void) crDmpStrF(CR_DUMPER *pDumper, const char *pszStr, ...)
+{
+ va_list pArgList;
+ va_start(pArgList, pszStr);
+ crDmpStrV(pDumper, pszStr, pArgList);
+ va_end(pArgList);
+}
+
+DECLINLINE(void) crDmpImgV(CR_DUMPER *pDumper, CR_BLITTER_IMG *pImg, const char *pszStr, va_list pArgList)
+{
+ char szBuffer[4096] = {0};
+ vsprintf_s(szBuffer, sizeof (szBuffer), pszStr, pArgList);
+ crDmpImg(pDumper, pImg, szBuffer);
+}
+
+DECLINLINE(void) crDmpImgF(CR_DUMPER *pDumper, CR_BLITTER_IMG *pImg, const char *pszStr, ...)
+{
+ va_list pArgList;
+ va_start(pArgList, pszStr);
+ crDmpImgV(pDumper, pImg, pszStr, pArgList);
+ va_end(pArgList);
+}
+
+VBOXDUMPDECL(size_t) crDmpFormatArray(char *pString, size_t cbString, const char *pszElFormat, uint32_t cbEl, const void *pVal, uint32_t cVal);
+VBOXDUMPDECL(size_t) crDmpFormatRawArray(char *pString, size_t cbString, const char *pszElFormat, uint32_t cbEl, const void *pVal, uint32_t cVal);
+VBOXDUMPDECL(size_t) crDmpFormatMatrixArray(char *pString, size_t cbString, const char *pszElFormat, uint32_t cbEl, const void *pVal, uint32_t cX, uint32_t cY);
+
+typedef struct CR_DBGPRINT_DUMPER
+{
+ CR_DUMPER Base;
+} CR_DBGPRINT_DUMPER;
+
+typedef struct CR_HTML_DUMPER
+{
+ CR_DUMPER Base;
+ const char* pszFile;
+ const char* pszDir;
+ FILE *pFile;
+ uint32_t cImg;
+} CR_HTML_DUMPER;
+
+DECLEXPORT(bool) crDmpHtmlIsInited(struct CR_HTML_DUMPER * pDumper);
+DECLEXPORT(void) crDmpHtmlTerm(struct CR_HTML_DUMPER * pDumper);
+DECLEXPORT(int) crDmpHtmlInit(struct CR_HTML_DUMPER * pDumper, const char *pszDir, const char *pszFile);
+DECLEXPORT(int) crDmpHtmlInitV(struct CR_HTML_DUMPER * pDumper, const char *pszDir, const char *pszFile, va_list pArgList);
+DECLEXPORT(int) crDmpHtmlInitF(struct CR_HTML_DUMPER * pDumper, const char *pszDir, const char *pszFile, ...);
+
+#ifdef RT_OS_WINDOWS
+DECLINLINE(void) crDmpDbgPrintInit(CR_DBGPRINT_DUMPER *pDumper)
+{
+ pDumper->Base.pfnDumpImg = crDmpDumpImgDmlBreak;
+ pDumper->Base.pfnDumpStr = crDmpDumpStrDbgPrint;
+}
+#endif
+
+typedef struct CR_RECORDER
+{
+ CR_BLITTER *pBlitter;
+ SPUDispatchTable *pDispatch;
+ CR_DUMPER *pDumper;
+} CR_RECORDER;
+
+DECLINLINE(void) crRecInit(CR_RECORDER *pRec, CR_BLITTER *pBlitter, SPUDispatchTable *pDispatch, CR_DUMPER *pDumper)
+{
+ pRec->pBlitter = pBlitter;
+ pRec->pDispatch = pDispatch;
+ pRec->pDumper = pDumper;
+}
+
+VBOXDUMPDECL(void) crRecDumpBuffer(CR_RECORDER *pRec, CRContext *ctx, CR_BLITTER_CONTEXT *pCurCtx, CR_BLITTER_WINDOW *pCurWin, GLint idRedirFBO, VBOXVR_TEXTURE *pRedirTex);
+VBOXDUMPDECL(void) crRecDumpTextures(CR_RECORDER *pRec, CRContext *ctx, CR_BLITTER_CONTEXT *pCurCtx, CR_BLITTER_WINDOW *pCurWin);
+VBOXDUMPDECL(void) crRecDumpTextureV(CR_RECORDER *pRec, const VBOXVR_TEXTURE *pTex, CR_BLITTER_CONTEXT *pCurCtx, CR_BLITTER_WINDOW *pCurWin, const char *pszStr, va_list pArgList);
+VBOXDUMPDECL(void) crRecDumpTextureF(CR_RECORDER *pRec, const VBOXVR_TEXTURE *pTex, CR_BLITTER_CONTEXT *pCurCtx, CR_BLITTER_WINDOW *pCurWin, const char *pszStr, ...);
+VBOXDUMPDECL(void) crRecDumpTextureByIdV(CR_RECORDER *pRec, CRContext *ctx, GLint id, CR_BLITTER_CONTEXT *pCurCtx, CR_BLITTER_WINDOW *pCurWin, const char *pszStr, va_list pArgList);
+VBOXDUMPDECL(void) crRecDumpTextureByIdF(CR_RECORDER *pRec, CRContext *ctx, GLint id, CR_BLITTER_CONTEXT *pCurCtx, CR_BLITTER_WINDOW *pCurWin, const char *pszStr, ...);
+VBOXDUMPDECL(void) crRecDumpShader(CR_RECORDER *pRec, CRContext *ctx, GLint id, GLint hwid);
+VBOXDUMPDECL(void) crRecDumpProgram(CR_RECORDER *pRec, CRContext *ctx, GLint id, GLint hwid);
+VBOXDUMPDECL(void) crRecRecompileShader(CR_RECORDER *pRec, CRContext *ctx, GLint id, GLint hwid);
+VBOXDUMPDECL(void) crRecRecompileProgram(CR_RECORDER *pRec, CRContext *ctx, GLint id, GLint hwid);
+VBOXDUMPDECL(void) crRecDumpCurrentProgram(CR_RECORDER *pRec, CRContext *ctx);
+VBOXDUMPDECL(void) crRecDumpProgramUniforms(CR_RECORDER *pRec, CRContext *ctx, GLint id, GLint hwid);
+VBOXDUMPDECL(void) crRecDumpCurrentProgramUniforms(CR_RECORDER *pRec, CRContext *ctx);
+VBOXDUMPDECL(void) crRecRecompileCurrentProgram(CR_RECORDER *pRec, CRContext *ctx);
+VBOXDUMPDECL(void) crRecDumpProgramAttribs(CR_RECORDER *pRec, CRContext *ctx, GLint id, GLint hwid);
+VBOXDUMPDECL(void) crRecDumpCurrentProgramAttribs(CR_RECORDER *pRec, CRContext *ctx);
+VBOXDUMPDECL(void) crRecDumpGlGetState(CR_RECORDER *pRec, CRContext *ctx);
+VBOXDUMPDECL(void) crRecDumpGlEnableState(CR_RECORDER *pRec, CRContext *ctx);
+VBOXDUMPDECL(void) crRecDumpVertAttrv(CR_RECORDER *pRec, CRContext *ctx, GLuint idx, const char*pszElFormat, uint32_t cbEl, const void *pvVal, uint32_t cVal);
+VBOXDUMPDECL(void) crRecDumpVertAttrF(CR_RECORDER *pRec, CRContext *ctx, const char*pszFormat, ...);
+VBOXDUMPDECL(void) crRecDumpVertAttrV(CR_RECORDER *pRec, CRContext *ctx, const char*pszFormat, va_list pArgList);
+VBOXDUMPDECL(void) crRecDumpTexParam(CR_RECORDER *pRec, CRContext *ctx, GLenum enmTarget);
+VBOXDUMPDECL(void) crRecDumpTexEnv(CR_RECORDER *pRec, CRContext *ctx);
+VBOXDUMPDECL(void) crRecDumpTexGen(CR_RECORDER *pRec, CRContext *ctx);
+
+VBOXDUMPDECL(int) crRecAlphaImgCreate(const CR_BLITTER_IMG *pImg, CR_BLITTER_IMG *pAlphaImg);
+VBOXDUMPDECL(void) crRecAlphaImgDestroy(CR_BLITTER_IMG *pImg);
+
+
+typedef DECLCALLBACKPTR(GLuint, PFNCRDUMPGETHWID)(void *pvObj);
+void* crDmpHashtableSearchByHwid(CRHashTable *pHash, GLuint hwid, PFNCRDUMPGETHWID pfnGetHwid, unsigned long *pKey);
+
+RT_C_DECLS_END
+
+#endif /* VBOX_WITH_CRDUMPER */
+/* */
+
+#endif /* #ifndef ___cr_dump_h__ */
diff --git a/src/VBox/GuestHost/OpenGL/include/cr_error.h b/src/VBox/GuestHost/OpenGL/include/cr_error.h
index a73a47bc..ca472d28 100644
--- a/src/VBox/GuestHost/OpenGL/include/cr_error.h
+++ b/src/VBox/GuestHost/OpenGL/include/cr_error.h
@@ -24,10 +24,29 @@ extern "C" {
#define PRINTF
#endif
+#ifndef WARN
+# ifndef IN_RING0
+# define LOG(_m) do { crDebug _m ; } while (0)
+# define LOGREL(_m) do { crDebug _m ; } while (0)
+# define WARN(_m) do { crWarning _m ; AssertMsgFailed(_m); } while (0)
+# else
+# define LOG(_m) do { } while (0)
+# define LOGREL(_m) do { } while (0)
+# define WARN(_m) do { AssertMsgFailed(_m); } while (0)
+# endif
+#endif
+
DECLEXPORT(void) crEnableWarnings(int onOff);
DECLEXPORT(void) crDebug(const char *format, ... ) PRINTF;
+#if defined(DEBUG_misha) && defined(RT_OS_WINDOWS)
+typedef void FNCRDEBUG(const char *format, ... ) PRINTF;
+typedef FNCRDEBUG *PFNCRDEBUG;
+DECLINLINE(PFNCRDEBUG) crGetDebug() {return crDebug;}
+# define crWarning (RT_BREAKPOINT(), crDebug)
+#else
DECLEXPORT(void) crWarning(const char *format, ... ) PRINTF;
+#endif
DECLEXPORT(void) crInfo(const char *format, ... ) PRINTF;
DECLEXPORT(void) crError(const char *format, ... ) NORETURN_PRINTF;
diff --git a/src/VBox/GuestHost/OpenGL/include/cr_extstring.h b/src/VBox/GuestHost/OpenGL/include/cr_extstring.h
index 1d894983..5940379e 100644
--- a/src/VBox/GuestHost/OpenGL/include/cr_extstring.h
+++ b/src/VBox/GuestHost/OpenGL/include/cr_extstring.h
@@ -237,6 +237,10 @@ static const char *crExtensions =
#ifdef CR_EXT_stencil_two_side
"GL_EXT_stencil_two_side "
#endif
+#ifdef CR_GREMEDY_string_marker
+ "GL_GREMEDY_string_marker "
+#endif
+
"";
/*
diff --git a/src/VBox/GuestHost/OpenGL/include/cr_glext.h b/src/VBox/GuestHost/OpenGL/include/cr_glext.h
new file mode 100644
index 00000000..429e218c
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/include/cr_glext.h
@@ -0,0 +1,34 @@
+/* $Id: cr_glext.h $ */
+
+/** @file
+ * GL chromium platform specifics
+ */
+/*
+ * Copyright (C) 2014 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+#ifndef ___cr_glext_h__
+#define ___cr_glext_h__
+
+#include <iprt/assert.h>
+
+#ifndef __glext_h_
+/* glext NOT included yet */
+# include "GL/glext.h"
+#else
+/* glext IS included yet */
+# ifndef RT_OS_DARWIN
+typedef unsigned int VBoxGLhandleARB; /* shader object handle */
+AssertCompile(sizeof (VBoxGLhandleARB) == sizeof (GLhandleARB));
+# else
+# error "patched glext is required for OSX!"
+# endif
+#endif
+#endif /*___cr_glext_h__*/
diff --git a/src/VBox/GuestHost/OpenGL/include/cr_glstate.h b/src/VBox/GuestHost/OpenGL/include/cr_glstate.h
index fd82b576..95b3477d 100644
--- a/src/VBox/GuestHost/OpenGL/include/cr_glstate.h
+++ b/src/VBox/GuestHost/OpenGL/include/cr_glstate.h
@@ -51,20 +51,19 @@ typedef struct CRContext CRContext;
#include <iprt/cdefs.h>
-#ifndef IN_GUEST
# include <VBox/vmm/ssm.h>
# include <iprt/asm.h>
# define CR_STATE_SHAREDOBJ_USAGE_INIT(_pObj) (crMemset((_pObj)->ctxUsage, 0, sizeof ((_pObj)->ctxUsage)))
# define CR_STATE_SHAREDOBJ_USAGE_SET(_pObj, _pCtx) (ASMBitSet((_pObj)->ctxUsage, (_pCtx)->id))
-# define CR_STATE_SHAREDOBJ_USAGE_CLEAR(_pObj, _pCtx) (ASMBitClear((_pObj)->ctxUsage, (_pCtx)->id))
+# define CR_STATE_SHAREDOBJ_USAGE_IS_SET(_pObj, _pCtx) (ASMBitTest((_pObj)->ctxUsage, (_pCtx)->id))
+# define CR_STATE_SHAREDOBJ_USAGE_CLEAR_IDX(_pObj, _i) (ASMBitClear((_pObj)->ctxUsage, (_i)))
+# define CR_STATE_SHAREDOBJ_USAGE_CLEAR(_pObj, _pCtx) (CR_STATE_SHAREDOBJ_USAGE_CLEAR_IDX((_pObj), (_pCtx)->id))
# define CR_STATE_SHAREDOBJ_USAGE_IS_USED(_pObj) (ASMBitFirstSet((_pObj)->ctxUsage, sizeof ((_pObj)->ctxUsage)<<3) >= 0)
-#else
-# define CR_STATE_SHAREDOBJ_USAGE_INIT(_pObj) do {} while (0)
-# define CR_STATE_SHAREDOBJ_USAGE_SET(_pObj, _pCtx) do {} while (0)
-# define CR_STATE_SHAREDOBJ_USAGE_CLEAR(_pObj, _pCtx) do {} while (0)
-# define CR_STATE_SHAREDOBJ_USAGE_IS_USED(_pObj) (GL_FALSE)
-#endif
+# define CR_STATE_SHAREDOBJ_USAGE_GET_FIRST_USED_IDX(_pObj) (ASMBitFirstSet((_pObj)->ctxUsage, sizeof ((_pObj)->ctxUsage)<<3))
+# define CR_STATE_SHAREDOBJ_USAGE_GET_NEXT_USED_IDX(_pObj, _i) (ASMBitNextSet((_pObj)->ctxUsage, sizeof ((_pObj)->ctxUsage)<<3, (_i)))
+
+# define CR_STATE_SHAREDOBJ_USAGE_FOREACH_USED_IDX(_pObj, _i) for ((_i) = CR_STATE_SHAREDOBJ_USAGE_GET_FIRST_USED_IDX(_pObj); ((int)(_i)) >= 0; (_i) = CR_STATE_SHAREDOBJ_USAGE_GET_NEXT_USED_IDX((_pObj), ((int)(_i))))
#define CR_MAX_EXTENTS 256
@@ -218,8 +217,10 @@ DECLEXPORT(CRContext *) crStateGetCurrent(void);
DECLEXPORT(void) crStateDestroyContext(CRContext *ctx);
DECLEXPORT(GLboolean) crStateEnableDiffOnMakeCurrent(GLboolean fEnable);
-CRContext * crStateSwichPrepare(CRContext *toCtx, GLboolean fMultipleContexts, GLuint idFBO);
-void crStateSwichPostprocess(CRContext *fromCtx, GLboolean fMultipleContexts, GLuint idFBO);
+void crStateSwitchPrepare(CRContext *toCtx, CRContext *fromCtx, GLuint idDrawFBO, GLuint idReadFBO);
+void crStateSwitchPostprocess(CRContext *toCtx, CRContext *fromCtx, GLuint idDrawFBO, GLuint idReadFBO);
+
+void crStateSyncHWErrorState(CRContext *ctx);
DECLEXPORT(void) crStateFlushFunc( CRStateFlushFunc ff );
DECLEXPORT(void) crStateFlushArg( void *arg );
@@ -233,15 +234,53 @@ DECLEXPORT(void) crStateSetExtensionString( CRContext *ctx, const GLubyte *exten
DECLEXPORT(void) crStateDiffContext( CRContext *from, CRContext *to );
DECLEXPORT(void) crStateSwitchContext( CRContext *from, CRContext *to );
-DECLEXPORT(void) crStateApplyFBImage(CRContext *to);
+
+DECLEXPORT(unsigned int) crStateHlpComponentsCount( GLenum pname );
+
+typedef struct CRFBDataElement
+{
+ /* FBO, can be NULL */
+ GLint idFBO;
+ /* to be used for glDraw/ReadBuffer, i.e. GL_FRONT, GL_BACK, GL_COLOR_ATTACHMENTX */
+ GLenum enmBuffer;
+ GLint posX;
+ GLint posY;
+ GLint width;
+ GLint height;
+ GLenum enmFormat;
+ GLenum enmType;
+ GLuint cbData;
+ GLvoid *pvData;
+} CRFBDataElement;
+
+typedef struct CRFBData
+{
+ /* override default draw and read buffers to be used for offscreen rendering */
+ GLint idOverrrideFBO;
+ uint32_t cElements;
+ CRFBDataElement aElements[1];
+} CRFBData;
+
+DECLEXPORT(void) crStateApplyFBImage(CRContext *to, CRFBData *data);
+DECLEXPORT(int) crStateAcquireFBImage(CRContext *to, CRFBData *data);
+DECLEXPORT(void) crStateFreeFBImageLegacy(CRContext *to);
+
+DECLEXPORT(void) crStateGetTextureObjectAndImage(CRContext *g, GLenum texTarget, GLint level,
+ CRTextureObj **obj, CRTextureLevel **img);
+
#ifndef IN_GUEST
DECLEXPORT(int32_t) crStateSaveContext(CRContext *pContext, PSSMHANDLE pSSM);
typedef DECLCALLBACK(CRContext*) FNCRSTATE_CONTEXT_GET(void*);
typedef FNCRSTATE_CONTEXT_GET *PFNCRSTATE_CONTEXT_GET;
DECLEXPORT(int32_t) crStateLoadContext(CRContext *pContext, CRHashTable * pCtxTable, PFNCRSTATE_CONTEXT_GET pfnCtxGet, PSSMHANDLE pSSM, uint32_t u32Version);
-DECLEXPORT(void) crStateFreeShared(CRContext *pContext, CRSharedState *s);
DECLEXPORT(void) crStateFreeShared(CRContext *pContext, CRSharedState *s);
+
+DECLEXPORT(int32_t) crStateLoadGlobals(PSSMHANDLE pSSM, uint32_t u32Version);
+DECLEXPORT(int32_t) crStateSaveGlobals(PSSMHANDLE pSSM);
+
+DECLEXPORT(CRSharedState *) crStateGlobalSharedAcquire();
+DECLEXPORT(void) crStateGlobalSharedRelease();
#endif
DECLEXPORT(void) crStateSetTextureUsed(GLuint texture, GLboolean used);
@@ -270,7 +309,7 @@ DECLEXPORT(void) STATE_APIENTRY crStateShareContext(GLboolean value);
DECLEXPORT(void) STATE_APIENTRY crStateSetSharedContext(CRContext *pCtx);
DECLEXPORT(GLboolean) STATE_APIENTRY crStateContextIsShared(CRContext *pCtx);
-DECLEXPORT(void) STATE_APIENTRY crStateQueryHWState();
+DECLEXPORT(void) STATE_APIENTRY crStateQueryHWState(GLuint fbFbo, GLuint bbFbo);
#ifdef __cplusplus
}
#endif
diff --git a/src/VBox/GuestHost/OpenGL/include/cr_hash.h b/src/VBox/GuestHost/OpenGL/include/cr_hash.h
index 9bda7454..0f28c798 100644
--- a/src/VBox/GuestHost/OpenGL/include/cr_hash.h
+++ b/src/VBox/GuestHost/OpenGL/include/cr_hash.h
@@ -15,17 +15,36 @@
extern "C" {
#endif
+typedef struct CRHashIdPool CRHashIdPool;
typedef struct CRHashTable CRHashTable;
/* Callback function used for freeing/deleting table entries */
typedef void (*CRHashtableCallback)(void *data);
/* Callback function used for walking through table entries */
typedef void (*CRHashtableWalkCallback)(unsigned long key, void *data1, void *data2);
+/* Callback function used for walking through allocated keys */
+typedef void (*CRHashIdWalkKeys)(unsigned long firstKey, unsigned long count, void *data);
+
+DECLEXPORT(CRHashIdPool *) crAllocHashIdPool( void );
+DECLEXPORT(CRHashIdPool *) crAllocHashIdPoolEx( GLuint min, GLuint max );
+DECLEXPORT(void) crFreeHashIdPool( CRHashIdPool *pool );
+DECLEXPORT(GLboolean) crHashIdPoolIsIdFree( const CRHashIdPool *pool, GLuint id );
+DECLEXPORT(GLuint) crHashIdPoolAllocBlock( CRHashIdPool *pool, GLuint count );
+DECLEXPORT(void) crHashIdPoolFreeBlock( CRHashIdPool *pool, GLuint first, GLuint count );
+/* @return GL_TRUE if the id is allocated, and GL_FALSE if the id was already allocated */
+DECLEXPORT(GLboolean) crHashIdPoolAllocId( CRHashIdPool *pool, GLuint id );
+DECLEXPORT(void) crHashIdWalkKeys( CRHashIdPool *pool, CRHashIdWalkKeys walkFunc , void *data);
DECLEXPORT(CRHashTable *) crAllocHashtable( void );
+DECLEXPORT(CRHashTable *) crAllocHashtableEx( GLuint min, GLuint max );
DECLEXPORT(void) crFreeHashtable( CRHashTable *hash, CRHashtableCallback deleteCallback );
DECLEXPORT(void) crHashtableAdd( CRHashTable *h, unsigned long key, void *data );
+/* to ensure hash table pool id consistency, there is no crHashTableFreeKeys/UnregisterKey,
+ * one should call crHashtableDelete to free unneeded keys,
+ * which will also ensure there is no entry with the specified key left in the table */
DECLEXPORT(GLuint) crHashtableAllocKeys( CRHashTable *h, GLsizei range );
+/* @return GL_TRUE if the id is allocated, and GL_FALSE if the id was already allocated */
+DECLEXPORT(GLboolean) crHashtableAllocRegisterKey( CRHashTable *h, GLuint key);
DECLEXPORT(void) crHashtableDelete( CRHashTable *h, unsigned long key, CRHashtableCallback deleteCallback );
DECLEXPORT(void) crHashtableDeleteBlock( CRHashTable *h, unsigned long key, GLsizei range, CRHashtableCallback deleteFunc );
DECLEXPORT(void *) crHashtableSearch( const CRHashTable *h, unsigned long key );
@@ -33,10 +52,13 @@ DECLEXPORT(void) crHashtableReplace( CRHashTable *h, unsigned long key, void *da
DECLEXPORT(unsigned int) crHashtableNumElements( const CRHashTable *h) ;
DECLEXPORT(GLboolean) crHashtableIsKeyUsed( const CRHashTable *h, GLuint id );
DECLEXPORT(void) crHashtableWalk( CRHashTable *hash, CRHashtableWalkCallback walkFunc , void *data);
+/* walk the hashtable w/o holding the table lock */
+DECLEXPORT(void) crHashtableWalkUnlocked( CRHashTable *hash, CRHashtableWalkCallback walkFunc , void *data);
/*Returns GL_TRUE if given hashtable hold the data, pKey is updated with key value for data in this case*/
DECLEXPORT(GLboolean) crHashtableGetDataKey(CRHashTable *pHash, void *pData, unsigned long *pKey);
DECLEXPORT(void) crHashtableLock(CRHashTable *h);
DECLEXPORT(void) crHashtableUnlock(CRHashTable *h);
+DECLEXPORT(void) crHashtableWalkKeys(CRHashTable *hash, CRHashIdWalkKeys walkFunc , void *data);
#ifdef __cplusplus
} /* extern "C" */
diff --git a/src/VBox/GuestHost/OpenGL/include/cr_htable.h b/src/VBox/GuestHost/OpenGL/include/cr_htable.h
new file mode 100644
index 00000000..26c8bffd
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/include/cr_htable.h
@@ -0,0 +1,120 @@
+/* $Id: cr_htable.h $ */
+
+/** @file
+ * uint32_t handle to void simple table API
+ */
+
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+#ifndef ___cr_htable_h_
+#define ___cr_htable_h_
+
+#include <iprt/types.h>
+#include <iprt/cdefs.h>
+
+#include <cr_error.h>
+
+#ifndef IN_RING0
+# define VBOXHTABLEDECL(_type) DECLEXPORT(_type)
+#else
+# define VBOXHTABLEDECL(_type) RTDECL(_type)
+#endif
+
+
+
+RT_C_DECLS_BEGIN
+
+typedef uint32_t CRHTABLE_HANDLE;
+#define CRHTABLE_HANDLE_INVALID 0UL
+
+typedef struct CRHTABLE
+{
+ uint32_t cData;
+ uint32_t iNext2Search;
+ uint32_t cSize;
+ void **paData;
+} CRHTABLE, *PCRHTABLE;
+
+typedef struct CRHTABLE_ITERATOR
+{
+ PCRHTABLE pTbl;
+ uint32_t iCur;
+ uint32_t cLeft;
+} VCRHTABLE_ITERATOR, *PCRHTABLE_ITERATOR;
+
+/*private stuff, not to be used directly */
+DECLINLINE(CRHTABLE_HANDLE) crHTableIndex2Handle(uint32_t iIndex)
+{
+ return iIndex+1;
+}
+
+DECLINLINE(uint32_t) crHTableHandle2Index(CRHTABLE_HANDLE hHandle)
+{
+ return hHandle-1;
+}
+
+/* public API */
+DECLINLINE(void) CrHTableIterInit(PCRHTABLE pTbl, PCRHTABLE_ITERATOR pIter)
+{
+ pIter->pTbl = pTbl;
+ pIter->iCur = 0;
+ pIter->cLeft = pTbl->cData;
+}
+
+DECLINLINE(void*) CrHTableIterNext(PCRHTABLE_ITERATOR pIter, CRHTABLE_HANDLE *phHandle)
+{
+ PCRHTABLE pTbl;
+ uint32_t i;
+ if (!pIter->cLeft)
+ {
+ if (phHandle)
+ *phHandle = 0;
+ return NULL;
+ }
+
+ pTbl = pIter->pTbl;
+
+ for (i = pIter->iCur; i < pTbl->cSize; ++i)
+ {
+ if (pTbl->paData[i])
+ {
+ pIter->iCur = i+1;
+ --(pIter->cLeft);
+ if (phHandle)
+ *phHandle = crHTableIndex2Handle(i);
+ return pTbl->paData[i];
+ }
+ }
+
+ crWarning("interator concurent modification!");
+ return NULL;
+}
+
+VBOXHTABLEDECL(int) CrHTableCreate(PCRHTABLE pTbl, uint32_t cSize);
+DECLINLINE(void) CrHTableMoveTo(PCRHTABLE pSrcTbl, PCRHTABLE pDstTbl)
+{
+ *pDstTbl = *pSrcTbl;
+ CrHTableCreate(pSrcTbl, 0);
+}
+VBOXHTABLEDECL(void) CrHTableEmpty(PCRHTABLE pTbl);
+VBOXHTABLEDECL(void) CrHTableDestroy(PCRHTABLE pTbl);
+VBOXHTABLEDECL(int) CrHTableRealloc(PCRHTABLE pTbl, uint32_t cNewSize);
+VBOXHTABLEDECL(CRHTABLE_HANDLE) CrHTablePut(PCRHTABLE pTbl, void *pvData);
+VBOXHTABLEDECL(int) CrHTablePutToSlot(PCRHTABLE pTbl, CRHTABLE_HANDLE hHandle, void* pvData);
+
+/* note: can be called for the element returned with CrHTableIterNext w/o corrupting the iterator */
+VBOXHTABLEDECL(void*) CrHTableRemove(PCRHTABLE pTbl, CRHTABLE_HANDLE hHandle);
+VBOXHTABLEDECL(void*) CrHTableGet(PCRHTABLE pTbl, CRHTABLE_HANDLE hHandle);
+
+RT_C_DECLS_END
+
+#endif /* #ifndef ___cr_htable_h_*/
diff --git a/src/VBox/GuestHost/OpenGL/include/cr_pack.h b/src/VBox/GuestHost/OpenGL/include/cr_pack.h
index 82f7d5d7..3f7f930e 100644
--- a/src/VBox/GuestHost/OpenGL/include/cr_pack.h
+++ b/src/VBox/GuestHost/OpenGL/include/cr_pack.h
@@ -117,7 +117,11 @@ extern DECLEXPORT(void) crPackResetPointers( CRPackContext *pc );
extern DECLEXPORT(int) crPackMaxOpcodes( int buffer_size );
extern DECLEXPORT(int) crPackMaxData( int buffer_size );
-extern DECLEXPORT(void) crPackInitBuffer( CRPackBuffer *buffer, void *buf, int size, int mtu );
+extern DECLEXPORT(void) crPackInitBuffer( CRPackBuffer *buffer, void *buf, int size, int mtu
+#ifdef IN_RING0
+ , unsigned int num_opcodes
+#endif
+ );
extern DECLEXPORT(void) crPackFlushFunc( CRPackContext *pc, CRPackFlushFunc ff );
extern DECLEXPORT(void) crPackFlushArg( CRPackContext *pc, void *flush_arg );
extern DECLEXPORT(void) crPackSendHugeFunc( CRPackContext *pc, CRPackSendHugeFunc shf );
@@ -140,8 +144,10 @@ extern DECLEXPORT(int) crPackCanHoldBoundedBuffer( CR_PACKER_CONTEXT_ARGDECL con
#else
#undef CR_UNALIGNED_ACCESS_OKAY
#endif
+#ifndef IN_RING0
extern DECLEXPORT(void) crWriteUnalignedDouble( void *buffer, double d );
extern DECLEXPORT(void) crWriteSwappedDouble( void *buffer, double d );
+#endif
extern DECLEXPORT(void) *crPackAlloc( CR_PACKER_CONTEXT_ARGDECL unsigned int len );
extern DECLEXPORT(void) crHugePacket( CR_PACKER_CONTEXT_ARGDECL CROpcode op, void *ptr );
@@ -304,12 +310,22 @@ crPackCanHoldOpcode(const CRPackContext *pc, int num_opcode, int num_data)
#define WRITE_DOUBLE( offset, data ) \
WRITE_DATA( offset, GLdouble, data )
#else
-#define WRITE_DOUBLE( offset, data ) \
- crWriteUnalignedDouble( data_ptr + (offset), (data) )
+# ifndef IN_RING0
+# define WRITE_DOUBLE( offset, data ) \
+ crWriteUnalignedDouble( data_ptr + (offset), (data) )
+# else
+# define WRITE_DOUBLE( offset, data ) \
+ AssertReleaseFailed()
+# endif
#endif
+#ifndef IN_RING0
#define WRITE_SWAPPED_DOUBLE( offset, data ) \
crWriteSwappedDouble( data_ptr + (offset), (data) )
+#else
+#define WRITE_SWAPPED_DOUBLE( offset, data ) \
+ AssertReleaseFailed()
+#endif
#define WRITE_OPCODE( pc, opcode ) \
*(pc->buffer.opcode_current--) = (unsigned char) opcode
diff --git a/src/VBox/GuestHost/OpenGL/include/cr_pixeldata.h b/src/VBox/GuestHost/OpenGL/include/cr_pixeldata.h
index 9b194eef..da3ebe34 100644
--- a/src/VBox/GuestHost/OpenGL/include/cr_pixeldata.h
+++ b/src/VBox/GuestHost/OpenGL/include/cr_pixeldata.h
@@ -11,6 +11,7 @@
#include "state/cr_client.h"
#include <iprt/cdefs.h>
+#include <stdarg.h>
#ifdef __cplusplus
extern "C" {
@@ -43,6 +44,8 @@ DECLEXPORT(void) crBitmapCopy( GLsizei width, GLsizei height, GLubyte *dstPtr,
const GLubyte *srcPtr, const CRPixelPackState *srcPacking );
DECLEXPORT(void) crDumpNamedTGA(const char *fname, GLint w, GLint h, GLvoid *data);
+DECLEXPORT(void) crDumpNamedTGAV(GLint w, GLint h, GLvoid *data, const char* fname, va_list va);
+DECLEXPORT(void) crDumpNamedTGAF(GLint w, GLint h, GLvoid *data, const char* fname, ...);
DECLEXPORT(void) crDumpTGA(GLint w, GLint h, GLvoid *data);
#ifdef __cplusplus
}
diff --git a/src/VBox/GuestHost/OpenGL/include/cr_protocol.h b/src/VBox/GuestHost/OpenGL/include/cr_protocol.h
index 5e24f207..1bf785ba 100644
--- a/src/VBox/GuestHost/OpenGL/include/cr_protocol.h
+++ b/src/VBox/GuestHost/OpenGL/include/cr_protocol.h
@@ -7,6 +7,7 @@
#ifndef CR_PROTOCOL_H
#define CR_PROTOCOL_H
+#include <iprt/types.h>
#include <iprt/cdefs.h>
#ifdef DEBUG_misha
#include "cr_error.h"
@@ -21,6 +22,23 @@ extern "C" {
#define CR_PROTOCOL_VERSION_MAJOR 9
#define CR_PROTOCOL_VERSION_MINOR 1
+/* new TexPresent mechanism is available */
+#define CR_VBOX_CAP_TEX_PRESENT 0x00000001
+/* vbva command submission mechanism supported */
+#define CR_VBOX_CAP_CMDVBVA 0x00000002
+
+
+#define CR_PRESENT_SCREEN_MASK 0xffff
+#define CR_PRESENT_FLAGS_OFFSET 16
+#define CR_PRESENT_FLAGS_MASK 0xffff0000
+#define CR_PRESENT_DEFINE_FLAG(_f) (1 << (CR_PRESENT_FLAGS_OFFSET + _f))
+
+#define CR_PRESENT_FLAG_CLEAR_RECTS CR_PRESENT_DEFINE_FLAG(0)
+#define CR_PRESENT_FLAG_TEX_NONINVERT_YCOORD CR_PRESENT_DEFINE_FLAG(1)
+
+#define CR_PRESENT_GET_SCREEN(_cfg) ((_cfg) & CR_PRESENT_SCREEN_MASK)
+#define CR_PRESENT_GET_FLAGS(_cfg) ((_cfg) & CR_PRESENT_FLAGS_MASK)
+
typedef enum {
/* first message types is 'wGL\001', so we can immediately
recognize bad message types */
@@ -51,7 +69,7 @@ typedef union {
/* unsigned int junk[512]; */
} CRNetworkPointer;
-#ifdef DEBUG_misha
+#if 0 //def DEBUG_misha
#define CRDBGPTR_SETZ(_p) crMemset((_p), 0, sizeof (CRNetworkPointer))
#define CRDBGPTR_CHECKZ(_p) do { \
CRNetworkPointer _ptr = {0}; \
@@ -80,26 +98,32 @@ typedef union {
#ifdef VBOX_WITH_CRHGSMI
typedef struct CRVBOXHGSMI_CMDDATA {
- struct VBOXVDMACMD_CHROMIUM_CMD *pCmd;
+ union
+ {
+ struct VBOXVDMACMD_CHROMIUM_CMD *pHgsmiCmd;
+ struct VBOXCMDVBVA_CRCMD_CMD *pVbvaCmd;
+ void *pvCmd;
+ };
int *pCmdRc;
char *pWriteback;
unsigned int *pcbWriteback;
unsigned int cbWriteback;
+ bool fHgsmiCmd;
} CRVBOXHGSMI_CMDDATA, *PCRVBOXHGSMI_CMDDATA;
#ifdef DEBUG
# define CRVBOXHGSMI_CMDDATA_ASSERT_CONSISTENT(_pData) do { \
- CRASSERT(!(_pData)->pCmd == !(_pData)->pCmdRc); \
+ CRASSERT(!(_pData)->pvCmd == !(_pData)->pCmdRc); \
CRASSERT(!(_pData)->pWriteback == !(_pData)->pcbWriteback); \
CRASSERT(!(_pData)->pWriteback == !(_pData)->cbWriteback); \
if ((_pData)->pWriteback) \
{ \
- CRASSERT((_pData)->pCmd); \
+ CRASSERT((_pData)->pvCmd); \
} \
} while (0)
# define CRVBOXHGSMI_CMDDATA_ASSERT_CLEANED(_pData) do { \
- CRASSERT(!(_pData)->pCmd); \
+ CRASSERT(!(_pData)->pvCmd); \
CRASSERT(!(_pData)->pCmdRc); \
CRASSERT(!(_pData)->pWriteback); \
CRASSERT(!(_pData)->pcbWriteback); \
@@ -122,7 +146,8 @@ typedef struct CRVBOXHGSMI_CMDDATA {
# define CRVBOXHGSMI_CMDDATA_ASSERT_ISSETWB(_pData) do { } while (0)
#endif
-#define CRVBOXHGSMI_CMDDATA_IS_SET(_pData) (!!(_pData)->pCmd)
+#define CRVBOXHGSMI_CMDDATA_IS_HGSMICMD(_pData) (!!(_pData)->fHgsmiCmd)
+#define CRVBOXHGSMI_CMDDATA_IS_SET(_pData) (!!(_pData)->pvCmd)
#define CRVBOXHGSMI_CMDDATA_IS_SETWB(_pData) (!!(_pData)->pWriteback)
#define CRVBOXHGSMI_CMDDATA_CLEANUP(_pData) do { \
@@ -131,15 +156,16 @@ typedef struct CRVBOXHGSMI_CMDDATA {
CRVBOXHGSMI_CMDDATA_ASSERT_CONSISTENT(_pData); \
} while (0)
-#define CRVBOXHGSMI_CMDDATA_SET(_pData, _pCmd, _pHdr) do { \
+#define CRVBOXHGSMI_CMDDATA_SET(_pData, _pCmd, _pHdr, _fHgsmiCmd) do { \
CRVBOXHGSMI_CMDDATA_ASSERT_CLEANED(_pData); \
- (_pData)->pCmd = (_pCmd); \
+ (_pData)->pvCmd = (_pCmd); \
(_pData)->pCmdRc = &(_pHdr)->result; \
+ (_pData)->fHgsmiCmd = (_fHgsmiCmd); \
CRVBOXHGSMI_CMDDATA_ASSERT_CONSISTENT(_pData); \
} while (0)
-#define CRVBOXHGSMI_CMDDATA_SETWB(_pData, _pCmd, _pHdr, _pWb, _cbWb, _pcbWb) do { \
- CRVBOXHGSMI_CMDDATA_SET(_pData, _pCmd, _pHdr); \
+#define CRVBOXHGSMI_CMDDATA_SETWB(_pData, _pCmd, _pHdr, _pWb, _cbWb, _pcbWb, _fHgsmiCmd) do { \
+ CRVBOXHGSMI_CMDDATA_SET(_pData, _pCmd, _pHdr, _fHgsmiCmd); \
(_pData)->pWriteback = (_pWb); \
(_pData)->pcbWriteback = (_pcbWb); \
(_pData)->cbWriteback = (_cbWb); \
diff --git a/src/VBox/GuestHost/OpenGL/include/cr_server.h b/src/VBox/GuestHost/OpenGL/include/cr_server.h
index 027354a2..b215d4cb 100644
--- a/src/VBox/GuestHost/OpenGL/include/cr_server.h
+++ b/src/VBox/GuestHost/OpenGL/include/cr_server.h
@@ -12,19 +12,28 @@
#include "cr_hash.h"
#include "cr_protocol.h"
#include "cr_glstate.h"
+#include "cr_vreg.h"
+#include "cr_blitter.h"
#include "spu_dispatch_table.h"
+#include "cr_dump.h"
#include "state/cr_currentpointers.h"
#include <iprt/types.h>
#include <iprt/err.h>
#include <iprt/string.h>
+#include <iprt/list.h>
+#include <iprt/thread.h>
+#include <iprt/critsect.h>
+#include <iprt/semaphore.h>
+#include <iprt/memcache.h>
#include <VBox/vmm/ssm.h>
-#ifdef VBOX_WITH_CRHGSMI
-# include <VBox/VBoxVideo.h>
-#endif
+#include <VBox/VBoxVideo.h>
+#include <VBox/Hardware/VBoxVideoVBE.h>
+#include <VBox/VBoxVideo3D.h>
+#include <VBox/VBoxVideoHost3D.h>
#ifdef __cplusplus
extern "C" {
@@ -34,7 +43,7 @@ extern "C" {
#define CR_MAX_CLIENTS 64
/*@todo must match MaxGuestMonitors from SchemaDefs.h*/
-#define CR_MAX_GUEST_MONITORS 8
+#define CR_MAX_GUEST_MONITORS VBOX_VIDEO_MAX_SCREENS
typedef DECLCALLBACKPTR(void, PFNCRSERVERPRESENTFBO) (void *data, int32_t screenId, int32_t x, int32_t y, uint32_t w, uint32_t h);
@@ -54,7 +63,7 @@ typedef struct {
DECLR3CALLBACKMEMBER(void, CRORGeometry, (void *pvInstance,
int32_t x, int32_t y, uint32_t w, uint32_t h));
DECLR3CALLBACKMEMBER(void, CRORVisibleRegion, (void *pvInstance,
- uint32_t cRects, RTRECT *paRects));
+ uint32_t cRects, const RTRECT *paRects));
DECLR3CALLBACKMEMBER(void, CRORFrame, (void *pvInstance,
void *pvData, uint32_t cbData));
DECLR3CALLBACKMEMBER(void, CROREnd, (void *pvInstance));
@@ -75,6 +84,140 @@ typedef struct {
struct BucketingInfo;
+typedef struct {
+ char *pszDpyName;
+ GLint visualBits;
+ int32_t externalID;
+} CRCreateInfo_t;
+
+typedef struct {
+ char *pszDpyName;
+ int32_t externalID;
+ GLint requestedVisualBits;
+ GLint realVisualBits;
+} CRCreateInfoEx_t;
+
+/* VRAM->RAM worker thread */
+
+typedef enum
+{
+ CR_SERVER_RPW_STATE_UNINITIALIZED = 0,
+ CR_SERVER_RPW_STATE_INITIALIZING,
+ CR_SERVER_RPW_STATE_INITIALIZED,
+ CR_SERVER_RPW_STATE_UNINITIALIZING,
+} CR_SERVER_RPW_STATE;
+
+/* worker control command */
+typedef enum
+{
+ CR_SERVER_RPW_CTL_TYPE_UNDEFINED = 0,
+ CR_SERVER_RPW_CTL_TYPE_WAIT_COMPLETE,
+ CR_SERVER_RPW_CTL_TYPE_TERM
+} CR_SERVER_RPW_CTL_TYPE;
+
+struct CR_SERVER_RPW_ENTRY;
+
+typedef struct CR_SERVER_RPW_CTL {
+ CR_SERVER_RPW_CTL_TYPE enmType;
+ int rc;
+ RTSEMEVENT hCompleteEvent;
+ /* valid for *_WAIT_COMPLETE and *_CANCEL */
+ struct CR_SERVER_RPW_ENTRY *pEntry;
+} CR_SERVER_RPW_CTL;
+
+
+struct CR_SERVER_RPW_ENTRY;
+
+typedef DECLCALLBACKPTR(void, PFNCR_SERVER_RPW_DATA) (const struct CR_SERVER_RPW_ENTRY* pEntry, void *pvEntryTexData);
+
+typedef DECLCALLBACKPTR(void, PFNCRSERVERNOTIFYEVENT) (int32_t screenId, uint32_t uEvent, void*pvData);
+
+typedef struct CR_SERVER_RPW_ENTRY
+{
+ RTRECTSIZE Size;
+ /* We have to use 4 textures here.
+ *
+ * 1. iDrawTex - the texture clients can draw to and then submit it for contents acquisition via crServerRpwEntrySubmit
+ * 2. iSubmittedTex - the texture submitted to the worker for processing and, whose processing has not start yet,
+ * i.e. it is being in the queue and can be safely removed/replaced [from] there
+ * 3. iWorkerTex - the texture being prepared & passed by the worker to the GPU (stage 1 of a worker contents acquisition process)
+ * 4. iGpuTex - the texture passed/processed to/by the GPU, whose data is then acquired by the server (stage 2 of a worker contents acquisition process)
+ *
+ * - There can be valid distinct iGpuTex, iWorkerTex, iSubmittedTex and iDrawTex present simultaneously.
+ * - Either or both of iSubmittedTex and iFreeTex are always valid
+ *
+ * Detail:
+ *
+ * - iSubmittedTex and iFreeTex modifications are performed under CR_SERVER_RPW::CritSect lock.
+ *
+ * - iDrawTex can only be changed by client side (i.e. the crServerRpwEntrySubmit caller), this is why client thread can access it w/o a lock
+ * - iSubmittedTex and iFreeTex can be modified by both client and worker, so lock is always required
+ *
+ * - iDrawTex can be accessed by client code only
+ * - iWorkerTex and iGpuTex can be accessed by worker code only
+ * - iSubmittedTex and iFreeTex can be accessed under CR_SERVER_RPW::CritSect lock only
+ * - either or both of iSubmittedTex and iFreeTex are always valid (see below for more explanation),
+ * this is why client can easily determine the new iDrawTex value on Submit, i.e. :
+ *
+ * (if initial iSubmittedTex was valid)
+ * ---------------
+ * | ^
+ * > |
+ * Submit-> iDrawTex -> iSubmittedTex
+ * ^
+ * | (if initial iSubmittedTex was NOT valid)
+ * iFreeTex
+ *
+ * - The worker can invalidate the iSubmittedTex (i.e. do iSubmittedTex -> iWorkerTex) only after it is done
+ * with the last iWorkerTex -> iGpuTex transformation freeing the previously used iGpuTex to iFreeTex.
+ *
+ * - A simplified worker iXxxTex transformation logic is:
+ * 1. iFreeTex is initially valid
+ * 2. iSubmittedTex -> iWorkerTex;
+ * 3. submit iWorkerTex acquire request to the GPU
+ * 4. complete current iGpuTex
+ * 5. iGpuTex -> iFreeTex
+ * 6. iWorkerTex -> iGpuTex
+ * 7. goto 1
+ *
+ * */
+ int8_t iTexDraw;
+ int8_t iTexSubmitted;
+ int8_t iTexWorker;
+ int8_t iTexGpu;
+ int8_t iCurPBO;
+ GLuint aidWorkerTexs[4];
+ GLuint aidPBOs[2];
+ RTLISTNODE WorkEntry;
+ RTLISTNODE WorkerWorkEntry;
+ RTLISTNODE GpuSubmittedEntry;
+ PFNCR_SERVER_RPW_DATA pfnData;
+} CR_SERVER_RPW_ENTRY;
+
+typedef struct CR_SERVER_RPW {
+ RTLISTNODE WorkList;
+ RTCRITSECT CritSect;
+ RTSEMEVENT hSubmitEvent;
+ /* only one outstanding command is supported,
+ * and ctl requests must be cynchronized, hold it right here */
+ CR_SERVER_RPW_CTL Ctl;
+ int ctxId;
+ GLint ctxVisBits;
+ RTTHREAD hThread;
+} CR_SERVER_RPW;
+/* */
+
+/* FRAMEBUFFER */
+typedef struct CR_FRAMEBUFFER *HCR_FRAMEBUFFER;
+typedef struct CR_FRAMEBUFFER_ENTRY *HCR_FRAMEBUFFER_ENTRY;
+/* */
+
+typedef struct CR_FBDATA
+{
+ HCR_FRAMEBUFFER hFb;
+ HCR_FRAMEBUFFER_ENTRY hFbEntry;
+ CR_TEXDATA* apTexDatas[2];
+} CR_FBDATA;
/**
* Mural info
*/
@@ -88,30 +231,55 @@ typedef struct {
int screenId;
GLboolean bVisible; /*guest window is visible*/
- GLboolean bUseFBO; /*redirect to FBO instead of real host window*/
+ GLubyte u8Unused; /*redirect to FBO instead of real host window*/
GLboolean bFbDraw; /*GL_FRONT buffer is drawn to directly*/
+ GLboolean fIsDummyRefference;
GLint cVisibleRects; /*count of visible rects*/
GLint *pVisibleRects; /*visible rects left, top, right, bottom*/
GLboolean bReceivedRects; /*indicates if guest did any updates for visible regions*/
- GLuint idFBO, idColorTex, idDepthStencilRB;
+ GLuint cBuffers;
+ GLuint iBbBuffer;
+ GLuint aidFBOs[2];
+ GLuint aidColorTexs[2];
+
+ void *pvReserved;
+
+ CRCreateInfoEx_t CreateInfo;
+
+ /* to avoid saved state breakage we need to keep RT_OFFSETOF(CRMuralInfo, CreateInfo) intact
+ * this is why we place some FBO stuff to the tail
+ * @todo: once we need to increment a saved state version, we could refactor this structure */
+ GLint iCurDrawBuffer;
+ GLint iCurReadBuffer;
+
+ GLuint idDepthStencilRB;
GLuint fboWidth, fboHeight;
- GLuint idPBO;
- void *pvOutputRedirectInstance;
-} CRMuralInfo;
+ GLboolean fHasParentWindow;
-typedef struct {
- char *pszDpyName;
- GLint visualBits;
- int32_t externalID;
-} CRCreateInfo_t;
+ GLboolean fRedirected;
+ GLboolean fForcePresentState;
+ GLboolean fOrPresentOnReenable;
+
+ GLboolean fIsVisible;
+
+ CR_TEXDATA aTexs[2];
+ uint32_t cUsedFBDatas;
+ CR_FBDATA *apUsedFBDatas[CR_MAX_GUEST_MONITORS];
+ CR_FBDATA aFBDatas[CR_MAX_GUEST_MONITORS];
+
+ /* bitfield representing contexts the mural has been ever current with
+ * we just reuse CR_STATE_SHAREDOBJ_USAGE_XXX API here for simplicity */
+ CRbitvalue ctxUsage[CR_MAX_BITARRAY];
+} CRMuralInfo;
typedef struct {
CRContext *pContext;
int SpuContext;
- CRCreateInfo_t CreateInfo;
+ CRCreateInfoEx_t CreateInfo;
+ CRMuralInfo * currentMural;
} CRContextInfo;
/**
@@ -168,10 +336,15 @@ typedef struct {
} CRScreenInfo;
typedef struct {
- int32_t x, y;
- uint32_t w, h;
+ RTRECT Rect;
} CRScreenViewportInfo;
+/* BFB (BlitFramebuffer Blitter) flags
+ * so far only CR_SERVER_BFB_ON_ALWAIS is supported and is alwais used if any flag is set */
+#define CR_SERVER_BFB_DISABLED 0
+#define CR_SERVER_BFB_ON_INVERTED_BLIT 1
+#define CR_SERVER_BFB_ON_STRAIGHT_BLIT 2
+#define CR_SERVER_BFB_ON_ALWAIS (CR_SERVER_BFB_ON_INVERTED_BLIT | CR_SERVER_BFB_ON_STRAIGHT_BLIT)
typedef struct {
unsigned short tcpip_port;
@@ -194,14 +367,12 @@ typedef struct {
CRContextInfo *currentCtxInfo;
GLint currentWindow;
GLint currentNativeWindow;
+ CRMuralInfo *currentMural;
CRHashTable *muralTable; /**< hash table where all murals are stored */
- CRHashTable *pWindowCreateInfoTable; /**< hash table with windows creation info */
int client_spu_id;
- CRServerFreeIDsPool_t idsPool;
-
int mtu;
int buffer_size;
char protocol[1024];
@@ -221,6 +392,23 @@ typedef struct {
CRHashTable *programTable; /**< for vertex programs */
GLuint currentProgram;
+ /* visBits -> dummy mural association */
+ CRHashTable *dummyMuralTable;
+
+ GLboolean fRootVrOn;
+ VBOXVR_LIST RootVr;
+ /* we need to translate Root Vr to each window coords, this one cpecifies the current translation point
+ * note that since window attributes modifications is performed in HGCM thread only and thus is serialized,
+ * we deal with the global RootVr data directly */
+ RTPOINT RootVrCurPoint;
+
+ /* blitter so far used for working around host drivers BlitFramebuffer bugs
+ * by implementing */
+ uint32_t fBlitterMode;
+ CR_BLITTER Blitter;
+
+ CR_SERVER_RPW RpwWorker;
+
/** configuration options */
/*@{*/
int useL2;
@@ -276,14 +464,38 @@ typedef struct {
GLuint currentSerialNo;
PFNCRSERVERPRESENTFBO pfnPresentFBO;
- GLboolean bForceOffscreenRendering; /*Force server to render 3d data offscreen
- *using callback above to update vbox framebuffers*/
+
+ GLuint fVisualBitsDefault;
GLboolean bUsePBOForReadback; /*Use PBO's for data readback*/
- GLboolean bUseOutputRedirect; /* Whether the output redirect was set. */
CROutputRedirect outputRedirect;
GLboolean bUseMultipleContexts;
+
+ GLboolean bWindowsInitiallyHidden;
+
+ /* OR-ed CR_VBOX_CAP_XXX cap values
+ * describing VBox Chromium functionality caps visible to guest
+ * Currently can have only CR_VBOX_CAP_TEX_PRESENT cap to notify
+ * that the TexPresent mechanism is available and enabled */
+ uint32_t u32Caps;
+
+ PFNCRSERVERNOTIFYEVENT pfnNotifyEventCB;
+
+ SPUDispatchTable TmpCtxDispatch;
+
+ VBOXCRCMD_SVRENABLE_INFO CrCmdClientInfo;
+
+#ifdef VBOX_WITH_CRSERVER_DUMPER
+ CR_RECORDER Recorder;
+ CR_BLITTER RecorderBlitter;
+ CR_DBGPRINT_DUMPER DbgPrintDumper;
+ CR_HTML_DUMPER HtmlDumper;
+ CR_DUMPER *pDumper;
+#endif
+
+ int RcToGuest;
+ int RcToGuestOnce;
} CRServer;
@@ -301,16 +513,31 @@ extern DECLEXPORT(void) crVBoxServerRemoveClient(uint32_t u32ClientID);
extern DECLEXPORT(int32_t) crVBoxServerClientWrite(uint32_t u32ClientID, uint8_t *pBuffer, uint32_t cbBuffer);
extern DECLEXPORT(int32_t) crVBoxServerClientRead(uint32_t u32ClientID, uint8_t *pBuffer, uint32_t *pcbBuffer);
extern DECLEXPORT(int32_t) crVBoxServerClientSetVersion(uint32_t u32ClientID, uint32_t vMajor, uint32_t vMinor);
+extern DECLEXPORT(int32_t) crVBoxServerClientGetCaps(uint32_t u32ClientID, uint32_t *pu32Caps);
extern DECLEXPORT(int32_t) crVBoxServerClientSetPID(uint32_t u32ClientID, uint64_t pid);
extern DECLEXPORT(int32_t) crVBoxServerSaveState(PSSMHANDLE pSSM);
extern DECLEXPORT(int32_t) crVBoxServerLoadState(PSSMHANDLE pSSM, uint32_t version);
+typedef struct
+{
+ CR_BLITTER_IMG Img;
+ uint32_t u32Screen;
+ uint32_t fDataAllocated;
+} CR_SCREENSHOT;
+
+extern DECLEXPORT(int) crServerVBoxWindowsShow(bool fShow);
+extern DECLEXPORT(int) crServerVBoxScreenshotGet(uint32_t u32Screen, uint32_t width, uint32_t height, uint32_t pitch, void *pvBuffer, CR_SCREENSHOT *pScreenshot);
+extern DECLEXPORT(void) crServerVBoxScreenshotRelease(CR_SCREENSHOT *pScreenshot);
+
+extern DECLEXPORT(void) crServerVBoxCompositionSetEnableStateGlobal(GLboolean fEnable);
extern DECLEXPORT(int32_t) crVBoxServerSetScreenCount(int sCount);
extern DECLEXPORT(int32_t) crVBoxServerUnmapScreen(int sIndex);
extern DECLEXPORT(int32_t) crVBoxServerMapScreen(int sIndex, int32_t x, int32_t y, uint32_t w, uint32_t h, uint64_t winID);
-
-extern DECLEXPORT(int32_t) crVBoxServerSetRootVisibleRegion(GLint cRects, GLint *pRects);
+extern DECLEXPORT(void) crServerVBoxCompositionSetEnableStateGlobal(GLboolean fEnable);
+struct VBVAINFOSCREEN;
+extern DECLEXPORT(int) crVBoxServerNotifyResize(const struct VBVAINFOSCREEN *pScreen, void *pvVRAM);
+extern DECLEXPORT(int32_t) crVBoxServerSetRootVisibleRegion(GLint cRects, const RTRECT *pRects);
extern DECLEXPORT(void) crVBoxServerSetPresentFBOCB(PFNCRSERVERPRESENTFBO pfnPresentFBO);
@@ -320,6 +547,8 @@ extern DECLEXPORT(int32_t) crVBoxServerOutputRedirectSet(const CROutputRedirect
extern DECLEXPORT(int32_t) crVBoxServerSetScreenViewport(int sIndex, int32_t x, int32_t y, uint32_t w, uint32_t h);
+extern DECLEXPORT(void) crServerVBoxSetNotifyEventCB(PFNCRSERVERNOTIFYEVENT pfnCb);
+
#ifdef VBOX_WITH_CRHGSMI
/* We moved all CrHgsmi command processing to crserverlib to keep the logic of dealing with CrHgsmi commands in one place.
*
@@ -336,8 +565,14 @@ extern DECLEXPORT(int32_t) crVBoxServerSetScreenViewport(int sIndex, int32_t x,
* */
extern DECLEXPORT(int32_t) crVBoxServerCrHgsmiCmd(struct VBOXVDMACMD_CHROMIUM_CMD *pCmd, uint32_t cbCmd);
extern DECLEXPORT(int32_t) crVBoxServerCrHgsmiCtl(struct VBOXVDMACMD_CHROMIUM_CTL *pCtl, uint32_t cbCtl);
+
#endif
+extern DECLEXPORT(int32_t) crVBoxServerHgcmEnable(HVBOXCRCMDCTL_REMAINING_HOST_COMMAND hRHCmd, PFNVBOXCRCMDCTL_REMAINING_HOST_COMMAND pfnRHCmd);
+extern DECLEXPORT(int32_t) crVBoxServerHgcmDisable();
+
+extern int crVBoxServerHostCtl(VBOXCRCMDCTL *pCtl, uint32_t cbCtl);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/VBox/GuestHost/OpenGL/include/cr_string.h b/src/VBox/GuestHost/OpenGL/include/cr_string.h
index 87f1df38..972d08f1 100644
--- a/src/VBox/GuestHost/OpenGL/include/cr_string.h
+++ b/src/VBox/GuestHost/OpenGL/include/cr_string.h
@@ -36,6 +36,30 @@ DECLEXPORT(int) crIsDigit( char c );
DECLEXPORT(void) crBytesToString( char *string, int nstring, void *data, int ndata );
DECLEXPORT(void) crWordsToString( char *string, int nstring, void *data, int ndata );
+#define CR_GLVERSION_OFFSET_MAJOR (24)
+#define CR_GLVERSION_OFFSET_MINOR (16)
+#define CR_GLVERSION_OFFSET_BUILD (0)
+
+#define CR_GLVERSION_MAX_MAJOR (0x7f)
+#define CR_GLVERSION_MAX_MINOR (0xff)
+#define CR_GLVERSION_MAX_BUILD (0xffff)
+
+#define CR_GLVERSION_MASK_MAJOR (CR_GLVERSION_MAX_MAJOR << CR_GLVERSION_OFFSET_MAJOR)
+#define CR_GLVERSION_MASK_MINOR (CR_GLVERSION_MAX_MINOR << CR_GLVERSION_OFFSET_MINOR)
+#define CR_GLVERSION_MASK_BUILD (CR_GLVERSION_MAX_BUILD << CR_GLVERSION_OFFSET_BUILD)
+
+#define CR_GLVERSION_COMPOSE_EL(_val, _type) (((_val) << CR_GLVERSION_OFFSET_##_type) & CR_GLVERSION_MASK_##_type)
+
+#define CR_GLVERSION_COMPOSE(_maj, _min, _build) (CR_GLVERSION_COMPOSE_EL((_maj), MAJOR) \
+ + CR_GLVERSION_COMPOSE_EL((_min), MINOR) \
+ + CR_GLVERSION_COMPOSE_EL((_build), BUILD))
+
+#define CR_GLVERSION_GET_EL(_val, _type) (((_val) & CR_GLVERSION_MASK_##_type) >> CR_GLVERSION_OFFSET_##_type)
+#define CR_GLVERSION_GET_MAJOR(_val) CR_GLVERSION_GET_EL((_val), MAJOR)
+#define CR_GLVERSION_GET_MINOR(_val) CR_GLVERSION_GET_EL((_val), MINOR)
+#define CR_GLVERSION_GET_BUILD(_val) CR_GLVERSION_GET_EL((_val), BUILD)
+
+DECLEXPORT(int) crStrParseGlVersion(const char * ver);
RT_C_DECLS_END
#endif /* CR_STRING_H */
diff --git a/src/VBox/GuestHost/OpenGL/include/cr_version.h b/src/VBox/GuestHost/OpenGL/include/cr_version.h
index 06d99de6..6b6a7c5f 100644
--- a/src/VBox/GuestHost/OpenGL/include/cr_version.h
+++ b/src/VBox/GuestHost/OpenGL/include/cr_version.h
@@ -7,9 +7,40 @@
#ifndef CR_VERSION_H
#define CR_VERSION_H
-#define SHCROGL_SSM_VERSION_BEFORE_CTXUSAGE_BITS 28
-#define SHCROGL_SSM_VERSION_BEFORE_FRONT_DRAW_TRACKING 29
-#define SHCROGL_SSM_VERSION 30
+#define SHCROGL_SSM_VERSION_BEFORE_CTXUSAGE_BITS 28
+/* version which might have context usage bits saved */
+#define SHCROGL_SSM_VERSION_WITH_SAVED_CTXUSAGE_BITS SHCROGL_SSM_VERSION_BEFORE_CTXUSAGE_BITS
+#define SHCROGL_SSM_VERSION_BEFORE_FRONT_DRAW_TRACKING 29
+/* version that might have corrupted state data */
+#define SHCROGL_SSM_VERSION_WITH_CORUPTED_STATE 30
+/* version with invalid glGetError state */
+#define SHCROGL_SSM_VERSION_WITH_INVALID_ERROR_STATE 30
+/* VBox 4.2.12 had a bug that incorrectly CRMuralInfo data
+ * in a different format without changing the state version,
+ * i.e. 30 version can have both "correct" and "incorrect" CRMuralInfo data */
+#define SHCROGL_SSM_VERSION_WITH_BUGGY_MURAL_INFO 30
+/* the saved state has incorrect front and back buffer image data */
+#define SHCROGL_SSM_VERSION_WITH_BUGGY_FB_IMAGE_DATA 31
+#define SHCROGL_SSM_VERSION_WITH_STATE_BITS 33
+#define SHCROGL_SSM_VERSION_WITH_WINDOW_CTX_USAGE 33
+#define SHCROGL_SSM_VERSION_WITH_FIXED_STENCIL 34
+#define SHCROGL_SSM_VERSION_WITH_SAVED_DEPTH_STENCIL_BUFFER 35
+/* some ogl drivers fail to Read/DrawPixels for DEPTH and STENCIL separately
+ * from DEPTH_STENCIL renderbuffer we used for offscreen rendering
+ * this is why we switched to glReadDrawPixels(GL_DEPTH_STENCIL) in one run */
+#define SHCROGL_SSM_VERSION_WITH_SINGLE_DEPTH_STENCIL 36
+#define SHCROGL_SSM_VERSION_WITH_PRESENT_STATE 37
+/* older state did not have glPointParameter ( GL_POINT_SPRITE_COORD_ORIGIN ) implementation */
+#define SHCROGL_SSM_VERSION_WITH_SPRITE_COORD_ORIGIN 38
+/* dirty bits are not needed for now, remove */
+#define SHCROGL_SSM_VERSION_WITHOUT_DIRTY_BITS 38
+/* dummy windows and contexts have 0 external IDs, so never get stored to the state */
+#define SHCROGL_SSM_VERSION_WITH_FIXED_DUMMYIDS 39
+#define SHCROGL_SSM_VERSION_WITH_SCREEN_INFO 40
+#define SHCROGL_SSM_VERSION_WITH_ALLOCATED_KEYS 41
+#define SHCROGL_SSM_VERSION_WITH_FB_INFO 42
+#define SHCROGL_SSM_VERSION_WITH_BUGGY_KEYS 42
+#define SHCROGL_SSM_VERSION 43
/* These define the Chromium release number.
* Alpha Release = 0.1.0, Beta Release = 0.2.0
@@ -139,4 +170,6 @@
#define CR_EXT_blend_equation_separate 1
#define CR_EXT_stencil_two_side 1
+#define CR_GREMEDY_string_marker 1
+
#endif /* CR_VERSION_H */
diff --git a/src/VBox/GuestHost/OpenGL/include/cr_vreg.h b/src/VBox/GuestHost/OpenGL/include/cr_vreg.h
new file mode 100644
index 00000000..0f5786be
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/include/cr_vreg.h
@@ -0,0 +1,377 @@
+/* $Id: cr_vreg.h $ */
+
+/** @file
+ * Visible Regions processing API
+ */
+
+/*
+ * Copyright (C) 2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+#ifndef ___cr_vreg_h_
+#define ___cr_vreg_h_
+
+#include <iprt/list.h>
+#include <iprt/types.h>
+#include <iprt/mem.h>
+#include <iprt/string.h>
+#include <iprt/assert.h>
+#include <iprt/critsect.h>
+#include <iprt/asm.h>
+
+#ifndef IN_RING0
+# define VBOXVREGDECL(_type) DECLEXPORT(_type)
+#else
+# define VBOXVREGDECL(_type) RTDECL(_type)
+#endif
+
+
+
+RT_C_DECLS_BEGIN
+
+typedef struct VBOXVR_LIST
+{
+ RTLISTNODE ListHead;
+ uint32_t cEntries;
+} VBOXVR_LIST, *PVBOXVR_LIST;
+
+DECLINLINE(int) VBoxRectCmp(const RTRECT * pRect1, const RTRECT * pRect2)
+{
+ return memcmp(pRect1, pRect2, sizeof (*pRect1));
+}
+
+#ifndef IN_RING0
+#define CR_FLOAT_RCAST(_t, _v) ((_t)((float)(_v) + 0.5))
+
+DECLINLINE(void) VBoxRectScale(PRTRECT pRect, float xScale, float yScale)
+{
+ pRect->xLeft = CR_FLOAT_RCAST(int32_t, pRect->xLeft * xScale);
+ pRect->yTop = CR_FLOAT_RCAST(int32_t, pRect->yTop * yScale);
+ pRect->xRight = CR_FLOAT_RCAST(int32_t, pRect->xRight * xScale);
+ pRect->yBottom = CR_FLOAT_RCAST(int32_t, pRect->yBottom * yScale);
+}
+
+DECLINLINE(void) VBoxRectScaled(const RTRECT *pRect, float xScale, float yScale, PRTRECT pResult)
+{
+ *pResult = *pRect;
+ VBoxRectScale(pResult, xScale, yScale);
+}
+
+DECLINLINE(void) VBoxRectUnscale(PRTRECT pRect, float xScale, float yScale)
+{
+ pRect->xLeft = CR_FLOAT_RCAST(int32_t, pRect->xLeft / xScale);
+ pRect->yTop = CR_FLOAT_RCAST(int32_t, pRect->yTop / yScale);
+ pRect->xRight = CR_FLOAT_RCAST(int32_t, pRect->xRight / xScale);
+ pRect->yBottom = CR_FLOAT_RCAST(int32_t, pRect->yBottom / yScale);
+}
+
+DECLINLINE(void) VBoxRectUnscaled(const RTRECT *pRect, float xScale, float yScale, PRTRECT pResult)
+{
+ *pResult = *pRect;
+ VBoxRectUnscale(pResult, xScale, yScale);
+}
+#endif
+
+DECLINLINE(void) VBoxRectIntersect(PRTRECT pRect1, const RTRECT * pRect2)
+{
+ Assert(pRect1);
+ Assert(pRect2);
+ pRect1->xLeft = RT_MAX(pRect1->xLeft, pRect2->xLeft);
+ pRect1->yTop = RT_MAX(pRect1->yTop, pRect2->yTop);
+ pRect1->xRight = RT_MIN(pRect1->xRight, pRect2->xRight);
+ pRect1->yBottom = RT_MIN(pRect1->yBottom, pRect2->yBottom);
+}
+
+DECLINLINE(void) VBoxRectIntersected(const RTRECT *pRect1, const RTRECT * pRect2, RTRECT *pResult)
+{
+ *pResult = *pRect1;
+ VBoxRectIntersect(pResult, pRect2);
+}
+
+
+DECLINLINE(void) VBoxRectTranslate(RTRECT * pRect, int32_t x, int32_t y)
+{
+ pRect->xLeft += x;
+ pRect->yTop += y;
+ pRect->xRight += x;
+ pRect->yBottom += y;
+}
+
+DECLINLINE(void) VBoxRectTranslated(const RTRECT * pRect, int32_t x, int32_t y, RTRECT *pResult)
+{
+ *pResult = *pRect;
+ VBoxRectTranslate(pResult, x, y);
+}
+
+DECLINLINE(void) VBoxRectInvertY(RTRECT * pRect)
+{
+ int32_t y = pRect->yTop;
+ pRect->yTop = pRect->yBottom;
+ pRect->yBottom = y;
+}
+
+DECLINLINE(void) VBoxRectInvertedY(const RTRECT * pRect, RTRECT * pResult)
+{
+ *pResult = *pRect;
+ VBoxRectInvertY(pResult);
+}
+
+DECLINLINE(void) VBoxRectMove(RTRECT * pRect, int32_t x, int32_t y)
+{
+ int32_t w = pRect->xRight - pRect->xLeft;
+ int32_t h = pRect->yBottom - pRect->yTop;
+ pRect->xLeft = x;
+ pRect->yTop = y;
+ pRect->xRight = w + x;
+ pRect->yBottom = h + y;
+}
+
+DECLINLINE(void) VBoxRectMoved(const RTRECT * pRect, int32_t x, int32_t y, RTRECT *pResult)
+{
+ *pResult = *pRect;
+ VBoxRectMove(pResult, x, y);
+}
+
+DECLINLINE(bool) VBoxRectCovers(const RTRECT *pRect, const RTRECT *pCovered)
+{
+ Assert(pRect);
+ Assert(pCovered);
+ if (pRect->xLeft > pCovered->xLeft)
+ return false;
+ if (pRect->yTop > pCovered->yTop)
+ return false;
+ if (pRect->xRight < pCovered->xRight)
+ return false;
+ if (pRect->yBottom < pCovered->yBottom)
+ return false;
+ return true;
+}
+
+DECLINLINE(bool) VBoxRectIsZero(const RTRECT *pRect)
+{
+ return pRect->xLeft == pRect->xRight || pRect->yTop == pRect->yBottom;
+}
+
+DECLINLINE(bool) VBoxRectIsIntersect(const RTRECT * pRect1, const RTRECT * pRect2)
+{
+ return !((pRect1->xLeft < pRect2->xLeft && pRect1->xRight <= pRect2->xLeft)
+ || (pRect2->xLeft < pRect1->xLeft && pRect2->xRight <= pRect1->xLeft)
+ || (pRect1->yTop < pRect2->yTop && pRect1->yBottom <= pRect2->yTop)
+ || (pRect2->yTop < pRect1->yTop && pRect2->yBottom <= pRect1->yTop));
+}
+
+DECLINLINE(uint32_t) VBoxVrListRectsCount(const VBOXVR_LIST *pList)
+{
+ return pList->cEntries;
+}
+
+DECLINLINE(bool) VBoxVrListIsEmpty(const VBOXVR_LIST *pList)
+{
+ return !VBoxVrListRectsCount(pList);
+}
+
+DECLINLINE(void) VBoxVrListInit(PVBOXVR_LIST pList)
+{
+ RTListInit(&pList->ListHead);
+ pList->cEntries = 0;
+}
+
+VBOXVREGDECL(void) VBoxVrListClear(PVBOXVR_LIST pList);
+
+/* moves list data to pDstList and empties the pList */
+VBOXVREGDECL(void) VBoxVrListMoveTo(PVBOXVR_LIST pList, PVBOXVR_LIST pDstList);
+
+VBOXVREGDECL(void) VBoxVrListTranslate(PVBOXVR_LIST pList, int32_t x, int32_t y);
+
+VBOXVREGDECL(int) VBoxVrListCmp(const VBOXVR_LIST *pList1, const VBOXVR_LIST *pList2);
+
+VBOXVREGDECL(int) VBoxVrListRectsSet(PVBOXVR_LIST pList, uint32_t cRects, const RTRECT * aRects, bool *pfChanged);
+VBOXVREGDECL(int) VBoxVrListRectsAdd(PVBOXVR_LIST pList, uint32_t cRects, const RTRECT * aRects, bool *pfChanged);
+VBOXVREGDECL(int) VBoxVrListRectsSubst(PVBOXVR_LIST pList, uint32_t cRects, const RTRECT * aRects, bool *pfChanged);
+VBOXVREGDECL(int) VBoxVrListRectsGet(PVBOXVR_LIST pList, uint32_t cRects, RTRECT * aRects);
+
+VBOXVREGDECL(int) VBoxVrListClone(const VBOXVR_LIST *pList, VBOXVR_LIST *pDstList);
+
+/* NOTE: with the current implementation the VBoxVrListIntersect is faster than VBoxVrListRectsIntersect,
+ * i.e. VBoxVrListRectsIntersect is actually a convenience function that create a temporary list and calls VBoxVrListIntersect internally */
+VBOXVREGDECL(int) VBoxVrListRectsIntersect(PVBOXVR_LIST pList, uint32_t cRects, const RTRECT * aRects, bool *pfChanged);
+VBOXVREGDECL(int) VBoxVrListIntersect(PVBOXVR_LIST pList, const VBOXVR_LIST *pList2, bool *pfChanged);
+
+VBOXVREGDECL(int) VBoxVrInit(void);
+VBOXVREGDECL(void) VBoxVrTerm(void);
+
+typedef struct VBOXVR_LIST_ITERATOR
+{
+ PVBOXVR_LIST pList;
+ PRTLISTNODE pNextEntry;
+} VBOXVR_LIST_ITERATOR, *PVBOXVR_LIST_ITERATOR;
+
+DECLINLINE(void) VBoxVrListIterInit(PVBOXVR_LIST pList, PVBOXVR_LIST_ITERATOR pIter)
+{
+ pIter->pList = pList;
+ pIter->pNextEntry = pList->ListHead.pNext;
+}
+
+typedef struct VBOXVR_REG
+{
+ RTLISTNODE ListEntry;
+ RTRECT Rect;
+} VBOXVR_REG, *PVBOXVR_REG;
+
+#define PVBOXVR_REG_FROM_ENTRY(_pEntry) ((PVBOXVR_REG)(((uint8_t*)(_pEntry)) - RT_OFFSETOF(VBOXVR_REG, ListEntry)))
+
+DECLINLINE(PCRTRECT) VBoxVrListIterNext(PVBOXVR_LIST_ITERATOR pIter)
+{
+ PRTLISTNODE pNextEntry = pIter->pNextEntry;
+ if (pNextEntry != &pIter->pList->ListHead)
+ {
+ PCRTRECT pRect = &(PVBOXVR_REG_FROM_ENTRY(pNextEntry)->Rect);
+ pIter->pNextEntry = pNextEntry->pNext;
+ return pRect;
+ }
+ return NULL;
+}
+
+typedef struct VBOXVR_COMPOSITOR_ENTRY
+{
+ RTLISTNODE Node;
+ VBOXVR_LIST Vr;
+ uint32_t cRefs;
+} VBOXVR_COMPOSITOR_ENTRY, *PVBOXVR_COMPOSITOR_ENTRY;
+
+struct VBOXVR_COMPOSITOR;
+
+typedef DECLCALLBACK(void) FNVBOXVRCOMPOSITOR_ENTRY_RELEASED(const struct VBOXVR_COMPOSITOR *pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, PVBOXVR_COMPOSITOR_ENTRY pReplacingEntry);
+typedef FNVBOXVRCOMPOSITOR_ENTRY_RELEASED *PFNVBOXVRCOMPOSITOR_ENTRY_RELEASED;
+
+typedef struct VBOXVR_COMPOSITOR
+{
+ RTLISTNODE List;
+ PFNVBOXVRCOMPOSITOR_ENTRY_RELEASED pfnEntryReleased;
+} VBOXVR_COMPOSITOR, *PVBOXVR_COMPOSITOR;
+
+typedef DECLCALLBACK(bool) FNVBOXVRCOMPOSITOR_VISITOR(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, void *pvVisitor);
+typedef FNVBOXVRCOMPOSITOR_VISITOR *PFNVBOXVRCOMPOSITOR_VISITOR;
+
+VBOXVREGDECL(void) VBoxVrCompositorInit(PVBOXVR_COMPOSITOR pCompositor, PFNVBOXVRCOMPOSITOR_ENTRY_RELEASED pfnEntryReleased);
+VBOXVREGDECL(void) VBoxVrCompositorClear(PVBOXVR_COMPOSITOR pCompositor);
+VBOXVREGDECL(void) VBoxVrCompositorRegionsClear(PVBOXVR_COMPOSITOR pCompositor, bool *pfChanged);
+VBOXVREGDECL(void) VBoxVrCompositorEntryInit(PVBOXVR_COMPOSITOR_ENTRY pEntry);
+DECLINLINE(bool) VBoxVrCompositorEntryIsInList(const VBOXVR_COMPOSITOR_ENTRY *pEntry)
+{
+ return !VBoxVrListIsEmpty(&pEntry->Vr);
+}
+
+#define CRBLT_F_LINEAR 0x00000001
+#define CRBLT_F_INVERT_SRC_YCOORDS 0x00000002
+#define CRBLT_F_INVERT_DST_YCOORDS 0x00000004
+#define CRBLT_F_INVERT_YCOORDS (CRBLT_F_INVERT_SRC_YCOORDS | CRBLT_F_INVERT_DST_YCOORDS)
+/* the blit operation with discard the source alpha channel values and set the destination alpha values to 1.0 */
+#define CRBLT_F_NOALPHA 0x00000010
+
+#define CRBLT_FTYPE_XOR CRBLT_F_INVERT_YCOORDS
+#define CRBLT_FTYPE_OR (CRBLT_F_LINEAR | CRBLT_F_NOALPHA)
+#define CRBLT_FOP_COMBINE(_f1, _f2) ((((_f1) ^ (_f2)) & CRBLT_FTYPE_XOR) | (((_f1) | (_f2)) & CRBLT_FTYPE_OR))
+
+#define CRBLT_FLAGS_FROM_FILTER(_f) ( ((_f) & GL_LINEAR) ? CRBLT_F_LINEAR : 0)
+#define CRBLT_FILTER_FROM_FLAGS(_f) (((_f) & CRBLT_F_LINEAR) ? GL_LINEAR : GL_NEAREST)
+
+/* compositor regions changed */
+#define VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED 0x00000001
+/* other entries changed along while doing current entry modification
+ * always comes with VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED */
+#define VBOXVR_COMPOSITOR_CF_OTHER_ENTRIES_REGIONS_CHANGED 0x00000002
+/* only current entry regions changed
+ * can come wither with VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED or with VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED */
+#define VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED 0x00000004
+/* the given entry has replaced some other entry, while overal regions did NOT change.
+ * always comes with VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED */
+#define VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED 0x00000008
+
+
+VBOXVREGDECL(bool) VBoxVrCompositorEntryRemove(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry);
+VBOXVREGDECL(bool) VBoxVrCompositorEntryReplace(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, PVBOXVR_COMPOSITOR_ENTRY pNewEntry);
+VBOXVREGDECL(int) VBoxVrCompositorEntryRegionsAdd(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, uint32_t cRegions, const RTRECT *paRegions, PVBOXVR_COMPOSITOR_ENTRY *ppReplacedEntry, uint32_t *pfChangeFlags);
+VBOXVREGDECL(int) VBoxVrCompositorEntryRegionsSubst(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, uint32_t cRegions, const RTRECT *paRegions, bool *pfChanged);
+VBOXVREGDECL(int) VBoxVrCompositorEntryRegionsSet(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, uint32_t cRegions, const RTRECT *paRegions, bool *pfChanged);
+VBOXVREGDECL(int) VBoxVrCompositorEntryRegionsIntersect(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, uint32_t cRegions, const RTRECT *paRegions, bool *pfChanged);
+VBOXVREGDECL(int) VBoxVrCompositorEntryListIntersect(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, const VBOXVR_LIST *pList2, bool *pfChanged);
+VBOXVREGDECL(int) VBoxVrCompositorEntryRegionsIntersectAll(PVBOXVR_COMPOSITOR pCompositor, uint32_t cRegions, const RTRECT *paRegions, bool *pfChanged);
+VBOXVREGDECL(int) VBoxVrCompositorEntryListIntersectAll(PVBOXVR_COMPOSITOR pCompositor, const VBOXVR_LIST *pList2, bool *pfChanged);
+VBOXVREGDECL(int) VBoxVrCompositorEntryRegionsTranslate(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, int32_t x, int32_t y, bool *pfChanged);
+VBOXVREGDECL(void) VBoxVrCompositorVisit(PVBOXVR_COMPOSITOR pCompositor, PFNVBOXVRCOMPOSITOR_VISITOR pfnVisitor, void *pvVisitor);
+
+DECLINLINE(bool) VBoxVrCompositorIsEmpty(const VBOXVR_COMPOSITOR *pCompositor)
+{
+ return RTListIsEmpty(&pCompositor->List);
+}
+
+typedef struct VBOXVR_COMPOSITOR_ITERATOR
+{
+ PVBOXVR_COMPOSITOR pCompositor;
+ PRTLISTNODE pNextEntry;
+} VBOXVR_COMPOSITOR_ITERATOR ,*PVBOXVR_COMPOSITOR_ITERATOR;
+
+typedef struct VBOXVR_COMPOSITOR_CONST_ITERATOR
+{
+ const VBOXVR_COMPOSITOR *pCompositor;
+ const RTLISTNODE *pNextEntry;
+} VBOXVR_COMPOSITOR_CONST_ITERATOR ,*PVBOXVR_COMPOSITOR_CONST_ITERATOR;
+
+DECLINLINE(void) VBoxVrCompositorIterInit(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ITERATOR pIter)
+{
+ pIter->pCompositor = pCompositor;
+ pIter->pNextEntry = pCompositor->List.pNext;
+}
+
+DECLINLINE(void) VBoxVrCompositorConstIterInit(const VBOXVR_COMPOSITOR *pCompositor, PVBOXVR_COMPOSITOR_CONST_ITERATOR pIter)
+{
+ pIter->pCompositor = pCompositor;
+ pIter->pNextEntry = pCompositor->List.pNext;
+}
+
+#define VBOXVR_COMPOSITOR_ENTRY_FROM_NODE(_p) ((PVBOXVR_COMPOSITOR_ENTRY)(((uint8_t*)(_p)) - RT_OFFSETOF(VBOXVR_COMPOSITOR_ENTRY, Node)))
+#define VBOXVR_COMPOSITOR_CONST_ENTRY_FROM_NODE(_p) ((const VBOXVR_COMPOSITOR_ENTRY*)(((uint8_t*)(_p)) - RT_OFFSETOF(VBOXVR_COMPOSITOR_ENTRY, Node)))
+
+DECLINLINE(PVBOXVR_COMPOSITOR_ENTRY) VBoxVrCompositorIterNext(PVBOXVR_COMPOSITOR_ITERATOR pIter)
+{
+ PRTLISTNODE pNextEntry = pIter->pNextEntry;
+ if (pNextEntry != &pIter->pCompositor->List)
+ {
+ PVBOXVR_COMPOSITOR_ENTRY pEntry = VBOXVR_COMPOSITOR_ENTRY_FROM_NODE(pNextEntry);
+ pIter->pNextEntry = pNextEntry->pNext;
+ return pEntry;
+ }
+ return NULL;
+}
+
+DECLINLINE(const VBOXVR_COMPOSITOR_ENTRY*) VBoxVrCompositorConstIterNext(PVBOXVR_COMPOSITOR_CONST_ITERATOR pIter)
+{
+ const RTLISTNODE *pNextEntry = pIter->pNextEntry;
+ if (pNextEntry != &pIter->pCompositor->List)
+ {
+ const VBOXVR_COMPOSITOR_ENTRY *pEntry = VBOXVR_COMPOSITOR_CONST_ENTRY_FROM_NODE(pNextEntry);
+ pIter->pNextEntry = pNextEntry->pNext;
+ return pEntry;
+ }
+ return NULL;
+}
+
+typedef struct VBOXVR_TEXTURE
+{
+ int32_t width;
+ int32_t height;
+ uint32_t target;
+ uint32_t hwid;
+} VBOXVR_TEXTURE, *PVBOXVR_TEXTURE;
+
+RT_C_DECLS_END
+
+#endif /* #ifndef ___cr_vreg_h_ */
diff --git a/src/VBox/GuestHost/OpenGL/include/state/cr_attrib.h b/src/VBox/GuestHost/OpenGL/include/state/cr_attrib.h
index 855f5736..579e71dd 100644
--- a/src/VBox/GuestHost/OpenGL/include/state/cr_attrib.h
+++ b/src/VBox/GuestHost/OpenGL/include/state/cr_attrib.h
@@ -245,6 +245,18 @@ typedef struct {
GLenum passDepthPass;
GLint clearValue;
GLint writeMask;
+} CRStencilBufferStack_v_33;
+
+typedef struct {
+ /* true if stencil test is enabled */
+ GLboolean stencilTest;
+ /* true if GL_EXT_stencil_two_side is enabled (glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)) */
+ GLboolean stencilTwoSideEXT;
+ /* GL_FRONT or GL_BACK */
+ GLenum activeStencilFace;
+ GLint clearValue;
+ GLint writeMask;
+ CRStencilBufferState buffers[CRSTATE_STENCIL_BUFFER_COUNT];
} CRStencilBufferStack;
typedef struct {
diff --git a/src/VBox/GuestHost/OpenGL/include/state/cr_bufferobject.h b/src/VBox/GuestHost/OpenGL/include/state/cr_bufferobject.h
index d83ac973..8584adc0 100644
--- a/src/VBox/GuestHost/OpenGL/include/state/cr_bufferobject.h
+++ b/src/VBox/GuestHost/OpenGL/include/state/cr_bufferobject.h
@@ -41,10 +41,8 @@ typedef struct {
so we need to resync every time guest wants to read from it*/
CRbitvalue dirty[CR_MAX_BITARRAY]; /* dirty data or state */
GLintptrARB dirtyStart, dirtyLength; /* dirty region */
-#ifndef IN_GUEST
/* bitfield representing the object usage. 1 means the object is used by the context with the given bitid */
CRbitvalue ctxUsage[CR_MAX_BITARRAY];
-#endif
} CRBufferObject;
typedef struct {
@@ -59,10 +57,13 @@ typedef struct {
DECLEXPORT(CRBufferObject *) crStateGetBoundBufferObject(GLenum target, CRBufferObjectState *b);
DECLEXPORT(GLboolean) crStateIsBufferBound(GLenum target);
+struct CRContext;
+DECLEXPORT(GLboolean) crStateIsBufferBoundForCtx(struct CRContext *g, GLenum target);
DECLEXPORT(GLuint) STATE_APIENTRY crStateBufferHWIDtoID(GLuint hwid);
DECLEXPORT(GLuint) STATE_APIENTRY crStateGetBufferHWID(GLuint id);
+DECLEXPORT(void) crStateRegBuffers(GLsizei n, GLuint *buffers);
#ifdef __cplusplus
}
#endif
diff --git a/src/VBox/GuestHost/OpenGL/include/state/cr_client.h b/src/VBox/GuestHost/OpenGL/include/state/cr_client.h
index e328857a..a727f260 100644
--- a/src/VBox/GuestHost/OpenGL/include/state/cr_client.h
+++ b/src/VBox/GuestHost/OpenGL/include/state/cr_client.h
@@ -125,10 +125,12 @@ typedef struct {
extern const CRPixelPackState crStateNativePixelPacking;
+struct CRContext;
+
DECLEXPORT(void) crStateClientInitBits(CRClientBits *c);
DECLEXPORT(void) crStateClientDestroyBits(CRClientBits *c);
-DECLEXPORT(void) crStateClientInit(CRClientState *c);
-DECLEXPORT(void) crStateClientDestroy(CRClientState *c);
+DECLEXPORT(void) crStateClientInit(struct CRContext *g);
+DECLEXPORT(void) crStateClientDestroy(struct CRContext *g);
DECLEXPORT(GLboolean) crStateUseServerArrays(void);
DECLEXPORT(GLboolean) crStateUseServerArrayElements(void);
diff --git a/src/VBox/GuestHost/OpenGL/include/state/cr_framebuffer.h b/src/VBox/GuestHost/OpenGL/include/state/cr_framebuffer.h
index adc7b3b2..f8da8a7c 100644
--- a/src/VBox/GuestHost/OpenGL/include/state/cr_framebuffer.h
+++ b/src/VBox/GuestHost/OpenGL/include/state/cr_framebuffer.h
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2009 Oracle Corporation
+ * Copyright (C) 2009-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -48,10 +48,9 @@ typedef struct {
GLenum drawbuffer[1];
#ifdef IN_GUEST
GLenum status;
-#else
+#endif
/* bitfield representing the object usage. 1 means the object is used by the context with the given bitid */
CRbitvalue ctxUsage[CR_MAX_BITARRAY];
-#endif
} CRFramebufferObject;
typedef struct {
@@ -59,10 +58,8 @@ typedef struct {
GLsizei width, height;
GLenum internalformat;
GLuint redBits, greenBits, blueBits, alphaBits, depthBits, stencilBits;
-#ifndef IN_GUEST
/* bitfield representing the object usage. 1 means the object is used by the context with the given bitid */
CRbitvalue ctxUsage[CR_MAX_BITARRAY];
-#endif
} CRRenderbufferObject;
typedef struct {
@@ -74,8 +71,8 @@ DECLEXPORT(void) STATE_APIENTRY crStateFramebufferObjectInit(CRContext *ctx);
DECLEXPORT(void) STATE_APIENTRY crStateFramebufferObjectDestroy(CRContext *ctx);
DECLEXPORT(void) STATE_APIENTRY crStateFramebufferObjectSwitch(CRContext *from, CRContext *to);
-DECLEXPORT(void) STATE_APIENTRY crStateFramebufferObjectDisableHW(CRContext *ctx, GLuint idFBO);
-DECLEXPORT(void) STATE_APIENTRY crStateFramebufferObjectReenableHW(CRContext *fromCtx, CRContext *toCtx, GLuint idFBO);
+DECLEXPORT(void) STATE_APIENTRY crStateFramebufferObjectDisableHW(CRContext *ctx, GLuint idDrawFBO, GLuint idReadFBO);
+DECLEXPORT(void) STATE_APIENTRY crStateFramebufferObjectReenableHW(CRContext *fromCtx, CRContext *toCtx, GLuint idDrawFBO, GLuint idReadFBO);
DECLEXPORT(GLuint) STATE_APIENTRY crStateGetFramebufferHWID(GLuint id);
DECLEXPORT(GLuint) STATE_APIENTRY crStateGetRenderbufferHWID(GLuint id);
@@ -96,6 +93,9 @@ DECLEXPORT(void) STATE_APIENTRY crStateGenerateMipmapEXT(GLenum target);
DECLEXPORT(GLuint) STATE_APIENTRY crStateFBOHWIDtoID(GLuint hwid);
DECLEXPORT(GLuint) STATE_APIENTRY crStateRBOHWIDtoID(GLuint hwid);
+DECLEXPORT(void) crStateRegFramebuffers(GLsizei n, GLuint *buffers);
+DECLEXPORT(void) crStateRegRenderbuffers(GLsizei n, GLuint *buffers);
+
#ifdef IN_GUEST
DECLEXPORT(GLenum) STATE_APIENTRY crStateCheckFramebufferStatusEXT(GLenum target);
DECLEXPORT(GLenum) STATE_APIENTRY crStateSetFramebufferStatus(GLenum target, GLenum status);
diff --git a/src/VBox/GuestHost/OpenGL/include/state/cr_glsl.h b/src/VBox/GuestHost/OpenGL/include/state/cr_glsl.h
index 2713c434..81ed568e 100644
--- a/src/VBox/GuestHost/OpenGL/include/state/cr_glsl.h
+++ b/src/VBox/GuestHost/OpenGL/include/state/cr_glsl.h
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2009 Oracle Corporation
+ * Copyright (C) 2009-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -99,6 +99,7 @@ DECLEXPORT(GLboolean) STATE_APIENTRY crStateIsIntUniform(GLenum type);
DECLEXPORT(GLuint) STATE_APIENTRY crStateCreateShader(GLuint id, GLenum type);
DECLEXPORT(GLuint) STATE_APIENTRY crStateCreateProgram(GLuint id);
+DECLEXPORT(GLuint) STATE_APIENTRY crStateDeleteObjectARB( VBoxGLhandleARB obj );
DECLEXPORT(GLboolean) STATE_APIENTRY crStateIsProgramUniformsCached(GLuint program);
diff --git a/src/VBox/GuestHost/OpenGL/include/state/cr_point.h b/src/VBox/GuestHost/OpenGL/include/state/cr_point.h
index 4f5987b0..fe3dffe3 100644
--- a/src/VBox/GuestHost/OpenGL/include/state/cr_point.h
+++ b/src/VBox/GuestHost/OpenGL/include/state/cr_point.h
@@ -28,6 +28,7 @@ typedef struct {
CRbitvalue enableSprite[CR_MAX_BITARRAY];
CRbitvalue coordReplacement[CR_MAX_TEXTURE_UNITS][CR_MAX_BITARRAY];
#endif
+ CRbitvalue spriteCoordOrigin[CR_MAX_BITARRAY];
CRbitvalue dirty[CR_MAX_BITARRAY];
} CRPointBits;
@@ -43,6 +44,8 @@ typedef struct {
GLboolean pointSprite;
GLboolean coordReplacement[CR_MAX_TEXTURE_UNITS];
#endif
+ GLfloat spriteCoordOrigin;
+ GLfloat reserved; /* added to make sure alignment of sttructures following CRPointState in CRContext does not change */
} CRPointState;
DECLEXPORT(void) crStatePointInit (CRContext *ctx);
diff --git a/src/VBox/GuestHost/OpenGL/include/state/cr_stencil.h b/src/VBox/GuestHost/OpenGL/include/state/cr_stencil.h
index 1443e951..27823eb2 100644
--- a/src/VBox/GuestHost/OpenGL/include/state/cr_stencil.h
+++ b/src/VBox/GuestHost/OpenGL/include/state/cr_stencil.h
@@ -11,33 +11,89 @@
#include "state/cr_statetypes.h"
#include <iprt/cdefs.h>
+#include <iprt/assert.h>
#ifdef __cplusplus
extern "C" {
#endif
+#define CRSTATE_STENCIL_BUFFER_ID_FRONT 0
+#define CRSTATE_STENCIL_BUFFER_ID_BACK 1
+#define CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK 2
+#define CRSTATE_STENCIL_BUFFER_COUNT 3
+
+/* stencil buffer settings were accessed with StencilXxx with ActiveStencilFaceEXT == GL_FRONT or StencilXxxSeparate(GL_FRONT_AND_BACK) */
+#define CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK 0
+/* stencil buffer settings were accessed with StencilXxxSeparate(GL_FRONT_FRONT) */
+#define CRSTATE_STENCIL_BUFFER_REF_ID_FRONT 1
+/* stencil buffer settings were accessed with StencilXxxSeparate(GL_FRONT_BACK) */
+#define CRSTATE_STENCIL_BUFFER_REF_ID_BACK 2
+/* stencil buffer settings were accessed with StencilXxx with ActiveStencilFaceEXT == GL_BACK */
+#define CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK 3
+#define CRSTATE_STENCIL_BUFFER_REF_COUNT 4
+
+typedef struct {
+ CRbitvalue dirty[CR_MAX_BITARRAY];
+ CRbitvalue enable[CR_MAX_BITARRAY];
+ CRbitvalue func[CR_MAX_BITARRAY];
+ CRbitvalue op[CR_MAX_BITARRAY];
+ CRbitvalue clearValue[CR_MAX_BITARRAY];
+ CRbitvalue writeMask[CR_MAX_BITARRAY];
+} CRStencilBits_v_33;
+
+typedef struct {
+ CRbitvalue func[CR_MAX_BITARRAY];
+ CRbitvalue op[CR_MAX_BITARRAY];
+} CRStencilBufferRefBits;
+
typedef struct {
- CRbitvalue dirty[CR_MAX_BITARRAY];
- CRbitvalue enable[CR_MAX_BITARRAY];
- CRbitvalue func[CR_MAX_BITARRAY];
- CRbitvalue op[CR_MAX_BITARRAY];
- CRbitvalue clearValue[CR_MAX_BITARRAY];
- CRbitvalue writeMask[CR_MAX_BITARRAY];
+ CRbitvalue dirty[CR_MAX_BITARRAY];
+ CRbitvalue enable[CR_MAX_BITARRAY];
+ CRbitvalue enableTwoSideEXT[CR_MAX_BITARRAY];
+ CRbitvalue activeStencilFace[CR_MAX_BITARRAY];
+ CRbitvalue clearValue[CR_MAX_BITARRAY];
+ CRbitvalue writeMask[CR_MAX_BITARRAY];
+ /* note: here we use _BUFFER_REF_ rather than _REF_ because we track the way buffers are accessed here,
+ * to ensure the correct function is called on hw->chromium state restoration,
+ * i.e. we want to avoid always calling StencilXxxSeparate, but call StencilXxx when it was actually called */
+ CRStencilBufferRefBits bufferRefs[CRSTATE_STENCIL_BUFFER_REF_COUNT];
} CRStencilBits;
typedef struct {
+ GLboolean stencilTest;
+ GLenum func;
+ GLint mask;
+ GLint ref;
+ GLenum fail;
+ GLenum passDepthFail;
+ GLenum passDepthPass;
+ GLint clearValue;
+ GLint writeMask;
+} CRStencilState_v_33;
+
+typedef struct {
+ GLenum func;
+ GLint mask;
+ GLint ref;
+ GLenum fail;
+ GLenum passDepthFail;
+ GLenum passDepthPass;
+} CRStencilBufferState;
+
+typedef struct {
+ /* true if stencil test is enabled */
GLboolean stencilTest;
- GLenum func;
- GLint mask;
- GLint ref;
- GLenum fail;
- GLenum passDepthFail;
- GLenum passDepthPass;
- GLint clearValue;
- GLint writeMask;
+ /* true if GL_EXT_stencil_two_side is enabled (glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)) */
+ GLboolean stencilTwoSideEXT;
+ /* GL_FRONT or GL_BACK */
+ GLenum activeStencilFace;
+ GLint clearValue;
+ GLint writeMask;
+ CRStencilBufferState buffers[CRSTATE_STENCIL_BUFFER_COUNT];
} CRStencilState;
DECLEXPORT(void) crStateStencilInit(CRContext *ctx);
+DECLEXPORT(void) crStateStencilBufferInit(CRStencilBufferState *s);
DECLEXPORT(void) crStateStencilDiff(CRStencilBits *bb, CRbitvalue *bitID,
CRContext *fromCtx, CRContext *toCtx);
diff --git a/src/VBox/GuestHost/OpenGL/include/state/cr_texture.h b/src/VBox/GuestHost/OpenGL/include/state/cr_texture.h
index 5d0262d4..c55d0da9 100644
--- a/src/VBox/GuestHost/OpenGL/include/state/cr_texture.h
+++ b/src/VBox/GuestHost/OpenGL/include/state/cr_texture.h
@@ -96,10 +96,8 @@ typedef struct {
CRbitvalue dirty[CR_MAX_BITARRAY];
CRbitvalue imageBit[CR_MAX_BITARRAY];
CRbitvalue paramsBit[CR_MAX_TEXTURE_UNITS][CR_MAX_BITARRAY];
-#ifndef IN_GUEST
/* bitfield representing the object usage. 1 means the object is used by the context with the given bitid */
CRbitvalue ctxUsage[CR_MAX_BITARRAY];
-#endif
} CRTextureObj;
typedef struct {
@@ -242,6 +240,8 @@ DECLEXPORT(GLuint) STATE_APIENTRY crStateTextureHWIDtoID(GLuint hwid);
DECLEXPORT(GLuint) STATE_APIENTRY crStateGetTextureHWID(GLuint id);
DECLEXPORT(GLuint) STATE_APIENTRY crStateGetTextureObjHWID(CRTextureObj *tobj);
+void crStateRegTextures(GLsizei n, GLuint *names);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/VBox/GuestHost/OpenGL/packer/opcodes.py b/src/VBox/GuestHost/OpenGL/packer/opcodes.py
index e198150b..f359d218 100644
--- a/src/VBox/GuestHost/OpenGL/packer/opcodes.py
+++ b/src/VBox/GuestHost/OpenGL/packer/opcodes.py
@@ -50,21 +50,50 @@ print "} CROpcode;\n"
# count up number of extended opcode commands
num_extends = 0
+num_auto_codes = 0
for func in keys:
if "extpack" in apiutil.ChromiumProps(func):
num_extends += 1
+ if apiutil.ChromiumRelOpCode(func) < 0:
+ num_auto_codes += 1
+
+# sanity check for compatibility breakage
+# we currently have 304
+if num_auto_codes != 304:
+ print >> sys.stderr, "number of auto-generated op-codes should be 304, but is " + str(num_auto_codes)
+ print >> sys.stderr, "which breaks backwards compatibility"
+ print >> sys.stderr, "if this is really what you want to do, please adjust this script"
+ print >> sys.stderr, "to handle a new auto-generated opcodes count"
+ print "#error -- num_auto_codes should be 304, but is " + str(num_auto_codes)
+ sys.exit(-1)
print "/* Functions with a return value or output parameters */"
print "typedef enum {"
+opcode_index = 0
enum_index = 0
+chrelopcodes = {}
for func in keys:
if "extpack" in apiutil.ChromiumProps(func):
opcodeName = apiutil.ExtendedOpcodeName(func)
+ chrelopcode = apiutil.ChromiumRelOpCode(func)
+ opcode = -1
+ if chrelopcode >= 0:
+ if not chrelopcode in chrelopcodes.keys():
+ chrelopcodes[chrelopcode] = chrelopcode
+ else:
+ print >> sys.stderr, "non-unique chrelopcode: " + str(chrelopcode)
+ print "#error -- non-unique chrelopcode: " + str(num_auto_codes)
+ sys.exit(-1)
+ opcode = num_auto_codes + chrelopcode
+ else:
+ opcode = opcode_index
+ opcode_index = opcode_index + 1
+
if enum_index != num_extends-1:
- print "\t%s = %d," % (opcodeName, enum_index )
+ print "\t%s = %d," % (opcodeName, opcode )
else:
- print "\t%s = %d" % (opcodeName, enum_index )
+ print "\t%s = %d" % (opcodeName, opcode )
enum_index = enum_index + 1
print "} CRExtendOpcode;\n"
print "#endif /* CR_OPCODES_H */"
diff --git a/src/VBox/GuestHost/OpenGL/packer/pack_buffer.c b/src/VBox/GuestHost/OpenGL/packer/pack_buffer.c
index 48d1250a..d4ddaf5f 100644
--- a/src/VBox/GuestHost/OpenGL/packer/pack_buffer.c
+++ b/src/VBox/GuestHost/OpenGL/packer/pack_buffer.c
@@ -149,7 +149,11 @@ void crPackResetPointers( CRPackContext *pc )
const GLboolean canBarf = pc->buffer.canBarf;
CRPackBuffer *buf = pc->currentBuffer;
CRASSERT(buf);
- crPackInitBuffer( buf, buf->pack, buf->size, buf->mtu );
+ crPackInitBuffer( buf, buf->pack, buf->size, buf->mtu
+#ifdef IN_RING0
+ , 0
+#endif
+ );
pc->buffer.geometry_only = geom_only; /* restore the flag */
pc->buffer.holds_BeginEnd = holds_BeginEnd;
pc->buffer.in_BeginEnd = in_BeginEnd;
@@ -221,9 +225,15 @@ crPackMaxData( int buffer_size )
* has 'mtu' bytes in it, we have to send it. The MTU might
* be somewhat smaller than the buffer size.
*/
-void crPackInitBuffer( CRPackBuffer *buf, void *pack, int size, int mtu )
+void crPackInitBuffer( CRPackBuffer *buf, void *pack, int size, int mtu
+#ifdef IN_RING0
+ , unsigned int num_opcodes
+#endif
+ )
{
+#ifndef IN_RING0
unsigned int num_opcodes;
+#endif
CRASSERT(mtu <= size);
@@ -231,7 +241,16 @@ void crPackInitBuffer( CRPackBuffer *buf, void *pack, int size, int mtu )
buf->mtu = mtu;
buf->pack = pack;
- num_opcodes = crPackMaxOpcodes( buf->size );
+#ifdef IN_RING0
+ if(num_opcodes)
+ {
+ num_opcodes = (num_opcodes + 0x3) & (~0x3);
+ }
+ else
+#endif
+ {
+ num_opcodes = crPackMaxOpcodes( buf->size );
+ }
buf->data_start =
(unsigned char *) buf->pack + num_opcodes + sizeof(CRMessageOpcodes);
diff --git a/src/VBox/GuestHost/OpenGL/packer/pack_extensions.c b/src/VBox/GuestHost/OpenGL/packer/pack_extensions.c
index 14b86a91..a8ae7fc4 100644
--- a/src/VBox/GuestHost/OpenGL/packer/pack_extensions.c
+++ b/src/VBox/GuestHost/OpenGL/packer/pack_extensions.c
@@ -6,8 +6,6 @@
#include "packer.h"
-#include <GL/glext.h>
-
int __packTexParameterNumParams( GLenum param )
{
switch( param )
diff --git a/src/VBox/GuestHost/OpenGL/packer/pack_framebuffer.c b/src/VBox/GuestHost/OpenGL/packer/pack_framebuffer.c
index ab904d37..bc1ab543 100644
--- a/src/VBox/GuestHost/OpenGL/packer/pack_framebuffer.c
+++ b/src/VBox/GuestHost/OpenGL/packer/pack_framebuffer.c
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2009 Oracle Corporation
+ * Copyright (C) 2009-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
diff --git a/src/VBox/GuestHost/OpenGL/packer/pack_misc.c b/src/VBox/GuestHost/OpenGL/packer/pack_misc.c
index 40da1223..ebc0e5bd 100644
--- a/src/VBox/GuestHost/OpenGL/packer/pack_misc.c
+++ b/src/VBox/GuestHost/OpenGL/packer/pack_misc.c
@@ -7,7 +7,7 @@
#include "packer.h"
#include "cr_error.h"
-void PACK_APIENTRY crPackChromiumParametervCR(GLenum target, GLenum type, GLsizei count, const GLvoid *values)
+void PACK_APIENTRY crPackChromiumParametervCR(CR_PACKER_CONTEXT_ARGDECL GLenum target, GLenum type, GLsizei count, const GLvoid *values)
{
CR_GET_PACKER_CONTEXT(pc);
unsigned int header_length = 2 * sizeof(int) + sizeof(target) + sizeof(type) + sizeof(count);
@@ -29,9 +29,11 @@ void PACK_APIENTRY crPackChromiumParametervCR(GLenum target, GLenum type, GLsize
case GL_UNSIGNED_INT:
params_length = sizeof(GLint) * count;
break;
+#ifndef IN_RING0
case GL_FLOAT:
params_length = sizeof(GLfloat) * count;
break;
+#endif
#if 0
case GL_DOUBLE:
params_length = sizeof(GLdouble) * count;
@@ -74,11 +76,13 @@ void PACK_APIENTRY crPackChromiumParametervCR(GLenum target, GLenum type, GLsize
WRITE_DATA( pos, GLint, ((GLint *) values)[i]);
}
break;
+#ifndef IN_RING0
case GL_FLOAT:
for (i = 0; i < count; i++, pos += sizeof(GLfloat)) {
WRITE_DATA( pos, GLfloat, ((GLfloat *) values)[i]);
}
break;
+#endif
#if 0
case GL_DOUBLE:
for (i = 0; i < count; i++) {
@@ -95,7 +99,8 @@ void PACK_APIENTRY crPackChromiumParametervCR(GLenum target, GLenum type, GLsize
CR_UNLOCK_PACKER_CONTEXT(pc);
}
-void PACK_APIENTRY crPackDeleteQueriesARB(GLsizei n, const GLuint * ids)
+#ifndef IN_RING0
+void PACK_APIENTRY crPackDeleteQueriesARB(CR_PACKER_CONTEXT_ARGDECL GLsizei n, const GLuint * ids)
{
unsigned char *data_ptr;
int packet_length = sizeof(GLenum)+sizeof(n)+n*sizeof(*ids);
@@ -107,3 +112,78 @@ void PACK_APIENTRY crPackDeleteQueriesARB(GLsizei n, const GLuint * ids)
crHugePacket(CR_EXTEND_OPCODE, data_ptr);
crPackFree(data_ptr);
}
+#endif
+
+void PACK_APIENTRY crPackVBoxTexPresent( CR_PACKER_CONTEXT_ARGDECL GLuint texture, GLuint cfg, GLint xPos, GLint yPos, GLint cRects, const GLint * pRects )
+{
+ GLint i, size, cnt;
+
+ CR_GET_PACKER_CONTEXT(pc);
+ unsigned char *data_ptr;
+ (void) pc;
+ size = 28 + cRects * 4 * sizeof(GLint);
+ CR_GET_BUFFERED_POINTER( pc, size );
+ WRITE_DATA( 0, GLint, size );
+ WRITE_DATA( 4, GLenum, CR_VBOXTEXPRESENT_EXTEND_OPCODE );
+ WRITE_DATA( 8, GLuint, texture );
+ WRITE_DATA( 12, GLuint, cfg );
+ WRITE_DATA( 16, GLint, xPos );
+ WRITE_DATA( 20, GLint, yPos );
+ WRITE_DATA( 24, GLint, cRects );
+
+ cnt = 28;
+ for (i=0; i<cRects; ++i)
+ {
+ WRITE_DATA(cnt, GLint, (GLint) pRects[4*i+0]);
+ WRITE_DATA(cnt+4, GLint, (GLint) pRects[4*i+1]);
+ WRITE_DATA(cnt+8, GLint, (GLint) pRects[4*i+2]);
+ WRITE_DATA(cnt+12, GLint, (GLint) pRects[4*i+3]);
+ cnt += 16;
+ }
+ WRITE_OPCODE( pc, CR_EXTEND_OPCODE );
+ CR_UNLOCK_PACKER_CONTEXT(pc);
+}
+
+void PACK_APIENTRY crPackWindowPosition( CR_PACKER_CONTEXT_ARGDECL GLint window, GLint x, GLint y )
+{
+ CR_GET_PACKER_CONTEXT(pc);
+ unsigned char *data_ptr;
+ (void) pc;
+ CR_GET_BUFFERED_POINTER( pc, 20 );
+ WRITE_DATA( 0, GLint, 20 );
+ WRITE_DATA( 4, GLenum, CR_WINDOWPOSITION_EXTEND_OPCODE );
+ WRITE_DATA( 8, GLint, window );
+ WRITE_DATA( 12, GLint, x );
+ WRITE_DATA( 16, GLint, y );
+ WRITE_OPCODE( pc, CR_EXTEND_OPCODE );
+ CR_UNLOCK_PACKER_CONTEXT(pc);
+}
+
+void PACK_APIENTRY crPackWindowShow( CR_PACKER_CONTEXT_ARGDECL GLint window, GLint flag )
+{
+ CR_GET_PACKER_CONTEXT(pc);
+ unsigned char *data_ptr;
+ (void) pc;
+ CR_GET_BUFFERED_POINTER( pc, 16 );
+ WRITE_DATA( 0, GLint, 16 );
+ WRITE_DATA( 4, GLenum, CR_WINDOWSHOW_EXTEND_OPCODE );
+ WRITE_DATA( 8, GLint, window );
+ WRITE_DATA( 12, GLint, flag );
+ WRITE_OPCODE( pc, CR_EXTEND_OPCODE );
+ CR_UNLOCK_PACKER_CONTEXT(pc);
+}
+
+void PACK_APIENTRY crPackWindowSize( CR_PACKER_CONTEXT_ARGDECL GLint window, GLint w, GLint h )
+{
+ CR_GET_PACKER_CONTEXT(pc);
+ unsigned char *data_ptr;
+ (void) pc;
+ CR_GET_BUFFERED_POINTER( pc, 20 );
+ WRITE_DATA( 0, GLint, 20 );
+ WRITE_DATA( 4, GLenum, CR_WINDOWSIZE_EXTEND_OPCODE );
+ WRITE_DATA( 8, GLint, window );
+ WRITE_DATA( 12, GLint, w );
+ WRITE_DATA( 16, GLint, h );
+ WRITE_OPCODE( pc, CR_EXTEND_OPCODE );
+ CR_UNLOCK_PACKER_CONTEXT(pc);
+}
diff --git a/src/VBox/GuestHost/OpenGL/packer/pack_pixels.c b/src/VBox/GuestHost/OpenGL/packer/pack_pixels.c
index 19f2a1d5..2508643a 100644
--- a/src/VBox/GuestHost/OpenGL/packer/pack_pixels.c
+++ b/src/VBox/GuestHost/OpenGL/packer/pack_pixels.c
@@ -143,7 +143,8 @@ void PACK_APIENTRY crPackBitmap(GLsizei width, GLsizei height,
WRITE_DATA( 24, GLuint, noimagedata );
WRITE_DATA( 28, GLint, (GLint) (uintptr_t) bitmap);
- crBitmapCopy(width, height, (GLubyte *)(data_ptr + 32), bitmap, unpack);
+ if (!noimagedata)
+ crBitmapCopy(width, height, (GLubyte *)(data_ptr + 32), bitmap, unpack);
crHugePacket( CR_BITMAP_OPCODE, data_ptr );
crPackFree( data_ptr );
diff --git a/src/VBox/GuestHost/OpenGL/packer/pack_shaders.c b/src/VBox/GuestHost/OpenGL/packer/pack_shaders.c
index 36fc6bea..b788bd4d 100644
--- a/src/VBox/GuestHost/OpenGL/packer/pack_shaders.c
+++ b/src/VBox/GuestHost/OpenGL/packer/pack_shaders.c
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2009 Oracle Corporation
+ * Copyright (C) 2009-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -52,7 +52,7 @@ void PACK_APIENTRY crPackShaderSource(GLuint shader, GLsizei count, const char *
for (i=0; i<count; ++i)
{
- pLocalLength[i] = (length && (length[i]>=0)) ? length[i] : crStrlen(string[i])+1;
+ pLocalLength[i] = ((length && (length[i]>=0)) ? length[i] : crStrlen(string[i]))+1;
packet_length += pLocalLength[i];
}
@@ -80,7 +80,17 @@ void PACK_APIENTRY crPackShaderSource(GLuint shader, GLsizei count, const char *
{
if (string[i])
{
- crMemcpy(data_ptr, string[i], pLocalLength[i]);
+ if (length && (length[i]>=0))
+ {
+ /* include \0 in the string to make intel drivers happy */
+ crMemcpy(data_ptr, string[i], pLocalLength[i] - 1);
+ data_ptr[pLocalLength[i] - 1] = '\0';
+ }
+ else
+ {
+ /* the \0 s already in the string */
+ crMemcpy(data_ptr, string[i], pLocalLength[i]);
+ }
}
else
{
@@ -458,7 +468,7 @@ void PACK_APIENTRY crPackGetAttachedShaders(GLuint program, GLsizei maxCount, GL
CR_UNLOCK_PACKER_CONTEXT(pc);
}
-void PACK_APIENTRY crPackGetAttachedObjectsARB(GLhandleARB containerObj, GLsizei maxCount, GLsizei * count, GLhandleARB * obj, int * writeback)
+void PACK_APIENTRY crPackGetAttachedObjectsARB(VBoxGLhandleARB containerObj, GLsizei maxCount, GLsizei * count, VBoxGLhandleARB * obj, int * writeback)
{
CR_GET_PACKER_CONTEXT(pc);
unsigned char *data_ptr;
@@ -466,7 +476,7 @@ void PACK_APIENTRY crPackGetAttachedObjectsARB(GLhandleARB containerObj, GLsizei
CR_GET_BUFFERED_POINTER(pc, 32);
WRITE_DATA(0, GLint, 32);
WRITE_DATA(4, GLenum, CR_GETATTACHEDOBJECTSARB_EXTEND_OPCODE);
- WRITE_DATA(8, GLhandleARB, containerObj);
+ WRITE_DATA(8, VBoxGLhandleARB, containerObj);
WRITE_DATA(12, GLsizei, maxCount);
WRITE_NETWORK_POINTER(16, (void *) count);
WRITE_NETWORK_POINTER(24, (void *) writeback);
@@ -474,7 +484,7 @@ void PACK_APIENTRY crPackGetAttachedObjectsARB(GLhandleARB containerObj, GLsizei
CR_UNLOCK_PACKER_CONTEXT(pc);
}
-void PACK_APIENTRY crPackGetInfoLogARB(GLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * infoLog, int * writeback)
+void PACK_APIENTRY crPackGetInfoLogARB(VBoxGLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * infoLog, int * writeback)
{
CR_GET_PACKER_CONTEXT(pc);
unsigned char *data_ptr;
@@ -482,7 +492,7 @@ void PACK_APIENTRY crPackGetInfoLogARB(GLhandleARB obj, GLsizei maxLength, GLsiz
CR_GET_BUFFERED_POINTER(pc, 32);
WRITE_DATA(0, GLint, 32);
WRITE_DATA(4, GLenum, CR_GETINFOLOGARB_EXTEND_OPCODE);
- WRITE_DATA(8, GLhandleARB, obj);
+ WRITE_DATA(8, VBoxGLhandleARB, obj);
WRITE_DATA(12, GLsizei, maxLength);
WRITE_NETWORK_POINTER(16, (void *) length);
WRITE_NETWORK_POINTER(24, (void *) writeback);
diff --git a/src/VBox/GuestHost/OpenGL/packer/pack_visibleregion.c b/src/VBox/GuestHost/OpenGL/packer/pack_visibleregion.c
index d76fc29c..e0155fc7 100644
--- a/src/VBox/GuestHost/OpenGL/packer/pack_visibleregion.c
+++ b/src/VBox/GuestHost/OpenGL/packer/pack_visibleregion.c
@@ -3,7 +3,7 @@
*/
/*
- * Copyright (C) 2008 Oracle Corporation
+ * Copyright (C) 2008-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -22,7 +22,7 @@
#include <windows.h>
#endif
-void PACK_APIENTRY crPackWindowVisibleRegion( GLint window, GLint cRects, GLint * pRects )
+void PACK_APIENTRY crPackWindowVisibleRegion( CR_PACKER_CONTEXT_ARGDECL GLint window, GLint cRects, const GLint * pRects )
{
GLint i, size, cnt;
@@ -49,7 +49,7 @@ void PACK_APIENTRY crPackWindowVisibleRegion( GLint window, GLint cRects, GLint
CR_UNLOCK_PACKER_CONTEXT(pc);
}
-void PACK_APIENTRY crPackWindowVisibleRegionSWAP( GLint window, GLint cRects, GLint * pRects )
+void PACK_APIENTRY crPackWindowVisibleRegionSWAP( CR_PACKER_CONTEXT_ARGDECL GLint window, GLint cRects, const GLint * pRects )
{
crError( "crPackWindowVisibleRegionSWAP unimplemented and shouldn't be called" );
}
diff --git a/src/VBox/GuestHost/OpenGL/packer/packer.h b/src/VBox/GuestHost/OpenGL/packer/packer.h
index 965799a0..f70a5bb4 100644
--- a/src/VBox/GuestHost/OpenGL/packer/packer.h
+++ b/src/VBox/GuestHost/OpenGL/packer/packer.h
@@ -18,6 +18,10 @@
#include "packer_extensions.h"
#include "cr_mem.h"
+#ifndef IN_RING0
extern void __PackError( int line, const char *file, GLenum error, const char *info );
+#else
+# define __PackError( line, file, error, info) do { AssertReleaseFailed(); } while (0)
+#endif
#endif /* CR_PACKER_H */
diff --git a/src/VBox/GuestHost/OpenGL/packer/packer.py b/src/VBox/GuestHost/OpenGL/packer/packer.py
index a2708438..386b6bec 100644
--- a/src/VBox/GuestHost/OpenGL/packer/packer.py
+++ b/src/VBox/GuestHost/OpenGL/packer/packer.py
@@ -113,9 +113,9 @@ def UpdateCurrentPointer( func_name ):
def PrintFunc( func_name, params, is_swapped, can_have_pointers ):
"""Emit a packer function."""
if is_swapped:
- print 'void PACK_APIENTRY crPack%sSWAP( %s )' % (func_name, apiutil.MakeDeclarationString(params))
+ print 'void PACK_APIENTRY crPack%sSWAP( %s )' % (func_name, apiutil.MakeDeclarationStringWithContext('CR_PACKER_CONTEXT', params))
else:
- print 'void PACK_APIENTRY crPack%s( %s )' % (func_name, apiutil.MakeDeclarationString(params))
+ print 'void PACK_APIENTRY crPack%s( %s )' % (func_name, apiutil.MakeDeclarationStringWithContext('CR_PACKER_CONTEXT', params))
print '{'
print '\tCR_GET_PACKER_CONTEXT(pc);'
diff --git a/src/VBox/GuestHost/OpenGL/packer/packer_special b/src/VBox/GuestHost/OpenGL/packer/packer_special
index 848a05c5..b37cf2f3 100644
--- a/src/VBox/GuestHost/OpenGL/packer/packer_special
+++ b/src/VBox/GuestHost/OpenGL/packer/packer_special
@@ -176,3 +176,7 @@ UniformMatrix2x4fv
UniformMatrix4x2fv
UniformMatrix3x4fv
UniformMatrix4x3fv
+VBoxTexPresent
+WindowPosition
+WindowShow
+WindowSize
diff --git a/src/VBox/GuestHost/OpenGL/spu_loader/glloader.py b/src/VBox/GuestHost/OpenGL/spu_loader/glloader.py
index 0eb78aa2..a84f7299 100644
--- a/src/VBox/GuestHost/OpenGL/spu_loader/glloader.py
+++ b/src/VBox/GuestHost/OpenGL/spu_loader/glloader.py
@@ -65,10 +65,6 @@ static CRDLL *aglDll = NULL;
#define GLLOADER_APIENTRY
#endif
-#if defined(WINDOWS) && (defined(DEBUG_leo) || defined(DEBUG_ll158262) || defined(DEBUG_misha))
-# define CR_NO_GL_SYSTEM_PATH 1
-#endif
-
/*
* Add an entry to the SPUNamedFunctionTable
*/
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/dump.cpp b/src/VBox/GuestHost/OpenGL/state_tracker/dump.cpp
new file mode 100644
index 00000000..8132d9f9
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/dump.cpp
@@ -0,0 +1,1741 @@
+/* $Id: dump.cpp $ */
+
+/** @file
+ * Blitter API implementation
+ */
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+#include "cr_blitter.h"
+#include "cr_spu.h"
+#include "chromium.h"
+#include "cr_error.h"
+#include "cr_net.h"
+#include "cr_rand.h"
+#include "cr_mem.h"
+#include "cr_string.h"
+#include <cr_dump.h>
+#include "cr_pixeldata.h"
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/mem.h>
+
+#include <stdio.h>
+
+#ifdef VBOX_WITH_CRDUMPER
+
+static uint32_t g_CrDbgDumpRecTexInfo = 1;
+static uint32_t g_CrDbgDumpAlphaData = 1;
+
+/* dump stuff */
+#pragma pack(1)
+typedef struct VBOX_BITMAPFILEHEADER {
+ uint16_t bfType;
+ uint32_t bfSize;
+ uint16_t bfReserved1;
+ uint16_t bfReserved2;
+ uint32_t bfOffBits;
+} VBOX_BITMAPFILEHEADER;
+
+typedef struct VBOX_BITMAPINFOHEADER {
+ uint32_t biSize;
+ int32_t biWidth;
+ int32_t biHeight;
+ uint16_t biPlanes;
+ uint16_t biBitCount;
+ uint32_t biCompression;
+ uint32_t biSizeImage;
+ int32_t biXPelsPerMeter;
+ int32_t biYPelsPerMeter;
+ uint32_t biClrUsed;
+ uint32_t biClrImportant;
+} VBOX_BITMAPINFOHEADER;
+#pragma pack()
+
+void crDmpImgBmp(CR_BLITTER_IMG *pImg, const char *pszFilename)
+{
+ static int sIdx = 0;
+
+ if ( pImg->bpp != 16
+ && pImg->bpp != 24
+ && pImg->bpp != 32)
+ {
+ crWarning("not supported bpp %d", pImg->bpp);
+ return;
+ }
+
+ FILE *f = fopen (pszFilename, "wb");
+ if (!f)
+ {
+ crWarning("fopen failed");
+ return;
+ }
+
+ VBOX_BITMAPFILEHEADER bf;
+
+ bf.bfType = 'MB';
+ bf.bfSize = sizeof (VBOX_BITMAPFILEHEADER) + sizeof (VBOX_BITMAPINFOHEADER) + pImg->cbData;
+ bf.bfReserved1 = 0;
+ bf.bfReserved2 = 0;
+ bf.bfOffBits = sizeof (VBOX_BITMAPFILEHEADER) + sizeof (VBOX_BITMAPINFOHEADER);
+
+ VBOX_BITMAPINFOHEADER bi;
+
+ bi.biSize = sizeof (bi);
+ bi.biWidth = pImg->width;
+ bi.biHeight = pImg->height;
+ bi.biPlanes = 1;
+ bi.biBitCount = pImg->bpp;
+ bi.biCompression = 0;
+ bi.biSizeImage = pImg->cbData;
+ bi.biXPelsPerMeter = 0;
+ bi.biYPelsPerMeter = 0;
+ bi.biClrUsed = 0;
+ bi.biClrImportant = 0;
+
+ fwrite (&bf, 1, sizeof (bf), f);
+ fwrite (&bi, 1, sizeof (bi), f);
+ fwrite (pImg->pvData, 1, pImg->cbData, f);
+
+ fclose (f);
+}
+
+typedef struct CRDUMPGETHWID_DATA
+{
+ GLuint hwid;
+ PFNCRDUMPGETHWID pfnGetHwid;
+ unsigned long Key;
+ void* pvObj;
+} CRDUMPGETHWID_DATA;
+
+static void crDmpHashtableSearchByHwidCB(unsigned long key, void *pData1, void *pData2)
+{
+ CRDUMPGETHWID_DATA *pData = (CRDUMPGETHWID_DATA*)pData2;
+ if (pData->pvObj)
+ return;
+
+ if (pData->hwid == pData->pfnGetHwid(pData1))
+ {
+ pData->Key = key;
+ pData->pvObj = pData1;
+ }
+}
+
+void* crDmpHashtableSearchByHwid(CRHashTable *pHash, GLuint hwid, PFNCRDUMPGETHWID pfnGetHwid, unsigned long *pKey)
+{
+ CRDUMPGETHWID_DATA Data = {0};
+ Data.hwid = hwid;
+ Data.pfnGetHwid = pfnGetHwid;
+ crHashtableWalk(pHash, crDmpHashtableSearchByHwidCB, &Data);
+
+ Assert(Data.pvObj);
+
+ if (pKey)
+ *pKey = Data.Key;
+ return Data.pvObj;
+}
+
+#if 0
+typedef struct CR_SERVER_DUMP_FIND_TEX
+{
+ GLint hwid;
+ CRTextureObj *pTobj
+} CR_SERVER_DUMP_FIND_TEX;
+
+void crServerDumpFindTexCb(unsigned long key, void *pData1, void *pData2)
+{
+ CR_SERVER_DUMP_FIND_TEX *pTex = (CR_SERVER_DUMP_FIND_TEX*)pData2;
+ CRTextureObj *pTobj = (CRTextureObj *)pData1;
+ if (pTobj->hwid == pTex->hwid)
+ pTex->pTobj = pTobj;
+}
+#endif
+
+#define CR_DUMP_MAKE_CASE(_val) case _val: return #_val
+#define CR_DUMP_MAKE_CASE_UNKNOWN(_val, _str, _pDumper) default: { \
+ crWarning("%s %d", (_str), _val); \
+ crDmpStrF((_pDumper), "WARNING: %s %d", (_str), _val); \
+ return (_str); \
+}
+
+DECLINLINE(size_t) crDmpFormatVal(char *pString, size_t cbString, const char *pszElFormat, uint32_t cbVal, const void *pvVal)
+{
+ if (pszElFormat[0] != '%' || pszElFormat[1] == '\0')
+ {
+ crWarning("invalid format %s", pszElFormat);
+ return 0;
+ }
+ switch (cbVal)
+ {
+ case 8:
+ return sprintf_s(pString, cbString, pszElFormat, *((double*)pvVal));
+ case 4:
+ {
+ /* we do not care only about type specifiers, all the rest is not accepted */
+ switch (pszElFormat[1])
+ {
+ case 'f':
+ /* float would be promoted to double */
+ return sprintf_s(pString, cbString, pszElFormat, *((float*)pvVal));
+ default:
+ return sprintf_s(pString, cbString, pszElFormat, *((uint32_t*)pvVal));
+ }
+ }
+ case 2:
+ return sprintf_s(pString, cbString, pszElFormat, *((uint16_t*)pvVal));
+ case 1:
+ return sprintf_s(pString, cbString, pszElFormat, *((uint8_t*)pvVal));
+ default:
+ crWarning("unsupported size %d", cbVal);
+ return 0;
+ }
+}
+
+VBOXDUMPDECL(size_t) crDmpFormatRawArray(char *pString, size_t cbString, const char *pszElFormat, uint32_t cbEl, const void *pvVal, uint32_t cVal)
+{
+ if (cbString < 2)
+ {
+ crWarning("too few buffer size");
+ return 0;
+ }
+
+ const size_t cbInitString = cbString;
+ *pString++ = '{';
+ --cbString;
+ size_t cbWritten;
+ const uint8_t *pu8Val = (const uint8_t *)pvVal;
+ for (uint32_t i = 0; i < cVal; ++i)
+ {
+ cbWritten = crDmpFormatVal(pString, cbString, pszElFormat, cbEl, (const void *)pu8Val);
+ pu8Val += cbEl;
+ Assert(cbString >= cbWritten);
+ pString += cbWritten;
+ cbString -= cbWritten;
+ if (i != cVal - 1)
+ {
+ cbWritten = sprintf_s(pString, cbString, ", ");
+ Assert(cbString >= cbWritten);
+ pString += cbWritten;
+ cbString -= cbWritten;
+ }
+ }
+
+ if (!cbString)
+ {
+ crWarning("too few buffer size");
+ return 0;
+ }
+ *pString++ = '}';
+ --cbString;
+
+ if (!cbString)
+ {
+ crWarning("too few buffer size");
+ return 0;
+ }
+ *pString++ = '\0';
+
+ return cbInitString - cbString;
+}
+
+VBOXDUMPDECL(size_t) crDmpFormatMatrixArray(char *pString, size_t cbString, const char *pszElFormat, uint32_t cbEl, const void *pvVal, uint32_t cX, uint32_t cY)
+{
+ if (cbString < 2)
+ {
+ crWarning("too few buffer size");
+ return 0;
+ }
+
+ const size_t cbInitString = cbString;
+ *pString++ = '{';
+ --cbString;
+ size_t cbWritten;
+ const uint8_t *pu8Val = (const uint8_t *)pvVal;
+ for (uint32_t i = 0; i < cY; ++i)
+ {
+ cbWritten = crDmpFormatRawArray(pString, cbString, pszElFormat, cbEl, (const void *)pu8Val, cX);
+ pu8Val += (cbEl * cX);
+ Assert(cbString >= cbWritten);
+ pString += cbWritten;
+ cbString -= cbWritten;
+ if (i != cY - 1)
+ {
+ if (cbString < 3)
+ {
+ crWarning("too few buffer size");
+ return 0;
+ }
+ *pString++ = ',';
+ --cbString;
+ *pString++ = '\n';
+ --cbString;
+ }
+ }
+ if (!cbString)
+ {
+ crWarning("too few buffer size");
+ return 0;
+ }
+ *pString++ = '}';
+ --cbString;
+
+ if (!cbString)
+ {
+ crWarning("too few buffer size");
+ return 0;
+ }
+ *pString++ = '\0';
+
+ return cbInitString - cbString;
+}
+
+VBOXDUMPDECL(size_t) crDmpFormatArray(char *pString, size_t cbString, const char *pszElFormat, uint32_t cbEl, const void *pvVal, uint32_t cVal)
+{
+ switch(cVal)
+ {
+ case 1:
+ return crDmpFormatVal(pString, cbString, pszElFormat, cbEl, pvVal);
+ case 16:
+ return crDmpFormatMatrixArray(pString, cbString, pszElFormat, cbEl, pvVal, 4, 4);
+ case 9:
+ return crDmpFormatMatrixArray(pString, cbString, pszElFormat, cbEl, pvVal, 3, 3);
+ case 0:
+ crWarning("value array is empty");
+ return 0;
+ default:
+ return crDmpFormatRawArray(pString, cbString, pszElFormat, cbEl, pvVal, cVal);
+ }
+}
+
+VBOXDUMPDECL(void) crRecDumpVertAttrv(CR_RECORDER *pRec, CRContext *ctx, GLuint idx, const char*pszElFormat, uint32_t cbEl, const void *pvVal, uint32_t cVal)
+{
+ char aBuf[1024];
+ crDmpFormatRawArray(aBuf, sizeof (aBuf), pszElFormat, cbEl, pvVal, cVal);
+ crDmpStrF(pRec->pDumper, "(%u, %s)", idx, aBuf);
+}
+
+VBOXDUMPDECL(void) crRecDumpVertAttrV(CR_RECORDER *pRec, CRContext *ctx, const char*pszFormat, va_list pArgList)
+{
+ crDmpStrV(pRec->pDumper, pszFormat, pArgList);
+}
+
+VBOXDUMPDECL(void) crRecDumpVertAttrF(CR_RECORDER *pRec, CRContext *ctx, const char*pszFormat, ...)
+{
+ va_list pArgList;
+ va_start(pArgList, pszFormat);
+ crRecDumpVertAttrV(pRec, ctx, pszFormat, pArgList);
+ va_end(pArgList);
+}
+
+void crRecDumpBuffer(CR_RECORDER *pRec, CRContext *ctx, GLint idRedirFBO, VBOXVR_TEXTURE *pRedirTex)
+{
+ GLenum texTarget = 0;
+ GLint hwBuf = 0, hwDrawBuf = 0;
+ GLint hwTex = 0, hwObjType = 0, hwTexLevel = 0, hwCubeFace = 0;
+ GLint width = 0, height = 0, depth = 0;
+ GLint id = 0;
+ CR_BLITTER_IMG Img = {0};
+ VBOXVR_TEXTURE Tex;
+ int rc;
+
+ pRec->pDispatch->GetIntegerv(GL_DRAW_BUFFER, &hwDrawBuf);
+ pRec->pDispatch->GetIntegerv(GL_FRAMEBUFFER_BINDING, &hwBuf);
+ if (hwBuf)
+ {
+ pRec->pDispatch->GetFramebufferAttachmentParameterivEXT(GL_DRAW_FRAMEBUFFER, hwDrawBuf, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &hwTex);
+ pRec->pDispatch->GetFramebufferAttachmentParameterivEXT(GL_DRAW_FRAMEBUFFER, hwDrawBuf, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &hwObjType);
+ if (hwObjType == GL_TEXTURE)
+ {
+ pRec->pDispatch->GetFramebufferAttachmentParameterivEXT(GL_DRAW_FRAMEBUFFER, hwDrawBuf, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, &hwTexLevel);
+ pRec->pDispatch->GetFramebufferAttachmentParameterivEXT(GL_DRAW_FRAMEBUFFER, hwDrawBuf, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, &hwCubeFace);
+ if (hwCubeFace)
+ {
+ crWarning("cube face: unsupported");
+ return;
+ }
+
+ if (hwTexLevel)
+ {
+ crWarning("non-zero tex level attached, unsupported");
+ return;
+ }
+ }
+ else
+ {
+ crWarning("unsupported");
+ return;
+ }
+ }
+ else
+ {
+ crWarning("no buffer attached: unsupported");
+ return;
+ }
+
+ if (ctx->framebufferobject.drawFB)
+ {
+ GLuint iColor = (hwDrawBuf - GL_COLOR_ATTACHMENT0_EXT);
+ CRTextureObj *pTobj = (CRTextureObj *)crHashtableSearch(ctx->shared->textureTable, ctx->framebufferobject.drawFB->color[iColor].name);
+ CRTextureLevel *pTl = NULL;
+
+ id = pTobj->id;
+
+ Assert(iColor < RT_ELEMENTS(ctx->framebufferobject.drawFB->color));
+
+ if (!pTobj)
+ {
+ crWarning("no tobj");
+ return;
+ }
+ Assert(pTobj->hwid == hwTex);
+ Assert(pTobj);
+ Assert(ctx->framebufferobject.drawFB->hwid);
+ Assert(ctx->framebufferobject.drawFB->hwid == hwBuf);
+ Assert(ctx->framebufferobject.drawFB->drawbuffer[0] == hwDrawBuf);
+
+ Assert(ctx->framebufferobject.drawFB->color[iColor].level == hwTexLevel);
+ Assert(ctx->framebufferobject.drawFB->color[iColor].type == hwObjType);
+
+ texTarget = pTobj->target;
+
+ Assert(texTarget == GL_TEXTURE_2D);
+
+ pTl = &pTobj->level[0][hwTexLevel];
+
+ rc = CrBltEnter(pRec->pBlitter);
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("CrBltEnter failed, rc %d", rc);
+ return;
+ }
+
+ pRec->pDispatch->BindTexture(texTarget, hwTex);
+
+ pRec->pDispatch->GetTexLevelParameteriv(texTarget, hwTexLevel, GL_TEXTURE_WIDTH, &width);
+ pRec->pDispatch->GetTexLevelParameteriv(texTarget, hwTexLevel, GL_TEXTURE_HEIGHT, &height);
+ pRec->pDispatch->GetTexLevelParameteriv(texTarget, hwTexLevel, GL_TEXTURE_DEPTH, &depth);
+
+ Assert(width == pTl->width);
+ Assert(height == pTl->height);
+ Assert(depth == pTl->depth);
+
+ pRec->pDispatch->BindTexture(texTarget, 0);
+ }
+ else
+ {
+ Assert(hwBuf == idRedirFBO);
+ if (!pRedirTex)
+ {
+ crWarning("pRedirTex is expected for non-FBO state!");
+ return;
+ }
+
+ Assert(hwTex == pRedirTex->hwid);
+
+ texTarget = pRedirTex->target;
+
+ width = pRedirTex->width;
+ height = pRedirTex->height;
+
+ rc = CrBltEnter(pRec->pBlitter);
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("CrBltEnter failed, rc %d", rc);
+ return;
+ }
+ }
+
+ Tex.width = width;
+ Tex.height = height;
+ Tex.target = texTarget;
+ Tex.hwid = hwTex;
+
+ rc = CrBltImgGetTex(pRec->pBlitter, &Tex, GL_BGRA, &Img);
+ if (RT_SUCCESS(rc))
+ {
+ crDmpImgF(pRec->pDumper, &Img, "ctx(%d), BUFFER: id(%d) hwid(%d), width(%d), height(%d)", ctx, id, Tex.hwid, width, height);
+
+ if (g_CrDbgDumpAlphaData)
+ {
+ CR_BLITTER_IMG AlphaImg = {0};
+ rc = crRecAlphaImgCreate(&Img, &AlphaImg);
+ if (RT_SUCCESS(rc))
+ {
+ crDmpImgF(pRec->pDumper, &AlphaImg, "Buffer ALPHA Data");
+ crRecAlphaImgDestroy(&AlphaImg);
+ }
+ else
+ {
+ crWarning("crRecAlphaImgCreate failed rc %d", rc);
+ }
+ }
+
+ CrBltImgFree(pRec->pBlitter, &Img);
+ }
+ else
+ {
+ crWarning("CrBltImgGetTex failed, rc %d", rc);
+ }
+
+ CrBltLeave(pRec->pBlitter);
+}
+
+static const char *crRecDumpShaderTypeString(GLenum enmType, CR_DUMPER *pDumper)
+{
+ switch (enmType)
+ {
+ CR_DUMP_MAKE_CASE(GL_VERTEX_SHADER_ARB);
+ CR_DUMP_MAKE_CASE(GL_FRAGMENT_SHADER_ARB);
+ CR_DUMP_MAKE_CASE(GL_GEOMETRY_SHADER_ARB);
+ CR_DUMP_MAKE_CASE_UNKNOWN(enmType, "Unknown Shader Type", pDumper);
+ }
+}
+
+static const char *crRecDumpVarTypeString(GLenum enmType, CR_DUMPER *pDumper)
+{
+ switch (enmType)
+ {
+ CR_DUMP_MAKE_CASE(GL_BYTE);
+ CR_DUMP_MAKE_CASE(GL_UNSIGNED_BYTE);
+ CR_DUMP_MAKE_CASE(GL_SHORT);
+ CR_DUMP_MAKE_CASE(GL_UNSIGNED_SHORT);
+ CR_DUMP_MAKE_CASE(GL_FLOAT);
+ CR_DUMP_MAKE_CASE(GL_DOUBLE);
+ CR_DUMP_MAKE_CASE(GL_FLOAT_VEC2);
+ CR_DUMP_MAKE_CASE(GL_FLOAT_VEC3);
+ CR_DUMP_MAKE_CASE(GL_FLOAT_VEC4);
+ CR_DUMP_MAKE_CASE(GL_INT);
+ CR_DUMP_MAKE_CASE(GL_UNSIGNED_INT);
+ CR_DUMP_MAKE_CASE(GL_INT_VEC2);
+ CR_DUMP_MAKE_CASE(GL_INT_VEC3);
+ CR_DUMP_MAKE_CASE(GL_INT_VEC4);
+ CR_DUMP_MAKE_CASE(GL_BOOL);
+ CR_DUMP_MAKE_CASE(GL_BOOL_VEC2);
+ CR_DUMP_MAKE_CASE(GL_BOOL_VEC3);
+ CR_DUMP_MAKE_CASE(GL_BOOL_VEC4);
+ CR_DUMP_MAKE_CASE(GL_FLOAT_MAT2);
+ CR_DUMP_MAKE_CASE(GL_FLOAT_MAT3);
+ CR_DUMP_MAKE_CASE(GL_FLOAT_MAT4);
+ CR_DUMP_MAKE_CASE(GL_SAMPLER_1D);
+ CR_DUMP_MAKE_CASE(GL_SAMPLER_2D);
+ CR_DUMP_MAKE_CASE(GL_SAMPLER_3D);
+ CR_DUMP_MAKE_CASE(GL_SAMPLER_CUBE);
+ CR_DUMP_MAKE_CASE(GL_SAMPLER_1D_SHADOW);
+ CR_DUMP_MAKE_CASE(GL_SAMPLER_2D_SHADOW);
+ CR_DUMP_MAKE_CASE(GL_SAMPLER_2D_RECT_ARB);
+ CR_DUMP_MAKE_CASE(GL_SAMPLER_2D_RECT_SHADOW_ARB);
+ CR_DUMP_MAKE_CASE(GL_FLOAT_MAT2x3);
+ CR_DUMP_MAKE_CASE(GL_FLOAT_MAT2x4);
+ CR_DUMP_MAKE_CASE(GL_FLOAT_MAT3x2);
+ CR_DUMP_MAKE_CASE(GL_FLOAT_MAT3x4);
+ CR_DUMP_MAKE_CASE(GL_FLOAT_MAT4x2);
+ CR_DUMP_MAKE_CASE(GL_FLOAT_MAT4x3);
+ CR_DUMP_MAKE_CASE_UNKNOWN(enmType, "Unknown Variable Type", pDumper);
+ }
+}
+
+static char *crRecDumpGetLine(char **ppszStr, uint32_t *pcbStr)
+{
+ char *pszStr, *pNewLine;
+ const uint32_t cbStr = *pcbStr;
+
+ if (!cbStr)
+ {
+ /* zero-length string */
+ return NULL;
+ }
+
+ if ((*ppszStr)[cbStr-1] != '\0')
+ {
+ crWarning("string should be null-rerminated, forcing it!");
+ (*ppszStr)[cbStr-1] = '\0';
+ }
+ pszStr = *ppszStr;
+ if (!*pszStr)
+ {
+ *pcbStr = 0;
+ return NULL;
+ }
+
+ if (!(pNewLine = strstr(pszStr, "\n")))
+ {
+ /* the string contains a single line! */
+ *ppszStr += strlen(pszStr);
+ *pcbStr = 0;
+ return pszStr;
+ }
+
+ *pNewLine = '\0';
+ *pcbStr = cbStr - (((uintptr_t)pNewLine) - ((uintptr_t)pszStr)) - 1;
+ Assert((*pcbStr) < UINT32_MAX/2);
+ Assert((*pcbStr) < cbStr);
+ *ppszStr = pNewLine + 1;
+
+ return pszStr;
+}
+
+static void crRecDumpStrByLine(CR_DUMPER *pDumper, char *pszStr, uint32_t cbStr)
+{
+ char *pszCurLine;
+ while ((pszCurLine = crRecDumpGetLine(&pszStr, &cbStr)) != NULL)
+ {
+ crDmpStrF(pDumper, "%s", pszCurLine);
+ }
+}
+
+static DECLCALLBACK(GLuint) crDmpGetHwidShaderCB(void *pvObj)
+{
+ return ((CRGLSLShader*)pvObj)->hwid;
+}
+
+static DECLCALLBACK(GLuint) crDmpGetHwidProgramCB(void *pvObj)
+{
+ return ((CRGLSLProgram*)pvObj)->hwid;
+}
+
+/* Context activation is done by the caller. */
+void crRecDumpLog(CR_RECORDER *pRec, GLint hwid)
+{
+ GLint cbLog = 0;
+ pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_INFO_LOG_LENGTH_ARB, &cbLog);
+
+ crDmpStrF(pRec->pDumper, "Log===%d===", hwid);
+
+ if (cbLog > 1)
+ {
+ GLchar *pszLog = (GLchar *) crAlloc(cbLog*sizeof (GLchar));
+
+ pRec->pDispatch->GetInfoLogARB(hwid, cbLog, NULL, pszLog);
+
+ crRecDumpStrByLine(pRec->pDumper, pszLog, cbLog);
+
+ crFree(pszLog);
+ }
+ crDmpStrF(pRec->pDumper, "End Log======");
+}
+
+void crRecDumpShader(CR_RECORDER *pRec, CRContext *ctx, GLint id, GLint hwid)
+{
+ GLint length = 0;
+ GLint type = 0;
+ GLint compileStatus = 0;
+
+#ifndef IN_GUEST
+ CRGLSLShader *pShad;
+
+ if (!id)
+ {
+ unsigned long tstKey = 0;
+ Assert(hwid);
+ pShad = (CRGLSLShader *)crDmpHashtableSearchByHwid(ctx->glsl.shaders, hwid, crDmpGetHwidShaderCB, &tstKey);
+ Assert(pShad);
+ if (!pShad)
+ return;
+ id = pShad->id;
+ Assert(tstKey == id);
+ }
+ else
+ {
+ pShad = (CRGLSLShader *)crHashtableSearch(ctx->glsl.shaders, id);
+ Assert(pShad);
+ if (!pShad)
+ return;
+ }
+
+ if (!hwid)
+ hwid = pShad->hwid;
+
+ Assert(pShad->hwid == hwid);
+ Assert(pShad->id == id);
+#else
+ if (!id)
+ id = hwid;
+ else if (!hwid)
+ hwid = id;
+
+ Assert(id);
+ Assert(hwid);
+ Assert(hwid == id);
+#endif
+
+ pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_SUBTYPE_ARB, &type);
+ pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_COMPILE_STATUS_ARB, &compileStatus);
+ crDmpStrF(pRec->pDumper, "SHADER ctx(%d) id(%d) hwid(%d) type(%s) status(%d):", ctx->id, id, hwid, crRecDumpShaderTypeString(type, pRec->pDumper), compileStatus);
+
+ crRecDumpLog(pRec, hwid);
+
+ pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_SHADER_SOURCE_LENGTH_ARB, &length);
+
+ char *pszSource = (char*)crCalloc(length + 1);
+ if (!pszSource)
+ {
+ crWarning("crCalloc failed");
+ crDmpStrF(pRec->pDumper, "WARNING: crCalloc failed");
+ return;
+ }
+
+ pRec->pDispatch->GetShaderSource(hwid, length, NULL, pszSource);
+ crRecDumpStrByLine(pRec->pDumper, pszSource, length);
+
+ crFree(pszSource);
+
+ crDmpStr(pRec->pDumper, "===END SHADER====");
+}
+
+void crRecDumpProgram(CR_RECORDER *pRec, CRContext *ctx, GLint id, GLint hwid)
+{
+ GLint cShaders = 0, linkStatus = 0;
+ char *source = NULL;
+ CRGLSLProgram *pProg;
+
+ if (!id)
+ {
+ unsigned long tstKey = 0;
+ Assert(hwid);
+ pProg = (CRGLSLProgram*)crDmpHashtableSearchByHwid(ctx->glsl.programs, hwid, crDmpGetHwidProgramCB, &tstKey);
+ Assert(pProg);
+ if (!pProg)
+ return;
+ id = pProg->id;
+ Assert(tstKey == id);
+ }
+ else
+ {
+ pProg = (CRGLSLProgram *) crHashtableSearch(ctx->glsl.programs, id);
+ Assert(pProg);
+ if (!pProg)
+ return;
+ }
+
+ if (!hwid)
+ hwid = pProg->hwid;
+
+ Assert(pProg->hwid == hwid);
+ Assert(pProg->id == id);
+
+ pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_ATTACHED_OBJECTS_ARB, &cShaders);
+ pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_LINK_STATUS_ARB, &linkStatus);
+
+ crDmpStrF(pRec->pDumper, "PROGRAM ctx(%d) id(%d) hwid(%d) status(%d) shaders(%d):", ctx->id, id, hwid, linkStatus, cShaders);
+
+ crRecDumpLog(pRec, hwid);
+
+ VBoxGLhandleARB *pShaders = (VBoxGLhandleARB*)crCalloc(cShaders * sizeof (*pShaders));
+ if (!pShaders)
+ {
+ crWarning("crCalloc failed");
+ crDmpStrF(pRec->pDumper, "WARNING: crCalloc failed");
+ return;
+ }
+
+ pRec->pDispatch->GetAttachedObjectsARB(hwid, cShaders, NULL, pShaders);
+ for (GLint i = 0; i < cShaders; ++i)
+ {
+ if (pShaders[i])
+ crRecDumpShader(pRec, ctx, 0, pShaders[i]);
+ else
+ crDmpStrF(pRec->pDumper, "WARNING: Shader[%d] is null", i);
+ }
+
+ crFree(pShaders);
+
+ GLsizei cbLog = 0;
+
+ pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_INFO_LOG_LENGTH_ARB, &cbLog);
+ if (cbLog)
+ {
+ char *pszLog = (char *)crCalloc(cbLog+1);
+ pRec->pDispatch->GetInfoLogARB(hwid, cbLog, NULL, pszLog);
+ crDmpStrF(pRec->pDumper, "==LOG==");
+ crRecDumpStrByLine(pRec->pDumper, pszLog, cbLog);
+ crDmpStrF(pRec->pDumper, "==Done LOG==");
+ crFree(pszLog);
+ }
+ else
+ {
+ crDmpStrF(pRec->pDumper, "==No LOG==");
+ }
+
+ crDmpStr(pRec->pDumper, "===END PROGRAM====");
+}
+
+void crRecRecompileShader(CR_RECORDER *pRec, CRContext *ctx, GLint id, GLint hwid)
+{
+ GLint length = 0;
+ GLint type = 0;
+ GLint compileStatus = 0;
+ CRGLSLShader *pShad;
+
+ if (!id)
+ {
+ unsigned long tstKey = 0;
+ Assert(hwid);
+ pShad = (CRGLSLShader *)crDmpHashtableSearchByHwid(ctx->glsl.shaders, hwid, crDmpGetHwidShaderCB, &tstKey);
+ Assert(pShad);
+ if (!pShad)
+ return;
+ id = pShad->id;
+ Assert(tstKey == id);
+ }
+ else
+ {
+ pShad = (CRGLSLShader *)crHashtableSearch(ctx->glsl.shaders, id);
+ Assert(pShad);
+ if (!pShad)
+ return;
+ }
+
+ if (!hwid)
+ hwid = pShad->hwid;
+
+ Assert(pShad->hwid == hwid);
+ Assert(pShad->id == id);
+
+ pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_SUBTYPE_ARB, &type);
+ pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_COMPILE_STATUS_ARB, &compileStatus);
+ crDmpStrF(pRec->pDumper, "==RECOMPILE SHADER ctx(%d) id(%d) hwid(%d) type(%s) status(%d)==", ctx->id, id, hwid, crRecDumpShaderTypeString(type, pRec->pDumper), compileStatus);
+
+ compileStatus = 0;
+ GLenum status;
+ while ((status = pRec->pDispatch->GetError()) != GL_NO_ERROR) {/*Assert(0);*/}
+ pRec->pDispatch->CompileShader(hwid);
+ while ((status = pRec->pDispatch->GetError()) != GL_NO_ERROR) {Assert(0);}
+ pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_COMPILE_STATUS_ARB, &compileStatus);
+
+ crDmpStrF(pRec->pDumper, "==Done RECOMPILE SHADER, status(%d)==", compileStatus);
+}
+
+void crRecRecompileProgram(CR_RECORDER *pRec, CRContext *ctx, GLint id, GLint hwid)
+{
+ GLint cShaders = 0, linkStatus = 0;
+ char *source = NULL;
+ CRGLSLProgram *pProg;
+
+ if (!id)
+ {
+ unsigned long tstKey = 0;
+ Assert(hwid);
+ pProg = (CRGLSLProgram*)crDmpHashtableSearchByHwid(ctx->glsl.programs, hwid, crDmpGetHwidProgramCB, &tstKey);
+ Assert(pProg);
+ if (!pProg)
+ return;
+ id = pProg->id;
+ Assert(tstKey == id);
+ }
+ else
+ {
+ pProg = (CRGLSLProgram *) crHashtableSearch(ctx->glsl.programs, id);
+ Assert(pProg);
+ if (!pProg)
+ return;
+ }
+
+ if (!hwid)
+ hwid = pProg->hwid;
+
+ Assert(pProg->hwid == hwid);
+ Assert(pProg->id == id);
+
+ pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_ATTACHED_OBJECTS_ARB, &cShaders);
+ pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_LINK_STATUS_ARB, &linkStatus);
+
+ crDmpStrF(pRec->pDumper, "==RECOMPILE PROGRAM ctx(%d) id(%d) hwid(%d) status(%d) shaders(%d)==", ctx->id, id, hwid, linkStatus, cShaders);
+
+ VBoxGLhandleARB *pShaders = (VBoxGLhandleARB*)crCalloc(cShaders * sizeof (*pShaders));
+ if (!pShaders)
+ {
+ crWarning("crCalloc failed");
+ crDmpStrF(pRec->pDumper, "WARNING: crCalloc failed");
+ return;
+ }
+
+ pRec->pDispatch->GetAttachedObjectsARB(hwid, cShaders, NULL, pShaders);
+ for (GLint i = 0; i < cShaders; ++i)
+ {
+ crRecRecompileShader(pRec, ctx, 0, pShaders[i]);
+ }
+
+ crFree(pShaders);
+
+ linkStatus = 0;
+ GLenum status;
+ while ((status = pRec->pDispatch->GetError()) != GL_NO_ERROR) {/*Assert(0);*/}
+ pRec->pDispatch->LinkProgram(hwid);
+ while ((status = pRec->pDispatch->GetError()) != GL_NO_ERROR) {Assert(0);}
+ pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_LINK_STATUS_ARB, &linkStatus);
+
+ crDmpStrF(pRec->pDumper, "==Done RECOMPILE PROGRAM, status(%d)==", linkStatus);
+}
+
+VBOXDUMPDECL(void) crRecDumpCurrentProgram(CR_RECORDER *pRec, CRContext *ctx)
+{
+ GLint curProgram = 0;
+ pRec->pDispatch->GetIntegerv(GL_CURRENT_PROGRAM, &curProgram);
+ if (curProgram)
+ {
+ Assert(ctx->glsl.activeProgram);
+ if (!ctx->glsl.activeProgram)
+ crWarning("no active program state with active hw program");
+ else
+ Assert(ctx->glsl.activeProgram->hwid == curProgram);
+ crRecDumpProgram(pRec, ctx, 0, curProgram);
+ }
+ else
+ {
+ Assert(!ctx->glsl.activeProgram);
+ crDmpStrF(pRec->pDumper, "--no active program");
+ }
+}
+
+void crRecDumpProgramUniforms(CR_RECORDER *pRec, CRContext *ctx, GLint id, GLint hwid)
+{
+ CRGLSLProgram *pProg;
+
+ if (!id)
+ {
+ unsigned long tstKey = 0;
+ Assert(hwid);
+ pProg = (CRGLSLProgram*)crDmpHashtableSearchByHwid(ctx->glsl.programs, hwid, crDmpGetHwidProgramCB, &tstKey);
+ Assert(pProg);
+ if (!pProg)
+ return;
+ id = pProg->id;
+ Assert(tstKey == id);
+ }
+ else
+ {
+ pProg = (CRGLSLProgram *) crHashtableSearch(ctx->glsl.programs, id);
+ Assert(pProg);
+ if (!pProg)
+ return;
+ }
+
+ if (!hwid)
+ hwid = pProg->hwid;
+
+ Assert(pProg->hwid == hwid);
+ Assert(pProg->id == id);
+
+ GLint maxUniformLen = 0, activeUniforms = 0, i, j, uniformsCount = 0;
+ GLenum type;
+ GLint size, location;
+ GLchar *pszName = NULL;
+ pRec->pDispatch->GetProgramiv(hwid, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformLen);
+ pRec->pDispatch->GetProgramiv(hwid, GL_ACTIVE_UNIFORMS, &activeUniforms);
+
+ if (!maxUniformLen)
+ {
+ if (activeUniforms)
+ {
+ crWarning("activeUniforms (%d), while maxUniformLen is zero", activeUniforms);
+ activeUniforms = 0;
+ }
+ }
+
+ if (activeUniforms>0)
+ {
+ pszName = (GLchar *) crAlloc((maxUniformLen+8)*sizeof(GLchar));
+
+ if (!pszName)
+ {
+ crWarning("crRecDumpProgramUniforms: out of memory");
+ return;
+ }
+ }
+
+ for (i=0; i<activeUniforms; ++i)
+ {
+ pRec->pDispatch->GetActiveUniform(hwid, i, maxUniformLen, NULL, &size, &type, pszName);
+ uniformsCount += size;
+ }
+ Assert(uniformsCount>=activeUniforms);
+
+ if (activeUniforms>0)
+ {
+ GLfloat fdata[16];
+ GLint idata[16];
+ char *pIndexStr=NULL;
+
+ for (i=0; i<activeUniforms; ++i)
+ {
+ bool fPrintBraketsWithName = false;
+ pRec->pDispatch->GetActiveUniform(hwid, i, maxUniformLen, NULL, &size, &type, pszName);
+
+ if (size>1)
+ {
+ pIndexStr = crStrchr(pszName, '[');
+ if (!pIndexStr)
+ {
+ pIndexStr = pszName+crStrlen(pszName);
+ fPrintBraketsWithName = true;
+ }
+ }
+
+ if (fPrintBraketsWithName)
+ {
+ crDmpStrF(pRec->pDumper, "%s %s[%d];", crRecDumpVarTypeString(type, pRec->pDumper), pszName, size);
+ Assert(size > 1);
+ }
+ else
+ crDmpStrF(pRec->pDumper, "%s %s;", crRecDumpVarTypeString(type, pRec->pDumper), pszName);
+
+ GLint uniformTypeSize = crStateGetUniformSize(type);
+ Assert(uniformTypeSize >= 1);
+
+ for (j=0; j<size; ++j)
+ {
+ if (size>1)
+ {
+ sprintf(pIndexStr, "[%i]", j);
+ }
+ location = pRec->pDispatch->GetUniformLocation(hwid, pszName);
+
+ if (crStateIsIntUniform(type))
+ {
+ pRec->pDispatch->GetUniformiv(hwid, location, &idata[0]);
+ switch (uniformTypeSize)
+ {
+ case 1:
+ crDmpStrF(pRec->pDumper, "%s = %d; //location %d", pszName, idata[0], location);
+ break;
+ case 2:
+ crDmpStrF(pRec->pDumper, "%s = {%d, %d}; //location %d", pszName, idata[0], idata[1], location);
+ break;
+ case 3:
+ crDmpStrF(pRec->pDumper, "%s = {%d, %d, %d}; //location %d", pszName, idata[0], idata[1], idata[2], location);
+ break;
+ case 4:
+ crDmpStrF(pRec->pDumper, "%s = {%d, %d, %d, %d}; //location %d", pszName, idata[0], idata[1], idata[2], idata[3], location);
+ break;
+ default:
+ for (GLint k = 0; k < uniformTypeSize; ++k)
+ {
+ crDmpStrF(pRec->pDumper, "%s[%d] = %d; //location %d", pszName, k, idata[k], location);
+ }
+ break;
+ }
+ }
+ else
+ {
+ pRec->pDispatch->GetUniformfv(hwid, location, &fdata[0]);
+ switch (uniformTypeSize)
+ {
+ case 1:
+ crDmpStrF(pRec->pDumper, "%s = %f; //location %d", pszName, fdata[0], location);
+ break;
+ case 2:
+ crDmpStrF(pRec->pDumper, "%s = {%f, %f}; //location %d", pszName, fdata[0], fdata[1], location);
+ break;
+ case 3:
+ crDmpStrF(pRec->pDumper, "%s = {%f, %f, %f}; //location %d", pszName, fdata[0], fdata[1], fdata[2], location);
+ break;
+ case 4:
+ crDmpStrF(pRec->pDumper, "%s = {%f, %f, %f, %f}; //location %d", pszName, fdata[0], fdata[1], fdata[2], fdata[3], location);
+ break;
+ default:
+ for (GLint k = 0; k < uniformTypeSize; ++k)
+ {
+ crDmpStrF(pRec->pDumper, "%s[%d] = %f; //location %d", pszName, k, fdata[k], location);
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ crFree(pszName);
+ }
+}
+
+void crRecDumpProgramAttribs(CR_RECORDER *pRec, CRContext *ctx, GLint id, GLint hwid)
+{
+ CRGLSLProgram *pProg;
+
+ if (!id)
+ {
+ unsigned long tstKey = 0;
+ Assert(hwid);
+ pProg = (CRGLSLProgram*)crDmpHashtableSearchByHwid(ctx->glsl.programs, hwid, crDmpGetHwidProgramCB, &tstKey);
+ Assert(pProg);
+ if (!pProg)
+ return;
+ id = pProg->id;
+ Assert(tstKey == id);
+ }
+ else
+ {
+ pProg = (CRGLSLProgram *) crHashtableSearch(ctx->glsl.programs, id);
+ Assert(pProg);
+ if (!pProg)
+ return;
+ }
+
+ if (!hwid)
+ hwid = pProg->hwid;
+
+ Assert(pProg->hwid == hwid);
+ Assert(pProg->id == id);
+
+ GLint maxAttribLen = 0, activeAttrib = 0, i, j, attribCount = 0;
+ GLenum type;
+ GLint size, location;
+ GLchar *pszName = NULL;
+ pRec->pDispatch->GetProgramiv(hwid, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxAttribLen);
+ pRec->pDispatch->GetProgramiv(hwid, GL_ACTIVE_ATTRIBUTES, &activeAttrib);
+
+ if (!maxAttribLen)
+ {
+ if (activeAttrib)
+ {
+ crWarning("activeAttrib (%d), while maxAttribLen is zero", activeAttrib);
+ activeAttrib = 0;
+ }
+ }
+
+ if (activeAttrib>0)
+ {
+ pszName = (GLchar *) crAlloc((maxAttribLen+8)*sizeof(GLchar));
+
+ if (!pszName)
+ {
+ crWarning("crRecDumpProgramAttrib: out of memory");
+ return;
+ }
+ }
+
+ for (i=0; i<activeAttrib; ++i)
+ {
+ pRec->pDispatch->GetActiveAttrib(hwid, i, maxAttribLen, NULL, &size, &type, pszName);
+ attribCount += size;
+ }
+ Assert(attribCount>=activeAttrib);
+
+ if (activeAttrib>0)
+ {
+ GLfloat fdata[16];
+ GLint idata[16];
+ char *pIndexStr=NULL;
+
+ for (i=0; i<activeAttrib; ++i)
+ {
+ bool fPrintBraketsWithName = false;
+ pRec->pDispatch->GetActiveAttrib(hwid, i, maxAttribLen, NULL, &size, &type, pszName);
+ GLint arrayBufferBind = 0, arrayEnabled = 0, arraySize = 0, arrayStride = 0, arrayType = 0, arrayNormalized = 0, arrayInteger = 0/*, arrayDivisor = 0*/;
+
+ pRec->pDispatch->GetVertexAttribivARB(i, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &arrayBufferBind);
+ pRec->pDispatch->GetVertexAttribivARB(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &arrayEnabled);
+ pRec->pDispatch->GetVertexAttribivARB(i, GL_VERTEX_ATTRIB_ARRAY_SIZE, &arraySize);
+ pRec->pDispatch->GetVertexAttribivARB(i, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &arrayStride);
+ pRec->pDispatch->GetVertexAttribivARB(i, GL_VERTEX_ATTRIB_ARRAY_TYPE, &arrayType);
+ pRec->pDispatch->GetVertexAttribivARB(i, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &arrayNormalized);
+ pRec->pDispatch->GetVertexAttribivARB(i, GL_VERTEX_ATTRIB_ARRAY_INTEGER, &arrayInteger);
+// pRec->pDispatch->GetVertexAttribivARB(i, GL_VERTEX_ATTRIB_ARRAY_DIVISOR, &arrayDivisor);
+
+ if (size>1)
+ {
+ pIndexStr = crStrchr(pszName, '[');
+ if (!pIndexStr)
+ {
+ pIndexStr = pszName+crStrlen(pszName);
+ fPrintBraketsWithName = true;
+ }
+ }
+
+ if (fPrintBraketsWithName)
+ {
+ crDmpStrF(pRec->pDumper, "%s %s[%d];", crRecDumpVarTypeString(type, pRec->pDumper), pszName, size);
+ Assert(size > 1);
+ }
+ else
+ crDmpStrF(pRec->pDumper, "%s %s;", crRecDumpVarTypeString(type, pRec->pDumper), pszName);
+
+ crDmpStrF(pRec->pDumper, "Array buff(%d), enabled(%d) size(%d), stride(%d), type(%s), normalized(%d), integer(%d)", arrayBufferBind, arrayEnabled, arraySize, arrayStride, crRecDumpVarTypeString(arrayType, pRec->pDumper), arrayNormalized, arrayInteger);
+
+ GLint attribTypeSize = crStateGetUniformSize(type);
+ Assert(attribTypeSize >= 1);
+
+ for (j=0; j<size; ++j)
+ {
+ if (size>1)
+ {
+ sprintf(pIndexStr, "[%i]", j);
+ }
+ location = pRec->pDispatch->GetAttribLocation(hwid, pszName);
+
+ if (crStateIsIntUniform(type))
+ {
+ pRec->pDispatch->GetVertexAttribivARB(location, GL_CURRENT_VERTEX_ATTRIB, &idata[0]);
+ switch (attribTypeSize)
+ {
+ case 1:
+ crDmpStrF(pRec->pDumper, "%s = %d; //location %d", pszName, idata[0], location);
+ break;
+ case 2:
+ crDmpStrF(pRec->pDumper, "%s = {%d, %d}; //location %d", pszName, idata[0], idata[1], location);
+ break;
+ case 3:
+ crDmpStrF(pRec->pDumper, "%s = {%d, %d, %d}; //location %d", pszName, idata[0], idata[1], idata[2], location);
+ break;
+ case 4:
+ crDmpStrF(pRec->pDumper, "%s = {%d, %d, %d, %d}; //location %d", pszName, idata[0], idata[1], idata[2], idata[3], location);
+ break;
+ default:
+ for (GLint k = 0; k < attribTypeSize; ++k)
+ {
+ crDmpStrF(pRec->pDumper, "%s[%d] = %d; //location %d", pszName, k, idata[k], location);
+ }
+ break;
+ }
+ }
+ else
+ {
+ pRec->pDispatch->GetVertexAttribfvARB(location, GL_CURRENT_VERTEX_ATTRIB, &fdata[0]);
+ switch (attribTypeSize)
+ {
+ case 1:
+ crDmpStrF(pRec->pDumper, "%s = %f; //location %d", pszName, fdata[0], location);
+ break;
+ case 2:
+ crDmpStrF(pRec->pDumper, "%s = {%f, %f}; //location %d", pszName, fdata[0], fdata[1], location);
+ break;
+ case 3:
+ crDmpStrF(pRec->pDumper, "%s = {%f, %f, %f}; //location %d", pszName, fdata[0], fdata[1], fdata[2], location);
+ break;
+ case 4:
+ crDmpStrF(pRec->pDumper, "%s = {%f, %f, %f, %f}; //location %d", pszName, fdata[0], fdata[1], fdata[2], fdata[3], location);
+ break;
+ default:
+ for (GLint k = 0; k < attribTypeSize; ++k)
+ {
+ crDmpStrF(pRec->pDumper, "%s[%d] = %f; //location %d", pszName, k, fdata[k], location);
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ crFree(pszName);
+ }
+}
+
+VBOXDUMPDECL(void) crRecDumpCurrentProgramUniforms(CR_RECORDER *pRec, CRContext *ctx)
+{
+ GLint curProgram = 0;
+ pRec->pDispatch->GetIntegerv(GL_CURRENT_PROGRAM, &curProgram);
+ if (curProgram)
+ {
+ Assert(ctx->glsl.activeProgram);
+ if (!ctx->glsl.activeProgram)
+ crWarning("no active program state with active hw program");
+ else
+ Assert(ctx->glsl.activeProgram->hwid == curProgram);
+ crRecDumpProgramUniforms(pRec, ctx, 0, curProgram);
+ }
+ else
+ {
+ Assert(!ctx->glsl.activeProgram);
+ crDmpStrF(pRec->pDumper, "--no active program");
+ }
+}
+
+VBOXDUMPDECL(void) crRecDumpCurrentProgramAttribs(CR_RECORDER *pRec, CRContext *ctx)
+{
+ GLint curProgram = 0;
+ pRec->pDispatch->GetIntegerv(GL_CURRENT_PROGRAM, &curProgram);
+ if (curProgram)
+ {
+ Assert(ctx->glsl.activeProgram);
+ if (!ctx->glsl.activeProgram)
+ crWarning("no active program state with active hw program");
+ else
+ Assert(ctx->glsl.activeProgram->hwid == curProgram);
+ crRecDumpProgramAttribs(pRec, ctx, 0, curProgram);
+ }
+ else
+ {
+ Assert(!ctx->glsl.activeProgram);
+ crDmpStrF(pRec->pDumper, "--no active program");
+ }
+}
+
+VBOXDUMPDECL(void) crRecRecompileCurrentProgram(CR_RECORDER *pRec, CRContext *ctx)
+{
+ GLint curProgram = 0;
+ pRec->pDispatch->GetIntegerv(GL_CURRENT_PROGRAM, &curProgram);
+ if (curProgram)
+ {
+ Assert(ctx->glsl.activeProgram);
+ if (!ctx->glsl.activeProgram)
+ crWarning("no active program state with active hw program");
+ else
+ Assert(ctx->glsl.activeProgram->hwid == curProgram);
+ crRecRecompileProgram(pRec, ctx, 0, curProgram);
+ }
+ else
+ {
+ Assert(!ctx->glsl.activeProgram);
+ crDmpStrF(pRec->pDumper, "--no active program");
+ }
+}
+
+int crRecAlphaImgCreate(const CR_BLITTER_IMG *pImg, CR_BLITTER_IMG *pAlphaImg)
+{
+ if (pImg->enmFormat != GL_RGBA
+ && pImg->enmFormat != GL_BGRA)
+ {
+ crWarning("unsupported format 0x%x", pImg->enmFormat);
+ return VERR_NOT_IMPLEMENTED;
+ }
+
+ pAlphaImg->bpp = 32;
+ pAlphaImg->pitch = pImg->width * 4;
+ pAlphaImg->cbData = pAlphaImg->pitch * pImg->height;
+ pAlphaImg->enmFormat = GL_BGRA;
+ pAlphaImg->width = pImg->width;
+ pAlphaImg->height = pImg->height;
+
+ pAlphaImg->pvData = RTMemAlloc(pAlphaImg->cbData);
+ if (!pAlphaImg->pvData)
+ {
+ crWarning("RTMemAlloc failed");
+ return VERR_NO_MEMORY;
+ }
+
+ uint8_t *pu8SrcBuf = (uint8_t*)pImg->pvData;
+ uint8_t *pu8DstBuf = (uint8_t*)pAlphaImg->pvData;
+ for (uint32_t ih = 0; ih < pAlphaImg->height; ++ih)
+ {
+ uint32_t *pu32SrcBuf = (uint32_t*)pu8SrcBuf;
+ uint32_t *pu32DstBuf = (uint32_t*)pu8DstBuf;
+ for (uint32_t iw = 0; iw < pAlphaImg->width; ++iw)
+ {
+ uint8_t alpha = (((*pu32SrcBuf) >> 24) & 0xff);
+ *pu32DstBuf = (0xff << 24) || (alpha << 16) || (alpha << 8) || alpha;
+ ++pu32SrcBuf;
+ ++pu32DstBuf;
+ }
+ pu8SrcBuf += pImg->pitch;
+ pu8DstBuf += pAlphaImg->pitch;
+ }
+
+ return VINF_SUCCESS;
+}
+
+void crRecAlphaImgDestroy(CR_BLITTER_IMG *pImg)
+{
+ RTMemFree(pImg->pvData);
+ pImg->pvData = NULL;
+}
+
+void crRecDumpTextureV(CR_RECORDER *pRec, const VBOXVR_TEXTURE *pTex, const char *pszStr, va_list pArgList)
+{
+ CR_BLITTER_IMG Img = {0};
+ int rc = CrBltEnter(pRec->pBlitter);
+ if (RT_SUCCESS(rc))
+ {
+ rc = CrBltImgGetTex(pRec->pBlitter, pTex, GL_BGRA, &Img);
+ if (RT_SUCCESS(rc))
+ {
+ crDmpImgV(pRec->pDumper, &Img, pszStr, pArgList);
+ if (g_CrDbgDumpAlphaData)
+ {
+ CR_BLITTER_IMG AlphaImg = {0};
+ rc = crRecAlphaImgCreate(&Img, &AlphaImg);
+ if (RT_SUCCESS(rc))
+ {
+ crDmpImgF(pRec->pDumper, &AlphaImg, "Texture ALPHA Data");
+ crRecAlphaImgDestroy(&AlphaImg);
+ }
+ else
+ {
+ crWarning("crRecAlphaImgCreate failed rc %d", rc);
+ }
+ }
+ CrBltImgFree(pRec->pBlitter, &Img);
+ }
+ else
+ {
+ crWarning("CrBltImgGetTex failed, rc %d", rc);
+ }
+ CrBltLeave(pRec->pBlitter);
+ }
+ else
+ {
+ crWarning("CrBltEnter failed, rc %d", rc);
+ }
+}
+
+void crRecDumpTextureF(CR_RECORDER *pRec, const VBOXVR_TEXTURE *pTex, const char *pszStr, ...)
+{
+ va_list pArgList;
+ va_start(pArgList, pszStr);
+ crRecDumpTextureV(pRec, pTex, pszStr, pArgList);
+ va_end(pArgList);
+}
+
+void crRecDumpTextureByIdV(CR_RECORDER *pRec, CRContext *ctx, GLint id, const char *pszStr, va_list pArgList)
+{
+ CRTextureObj *pTobj = (CRTextureObj *)crHashtableSearch(ctx->shared->textureTable, id);
+ if (!pTobj)
+ {
+ crWarning("no texture of id %d", id);
+ return;
+ }
+
+ CRTextureLevel *pTl = &pTobj->level[0][0 /* level */];
+ VBOXVR_TEXTURE Tex;
+ Tex.width = pTl->width;
+ Tex.height = pTl->height;
+ Tex.target = pTobj->target;
+ Assert(Tex.target == GL_TEXTURE_2D);
+ Tex.hwid = pTobj->hwid;
+ if (!Tex.hwid)
+ {
+ crWarning("no texture hwid of id %d", id);
+ return;
+ }
+
+ crRecDumpTextureV(pRec, &Tex, pszStr, pArgList);
+}
+
+void crRecDumpTextureByIdF(CR_RECORDER *pRec, CRContext *ctx, GLint id, const char *pszStr, ...)
+{
+ va_list pArgList;
+ va_start(pArgList, pszStr);
+ crRecDumpTextureByIdV(pRec, ctx, id, pszStr, pArgList);
+ va_end(pArgList);
+}
+
+void crRecDumpTextures(CR_RECORDER *pRec, CRContext *ctx)
+{
+ GLint maxUnits = 0;
+ GLint curTexUnit = 0;
+ GLint restoreTexUnit = 0;
+ GLint curProgram = 0;
+ int i;
+
+ pRec->pDispatch->GetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxUnits);
+ maxUnits = RT_MIN(CR_MAX_TEXTURE_UNITS, maxUnits);
+
+ pRec->pDispatch->GetIntegerv(GL_CURRENT_PROGRAM, &curProgram);
+ Assert(curProgram);
+ Assert(ctx->glsl.activeProgram && ctx->glsl.activeProgram->hwid == curProgram);
+
+ Assert(maxUnits);
+ pRec->pDispatch->GetIntegerv(GL_ACTIVE_TEXTURE, &curTexUnit);
+ restoreTexUnit = curTexUnit;
+ Assert(curTexUnit >= GL_TEXTURE0);
+ Assert(curTexUnit < GL_TEXTURE0 + maxUnits);
+
+ Assert(ctx->texture.curTextureUnit == restoreTexUnit - GL_TEXTURE0);
+
+ for (i = 0; i < maxUnits; ++i)
+ {
+ GLboolean enabled1D;
+ GLboolean enabled2D;
+ GLboolean enabled3D;
+ GLboolean enabledCubeMap;
+ GLboolean enabledRect;
+ CRTextureUnit *tu = &ctx->texture.unit[i];
+
+ if (i > 1)
+ break;
+
+ if (curTexUnit != i + GL_TEXTURE0)
+ {
+ pRec->pDispatch->ActiveTextureARB(i + GL_TEXTURE0);
+ curTexUnit = i + GL_TEXTURE0;
+ }
+
+ enabled1D = pRec->pDispatch->IsEnabled(GL_TEXTURE_1D);
+ enabled2D = pRec->pDispatch->IsEnabled(GL_TEXTURE_2D);
+ enabled3D = pRec->pDispatch->IsEnabled(GL_TEXTURE_3D);
+ enabledCubeMap = pRec->pDispatch->IsEnabled(GL_TEXTURE_CUBE_MAP_ARB);
+ enabledRect = pRec->pDispatch->IsEnabled(GL_TEXTURE_RECTANGLE_NV);
+
+ Assert(enabled1D == tu->enabled1D);
+ Assert(enabled2D == tu->enabled2D);
+ Assert(enabled3D == tu->enabled3D);
+ Assert(enabledCubeMap == tu->enabledCubeMap);
+ Assert(enabledRect == tu->enabledRect);
+
+ if (enabled1D)
+ {
+ crWarning("GL_TEXTURE_1D: unsupported");
+ }
+
+// if (enabled2D)
+ {
+ GLint hwTex = 0;
+ VBOXVR_TEXTURE Tex;
+
+ GLint width = 0, height = 0, depth = 0;
+ CRTextureObj *pTobj = tu->currentTexture2D;
+
+ pRec->pDispatch->GetIntegerv(GL_TEXTURE_BINDING_2D, &hwTex);
+ if (hwTex)
+ {
+ CRTextureLevel *pTl = &pTobj->level[0][0 /* level */];
+ Assert(pTobj
+ && pTobj->hwid == hwTex);
+
+ pRec->pDispatch->GetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
+ pRec->pDispatch->GetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
+ pRec->pDispatch->GetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_DEPTH, &depth);
+
+ Assert(width == pTl->width);
+ Assert(height == pTl->height);
+ Assert(depth == pTl->depth);
+
+ Tex.width = width;
+ Tex.height = height;
+ Tex.target = GL_TEXTURE_2D;
+ Tex.hwid = hwTex;
+
+ if (g_CrDbgDumpRecTexInfo)
+ {
+ crRecDumpTexParam(pRec, ctx, GL_TEXTURE_2D);
+ crRecDumpTexEnv(pRec, ctx);
+ crRecDumpTexGen(pRec, ctx);
+ }
+
+ crRecDumpTextureF(pRec, &Tex, "ctx(%d), Unit %d: TEXTURE_2D id(%d) hwid(%d), width(%d), height(%d)", ctx, i, pTobj->id, pTobj->hwid, width, height);
+ }
+// else
+// {
+// Assert(!pTobj || pTobj->hwid == 0);
+// crWarning("no TEXTURE_2D bound!");
+// }
+ }
+#if 0
+ if (enabled3D)
+ {
+ crWarning("GL_TEXTURE_3D: unsupported");
+ }
+
+ if (enabledCubeMap)
+ {
+ crWarning("GL_TEXTURE_CUBE_MAP_ARB: unsupported");
+ }
+
+// if (enabledRect)
+ {
+ GLint hwTex = 0;
+ CR_BLITTER_IMG Img = {0};
+ VBOXVR_TEXTURE Tex;
+
+ GLint width = 0, height = 0, depth = 0;
+ CRTextureObj *pTobj = tu->currentTextureRect;
+
+ pRec->pDispatch->GetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_NV, &hwTex);
+ if (hwTex)
+ {
+ CRTextureLevel *pTl = &pTobj->level[0][0 /* level */];
+ Assert(pTobj
+ && pTobj->hwid == hwTex);
+
+ pRec->pDispatch->GetTexLevelParameteriv(GL_TEXTURE_RECTANGLE_NV, 0, GL_TEXTURE_WIDTH, &width);
+ pRec->pDispatch->GetTexLevelParameteriv(GL_TEXTURE_RECTANGLE_NV, 0, GL_TEXTURE_HEIGHT, &height);
+ pRec->pDispatch->GetTexLevelParameteriv(GL_TEXTURE_RECTANGLE_NV, 0, GL_TEXTURE_DEPTH, &depth);
+
+ Assert(width == pTl->width);
+ Assert(height == pTl->height);
+ Assert(depth == pTl->depth);
+
+ Tex.width = width;
+ Tex.height = height;
+ Tex.target = GL_TEXTURE_RECTANGLE_NV;
+ Tex.hwid = hwTex;
+
+ rc = CrBltEnter(pRec->pBlitter);
+ if (RT_SUCCESS(rc))
+ {
+ rc = CrBltImgGetTex(pRec->pBlitter, &Tex, GL_BGRA, &Img);
+ if (RT_SUCCESS(rc))
+ {
+ crDmpImgF(pRec->pDumper, &Img, "Unit %d: TEXTURE_RECTANGLE data", i);
+ CrBltImgFree(pRec->pBlitter, &Img);
+ }
+ else
+ {
+ crWarning("CrBltImgGetTex failed, rc %d", rc);
+ }
+ CrBltLeave(pRec->pBlitter);
+ }
+ else
+ {
+ crWarning("CrBltEnter failed, rc %d", rc);
+ }
+ }
+// else
+// {
+// Assert(!pTobj || pTobj->hwid == 0);
+// crWarning("no TEXTURE_RECTANGLE bound!");
+// }
+ }
+#endif
+ }
+
+ if (curTexUnit != restoreTexUnit)
+ {
+ pRec->pDispatch->ActiveTextureARB(restoreTexUnit);
+ curTexUnit = restoreTexUnit;
+ }
+}
+
+#ifdef RT_OS_WINDOWS
+static void crDmpPrint(const char* szString, ...)
+{
+ char szBuffer[4096] = {0};
+ va_list pArgList;
+ va_start(pArgList, szString);
+ RTStrPrintfV(szBuffer, sizeof (szBuffer), szString, pArgList);
+ va_end(pArgList);
+
+ OutputDebugStringA(szBuffer);
+}
+
+static void crDmpPrintDmlCmd(const char* pszDesc, const char* pszCmd)
+{
+ crDmpPrint("<?dml?><exec cmd=\"%s\">%s</exec>, ( %s )\n", pszCmd, pszDesc, pszCmd);
+}
+
+void crDmpPrintDumpDmlCmd(const char* pszDesc, const void *pvData, uint32_t width, uint32_t height, uint32_t bpp, uint32_t pitch)
+{
+ char Cmd[1024];
+ sprintf(Cmd, "!vbvdbg.ms 0x%p 0n%d 0n%d 0n%d 0n%d", pvData, width, height, bpp, pitch);
+ crDmpPrintDmlCmd(pszDesc, Cmd);
+}
+
+DECLCALLBACK(void) crDmpDumpImgDmlBreak(struct CR_DUMPER * pDumper, CR_BLITTER_IMG *pImg, const char*pszEntryDesc)
+{
+ crDmpPrintDumpDmlCmd(pszEntryDesc, pImg->pvData, pImg->width, pImg->height, pImg->bpp, pImg->pitch);
+ RT_BREAKPOINT();
+}
+
+DECLCALLBACK(void) crDmpDumpStrDbgPrint(struct CR_DUMPER * pDumper, const char*pszStr)
+{
+ crDmpPrint("%s\n", pszStr);
+}
+#endif
+
+static void crDmpHtmlDumpStrExact(struct CR_HTML_DUMPER * pDumper, const char *pszStr)
+{
+ fprintf(pDumper->pFile, "%s", pszStr);
+ fflush(pDumper->pFile);
+}
+
+static DECLCALLBACK(void) crDmpHtmlDumpStr(struct CR_DUMPER * pDumper, const char*pszStr)
+{
+ CR_HTML_DUMPER * pHtmlDumper = (CR_HTML_DUMPER*)pDumper;
+ fprintf(pHtmlDumper->pFile, "<pre>%s</pre>\n", pszStr);
+ fflush(pHtmlDumper->pFile);
+}
+
+static DECLCALLBACK(void) crDmpHtmlDumpImg(struct CR_DUMPER * pDumper, CR_BLITTER_IMG *pImg, const char*pszEntryDesc)
+{
+ CR_HTML_DUMPER * pHtmlDumper = (CR_HTML_DUMPER*)pDumper;
+ char szBuffer[4096] = {0};
+ size_t cbWritten = RTStrPrintf(szBuffer, sizeof(szBuffer), "%s/", pHtmlDumper->pszDir);
+ char *pszFileName = szBuffer + cbWritten;
+ RTStrPrintf(pszFileName, sizeof(szBuffer) - cbWritten, "img%d.bmp", ++pHtmlDumper->cImg);
+ crDmpImgBmp(pImg, szBuffer);
+ fprintf(pHtmlDumper->pFile, "<a href=\"%s\"><pre>%s</pre><img src=\"%s\" alt=\"%s\" width=\"150\" height=\"100\" /></a><br>\n",
+ pszFileName, pszEntryDesc, pszFileName, pszEntryDesc);
+ fflush(pHtmlDumper->pFile);
+}
+
+static void crDmpHtmlPrintHeader(struct CR_HTML_DUMPER * pDumper)
+{
+ fprintf(pDumper->pFile, "<html><body>\n");
+ fflush(pDumper->pFile);
+}
+
+static void crDmpHtmlPrintFooter(struct CR_HTML_DUMPER * pDumper)
+{
+ fprintf(pDumper->pFile, "</body></html>\n");
+ fflush(pDumper->pFile);
+}
+
+DECLEXPORT(bool) crDmpHtmlIsInited(struct CR_HTML_DUMPER * pDumper)
+{
+ return !!pDumper->pFile;
+}
+
+DECLEXPORT(void) crDmpHtmlTerm(struct CR_HTML_DUMPER * pDumper)
+{
+ crDmpHtmlPrintFooter(pDumper);
+ fclose (pDumper->pFile);
+ pDumper->pFile = NULL;
+}
+
+DECLEXPORT(int) crDmpHtmlInit(struct CR_HTML_DUMPER * pDumper, const char *pszDir, const char *pszFile)
+{
+ int rc = VERR_NO_MEMORY;
+ pDumper->Base.pfnDumpImg = crDmpHtmlDumpImg;
+ pDumper->Base.pfnDumpStr = crDmpHtmlDumpStr;
+ pDumper->cImg = 0;
+ pDumper->pszDir = crStrdup(pszDir);
+ if (pDumper->pszDir)
+ {
+ pDumper->pszFile = crStrdup(pszFile);
+ if (pDumper->pszFile)
+ {
+ char szBuffer[4096] = {0};
+ RTStrPrintf(szBuffer, sizeof(szBuffer), "%s/%s", pszDir, pszFile);
+
+ pDumper->pszFile = crStrdup(pszFile);
+ pDumper->pFile = fopen(szBuffer, "w");
+ if (pDumper->pFile)
+ {
+ crDmpHtmlPrintHeader(pDumper);
+ return VINF_SUCCESS;
+ }
+ else
+ {
+ crWarning("open failed");
+ rc = VERR_OPEN_FAILED;
+ }
+ crFree((void*)pDumper->pszFile);
+ }
+ else
+ {
+ crWarning("open failed");
+ }
+ crFree((void*)pDumper->pszDir);
+ }
+ else
+ {
+ crWarning("open failed");
+ }
+ return rc;
+}
+
+DECLEXPORT(int) crDmpHtmlInitV(struct CR_HTML_DUMPER * pDumper, const char *pszDir, const char *pszFile, va_list pArgList)
+{
+ char szBuffer[4096] = {0};
+ vsprintf_s(szBuffer, sizeof (szBuffer), pszFile, pArgList);
+ return crDmpHtmlInit(pDumper, pszDir, szBuffer);
+}
+
+DECLEXPORT(int) crDmpHtmlInitF(struct CR_HTML_DUMPER * pDumper, const char *pszDir, const char *pszFile, ...)
+{
+ int rc;
+ va_list pArgList;
+ va_start(pArgList, pszFile);
+ rc = crDmpHtmlInitV(pDumper, pszDir, pszFile, pArgList);
+ va_end(pArgList);
+ return rc;
+}
+
+#endif
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/dump_gen.py b/src/VBox/GuestHost/OpenGL/state_tracker/dump_gen.py
new file mode 100644
index 00000000..7103ed4e
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/dump_gen.py
@@ -0,0 +1,257 @@
+import sys
+
+import apiutil
+
+import sys, re, string
+
+
+line_re = re.compile(r'^(\S+)\s+(GL_\S+)\s+(.*)\s*$')
+extensions_line_re = re.compile(r'^(\S+)\s+(GL_\S+)\s(\S+)\s+(.*)\s*$')
+
+params = {}
+extended_params = {}
+
+input = open( sys.argv[2]+"/state_isenabled.txt", 'r' )
+for line in input.readlines():
+ match = line_re.match( line )
+ if match:
+ type = match.group(1)
+ pname = match.group(2)
+ fields = string.split( match.group(3) )
+ params[pname] = ( type, fields )
+
+input = open( sys.argv[2]+"/state_extensions_isenabled.txt", 'r' )
+for line in input.readlines():
+ match = extensions_line_re.match( line )
+ if match:
+ type = match.group(1)
+ pname = match.group(2)
+ ifdef = match.group(3)
+ fields = string.split( match.group(4) )
+ extended_params[pname] = ( type, ifdef, fields )
+
+
+apiutil.CopyrightC()
+
+print """#include "cr_blitter.h"
+#include "cr_spu.h"
+#include "chromium.h"
+#include "cr_error.h"
+#include "cr_net.h"
+#include "cr_rand.h"
+#include "cr_mem.h"
+#include "cr_string.h"
+#include <cr_dump.h>
+#include "cr_pixeldata.h"
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/mem.h>
+
+#include <stdio.h>
+
+#ifdef VBOX_WITH_CRDUMPER
+"""
+
+from get_sizes import *;
+
+getprops = apiutil.ParamProps("GetDoublev")
+enableprops = apiutil.ParamProps("Enable")
+
+#print "//missing get props:"
+#for prop in getprops:
+# try:
+# tmp = num_get_values[prop]
+# except KeyError:
+# try:
+# keyvalues = extensions_num_get_values[prop]
+# except KeyError:
+# print "//%s" % prop
+#
+print """
+static void crRecDumpPrintVal(CR_DUMPER *pDumper, struct nv_struct *pDesc, float *pfData)
+{
+ char aBuf[4096];
+ crDmpFormatArray(aBuf, sizeof (aBuf), "%f", sizeof (float), pfData, pDesc->num_values);
+ crDmpStrF(pDumper, "%s = %s;", pDesc->pszName, aBuf);
+}
+
+
+void crRecDumpGlGetState(CR_RECORDER *pRec, CRContext *ctx)
+{
+ float afData[CR_MAX_GET_VALUES];
+ struct nv_struct *pDesc;
+
+ for (pDesc = num_values_array; pDesc->num_values != 0 ; pDesc++)
+ {
+ memset(afData, 0, sizeof(afData));
+ pRec->pDispatch->GetFloatv(pDesc->pname, afData);
+ crRecDumpPrintVal(pRec->pDumper, pDesc, afData);
+ }
+}
+
+void crRecDumpGlEnableState(CR_RECORDER *pRec, CRContext *ctx)
+{
+ GLboolean fEnabled;
+"""
+keys = params.keys()
+keys.sort();
+
+for pname in keys:
+ print "\tfEnabled = pRec->pDispatch->IsEnabled(%s);" % pname
+ print "\tcrDmpStrF(pRec->pDumper, \"%s = %%d;\", fEnabled);" % pname
+
+keys = extended_params.keys();
+keys.sort()
+
+for pname in keys:
+ (srctype,ifdef,fields) = extended_params[pname]
+ ext = ifdef[3:] # the extension name with the "GL_" prefix removed
+ ext = ifdef
+ print '#ifdef CR_%s' % ext
+ print "\tfEnabled = pRec->pDispatch->IsEnabled(%s);" % pname
+ print "\tcrDmpStrF(pRec->pDumper, \"%s = %%d;\", fEnabled);" % pname
+ print '#endif /* CR_%s */' % ext
+
+#print "//missing enable props:"
+#for prop in enableprops:
+# try:
+# keyvalues = params[prop]
+# except KeyError:
+# try:
+# keyvalues = extended_params[prop]
+# except KeyError:
+# print "//%s" % prop
+#
+print """
+}
+#endif
+"""
+
+texenv_mappings = {
+ 'GL_TEXTURE_ENV' : [
+ 'GL_TEXTURE_ENV_MODE',
+ 'GL_TEXTURE_ENV_COLOR',
+ 'GL_COMBINE_RGB',
+ 'GL_COMBINE_ALPHA',
+ 'GL_RGB_SCALE',
+ 'GL_ALPHA_SCALE',
+ 'GL_SRC0_RGB',
+ 'GL_SRC1_RGB',
+ 'GL_SRC2_RGB',
+ 'GL_SRC0_ALPHA',
+ 'GL_SRC1_ALPHA',
+ 'GL_SRC2_ALPHA'
+ ],
+ 'GL_TEXTURE_FILTER_CONTROL' : [
+ 'GL_TEXTURE_LOD_BIAS'
+ ],
+ 'GL_POINT_SPRITE' : [
+ 'GL_COORD_REPLACE'
+ ]
+}
+
+texgen_coords = [
+ 'GL_S',
+ 'GL_T',
+ 'GL_R',
+ 'GL_Q'
+]
+
+texgen_names = [
+ 'GL_TEXTURE_GEN_MODE',
+ 'GL_OBJECT_PLANE',
+ 'GL_EYE_PLANE'
+]
+
+texparam_names = [
+ 'GL_TEXTURE_MAG_FILTER',
+ 'GL_TEXTURE_MIN_FILTER',
+ 'GL_TEXTURE_MIN_LOD',
+ 'GL_TEXTURE_MAX_LOD',
+ 'GL_TEXTURE_BASE_LEVEL',
+ 'GL_TEXTURE_MAX_LEVEL',
+ 'GL_TEXTURE_WRAP_S',
+ 'GL_TEXTURE_WRAP_T',
+ 'GL_TEXTURE_WRAP_R',
+ 'GL_TEXTURE_BORDER_COLOR',
+ 'GL_TEXTURE_PRIORITY',
+ 'GL_TEXTURE_RESIDENT',
+ 'GL_TEXTURE_COMPARE_MODE',
+ 'GL_TEXTURE_COMPARE_FUNC',
+ 'GL_DEPTH_TEXTURE_MODE',
+ 'GL_GENERATE_MIPMAP'
+]
+
+print """
+void crRecDumpTexParam(CR_RECORDER *pRec, CRContext *ctx, GLenum enmTarget)
+{
+ GLfloat afBuf[4];
+ char acBuf[1024];
+ unsigned int cComponents;
+ crDmpStrF(pRec->pDumper, "==TEX_PARAM for target(0x%x)==", enmTarget);
+"""
+for pname in texparam_names:
+ print "\tcComponents = crStateHlpComponentsCount(%s);" % pname
+ print "\tAssert(cComponents <= RT_ELEMENTS(afBuf));"
+ print "\tmemset(afBuf, 0, sizeof (afBuf));"
+ print "\tpRec->pDispatch->GetTexParameterfv(enmTarget, %s, afBuf);" % pname
+ print "\tcrDmpFormatArray(acBuf, sizeof (acBuf), \"%f\", sizeof (afBuf[0]), afBuf, cComponents);"
+ print "\tcrDmpStrF(pRec->pDumper, \"%s = %%s;\", acBuf);" % pname
+print """
+ crDmpStrF(pRec->pDumper, "==Done TEX_PARAM for target(0x%x)==", enmTarget);
+}
+"""
+
+print """
+void crRecDumpTexEnv(CR_RECORDER *pRec, CRContext *ctx)
+{
+ GLfloat afBuf[4];
+ char acBuf[1024];
+ unsigned int cComponents;
+ crDmpStrF(pRec->pDumper, "==TEX_ENV==");
+"""
+
+keys = texenv_mappings.keys()
+keys.sort();
+
+for target in keys:
+ print "\tcrDmpStrF(pRec->pDumper, \"===%s===\");" % target
+ values = texenv_mappings[target]
+ for pname in values:
+ print "\tcComponents = crStateHlpComponentsCount(%s);" % pname
+ print "\tAssert(cComponents <= RT_ELEMENTS(afBuf));"
+ print "\tmemset(afBuf, 0, sizeof (afBuf));"
+ print "\tpRec->pDispatch->GetTexEnvfv(%s, %s, afBuf);" % (target, pname)
+ print "\tcrDmpFormatArray(acBuf, sizeof (acBuf), \"%f\", sizeof (afBuf[0]), afBuf, cComponents);"
+ print "\tcrDmpStrF(pRec->pDumper, \"%s = %%s;\", acBuf);" % pname
+ print "\tcrDmpStrF(pRec->pDumper, \"===Done %s===\");" % target
+print """
+ crDmpStrF(pRec->pDumper, "==Done TEX_ENV==");
+}
+"""
+
+
+print """
+void crRecDumpTexGen(CR_RECORDER *pRec, CRContext *ctx)
+{
+ GLdouble afBuf[4];
+ char acBuf[1024];
+ unsigned int cComponents;
+ crDmpStrF(pRec->pDumper, "==TEX_GEN==");
+"""
+
+for coord in texgen_coords:
+ print "\tcrDmpStrF(pRec->pDumper, \"===%s===\");" % coord
+ for pname in texgen_names:
+ print "\tcComponents = crStateHlpComponentsCount(%s);" % pname
+ print "\tAssert(cComponents <= RT_ELEMENTS(afBuf));"
+ print "\tmemset(afBuf, 0, sizeof (afBuf));"
+ print "\tpRec->pDispatch->GetTexGendv(%s, %s, afBuf);" % (coord, pname)
+ print "\tcrDmpFormatArray(acBuf, sizeof (acBuf), \"%f\", sizeof (afBuf[0]), afBuf, cComponents);"
+ print "\tcrDmpStrF(pRec->pDumper, \"%s = %%s;\", acBuf);" % pname
+ print "\tcrDmpStrF(pRec->pDumper, \"===Done %s===\");" % coord
+print """
+ crDmpStrF(pRec->pDumper, "==Done TEX_GEN==");
+}
+"""
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/get_components.py b/src/VBox/GuestHost/OpenGL/state_tracker/get_components.py
new file mode 100644
index 00000000..c9a32452
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/get_components.py
@@ -0,0 +1,144 @@
+# Copyright (c) 2001, Stanford University
+# All rights reserved.
+#
+# See the file LICENSE.txt for information on redistributing this software.
+
+num_components = {
+ 'GL_AMBIENT' : 4,
+ 'GL_DIFFUSE' : 4,
+ 'GL_SPECULAR' : 4,
+ 'GL_POSITION' : 4,
+ 'GL_SPOT_DIRECTION' : 3,
+ 'GL_SPOT_EXPONENT' : 1,
+ 'GL_SPOT_CUTOFF' : 1,
+ 'GL_CONSTANT_ATTENUATION' : 1,
+ 'GL_LINEAR_ATTENUATION' : 1,
+ 'GL_QUADRATIC_ATTENUATION' : 1,
+ 'GL_EMISSION' : 4,
+ 'GL_SHININESS' : 1,
+ 'GL_COLOR_INDEXES' : 3,
+ 'GL_TEXTURE_ENV_MODE' : 1,
+ 'GL_TEXTURE_ENV_COLOR' : 4,
+ 'GL_TEXTURE_GEN_MODE' : 1,
+ 'GL_OBJECT_PLANE' : 4,
+ 'GL_EYE_PLANE' : 4,
+ 'GL_TEXTURE_MAG_FILTER' : 1,
+ 'GL_TEXTURE_MIN_FILTER' : 1,
+ 'GL_TEXTURE_WRAP_S' : 1,
+ 'GL_TEXTURE_WRAP_T' : 1,
+ 'GL_TEXTURE_BORDER_COLOR' : 4,
+ 'GL_TEXTURE_WIDTH': 1,
+ 'GL_TEXTURE_HEIGHT': 1,
+ 'GL_TEXTURE_DEPTH': 1,
+ # 'GL_TEXTURE_INTERNAL_FORMAT': 1, THIS CONFLICTS WITH GL_TEXTURE_COMPONENTS!
+ 'GL_TEXTURE_BORDER': 1,
+ 'GL_TEXTURE_RED_SIZE': 1,
+ 'GL_TEXTURE_GREEN_SIZE': 1,
+ 'GL_TEXTURE_BLUE_SIZE': 1,
+ 'GL_TEXTURE_ALPHA_SIZE': 1,
+ 'GL_TEXTURE_LUMINANCE_SIZE': 1,
+ 'GL_TEXTURE_INTENSITY_SIZE': 1,
+ 'GL_TEXTURE_COMPONENTS': 1,
+ 'GL_TEXTURE_RESIDENT': 1
+}
+
+num_extended_components = {
+ 'GL_TEXTURE_MAX_ANISOTROPY_EXT': ( 1, 'CR_EXT_texture_filter_anisotropic' ),
+ 'GL_TEXTURE_WRAP_R': ( 1, 'CR_OPENGL_VERSION_1_2'),
+ 'GL_TEXTURE_PRIORITY': ( 1, 'CR_OPENGL_VERSION_1_2'),
+ 'GL_TEXTURE_MIN_LOD': ( 1, 'CR_OPENGL_VERSION_1_2'),
+ 'GL_TEXTURE_MAX_LOD': ( 1, 'CR_OPENGL_VERSION_1_2'),
+ 'GL_TEXTURE_BASE_LEVEL': ( 1, 'CR_OPENGL_VERSION_1_2'),
+ 'GL_TEXTURE_MAX_LEVEL': ( 1, 'CR_OPENGL_VERSION_1_2'),
+ 'GL_COMBINER_INPUT_NV': ( 1, 'CR_NV_register_combiners'),
+ 'GL_COMBINER_MAPPING_NV': ( 1, 'CR_NV_register_combiners'),
+ 'GL_COMBINER_COMPONENT_USAGE_NV': ( 1, 'CR_NV_register_combiners'),
+ 'GL_COMBINER_AB_DOT_PRODUCT_NV': ( 1, 'CR_NV_register_combiners'),
+ 'GL_COMBINER_CD_DOT_PRODUCT_NV': ( 1, 'CR_NV_register_combiners'),
+ 'GL_COMBINER_MUX_SUM_NV': ( 1, 'CR_NV_register_combiners'),
+ 'GL_COMBINER_SCALE_NV': ( 1, 'CR_NV_register_combiners'),
+ 'GL_COMBINER_BIAS_NV': ( 1, 'CR_NV_register_combiners'),
+ 'GL_COMBINER_AB_OUTPUT_NV': ( 1, 'CR_NV_register_combiners'),
+ 'GL_COMBINER_CD_OUTPUT_NV': ( 1, 'CR_NV_register_combiners'),
+ 'GL_COMBINER_SUM_OUTPUT_NV': ( 1, 'CR_NV_register_combiners'),
+ 'GL_COMBINER_INPUT_NV': ( 1, 'CR_NV_register_combiners'),
+ 'GL_COMBINER_INPUT_NV': ( 1, 'CR_NV_register_combiners'),
+ 'GL_COMBINER_MAPPING_NV': ( 1, 'CR_NV_register_combiners'),
+ 'GL_COMBINER_COMPONENT_USAGE_NV': ( 1, 'CR_NV_register_combiners'),
+ 'GL_CONSTANT_COLOR0_NV': ( 4, 'CR_NV_register_combiners'),
+ 'GL_CONSTANT_COLOR1_NV': ( 4, 'CR_NV_register_combiners'),
+ 'GL_COMBINE_RGB_ARB': (1, 'CR_ARB_texture_env_combine'),
+ 'GL_COMBINE_ALPHA_ARB': (1, 'CR_ARB_texture_env_combine'),
+ 'GL_SOURCE0_RGB_ARB': (1, 'CR_ARB_texture_env_combine'),
+ 'GL_SOURCE1_RGB_ARB': (1, 'CR_ARB_texture_env_combine'),
+ 'GL_SOURCE2_RGB_ARB': (1, 'CR_ARB_texture_env_combine'),
+ 'GL_SOURCE0_ALPHA_ARB': (1, 'CR_ARB_texture_env_combine'),
+ 'GL_SOURCE1_ALPHA_ARB': (1, 'CR_ARB_texture_env_combine'),
+ 'GL_SOURCE2_ALPHA_ARB': (1, 'CR_ARB_texture_env_combine'),
+ 'GL_OPERAND0_RGB_ARB': (1, 'CR_ARB_texture_env_combine'),
+ 'GL_OPERAND1_RGB_ARB': (1, 'CR_ARB_texture_env_combine'),
+ 'GL_OPERAND2_RGB_ARB': (1, 'CR_ARB_texture_env_combine'),
+ 'GL_OPERAND0_ALPHA_ARB': (1, 'CR_ARB_texture_env_combine'),
+ 'GL_OPERAND1_ALPHA_ARB': (1, 'CR_ARB_texture_env_combine'),
+ 'GL_OPERAND2_ALPHA_ARB': (1, 'CR_ARB_texture_env_combine'),
+ 'GL_RGB_SCALE_ARB': (1, 'CR_ARB_texture_env_combine'),
+ 'GL_ALPHA_SCALE': (1, 'CR_ARB_texture_env_combine'),
+ 'GL_DEPTH_TEXTURE_MODE_ARB': (1, 'CR_ARB_depth_texture'),
+ 'GL_TEXTURE_DEPTH_SIZE_ARB': (1, 'CR_ARB_depth_texture'),
+ 'GL_TEXTURE_COMPARE_MODE_ARB': (1, 'CR_ARB_shadow'),
+ 'GL_TEXTURE_COMPARE_FUNC_ARB': (1, 'CR_ARB_shadow'),
+ 'GL_TEXTURE_COMPARE_FAIL_VALUE_ARB': (1, 'CR_ARB_shadow_ambient'),
+ 'GL_GENERATE_MIPMAP_SGIS': (1, 'CR_SGIS_generate_mipmap'),
+ 'GL_TEXTURE_LOD_BIAS_EXT': (1, 'CR_EXT_texture_lod_bias'),
+ 'GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB': (1, 'CR_any_vertex_program'),
+ 'GL_CURRENT_VERTEX_ATTRIB_ARB': (4, 'CR_any_vertex_program'),
+ 'GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB': (1, 'CR_any_vertex_program'),
+ 'GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB': (1, 'CR_any_vertex_program'),
+ 'GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB': (1, 'CR_any_vertex_program'),
+ 'GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB': (1, 'CR_any_vertex_program'),
+ 'GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB': (1, 'CR_any_vertex_program'),
+ 'GL_TRACK_MATRIX_NV': (24, 'CR_any_vertex_program'),
+ 'GL_TRACK_MATRIX_TRANSFORM_NV': (24, 'CR_any_vertex_program'),
+ 'GL_BUFFER_SIZE_ARB': (1, 'CR_ARB_vertex_buffer_object'),
+ 'GL_BUFFER_USAGE_ARB': (1, 'CR_ARB_vertex_buffer_object'),
+ 'GL_BUFFER_ACCESS_ARB': (1, 'CR_ARB_vertex_buffer_object'),
+ 'GL_BUFFER_MAPPED_ARB': (1, 'CR_ARB_vertex_buffer_object'),
+ 'GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB': (1, 'CR_ARB_vertex_buffer_object'),
+ 'GL_QUERY_COUNTER_BITS_ARB': (1, 'CR_ARB_occlusion_query'),
+ 'GL_QUERY_RESULT_AVAILABLE_ARB': (1, 'CR_ARB_occlusion_query'),
+ 'GL_QUERY_RESULT_ARB': (1, 'CR_ARB_occlusion_query'),
+ 'GL_CURRENT_QUERY_ARB': (1, 'CR_ARB_occlusion_query'),
+ 'GL_TEXTURE_COMPRESSED_IMAGE_SIZE': (1, 'CR_ARB_texture_compression'),
+ 'GL_TEXTURE_COMPRESSED': (1, 'CR_ARB_texture_compression'),
+ 'GL_COORD_REPLACE_ARB': (1, 'CR_ARB_point_sprite'),
+}
+
+print """unsigned int crStateHlpComponentsCount( GLenum pname )
+{
+ switch( pname )
+ {
+"""
+comps = num_components.keys();
+comps.sort();
+for comp in comps:
+ print '\t\t\tcase %s: return %d;' % (comp,num_components[comp])
+
+comps = num_extended_components.keys();
+comps.sort();
+for comp in comps:
+ (nc, ifdef) = num_extended_components[comp]
+ print '#ifdef %s' % ifdef
+ print '\t\t\tcase %s: return %d;' % (comp,nc)
+ print '#endif /* %s */' % ifdef
+
+print """
+ default:
+ crError( "Unknown parameter name in crStateHlpComponentsCount: %d", (int) pname );
+ break;
+ }
+ /* NOTREACHED */
+ return 0;
+}
+"""
+
+
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state.h b/src/VBox/GuestHost/OpenGL/state_tracker/state.h
index c94525a1..07429aa9 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state.h
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state.h
@@ -9,6 +9,16 @@
#include "cr_glstate.h"
+#define CRSTATE_CHECKERR_RET(expr, result, message, ret) \
+ if (expr) { \
+ crStateError(__LINE__, __FILE__, result, message); \
+ return ret; \
+ }
+
+#define CRSTATE_NO_RETURN
+
+#define CRSTATE_CHECKERR(expr, result, message) CRSTATE_CHECKERR_RET(expr, result, message, CRSTATE_NO_RETURN)
+
typedef struct _crCheckIDHWID {
GLuint id, hwid;
} crCheckIDHWID_t;
@@ -33,6 +43,11 @@ extern CRContext *__currentContext;
#define GetCurrentContext() __currentContext
#endif
+extern GLboolean g_bVBoxEnableDiffOnMakeCurrent;
+
+extern CRContext *g_pAvailableContexts[CR_MAX_CONTEXTS];
+extern uint32_t g_cContexts;
+
extern void crStateTextureInitTextureObj (CRContext *ctx, CRTextureObj *tobj, GLuint name, GLenum target);
extern void crStateTextureInitTextureFormat( CRTextureLevel *tl, GLenum internalFormat );
@@ -55,10 +70,10 @@ void crStateClientDiff(CRClientBits *cb, CRbitvalue *bitID, CRContext *from, CRC
void crStateClientSwitch(CRClientBits *cb, CRbitvalue *bitID, CRContext *from, CRContext *to);
-void crStateGetTextureObjectAndImage(CRContext *g, GLenum texTarget, GLint level,
- CRTextureObj **obj, CRTextureLevel **img);
-
void crStateFreeBufferObject(void *data);
void crStateFreeFBO(void *data);
void crStateFreeRBO(void *data);
+
+void crStateGenNames(CRContext *g, CRHashTable *table, GLsizei n, GLuint *names);
+void crStateRegNames(CRContext *g, CRHashTable *table, GLsizei n, GLuint *names);
#endif
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_attrib.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_attrib.c
index 836c2221..68cbdb62 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_attrib.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_attrib.c
@@ -439,14 +439,17 @@ void STATE_APIENTRY crStatePushAttrib(GLbitfield mask)
if (mask & GL_STENCIL_BUFFER_BIT)
{
a->stencilBufferStack[a->stencilBufferStackDepth].stencilTest = g->stencil.stencilTest;
- a->stencilBufferStack[a->stencilBufferStackDepth].func = g->stencil.func;
- a->stencilBufferStack[a->stencilBufferStackDepth].mask = g->stencil.mask;
- a->stencilBufferStack[a->stencilBufferStackDepth].ref = g->stencil.ref;
- a->stencilBufferStack[a->stencilBufferStackDepth].fail = g->stencil.fail;
- a->stencilBufferStack[a->stencilBufferStackDepth].passDepthFail = g->stencil.passDepthFail;
- a->stencilBufferStack[a->stencilBufferStackDepth].passDepthPass = g->stencil.passDepthPass;
a->stencilBufferStack[a->stencilBufferStackDepth].clearValue = g->stencil.clearValue;
a->stencilBufferStack[a->stencilBufferStackDepth].writeMask = g->stencil.writeMask;
+ for (i = 0; i < CRSTATE_STENCIL_BUFFER_COUNT; ++i)
+ {
+ a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].func = g->stencil.buffers[i].func;
+ a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].mask = g->stencil.buffers[i].mask;
+ a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].ref = g->stencil.buffers[i].ref;
+ a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].fail = g->stencil.buffers[i].fail;
+ a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].passDepthFail = g->stencil.buffers[i].passDepthFail;
+ a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].passDepthPass = g->stencil.buffers[i].passDepthPass;
+ }
a->stencilBufferStackDepth++;
}
if (mask & GL_TEXTURE_BIT)
@@ -1033,20 +1036,28 @@ void STATE_APIENTRY crStatePopAttrib(void)
}
a->stencilBufferStackDepth--;
g->stencil.stencilTest = a->stencilBufferStack[a->stencilBufferStackDepth].stencilTest;
- g->stencil.func = a->stencilBufferStack[a->stencilBufferStackDepth].func;
- g->stencil.mask = a->stencilBufferStack[a->stencilBufferStackDepth].mask;
- g->stencil.ref = a->stencilBufferStack[a->stencilBufferStackDepth].ref;
- g->stencil.fail = a->stencilBufferStack[a->stencilBufferStackDepth].fail;
- g->stencil.passDepthFail = a->stencilBufferStack[a->stencilBufferStackDepth].passDepthFail;
- g->stencil.passDepthPass = a->stencilBufferStack[a->stencilBufferStackDepth].passDepthPass;
g->stencil.clearValue = a->stencilBufferStack[a->stencilBufferStackDepth].clearValue;
g->stencil.writeMask = a->stencilBufferStack[a->stencilBufferStackDepth].writeMask;
+ for (i = 0; i < CRSTATE_STENCIL_BUFFER_COUNT; ++i)
+ {
+ g->stencil.buffers[i].func = a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].func;
+ g->stencil.buffers[i].mask = a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].mask;
+ g->stencil.buffers[i].ref = a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].ref;
+ g->stencil.buffers[i].fail = a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].fail;
+ g->stencil.buffers[i].passDepthFail = a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].passDepthFail;
+ g->stencil.buffers[i].passDepthPass = a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].passDepthPass;
+ }
+
DIRTY(sb->stencil.dirty, g->neg_bitid);
DIRTY(sb->stencil.enable, g->neg_bitid);
- DIRTY(sb->stencil.func, g->neg_bitid);
- DIRTY(sb->stencil.op, g->neg_bitid);
DIRTY(sb->stencil.clearValue, g->neg_bitid);
DIRTY(sb->stencil.writeMask, g->neg_bitid);
+
+ for (i = 0; i < CRSTATE_STENCIL_BUFFER_REF_COUNT; ++i)
+ {
+ DIRTY(sb->stencil.bufferRefs[i].func, g->neg_bitid);
+ DIRTY(sb->stencil.bufferRefs[i].op, g->neg_bitid);
+ }
}
if (mask & GL_TEXTURE_BIT)
{
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_bits_globalop.h b/src/VBox/GuestHost/OpenGL/state_tracker/state_bits_globalop.h
new file mode 100644
index 00000000..351a85a3
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_bits_globalop.h
@@ -0,0 +1,338 @@
+/* $Id: state_bits_globalop.h $ */
+
+/** @file
+ * Global State bits operation
+ */
+
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include <iprt/cdefs.h>
+
+#include <cr_version.h>
+
+#ifndef CRSTATE_BITS_OP
+# error "CRSTATE_BITS_OP must be defined!"
+#endif
+
+#define _CRSTATE_BITS_OP_SIZEOF(_val) CRSTATE_BITS_OP(_val, RT_SIZEOFMEMB(CRStateBits, _val))
+
+#ifndef CRSTATE_BITS_OP_VERSION
+# define CRSTATE_BITS_OP_VERSION SHCROGL_SSM_VERSION
+#endif
+
+do {
+int i;
+#ifdef _CRSTATE_BITS_OP_STENCIL_V_33
+# error "_CRSTATE_BITS_OP_STENCIL_V_33 must no be defined!"
+#endif
+#if CRSTATE_BITS_OP_VERSION < SHCROGL_SSM_VERSION_WITH_FIXED_STENCIL
+# define _CRSTATE_BITS_OP_STENCIL_V_33
+#endif
+
+#ifdef _CRSTATE_BITS_OP_STENCIL_V_33
+# ifndef CRSTATE_BITS_OP_STENCIL_OP_V_33
+# error "CRSTATE_BITS_OP_STENCIL_OP_V_33 undefined!"
+# endif
+# ifndef CRSTATE_BITS_OP_STENCIL_FUNC_V_33
+# error "CRSTATE_BITS_OP_STENCIL_FUNC_V_33 undefined!"
+# endif
+#endif
+
+_CRSTATE_BITS_OP_SIZEOF(attrib.dirty);
+
+_CRSTATE_BITS_OP_SIZEOF(buffer.dirty);
+_CRSTATE_BITS_OP_SIZEOF(buffer.enable);
+_CRSTATE_BITS_OP_SIZEOF(buffer.alphaFunc);
+_CRSTATE_BITS_OP_SIZEOF(buffer.depthFunc);
+_CRSTATE_BITS_OP_SIZEOF(buffer.blendFunc);
+_CRSTATE_BITS_OP_SIZEOF(buffer.logicOp);
+_CRSTATE_BITS_OP_SIZEOF(buffer.indexLogicOp);
+_CRSTATE_BITS_OP_SIZEOF(buffer.drawBuffer);
+_CRSTATE_BITS_OP_SIZEOF(buffer.readBuffer);
+_CRSTATE_BITS_OP_SIZEOF(buffer.indexMask);
+_CRSTATE_BITS_OP_SIZEOF(buffer.colorWriteMask);
+_CRSTATE_BITS_OP_SIZEOF(buffer.clearColor);
+_CRSTATE_BITS_OP_SIZEOF(buffer.clearIndex);
+_CRSTATE_BITS_OP_SIZEOF(buffer.clearDepth);
+_CRSTATE_BITS_OP_SIZEOF(buffer.clearAccum);
+_CRSTATE_BITS_OP_SIZEOF(buffer.depthMask);
+#ifdef CR_EXT_blend_color
+_CRSTATE_BITS_OP_SIZEOF(buffer.blendColor);
+#endif
+#if defined(CR_EXT_blend_minmax) || defined(CR_EXT_blend_subtract) || defined(CR_EXT_blend_logic_op)
+_CRSTATE_BITS_OP_SIZEOF(buffer.blendEquation);
+#endif
+#if defined(CR_EXT_blend_func_separate)
+_CRSTATE_BITS_OP_SIZEOF(buffer.blendFuncSeparate);
+#endif
+
+#ifdef CR_ARB_vertex_buffer_object
+_CRSTATE_BITS_OP_SIZEOF(bufferobject.dirty);
+_CRSTATE_BITS_OP_SIZEOF(bufferobject.arrayBinding);
+_CRSTATE_BITS_OP_SIZEOF(bufferobject.elementsBinding);
+# ifdef CR_ARB_pixel_buffer_object
+_CRSTATE_BITS_OP_SIZEOF(bufferobject.packBinding);
+_CRSTATE_BITS_OP_SIZEOF(bufferobject.unpackBinding);
+# endif
+#endif
+
+_CRSTATE_BITS_OP_SIZEOF(client.dirty);
+_CRSTATE_BITS_OP_SIZEOF(client.pack);
+_CRSTATE_BITS_OP_SIZEOF(client.unpack);
+_CRSTATE_BITS_OP_SIZEOF(client.enableClientState);
+_CRSTATE_BITS_OP_SIZEOF(client.clientPointer);
+CRSTATE_BITS_OP(client.v, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+CRSTATE_BITS_OP(client.n, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+CRSTATE_BITS_OP(client.c, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+CRSTATE_BITS_OP(client.i, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+CRSTATE_BITS_OP(client.e, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+CRSTATE_BITS_OP(client.s, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+CRSTATE_BITS_OP(client.f, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+for (i=0; i<CR_MAX_TEXTURE_UNITS; i++)
+{
+ CRSTATE_BITS_OP(client.t[i], GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+}
+#ifdef CR_NV_vertex_program
+for (i=0; i<CR_MAX_VERTEX_ATTRIBS; i++)
+{
+ CRSTATE_BITS_OP(client.a[i], GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+}
+#endif
+
+_CRSTATE_BITS_OP_SIZEOF(current.dirty);
+for (i=0; i<CR_MAX_VERTEX_ATTRIBS; i++)
+{
+ _CRSTATE_BITS_OP_SIZEOF(current.vertexAttrib[i]);
+}
+_CRSTATE_BITS_OP_SIZEOF(current.edgeFlag);
+_CRSTATE_BITS_OP_SIZEOF(current.colorIndex);
+_CRSTATE_BITS_OP_SIZEOF(current.rasterPos);
+
+
+_CRSTATE_BITS_OP_SIZEOF(eval.dirty);
+for (i=0; i<GLEVAL_TOT; i++)
+{
+ _CRSTATE_BITS_OP_SIZEOF(eval.eval1D[i]);
+ _CRSTATE_BITS_OP_SIZEOF(eval.eval2D[i]);
+ _CRSTATE_BITS_OP_SIZEOF(eval.enable1D[i]);
+ _CRSTATE_BITS_OP_SIZEOF(eval.enable2D[i]);
+}
+_CRSTATE_BITS_OP_SIZEOF(eval.enable);
+_CRSTATE_BITS_OP_SIZEOF(eval.grid1D);
+_CRSTATE_BITS_OP_SIZEOF(eval.grid2D);
+#ifdef CR_NV_vertex_program
+ /*@todo Those seems to be unused?
+_CRSTATE_BITS_OP_SIZEOF(eval.enableAttrib1D);
+_CRSTATE_BITS_OP_SIZEOF(eval.enableAttrib2D);
+ */
+#endif
+
+_CRSTATE_BITS_OP_SIZEOF(feedback.dirty);
+_CRSTATE_BITS_OP_SIZEOF(selection.dirty);
+
+_CRSTATE_BITS_OP_SIZEOF(fog.dirty);
+_CRSTATE_BITS_OP_SIZEOF(fog.color);
+_CRSTATE_BITS_OP_SIZEOF(fog.index);
+_CRSTATE_BITS_OP_SIZEOF(fog.density);
+_CRSTATE_BITS_OP_SIZEOF(fog.start);
+_CRSTATE_BITS_OP_SIZEOF(fog.end);
+_CRSTATE_BITS_OP_SIZEOF(fog.mode);
+_CRSTATE_BITS_OP_SIZEOF(fog.enable);
+#ifdef CR_NV_fog_distance
+_CRSTATE_BITS_OP_SIZEOF(fog.fogDistanceMode);
+#endif
+#ifdef CR_EXT_fog_coord
+_CRSTATE_BITS_OP_SIZEOF(fog.fogCoordinateSource);
+#endif
+
+_CRSTATE_BITS_OP_SIZEOF(hint.dirty);
+_CRSTATE_BITS_OP_SIZEOF(hint.perspectiveCorrection);
+_CRSTATE_BITS_OP_SIZEOF(hint.pointSmooth);
+_CRSTATE_BITS_OP_SIZEOF(hint.lineSmooth);
+_CRSTATE_BITS_OP_SIZEOF(hint.polygonSmooth);
+_CRSTATE_BITS_OP_SIZEOF(hint.fog);
+#ifdef CR_EXT_clip_volume_hint
+_CRSTATE_BITS_OP_SIZEOF(hint.clipVolumeClipping);
+
+#endif
+#ifdef CR_ARB_texture_compression
+_CRSTATE_BITS_OP_SIZEOF(hint.textureCompression);
+#endif
+#ifdef CR_SGIS_generate_mipmap
+_CRSTATE_BITS_OP_SIZEOF(hint.generateMipmap);
+#endif
+
+_CRSTATE_BITS_OP_SIZEOF(lighting.dirty);
+_CRSTATE_BITS_OP_SIZEOF(lighting.shadeModel);
+_CRSTATE_BITS_OP_SIZEOF(lighting.colorMaterial);
+_CRSTATE_BITS_OP_SIZEOF(lighting.lightModel);
+_CRSTATE_BITS_OP_SIZEOF(lighting.material);
+_CRSTATE_BITS_OP_SIZEOF(lighting.enable);
+for (i=0; i<CR_MAX_LIGHTS; ++i)
+{
+ _CRSTATE_BITS_OP_SIZEOF(lighting.light[i].dirty);
+ _CRSTATE_BITS_OP_SIZEOF(lighting.light[i].enable);
+ _CRSTATE_BITS_OP_SIZEOF(lighting.light[i].ambient);
+ _CRSTATE_BITS_OP_SIZEOF(lighting.light[i].diffuse);
+ _CRSTATE_BITS_OP_SIZEOF(lighting.light[i].specular);
+ _CRSTATE_BITS_OP_SIZEOF(lighting.light[i].position);
+ _CRSTATE_BITS_OP_SIZEOF(lighting.light[i].attenuation);
+ _CRSTATE_BITS_OP_SIZEOF(lighting.light[i].spot);
+}
+
+_CRSTATE_BITS_OP_SIZEOF(line.dirty);
+_CRSTATE_BITS_OP_SIZEOF(line.enable);
+_CRSTATE_BITS_OP_SIZEOF(line.width);
+_CRSTATE_BITS_OP_SIZEOF(line.stipple);
+
+_CRSTATE_BITS_OP_SIZEOF(lists.dirty);
+_CRSTATE_BITS_OP_SIZEOF(lists.base);
+
+_CRSTATE_BITS_OP_SIZEOF(multisample.dirty);
+_CRSTATE_BITS_OP_SIZEOF(multisample.enable);
+_CRSTATE_BITS_OP_SIZEOF(multisample.sampleAlphaToCoverage);
+_CRSTATE_BITS_OP_SIZEOF(multisample.sampleAlphaToOne);
+_CRSTATE_BITS_OP_SIZEOF(multisample.sampleCoverage);
+_CRSTATE_BITS_OP_SIZEOF(multisample.sampleCoverageValue);
+
+#if CR_ARB_occlusion_query
+_CRSTATE_BITS_OP_SIZEOF(occlusion.dirty);
+#endif
+
+_CRSTATE_BITS_OP_SIZEOF(pixel.dirty);
+_CRSTATE_BITS_OP_SIZEOF(pixel.transfer);
+_CRSTATE_BITS_OP_SIZEOF(pixel.zoom);
+_CRSTATE_BITS_OP_SIZEOF(pixel.maps);
+
+_CRSTATE_BITS_OP_SIZEOF(point.dirty);
+_CRSTATE_BITS_OP_SIZEOF(point.enableSmooth);
+_CRSTATE_BITS_OP_SIZEOF(point.size);
+#ifdef CR_ARB_point_parameters
+_CRSTATE_BITS_OP_SIZEOF(point.minSize);
+_CRSTATE_BITS_OP_SIZEOF(point.maxSize);
+_CRSTATE_BITS_OP_SIZEOF(point.fadeThresholdSize);
+_CRSTATE_BITS_OP_SIZEOF(point.distanceAttenuation);
+#endif
+#ifdef CR_ARB_point_sprite
+_CRSTATE_BITS_OP_SIZEOF(point.enableSprite);
+for (i=0; i<CR_MAX_TEXTURE_UNITS; ++i)
+{
+ _CRSTATE_BITS_OP_SIZEOF(point.coordReplacement[i]);
+}
+#endif
+#if CRSTATE_BITS_OP_VERSION >= SHCROGL_SSM_VERSION_WITH_SPRITE_COORD_ORIGIN
+_CRSTATE_BITS_OP_SIZEOF(point.spriteCoordOrigin);
+#endif
+
+_CRSTATE_BITS_OP_SIZEOF(polygon.dirty);
+_CRSTATE_BITS_OP_SIZEOF(polygon.enable);
+_CRSTATE_BITS_OP_SIZEOF(polygon.offset);
+_CRSTATE_BITS_OP_SIZEOF(polygon.mode);
+_CRSTATE_BITS_OP_SIZEOF(polygon.stipple);
+
+_CRSTATE_BITS_OP_SIZEOF(program.dirty);
+_CRSTATE_BITS_OP_SIZEOF(program.vpEnable);
+_CRSTATE_BITS_OP_SIZEOF(program.fpEnable);
+_CRSTATE_BITS_OP_SIZEOF(program.vpBinding);
+_CRSTATE_BITS_OP_SIZEOF(program.fpBinding);
+for (i=0; i<CR_MAX_VERTEX_ATTRIBS; ++i)
+{
+ _CRSTATE_BITS_OP_SIZEOF(program.vertexAttribArrayEnable[i]);
+ _CRSTATE_BITS_OP_SIZEOF(program.map1AttribArrayEnable[i]);
+ _CRSTATE_BITS_OP_SIZEOF(program.map2AttribArrayEnable[i]);
+}
+for (i=0; i<CR_MAX_VERTEX_PROGRAM_ENV_PARAMS; ++i)
+{
+ _CRSTATE_BITS_OP_SIZEOF(program.vertexEnvParameter[i]);
+}
+for (i=0; i<CR_MAX_FRAGMENT_PROGRAM_ENV_PARAMS; ++i)
+{
+ _CRSTATE_BITS_OP_SIZEOF(program.fragmentEnvParameter[i]);
+}
+_CRSTATE_BITS_OP_SIZEOF(program.vertexEnvParameters);
+_CRSTATE_BITS_OP_SIZEOF(program.fragmentEnvParameters);
+for (i=0; i<CR_MAX_VERTEX_PROGRAM_ENV_PARAMS/4; ++i)
+{
+ _CRSTATE_BITS_OP_SIZEOF(program.trackMatrix[i]);
+}
+
+_CRSTATE_BITS_OP_SIZEOF(regcombiner.dirty);
+_CRSTATE_BITS_OP_SIZEOF(regcombiner.enable);
+_CRSTATE_BITS_OP_SIZEOF(regcombiner.regCombinerVars);
+_CRSTATE_BITS_OP_SIZEOF(regcombiner.regCombinerColor0);
+_CRSTATE_BITS_OP_SIZEOF(regcombiner.regCombinerColor1);
+for (i=0; i<CR_MAX_GENERAL_COMBINERS; ++i)
+{
+ _CRSTATE_BITS_OP_SIZEOF(regcombiner.regCombinerStageColor0[i]);
+ _CRSTATE_BITS_OP_SIZEOF(regcombiner.regCombinerStageColor1[i]);
+ _CRSTATE_BITS_OP_SIZEOF(regcombiner.regCombinerInput[i]);
+ _CRSTATE_BITS_OP_SIZEOF(regcombiner.regCombinerOutput[i]);
+}
+_CRSTATE_BITS_OP_SIZEOF(regcombiner.regCombinerFinalInput);
+
+_CRSTATE_BITS_OP_SIZEOF(stencil.dirty);
+_CRSTATE_BITS_OP_SIZEOF(stencil.enable);
+#ifdef _CRSTATE_BITS_OP_STENCIL_V_33
+_CRSTATE_BITS_OP_SIZEOF(stencil.bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].func);
+_CRSTATE_BITS_OP_SIZEOF(stencil.bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].op);
+for (i = CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK + 1; i < CRSTATE_STENCIL_BUFFER_REF_COUNT; ++i)
+{
+ CRSTATE_BITS_OP_STENCIL_FUNC_V_33(i, stencil.bufferRefs[i].func);
+ CRSTATE_BITS_OP_STENCIL_OP_V_33(i, stencil.bufferRefs[i].op);
+}
+_CRSTATE_BITS_OP_SIZEOF(stencil.clearValue);
+_CRSTATE_BITS_OP_SIZEOF(stencil.writeMask);
+#else
+_CRSTATE_BITS_OP_SIZEOF(stencil.enableTwoSideEXT);
+_CRSTATE_BITS_OP_SIZEOF(stencil.activeStencilFace);
+_CRSTATE_BITS_OP_SIZEOF(stencil.clearValue);
+_CRSTATE_BITS_OP_SIZEOF(stencil.writeMask);
+for (i = 0; i < CRSTATE_STENCIL_BUFFER_REF_COUNT; ++i)
+{
+ _CRSTATE_BITS_OP_SIZEOF(stencil.bufferRefs[i].func);
+ _CRSTATE_BITS_OP_SIZEOF(stencil.bufferRefs[i].op);
+}
+#endif
+
+_CRSTATE_BITS_OP_SIZEOF(texture.dirty);
+for (i=0; i<CR_MAX_TEXTURE_UNITS; ++i)
+{
+ _CRSTATE_BITS_OP_SIZEOF(texture.enable[i]);
+ _CRSTATE_BITS_OP_SIZEOF(texture.current[i]);
+ _CRSTATE_BITS_OP_SIZEOF(texture.objGen[i]);
+ _CRSTATE_BITS_OP_SIZEOF(texture.eyeGen[i]);
+ _CRSTATE_BITS_OP_SIZEOF(texture.genMode[i]);
+ _CRSTATE_BITS_OP_SIZEOF(texture.envBit[i]);
+}
+
+_CRSTATE_BITS_OP_SIZEOF(transform.dirty);
+_CRSTATE_BITS_OP_SIZEOF(transform.matrixMode);
+_CRSTATE_BITS_OP_SIZEOF(transform.modelviewMatrix);
+_CRSTATE_BITS_OP_SIZEOF(transform.projectionMatrix);
+_CRSTATE_BITS_OP_SIZEOF(transform.colorMatrix);
+_CRSTATE_BITS_OP_SIZEOF(transform.textureMatrix);
+_CRSTATE_BITS_OP_SIZEOF(transform.programMatrix);
+_CRSTATE_BITS_OP_SIZEOF(transform.clipPlane);
+_CRSTATE_BITS_OP_SIZEOF(transform.enable);
+_CRSTATE_BITS_OP_SIZEOF(transform.base);
+
+_CRSTATE_BITS_OP_SIZEOF(viewport.dirty);
+_CRSTATE_BITS_OP_SIZEOF(viewport.v_dims);
+_CRSTATE_BITS_OP_SIZEOF(viewport.s_dims);
+_CRSTATE_BITS_OP_SIZEOF(viewport.enable);
+_CRSTATE_BITS_OP_SIZEOF(viewport.depth);
+
+} while (0);
+
+#undef CRSTATE_BITS_OP_VERSION
+#undef _CRSTATE_BITS_OP_STENCIL_V_33
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_buffer.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_buffer.c
index 6214e889..90917ab5 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_buffer.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_buffer.c
@@ -483,6 +483,7 @@ void STATE_APIENTRY crStateDrawBuffer (GLenum mode)
switch (mode)
{
case GL_NONE:
+ break;
case GL_FRONT_LEFT:
case GL_FRONT_RIGHT:
case GL_BACK_LEFT:
@@ -548,6 +549,7 @@ void STATE_APIENTRY crStateReadBuffer (GLenum mode)
switch (mode)
{
case GL_NONE:
+ break;
case GL_FRONT_LEFT:
case GL_FRONT_RIGHT:
case GL_BACK_LEFT:
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_bufferobject.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_bufferobject.c
index 5a3d2e49..bd6a1e20 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_bufferobject.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_bufferobject.c
@@ -22,16 +22,25 @@ static CRBufferObject *AllocBufferObject(GLuint name)
b->usage = GL_STATIC_DRAW_ARB;
b->access = GL_READ_WRITE_ARB;
b->bResyncOnRead = GL_FALSE;
-#ifndef IN_GUEST
CR_STATE_SHAREDOBJ_USAGE_INIT(b);
-#endif
}
return b;
}
-GLboolean crStateIsBufferBound(GLenum target)
+void STATE_APIENTRY crStateGenBuffersARB(GLsizei n, GLuint *buffers)
+{
+ CRContext *g = GetCurrentContext();
+ crStateGenNames(g, g->shared->buffersTable, n, buffers);
+}
+
+void crStateRegBuffers(GLsizei n, GLuint *buffers)
{
CRContext *g = GetCurrentContext();
+ crStateRegNames(g, g->shared->buffersTable, n, buffers);
+}
+
+GLboolean crStateIsBufferBoundForCtx(CRContext *g, GLenum target)
+{
CRBufferObjectState *b = &(g->bufferobject);
switch (target)
@@ -51,6 +60,12 @@ GLboolean crStateIsBufferBound(GLenum target)
}
}
+GLboolean crStateIsBufferBound(GLenum target)
+{
+ CRContext *g = GetCurrentContext();
+ return crStateIsBufferBoundForCtx(g, target);
+}
+
CRBufferObject *crStateGetBoundBufferObject(GLenum target, CRBufferObjectState *b)
{
switch (target)
@@ -70,6 +85,21 @@ CRBufferObject *crStateGetBoundBufferObject(GLenum target, CRBufferObjectState *
}
}
+DECLEXPORT(GLboolean) STATE_APIENTRY crStateIsBufferARB( GLuint buffer )
+{
+ CRContext *g = GetCurrentContext();
+
+ FLUSH();
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glIsBufferARB called in begin/end");
+ return GL_FALSE;
+ }
+
+ return buffer ? crHashtableIsKeyUsed(g->shared->buffersTable, buffer) : GL_FALSE;
+}
+
void crStateBufferObjectInit (CRContext *ctx)
{
CRStateBits *sb = GetCurrentBits();
@@ -93,7 +123,7 @@ void crStateBufferObjectInit (CRContext *ctx)
b->nullBuffer = AllocBufferObject(0);
b->arrayBuffer = b->nullBuffer;
b->elementsBuffer = b->nullBuffer;
- b->nullBuffer->refCount = 3;
+ b->nullBuffer->refCount += 2;
#ifdef CR_ARB_pixel_buffer_object
b->packBuffer = b->nullBuffer;
b->unpackBuffer = b->nullBuffer;
@@ -184,17 +214,22 @@ crStateBindBufferARB (GLenum target, GLuint buffer)
else {
newObj = (CRBufferObject *) crHashtableSearch(g->shared->buffersTable, buffer);
if (!newObj) {
+ CRSTATE_CHECKERR(!crHashtableIsKeyUsed(g->shared->buffersTable, buffer), GL_INVALID_OPERATION, "name is not a buffer object");
newObj = AllocBufferObject(buffer);
- if (!newObj) {
- crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, "glBindBuffer");
+ CRSTATE_CHECKERR(!newObj, GL_OUT_OF_MEMORY, "glBindBuffer");
+#ifndef IN_GUEST
+ diff_api.GenBuffersARB(1, &newObj->hwid);
+ if (!newObj->hwid)
+ {
+ crWarning("GenBuffersARB failed!");
+ crFree(newObj);
return;
}
+#endif
crHashtableAdd( g->shared->buffersTable, buffer, newObj );
}
-#ifndef IN_GUEST
CR_STATE_SHAREDOBJ_USAGE_SET(newObj, g);
-#endif
}
newObj->refCount++;
@@ -243,127 +278,124 @@ crStateBindBufferARB (GLenum target, GLuint buffer)
#endif
}
-void STATE_APIENTRY
-crStateDeleteBuffersARB(GLsizei n, const GLuint *buffers)
+static void ctStateBuffersRefsCleanup(CRContext *ctx, CRBufferObject *obj, CRbitvalue *neg_bitid)
{
- CRContext *g = GetCurrentContext();
- CRBufferObjectState *b = &(g->bufferobject);
+ CRBufferObjectState *b = &(ctx->bufferobject);
CRStateBits *sb = GetCurrentBits();
CRBufferObjectBits *bb = &(sb->bufferobject);
- int i;
+ int j, k;
- FLUSH();
-
- if (g->current.inBeginEnd) {
- crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
- "glDeleteBuffersARB called in Begin/End");
- return;
+ if (obj == b->arrayBuffer)
+ {
+ b->arrayBuffer = b->nullBuffer;
+ b->arrayBuffer->refCount++;
+ DIRTY(bb->dirty, neg_bitid);
+ DIRTY(bb->arrayBinding, neg_bitid);
}
-
- if (n < 0) {
- crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
- "glDeleteBuffersARB(n < 0)");
- return;
+ if (obj == b->elementsBuffer)
+ {
+ b->elementsBuffer = b->nullBuffer;
+ b->elementsBuffer->refCount++;
+ DIRTY(bb->dirty, neg_bitid);
+ DIRTY(bb->elementsBinding, neg_bitid);
}
-
- for (i = 0; i < n; i++) {
- if (buffers[i]) {
- CRBufferObject *obj = (CRBufferObject *)
- crHashtableSearch(g->shared->buffersTable, buffers[i]);
- if (obj) {
- if (obj == b->arrayBuffer)
- {
- b->arrayBuffer = b->nullBuffer;
- b->arrayBuffer->refCount++;
- DIRTY(bb->dirty, g->neg_bitid);
- DIRTY(bb->arrayBinding, g->neg_bitid);
- }
- else if (obj == b->elementsBuffer)
- {
- b->elementsBuffer = b->nullBuffer;
- b->elementsBuffer->refCount++;
- DIRTY(bb->dirty, g->neg_bitid);
- DIRTY(bb->elementsBinding, g->neg_bitid);
- }
#ifdef CR_ARB_pixel_buffer_object
- else if (obj == b->packBuffer)
- {
- b->packBuffer = b->nullBuffer;
- b->packBuffer->refCount++;
- DIRTY(bb->dirty, g->neg_bitid);
- DIRTY(bb->packBinding, g->neg_bitid);
- }
- else if (obj == b->unpackBuffer)
- {
- b->unpackBuffer = b->nullBuffer;
- b->unpackBuffer->refCount++;
- DIRTY(bb->dirty, g->neg_bitid);
- DIRTY(bb->unpackBinding, g->neg_bitid);
- }
+ if (obj == b->packBuffer)
+ {
+ b->packBuffer = b->nullBuffer;
+ b->packBuffer->refCount++;
+ DIRTY(bb->dirty, neg_bitid);
+ DIRTY(bb->packBinding, neg_bitid);
+ }
+ if (obj == b->unpackBuffer)
+ {
+ b->unpackBuffer = b->nullBuffer;
+ b->unpackBuffer->refCount++;
+ DIRTY(bb->dirty, neg_bitid);
+ DIRTY(bb->unpackBinding, neg_bitid);
+ }
#endif
- /* @todo check bindings with the vertex arrays */
- crHashtableDelete(g->shared->buffersTable, buffers[i], crStateFreeBufferObject);
+#ifdef CR_ARB_vertex_buffer_object
+ for (j=0; j<CRSTATECLIENT_MAX_VERTEXARRAYS; ++j)
+ {
+ CRClientPointer *cp = crStateGetClientPointerByIndex(j, &ctx->client.array);
+ if (obj == cp->buffer)
+ {
+ cp->buffer = b->nullBuffer;
+ ++b->nullBuffer->refCount;
+ }
+ }
+
+ for (k=0; k<ctx->client.vertexArrayStackDepth; ++k)
+ {
+ CRVertexArrays *pArray = &ctx->client.vertexArrayStack[k];
+ for (j=0; j<CRSTATECLIENT_MAX_VERTEXARRAYS; ++j)
+ {
+ CRClientPointer *cp = crStateGetClientPointerByIndex(j, pArray);
+ if (obj == cp->buffer)
+ {
+ cp->buffer = b->nullBuffer;
+ ++b->nullBuffer->refCount;
}
}
}
-}
+#endif
+ CR_STATE_SHAREDOBJ_USAGE_CLEAR(obj, ctx);
+}
void STATE_APIENTRY
-crStateGenBuffersARB(GLsizei n, GLuint * buffers)
+crStateDeleteBuffersARB(GLsizei n, const GLuint *buffers)
{
CRContext *g = GetCurrentContext();
- CRBufferObjectState *b = &(g->bufferobject);
- GLint start;
+ int i;
FLUSH();
if (g->current.inBeginEnd) {
crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
- "glGenBuffersARB called in Begin/End");
+ "glDeleteBuffersARB called in Begin/End");
return;
}
if (n < 0) {
crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
- "glGenBuffersARB(n < 0)");
+ "glDeleteBuffersARB(n < 0)");
return;
}
- start = crHashtableAllocKeys(g->shared->buffersTable, n);
- if (start) {
- GLint i;
- for (i = 0; i < n; i++)
- buffers[i] = (GLuint) (start + i);
- }
- else {
- crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, "glGenBuffersARB");
- }
-}
-
+ for (i = 0; i < n; i++) {
+ if (buffers[i]) {
+ CRBufferObject *obj = (CRBufferObject *)
+ crHashtableSearch(g->shared->buffersTable, buffers[i]);
+ if (obj) {
+ int j;
-GLboolean STATE_APIENTRY
-crStateIsBufferARB(GLuint buffer)
-{
- CRContext *g = GetCurrentContext();
- CRBufferObjectState *b = &g->bufferobject;
+ ctStateBuffersRefsCleanup(g, obj, g->neg_bitid);
- FLUSH();
+ CR_STATE_SHAREDOBJ_USAGE_FOREACH_USED_IDX(obj, j)
+ {
+ /* saved state version <= SHCROGL_SSM_VERSION_BEFORE_CTXUSAGE_BITS does not have usage bits info,
+ * so on restore, we set mark bits as used.
+ * This is why g_pAvailableContexts[j] could be NULL
+ * also g_pAvailableContexts[0] will hold default context, which we should discard */
+ CRContext *ctx = g_pAvailableContexts[j];
+ if (j && ctx)
+ {
+ ctStateBuffersRefsCleanup(ctx, obj, g->neg_bitid); /* <- yes, use g->neg_bitid, i.e. neg_bitid of the current context to ensure others bits get dirtified,
+ * but not the current context ones*/
+ }
+ else
+ CR_STATE_SHAREDOBJ_USAGE_CLEAR_IDX(obj, j);
+ }
- if (g->current.inBeginEnd) {
- crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
- "glIsBufferARB called in begin/end");
- return GL_FALSE;
+ crHashtableDelete(g->shared->buffersTable, buffers[i], crStateFreeBufferObject);
+ }
+ }
}
-
- if (buffer && crHashtableSearch(g->shared->buffersTable, buffer))
- return GL_TRUE;
- else
- return GL_FALSE;
}
-
void STATE_APIENTRY
crStateBufferDataARB(GLenum target, GLsizeiptrARB size, const GLvoid * data, GLenum usage)
{
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_client.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_client.c
index f0405c64..e02f3abe 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_client.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_client.c
@@ -83,8 +83,9 @@ static void crStateUnlockClientPointer(CRClientPointer* cp)
}
}
-void crStateClientDestroy(CRClientState *c)
+void crStateClientDestroy(CRContext *g)
{
+ CRClientState *c = &(g->client);
#ifdef CR_EXT_compiled_vertex_array
if (c->array.locked)
{
@@ -109,9 +110,9 @@ void crStateClientDestroy(CRClientState *c)
#endif
}
-void crStateClientInit(CRClientState *c)
+void crStateClientInit(CRContext *ctx)
{
- CRContext *g = GetCurrentContext();
+ CRClientState *c = &(ctx->client);
unsigned int i;
/* pixel pack/unpack */
@@ -151,7 +152,9 @@ void crStateClientInit(CRClientState *c)
c->array.v.stride = 0;
c->array.v.enabled = 0;
#ifdef CR_ARB_vertex_buffer_object
- c->array.v.buffer = g ? g->bufferobject.arrayBuffer : NULL;
+ c->array.v.buffer = ctx->bufferobject.arrayBuffer;
+ if (c->array.v.buffer)
+ ++c->array.v.buffer->refCount;
#endif
#ifdef CR_EXT_compiled_vertex_array
c->array.v.locked = GL_FALSE;
@@ -166,7 +169,9 @@ void crStateClientInit(CRClientState *c)
c->array.c.stride = 0;
c->array.c.enabled = 0;
#ifdef CR_ARB_vertex_buffer_object
- c->array.c.buffer = g ? g->bufferobject.arrayBuffer : NULL;
+ c->array.c.buffer = ctx->bufferobject.arrayBuffer;
+ if (c->array.c.buffer)
+ ++c->array.c.buffer->refCount;
#endif
#ifdef CR_EXT_compiled_vertex_array
c->array.c.locked = GL_FALSE;
@@ -181,7 +186,9 @@ void crStateClientInit(CRClientState *c)
c->array.f.stride = 0;
c->array.f.enabled = 0;
#ifdef CR_ARB_vertex_buffer_object
- c->array.f.buffer = g ? g->bufferobject.arrayBuffer : NULL;
+ c->array.f.buffer = ctx->bufferobject.arrayBuffer;
+ if (c->array.f.buffer)
+ ++c->array.f.buffer->refCount;
#endif
#ifdef CR_EXT_compiled_vertex_array
c->array.f.locked = GL_FALSE;
@@ -196,7 +203,9 @@ void crStateClientInit(CRClientState *c)
c->array.s.stride = 0;
c->array.s.enabled = 0;
#ifdef CR_ARB_vertex_buffer_object
- c->array.s.buffer = g ? g->bufferobject.arrayBuffer : NULL;
+ c->array.s.buffer = ctx->bufferobject.arrayBuffer;
+ if (c->array.s.buffer)
+ ++c->array.s.buffer->refCount;
#endif
#ifdef CR_EXT_compiled_vertex_array
c->array.s.locked = GL_FALSE;
@@ -211,7 +220,9 @@ void crStateClientInit(CRClientState *c)
c->array.e.stride = 0;
c->array.e.enabled = 0;
#ifdef CR_ARB_vertex_buffer_object
- c->array.e.buffer = g ? g->bufferobject.arrayBuffer : NULL;
+ c->array.e.buffer = ctx->bufferobject.arrayBuffer;
+ if (c->array.e.buffer)
+ ++c->array.e.buffer->refCount;
#endif
#ifdef CR_EXT_compiled_vertex_array
c->array.e.locked = GL_FALSE;
@@ -226,7 +237,9 @@ void crStateClientInit(CRClientState *c)
c->array.i.stride = 0;
c->array.i.enabled = 0;
#ifdef CR_ARB_vertex_buffer_object
- c->array.i.buffer = g ? g->bufferobject.arrayBuffer : NULL;
+ c->array.i.buffer = ctx->bufferobject.arrayBuffer;
+ if (c->array.i.buffer)
+ ++c->array.i.buffer->refCount;
#endif
#ifdef CR_EXT_compiled_vertex_array
c->array.i.locked = GL_FALSE;
@@ -241,7 +254,9 @@ void crStateClientInit(CRClientState *c)
c->array.n.stride = 0;
c->array.n.enabled = 0;
#ifdef CR_ARB_vertex_buffer_object
- c->array.n.buffer = g ? g->bufferobject.arrayBuffer : NULL;
+ c->array.n.buffer = ctx->bufferobject.arrayBuffer;
+ if (c->array.n.buffer)
+ ++c->array.n.buffer->refCount;
#endif
#ifdef CR_EXT_compiled_vertex_array
c->array.n.locked = GL_FALSE;
@@ -258,7 +273,9 @@ void crStateClientInit(CRClientState *c)
c->array.t[i].stride = 0;
c->array.t[i].enabled = 0;
#ifdef CR_ARB_vertex_buffer_object
- c->array.t[i].buffer = g ? g->bufferobject.arrayBuffer : NULL;
+ c->array.t[i].buffer = ctx->bufferobject.arrayBuffer;
+ if (c->array.t[i].buffer)
+ ++c->array.t[i].buffer->refCount;
#endif
#ifdef CR_EXT_compiled_vertex_array
c->array.t[i].locked = GL_FALSE;
@@ -275,7 +292,9 @@ void crStateClientInit(CRClientState *c)
c->array.a[i].size = 4;
c->array.a[i].stride = 0;
#ifdef CR_ARB_vertex_buffer_object
- c->array.a[i].buffer = g ? g->bufferobject.arrayBuffer : NULL;
+ c->array.a[i].buffer = ctx->bufferobject.arrayBuffer;
+ if (c->array.a[i].buffer)
+ ++c->array.a[i].buffer->refCount;
#endif
#ifdef CR_EXT_compiled_vertex_array
c->array.a[i].locked = GL_FALSE;
@@ -622,7 +641,14 @@ crStateClientSetPointer(CRClientPointer *cp, GLint size,
cp->stride = cp->bytesPerIndex;
#ifdef CR_ARB_vertex_buffer_object
+ if (cp->buffer)
+ {
+ --cp->buffer->refCount;
+ CRASSERT(cp->buffer->refCount && cp->buffer->refCount < UINT32_MAX/2);
+ }
cp->buffer = g->bufferobject.arrayBuffer;
+ if (cp->buffer)
+ ++cp->buffer->refCount;
#endif
}
@@ -1622,6 +1648,7 @@ crStateUseServerArrayElements(void)
#endif
}
+#define CR_BUFFER_HWID(_p) ((_p) ? (_p)->hwid : 0)
void
crStateClientDiff(CRClientBits *cb, CRbitvalue *bitID,
@@ -1631,6 +1658,17 @@ crStateClientDiff(CRClientBits *cb, CRbitvalue *bitID,
const CRClientState *to = &(toCtx->client);
GLint curClientTextureUnit = from->curClientTextureUnit;
int i;
+ GLint idHwArrayBuffer = CR_BUFFER_HWID(toCtx->bufferobject.arrayBuffer);
+ const GLint idHwInitialBuffer = idHwArrayBuffer;
+
+#ifdef DEBUG_misha
+ {
+ GLint tstHwBuffer = -1;
+ diff_api.GetIntegerv(GL_ARRAY_BUFFER_BINDING, &tstHwBuffer);
+ CRASSERT(idHwInitialBuffer == tstHwBuffer);
+ }
+#endif
+
if (CHECKDIRTY(cb->clientPointer, bitID)) {
/* one or more vertex pointers is dirty */
@@ -1638,7 +1676,14 @@ crStateClientDiff(CRClientBits *cb, CRbitvalue *bitID,
if (from->array.v.size != to->array.v.size ||
from->array.v.type != to->array.v.type ||
from->array.v.stride != to->array.v.stride ||
+ from->array.v.p != to->array.v.p ||
from->array.v.buffer != to->array.v.buffer) {
+ GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.v.buffer);
+ if (idHwArrayBufferUsed != idHwArrayBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed);
+ idHwArrayBuffer = idHwArrayBufferUsed;
+ }
diff_api.VertexPointer(to->array.v.size, to->array.v.type,
to->array.v.stride, to->array.v.p);
from->array.v.size = to->array.v.size;
@@ -1653,7 +1698,14 @@ crStateClientDiff(CRClientBits *cb, CRbitvalue *bitID,
if (CHECKDIRTY(cb->n, bitID)) {
if (from->array.n.type != to->array.n.type ||
from->array.n.stride != to->array.n.stride ||
+ from->array.n.p != to->array.n.p ||
from->array.n.buffer != to->array.n.buffer) {
+ GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.n.buffer);
+ if (idHwArrayBufferUsed != idHwArrayBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed);
+ idHwArrayBuffer = idHwArrayBufferUsed;
+ }
diff_api.NormalPointer(to->array.n.type,
to->array.n.stride, to->array.n.p);
from->array.n.type = to->array.n.type;
@@ -1668,7 +1720,14 @@ crStateClientDiff(CRClientBits *cb, CRbitvalue *bitID,
if (from->array.c.size != to->array.c.size ||
from->array.c.type != to->array.c.type ||
from->array.c.stride != to->array.c.stride ||
+ from->array.c.p != to->array.c.p ||
from->array.c.buffer != to->array.c.buffer) {
+ GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.c.buffer);
+ if (idHwArrayBufferUsed != idHwArrayBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed);
+ idHwArrayBuffer = idHwArrayBufferUsed;
+ }
diff_api.ColorPointer(to->array.c.size, to->array.c.type,
to->array.c.stride, to->array.c.p);
from->array.c.size = to->array.c.size;
@@ -1683,7 +1742,14 @@ crStateClientDiff(CRClientBits *cb, CRbitvalue *bitID,
if (CHECKDIRTY(cb->i, bitID)) {
if (from->array.i.type != to->array.i.type ||
from->array.i.stride != to->array.i.stride ||
+ from->array.i.p != to->array.i.p ||
from->array.i.buffer != to->array.i.buffer) {
+ GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.i.buffer);
+ if (idHwArrayBufferUsed != idHwArrayBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed);
+ idHwArrayBuffer = idHwArrayBufferUsed;
+ }
diff_api.IndexPointer(to->array.i.type,
to->array.i.stride, to->array.i.p);
from->array.i.type = to->array.i.type;
@@ -1699,7 +1765,14 @@ crStateClientDiff(CRClientBits *cb, CRbitvalue *bitID,
if (from->array.t[i].size != to->array.t[i].size ||
from->array.t[i].type != to->array.t[i].type ||
from->array.t[i].stride != to->array.t[i].stride ||
+ from->array.t[i].p != to->array.t[i].p ||
from->array.t[i].buffer != to->array.t[i].buffer) {
+ GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.t[i].buffer);
+ if (idHwArrayBufferUsed != idHwArrayBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed);
+ idHwArrayBuffer = idHwArrayBufferUsed;
+ }
diff_api.ClientActiveTextureARB(GL_TEXTURE0_ARB + i);
curClientTextureUnit = i;
diff_api.TexCoordPointer(to->array.t[i].size, to->array.t[i].type,
@@ -1716,7 +1789,14 @@ crStateClientDiff(CRClientBits *cb, CRbitvalue *bitID,
/* edge flag */
if (CHECKDIRTY(cb->e, bitID)) {
if (from->array.e.stride != to->array.e.stride ||
+ from->array.e.p != to->array.e.p ||
from->array.e.buffer != to->array.e.buffer) {
+ GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.e.buffer);
+ if (idHwArrayBufferUsed != idHwArrayBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed);
+ idHwArrayBuffer = idHwArrayBufferUsed;
+ }
diff_api.EdgeFlagPointer(to->array.e.stride, to->array.e.p);
from->array.e.stride = to->array.e.stride;
from->array.e.p = to->array.e.p;
@@ -1729,7 +1809,14 @@ crStateClientDiff(CRClientBits *cb, CRbitvalue *bitID,
if (from->array.s.size != to->array.s.size ||
from->array.s.type != to->array.s.type ||
from->array.s.stride != to->array.s.stride ||
+ from->array.s.p != to->array.s.p ||
from->array.s.buffer != to->array.s.buffer) {
+ GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.s.buffer);
+ if (idHwArrayBufferUsed != idHwArrayBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed);
+ idHwArrayBuffer = idHwArrayBufferUsed;
+ }
diff_api.SecondaryColorPointerEXT(to->array.s.size, to->array.s.type,
to->array.s.stride, to->array.s.p);
from->array.s.size = to->array.s.size;
@@ -1744,7 +1831,14 @@ crStateClientDiff(CRClientBits *cb, CRbitvalue *bitID,
if (CHECKDIRTY(cb->f, bitID)) {
if (from->array.f.type != to->array.f.type ||
from->array.f.stride != to->array.f.stride ||
+ from->array.f.p != to->array.f.p ||
from->array.f.buffer != to->array.f.buffer) {
+ GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.f.buffer);
+ if (idHwArrayBufferUsed != idHwArrayBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed);
+ idHwArrayBuffer = idHwArrayBufferUsed;
+ }
diff_api.FogCoordPointerEXT(to->array.f.type,
to->array.f.stride, to->array.f.p);
from->array.f.type = to->array.f.type;
@@ -1762,7 +1856,14 @@ crStateClientDiff(CRClientBits *cb, CRbitvalue *bitID,
from->array.a[i].type != to->array.a[i].type ||
from->array.a[i].stride != to->array.a[i].stride ||
from->array.a[i].normalized != to->array.a[i].normalized ||
+ from->array.a[i].p != to->array.a[i].p ||
from->array.a[i].buffer != to->array.a[i].buffer) {
+ GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.a[i].buffer);
+ if (idHwArrayBufferUsed != idHwArrayBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed);
+ idHwArrayBuffer = idHwArrayBufferUsed;
+ }
diff_api.VertexAttribPointerARB(i, to->array.a[i].size,
to->array.a[i].type,
to->array.a[i].normalized,
@@ -1781,11 +1882,16 @@ crStateClientDiff(CRClientBits *cb, CRbitvalue *bitID,
#endif
}
+ if (idHwArrayBuffer != idHwInitialBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwInitialBuffer);
+ }
+
if (CHECKDIRTY(cb->enableClientState, bitID)) {
/* update vertex array enable/disable flags */
glAble able[2];
- able[0] = diff_api.Disable;
- able[1] = diff_api.Enable;
+ able[0] = diff_api.DisableClientState;
+ able[1] = diff_api.EnableClientState;
if (from->array.v.enabled != to->array.v.enabled) {
able[to->array.v.enabled](GL_VERTEX_ARRAY);
from->array.v.enabled = to->array.v.enabled;
@@ -1849,6 +1955,16 @@ crStateClientSwitch(CRClientBits *cb, CRbitvalue *bitID,
const CRClientState *to = &(toCtx->client);
GLint curClientTextureUnit = from->curClientTextureUnit;
int i;
+ GLint idHwArrayBuffer = CR_BUFFER_HWID(toCtx->bufferobject.arrayBuffer);
+ const GLint idHwInitialBuffer = idHwArrayBuffer;
+
+#ifdef DEBUG_misha
+ {
+ GLint tstHwBuffer = -1;
+ diff_api.GetIntegerv(GL_ARRAY_BUFFER_BINDING, &tstHwBuffer);
+ CRASSERT(idHwInitialBuffer == tstHwBuffer);
+ }
+#endif
if (CHECKDIRTY(cb->clientPointer, bitID)) {
/* one or more vertex pointers is dirty */
@@ -1856,7 +1972,14 @@ crStateClientSwitch(CRClientBits *cb, CRbitvalue *bitID,
if (from->array.v.size != to->array.v.size ||
from->array.v.type != to->array.v.type ||
from->array.v.stride != to->array.v.stride ||
+ from->array.v.p != to->array.v.p ||
from->array.v.buffer != to->array.v.buffer) {
+ GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.v.buffer);
+ if (idHwArrayBufferUsed != idHwArrayBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed);
+ idHwArrayBuffer = idHwArrayBufferUsed;
+ }
diff_api.VertexPointer(to->array.v.size, to->array.v.type,
to->array.v.stride, to->array.v.p);
FILLDIRTY(cb->v);
@@ -1869,7 +1992,14 @@ crStateClientSwitch(CRClientBits *cb, CRbitvalue *bitID,
if (CHECKDIRTY(cb->n, bitID)) {
if (from->array.n.type != to->array.n.type ||
from->array.n.stride != to->array.n.stride ||
+ from->array.n.p != to->array.n.p ||
from->array.n.buffer != to->array.n.buffer) {
+ GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.n.buffer);
+ if (idHwArrayBufferUsed != idHwArrayBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed);
+ idHwArrayBuffer = idHwArrayBufferUsed;
+ }
diff_api.NormalPointer(to->array.n.type,
to->array.n.stride, to->array.n.p);
FILLDIRTY(cb->n);
@@ -1883,7 +2013,14 @@ crStateClientSwitch(CRClientBits *cb, CRbitvalue *bitID,
if (from->array.c.size != to->array.c.size ||
from->array.c.type != to->array.c.type ||
from->array.c.stride != to->array.c.stride ||
+ from->array.c.p != to->array.c.p ||
from->array.c.buffer != to->array.c.buffer) {
+ GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.c.buffer);
+ if (idHwArrayBufferUsed != idHwArrayBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed);
+ idHwArrayBuffer = idHwArrayBufferUsed;
+ }
diff_api.ColorPointer(to->array.c.size, to->array.c.type,
to->array.c.stride, to->array.c.p);
FILLDIRTY(cb->c);
@@ -1896,7 +2033,14 @@ crStateClientSwitch(CRClientBits *cb, CRbitvalue *bitID,
if (CHECKDIRTY(cb->i, bitID)) {
if (from->array.i.type != to->array.i.type ||
from->array.i.stride != to->array.i.stride ||
+ from->array.i.p != to->array.i.p ||
from->array.i.buffer != to->array.i.buffer) {
+ GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.i.buffer);
+ if (idHwArrayBufferUsed != idHwArrayBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed);
+ idHwArrayBuffer = idHwArrayBufferUsed;
+ }
diff_api.IndexPointer(to->array.i.type,
to->array.i.stride, to->array.i.p);
FILLDIRTY(cb->i);
@@ -1911,7 +2055,14 @@ crStateClientSwitch(CRClientBits *cb, CRbitvalue *bitID,
if (from->array.t[i].size != to->array.t[i].size ||
from->array.t[i].type != to->array.t[i].type ||
from->array.t[i].stride != to->array.t[i].stride ||
+ from->array.t[i].p != to->array.t[i].p ||
from->array.t[i].buffer != to->array.t[i].buffer) {
+ GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.t[i].buffer);
+ if (idHwArrayBufferUsed != idHwArrayBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed);
+ idHwArrayBuffer = idHwArrayBufferUsed;
+ }
diff_api.ClientActiveTextureARB(GL_TEXTURE0_ARB + i);
curClientTextureUnit = i;
diff_api.TexCoordPointer(to->array.t[i].size, to->array.t[i].type,
@@ -1926,7 +2077,14 @@ crStateClientSwitch(CRClientBits *cb, CRbitvalue *bitID,
/* edge flag */
if (CHECKDIRTY(cb->e, bitID)) {
if (from->array.e.stride != to->array.e.stride ||
+ from->array.e.p != to->array.e.p ||
from->array.e.buffer != to->array.e.buffer) {
+ GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.e.buffer);
+ if (idHwArrayBufferUsed != idHwArrayBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed);
+ idHwArrayBuffer = idHwArrayBufferUsed;
+ }
diff_api.EdgeFlagPointer(to->array.e.stride, to->array.e.p);
FILLDIRTY(cb->e);
FILLDIRTY(cb->clientPointer);
@@ -1939,7 +2097,14 @@ crStateClientSwitch(CRClientBits *cb, CRbitvalue *bitID,
if (from->array.s.size != to->array.s.size ||
from->array.s.type != to->array.s.type ||
from->array.s.stride != to->array.s.stride ||
+ from->array.s.p != to->array.s.p ||
from->array.s.buffer != to->array.s.buffer) {
+ GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.s.buffer);
+ if (idHwArrayBufferUsed != idHwArrayBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed);
+ idHwArrayBuffer = idHwArrayBufferUsed;
+ }
diff_api.SecondaryColorPointerEXT(to->array.s.size, to->array.s.type,
to->array.s.stride, to->array.s.p);
FILLDIRTY(cb->s);
@@ -1952,7 +2117,14 @@ crStateClientSwitch(CRClientBits *cb, CRbitvalue *bitID,
if (CHECKDIRTY(cb->f, bitID)) {
if (from->array.f.type != to->array.f.type ||
from->array.f.stride != to->array.f.stride ||
+ from->array.f.p != to->array.f.p ||
from->array.f.buffer != to->array.f.buffer) {
+ GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.f.buffer);
+ if (idHwArrayBufferUsed != idHwArrayBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed);
+ idHwArrayBuffer = idHwArrayBufferUsed;
+ }
diff_api.FogCoordPointerEXT(to->array.f.type,
to->array.f.stride, to->array.f.p);
FILLDIRTY(cb->f);
@@ -1969,7 +2141,14 @@ crStateClientSwitch(CRClientBits *cb, CRbitvalue *bitID,
from->array.a[i].type != to->array.a[i].type ||
from->array.a[i].stride != to->array.a[i].stride ||
from->array.a[i].normalized != to->array.a[i].normalized ||
+ from->array.a[i].p != to->array.a[i].p ||
from->array.a[i].buffer != to->array.a[i].buffer) {
+ GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.a[i].buffer);
+ if (idHwArrayBufferUsed != idHwArrayBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed);
+ idHwArrayBuffer = idHwArrayBufferUsed;
+ }
diff_api.VertexAttribPointerARB(i, to->array.a[i].size,
to->array.a[i].type,
to->array.a[i].normalized,
@@ -1985,11 +2164,16 @@ crStateClientSwitch(CRClientBits *cb, CRbitvalue *bitID,
#endif
}
+ if (idHwArrayBuffer != idHwInitialBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwInitialBuffer);
+ }
+
if (CHECKDIRTY(cb->enableClientState, bitID)) {
/* update vertex array enable/disable flags */
glAble able[2];
- able[0] = diff_api.Disable;
- able[1] = diff_api.Enable;
+ able[0] = diff_api.DisableClientState;
+ able[1] = diff_api.EnableClientState;
if (from->array.v.enabled != to->array.v.enabled) {
able[to->array.v.enabled](GL_VERTEX_ARRAY);
FILLDIRTY(cb->enableClientState);
@@ -2038,7 +2222,7 @@ crStateClientSwitch(CRClientBits *cb, CRbitvalue *bitID,
if (from->array.a[i].enabled != to->array.a[i].enabled) {
if (to->array.a[i].enabled)
diff_api.EnableVertexAttribArrayARB(i);
- else
+ else
diff_api.DisableVertexAttribArrayARB(i);
FILLDIRTY(cb->enableClientState);
FILLDIRTY(cb->dirty);
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_diff.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_diff.c
index d46a9561..c8e616d2 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_diff.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_diff.c
@@ -8,6 +8,8 @@
#include "cr_error.h"
#include "cr_mem.h"
#include "cr_pixeldata.h"
+#include <iprt/err.h>
+#include <stdio.h>
void crStateDiffContext( CRContext *from, CRContext *to )
{
@@ -121,12 +123,165 @@ void crStateDiffContext( CRContext *from, CRContext *to )
}
}
-void crStateApplyFBImage(CRContext *to)
+void crStateFreeFBImageLegacy(CRContext *to)
+{
+ if (to->buffer.pFrontImg)
+ {
+ crFree(to->buffer.pFrontImg);
+ to->buffer.pFrontImg = NULL;
+ }
+ if (to->buffer.pBackImg)
+ {
+ crFree(to->buffer.pBackImg);
+ to->buffer.pBackImg = NULL;
+ }
+
+ to->buffer.storedWidth = 0;
+ to->buffer.storedHeight = 0;
+}
+
+int crStateAcquireFBImage(CRContext *to, CRFBData *data)
+{
+ CRBufferState *pBuf = &to->buffer;
+ CRPixelPackState packing = to->client.pack;
+ uint32_t i;
+
+ diff_api.PixelStorei(GL_PACK_SKIP_ROWS, 0);
+ diff_api.PixelStorei(GL_PACK_SKIP_PIXELS, 0);
+ diff_api.PixelStorei(GL_PACK_ALIGNMENT, 1);
+ diff_api.PixelStorei(GL_PACK_ROW_LENGTH, 0);
+ diff_api.PixelStorei(GL_PACK_IMAGE_HEIGHT, 0);
+ diff_api.PixelStorei(GL_PACK_SKIP_IMAGES, 0);
+ diff_api.PixelStorei(GL_PACK_SWAP_BYTES, 0);
+ diff_api.PixelStorei(GL_PACK_LSB_FIRST, 0);
+
+ if (to->bufferobject.packBuffer->hwid>0)
+ {
+ diff_api.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
+ }
+
+ for (i = 0; i < data->cElements; ++i)
+ {
+ CRFBDataElement *el = &data->aElements[i];
+
+ if (el->enmFormat == GL_DEPTH_COMPONENT || el->enmFormat == GL_DEPTH_STENCIL)
+ {
+ if (!to->buffer.depthTest)
+ {
+ diff_api.Enable(GL_DEPTH_TEST);
+ }
+ if (to->pixel.depthScale != 1.0f)
+ {
+ diff_api.PixelTransferf (GL_DEPTH_SCALE, 1.0f);
+ }
+ if (to->pixel.depthBias != 0.0f)
+ {
+ diff_api.PixelTransferf (GL_DEPTH_BIAS, 0.0f);
+ }
+ }
+ if (el->enmFormat == GL_STENCIL_INDEX || el->enmFormat == GL_DEPTH_STENCIL)
+ {
+ if (!to->stencil.stencilTest)
+ {
+ diff_api.Enable(GL_STENCIL_TEST);
+ }
+ if (to->pixel.mapStencil)
+ {
+ diff_api.PixelTransferi (GL_MAP_STENCIL, GL_FALSE);
+ }
+ if (to->pixel.indexOffset)
+ {
+ diff_api.PixelTransferi (GL_INDEX_OFFSET, 0);
+ }
+ if (to->pixel.indexShift)
+ {
+ diff_api.PixelTransferi (GL_INDEX_SHIFT, 0);
+ }
+ }
+
+ diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, el->idFBO);
+
+ if (el->enmBuffer)
+ diff_api.ReadBuffer(el->enmBuffer);
+
+ diff_api.ReadPixels(el->posX, el->posY, el->width, el->height, el->enmFormat, el->enmType, el->pvData);
+ crDebug("Acquired %d;%d;%d;%d;%d;0x%p fb image", el->enmBuffer, el->width, el->height, el->enmFormat, el->enmType, el->pvData);
+
+ if (el->enmFormat == GL_DEPTH_COMPONENT || el->enmFormat == GL_DEPTH_STENCIL)
+ {
+ if (to->pixel.depthScale != 1.0f)
+ {
+ diff_api.PixelTransferf (GL_DEPTH_SCALE, to->pixel.depthScale);
+ }
+ if (to->pixel.depthBias != 0.0f)
+ {
+ diff_api.PixelTransferf (GL_DEPTH_BIAS, to->pixel.depthBias);
+ }
+ if (!to->buffer.depthTest)
+ {
+ diff_api.Disable(GL_DEPTH_TEST);
+ }
+ }
+ if (el->enmFormat == GL_STENCIL_INDEX || el->enmFormat == GL_DEPTH_STENCIL)
+ {
+ if (to->pixel.indexOffset)
+ {
+ diff_api.PixelTransferi (GL_INDEX_OFFSET, to->pixel.indexOffset);
+ }
+ if (to->pixel.indexShift)
+ {
+ diff_api.PixelTransferi (GL_INDEX_SHIFT, to->pixel.indexShift);
+ }
+ if (to->pixel.mapStencil)
+ {
+ diff_api.PixelTransferi (GL_MAP_STENCIL, GL_TRUE);
+ }
+ if (!to->stencil.stencilTest)
+ {
+ diff_api.Disable(GL_STENCIL_TEST);
+ }
+ }
+ }
+
+ if (to->bufferobject.packBuffer->hwid>0)
+ {
+ diff_api.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, to->bufferobject.packBuffer->hwid);
+ }
+ if (to->framebufferobject.readFB)
+ {
+ CRASSERT(to->framebufferobject.readFB->hwid);
+ diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, to->framebufferobject.readFB->hwid);
+ diff_api.ReadBuffer(to->framebufferobject.readFB->readbuffer);
+
+ }
+ else if (data->idOverrrideFBO)
+ {
+ diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, data->idOverrrideFBO);
+ diff_api.ReadBuffer(GL_COLOR_ATTACHMENT0);
+ }
+ else
+ {
+ diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, 0);
+ diff_api.ReadBuffer(to->buffer.readBuffer);
+ }
+
+ diff_api.PixelStorei(GL_PACK_SKIP_ROWS, packing.skipRows);
+ diff_api.PixelStorei(GL_PACK_SKIP_PIXELS, packing.skipPixels);
+ diff_api.PixelStorei(GL_PACK_ALIGNMENT, packing.alignment);
+ diff_api.PixelStorei(GL_PACK_ROW_LENGTH, packing.rowLength);
+ diff_api.PixelStorei(GL_PACK_IMAGE_HEIGHT, packing.imageHeight);
+ diff_api.PixelStorei(GL_PACK_SKIP_IMAGES, packing.skipImages);
+ diff_api.PixelStorei(GL_PACK_SWAP_BYTES, packing.swapBytes);
+ diff_api.PixelStorei(GL_PACK_LSB_FIRST, packing.psLSBFirst);
+ return VINF_SUCCESS;
+}
+
+void crStateApplyFBImage(CRContext *to, CRFBData *data)
{
- if (to->buffer.pFrontImg || to->buffer.pBackImg)
{
CRBufferState *pBuf = &to->buffer;
CRPixelPackState unpack = to->client.unpack;
+ uint32_t i;
diff_api.PixelStorei(GL_UNPACK_SKIP_ROWS, 0);
diff_api.PixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
@@ -137,11 +292,6 @@ void crStateApplyFBImage(CRContext *to)
diff_api.PixelStorei(GL_UNPACK_SWAP_BYTES, 0);
diff_api.PixelStorei(GL_UNPACK_LSB_FIRST, 0);
- if (to->framebufferobject.drawFB)
- {
- diff_api.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0);
- }
-
if (to->bufferobject.unpackBuffer->hwid>0)
{
diff_api.BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
@@ -151,25 +301,84 @@ void crStateApplyFBImage(CRContext *to)
diff_api.Disable(GL_SCISSOR_TEST);
diff_api.Disable(GL_BLEND);
diff_api.Disable(GL_COLOR_LOGIC_OP);
+ diff_api.Disable(GL_DEPTH_TEST);
+ diff_api.Disable(GL_STENCIL_TEST);
- if (pBuf->pFrontImg)
+ for (i = 0; i < data->cElements; ++i)
{
- diff_api.DrawBuffer(GL_FRONT);
- diff_api.WindowPos2iARB(0, 0);
- diff_api.DrawPixels(pBuf->storedWidth, pBuf->storedHeight, GL_RGBA, GL_UNSIGNED_BYTE, pBuf->pFrontImg);
- crDebug("Applied %ix%i fb image", pBuf->storedWidth, pBuf->storedHeight);
- crFree(pBuf->pFrontImg);
- pBuf->pFrontImg = NULL;
- }
+ CRFBDataElement *el = &data->aElements[i];
+#if 0
+ char fname[200];
+ sprintf(fname, "./img_apply_%p_%d_%d.tga", to, i, el->enmFormat);
+ crDumpNamedTGA(fname, el->width, el->height, el->pvData);
+#endif
- if (pBuf->pBackImg)
- {
- diff_api.DrawBuffer(GL_BACK);
- diff_api.WindowPos2iARB(0, 0);
- diff_api.DrawPixels(pBuf->storedWidth, pBuf->storedHeight, GL_RGBA, GL_UNSIGNED_BYTE, pBuf->pBackImg);
- crDebug("Applied %ix%i bb image", pBuf->storedWidth, pBuf->storedHeight);
- crFree(pBuf->pBackImg);
- pBuf->pBackImg = NULL;
+ if (el->enmFormat == GL_DEPTH_COMPONENT || el->enmFormat == GL_DEPTH_STENCIL)
+ {
+ diff_api.Enable(GL_DEPTH_TEST);
+ if (to->pixel.depthScale != 1.0f)
+ {
+ diff_api.PixelTransferf (GL_DEPTH_SCALE, 1.0f);
+ }
+ if (to->pixel.depthBias != 0.0f)
+ {
+ diff_api.PixelTransferf (GL_DEPTH_BIAS, 0.0f);
+ }
+ }
+ if (el->enmFormat == GL_STENCIL_INDEX || el->enmFormat == GL_DEPTH_STENCIL)
+ {
+ diff_api.Enable(GL_STENCIL_TEST);
+ if (to->pixel.mapStencil)
+ {
+ diff_api.PixelTransferi (GL_MAP_STENCIL, GL_FALSE);
+ }
+ if (to->pixel.indexOffset)
+ {
+ diff_api.PixelTransferi (GL_INDEX_OFFSET, 0);
+ }
+ if (to->pixel.indexShift)
+ {
+ diff_api.PixelTransferi (GL_INDEX_SHIFT, 0);
+ }
+ }
+
+ diff_api.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, el->idFBO);
+
+ if (el->enmBuffer)
+ diff_api.DrawBuffer(el->enmBuffer);
+
+ diff_api.WindowPos2iARB(el->posX, el->posY);
+ diff_api.DrawPixels(el->width, el->height, el->enmFormat, el->enmType, el->pvData);
+ crDebug("Applied %d;%d;%d;%d;%d;0x%p fb image", el->enmBuffer, el->width, el->height, el->enmFormat, el->enmType, el->pvData);
+
+ if (el->enmFormat == GL_DEPTH_COMPONENT || el->enmFormat == GL_DEPTH_STENCIL)
+ {
+ if (to->pixel.depthScale != 1.0f)
+ {
+ diff_api.PixelTransferf (GL_DEPTH_SCALE, to->pixel.depthScale);
+ }
+ if (to->pixel.depthBias != 0.0f)
+ {
+ diff_api.PixelTransferf (GL_DEPTH_BIAS, to->pixel.depthBias);
+ }
+ diff_api.Disable(GL_DEPTH_TEST);
+ }
+ if (el->enmFormat == GL_STENCIL_INDEX || el->enmFormat == GL_DEPTH_STENCIL)
+ {
+ if (to->pixel.indexOffset)
+ {
+ diff_api.PixelTransferi (GL_INDEX_OFFSET, to->pixel.indexOffset);
+ }
+ if (to->pixel.indexShift)
+ {
+ diff_api.PixelTransferi (GL_INDEX_SHIFT, to->pixel.indexShift);
+ }
+ if (to->pixel.mapStencil)
+ {
+ diff_api.PixelTransferi (GL_MAP_STENCIL, GL_TRUE);
+ }
+ diff_api.Disable(GL_STENCIL_TEST);
+ }
}
diff_api.WindowPos3fvARB(to->current.rasterAttrib[VERT_ATTRIB_POS]);
@@ -179,10 +388,20 @@ void crStateApplyFBImage(CRContext *to)
}
if (to->framebufferobject.drawFB)
{
+ CRASSERT(to->framebufferobject.drawFB->hwid);
diff_api.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, to->framebufferobject.drawFB->hwid);
+ diff_api.DrawBuffer(to->framebufferobject.drawFB->drawbuffer[0]);
+ }
+ else if (data->idOverrrideFBO)
+ {
+ diff_api.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, data->idOverrrideFBO);
+ diff_api.DrawBuffer(GL_COLOR_ATTACHMENT0);
+ }
+ else
+ {
+ diff_api.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0);
+ diff_api.DrawBuffer(to->buffer.drawBuffer);
}
- diff_api.DrawBuffer(to->framebufferobject.drawFB ?
- to->framebufferobject.drawFB->drawbuffer[0] : to->buffer.drawBuffer);
if (to->buffer.alphaTest)
{
diff_api.Enable(GL_ALPHA_TEST);
@@ -199,6 +418,14 @@ void crStateApplyFBImage(CRContext *to)
{
diff_api.Enable(GL_COLOR_LOGIC_OP);
}
+ if (to->buffer.depthTest)
+ {
+ diff_api.Enable(GL_DEPTH_TEST);
+ }
+ if (to->stencil.stencilTest)
+ {
+ diff_api.Enable(GL_STENCIL_TEST);
+ }
diff_api.PixelStorei(GL_UNPACK_SKIP_ROWS, unpack.skipRows);
diff_api.PixelStorei(GL_UNPACK_SKIP_PIXELS, unpack.skipPixels);
@@ -341,34 +568,59 @@ void crStateSwitchContext( CRContext *from, CRContext *to )
}
#ifdef WINDOWS
- crStateApplyFBImage(to);
+ if (to->buffer.pFrontImg)
+ {
+ CRFBData *pLazyData = (CRFBData *)to->buffer.pFrontImg;
+ crStateApplyFBImage(to, pLazyData);
+ crStateFreeFBImageLegacy(to);
+ }
#endif
}
-CRContext * crStateSwichPrepare(CRContext *toCtx, GLboolean fMultipleContexts, GLuint idFBO)
+void crStateSyncHWErrorState(CRContext *ctx)
{
- CRContext *fromCtx = GetCurrentContext();
-
- if (!fMultipleContexts)
+ GLenum err;
+ while ((err = diff_api.GetError()) != GL_NO_ERROR)
{
+ if (ctx->error != GL_NO_ERROR)
+ ctx->error = err;
+ }
+}
+
+void crStateSwitchPrepare(CRContext *toCtx, CRContext *fromCtx, GLuint idDrawFBO, GLuint idReadFBO)
+{
+ if (!fromCtx)
+ return;
+
+ if (g_bVBoxEnableDiffOnMakeCurrent && toCtx && toCtx != fromCtx)
+ crStateSyncHWErrorState(fromCtx);
+
#ifdef CR_EXT_framebuffer_object
- if (fromCtx)
- crStateFramebufferObjectDisableHW(fromCtx, idFBO);
+ crStateFramebufferObjectDisableHW(fromCtx, idDrawFBO, idReadFBO);
#endif
- }
- return fromCtx;
}
-void crStateSwichPostprocess(CRContext *fromCtx, GLboolean fMultipleContexts, GLuint idFBO)
+void crStateSwitchPostprocess(CRContext *toCtx, CRContext *fromCtx, GLuint idDrawFBO, GLuint idReadFBO)
{
- CRContext *toCtx = GetCurrentContext();;
- if (!fromCtx || !toCtx)
+ if (!toCtx)
return;
- if (!fMultipleContexts)
+ if (g_bVBoxEnableDiffOnMakeCurrent && fromCtx && toCtx != fromCtx)
{
-#ifdef CR_EXT_framebuffer_object
- crStateFramebufferObjectReenableHW(fromCtx, toCtx, idFBO);
+ GLenum err;
+ while ((err = diff_api.GetError()) != GL_NO_ERROR)
+ {
+ static int cErrPrints = 0;
+#ifndef DEBUG_misha
+ if (cErrPrints < 5)
#endif
+ {
+ ++cErrPrints;
+ crWarning("gl error (0x%x) after context switch, ignoring.. (%d out of 5) ..", err, cErrPrints);
+ }
+ }
}
+#ifdef CR_EXT_framebuffer_object
+ crStateFramebufferObjectReenableHW(fromCtx, toCtx, idDrawFBO, idReadFBO);
+#endif
}
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_enable.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_enable.c
index 75a1534d..185de9eb 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_enable.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_enable.c
@@ -496,6 +496,13 @@ static void __enableSet (CRContext *g, CRStateBits *sb, CRbitvalue *neg_bitid,
else
crStateDisableClientState(cap);
break;
+#ifdef CR_EXT_stencil_two_side
+ case GL_STENCIL_TEST_TWO_SIDE_EXT:
+ g->stencil.stencilTwoSideEXT= val;
+ DIRTY(sb->stencil.enableTwoSideEXT, neg_bitid);
+ DIRTY(sb->stencil.dirty, neg_bitid);
+ break;
+#endif
default:
crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glEnable/glDisable called with bogus cap: 0x%x", cap);
return;
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_error.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_error.c
index 60eaa457..07a7b494 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_error.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_error.c
@@ -18,9 +18,14 @@ void crStateError( int line, const char *file, GLenum error, const char *format,
char errstr[8096];
va_list args;
- g->error = error;
+ CRASSERT(error != GL_NO_ERROR);
+ if (g->error == GL_NO_ERROR)
+ g->error = error;
+
+#ifndef DEBUG_misha
if (crGetenv("CR_DEBUG"))
+#endif
{
char *glerr;
va_start( args, format );
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_framebuffer.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_framebuffer.c
index cdd3cecd..2f150361 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_framebuffer.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_framebuffer.c
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2009 Oracle Corporation
+ * Copyright (C) 2009-2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -22,12 +22,6 @@
#include "state_internals.h"
#include "cr_mem.h"
-#define CRSTATE_FBO_CHECKERR(expr, result, message) \
- if (expr) { \
- crStateError(__LINE__, __FILE__, result, message); \
- return; \
- }
-
DECLEXPORT(void) STATE_APIENTRY
crStateFramebufferObjectInit(CRContext *ctx)
{
@@ -39,6 +33,82 @@ crStateFramebufferObjectInit(CRContext *ctx)
ctx->shared->bFBOResyncNeeded = GL_FALSE;
}
+void STATE_APIENTRY crStateGenFramebuffersEXT(GLsizei n, GLuint *buffers)
+{
+ CRContext *g = GetCurrentContext();
+ crStateGenNames(g, g->shared->fbTable, n, buffers);
+}
+
+void STATE_APIENTRY crStateGenRenderbuffersEXT(GLsizei n, GLuint *buffers)
+{
+ CRContext *g = GetCurrentContext();
+ crStateGenNames(g, g->shared->rbTable, n, buffers);
+}
+
+void crStateRegFramebuffers(GLsizei n, GLuint *buffers)
+{
+ CRContext *g = GetCurrentContext();
+ crStateRegNames(g, g->shared->fbTable, n, buffers);
+}
+
+void crStateRegRenderbuffers(GLsizei n, GLuint *buffers)
+{
+ CRContext *g = GetCurrentContext();
+ crStateRegNames(g, g->shared->rbTable, n, buffers);
+}
+
+static void crStateInitFrameBuffer(CRFramebufferObject *fbo);
+
+static CRFramebufferObject *
+crStateFramebufferAllocate(CRContext *ctx, GLuint name)
+{
+ CRFramebufferObject *buffer = (CRFramebufferObject*) crCalloc(sizeof(CRFramebufferObject));
+ CRSTATE_CHECKERR_RET(!buffer, GL_OUT_OF_MEMORY, "crStateFramebufferAllocate", NULL);
+ buffer->id = name;
+#ifndef IN_GUEST
+ diff_api.GenFramebuffersEXT(1, &buffer->hwid);
+ if (!buffer->hwid)
+ {
+ crWarning("GenFramebuffersEXT failed!");
+ crFree(buffer);
+ return NULL;
+ }
+#else
+ buffer->hwid = name;
+#endif
+
+ crStateInitFrameBuffer(buffer);
+ crHashtableAdd(ctx->shared->fbTable, name, buffer);
+ CR_STATE_SHAREDOBJ_USAGE_INIT(buffer);
+
+ return buffer;
+}
+
+static CRRenderbufferObject *
+crStateRenderbufferAllocate(CRContext *ctx, GLuint name)
+{
+ CRRenderbufferObject *buffer = (CRRenderbufferObject*) crCalloc(sizeof(CRRenderbufferObject));
+ CRSTATE_CHECKERR_RET(!buffer, GL_OUT_OF_MEMORY, "crStateRenderbufferAllocate", NULL);
+ buffer->id = name;
+#ifndef IN_GUEST
+ diff_api.GenRenderbuffersEXT(1, &buffer->hwid);
+ if (!buffer->hwid)
+ {
+ crWarning("GenRenderbuffersEXT failed!");
+ crFree(buffer);
+ return NULL;
+ }
+#else
+ buffer->hwid = name;
+#endif
+
+ buffer->internalformat = GL_RGBA;
+ crHashtableAdd(ctx->shared->rbTable, name, buffer);
+ CR_STATE_SHAREDOBJ_USAGE_INIT(buffer);
+
+ return buffer;
+}
+
void crStateFreeFBO(void *data)
{
CRFramebufferObject *pObj = (CRFramebufferObject *)data;
@@ -83,28 +153,18 @@ crStateBindRenderbufferEXT(GLenum target, GLuint renderbuffer)
CRContext *g = GetCurrentContext();
CRFramebufferObjectState *fbo = &g->framebufferobject;
- CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
- CRSTATE_FBO_CHECKERR(target!=GL_RENDERBUFFER_EXT, GL_INVALID_ENUM, "invalid target");
+ CRSTATE_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
+ CRSTATE_CHECKERR(target!=GL_RENDERBUFFER_EXT, GL_INVALID_ENUM, "invalid target");
if (renderbuffer)
{
fbo->renderbuffer = (CRRenderbufferObject*) crHashtableSearch(g->shared->rbTable, renderbuffer);
if (!fbo->renderbuffer)
{
- fbo->renderbuffer = (CRRenderbufferObject*) crCalloc(sizeof(CRRenderbufferObject));
- CRSTATE_FBO_CHECKERR(!fbo->renderbuffer, GL_OUT_OF_MEMORY, "glBindRenderbufferEXT");
- fbo->renderbuffer->id = renderbuffer;
- fbo->renderbuffer->hwid = renderbuffer;
- fbo->renderbuffer->internalformat = GL_RGBA;
- crHashtableAdd(g->shared->rbTable, renderbuffer, fbo->renderbuffer);
-#ifndef IN_GUEST
- CR_STATE_SHAREDOBJ_USAGE_INIT(fbo->renderbuffer);
-#endif
+ CRSTATE_CHECKERR(!crHashtableIsKeyUsed(g->shared->rbTable, renderbuffer), GL_INVALID_OPERATION, "name is not a renderbuffer");
+ fbo->renderbuffer = crStateRenderbufferAllocate(g, renderbuffer);
}
-#ifndef IN_GUEST
CR_STATE_SHAREDOBJ_USAGE_SET(fbo->renderbuffer, g);
-#endif
-
}
else fbo->renderbuffer = NULL;
}
@@ -147,6 +207,22 @@ static void crStateCheckFBOAttachments(CRFramebufferObject *pFBO, GLuint rbo, GL
}
}
+static void ctStateRenderbufferRefsCleanup(CRContext *g, GLuint fboId, CRRenderbufferObject *rbo)
+{
+ CRFramebufferObjectState *fbo = &g->framebufferobject;
+
+ if (fbo->renderbuffer==rbo)
+ {
+ fbo->renderbuffer = NULL;
+ }
+
+ /* check the attachments of current framebuffers */
+ crStateCheckFBOAttachments(fbo->readFB, fboId, GL_READ_FRAMEBUFFER);
+ crStateCheckFBOAttachments(fbo->drawFB, fboId, GL_DRAW_FRAMEBUFFER);
+
+ CR_STATE_SHAREDOBJ_USAGE_CLEAR(rbo, g);
+}
+
DECLEXPORT(void) STATE_APIENTRY
crStateDeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers)
{
@@ -154,8 +230,8 @@ crStateDeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers)
CRFramebufferObjectState *fbo = &g->framebufferobject;
int i;
- CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
- CRSTATE_FBO_CHECKERR(n<0, GL_INVALID_OPERATION, "n<0");
+ CRSTATE_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
+ CRSTATE_CHECKERR(n<0, GL_INVALID_OPERATION, "n<0");
for (i = 0; i < n; i++)
{
@@ -165,15 +241,29 @@ crStateDeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers)
rbo = (CRRenderbufferObject*) crHashtableSearch(g->shared->rbTable, renderbuffers[i]);
if (rbo)
{
- if (fbo->renderbuffer==rbo)
+ int j;
+
+ ctStateRenderbufferRefsCleanup(g, renderbuffers[i], rbo);
+ CR_STATE_SHAREDOBJ_USAGE_FOREACH_USED_IDX(rbo, j)
{
- fbo->renderbuffer = NULL;
+ /* saved state version <= SHCROGL_SSM_VERSION_BEFORE_CTXUSAGE_BITS does not have usage bits info,
+ * so on restore, we set mark bits as used.
+ * This is why g_pAvailableContexts[j] could be NULL
+ * also g_pAvailableContexts[0] will hold default context, which we should discard */
+ CRContext *ctx = g_pAvailableContexts[j];
+ if (j && ctx)
+ {
+ CRFramebufferObjectState *ctxFbo;
+ CRASSERT(ctx);
+ ctxFbo = &ctx->framebufferobject;
+ if (ctxFbo->renderbuffer==rbo)
+ crWarning("deleting RBO being used by another context %d", ctx->id);
+
+ ctStateRenderbufferRefsCleanup(ctx, renderbuffers[i], rbo);
+ }
+ else
+ CR_STATE_SHAREDOBJ_USAGE_CLEAR_IDX(rbo, j);
}
-
- /* check the attachments of current framebuffers */
- crStateCheckFBOAttachments(fbo->readFB, renderbuffers[i], GL_READ_FRAMEBUFFER);
- crStateCheckFBOAttachments(fbo->drawFB, renderbuffers[i], GL_DRAW_FRAMEBUFFER);
-
crHashtableDelete(g->shared->rbTable, renderbuffers[i], crStateFreeRBO);
}
}
@@ -187,9 +277,9 @@ crStateRenderbufferStorageEXT(GLenum target, GLenum internalformat, GLsizei widt
CRFramebufferObjectState *fbo = &g->framebufferobject;
CRRenderbufferObject *rb = fbo->renderbuffer;
- CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
- CRSTATE_FBO_CHECKERR(target!=GL_RENDERBUFFER_EXT, GL_INVALID_ENUM, "invalid target");
- CRSTATE_FBO_CHECKERR(!rb, GL_INVALID_OPERATION, "no bound renderbuffer");
+ CRSTATE_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
+ CRSTATE_CHECKERR(target!=GL_RENDERBUFFER_EXT, GL_INVALID_ENUM, "invalid target");
+ CRSTATE_CHECKERR(!rb, GL_INVALID_OPERATION, "no bound renderbuffer");
rb->width = width;
rb->height = height;
@@ -203,9 +293,9 @@ crStateGetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint *params)
CRFramebufferObjectState *fbo = &g->framebufferobject;
CRRenderbufferObject *rb = fbo->renderbuffer;
- CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
- CRSTATE_FBO_CHECKERR(target!=GL_RENDERBUFFER_EXT, GL_INVALID_ENUM, "invalid target");
- CRSTATE_FBO_CHECKERR(!rb, GL_INVALID_OPERATION, "no bound renderbuffer");
+ CRSTATE_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
+ CRSTATE_CHECKERR(target!=GL_RENDERBUFFER_EXT, GL_INVALID_ENUM, "invalid target");
+ CRSTATE_CHECKERR(!rb, GL_INVALID_OPERATION, "no bound renderbuffer");
switch (pname)
{
@@ -224,10 +314,10 @@ crStateGetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint *params)
case GL_RENDERBUFFER_ALPHA_SIZE_EXT:
case GL_RENDERBUFFER_DEPTH_SIZE_EXT:
case GL_RENDERBUFFER_STENCIL_SIZE_EXT:
- CRSTATE_FBO_CHECKERR(GL_TRUE, GL_INVALID_OPERATION, "unimplemented");
+ CRSTATE_CHECKERR(GL_TRUE, GL_INVALID_OPERATION, "unimplemented");
break;
default:
- CRSTATE_FBO_CHECKERR(GL_TRUE, GL_INVALID_ENUM, "invalid pname");
+ CRSTATE_CHECKERR(GL_TRUE, GL_INVALID_ENUM, "invalid pname");
}
}
@@ -286,8 +376,8 @@ crStateBindFramebufferEXT(GLenum target, GLuint framebuffer)
CRFramebufferObjectState *fbo = &g->framebufferobject;
CRFramebufferObject *pFBO=NULL;
- CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
- CRSTATE_FBO_CHECKERR(((target!=GL_FRAMEBUFFER_EXT) && (target!=GL_READ_FRAMEBUFFER) && (target!=GL_DRAW_FRAMEBUFFER)),
+ CRSTATE_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
+ CRSTATE_CHECKERR(((target!=GL_FRAMEBUFFER_EXT) && (target!=GL_READ_FRAMEBUFFER) && (target!=GL_DRAW_FRAMEBUFFER)),
GL_INVALID_ENUM, "invalid target");
if (framebuffer)
@@ -295,20 +385,12 @@ crStateBindFramebufferEXT(GLenum target, GLuint framebuffer)
pFBO = (CRFramebufferObject*) crHashtableSearch(g->shared->fbTable, framebuffer);
if (!pFBO)
{
- pFBO = (CRFramebufferObject*) crCalloc(sizeof(CRFramebufferObject));
- CRSTATE_FBO_CHECKERR(!pFBO, GL_OUT_OF_MEMORY, "glBindFramebufferEXT");
- pFBO->id = framebuffer;
- pFBO->hwid = framebuffer;
- crStateInitFrameBuffer(pFBO);
- crHashtableAdd(g->shared->fbTable, framebuffer, pFBO);
-#ifndef IN_GUEST
- CR_STATE_SHAREDOBJ_USAGE_INIT(pFBO);
-#endif
+ CRSTATE_CHECKERR(!crHashtableIsKeyUsed(g->shared->fbTable, framebuffer), GL_INVALID_OPERATION, "name is not a framebuffer");
+ pFBO = crStateFramebufferAllocate(g, framebuffer);
}
-#ifndef IN_GUEST
+
CR_STATE_SHAREDOBJ_USAGE_SET(pFBO, g);
-#endif
}
/* @todo: http://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
@@ -331,15 +413,29 @@ crStateBindFramebufferEXT(GLenum target, GLuint framebuffer)
}
}
+static void ctStateFramebufferRefsCleanup(CRContext *g, CRFramebufferObject *fb)
+{
+ CRFramebufferObjectState *fbo = &g->framebufferobject;
+ if (fbo->readFB==fb)
+ {
+ fbo->readFB = NULL;
+ }
+ if (fbo->drawFB==fb)
+ {
+ fbo->drawFB = NULL;
+ }
+
+ CR_STATE_SHAREDOBJ_USAGE_CLEAR(fb, g);
+}
+
DECLEXPORT(void) STATE_APIENTRY
crStateDeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers)
{
CRContext *g = GetCurrentContext();
- CRFramebufferObjectState *fbo = &g->framebufferobject;
int i;
- CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
- CRSTATE_FBO_CHECKERR(n<0, GL_INVALID_OPERATION, "n<0");
+ CRSTATE_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
+ CRSTATE_CHECKERR(n<0, GL_INVALID_OPERATION, "n<0");
for (i = 0; i < n; i++)
{
@@ -349,13 +445,32 @@ crStateDeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers)
fb = (CRFramebufferObject*) crHashtableSearch(g->shared->fbTable, framebuffers[i]);
if (fb)
{
- if (fbo->readFB==fb)
- {
- fbo->readFB = NULL;
- }
- if (fbo->drawFB==fb)
+ int j;
+
+ ctStateFramebufferRefsCleanup(g, fb);
+
+ CR_STATE_SHAREDOBJ_USAGE_FOREACH_USED_IDX(fb, j)
{
- fbo->drawFB = NULL;
+ /* saved state version <= SHCROGL_SSM_VERSION_BEFORE_CTXUSAGE_BITS does not have usage bits info,
+ * so on restore, we set mark bits as used.
+ * This is why g_pAvailableContexts[j] could be NULL
+ * also g_pAvailableContexts[0] will hold default context, which we should discard */
+ CRContext *ctx = g_pAvailableContexts[j];
+ if (j && ctx)
+ {
+ CRFramebufferObjectState *ctxFbo;
+ CRASSERT(ctx);
+ ctxFbo = &ctx->framebufferobject;
+ if (ctxFbo->readFB==fb)
+ crWarning("deleting FBO being used as read buffer by another context %d", ctx->id);
+
+ if (ctxFbo->drawFB==fb)
+ crWarning("deleting FBO being used as draw buffer by another context %d", ctx->id);
+
+ ctStateFramebufferRefsCleanup(ctx, fb);
+ }
+ else
+ CR_STATE_SHAREDOBJ_USAGE_CLEAR_IDX(fb, j);
}
crHashtableDelete(g->shared->fbTable, framebuffers[i], crStateFreeFBO);
}
@@ -380,27 +495,72 @@ unsigned int crLog2Floor(unsigned int x)
return (x & 0x0000003f) - 1;
}
-static void crStateFramebufferTextureCheck(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level,
- GLboolean *failed, CRFBOAttachmentPoint **ap, CRTextureObj **tobj)
+static GLuint crStateFramebufferGet(CRFramebufferObjectState *fbo, GLenum target, CRFramebufferObject **apFBOs)
+{
+ GLuint cPBOs = 0;
+ switch (target)
+ {
+ case GL_READ_FRAMEBUFFER:
+ cPBOs = 1;
+ apFBOs[0] = fbo->readFB;
+ break;
+ case GL_DRAW_FRAMEBUFFER:
+ cPBOs = 1;
+ apFBOs[0] = fbo->drawFB;
+ break;
+ case GL_FRAMEBUFFER:
+ if (fbo->readFB == fbo->drawFB)
+ {
+ cPBOs = 1;
+ apFBOs[0] = fbo->readFB;
+ }
+ else
+ {
+ cPBOs = 2;
+ apFBOs[0] = fbo->readFB;
+ apFBOs[1] = fbo->drawFB;
+ }
+ break;
+ default:
+ crWarning("unexpected target value: 0x%x", target);
+ cPBOs = 0;
+ break;
+ }
+
+ return cPBOs;
+}
+
+static GLuint crStateFramebufferTextureCheck(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level,
+ CRFBOAttachmentPoint **aap, CRTextureObj **tobj)
{
CRContext *g = GetCurrentContext();
CRFramebufferObjectState *fbo = &g->framebufferobject;
- CRFramebufferObject *pFBO;
+ CRFramebufferObject *apFBOs[2];
+ GLuint cFBOs = 0, i;
GLuint maxtexsizelog2;
- *failed = GL_TRUE;
+ CRSTATE_CHECKERR_RET(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end", 0);
+ CRSTATE_CHECKERR_RET(((target!=GL_FRAMEBUFFER_EXT) && (target!=GL_READ_FRAMEBUFFER) && (target!=GL_DRAW_FRAMEBUFFER)),
+ GL_INVALID_ENUM, "invalid target", 0);
- CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
- CRSTATE_FBO_CHECKERR(((target!=GL_FRAMEBUFFER_EXT) && (target!=GL_READ_FRAMEBUFFER) && (target!=GL_DRAW_FRAMEBUFFER)),
- GL_INVALID_ENUM, "invalid target");
- pFBO = GL_READ_FRAMEBUFFER==target ? fbo->readFB : fbo->drawFB;
- CRSTATE_FBO_CHECKERR(!pFBO, GL_INVALID_OPERATION, "no fbo bound");
- CRSTATE_FBO_CHECKERR(!crStateGetFBOAttachmentPoint(pFBO, attachment, ap), GL_INVALID_ENUM, "invalid attachment");
+ cFBOs = crStateFramebufferGet(fbo, target, apFBOs);
+ CRSTATE_CHECKERR_RET(!cFBOs, GL_INVALID_ENUM, "unexpected target", 0);
+ for (i = 0; i < cFBOs; ++i)
+ {
+ CRSTATE_CHECKERR_RET(!apFBOs[i], GL_INVALID_OPERATION, "zero fbo bound", 0);
+ }
+
+ Assert(cFBOs);
+ Assert(cFBOs <= 2);
+
+ for (i = 0; i < cFBOs; ++i)
+ {
+ CRSTATE_CHECKERR_RET(!crStateGetFBOAttachmentPoint(apFBOs[i], attachment, &aap[i]), GL_INVALID_ENUM, "invalid attachment", 0);
+ }
if (!texture)
{
- *failed = GL_FALSE;
- return;
+ return cFBOs;
}
switch (textarget)
@@ -428,27 +588,33 @@ static void crStateFramebufferTextureCheck(GLenum target, GLenum attachment, GLe
*tobj = crStateTextureGet(textarget, texture);
break;
default:
- CRSTATE_FBO_CHECKERR(GL_TRUE, GL_INVALID_OPERATION, "invalid textarget");
+ CRSTATE_CHECKERR_RET(GL_TRUE, GL_INVALID_OPERATION, "invalid textarget", 0);
}
- CRSTATE_FBO_CHECKERR(!*tobj, GL_INVALID_OPERATION, "invalid textarget/texture combo");
+ CRSTATE_CHECKERR_RET(!*tobj, GL_INVALID_OPERATION, "invalid textarget/texture combo", 0);
if (GL_TEXTURE_RECTANGLE_ARB==textarget)
{
- CRSTATE_FBO_CHECKERR(level!=0, GL_INVALID_VALUE, "non zero mipmap level");
+ CRSTATE_CHECKERR_RET(level!=0, GL_INVALID_VALUE, "non zero mipmap level", 0);
}
- CRSTATE_FBO_CHECKERR(level<0, GL_INVALID_VALUE, "level<0");
- CRSTATE_FBO_CHECKERR(level>maxtexsizelog2, GL_INVALID_VALUE, "level too big");
-
- *failed = GL_FALSE;
+ CRSTATE_CHECKERR_RET(level<0, GL_INVALID_VALUE, "level<0", 0);
+ CRSTATE_CHECKERR_RET(level>maxtexsizelog2, GL_INVALID_VALUE, "level too big", 0);
#ifdef IN_GUEST
- if ((*ap)->type!=GL_TEXTURE || (*ap)->name!=texture || (*ap)->level!=level)
+ for (i = 0; i < cFBOs; ++i)
{
- pFBO->status = GL_FRAMEBUFFER_UNDEFINED;
+ if ((aap[i])->type!=GL_TEXTURE || (aap[i])->name!=texture || (aap[i])->level!=level)
+ {
+ apFBOs[i]->status = GL_FRAMEBUFFER_UNDEFINED;
+ }
}
#endif
+
+ Assert(cFBOs);
+ Assert(cFBOs <= 2);
+
+ return cFBOs;
}
DECLEXPORT(void) STATE_APIENTRY
@@ -456,29 +622,33 @@ crStateFramebufferTexture1DEXT(GLenum target, GLenum attachment, GLenum textarge
{
CRContext *g = GetCurrentContext();
CRFramebufferObjectState *fbo = &g->framebufferobject;
- CRFBOAttachmentPoint *ap;
+ CRFBOAttachmentPoint *aap[2];
+ GLuint cap, i;
CRTextureObj *tobj;
- GLboolean failed;
- crStateFramebufferTextureCheck(target, attachment, textarget, texture, level, &failed, &ap, &tobj);
- if (failed) return;
+ cap = crStateFramebufferTextureCheck(target, attachment, textarget, texture, level, aap, &tobj);
+ if (!cap) return;
if (!texture)
{
- crStateInitFBOAttachmentPoint(ap);
+ for (i = 0; i < cap; ++i)
+ {
+ crStateInitFBOAttachmentPoint(aap[i]);
+ }
return;
}
- CRSTATE_FBO_CHECKERR(textarget!=GL_TEXTURE_1D, GL_INVALID_OPERATION, "textarget");
+ CRSTATE_CHECKERR(textarget!=GL_TEXTURE_1D, GL_INVALID_OPERATION, "textarget");
-#ifndef IN_GUEST
CR_STATE_SHAREDOBJ_USAGE_SET(tobj, g);
-#endif
- crStateInitFBOAttachmentPoint(ap);
- ap->type = GL_TEXTURE;
- ap->name = texture;
- ap->level = level;
+ for (i = 0; i < cap; ++i)
+ {
+ crStateInitFBOAttachmentPoint(aap[i]);
+ aap[i]->type = GL_TEXTURE;
+ aap[i]->name = texture;
+ aap[i]->level = level;
+ }
}
DECLEXPORT(void) STATE_APIENTRY
@@ -486,32 +656,36 @@ crStateFramebufferTexture2DEXT(GLenum target, GLenum attachment, GLenum textarge
{
CRContext *g = GetCurrentContext();
CRFramebufferObjectState *fbo = &g->framebufferobject;
- CRFBOAttachmentPoint *ap;
+ CRFBOAttachmentPoint *aap[2];
+ GLuint cap, i;
CRTextureObj *tobj;
- GLboolean failed;
- crStateFramebufferTextureCheck(target, attachment, textarget, texture, level, &failed, &ap, &tobj);
- if (failed) return;
+ cap = crStateFramebufferTextureCheck(target, attachment, textarget, texture, level, aap, &tobj);
+ if (!cap) return;
if (!texture)
{
- crStateInitFBOAttachmentPoint(ap);
+ for (i = 0; i < cap; ++i)
+ {
+ crStateInitFBOAttachmentPoint(aap[i]);
+ }
return;
}
- CRSTATE_FBO_CHECKERR(GL_TEXTURE_1D==textarget || GL_TEXTURE_3D==textarget, GL_INVALID_OPERATION, "textarget");
+ CRSTATE_CHECKERR(GL_TEXTURE_1D==textarget || GL_TEXTURE_3D==textarget, GL_INVALID_OPERATION, "textarget");
-#ifndef IN_GUEST
CR_STATE_SHAREDOBJ_USAGE_SET(tobj, g);
-#endif
- crStateInitFBOAttachmentPoint(ap);
- ap->type = GL_TEXTURE;
- ap->name = texture;
- ap->level = level;
- if (textarget!=GL_TEXTURE_2D && textarget!=GL_TEXTURE_RECTANGLE_ARB)
+ for (i = 0; i < cap; ++i)
{
- ap->face = textarget;
+ crStateInitFBOAttachmentPoint(aap[i]);
+ aap[i]->type = GL_TEXTURE;
+ aap[i]->name = texture;
+ aap[i]->level = level;
+ if (textarget!=GL_TEXTURE_2D && textarget!=GL_TEXTURE_RECTANGLE_ARB)
+ {
+ aap[i]->face = textarget;
+ }
}
}
@@ -520,31 +694,35 @@ crStateFramebufferTexture3DEXT(GLenum target, GLenum attachment, GLenum textarge
{
CRContext *g = GetCurrentContext();
CRFramebufferObjectState *fbo = &g->framebufferobject;
- CRFBOAttachmentPoint *ap;
+ CRFBOAttachmentPoint *aap[2];
+ GLuint cap, i;
CRTextureObj *tobj;
- GLboolean failed;
- crStateFramebufferTextureCheck(target, attachment, textarget, texture, level, &failed, &ap, &tobj);
- if (failed) return;
+ cap = crStateFramebufferTextureCheck(target, attachment, textarget, texture, level, aap, &tobj);
+ if (!cap) return;
if (!texture)
{
- crStateInitFBOAttachmentPoint(ap);
+ for (i = 0; i < cap; ++i)
+ {
+ crStateInitFBOAttachmentPoint(aap[i]);
+ }
return;
}
- CRSTATE_FBO_CHECKERR(zoffset>(g->limits.max3DTextureSize-1), GL_INVALID_VALUE, "zoffset too big");
- CRSTATE_FBO_CHECKERR(textarget!=GL_TEXTURE_3D, GL_INVALID_OPERATION, "textarget");
+ CRSTATE_CHECKERR(zoffset>(g->limits.max3DTextureSize-1), GL_INVALID_VALUE, "zoffset too big");
+ CRSTATE_CHECKERR(textarget!=GL_TEXTURE_3D, GL_INVALID_OPERATION, "textarget");
-#ifndef IN_GUEST
CR_STATE_SHAREDOBJ_USAGE_SET(tobj, g);
-#endif
- crStateInitFBOAttachmentPoint(ap);
- ap->type = GL_TEXTURE;
- ap->name = texture;
- ap->level = level;
- ap->zoffset = zoffset;
+ for (i = 0; i < cap; ++i)
+ {
+ crStateInitFBOAttachmentPoint(aap[i]);
+ aap[i]->type = GL_TEXTURE;
+ aap[i]->name = texture;
+ aap[i]->level = level;
+ aap[i]->zoffset = zoffset;
+ }
}
DECLEXPORT(void) STATE_APIENTRY
@@ -552,41 +730,62 @@ crStateFramebufferRenderbufferEXT(GLenum target, GLenum attachment, GLenum rende
{
CRContext *g = GetCurrentContext();
CRFramebufferObjectState *fbo = &g->framebufferobject;
- CRFramebufferObject *pFBO;
- CRFBOAttachmentPoint *ap;
+ CRFramebufferObject *apFBOs[2];
+ GLuint cFBOs, i;
+ CRFBOAttachmentPoint *aap[2];
CRRenderbufferObject *rb;
- CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
- CRSTATE_FBO_CHECKERR(((target!=GL_FRAMEBUFFER_EXT) && (target!=GL_READ_FRAMEBUFFER) && (target!=GL_DRAW_FRAMEBUFFER)),
+ CRSTATE_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
+ CRSTATE_CHECKERR(((target!=GL_FRAMEBUFFER_EXT) && (target!=GL_READ_FRAMEBUFFER) && (target!=GL_DRAW_FRAMEBUFFER)),
GL_INVALID_ENUM, "invalid target");
- pFBO = GL_READ_FRAMEBUFFER==target ? fbo->readFB : fbo->drawFB;
- CRSTATE_FBO_CHECKERR(!pFBO, GL_INVALID_OPERATION, "no fbo bound");
- CRSTATE_FBO_CHECKERR(!crStateGetFBOAttachmentPoint(pFBO, attachment, &ap), GL_INVALID_ENUM, "invalid attachment");
+ cFBOs = crStateFramebufferGet(fbo, target, apFBOs);
+ CRSTATE_CHECKERR(!cFBOs, GL_INVALID_OPERATION, "no fbo bound");
+ for (i = 0; i < cFBOs; ++i)
+ {
+ CRSTATE_CHECKERR(!apFBOs[i], GL_INVALID_OPERATION, "zero fbo bound");
+ }
+
+ for (i = 0; i < cFBOs; ++i)
+ {
+ CRSTATE_CHECKERR(!crStateGetFBOAttachmentPoint(apFBOs[i], attachment, &aap[i]), GL_INVALID_ENUM, "invalid attachment");
+ }
if (!renderbuffer)
{
-#ifdef IN_GUEST
- if (ap->type!=GL_NONE)
+ for (i = 0; i < cFBOs; ++i)
{
- pFBO->status = GL_FRAMEBUFFER_UNDEFINED;
- }
+#ifdef IN_GUEST
+ if (&aap[i]->type!=GL_NONE)
+ {
+ apFBOs[i]->status = GL_FRAMEBUFFER_UNDEFINED;
+ }
#endif
- crStateInitFBOAttachmentPoint(ap);
+ crStateInitFBOAttachmentPoint(aap[i]);
+ }
return;
}
rb = (CRRenderbufferObject*) crHashtableSearch(g->shared->rbTable, renderbuffer);
- CRSTATE_FBO_CHECKERR(!rb, GL_INVALID_OPERATION, "rb doesn't exist");
+ if (!rb)
+ {
+ CRSTATE_CHECKERR(!crHashtableIsKeyUsed(g->shared->rbTable, renderbuffer), GL_INVALID_OPERATION, "rb doesn't exist");
+ rb = crStateRenderbufferAllocate(g, renderbuffer);
+ }
+ CR_STATE_SHAREDOBJ_USAGE_SET(rb, g);
+
+ for (i = 0; i < cFBOs; ++i)
+ {
#ifdef IN_GUEST
- if (ap->type!=GL_RENDERBUFFER_EXT || ap->name!=renderbuffer)
+ if (aap[i]->type!=GL_RENDERBUFFER_EXT || aap[i]->name!=renderbuffer)
{
- pFBO->status = GL_FRAMEBUFFER_UNDEFINED;
+ apFBOs[i]->status = GL_FRAMEBUFFER_UNDEFINED;
}
#endif
- crStateInitFBOAttachmentPoint(ap);
- ap->type = GL_RENDERBUFFER_EXT;
- ap->name = renderbuffer;
+ crStateInitFBOAttachmentPoint(aap[i]);
+ aap[i]->type = GL_RENDERBUFFER_EXT;
+ aap[i]->name = renderbuffer;
+ }
}
DECLEXPORT(void) STATE_APIENTRY
@@ -594,40 +793,87 @@ crStateGetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment,
{
CRContext *g = GetCurrentContext();
CRFramebufferObjectState *fbo = &g->framebufferobject;
- CRFramebufferObject *pFBO;
+ CRFramebufferObject *apFBOs[2];
+ GLint cFBOs = 0, i;
CRFBOAttachmentPoint *ap;
- CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
- CRSTATE_FBO_CHECKERR(((target!=GL_FRAMEBUFFER_EXT) && (target!=GL_READ_FRAMEBUFFER) && (target!=GL_DRAW_FRAMEBUFFER)),
+ CRSTATE_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
+ CRSTATE_CHECKERR(((target!=GL_FRAMEBUFFER_EXT) && (target!=GL_READ_FRAMEBUFFER) && (target!=GL_DRAW_FRAMEBUFFER)),
GL_INVALID_ENUM, "invalid target");
- pFBO = GL_READ_FRAMEBUFFER==target ? fbo->readFB : fbo->drawFB;
- CRSTATE_FBO_CHECKERR(!pFBO, GL_INVALID_OPERATION, "no fbo bound");
- CRSTATE_FBO_CHECKERR(!crStateGetFBOAttachmentPoint(pFBO, attachment, &ap), GL_INVALID_ENUM, "invalid attachment");
- switch (pname)
+ cFBOs = crStateFramebufferGet(fbo, target, apFBOs);
+
+ CRSTATE_CHECKERR(!cFBOs, GL_INVALID_OPERATION, "no fbo bound");
+ for (i = 0; i < cFBOs; ++i)
{
- case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT:
- *params = ap->type;
- break;
- case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT:
- CRSTATE_FBO_CHECKERR(ap->type!=GL_RENDERBUFFER_EXT && ap->type!=GL_TEXTURE, GL_INVALID_ENUM, "can't query object name when it's not bound")
- *params = ap->name;
- break;
- case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT:
- CRSTATE_FBO_CHECKERR(ap->type!=GL_TEXTURE, GL_INVALID_ENUM, "not a texture");
- *params = ap->level;
- break;
- case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT:
- CRSTATE_FBO_CHECKERR(ap->type!=GL_TEXTURE, GL_INVALID_ENUM, "not a texture");
- *params = ap->face;
- break;
- case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT:
- CRSTATE_FBO_CHECKERR(ap->type!=GL_TEXTURE, GL_INVALID_ENUM, "not a texture");
- *params = ap->zoffset;
- break;
- default:
- CRSTATE_FBO_CHECKERR(GL_TRUE, GL_INVALID_ENUM, "invalid pname");
+ CRSTATE_CHECKERR(!apFBOs[i], GL_INVALID_OPERATION, "zero fbo bound");
+ }
+
+ if(cFBOs != 1)
+ {
+ crWarning("different FBPs attached to draw and read buffers, returning info for the read buffer");
+ }
+
+ for (i = 0; i < 1; ++i)
+ {
+ CRSTATE_CHECKERR(!crStateGetFBOAttachmentPoint(apFBOs[i], attachment, &ap), GL_INVALID_ENUM, "invalid attachment");
+
+ switch (pname)
+ {
+ case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT:
+ *params = ap->type;
+ break;
+ case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT:
+ CRSTATE_CHECKERR(ap->type!=GL_RENDERBUFFER_EXT && ap->type!=GL_TEXTURE, GL_INVALID_ENUM, "can't query object name when it's not bound")
+ *params = ap->name;
+ break;
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT:
+ CRSTATE_CHECKERR(ap->type!=GL_TEXTURE, GL_INVALID_ENUM, "not a texture");
+ *params = ap->level;
+ break;
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT:
+ CRSTATE_CHECKERR(ap->type!=GL_TEXTURE, GL_INVALID_ENUM, "not a texture");
+ *params = ap->face;
+ break;
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT:
+ CRSTATE_CHECKERR(ap->type!=GL_TEXTURE, GL_INVALID_ENUM, "not a texture");
+ *params = ap->zoffset;
+ break;
+ default:
+ CRSTATE_CHECKERR(GL_TRUE, GL_INVALID_ENUM, "invalid pname");
+ }
+ }
+}
+
+DECLEXPORT(GLboolean) STATE_APIENTRY crStateIsFramebufferEXT( GLuint framebuffer )
+{
+ CRContext *g = GetCurrentContext();
+
+ FLUSH();
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glIsFramebufferEXT called in begin/end");
+ return GL_FALSE;
}
+
+ return framebuffer ? crHashtableIsKeyUsed(g->shared->fbTable, framebuffer) : GL_FALSE;
+}
+
+DECLEXPORT(GLboolean) STATE_APIENTRY crStateIsRenderbufferEXT( GLuint renderbuffer )
+{
+ CRContext *g = GetCurrentContext();
+
+
+ FLUSH();
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glIsRenderbufferEXT called in begin/end");
+ return GL_FALSE;
+ }
+
+ return renderbuffer ? crHashtableIsKeyUsed(g->shared->rbTable, renderbuffer) : GL_FALSE;
}
DECLEXPORT(void) STATE_APIENTRY
@@ -642,8 +888,11 @@ static void crStateSyncRenderbuffersCB(unsigned long key, void *data1, void *dat
diff_api.GenRenderbuffersEXT(1, &pRBO->hwid);
- diff_api.BindRenderbufferEXT(GL_RENDERBUFFER_EXT, pRBO->hwid);
- diff_api.RenderbufferStorageEXT(GL_RENDERBUFFER_EXT, pRBO->internalformat, pRBO->width, pRBO->height);
+ if (pRBO->width && pRBO->height)
+ {
+ diff_api.BindRenderbufferEXT(GL_RENDERBUFFER_EXT, pRBO->hwid);
+ diff_api.RenderbufferStorageEXT(GL_RENDERBUFFER_EXT, pRBO->internalformat, pRBO->width, pRBO->height);
+ }
}
static void crStateSyncAP(CRFBOAttachmentPoint *pAP, GLenum ap, CRContext *ctx)
@@ -774,36 +1023,37 @@ crStateFramebufferObjectSwitch(CRContext *from, CRContext *to)
}
DECLEXPORT(void) STATE_APIENTRY
-crStateFramebufferObjectDisableHW(CRContext *ctx, GLuint idFBO)
+crStateFramebufferObjectDisableHW(CRContext *ctx, GLuint idDrawFBO, GLuint idReadFBO)
{
- GLboolean fAdjustDrawReadBuffers = GL_FALSE;
+ GLenum idDrawBuffer = 0, idReadBuffer = 0;
- if (ctx->framebufferobject.drawFB || idFBO)
+ if (ctx->framebufferobject.drawFB || idDrawFBO)
{
diff_api.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0);
- fAdjustDrawReadBuffers = GL_TRUE;
+ idDrawBuffer = ctx->buffer.drawBuffer;
}
- if (ctx->framebufferobject.readFB ||idFBO)
+ if (ctx->framebufferobject.readFB || idReadFBO)
{
diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, 0);
- fAdjustDrawReadBuffers = GL_TRUE;
+ idReadBuffer = ctx->buffer.readBuffer;
}
- if (fAdjustDrawReadBuffers)
- {
- diff_api.DrawBuffer(GL_BACK);
- diff_api.ReadBuffer(GL_BACK);
- }
+ if (idDrawBuffer)
+ diff_api.DrawBuffer(idDrawBuffer);
+ if (idReadBuffer)
+ diff_api.ReadBuffer(idReadBuffer);
if (ctx->framebufferobject.renderbuffer)
diff_api.BindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
}
DECLEXPORT(void) STATE_APIENTRY
-crStateFramebufferObjectReenableHW(CRContext *fromCtx, CRContext *toCtx, GLuint idFBO)
+crStateFramebufferObjectReenableHW(CRContext *fromCtx, CRContext *toCtx, GLuint idDrawFBO, GLuint idReadFBO)
{
GLuint idReadBuffer = 0, idDrawBuffer = 0;
+ if (!fromCtx)
+ fromCtx = toCtx; /* <- in case fromCtx is zero, set it to toCtx to ensure framebuffer state gets re-enabled correctly */
if ((fromCtx->framebufferobject.drawFB) /* <- the FBO state was reset in crStateFramebufferObjectDisableHW */
&& fromCtx->framebufferobject.drawFB == toCtx->framebufferobject.drawFB) /* .. and it was NOT restored properly in crStateFramebufferObjectSwitch */
@@ -811,9 +1061,9 @@ crStateFramebufferObjectReenableHW(CRContext *fromCtx, CRContext *toCtx, GLuint
diff_api.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, toCtx->framebufferobject.drawFB->hwid);
idDrawBuffer = toCtx->framebufferobject.drawFB->drawbuffer[0];
}
- else if (idFBO && !toCtx->framebufferobject.drawFB)
+ else if (idDrawFBO && !toCtx->framebufferobject.drawFB)
{
- diff_api.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, idFBO);
+ diff_api.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, idDrawFBO);
idDrawBuffer = GL_COLOR_ATTACHMENT0;
}
@@ -823,9 +1073,9 @@ crStateFramebufferObjectReenableHW(CRContext *fromCtx, CRContext *toCtx, GLuint
diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, toCtx->framebufferobject.readFB->hwid);
idReadBuffer = toCtx->framebufferobject.readFB->readbuffer;
}
- else if (idFBO && !toCtx->framebufferobject.readFB)
+ else if (idReadFBO && !toCtx->framebufferobject.readFB)
{
- diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, idFBO);
+ diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, idReadFBO);
idReadBuffer = GL_COLOR_ATTACHMENT0;
}
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_get.py b/src/VBox/GuestHost/OpenGL/state_tracker/state_get.py
index 674eb6b6..759c30d9 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_get.py
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_get.py
@@ -233,3 +233,5 @@ for rettype in types:
print '\t\t\treturn;'
print '\t}'
print '}'
+
+from get_components import * \ No newline at end of file
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_get.txt b/src/VBox/GuestHost/OpenGL/state_tracker/state_get.txt
index 01974573..150d350b 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_get.txt
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_get.txt
@@ -80,6 +80,7 @@ GLfloat GL_POINT_SIZE g->point.pointSize
GLfloat GL_POINT_SIZE_MIN_ARB g->point.minSize
GLfloat GL_POINT_SIZE_MAX_ARB g->point.maxSize
GLfloat GL_POINT_FADE_THRESHOLD_SIZE_ARB g->point.fadeThresholdSize
+GLfloat GL_POINT_SPRITE_COORD_ORIGIN g->point.spriteCoordOrigin
GLfloat GL_POINT_DISTANCE_ATTENUATION_ARB g->point.distanceAttenuation[0] g->point.distanceAttenuation[1] g->point.distanceAttenuation[2]
GLboolean GL_NORMALIZE g->transform.normalize
@@ -233,13 +234,19 @@ GLint GL_LIST_INDEX g->lists.currentIndex
GLenum GL_LIST_MODE g->lists.mode
GLint GL_STENCIL_CLEAR_VALUE g->stencil.clearValue
-GLint GL_STENCIL_FAIL g->stencil.fail
-GLint GL_STENCIL_FUNC g->stencil.func
-GLint GL_STENCIL_PASS_DEPTH_FAIL g->stencil.passDepthFail
-GLint GL_STENCIL_PASS_DEPTH_PASS g->stencil.passDepthPass
-GLint GL_STENCIL_REF g->stencil.ref
+GLint GL_STENCIL_FAIL g->stencil.buffers[g->stencil.activeStencilFace==GL_FRONT?CRSTATE_STENCIL_BUFFER_ID_FRONT:CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].fail
+GLint GL_STENCIL_BACK_FAIL g->stencil.buffers[g->stencil.activeStencilFace==GL_FRONT?CRSTATE_STENCIL_BUFFER_ID_BACK:CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].fail
+GLint GL_STENCIL_FUNC g->stencil.buffers[g->stencil.activeStencilFace==GL_FRONT?CRSTATE_STENCIL_BUFFER_ID_FRONT:CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].func
+GLint GL_STENCIL_BACK_FUNC g->stencil.buffers[g->stencil.activeStencilFace==GL_FRONT?CRSTATE_STENCIL_BUFFER_ID_BACK:CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].func
+GLint GL_STENCIL_PASS_DEPTH_FAIL g->stencil.buffers[g->stencil.activeStencilFace==GL_FRONT?CRSTATE_STENCIL_BUFFER_ID_FRONT:CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].passDepthFail
+GLint GL_STENCIL_BACK_PASS_DEPTH_FAIL g->stencil.buffers[g->stencil.activeStencilFace==GL_FRONT?CRSTATE_STENCIL_BUFFER_ID_BACK:CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].passDepthFail
+GLint GL_STENCIL_PASS_DEPTH_PASS g->stencil.buffers[g->stencil.activeStencilFace==GL_FRONT?CRSTATE_STENCIL_BUFFER_ID_FRONT:CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].passDepthPass
+GLint GL_STENCIL_BACK_PASS_DEPTH_PASS g->stencil.buffers[g->stencil.activeStencilFace==GL_FRONT?CRSTATE_STENCIL_BUFFER_ID_BACK:CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].passDepthPass
+GLint GL_STENCIL_REF g->stencil.buffers[g->stencil.activeStencilFace==GL_FRONT?CRSTATE_STENCIL_BUFFER_ID_FRONT:CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].ref
+GLint GL_STENCIL_BACK_REF g->stencil.buffers[g->stencil.activeStencilFace==GL_FRONT?CRSTATE_STENCIL_BUFFER_ID_BACK:CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].ref
GLboolean GL_STENCIL_TEST g->stencil.stencilTest
-GLint GL_STENCIL_VALUE_MASK g->stencil.mask
+GLint GL_STENCIL_VALUE_MASK g->stencil.buffers[g->stencil.activeStencilFace==GL_FRONT?CRSTATE_STENCIL_BUFFER_ID_FRONT:CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].mask
+GLint GL_STENCIL_BACK_VALUE_MASK g->stencil.buffers[g->stencil.activeStencilFace==GL_FRONT?CRSTATE_STENCIL_BUFFER_ID_BACK:CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].mask
GLint GL_STENCIL_WRITEMASK g->stencil.writeMask
GLfloat GL_CURRENT_INDEX g->current.colorIndex
@@ -308,3 +315,5 @@ GLint GL_RENDERBUFFER_BINDING_EXT (g->framebufferobject.renderbuffer?g->framebuf
#CVA
GLint GL_ARRAY_ELEMENT_LOCK_FIRST_EXT g->client.array.lockFirst
GLint GL_ARRAY_ELEMENT_LOCK_COUNT_EXT g->client.array.lockCount
+
+GLint GL_ACTIVE_STENCIL_FACE_EXT g->stencil.activeStencilFace \ No newline at end of file
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_glsl.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_glsl.c
index 7741007b..48d5a7e8 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_glsl.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_glsl.c
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2009 Oracle Corporation
+ * Copyright (C) 2009-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -258,6 +258,21 @@ DECLEXPORT(GLuint) STATE_APIENTRY crStateGLSLProgramHWIDtoID(GLuint hwid)
return parms.id;
}
+DECLEXPORT(GLuint) STATE_APIENTRY crStateDeleteObjectARB( VBoxGLhandleARB obj )
+{
+ GLuint hwId = crStateGetProgramHWID(obj);
+ if (hwId)
+ {
+ crStateDeleteProgram(obj);
+ }
+ else
+ {
+ hwId = crStateGetShaderHWID(obj);
+ crStateDeleteShader(obj);
+ }
+ return hwId;
+}
+
DECLEXPORT(GLuint) STATE_APIENTRY crStateCreateShader(GLuint hwid, GLenum type)
{
CRGLSLShader *pShader;
@@ -267,13 +282,17 @@ DECLEXPORT(GLuint) STATE_APIENTRY crStateCreateShader(GLuint hwid, GLenum type)
#ifdef IN_GUEST
CRASSERT(!crStateGetShaderObj(stateId));
#else
- /* the id may not necesserily be hwid after save state restoration */
- while ((pShader = crStateGetShaderObj(stateId)) != NULL)
+ /* the proogram and shader names must not intersect because DeleteObjectARB must distinguish between them
+ * see crStateDeleteObjectARB
+ * this is why use programs table for shader keys allocation */
+ stateId = crHashtableAllocKeys(g->glsl.programs, 1);
+ if (!stateId)
{
- GLuint newStateId = stateId + 7;
- crDebug("Shader object %d already exists, generating a new one, %d", stateId, newStateId);
- stateId = newStateId;
+ crWarning("failed to allocate program key");
+ return 0;
}
+
+ Assert((pShader = crStateGetShaderObj(stateId)) == NULL);
#endif
pShader = (CRGLSLShader *) crAlloc(sizeof(*pShader));
@@ -311,19 +330,18 @@ DECLEXPORT(GLuint) STATE_APIENTRY crStateCreateProgram(GLuint hwid)
CRASSERT(!crStateGetProgramObj(stateId));
}
#else
- /* the id may not necesserily be hwid after save state restoration */
- while ((pProgram = crStateGetProgramObj(stateId)) != NULL)
+ stateId = crHashtableAllocKeys(g->glsl.programs, 1);
+ if (!stateId)
{
- GLuint newStateId = stateId + 7;
- crDebug("Program object %d already exists, generating a new one, %d", stateId, newStateId);
- stateId = newStateId;
+ crWarning("failed to allocate program key");
+ return 0;
}
#endif
pProgram = (CRGLSLProgram *) crAlloc(sizeof(*pProgram));
if (!pProgram)
{
- crWarning("crStateCreateShader: Out of memory!");
+ crWarning("crStateCreateProgram: Out of memory!");
return 0;
}
@@ -363,6 +381,11 @@ DECLEXPORT(void) STATE_APIENTRY crStateCompileShader(GLuint shader)
pShader->compiled = GL_TRUE;
}
+static void crStateDbgCheckNoProgramOfId(void *data)
+{
+ crError("Unexpected Program id");
+}
+
DECLEXPORT(void) STATE_APIENTRY crStateDeleteShader(GLuint shader)
{
CRGLSLShader *pShader = crStateGetShaderObj(shader);
@@ -378,6 +401,10 @@ DECLEXPORT(void) STATE_APIENTRY crStateDeleteShader(GLuint shader)
{
CRContext *g = GetCurrentContext();
crHashtableDelete(g->glsl.shaders, shader, crStateFreeGLSLShader);
+ /* since we use programs table for key allocation key allocation, we need to
+ * free the key in the programs table.
+ * See comment in crStateCreateShader */
+ crHashtableDelete(g->glsl.programs, shader, crStateDbgCheckNoProgramOfId);
}
}
@@ -598,8 +625,7 @@ DECLEXPORT(void) STATE_APIENTRY crStateBindAttribLocation(GLuint program, GLuint
{
if (!crStrcmp(pProgram->currentState.pAttribs[i].name, name))
{
- crFree(pProgram->currentState.pAttribs[i].name);
- pProgram->currentState.pAttribs[i].name = crStrdup(name);
+ pProgram->currentState.pAttribs[i].index = index;
return;
}
}
@@ -1186,6 +1212,7 @@ static void crStateGLSLCreateProgramCB(unsigned long key, void *data1, void *dat
DECLEXPORT(void) STATE_APIENTRY crStateGLSLSwitch(CRContext *from, CRContext *to)
{
+ GLboolean fForceUseProgramSet = GL_FALSE;
if (to->glsl.bResyncNeeded)
{
to->glsl.bResyncNeeded = GL_FALSE;
@@ -1194,10 +1221,13 @@ DECLEXPORT(void) STATE_APIENTRY crStateGLSLSwitch(CRContext *from, CRContext *to
crHashtableWalk(to->glsl.programs, crStateGLSLCreateProgramCB, to);
+ /* crStateGLSLCreateProgramCB changes the current program, ensure we have the proper program re-sored */
+ fForceUseProgramSet = GL_TRUE;
+
crHashtableWalk(to->glsl.shaders, crStateGLSLSyncShadersCB, NULL);
}
- if (to->glsl.activeProgram != from->glsl.activeProgram)
+ if (to->glsl.activeProgram != from->glsl.activeProgram || fForceUseProgramSet)
{
diff_api.UseProgram(to->glsl.activeProgram ? to->glsl.activeProgram->hwid : 0);
}
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_init.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_init.c
index f8ac1f5a..49bcd38b 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_init.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_init.c
@@ -17,13 +17,14 @@ CRContext *__currentContext = NULL;
#endif
CRStateBits *__currentBits = NULL;
-GLboolean g_availableContexts[CR_MAX_CONTEXTS];
+CRContext *g_pAvailableContexts[CR_MAX_CONTEXTS];
+uint32_t g_cContexts = 0;
static CRSharedState *gSharedState=NULL;
static CRContext *defaultContext = NULL;
-static GLboolean g_bVBoxEnableDiffOnMakeCurrent = GL_TRUE;
+GLboolean g_bVBoxEnableDiffOnMakeCurrent = GL_TRUE;
/**
@@ -60,7 +61,6 @@ crStateDeleteTextureCallback(void *texObj)
crStateDeleteTextureObject((CRTextureObj *) texObj);
}
-#ifndef IN_GUEST
typedef struct CR_STATE_RELEASEOBJ
{
CRContext *pCtx;
@@ -102,7 +102,7 @@ static void ReleaseRBOCallback(unsigned long key, void *data1, void *data2)
if (!CR_STATE_SHAREDOBJ_USAGE_IS_USED(pObj))
crHashtableDelete(pData->s->rbTable, key, crStateFreeRBO);
}
-#endif
+
/**
* Decrement shared state's refcount and delete when it hits zero.
*/
@@ -110,6 +110,7 @@ DECLEXPORT(void)
crStateFreeShared(CRContext *pContext, CRSharedState *s)
{
s->refCount--;
+ Assert(s->refCount >= 0);
if (s->refCount <= 0) {
if (s==gSharedState)
{
@@ -122,8 +123,7 @@ crStateFreeShared(CRContext *pContext, CRSharedState *s)
crFreeHashtable(s->rbTable, crStateFreeRBO);
crFree(s);
}
-#ifndef IN_GUEST
- else
+ else if (pContext)
{
/* evaluate usage bits*/
CR_STATE_RELEASEOBJ CbData;
@@ -134,7 +134,22 @@ crStateFreeShared(CRContext *pContext, CRSharedState *s)
crHashtableWalk(s->fbTable, ReleaseFBOCallback, &CbData);
crHashtableWalk(s->rbTable, ReleaseRBOCallback, &CbData);
}
-#endif
+}
+
+DECLEXPORT(CRSharedState *) crStateGlobalSharedAcquire()
+{
+ if (!gSharedState)
+ {
+ crWarning("No Global Shared State!");
+ return NULL;
+ }
+ gSharedState->refCount++;
+ return gSharedState;
+}
+
+DECLEXPORT(void) crStateGlobalSharedRelease()
+{
+ crStateFreeShared(NULL, gSharedState);
}
DECLEXPORT(void) STATE_APIENTRY
@@ -218,11 +233,26 @@ static CRContext *
crStateCreateContextId(int i, const CRLimitsState *limits,
GLint visBits, CRContext *shareCtx)
{
- CRContext *ctx = (CRContext *) crCalloc( sizeof( *ctx ) );
+ CRContext *ctx;
int j;
int node32 = i >> 5;
int node = i & 0x1f;
+ if (g_pAvailableContexts[i] != NULL)
+ {
+ crWarning("trying to create context with used id");
+ return NULL;
+ }
+
+ ctx = (CRContext *) crCalloc( sizeof( *ctx ) );
+ if (!ctx)
+ {
+ crWarning("failed to allocate context");
+ return NULL;
+ }
+ g_pAvailableContexts[i] = ctx;
+ ++g_cContexts;
+ CRASSERT(g_cContexts < RT_ELEMENTS(g_pAvailableContexts));
ctx->id = i;
#ifdef CHROMIUM_THREADSAFE
VBoxTlsRefInit(ctx, crStateContextDtor);
@@ -252,7 +282,7 @@ crStateCreateContextId(int i, const CRLimitsState *limits,
crStateExtensionsInit( &(ctx->limits), &(ctx->extensions) );
crStateBufferObjectInit( ctx ); /* must precede client state init! */
- crStateClientInit( &(ctx->client) );
+ crStateClientInit( ctx );
crStateBufferInit( ctx );
crStateCurrentInit( ctx );
@@ -330,7 +360,23 @@ crStateCreateContextId(int i, const CRLimitsState *limits,
static void
crStateFreeContext(CRContext *ctx)
{
- crStateClientDestroy( &(ctx->client) );
+#ifndef DEBUG_misha
+ CRASSERT(g_pAvailableContexts[ctx->id] == ctx);
+#endif
+ if (g_pAvailableContexts[ctx->id] == ctx)
+ {
+ g_pAvailableContexts[ctx->id] = NULL;
+ --g_cContexts;
+ CRASSERT(g_cContexts < RT_ELEMENTS(g_pAvailableContexts));
+ }
+ else
+ {
+#ifndef DEBUG_misha
+ crWarning("freeing context %p, id(%d) not being in the context list", ctx, ctx->id);
+#endif
+ }
+
+ crStateClientDestroy( ctx );
crStateLimitsDestroy( &(ctx->limits) );
crStateBufferObjectDestroy( ctx );
crStateEvaluatorDestroy( ctx );
@@ -377,10 +423,15 @@ void crStateInit(void)
crStateClientInitBits( &(__currentBits->client) );
crStateLightingInitBits( &(__currentBits->lighting) );
} else
+ {
+#ifndef DEBUG_misha
crWarning("State tracker is being re-initialized..\n");
+#endif
+ }
for (i=0;i<CR_MAX_CONTEXTS;i++)
- g_availableContexts[i] = 0;
+ g_pAvailableContexts[i] = NULL;
+ g_cContexts = 0;
#ifdef CHROMIUM_THREADSAFE
if (!__isContextTLSInited)
@@ -411,11 +462,14 @@ void crStateInit(void)
/* Reset diff_api */
crMemZero(&diff_api, sizeof(SPUDispatchTable));
+ Assert(!gSharedState);
+ gSharedState = NULL;
+
/* Allocate the default/NULL context */
+ CRASSERT(g_pAvailableContexts[0] == NULL);
defaultContext = crStateCreateContextId(0, NULL, CR_RGB_BIT, NULL);
- CRASSERT(g_availableContexts[0] == 0);
- g_availableContexts[0] = 1; /* in use forever */
-
+ CRASSERT(g_pAvailableContexts[0] == defaultContext);
+ CRASSERT(g_cContexts == 1);
#ifdef CHROMIUM_THREADSAFE
SetCurrentContext(defaultContext);
#else
@@ -425,6 +479,7 @@ void crStateInit(void)
void crStateDestroy(void)
{
+ int i;
if (__currentBits)
{
crStateClientDestroyBits(&(__currentBits->client));
@@ -433,6 +488,25 @@ void crStateDestroy(void)
__currentBits = NULL;
}
+ SetCurrentContext(NULL);
+
+ for (i = CR_MAX_CONTEXTS-1; i >= 0; i--)
+ {
+ if (g_pAvailableContexts[i])
+ {
+#ifdef CHROMIUM_THREADSAFE
+ if (VBoxTlsRefIsFunctional(g_pAvailableContexts[i]))
+ VBoxTlsRefRelease(g_pAvailableContexts[i]);
+#else
+ crStateFreeContext(g_pAvailableContexts[i]);
+#endif
+ }
+ }
+
+ /* default context was stored in g_pAvailableContexts[0], so it was destroyed already */
+ defaultContext = NULL;
+
+
#ifdef CHROMIUM_THREADSAFE
crFreeTSD(&__contextTSD);
__isContextTLSInited = 0;
@@ -452,7 +526,7 @@ void crStateDestroy(void)
* (i.e. the old context to the new context). The transformation
* is accomplished by calling GL functions through the 'diff_api'
* so that the downstream GL machine (represented by the __currentContext
- * structure) is updated to reflect the new context state. Finally,
+ * structure) is updated to reflect the new context state. Finally,
* we point __currentContext to the new context.
*
* A subtle problem we have to deal with is context destruction.
@@ -485,35 +559,46 @@ void crStateDestroy(void)
CRContext *
crStateCreateContext(const CRLimitsState *limits, GLint visBits, CRContext *share)
{
- int i;
+ return crStateCreateContextEx(limits, visBits, share, -1);
+}
+CRContext *
+crStateCreateContextEx(const CRLimitsState *limits, GLint visBits, CRContext *share, GLint presetID)
+{
/* Must have created the default context via crStateInit() first */
CRASSERT(defaultContext);
- for (i = 1 ; i < CR_MAX_CONTEXTS ; i++)
+ if (presetID>0)
{
- if (!g_availableContexts[i])
+ if(g_pAvailableContexts[presetID])
{
- g_availableContexts[i] = 1; /* it's no longer available */
- return crStateCreateContextId( i, limits, visBits, share );
+ crWarning("requesting to create context with already allocated id");
+ return NULL;
}
}
- crError( "Out of available contexts in crStateCreateContexts (max %d)",
- CR_MAX_CONTEXTS );
- /* never get here */
- return NULL;
-}
-
-CRContext *
-crStateCreateContextEx(const CRLimitsState *limits, GLint visBits, CRContext *share, GLint presetID)
-{
- if (presetID>0)
+ else
{
- CRASSERT(!g_availableContexts[presetID]);
- g_availableContexts[presetID] = 1;
- return crStateCreateContextId(presetID, limits, visBits, share);
+ int i;
+
+ for (i = 1 ; i < CR_MAX_CONTEXTS ; i++)
+ {
+ if (!g_pAvailableContexts[i])
+ {
+ presetID = i;
+ break;
+ }
+ }
+
+ if (presetID<=0)
+ {
+ crError( "Out of available contexts in crStateCreateContexts (max %d)",
+ CR_MAX_CONTEXTS );
+ /* never get here */
+ return NULL;
+ }
}
- else return crStateCreateContext(limits, visBits, share);
+
+ return crStateCreateContextId(presetID, limits, visBits, share);
}
void crStateDestroyContext( CRContext *ctx )
@@ -535,9 +620,17 @@ void crStateDestroyContext( CRContext *ctx )
/* ensure matrix state is also current */
crStateMatrixMode(defaultContext->transform.matrixMode);
}
- g_availableContexts[ctx->id] = 0;
#ifdef CHROMIUM_THREADSAFE
+ VBoxTlsRefMarkDestroy(ctx);
+# ifdef IN_GUEST
+ if (VBoxTlsRefCountGet(ctx) > 1 && ctx->shared == gSharedState)
+ {
+ /* we always need to free the global shared state to prevent the situation when guest thinks the shared objects are still valid, while host destroys them */
+ crStateFreeShared(ctx, ctx->shared);
+ ctx->shared = crStateAllocShared();
+ }
+# endif
VBoxTlsRefRelease(ctx);
#else
crStateFreeContext(ctx);
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_lists.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_lists.c
index 09831311..005f9462 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_lists.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_lists.c
@@ -30,7 +30,7 @@ void crStateListsInit(CRContext *ctx)
RESET(lb->dirty, ctx->bitid);
}
-/*#define CRSTATE_DEBUG_QUERY_HW_STATE*/
+//#define CRSTATE_DEBUG_QUERY_HW_STATE
#ifndef CRSTATE_DEBUG_QUERY_HW_STATE
# define CRSTATE_SET_CAP(state, value, format) g->state=value
@@ -168,7 +168,7 @@ void crStateListsInit(CRContext *ctx)
} \
}
-void STATE_APIENTRY crStateQueryHWState()
+void STATE_APIENTRY crStateQueryHWState(GLuint fbFbo, GLuint bbFbo)
{
CRContext *g = GetCurrentContext();
CRStateBits *sb = GetCurrentBits();
@@ -217,12 +217,68 @@ void STATE_APIENTRY crStateQueryHWState()
if (CHECKDIRTY(sb->buffer.drawBuffer, negbitID))
{
- CRSTATE_SET_ENUM(buffer.drawBuffer, GL_DRAW_BUFFER);
+ GLuint buf = 0;
+ diff_api.GetIntegerv(GL_DRAW_BUFFER, &buf);
+
+ if (buf == GL_COLOR_ATTACHMENT0_EXT && (bbFbo || fbFbo))
+ {
+ GLuint binding = 0;
+ diff_api.GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &binding);
+ if (!binding)
+ {
+ crWarning("HW state synch: GL_DRAW_FRAMEBUFFER_BINDING is NULL");
+ }
+
+ if (bbFbo && binding == bbFbo)
+ {
+ g->buffer.drawBuffer = GL_BACK;
+ }
+ else if (fbFbo && binding == fbFbo)
+ {
+ g->buffer.drawBuffer = GL_FRONT;
+ }
+ else
+ {
+ g->buffer.drawBuffer = buf;
+ }
+ }
+ else
+ {
+ g->buffer.drawBuffer = buf;
+ }
}
if (CHECKDIRTY(sb->buffer.readBuffer, negbitID))
{
- CRSTATE_SET_ENUM(buffer.readBuffer, GL_READ_BUFFER);
+ GLuint buf = 0;
+ diff_api.GetIntegerv(GL_READ_BUFFER, &buf);
+
+ if (buf == GL_COLOR_ATTACHMENT0_EXT && (bbFbo || fbFbo))
+ {
+ GLuint binding = 0;
+ diff_api.GetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &binding);
+ if (!binding)
+ {
+ crWarning("HW state synch: GL_READ_FRAMEBUFFER_BINDING is NULL");
+ }
+
+ if (bbFbo && binding == bbFbo)
+ {
+ g->buffer.readBuffer = GL_BACK;
+ }
+ else if (fbFbo && binding == fbFbo)
+ {
+ g->buffer.readBuffer = GL_FRONT;
+ }
+ else
+ {
+ g->buffer.readBuffer = buf;
+ }
+ }
+ else
+ {
+ g->buffer.readBuffer = buf;
+ }
}
if (CHECKDIRTY(sb->buffer.indexMask, negbitID))
@@ -295,23 +351,122 @@ void STATE_APIENTRY crStateQueryHWState()
if (CHECKDIRTY(sb->stencil.dirty, negbitID))
{
+ GLenum activeFace;
+ GLboolean backIsSet = GL_FALSE, frontIsSet = GL_FALSE;
+
if (CHECKDIRTY(sb->stencil.enable, negbitID))
{
CRSTATE_SET_ENABLED(stencil.stencilTest, GL_STENCIL_TEST);
}
- if (CHECKDIRTY(sb->stencil.func, negbitID))
+ if (CHECKDIRTY(sb->stencil.enableTwoSideEXT, negbitID))
{
- CRSTATE_SET_ENUM(stencil.func, GL_STENCIL_FUNC);
- CRSTATE_SET_INT(stencil.ref, GL_STENCIL_REF);
- CRSTATE_SET_INT(stencil.mask, GL_STENCIL_VALUE_MASK);
+ CRSTATE_SET_ENABLED(stencil.stencilTwoSideEXT, GL_STENCIL_TEST_TWO_SIDE_EXT);
}
- if (CHECKDIRTY(sb->stencil.op, negbitID))
+ if (CHECKDIRTY(sb->stencil.activeStencilFace, negbitID))
{
- CRSTATE_SET_ENUM(stencil.fail, GL_STENCIL_FAIL);
- CRSTATE_SET_ENUM(stencil.passDepthFail, GL_STENCIL_PASS_DEPTH_FAIL);
- CRSTATE_SET_ENUM(stencil.passDepthPass, GL_STENCIL_PASS_DEPTH_PASS);
+ CRSTATE_SET_ENUM(stencil.activeStencilFace, GL_ACTIVE_STENCIL_FACE_EXT);
+ }
+
+ activeFace = g->stencil.activeStencilFace;
+
+
+#define CRSTATE_SET_STENCIL_FUNC(_idx, _suff) do { \
+ CRSTATE_SET_ENUM(stencil.buffers[(_idx)].func, GL_STENCIL##_suff##FUNC); \
+ CRSTATE_SET_INT(stencil.buffers[(_idx)].ref, GL_STENCIL##_suff##REF); \
+ CRSTATE_SET_INT(stencil.buffers[(_idx)].mask, GL_STENCIL##_suff##VALUE_MASK); \
+ } while (0)
+
+#define CRSTATE_SET_STENCIL_OP(_idx, _suff) do { \
+ CRSTATE_SET_ENUM(stencil.buffers[(_idx)].fail, GL_STENCIL##_suff##FAIL); \
+ CRSTATE_SET_ENUM(stencil.buffers[(_idx)].passDepthFail, GL_STENCIL##_suff##PASS_DEPTH_FAIL); \
+ CRSTATE_SET_ENUM(stencil.buffers[(_idx)].passDepthPass, GL_STENCIL##_suff##PASS_DEPTH_PASS); \
+ } while (0)
+
+ /* func */
+
+ if (CHECKDIRTY(sb->stencil.bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].func, negbitID))
+ {
+ /* this if branch is not needed here actually, just in case ogl drivers misbehave */
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_SET_STENCIL_FUNC(CRSTATE_STENCIL_BUFFER_ID_BACK, _BACK_);
+ backIsSet = GL_TRUE;
+ }
+
+ if (CHECKDIRTY(sb->stencil.bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].func, negbitID))
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+ CRSTATE_SET_STENCIL_FUNC(CRSTATE_STENCIL_BUFFER_ID_FRONT, _);
+ frontIsSet = GL_TRUE;
+ }
+
+ if ((!frontIsSet || !backIsSet) && CHECKDIRTY(sb->stencil.bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].func, negbitID))
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+ CRSTATE_SET_STENCIL_FUNC(CRSTATE_STENCIL_BUFFER_ID_FRONT, _);
+ if (!backIsSet)
+ {
+ g->stencil.buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].func = g->stencil.buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func;
+ g->stencil.buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].ref = g->stencil.buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref;
+ g->stencil.buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].mask = g->stencil.buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask;
+ }
+ }
+
+ /* op */
+ backIsSet = GL_FALSE, frontIsSet = GL_FALSE;
+
+ if (CHECKDIRTY(sb->stencil.bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].op, negbitID))
+ {
+ /* this if branch is not needed here actually, just in case ogl drivers misbehave */
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_SET_STENCIL_OP(CRSTATE_STENCIL_BUFFER_ID_BACK, _BACK_);
+ backIsSet = GL_TRUE;
+ }
+
+ if (CHECKDIRTY(sb->stencil.bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].op, negbitID))
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+ CRSTATE_SET_STENCIL_OP(CRSTATE_STENCIL_BUFFER_ID_FRONT, _);
+ frontIsSet = GL_TRUE;
+ }
+
+ if ((!frontIsSet || !backIsSet) && CHECKDIRTY(sb->stencil.bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].op, negbitID))
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+ CRSTATE_SET_STENCIL_OP(CRSTATE_STENCIL_BUFFER_ID_FRONT, _);
+ if (!backIsSet)
+ {
+ g->stencil.buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].fail = g->stencil.buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail;
+ g->stencil.buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthFail = g->stencil.buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail;
+ g->stencil.buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthPass = g->stencil.buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass;
+ }
}
if (CHECKDIRTY(sb->stencil.clearValue, negbitID))
@@ -499,12 +654,12 @@ void STATE_APIENTRY crStateQueryHWState()
{
CRSTATE_SET_MATERIAL_COLOR(lighting.ambient[0], GL_FRONT, GL_AMBIENT);
CRSTATE_SET_MATERIAL_COLOR(lighting.ambient[1], GL_BACK, GL_AMBIENT);
- CRSTATE_SET_MATERIAL_COLOR(lighting.diffuse[0], GL_FRONT, GL_AMBIENT);
- CRSTATE_SET_MATERIAL_COLOR(lighting.diffuse[1], GL_BACK, GL_AMBIENT);
- CRSTATE_SET_MATERIAL_COLOR(lighting.specular[0], GL_FRONT, GL_AMBIENT);
- CRSTATE_SET_MATERIAL_COLOR(lighting.specular[1], GL_BACK, GL_AMBIENT);
- CRSTATE_SET_MATERIAL_COLOR(lighting.emission[0], GL_FRONT, GL_AMBIENT);
- CRSTATE_SET_MATERIAL_COLOR(lighting.emission[1], GL_BACK, GL_AMBIENT);
+ CRSTATE_SET_MATERIAL_COLOR(lighting.diffuse[0], GL_FRONT, GL_DIFFUSE);
+ CRSTATE_SET_MATERIAL_COLOR(lighting.diffuse[1], GL_BACK, GL_DIFFUSE);
+ CRSTATE_SET_MATERIAL_COLOR(lighting.specular[0], GL_FRONT, GL_SPECULAR);
+ CRSTATE_SET_MATERIAL_COLOR(lighting.specular[1], GL_BACK, GL_SPECULAR);
+ CRSTATE_SET_MATERIAL_COLOR(lighting.emission[0], GL_FRONT, GL_EMISSION);
+ CRSTATE_SET_MATERIAL_COLOR(lighting.emission[1], GL_BACK, GL_EMISSION);
CRSTATE_SET_MATERIAL_F(lighting.shininess[0], GL_FRONT, GL_SHININESS);
CRSTATE_SET_MATERIAL_F(lighting.shininess[1], GL_BACK, GL_SHININESS);
}
@@ -1093,7 +1248,7 @@ void STATE_APIENTRY crStateNewList (GLuint list, GLenum mode)
l->mode = mode;
}
-void STATE_APIENTRY crStateEndList (void)
+void STATE_APIENTRY crStateEndList (void)
{
CRContext *g = GetCurrentContext();
CRListsState *l = &(g->lists);
@@ -1110,13 +1265,6 @@ void STATE_APIENTRY crStateEndList (void)
return;
}
-#ifndef IN_GUEST
- if (l->mode==GL_COMPILE)
- {
- crStateQueryHWState();
- }
-#endif
-
l->currentIndex = 0;
l->mode = 0;
}
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_point.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_point.c
index fbaac24d..de40c089 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_point.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_point.c
@@ -40,6 +40,9 @@ void crStatePointInit (CRContext *ctx)
}
#endif
+ p->spriteCoordOrigin = (GLfloat)GL_UPPER_LEFT;
+ RESET(pb->spriteCoordOrigin, ctx->bitid);
+
RESET(pb->dirty, ctx->bitid);
/*
@@ -167,6 +170,17 @@ void STATE_APIENTRY crStatePointParameterfvARB(GLenum pname, const GLfloat *para
return;
}
break;
+ case GL_POINT_SPRITE_COORD_ORIGIN:
+ {
+ GLenum enmVal = (GLenum)params[0];
+ if (enmVal != GL_LOWER_LEFT && enmVal != GL_UPPER_LEFT) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glPointParameterfvARB invalid GL_POINT_SPRITE_COORD_ORIGIN value: %f", params[0]);
+ return;
+ }
+ p->spriteCoordOrigin = params[0];
+ DIRTY(pb->spriteCoordOrigin, g->neg_bitid);
+ break;
+ }
default:
crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glPointParameterfvARB invalid enum: %f", pname);
return;
@@ -186,3 +200,248 @@ void STATE_APIENTRY crStatePointParameteriv(GLenum pname, const GLint *params)
GLfloat f_param = (GLfloat) (*params);
crStatePointParameterfvARB( pname, &f_param );
}
+
+void crStatePointDiff(CRPointBits *b, CRbitvalue *bitID,
+ CRContext *fromCtx, CRContext *toCtx)
+{
+ CRPointState *from = &(fromCtx->point);
+ CRPointState *to = &(toCtx->point);
+ unsigned int j, i;
+ CRbitvalue nbitID[CR_MAX_BITARRAY];
+ Assert(0);
+ for (j=0;j<CR_MAX_BITARRAY;j++)
+ nbitID[j] = ~bitID[j];
+ i = 0; /* silence compiler */
+ if (CHECKDIRTY(b->enableSmooth, bitID))
+ {
+ glAble able[2];
+ able[0] = diff_api.Disable;
+ able[1] = diff_api.Enable;
+ if (from->pointSmooth != to->pointSmooth)
+ {
+ able[to->pointSmooth](GL_POINT_SMOOTH);
+ from->pointSmooth = to->pointSmooth;
+ }
+ CLEARDIRTY(b->enableSmooth, nbitID);
+ }
+ if (CHECKDIRTY(b->size, bitID))
+ {
+ if (from->pointSize != to->pointSize)
+ {
+ diff_api.PointSize (to->pointSize);
+ from->pointSize = to->pointSize;
+ }
+ CLEARDIRTY(b->size, nbitID);
+ }
+ if (CHECKDIRTY(b->minSize, bitID))
+ {
+ if (from->minSize != to->minSize)
+ {
+ diff_api.PointParameterfARB (GL_POINT_SIZE_MIN_ARB, to->minSize);
+ from->minSize = to->minSize;
+ }
+ CLEARDIRTY(b->minSize, nbitID);
+ }
+ if (CHECKDIRTY(b->maxSize, bitID))
+ {
+ if (from->maxSize != to->maxSize)
+ {
+ diff_api.PointParameterfARB (GL_POINT_SIZE_MAX_ARB, to->maxSize);
+ from->maxSize = to->maxSize;
+ }
+ CLEARDIRTY(b->maxSize, nbitID);
+ }
+ if (CHECKDIRTY(b->fadeThresholdSize, bitID))
+ {
+ if (from->fadeThresholdSize != to->fadeThresholdSize)
+ {
+ diff_api.PointParameterfARB (GL_POINT_FADE_THRESHOLD_SIZE_ARB, to->fadeThresholdSize);
+ from->fadeThresholdSize = to->fadeThresholdSize;
+ }
+ CLEARDIRTY(b->fadeThresholdSize, nbitID);
+ }
+ if (CHECKDIRTY(b->spriteCoordOrigin, bitID))
+ {
+ if (from->spriteCoordOrigin != to->spriteCoordOrigin)
+ {
+ diff_api.PointParameterfARB (GL_POINT_SPRITE_COORD_ORIGIN, to->spriteCoordOrigin);
+ from->spriteCoordOrigin = to->spriteCoordOrigin;
+ }
+ CLEARDIRTY(b->spriteCoordOrigin, nbitID);
+ }
+ if (CHECKDIRTY(b->distanceAttenuation, bitID))
+ {
+ if (from->distanceAttenuation[0] != to->distanceAttenuation[0] || from->distanceAttenuation[1] != to->distanceAttenuation[1] || from->distanceAttenuation[2] != to->distanceAttenuation[2]) {
+ diff_api.PointParameterfvARB (GL_POINT_DISTANCE_ATTENUATION_ARB, to->distanceAttenuation);
+ from->distanceAttenuation[0] = to->distanceAttenuation[0];
+ from->distanceAttenuation[1] = to->distanceAttenuation[1];
+ from->distanceAttenuation[2] = to->distanceAttenuation[2];
+ }
+ CLEARDIRTY(b->distanceAttenuation, nbitID);
+ }
+ if (CHECKDIRTY(b->enableSprite, bitID))
+ {
+ glAble able[2];
+ able[0] = diff_api.Disable;
+ able[1] = diff_api.Enable;
+ if (from->pointSprite != to->pointSprite)
+ {
+ able[to->pointSprite](GL_POINT_SPRITE_ARB);
+ from->pointSprite = to->pointSprite;
+ }
+ CLEARDIRTY(b->enableSprite, nbitID);
+ }
+ {
+ unsigned int activeUnit = (unsigned int) -1;
+ for (i = 0; i < CR_MAX_TEXTURE_UNITS; i++) {
+ if (CHECKDIRTY(b->coordReplacement[i], bitID))
+ {
+ GLint replacement = to->coordReplacement[i];
+ if (activeUnit != i) {
+ diff_api.ActiveTextureARB(i + GL_TEXTURE0_ARB );
+ activeUnit = i;
+ }
+ diff_api.TexEnviv(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, &replacement);
+ from->coordReplacement[i] = to->coordReplacement[i];
+ CLEARDIRTY(b->coordReplacement[i], nbitID);
+ }
+ }
+ if (activeUnit != toCtx->texture.curTextureUnit)
+ diff_api.ActiveTextureARB(GL_TEXTURE0 + toCtx->texture.curTextureUnit);
+ }
+ CLEARDIRTY(b->dirty, nbitID);
+}
+
+void crStatePointSwitch(CRPointBits *b, CRbitvalue *bitID,
+ CRContext *fromCtx, CRContext *toCtx)
+{
+ CRPointState *from = &(fromCtx->point);
+ CRPointState *to = &(toCtx->point);
+ unsigned int j, i;
+ GLboolean fEnabled;
+ CRbitvalue nbitID[CR_MAX_BITARRAY];
+ for (j=0;j<CR_MAX_BITARRAY;j++)
+ nbitID[j] = ~bitID[j];
+ i = 0; /* silence compiler */
+ if (CHECKDIRTY(b->enableSmooth, bitID))
+ {
+ glAble able[2];
+ able[0] = diff_api.Disable;
+ able[1] = diff_api.Enable;
+ if (from->pointSmooth != to->pointSmooth)
+ {
+ able[to->pointSmooth](GL_POINT_SMOOTH);
+ FILLDIRTY(b->enableSmooth);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->enableSmooth, nbitID);
+ }
+ if (CHECKDIRTY(b->size, bitID))
+ {
+ if (from->pointSize != to->pointSize)
+ {
+ diff_api.PointSize (to->pointSize);
+ FILLDIRTY(b->size);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->size, nbitID);
+ }
+ if (CHECKDIRTY(b->minSize, bitID))
+ {
+ if (from->minSize != to->minSize)
+ {
+ diff_api.PointParameterfARB (GL_POINT_SIZE_MIN_ARB, to->minSize);
+ FILLDIRTY(b->minSize);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->minSize, nbitID);
+ }
+ if (CHECKDIRTY(b->maxSize, bitID))
+ {
+ if (from->maxSize != to->maxSize)
+ {
+ diff_api.PointParameterfARB (GL_POINT_SIZE_MAX_ARB, to->maxSize);
+ FILLDIRTY(b->maxSize);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->maxSize, nbitID);
+ }
+ if (CHECKDIRTY(b->fadeThresholdSize, bitID))
+ {
+ if (from->fadeThresholdSize != to->fadeThresholdSize)
+ {
+ diff_api.PointParameterfARB (GL_POINT_FADE_THRESHOLD_SIZE_ARB, to->fadeThresholdSize);
+ FILLDIRTY(b->fadeThresholdSize);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->fadeThresholdSize, nbitID);
+ }
+ if (CHECKDIRTY(b->spriteCoordOrigin, bitID))
+ {
+ if (from->spriteCoordOrigin != to->spriteCoordOrigin)
+ {
+ diff_api.PointParameterfARB (GL_POINT_SPRITE_COORD_ORIGIN, to->spriteCoordOrigin);
+ FILLDIRTY(b->spriteCoordOrigin);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->spriteCoordOrigin, nbitID);
+ }
+ if (CHECKDIRTY(b->distanceAttenuation, bitID))
+ {
+ if (from->distanceAttenuation[0] != to->distanceAttenuation[0] || from->distanceAttenuation[1] != to->distanceAttenuation[1] || from->distanceAttenuation[2] != to->distanceAttenuation[2]) {
+ diff_api.PointParameterfvARB (GL_POINT_DISTANCE_ATTENUATION_ARB, to->distanceAttenuation);
+ FILLDIRTY(b->distanceAttenuation);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->distanceAttenuation, nbitID);
+ }
+ fEnabled = from->pointSprite;
+ {
+ unsigned int activeUnit = (unsigned int) -1;
+ for (i = 0; i < CR_MAX_TEXTURE_UNITS; i++) {
+ if (CHECKDIRTY(b->coordReplacement[i], bitID))
+ {
+ if (!fEnabled)
+ {
+ diff_api.Enable(GL_POINT_SPRITE_ARB);
+ fEnabled = GL_TRUE;
+ }
+#if 0
+ /*don't set coord replacement, it will be set just before drawing points when necessary,
+ * to work around gpu driver bugs
+ * See crServerDispatch[Begin|End|Draw*] */
+ GLint replacement = to->coordReplacement[i];
+ if (activeUnit != i) {
+ diff_api.ActiveTextureARB(i + GL_TEXTURE0_ARB );
+ activeUnit = i;
+ }
+ diff_api.TexEnviv(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, &replacement);
+#endif
+ CLEARDIRTY(b->coordReplacement[i], nbitID);
+ }
+ }
+ if (activeUnit != toCtx->texture.curTextureUnit)
+ diff_api.ActiveTextureARB(GL_TEXTURE0 + toCtx->texture.curTextureUnit);
+ }
+ if (CHECKDIRTY(b->enableSprite, bitID))
+ {
+ glAble able[2];
+ able[0] = diff_api.Disable;
+ able[1] = diff_api.Enable;
+ if (fEnabled != to->pointSprite)
+ {
+ able[to->pointSprite](GL_POINT_SPRITE_ARB);
+ FILLDIRTY(b->enableSprite);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->enableSprite, nbitID);
+ }
+ else if (fEnabled != to->pointSprite)
+ {
+ glAble able[2];
+ able[0] = diff_api.Disable;
+ able[1] = diff_api.Enable;
+ able[to->pointSprite](GL_POINT_SPRITE_ARB);
+ }
+ CLEARDIRTY(b->dirty, nbitID);
+}
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_point.txt b/src/VBox/GuestHost/OpenGL/state_tracker/state_point.txt
index 69ab8a70..ba92c153 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_point.txt
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_point.txt
@@ -7,6 +7,7 @@
:minSize:minSize:PointParameterfARB,GL_POINT_SIZE_MIN_ARB
:maxSize:maxSize:PointParameterfARB,GL_POINT_SIZE_MAX_ARB
:fadeThresholdSize:fadeThresholdSize:PointParameterfARB,GL_POINT_FADE_THRESHOLD_SIZE_ARB
+:spriteCoordOrigin:spriteCoordOrigin:PointParameterfARB,GL_POINT_SPRITE_COORD_ORIGIN
#:distanceAttenuation:distanceAttenuation:PointParameterfvARB,GL_POINT_DISTANCE_ATTENUATION_ARB
-:distanceAttenuation:*if (from->distanceAttenuation[0] != to->distanceAttenuation[0] || from->distanceAttenuation[1] != to->distanceAttenuation[1] || from->distanceAttenuation[2] != to->distanceAttenuation[2]) {
-:distanceAttenuation:* diff_api.PointParameterfvARB (GL_POINT_DISTANCE_ATTENUATION_ARB, to->distanceAttenuation);
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_polygon.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_polygon.c
index 31410bed..611e2f18 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_polygon.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_polygon.c
@@ -180,8 +180,7 @@ void STATE_APIENTRY crStatePolygonStipple (const GLubyte *p)
if (!p && !crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB))
{
- crStateError(__LINE__, __FILE__, GL_NO_ERROR,
- "Void pointer passed to PolygonStipple");
+ crDebug("Void pointer passed to PolygonStipple");
return;
}
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_program.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_program.c
index 2b0940bb..e8dd5971 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_program.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_program.c
@@ -267,25 +267,10 @@ void STATE_APIENTRY crStateGenProgramsNV(GLsizei n, GLuint *ids)
{
CRContext *g = GetCurrentContext();
CRProgramState *p = &(g->program);
- GLint start, i;
- if (g->current.inBeginEnd) {
- crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
- "glGenProgramsNV called in Begin/End");
- return;
- }
-
- if (n < 0) {
- crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glGenProgramsNV(n)");
- return;
- }
-
- start = crHashtableAllocKeys(p->programHash , n);
- for (i = 0; i < n; i++)
- ids[i] = (GLuint) (start + i);
+ crStateGenNames(g, p->programHash, n, ids);
}
-
void STATE_APIENTRY crStateGenProgramsARB(GLsizei n, GLuint *ids)
{
crStateGenProgramsNV(n, ids);
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_snapshot.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_snapshot.c
index eadc228a..6b2a5baa 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_snapshot.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_snapshot.c
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2008 Oracle Corporation
+ * Copyright (C) 2008-2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -85,6 +85,18 @@ static int32_t crStateAllocAndSSMR3GetMem(PSSMHANDLE pSSM, void **pBuffer, size_
} \
} while (0)
+#define SHCROGL_ROUNDBOUND(_v, _b) (((_v) + ((_b) - 1)) & ~((_b) - 1))
+#define SHCROGL_ALIGNTAILSIZE(_v, _b) (SHCROGL_ROUNDBOUND((_v),(_b)) - (_v))
+#define SHCROGL_CUT_FOR_OLD_TYPE_TO_ENSURE_ALIGNMENT_SIZE(_type, _field, _oldFieldType, _nextFieldAllignment) (SHCROGL_ALIGNTAILSIZE(((RT_OFFSETOF(_type, _field) + sizeof (_oldFieldType))), (_nextFieldAllignment)))
+#define SHCROGL_CUT_FOR_OLD_TYPE_TO_ENSURE_ALIGNMENT(_type, _field, _oldFieldType, _nextFieldAllignment) do { \
+ const int32_t cbAlignment = SHCROGL_CUT_FOR_OLD_TYPE_TO_ENSURE_ALIGNMENT_SIZE(_type, _field, _oldFieldType, _nextFieldAllignment); \
+ /*AssertCompile(SHCROGL_CUT_TAIL_ALIGNMENT_SIZE(_type, _lastField) >= 0 && SHCROGL_CUT_TAIL_ALIGNMENT_SIZE(_type, _lastField) < sizeof (void*));*/ \
+ if (cbAlignment) { \
+ rc = SSMR3Skip(pSSM, cbAlignment); \
+ } \
+ } while (0)
+
+
#define SHCROGL_CUT_TAIL_ALIGNMENT_SIZE(_type, _lastField) (sizeof (_type) - RT_OFFSETOF(_type, _lastField) - RT_SIZEOFMEMB(_type, _lastField))
#define SHCROGL_CUT_TAIL_ALIGNMENT(_type, _lastField) do { \
const int32_t cbAlignment = SHCROGL_CUT_TAIL_ALIGNMENT_SIZE(_type, _lastField); \
@@ -139,6 +151,35 @@ static int32_t crStateLoadTextureUnit_v_BEFORE_CTXUSAGE_BITS(CRTextureUnit *t, P
return rc;
}
+static int crStateLoadStencilPoint_v_37(CRPointState *pPoint, PSSMHANDLE pSSM)
+{
+ int rc = VINF_SUCCESS;
+ SHCROGL_GET_STRUCT_HEAD(pPoint, CRPointState, spriteCoordOrigin);
+ pPoint->spriteCoordOrigin = (GLfloat)GL_UPPER_LEFT;
+ return rc;
+}
+
+static int32_t crStateLoadStencilState_v_33(CRStencilState *s, PSSMHANDLE pSSM)
+{
+ CRStencilState_v_33 stencilV33;
+ int32_t rc = SSMR3GetMem(pSSM, &stencilV33, sizeof (stencilV33));
+ AssertRCReturn(rc, rc);
+ s->stencilTest = stencilV33.stencilTest;
+ s->stencilTwoSideEXT = GL_FALSE;
+ s->activeStencilFace = GL_FRONT;
+ s->clearValue = stencilV33.clearValue;
+ s->writeMask = stencilV33.writeMask;
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func = stencilV33.func;
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask = stencilV33.mask;
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref = stencilV33.ref;
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail = stencilV33.fail;
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail = stencilV33.passDepthFail;
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass = stencilV33.passDepthPass;
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK] = s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT];
+ crStateStencilBufferInit(&s->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK]);
+ return VINF_SUCCESS;
+}
+
static int32_t crStateLoadTextureState_v_BEFORE_CTXUSAGE_BITS(CRTextureState *t, PSSMHANDLE pSSM)
{
GLint i;
@@ -202,6 +243,47 @@ static int32_t crStateLoadTextureState_v_BEFORE_CTXUSAGE_BITS(CRTextureState *t,
SHCROGL_CUT_TAIL_ALIGNMENT(CRTextureState, unit);
+ return VINF_SUCCESS;
+}
+
+static int32_t crStateStencilBufferStack_v_33(CRStencilBufferStack *s, PSSMHANDLE pSSM)
+{
+ CRStencilBufferStack_v_33 stackV33;
+ int32_t rc = SSMR3GetMem(pSSM, &stackV33, sizeof (stackV33));
+
+ s->stencilTest = stackV33.stencilTest;
+ s->stencilTwoSideEXT = GL_FALSE;
+ s->activeStencilFace = GL_FRONT;
+ s->clearValue = stackV33.clearValue;
+ s->writeMask = stackV33.writeMask;
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func = stackV33.func;
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask = stackV33.mask;
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref = stackV33.ref;
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail = stackV33.fail;
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail = stackV33.passDepthFail;
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass = stackV33.passDepthPass;
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK] = s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT];
+
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].func = GL_ALWAYS;
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].mask = 0xFFFFFFFF;
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].ref = 0;
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].fail = GL_KEEP;
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].passDepthFail = GL_KEEP;
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].passDepthPass = GL_KEEP;
+
+ return VINF_SUCCESS;
+}
+
+static int32_t crStateLoadAttribState_v_33(CRAttribState *t, PSSMHANDLE pSSM)
+{
+ int32_t i, rc;
+ SHCROGL_GET_STRUCT_HEAD(t, CRAttribState, stencilBufferStack);
+ for (i = 0; i < CR_MAX_ATTRIB_STACK_DEPTH; ++i)
+ {
+ rc = crStateStencilBufferStack_v_33(&t->stencilBufferStack[i], pSSM);
+ AssertRCReturn(rc, rc);
+ }
+ SHCROGL_GET_STRUCT_TAIL(t, CRAttribState, textureStackDepth);
return rc;
}
@@ -221,7 +303,14 @@ static int32_t crStateLoadTextureStack_v_BEFORE_CTXUSAGE_BITS(CRTextureStack *t,
static int32_t crStateLoadAttribState_v_BEFORE_CTXUSAGE_BITS(CRAttribState *t, PSSMHANDLE pSSM)
{
int32_t i, rc;
- SHCROGL_GET_STRUCT_HEAD(t, CRAttribState, textureStack);
+
+ SHCROGL_GET_STRUCT_HEAD(t, CRAttribState, stencilBufferStack);
+ for (i = 0; i < CR_MAX_ATTRIB_STACK_DEPTH; ++i)
+ {
+ rc = crStateStencilBufferStack_v_33(&t->stencilBufferStack[i], pSSM);
+ AssertRCReturn(rc, rc);
+ }
+ SHCROGL_GET_STRUCT_PART(t, CRAttribState, textureStackDepth, textureStack);
for (i = 0; i < CR_MAX_ATTRIB_STACK_DEPTH; ++i)
{
rc = crStateLoadTextureStack_v_BEFORE_CTXUSAGE_BITS(&t->textureStack[i], pSSM);
@@ -1069,6 +1158,15 @@ static void crStateSaveGLSLProgramCB(unsigned long key, void *data1, void *data2
diff_api.GetProgramiv(pProgram->hwid, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformLen);
diff_api.GetProgramiv(pProgram->hwid, GL_ACTIVE_UNIFORMS, &activeUniforms);
+ if (!maxUniformLen)
+ {
+ if (activeUniforms)
+ {
+ crWarning("activeUniforms (%d), while maxUniformLen is zero", activeUniforms);
+ activeUniforms = 0;
+ }
+ }
+
if (activeUniforms>0)
{
name = (GLchar *) crAlloc((maxUniformLen+8)*sizeof(GLchar));
@@ -1148,7 +1246,11 @@ static int32_t crStateSaveClientPointer(CRVertexArrays *pArrays, int32_t index,
cp = crStateGetClientPointerByIndex(index, pArrays);
- rc = SSMR3PutU32(pSSM, cp->buffer->id);
+ if (cp->buffer)
+ rc = SSMR3PutU32(pSSM, cp->buffer->id);
+ else
+ rc = SSMR3PutU32(pSSM, 0);
+
AssertRCReturn(rc, rc);
#ifdef CR_EXT_compiled_vertex_array
@@ -1304,6 +1406,59 @@ static int32_t crStateLoadCurrentBits(CRStateBits *pBits, PSSMHANDLE pSSM)
return VINF_SUCCESS;
}
+static void crStateSaveKeysCB(unsigned long firstKey, unsigned long count, void *data)
+{
+ PSSMHANDLE pSSM = (PSSMHANDLE)data;
+ int rc;
+ CRASSERT(firstKey);
+ CRASSERT(count);
+ rc = SSMR3PutU32(pSSM, firstKey);
+ CRASSERT(RT_SUCCESS(rc));
+ rc = SSMR3PutU32(pSSM, count);
+ CRASSERT(RT_SUCCESS(rc));
+}
+
+static int32_t crStateSaveKeys(CRHashTable *pHash, PSSMHANDLE pSSM)
+{
+ crHashtableWalkKeys(pHash, crStateSaveKeysCB , pSSM);
+ /* use null terminator */
+ SSMR3PutU32(pSSM, 0);
+ return VINF_SUCCESS;
+}
+
+static int32_t crStateLoadKeys(CRHashTable *pHash, PSSMHANDLE pSSM, uint32_t u32Version)
+{
+ uint32_t u32Key, u32Count, i;
+ int rc;
+ for(;;)
+ {
+ rc = SSMR3GetU32(pSSM, &u32Key);
+ AssertRCReturn(rc, rc);
+
+ if (!u32Key)
+ return rc;
+
+ rc = SSMR3GetU32(pSSM, &u32Count);
+ AssertRCReturn(rc, rc);
+
+ CRASSERT(u32Count);
+
+ if (u32Version > SHCROGL_SSM_VERSION_WITH_BUGGY_KEYS)
+ {
+ for (i = u32Key; i < u32Count + u32Key; ++i)
+ {
+ GLboolean fIsNew = crHashtableAllocRegisterKey(pHash, i);
+#if 0 //def DEBUG_misha
+ CRASSERT(fIsNew);
+#endif
+ }
+ }
+ }
+
+ return rc;
+}
+
+
int32_t crStateSaveContext(CRContext *pContext, PSSMHANDLE pSSM)
{
int32_t rc, i;
@@ -1312,30 +1467,18 @@ int32_t crStateSaveContext(CRContext *pContext, PSSMHANDLE pSSM)
CRASSERT(pContext && pSSM);
- pContext->buffer.storedWidth = pContext->buffer.width;
- pContext->buffer.storedHeight = pContext->buffer.height;
+ CRASSERT(pContext->client.attribStackDepth == 0);
- CRASSERT(VBoxTlsRefIsFunctional(pContext));
+ /* this stuff is not used anymore, zero it up for sanity */
+ pContext->buffer.storedWidth = 0;
+ pContext->buffer.storedHeight = 0;
- /* do not increment the saved state version due to VBOXTLSREFDATA addition to CRContext */
- rc = SSMR3PutMem(pSSM, pContext, VBOXTLSREFDATA_OFFSET(CRContext));
- AssertRCReturn(rc, rc);
-
- /* now store bitid & neg_bitid */
- rc = SSMR3PutMem(pSSM, pContext->bitid, sizeof (pContext->bitid) + sizeof (pContext->neg_bitid));
- AssertRCReturn(rc, rc);
+ CRASSERT(VBoxTlsRefIsFunctional(pContext));
- /* the pre-VBOXTLSREFDATA CRContext structure might have additional allignment bits before the CRContext::shared */
- ui32 = VBOXTLSREFDATA_OFFSET(CRContext) + sizeof (pContext->bitid) + sizeof (pContext->neg_bitid);
- ui32 &= (sizeof (void*) - 1);
- if (ui32)
- {
- void* pTmp = NULL;
- rc = SSMR3PutMem(pSSM, &pTmp, ui32);
- AssertRCReturn(rc, rc);
- }
+ /* make sure the gl error state is captured by our state mechanism to store the correct gl error value */
+ crStateSyncHWErrorState(pContext);
- rc = SSMR3PutMem(pSSM, &pContext->shared, sizeof (CRContext) - RT_OFFSETOF(CRContext, shared));
+ rc = SSMR3PutMem(pSSM, pContext, sizeof (*pContext));
AssertRCReturn(rc, rc);
if (crHashtableNumElements(pContext->shared->dlistTable)>0)
@@ -1412,6 +1555,8 @@ int32_t crStateSaveContext(CRContext *pContext, PSSMHANDLE pSSM)
if (bSaveShared)
{
CRASSERT(pContext->shared && pContext->shared->textureTable);
+ rc = crStateSaveKeys(pContext->shared->textureTable, pSSM);
+ AssertRCReturn(rc, rc);
ui32 = crHashtableNumElements(pContext->shared->textureTable);
rc = SSMR3PutU32(pSSM, ui32);
AssertRCReturn(rc, rc);
@@ -1509,6 +1654,11 @@ int32_t crStateSaveContext(CRContext *pContext, PSSMHANDLE pSSM)
#ifdef CR_ARB_vertex_buffer_object
/* Save buffer objects */
+ if (bSaveShared)
+ {
+ rc = crStateSaveKeys(pContext->shared->buffersTable, pSSM);
+ AssertRCReturn(rc, rc);
+ }
ui32 = bSaveShared? crHashtableNumElements(pContext->shared->buffersTable):0;
rc = SSMR3PutU32(pSSM, ui32);
AssertRCReturn(rc, rc);
@@ -1576,10 +1726,15 @@ int32_t crStateSaveContext(CRContext *pContext, PSSMHANDLE pSSM)
/* Save FBOs */
if (bSaveShared)
{
+ rc = crStateSaveKeys(pContext->shared->fbTable, pSSM);
+ AssertRCReturn(rc, rc);
ui32 = crHashtableNumElements(pContext->shared->fbTable);
rc = SSMR3PutU32(pSSM, ui32);
AssertRCReturn(rc, rc);
crHashtableWalk(pContext->shared->fbTable, crStateSaveFramebuffersCB, pSSM);
+
+ rc = crStateSaveKeys(pContext->shared->rbTable, pSSM);
+ AssertRCReturn(rc, rc);
ui32 = crHashtableNumElements(pContext->shared->rbTable);
rc = SSMR3PutU32(pSSM, ui32);
AssertRCReturn(rc, rc);
@@ -1607,72 +1762,6 @@ int32_t crStateSaveContext(CRContext *pContext, PSSMHANDLE pSSM)
AssertRCReturn(rc, rc);
#endif
- if (pContext->buffer.storedWidth && pContext->buffer.storedHeight)
- {
- CRBufferState *pBuf = &pContext->buffer;
- CRPixelPackState packing = pContext->client.pack;
- GLint cbData;
- void *pData;
-
- cbData = crPixelSize(GL_RGBA, GL_UNSIGNED_BYTE) * pBuf->storedWidth * pBuf->storedHeight;
- pData = crAlloc(cbData);
-
- if (!pData)
- {
- return VERR_NO_MEMORY;
- }
-
- diff_api.PixelStorei(GL_PACK_SKIP_ROWS, 0);
- diff_api.PixelStorei(GL_PACK_SKIP_PIXELS, 0);
- diff_api.PixelStorei(GL_PACK_ALIGNMENT, 1);
- diff_api.PixelStorei(GL_PACK_ROW_LENGTH, 0);
- diff_api.PixelStorei(GL_PACK_IMAGE_HEIGHT, 0);
- diff_api.PixelStorei(GL_PACK_SKIP_IMAGES, 0);
- diff_api.PixelStorei(GL_PACK_SWAP_BYTES, 0);
- diff_api.PixelStorei(GL_PACK_LSB_FIRST, 0);
-
- if (pContext->framebufferobject.readFB)
- {
- diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, 0);
- }
- if (pContext->bufferobject.packBuffer->hwid>0)
- {
- diff_api.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
- }
-
- diff_api.ReadBuffer(GL_FRONT);
- diff_api.ReadPixels(0, 0, pBuf->storedWidth, pBuf->storedHeight, GL_RGBA, GL_UNSIGNED_BYTE, pData);
- rc = SSMR3PutMem(pSSM, pData, cbData);
- AssertRCReturn(rc, rc);
-
- diff_api.ReadBuffer(GL_BACK);
- diff_api.ReadPixels(0, 0, pBuf->storedWidth, pBuf->storedHeight, GL_RGBA, GL_UNSIGNED_BYTE, pData);
- rc = SSMR3PutMem(pSSM, pData, cbData);
- AssertRCReturn(rc, rc);
-
- if (pContext->bufferobject.packBuffer->hwid>0)
- {
- diff_api.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pContext->bufferobject.packBuffer->hwid);
- }
- if (pContext->framebufferobject.readFB)
- {
- diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, pContext->framebufferobject.readFB->hwid);
- }
- diff_api.ReadBuffer(pContext->framebufferobject.readFB ?
- pContext->framebufferobject.readFB->readbuffer : pContext->buffer.readBuffer);
-
- diff_api.PixelStorei(GL_PACK_SKIP_ROWS, packing.skipRows);
- diff_api.PixelStorei(GL_PACK_SKIP_PIXELS, packing.skipPixels);
- diff_api.PixelStorei(GL_PACK_ALIGNMENT, packing.alignment);
- diff_api.PixelStorei(GL_PACK_ROW_LENGTH, packing.rowLength);
- diff_api.PixelStorei(GL_PACK_IMAGE_HEIGHT, packing.imageHeight);
- diff_api.PixelStorei(GL_PACK_SKIP_IMAGES, packing.skipImages);
- diff_api.PixelStorei(GL_PACK_SWAP_BYTES, packing.swapBytes);
- diff_api.PixelStorei(GL_PACK_LSB_FIRST, packing.psLSBFirst);
-
- crFree(pData);
- }
-
return VINF_SUCCESS;
}
@@ -1693,6 +1782,77 @@ static void crStateFindSharedCB(unsigned long key, void *data1, void *data2)
}
}
+int32_t crStateSaveGlobals(PSSMHANDLE pSSM)
+{
+ /* don't need that for now */
+#if 0
+ CRStateBits *pBits;
+ int rc;
+
+ CRASSERT(g_cContexts >= 1);
+ if (g_cContexts <= 1)
+ return VINF_SUCCESS;
+
+ pBits = GetCurrentBits();
+#define CRSTATE_BITS_OP(_var, _size) \
+ rc = SSMR3PutMem(pSSM, (pBits->_var), _size); \
+ AssertRCReturn(rc, rc);
+#include "state_bits_globalop.h"
+#undef CRSTATE_BITS_OP
+#endif
+ return VINF_SUCCESS;
+}
+
+int32_t crStateLoadGlobals(PSSMHANDLE pSSM, uint32_t u32Version)
+{
+ CRStateBits *pBits;
+ int rc;
+ CRASSERT(g_cContexts >= 1);
+ if (g_cContexts <= 1)
+ return VINF_SUCCESS;
+
+ pBits = GetCurrentBits();
+
+ if (u32Version >= SHCROGL_SSM_VERSION_WITH_STATE_BITS)
+ {
+#define CRSTATE_BITS_OP(_var, _size) \
+ rc = SSMR3GetMem(pSSM, (pBits->_var), _size); \
+ AssertRCReturn(rc, rc);
+
+ if (u32Version < SHCROGL_SSM_VERSION_WITH_FIXED_STENCIL)
+ {
+#define CRSTATE_BITS_OP_VERSION (SHCROGL_SSM_VERSION_WITH_FIXED_STENCIL - 1)
+#define CRSTATE_BITS_OP_STENCIL_FUNC_V_33(_i, _var) do {} while (0)
+#define CRSTATE_BITS_OP_STENCIL_OP_V_33(_i, _var) do {} while (0)
+#include "state_bits_globalop.h"
+#undef CRSTATE_BITS_OP_VERSION
+#undef CRSTATE_BITS_OP_STENCIL_FUNC_V_33
+#undef CRSTATE_BITS_OP_STENCIL_OP_V_33
+ }
+ else if (u32Version < SHCROGL_SSM_VERSION_WITH_SPRITE_COORD_ORIGIN)
+ {
+#define CRSTATE_BITS_OP_VERSION (SHCROGL_SSM_VERSION_WITH_SPRITE_COORD_ORIGIN - 1)
+#include "state_bits_globalop.h"
+#undef CRSTATE_BITS_OP_VERSION
+ }
+ else
+ {
+ /* we do not put dirty bits to state anymore,
+ * nop */
+//#include "state_bits_globalop.h"
+ }
+#undef CRSTATE_BITS_OP
+ /* always dirty all bits */
+ /* return VINF_SUCCESS; */
+ }
+
+#define CRSTATE_BITS_OP(_var, _size) FILLDIRTY(pBits->_var);
+#include "state_bits_globalop.h"
+#undef CRSTATE_BITS_OP
+ return VINF_SUCCESS;
+}
+
+
#define SLC_COPYPTR(ptr) pTmpContext->ptr = pContext->ptr
#define SLC_ASSSERT_NULL_PTR(ptr) CRASSERT(!pContext->ptr)
@@ -1707,12 +1867,7 @@ int32_t crStateLoadContext(CRContext *pContext, CRHashTable * pCtxTable, PFNCRST
uint32_t uiNumElems, ui, k;
unsigned long key;
GLboolean bLoadShared = GL_TRUE;
- union {
- CRbitvalue bitid[CR_MAX_BITARRAY];
- struct {
- VBOXTLSREFDATA
- } tlsRef;
- } bitid;
+ GLenum err;
CRASSERT(pContext && pSSM);
@@ -1723,70 +1878,130 @@ int32_t crStateLoadContext(CRContext *pContext, CRHashTable * pCtxTable, PFNCRST
CRASSERT(VBoxTlsRefIsFunctional(pContext));
- /* do not increment the saved state version due to VBOXTLSREFDATA addition to CRContext */
- rc = SSMR3GetMem(pSSM, pTmpContext, VBOXTLSREFDATA_OFFSET(CRContext));
- AssertRCReturn(rc, rc);
-
- /* VBox 4.1.8 had a bug that VBOXTLSREFDATA was also stored in the snapshot,
- * thus the saved state data format was changed w/o changing the saved state version.
- * here we determine whether the saved state contains VBOXTLSREFDATA, and if so, treat it accordingly */
- rc = SSMR3GetMem(pSSM, &bitid, sizeof (bitid));
- AssertRCReturn(rc, rc);
-
- /* the bitid array has one bit set only. this is why if bitid.tlsRef has both cTlsRefs
- * and enmTlsRefState non-zero - this is definitely NOT a bit id and is a VBOXTLSREFDATA */
- if (bitid.tlsRef.enmTlsRefState == VBOXTLSREFDATA_STATE_INITIALIZED
- && bitid.tlsRef.cTlsRefs)
+ if (u32Version <= SHCROGL_SSM_VERSION_WITH_INVALID_ERROR_STATE)
{
- /* VBOXTLSREFDATA is stored, skip it */
- crMemcpy(&pTmpContext->bitid, ((uint8_t*)&bitid) + VBOXTLSREFDATA_SIZE(), sizeof (bitid) - VBOXTLSREFDATA_SIZE());
- rc = SSMR3GetMem(pSSM, ((uint8_t*)&pTmpContext->bitid) + sizeof (pTmpContext->bitid) - VBOXTLSREFDATA_SIZE(), sizeof (pTmpContext->neg_bitid) + VBOXTLSREFDATA_SIZE());
+ union {
+ CRbitvalue bitid[CR_MAX_BITARRAY];
+ struct {
+ VBOXTLSREFDATA
+ } tlsRef;
+ } bitid;
+
+ /* do not increment the saved state version due to VBOXTLSREFDATA addition to CRContext */
+ rc = SSMR3GetMem(pSSM, pTmpContext, VBOXTLSREFDATA_OFFSET(CRContext));
AssertRCReturn(rc, rc);
- ui = VBOXTLSREFDATA_OFFSET(CRContext) + VBOXTLSREFDATA_SIZE() + sizeof (pTmpContext->bitid) + sizeof (pTmpContext->neg_bitid);
- ui = RT_OFFSETOF(CRContext, shared) - ui;
- }
- else
- {
- /* VBOXTLSREFDATA is NOT stored */
- crMemcpy(&pTmpContext->bitid, &bitid, sizeof (bitid));
- rc = SSMR3GetMem(pSSM, &pTmpContext->neg_bitid, sizeof (pTmpContext->neg_bitid));
+ /* VBox 4.1.8 had a bug that VBOXTLSREFDATA was also stored in the snapshot,
+ * thus the saved state data format was changed w/o changing the saved state version.
+ * here we determine whether the saved state contains VBOXTLSREFDATA, and if so, treat it accordingly */
+ rc = SSMR3GetMem(pSSM, &bitid, sizeof (bitid));
AssertRCReturn(rc, rc);
- /* the pre-VBOXTLSREFDATA CRContext structure might have additional allignment bits before the CRContext::shared */
- ui = VBOXTLSREFDATA_OFFSET(CRContext) + sizeof (pTmpContext->bitid) + sizeof (pTmpContext->neg_bitid);
+ /* the bitid array has one bit set only. this is why if bitid.tlsRef has both cTlsRefs
+ * and enmTlsRefState non-zero - this is definitely NOT a bit id and is a VBOXTLSREFDATA */
+ if (bitid.tlsRef.enmTlsRefState == VBOXTLSREFDATA_STATE_INITIALIZED
+ && bitid.tlsRef.cTlsRefs)
+ {
+ /* VBOXTLSREFDATA is stored, skip it */
+ crMemcpy(&pTmpContext->bitid, ((uint8_t*)&bitid) + VBOXTLSREFDATA_SIZE(), sizeof (bitid) - VBOXTLSREFDATA_SIZE());
+ rc = SSMR3GetMem(pSSM, ((uint8_t*)&pTmpContext->bitid) + sizeof (pTmpContext->bitid) - VBOXTLSREFDATA_SIZE(), sizeof (pTmpContext->neg_bitid) + VBOXTLSREFDATA_SIZE());
+ AssertRCReturn(rc, rc);
- ui &= (sizeof (void*) - 1);
- }
+ ui = VBOXTLSREFDATA_OFFSET(CRContext) + VBOXTLSREFDATA_SIZE() + sizeof (pTmpContext->bitid) + sizeof (pTmpContext->neg_bitid);
+ ui = RT_OFFSETOF(CRContext, shared) - ui;
+ }
+ else
+ {
+ /* VBOXTLSREFDATA is NOT stored */
+ crMemcpy(&pTmpContext->bitid, &bitid, sizeof (bitid));
+ rc = SSMR3GetMem(pSSM, &pTmpContext->neg_bitid, sizeof (pTmpContext->neg_bitid));
+ AssertRCReturn(rc, rc);
- if (ui)
- {
- void* pTmp = NULL;
- rc = SSMR3GetMem(pSSM, &pTmp, ui);
- AssertRCReturn(rc, rc);
- }
+ /* the pre-VBOXTLSREFDATA CRContext structure might have additional allignment bits before the CRContext::shared */
+ ui = VBOXTLSREFDATA_OFFSET(CRContext) + sizeof (pTmpContext->bitid) + sizeof (pTmpContext->neg_bitid);
- /* we will later do crMemcpy from entire pTmpContext to pContext,
- * for simplicity store the VBOXTLSREFDATA from the pContext to pTmpContext */
- VBOXTLSREFDATA_COPY(pTmpContext, pContext);
+ ui &= (sizeof (void*) - 1);
+ }
- if (u32Version == SHCROGL_SSM_VERSION_BEFORE_CTXUSAGE_BITS)
+ if (ui)
+ {
+ void* pTmp = NULL;
+ rc = SSMR3GetMem(pSSM, &pTmp, ui);
+ AssertRCReturn(rc, rc);
+ }
+
+ if (u32Version == SHCROGL_SSM_VERSION_BEFORE_CTXUSAGE_BITS)
+ {
+ SHCROGL_GET_STRUCT_PART(pTmpContext, CRContext, shared, attrib);
+ rc = crStateLoadAttribState_v_BEFORE_CTXUSAGE_BITS(&pTmpContext->attrib, pSSM);
+ AssertRCReturn(rc, rc);
+ SHCROGL_CUT_FIELD_ALIGNMENT(CRContext, attrib, buffer);
+ SHCROGL_GET_STRUCT_PART(pTmpContext, CRContext, buffer, point);
+ rc = crStateLoadStencilPoint_v_37(&pTmpContext->point, pSSM);
+ AssertRCReturn(rc, rc);
+ SHCROGL_GET_STRUCT_PART(pTmpContext, CRContext, polygon, stencil);
+ rc = crStateLoadStencilState_v_33(&pTmpContext->stencil, pSSM);
+ AssertRCReturn(rc, rc);
+ SHCROGL_CUT_FOR_OLD_TYPE_TO_ENSURE_ALIGNMENT(CRContext, stencil, CRStencilState_v_33, sizeof (void*));
+ rc = crStateLoadTextureState_v_BEFORE_CTXUSAGE_BITS(&pTmpContext->texture, pSSM);
+ AssertRCReturn(rc, rc);
+ SHCROGL_CUT_FIELD_ALIGNMENT(CRContext, texture, transform);
+ SHCROGL_GET_STRUCT_TAIL(pTmpContext, CRContext, transform);
+ }
+ else
+ {
+ SHCROGL_GET_STRUCT_PART(pTmpContext, CRContext, shared, attrib);
+ rc = crStateLoadAttribState_v_33(&pTmpContext->attrib, pSSM);
+ AssertRCReturn(rc, rc);
+ SHCROGL_CUT_FIELD_ALIGNMENT(CRContext, attrib, buffer);
+ SHCROGL_GET_STRUCT_PART(pTmpContext, CRContext, buffer, point);
+ rc = crStateLoadStencilPoint_v_37(&pTmpContext->point, pSSM);
+ AssertRCReturn(rc, rc);
+ SHCROGL_GET_STRUCT_PART(pTmpContext, CRContext, polygon, stencil);
+ rc = crStateLoadStencilState_v_33(&pTmpContext->stencil, pSSM);
+ AssertRCReturn(rc, rc);
+ SHCROGL_CUT_FOR_OLD_TYPE_TO_ENSURE_ALIGNMENT(CRContext, stencil, CRStencilState_v_33, sizeof (void*));
+ SHCROGL_GET_STRUCT_TAIL(pTmpContext, CRContext, texture);
+ }
+
+ pTmpContext->error = GL_NO_ERROR; /* <- the error state contained some random error data here
+ * treat as no error */
+ }
+ else if (u32Version < SHCROGL_SSM_VERSION_WITH_FIXED_STENCIL)
{
- SHCROGL_GET_STRUCT_PART(pTmpContext, CRContext, shared, attrib);
- rc = crStateLoadAttribState_v_BEFORE_CTXUSAGE_BITS(&pTmpContext->attrib, pSSM);
+ SHCROGL_GET_STRUCT_HEAD(pTmpContext, CRContext, attrib);
+ rc = crStateLoadAttribState_v_33(&pTmpContext->attrib, pSSM);
AssertRCReturn(rc, rc);
SHCROGL_CUT_FIELD_ALIGNMENT(CRContext, attrib, buffer);
- SHCROGL_GET_STRUCT_PART(pTmpContext, CRContext, buffer, texture);
- rc = crStateLoadTextureState_v_BEFORE_CTXUSAGE_BITS(&pTmpContext->texture, pSSM);
+ SHCROGL_GET_STRUCT_PART(pTmpContext, CRContext, buffer, point);
+ rc = crStateLoadStencilPoint_v_37(&pTmpContext->point, pSSM);
AssertRCReturn(rc, rc);
- SHCROGL_CUT_FIELD_ALIGNMENT(CRContext, texture, transform);
- SHCROGL_GET_STRUCT_TAIL(pTmpContext, CRContext, transform);
+ SHCROGL_GET_STRUCT_PART(pTmpContext, CRContext, polygon, stencil);
+ rc = crStateLoadStencilState_v_33(&pTmpContext->stencil, pSSM);
+ AssertRCReturn(rc, rc);
+ SHCROGL_CUT_FOR_OLD_TYPE_TO_ENSURE_ALIGNMENT(CRContext, stencil, CRStencilState_v_33, sizeof (void*));
+ SHCROGL_GET_STRUCT_TAIL(pTmpContext, CRContext, texture);
+ }
+ else if (u32Version < SHCROGL_SSM_VERSION_WITH_SPRITE_COORD_ORIGIN)
+ {
+ SHCROGL_GET_STRUCT_HEAD(pTmpContext, CRContext, point);
+ crStateLoadStencilPoint_v_37(&pTmpContext->point, pSSM);
+ SHCROGL_GET_STRUCT_TAIL(pTmpContext, CRContext, polygon);
}
else
{
- SHCROGL_GET_STRUCT_TAIL(pTmpContext, CRContext, shared);
+ rc = SSMR3GetMem(pSSM, pTmpContext, sizeof (*pTmpContext));
+ AssertRCReturn(rc, rc);
}
+ /* preserve the error to restore it at the end of context creation,
+ * it should not normally change, but just in case it it changed */
+ err = pTmpContext->error;
+
+ /* we will later do crMemcpy from entire pTmpContext to pContext,
+ * for simplicity store the VBOXTLSREFDATA from the pContext to pTmpContext */
+ VBOXTLSREFDATA_COPY(pTmpContext, pContext);
+
/* Deal with shared state */
{
crFindSharedCtxParms_t parms;
@@ -2018,6 +2233,13 @@ int32_t crStateLoadContext(CRContext *pContext, CRHashTable * pCtxTable, PFNCRST
{
/* Load shared textures */
CRASSERT(pContext->shared && pContext->shared->textureTable);
+
+ if (u32Version >= SHCROGL_SSM_VERSION_WITH_ALLOCATED_KEYS)
+ {
+ rc = crStateLoadKeys(pContext->shared->buffersTable, pSSM, u32Version);
+ AssertRCReturn(rc, rc);
+ }
+
rc = SSMR3GetU32(pSSM, &uiNumElems);
AssertRCReturn(rc, rc);
for (ui=0; ui<uiNumElems; ++ui)
@@ -2120,6 +2342,15 @@ int32_t crStateLoadContext(CRContext *pContext, CRHashTable * pCtxTable, PFNCRST
/* Load buffer objects */
#ifdef CR_ARB_vertex_buffer_object
+ if (bLoadShared)
+ {
+ if (u32Version >= SHCROGL_SSM_VERSION_WITH_ALLOCATED_KEYS)
+ {
+ rc = crStateLoadKeys(pContext->shared->textureTable, pSSM, u32Version);
+ AssertRCReturn(rc, rc);
+ }
+ }
+
rc = SSMR3GetU32(pSSM, &uiNumElems);
AssertRCReturn(rc, rc);
for (ui=0; ui<=uiNumElems; ++ui) /*ui<=uiNumElems to load nullBuffer in same loop*/
@@ -2242,6 +2473,12 @@ int32_t crStateLoadContext(CRContext *pContext, CRHashTable * pCtxTable, PFNCRST
/* Load FBOs */
if (bLoadShared)
{
+ if (u32Version >= SHCROGL_SSM_VERSION_WITH_ALLOCATED_KEYS)
+ {
+ rc = crStateLoadKeys(pContext->shared->fbTable, pSSM, u32Version);
+ AssertRCReturn(rc, rc);
+ }
+
rc = SSMR3GetU32(pSSM, &uiNumElems);
AssertRCReturn(rc, rc);
for (ui=0; ui<uiNumElems; ++ui)
@@ -2256,9 +2493,17 @@ int32_t crStateLoadContext(CRContext *pContext, CRHashTable * pCtxTable, PFNCRST
rc = crStateLoadFramebufferObject(pFBO, pSSM, u32Version);
AssertRCReturn(rc, rc);
+ Assert(key == pFBO->id);
+
crHashtableAdd(pContext->shared->fbTable, key, pFBO);
}
+ if (u32Version >= SHCROGL_SSM_VERSION_WITH_ALLOCATED_KEYS)
+ {
+ rc = crStateLoadKeys(pContext->shared->rbTable, pSSM, u32Version);
+ AssertRCReturn(rc, rc);
+ }
+
rc = SSMR3GetU32(pSSM, &uiNumElems);
AssertRCReturn(rc, rc);
for (ui=0; ui<uiNumElems; ++ui)
@@ -2304,7 +2549,10 @@ int32_t crStateLoadContext(CRContext *pContext, CRHashTable * pCtxTable, PFNCRST
for (ui=0; ui<uiNumElems; ++ui)
{
CRGLSLShader *pShader = crStateLoadGLSLShader(pSSM);
+ GLboolean fNewKeyCheck;
if (!pShader) return VERR_SSM_UNEXPECTED_DATA;
+ fNewKeyCheck = crHashtableAllocRegisterKey(pContext->glsl.programs, pShader->id);
+ CRASSERT(fNewKeyCheck);
crHashtableAdd(pContext->glsl.shaders, pShader->id, pShader);
}
@@ -2416,310 +2664,11 @@ int32_t crStateLoadContext(CRContext *pContext, CRHashTable * pCtxTable, PFNCRST
pContext->glsl.bResyncNeeded = GL_TRUE;
#endif
-
- /*Restore front/back buffer images*/
- if (pContext->buffer.storedWidth && pContext->buffer.storedHeight)
- {
- CRBufferState *pBuf = &pContext->buffer;
- GLint cbData;
- void *pData;
-
- cbData = crPixelSize(GL_RGBA, GL_UNSIGNED_BYTE) * pBuf->storedWidth * pBuf->storedHeight;
-
- pData = crAlloc(cbData);
- if (!pData)
- {
- pBuf->pFrontImg = NULL;
- pBuf->pBackImg = NULL;
- return VERR_NO_MEMORY;
- }
-
- rc = SSMR3GetMem(pSSM, pData, cbData);
- AssertRCReturn(rc, rc);
-
- pBuf->pFrontImg = pData;
-
- pData = crAlloc(cbData);
- if (!pData)
- {
- pBuf->pBackImg = NULL;
- return VERR_NO_MEMORY;
- }
-
- rc = SSMR3GetMem(pSSM, pData, cbData);
- AssertRCReturn(rc, rc);
-
- pBuf->pBackImg = pData;
- }
-
-
- /*Mark all as dirty to make sure we'd restore correct context state*/
+ if (pContext->error != err)
{
- CRStateBits *pBits = GetCurrentBits();
-
- FILLDIRTY(pBits->attrib.dirty);
-
- FILLDIRTY(pBits->buffer.dirty);
- FILLDIRTY(pBits->buffer.enable);
- FILLDIRTY(pBits->buffer.alphaFunc);
- FILLDIRTY(pBits->buffer.depthFunc);
- FILLDIRTY(pBits->buffer.blendFunc);
- FILLDIRTY(pBits->buffer.logicOp);
- FILLDIRTY(pBits->buffer.indexLogicOp);
- FILLDIRTY(pBits->buffer.drawBuffer);
- FILLDIRTY(pBits->buffer.readBuffer);
- FILLDIRTY(pBits->buffer.indexMask);
- FILLDIRTY(pBits->buffer.colorWriteMask);
- FILLDIRTY(pBits->buffer.clearColor);
- FILLDIRTY(pBits->buffer.clearIndex);
- FILLDIRTY(pBits->buffer.clearDepth);
- FILLDIRTY(pBits->buffer.clearAccum);
- FILLDIRTY(pBits->buffer.depthMask);
-#ifdef CR_EXT_blend_color
- FILLDIRTY(pBits->buffer.blendColor);
-#endif
-#if defined(CR_EXT_blend_minmax) || defined(CR_EXT_blend_subtract) || defined(CR_EXT_blend_logic_op)
- FILLDIRTY(pBits->buffer.blendEquation);
-#endif
-#if defined(CR_EXT_blend_func_separate)
- FILLDIRTY(pBits->buffer.blendFuncSeparate);
-#endif
-
-#ifdef CR_ARB_vertex_buffer_object
- FILLDIRTY(pBits->bufferobject.dirty);
- FILLDIRTY(pBits->bufferobject.arrayBinding);
- FILLDIRTY(pBits->bufferobject.elementsBinding);
-# ifdef CR_ARB_pixel_buffer_object
- FILLDIRTY(pBits->bufferobject.packBinding);
- FILLDIRTY(pBits->bufferobject.unpackBinding);
-# endif
-#endif
-
- FILLDIRTY(pBits->client.dirty);
- FILLDIRTY(pBits->client.pack);
- FILLDIRTY(pBits->client.unpack);
- FILLDIRTY(pBits->client.enableClientState);
- FILLDIRTY(pBits->client.clientPointer);
- FILLDIRTY(pBits->client.v);
- FILLDIRTY(pBits->client.n);
- FILLDIRTY(pBits->client.c);
- FILLDIRTY(pBits->client.i);
- FILLDIRTY(pBits->client.e);
- FILLDIRTY(pBits->client.s);
- FILLDIRTY(pBits->client.f);
- for (i=0; i<CR_MAX_TEXTURE_UNITS; i++)
- {
- FILLDIRTY(pBits->client.t[i]);
- }
-#ifdef CR_NV_vertex_program
- for (i=0; i<CR_MAX_VERTEX_ATTRIBS; i++)
- {
- FILLDIRTY(pBits->client.a[i]);
- }
-#endif
-
- FILLDIRTY(pBits->current.dirty);
- for (i=0; i<CR_MAX_VERTEX_ATTRIBS; i++)
- {
- FILLDIRTY(pBits->current.vertexAttrib[i]);
- }
- FILLDIRTY(pBits->current.edgeFlag);
- FILLDIRTY(pBits->current.colorIndex);
- FILLDIRTY(pBits->current.rasterPos);
-
-
- FILLDIRTY(pBits->eval.dirty);
- for (i=0; i<GLEVAL_TOT; i++)
- {
- FILLDIRTY(pBits->eval.eval1D[i]);
- FILLDIRTY(pBits->eval.eval2D[i]);
- FILLDIRTY(pBits->eval.enable1D[i]);
- FILLDIRTY(pBits->eval.enable2D[i]);
- }
- FILLDIRTY(pBits->eval.enable);
- FILLDIRTY(pBits->eval.grid1D);
- FILLDIRTY(pBits->eval.grid2D);
-#ifdef CR_NV_vertex_program
- /*@todo Those seems to be unused?
- FILLDIRTY(pBits->eval.enableAttrib1D);
- FILLDIRTY(pBits->eval.enableAttrib2D);
- */
-#endif
-
- FILLDIRTY(pBits->feedback.dirty);
- FILLDIRTY(pBits->selection.dirty);
-
- FILLDIRTY(pBits->fog.dirty);
- FILLDIRTY(pBits->fog.color);
- FILLDIRTY(pBits->fog.index);
- FILLDIRTY(pBits->fog.density);
- FILLDIRTY(pBits->fog.start);
- FILLDIRTY(pBits->fog.end);
- FILLDIRTY(pBits->fog.mode);
- FILLDIRTY(pBits->fog.enable);
-#ifdef CR_NV_fog_distance
- FILLDIRTY(pBits->fog.fogDistanceMode);
-#endif
-#ifdef CR_EXT_fog_coord
- FILLDIRTY(pBits->fog.fogCoordinateSource);
-#endif
-
- FILLDIRTY(pBits->hint.dirty);
- FILLDIRTY(pBits->hint.perspectiveCorrection);
- FILLDIRTY(pBits->hint.pointSmooth);
- FILLDIRTY(pBits->hint.lineSmooth);
- FILLDIRTY(pBits->hint.polygonSmooth);
- FILLDIRTY(pBits->hint.fog);
-#ifdef CR_EXT_clip_volume_hint
- FILLDIRTY(pBits->hint.clipVolumeClipping);
-
-#endif
-#ifdef CR_ARB_texture_compression
- FILLDIRTY(pBits->hint.textureCompression);
-#endif
-#ifdef CR_SGIS_generate_mipmap
- FILLDIRTY(pBits->hint.generateMipmap);
-#endif
-
- FILLDIRTY(pBits->lighting.dirty);
- FILLDIRTY(pBits->lighting.shadeModel);
- FILLDIRTY(pBits->lighting.colorMaterial);
- FILLDIRTY(pBits->lighting.lightModel);
- FILLDIRTY(pBits->lighting.material);
- FILLDIRTY(pBits->lighting.enable);
- for (i=0; i<CR_MAX_LIGHTS; ++i)
- {
- FILLDIRTY(pBits->lighting.light[i].dirty);
- FILLDIRTY(pBits->lighting.light[i].enable);
- FILLDIRTY(pBits->lighting.light[i].ambient);
- FILLDIRTY(pBits->lighting.light[i].diffuse);
- FILLDIRTY(pBits->lighting.light[i].specular);
- FILLDIRTY(pBits->lighting.light[i].position);
- FILLDIRTY(pBits->lighting.light[i].attenuation);
- FILLDIRTY(pBits->lighting.light[i].spot);
- }
-
- FILLDIRTY(pBits->line.dirty);
- FILLDIRTY(pBits->line.enable);
- FILLDIRTY(pBits->line.width);
- FILLDIRTY(pBits->line.stipple);
-
- FILLDIRTY(pBits->lists.dirty);
- FILLDIRTY(pBits->lists.base);
-
- FILLDIRTY(pBits->multisample.dirty);
- FILLDIRTY(pBits->multisample.enable);
- FILLDIRTY(pBits->multisample.sampleAlphaToCoverage);
- FILLDIRTY(pBits->multisample.sampleAlphaToOne);
- FILLDIRTY(pBits->multisample.sampleCoverage);
- FILLDIRTY(pBits->multisample.sampleCoverageValue);
-
-#if CR_ARB_occlusion_query
- FILLDIRTY(pBits->occlusion.dirty);
-#endif
-
- FILLDIRTY(pBits->pixel.dirty);
- FILLDIRTY(pBits->pixel.transfer);
- FILLDIRTY(pBits->pixel.zoom);
- FILLDIRTY(pBits->pixel.maps);
-
- FILLDIRTY(pBits->point.dirty);
- FILLDIRTY(pBits->point.enableSmooth);
- FILLDIRTY(pBits->point.size);
-#ifdef CR_ARB_point_parameters
- FILLDIRTY(pBits->point.minSize);
- FILLDIRTY(pBits->point.maxSize);
- FILLDIRTY(pBits->point.fadeThresholdSize);
- FILLDIRTY(pBits->point.distanceAttenuation);
-#endif
-#ifdef CR_ARB_point_sprite
- FILLDIRTY(pBits->point.enableSprite);
- for (i=0; i<CR_MAX_TEXTURE_UNITS; ++i)
- {
- FILLDIRTY(pBits->point.coordReplacement[i]);
- }
-#endif
-
- FILLDIRTY(pBits->polygon.dirty);
- FILLDIRTY(pBits->polygon.enable);
- FILLDIRTY(pBits->polygon.offset);
- FILLDIRTY(pBits->polygon.mode);
- FILLDIRTY(pBits->polygon.stipple);
-
- FILLDIRTY(pBits->program.dirty);
- FILLDIRTY(pBits->program.vpEnable);
- FILLDIRTY(pBits->program.fpEnable);
- FILLDIRTY(pBits->program.vpBinding);
- FILLDIRTY(pBits->program.fpBinding);
- for (i=0; i<CR_MAX_VERTEX_ATTRIBS; ++i)
- {
- FILLDIRTY(pBits->program.vertexAttribArrayEnable[i]);
- FILLDIRTY(pBits->program.map1AttribArrayEnable[i]);
- FILLDIRTY(pBits->program.map2AttribArrayEnable[i]);
- }
- for (i=0; i<CR_MAX_VERTEX_PROGRAM_ENV_PARAMS; ++i)
- {
- FILLDIRTY(pBits->program.vertexEnvParameter[i]);
- }
- for (i=0; i<CR_MAX_FRAGMENT_PROGRAM_ENV_PARAMS; ++i)
- {
- FILLDIRTY(pBits->program.fragmentEnvParameter[i]);
- }
- FILLDIRTY(pBits->program.vertexEnvParameters);
- FILLDIRTY(pBits->program.fragmentEnvParameters);
- for (i=0; i<CR_MAX_VERTEX_PROGRAM_ENV_PARAMS/4; ++i)
- {
- FILLDIRTY(pBits->program.trackMatrix[i]);
- }
-
- FILLDIRTY(pBits->regcombiner.dirty);
- FILLDIRTY(pBits->regcombiner.enable);
- FILLDIRTY(pBits->regcombiner.regCombinerVars);
- FILLDIRTY(pBits->regcombiner.regCombinerColor0);
- FILLDIRTY(pBits->regcombiner.regCombinerColor1);
- for (i=0; i<CR_MAX_GENERAL_COMBINERS; ++i)
- {
- FILLDIRTY(pBits->regcombiner.regCombinerStageColor0[i]);
- FILLDIRTY(pBits->regcombiner.regCombinerStageColor1[i]);
- FILLDIRTY(pBits->regcombiner.regCombinerInput[i]);
- FILLDIRTY(pBits->regcombiner.regCombinerOutput[i]);
- }
- FILLDIRTY(pBits->regcombiner.regCombinerFinalInput);
-
- FILLDIRTY(pBits->stencil.dirty);
- FILLDIRTY(pBits->stencil.enable);
- FILLDIRTY(pBits->stencil.func);
- FILLDIRTY(pBits->stencil.op);
- FILLDIRTY(pBits->stencil.clearValue);
- FILLDIRTY(pBits->stencil.writeMask);
-
- FILLDIRTY(pBits->texture.dirty);
- for (i=0; i<CR_MAX_TEXTURE_UNITS; ++i)
- {
- FILLDIRTY(pBits->texture.enable[i]);
- FILLDIRTY(pBits->texture.current[i]);
- FILLDIRTY(pBits->texture.objGen[i]);
- FILLDIRTY(pBits->texture.eyeGen[i]);
- FILLDIRTY(pBits->texture.genMode[i]);
- FILLDIRTY(pBits->texture.envBit[i]);
- }
-
- FILLDIRTY(pBits->transform.dirty);
- FILLDIRTY(pBits->transform.matrixMode);
- FILLDIRTY(pBits->transform.modelviewMatrix);
- FILLDIRTY(pBits->transform.projectionMatrix);
- FILLDIRTY(pBits->transform.colorMatrix);
- FILLDIRTY(pBits->transform.textureMatrix);
- FILLDIRTY(pBits->transform.programMatrix);
- FILLDIRTY(pBits->transform.clipPlane);
- FILLDIRTY(pBits->transform.enable);
- FILLDIRTY(pBits->transform.base);
-
- FILLDIRTY(pBits->viewport.dirty);
- FILLDIRTY(pBits->viewport.v_dims);
- FILLDIRTY(pBits->viewport.s_dims);
- FILLDIRTY(pBits->viewport.enable);
- FILLDIRTY(pBits->viewport.depth);
+ crWarning("context error state changed on context restore, was 0x%x, but became 0x%x, resetting to its original value",
+ err, pContext->error);
+ pContext->error = err;
}
return VINF_SUCCESS;
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_special b/src/VBox/GuestHost/OpenGL/state_tracker/state_special
index e0bcc305..dfdca2f1 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_special
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_special
@@ -157,6 +157,9 @@ GetIntegerv
GetError
StencilFunc
StencilOp
+StencilFuncSeparate
+StencilOpSeparate
+ActiveStencilFaceEXT
ClearStencil
StencilMask
Viewport
@@ -375,3 +378,7 @@ ValidateProgram
BindAttribLocation
GetUniformLocation
CopyTexImage2D
+GenFramebuffersEXT
+GenRenderbuffersEXT
+IsRenderbufferEXT
+IsFramebufferEXT
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_stencil.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_stencil.c
index e284b31a..d543e301 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_stencil.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_stencil.c
@@ -9,24 +9,74 @@
#include "state/cr_statetypes.h"
#include "state_internals.h"
+
+static GLint crStateStencilBufferGetIdxAndCount(CRStencilState *s, GLenum face, GLint *pIdx, GLint *pBitsIdx)
+{
+ switch (face)
+ {
+ case GL_FRONT_AND_BACK:
+ *pIdx = 0;
+ *pBitsIdx = CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK;
+ return 2;
+ case GL_FRONT:
+ *pIdx = CRSTATE_STENCIL_BUFFER_ID_FRONT;
+ *pBitsIdx = CRSTATE_STENCIL_BUFFER_REF_ID_FRONT;
+ return 1;
+ case GL_BACK:
+ *pIdx = CRSTATE_STENCIL_BUFFER_ID_BACK;
+ *pBitsIdx = CRSTATE_STENCIL_BUFFER_REF_ID_BACK;
+ return 1;
+ case 0:
+ if (!s->stencilTwoSideEXT || s->activeStencilFace == GL_FRONT)
+ {
+ /* both front and back */
+ *pIdx = 0;
+ *pBitsIdx = CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK;
+ return 2;
+ }
+ *pIdx = CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK;
+ *pBitsIdx = CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK;
+ return 1;
+ default:
+ crStateError(__LINE__,__FILE__,GL_INVALID_ENUM, "crStateStencilBufferGetIdxAndCount");
+ return 0;
+ }
+ crError("should never be here!");
+ return 0;
+}
+
+void crStateStencilBufferInit(CRStencilBufferState *s)
+{
+ s->func = GL_ALWAYS;
+ s->mask = 0xFFFFFFFF;
+ s->ref = 0;
+
+ s->fail = GL_KEEP;
+ s->passDepthFail = GL_KEEP;
+ s->passDepthPass = GL_KEEP;
+}
+
+static void crStateStencilBufferRefBitsInit(CRContext *ctx, CRStencilBufferRefBits *sb)
+{
+ RESET(sb->func, ctx->bitid);
+ RESET(sb->op, ctx->bitid);
+}
+
void crStateStencilInit(CRContext *ctx)
{
CRStencilState *s = &ctx->stencil;
CRStateBits *stateb = GetCurrentBits();
CRStencilBits *sb = &(stateb->stencil);
+ int i;
s->stencilTest = GL_FALSE;
RESET(sb->enable, ctx->bitid);
- s->func = GL_ALWAYS;
- s->mask = 0xFFFFFFFF;
- s->ref = 0;
- RESET(sb->func, ctx->bitid);
+ s->stencilTwoSideEXT = GL_FALSE;
+ RESET(sb->enableTwoSideEXT, ctx->bitid);
- s->fail = GL_KEEP;
- s->passDepthFail = GL_KEEP;
- s->passDepthPass = GL_KEEP;
- RESET(sb->op, ctx->bitid);
+ s->activeStencilFace = GL_FRONT;
+ RESET(sb->activeStencilFace, ctx->bitid);
s->clearValue = 0;
RESET(sb->clearValue, ctx->bitid);
@@ -35,53 +85,101 @@ void crStateStencilInit(CRContext *ctx)
RESET(sb->writeMask, ctx->bitid);
RESET(sb->dirty, ctx->bitid);
+
+ for (i = 0; i < CRSTATE_STENCIL_BUFFER_COUNT; ++i)
+ {
+ crStateStencilBufferInit(&s->buffers[i]);
+ }
+
+ for (i = 0; i < CRSTATE_STENCIL_BUFFER_REF_COUNT; ++i)
+ {
+ crStateStencilBufferRefBitsInit(ctx, &sb->bufferRefs[i]);
+ }
}
-void STATE_APIENTRY crStateStencilFunc(GLenum func, GLint ref, GLuint mask)
+static void crStateStencilBufferFunc(CRContext *g, CRStencilBufferState *s, GLenum func, GLint ref, GLuint mask)
{
- CRContext *g = GetCurrentContext();
- CRStencilState *s = &(g->stencil);
- CRStateBits *stateb = GetCurrentBits();
- CRStencilBits *sb = &(stateb->stencil);
+ s->func = func;
+ s->ref = ref;
+ s->mask = mask;
+}
+static void crStateStencilFuncPerform(GLenum face, GLenum func, GLint ref, GLuint mask)
+{
+ CRContext *g = GetCurrentContext();
+ CRStencilState *s = &(g->stencil);
+ CRStateBits *stateb = GetCurrentBits();
+ CRStencilBits *sb = &(stateb->stencil);
+ GLint idx, bitsIdx, count, i;
- if (g->current.inBeginEnd)
- {
- crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
- "glStencilFunc called in begin/end");
- return;
- }
- FLUSH();
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glStencilFunc called in begin/end");
+ return;
+ }
- if (func != GL_NEVER &&
- func != GL_LESS &&
- func != GL_LEQUAL &&
- func != GL_GREATER &&
- func != GL_GEQUAL &&
- func != GL_EQUAL &&
- func != GL_NOTEQUAL &&
- func != GL_ALWAYS)
- {
- crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
- "glStencilFunc called with bogu func: %d", func);
- return;
- }
+ FLUSH();
- s->func = func;
- s->ref = ref;
- s->mask = mask;
+ if (func != GL_NEVER &&
+ func != GL_LESS &&
+ func != GL_LEQUAL &&
+ func != GL_GREATER &&
+ func != GL_GEQUAL &&
+ func != GL_EQUAL &&
+ func != GL_NOTEQUAL &&
+ func != GL_ALWAYS)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glStencilFunc called with bogu func: %d", func);
+ return;
+ }
- DIRTY(sb->func, g->neg_bitid);
- DIRTY(sb->dirty, g->neg_bitid);
+ count = crStateStencilBufferGetIdxAndCount(s, face, &idx, &bitsIdx);
+ if (count)
+ {
+ for (i = idx; i < idx + count; ++i)
+ {
+ crStateStencilBufferFunc(g, &s->buffers[i], func, ref, mask);
+ }
+ DIRTY(sb->bufferRefs[bitsIdx].func, g->neg_bitid);
+
+ DIRTY(sb->dirty, g->neg_bitid);
+ }
+}
+
+void STATE_APIENTRY crStateStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
+{
+ if (!face)
+ {
+ /* crStateStencilFuncPerform accepts 0 value, while glStencilFuncSeparate does not,
+ * filter it out here */
+ crStateError(__LINE__,__FILE__,GL_INVALID_ENUM, "crStateStencilFuncSeparate");
+ return;
+ }
+ crStateStencilFuncPerform(face, func, ref, mask);
}
-void STATE_APIENTRY crStateStencilOp (GLenum fail, GLenum zfail, GLenum zpass)
+void STATE_APIENTRY crStateStencilFunc(GLenum func, GLint ref, GLuint mask)
+{
+ crStateStencilFuncPerform(0, func, ref, mask);
+}
+
+static void STATE_APIENTRY crStateStencilBufferOp (CRContext *g, CRStencilBufferState *s, GLenum fail, GLenum zfail, GLenum zpass)
+{
+ s->fail = fail;
+ s->passDepthFail = zfail;
+ s->passDepthPass = zpass;
+}
+
+static void crStateStencilOpPerform (GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
{
CRContext *g = GetCurrentContext();
CRStencilState *s = &(g->stencil);
CRStateBits *stateb = GetCurrentBits();
CRStencilBits *sb = &(stateb->stencil);
+ GLint idx, bitsIdx, count, i;
if (g->current.inBeginEnd)
{
@@ -146,14 +244,36 @@ void STATE_APIENTRY crStateStencilOp (GLenum fail, GLenum zfail, GLenum zpass)
return;
}
- s->fail = fail;
- s->passDepthFail = zfail;
- s->passDepthPass = zpass;
+ count = crStateStencilBufferGetIdxAndCount(s, face, &idx, &bitsIdx);
+ if (count)
+ {
+ for (i = idx; i < idx + count; ++i)
+ {
+ crStateStencilBufferOp(g, &s->buffers[i], fail, zfail, zpass);
+ }
- DIRTY(sb->op, g->neg_bitid);
- DIRTY(sb->dirty, g->neg_bitid);
+ DIRTY(sb->bufferRefs[bitsIdx].op, g->neg_bitid);
+
+ DIRTY(sb->dirty, g->neg_bitid);
+ }
}
+void STATE_APIENTRY crStateStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
+{
+ if (!face)
+ {
+ /* crStateStencilOpPerform accepts 0 value, while glStencilOpSeparate does not,
+ * filter it out here */
+ crStateError(__LINE__,__FILE__,GL_INVALID_ENUM, "crStateStencilOpSeparate");
+ return;
+ }
+ crStateStencilOpPerform (0, fail, zfail, zpass);
+}
+
+void STATE_APIENTRY crStateStencilOp (GLenum fail, GLenum zfail, GLenum zpass)
+{
+ crStateStencilOpPerform (0, fail, zfail, zpass);
+}
void STATE_APIENTRY crStateClearStencil (GLint c)
{
@@ -171,7 +291,6 @@ void STATE_APIENTRY crStateClearStencil (GLint c)
FLUSH();
-
s->clearValue = c;
DIRTY(sb->clearValue, g->neg_bitid);
@@ -199,3 +318,1129 @@ void STATE_APIENTRY crStateStencilMask (GLuint mask)
DIRTY(sb->writeMask, g->neg_bitid);
DIRTY(sb->dirty, g->neg_bitid);
}
+
+void STATE_APIENTRY crStateActiveStencilFaceEXT (GLenum face)
+{
+ CRContext *g = GetCurrentContext();
+ CRStencilState *s = &(g->stencil);
+ CRStateBits *stateb = GetCurrentBits();
+ CRStencilBits *sb = &(stateb->stencil);
+
+ switch (face)
+ {
+ case GL_FRONT:
+ case GL_BACK:
+ s->activeStencilFace = face;
+ break;
+ default:
+ crStateError(__LINE__,__FILE__,GL_INVALID_ENUM, "crStateActiveStencilFaceEXT");
+ return;
+ }
+
+ DIRTY(sb->activeStencilFace, g->neg_bitid);
+ DIRTY(sb->dirty, g->neg_bitid);
+}
+
+#ifdef CRSTATE_DEBUG_STENCIL_ERR
+#define CRSTATE_CLEARERR() do { \
+ while (diff_api.GetError() != GL_NO_ERROR) {} \
+ } while (0)
+
+#define CRSTATE_CHECKGLERR(_op) do {\
+ GLenum _glErr; \
+ CRSTATE_CLEARERR(); \
+ _op; \
+ while ((_glErr = diff_api.GetError()) != GL_NO_ERROR) { Assert(0);} \
+ }while (0)
+#else
+#define CRSTATE_CHECKGLERR(_op) do { _op; } while (0)
+#endif
+
+#define CR_STATE_STENCIL_FUNC_MATCH(_s1, _i1, _s2, _i2) (\
+ (_s1)->buffers[(_i1)].func == (_s2)->buffers[(_i2)].func && \
+ (_s1)->buffers[(_i1)].ref == (_s2)->buffers[(_i2)].ref && \
+ (_s1)->buffers[(_i1)].mask == (_s2)->buffers[(_i2)].mask)
+
+#define CR_STATE_STENCIL_FUNC_COPY(_s1, _i1, _s2, _i2) do { \
+ (_s1)->buffers[(_i1)].func = (_s2)->buffers[(_i2)].func; \
+ (_s1)->buffers[(_i1)].ref = (_s2)->buffers[(_i2)].ref; \
+ (_s1)->buffers[(_i1)].mask = (_s2)->buffers[(_i2)].mask; \
+ } while (0)
+
+
+#define CR_STATE_STENCIL_OP_MATCH(_s1, _i1, _s2, _i2) (\
+ (_s1)->buffers[(_i1)].fail == (_s2)->buffers[(_i2)].fail && \
+ (_s1)->buffers[(_i1)].passDepthFail == (_s2)->buffers[(_i2)].passDepthFail && \
+ (_s1)->buffers[(_i1)].passDepthPass == (_s2)->buffers[(_i2)].passDepthPass)
+
+#define CR_STATE_STENCIL_OP_COPY(_s1, _i1, _s2, _i2) do { \
+ (_s1)->buffers[(_i1)].fail = (_s2)->buffers[(_i2)].fail; \
+ (_s1)->buffers[(_i1)].passDepthFail = (_s2)->buffers[(_i2)].passDepthFail; \
+ (_s1)->buffers[(_i1)].passDepthPass = (_s2)->buffers[(_i2)].passDepthPass; \
+ } while (0)
+
+
+void crStateStencilDiff(CRStencilBits *b, CRbitvalue *bitID,
+ CRContext *fromCtx, CRContext *toCtx)
+{
+ CRStencilState *from = &(fromCtx->stencil);
+ CRStencilState *to = &(toCtx->stencil);
+ unsigned int j, i;
+ GLenum activeFace;
+ GLboolean backIsSet = GL_FALSE, frontIsSet = GL_FALSE, frontBackDirty, frontDirty, backDirty;
+ GLchar frontMatch = -1, backMatch = -1, toFrontBackMatch = -1;
+ CRbitvalue nbitID[CR_MAX_BITARRAY];
+ for (j=0;j<CR_MAX_BITARRAY;j++)
+ nbitID[j] = ~bitID[j];
+ i = 0; /* silence compiler */
+
+ if (CHECKDIRTY(b->enable, bitID))
+ {
+ glAble able[2];
+ able[0] = diff_api.Disable;
+ able[1] = diff_api.Enable;
+ if (from->stencilTest != to->stencilTest)
+ {
+ able[to->stencilTest](GL_STENCIL_TEST);
+ from->stencilTest = to->stencilTest;
+ }
+ CLEARDIRTY(b->enable, nbitID);
+ }
+
+ if (CHECKDIRTY(b->enableTwoSideEXT, bitID))
+ {
+ glAble able[2];
+ able[0] = diff_api.Disable;
+ able[1] = diff_api.Enable;
+ if (from->stencilTwoSideEXT != to->stencilTwoSideEXT)
+ {
+ able[to->stencilTwoSideEXT](GL_STENCIL_TEST_TWO_SIDE_EXT);
+ from->stencilTwoSideEXT = to->stencilTwoSideEXT;
+ }
+ CLEARDIRTY(b->enableTwoSideEXT, nbitID);
+ }
+
+ if (CHECKDIRTY(b->clearValue, bitID))
+ {
+ if (from->clearValue != to->clearValue)
+ {
+ diff_api.ClearStencil (to->clearValue);
+ from->clearValue = to->clearValue;
+ }
+ CLEARDIRTY(b->clearValue, nbitID);
+ }
+
+ activeFace = to->activeStencilFace;
+
+
+ /* func */
+ frontBackDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].func, bitID);
+ frontDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].func, bitID);
+ backDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].func, bitID);
+#define CR_STATE_STENCIL_FUNC_FRONT_MATCH() ( \
+ frontMatch >= 0 ? \
+ frontMatch \
+ : (frontMatch = CR_STATE_STENCIL_FUNC_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT)))
+
+#define CR_STATE_STENCIL_FUNC_BACK_MATCH() ( \
+ backMatch >= 0 ? \
+ backMatch \
+ : (backMatch = CR_STATE_STENCIL_FUNC_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK)))
+
+#define CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH() ( \
+ toFrontBackMatch >= 0 ? \
+ toFrontBackMatch \
+ : (toFrontBackMatch = CR_STATE_STENCIL_FUNC_MATCH(to, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_BACK)))
+
+ if (frontBackDirty)
+ {
+ if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH()
+ || !CR_STATE_STENCIL_FUNC_BACK_MATCH())
+ {
+ if (CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH())
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask);
+
+ CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
+ CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
+ frontIsSet = GL_TRUE;
+ backIsSet = GL_TRUE;
+ }
+ else if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH())
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ diff_api.StencilFuncSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask);
+
+ CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
+ frontIsSet = GL_TRUE;
+ }
+ else if (!CR_STATE_STENCIL_FUNC_BACK_MATCH())
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ diff_api.StencilFuncSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].mask);
+
+ CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK);
+
+ backIsSet = GL_TRUE;
+ }
+ }
+
+ CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].func, nbitID);
+ }
+
+ if (frontDirty)
+ {
+ if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH())
+ {
+ if (CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH())
+ {
+ if (!frontIsSet || !backIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask);
+
+ CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
+ CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
+
+ frontIsSet = GL_TRUE;
+ backIsSet = GL_TRUE;
+ }
+ }
+ else if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH())
+ {
+ if (!frontIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ diff_api.StencilFuncSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask);
+
+ CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
+ frontIsSet = GL_TRUE;
+ }
+ }
+ else if (!CR_STATE_STENCIL_FUNC_BACK_MATCH())
+ {
+ if (!backIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ diff_api.StencilFuncSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].mask);
+ CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK);
+ backIsSet = GL_TRUE;
+ }
+ }
+ }
+ CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].func, nbitID);
+ }
+
+
+ if (backDirty)
+ {
+ if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH())
+ {
+ if (CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH())
+ {
+ if (!frontIsSet || !backIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask);
+
+ CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
+ CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
+
+ frontIsSet = GL_TRUE;
+ backIsSet = GL_TRUE;
+ }
+ }
+ else if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH())
+ {
+ if (!frontIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ diff_api.StencilFuncSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask);
+
+ CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
+ frontIsSet = GL_TRUE;
+ }
+ }
+ else if (!CR_STATE_STENCIL_FUNC_BACK_MATCH())
+ {
+ if (!backIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ diff_api.StencilFuncSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].mask);
+ CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK);
+ backIsSet = GL_TRUE;
+ }
+ }
+ }
+ CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].func, nbitID);
+ }
+
+ if (CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].func, bitID))
+ {
+ if (!CR_STATE_STENCIL_FUNC_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK, to, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK))
+ {
+ if (activeFace == GL_FRONT)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_BACK);
+ activeFace = GL_BACK;
+ }
+
+ diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].mask);
+ CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK, to, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK);
+ }
+ CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].func, nbitID);
+ }
+
+#undef CR_STATE_STENCIL_FUNC_FRONT_MATCH
+#undef CR_STATE_STENCIL_FUNC_BACK_MATCH
+#undef CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH
+
+ /* op */
+ backIsSet = GL_FALSE, frontIsSet = GL_FALSE;
+ frontMatch = -1, backMatch = -1, toFrontBackMatch = -1;
+ frontBackDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].op, bitID);
+ frontDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].op, bitID);
+ backDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].op, bitID);
+
+#define CR_STATE_STENCIL_OP_FRONT_MATCH() ( \
+ frontMatch >= 0 ? \
+ frontMatch \
+ : (frontMatch = CR_STATE_STENCIL_OP_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT)))
+
+#define CR_STATE_STENCIL_OP_BACK_MATCH() ( \
+ backMatch >= 0 ? \
+ backMatch \
+ : (backMatch = CR_STATE_STENCIL_OP_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK)))
+
+#define CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH() ( \
+ toFrontBackMatch >= 0 ? \
+ toFrontBackMatch \
+ : (toFrontBackMatch = CR_STATE_STENCIL_OP_MATCH(to, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_BACK)))
+
+ if (frontBackDirty)
+ {
+ if (!CR_STATE_STENCIL_OP_FRONT_MATCH()
+ || !CR_STATE_STENCIL_OP_BACK_MATCH())
+ {
+ if (CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH())
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass);
+
+ CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
+ CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
+
+ frontIsSet = GL_TRUE;
+ backIsSet = GL_TRUE;
+ }
+ else if (!CR_STATE_STENCIL_OP_FRONT_MATCH())
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ diff_api.StencilOpSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass);
+ CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
+ frontIsSet = GL_TRUE;
+ }
+ else if (!CR_STATE_STENCIL_OP_BACK_MATCH())
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ diff_api.StencilOpSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthPass);
+ CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK);
+ backIsSet = GL_TRUE;
+ }
+ }
+
+ CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].op, nbitID);
+ }
+
+ if (frontDirty)
+ {
+ if (!CR_STATE_STENCIL_OP_FRONT_MATCH())
+ {
+ if (CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH())
+ {
+ if (!frontIsSet || !backIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass);
+
+ CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
+ CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
+
+ frontIsSet = GL_TRUE;
+ backIsSet = GL_TRUE;
+ }
+ }
+ else if (!CR_STATE_STENCIL_OP_FRONT_MATCH())
+ {
+ if (!frontIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ diff_api.StencilOpSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass);
+
+ CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
+
+ frontIsSet = GL_TRUE;
+ }
+ }
+ else if (!CR_STATE_STENCIL_OP_BACK_MATCH())
+ {
+ if (!backIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ diff_api.StencilOpSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthPass);
+ CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK);
+ backIsSet = GL_TRUE;
+ }
+ }
+ }
+ CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].op, nbitID);
+ }
+
+
+ if (backDirty)
+ {
+ if (!CR_STATE_STENCIL_OP_FRONT_MATCH())
+ {
+ if (CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH())
+ {
+ if (!frontIsSet || !backIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass);
+
+ CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
+ CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
+
+ frontIsSet = GL_TRUE;
+ backIsSet = GL_TRUE;
+ }
+ }
+ else if (!CR_STATE_STENCIL_OP_FRONT_MATCH())
+ {
+ if (!frontIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ diff_api.StencilOpSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass);
+
+ CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
+
+ frontIsSet = GL_TRUE;
+ }
+ }
+ else if (!CR_STATE_STENCIL_OP_BACK_MATCH())
+ {
+ if (!backIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ diff_api.StencilOpSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthPass);
+ CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK);
+ backIsSet = GL_TRUE;
+ }
+ }
+ }
+ CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].op, nbitID);
+ }
+
+ if (CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].op, bitID))
+ {
+ if (!CR_STATE_STENCIL_OP_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK, to, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK))
+ {
+ if (activeFace == GL_FRONT)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_BACK);
+ activeFace = GL_BACK;
+ }
+
+ diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].passDepthPass);
+ CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK, to, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK);
+ }
+ CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].op, nbitID);
+ }
+
+#undef CR_STATE_STENCIL_OP_FRONT_MATCH
+#undef CR_STATE_STENCIL_OP_BACK_MATCH
+#undef CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH
+
+
+ if (activeFace != to->activeStencilFace)
+ {
+ diff_api.ActiveStencilFaceEXT(activeFace);
+ }
+
+ if (CHECKDIRTY(b->activeStencilFace, bitID))
+ {
+ if (from->activeStencilFace != to->activeStencilFace)
+ {
+ /* we already did it ( see above )*/
+ /* diff_api.ActiveStencilFaceEXT(to->activeStencilFace); */
+ from->activeStencilFace = to->activeStencilFace;
+ }
+ CLEARDIRTY(b->activeStencilFace, nbitID);
+ }
+
+ if (CHECKDIRTY(b->writeMask, bitID))
+ {
+ if (from->writeMask != to->writeMask)
+ {
+ diff_api.StencilMask (to->writeMask);
+ from->writeMask = to->writeMask;
+ }
+ CLEARDIRTY(b->writeMask, nbitID);
+ }
+ CLEARDIRTY(b->dirty, nbitID);
+}
+
+void crStateStencilSwitch(CRStencilBits *b, CRbitvalue *bitID,
+ CRContext *fromCtx, CRContext *toCtx)
+{
+ CRStencilState *from = &(fromCtx->stencil);
+ CRStencilState *to = &(toCtx->stencil);
+ unsigned int j, i;
+ GLenum activeFace;
+ GLboolean backIsSet = GL_FALSE, frontIsSet = GL_FALSE, frontBackDirty, frontDirty, backDirty;
+ GLchar frontMatch = -1, backMatch = -1, toFrontBackMatch = -1;
+ CRbitvalue nbitID[CR_MAX_BITARRAY];
+ for (j=0;j<CR_MAX_BITARRAY;j++)
+ nbitID[j] = ~bitID[j];
+ i = 0; /* silence compiler */
+
+ if (CHECKDIRTY(b->enable, bitID))
+ {
+ glAble able[2];
+ able[0] = diff_api.Disable;
+ able[1] = diff_api.Enable;
+ if (from->stencilTest != to->stencilTest)
+ {
+ CRSTATE_CHECKGLERR(able[to->stencilTest](GL_STENCIL_TEST));
+ FILLDIRTY(b->enable);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->enable, nbitID);
+ }
+ if (CHECKDIRTY(b->enableTwoSideEXT, bitID))
+ {
+ glAble able[2];
+ able[0] = diff_api.Disable;
+ able[1] = diff_api.Enable;
+ if (from->stencilTwoSideEXT != to->stencilTwoSideEXT)
+ {
+ CRSTATE_CHECKGLERR(able[to->stencilTwoSideEXT](GL_STENCIL_TEST_TWO_SIDE_EXT));
+ FILLDIRTY(b->enableTwoSideEXT);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->enableTwoSideEXT, nbitID);
+ }
+ if (CHECKDIRTY(b->clearValue, bitID))
+ {
+ if (from->clearValue != to->clearValue)
+ {
+ CRSTATE_CHECKGLERR(diff_api.ClearStencil (to->clearValue));
+ FILLDIRTY(b->clearValue);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->clearValue, nbitID);
+ }
+
+ activeFace = from->activeStencilFace;
+
+ /* func */
+ frontBackDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].func, bitID);
+ frontDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].func, bitID);
+ backDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].func, bitID);
+#define CR_STATE_STENCIL_FUNC_FRONT_MATCH() ( \
+ frontMatch >= 0 ? \
+ frontMatch \
+ : (frontMatch = CR_STATE_STENCIL_FUNC_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT)))
+
+#define CR_STATE_STENCIL_FUNC_BACK_MATCH() ( \
+ backMatch >= 0 ? \
+ backMatch \
+ : (backMatch = CR_STATE_STENCIL_FUNC_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK)))
+
+#define CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH() ( \
+ toFrontBackMatch >= 0 ? \
+ toFrontBackMatch \
+ : (toFrontBackMatch = CR_STATE_STENCIL_FUNC_MATCH(to, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_BACK)))
+
+ if (frontBackDirty)
+ {
+ if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH()
+ || !CR_STATE_STENCIL_FUNC_BACK_MATCH())
+ {
+ if (CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH())
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask));
+
+ frontIsSet = GL_TRUE;
+ backIsSet = GL_TRUE;
+ }
+ else if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH())
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilFuncSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask));
+ frontIsSet = GL_TRUE;
+ }
+ else if (!CR_STATE_STENCIL_FUNC_BACK_MATCH())
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilFuncSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].mask));
+ backIsSet = GL_TRUE;
+ }
+ FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].func);
+ FILLDIRTY(b->dirty);
+ }
+
+ CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].func, nbitID);
+ }
+
+ if (frontDirty)
+ {
+ if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH())
+ {
+ if (CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH())
+ {
+ if (!frontIsSet || !backIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask));
+
+ frontIsSet = GL_TRUE;
+ backIsSet = GL_TRUE;
+ }
+ }
+ else if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH())
+ {
+ if (!frontIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilFuncSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask));
+ frontIsSet = GL_TRUE;
+ }
+ }
+ else if (!CR_STATE_STENCIL_FUNC_BACK_MATCH())
+ {
+ if (!backIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilFuncSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].mask));
+ backIsSet = GL_TRUE;
+ }
+ }
+ FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].func);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].func, nbitID);
+ }
+
+
+ if (backDirty)
+ {
+ if (!CR_STATE_STENCIL_FUNC_BACK_MATCH())
+ {
+ if (CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH())
+ {
+ if (!frontIsSet || !backIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask));
+
+ frontIsSet = GL_TRUE;
+ backIsSet = GL_TRUE;
+ }
+ }
+ else if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH())
+ {
+ if (!frontIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilFuncSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask));
+ frontIsSet = GL_TRUE;
+ }
+ }
+ else if (!CR_STATE_STENCIL_FUNC_BACK_MATCH())
+ {
+ if (!backIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilFuncSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].mask));
+ backIsSet = GL_TRUE;
+ }
+ }
+ FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].func);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].func, nbitID);
+ }
+
+ if (CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].func, bitID))
+ {
+ if (!CR_STATE_STENCIL_FUNC_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK, to, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK))
+ {
+ if (activeFace == GL_FRONT)
+ {
+ CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_BACK));
+ activeFace = GL_BACK;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].mask));
+
+ FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].func);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].func, nbitID);
+ }
+
+#undef CR_STATE_STENCIL_FUNC_FRONT_MATCH
+#undef CR_STATE_STENCIL_FUNC_BACK_MATCH
+#undef CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH
+
+ /* op */
+ backIsSet = GL_FALSE, frontIsSet = GL_FALSE;
+ frontMatch = -1, backMatch = -1, toFrontBackMatch = -1;
+ frontBackDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].op, bitID);
+ frontDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].op, bitID);
+ backDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].op, bitID);
+
+#define CR_STATE_STENCIL_OP_FRONT_MATCH() ( \
+ frontMatch >= 0 ? \
+ frontMatch \
+ : (frontMatch = CR_STATE_STENCIL_OP_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT)))
+
+#define CR_STATE_STENCIL_OP_BACK_MATCH() ( \
+ backMatch >= 0 ? \
+ backMatch \
+ : (backMatch = CR_STATE_STENCIL_OP_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK)))
+
+#define CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH() ( \
+ toFrontBackMatch >= 0 ? \
+ toFrontBackMatch \
+ : (toFrontBackMatch = CR_STATE_STENCIL_OP_MATCH(to, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_BACK)))
+
+ if (frontBackDirty)
+ {
+ if (!CR_STATE_STENCIL_OP_FRONT_MATCH()
+ || !CR_STATE_STENCIL_OP_BACK_MATCH())
+ {
+ if (CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH())
+ {
+ if (activeFace == GL_BACK)
+ {
+ CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_FRONT));
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass));
+
+ frontIsSet = GL_TRUE;
+ backIsSet = GL_TRUE;
+ }
+ else if (!CR_STATE_STENCIL_OP_FRONT_MATCH())
+ {
+ if (activeFace == GL_BACK)
+ {
+ CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_FRONT));
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilOpSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass));
+ frontIsSet = GL_TRUE;
+ }
+ else if (!CR_STATE_STENCIL_OP_BACK_MATCH())
+ {
+ if (activeFace == GL_BACK)
+ {
+ CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_FRONT));
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilOpSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthPass));
+ backIsSet = GL_TRUE;
+ }
+ FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].op);
+ FILLDIRTY(b->dirty);
+ }
+
+ CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].op, nbitID);
+ }
+
+ if (frontDirty)
+ {
+ if (!CR_STATE_STENCIL_OP_FRONT_MATCH())
+ {
+ if (CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH())
+ {
+ if (!frontIsSet || !backIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_FRONT));
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass));
+
+ frontIsSet = GL_TRUE;
+ backIsSet = GL_TRUE;
+ }
+ }
+ else if (!CR_STATE_STENCIL_OP_FRONT_MATCH())
+ {
+ if (!frontIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_FRONT));
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilOpSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass));
+ frontIsSet = GL_TRUE;
+ }
+ }
+ else if (!CR_STATE_STENCIL_OP_BACK_MATCH())
+ {
+ if (!backIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_FRONT));
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilOpSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthPass));
+ backIsSet = GL_TRUE;
+ }
+ }
+
+ FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].op);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].op, nbitID);
+ }
+
+
+ if (backDirty)
+ {
+ if (!CR_STATE_STENCIL_OP_BACK_MATCH())
+ {
+ if (CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH())
+ {
+ if (!frontIsSet || !backIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_FRONT));
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass));
+
+ frontIsSet = GL_TRUE;
+ backIsSet = GL_TRUE;
+ }
+ }
+ else if (!CR_STATE_STENCIL_OP_FRONT_MATCH())
+ {
+ if (!frontIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_FRONT));
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilOpSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass));
+ frontIsSet = GL_TRUE;
+ }
+ }
+ else if (!CR_STATE_STENCIL_OP_BACK_MATCH())
+ {
+ if (!backIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_FRONT));
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilOpSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthPass));
+ backIsSet = GL_TRUE;
+ }
+ }
+
+ FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].op);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].op, nbitID);
+ }
+
+ if (CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].op, bitID))
+ {
+ if (!CR_STATE_STENCIL_OP_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK, to, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK))
+ {
+ if (activeFace == GL_FRONT)
+ {
+ CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_BACK));
+ activeFace = GL_BACK;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].passDepthPass));
+
+ FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].op);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].op, nbitID);
+ }
+
+#undef CR_STATE_STENCIL_OP_FRONT_MATCH
+#undef CR_STATE_STENCIL_OP_BACK_MATCH
+#undef CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH
+
+ if (activeFace != to->activeStencilFace)
+ {
+ CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(activeFace));
+ }
+
+ if (CHECKDIRTY(b->activeStencilFace, bitID))
+ {
+ if (from->activeStencilFace != to->activeStencilFace)
+ {
+ /* we already did it ( see above )*/
+ /* diff_api.ActiveStencilFaceEXT(to->activeStencilFace); */
+ FILLDIRTY(b->activeStencilFace);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->activeStencilFace, nbitID);
+ }
+
+ if (CHECKDIRTY(b->writeMask, bitID))
+ {
+ if (from->writeMask != to->writeMask)
+ {
+ CRSTATE_CHECKGLERR(diff_api.StencilMask (to->writeMask));
+ FILLDIRTY(b->writeMask);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->writeMask, nbitID);
+ }
+
+ CLEARDIRTY(b->dirty, nbitID);
+}
+
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_texdiff.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_texdiff.c
index 00adbfff..5ac9028a 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_texdiff.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_texdiff.c
@@ -603,6 +603,10 @@ crStateTextureObjectDiff(CRContext *fromCtx,
CRTextureState *from = &(fromCtx->texture);
glAble able[2];
int u = 0; /* always use texture unit 0 for diff'ing */
+ GLuint hwid = crStateGetTextureObjHWID(tobj);
+
+ if (!hwid)
+ return;
able[0] = diff_api.Disable;
able[1] = diff_api.Enable;
@@ -619,7 +623,7 @@ crStateTextureObjectDiff(CRContext *fromCtx,
}
#endif
- diff_api.BindTexture(tobj->target, crStateGetTextureObjHWID(tobj));
+ diff_api.BindTexture(tobj->target, hwid);
if (alwaysDirty || CHECKDIRTY(tobj->paramsBit[u], bitID))
{
@@ -1448,7 +1452,7 @@ crStateDiffAllTextureObjects( CRContext *g, CRbitvalue *bitID, GLboolean bForceU
#endif
/* restore bindings */
- diff_api.ActiveTextureARB(GL_TEXTURE0_ARB + origUnit);
+ /* first restore unit 0 bindings the unit 0 is active currently */
diff_api.BindTexture(GL_TEXTURE_1D, orig1D);
diff_api.BindTexture(GL_TEXTURE_2D, orig2D);
diff_api.BindTexture(GL_TEXTURE_3D, orig3D);
@@ -1458,4 +1462,6 @@ crStateDiffAllTextureObjects( CRContext *g, CRbitvalue *bitID, GLboolean bForceU
#ifdef CR_NV_texture_rectangle
diff_api.BindTexture(GL_TEXTURE_RECTANGLE_NV, origRect);
#endif
+ /* now restore the proper active unit */
+ diff_api.ActiveTextureARB(GL_TEXTURE0_ARB + origUnit);
}
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_teximage.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_teximage.c
index 6917197b..41d96125 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_teximage.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_teximage.c
@@ -245,7 +245,7 @@ crStateGetTextureObjectAndImage(CRContext *g, GLenum texTarget, GLint level,
return;
default:
/* fall-through */
- ;
+ ;
}
#ifdef CR_NV_texture_rectangle
@@ -308,6 +308,7 @@ crStateGetTextureObjectAndImage(CRContext *g, GLenum texTarget, GLint level,
}
#endif
+ crWarning("unexpected texTarget 0x%x", texTarget);
*obj = NULL;
*img = NULL;
}
@@ -971,6 +972,13 @@ crStateTexSubImage1D(GLenum target, GLint level, GLint xoffset,
return; /* GL error state already set */
}
+#ifdef DEBUG_misha
+ CRASSERT(tl->bytes);
+ CRASSERT(tl->height);
+ CRASSERT(tl->width);
+ CRASSERT(tl->depth);
+#endif
+
#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
xoffset += tl->border;
@@ -1024,6 +1032,13 @@ crStateTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
CRASSERT(tobj);
CRASSERT(tl);
+#ifdef DEBUG_misha
+ CRASSERT(tl->bytes);
+ CRASSERT(tl->height);
+ CRASSERT(tl->width);
+ CRASSERT(tl->depth);
+#endif
+
#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
xoffset += tl->border;
yoffset += tl->border;
@@ -1109,6 +1124,14 @@ crStateTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
return; /* GL error state already set */
}
+#ifdef DEBUG_misha
+ CRASSERT(target == GL_TEXTURE_3D);
+ CRASSERT(tl->bytes);
+ CRASSERT(tl->height);
+ CRASSERT(tl->width);
+ CRASSERT(tl->depth);
+#endif
+
#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
xoffset += tl->border;
yoffset += tl->border;
@@ -1416,6 +1439,14 @@ crStateCompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
return; /* GL error state already set */
}
+#ifdef DEBUG_misha
+ CRASSERT(target == GL_TEXTURE_1D);
+ CRASSERT(tl->bytes);
+ CRASSERT(tl->height);
+ CRASSERT(tl->width);
+ CRASSERT(tl->depth);
+#endif
+
#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
xoffset += tl->border;
@@ -1456,11 +1487,19 @@ crStateCompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
CRStateBits *sb = GetCurrentBits();
CRTextureBits *tb = &(sb->texture);
CRTextureUnit *unit = t->unit + t->curTextureUnit;
- CRTextureObj *tobj = unit->currentTexture1D;
+ CRTextureObj *tobj = unit->currentTexture2D;
CRTextureLevel *tl = tobj->level[0] + level;
FLUSH();
+#ifdef DEBUG_misha
+ CRASSERT(target == GL_TEXTURE_2D);
+ CRASSERT(tl->bytes);
+ CRASSERT(tl->height);
+ CRASSERT(tl->width);
+ CRASSERT(tl->depth);
+#endif
+
if (ErrorCheckTexSubImage(2, target, level, xoffset, yoffset, 0,
width, height, 1)) {
return; /* GL error state already set */
@@ -1510,11 +1549,19 @@ crStateCompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
CRStateBits *sb = GetCurrentBits();
CRTextureBits *tb = &(sb->texture);
CRTextureUnit *unit = t->unit + t->curTextureUnit;
- CRTextureObj *tobj = unit->currentTexture1D;
+ CRTextureObj *tobj = unit->currentTexture3D;
CRTextureLevel *tl = tobj->level[0] + level;
FLUSH();
+#ifdef DEBUG_misha
+ CRASSERT(target == GL_TEXTURE_3D);
+ CRASSERT(tl->bytes);
+ CRASSERT(tl->height);
+ CRASSERT(tl->width);
+ CRASSERT(tl->depth);
+#endif
+
if (ErrorCheckTexSubImage(3, target, level, xoffset, yoffset, zoffset,
width, height, depth)) {
return; /* GL error state already set */
@@ -1580,6 +1627,13 @@ crStateGetCompressedTexImageARB(GLenum target, GLint level, GLvoid * img)
return;
}
+#ifdef DEBUG_misha
+ CRASSERT(tl->bytes);
+ CRASSERT(tl->height);
+ CRASSERT(tl->width);
+ CRASSERT(tl->depth);
+#endif
+
#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
crMemcpy(img, tl->img, tl->bytes);
#else
@@ -1616,6 +1670,13 @@ crStateGetTexImage(GLenum target, GLint level, GLenum format,
return;
}
+#ifdef DEBUG_misha
+ CRASSERT(tl->bytes);
+ CRASSERT(tl->height);
+ CRASSERT(tl->width);
+ CRASSERT(tl->depth);
+#endif
+
switch (format)
{
case GL_RED:
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_texture.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_texture.c
index 951a0e55..5da27393 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_texture.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_texture.c
@@ -250,10 +250,8 @@ crStateTextureInitTextureObj(CRContext *ctx, CRTextureObj *tobj,
RESET(tobj->paramsBit[i], ctx->bitid);
}
-#ifndef IN_GUEST
CR_STATE_SHAREDOBJ_USAGE_INIT(tobj);
CR_STATE_SHAREDOBJ_USAGE_SET(tobj, ctx);
-#endif
}
@@ -620,9 +618,29 @@ crStateDeleteTextureObject(CRTextureObj *tobj)
crFree(tobj);
}
-void STATE_APIENTRY crStateGenTextures(GLsizei n, GLuint *textures)
+void crStateRegNames(CRContext *g, CRHashTable *table, GLsizei n, GLuint *names)
+{
+ GLint i;
+ for (i = 0; i < n; i++)
+ {
+ if (names[i])
+ {
+ GLboolean isNewKey = crHashtableAllocRegisterKey(table, names[i]);
+ CRASSERT(isNewKey);
+ }
+ else
+ crWarning("RegNames: requested to register a null name");
+ }
+}
+
+void crStateRegTextures(GLsizei n, GLuint *names)
{
CRContext *g = GetCurrentContext();
+ crStateRegNames(g, g->shared->textureTable, n, names);
+}
+
+void crStateGenNames(CRContext *g, CRHashTable *table, GLsizei n, GLuint *names)
+{
GLint start;
FLUSH();
@@ -630,23 +648,23 @@ void STATE_APIENTRY crStateGenTextures(GLsizei n, GLuint *textures)
if (g->current.inBeginEnd)
{
crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
- "glGenTextures called in Begin/End");
+ "crStateGenNames called in Begin/End");
return;
}
if (n < 0)
{
crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
- "Negative n passed to glGenTextures: %d", n);
+ "Negative n passed to crStateGenNames: %d", n);
return;
}
- start = crHashtableAllocKeys(g->shared->textureTable, n);
+ start = crHashtableAllocKeys(table, n);
if (start)
{
GLint i;
for (i = 0; i < n; i++)
- textures[i] = (GLuint) (start + i);
+ names[i] = (GLuint) (start + i);
}
else
{
@@ -654,6 +672,12 @@ void STATE_APIENTRY crStateGenTextures(GLsizei n, GLuint *textures)
}
}
+void STATE_APIENTRY crStateGenTextures(GLsizei n, GLuint *textures)
+{
+ CRContext *g = GetCurrentContext();
+ crStateGenNames(g, g->shared->textureTable, n, textures);
+}
+
static void crStateTextureCheckFBOAPs(GLenum target, GLuint texture)
{
GLuint u;
@@ -730,6 +754,7 @@ static void crStateCleanupTextureRefs(CRContext *g, CRTextureObj *tObj)
#endif
}
+ CR_STATE_SHAREDOBJ_USAGE_CLEAR(tObj, g);
}
void STATE_APIENTRY crStateDeleteTextures(GLsizei n, const GLuint *textures)
@@ -760,15 +785,39 @@ void STATE_APIENTRY crStateDeleteTextures(GLsizei n, const GLuint *textures)
{
GLuint name = textures[i];
CRTextureObj *tObj;
+ if (!name)
+ continue;
+
GET_TOBJ(tObj, g, name);
- if (name && tObj)
+ if (tObj)
{
+ GLuint j;
+
crStateCleanupTextureRefs(g, tObj);
+ CR_STATE_SHAREDOBJ_USAGE_FOREACH_USED_IDX(tObj, j)
+ {
+ /* saved state version <= SHCROGL_SSM_VERSION_BEFORE_CTXUSAGE_BITS does not have usage bits info,
+ * so on restore, we set mark bits as used.
+ * This is why g_pAvailableContexts[j] could be NULL
+ * also g_pAvailableContexts[0] will hold default context, which we should discard */
+ CRContext *ctx = g_pAvailableContexts[j];
+ if (j && ctx)
+ crStateCleanupTextureRefs(ctx, tObj);
+ else
+ CR_STATE_SHAREDOBJ_USAGE_CLEAR_IDX(tObj, j);
+ }
+
/* on the host side, ogl texture object is deleted by a separate cr_server.head_spu->dispatch_table.DeleteTextures(n, newTextures);
* in crServerDispatchDeleteTextures, we just delete a state object here, which crStateDeleteTextureObject does */
crHashtableDelete(g->shared->textureTable, name, (CRHashtableCallback)crStateDeleteTextureObject);
}
+ else
+ {
+ /* call crHashtableDelete in any way, to ensure the allocated key is freed */
+ Assert(crHashtableIsKeyUsed(g->shared->textureTable, name));
+ crHashtableDelete(g->shared->textureTable, name, NULL);
+ }
}
DIRTY(tb->dirty, g->neg_bitid);
@@ -858,8 +907,17 @@ DECLEXPORT(void) crStateSetTextureUsed(GLuint texture, GLboolean used)
GET_TOBJ(tobj, g, texture);
if (!tobj)
{
- crWarning("crStateSetTextureUsed: failed to fined a HW name for texture(%d)!", texture);
- return;
+#ifdef IN_GUEST
+ if (used)
+ {
+ tobj = crStateTextureAllocate_t(g, texture);
+ }
+ else
+#endif
+ {
+ crWarning("crStateSetTextureUsed: failed to fined a HW name for texture(%d)!", texture);
+ return;
+ }
}
if (used)
@@ -870,8 +928,6 @@ DECLEXPORT(void) crStateSetTextureUsed(GLuint texture, GLboolean used)
CRTextureBits *tb = &(sb->texture);
CRTextureState *t = &(g->texture);
- CR_STATE_SHAREDOBJ_USAGE_CLEAR(tobj, g);
-
crStateCleanupTextureRefs(g, tobj);
if (!CR_STATE_SHAREDOBJ_USAGE_IS_USED(tobj))
@@ -953,12 +1009,11 @@ void STATE_APIENTRY crStateBindTexture(GLenum target, GLuint texture)
GET_TOBJ(tobj, g, texture);
if (!tobj)
{
+ Assert(crHashtableIsKeyUsed(g->shared->textureTable, texture));
tobj = crStateTextureAllocate_t(g, texture);
}
-#ifndef IN_GUEST
CR_STATE_SHAREDOBJ_USAGE_SET(tobj, g);
-#endif
/* Check the targets */
if (tobj->target == GL_NONE)
@@ -3204,10 +3259,28 @@ void STATE_APIENTRY
crStatePrioritizeTextures(GLsizei n, const GLuint *textures,
const GLclampf *priorities)
{
- UNUSED(n);
- UNUSED(textures);
+ CRContext *g = GetCurrentContext();
+ CRTextureObj *tobj;
+ GLsizei i;
UNUSED(priorities);
- /* TODO: */
+
+ for (i = 0; i < n; ++i)
+ {
+ GLuint tex = textures[i];
+ GET_TOBJ(tobj, g, tex);
+ if (!tobj)
+ {
+ Assert(crHashtableIsKeyUsed(g->shared->textureTable, tex));
+ tobj = crStateTextureAllocate_t(g, tex);
+ }
+
+ /* so far the code just ensures the tex object is created to make
+ * the crserverlib code be able to pass it to host ogl */
+
+ /* TODO: store texture priorities in the state data to be able to restore it properly
+ * on save state load */
+ }
+
return;
}
@@ -3259,7 +3332,9 @@ DECLEXPORT(GLuint) STATE_APIENTRY crStateTextureHWIDtoID(GLuint hwid)
DECLEXPORT(GLuint) STATE_APIENTRY crStateGetTextureHWID(GLuint id)
{
CRContext *g = GetCurrentContext();
- CRTextureObj *tobj = GET_TOBJ(tobj, g, id);
+ CRTextureObj *tobj;
+
+ GET_TOBJ(tobj, g, id);
#ifdef DEBUG_misha
if (id)
diff --git a/src/VBox/GuestHost/OpenGL/util/blitter.cpp b/src/VBox/GuestHost/OpenGL/util/blitter.cpp
new file mode 100644
index 00000000..a14c0916
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/util/blitter.cpp
@@ -0,0 +1,1751 @@
+/* $Id$ */
+
+/** @file
+ * Blitter API implementation
+ */
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+#include "cr_blitter.h"
+#include "cr_spu.h"
+#include "chromium.h"
+#include "cr_error.h"
+#include "cr_net.h"
+#include "cr_rand.h"
+#include "cr_mem.h"
+#include "cr_string.h"
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/mem.h>
+
+/* @param pCtxBase - contains the blitter context info. Its value is treated differently depending on the fCreateNewCtx value
+ * @param fCreateNewCtx - if true - the pCtxBase must NOT be NULL. its visualBits is used as a visual bits info for the new context,
+ * its id field is used to specified the shared context id to be used for blitter context.
+ * The id can be null to specify no shared context is needed
+ * if false - if pCtxBase is NOT null AND its id field is NOT null -
+ * specified the blitter context to be used
+ * blitter treats it as if it has default ogl state.
+ * otherwise -
+ * the blitter works in a "no-context" mode, i.e. a caller is responsible
+ * to making a proper context current before calling the blitter.
+ * Note that BltEnter/Leave MUST still be called, but the proper context
+ * must be set before doing BltEnter, and ResoreContext info is ignored in that case.
+ * Also note that blitter caches the current window info, and assumes the current context's values are preserved
+ * wrt that window before the calls, so if one uses different contexts for one blitter,
+ * the blitter current window values must be explicitly reset by doing CrBltMuralSetCurrentInfo(pBlitter, NULL)
+ * @param fForceDrawBlt - if true - forces the blitter to always use glDrawXxx-based blits even if GL_EXT_framebuffer_blit.
+ * This is needed because BlitFramebufferEXT is known to be often buggy, and glDrawXxx-based blits appear to be more reliable
+ */
+VBOXBLITTERDECL(int) CrBltInit(PCR_BLITTER pBlitter, const CR_BLITTER_CONTEXT *pCtxBase, bool fCreateNewCtx, bool fForceDrawBlt, const CR_GLSL_CACHE *pShaders, SPUDispatchTable *pDispatch)
+{
+ if (pCtxBase && pCtxBase->Base.id < 0)
+ {
+ crWarning("Default share context not initialized!");
+ return VERR_INVALID_PARAMETER;
+ }
+
+ if (!pCtxBase && fCreateNewCtx)
+ {
+ crWarning("pCtxBase is zero while fCreateNewCtx is set!");
+ return VERR_INVALID_PARAMETER;
+ }
+
+ memset(pBlitter, 0, sizeof (*pBlitter));
+
+ pBlitter->pDispatch = pDispatch;
+ if (pCtxBase)
+ pBlitter->CtxInfo = *pCtxBase;
+
+ pBlitter->Flags.ForceDrawBlit = fForceDrawBlt;
+
+ if (fCreateNewCtx)
+ {
+ pBlitter->CtxInfo.Base.id = pDispatch->CreateContext("", pCtxBase->Base.visualBits, pCtxBase->Base.id);
+ if (!pBlitter->CtxInfo.Base.id)
+ {
+ memset(pBlitter, 0, sizeof (*pBlitter));
+ crWarning("CreateContext failed!");
+ return VERR_GENERAL_FAILURE;
+ }
+ pBlitter->Flags.CtxCreated = 1;
+ }
+
+ if (pShaders)
+ {
+ pBlitter->pGlslCache = pShaders;
+ pBlitter->Flags.ShadersGloal = 1;
+ }
+ else
+ {
+ CrGlslInit(&pBlitter->LocalGlslCache, pDispatch);
+ pBlitter->pGlslCache = &pBlitter->LocalGlslCache;
+ }
+
+ return VINF_SUCCESS;
+}
+
+VBOXBLITTERDECL(int) CrBltCleanup(PCR_BLITTER pBlitter)
+{
+ if (CrBltIsEntered(pBlitter))
+ {
+ WARN(("CrBltBlitTexTex: blitter is entered"));
+ return VERR_INVALID_STATE;
+ }
+
+ if (pBlitter->Flags.ShadersGloal || !CrGlslNeedsCleanup(&pBlitter->LocalGlslCache))
+ return VINF_SUCCESS;
+
+ int rc = CrBltEnter(pBlitter);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("CrBltEnter failed, rc %d", rc));
+ return rc;
+ }
+
+ CrGlslCleanup(&pBlitter->LocalGlslCache);
+
+ CrBltLeave(pBlitter);
+
+ return VINF_SUCCESS;
+}
+
+void CrBltTerm(PCR_BLITTER pBlitter)
+{
+ if (pBlitter->Flags.CtxCreated)
+ pBlitter->pDispatch->DestroyContext(pBlitter->CtxInfo.Base.id);
+ memset(pBlitter, 0, sizeof (*pBlitter));
+}
+
+int CrBltMuralSetCurrentInfo(PCR_BLITTER pBlitter, const CR_BLITTER_WINDOW *pMural)
+{
+ if (pMural)
+ {
+ if (!memcmp(&pBlitter->CurrentMural, pMural, sizeof (pBlitter->CurrentMural)))
+ return VINF_SUCCESS;
+ memcpy(&pBlitter->CurrentMural, pMural, sizeof (pBlitter->CurrentMural));
+ }
+ else
+ {
+ if (CrBltIsEntered(pBlitter))
+ {
+ WARN(("can not set null mural for entered bleater"));
+ return VERR_INVALID_STATE;
+ }
+ if (!pBlitter->CurrentMural.Base.id)
+ return VINF_SUCCESS;
+ pBlitter->CurrentMural.Base.id = 0;
+ }
+
+ pBlitter->Flags.CurrentMuralChanged = 1;
+
+ if (!CrBltIsEntered(pBlitter))
+ return VINF_SUCCESS;
+ else if (!pBlitter->CtxInfo.Base.id)
+ {
+ WARN(("setting current mural for entered no-context blitter"));
+ return VERR_INVALID_STATE;
+ }
+
+ WARN(("changing mural for entered blitter, is is somewhat expected?"));
+
+ pBlitter->pDispatch->Flush();
+
+ pBlitter->pDispatch->MakeCurrent(pMural->Base.id, pBlitter->i32MakeCurrentUserData, pBlitter->CtxInfo.Base.id);
+
+ return VINF_SUCCESS;
+}
+
+static DECLCALLBACK(int) crBltBlitTexBufImplFbo(PCR_BLITTER pBlitter, const VBOXVR_TEXTURE *pSrc, const RTRECT *paSrcRect, const RTRECTSIZE *pDstSize, const RTRECT *paDstRect, uint32_t cRects, uint32_t fFlags)
+{
+ GLenum filter = CRBLT_FILTER_FROM_FLAGS(fFlags);
+ pBlitter->pDispatch->BindFramebufferEXT(GL_READ_FRAMEBUFFER, pBlitter->idFBO);
+ pBlitter->pDispatch->FramebufferTexture2DEXT(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, pSrc->target, pSrc->hwid, 0);
+ pBlitter->pDispatch->ReadBuffer(GL_COLOR_ATTACHMENT0);
+
+ for (uint32_t i = 0; i < cRects; ++i)
+ {
+ const RTRECT * pSrcRect = &paSrcRect[i];
+ const RTRECT * pDstRect = &paDstRect[i];
+ int32_t srcY1;
+ int32_t srcY2;
+ int32_t dstY1;
+ int32_t dstY2;
+ int32_t srcX1 = pSrcRect->xLeft;
+ int32_t srcX2 = pSrcRect->xRight;
+ int32_t dstX1 = pDstRect->xLeft;
+ int32_t dstX2 = pDstRect->xRight;
+
+ if (CRBLT_F_INVERT_SRC_YCOORDS & fFlags)
+ {
+ srcY1 = pSrc->height - pSrcRect->yTop;
+ srcY2 = pSrc->height - pSrcRect->yBottom;
+ }
+ else
+ {
+ srcY1 = pSrcRect->yTop;
+ srcY2 = pSrcRect->yBottom;
+ }
+
+ if (CRBLT_F_INVERT_DST_YCOORDS & fFlags)
+ {
+ dstY1 = pDstSize->cy - pDstRect->yTop;
+ dstY2 = pDstSize->cy - pDstRect->yBottom;
+ }
+ else
+ {
+ dstY1 = pDstRect->yTop;
+ dstY2 = pDstRect->yBottom;
+ }
+
+ if (srcY1 > srcY2)
+ {
+ if (dstY1 > dstY2)
+ {
+ /* use srcY1 < srcY2 && dstY1 < dstY2 whenever possible to avoid GPU driver bugs */
+ int32_t tmp = srcY1;
+ srcY1 = srcY2;
+ srcY2 = tmp;
+ tmp = dstY1;
+ dstY1 = dstY2;
+ dstY2 = tmp;
+ }
+ }
+
+ if (srcX1 > srcX2)
+ {
+ if (dstX1 > dstX2)
+ {
+ /* use srcX1 < srcX2 && dstX1 < dstX2 whenever possible to avoid GPU driver bugs */
+ int32_t tmp = srcX1;
+ srcX1 = srcX2;
+ srcX2 = tmp;
+ tmp = dstX1;
+ dstX1 = dstX2;
+ dstX2 = tmp;
+ }
+ }
+
+ pBlitter->pDispatch->BlitFramebufferEXT(srcX1, srcY1, srcX2, srcY2,
+ dstX1, dstY1, dstX2, dstY2,
+ GL_COLOR_BUFFER_BIT, filter);
+ }
+
+ return VINF_SUCCESS;
+}
+
+/* GL_TRIANGLE_FAN */
+DECLINLINE(GLfloat*) crBltVtRectTFNormalized(const RTRECT *pRect, uint32_t normalX, uint32_t normalY, GLfloat* pBuff, uint32_t height)
+{
+ /* going ccw:
+ * 1. (left;top) 4. (right;top)
+ * | ^
+ * > |
+ * 2. (left;bottom) -> 3. (right;bottom) */
+ /* xLeft yTop */
+ pBuff[0] = ((float)pRect->xLeft)/((float)normalX);
+ pBuff[1] = ((float)(height ? height - pRect->yTop : pRect->yTop))/((float)normalY);
+
+ /* xLeft yBottom */
+ pBuff[2] = pBuff[0];
+ pBuff[3] = ((float)(height ? height - pRect->yBottom : pRect->yBottom))/((float)normalY);
+
+ /* xRight yBottom */
+ pBuff[4] = ((float)pRect->xRight)/((float)normalX);
+ pBuff[5] = pBuff[3];
+
+ /* xRight yTop */
+ pBuff[6] = pBuff[4];
+ pBuff[7] = pBuff[1];
+ return &pBuff[8];
+}
+
+DECLINLINE(GLfloat*) crBltVtRectsTFNormalized(const RTRECT *paRects, uint32_t cRects, uint32_t normalX, uint32_t normalY, GLfloat* pBuff, uint32_t height)
+{
+ for (uint32_t i = 0; i < cRects; ++i)
+ {
+ pBuff = crBltVtRectTFNormalized(&paRects[i], normalX, normalY, pBuff, height);
+ }
+ return pBuff;
+}
+
+DECLINLINE(GLint*) crBltVtRectTF(const RTRECT *pRect, uint32_t normalX, uint32_t normalY, GLint* pBuff, uint32_t height)
+{
+ /* xLeft yTop */
+ pBuff[0] = pRect->xLeft;
+ pBuff[1] = height ? height - pRect->yTop : pRect->yTop;
+
+ /* xLeft yBottom */
+ pBuff[2] = pBuff[0];
+ pBuff[3] = height ? height - pRect->yBottom : pRect->yBottom;
+
+ /* xRight yBottom */
+ pBuff[4] = pRect->xRight;
+ pBuff[5] = pBuff[3];
+
+ /* xRight yTop */
+ pBuff[6] = pBuff[4];
+ pBuff[7] = pBuff[1];
+ return &pBuff[8];
+}
+
+DECLINLINE(GLubyte*) crBltVtFillRectIndicies(GLubyte *pIndex, GLubyte *piBase)
+{
+ GLubyte iBase = *piBase;
+ /* triangle 1 */
+ pIndex[0] = iBase;
+ pIndex[1] = iBase + 1;
+ pIndex[2] = iBase + 2;
+
+ /* triangle 2 */
+ pIndex[3] = iBase;
+ pIndex[4] = iBase + 2;
+ pIndex[5] = iBase + 3;
+ *piBase = iBase + 4;
+ return pIndex + 6;
+}
+
+/* Indexed GL_TRIANGLES */
+DECLINLINE(GLfloat*) crBltVtRectITNormalized(const RTRECT *pRect, uint32_t normalX, uint32_t normalY, GLfloat* pBuff, uint32_t height)
+{
+ GLfloat* ret = crBltVtRectTFNormalized(pRect, normalX, normalY, pBuff, height);
+ return ret;
+}
+
+DECLINLINE(GLint*) crBltVtRectIT(RTRECT *pRect, uint32_t normalX, uint32_t normalY, GLint* pBuff, GLubyte **ppIndex, GLubyte *piBase, uint32_t height)
+{
+ GLint* ret = crBltVtRectTF(pRect, normalX, normalY, pBuff, height);
+
+ if (ppIndex)
+ *ppIndex = crBltVtFillRectIndicies(*ppIndex, piBase);
+
+ return ret;
+}
+
+DECLINLINE(GLuint) crBltVtGetNumVerticiesTF(GLuint cRects)
+{
+ return cRects * 4;
+}
+
+#define crBltVtGetNumVerticiesIT crBltVtGetNumVerticiesTF
+
+DECLINLINE(GLuint) crBltVtGetNumIndiciesIT(GLuint cRects)
+{
+ return 6 * cRects;
+}
+
+
+static GLfloat* crBltVtRectsITNormalized(const RTRECT *paRects, uint32_t cRects, uint32_t normalX, uint32_t normalY, GLfloat* pBuff, GLubyte **ppIndex, GLubyte *piBase, uint32_t height)
+{
+ uint32_t i;
+ for (i = 0; i < cRects; ++i)
+ {
+ pBuff = crBltVtRectITNormalized(&paRects[i], normalX, normalY, pBuff, height);
+ }
+
+
+ if (ppIndex)
+ {
+ GLubyte *pIndex = (GLubyte*)pBuff;
+ *ppIndex = pIndex;
+ for (i = 0; i < cRects; ++i)
+ {
+ pIndex = crBltVtFillRectIndicies(pIndex, piBase);
+ }
+ pBuff = (GLfloat*)pIndex;
+ }
+
+ return pBuff;
+}
+
+static void* crBltBufGet(PCR_BLITTER_BUFFER pBuffer, GLuint cbBuffer)
+{
+ if (pBuffer->cbBuffer < cbBuffer)
+ {
+ if (pBuffer->pvBuffer)
+ {
+ RTMemFree(pBuffer->pvBuffer);
+ }
+
+#ifndef DEBUG_misha
+ /* debugging: ensure we calculate proper buffer size */
+ cbBuffer += 16;
+#endif
+
+ pBuffer->pvBuffer = RTMemAlloc(cbBuffer);
+ if (pBuffer->pvBuffer)
+ pBuffer->cbBuffer = cbBuffer;
+ else
+ {
+ crWarning("failed to allocate buffer of size %d", cbBuffer);
+ pBuffer->cbBuffer = 0;
+ }
+ }
+ return pBuffer->pvBuffer;
+}
+
+static void crBltCheckSetupViewport(PCR_BLITTER pBlitter, const RTRECTSIZE *pDstSize, bool fFBODraw)
+{
+ bool fUpdateViewport = pBlitter->Flags.CurrentMuralChanged;
+ if (pBlitter->CurrentSetSize.cx != pDstSize->cx
+ || pBlitter->CurrentSetSize.cy != pDstSize->cy)
+ {
+ pBlitter->CurrentSetSize = *pDstSize;
+ pBlitter->pDispatch->MatrixMode(GL_PROJECTION);
+ pBlitter->pDispatch->LoadIdentity();
+ pBlitter->pDispatch->Ortho(0, pDstSize->cx, 0, pDstSize->cy, -1, 1);
+ fUpdateViewport = true;
+ }
+
+ if (fUpdateViewport)
+ {
+ pBlitter->pDispatch->Viewport(0, 0, pBlitter->CurrentSetSize.cx, pBlitter->CurrentSetSize.cy);
+ pBlitter->Flags.CurrentMuralChanged = 0;
+ }
+
+ pBlitter->Flags.LastWasFBODraw = fFBODraw;
+}
+
+static DECLCALLBACK(int) crBltBlitTexBufImplDraw2D(PCR_BLITTER pBlitter, const VBOXVR_TEXTURE *pSrc, const RTRECT *paSrcRect, const RTRECTSIZE *pDstSize, const RTRECT *paDstRect, uint32_t cRects, uint32_t fFlags)
+{
+ GLuint normalX, normalY;
+ uint32_t srcHeight = (fFlags & CRBLT_F_INVERT_SRC_YCOORDS) ? pSrc->height : 0;
+ uint32_t dstHeight = (fFlags & CRBLT_F_INVERT_DST_YCOORDS) ? pDstSize->cy : 0;
+
+ switch (pSrc->target)
+ {
+ case GL_TEXTURE_2D:
+ {
+ normalX = pSrc->width;
+ normalY = pSrc->height;
+ break;
+ }
+
+ case GL_TEXTURE_RECTANGLE_ARB:
+ {
+ normalX = 1;
+ normalY = 1;
+ break;
+ }
+
+ default:
+ {
+ crWarning("Unsupported texture target 0x%x", pSrc->target);
+ return VERR_INVALID_PARAMETER;
+ }
+ }
+
+ Assert(pSrc->hwid);
+
+ pBlitter->pDispatch->BindTexture(pSrc->target, pSrc->hwid);
+
+ if (cRects == 1)
+ {
+ /* just optimization to draw a single rect with GL_TRIANGLE_FAN */
+ GLfloat *pVerticies;
+ GLfloat *pTexCoords;
+ GLuint cElements = crBltVtGetNumVerticiesTF(cRects);
+
+ pVerticies = (GLfloat*)crBltBufGet(&pBlitter->Verticies, cElements * 2 * 2 * sizeof (*pVerticies));
+ pTexCoords = crBltVtRectsTFNormalized(paDstRect, cRects, 1, 1, pVerticies, dstHeight);
+ crBltVtRectsTFNormalized(paSrcRect, cRects, normalX, normalY, pTexCoords, srcHeight);
+
+ pBlitter->pDispatch->EnableClientState(GL_VERTEX_ARRAY);
+ pBlitter->pDispatch->VertexPointer(2, GL_FLOAT, 0, pVerticies);
+
+ pBlitter->pDispatch->EnableClientState(GL_TEXTURE_COORD_ARRAY);
+ pBlitter->pDispatch->TexCoordPointer(2, GL_FLOAT, 0, pTexCoords);
+
+ pBlitter->pDispatch->Enable(pSrc->target);
+
+ pBlitter->pDispatch->DrawArrays(GL_TRIANGLE_FAN, 0, cElements);
+
+ pBlitter->pDispatch->Disable(pSrc->target);
+
+ pBlitter->pDispatch->DisableClientState(GL_TEXTURE_COORD_ARRAY);
+ pBlitter->pDispatch->DisableClientState(GL_VERTEX_ARRAY);
+ }
+ else
+ {
+ GLfloat *pVerticies;
+ GLfloat *pTexCoords;
+ GLubyte *pIndicies;
+ GLuint cElements = crBltVtGetNumVerticiesIT(cRects);
+ GLuint cIndicies = crBltVtGetNumIndiciesIT(cRects);
+ GLubyte iIdxBase = 0;
+
+ pVerticies = (GLfloat*)crBltBufGet(&pBlitter->Verticies, cElements * 2 * 2 * sizeof (*pVerticies) + cIndicies * sizeof (*pIndicies));
+ pTexCoords = crBltVtRectsITNormalized(paDstRect, cRects, 1, 1, pVerticies, &pIndicies, &iIdxBase, dstHeight);
+ crBltVtRectsITNormalized(paSrcRect, cRects, normalX, normalY, pTexCoords, NULL, NULL, srcHeight);
+
+ pBlitter->pDispatch->EnableClientState(GL_VERTEX_ARRAY);
+ pBlitter->pDispatch->VertexPointer(2, GL_FLOAT, 0, pVerticies);
+
+ pBlitter->pDispatch->EnableClientState(GL_TEXTURE_COORD_ARRAY);
+ pBlitter->pDispatch->TexCoordPointer(2, GL_FLOAT, 0, pTexCoords);
+
+ pBlitter->pDispatch->Enable(pSrc->target);
+
+ pBlitter->pDispatch->DrawElements(GL_TRIANGLES, cIndicies, GL_UNSIGNED_BYTE, pIndicies);
+
+ pBlitter->pDispatch->Disable(pSrc->target);
+
+ pBlitter->pDispatch->DisableClientState(GL_TEXTURE_COORD_ARRAY);
+ pBlitter->pDispatch->DisableClientState(GL_VERTEX_ARRAY);
+ }
+
+ pBlitter->pDispatch->BindTexture(pSrc->target, 0);
+
+ return VINF_SUCCESS;
+}
+
+static int crBltInitOnMakeCurent(PCR_BLITTER pBlitter)
+{
+ const char * pszExtension = (const char*)pBlitter->pDispatch->GetString(GL_EXTENSIONS);
+ if (crStrstr(pszExtension, "GL_EXT_framebuffer_object"))
+ {
+ pBlitter->Flags.SupportsFBO = 1;
+ pBlitter->pDispatch->GenFramebuffersEXT(1, &pBlitter->idFBO);
+ Assert(pBlitter->idFBO);
+ }
+ else
+ crWarning("GL_EXT_framebuffer_object not supported, blitter can only blit to window");
+
+ if (crStrstr(pszExtension, "GL_ARB_pixel_buffer_object"))
+ pBlitter->Flags.SupportsPBO = 1;
+ else
+ crWarning("GL_ARB_pixel_buffer_object not supported");
+
+ /* BlitFramebuffer seems to be buggy on Intel,
+ * try always glDrawXxx for now */
+ if (!pBlitter->Flags.ForceDrawBlit && crStrstr(pszExtension, "GL_EXT_framebuffer_blit"))
+ {
+ pBlitter->pfnBlt = crBltBlitTexBufImplFbo;
+ }
+ else
+ {
+// crWarning("GL_EXT_framebuffer_blit not supported, will use Draw functions for blitting, which might be less efficient");
+ pBlitter->pfnBlt = crBltBlitTexBufImplDraw2D;
+ }
+
+ /* defaults. but just in case */
+ pBlitter->pDispatch->MatrixMode(GL_TEXTURE);
+ pBlitter->pDispatch->LoadIdentity();
+ pBlitter->pDispatch->MatrixMode(GL_MODELVIEW);
+ pBlitter->pDispatch->LoadIdentity();
+
+ return VINF_SUCCESS;
+}
+
+void CrBltLeave(PCR_BLITTER pBlitter)
+{
+ if (!pBlitter->cEnters)
+ {
+ WARN(("blitter not entered!"));
+ return;
+ }
+
+ if (--pBlitter->cEnters)
+ return;
+
+ if (pBlitter->Flags.SupportsFBO)
+ {
+ pBlitter->pDispatch->BindFramebufferEXT(GL_FRAMEBUFFER, 0);
+ pBlitter->pDispatch->DrawBuffer(GL_BACK);
+ pBlitter->pDispatch->ReadBuffer(GL_BACK);
+ }
+
+ pBlitter->pDispatch->Flush();
+
+ if (pBlitter->CtxInfo.Base.id)
+ pBlitter->pDispatch->MakeCurrent(0, 0, 0);
+}
+
+int CrBltEnter(PCR_BLITTER pBlitter)
+{
+ if (!pBlitter->CurrentMural.Base.id && pBlitter->CtxInfo.Base.id)
+ {
+ WARN(("current mural not initialized!"));
+ return VERR_INVALID_STATE;
+ }
+
+ if (pBlitter->cEnters++)
+ return VINF_SUCCESS;
+
+ if (pBlitter->CurrentMural.Base.id) /* <- pBlitter->CurrentMural.Base.id can be null if the blitter is in a "no-context" mode (see comments to BltInit for detail)*/
+ {
+ pBlitter->pDispatch->MakeCurrent(pBlitter->CurrentMural.Base.id, pBlitter->i32MakeCurrentUserData, pBlitter->CtxInfo.Base.id);
+ }
+
+ if (pBlitter->Flags.Initialized)
+ return VINF_SUCCESS;
+
+ int rc = crBltInitOnMakeCurent(pBlitter);
+ if (RT_SUCCESS(rc))
+ {
+ pBlitter->Flags.Initialized = 1;
+ return VINF_SUCCESS;
+ }
+
+ WARN(("crBltInitOnMakeCurent failed, rc %d", rc));
+ CrBltLeave(pBlitter);
+ return rc;
+}
+
+static void crBltBlitTexBuf(PCR_BLITTER pBlitter, const VBOXVR_TEXTURE *pSrc, const RTRECT *paSrcRects, GLenum enmDstBuff, const RTRECTSIZE *pDstSize, const RTRECT *paDstRects, uint32_t cRects, uint32_t fFlags)
+{
+ pBlitter->pDispatch->DrawBuffer(enmDstBuff);
+
+ crBltCheckSetupViewport(pBlitter, pDstSize, enmDstBuff == GL_DRAW_FRAMEBUFFER);
+
+ if (!(fFlags & CRBLT_F_NOALPHA))
+ pBlitter->pfnBlt(pBlitter, pSrc, paSrcRects, pDstSize, paDstRects, cRects, fFlags);
+ else
+ {
+ int rc = pBlitter->Flags.ShadersGloal ?
+ CrGlslProgUseNoAlpha(pBlitter->pGlslCache, pSrc->target)
+ :
+ CrGlslProgUseGenNoAlpha(&pBlitter->LocalGlslCache, pSrc->target);
+
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("Failed to use no-alpha program rc %d!, falling back to default blit", rc);
+ pBlitter->pfnBlt(pBlitter, pSrc, paSrcRects, pDstSize, paDstRects, cRects, fFlags);
+ return;
+ }
+
+ /* since we use shaders, we need to use draw commands rather than framebuffer blits.
+ * force using draw-based blitting */
+ crBltBlitTexBufImplDraw2D(pBlitter, pSrc, paSrcRects, pDstSize, paDstRects, cRects, fFlags);
+
+ Assert(pBlitter->Flags.ShadersGloal || &pBlitter->LocalGlslCache == pBlitter->pGlslCache);
+
+ CrGlslProgClear(pBlitter->pGlslCache);
+ }
+}
+
+void CrBltCheckUpdateViewport(PCR_BLITTER pBlitter)
+{
+ RTRECTSIZE DstSize = {pBlitter->CurrentMural.width, pBlitter->CurrentMural.height};
+ crBltCheckSetupViewport(pBlitter, &DstSize, false);
+}
+
+void CrBltBlitTexMural(PCR_BLITTER pBlitter, bool fBb, const VBOXVR_TEXTURE *pSrc, const RTRECT *paSrcRects, const RTRECT *paDstRects, uint32_t cRects, uint32_t fFlags)
+{
+ if (!CrBltIsEntered(pBlitter))
+ {
+ WARN(("CrBltBlitTexMural: blitter not entered"));
+ return;
+ }
+
+ RTRECTSIZE DstSize = {pBlitter->CurrentMural.width, pBlitter->CurrentMural.height};
+
+ pBlitter->pDispatch->BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0);
+
+ crBltBlitTexBuf(pBlitter, pSrc, paSrcRects, fBb ? GL_BACK : GL_FRONT, &DstSize, paDstRects, cRects, fFlags);
+}
+
+void CrBltBlitTexTex(PCR_BLITTER pBlitter, const VBOXVR_TEXTURE *pSrc, const RTRECT *pSrcRect, const VBOXVR_TEXTURE *pDst, const RTRECT *pDstRect, uint32_t cRects, uint32_t fFlags)
+{
+ if (!CrBltIsEntered(pBlitter))
+ {
+ WARN(("CrBltBlitTexTex: blitter not entered"));
+ return;
+ }
+
+ RTRECTSIZE DstSize = {(uint32_t)pDst->width, (uint32_t)pDst->height};
+
+ pBlitter->pDispatch->BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, pBlitter->idFBO);
+
+ /* TODO: mag/min filters ? */
+
+ pBlitter->pDispatch->FramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, pDst->target, pDst->hwid, 0);
+
+// pBlitter->pDispatch->FramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
+// pBlitter->pDispatch->FramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
+
+ crBltBlitTexBuf(pBlitter, pSrc, pSrcRect, GL_DRAW_FRAMEBUFFER, &DstSize, pDstRect, cRects, fFlags);
+
+ pBlitter->pDispatch->FramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, pDst->target, 0, 0);
+}
+
+void CrBltPresent(PCR_BLITTER pBlitter)
+{
+ if (!CrBltIsEntered(pBlitter))
+ {
+ WARN(("CrBltPresent: blitter not entered"));
+ return;
+ }
+
+ if (pBlitter->CtxInfo.Base.visualBits & CR_DOUBLE_BIT)
+ pBlitter->pDispatch->SwapBuffers(pBlitter->CurrentMural.Base.id, 0);
+ else
+ pBlitter->pDispatch->Flush();
+}
+
+static int crBltImgInitBaseForTex(const VBOXVR_TEXTURE *pSrc, CR_BLITTER_IMG *pDst, GLenum enmFormat)
+{
+ memset(pDst, 0, sizeof (*pDst));
+ if (enmFormat != GL_RGBA
+ && enmFormat != GL_BGRA)
+ {
+ WARN(("unsupported format 0x%x", enmFormat));
+ return VERR_NOT_IMPLEMENTED;
+ }
+
+ uint32_t bpp = 32;
+
+ uint32_t pitch = ((bpp * pSrc->width) + 7) >> 3;
+ uint32_t cbData = pitch * pSrc->height;
+ pDst->cbData = cbData;
+ pDst->enmFormat = enmFormat;
+ pDst->width = pSrc->width;
+ pDst->height = pSrc->height;
+ pDst->bpp = bpp;
+ pDst->pitch = pitch;
+ return VINF_SUCCESS;
+}
+
+static int crBltImgCreateForTex(const VBOXVR_TEXTURE *pSrc, CR_BLITTER_IMG *pDst, GLenum enmFormat)
+{
+ int rc = crBltImgInitBaseForTex(pSrc, pDst, enmFormat);
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("crBltImgInitBaseForTex failed rc %d", rc);
+ return rc;
+ }
+
+ uint32_t cbData = pDst->cbData;
+ pDst->pvData = RTMemAllocZ(cbData);
+ if (!pDst->pvData)
+ {
+ crWarning("RTMemAlloc failed");
+ return VERR_NO_MEMORY;
+ }
+
+#ifdef DEBUG_misha
+ {
+ char *pTmp = (char*)pDst->pvData;
+ for (uint32_t i = 0; i < cbData; ++i)
+ {
+ pTmp[i] = (char)((1 << i) % 255);
+ }
+ }
+#endif
+ return VINF_SUCCESS;
+}
+
+VBOXBLITTERDECL(int) CrBltImgGetTex(PCR_BLITTER pBlitter, const VBOXVR_TEXTURE *pSrc, GLenum enmFormat, CR_BLITTER_IMG *pDst)
+{
+ if (!CrBltIsEntered(pBlitter))
+ {
+ WARN(("CrBltImgGetTex: blitter not entered"));
+ return VERR_INVALID_STATE;
+ }
+
+ int rc = crBltImgCreateForTex(pSrc, pDst, enmFormat);
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("crBltImgCreateForTex failed, rc %d", rc);
+ return rc;
+ }
+ pBlitter->pDispatch->BindTexture(pSrc->target, pSrc->hwid);
+
+#ifdef DEBUG_misha
+ {
+ GLint width = 0, height = 0, depth = 0;
+ pBlitter->pDispatch->GetTexLevelParameteriv(pSrc->target, 0, GL_TEXTURE_WIDTH, &width);
+ pBlitter->pDispatch->GetTexLevelParameteriv(pSrc->target, 0, GL_TEXTURE_HEIGHT, &height);
+ pBlitter->pDispatch->GetTexLevelParameteriv(pSrc->target, 0, GL_TEXTURE_DEPTH, &depth);
+
+ Assert(width == pSrc->width);
+ Assert(height == pSrc->height);
+// Assert(depth == pSrc->depth);
+ }
+#endif
+
+ pBlitter->pDispatch->GetTexImage(pSrc->target, 0, enmFormat, GL_UNSIGNED_BYTE, pDst->pvData);
+
+ pBlitter->pDispatch->BindTexture(pSrc->target, 0);
+ return VINF_SUCCESS;
+}
+
+VBOXBLITTERDECL(int) CrBltImgGetMural(PCR_BLITTER pBlitter, bool fBb, CR_BLITTER_IMG *pDst)
+{
+ if (!CrBltIsEntered(pBlitter))
+ {
+ WARN(("CrBltImgGetMural: blitter not entered"));
+ return VERR_INVALID_STATE;
+ }
+
+ crWarning("NOT IMPLEMENTED");
+ return VERR_NOT_IMPLEMENTED;
+}
+
+VBOXBLITTERDECL(void) CrBltImgFree(PCR_BLITTER pBlitter, CR_BLITTER_IMG *pDst)
+{
+ if (!CrBltIsEntered(pBlitter))
+ {
+ WARN(("CrBltImgFree: blitter not entered"));
+ return;
+ }
+
+ if (pDst->pvData)
+ {
+ RTMemFree(pDst->pvData);
+ pDst->pvData = NULL;
+ }
+}
+
+
+VBOXBLITTERDECL(bool) CrGlslIsSupported(CR_GLSL_CACHE *pCache)
+{
+ if (pCache->iGlVersion == 0)
+ {
+ const char * pszStr = (const char*)pCache->pDispatch->GetString(GL_VERSION);
+ pCache->iGlVersion = crStrParseGlVersion(pszStr);
+ if (pCache->iGlVersion <= 0)
+ {
+ crWarning("crStrParseGlVersion returned %d", pCache->iGlVersion);
+ pCache->iGlVersion = -1;
+ }
+ }
+
+ if (pCache->iGlVersion >= CR_GLVERSION_COMPOSE(2, 0, 0))
+ return true;
+
+ crWarning("GLSL unsuported, gl version %d", pCache->iGlVersion);
+
+ /* @todo: we could also check for GL_ARB_shader_objects and GL_ARB_fragment_shader,
+ * but seems like chromium does not support properly gl*Object versions of shader functions used with those extensions */
+ return false;
+}
+
+#define CR_GLSL_STR_V_120 "#version 120\n"
+#define CR_GLSL_STR_EXT_TR "#extension GL_ARB_texture_rectangle : enable\n"
+#define CR_GLSL_STR_2D "2D"
+#define CR_GLSL_STR_2DRECT "2DRect"
+
+#define CR_GLSL_PATTERN_FS_NOALPHA(_ver, _ext, _tex) \
+ _ver \
+ _ext \
+ "uniform sampler" _tex " sampler0;\n" \
+ "void main()\n" \
+ "{\n" \
+ "vec2 srcCoord = vec2(gl_TexCoord[0]);\n" \
+ "gl_FragData[0].xyz = (texture" _tex "(sampler0, srcCoord).xyz);\n" \
+ "gl_FragData[0].w = 1.0;\n" \
+ "}\n"
+
+static const char* crGlslGetFsStringNoAlpha(CR_GLSL_CACHE *pCache, GLenum enmTexTarget)
+{
+ if (!CrGlslIsSupported(pCache))
+ {
+ crWarning("CrGlslIsSupported is false");
+ return NULL;
+ }
+
+ if (pCache->iGlVersion >= CR_GLVERSION_COMPOSE(2, 1, 0))
+ {
+ if (enmTexTarget == GL_TEXTURE_2D)
+ return CR_GLSL_PATTERN_FS_NOALPHA(CR_GLSL_STR_V_120, "", CR_GLSL_STR_2D);
+ else if (enmTexTarget == GL_TEXTURE_RECTANGLE_ARB)
+ return CR_GLSL_PATTERN_FS_NOALPHA(CR_GLSL_STR_V_120, CR_GLSL_STR_EXT_TR, CR_GLSL_STR_2DRECT);
+
+ crWarning("invalid enmTexTarget %#x", enmTexTarget);
+ return NULL;
+ }
+ else if (pCache->iGlVersion >= CR_GLVERSION_COMPOSE(2, 0, 0))
+ {
+ if (enmTexTarget == GL_TEXTURE_2D)
+ return CR_GLSL_PATTERN_FS_NOALPHA("", "", CR_GLSL_STR_2D);
+ else if (enmTexTarget == GL_TEXTURE_RECTANGLE_ARB)
+ return CR_GLSL_PATTERN_FS_NOALPHA("", CR_GLSL_STR_EXT_TR, CR_GLSL_STR_2DRECT);
+
+ crWarning("invalid enmTexTarget %#x", enmTexTarget);
+ return NULL;
+ }
+
+ crError("crGlslGetFsStringNoAlpha: we should not be here!");
+ return NULL;
+}
+
+static int crGlslProgGenNoAlpha(CR_GLSL_CACHE *pCache, GLenum enmTexTarget, GLuint *puiProgram)
+{
+ *puiProgram = 0;
+
+ const char*pStrFsShader = crGlslGetFsStringNoAlpha(pCache, enmTexTarget);
+ if (!pStrFsShader)
+ {
+ crWarning("crGlslGetFsStringNoAlpha failed");
+ return VERR_NOT_SUPPORTED;
+ }
+
+ int rc = VINF_SUCCESS;
+ GLchar * pBuf = NULL;
+ GLuint uiProgram = 0;
+ GLint iUniform = -1;
+ GLuint uiShader = pCache->pDispatch->CreateShader(GL_FRAGMENT_SHADER);
+ if (!uiShader)
+ {
+ crWarning("CreateShader failed");
+ return VERR_NOT_SUPPORTED;
+ }
+
+ pCache->pDispatch->ShaderSource(uiShader, 1, &pStrFsShader, NULL);
+
+ pCache->pDispatch->CompileShader(uiShader);
+
+ GLint compiled = 0;
+ pCache->pDispatch->GetShaderiv(uiShader, GL_COMPILE_STATUS, &compiled);
+
+#ifndef DEBUG_misha
+ if(!compiled)
+#endif
+ {
+ if (!pBuf)
+ pBuf = (GLchar *)RTMemAlloc(16300);
+ pCache->pDispatch->GetShaderInfoLog(uiShader, 16300, NULL, pBuf);
+#ifdef DEBUG_misha
+ if (compiled)
+ crDebug("compile success:\n-------------------\n%s\n--------\n", pBuf);
+ else
+#endif
+ {
+ crWarning("compile FAILURE:\n-------------------\n%s\n--------\n", pBuf);
+ rc = VERR_NOT_SUPPORTED;
+ goto end;
+ }
+ }
+
+ Assert(compiled);
+
+ uiProgram = pCache->pDispatch->CreateProgram();
+ if (!uiProgram)
+ {
+ rc = VERR_NOT_SUPPORTED;
+ goto end;
+ }
+
+ pCache->pDispatch->AttachShader(uiProgram, uiShader);
+
+ pCache->pDispatch->LinkProgram(uiProgram);
+
+ GLint linked;
+ pCache->pDispatch->GetProgramiv(uiProgram, GL_LINK_STATUS, &linked);
+#ifndef DEBUG_misha
+ if(!linked)
+#endif
+ {
+ if (!pBuf)
+ pBuf = (GLchar *)RTMemAlloc(16300);
+ pCache->pDispatch->GetProgramInfoLog(uiProgram, 16300, NULL, pBuf);
+#ifdef DEBUG_misha
+ if (linked)
+ crDebug("link success:\n-------------------\n%s\n--------\n", pBuf);
+ else
+#endif
+ {
+ crWarning("link FAILURE:\n-------------------\n%s\n--------\n", pBuf);
+ rc = VERR_NOT_SUPPORTED;
+ goto end;
+ }
+ }
+
+ Assert(linked);
+
+ iUniform = pCache->pDispatch->GetUniformLocation(uiProgram, "sampler0");
+ if (iUniform == -1)
+ {
+ crWarning("GetUniformLocation failed for sampler0");
+ }
+ else
+ {
+ pCache->pDispatch->Uniform1i(iUniform, 0);
+ }
+
+ *puiProgram = uiProgram;
+
+ /* avoid end finalizer from cleaning it */
+ uiProgram = 0;
+
+ end:
+ if (uiShader)
+ pCache->pDispatch->DeleteShader(uiShader);
+ if (uiProgram)
+ pCache->pDispatch->DeleteProgram(uiProgram);
+ if (pBuf)
+ RTMemFree(pBuf);
+ return rc;
+}
+
+DECLINLINE(GLuint) crGlslProgGetNoAlpha(const CR_GLSL_CACHE *pCache, GLenum enmTexTarget)
+{
+ switch (enmTexTarget)
+ {
+ case GL_TEXTURE_2D:
+ return pCache->uNoAlpha2DProg;
+ case GL_TEXTURE_RECTANGLE_ARB:
+ return pCache->uNoAlpha2DRectProg;
+ default:
+ crWarning("invalid tex enmTexTarget %#x", enmTexTarget);
+ return 0;
+ }
+}
+
+DECLINLINE(GLuint*) crGlslProgGetNoAlphaPtr(CR_GLSL_CACHE *pCache, GLenum enmTexTarget)
+{
+ switch (enmTexTarget)
+ {
+ case GL_TEXTURE_2D:
+ return &pCache->uNoAlpha2DProg;
+ case GL_TEXTURE_RECTANGLE_ARB:
+ return &pCache->uNoAlpha2DRectProg;
+ default:
+ crWarning("invalid tex enmTexTarget %#x", enmTexTarget);
+ return NULL;
+ }
+}
+
+VBOXBLITTERDECL(int) CrGlslProgGenNoAlpha(CR_GLSL_CACHE *pCache, GLenum enmTexTarget)
+{
+ GLuint*puiProgram = crGlslProgGetNoAlphaPtr(pCache, enmTexTarget);
+ if (!puiProgram)
+ return VERR_INVALID_PARAMETER;
+
+ if (*puiProgram)
+ return VINF_SUCCESS;
+
+ return crGlslProgGenNoAlpha(pCache, enmTexTarget, puiProgram);
+}
+
+VBOXBLITTERDECL(int) CrGlslProgGenAllNoAlpha(CR_GLSL_CACHE *pCache)
+{
+ int rc = CrGlslProgGenNoAlpha(pCache, GL_TEXTURE_2D);
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("CrGlslProgGenNoAlpha GL_TEXTURE_2D failed rc %d", rc);
+ return rc;
+ }
+
+ rc = CrGlslProgGenNoAlpha(pCache, GL_TEXTURE_RECTANGLE_ARB);
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("CrGlslProgGenNoAlpha GL_TEXTURE_RECTANGLE failed rc %d", rc);
+ return rc;
+ }
+
+ return VINF_SUCCESS;
+}
+
+VBOXBLITTERDECL(void) CrGlslProgClear(const CR_GLSL_CACHE *pCache)
+{
+ pCache->pDispatch->UseProgram(0);
+}
+
+VBOXBLITTERDECL(int) CrGlslProgUseNoAlpha(const CR_GLSL_CACHE *pCache, GLenum enmTexTarget)
+{
+ GLuint uiProg = crGlslProgGetNoAlpha(pCache, enmTexTarget);
+ if (!uiProg)
+ {
+ crWarning("request to use inexistent program!");
+ return VERR_INVALID_STATE;
+ }
+
+ Assert(uiProg);
+
+ pCache->pDispatch->UseProgram(uiProg);
+
+ return VINF_SUCCESS;
+}
+
+VBOXBLITTERDECL(int) CrGlslProgUseGenNoAlpha(CR_GLSL_CACHE *pCache, GLenum enmTexTarget)
+{
+ GLuint uiProg = crGlslProgGetNoAlpha(pCache, enmTexTarget);
+ if (!uiProg)
+ {
+ int rc = CrGlslProgGenNoAlpha(pCache, enmTexTarget);
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("CrGlslProgGenNoAlpha failed, rc %d", rc);
+ return rc;
+ }
+
+ uiProg = crGlslProgGetNoAlpha(pCache, enmTexTarget);
+ CRASSERT(uiProg);
+ }
+
+ Assert(uiProg);
+
+ pCache->pDispatch->UseProgram(uiProg);
+
+ return VINF_SUCCESS;
+}
+
+VBOXBLITTERDECL(bool) CrGlslNeedsCleanup(const CR_GLSL_CACHE *pCache)
+{
+ return pCache->uNoAlpha2DProg || pCache->uNoAlpha2DRectProg;
+}
+
+VBOXBLITTERDECL(void) CrGlslCleanup(CR_GLSL_CACHE *pCache)
+{
+ if (pCache->uNoAlpha2DProg)
+ {
+ pCache->pDispatch->DeleteProgram(pCache->uNoAlpha2DProg);
+ pCache->uNoAlpha2DProg = 0;
+ }
+
+ if (pCache->uNoAlpha2DRectProg)
+ {
+ pCache->pDispatch->DeleteProgram(pCache->uNoAlpha2DRectProg);
+ pCache->uNoAlpha2DRectProg = 0;
+ }
+}
+
+VBOXBLITTERDECL(void) CrGlslTerm(CR_GLSL_CACHE *pCache)
+{
+ CRASSERT(!CrGlslNeedsCleanup(pCache));
+
+ CrGlslCleanup(pCache);
+
+ /* sanity */
+ memset(pCache, 0, sizeof (*pCache));
+}
+
+
+/*TdBlt*/
+static void crTdBltCheckPBO(PCR_TEXDATA pTex)
+{
+ if (pTex->idPBO)
+ return;
+
+ PCR_BLITTER pBlitter = pTex->pBlitter;
+
+ if (!pBlitter->Flags.SupportsPBO)
+ return;
+
+ pBlitter->pDispatch->GenBuffersARB(1, &pTex->idPBO);
+ if (!pTex->idPBO)
+ {
+ crWarning("PBO create failed");
+ return;
+ }
+
+ pBlitter->pDispatch->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pTex->idPBO);
+ pBlitter->pDispatch->BufferDataARB(GL_PIXEL_PACK_BUFFER_ARB,
+ pTex->Tex.width*pTex->Tex.height*4,
+ 0, GL_STREAM_READ_ARB);
+ pBlitter->pDispatch->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
+}
+
+static uint32_t crTdBltTexCreate(PCR_BLITTER pBlitter, uint32_t width, uint32_t height, GLenum enmTarget)
+{
+ uint32_t tex = 0;
+ pBlitter->pDispatch->GenTextures(1, &tex);
+ if (!tex)
+ {
+ crWarning("Tex create failed");
+ return 0;
+ }
+
+ pBlitter->pDispatch->BindTexture(enmTarget, tex);
+ pBlitter->pDispatch->TexParameteri(enmTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ pBlitter->pDispatch->TexParameteri(enmTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ pBlitter->pDispatch->TexParameteri(enmTarget, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ pBlitter->pDispatch->TexParameteri(enmTarget, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ pBlitter->pDispatch->TexImage2D(enmTarget, 0, GL_RGBA8,
+ width, height,
+ 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
+
+
+ /*Restore gl state*/
+ pBlitter->pDispatch->BindTexture(enmTarget, 0);
+
+ return tex;
+}
+
+int crTdBltCheckInvertTex(PCR_TEXDATA pTex)
+{
+ if (pTex->idInvertTex)
+ return VINF_SUCCESS;
+
+ pTex->idInvertTex = crTdBltTexCreate(pTex->pBlitter, pTex->Tex.width, pTex->Tex.height, pTex->Tex.target);
+ if (!pTex->idInvertTex)
+ {
+ crWarning("Invert Tex create failed");
+ return VERR_GENERAL_FAILURE;
+ }
+ return VINF_SUCCESS;
+}
+
+void crTdBltImgRelease(PCR_TEXDATA pTex)
+{
+ pTex->Flags.DataValid = 0;
+}
+
+void crTdBltImgFree(PCR_TEXDATA pTex)
+{
+ if (!pTex->Img.pvData)
+ {
+ Assert(!pTex->Flags.DataValid);
+ return;
+ }
+
+ crTdBltImgRelease(pTex);
+
+ Assert(!pTex->Flags.DataValid);
+
+
+ if (pTex->idPBO)
+ {
+ PCR_BLITTER pBlitter = pTex->pBlitter;
+
+ Assert(CrBltIsEntered(pBlitter));
+ pBlitter->pDispatch->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pTex->idPBO);
+ pBlitter->pDispatch->UnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
+ pBlitter->pDispatch->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
+ }
+ else
+ {
+ Assert(pTex->Img.pvData);
+ RTMemFree(pTex->Img.pvData);
+ }
+
+ pTex->Img.pvData = NULL;
+}
+
+int crTdBltImgAcquire(PCR_TEXDATA pTex, GLenum enmFormat, bool fInverted)
+{
+ void *pvData = pTex->Img.pvData;
+ Assert(!pTex->Flags.DataValid);
+ int rc = crBltImgInitBaseForTex(&pTex->Tex, &pTex->Img, enmFormat);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("crBltImgInitBaseForTex failed rc %d", rc));
+ return rc;
+ }
+
+ PCR_BLITTER pBlitter = pTex->pBlitter;
+ Assert(CrBltIsEntered(pBlitter));
+ pBlitter->pDispatch->BindTexture(pTex->Tex.target, fInverted ? pTex->idInvertTex : pTex->Tex.hwid);
+
+ pBlitter->pDispatch->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pTex->idPBO);
+
+ if (pvData)
+ {
+ if (pTex->idPBO)
+ {
+ pBlitter->pDispatch->UnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
+ pvData = NULL;
+
+ }
+ }
+ else
+ {
+ if (!pTex->idPBO)
+ {
+ pvData = RTMemAlloc(4*pTex->Tex.width*pTex->Tex.height);
+ if (!pvData)
+ {
+ WARN(("Out of memory in crTdBltImgAcquire"));
+ pBlitter->pDispatch->BindTexture(pTex->Tex.target, 0);
+ return VERR_NO_MEMORY;
+ }
+ }
+ }
+
+ Assert(!pvData == !!pTex->idPBO);
+
+ /*read the texture, note pixels are NULL for PBO case as it's offset in the buffer*/
+ pBlitter->pDispatch->GetTexImage(GL_TEXTURE_2D, 0, enmFormat, GL_UNSIGNED_BYTE, pvData);
+
+ /*restore gl state*/
+ pBlitter->pDispatch->BindTexture(pTex->Tex.target, 0);
+
+ if (pTex->idPBO)
+ {
+ pvData = pBlitter->pDispatch->MapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
+ if (!pvData)
+ {
+ WARN(("Failed to MapBuffer in CrHlpGetTexImage"));
+ return VERR_GENERAL_FAILURE;
+ }
+
+ pBlitter->pDispatch->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
+ }
+
+ Assert(pvData);
+ pTex->Img.pvData = pvData;
+ pTex->Flags.DataValid = 1;
+ pTex->Flags.DataInverted = fInverted;
+ return VINF_SUCCESS;
+}
+
+/* release the texture data, the data remains cached in the CR_TEXDATA object until it is discarded with CrTdBltDataInvalidateNe or CrTdBltDataCleanup */
+VBOXBLITTERDECL(int) CrTdBltDataRelease(PCR_TEXDATA pTex)
+{
+ if (!pTex->Flags.Entered)
+ {
+ WARN(("tex not entered"));
+ return VERR_INVALID_STATE;
+ }
+
+ if (!pTex->Flags.DataAcquired)
+ {
+ WARN(("Data NOT acquired"));
+ return VERR_INVALID_STATE;
+ }
+
+ Assert(pTex->Img.pvData);
+ Assert(pTex->Flags.DataValid);
+
+ pTex->Flags.DataAcquired = 0;
+
+ return VINF_SUCCESS;
+}
+
+static void crTdBltDataFree(PCR_TEXDATA pTex)
+{
+ crTdBltImgFree(pTex);
+
+ if (pTex->pScaledCache)
+ CrTdBltDataFreeNe(pTex->pScaledCache);
+}
+
+/* discard the texture data cached with previous CrTdBltDataAcquire.
+ * Must be called wit data released (CrTdBltDataRelease) */
+VBOXBLITTERDECL(int) CrTdBltDataFree(PCR_TEXDATA pTex)
+{
+ if (!pTex->Flags.Entered)
+ {
+ WARN(("tex not entered"));
+ return VERR_INVALID_STATE;
+ }
+
+ crTdBltDataFree(pTex);
+
+ return VINF_SUCCESS;
+}
+
+VBOXBLITTERDECL(void) CrTdBltDataInvalidateNe(PCR_TEXDATA pTex)
+{
+ crTdBltImgRelease(pTex);
+
+ if (pTex->pScaledCache)
+ CrTdBltDataInvalidateNe(pTex->pScaledCache);
+}
+
+VBOXBLITTERDECL(int) CrTdBltDataFreeNe(PCR_TEXDATA pTex)
+{
+ if (!pTex->Img.pvData)
+ return VINF_SUCCESS;
+
+ bool fEntered = false;
+ if (pTex->idPBO)
+ {
+ int rc = CrTdBltEnter(pTex);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ fEntered = true;
+ }
+
+ crTdBltDataFree(pTex);
+
+ if (fEntered)
+ CrTdBltLeave(pTex);
+
+ return VINF_SUCCESS;
+}
+
+static void crTdBltSdCleanupCacheNe(PCR_TEXDATA pTex)
+{
+ if (pTex->pScaledCache)
+ {
+ CrTdBltDataCleanupNe(pTex->pScaledCache);
+ CrTdRelease(pTex->pScaledCache);
+ pTex->pScaledCache = NULL;
+ }
+}
+
+static void crTdBltDataCleanup(PCR_TEXDATA pTex)
+{
+ crTdBltImgFree(pTex);
+
+ PCR_BLITTER pBlitter = pTex->pBlitter;
+
+ if (pTex->idPBO)
+ {
+ Assert(CrBltIsEntered(pBlitter));
+ pBlitter->pDispatch->DeleteBuffersARB(1, &pTex->idPBO);
+ pTex->idPBO = 0;
+ }
+
+ if (pTex->idInvertTex)
+ {
+ Assert(CrBltIsEntered(pBlitter));
+ pBlitter->pDispatch->DeleteTextures(1, &pTex->idInvertTex);
+ pTex->idInvertTex = 0;
+ }
+
+ crTdBltSdCleanupCacheNe(pTex);
+}
+
+/* does same as CrTdBltDataFree, and in addition cleans up */
+VBOXBLITTERDECL(int) CrTdBltDataCleanup(PCR_TEXDATA pTex)
+{
+ if (!pTex->Flags.Entered)
+ {
+ WARN(("tex not entered"));
+ return VERR_INVALID_STATE;
+ }
+
+ crTdBltDataCleanup(pTex);
+
+ return VINF_SUCCESS;
+}
+
+VBOXBLITTERDECL(int) CrTdBltDataCleanupNe(PCR_TEXDATA pTex)
+{
+ bool fEntered = false;
+ if (pTex->idPBO || pTex->idInvertTex)
+ {
+ int rc = CrTdBltEnter(pTex);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ fEntered = true;
+ }
+
+ crTdBltDataCleanup(pTex);
+
+ if (fEntered)
+ CrTdBltLeave(pTex);
+
+ return VINF_SUCCESS;
+}
+
+/* acquire the texture data, returns the cached data in case it is cached.
+ * the data remains cached in the CR_TEXDATA object until it is discarded with CrTdBltDataFree or CrTdBltDataCleanup.
+ * */
+VBOXBLITTERDECL(int) CrTdBltDataAcquire(PCR_TEXDATA pTex, GLenum enmFormat, bool fInverted, const CR_BLITTER_IMG**ppImg)
+{
+ if (!pTex->Flags.Entered)
+ {
+ WARN(("tex not entered"));
+ return VERR_INVALID_STATE;
+ }
+
+ if (pTex->Flags.DataAcquired)
+ {
+ WARN(("Data acquired already"));
+ return VERR_INVALID_STATE;
+ }
+
+ if (pTex->Flags.DataValid && pTex->Img.enmFormat == enmFormat && !pTex->Flags.DataInverted == !fInverted)
+ {
+ Assert(pTex->Img.pvData);
+ *ppImg = &pTex->Img;
+ pTex->Flags.DataAcquired = 1;
+ return VINF_SUCCESS;
+ }
+
+ crTdBltImgRelease(pTex);
+
+ crTdBltCheckPBO(pTex);
+
+ int rc;
+
+ if (fInverted)
+ {
+ rc = crTdBltCheckInvertTex(pTex);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("crTdBltCheckInvertTex failed rc %d", rc));
+ return rc;
+ }
+
+ RTRECT SrcRect, DstRect;
+ VBOXVR_TEXTURE InvertTex;
+
+ InvertTex = pTex->Tex;
+ InvertTex.hwid = pTex->idInvertTex;
+
+ SrcRect.xLeft = 0;
+ SrcRect.yTop = InvertTex.height;
+ SrcRect.xRight = InvertTex.width;
+ SrcRect.yBottom = 0;
+
+ DstRect.xLeft = 0;
+ DstRect.yTop = 0;
+ DstRect.xRight = InvertTex.width;
+ DstRect.yBottom = InvertTex.height;
+
+ CrBltBlitTexTex(pTex->pBlitter, &pTex->Tex, &SrcRect, &InvertTex, &DstRect, 1, 0);
+ }
+
+ rc = crTdBltImgAcquire(pTex, enmFormat, fInverted);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("crTdBltImgAcquire failed rc %d", rc));
+ return rc;
+ }
+
+ Assert(pTex->Img.pvData);
+ *ppImg = &pTex->Img;
+ pTex->Flags.DataAcquired = 1;
+
+ return VINF_SUCCESS;
+}
+
+DECLINLINE(void) crTdResize(PCR_TEXDATA pTex, const VBOXVR_TEXTURE *pVrTex)
+{
+ crTdBltDataCleanup(pTex);
+
+ pTex->Tex = *pVrTex;
+}
+
+static DECLCALLBACK(void) ctTdBltSdReleased(struct CR_TEXDATA *pTexture)
+{
+ PCR_BLITTER pBlitter = pTexture->pBlitter;
+
+ int rc = CrBltEnter(pBlitter);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("CrBltEnter failed, rc %d", rc));
+ return;
+ }
+
+ CrTdBltDataCleanupNe(pTexture);
+
+ pBlitter->pDispatch->DeleteTextures(1, &pTexture->Tex.hwid);
+
+ CrBltLeave(pBlitter);
+
+ RTMemFree(pTexture);
+}
+
+static int ctTdBltSdCreate(PCR_BLITTER pBlitter, uint32_t width, uint32_t height, GLenum enmTarget, PCR_TEXDATA *ppScaledCache)
+{
+ PCR_TEXDATA pScaledCache;
+
+ Assert(CrBltIsEntered(pBlitter));
+
+ *ppScaledCache = NULL;
+
+ pScaledCache = (PCR_TEXDATA)RTMemAlloc(sizeof (*pScaledCache));
+ if (!pScaledCache)
+ {
+ WARN(("RTMemAlloc failed"));
+ return VERR_NO_MEMORY;
+ }
+
+ VBOXVR_TEXTURE Tex;
+ Tex.width = width;
+ Tex.height = height;
+ Tex.target = enmTarget;
+ Tex.hwid = crTdBltTexCreate(pBlitter, width, height, enmTarget);
+ if (!Tex.hwid)
+ {
+ WARN(("Tex create failed"));
+ RTMemFree(pScaledCache);
+ return VERR_GENERAL_FAILURE;
+ }
+
+ CrTdInit(pScaledCache, &Tex, pBlitter, ctTdBltSdReleased);
+
+ *ppScaledCache = pScaledCache;
+
+ return VINF_SUCCESS;
+}
+
+static int ctTdBltSdGet(PCR_TEXDATA pTex, uint32_t width, uint32_t height, PCR_TEXDATA *ppScaledCache)
+{
+ Assert(CrBltIsEntered(pTex->pBlitter));
+
+ PCR_TEXDATA pScaledCache;
+
+ *ppScaledCache = NULL;
+
+ if (!pTex->pScaledCache)
+ {
+ int rc = ctTdBltSdCreate(pTex->pBlitter, width, height, pTex->Tex.target, &pScaledCache);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("ctTdBltSdCreate failed %d", rc));
+ return rc;
+ }
+
+ pTex->pScaledCache = pScaledCache;
+ }
+ else
+ {
+ int cmp = pTex->pScaledCache->Tex.width - width;
+ if (cmp <= 0)
+ cmp = pTex->pScaledCache->Tex.height - height;
+
+ if (!cmp)
+ pScaledCache = pTex->pScaledCache;
+ else if (cmp < 0) /* current cache is "less" than the requested */
+ {
+ int rc = ctTdBltSdCreate(pTex->pBlitter, width, height, pTex->Tex.target, &pScaledCache);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("ctTdBltSdCreate failed %d", rc));
+ return rc;
+ }
+
+ pScaledCache->pScaledCache = pTex->pScaledCache;
+ pTex->pScaledCache = pScaledCache;
+ }
+ else /* cmp > 0 */
+ {
+ int rc = ctTdBltSdGet(pTex->pScaledCache, width, height, &pScaledCache);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("ctTdBltSdGet failed %d", rc));
+ return rc;
+ }
+ }
+ }
+
+ Assert(pScaledCache);
+
+#if 0
+ {
+ VBOXVR_TEXTURE Tex;
+ Tex.width = width;
+ Tex.height = height;
+ Tex.target = pTex->Tex.target;
+ Tex.hwid = crTdBltTexCreate(pTex, width, height);
+ if (!Tex.hwid)
+ {
+ WARN(("Tex create failed"));
+ return VERR_GENERAL_FAILURE;
+ }
+
+ pTex->pBlitter->pDispatch->DeleteTextures(1, &pTex->pScaledCache->Tex.hwid);
+
+ crTdResize(pTex->pScaledCache, &Tex);
+ }
+#endif
+
+ *ppScaledCache = pScaledCache;
+ return VINF_SUCCESS;
+}
+
+static int ctTdBltSdGetUpdated(PCR_TEXDATA pTex, uint32_t width, uint32_t height, PCR_TEXDATA *ppScaledCache)
+{
+ PCR_TEXDATA pScaledCache;
+
+ *ppScaledCache = NULL;
+ int rc = ctTdBltSdGet(pTex, width, height, &pScaledCache);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("ctTdBltSdGet failed %d", rc));
+ return rc;
+ }
+
+ Assert(width == pScaledCache->Tex.width);
+ Assert(height == pScaledCache->Tex.height);
+
+ if (!pScaledCache->Flags.DataValid)
+ {
+ RTRECT SrcRect, DstRect;
+
+ SrcRect.xLeft = 0;
+ SrcRect.yTop = 0;
+ SrcRect.xRight = pTex->Tex.width;
+ SrcRect.yBottom = pTex->Tex.height;
+
+ DstRect.xLeft = 0;
+ DstRect.yTop = 0;
+ DstRect.xRight = width;
+ DstRect.yBottom = height;
+
+ CrBltBlitTexTex(pTex->pBlitter, &pTex->Tex, &SrcRect, &pScaledCache->Tex, &DstRect, 1, 0);
+ }
+
+ *ppScaledCache = pScaledCache;
+
+ return VINF_SUCCESS;
+}
+
+VBOXBLITTERDECL(int) CrTdBltDataAcquireScaled(PCR_TEXDATA pTex, GLenum enmFormat, bool fInverted, uint32_t width, uint32_t height, const CR_BLITTER_IMG**ppImg)
+{
+ if (pTex->Tex.width == width && pTex->Tex.height == height)
+ return CrTdBltDataAcquire(pTex, enmFormat, fInverted, ppImg);
+
+ if (!pTex->Flags.Entered)
+ {
+ WARN(("tex not entered"));
+ return VERR_INVALID_STATE;
+ }
+
+ PCR_TEXDATA pScaledCache;
+
+ int rc = ctTdBltSdGetUpdated(pTex, width, height, &pScaledCache);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("ctTdBltSdGetUpdated failed rc %d", rc));
+ return rc;
+ }
+
+ rc = CrTdBltEnter(pScaledCache);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("CrTdBltEnter failed rc %d", rc));
+ return rc;
+ }
+
+ rc = CrTdBltDataAcquire(pScaledCache, enmFormat, fInverted, ppImg);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("CrTdBltDataAcquire failed rc %d", rc));
+ CrTdBltLeave(pTex->pScaledCache);
+ return rc;
+ }
+
+ return VINF_SUCCESS;
+}
+
+VBOXBLITTERDECL(int) CrTdBltDataReleaseScaled(PCR_TEXDATA pTex, const CR_BLITTER_IMG *pImg)
+{
+ PCR_TEXDATA pScaledCache = RT_FROM_MEMBER(pImg, CR_TEXDATA, Img);
+ int rc = CrTdBltDataRelease(pScaledCache);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("CrTdBltDataRelease failed rc %d", rc));
+ return rc;
+ }
+
+ if (pScaledCache != pTex)
+ CrTdBltLeave(pScaledCache);
+
+ return VINF_SUCCESS;
+}
+
+VBOXBLITTERDECL(void) CrTdBltScaleCacheMoveTo(PCR_TEXDATA pTex, PCR_TEXDATA pDstTex)
+{
+ if (!pTex->pScaledCache)
+ return;
+
+ crTdBltSdCleanupCacheNe(pDstTex);
+
+ pDstTex->pScaledCache = pTex->pScaledCache;
+ pTex->pScaledCache = NULL;
+}
diff --git a/src/VBox/GuestHost/OpenGL/util/bmpscale.cpp b/src/VBox/GuestHost/OpenGL/util/bmpscale.cpp
new file mode 100644
index 00000000..1b32487b
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/util/bmpscale.cpp
@@ -0,0 +1,319 @@
+/** @file
+ * Image resampling code, used for snapshot thumbnails.
+ */
+
+/*
+ * Copyright (C) 2009-2011 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+/*
+ * Based on gdImageCopyResampled from libgd.
+ * Original copyright notice follows:
+
+ Portions copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ Pierre-Alain Joye (pierre@libgd.org).
+
+ Permission has been granted to copy, distribute and modify gd in
+ any context without fee, including a commercial application,
+ provided that this notice is present in user-accessible supporting
+ documentation.
+
+ This does not affect your ownership of the derived work itself, and
+ the intent is to assure proper credit for the authors of gd, not to
+ interfere with your productive use of gd. If you have questions,
+ ask. "Derived works" includes all programs that utilize the
+ library. Credit must be given in user-accessible documentation.
+
+ This software is provided "AS IS." The copyright holders disclaim
+ all warranties, either express or implied, including but not
+ limited to implied warranties of merchantability and fitness for a
+ particular purpose, with respect to this code and accompanying
+ documentation.
+ */
+
+/*
+ *
+ * @todo Simplify: Offsets of images are 0,0 => no dstX, dstY, srcX, srcY;
+ * Screenshot has no alpha channel => no processing of alpha byte.
+ */
+
+#include <cr_bmpscale.h>
+
+/* 2.0.10: cast instead of floor() yields 35% performance improvement.
+ Thanks to John Buckman. */
+
+#define floor2(exp) ((long) exp)
+/*#define floor2(exp) floor(exp)*/
+
+typedef uint8_t *gdImagePtr;
+
+DECLINLINE(int) gdImageGetTrueColorPixel (gdImagePtr im, int x, int y, int w)
+{
+ return *(int32_t *)(im + y * w * 4 + x * 4);
+}
+
+DECLINLINE(void) gdImageSetPixel (gdImagePtr im, int x, int y, int color, int cbLine)
+{
+ *(int32_t *)(im + y * cbLine + x * 4) = color;
+}
+
+#define gdAlphaMax 127
+#define gdAlphaOpaque 0
+#define gdAlphaTransparent 127
+#define gdRedMax 255
+#define gdGreenMax 255
+#define gdBlueMax 255
+#define gdTrueColorGetAlpha(c) (((c) & 0x7F000000) >> 24)
+#define gdTrueColorGetRed(c) (((c) & 0xFF0000) >> 16)
+#define gdTrueColorGetGreen(c) (((c) & 0x00FF00) >> 8)
+#define gdTrueColorGetBlue(c) ((c) & 0x0000FF)
+#define gdTrueColorAlpha(r, g, b, a) (((a) << 24) + \
+ ((r) << 16) + \
+ ((g) << 8) + \
+ (b))
+
+void gdImageCopyResampled (uint8_t *dst,
+ uint8_t *src,
+ int dstX, int dstY,
+ int srcX, int srcY,
+ int dstW, int dstH, int srcW, int srcH)
+{
+ int x, y;
+ double sy1, sy2, sx1, sx2;
+ for (y = dstY; (y < dstY + dstH); y++)
+ {
+ sy1 = ((double) y - (double) dstY) * (double) srcH / (double) dstH;
+ sy2 = ((double) (y + 1) - (double) dstY) * (double) srcH /
+ (double) dstH;
+ for (x = dstX; (x < dstX + dstW); x++)
+ {
+ double sx, sy;
+ double spixels = 0;
+ double red = 0.0, green = 0.0, blue = 0.0, alpha = 0.0;
+ sx1 = ((double) x - (double) dstX) * (double) srcW / dstW;
+ sx2 = ((double) (x + 1) - (double) dstX) * (double) srcW / dstW;
+ sy = sy1;
+ do
+ {
+ double yportion;
+ if (floor2 (sy) == floor2 (sy1))
+ {
+ yportion = 1.0 - (sy - floor2 (sy));
+ if (yportion > sy2 - sy1)
+ {
+ yportion = sy2 - sy1;
+ }
+ sy = floor2 (sy);
+ }
+ else if (sy == floor2 (sy2))
+ {
+ yportion = sy2 - floor2 (sy2);
+ }
+ else
+ {
+ yportion = 1.0;
+ }
+ sx = sx1;
+ do
+ {
+ double xportion;
+ double pcontribution;
+ int p;
+ if (floor2 (sx) == floor2 (sx1))
+ {
+ xportion = 1.0 - (sx - floor2 (sx));
+ if (xportion > sx2 - sx1)
+ {
+ xportion = sx2 - sx1;
+ }
+ sx = floor2 (sx);
+ }
+ else if (sx == floor2 (sx2))
+ {
+ xportion = sx2 - floor2 (sx2);
+ }
+ else
+ {
+ xportion = 1.0;
+ }
+ pcontribution = xportion * yportion;
+ /* 2.08: previously srcX and srcY were ignored.
+ Andrew Pattison */
+ p = gdImageGetTrueColorPixel (src,
+ (int) sx + srcX,
+ (int) sy + srcY, srcW);
+ red += gdTrueColorGetRed (p) * pcontribution;
+ green += gdTrueColorGetGreen (p) * pcontribution;
+ blue += gdTrueColorGetBlue (p) * pcontribution;
+ alpha += gdTrueColorGetAlpha (p) * pcontribution;
+ spixels += xportion * yportion;
+ sx += 1.0;
+ }
+ while (sx < sx2);
+ sy += 1.0;
+ }
+ while (sy < sy2);
+ if (spixels != 0.0)
+ {
+ red /= spixels;
+ green /= spixels;
+ blue /= spixels;
+ alpha /= spixels;
+ }
+ /* Clamping to allow for rounding errors above */
+ if (red > 255.0)
+ {
+ red = 255.0;
+ }
+ if (green > 255.0)
+ {
+ green = 255.0;
+ }
+ if (blue > 255.0)
+ {
+ blue = 255.0;
+ }
+ if (alpha > gdAlphaMax)
+ {
+ alpha = gdAlphaMax;
+ }
+ gdImageSetPixel (dst,
+ x, y,
+ gdTrueColorAlpha ((int) red,
+ (int) green,
+ (int) blue, (int) alpha), dstW * 4);
+ }
+ }
+}
+
+/* Fast integer implementation for 32 bpp bitmap scaling.
+ * Use fixed point values * 16.
+ */
+typedef int32_t FIXEDPOINT;
+#define INT_TO_FIXEDPOINT(i) (FIXEDPOINT)((i) << 4)
+#define FIXEDPOINT_TO_INT(v) (int)((v) >> 4)
+#define FIXEDPOINT_FLOOR(v) ((v) & ~0xF)
+#define FIXEDPOINT_FRACTION(v) ((v) & 0xF)
+
+/* For 32 bit source only. */
+VBOXBMPSCALEDECL(void) CrBmpScale32 (uint8_t *dst,
+ int iDstDeltaLine,
+ int dstW, int dstH,
+ const uint8_t *src,
+ int iSrcDeltaLine,
+ int srcW, int srcH)
+{
+ int x, y;
+
+ for (y = 0; y < dstH; y++)
+ {
+ FIXEDPOINT sy1 = INT_TO_FIXEDPOINT(y * srcH) / dstH;
+ FIXEDPOINT sy2 = INT_TO_FIXEDPOINT((y + 1) * srcH) / dstH;
+
+ for (x = 0; x < dstW; x++)
+ {
+ FIXEDPOINT red = 0, green = 0, blue = 0;
+
+ FIXEDPOINT sx1 = INT_TO_FIXEDPOINT(x * srcW) / dstW;
+ FIXEDPOINT sx2 = INT_TO_FIXEDPOINT((x + 1) * srcW) / dstW;
+
+ FIXEDPOINT spixels = (sx2 - sx1) * (sy2 - sy1);
+
+ FIXEDPOINT sy = sy1;
+
+ do
+ {
+ FIXEDPOINT yportion;
+ if (FIXEDPOINT_FLOOR (sy) == FIXEDPOINT_FLOOR (sy1))
+ {
+ yportion = INT_TO_FIXEDPOINT(1) - FIXEDPOINT_FRACTION(sy);
+ if (yportion > sy2 - sy1)
+ {
+ yportion = sy2 - sy1;
+ }
+ sy = FIXEDPOINT_FLOOR (sy);
+ }
+ else if (sy == FIXEDPOINT_FLOOR (sy2))
+ {
+ yportion = FIXEDPOINT_FRACTION(sy2);
+ }
+ else
+ {
+ yportion = INT_TO_FIXEDPOINT(1);
+ }
+
+ const uint8_t *pu8SrcLine = src + iSrcDeltaLine * FIXEDPOINT_TO_INT(sy);
+ FIXEDPOINT sx = sx1;
+ do
+ {
+ FIXEDPOINT xportion;
+ FIXEDPOINT pcontribution;
+ int p;
+ if (FIXEDPOINT_FLOOR (sx) == FIXEDPOINT_FLOOR (sx1))
+ {
+ xportion = INT_TO_FIXEDPOINT(1) - FIXEDPOINT_FRACTION(sx);
+ if (xportion > sx2 - sx1)
+ {
+ xportion = sx2 - sx1;
+ }
+ pcontribution = xportion * yportion;
+ sx = FIXEDPOINT_FLOOR (sx);
+ }
+ else if (sx == FIXEDPOINT_FLOOR (sx2))
+ {
+ xportion = FIXEDPOINT_FRACTION(sx2);
+ pcontribution = xportion * yportion;
+ }
+ else
+ {
+ xportion = INT_TO_FIXEDPOINT(1);
+ pcontribution = xportion * yportion;
+ }
+ /* Color depth specific code begin */
+ p = *(uint32_t *)(pu8SrcLine + FIXEDPOINT_TO_INT(sx) * 4);
+ /* Color depth specific code end */
+ red += gdTrueColorGetRed (p) * pcontribution;
+ green += gdTrueColorGetGreen (p) * pcontribution;
+ blue += gdTrueColorGetBlue (p) * pcontribution;
+
+ sx += INT_TO_FIXEDPOINT(1);
+ } while (sx < sx2);
+
+ sy += INT_TO_FIXEDPOINT(1);
+ } while (sy < sy2);
+
+ if (spixels != 0)
+ {
+ red /= spixels;
+ green /= spixels;
+ blue /= spixels;
+ }
+ /* Clamping to allow for rounding errors above */
+ if (red > 255)
+ {
+ red = 255;
+ }
+ if (green > 255)
+ {
+ green = 255;
+ }
+ if (blue > 255)
+ {
+ blue = 255;
+ }
+ gdImageSetPixel (dst,
+ x, y,
+ ( ((int) red) << 16) + (((int) green) << 8) + ((int) blue),
+ iDstDeltaLine);
+ }
+ }
+}
+
diff --git a/src/VBox/GuestHost/OpenGL/util/compositor.cpp b/src/VBox/GuestHost/OpenGL/util/compositor.cpp
new file mode 100644
index 00000000..f7c50bcd
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/util/compositor.cpp
@@ -0,0 +1,1015 @@
+/* $Id: compositor.cpp $ */
+
+/** @file
+ * Compositor impl
+ */
+
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+#include <cr_compositor.h>
+
+#define VBOXVR_SCR_COMPOSITOR_RECTS_UNDEFINED UINT32_MAX
+
+
+static int crVrScrCompositorRectsAssignBuffer(PVBOXVR_SCR_COMPOSITOR pCompositor, uint32_t cRects)
+{
+ Assert(cRects);
+
+ if (pCompositor->cRectsBuffer >= cRects)
+ {
+ pCompositor->cRects = cRects;
+ return VINF_SUCCESS;
+ }
+
+ if (pCompositor->cRectsBuffer)
+ {
+ Assert(pCompositor->paSrcRects);
+ RTMemFree(pCompositor->paSrcRects);
+ pCompositor->paSrcRects = NULL;
+ Assert(pCompositor->paDstRects);
+ RTMemFree(pCompositor->paDstRects);
+ pCompositor->paDstRects = NULL;
+ Assert(pCompositor->paDstUnstretchedRects);
+ RTMemFree(pCompositor->paDstUnstretchedRects);
+ pCompositor->paDstUnstretchedRects = NULL;
+ }
+ else
+ {
+ Assert(!pCompositor->paSrcRects);
+ Assert(!pCompositor->paDstRects);
+ Assert(!pCompositor->paDstUnstretchedRects);
+ }
+
+ pCompositor->paSrcRects = (PRTRECT)RTMemAlloc(sizeof (*pCompositor->paSrcRects) * cRects);
+ if (pCompositor->paSrcRects)
+ {
+ pCompositor->paDstRects = (PRTRECT)RTMemAlloc(sizeof (*pCompositor->paDstRects) * cRects);
+ if (pCompositor->paDstRects)
+ {
+ pCompositor->paDstUnstretchedRects = (PRTRECT)RTMemAlloc(sizeof (*pCompositor->paDstUnstretchedRects) * cRects);
+ if (pCompositor->paDstUnstretchedRects)
+ {
+ pCompositor->cRects = cRects;
+ pCompositor->cRectsBuffer = cRects;
+ return VINF_SUCCESS;
+ }
+
+ RTMemFree(pCompositor->paDstRects);
+ pCompositor->paDstRects = NULL;
+ }
+ else
+ {
+ WARN(("RTMemAlloc failed!"));
+ }
+ RTMemFree(pCompositor->paSrcRects);
+ pCompositor->paSrcRects = NULL;
+ }
+ else
+ {
+ WARN(("RTMemAlloc failed!"));
+ }
+
+ pCompositor->cRects = VBOXVR_SCR_COMPOSITOR_RECTS_UNDEFINED;
+ pCompositor->cRectsBuffer = 0;
+
+ return VERR_NO_MEMORY;
+}
+
+static void crVrScrCompositorRectsInvalidate(PVBOXVR_SCR_COMPOSITOR pCompositor)
+{
+ pCompositor->cRects = VBOXVR_SCR_COMPOSITOR_RECTS_UNDEFINED;
+}
+
+static DECLCALLBACK(bool) crVrScrCompositorRectsCounterCb(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, void *pvVisitor)
+{
+ uint32_t* pCounter = (uint32_t*)pvVisitor;
+ Assert(VBoxVrListRectsCount(&pEntry->Vr));
+ *pCounter += VBoxVrListRectsCount(&pEntry->Vr);
+ return true;
+}
+
+typedef struct VBOXVR_SCR_COMPOSITOR_RECTS_ASSIGNER
+{
+ PRTRECT paSrcRects;
+ PRTRECT paDstRects;
+ PRTRECT paDstUnstretchedRects;
+ uint32_t cRects;
+} VBOXVR_SCR_COMPOSITOR_RECTS_ASSIGNER, *PVBOXVR_SCR_COMPOSITOR_RECTS_ASSIGNER;
+
+static DECLCALLBACK(bool) crVrScrCompositorRectsAssignerCb(PVBOXVR_COMPOSITOR pCCompositor, PVBOXVR_COMPOSITOR_ENTRY pCEntry, void *pvVisitor)
+{
+ PVBOXVR_SCR_COMPOSITOR_RECTS_ASSIGNER pData = (PVBOXVR_SCR_COMPOSITOR_RECTS_ASSIGNER)pvVisitor;
+ PVBOXVR_SCR_COMPOSITOR pCompositor = VBOXVR_SCR_COMPOSITOR_FROM_COMPOSITOR(pCCompositor);
+ PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry = VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pCEntry);
+ pEntry->paSrcRects = pData->paSrcRects;
+ pEntry->paDstRects = pData->paDstRects;
+ pEntry->paDstUnstretchedRects = pData->paDstUnstretchedRects;
+ uint32_t cRects = VBoxVrListRectsCount(&pCEntry->Vr);
+ Assert(cRects);
+ Assert(cRects <= pData->cRects);
+ int rc = VBoxVrListRectsGet(&pCEntry->Vr, cRects, pEntry->paDstUnstretchedRects);
+ AssertRC(rc);
+
+ if (!pEntry->Rect.xLeft && !pEntry->Rect.yTop)
+ {
+ memcpy(pEntry->paSrcRects, pEntry->paDstUnstretchedRects, cRects * sizeof (*pEntry->paSrcRects));
+ }
+ else
+ {
+ for (uint32_t i = 0; i < cRects; ++i)
+ {
+ pEntry->paSrcRects[i].xLeft = (int32_t)((pEntry->paDstUnstretchedRects[i].xLeft - pEntry->Rect.xLeft));
+ pEntry->paSrcRects[i].yTop = (int32_t)((pEntry->paDstUnstretchedRects[i].yTop - pEntry->Rect.yTop));
+ pEntry->paSrcRects[i].xRight = (int32_t)((pEntry->paDstUnstretchedRects[i].xRight - pEntry->Rect.xLeft));
+ pEntry->paSrcRects[i].yBottom = (int32_t)((pEntry->paDstUnstretchedRects[i].yBottom - pEntry->Rect.yTop));
+ }
+ }
+
+#ifndef IN_RING0
+ if (pCompositor->StretchX != 1. || pCompositor->StretchY != 1.)
+ {
+ for (uint32_t i = 0; i < cRects; ++i)
+ {
+ if (pCompositor->StretchX != 1.)
+ {
+ pEntry->paDstRects[i].xLeft = (int32_t)(pEntry->paDstUnstretchedRects[i].xLeft * pCompositor->StretchX);
+ pEntry->paDstRects[i].xRight = (int32_t)(pEntry->paDstUnstretchedRects[i].xRight * pCompositor->StretchX);
+ }
+ if (pCompositor->StretchY != 1.)
+ {
+ pEntry->paDstRects[i].yTop = (int32_t)(pEntry->paDstUnstretchedRects[i].yTop * pCompositor->StretchY);
+ pEntry->paDstRects[i].yBottom = (int32_t)(pEntry->paDstUnstretchedRects[i].yBottom * pCompositor->StretchY);
+ }
+ }
+ }
+ else
+#endif
+ {
+ memcpy(pEntry->paDstRects, pEntry->paDstUnstretchedRects, cRects * sizeof (*pEntry->paDstUnstretchedRects));
+ }
+
+#if 0//ndef IN_RING0
+ bool canZeroX = (pCompositor->StretchX < 1.);
+ bool canZeroY = (pCompositor->StretchY < 1.);
+ if (canZeroX && canZeroY)
+ {
+ /* filter out zero rectangles*/
+ uint32_t iOrig, iNew;
+ for (iOrig = 0, iNew = 0; iOrig < cRects; ++iOrig)
+ {
+ PRTRECT pOrigRect = &pEntry->paDstRects[iOrig];
+ if (pOrigRect->xLeft != pOrigRect->xRight
+ && pOrigRect->yTop != pOrigRect->yBottom)
+ continue;
+
+ if (iNew != iOrig)
+ {
+ PRTRECT pNewRect = &pEntry->paSrcRects[iNew];
+ *pNewRect = *pOrigRect;
+ }
+
+ ++iNew;
+ }
+
+ Assert(iNew <= iOrig);
+
+ uint32_t cDiff = iOrig - iNew;
+
+ if (cDiff)
+ {
+ pCompositor->cRects -= cDiff;
+ cRects -= cDiff;
+ }
+ }
+#endif
+
+ pEntry->cRects = cRects;
+ pData->paDstRects += cRects;
+ pData->paSrcRects += cRects;
+ pData->paDstUnstretchedRects += cRects;
+ pData->cRects -= cRects;
+ return true;
+}
+
+static int crVrScrCompositorRectsCheckInit(const VBOXVR_SCR_COMPOSITOR *pcCompositor)
+{
+ VBOXVR_SCR_COMPOSITOR *pCompositor = const_cast<VBOXVR_SCR_COMPOSITOR*>(pcCompositor);
+
+ if (pCompositor->cRects != VBOXVR_SCR_COMPOSITOR_RECTS_UNDEFINED)
+ return VINF_SUCCESS;
+
+ uint32_t cRects = 0;
+ VBoxVrCompositorVisit(&pCompositor->Compositor, crVrScrCompositorRectsCounterCb, &cRects);
+
+ if (!cRects)
+ {
+ pCompositor->cRects = 0;
+ return VINF_SUCCESS;
+ }
+
+ int rc = crVrScrCompositorRectsAssignBuffer(pCompositor, cRects);
+ if (!RT_SUCCESS(rc))
+ return rc;
+
+ VBOXVR_SCR_COMPOSITOR_RECTS_ASSIGNER AssignerData;
+ AssignerData.paSrcRects = pCompositor->paSrcRects;
+ AssignerData.paDstRects = pCompositor->paDstRects;
+ AssignerData.paDstUnstretchedRects = pCompositor->paDstUnstretchedRects;
+ AssignerData.cRects = pCompositor->cRects;
+ VBoxVrCompositorVisit(&pCompositor->Compositor, crVrScrCompositorRectsAssignerCb, &AssignerData);
+ Assert(!AssignerData.cRects);
+ return VINF_SUCCESS;
+}
+
+
+static int crVrScrCompositorEntryRegionsAdd(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, uint32_t cRegions, const RTRECT *paRegions, VBOXVR_SCR_COMPOSITOR_ENTRY **ppReplacedScrEntry, uint32_t *pfChangedFlags)
+{
+ uint32_t fChangedFlags = 0;
+ PVBOXVR_COMPOSITOR_ENTRY pReplacedEntry;
+ int rc = VBoxVrCompositorEntryRegionsAdd(&pCompositor->Compositor, pEntry ? &pEntry->Ce : NULL, cRegions, paRegions, &pReplacedEntry, &fChangedFlags);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("VBoxVrCompositorEntryRegionsAdd failed, rc %d", rc));
+ return rc;
+ }
+
+ VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacedScrEntry = VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pReplacedEntry);
+
+ if (fChangedFlags & VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED)
+ {
+ crVrScrCompositorRectsInvalidate(pCompositor);
+ }
+ else if (fChangedFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED)
+ {
+ Assert(pReplacedScrEntry);
+ }
+
+ if (fChangedFlags & VBOXVR_COMPOSITOR_CF_OTHER_ENTRIES_REGIONS_CHANGED)
+ {
+ CrVrScrCompositorEntrySetAllChanged(pCompositor, true);
+ }
+ else if ((fChangedFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED) && pEntry)
+ {
+ CrVrScrCompositorEntrySetChanged(pEntry, true);
+ }
+
+ if (pfChangedFlags)
+ *pfChangedFlags = fChangedFlags;
+
+ if (ppReplacedScrEntry)
+ *ppReplacedScrEntry = pReplacedScrEntry;
+
+ return VINF_SUCCESS;
+}
+
+static int crVrScrCompositorEntryRegionsSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, uint32_t cRegions, const RTRECT *paRegions, bool *pfChanged)
+{
+ bool fChanged;
+ int rc = VBoxVrCompositorEntryRegionsSet(&pCompositor->Compositor, &pEntry->Ce, cRegions, paRegions, &fChanged);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("VBoxVrCompositorEntryRegionsSet failed, rc %d", rc));
+ return rc;
+ }
+
+ if (fChanged)
+ {
+ CrVrScrCompositorEntrySetAllChanged(pCompositor, true);
+ if (!CrVrScrCompositorEntryIsInList(pEntry))
+ {
+ pEntry->cRects = 0;
+ pEntry->paSrcRects = NULL;
+ pEntry->paDstRects = NULL;
+ pEntry->paDstUnstretchedRects = NULL;
+ }
+ crVrScrCompositorRectsInvalidate(pCompositor);
+ }
+
+
+ if (pfChanged)
+ *pfChanged = fChanged;
+ return VINF_SUCCESS;
+}
+
+static int crVrScrCompositorEntryPositionSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const RTPOINT *pPos, bool *pfChanged)
+{
+ if (pfChanged)
+ *pfChanged = false;
+ if (pEntry && (pEntry->Rect.xLeft != pPos->x || pEntry->Rect.yTop != pPos->y))
+ {
+ if (VBoxVrCompositorEntryIsInList(&pEntry->Ce))
+ {
+ int rc = VBoxVrCompositorEntryRegionsTranslate(&pCompositor->Compositor, &pEntry->Ce, pPos->x - pEntry->Rect.xLeft, pPos->y - pEntry->Rect.yTop, pfChanged);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("VBoxVrCompositorEntryRegionsTranslate failed rc %d", rc));
+ return rc;
+ }
+
+ crVrScrCompositorRectsInvalidate(pCompositor);
+ }
+
+ VBoxRectMove(&pEntry->Rect, pPos->x, pPos->y);
+ CrVrScrCompositorEntrySetChanged(pEntry, true);
+
+ if (pfChanged)
+ *pfChanged = true;
+ }
+ return VINF_SUCCESS;
+}
+
+static int crVrScrCompositorEntryEnsureRegionsBounds(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, bool *pfChanged)
+{
+ RTRECT Rect;
+ Rect.xLeft = RT_MAX(pCompositor->Rect.xLeft, pEntry->Rect.xLeft);
+ Rect.yTop = RT_MAX(pCompositor->Rect.yTop, pEntry->Rect.yTop);
+ Rect.xRight = RT_MIN(pCompositor->Rect.xRight, pEntry->Rect.xRight);
+ Rect.yBottom = RT_MIN(pCompositor->Rect.yBottom, pEntry->Rect.yBottom);
+ bool fChanged = false;
+
+ if (pfChanged)
+ *pfChanged = false;
+
+ int rc = CrVrScrCompositorEntryRegionsIntersect(pCompositor, pEntry, 1, &Rect, &fChanged);
+ if (!RT_SUCCESS(rc))
+ WARN(("CrVrScrCompositorEntryRegionsIntersect failed, rc %d", rc));
+
+ if (pfChanged)
+ *pfChanged = fChanged;
+ return rc;
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsAdd(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated, VBOXVR_SCR_COMPOSITOR_ENTRY **ppReplacedScrEntry, uint32_t *pfChangeFlags)
+{
+ int rc;
+ uint32_t fChangeFlags = 0;
+ bool fPosChanged = false;
+ RTRECT *paTranslatedRects = NULL;
+ if (pPos)
+ {
+ rc = crVrScrCompositorEntryPositionSet(pCompositor, pEntry, pPos, &fPosChanged);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("RegionsAdd: crVrScrCompositorEntryPositionSet failed rc %d", rc));
+ return rc;
+ }
+ }
+
+ if (fPosRelated)
+ {
+ if (!pEntry)
+ {
+ WARN(("Entry is expected to be specified for pos-related regions"));
+ return VERR_INVALID_PARAMETER;
+ }
+
+ if (cRegions && (pEntry->Rect.xLeft || pEntry->Rect.yTop))
+ {
+ paTranslatedRects = (RTRECT*)RTMemAlloc(sizeof (RTRECT) * cRegions);
+ if (!paTranslatedRects)
+ {
+ WARN(("RTMemAlloc failed"));
+ return VERR_NO_MEMORY;
+ }
+ memcpy (paTranslatedRects, paRegions, sizeof (RTRECT) * cRegions);
+ for (uint32_t i = 0; i < cRegions; ++i)
+ {
+ VBoxRectTranslate(&paTranslatedRects[i], pEntry->Rect.xLeft, pEntry->Rect.yTop);
+ paRegions = paTranslatedRects;
+ }
+ }
+ }
+
+ rc = crVrScrCompositorEntryRegionsAdd(pCompositor, pEntry, cRegions, paRegions, ppReplacedScrEntry, &fChangeFlags);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("crVrScrCompositorEntryRegionsAdd failed, rc %d", rc));
+ goto done;
+ }
+
+ if ((fPosChanged || (fChangeFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED)) && pEntry)
+ {
+ bool fAdjusted = false;
+ rc = crVrScrCompositorEntryEnsureRegionsBounds(pCompositor, pEntry, &fAdjusted);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("crVrScrCompositorEntryEnsureRegionsBounds failed, rc %d", rc));
+ goto done;
+ }
+
+ if (fAdjusted)
+ {
+ if (CrVrScrCompositorEntryIsUsed(pEntry))
+ {
+ fChangeFlags &= ~VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED;
+ fChangeFlags |= VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED | VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED;
+ }
+ else
+ {
+ fChangeFlags = 0;
+ }
+ }
+ }
+
+ if (fChangeFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED)
+ fPosChanged = false;
+ else if (ppReplacedScrEntry)
+ *ppReplacedScrEntry = NULL;
+
+ if (pfChangeFlags)
+ {
+ if (fPosChanged)
+ {
+ /* means entry was in list and was moved, so regions changed */
+ *pfChangeFlags = VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED | VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED | VBOXVR_COMPOSITOR_CF_OTHER_ENTRIES_REGIONS_CHANGED;
+ }
+ else
+ *pfChangeFlags = fChangeFlags;
+ }
+
+done:
+
+ if (paTranslatedRects)
+ RTMemFree(paTranslatedRects);
+
+ return rc;
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorEntryRectSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const RTRECT *pRect)
+{
+ if (!memcmp(&pEntry->Rect, pRect, sizeof (*pRect)))
+ {
+ return VINF_SUCCESS;
+ }
+ RTPOINT Point = {pRect->xLeft, pRect->yTop};
+ bool fChanged = false;
+ int rc = crVrScrCompositorEntryPositionSet(pCompositor, pEntry, &Point, &fChanged);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("crVrScrCompositorEntryPositionSet failed %d", rc));
+ return rc;
+ }
+
+ pEntry->Rect = *pRect;
+
+ if (!CrVrScrCompositorEntryIsUsed(pEntry))
+ return VINF_SUCCESS;
+
+ rc = crVrScrCompositorEntryEnsureRegionsBounds(pCompositor, pEntry, NULL);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("crVrScrCompositorEntryEnsureRegionsBounds failed, rc %d", rc));
+ return rc;
+ }
+
+ return VINF_SUCCESS;
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorEntryTexAssign(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, CR_TEXDATA *pTex)
+{
+ if (pEntry->pTex == pTex)
+ return VINF_SUCCESS;
+
+ if (pEntry->pTex)
+ CrTdRelease(pEntry->pTex);
+ if (pTex)
+ CrTdAddRef(pTex);
+ pEntry->pTex = pTex;
+ return VINF_SUCCESS;
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated, bool *pfChanged)
+{
+ /* @todo: the fChanged sate calculation is really rough now, this is enough for now though */
+ bool fChanged = false, fPosChanged = false;
+ bool fWasInList = CrVrScrCompositorEntryIsInList(pEntry);
+ RTRECT *paTranslatedRects = NULL;
+ int rc = CrVrScrCompositorEntryRemove(pCompositor, pEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("RegionsSet: CrVrScrCompositorEntryRemove failed rc %d", rc));
+ return rc;
+ }
+
+ if (pPos)
+ {
+ rc = crVrScrCompositorEntryPositionSet(pCompositor, pEntry, pPos, &fPosChanged);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("RegionsSet: crVrScrCompositorEntryPositionSet failed rc %d", rc));
+ return rc;
+ }
+ }
+
+ if (fPosRelated)
+ {
+ if (!pEntry)
+ {
+ WARN(("Entry is expected to be specified for pos-related regions"));
+ return VERR_INVALID_PARAMETER;
+ }
+
+ if (cRegions && (pEntry->Rect.xLeft || pEntry->Rect.yTop))
+ {
+ paTranslatedRects = (RTRECT*)RTMemAlloc(sizeof (RTRECT) * cRegions);
+ if (!paTranslatedRects)
+ {
+ WARN(("RTMemAlloc failed"));
+ return VERR_NO_MEMORY;
+ }
+ memcpy (paTranslatedRects, paRegions, sizeof (RTRECT) * cRegions);
+ for (uint32_t i = 0; i < cRegions; ++i)
+ {
+ VBoxRectTranslate(&paTranslatedRects[i], pEntry->Rect.xLeft, pEntry->Rect.yTop);
+ paRegions = paTranslatedRects;
+ }
+ }
+ }
+
+ rc = crVrScrCompositorEntryRegionsSet(pCompositor, pEntry, cRegions, paRegions, &fChanged);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("crVrScrCompositorEntryRegionsSet failed, rc %d", rc));
+ return rc;
+ }
+
+ if (fChanged && CrVrScrCompositorEntryIsUsed(pEntry))
+ {
+ rc = crVrScrCompositorEntryEnsureRegionsBounds(pCompositor, pEntry, NULL);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("crVrScrCompositorEntryEnsureRegionsBounds failed, rc %d", rc));
+ return rc;
+ }
+ }
+
+ if (pfChanged)
+ *pfChanged = fPosChanged || fChanged || fWasInList;
+
+ return VINF_SUCCESS;
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorEntryListIntersect(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const VBOXVR_LIST *pList2, bool *pfChanged)
+{
+ bool fChanged = false;
+ int rc = VBoxVrCompositorEntryListIntersect(&pCompositor->Compositor, &pEntry->Ce, pList2, &fChanged);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("RegionsIntersect: VBoxVrCompositorEntryRegionsIntersect failed rc %d", rc));
+ return rc;
+ }
+
+ if (fChanged)
+ {
+ CrVrScrCompositorEntrySetChanged(pEntry, true);
+ crVrScrCompositorRectsInvalidate(pCompositor);
+ }
+
+ if (pfChanged)
+ *pfChanged = fChanged;
+
+ return VINF_SUCCESS;
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsIntersect(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, uint32_t cRegions, const RTRECT *paRegions, bool *pfChanged)
+{
+ bool fChanged = false;
+ int rc = VBoxVrCompositorEntryRegionsIntersect(&pCompositor->Compositor, &pEntry->Ce, cRegions, paRegions, &fChanged);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("RegionsIntersect: VBoxVrCompositorEntryRegionsIntersect failed rc %d", rc));
+ return rc;
+ }
+
+ if (fChanged)
+ crVrScrCompositorRectsInvalidate(pCompositor);
+
+ if (pfChanged)
+ *pfChanged = fChanged;
+
+ return VINF_SUCCESS;
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorEntryListIntersectAll(PVBOXVR_SCR_COMPOSITOR pCompositor, const VBOXVR_LIST *pList2, bool *pfChanged)
+{
+ VBOXVR_SCR_COMPOSITOR_ITERATOR Iter;
+ CrVrScrCompositorIterInit(pCompositor, &Iter);
+ PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
+ int rc = VINF_SUCCESS;
+ bool fChanged = false;
+
+ while ((pEntry = CrVrScrCompositorIterNext(&Iter)) != NULL)
+ {
+ bool fTmpChanged = false;
+ int tmpRc = CrVrScrCompositorEntryListIntersect(pCompositor, pEntry, pList2, &fTmpChanged);
+ if (RT_SUCCESS(tmpRc))
+ {
+ fChanged |= fTmpChanged;
+ }
+ else
+ {
+ WARN(("CrVrScrCompositorEntryRegionsIntersect failed, rc %d", tmpRc));
+ rc = tmpRc;
+ }
+ }
+
+ if (pfChanged)
+ *pfChanged = fChanged;
+
+ return rc;
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsIntersectAll(PVBOXVR_SCR_COMPOSITOR pCompositor, uint32_t cRegions, const RTRECT *paRegions, bool *pfChanged)
+{
+ VBOXVR_SCR_COMPOSITOR_ITERATOR Iter;
+ CrVrScrCompositorIterInit(pCompositor, &Iter);
+ PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
+ int rc = VINF_SUCCESS;
+ bool fChanged = false;
+
+ while ((pEntry = CrVrScrCompositorIterNext(&Iter)) != NULL)
+ {
+ bool fTmpChanged = false;
+ int tmpRc = CrVrScrCompositorEntryRegionsIntersect(pCompositor, pEntry, cRegions, paRegions, &fTmpChanged);
+ if (RT_SUCCESS(tmpRc))
+ {
+ fChanged |= fTmpChanged;
+ }
+ else
+ {
+ WARN(("CrVrScrCompositorEntryRegionsIntersect failed, rc %d", tmpRc));
+ rc = tmpRc;
+ }
+ }
+
+ if (pfChanged)
+ *pfChanged = fChanged;
+
+ return rc;
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorEntryPosSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const RTPOINT *pPos)
+{
+ int rc = crVrScrCompositorEntryPositionSet(pCompositor, pEntry, pPos, NULL);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("RegionsSet: crVrScrCompositorEntryPositionSet failed rc %d", rc));
+ return rc;
+ }
+
+ rc = crVrScrCompositorEntryEnsureRegionsBounds(pCompositor, pEntry, NULL);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("RegionsSet: crVrScrCompositorEntryEnsureRegionsBounds failed rc %d", rc));
+ return rc;
+ }
+
+ return VINF_SUCCESS;
+}
+
+/* regions are valid until the next CrVrScrCompositor call */
+VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsGet(const VBOXVR_SCR_COMPOSITOR *pCompositor, const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry, uint32_t *pcRegions, const RTRECT **ppaSrcRegions, const RTRECT **ppaDstRegions, const RTRECT **ppaDstUnstretchedRects)
+{
+ if (CrVrScrCompositorEntryIsUsed(pEntry))
+ {
+ int rc = crVrScrCompositorRectsCheckInit(pCompositor);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("crVrScrCompositorRectsCheckInit failed, rc %d", rc));
+ return rc;
+ }
+ }
+
+ Assert(pCompositor->cRects != VBOXVR_SCR_COMPOSITOR_RECTS_UNDEFINED);
+
+ *pcRegions = pEntry->cRects;
+ if (ppaSrcRegions)
+ *ppaSrcRegions = pEntry->paSrcRects;
+ if (ppaDstRegions)
+ *ppaDstRegions = pEntry->paDstRects;
+ if (ppaDstUnstretchedRects)
+ *ppaDstUnstretchedRects = pEntry->paDstUnstretchedRects;
+
+ return VINF_SUCCESS;
+}
+
+VBOXVREGDECL(uint32_t) CrVrScrCompositorEntryFlagsCombinedGet(const VBOXVR_SCR_COMPOSITOR *pCompositor, const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry)
+{
+ return CRBLT_FOP_COMBINE(pCompositor->fFlags, pEntry->fFlags);
+}
+
+VBOXVREGDECL(void) CrVrScrCompositorEntryFlagsSet(PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, uint32_t fFlags)
+{
+ if (pEntry->fFlags == fFlags)
+ return;
+
+ pEntry->fFlags = fFlags;
+ CrVrScrCompositorEntrySetChanged(pEntry, true);
+}
+
+static void crVrScrCompositorEntryDataCleanup(PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry)
+{
+ pEntry->cRects = 0;
+ pEntry->paSrcRects = NULL;
+ pEntry->paDstRects = NULL;
+ pEntry->paDstUnstretchedRects = NULL;
+}
+
+static void crVrScrCompositorEntryDataCopy(PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, PVBOXVR_SCR_COMPOSITOR_ENTRY pToEntry)
+{
+ pToEntry->cRects = pEntry->cRects;
+ pToEntry->paSrcRects = pEntry->paSrcRects;
+ pToEntry->paDstRects = pEntry->paDstRects;
+ pToEntry->paDstUnstretchedRects = pEntry->paDstUnstretchedRects;
+ crVrScrCompositorEntryDataCleanup(pEntry);
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorEntryRemove(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry)
+{
+ if (!VBoxVrCompositorEntryRemove(&pCompositor->Compositor, &pEntry->Ce))
+ return VINF_SUCCESS;
+
+ CrVrScrCompositorEntrySetChanged(pEntry, true);
+ crVrScrCompositorEntryDataCleanup(pEntry);
+
+ crVrScrCompositorRectsInvalidate(pCompositor);
+ return VINF_SUCCESS;
+}
+
+VBOXVREGDECL(bool) CrVrScrCompositorEntryReplace(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, PVBOXVR_SCR_COMPOSITOR_ENTRY pNewEntry)
+{
+ Assert(!CrVrScrCompositorEntryIsUsed(pNewEntry));
+
+ if (!VBoxVrCompositorEntryReplace(&pCompositor->Compositor, &pEntry->Ce, &pNewEntry->Ce))
+ return false;
+
+ CrVrScrCompositorEntrySetChanged(pEntry, true);
+ crVrScrCompositorEntryDataCopy(pEntry, pNewEntry);
+ CrVrScrCompositorEntrySetChanged(pNewEntry, true);
+
+ return true;
+}
+
+static DECLCALLBACK(void) crVrScrCompositorEntryReleasedCB(const struct VBOXVR_COMPOSITOR *pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, PVBOXVR_COMPOSITOR_ENTRY pReplacingEntry)
+{
+ PVBOXVR_SCR_COMPOSITOR_ENTRY pCEntry = VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pEntry);
+
+ CrVrScrCompositorEntrySetChanged(pCEntry, true);
+
+ Assert(!CrVrScrCompositorEntryIsInList(pCEntry));
+
+ if (pReplacingEntry)
+ {
+ PVBOXVR_SCR_COMPOSITOR_ENTRY pCReplacingEntry = VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pReplacingEntry);
+ Assert(CrVrScrCompositorEntryIsInList(pCReplacingEntry));
+ pCReplacingEntry->cRects = pCEntry->cRects;
+ pCReplacingEntry->paSrcRects = pCEntry->paSrcRects;
+ pCReplacingEntry->paDstRects = pCEntry->paDstRects;
+ pCReplacingEntry->paDstUnstretchedRects = pCEntry->paDstUnstretchedRects;
+ }
+
+ if (pCEntry->pfnEntryReleased)
+ {
+ PVBOXVR_SCR_COMPOSITOR_ENTRY pCReplacingEntry = pReplacingEntry ? VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pReplacingEntry) : NULL;
+ PVBOXVR_SCR_COMPOSITOR pCConpositor = VBOXVR_SCR_COMPOSITOR_FROM_COMPOSITOR(pCompositor);
+ pCEntry->pfnEntryReleased(pCConpositor, pCEntry, pCReplacingEntry);
+ }
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorRectSet(PVBOXVR_SCR_COMPOSITOR pCompositor, const RTRECT *pRect, bool *pfChanged)
+{
+ if (!memcmp(&pCompositor->Rect, pRect, sizeof (pCompositor->Rect)))
+ {
+ if (pfChanged)
+ *pfChanged = false;
+ return VINF_SUCCESS;
+ }
+
+ pCompositor->Rect = *pRect;
+
+ VBOXVR_SCR_COMPOSITOR_ITERATOR Iter;
+ CrVrScrCompositorIterInit(pCompositor, &Iter);
+ PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
+ while ((pEntry = CrVrScrCompositorIterNext(&Iter)) != NULL)
+ {
+ int rc = crVrScrCompositorEntryEnsureRegionsBounds(pCompositor, pEntry, NULL);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("crVrScrCompositorEntryEnsureRegionsBounds failed, rc %d", rc));
+ return rc;
+ }
+ }
+
+ return VINF_SUCCESS;
+}
+
+VBOXVREGDECL(void) CrVrScrCompositorInit(PVBOXVR_SCR_COMPOSITOR pCompositor, const RTRECT *pRect)
+{
+ memset(pCompositor, 0, sizeof (*pCompositor));
+ VBoxVrCompositorInit(&pCompositor->Compositor, crVrScrCompositorEntryReleasedCB);
+ pCompositor->fFlags = CRBLT_F_LINEAR | CRBLT_F_INVERT_YCOORDS;
+ if (pRect)
+ pCompositor->Rect = *pRect;
+#ifndef IN_RING0
+ pCompositor->StretchX = 1.0;
+ pCompositor->StretchY = 1.0;
+#endif
+}
+
+VBOXVREGDECL(void) CrVrScrCompositorRegionsClear(PVBOXVR_SCR_COMPOSITOR pCompositor, bool *pfChanged)
+{
+ /* set changed flag first, while entries are in the list and we have them */
+ CrVrScrCompositorEntrySetAllChanged(pCompositor, true);
+ VBoxVrCompositorRegionsClear(&pCompositor->Compositor, pfChanged);
+ crVrScrCompositorRectsInvalidate(pCompositor);
+}
+
+VBOXVREGDECL(void) CrVrScrCompositorClear(PVBOXVR_SCR_COMPOSITOR pCompositor)
+{
+ CrVrScrCompositorRegionsClear(pCompositor, NULL);
+ if (pCompositor->paDstRects)
+ {
+ RTMemFree(pCompositor->paDstRects);
+ pCompositor->paDstRects = NULL;
+ }
+ if (pCompositor->paSrcRects)
+ {
+ RTMemFree(pCompositor->paSrcRects);
+ pCompositor->paSrcRects = NULL;
+ }
+ if (pCompositor->paDstUnstretchedRects)
+ {
+ RTMemFree(pCompositor->paDstUnstretchedRects);
+ pCompositor->paDstUnstretchedRects = NULL;
+ }
+
+ pCompositor->cRects = 0;
+ pCompositor->cRectsBuffer = 0;
+}
+
+VBOXVREGDECL(void) CrVrScrCompositorEntrySetAllChanged(PVBOXVR_SCR_COMPOSITOR pCompositor, bool fChanged)
+{
+ VBOXVR_SCR_COMPOSITOR_ITERATOR CIter;
+ PVBOXVR_SCR_COMPOSITOR_ENTRY pCurEntry;
+ CrVrScrCompositorIterInit(pCompositor, &CIter);
+
+ while ((pCurEntry = CrVrScrCompositorIterNext(&CIter)) != NULL)
+ {
+ CrVrScrCompositorEntrySetChanged(pCurEntry, fChanged);
+ }
+}
+
+#ifndef IN_RING0
+VBOXVREGDECL(void) CrVrScrCompositorSetStretching(PVBOXVR_SCR_COMPOSITOR pCompositor, float StretchX, float StretchY)
+{
+ if (pCompositor->StretchX == StretchX && pCompositor->StretchY == StretchY)
+ return;
+
+ pCompositor->StretchX = StretchX;
+ pCompositor->StretchY = StretchY;
+ crVrScrCompositorRectsInvalidate(pCompositor);
+ CrVrScrCompositorEntrySetAllChanged(pCompositor, true);
+}
+#endif
+
+/* regions are valid until the next CrVrScrCompositor call */
+VBOXVREGDECL(int) CrVrScrCompositorRegionsGet(const VBOXVR_SCR_COMPOSITOR *pCompositor, uint32_t *pcRegions, const RTRECT **ppaSrcRegions, const RTRECT **ppaDstRegions, const RTRECT **ppaDstUnstretchedRects)
+{
+ int rc = crVrScrCompositorRectsCheckInit(pCompositor);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("crVrScrCompositorRectsCheckInit failed, rc %d", rc));
+ return rc;
+ }
+
+ Assert(pCompositor->cRects != VBOXVR_SCR_COMPOSITOR_RECTS_UNDEFINED);
+
+ *pcRegions = pCompositor->cRects;
+ if (ppaSrcRegions)
+ *ppaSrcRegions = pCompositor->paSrcRects;
+ if (ppaDstRegions)
+ *ppaDstRegions = pCompositor->paDstRects;
+ if (ppaDstUnstretchedRects)
+ *ppaDstUnstretchedRects = pCompositor->paDstUnstretchedRects;
+
+ return VINF_SUCCESS;
+}
+
+typedef struct VBOXVR_SCR_COMPOSITOR_VISITOR_CB
+{
+ PFNVBOXVRSCRCOMPOSITOR_VISITOR pfnVisitor;
+ void *pvVisitor;
+} VBOXVR_SCR_COMPOSITOR_VISITOR_CB, *PVBOXVR_SCR_COMPOSITOR_VISITOR_CB;
+
+static DECLCALLBACK(bool) crVrScrCompositorVisitCb(PVBOXVR_COMPOSITOR pCCompositor, PVBOXVR_COMPOSITOR_ENTRY pCEntry, void *pvVisitor)
+{
+ PVBOXVR_SCR_COMPOSITOR_VISITOR_CB pData = (PVBOXVR_SCR_COMPOSITOR_VISITOR_CB)pvVisitor;
+ PVBOXVR_SCR_COMPOSITOR pCompositor = VBOXVR_SCR_COMPOSITOR_FROM_COMPOSITOR(pCCompositor);
+ PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry = VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pCEntry);
+ return pData->pfnVisitor(pCompositor, pEntry, pData->pvVisitor);
+}
+
+VBOXVREGDECL(void) CrVrScrCompositorVisit(PVBOXVR_SCR_COMPOSITOR pCompositor, PFNVBOXVRSCRCOMPOSITOR_VISITOR pfnVisitor, void *pvVisitor)
+{
+ VBOXVR_SCR_COMPOSITOR_VISITOR_CB Data;
+ Data.pfnVisitor = pfnVisitor;
+ Data.pvVisitor = pvVisitor;
+ VBoxVrCompositorVisit(&pCompositor->Compositor, crVrScrCompositorVisitCb, &Data);
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorClone(const VBOXVR_SCR_COMPOSITOR *pCompositor, PVBOXVR_SCR_COMPOSITOR pDstCompositor, PFNVBOXVR_SCR_COMPOSITOR_ENTRY_FOR pfnEntryFor, void* pvEntryFor)
+{
+ /* for simplicity just copy from one to another */
+ CrVrScrCompositorInit(pDstCompositor, CrVrScrCompositorRectGet(pCompositor));
+ VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR CIter;
+ const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
+ CrVrScrCompositorConstIterInit(pCompositor, &CIter);
+ int rc = VINF_SUCCESS;
+ uint32_t cRects;
+ const RTRECT *pRects;
+
+ while ((pEntry = CrVrScrCompositorConstIterNext(&CIter)) != NULL)
+ {
+ /* get source rects, that will be non-stretched and entry pos - pased */
+ rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRects, NULL, NULL, &pRects);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc));
+ return rc;
+ }
+
+ PVBOXVR_SCR_COMPOSITOR_ENTRY pDstEntry = pfnEntryFor(pEntry, pvEntryFor);
+ if (!pDstEntry)
+ {
+ WARN(("pfnEntryFor failed"));
+ return VERR_INVALID_STATE;
+ }
+
+ rc = CrVrScrCompositorEntryRegionsSet(pDstCompositor, pDstEntry, NULL, cRects, pRects, false, NULL);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc));
+ return rc;
+ }
+ }
+
+ return rc;
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorIntersectList(PVBOXVR_SCR_COMPOSITOR pCompositor, const VBOXVR_LIST *pVr, bool *pfChanged)
+{
+ VBOXVR_SCR_COMPOSITOR_ITERATOR CIter;
+ PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
+ CrVrScrCompositorIterInit(pCompositor, &CIter);
+ int rc = VINF_SUCCESS;
+ bool fChanged = false;
+
+ while ((pEntry = CrVrScrCompositorIterNext(&CIter)) != NULL)
+ {
+ bool fCurChanged = false;
+
+ rc = CrVrScrCompositorEntryListIntersect(pCompositor, pEntry, pVr, &fCurChanged);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc));
+ break;
+ }
+
+ fChanged |= fCurChanged;
+ }
+
+ if (pfChanged)
+ *pfChanged = fChanged;
+
+ return rc;
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorIntersectedList(const VBOXVR_SCR_COMPOSITOR *pCompositor, const VBOXVR_LIST *pVr, PVBOXVR_SCR_COMPOSITOR pDstCompositor, PFNVBOXVR_SCR_COMPOSITOR_ENTRY_FOR pfnEntryFor, void* pvEntryFor, bool *pfChanged)
+{
+ int rc = CrVrScrCompositorClone(pCompositor, pDstCompositor, pfnEntryFor, pvEntryFor);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("CrVrScrCompositorClone failed, rc %d", rc));
+ return rc;
+ }
+
+ rc = CrVrScrCompositorIntersectList(pDstCompositor, pVr, pfChanged);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("CrVrScrCompositorIntersectList failed, rc %d", rc));
+ CrVrScrCompositorClear(pDstCompositor);
+ return rc;
+ }
+
+ return VINF_SUCCESS;
+}
+
diff --git a/src/VBox/GuestHost/OpenGL/util/dll.c b/src/VBox/GuestHost/OpenGL/util/dll.c
index a3245a36..dbc61759 100644
--- a/src/VBox/GuestHost/OpenGL/util/dll.c
+++ b/src/VBox/GuestHost/OpenGL/util/dll.c
@@ -18,6 +18,10 @@
#include <dlfcn.h>
#endif
+#ifdef WINDOWS
+#include <Shlwapi.h>
+#endif
+
#ifdef DARWIN
#include <Carbon/Carbon.h>
@@ -147,7 +151,6 @@ int get_dll_type( const char *name ) {
#endif
-
/*
* Open the named shared library.
* If resolveGlobal is non-zero, unresolved symbols can be satisfied by
@@ -162,14 +165,77 @@ CRDLL *crDLLOpen( const char *dllname, int resolveGlobal )
{
CRDLL *dll;
char *dll_err;
+#if defined(WINDOWS)
+ WCHAR szwPath[MAX_PATH];
+ UINT cwcPath = 0;
+
+ (void) resolveGlobal;
+
+# ifndef CR_NO_GL_SYSTEM_PATH
+ if (PathIsRelative(dllname))
+ {
+ size_t cName = strlen(dllname) + 1;
+# ifdef IN_GUEST
+ cwcPath = GetSystemDirectoryW(szwPath, RT_ELEMENTS(szwPath));
+ if (!cwcPath || cwcPath >= MAX_PATH)
+ {
+ DWORD winEr = GetLastError();
+ crError("GetSystemDirectoryW failed err %d", winEr);
+ SetLastError(winEr);
+ return NULL;
+ }
+# else
+ WCHAR * pszwSlashFile;
+ cwcPath = GetModuleFileNameW(NULL, szwPath, RT_ELEMENTS(szwPath));
+ if (!cwcPath || cwcPath >= MAX_PATH)
+ {
+ DWORD winEr = GetLastError();
+ crError("GetModuleFileNameW failed err %d", winEr);
+ SetLastError(winEr);
+ return NULL;
+ }
+
+ pszwSlashFile = wcsrchr(szwPath, L'\\');
+ if (!pszwSlashFile)
+ {
+ crError("failed to match file name");
+ SetLastError(ERROR_PATH_NOT_FOUND);
+ return NULL;
+ }
+
+ cwcPath = pszwSlashFile - szwPath;
+# endif
+
+ if (cwcPath + 1 + cName > MAX_PATH)
+ {
+ crError("invalid path specified");
+ SetLastError(ERROR_FILENAME_EXCED_RANGE);
+ return NULL;
+ }
+ szwPath[cwcPath] = '\\';
+ ++cwcPath;
+ }
+
+ if (!MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, dllname, -1, &szwPath[cwcPath], MAX_PATH - cwcPath))
+ {
+ DWORD winEr = GetLastError();
+ crError("MultiByteToWideChar failed err %d", winEr);
+ SetLastError(winEr);
+ return NULL;
+ }
+# endif // CR_NO_GL_SYSTEM_PATH
+#endif
dll = (CRDLL *) crAlloc( sizeof( CRDLL ) );
dll->name = crStrdup( dllname );
#if defined(WINDOWS)
- (void) resolveGlobal;
- dll->hinstLib = LoadLibrary( dllname );
- dll_err = NULL;
+ dll->hinstLib = LoadLibraryW( szwPath );
+ if (!dll->hinstLib)
+ {
+ crError("failed to load dll %s", dllname);
+ }
+ dll_err = NULL;
#elif defined(DARWIN)
/* XXX \todo Get better error handling in here */
dll->type = get_dll_type( dllname );
diff --git a/src/VBox/GuestHost/OpenGL/util/error.c b/src/VBox/GuestHost/OpenGL/util/error.c
index 4a8254b3..48fbc577 100644
--- a/src/VBox/GuestHost/OpenGL/util/error.c
+++ b/src/VBox/GuestHost/OpenGL/util/error.c
@@ -125,7 +125,7 @@ static void __crCheckAustralia(void)
static void outputChromiumMessage( FILE *output, char *str )
{
- fprintf( output, "%s%s%s%s\n", str,
+ fprintf( output, "%s%s%s%s\n", str,
swedish_chef ? " BORK BORK BORK!" : "",
canada ? ", eh?" : "",
australia ? ", mate!" : ""
@@ -219,7 +219,7 @@ DECLEXPORT(void) crError(const char *format, ... )
MessageBox( NULL, txt, "Chromium Error", MB_OK );
}
else
- {
+ {
#endif
va_end( args );
#ifdef WINDOWS
@@ -241,10 +241,13 @@ DECLEXPORT(void) crError(const char *format, ... )
}
void crEnableWarnings(int onOff)
-{
+{
warnings_enabled = onOff;
}
+#ifdef DEBUG_misha
+# undef crWarning
+#endif
DECLEXPORT(void) crWarning(const char *format, ... )
{
if (warnings_enabled) {
@@ -268,7 +271,7 @@ DECLEXPORT(void) crWarning(const char *format, ... )
#endif
va_end( args );
-#if defined(WINDOWS) && defined(DEBUG) && !defined(IN_GUEST)
+#if defined(WINDOWS) && defined(DEBUG) && !defined(IN_GUEST) && defined(DEBUG_misha)
DebugBreak();
#endif
}
@@ -373,13 +376,13 @@ DECLEXPORT(void) crDebug(const char *format, ... )
if (crStrlen(fnamePrefix) < sizeof (str) - sizeof (pname) - 20)
{
crGetProcName(pname, 1024);
- sprintf(str, "%s_%s_%u.txt", fnamePrefix, pname,
+ sprintf(str,
#ifdef RT_OS_WINDOWS
- GetCurrentProcessId()
+ "%s_%s_%u.txt", fnamePrefix, pname, GetCurrentProcessId()
#else
- crGetPID()
+ "%s_%s_%lu.txt", fnamePrefix, pname, crGetPID()
#endif
- );
+ );
fname = &str[0];
}
}
@@ -399,7 +402,7 @@ DECLEXPORT(void) crDebug(const char *format, ... )
output = fopen( fname, "w" );
if (!output)
{
- crError( "Couldn't open debug log %s", fname );
+ crError( "Couldn't open debug log %s", fname );
}
}
else
@@ -495,18 +498,16 @@ DECLEXPORT(void) crDebug(const char *format, ... )
outputChromiumMessage( output, txt );
#else
if (!output
-# ifndef DEBUG_misha
+#ifndef DEBUG_misha
|| output==stderr
-# endif
+#endif
)
{
LogRel(("%s\n", txt));
}
else
{
-# ifndef DEBUG_misha
LogRel(("%s\n", txt));
-# endif
outputChromiumMessage(output, txt);
}
#endif
diff --git a/src/VBox/GuestHost/OpenGL/util/hash.c b/src/VBox/GuestHost/OpenGL/util/hash.c
index c91c4ad0..95f3ab65 100644
--- a/src/VBox/GuestHost/OpenGL/util/hash.c
+++ b/src/VBox/GuestHost/OpenGL/util/hash.c
@@ -9,20 +9,25 @@
#include "cr_mem.h"
#include "cr_error.h"
+#include <iprt/list.h>
+
#define CR_MAXUINT ((GLuint) 0xFFFFFFFF)
+#define CR_HASH_ID_MIN ((GLuint)1)
+#define CR_HASH_ID_MAX CR_MAXUINT
#define CR_NUM_BUCKETS 1047
typedef struct FreeElemRec {
+ RTLISTNODE Node;
GLuint min;
GLuint max;
- struct FreeElemRec *next;
- struct FreeElemRec *prev;
} FreeElem;
-typedef struct CRHashIdPoolRec {
- FreeElem *freeList;
-} CRHashIdPool;
+struct CRHashIdPool {
+ RTLISTNODE freeList;
+ GLuint min;
+ GLuint max;
+};
typedef struct CRHashNode {
unsigned long key;
@@ -40,86 +45,124 @@ struct CRHashTable {
};
-static CRHashIdPool *crAllocHashIdPool( void )
+CRHashIdPool *crAllocHashIdPoolEx( GLuint min, GLuint max )
{
- CRHashIdPool *pool = (CRHashIdPool *) crCalloc(sizeof(CRHashIdPool));
- pool->freeList = (FreeElem *) crCalloc(sizeof(FreeElem));
- pool->freeList->min = 1;
- pool->freeList->max = CR_MAXUINT;
- pool->freeList->next = NULL;
- pool->freeList->prev = NULL;
+ CRHashIdPool *pool;
+ FreeElem *elem;
+ if (min < CR_HASH_ID_MIN || max > CR_HASH_ID_MAX || min >= max)
+ {
+ crWarning("invalid min man vals");
+ return NULL;
+ }
+ pool = (CRHashIdPool *) crCalloc(sizeof(CRHashIdPool));
+ elem = (FreeElem *) crCalloc(sizeof(FreeElem));
+ RTListInit(&pool->freeList);
+ elem->min = min;
+ elem->max = max;
+ RTListAppend(&pool->freeList, &elem->Node);
+ pool->min = min;
+ pool->max = max;
return pool;
}
-static void crFreeHashIdPool( CRHashIdPool *pool )
+CRHashIdPool *crAllocHashIdPool( void )
+{
+ return crAllocHashIdPoolEx( CR_HASH_ID_MIN, CR_HASH_ID_MAX );
+}
+
+void crFreeHashIdPool( CRHashIdPool *pool )
{
FreeElem *i, *next;
- for (i = pool->freeList; i; i = next)
+ RTListForEachSafe(&pool->freeList, i, next, FreeElem, Node)
{
- next = i->next;
crFree(i);
}
+
crFree(pool);
}
+#ifdef DEBUG_misha
+static void crHashIdPoolDbgCheckConsistency(CRHashIdPool *pool)
+{
+ FreeElem *i;
+ GLuint min = 0;
+
+ /* null is a special case, it is always treated as allocated */
+ Assert(!crHashIdPoolIsIdFree(pool, 0));
+
+ /* first ensure entries have correct values */
+ RTListForEach(&pool->freeList, i, FreeElem, Node)
+ {
+ Assert(i->min >= pool->min);
+ Assert(i->max <= pool->max);
+ Assert(i->min < i->max);
+ }
+
+ /* now ensure entries do not intersect */
+ /* and that they are sorted */
+ RTListForEach(&pool->freeList, i, FreeElem, Node)
+ {
+ Assert(min < i->min);
+ min = i->max;
+ }
+}
+
+static void crHashIdPoolDbgCheckUsed( const CRHashIdPool *pool, GLuint start, GLuint count, GLboolean fUsed )
+{
+ GLuint i;
+ CRASSERT(count);
+ CRASSERT(start >= pool->min);
+ CRASSERT(start + count <= pool->max);
+ CRASSERT(start + count > start);
+ for (i = 0; i < count; ++i)
+ {
+ Assert(!fUsed == !!crHashIdPoolIsIdFree( pool, start + i ));
+ }
+}
+
+# define CR_HASH_IDPOOL_DBG_CHECK_USED(_p, _start, _count, _used) do { \
+ crHashIdPoolDbgCheckConsistency((_p)); \
+ crHashIdPoolDbgCheckUsed( (_p), (_start), (_count), (_used) ); \
+ } while (0)
+
+# define CR_HASH_IDPOOL_DBG_CHECK_CONSISTENCY(_p) do { crHashIdPoolDbgCheckConsistency((_p)); } while (0)
+#else
+# define CR_HASH_IDPOOL_DBG_CHECK_USED(_p, _start, _count, _used) do { } while (0)
+# define CR_HASH_IDPOOL_DBG_CHECK_CONSISTENCY(_p) do { } while (0)
+#endif
+
/*
* Allocate a block of <count> IDs. Return index of first one.
* Return 0 if we fail.
*/
-static GLuint crHashIdPoolAllocBlock( CRHashIdPool *pool, GLuint count )
+GLuint crHashIdPoolAllocBlock( CRHashIdPool *pool, GLuint count )
{
- FreeElem *f;
+ FreeElem *f, *next;
GLuint ret;
CRASSERT(count > 0);
-
- f = pool->freeList;
- while (f)
+ RTListForEachSafe(&pool->freeList, f, next, FreeElem, Node)
{
- if (f->max - f->min + 1 >= (GLuint) count)
+ Assert(f->max > f->min);
+ if (f->max - f->min >= (GLuint) count)
{
/* found a sufficiently large enough block */
ret = f->min;
f->min += count;
-
if (f->min == f->max)
{
- /* remove this block from linked list */
- if (f == pool->freeList)
- {
- /* remove from head */
- pool->freeList = pool->freeList->next;
- pool->freeList->prev = NULL;
- }
- else
- {
- /* remove from elsewhere */
- f->prev->next = f->next;
- f->next->prev = f->prev;
- }
+ RTListNodeRemove(&f->Node);
crFree(f);
}
-#ifdef DEBUG
- /* make sure the IDs really are allocated */
- {
- GLuint i;
- for (i = 0; i < count; i++)
- {
- //CRASSERT(crHashIdPoolIsIdUsed(pool, ret + i));
- }
- }
-#endif
-
+ CR_HASH_IDPOOL_DBG_CHECK_USED(pool, ret, count, GL_TRUE);
return ret;
}
- else {
- f = f->next;
- }
}
/* failed to find free block */
- crDebug("crHashIdPoolAllocBlock failed");
+ crWarning("crHashIdPoolAllocBlock failed");
+ CR_HASH_IDPOOL_DBG_CHECK_CONSISTENCY(pool);
return 0;
}
@@ -127,107 +170,91 @@ static GLuint crHashIdPoolAllocBlock( CRHashIdPool *pool, GLuint count )
/*
* Free a block of <count> IDs starting at <first>.
*/
-static void crHashIdPoolFreeBlock( CRHashIdPool *pool, GLuint first, GLuint count )
+void crHashIdPoolFreeBlock( CRHashIdPool *pool, GLuint first, GLuint count )
{
- FreeElem *i;
- FreeElem *newelem;
-
- /*********************************/
- /* Add the name to the freeList */
- /* Find the bracketing sequences */
+ FreeElem *f;
+ GLuint last;
+ GLuint newMax;
+ FreeElem *cur, *curNext;
- for (i = pool->freeList; i && i->next && i->next->min < first; i = i->next)
+ /* null is a special case, it is always treated as allocated */
+ if (!first)
{
- /* EMPTY BODY */
+ Assert(!crHashIdPoolIsIdFree(pool, 0));
+ ++first;
+ --count;
+ if (!count)
+ return;
}
- /* j will always be valid */
- if (!i) {
- return;
- }
- if (!i->next && i->max == first) {
- return;
- }
+ last = first + count;
+ CRASSERT(count > 0);
+ CRASSERT(last > first);
+ CRASSERT(first >= pool->min);
+ CRASSERT(last <= pool->max);
- /* Case: j:(~,first-1) */
- if (i->max + 1 == first)
+ /* the id list is sorted, first find a place to insert */
+ RTListForEach(&pool->freeList, f, FreeElem, Node)
{
- i->max += count;
- if (i->next && i->max+1 >= i->next->min)
+ Assert(f->max > f->min);
+
+ if (f->max < first)
+ continue;
+
+ if (f->min > last)
{
- /* Collapse */
- i->next->min = i->min;
- i->next->prev = i->prev;
- if (i->prev)
- {
- i->prev->next = i->next;
- }
- if (i == pool->freeList)
- {
- pool->freeList = i->next;
- }
- crFree(i);
+ /* we are here because first is > than prevEntry->max
+ * otherwise the previous loop iterations should handle that */
+ FreeElem *elem = (FreeElem *) crCalloc(sizeof(FreeElem));
+ elem->min = first;
+ elem->max = last;
+ RTListNodeInsertBefore(&f->Node, &elem->Node);
+ CR_HASH_IDPOOL_DBG_CHECK_USED(pool, first, count, GL_FALSE);
+ return;
}
- return;
- }
- /* Case: j->next: (first+1, ~) */
- if (i->next && i->next->min - count == first)
- {
- i->next->min -= count;
- if (i->max + 1 >= i->next->min)
+ /* now we have f->min <= last and f->max >= first,
+ * so we have either intersection */
+
+ if (f->min > first)
+ f->min = first; /* first is guaranteed not to touch any prev regions */
+
+ newMax = last;
+
+ if (f->max >= last)
{
- /* Collapse */
- i->next->min = i->min;
- i->next->prev = i->prev;
- if (i->prev)
- {
- i->prev->next = i->next;
- }
- if (i == pool->freeList)
- {
- pool->freeList = i->next;
- }
- crFree(i);
+ CR_HASH_IDPOOL_DBG_CHECK_USED(pool, first, count, GL_FALSE);
+ return;
}
- return;
- }
- /* Case: j: (first+1, ~) j->next: null */
- if (!i->next && i->min - count == first)
- {
- i->min -= count;
- return;
- }
+ for (cur = RTListNodeGetNext(&f->Node, FreeElem, Node),
+ curNext = RT_FROM_MEMBER(cur->Node.pNext, FreeElem, Node);
+ !RTListNodeIsDummy(&pool->freeList, cur, FreeElem, Node);
+ cur = curNext,
+ curNext = RT_FROM_MEMBER((cur)->Node.pNext, FreeElem, Node) )
+ {
+ if (cur->min > last)
+ break;
- /* allocate a new FreeElem node */
- newelem = (FreeElem *) crCalloc(sizeof(FreeElem));
- newelem->min = first;
- newelem->max = first + count - 1;
+ newMax = cur->max;
+ RTListNodeRemove(&cur->Node);
+ crFree(cur);
- /* Case: j: (~,first-(2+)) j->next: (first+(2+), ~) or null */
- if (first > i->max)
- {
- newelem->prev = i;
- newelem->next = i->next;
- if (i->next)
- {
- i->next->prev = newelem;
+ if (newMax >= last)
+ break;
}
- i->next = newelem;
- return;
- }
- /* Case: j: (first+(2+), ~) */
- /* Can only happen if j = t->freeList! */
- if (i == pool->freeList && i->min > first)
- {
- newelem->next = i;
- newelem->prev = i->prev;
- i->prev = newelem;
- pool->freeList = newelem;
+ f->max = newMax;
+ CR_HASH_IDPOOL_DBG_CHECK_USED(pool, first, count, GL_FALSE);
return;
}
+
+ /* we are here because either the list is empty or because all list rande elements have smaller values */
+ f = (FreeElem *) crCalloc(sizeof(FreeElem));
+ f->min = first;
+ f->max = last;
+ RTListAppend(&pool->freeList, &f->Node);
+ CR_HASH_IDPOOL_DBG_CHECK_USED(pool, first, count, GL_FALSE);
}
@@ -235,68 +262,116 @@ static void crHashIdPoolFreeBlock( CRHashIdPool *pool, GLuint first, GLuint coun
/*
* Mark the given Id as being allocated.
*/
-static void crHashIdPoolAllocId( CRHashIdPool *pool, GLuint id )
+GLboolean crHashIdPoolAllocId( CRHashIdPool *pool, GLuint id )
{
- FreeElem *f;
+ FreeElem *f, *next;
+
+ if (!id)
+ {
+ /* null is a special case, it is always treated as allocated */
+ Assert(!crHashIdPoolIsIdFree(pool, 0));
+ return GL_FALSE;
+ }
+
+// Assert(id != 2);
- f = pool->freeList;
- while (f)
+ RTListForEachSafe(&pool->freeList, f, next, FreeElem, Node)
{
- if (id >= f->min && id <= f->max)
+ if (f->max <= id)
+ continue;
+ if (f->min > id)
{
- /* found the block */
- if (id == f->min)
+ CR_HASH_IDPOOL_DBG_CHECK_USED(pool, id, 1, GL_TRUE);
+ return GL_FALSE;
+ }
+
+ /* f->min <= id && f->max > id */
+ if (id > f->min)
+ {
+ if (id + 1 < f->max)
{
- f->min++;
+ FreeElem *elem = (FreeElem *) crCalloc(sizeof(FreeElem));
+ elem->min = id + 1;
+ elem->max = f->max;
+ RTListNodeInsertAfter(&f->Node, &elem->Node);
}
- else if (id == f->max)
+ f->max = id;
+
+ CR_HASH_IDPOOL_DBG_CHECK_USED(pool, id, 1, GL_TRUE);
+ }
+ else
+ {
+ Assert(id == f->min);
+ if (id + 1 < f->max)
{
- f->max--;
+ f->min = id + 1;
+ CR_HASH_IDPOOL_DBG_CHECK_USED(pool, id, 1, GL_TRUE);
}
else
{
- /* somewhere in the middle - split the block */
- FreeElem *newelem = (FreeElem *) crCalloc(sizeof(FreeElem));
- newelem->min = id + 1;
- newelem->max = f->max;
- f->max = id - 1;
- newelem->next = f->next;
- if (f->next)
- f->next->prev = newelem;
- newelem->prev = f;
- f->next = newelem;
+ RTListNodeRemove(&f->Node);
+ crFree(f);
+ CR_HASH_IDPOOL_DBG_CHECK_USED(pool, id, 1, GL_TRUE);
}
- return;
}
- f = f->next;
+
+ CR_HASH_IDPOOL_DBG_CHECK_USED(pool, id, 1, GL_TRUE);
+ return GL_TRUE;
}
/* if we get here, the ID was already allocated - that's OK */
+ CR_HASH_IDPOOL_DBG_CHECK_USED(pool, id, 1, GL_TRUE);
+ return GL_FALSE;
}
/*
* Determine if the given id is free. Return GL_TRUE if so.
*/
-static GLboolean crHashIdPoolIsIdFree( const CRHashIdPool *pool, GLuint id )
+GLboolean crHashIdPoolIsIdFree( const CRHashIdPool *pool, GLuint id )
{
- FreeElem *i;
+ FreeElem *f;
+ CRASSERT(id <= pool->max);
- /* First find which region it fits in */
- for (i = pool->freeList; i && !(i->min <= id && id <= i->max); i=i->next)
+ RTListForEach(&pool->freeList, f, FreeElem, Node)
{
- /* EMPTY BODY */
- }
-
- if (i)
+ if (f->max <= id)
+ continue;
+ if (f->min > id)
+ return GL_FALSE;
return GL_TRUE;
- else
- return GL_FALSE;
+ }
+ return GL_FALSE;
}
+void crHashIdWalkKeys( CRHashIdPool *pool, CRHashIdWalkKeys walkFunc , void *data)
+{
+ FreeElem *prev = NULL, *f;
+
+ RTListForEach(&pool->freeList, f, FreeElem, Node)
+ {
+ if (prev)
+ {
+ Assert(prev->max < f->min);
+ walkFunc(prev->max+1, f->min - prev->max, data);
+ }
+ else if (f->min > pool->min)
+ {
+ walkFunc(pool->min, f->min - pool->min, data);
+ }
+
+ prev = f;
+ }
+ Assert(prev->max <= pool->max);
-CRHashTable *crAllocHashtable( void )
+ if (prev->max < pool->max)
+ {
+ walkFunc(prev->max+1, pool->max - prev->max, data);
+ }
+}
+
+CRHashTable *crAllocHashtableEx( GLuint min, GLuint max )
{
int i;
CRHashTable *hash = (CRHashTable *) crCalloc( sizeof( CRHashTable )) ;
@@ -305,13 +380,18 @@ CRHashTable *crAllocHashtable( void )
{
hash->buckets[i] = NULL;
}
- hash->idPool = crAllocHashIdPool();
+ hash->idPool = crAllocHashIdPoolEx( min, max );
#ifdef CHROMIUM_THREADSAFE
crInitMutex(&hash->mutex);
#endif
return hash;
}
+CRHashTable *crAllocHashtable( void )
+{
+ return crAllocHashtableEx(CR_HASH_ID_MIN, CR_HASH_ID_MAX);
+}
+
void crFreeHashtable( CRHashTable *hash, CRHashtableCallback deleteFunc )
{
int i;
@@ -366,17 +446,11 @@ void crHashtableUnlock(CRHashTable *h)
#endif
}
-void crHashtableWalk( CRHashTable *hash, CRHashtableWalkCallback walkFunc , void *dataPtr2)
+void crHashtableWalkUnlocked( CRHashTable *hash, CRHashtableWalkCallback walkFunc , void *dataPtr2)
{
int i;
CRHashNode *entry, *next;
- if (!hash)
- return;
-
-#ifdef CHROMIUM_THREADSAFE
- crLockMutex(&hash->mutex);
-#endif
for (i = 0; i < CR_NUM_BUCKETS; i++)
{
entry = hash->buckets[i];
@@ -390,6 +464,17 @@ void crHashtableWalk( CRHashTable *hash, CRHashtableWalkCallback walkFunc , void
entry = next;
}
}
+}
+
+void crHashtableWalk( CRHashTable *hash, CRHashtableWalkCallback walkFunc , void *dataPtr2)
+{
+ if (!hash)
+ return;
+
+#ifdef CHROMIUM_THREADSAFE
+ crLockMutex(&hash->mutex);
+#endif
+ crHashtableWalkUnlocked(hash, walkFunc , dataPtr2);
#ifdef CHROMIUM_THREADSAFE
crUnlockMutex(&hash->mutex);
#endif
@@ -417,6 +502,30 @@ void crHashtableAdd( CRHashTable *h, unsigned long key, void *data )
#endif
}
+GLboolean crHashtableAllocRegisterKey( CRHashTable *h, GLuint key)
+{
+ GLboolean fAllocated;
+#ifdef CHROMIUM_THREADSAFE
+ crLockMutex(&h->mutex);
+#endif
+ fAllocated = crHashIdPoolAllocId (h->idPool, key);
+#ifdef CHROMIUM_THREADSAFE
+ crUnlockMutex(&h->mutex);
+#endif
+ return fAllocated;
+}
+
+void crHashtableWalkKeys( CRHashTable *h, CRHashIdWalkKeys walkFunc , void *data)
+{
+#ifdef CHROMIUM_THREADSAFE
+ crLockMutex(&h->mutex);
+#endif
+ crHashIdWalkKeys(h->idPool, walkFunc , data);
+#ifdef CHROMIUM_THREADSAFE
+ crUnlockMutex(&h->mutex);
+#endif
+}
+
GLuint crHashtableAllocKeys( CRHashTable *h, GLsizei range)
{
GLuint res;
@@ -426,6 +535,14 @@ GLuint crHashtableAllocKeys( CRHashTable *h, GLsizei range)
crLockMutex(&h->mutex);
#endif
res = crHashIdPoolAllocBlock (h->idPool, range);
+#ifdef DEBUG_misha
+ Assert(res);
+ for (i = 0; i < range; ++i)
+ {
+ void *search = crHashtableSearch( h, res+i );
+ Assert(!search);
+ }
+#endif
#ifdef CHROMIUM_THREADSAFE
crUnlockMutex(&h->mutex);
#endif
@@ -446,23 +563,20 @@ void crHashtableDelete( CRHashTable *h, unsigned long key, CRHashtableCallback d
break;
beftemp = temp;
}
- if ( !temp ) {
-#ifdef CHROMIUM_THREADSAFE
- crUnlockMutex(&h->mutex);
-#endif
- return; /* not an error */
- }
- if ( beftemp )
- beftemp->next = temp->next;
- else
- h->buckets[index] = temp->next;
- h->num_elements--;
- if (temp->data && deleteFunc) {
- (*deleteFunc)( temp->data );
- }
-
- crFree( temp );
+ if ( temp )
+ {
+ if ( beftemp )
+ beftemp->next = temp->next;
+ else
+ h->buckets[index] = temp->next;
+ h->num_elements--;
+ if (temp->data && deleteFunc) {
+ (*deleteFunc)( temp->data );
+ }
+ crFree( temp );
+ }
+
crHashIdPoolFreeBlock( h->idPool, key, 1 );
#ifdef CHROMIUM_THREADSAFE
crUnlockMutex(&h->mutex);
diff --git a/src/VBox/GuestHost/OpenGL/util/htable.cpp b/src/VBox/GuestHost/OpenGL/util/htable.cpp
new file mode 100644
index 00000000..bb9434c7
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/util/htable.cpp
@@ -0,0 +1,195 @@
+/* $Id: htable.cpp $ */
+
+/** @file
+ * uint32_t handle to void simple table impl
+ */
+
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+#include <iprt/cdefs.h>
+#include <iprt/asm.h>
+#include "cr_spu.h"
+#include "cr_vreg.h"
+
+#include "cr_htable.h"
+#include "cr_spu.h"
+#include "chromium.h"
+#include "cr_error.h"
+#include "cr_net.h"
+#include "cr_rand.h"
+#include "cr_mem.h"
+#include "cr_string.h"
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/mem.h>
+#include <iprt/err.h>
+
+VBOXHTABLEDECL(int) CrHTableCreate(PCRHTABLE pTbl, uint32_t cSize)
+{
+ memset(pTbl, 0, sizeof (*pTbl));
+ if (!cSize)
+ return VINF_SUCCESS;
+ pTbl->paData = (void**)RTMemAllocZ(sizeof (pTbl->paData[0]) * cSize);
+ if (pTbl->paData)
+ {
+ pTbl->cSize = cSize;
+ return VINF_SUCCESS;
+ }
+ WARN(("RTMemAllocZ failed!"));
+ return VERR_NO_MEMORY;
+}
+
+VBOXHTABLEDECL(void) CrHTableDestroy(PCRHTABLE pTbl)
+{
+ if (!pTbl->paData)
+ return;
+
+ RTMemFree(pTbl->paData);
+}
+
+int crHTableRealloc(PCRHTABLE pTbl, uint32_t cNewSize)
+{
+ Assert(cNewSize > pTbl->cSize);
+ if (cNewSize > pTbl->cSize)
+ {
+ void **pvNewData = (void**)RTMemAllocZ(sizeof (pTbl->paData[0]) * cNewSize);
+ if (!pvNewData)
+ {
+ WARN(("RTMemAllocZ failed for size (%d)", (int)(sizeof (pTbl->paData[0]) * cNewSize)));
+ return VERR_NO_MEMORY;
+ }
+ memcpy(pvNewData, pTbl->paData, sizeof (pTbl->paData[0]) * pTbl->cSize);
+ RTMemFree(pTbl->paData);
+ pTbl->iNext2Search = pTbl->cSize;
+ pTbl->cSize = cNewSize;
+ pTbl->paData = pvNewData;
+ return VINF_SUCCESS;
+ }
+ else if (cNewSize >= pTbl->cData)
+ {
+ WARN(("not implemented"));
+ return VERR_NOT_IMPLEMENTED;
+ }
+ WARN(("invalid parameter"));
+ return VERR_INVALID_PARAMETER;
+
+}
+
+VBOXHTABLEDECL(int) CrHTableRealloc(PCRHTABLE pTbl, uint32_t cNewSize)
+{
+ return crHTableRealloc(pTbl, cNewSize);
+}
+
+VBOXHTABLEDECL(void) CrHTableEmpty(PCRHTABLE pTbl)
+{
+ pTbl->cData = 0;
+ pTbl->iNext2Search = 0;
+ if (pTbl->cSize)
+ memset(pTbl->paData, 0, sizeof (pTbl->paData[0]) * pTbl->cSize);
+}
+
+static void* crHTablePutToSlot(PCRHTABLE pTbl, uint32_t iSlot, void* pvData)
+{
+ Assert(pvData);
+ void* pvOld = pTbl->paData[iSlot];
+ pTbl->paData[iSlot] = pvData;
+ if (!pvOld)
+ ++pTbl->cData;
+ Assert(pTbl->cData <= pTbl->cSize);
+ return pvOld;
+}
+
+VBOXHTABLEDECL(int) CrHTablePutToSlot(PCRHTABLE pTbl, CRHTABLE_HANDLE hHandle, void* pvData)
+{
+ if (!pvData)
+ {
+ AssertMsgFailed(("pvData is NULL\n"));
+ return VERR_INVALID_PARAMETER;
+ }
+ uint32_t iIndex = crHTableHandle2Index(hHandle);
+ if (iIndex >= pTbl->cSize)
+ {
+ int rc = crHTableRealloc(pTbl, iIndex + RT_MAX(10, pTbl->cSize/4));
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("crHTableRealloc failed rc %d", rc));
+ return CRHTABLE_HANDLE_INVALID;
+ }
+ }
+
+ crHTablePutToSlot(pTbl, iIndex, pvData);
+
+ return VINF_SUCCESS;
+}
+
+VBOXHTABLEDECL(CRHTABLE_HANDLE) CrHTablePut(PCRHTABLE pTbl, void* pvData)
+{
+ if (!pvData)
+ {
+ AssertMsgFailed(("pvData is NULL\n"));
+ return VERR_INVALID_PARAMETER;
+ }
+
+ if (pTbl->cSize == pTbl->cData)
+ {
+ int rc = crHTableRealloc(pTbl, pTbl->cSize + RT_MAX(10, pTbl->cSize/4));
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("crHTableRealloc failed rc %d", rc));
+ return CRHTABLE_HANDLE_INVALID;
+ }
+ }
+ for (uint32_t i = pTbl->iNext2Search; ; ++i, i %= pTbl->cSize)
+ {
+ Assert(i < pTbl->cSize);
+ if (!pTbl->paData[i])
+ {
+ void *pvOld = crHTablePutToSlot(pTbl, i, pvData);
+ Assert(!pvOld);
+ pTbl->iNext2Search = i+1;
+ pTbl->iNext2Search %= pTbl->cSize;
+ return crHTableIndex2Handle(i);
+ }
+ }
+ WARN(("should not be here"));
+ return CRHTABLE_HANDLE_INVALID;
+}
+
+VBOXHTABLEDECL(void*) CrHTableRemove(PCRHTABLE pTbl, CRHTABLE_HANDLE hHandle)
+{
+ uint32_t iIndex = crHTableHandle2Index(hHandle);
+ Assert(iIndex < pTbl->cSize);
+ if (iIndex < pTbl->cSize)
+ {
+ void* pvData = pTbl->paData[iIndex];
+ if (pvData)
+ {
+ pTbl->paData[iIndex] = NULL;
+ --pTbl->cData;
+ Assert(pTbl->cData <= pTbl->cSize);
+ pTbl->iNext2Search = iIndex;
+ }
+ return pvData;
+ }
+ WARN(("invalid handle supplied %d", hHandle));
+ return NULL;
+}
+
+VBOXHTABLEDECL(void*) CrHTableGet(PCRHTABLE pTbl, CRHTABLE_HANDLE hHandle)
+{
+ uint32_t iIndex = crHTableHandle2Index(hHandle);
+ if (iIndex < pTbl->cSize)
+ return pTbl->paData[iIndex];
+ LOG(("invalid handle supplied %d", hHandle));
+ return NULL;
+}
diff --git a/src/VBox/GuestHost/OpenGL/util/net.c b/src/VBox/GuestHost/OpenGL/util/net.c
index cc2966f9..72d9f7ae 100644
--- a/src/VBox/GuestHost/OpenGL/util/net.c
+++ b/src/VBox/GuestHost/OpenGL/util/net.c
@@ -993,7 +993,7 @@ crNetRecvFlowControl( CRConnection *conn, CRMessageFlowControl *msg,
conn->InstantReclaim( conn, (CRMessage *) msg );
}
-
+#ifdef IN_GUEST
/**
* Called by the main receive function when we get a CR_MESSAGE_WRITEBACK
* message. Writeback is used to implement glGet*() functions.
@@ -1026,7 +1026,7 @@ crNetRecvReadback( CRMessageReadback *rb, unsigned int len )
(*writeback)--;
crMemcpy( dest_ptr, ((char *)rb) + sizeof(*rb), payload_len );
}
-
+#endif
/**
* This is used by the SPUs that do packing (such as Pack, Tilesort and
@@ -1104,13 +1104,21 @@ crNetDefaultRecv( CRConnection *conn, CRMessage *msg, unsigned int len )
}
break;
case CR_MESSAGE_READ_PIXELS:
- crError( "Can't handle read pixels" );
+ WARN(( "Can't handle read pixels" ));
return;
case CR_MESSAGE_WRITEBACK:
+#ifdef IN_GUEST
crNetRecvWriteback( &(pRealMsg->writeback) );
+#else
+ WARN(("CR_MESSAGE_WRITEBACK not expected\n"));
+#endif
return;
case CR_MESSAGE_READBACK:
+#ifdef IN_GUEST
crNetRecvReadback( &(pRealMsg->readback), len );
+#else
+ WARN(("CR_MESSAGE_READBACK not expected\n"));
+#endif
return;
case CR_MESSAGE_CRUT:
/* nothing */
@@ -1128,10 +1136,10 @@ crNetDefaultRecv( CRConnection *conn, CRMessage *msg, unsigned int len )
{
char string[128];
crBytesToString( string, sizeof(string), msg, len );
- crError("crNetDefaultRecv: received a bad message: type=%d buf=[%s]\n"
+ WARN(("crNetDefaultRecv: received a bad message: type=%d buf=[%s]\n"
"Did you add a new message type and forget to tell "
"crNetDefaultRecv() about it?\n",
- msg->header.type, string );
+ msg->header.type, string ));
}
}
diff --git a/src/VBox/GuestHost/OpenGL/util/pixel.c b/src/VBox/GuestHost/OpenGL/util/pixel.c
index c153dee2..5bea3e1f 100644
--- a/src/VBox/GuestHost/OpenGL/util/pixel.c
+++ b/src/VBox/GuestHost/OpenGL/util/pixel.c
@@ -11,6 +11,8 @@
#include <stdio.h>
#include <math.h>
+#include <iprt/string.h>
+
#if defined(WINDOWS)
# include <float.h>
# define isnan(x) _isnan(x)
@@ -1691,7 +1693,9 @@ void crPixelCopy3D( GLsizei width, GLsizei height, GLsizei depth,
/*@todo this should be implemented properly*/
+#ifndef DEBUG_misha
crWarning( "crPixelCopy3D: simply crMemcpy'ing from srcPtr to dstPtr" );
+#endif
if (dstFormat != srcFormat)
crWarning( "crPixelCopy3D: formats don't match!" );
if (dstType != srcType)
@@ -1841,3 +1845,19 @@ void crDumpNamedTGA(const char* fname, GLint w, GLint h, GLvoid *data)
fclose(out);
}
+
+void crDumpNamedTGAV(GLint w, GLint h, GLvoid *data, const char* fname, va_list va)
+{
+ char szName[4096];
+ RTStrPrintfV(szName, sizeof(szName), fname, va);
+ crDumpNamedTGA(szName, w, h, data);
+}
+
+void crDumpNamedTGAF(GLint w, GLint h, GLvoid *data, const char* fname, ...)
+{
+ va_list va;
+ int rc;
+ va_start(va, fname);
+ crDumpNamedTGAV(w, h, data, fname, va);
+ va_end(va);
+}
diff --git a/src/VBox/GuestHost/OpenGL/util/string.c b/src/VBox/GuestHost/OpenGL/util/string.c
index 75df10bc..0d7fff0b 100644
--- a/src/VBox/GuestHost/OpenGL/util/string.c
+++ b/src/VBox/GuestHost/OpenGL/util/string.c
@@ -6,6 +6,7 @@
#include "cr_mem.h"
#include "cr_string.h"
+#include "cr_error.h"
#include <string.h>
#include <stdio.h>
@@ -408,3 +409,125 @@ int crIsDigit(char c)
{
return c >= '0' && c <= '9';
}
+
+
+static int crStrParseGlSubver(const char * ver, const char ** pNext, bool bSpacePrefixAllowed)
+{
+ const char * initVer = ver;
+ int val = 0;
+
+ for(;;++ver)
+ {
+ if(*ver >= '0' && *ver <= '9')
+ {
+ if(!val)
+ {
+ if(*ver == '0')
+ continue;
+ }
+ else
+ {
+ val *= 10;
+ }
+ val += *ver - '0';
+ }
+ else if(*ver == '.')
+ {
+ *pNext = ver+1;
+ break;
+ }
+ else if(*ver == '\0')
+ {
+ *pNext = NULL;
+ break;
+ }
+ else if(*ver == ' ' || *ver == '\t' || *ver == 0x0d || *ver == 0x0a)
+ {
+ if(bSpacePrefixAllowed)
+ {
+ if(!val)
+ {
+ continue;
+ }
+ }
+
+ /* treat this as the end of version string */
+ *pNext = NULL;
+ break;
+ }
+ else
+ {
+ crWarning("error parsing version %s", initVer);
+ val = -1;
+ break;
+ }
+ }
+
+ return val;
+}
+
+int crStrParseGlVersion(const char * ver)
+{
+ const char * initVer = ver;
+ int tmp;
+ int iVer = crStrParseGlSubver(ver, &ver, true);
+ if(iVer <= 0)
+ {
+ crWarning("parsing major version returned %d, '%s'", iVer, initVer);
+ return iVer;
+ }
+
+ if (iVer > CR_GLVERSION_MAX_MAJOR)
+ {
+ crWarning("major version %d is bigger than the max supported %#x, this is somewhat not expected, failing", iVer, CR_GLVERSION_MAX_MAJOR);
+ return -1;
+ }
+
+ iVer <<= CR_GLVERSION_OFFSET_MAJOR;
+ if(!ver)
+ {
+ crDebug("no minor version supplied");
+ goto done;
+ }
+
+ tmp = crStrParseGlSubver(ver, &ver, false);
+ if (tmp < 0)
+ {
+ crWarning("parsing minor version failed, '%s'", initVer);
+ return -1;
+ }
+
+ if (tmp > CR_GLVERSION_MAX_MINOR)
+ {
+ crWarning("minor version %d is bigger than the max supported %#x, this is somewhat not expected, failing", iVer, CR_GLVERSION_MAX_MAJOR);
+ return -1;
+ }
+
+ iVer |= tmp << CR_GLVERSION_OFFSET_MINOR;
+
+ if (!ver)
+ {
+ crDebug("no build version supplied");
+ goto done;
+ }
+
+ tmp = crStrParseGlSubver(ver, &ver, false);
+ if (tmp < 0)
+ {
+ crWarning("parsing build version failed, '%s', using 0", initVer);
+ tmp = 0;
+ }
+
+ if (tmp > CR_GLVERSION_MAX_BUILD)
+ {
+ crWarning("build version %d is bigger than the max supported, using max supported val %#x", tmp, CR_GLVERSION_MAX_BUILD);
+ tmp = CR_GLVERSION_MAX_MAJOR;
+ }
+
+ iVer |= tmp << CR_GLVERSION_OFFSET_BUILD;
+
+done:
+ crDebug("returning version %#x for string '%s'", iVer, initVer);
+
+ return iVer;
+}
diff --git a/src/VBox/GuestHost/OpenGL/util/util.def b/src/VBox/GuestHost/OpenGL/util/util.def
index d4b6cd64..4fa97058 100644
--- a/src/VBox/GuestHost/OpenGL/util/util.def
+++ b/src/VBox/GuestHost/OpenGL/util/util.def
@@ -82,7 +82,10 @@ crHashtableSearch
crHashtableReplace
crHashtableNumElements
crHashtableWalk
+crHashtableWalkUnlocked
+crHashtableAllocRegisterKey
crAllocHashtable
+crAllocHashtableEx
crFreeHashtable
crHashtableGetDataKey
crDetermineEndianness
@@ -145,7 +148,6 @@ crGetCurrentDir
crHashtableAllocKeys
crHashtableDeleteBlock
crHashtableIsKeyUsed
-crHashtableWalk
crMatrixInit
crMatrixInitFromString
crMatrixInitFromFloats
diff --git a/src/VBox/GuestHost/OpenGL/util/vboxhgcm.c b/src/VBox/GuestHost/OpenGL/util/vboxhgcm.c
index fbf35304..d5d057d9 100644
--- a/src/VBox/GuestHost/OpenGL/util/vboxhgcm.c
+++ b/src/VBox/GuestHost/OpenGL/util/vboxhgcm.c
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2008 Oracle Corporation
+ * Copyright (C) 2008-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -195,9 +195,6 @@ typedef enum {
CR_VBOXHGCM_USERALLOCATED,
CR_VBOXHGCM_MEMORY,
CR_VBOXHGCM_MEMORY_BIG
-#ifdef RT_OS_WINDOWS
- ,CR_VBOXHGCM_DDRAW_SURFACE
-#endif
#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
,CR_VBOXHGCM_UHGSMI_BUFFER
#endif
@@ -220,9 +217,6 @@ typedef struct CRVBOXHGCMBUFFER {
PVBOXUHGSMI_BUFFER pBuffer;
#endif
};
-#ifdef RT_OS_WINDOWS
- LPDIRECTDRAWSURFACE pDDS;
-#endif
} CRVBOXHGCMBUFFER;
#ifndef RT_OS_WINDOWS
@@ -705,92 +699,6 @@ static void *_crVBoxHGCMAlloc(CRConnection *conn)
(void *) g_crvboxhgcm.bufpool,
(unsigned int)sizeof(CRVBOXHGCMBUFFER) + conn->buffer_size);
-#if defined(IN_GUEST) && defined(RT_OS_WINDOWS)
- /* Try to start DDRAW on guest side */
- if (!g_crvboxhgcm.pDirectDraw && 0)
- {
- HRESULT hr;
-
- hr = DirectDrawCreate(NULL, &g_crvboxhgcm.pDirectDraw, NULL);
- if (hr != DD_OK)
- {
- crWarning("Failed to create DirectDraw interface (%x)\n", hr);
- g_crvboxhgcm.pDirectDraw = NULL;
- }
- else
- {
- hr = IDirectDraw_SetCooperativeLevel(g_crvboxhgcm.pDirectDraw, NULL, DDSCL_NORMAL);
- if (hr != DD_OK)
- {
- crWarning("Failed to SetCooperativeLevel (%x)\n", hr);
- IDirectDraw_Release(g_crvboxhgcm.pDirectDraw);
- g_crvboxhgcm.pDirectDraw = NULL;
- }
- crDebug("Created DirectDraw and set CooperativeLevel successfully\n");
- }
- }
-
- /* Try to allocate buffer via DDRAW */
- if (g_crvboxhgcm.pDirectDraw)
- {
- DDSURFACEDESC ddsd;
- HRESULT hr;
- LPDIRECTDRAWSURFACE lpDDS;
-
- memset(&ddsd, 0, sizeof(ddsd));
- ddsd.dwSize = sizeof(ddsd);
-
- /* @todo DDSCAPS_VIDEOMEMORY ain't working for some reason
- * also, it would be better to request dwLinearSize but it fails too
- * ddsd.dwLinearSize = sizeof(CRVBOXHGCMBUFFER) + conn->buffer_size;
- */
-
- ddsd.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
- ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
- /* use 1 byte per pixel format */
- ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
- ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
- ddsd.ddpfPixelFormat.dwRGBBitCount = 8;
- ddsd.ddpfPixelFormat.dwRBitMask = 0xFF;
- ddsd.ddpfPixelFormat.dwGBitMask = 0;
- ddsd.ddpfPixelFormat.dwBBitMask = 0;
- /* request given buffer size, rounded to 1k */
- ddsd.dwWidth = 1024;
- ddsd.dwHeight = (sizeof(CRVBOXHGCMBUFFER) + conn->buffer_size + ddsd.dwWidth-1)/ddsd.dwWidth;
-
- hr = IDirectDraw_CreateSurface(g_crvboxhgcm.pDirectDraw, &ddsd, &lpDDS, NULL);
- if (hr != DD_OK)
- {
- crWarning("Failed to create DirectDraw surface (%x)\n", hr);
- }
- else
- {
- crDebug("Created DirectDraw surface (%x)\n", lpDDS);
-
- hr = IDirectDrawSurface_Lock(lpDDS, NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR, NULL);
- if (hr != DD_OK)
- {
- crWarning("Failed to lock DirectDraw surface (%x)\n", hr);
- IDirectDrawSurface_Release(lpDDS);
- }
- else
- {
- uint32_t cbLocked;
- cbLocked = (ddsd.dwFlags & DDSD_LINEARSIZE) ? ddsd.dwLinearSize : ddsd.lPitch*ddsd.dwHeight;
-
- crDebug("Locked %d bytes DirectDraw surface\n", cbLocked);
-
- buf = (CRVBOXHGCMBUFFER *) ddsd.lpSurface;
- CRASSERT(buf);
- buf->magic = CR_VBOXHGCM_BUFFER_MAGIC;
- buf->kind = CR_VBOXHGCM_DDRAW_SURFACE;
- buf->allocated = cbLocked;
- buf->pDDS = lpDDS;
- }
- }
- }
-#endif
-
/* We're either on host side, or we failed to allocate DDRAW buffer */
if (!buf)
{
@@ -800,9 +708,6 @@ static void *_crVBoxHGCMAlloc(CRConnection *conn)
buf->magic = CR_VBOXHGCM_BUFFER_MAGIC;
buf->kind = CR_VBOXHGCM_MEMORY;
buf->allocated = conn->buffer_size;
-#ifdef RT_OS_WINDOWS
- buf->pDDS = NULL;
-#endif
}
}
@@ -944,18 +849,9 @@ crVBoxHGCMWriteReadExact(CRConnection *conn, const void *buf, unsigned int len,
parms.hdr.u32Function = SHCRGL_GUEST_FN_WRITE_READ;
parms.hdr.cParms = SHCRGL_CPARMS_WRITE_READ;
- //if (bufferKind != CR_VBOXHGCM_DDRAW_SURFACE)
- {
- parms.pBuffer.type = VMMDevHGCMParmType_LinAddr_In;
- parms.pBuffer.u.Pointer.size = len;
- parms.pBuffer.u.Pointer.u.linearAddr = (uintptr_t) buf;
- }
- /*else ///@todo it fails badly, have to check why. bird: This fails because buf isn't a physical address?
- {
- parms.pBuffer.type = VMMDevHGCMParmType_PhysAddr;
- parms.pBuffer.u.Pointer.size = len;
- parms.pBuffer.u.Pointer.u.physAddr = (uintptr_t) buf;
- }*/
+ parms.pBuffer.type = VMMDevHGCMParmType_LinAddr_In;
+ parms.pBuffer.u.Pointer.size = len;
+ parms.pBuffer.u.Pointer.u.linearAddr = (uintptr_t) buf;
CRASSERT(!conn->pBuffer); //make sure there's no data to process
parms.pWriteback.type = VMMDevHGCMParmType_LinAddr_Out;
@@ -1202,9 +1098,6 @@ static void _crVBoxHGCMFree(CRConnection *conn, void *buf)
switch (hgcm_buffer->kind)
{
case CR_VBOXHGCM_MEMORY:
-#ifdef RT_OS_WINDOWS
- case CR_VBOXHGCM_DDRAW_SURFACE:
-#endif
#ifdef CHROMIUM_THREADSAFE
crLockMutex(&g_crvboxhgcm.mutex);
#endif
@@ -1283,7 +1176,7 @@ static void _crVBoxHGCMReceiveMessage(CRConnection *conn)
else
{
/* we should NEVER have redir_ptr disabled with HGSMI command now */
- CRASSERT(!conn->CmdData.pCmd);
+ CRASSERT(!conn->CmdData.pvCmd);
if ( len <= conn->buffer_size )
{
/* put in pre-allocated buffer */
@@ -1298,9 +1191,6 @@ static void _crVBoxHGCMReceiveMessage(CRConnection *conn)
hgcm_buffer->magic = CR_VBOXHGCM_BUFFER_MAGIC;
hgcm_buffer->kind = CR_VBOXHGCM_MEMORY_BIG;
hgcm_buffer->allocated = sizeof(CRVBOXHGCMBUFFER) + len;
-# ifdef RT_OS_WINDOWS
- hgcm_buffer->pDDS = NULL;
-# endif
}
hgcm_buffer->len = len;
@@ -1998,25 +1888,30 @@ _crVBoxHGSMIWriteReadExact(CRConnection *conn, PCRVBOXHGSMI_CLIENT pClient, void
else if (VERR_BUFFER_OVERFLOW == rc)
{
VBOXUHGSMI_BUFFER_TYPE_FLAGS Flags = {0};
- PVBOXUHGSMI_BUFFER pOldBuf = pClient->pHGBuffer;
+ PVBOXUHGSMI_BUFFER pNewBuf;
CRASSERT(!pClient->pvHGBuffer);
CRASSERT(cbWriteback>pClient->pHGBuffer->cbBuffer);
crDebug("Reallocating host buffer from %d to %d bytes", conn->cbHostBufferAllocated, cbWriteback);
- rc = pClient->pHgsmi->pfnBufferCreate(pClient->pHgsmi, CRVBOXHGSMI_PAGE_ALIGN(cbWriteback), Flags, &pClient->pHGBuffer);
+ rc = pClient->pHgsmi->pfnBufferCreate(pClient->pHgsmi, CRVBOXHGSMI_PAGE_ALIGN(cbWriteback), Flags, &pNewBuf);
if (RT_SUCCESS(rc))
{
- rc = pOldBuf->pfnDestroy(pOldBuf);
+ rc = pClient->pHGBuffer->pfnDestroy(pClient->pHGBuffer);
CRASSERT(RT_SUCCESS(rc));
+ pClient->pHGBuffer = pNewBuf;
+
_crVBoxHGSMIReadExact(conn, pClient/*, cbWriteback*/);
}
else
{
crWarning("_crVBoxHGSMIWriteReadExact: pfnBufferCreate(%d) failed!", CRVBOXHGSMI_PAGE_ALIGN(cbWriteback));
- crFree(conn->pHostBuffer);
- conn->cbHostBufferAllocated = cbWriteback;
- conn->pHostBuffer = crAlloc(conn->cbHostBufferAllocated);
+ if (conn->cbHostBufferAllocated < cbWriteback)
+ {
+ crFree(conn->pHostBuffer);
+ conn->cbHostBufferAllocated = cbWriteback;
+ conn->pHostBuffer = crAlloc(conn->cbHostBufferAllocated);
+ }
crVBoxHGCMReadExact(conn, NULL, cbWriteback);
}
}
@@ -2415,9 +2310,6 @@ void crVBoxHGCMInit(CRNetReceiveFuncList *rfl, CRNetCloseFuncList *cfl, unsigned
/* Callback function used to free buffer pool entries */
void crVBoxHGCMBufferFree(void *data)
{
-#ifdef RT_OS_WINDOWS
- LPDIRECTDRAWSURFACE lpDDS;
-#endif
CRVBOXHGCMBUFFER *hgcm_buffer = (CRVBOXHGCMBUFFER *) data;
CRASSERT(hgcm_buffer->magic == CR_VBOXHGCM_BUFFER_MAGIC);
@@ -2427,15 +2319,6 @@ void crVBoxHGCMBufferFree(void *data)
case CR_VBOXHGCM_MEMORY:
crFree( hgcm_buffer );
break;
-#ifdef RT_OS_WINDOWS
- case CR_VBOXHGCM_DDRAW_SURFACE:
- lpDDS = hgcm_buffer->pDDS;
- CRASSERT(lpDDS);
- IDirectDrawSurface_Unlock(lpDDS, NULL);
- IDirectDrawSurface_Release(lpDDS);
- crDebug("DDraw surface freed (%x)\n", lpDDS);
- break;
-#endif
case CR_VBOXHGCM_MEMORY_BIG:
crFree( hgcm_buffer );
break;
diff --git a/src/VBox/GuestHost/OpenGL/util/vboxhgsmi.c b/src/VBox/GuestHost/OpenGL/util/vboxhgsmi.c
index 60d5ce21..3da3496a 100644
--- a/src/VBox/GuestHost/OpenGL/util/vboxhgsmi.c
+++ b/src/VBox/GuestHost/OpenGL/util/vboxhgsmi.c
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2008 Oracle Corporation
+ * Copyright (C) 2008-2010 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
diff --git a/src/VBox/GuestHost/OpenGL/util/vreg.cpp b/src/VBox/GuestHost/OpenGL/util/vreg.cpp
new file mode 100644
index 00000000..e2cea3b3
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/util/vreg.cpp
@@ -0,0 +1,1692 @@
+/* $Id: vreg.cpp $ */
+
+/** @file
+ * Visible Regions processing API implementation
+ */
+
+/*
+ * Copyright (C) 2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+#include <cr_vreg.h>
+#include <iprt/err.h>
+#include <iprt/assert.h>
+#include <iprt/asm.h>
+
+#include <cr_error.h>
+
+#ifdef DEBUG_misha
+# define VBOXVDBG_VR_LAL_DISABLE
+#endif
+
+#ifndef IN_RING0
+#include <iprt/memcache.h>
+#ifndef VBOXVDBG_VR_LAL_DISABLE
+static RTMEMCACHE g_VBoxVrLookasideList;
+#define vboxVrRegLaAlloc(_c) RTMemCacheAlloc((_c))
+#define vboxVrRegLaFree(_c, _e) RTMemCacheFree((_c), (_e))
+DECLINLINE(int) vboxVrLaCreate(RTMEMCACHE *pCache, size_t cbElement)
+{
+ int rc = RTMemCacheCreate(pCache, cbElement,
+ 0, /* size_t cbAlignment */
+ UINT32_MAX, /* uint32_t cMaxObjects */
+ NULL, /* PFNMEMCACHECTOR pfnCtor*/
+ NULL, /* PFNMEMCACHEDTOR pfnDtor*/
+ NULL, /* void *pvUser*/
+ 0 /* uint32_t fFlags*/
+ );
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("RTMemCacheCreate failed rc %d", rc));
+ return rc;
+ }
+ return VINF_SUCCESS;
+}
+#define vboxVrLaDestroy(_c) RTMemCacheDestroy((_c))
+#endif
+#else
+# ifdef RT_OS_WINDOWS
+# ifdef PAGE_SIZE
+# undef PAGE_SIZE
+# endif
+# ifdef PAGE_SHIFT
+# undef PAGE_SHIFT
+# endif
+# define VBOX_WITH_WORKAROUND_MISSING_PACK
+# if (_MSC_VER >= 1400) && !defined(VBOX_WITH_PATCHED_DDK)
+# define _InterlockedExchange _InterlockedExchange_StupidDDKVsCompilerCrap
+# define _InterlockedExchangeAdd _InterlockedExchangeAdd_StupidDDKVsCompilerCrap
+# define _InterlockedCompareExchange _InterlockedCompareExchange_StupidDDKVsCompilerCrap
+# define _InterlockedAddLargeStatistic _InterlockedAddLargeStatistic_StupidDDKVsCompilerCrap
+# define _interlockedbittestandset _interlockedbittestandset_StupidDDKVsCompilerCrap
+# define _interlockedbittestandreset _interlockedbittestandreset_StupidDDKVsCompilerCrap
+# define _interlockedbittestandset64 _interlockedbittestandset64_StupidDDKVsCompilerCrap
+# define _interlockedbittestandreset64 _interlockedbittestandreset64_StupidDDKVsCompilerCrap
+# pragma warning(disable : 4163)
+# ifdef VBOX_WITH_WORKAROUND_MISSING_PACK
+# pragma warning(disable : 4103)
+# endif
+# include <ntddk.h>
+# pragma warning(default : 4163)
+# ifdef VBOX_WITH_WORKAROUND_MISSING_PACK
+# pragma pack()
+# pragma warning(default : 4103)
+# endif
+# undef _InterlockedExchange
+# undef _InterlockedExchangeAdd
+# undef _InterlockedCompareExchange
+# undef _InterlockedAddLargeStatistic
+# undef _interlockedbittestandset
+# undef _interlockedbittestandreset
+# undef _interlockedbittestandset64
+# undef _interlockedbittestandreset64
+# else
+# include <ntddk.h>
+# endif
+#ifndef VBOXVDBG_VR_LAL_DISABLE
+static LOOKASIDE_LIST_EX g_VBoxVrLookasideList;
+#define vboxVrRegLaAlloc(_c) ExAllocateFromLookasideListEx(&(_c))
+#define vboxVrRegLaFree(_c, _e) ExFreeToLookasideListEx(&(_c), (_e))
+#define VBOXWDDMVR_MEMTAG 'vDBV'
+DECLINLINE(int) vboxVrLaCreate(LOOKASIDE_LIST_EX *pCache, size_t cbElement)
+{
+ NTSTATUS Status = ExInitializeLookasideListEx(pCache,
+ NULL, /* PALLOCATE_FUNCTION_EX Allocate */
+ NULL, /* PFREE_FUNCTION_EX Free */
+ NonPagedPool,
+ 0, /* ULONG Flags */
+ cbElement,
+ VBOXWDDMVR_MEMTAG,
+ 0 /* USHORT Depth - reserved, must be null */
+ );
+ if (!NT_SUCCESS(Status))
+ {
+ WARN(("ExInitializeLookasideListEx failed, Status (0x%x)", Status));
+ return VERR_GENERAL_FAILURE;
+ }
+
+ return VINF_SUCCESS;
+}
+#define vboxVrLaDestroy(_c) ExDeleteLookasideListEx(&(_c))
+#endif
+# else
+# error "port me!"
+# endif
+#endif
+
+static volatile int32_t g_cVBoxVrInits = 0;
+
+static PVBOXVR_REG vboxVrRegCreate()
+{
+#ifndef VBOXVDBG_VR_LAL_DISABLE
+ PVBOXVR_REG pReg = (PVBOXVR_REG)vboxVrRegLaAlloc(g_VBoxVrLookasideList);
+ if (!pReg)
+ {
+ WARN(("ExAllocateFromLookasideListEx failed!"));
+ }
+ return pReg;
+#else
+ return (PVBOXVR_REG)RTMemAlloc(sizeof (VBOXVR_REG));
+#endif
+}
+
+static void vboxVrRegTerm(PVBOXVR_REG pReg)
+{
+#ifndef VBOXVDBG_VR_LAL_DISABLE
+ vboxVrRegLaFree(g_VBoxVrLookasideList, pReg);
+#else
+ RTMemFree(pReg);
+#endif
+}
+
+VBOXVREGDECL(void) VBoxVrListClear(PVBOXVR_LIST pList)
+{
+ PVBOXVR_REG pReg, pRegNext;
+
+ RTListForEachSafe(&pList->ListHead, pReg, pRegNext, VBOXVR_REG, ListEntry)
+ {
+ vboxVrRegTerm(pReg);
+ }
+ VBoxVrListInit(pList);
+}
+
+/* moves list data to pDstList and empties the pList */
+VBOXVREGDECL(void) VBoxVrListMoveTo(PVBOXVR_LIST pList, PVBOXVR_LIST pDstList)
+{
+ *pDstList = *pList;
+ pDstList->ListHead.pNext->pPrev = &pDstList->ListHead;
+ pDstList->ListHead.pPrev->pNext = &pDstList->ListHead;
+ VBoxVrListInit(pList);
+}
+
+#define VBOXVR_MEMTAG 'vDBV'
+
+VBOXVREGDECL(int) VBoxVrInit()
+{
+ int32_t cNewRefs = ASMAtomicIncS32(&g_cVBoxVrInits);
+ Assert(cNewRefs >= 1);
+ Assert(cNewRefs == 1); /* <- debugging */
+ if (cNewRefs > 1)
+ return VINF_SUCCESS;
+
+#ifndef VBOXVDBG_VR_LAL_DISABLE
+ int rc = vboxVrLaCreate(&g_VBoxVrLookasideList, sizeof (VBOXVR_REG));
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("ExInitializeLookasideListEx failed, rc (%d)", rc));
+ return rc;
+ }
+#endif
+
+ return VINF_SUCCESS;
+}
+
+VBOXVREGDECL(void) VBoxVrTerm()
+{
+ int32_t cNewRefs = ASMAtomicDecS32(&g_cVBoxVrInits);
+ Assert(cNewRefs >= 0);
+ if (cNewRefs > 0)
+ return;
+
+#ifndef VBOXVDBG_VR_LAL_DISABLE
+ vboxVrLaDestroy(g_VBoxVrLookasideList);
+#endif
+}
+
+typedef DECLCALLBACK(int) FNVBOXVR_CB_COMPARATOR(const VBOXVR_REG *pReg1, const VBOXVR_REG *pReg2);
+typedef FNVBOXVR_CB_COMPARATOR *PFNVBOXVR_CB_COMPARATOR;
+
+static DECLCALLBACK(int) vboxVrRegNonintersectedComparator(const RTRECT* pRect1, const RTRECT* pRect2)
+{
+ Assert(!VBoxRectIsIntersect(pRect1, pRect2));
+ if (pRect1->yTop != pRect2->yTop)
+ return pRect1->yTop - pRect2->yTop;
+ return pRect1->xLeft - pRect2->xLeft;
+}
+
+#ifdef DEBUG_misha
+static void vboxVrDbgListDoVerify(PVBOXVR_LIST pList)
+{
+ PVBOXVR_REG pReg1, pReg2;
+ RTListForEach(&pList->ListHead, pReg1, VBOXVR_REG, ListEntry)
+ {
+ Assert(!VBoxRectIsZero(&pReg1->Rect));
+ for (RTLISTNODE *pEntry2 = pReg1->ListEntry.pNext; pEntry2 != &pList->ListHead; pEntry2 = pEntry2->pNext)
+ {
+ pReg2 = PVBOXVR_REG_FROM_ENTRY(pEntry2);
+ Assert(vboxVrRegNonintersectedComparator(&pReg1->Rect, &pReg2->Rect) < 0);
+ }
+ }
+}
+
+#define vboxVrDbgListVerify vboxVrDbgListDoVerify
+#else
+#define vboxVrDbgListVerify(_p) do {} while (0)
+#endif
+
+static int vboxVrListUniteIntersection(PVBOXVR_LIST pList, PVBOXVR_LIST pIntersection);
+
+#define VBOXVR_INVALID_COORD (~0U)
+
+DECLINLINE(void) vboxVrListRegAdd(PVBOXVR_LIST pList, PVBOXVR_REG pReg, PRTLISTNODE pPlace, bool fAfter)
+{
+ if (fAfter)
+ RTListPrepend(pPlace, &pReg->ListEntry);
+ else
+ RTListAppend(pPlace, &pReg->ListEntry);
+ ++pList->cEntries;
+ vboxVrDbgListVerify(pList);
+}
+
+DECLINLINE(void) vboxVrListRegRemove(PVBOXVR_LIST pList, PVBOXVR_REG pReg)
+{
+ RTListNodeRemove(&pReg->ListEntry);
+ --pList->cEntries;
+ vboxVrDbgListVerify(pList);
+}
+
+static void vboxVrListRegAddOrder(PVBOXVR_LIST pList, PRTLISTNODE pMemberEntry, PVBOXVR_REG pReg)
+{
+ do
+ {
+ if (pMemberEntry != &pList->ListHead)
+ {
+ PVBOXVR_REG pMemberReg = PVBOXVR_REG_FROM_ENTRY(pMemberEntry);
+ if (vboxVrRegNonintersectedComparator(&pMemberReg->Rect, &pReg->Rect) < 0)
+ {
+ pMemberEntry = pMemberEntry->pNext;
+ continue;
+ }
+ }
+ vboxVrListRegAdd(pList, pReg, pMemberEntry, false);
+ break;
+ } while (1);
+}
+
+static void vboxVrListAddNonintersected(PVBOXVR_LIST pList1, PVBOXVR_LIST pList2)
+{
+ PRTLISTNODE pEntry1 = pList1->ListHead.pNext;
+
+ for (PRTLISTNODE pEntry2 = pList2->ListHead.pNext; pEntry2 != &pList2->ListHead; pEntry2 = pList2->ListHead.pNext)
+ {
+ PVBOXVR_REG pReg2 = PVBOXVR_REG_FROM_ENTRY(pEntry2);
+ do {
+ if (pEntry1 != &pList1->ListHead)
+ {
+ PVBOXVR_REG pReg1 = PVBOXVR_REG_FROM_ENTRY(pEntry1);
+ if (vboxVrRegNonintersectedComparator(&pReg1->Rect, &pReg2->Rect) < 0)
+ {
+ pEntry1 = pEntry1->pNext;
+ continue;
+ }
+ }
+ vboxVrListRegRemove(pList2, pReg2);
+ vboxVrListRegAdd(pList1, pReg2, pEntry1, false);
+ break;
+ } while (1);
+ }
+
+ Assert(VBoxVrListIsEmpty(pList2));
+}
+
+static int vboxVrListRegIntersectSubstNoJoin(PVBOXVR_LIST pList1, PVBOXVR_REG pReg1, const RTRECT * pRect2)
+{
+ uint32_t topLim = VBOXVR_INVALID_COORD;
+ uint32_t bottomLim = VBOXVR_INVALID_COORD;
+ RTLISTNODE List;
+ PVBOXVR_REG pBottomReg = NULL;
+#ifdef DEBUG_misha
+ RTRECT tmpRect = pReg1->Rect;
+ vboxVrDbgListVerify(pList1);
+#endif
+ Assert(!VBoxRectIsZero(pRect2));
+
+ RTListInit(&List);
+
+ Assert(VBoxRectIsIntersect(&pReg1->Rect, pRect2));
+
+ if (pReg1->Rect.yTop < pRect2->yTop)
+ {
+ Assert(pRect2->yTop < pReg1->Rect.yBottom);
+ PVBOXVR_REG pRegResult = vboxVrRegCreate();
+ pRegResult->Rect.yTop = pReg1->Rect.yTop;
+ pRegResult->Rect.xLeft = pReg1->Rect.xLeft;
+ pRegResult->Rect.yBottom = pRect2->yTop;
+ pRegResult->Rect.xRight = pReg1->Rect.xRight;
+ topLim = pRect2->yTop;
+ RTListAppend(&List, &pRegResult->ListEntry);
+ }
+
+ if (pReg1->Rect.yBottom > pRect2->yBottom)
+ {
+ Assert(pRect2->yBottom > pReg1->Rect.yTop);
+ PVBOXVR_REG pRegResult = vboxVrRegCreate();
+ pRegResult->Rect.yTop = pRect2->yBottom;
+ pRegResult->Rect.xLeft = pReg1->Rect.xLeft;
+ pRegResult->Rect.yBottom = pReg1->Rect.yBottom;
+ pRegResult->Rect.xRight = pReg1->Rect.xRight;
+ bottomLim = pRect2->yBottom;
+ pBottomReg = pRegResult;
+ }
+
+ if (pReg1->Rect.xLeft < pRect2->xLeft)
+ {
+ Assert(pRect2->xLeft < pReg1->Rect.xRight);
+ PVBOXVR_REG pRegResult = vboxVrRegCreate();
+ pRegResult->Rect.yTop = topLim == VBOXVR_INVALID_COORD ? pReg1->Rect.yTop : topLim;
+ pRegResult->Rect.xLeft = pReg1->Rect.xLeft;
+ pRegResult->Rect.yBottom = bottomLim == VBOXVR_INVALID_COORD ? pReg1->Rect.yBottom : bottomLim;
+ pRegResult->Rect.xRight = pRect2->xLeft;
+ RTListAppend(&List, &pRegResult->ListEntry);
+ }
+
+ if (pReg1->Rect.xRight > pRect2->xRight)
+ {
+ Assert(pRect2->xRight > pReg1->Rect.xLeft);
+ PVBOXVR_REG pRegResult = vboxVrRegCreate();
+ pRegResult->Rect.yTop = topLim == VBOXVR_INVALID_COORD ? pReg1->Rect.yTop : topLim;
+ pRegResult->Rect.xLeft = pRect2->xRight;
+ pRegResult->Rect.yBottom = bottomLim == VBOXVR_INVALID_COORD ? pReg1->Rect.yBottom : bottomLim;
+ pRegResult->Rect.xRight = pReg1->Rect.xRight;
+ RTListAppend(&List, &pRegResult->ListEntry);
+ }
+
+ if (pBottomReg)
+ RTListAppend(&List, &pBottomReg->ListEntry);
+
+ PRTLISTNODE pMemberEntry = pReg1->ListEntry.pNext;
+ vboxVrListRegRemove(pList1, pReg1);
+ vboxVrRegTerm(pReg1);
+
+ if (RTListIsEmpty(&List))
+ return VINF_SUCCESS; /* the region is covered by the pRect2 */
+
+ PRTLISTNODE pEntry = List.pNext, pNext;
+ for (; pEntry != &List; pEntry = pNext)
+ {
+ pNext = pEntry->pNext;
+ PVBOXVR_REG pReg = PVBOXVR_REG_FROM_ENTRY(pEntry);
+
+ vboxVrListRegAddOrder(pList1, pMemberEntry, pReg);
+ pMemberEntry = pEntry->pNext; /* the following elements should go after the given pEntry since they are ordered already */
+ }
+ return VINF_SUCCESS;
+}
+
+/* @returns Entry to be used for continuing the rectangles iterations being made currently on the callback call.
+ * ListHead is returned to break the current iteration
+ * @param ppNext specifies next reg entry to be used for iteration. the default is pReg1->ListEntry.pNext */
+typedef DECLCALLBACK(PRTLISTNODE) FNVBOXVR_CB_INTERSECTED_VISITOR(PVBOXVR_LIST pList1, PVBOXVR_REG pReg1, const RTRECT * pRect2, void *pvContext, PRTLISTNODE *ppNext);
+typedef FNVBOXVR_CB_INTERSECTED_VISITOR *PFNVBOXVR_CB_INTERSECTED_VISITOR;
+
+static void vboxVrListVisitIntersected(PVBOXVR_LIST pList1, uint32_t cRects, const RTRECT *aRects, PFNVBOXVR_CB_INTERSECTED_VISITOR pfnVisitor, void* pvVisitor)
+{
+ PRTLISTNODE pEntry1 = pList1->ListHead.pNext;
+ PRTLISTNODE pNext1;
+ uint32_t iFirst2 = 0;
+
+ for (; pEntry1 != &pList1->ListHead; pEntry1 = pNext1)
+ {
+ pNext1 = pEntry1->pNext;
+ PVBOXVR_REG pReg1 = PVBOXVR_REG_FROM_ENTRY(pEntry1);
+ for (uint32_t i = iFirst2; i < cRects; ++i)
+ {
+ const RTRECT *pRect2 = &aRects[i];
+ if (VBoxRectIsZero(pRect2))
+ continue;
+
+ if (!VBoxRectIsIntersect(&pReg1->Rect, pRect2))
+ continue;
+
+ /* the visitor can modify the list 1, apply necessary adjustments after it */
+ pEntry1 = pfnVisitor (pList1, pReg1, pRect2, pvVisitor, &pNext1);
+ if (pEntry1 == &pList1->ListHead)
+ break;
+ else
+ pReg1 = PVBOXVR_REG_FROM_ENTRY(pEntry1);
+ }
+ }
+}
+
+/* @returns Entry to be iterated next. ListHead is returned to break the iteration
+ *
+ */
+typedef DECLCALLBACK(PRTLISTNODE) FNVBOXVR_CB_NONINTERSECTED_VISITOR(PVBOXVR_LIST pList1, PVBOXVR_REG pReg1, void *pvContext);
+typedef FNVBOXVR_CB_NONINTERSECTED_VISITOR *PFNVBOXVR_CB_NONINTERSECTED_VISITOR;
+
+static void vboxVrListVisitNonintersected(PVBOXVR_LIST pList1, uint32_t cRects, const RTRECT *aRects, PFNVBOXVR_CB_NONINTERSECTED_VISITOR pfnVisitor, void* pvVisitor)
+{
+ PRTLISTNODE pEntry1 = pList1->ListHead.pNext;
+ PRTLISTNODE pNext1;
+ uint32_t iFirst2 = 0;
+
+ for (; pEntry1 != &pList1->ListHead; pEntry1 = pNext1)
+ {
+ PVBOXVR_REG pReg1 = PVBOXVR_REG_FROM_ENTRY(pEntry1);
+ uint32_t i = iFirst2;
+ for (; i < cRects; ++i)
+ {
+ const RTRECT *pRect2 = &aRects[i];
+ if (VBoxRectIsZero(pRect2))
+ continue;
+
+ if (VBoxRectIsIntersect(&pReg1->Rect, pRect2))
+ break;
+ }
+
+ if (i == cRects)
+ pNext1 = pfnVisitor(pList1, pReg1, pvVisitor);
+ else
+ pNext1 = pEntry1->pNext;
+ }
+}
+
+static void vboxVrListJoinRectsHV(PVBOXVR_LIST pList, bool fHorizontal)
+{
+ PRTLISTNODE pNext1, pNext2;
+
+ for (PRTLISTNODE pEntry1 = pList->ListHead.pNext; pEntry1 != &pList->ListHead; pEntry1 = pNext1)
+ {
+ PVBOXVR_REG pReg1 = PVBOXVR_REG_FROM_ENTRY(pEntry1);
+ pNext1 = pEntry1->pNext;
+ for (PRTLISTNODE pEntry2 = pEntry1->pNext; pEntry2 != &pList->ListHead; pEntry2 = pNext2)
+ {
+ PVBOXVR_REG pReg2 = PVBOXVR_REG_FROM_ENTRY(pEntry2);
+ pNext2 = pEntry2->pNext;
+ if (fHorizontal)
+ {
+ if (pReg1->Rect.yTop == pReg2->Rect.yTop)
+ {
+ if (pReg1->Rect.xRight == pReg2->Rect.xLeft)
+ {
+ /* join rectangles */
+ vboxVrListRegRemove(pList, pReg2);
+ if (pReg1->Rect.yBottom > pReg2->Rect.yBottom)
+ {
+ int32_t oldRight1 = pReg1->Rect.xRight;
+ int32_t oldBottom1 = pReg1->Rect.yBottom;
+ pReg1->Rect.xRight = pReg2->Rect.xRight;
+ pReg1->Rect.yBottom = pReg2->Rect.yBottom;
+
+ vboxVrDbgListVerify(pList);
+
+ pReg2->Rect.xLeft = pReg1->Rect.xLeft;
+ pReg2->Rect.yTop = pReg1->Rect.yBottom;
+ pReg2->Rect.xRight = oldRight1;
+ pReg2->Rect.yBottom = oldBottom1;
+ vboxVrListRegAddOrder(pList, pReg1->ListEntry.pNext, pReg2);
+ /* restart the pNext1 & pNext2 since regs are splitted into smaller ones in y dimension
+ * and thus can match one of the previous rects */
+ pNext1 = pList->ListHead.pNext;
+ break;
+ }
+ else if (pReg1->Rect.yBottom < pReg2->Rect.yBottom)
+ {
+ pReg1->Rect.xRight = pReg2->Rect.xRight;
+ vboxVrDbgListVerify(pList);
+ pReg2->Rect.yTop = pReg1->Rect.yBottom;
+ vboxVrListRegAddOrder(pList, pReg1->ListEntry.pNext, pReg2);
+ /* restart the pNext1 & pNext2 since regs are splitted into smaller ones in y dimension
+ * and thus can match one of the previous rects */
+ pNext1 = pList->ListHead.pNext;
+ break;
+ }
+ else
+ {
+ pReg1->Rect.xRight = pReg2->Rect.xRight;
+ vboxVrDbgListVerify(pList);
+ /* reset the pNext1 since it could be the pReg2 being destroyed */
+ pNext1 = pEntry1->pNext;
+ /* pNext2 stays the same since it is pReg2->ListEntry.pNext, which is kept intact */
+ vboxVrRegTerm(pReg2);
+ }
+ }
+ continue;
+ }
+ else if (pReg1->Rect.yBottom == pReg2->Rect.yBottom)
+ {
+ Assert(pReg1->Rect.yTop < pReg2->Rect.yTop); /* <- since pReg1 > pReg2 && pReg1->Rect.yTop != pReg2->Rect.yTop*/
+ if (pReg1->Rect.xRight == pReg2->Rect.xLeft)
+ {
+ /* join rectangles */
+ vboxVrListRegRemove(pList, pReg2);
+
+ pReg1->Rect.yBottom = pReg2->Rect.yTop;
+ vboxVrDbgListVerify(pList);
+ pReg2->Rect.xLeft = pReg1->Rect.xLeft;
+
+ vboxVrListRegAddOrder(pList, pNext2, pReg2);
+
+ /* restart the pNext1 & pNext2 since regs are splitted into smaller ones in y dimension
+ * and thus can match one of the previous rects */
+ pNext1 = pList->ListHead.pNext;
+ break;
+ }
+ else if (pReg1->Rect.xLeft == pReg2->Rect.xRight)
+ {
+ /* join rectangles */
+ vboxVrListRegRemove(pList, pReg2);
+
+ pReg1->Rect.yBottom = pReg2->Rect.yTop;
+ vboxVrDbgListVerify(pList);
+ pReg2->Rect.xRight = pReg1->Rect.xRight;
+
+ vboxVrListRegAddOrder(pList, pNext2, pReg2);
+
+ /* restart the pNext1 & pNext2 since regs are splitted into smaller ones in y dimension
+ * and thus can match one of the previous rects */
+ pNext1 = pList->ListHead.pNext;
+ break;
+ }
+ continue;
+ }
+ }
+ else
+ {
+ if (pReg1->Rect.yBottom == pReg2->Rect.yTop)
+ {
+ if (pReg1->Rect.xLeft == pReg2->Rect.xLeft)
+ {
+ if (pReg1->Rect.xRight == pReg2->Rect.xRight)
+ {
+ /* join rects */
+ vboxVrListRegRemove(pList, pReg2);
+
+ pReg1->Rect.yBottom = pReg2->Rect.yBottom;
+ vboxVrDbgListVerify(pList);
+
+ /* reset the pNext1 since it could be the pReg2 being destroyed */
+ pNext1 = pEntry1->pNext;
+ /* pNext2 stays the same since it is pReg2->ListEntry.pNext, which is kept intact */
+ vboxVrRegTerm(pReg2);
+ continue;
+ }
+ /* no more to be done for for pReg1 */
+ break;
+ }
+ else if (pReg1->Rect.xRight > pReg2->Rect.xLeft)
+ {
+ /* no more to be done for for pReg1 */
+ break;
+ }
+
+ continue;
+ }
+ else if (pReg1->Rect.yBottom < pReg2->Rect.yTop)
+ {
+ /* no more to be done for for pReg1 */
+ break;
+ }
+ }
+ }
+ }
+}
+
+static void vboxVrListJoinRects(PVBOXVR_LIST pList)
+{
+ vboxVrListJoinRectsHV(pList, true);
+ vboxVrListJoinRectsHV(pList, false);
+}
+
+typedef struct VBOXVR_CBDATA_SUBST
+{
+ int rc;
+ bool fChanged;
+} VBOXVR_CBDATA_SUBST, *PVBOXVR_CBDATA_SUBST;
+
+static DECLCALLBACK(PRTLISTNODE) vboxVrListSubstNoJoinCb(PVBOXVR_LIST pList, PVBOXVR_REG pReg1, const RTRECT *pRect2, void *pvContext, PRTLISTNODE *ppNext)
+{
+ PVBOXVR_CBDATA_SUBST pData = (PVBOXVR_CBDATA_SUBST)pvContext;
+ /* store the prev to get the new pNext out of it*/
+ PRTLISTNODE pPrev = pReg1->ListEntry.pPrev;
+ pData->fChanged = true;
+
+ Assert(VBoxRectIsIntersect(&pReg1->Rect, pRect2));
+
+ /* NOTE: the pReg1 will be invalid after the vboxVrListRegIntersectSubstNoJoin call!!! */
+ int rc = vboxVrListRegIntersectSubstNoJoin(pList, pReg1, pRect2);
+ if (RT_SUCCESS(rc))
+ {
+ *ppNext = pPrev->pNext;
+ return &pList->ListHead;
+ }
+ WARN(("vboxVrListRegIntersectSubstNoJoin failed!"));
+ Assert(!RT_SUCCESS(rc));
+ pData->rc = rc;
+ *ppNext = &pList->ListHead;
+ return &pList->ListHead;
+}
+
+static int vboxVrListSubstNoJoin(PVBOXVR_LIST pList, uint32_t cRects, const RTRECT * aRects, bool *pfChanged)
+{
+ if (pfChanged)
+ *pfChanged = false;
+
+ if (VBoxVrListIsEmpty(pList))
+ return VINF_SUCCESS;
+
+ VBOXVR_CBDATA_SUBST Data;
+ Data.rc = VINF_SUCCESS;
+ Data.fChanged = false;
+
+ vboxVrListVisitIntersected(pList, cRects, aRects, vboxVrListSubstNoJoinCb, &Data);
+ if (!RT_SUCCESS(Data.rc))
+ {
+ WARN(("vboxVrListVisitIntersected failed!"));
+ return Data.rc;
+ }
+
+ if (pfChanged)
+ *pfChanged = Data.fChanged;
+
+ return VINF_SUCCESS;
+}
+
+#if 0
+static const RTRECT * vboxVrRectsOrder(uint32_t cRects, const RTRECT * aRects)
+{
+#ifdef DEBUG
+ {
+ for (uint32_t i = 0; i < cRects; ++i)
+ {
+ RTRECT *pRectI = &aRects[i];
+ for (uint32_t j = i + 1; j < cRects; ++j)
+ {
+ RTRECT *pRectJ = &aRects[j];
+ Assert(!VBoxRectIsIntersect(pRectI, pRectJ));
+ }
+ }
+ }
+#endif
+
+ RTRECT * pRects = (RTRECT *)aRects;
+ /* check if rects are ordered already */
+ for (uint32_t i = 0; i < cRects - 1; ++i)
+ {
+ RTRECT *pRect1 = &pRects[i];
+ RTRECT *pRect2 = &pRects[i+1];
+ if (vboxVrRegNonintersectedComparator(pRect1, pRect2) < 0)
+ continue;
+
+ WARN(("rects are unoreded!"));
+
+ if (pRects == aRects)
+ {
+ pRects = (RTRECT *)RTMemAlloc(sizeof (RTRECT) * cRects);
+ if (!pRects)
+ {
+ WARN(("RTMemAlloc failed!"));
+ return NULL;
+ }
+
+ memcpy(pRects, aRects, sizeof (RTRECT) * cRects);
+ }
+
+ Assert(pRects != aRects);
+
+ int j = (int)i - 1;
+ do {
+ RTRECT Tmp = *pRect1;
+ *pRect1 = *pRect2;
+ *pRect2 = Tmp;
+
+ if (j < 0)
+ break;
+
+ if (vboxVrRegNonintersectedComparator(pRect1, pRect1-1) > 0)
+ break;
+
+ pRect2 = pRect1--;
+ --j;
+ } while (1);
+ }
+
+ return pRects;
+}
+#endif
+
+VBOXVREGDECL(void) VBoxVrListTranslate(PVBOXVR_LIST pList, int32_t x, int32_t y)
+{
+ for (PRTLISTNODE pEntry1 = pList->ListHead.pNext; pEntry1 != &pList->ListHead; pEntry1 = pEntry1->pNext)
+ {
+ PVBOXVR_REG pReg1 = PVBOXVR_REG_FROM_ENTRY(pEntry1);
+ VBoxRectTranslate(&pReg1->Rect, x, y);
+ }
+}
+
+static DECLCALLBACK(PRTLISTNODE) vboxVrListIntersectNoJoinNonintersectedCb(PVBOXVR_LIST pList1, PVBOXVR_REG pReg1, void *pvContext)
+{
+ VBOXVR_CBDATA_SUBST *pData = (VBOXVR_CBDATA_SUBST*)pvContext;
+
+ PRTLISTNODE pNext = pReg1->ListEntry.pNext;
+
+ vboxVrDbgListVerify(pList1);
+
+ vboxVrListRegRemove(pList1, pReg1);
+ vboxVrRegTerm(pReg1);
+
+ vboxVrDbgListVerify(pList1);
+
+ pData->fChanged = true;
+
+ return pNext;
+}
+
+static DECLCALLBACK(PRTLISTNODE) vboxVrListIntersectNoJoinIntersectedCb(PVBOXVR_LIST pList1, PVBOXVR_REG pReg1, const RTRECT *pRect2, void *pvContext, PRTLISTNODE *ppNext)
+{
+ PVBOXVR_CBDATA_SUBST pData = (PVBOXVR_CBDATA_SUBST)pvContext;
+ pData->fChanged = true;
+
+ vboxVrDbgListVerify(pList1);
+
+ PRTLISTNODE pMemberEntry = pReg1->ListEntry.pNext;
+
+ Assert(VBoxRectIsIntersect(&pReg1->Rect, pRect2));
+ Assert(!VBoxRectIsZero(pRect2));
+
+ vboxVrListRegRemove(pList1, pReg1);
+ VBoxRectIntersect(&pReg1->Rect, pRect2);
+ Assert(!VBoxRectIsZero(&pReg1->Rect));
+
+ vboxVrListRegAddOrder(pList1, pMemberEntry, pReg1);
+
+ vboxVrDbgListVerify(pList1);
+
+ return &pReg1->ListEntry;
+}
+
+static int vboxVrListIntersectNoJoin(PVBOXVR_LIST pList, const VBOXVR_LIST *pList2, bool *pfChanged)
+{
+ bool fChanged = false;
+ *pfChanged = false;
+
+ if (VBoxVrListIsEmpty(pList))
+ return VINF_SUCCESS;
+
+ if (VBoxVrListIsEmpty(pList2))
+ {
+ if (pfChanged)
+ *pfChanged = true;
+
+ VBoxVrListClear(pList);
+ return VINF_SUCCESS;
+ }
+
+ PRTLISTNODE pNext1;
+
+ for (PRTLISTNODE pEntry1 = pList->ListHead.pNext; pEntry1 != &pList->ListHead; pEntry1 = pNext1)
+ {
+ pNext1 = pEntry1->pNext;
+ PVBOXVR_REG pReg1 = PVBOXVR_REG_FROM_ENTRY(pEntry1);
+ RTRECT RegRect1 = pReg1->Rect;
+ PRTLISTNODE pMemberEntry = pReg1->ListEntry.pNext;
+
+ for (const RTLISTNODE *pEntry2 = pList2->ListHead.pNext; pEntry2 != &pList2->ListHead; pEntry2 = pEntry2->pNext)
+ {
+ const VBOXVR_REG *pReg2 = PVBOXVR_REG_FROM_ENTRY(pEntry2);
+ const RTRECT *pRect2 = &pReg2->Rect;
+
+ if (!VBoxRectIsIntersect(&RegRect1, pRect2))
+ continue;
+
+ if (pReg1)
+ {
+ if (VBoxRectCovers(pRect2, &RegRect1))
+ {
+ /* no change */
+
+ /* zero up the pReg1 to mark it as intersected (see the code after this inner loop) */
+ pReg1 = NULL;
+
+ if (!VBoxRectCmp(pRect2, &RegRect1))
+ break; /* and we can break the iteration here */
+ }
+ else
+ {
+ /*just to ensure the VBoxRectCovers is true for equal rects */
+ Assert(VBoxRectCmp(pRect2, &RegRect1));
+
+ /* @todo: this can have false-alarming sometimes if the separated rects will then be joind into the original rect,
+ * so far this should not be a problem for VReg clients, so keep it this way for now */
+ fChanged = true;
+
+ /* re-use the reg entry */
+ vboxVrListRegRemove(pList, pReg1);
+ VBoxRectIntersect(&pReg1->Rect, pRect2);
+ Assert(!VBoxRectIsZero(&pReg1->Rect));
+
+ vboxVrListRegAddOrder(pList, pMemberEntry, pReg1);
+ pReg1 = NULL;
+ }
+ }
+ else
+ {
+ Assert(fChanged); /* <- should be set by the if branch above */
+ PVBOXVR_REG pReg = vboxVrRegCreate();
+ if (!pReg)
+ {
+ WARN(("vboxVrRegCreate failed!"));
+ return VERR_NO_MEMORY;
+ }
+ VBoxRectIntersected(&RegRect1, pRect2, &pReg->Rect);
+ Assert(!VBoxRectIsZero(&pReg->Rect));
+ vboxVrListRegAddOrder(pList, pList->ListHead.pNext, pReg);
+ }
+ }
+
+ if (pReg1)
+ {
+ /* the region has no intersections, remove it */
+ vboxVrListRegRemove(pList, pReg1);
+ vboxVrRegTerm(pReg1);
+ fChanged = true;
+ }
+ }
+
+ *pfChanged = fChanged;
+ return VINF_SUCCESS;
+}
+
+VBOXVREGDECL(int) VBoxVrListIntersect(PVBOXVR_LIST pList, const VBOXVR_LIST *pList2, bool *pfChanged)
+{
+ if (pfChanged)
+ *pfChanged = false;
+
+ int rc = vboxVrListIntersectNoJoin(pList, pList2, pfChanged);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("vboxVrListSubstNoJoin failed!"));
+ return rc;
+ }
+
+ if (*pfChanged)
+ {
+ vboxVrListJoinRects(pList);
+ }
+
+ return rc;
+}
+
+VBOXVREGDECL(int) VBoxVrListRectsIntersect(PVBOXVR_LIST pList, uint32_t cRects, const RTRECT * aRects, bool *pfChanged)
+{
+ if (pfChanged)
+ *pfChanged = false;
+
+ if (VBoxVrListIsEmpty(pList))
+ return VINF_SUCCESS;
+
+ if (!cRects)
+ {
+ if (pfChanged)
+ *pfChanged = true;
+
+ VBoxVrListClear(pList);
+ return VINF_SUCCESS;
+ }
+
+ /* we perform intersection using lists because the algorythm axpects the rects to be non-intersected,
+ * which list guaranties to us */
+
+ VBOXVR_LIST TmpList;
+ VBoxVrListInit(&TmpList);
+
+ int rc = VBoxVrListRectsAdd(&TmpList, cRects, aRects, NULL);
+ if (RT_SUCCESS(rc))
+ {
+ rc = VBoxVrListIntersect(pList, &TmpList, pfChanged);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("VBoxVrListIntersect failed! rc %d", rc));
+ }
+ }
+ else
+ {
+ WARN(("VBoxVrListRectsAdd failed, rc %d", rc));
+ }
+ VBoxVrListClear(&TmpList);
+
+ return rc;
+}
+
+VBOXVREGDECL(int) VBoxVrListRectsSubst(PVBOXVR_LIST pList, uint32_t cRects, const RTRECT * aRects, bool *pfChanged)
+{
+#if 0
+ const RTRECT * pRects = vboxVrRectsOrder(cRects, aRects);
+ if (!pRects)
+ {
+ WARN(("vboxVrRectsOrder failed!"));
+ return VERR_NO_MEMORY;
+ }
+#endif
+
+ bool fChanged = false;
+
+ int rc = vboxVrListSubstNoJoin(pList, cRects, aRects, &fChanged);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("vboxVrListSubstNoJoin failed!"));
+ goto done;
+ }
+
+ if (fChanged)
+ goto done;
+
+ vboxVrListJoinRects(pList);
+
+done:
+#if 0
+ if (pRects != aRects)
+ RTMemFree(pRects);
+#endif
+
+ if (pfChanged)
+ *pfChanged = fChanged;
+
+ return rc;
+}
+
+VBOXVREGDECL(int) VBoxVrListRectsSet(PVBOXVR_LIST pList, uint32_t cRects, const RTRECT * aRects, bool *pfChanged)
+{
+ if (pfChanged)
+ *pfChanged = false;
+
+ if (!cRects && VBoxVrListIsEmpty(pList))
+ {
+ return VINF_SUCCESS;
+ }
+
+ /* @todo: fChanged will have false alarming here, fix if needed */
+ VBoxVrListClear(pList);
+
+ int rc = VBoxVrListRectsAdd(pList, cRects, aRects, NULL);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("VBoxVrListRectsSet failed rc %d", rc));
+ return rc;
+ }
+
+ if (pfChanged)
+ *pfChanged = true;
+
+ return VINF_SUCCESS;
+}
+
+VBOXVREGDECL(int) VBoxVrListRectsAdd(PVBOXVR_LIST pList, uint32_t cRects, const RTRECT * aRects, bool *pfChanged)
+{
+ uint32_t cCovered = 0;
+
+ if (pfChanged)
+ *pfChanged = false;
+
+#if 0
+#ifdef DEBUG
+ {
+ for (uint32_t i = 0; i < cRects; ++i)
+ {
+ RTRECT *pRectI = &aRects[i];
+ for (uint32_t j = i + 1; j < cRects; ++j)
+ {
+ RTRECT *pRectJ = &aRects[j];
+ Assert(!VBoxRectIsIntersect(pRectI, pRectJ));
+ }
+ }
+ }
+#endif
+#endif
+
+ /* early sort out the case when there are no new rects */
+ for (uint32_t i = 0; i < cRects; ++i)
+ {
+ if (VBoxRectIsZero(&aRects[i]))
+ {
+ cCovered++;
+ continue;
+ }
+
+ for (PRTLISTNODE pEntry1 = pList->ListHead.pNext; pEntry1 != &pList->ListHead; pEntry1 = pEntry1->pNext)
+ {
+ PVBOXVR_REG pReg1 = PVBOXVR_REG_FROM_ENTRY(pEntry1);
+
+ if (VBoxRectCovers(&pReg1->Rect, &aRects[i]))
+ {
+ cCovered++;
+ break;
+ }
+ }
+ }
+
+ if (cCovered == cRects)
+ return VINF_SUCCESS;
+
+ /* rects are not covered, need to go the slow way */
+
+ VBOXVR_LIST DiffList;
+ VBoxVrListInit(&DiffList);
+ RTRECT * pListRects = NULL;
+ uint32_t cAllocatedRects = 0;
+ bool fNeedRectreate = true;
+ bool fChanged = false;
+ int rc = VINF_SUCCESS;
+
+ for (uint32_t i = 0; i < cRects; ++i)
+ {
+ if (VBoxRectIsZero(&aRects[i]))
+ continue;
+
+ PVBOXVR_REG pReg = vboxVrRegCreate();
+ if (!pReg)
+ {
+ WARN(("vboxVrRegCreate failed!"));
+ rc = VERR_NO_MEMORY;
+ break;
+ }
+ pReg->Rect = aRects[i];
+
+ uint32_t cListRects = VBoxVrListRectsCount(pList);
+ if (!cListRects)
+ {
+ vboxVrListRegAdd(pList, pReg, &pList->ListHead, false);
+ fChanged = true;
+ continue;
+ }
+ else
+ {
+ Assert(VBoxVrListIsEmpty(&DiffList));
+ vboxVrListRegAdd(&DiffList, pReg, &DiffList.ListHead, false);
+ }
+
+ if (cAllocatedRects < cListRects)
+ {
+ cAllocatedRects = cListRects + cRects;
+ Assert(fNeedRectreate);
+ if (pListRects)
+ RTMemFree(pListRects);
+ pListRects = (RTRECT *)RTMemAlloc(sizeof (RTRECT) * cAllocatedRects);
+ if (!pListRects)
+ {
+ WARN(("RTMemAlloc failed!"));
+ rc = VERR_NO_MEMORY;
+ break;
+ }
+ }
+
+
+ if (fNeedRectreate)
+ {
+ rc = VBoxVrListRectsGet(pList, cListRects, pListRects);
+ Assert(rc == VINF_SUCCESS);
+ fNeedRectreate = false;
+ }
+
+ bool fDummyChanged = false;
+ rc = vboxVrListSubstNoJoin(&DiffList, cListRects, pListRects, &fDummyChanged);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("vboxVrListSubstNoJoin failed!"));
+ rc = VERR_NO_MEMORY;
+ break;
+ }
+
+ if (!VBoxVrListIsEmpty(&DiffList))
+ {
+ vboxVrListAddNonintersected(pList, &DiffList);
+ fNeedRectreate = true;
+ fChanged = true;
+ }
+
+ Assert(VBoxVrListIsEmpty(&DiffList));
+ }
+
+ if (pListRects)
+ RTMemFree(pListRects);
+
+ Assert(VBoxVrListIsEmpty(&DiffList) || rc != VINF_SUCCESS);
+ VBoxVrListClear(&DiffList);
+
+ if (fChanged)
+ vboxVrListJoinRects(pList);
+
+ if (pfChanged)
+ *pfChanged = fChanged;
+
+ return VINF_SUCCESS;
+}
+
+VBOXVREGDECL(int) VBoxVrListRectsGet(PVBOXVR_LIST pList, uint32_t cRects, RTRECT * aRects)
+{
+ if (cRects < VBoxVrListRectsCount(pList))
+ return VERR_BUFFER_OVERFLOW;
+
+ uint32_t i = 0;
+ for (PRTLISTNODE pEntry1 = pList->ListHead.pNext; pEntry1 != &pList->ListHead; pEntry1 = pEntry1->pNext, ++i)
+ {
+ PVBOXVR_REG pReg1 = PVBOXVR_REG_FROM_ENTRY(pEntry1);
+ aRects[i] = pReg1->Rect;
+ }
+ return VINF_SUCCESS;
+}
+
+VBOXVREGDECL(int) VBoxVrListCmp(const VBOXVR_LIST *pList1, const VBOXVR_LIST *pList2)
+{
+ int cTmp = pList1->cEntries - pList2->cEntries;
+ if (cTmp)
+ return cTmp;
+
+ PVBOXVR_REG pReg1, pReg2;
+
+ for (pReg1 = RTListNodeGetNext(&pList1->ListHead, VBOXVR_REG, ListEntry),
+ pReg2 = RTListNodeGetNext(&pList2->ListHead, VBOXVR_REG, ListEntry);
+ !RTListNodeIsDummy(&pList1->ListHead, pReg1, VBOXVR_REG, ListEntry);
+ pReg1 = RT_FROM_MEMBER(pReg1->ListEntry.pNext, VBOXVR_REG, ListEntry),
+ pReg2 = RT_FROM_MEMBER(pReg2->ListEntry.pNext, VBOXVR_REG, ListEntry))
+ {
+ Assert(!RTListNodeIsDummy(&pList2->ListHead, pReg2, VBOXVR_REG, ListEntry));
+ cTmp = VBoxRectCmp(&pReg1->Rect, &pReg2->Rect);
+ if (cTmp)
+ return cTmp;
+ }
+ Assert(RTListNodeIsDummy(&pList2->ListHead, pReg2, VBOXVR_REG, ListEntry));
+ return 0;
+}
+
+VBOXVREGDECL(int) VBoxVrListClone(const VBOXVR_LIST *pList, VBOXVR_LIST *pDstList)
+{
+ VBoxVrListInit(pDstList);
+ const VBOXVR_REG *pReg;
+ RTListForEach(&pList->ListHead, pReg, const VBOXVR_REG, ListEntry)
+ {
+ PVBOXVR_REG pDstReg = vboxVrRegCreate();
+ if (!pDstReg)
+ {
+ WARN(("vboxVrRegLaAlloc failed"));
+ VBoxVrListClear(pDstList);
+ return VERR_NO_MEMORY;
+ }
+ pDstReg->Rect = pReg->Rect;
+ vboxVrListRegAdd(pDstList, pDstReg, &pDstList->ListHead, true /*bool fAfter*/);
+ }
+
+ Assert(pDstList->cEntries == pList->cEntries);
+
+ return VINF_SUCCESS;
+}
+
+VBOXVREGDECL(void) VBoxVrCompositorInit(PVBOXVR_COMPOSITOR pCompositor, PFNVBOXVRCOMPOSITOR_ENTRY_RELEASED pfnEntryReleased)
+{
+ RTListInit(&pCompositor->List);
+ pCompositor->pfnEntryReleased = pfnEntryReleased;
+}
+
+VBOXVREGDECL(void) VBoxVrCompositorRegionsClear(PVBOXVR_COMPOSITOR pCompositor, bool *pfChanged)
+{
+ bool fChanged = false;
+ PVBOXVR_COMPOSITOR_ENTRY pEntry, pEntryNext;
+ RTListForEachSafe(&pCompositor->List, pEntry, pEntryNext, VBOXVR_COMPOSITOR_ENTRY, Node)
+ {
+ VBoxVrCompositorEntryRemove(pCompositor, pEntry);
+ fChanged = true;
+ }
+
+ if (pfChanged)
+ *pfChanged = fChanged;
+}
+
+VBOXVREGDECL(void) VBoxVrCompositorClear(PVBOXVR_COMPOSITOR pCompositor)
+{
+ VBoxVrCompositorRegionsClear(pCompositor, NULL);
+}
+
+DECLINLINE(void) vboxVrCompositorEntryRelease(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, PVBOXVR_COMPOSITOR_ENTRY pReplacingEntry)
+{
+ if (--pEntry->cRefs)
+ {
+ Assert(pEntry->cRefs < UINT32_MAX/2);
+ return;
+ }
+
+ Assert(!VBoxVrCompositorEntryIsInList(pEntry));
+
+ if (pCompositor->pfnEntryReleased)
+ pCompositor->pfnEntryReleased(pCompositor, pEntry, pReplacingEntry);
+}
+
+DECLINLINE(void) vboxVrCompositorEntryAddRef(PVBOXVR_COMPOSITOR_ENTRY pEntry)
+{
+ ++pEntry->cRefs;
+}
+
+DECLINLINE(void) vboxVrCompositorEntryAdd(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry)
+{
+ RTListPrepend(&pCompositor->List, &pEntry->Node);
+ vboxVrCompositorEntryAddRef(pEntry);
+}
+
+DECLINLINE(void) vboxVrCompositorEntryRemove(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, PVBOXVR_COMPOSITOR_ENTRY pReplacingEntry)
+{
+ RTListNodeRemove(&pEntry->Node);
+ vboxVrCompositorEntryRelease(pCompositor, pEntry, pReplacingEntry);
+}
+
+static void vboxVrCompositorEntryReplace(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, PVBOXVR_COMPOSITOR_ENTRY pReplacingEntry)
+{
+ VBoxVrListMoveTo(&pEntry->Vr, &pReplacingEntry->Vr);
+
+ pReplacingEntry->Node = pEntry->Node;
+ pReplacingEntry->Node.pNext->pPrev = &pReplacingEntry->Node;
+ pReplacingEntry->Node.pPrev->pNext = &pReplacingEntry->Node;
+ pEntry->Node.pNext = NULL;
+ pEntry->Node.pPrev = NULL;
+
+ vboxVrCompositorEntryAddRef(pReplacingEntry);
+ vboxVrCompositorEntryRelease(pCompositor, pEntry, pReplacingEntry);
+}
+
+
+
+VBOXVREGDECL(void) VBoxVrCompositorEntryInit(PVBOXVR_COMPOSITOR_ENTRY pEntry)
+{
+ VBoxVrListInit(&pEntry->Vr);
+ pEntry->cRefs = 0;
+}
+
+VBOXVREGDECL(bool) VBoxVrCompositorEntryRemove(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry)
+{
+ if (!VBoxVrCompositorEntryIsInList(pEntry))
+ return false;
+
+ vboxVrCompositorEntryAddRef(pEntry);
+
+ VBoxVrListClear(&pEntry->Vr);
+ vboxVrCompositorEntryRemove(pCompositor, pEntry, NULL);
+ vboxVrCompositorEntryRelease(pCompositor, pEntry, NULL);
+ return true;
+}
+
+VBOXVREGDECL(bool) VBoxVrCompositorEntryReplace(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, PVBOXVR_COMPOSITOR_ENTRY pNewEntry)
+{
+ if (!VBoxVrCompositorEntryIsInList(pEntry))
+ return false;
+
+ vboxVrCompositorEntryReplace(pCompositor, pEntry, pNewEntry);
+
+ return true;
+}
+
+static int vboxVrCompositorEntryRegionsSubst(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, uint32_t cRects, const RTRECT * paRects, bool *pfChanged)
+{
+ bool fChanged;
+ vboxVrCompositorEntryAddRef(pEntry);
+
+ int rc = VBoxVrListRectsSubst(&pEntry->Vr, cRects, paRects, &fChanged);
+ if (RT_SUCCESS(rc))
+ {
+ if (VBoxVrListIsEmpty(&pEntry->Vr))
+ {
+ Assert(fChanged);
+ vboxVrCompositorEntryRemove(pCompositor, pEntry, NULL);
+ }
+ if (pfChanged)
+ *pfChanged = false;
+ }
+ else
+ WARN(("VBoxVrListRectsSubst failed, rc %d", rc));
+
+ vboxVrCompositorEntryRelease(pCompositor, pEntry, NULL);
+ return rc;
+}
+
+VBOXVREGDECL(int) VBoxVrCompositorEntryRegionsAdd(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, uint32_t cRects, const RTRECT *paRects, PVBOXVR_COMPOSITOR_ENTRY *ppReplacedEntry, uint32_t *pfChangeFlags)
+{
+ bool fOthersChanged = false, fCurChanged = false, fEntryChanged = false, fEntryWasInList = false;
+ PVBOXVR_COMPOSITOR_ENTRY pCur, pNext, pReplacedEntry = NULL;
+ int rc = VINF_SUCCESS;
+
+ if (pEntry)
+ vboxVrCompositorEntryAddRef(pEntry);
+
+ if (!cRects)
+ {
+ if (pfChangeFlags)
+ *pfChangeFlags = 0;
+ if (pEntry)
+ vboxVrCompositorEntryRelease(pCompositor, pEntry, NULL);
+ return VINF_SUCCESS;
+ }
+
+ if (pEntry)
+ {
+ fEntryWasInList = VBoxVrCompositorEntryIsInList(pEntry);
+ rc = VBoxVrListRectsAdd(&pEntry->Vr, cRects, paRects, &fEntryChanged);
+ if (RT_SUCCESS(rc))
+ {
+ if (VBoxVrListIsEmpty(&pEntry->Vr))
+ {
+// WARN(("Empty rectangles passed in, is it expected?"));
+ if (pfChangeFlags)
+ *pfChangeFlags = 0;
+ vboxVrCompositorEntryRelease(pCompositor, pEntry, NULL);
+ return VINF_SUCCESS;
+ }
+ }
+ else
+ {
+ WARN(("VBoxVrListRectsAdd failed, rc %d", rc));
+ vboxVrCompositorEntryRelease(pCompositor, pEntry, NULL);
+ return rc;
+ }
+
+ Assert(!VBoxVrListIsEmpty(&pEntry->Vr));
+ }
+ else
+ {
+ fEntryChanged = true;
+ }
+
+ RTListForEachSafe(&pCompositor->List, pCur, pNext, VBOXVR_COMPOSITOR_ENTRY, Node)
+ {
+ Assert(!VBoxVrListIsEmpty(&pCur->Vr));
+ if (pCur != pEntry)
+ {
+ if (pEntry && !VBoxVrListCmp(&pCur->Vr, &pEntry->Vr))
+ {
+ VBoxVrListClear(&pCur->Vr);
+ pReplacedEntry = pCur;
+ vboxVrCompositorEntryAddRef(pReplacedEntry);
+ vboxVrCompositorEntryRemove(pCompositor, pCur, pEntry);
+ if (ppReplacedEntry)
+ *ppReplacedEntry = pReplacedEntry;
+ break;
+ }
+ else
+ {
+ rc = vboxVrCompositorEntryRegionsSubst(pCompositor, pCur, cRects, paRects, &fCurChanged);
+ if (RT_SUCCESS(rc))
+ fOthersChanged |= fCurChanged;
+ else
+ {
+ WARN(("vboxVrCompositorEntryRegionsSubst failed, rc %d", rc));
+ return rc;
+ }
+ }
+ }
+ }
+
+ AssertRC(rc);
+
+ if (pEntry)
+ {
+ if (!fEntryWasInList)
+ {
+ Assert(!VBoxVrListIsEmpty(&pEntry->Vr));
+ vboxVrCompositorEntryAdd(pCompositor, pEntry);
+ }
+ vboxVrCompositorEntryRelease(pCompositor, pEntry, NULL);
+ }
+
+ uint32_t fFlags = 0;
+ if (fOthersChanged)
+ {
+ Assert(!pReplacedEntry);
+ fFlags = VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED | VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED | VBOXVR_COMPOSITOR_CF_OTHER_ENTRIES_REGIONS_CHANGED;
+ }
+ else if (pReplacedEntry)
+ {
+ vboxVrCompositorEntryRelease(pCompositor, pReplacedEntry, pEntry);
+ Assert(fEntryChanged);
+ fFlags = VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED | VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED;
+ }
+ else if (fEntryChanged)
+ {
+ Assert(!pReplacedEntry);
+ fFlags = VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED | VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED;
+ }
+ else
+ {
+ Assert(!pReplacedEntry);
+ }
+
+ if (!fEntryWasInList)
+ Assert(fEntryChanged);
+
+ if (pfChangeFlags)
+ *pfChangeFlags = fFlags;
+
+ return VINF_SUCCESS;
+}
+
+VBOXVREGDECL(int) VBoxVrCompositorEntryRegionsSubst(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, uint32_t cRects, const RTRECT * paRects, bool *pfChanged)
+{
+ if (!pEntry)
+ {
+ WARN(("VBoxVrCompositorEntryRegionsSubst called with zero entry, unsupported!"));
+ if (pfChanged)
+ *pfChanged = false;
+ return VERR_INVALID_PARAMETER;
+ }
+
+ vboxVrCompositorEntryAddRef(pEntry);
+
+ if (VBoxVrListIsEmpty(&pEntry->Vr))
+ {
+ if (pfChanged)
+ *pfChanged = false;
+ vboxVrCompositorEntryRelease(pCompositor, pEntry, NULL);
+ return VINF_SUCCESS;
+ }
+
+ int rc = vboxVrCompositorEntryRegionsSubst(pCompositor, pEntry, cRects, paRects, pfChanged);
+ if (!RT_SUCCESS(rc))
+ WARN(("pfChanged failed, rc %d", rc));
+
+ vboxVrCompositorEntryRelease(pCompositor, pEntry, NULL);
+
+ return rc;
+}
+
+VBOXVREGDECL(int) VBoxVrCompositorEntryRegionsSet(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, uint32_t cRects, const RTRECT *paRects, bool *pfChanged)
+{
+ if (!pEntry)
+ {
+ WARN(("VBoxVrCompositorEntryRegionsSet called with zero entry, unsupported!"));
+ if (pfChanged)
+ *pfChanged = false;
+ return VERR_INVALID_PARAMETER;
+ }
+
+ vboxVrCompositorEntryAddRef(pEntry);
+
+ bool fChanged = false, fCurChanged = false;
+ uint32_t fChangeFlags = 0;
+ int rc;
+ fCurChanged = VBoxVrCompositorEntryRemove(pCompositor, pEntry);
+ fChanged |= fCurChanged;
+
+ rc = VBoxVrCompositorEntryRegionsAdd(pCompositor, pEntry, cRects, paRects, NULL, &fChangeFlags);
+ if (RT_SUCCESS(rc))
+ {
+ fChanged |= !!fChangeFlags;
+ if (pfChanged)
+ *pfChanged = fChanged;
+ }
+ else
+ WARN(("VBoxVrCompositorEntryRegionsAdd failed, rc %d", rc));
+
+ vboxVrCompositorEntryRelease(pCompositor, pEntry, NULL);
+
+ return VINF_SUCCESS;
+}
+
+VBOXVREGDECL(int) VBoxVrCompositorEntryListIntersect(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, const VBOXVR_LIST *pList2, bool *pfChanged)
+{
+ int rc = VINF_SUCCESS;
+ bool fChanged = false;
+
+ vboxVrCompositorEntryAddRef(pEntry);
+
+ if (VBoxVrCompositorEntryIsInList(pEntry))
+ {
+ rc = VBoxVrListIntersect(&pEntry->Vr, pList2, &fChanged);
+ if (RT_SUCCESS(rc))
+ {
+ if (VBoxVrListIsEmpty(&pEntry->Vr))
+ {
+ Assert(fChanged);
+ vboxVrCompositorEntryRemove(pCompositor, pEntry, NULL);
+ }
+ }
+ else
+ {
+ WARN(("VBoxVrListRectsIntersect failed, rc %d", rc));
+ }
+ }
+
+ if (pfChanged)
+ *pfChanged = fChanged;
+
+ vboxVrCompositorEntryRelease(pCompositor, pEntry, NULL);
+
+ return rc;
+}
+
+VBOXVREGDECL(int) VBoxVrCompositorEntryRegionsIntersect(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, uint32_t cRects, const RTRECT *paRects, bool *pfChanged)
+{
+ int rc = VINF_SUCCESS;
+ bool fChanged = false;
+
+ vboxVrCompositorEntryAddRef(pEntry);
+
+ if (VBoxVrCompositorEntryIsInList(pEntry))
+ {
+ rc = VBoxVrListRectsIntersect(&pEntry->Vr, cRects, paRects, &fChanged);
+ if (RT_SUCCESS(rc))
+ {
+ if (VBoxVrListIsEmpty(&pEntry->Vr))
+ {
+ Assert(fChanged);
+ vboxVrCompositorEntryRemove(pCompositor, pEntry, NULL);
+ }
+ }
+ else
+ {
+ WARN(("VBoxVrListRectsIntersect failed, rc %d", rc));
+ }
+ }
+
+ if (pfChanged)
+ *pfChanged = fChanged;
+
+ vboxVrCompositorEntryRelease(pCompositor, pEntry, NULL);
+
+ return rc;
+}
+
+VBOXVREGDECL(int) VBoxVrCompositorEntryListIntersectAll(PVBOXVR_COMPOSITOR pCompositor, const VBOXVR_LIST *pList2, bool *pfChanged)
+{
+ VBOXVR_COMPOSITOR_ITERATOR Iter;
+ VBoxVrCompositorIterInit(pCompositor, &Iter);
+ PVBOXVR_COMPOSITOR_ENTRY pEntry;
+ int rc = VINF_SUCCESS;
+ bool fChanged = false;
+
+ while ((pEntry = VBoxVrCompositorIterNext(&Iter)) != NULL)
+ {
+ bool fTmpChanged = false;
+ int tmpRc = VBoxVrCompositorEntryListIntersect(pCompositor, pEntry, pList2, &fTmpChanged);
+ if (RT_SUCCESS(tmpRc))
+ {
+ fChanged |= fChanged;
+ }
+ else
+ {
+ WARN(("VBoxVrCompositorEntryRegionsIntersect failed, rc %d", tmpRc));
+ rc = tmpRc;
+ }
+ }
+
+ if (pfChanged)
+ *pfChanged = fChanged;
+
+ return rc;
+}
+
+VBOXVREGDECL(int) VBoxVrCompositorEntryRegionsIntersectAll(PVBOXVR_COMPOSITOR pCompositor, uint32_t cRegions, const RTRECT *paRegions, bool *pfChanged)
+{
+ VBOXVR_COMPOSITOR_ITERATOR Iter;
+ VBoxVrCompositorIterInit(pCompositor, &Iter);
+ PVBOXVR_COMPOSITOR_ENTRY pEntry;
+ int rc = VINF_SUCCESS;
+ bool fChanged = false;
+
+ while ((pEntry = VBoxVrCompositorIterNext(&Iter)) != NULL)
+ {
+ bool fTmpChanged = false;
+ int tmpRc = VBoxVrCompositorEntryRegionsIntersect(pCompositor, pEntry, cRegions, paRegions, &fTmpChanged);
+ if (RT_SUCCESS(tmpRc))
+ {
+ fChanged |= fChanged;
+ }
+ else
+ {
+ WARN(("VBoxVrCompositorEntryRegionsIntersect failed, rc %d", tmpRc));
+ rc = tmpRc;
+ }
+ }
+
+ if (pfChanged)
+ *pfChanged = fChanged;
+
+ return rc;
+}
+
+VBOXVREGDECL(int) VBoxVrCompositorEntryRegionsTranslate(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, int32_t x, int32_t y, bool *pfChanged)
+{
+ if (!pEntry)
+ {
+ WARN(("VBoxVrCompositorEntryRegionsTranslate called with zero entry, unsupported!"));
+ if (pfChanged)
+ *pfChanged = false;
+ return VERR_INVALID_PARAMETER;
+ }
+
+ vboxVrCompositorEntryAddRef(pEntry);
+
+ if ((!x && !y)
+ || !VBoxVrCompositorEntryIsInList(pEntry))
+ {
+ if (pfChanged)
+ *pfChanged = false;
+
+ vboxVrCompositorEntryRelease(pCompositor, pEntry, NULL);
+ return VINF_SUCCESS;
+ }
+
+ VBoxVrListTranslate(&pEntry->Vr, x, y);
+
+ Assert(!VBoxVrListIsEmpty(&pEntry->Vr));
+
+ PVBOXVR_COMPOSITOR_ENTRY pCur;
+ uint32_t cRects = 0;
+ RTRECT *paRects = NULL;
+ int rc = VINF_SUCCESS;
+ RTListForEach(&pCompositor->List, pCur, VBOXVR_COMPOSITOR_ENTRY, Node)
+ {
+ Assert(!VBoxVrListIsEmpty(&pCur->Vr));
+
+ if (pCur == pEntry)
+ continue;
+
+ if (!paRects)
+ {
+ cRects = VBoxVrListRectsCount(&pEntry->Vr);
+ Assert(cRects);
+ paRects = (RTRECT*)RTMemAlloc(cRects * sizeof (RTRECT));
+ if (!paRects)
+ {
+ WARN(("RTMemAlloc failed!"));
+ rc = VERR_NO_MEMORY;
+ break;
+ }
+
+ rc = VBoxVrListRectsGet(&pEntry->Vr, cRects, paRects);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("VBoxVrListRectsGet failed! rc %d", rc));
+ break;
+ }
+ }
+
+ rc = vboxVrCompositorEntryRegionsSubst(pCompositor, pCur, cRects, paRects, NULL);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("vboxVrCompositorEntryRegionsSubst failed! rc %d", rc));
+ break;
+ }
+ }
+
+ if (pfChanged)
+ *pfChanged = true;
+
+ if (paRects)
+ RTMemFree(paRects);
+
+ vboxVrCompositorEntryRelease(pCompositor, pEntry, NULL);
+
+ return rc;
+}
+
+VBOXVREGDECL(void) VBoxVrCompositorVisit(PVBOXVR_COMPOSITOR pCompositor, PFNVBOXVRCOMPOSITOR_VISITOR pfnVisitor, void *pvVisitor)
+{
+ PVBOXVR_COMPOSITOR_ENTRY pEntry, pEntryNext;
+ RTListForEachSafe(&pCompositor->List, pEntry, pEntryNext, VBOXVR_COMPOSITOR_ENTRY, Node)
+ {
+ if (!pfnVisitor(pCompositor, pEntry, pvVisitor))
+ return;
+ }
+}