summaryrefslogtreecommitdiffstats
path: root/src/VBox/GuestHost/OpenGL/state_tracker
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-06 03:01:46 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-06 03:01:46 +0000
commitf8fe689a81f906d1b91bb3220acde2a4ecb14c5b (patch)
tree26484e9d7e2c67806c2d1760196ff01aaa858e8c /src/VBox/GuestHost/OpenGL/state_tracker
parentInitial commit. (diff)
downloadvirtualbox-f8fe689a81f906d1b91bb3220acde2a4ecb14c5b.tar.xz
virtualbox-f8fe689a81f906d1b91bb3220acde2a4ecb14c5b.zip
Adding upstream version 6.0.4-dfsg.upstream/6.0.4-dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/GuestHost/OpenGL/state_tracker')
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/Makefile.kup0
-rwxr-xr-xsrc/VBox/GuestHost/OpenGL/state_tracker/convert.py75
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/dump.cpp1741
-rwxr-xr-xsrc/VBox/GuestHost/OpenGL/state_tracker/dump_gen.py249
-rwxr-xr-xsrc/VBox/GuestHost/OpenGL/state_tracker/gendiffcode.py273
-rwxr-xr-xsrc/VBox/GuestHost/OpenGL/state_tracker/get_components.py141
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state.h80
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_attrib.c1185
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_bits_globalop.h338
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_buffer.c776
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_buffer.txt34
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_bufferobject.c1126
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_client.c2433
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_client.txt32
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_current.c435
-rwxr-xr-xsrc/VBox/GuestHost/OpenGL/state_tracker/state_current.py485
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_defs.py64
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_diff.c644
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_enable.c544
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_error.c86
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_evaluators.c1084
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_extensions_get.txt138
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_extensions_isenabled.txt71
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_feedback.c2423
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_feedback_special73
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_fence.c50
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_flush.c34
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_fog.c199
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_fog.txt13
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_framebuffer.c1202
-rwxr-xr-xsrc/VBox/GuestHost/OpenGL/state_tracker/state_funcs.py62
-rwxr-xr-xsrc/VBox/GuestHost/OpenGL/state_tracker/state_get.py234
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_get.txt319
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_getstring.c55
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_glsl.c1527
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_hint.c132
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_hint.txt12
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_init.c892
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_internals.h29
-rwxr-xr-xsrc/VBox/GuestHost/OpenGL/state_tracker/state_isenabled.py75
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_isenabled.txt76
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_lighting.c1212
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_lighting.txt63
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_limits.c475
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_line.c87
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_line.txt8
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_lists.c1407
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_multisample.c51
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_multisample.txt9
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_occlude.c354
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_pixel.c857
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_point.c447
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_point.txt39
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_polygon.c211
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_polygon.txt22
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_program.c2392
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_program.txt14
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_rasterpos.c327
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_regcombiner.c705
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_regcombiner.txt38
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_select_special61
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_snapshot.c2678
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_special385
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_stencil.c1450
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_stencil.txt9
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_texdiff.c1469
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_teximage.c1762
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_texture.c3418
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_transform.c1392
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_viewport.c166
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_viewport.txt14
71 files changed, 40963 insertions, 0 deletions
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/Makefile.kup b/src/VBox/GuestHost/OpenGL/state_tracker/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/Makefile.kup
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/convert.py b/src/VBox/GuestHost/OpenGL/state_tracker/convert.py
new file mode 100755
index 00000000..1adbf4e6
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/convert.py
@@ -0,0 +1,75 @@
+# Copyright (c) 2001, Stanford University
+# All rights reserved.
+#
+# See the file LICENSE.txt for information on redistributing this software.
+
+from __future__ import print_function
+import sys
+
+# Two different paths to the packer and opengl_stub directories since this
+# script will be called from both cr/state_tracker/ and cr/spu/tilesort/.
+sys.path.append( '../packer' )
+sys.path.append( '../../packer' )
+sys.path.append( '../glapi_parser' )
+sys.path.append( '../../glapi_parser' )
+from pack_currenttypes import *
+import apiutil
+
+apiutil.CopyrightC()
+
+print('''
+#include "state/cr_statetypes.h"
+
+static double __read_double( const void *src )
+{
+ const unsigned int *ui = (const unsigned int *) src;
+ double d;
+ ((unsigned int *) &d)[0] = ui[0];
+ ((unsigned int *) &d)[1] = ui[1];
+ return d;
+}
+''')
+
+for k in sorted(gltypes.keys()):
+ for i in range(1,5):
+ print('static void __convert_%s%d (GLfloat *dst, const %s *src) {' % (k,i,gltypes[k]['type']))
+ if k == 'd':
+ for j in range(i-1):
+ print('\t*dst++ = (GLfloat) __read_double(src++);')
+ print('\t*dst = (GLfloat) __read_double(src);')
+ else:
+ for j in range(i-1):
+ print('\t*dst++ = (GLfloat) *src++;')
+ print('\t*dst = (GLfloat) *src;')
+ print('}\n')
+
+scale = {
+ 'ub' : 'CR_MAXUBYTE',
+ 'b' : 'CR_MAXBYTE',
+ 'us' : 'CR_MAXUSHORT',
+ 's' : 'CR_MAXSHORT',
+ 'ui' : 'CR_MAXUINT',
+ 'i' : 'CR_MAXINT',
+ 'f' : '',
+ 'd' : ''
+}
+
+for k in sorted(gltypes.keys()):
+ if k != 'f' and k != 'd' and k != 'l':
+ if k[0:1] == "N":
+ k2 = k[1:]
+ else:
+ k2 = k
+ for i in range(1,5):
+ print('static void __convert_rescale_%s%d (GLfloat *dst, const %s *src) {' % (k,i,gltypes[k2]['type']))
+ for j in range(i-1):
+ print('\t*dst++ = ((GLfloat) *src++) / %s;' % scale[k2])
+ print('\t*dst = ((GLfloat) *src) / %s;' % scale[k2])
+ print('}\n')
+
+print('''
+
+static void __convert_boolean (GLboolean *dst, const GLboolean *src) {
+ *dst = *src;
+}
+''')
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..42a41df1
--- /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-2019 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 100755
index 00000000..c4cae06e
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/dump_gen.py
@@ -0,0 +1,249 @@
+from __future__ import print_function
+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;
+""")
+for pname in sorted(params.keys()):
+ print("\tfEnabled = pRec->pDispatch->IsEnabled(%s);" % pname)
+ print("\tcrDmpStrF(pRec->pDumper, \"%s = %%d;\", fEnabled);" % pname)
+
+for pname in sorted(extended_params.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==");
+""")
+
+for target in sorted(texenv_mappings.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/gendiffcode.py b/src/VBox/GuestHost/OpenGL/state_tracker/gendiffcode.py
new file mode 100755
index 00000000..6c3e91d6
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/gendiffcode.py
@@ -0,0 +1,273 @@
+# Copyright (c) 2001, Stanford University
+# All rights reserved.
+#
+# See the file LICENSE.txt for information on redistributing this software
+
+from __future__ import print_function
+import sys
+
+def main():
+ name = sys.argv[1]
+ Name = sys.argv[2]
+
+ print("""/* This code is AUTOGENERATED!!! */
+
+#include "state.h"
+#include "state_internals.h\"""")
+
+ print("""
+void crState%(Name)sDiff(CR%(Name)sBits *b, CRbitvalue *bitID,
+ CRContext *fromCtx, CRContext *toCtx)
+{
+ CR%(Name)sState *from = &(fromCtx->%(name)s);
+ CR%(Name)sState *to = &(toCtx->%(name)s);"""%vars())
+ gendiffcode("state_%s.txt"%(name.lower()), name, docopy=1, doinvalid=0)
+ print("""}
+
+void crState%(Name)sSwitch(CR%(Name)sBits *b, CRbitvalue *bitID,
+ CRContext *fromCtx, CRContext *toCtx)
+{
+ CR%(Name)sState *from = &(fromCtx->%(name)s);
+ CR%(Name)sState *to = &(toCtx->%(name)s);"""%vars())
+ gendiffcode("state_%s.txt"%(Name.lower()), Name, docopy=0, doinvalid=1)
+ print("}\n")
+
+def gendiffcode(fname, state_name, docopy, doinvalid):
+ target = "to"
+ current = "from"
+ bit = "b"
+ extrabit = ""
+ tab = "\t"
+ current_guard = ""
+ current_dependency = ""
+
+ v_types = {
+ 'l': 'GLboolean',
+ 'b': 'GLbyte',
+ 'ub': 'GLubyte',
+ 's': 'GLshort',
+ 'us': 'GLushort',
+ 'i': 'GLint',
+ 'ui': 'GLuint',
+ 'f': 'GLfloat',
+ 'd': 'GLdouble'
+ }
+
+ FILE = open(sys.argv[3]+"/"+fname, "r")
+
+ print(""" unsigned int j, i;
+ CRbitvalue nbitID[CR_MAX_BITARRAY];
+ for (j = 0; j<CR_MAX_BITARRAY; j++)
+ nbitID[j] = ~bitID[j];
+ i = 0; /* silence compiler */""")
+
+ import re
+ for line in FILE:
+ line = line.rstrip()
+
+ if re.match("#", line):
+ continue
+
+## Handle text dump
+ m = re.match("\+(.*)", line)
+ if m:
+ if doinvalid:
+ continue
+ line = m.group(1)
+
+ else:
+ m = re.match("-(.*)", line)
+ if m:
+ if docopy:
+ continue
+ line = m.group(1)
+
+ m = re.match(">(.*)", line)
+ if m:
+ text = m.group(1)
+ if re.search("}", line):
+ tab = tab[:-1]
+ print(tab+text)
+ if re.search("{", line):
+ tab = tab+"\t"
+ continue
+
+## Handle commands
+
+ m = re.search("%target=(\w*)", line)
+ if m:
+ target = m.group(1)
+ m = re.search("%current=(\w*)", line)
+ if m:
+ current = m.group(1)
+ m = re.search("%bit=(\w*)", line)
+ if m:
+ bit = m.group(1)
+ m = re.search("%extrabit=(\w*)", line)
+ if m:
+ extrabit = m.group(1)
+
+ if re.search("%flush", line):
+ if current_guard != "":
+ print(tab+"CLEARDIRTY(%(bit)s->%(current_guard)s, nbitID);"%vars())
+ tab = tab[:-1]
+ print(tab+"}")
+ if docopy and current_dependency != "":
+ tab = tab[:-1]
+ print(tab+"}")
+ current_guard = ""
+ current_dependency = ""
+ if re.search("%", line):
+ continue
+
+## Load the line
+ (dependency, guardbit, members, func) = \
+ (re.split(":", line) + ["", ""])[0:4]
+ func = func.rstrip()
+
+## Close the guardbit and dependency
+ if current_guard != "" and current_guard != guardbit:
+ print(tab+"CLEARDIRTY(%(bit)s->%(current_guard)s, nbitID);"%vars())
+ tab = tab[:-1]
+ print(tab+"}")
+ if docopy and current_dependency != "" and current_dependency != dependency:
+ tab = tab[:-1]
+ print(tab+"}")
+
+## Open the dependency if
+ if docopy and current_dependency != dependency and dependency != "":
+ print(tab+"if (%(target)s->%(dependency)s)\n%(tab)s{"%vars())
+ tab = tab+"\t"
+ current_dependency = dependency
+
+## Open the guard if
+ if docopy and current_dependency != dependency and dependency != "":
+ print(tab+"if ($(target)s->%(dependency)s)\n%(tab)s{"%vars())
+ tab = tab+"\t"
+
+ if current_guard != guardbit and guardbit != "":
+ print(tab+"if (CHECKDIRTY(%(bit)s->%(guardbit)s, bitID))\n%(tab)s{"%vars())
+ tab = tab+"\t"
+ if members[0] != "*" and guardbit[0:6] == "enable":
+ print(tab+"glAble able[2];")
+ print(tab+"able[0] = diff_api.Disable;")
+ print(tab+"able[1] = diff_api.Enable;")
+
+ current_dependency = dependency
+ current_guard = guardbit
+
+## Handle text dump
+ if members[0] == "*":
+ print(tab+members[1:])
+ else:
+ ## Parse the members variable
+ mainelem = re.split(",", members)
+ elems = re.split("\|", members)
+ if len(elems) > 1:
+ mainelem = [""]
+ mainelem[0] = elems[0]
+ elems = re.split(",", elems[1])
+ newelems = []
+ for elem in elems:
+ elem = mainelem[0] + "." + elem
+ newelems += [elem]
+ elems = newelems
+ else:
+ elems = re.split(",", members)
+
+ ## Check member values
+ if guardbit != "extensions":
+ sys.stdout.write(tab+"if (")
+ first = 1
+ for elem in elems:
+ if first != 1:
+ print(" ||\n"+tab+" ", end="")
+ first = 0
+ sys.stdout.write("%(current)s->%(elem)s != %(target)s->%(elem)s"%vars())
+ print(")\n"+tab+"{")
+ tab = tab+"\t"
+
+## Handle text function
+ if func[0] == "*":
+ func = func[1:]
+ print(tab+func)
+ else:
+ if func != "":
+## Call the glhw function
+ if guardbit[0:6] == "enable":
+ print(tab+"able["+target+"->"+elems[0]+"]("+func+");")
+ elif guardbit == "extensions":
+ print(tab+"crState$state_name",end="")
+ if docopy == 1:
+ print("Diff",end="")
+ else:
+ print("Switch",end="")
+ print("Extensions(from, to);")
+ else:
+ funcargs = re.split(",", func)
+ #print "// funcargs:",funcargs
+ func = funcargs.pop(0)
+
+ if func[-1] == "v":
+ v_type = func[-2:-1]
+ num_elems = len(elems)
+ print(tab+v_types[v_type]+" varg["+str(num_elems)+"];")
+ i = 0
+ for elem in elems:
+ print(tab+"varg["+str(i)+"] = "+target+"->"+elem+";")
+ i += 1
+ elif func[-3:] == "vNV":
+ v_type = func[-4:-3]
+ num_elems = len(elems)
+ print(tab+v_types[v_type]+" varg["+str(num_elems)+"];")
+ i = 0
+ for elem in elems:
+ print(tab+"varg["+str(i)+"] = "+target+"->"+elem+";")
+ i += 1
+
+ sys.stdout.write(tab+"diff_api.%(func)s("%vars())
+ for funcarg in funcargs:
+ sys.stdout.write(funcarg+", ")
+
+## Handle vargs
+ if func[-1] == "v" or func[-3:] == "vNV":
+ sys.stdout.write("varg")
+ else:
+ first = 1
+ for elem in elems:
+ if first != 1:
+ sys.stdout.write(",\n"+tab+" ")
+ first = 0
+ sys.stdout.write(target+"->"+elem)
+ print(");")
+
+## Do the sync if necessary
+ if docopy and guardbit != "extensions":
+ for elem in mainelem:
+ print(tab+current+"->"+elem+" = "+target+"->"+elem+";")
+
+ ## Do the clear if necessary
+ if doinvalid:
+ if guardbit != "":
+ print(tab+"FILLDIRTY(%(bit)s->%(guardbit)s);"%vars())
+ print(tab+"FILLDIRTY(%(bit)s->dirty);"%vars())
+ if extrabit != "":
+ print(tab+"FILLDIRTY(%(extrabit)s->dirty);"%vars())
+
+ ## Close the compare
+ if guardbit != "extensions":
+ tab = tab[:-1]
+ print(tab+"}")
+
+## Do final closures
+ if current_guard != "":
+ print(tab+"CLEARDIRTY(%(bit)s->%(current_guard)s, nbitID);"%vars())
+ tab = tab[:-1]
+ print(tab+"}")
+ if docopy and current_dependency != "":
+ tab = tab[:-1]
+ print(tab+"} /*%(current_dependency)s*/"%vars())
+
+ print(tab+"CLEARDIRTY(%(bit)s->dirty, nbitID);"%vars())
+
+main()
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 100755
index 00000000..dc7da7b2
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/get_components.py
@@ -0,0 +1,141 @@
+# Copyright (c) 2001, Stanford University
+# All rights reserved.
+#
+# See the file LICENSE.txt for information on redistributing this software.
+
+from __future__ import print_function
+
+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 )
+ {
+""")
+for comp in sorted(num_components.keys()):
+ print('\t\t\tcase %s: return %d;' % (comp,num_components[comp]))
+
+for comp in sorted(num_extended_components.keys()):
+ (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
new file mode 100644
index 00000000..9ba9d4c6
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state.h
@@ -0,0 +1,80 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved.
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#ifndef STATE_H
+#define STATE_H
+
+#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;
+
+extern SPUDispatchTable diff_api;
+extern CRStateBits *__currentBits;
+
+#define GetCurrentBits() __currentBits
+
+#ifdef CHROMIUM_THREADSAFE
+#include <cr_threads.h>
+
+extern CRtsd __contextTSD;
+#define GetCurrentContext() VBoxTlsRefGetCurrent(CRContext, &__contextTSD)
+
+/* NOTE: below SetCurrentContext stuff is supposed to be used only internally!!
+ * it is placed here only to simplify things since some code besides state_init.c
+ * (i.e. state_glsl.c) is using it */
+#define SetCurrentContext(_ctx) VBoxTlsRefSetCurrent(CRContext, &__contextTSD, _ctx)
+#else
+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 );
+
+/* Normally these functions would have been in cr_bufferobject.h but
+ * that led to a number of issues.
+ */
+void crStateBufferObjectInit(CRContext *ctx);
+
+void crStateBufferObjectDestroy (CRContext *ctx);
+
+void crStateBufferObjectDiff(CRBufferObjectBits *bb, CRbitvalue *bitID,
+ CRContext *fromCtx, CRContext *toCtx);
+
+void crStateBufferObjectSwitch(CRBufferObjectBits *bb, CRbitvalue *bitID,
+ CRContext *fromCtx, CRContext *toCtx);
+
+/* These would normally be in cr_client.h */
+
+void crStateClientDiff(CRClientBits *cb, CRbitvalue *bitID, CRContext *from, CRContext *to);
+
+void crStateClientSwitch(CRClientBits *cb, CRbitvalue *bitID, CRContext *from, CRContext *to);
+
+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);
+void crStateOnTextureUsageRelease(CRSharedState *pS, CRTextureObj *pObj);
+#endif
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_attrib.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_attrib.c
new file mode 100644
index 00000000..a226a8d7
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_attrib.c
@@ -0,0 +1,1185 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#include <stdio.h>
+#include "state.h"
+#include "state/cr_statetypes.h"
+#include "state_internals.h"
+#include "cr_error.h"
+#include "cr_mem.h"
+
+/**
+ * \mainpage state_tracker
+ *
+ * \section StateTrackerIntroduction Introduction
+ *
+ * Chromium consists of all the top-level files in the cr
+ * directory. The state_tracker module basically takes care of API dispatch,
+ * and OpenGL state management.
+ *
+ *
+ */
+void crStateAttribInit (CRAttribState *a)
+{
+ int i;
+ a->attribStackDepth = 0;
+ a->accumBufferStackDepth = 0;
+ a->colorBufferStackDepth = 0;
+ a->currentStackDepth = 0;
+ a->depthBufferStackDepth = 0;
+ a->enableStackDepth = 0;
+ for ( i = 0 ; i < CR_MAX_ATTRIB_STACK_DEPTH ; i++)
+ {
+ a->enableStack[i].clip = NULL;
+ a->enableStack[i].light = NULL;
+ a->lightingStack[i].light = NULL;
+ a->transformStack[i].clip = NULL;
+ a->transformStack[i].clipPlane = NULL;
+ }
+ a->evalStackDepth = 0;
+ a->fogStackDepth = 0;
+ a->lightingStackDepth = 0;
+ a->lineStackDepth = 0;
+ a->listStackDepth = 0;
+ a->pixelModeStackDepth = 0;
+ a->pointStackDepth = 0;
+ a->polygonStackDepth = 0;
+ a->polygonStippleStackDepth = 0;
+ a->scissorStackDepth = 0;
+ a->stencilBufferStackDepth = 0;
+ a->textureStackDepth = 0;
+ a->transformStackDepth = 0;
+ a->viewportStackDepth = 0;
+}
+
+/** @todo check if NV rect needed too*/
+static void
+copy_texunit(CRTextureUnit *dest, const CRTextureUnit *src)
+{
+ dest->enabled1D = src->enabled1D;
+ dest->enabled2D = src->enabled2D;
+ dest->enabled3D = src->enabled3D;
+ dest->enabledCubeMap = src->enabledCubeMap;
+ dest->envMode = src->envMode;
+ dest->envColor = src->envColor;
+ dest->textureGen = src->textureGen;
+ dest->objSCoeff = src->objSCoeff;
+ dest->objTCoeff = src->objTCoeff;
+ dest->objRCoeff = src->objRCoeff;
+ dest->objQCoeff = src->objQCoeff;
+ dest->eyeSCoeff = src->eyeSCoeff;
+ dest->eyeTCoeff = src->eyeTCoeff;
+ dest->eyeRCoeff = src->eyeRCoeff;
+ dest->eyeQCoeff = src->eyeQCoeff;
+ dest->gen = src->gen;
+ dest->currentTexture1D = src->currentTexture1D;
+ dest->currentTexture2D = src->currentTexture2D;
+ dest->currentTexture3D = src->currentTexture3D;
+ dest->currentTextureCubeMap = src->currentTextureCubeMap;
+}
+
+static void
+copy_texobj(CRTextureObj *dest, CRTextureObj *src, GLboolean copyName)
+{
+ if (copyName)
+ {
+ dest->id = src->id;
+ dest->hwid = crStateGetTextureObjHWID(src);
+ }
+
+ dest->borderColor = src->borderColor;
+ dest->wrapS = src->wrapS;
+ dest->wrapT = src->wrapT;
+ dest->minFilter = src->minFilter;
+ dest->magFilter = src->magFilter;
+#ifdef CR_OPENGL_VERSION_1_2
+ dest->priority = src->priority;
+ dest->wrapR = src->wrapR;
+ dest->minLod = src->minLod;
+ dest->maxLod = src->maxLod;
+ dest->baseLevel = src->baseLevel;
+ dest->maxLevel = src->maxLevel;
+#endif
+#ifdef CR_EXT_texture_filter_anisotropic
+ dest->maxAnisotropy = src->maxAnisotropy;
+#endif
+}
+
+void STATE_APIENTRY crStatePushAttrib(GLbitfield mask)
+{
+ CRContext *g = GetCurrentContext();
+ CRAttribState *a = &(g->attrib);
+ CRStateBits *sb = GetCurrentBits();
+ CRAttribBits *ab = &(sb->attrib);
+ unsigned int i;
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glPushAttrib called in Begin/End");
+ return;
+ }
+
+ if (a->attribStackDepth == CR_MAX_ATTRIB_STACK_DEPTH - 1)
+ {
+ crStateError(__LINE__, __FILE__, GL_STACK_OVERFLOW, "glPushAttrib called with a full stack!" );
+ return;
+ }
+
+ FLUSH();
+
+ a->pushMaskStack[a->attribStackDepth++] = mask;
+
+ if (mask & GL_ACCUM_BUFFER_BIT)
+ {
+ a->accumBufferStack[a->accumBufferStackDepth].accumClearValue = g->buffer.accumClearValue;
+ a->accumBufferStackDepth++;
+ }
+ if (mask & GL_COLOR_BUFFER_BIT)
+ {
+ a->colorBufferStack[a->colorBufferStackDepth].alphaTest = g->buffer.alphaTest;
+ a->colorBufferStack[a->colorBufferStackDepth].alphaTestFunc = g->buffer.alphaTestFunc;
+ a->colorBufferStack[a->colorBufferStackDepth].alphaTestRef = g->buffer.alphaTestRef;
+ a->colorBufferStack[a->colorBufferStackDepth].blend = g->buffer.blend;
+ a->colorBufferStack[a->colorBufferStackDepth].blendSrcRGB = g->buffer.blendSrcRGB;
+ a->colorBufferStack[a->colorBufferStackDepth].blendDstRGB = g->buffer.blendDstRGB;
+#if defined(CR_EXT_blend_func_separate)
+ a->colorBufferStack[a->colorBufferStackDepth].blendSrcA = g->buffer.blendSrcA;
+ a->colorBufferStack[a->colorBufferStackDepth].blendDstA = g->buffer.blendDstA;
+#endif
+#ifdef CR_EXT_blend_color
+ a->colorBufferStack[a->colorBufferStackDepth].blendColor = g->buffer.blendColor;
+#endif
+#if defined(CR_EXT_blend_minmax) || defined(CR_EXT_blend_subtract) || defined(CR_EXT_blend_logic_op)
+ a->colorBufferStack[a->colorBufferStackDepth].blendEquation = g->buffer.blendEquation;
+#endif
+ a->colorBufferStack[a->colorBufferStackDepth].dither = g->buffer.dither;
+ a->colorBufferStack[a->colorBufferStackDepth].drawBuffer = g->buffer.drawBuffer;
+ a->colorBufferStack[a->colorBufferStackDepth].logicOp = g->buffer.logicOp;
+ a->colorBufferStack[a->colorBufferStackDepth].indexLogicOp = g->buffer.indexLogicOp;
+ a->colorBufferStack[a->colorBufferStackDepth].logicOpMode = g->buffer.logicOpMode;
+ a->colorBufferStack[a->colorBufferStackDepth].colorClearValue = g->buffer.colorClearValue;
+ a->colorBufferStack[a->colorBufferStackDepth].indexClearValue = g->buffer.indexClearValue;
+ a->colorBufferStack[a->colorBufferStackDepth].colorWriteMask = g->buffer.colorWriteMask;
+ a->colorBufferStack[a->colorBufferStackDepth].indexWriteMask = g->buffer.indexWriteMask;
+ a->colorBufferStackDepth++;
+ }
+ if (mask & GL_CURRENT_BIT)
+ {
+ for (i = 0 ; i < CR_MAX_VERTEX_ATTRIBS ; i++)
+ {
+ COPY_4V(a->currentStack[a->currentStackDepth].attrib[i] , g->current.vertexAttrib[i]);
+ COPY_4V(a->currentStack[a->currentStackDepth].rasterAttrib[i] , g->current.rasterAttrib[i]);
+ }
+ a->currentStack[a->currentStackDepth].rasterValid = g->current.rasterValid;
+ a->currentStack[a->currentStackDepth].edgeFlag = g->current.edgeFlag;
+ a->currentStack[a->currentStackDepth].colorIndex = g->current.colorIndex;
+ a->currentStackDepth++;
+ }
+ if (mask & GL_DEPTH_BUFFER_BIT)
+ {
+ a->depthBufferStack[a->depthBufferStackDepth].depthTest = g->buffer.depthTest;
+ a->depthBufferStack[a->depthBufferStackDepth].depthFunc = g->buffer.depthFunc;
+ a->depthBufferStack[a->depthBufferStackDepth].depthClearValue = g->buffer.depthClearValue;
+ a->depthBufferStack[a->depthBufferStackDepth].depthMask = g->buffer.depthMask;
+ a->depthBufferStackDepth++;
+ }
+ if (mask & GL_ENABLE_BIT)
+ {
+ if (a->enableStack[a->enableStackDepth].clip == NULL)
+ {
+ a->enableStack[a->enableStackDepth].clip = (GLboolean *) crCalloc( g->limits.maxClipPlanes * sizeof( GLboolean ));
+ }
+ if (a->enableStack[a->enableStackDepth].light == NULL)
+ {
+ a->enableStack[a->enableStackDepth].light = (GLboolean *) crCalloc( g->limits.maxLights * sizeof( GLboolean ));
+ }
+ a->enableStack[a->enableStackDepth].alphaTest = g->buffer.alphaTest;
+ a->enableStack[a->enableStackDepth].autoNormal = g->eval.autoNormal;
+ a->enableStack[a->enableStackDepth].blend = g->buffer.blend;
+ for (i = 0 ; i < g->limits.maxClipPlanes ; i++)
+ {
+ a->enableStack[a->enableStackDepth].clip[i] = g->transform.clip[i];
+ }
+ a->enableStack[a->enableStackDepth].colorMaterial = g->lighting.colorMaterial;
+ a->enableStack[a->enableStackDepth].cullFace = g->polygon.cullFace;
+ a->enableStack[a->enableStackDepth].depthTest = g->buffer.depthTest;
+ a->enableStack[a->enableStackDepth].dither = g->buffer.dither;
+ a->enableStack[a->enableStackDepth].fog = g->fog.enable;
+ for (i = 0 ; i < g->limits.maxLights ; i++)
+ {
+ a->enableStack[a->enableStackDepth].light[i] = g->lighting.light[i].enable;
+ }
+ a->enableStack[a->enableStackDepth].lighting = g->lighting.lighting;
+ a->enableStack[a->enableStackDepth].lineSmooth = g->line.lineSmooth;
+ a->enableStack[a->enableStackDepth].lineStipple = g->line.lineStipple;
+ a->enableStack[a->enableStackDepth].logicOp = g->buffer.logicOp;
+ a->enableStack[a->enableStackDepth].indexLogicOp = g->buffer.indexLogicOp;
+ for (i = 0 ; i < GLEVAL_TOT ; i++)
+ {
+ a->enableStack[a->enableStackDepth].map1[i] = g->eval.enable1D[i];
+ a->enableStack[a->enableStackDepth].map2[i] = g->eval.enable2D[i];
+ }
+ a->enableStack[a->enableStackDepth].normalize = g->transform.normalize;
+ a->enableStack[a->enableStackDepth].pointSmooth = g->point.pointSmooth;
+#if CR_ARB_point_sprite
+ a->enableStack[a->enableStackDepth].pointSprite = g->point.pointSprite;
+ for (i = 0; i < CR_MAX_TEXTURE_UNITS; i++)
+ a->enableStack[a->enableStackDepth].coordReplacement[i] = g->point.coordReplacement[i];
+#endif
+ a->enableStack[a->enableStackDepth].polygonOffsetLine = g->polygon.polygonOffsetLine;
+ a->enableStack[a->enableStackDepth].polygonOffsetFill = g->polygon.polygonOffsetFill;
+ a->enableStack[a->enableStackDepth].polygonOffsetPoint = g->polygon.polygonOffsetPoint;
+ a->enableStack[a->enableStackDepth].polygonSmooth = g->polygon.polygonSmooth;
+ a->enableStack[a->enableStackDepth].polygonStipple = g->polygon.polygonStipple;
+#ifdef CR_OPENGL_VERSION_1_2
+ a->enableStack[a->enableStackDepth].rescaleNormals = g->transform.rescaleNormals;
+#endif
+ a->enableStack[a->enableStackDepth].scissorTest = g->viewport.scissorTest;
+ a->enableStack[a->enableStackDepth].stencilTest = g->stencil.stencilTest;
+ for (i = 0 ; i < g->limits.maxTextureUnits; i++)
+ {
+ a->enableStack[a->enableStackDepth].texture1D[i] = g->texture.unit[i].enabled1D;
+ a->enableStack[a->enableStackDepth].texture2D[i] = g->texture.unit[i].enabled2D;
+#ifdef CR_OPENGL_VERSION_1_2
+ a->enableStack[a->enableStackDepth].texture3D[i] = g->texture.unit[i].enabled3D;
+#endif
+#ifdef CR_ARB_texture_cube_map
+ a->enableStack[a->enableStackDepth].textureCubeMap[i] = g->texture.unit[i].enabledCubeMap;
+#endif
+#ifdef CR_NV_texture_rectangle
+ a->enableStack[a->enableStackDepth].textureRect[i] = g->texture.unit[i].enabledRect;
+#endif
+ a->enableStack[a->enableStackDepth].textureGenS[i] = g->texture.unit[i].textureGen.s;
+ a->enableStack[a->enableStackDepth].textureGenT[i] = g->texture.unit[i].textureGen.t;
+ a->enableStack[a->enableStackDepth].textureGenR[i] = g->texture.unit[i].textureGen.r;
+ a->enableStack[a->enableStackDepth].textureGenQ[i] = g->texture.unit[i].textureGen.q;
+ }
+ a->enableStackDepth++;
+ }
+ if (mask & GL_EVAL_BIT)
+ {
+ for (i = 0 ; i < GLEVAL_TOT ; i++)
+ {
+ int size1 = g->eval.eval1D[i].order * gleval_sizes[i] *
+ sizeof (GLfloat);
+ int size2 = g->eval.eval2D[i].uorder * g->eval.eval2D[i].vorder *
+ gleval_sizes[i] * sizeof (GLfloat);
+ a->evalStack[a->evalStackDepth].enable1D[i] = g->eval.enable1D[i];
+ a->evalStack[a->evalStackDepth].enable2D[i] = g->eval.enable2D[i];
+ a->evalStack[a->evalStackDepth].eval1D[i].u1 = g->eval.eval1D[i].u1;
+ a->evalStack[a->evalStackDepth].eval1D[i].u2 = g->eval.eval1D[i].u2;
+ a->evalStack[a->evalStackDepth].eval1D[i].order = g->eval.eval1D[i].order;
+ a->evalStack[a->evalStackDepth].eval1D[i].coeff = (GLfloat*)crCalloc(size1);
+ crMemcpy(a->evalStack[a->evalStackDepth].eval1D[i].coeff, g->eval.eval1D[i].coeff, size1);
+ a->evalStack[a->evalStackDepth].eval2D[i].u1 = g->eval.eval2D[i].u1;
+ a->evalStack[a->evalStackDepth].eval2D[i].u2 = g->eval.eval2D[i].u2;
+ a->evalStack[a->evalStackDepth].eval2D[i].v1 = g->eval.eval2D[i].v1;
+ a->evalStack[a->evalStackDepth].eval2D[i].v2 = g->eval.eval2D[i].v2;
+ a->evalStack[a->evalStackDepth].eval2D[i].uorder = g->eval.eval2D[i].uorder;
+ a->evalStack[a->evalStackDepth].eval2D[i].vorder = g->eval.eval2D[i].vorder;
+ a->evalStack[a->evalStackDepth].eval2D[i].coeff = (GLfloat*)crCalloc(size2);
+ crMemcpy(a->evalStack[a->evalStackDepth].eval2D[i].coeff, g->eval.eval2D[i].coeff, size2);
+ }
+ a->evalStack[a->evalStackDepth].autoNormal = g->eval.autoNormal;
+ a->evalStack[a->evalStackDepth].un1D = g->eval.un1D;
+ a->evalStack[a->evalStackDepth].u11D = g->eval.u11D;
+ a->evalStack[a->evalStackDepth].u21D = g->eval.u21D;
+ a->evalStack[a->evalStackDepth].un2D = g->eval.un2D;
+ a->evalStack[a->evalStackDepth].u12D = g->eval.u12D;
+ a->evalStack[a->evalStackDepth].u22D = g->eval.u22D;
+ a->evalStack[a->evalStackDepth].vn2D = g->eval.vn2D;
+ a->evalStack[a->evalStackDepth].v12D = g->eval.v12D;
+ a->evalStack[a->evalStackDepth].v22D = g->eval.v22D;
+ a->evalStackDepth++;
+ }
+ if (mask & GL_FOG_BIT)
+ {
+ a->fogStack[a->fogStackDepth].enable = g->fog.enable;
+ a->fogStack[a->fogStackDepth].color = g->fog.color;
+ a->fogStack[a->fogStackDepth].density = g->fog.density;
+ a->fogStack[a->fogStackDepth].start = g->fog.start;
+ a->fogStack[a->fogStackDepth].end = g->fog.end;
+ a->fogStack[a->fogStackDepth].index = g->fog.index;
+ a->fogStack[a->fogStackDepth].mode = g->fog.mode;
+ a->fogStackDepth++;
+ }
+ if (mask & GL_HINT_BIT)
+ {
+ a->hintStack[a->hintStackDepth].perspectiveCorrection = g->hint.perspectiveCorrection;
+ a->hintStack[a->hintStackDepth].pointSmooth = g->hint.pointSmooth;
+ a->hintStack[a->hintStackDepth].lineSmooth = g->hint.lineSmooth;
+ a->hintStack[a->hintStackDepth].polygonSmooth = g->hint.polygonSmooth;
+ a->hintStack[a->hintStackDepth].fog = g->hint.fog;
+#ifdef CR_EXT_clip_volume_hint
+ a->hintStack[a->hintStackDepth].clipVolumeClipping = g->hint.clipVolumeClipping;
+#endif
+#ifdef CR_ARB_texture_compression
+ a->hintStack[a->hintStackDepth].textureCompression = g->hint.textureCompression;
+#endif
+#ifdef CR_SGIS_generate_mipmap
+ a->hintStack[a->hintStackDepth].generateMipmap = g->hint.generateMipmap;
+#endif
+ a->hintStackDepth++;
+ }
+ if (mask & GL_LIGHTING_BIT)
+ {
+ if (a->lightingStack[a->lightingStackDepth].light == NULL)
+ {
+ a->lightingStack[a->lightingStackDepth].light = (CRLight *) crCalloc( g->limits.maxLights * sizeof( CRLight ));
+ }
+ a->lightingStack[a->lightingStackDepth].lightModelAmbient = g->lighting.lightModelAmbient;
+ a->lightingStack[a->lightingStackDepth].lightModelLocalViewer = g->lighting.lightModelLocalViewer;
+ a->lightingStack[a->lightingStackDepth].lightModelTwoSide = g->lighting.lightModelTwoSide;
+#if defined(CR_EXT_separate_specular_color) || defined(CR_OPENGL_VERSION_1_2)
+ a->lightingStack[a->lightingStackDepth].lightModelColorControlEXT = g->lighting.lightModelColorControlEXT;
+#endif
+ a->lightingStack[a->lightingStackDepth].lighting = g->lighting.lighting;
+ a->lightingStack[a->lightingStackDepth].colorMaterial = g->lighting.colorMaterial;
+ a->lightingStack[a->lightingStackDepth].colorMaterialMode = g->lighting.colorMaterialMode;
+ a->lightingStack[a->lightingStackDepth].colorMaterialFace = g->lighting.colorMaterialFace;
+ for (i = 0 ; i < g->limits.maxLights; i++)
+ {
+ a->lightingStack[a->lightingStackDepth].light[i].enable = g->lighting.light[i].enable;
+ a->lightingStack[a->lightingStackDepth].light[i].ambient = g->lighting.light[i].ambient;
+ a->lightingStack[a->lightingStackDepth].light[i].diffuse = g->lighting.light[i].diffuse;
+ a->lightingStack[a->lightingStackDepth].light[i].specular = g->lighting.light[i].specular;
+ a->lightingStack[a->lightingStackDepth].light[i].spotDirection = g->lighting.light[i].spotDirection;
+ a->lightingStack[a->lightingStackDepth].light[i].position = g->lighting.light[i].position;
+ a->lightingStack[a->lightingStackDepth].light[i].spotExponent = g->lighting.light[i].spotExponent;
+ a->lightingStack[a->lightingStackDepth].light[i].spotCutoff = g->lighting.light[i].spotCutoff;
+ a->lightingStack[a->lightingStackDepth].light[i].constantAttenuation = g->lighting.light[i].constantAttenuation;
+ a->lightingStack[a->lightingStackDepth].light[i].linearAttenuation = g->lighting.light[i].linearAttenuation;
+ a->lightingStack[a->lightingStackDepth].light[i].quadraticAttenuation = g->lighting.light[i].quadraticAttenuation;
+ }
+ for (i = 0 ; i < 2 ; i++)
+ {
+ a->lightingStack[a->lightingStackDepth].ambient[i] = g->lighting.ambient[i];
+ a->lightingStack[a->lightingStackDepth].diffuse[i] = g->lighting.diffuse[i];
+ a->lightingStack[a->lightingStackDepth].specular[i] = g->lighting.specular[i];
+ a->lightingStack[a->lightingStackDepth].emission[i] = g->lighting.emission[i];
+ a->lightingStack[a->lightingStackDepth].shininess[i] = g->lighting.shininess[i];
+ a->lightingStack[a->lightingStackDepth].indexes[i][0] = g->lighting.indexes[i][0];
+ a->lightingStack[a->lightingStackDepth].indexes[i][1] = g->lighting.indexes[i][1];
+ a->lightingStack[a->lightingStackDepth].indexes[i][2] = g->lighting.indexes[i][2];
+ }
+ a->lightingStack[a->lightingStackDepth].shadeModel = g->lighting.shadeModel;
+ a->lightingStackDepth++;
+ }
+ if (mask & GL_LINE_BIT)
+ {
+ a->lineStack[a->lineStackDepth].lineSmooth = g->line.lineSmooth;
+ a->lineStack[a->lineStackDepth].lineStipple = g->line.lineStipple;
+ a->lineStack[a->lineStackDepth].pattern = g->line.pattern;
+ a->lineStack[a->lineStackDepth].repeat = g->line.repeat;
+ a->lineStack[a->lineStackDepth].width = g->line.width;
+ a->lineStackDepth++;
+ }
+ if (mask & GL_LIST_BIT)
+ {
+ a->listStack[a->listStackDepth].base = g->lists.base;
+ a->listStackDepth++;
+ }
+ if (mask & GL_PIXEL_MODE_BIT)
+ {
+ a->pixelModeStack[a->pixelModeStackDepth].bias = g->pixel.bias;
+ a->pixelModeStack[a->pixelModeStackDepth].scale = g->pixel.scale;
+ a->pixelModeStack[a->pixelModeStackDepth].indexOffset = g->pixel.indexOffset;
+ a->pixelModeStack[a->pixelModeStackDepth].indexShift = g->pixel.indexShift;
+ a->pixelModeStack[a->pixelModeStackDepth].mapColor = g->pixel.mapColor;
+ a->pixelModeStack[a->pixelModeStackDepth].mapStencil = g->pixel.mapStencil;
+ a->pixelModeStack[a->pixelModeStackDepth].xZoom = g->pixel.xZoom;
+ a->pixelModeStack[a->pixelModeStackDepth].yZoom = g->pixel.yZoom;
+ a->pixelModeStack[a->pixelModeStackDepth].readBuffer = g->buffer.readBuffer;
+ a->pixelModeStackDepth++;
+ }
+ if (mask & GL_POINT_BIT)
+ {
+ a->pointStack[a->pointStackDepth].pointSmooth = g->point.pointSmooth;
+#if CR_ARB_point_sprite
+ a->pointStack[a->pointStackDepth].pointSprite = g->point.pointSprite;
+ for (i = 0; i < CR_MAX_TEXTURE_UNITS; i++)
+ a->pointStack[a->enableStackDepth].coordReplacement[i] = g->point.coordReplacement[i];
+#endif
+ a->pointStack[a->pointStackDepth].pointSize = g->point.pointSize;
+ a->pointStackDepth++;
+ }
+ if (mask & GL_POLYGON_BIT)
+ {
+ a->polygonStack[a->polygonStackDepth].cullFace = g->polygon.cullFace;
+ a->polygonStack[a->polygonStackDepth].cullFaceMode = g->polygon.cullFaceMode;
+ a->polygonStack[a->polygonStackDepth].frontFace = g->polygon.frontFace;
+ a->polygonStack[a->polygonStackDepth].frontMode = g->polygon.frontMode;
+ a->polygonStack[a->polygonStackDepth].backMode = g->polygon.backMode;
+ a->polygonStack[a->polygonStackDepth].polygonSmooth = g->polygon.polygonSmooth;
+ a->polygonStack[a->polygonStackDepth].polygonStipple = g->polygon.polygonStipple;
+ a->polygonStack[a->polygonStackDepth].polygonOffsetFill = g->polygon.polygonOffsetFill;
+ a->polygonStack[a->polygonStackDepth].polygonOffsetLine = g->polygon.polygonOffsetLine;
+ a->polygonStack[a->polygonStackDepth].polygonOffsetPoint = g->polygon.polygonOffsetPoint;
+ a->polygonStack[a->polygonStackDepth].offsetFactor = g->polygon.offsetFactor;
+ a->polygonStack[a->polygonStackDepth].offsetUnits = g->polygon.offsetUnits;
+ a->polygonStackDepth++;
+ }
+ if (mask & GL_POLYGON_STIPPLE_BIT)
+ {
+ crMemcpy( a->polygonStippleStack[a->polygonStippleStackDepth].pattern, g->polygon.stipple, 32*sizeof(GLint) );
+ a->polygonStippleStackDepth++;
+ }
+ if (mask & GL_SCISSOR_BIT)
+ {
+ a->scissorStack[a->scissorStackDepth].scissorTest = g->viewport.scissorTest;
+ a->scissorStack[a->scissorStackDepth].scissorX = g->viewport.scissorX;
+ a->scissorStack[a->scissorStackDepth].scissorY = g->viewport.scissorY;
+ a->scissorStack[a->scissorStackDepth].scissorW = g->viewport.scissorW;
+ a->scissorStack[a->scissorStackDepth].scissorH = g->viewport.scissorH;
+ a->scissorStackDepth++;
+ }
+ if (mask & GL_STENCIL_BUFFER_BIT)
+ {
+ a->stencilBufferStack[a->stencilBufferStackDepth].stencilTest = g->stencil.stencilTest;
+ 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)
+ {
+ CRTextureStack *tState = a->textureStack + a->textureStackDepth;
+ tState->curTextureUnit = g->texture.curTextureUnit;
+ for (i = 0 ; i < g->limits.maxTextureUnits ; i++)
+ {
+ /* per-unit state */
+ copy_texunit(&tState->unit[i], &g->texture.unit[i]);
+ /* texture object state */
+ copy_texobj(&tState->unit[i].Saved1D, g->texture.unit[i].currentTexture1D, GL_TRUE);
+ copy_texobj(&tState->unit[i].Saved2D, g->texture.unit[i].currentTexture2D, GL_TRUE);
+#ifdef CR_OPENGL_VERSION_1_2
+ copy_texobj(&tState->unit[i].Saved3D, g->texture.unit[i].currentTexture3D, GL_TRUE);
+#endif
+#ifdef CR_ARB_texture_cube_map
+ copy_texobj(&tState->unit[i].SavedCubeMap, g->texture.unit[i].currentTextureCubeMap, GL_TRUE);
+#endif
+#ifdef CR_NV_texture_rectangle
+ copy_texobj(&tState->unit[i].SavedRect, g->texture.unit[i].currentTextureRect, GL_TRUE);
+#endif
+ }
+ a->textureStackDepth++;
+ }
+ if (mask & GL_TRANSFORM_BIT)
+ {
+ if (a->transformStack[a->transformStackDepth].clip == NULL)
+ {
+ a->transformStack[a->transformStackDepth].clip = (GLboolean *) crCalloc( g->limits.maxClipPlanes * sizeof( GLboolean ));
+ }
+ if (a->transformStack[a->transformStackDepth].clipPlane == NULL)
+ {
+ a->transformStack[a->transformStackDepth].clipPlane = (GLvectord *) crCalloc( g->limits.maxClipPlanes * sizeof( GLvectord ));
+ }
+ a->transformStack[a->transformStackDepth].matrixMode = g->transform.matrixMode;
+ for (i = 0 ; i < g->limits.maxClipPlanes ; i++)
+ {
+ a->transformStack[a->transformStackDepth].clip[i] = g->transform.clip[i];
+ a->transformStack[a->transformStackDepth].clipPlane[i] = g->transform.clipPlane[i];
+ }
+ a->transformStack[a->transformStackDepth].normalize = g->transform.normalize;
+#ifdef CR_OPENGL_VERSION_1_2
+ a->transformStack[a->transformStackDepth].rescaleNormals = g->transform.rescaleNormals;
+#endif
+ a->transformStackDepth++;
+ }
+ if (mask & GL_VIEWPORT_BIT)
+ {
+ a->viewportStack[a->viewportStackDepth].viewportX = g->viewport.viewportX;
+ a->viewportStack[a->viewportStackDepth].viewportY = g->viewport.viewportY;
+ a->viewportStack[a->viewportStackDepth].viewportW = g->viewport.viewportW;
+ a->viewportStack[a->viewportStackDepth].viewportH = g->viewport.viewportH;
+ a->viewportStack[a->viewportStackDepth].nearClip = g->viewport.nearClip;
+ a->viewportStack[a->viewportStackDepth].farClip = g->viewport.farClip;
+ a->viewportStackDepth++;
+ }
+
+ DIRTY(ab->dirty, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStatePopAttrib(void)
+{
+ CRContext *g = GetCurrentContext();
+ CRAttribState *a = &(g->attrib);
+ CRStateBits *sb = GetCurrentBits();
+ CRAttribBits *ab = &(sb->attrib);
+ CRbitvalue mask;
+ unsigned int i;
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glPopAttrib called in Begin/End");
+ return;
+ }
+
+ if (a->attribStackDepth == 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty stack!" );
+ return;
+ }
+
+ FLUSH();
+
+ mask = a->pushMaskStack[--a->attribStackDepth];
+
+ if (mask & GL_ACCUM_BUFFER_BIT)
+ {
+ if (a->accumBufferStackDepth == 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty accum buffer stack!" );
+ return;
+ }
+ a->accumBufferStackDepth--;
+ g->buffer.accumClearValue = a->accumBufferStack[a->accumBufferStackDepth].accumClearValue;
+ DIRTY(sb->buffer.dirty, g->neg_bitid);
+ DIRTY(sb->buffer.clearAccum, g->neg_bitid);
+ }
+ if (mask & GL_COLOR_BUFFER_BIT)
+ {
+ if (a->colorBufferStackDepth == 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty color buffer stack!" );
+ return;
+ }
+ a->colorBufferStackDepth--;
+ g->buffer.alphaTest = a->colorBufferStack[a->colorBufferStackDepth].alphaTest;
+ g->buffer.alphaTestFunc = a->colorBufferStack[a->colorBufferStackDepth].alphaTestFunc;
+ g->buffer.alphaTestRef = a->colorBufferStack[a->colorBufferStackDepth].alphaTestRef;
+ g->buffer.blend = a->colorBufferStack[a->colorBufferStackDepth].blend;
+ g->buffer.blendSrcRGB = a->colorBufferStack[a->colorBufferStackDepth].blendSrcRGB;
+ g->buffer.blendDstRGB = a->colorBufferStack[a->colorBufferStackDepth].blendDstRGB;
+#if defined(CR_EXT_blend_func_separate)
+ g->buffer.blendSrcA = a->colorBufferStack[a->colorBufferStackDepth].blendSrcA;
+ g->buffer.blendDstA = a->colorBufferStack[a->colorBufferStackDepth].blendDstA;
+#endif
+#ifdef CR_EXT_blend_color
+ g->buffer.blendColor = a->colorBufferStack[a->colorBufferStackDepth].blendColor;
+#endif
+#if defined(CR_EXT_blend_minmax) || defined(CR_EXT_blend_subtract) || defined(CR_EXT_blend_logic_op)
+ g->buffer.blendEquation = a->colorBufferStack[a->colorBufferStackDepth].blendEquation;
+#endif
+ g->buffer.dither = a->colorBufferStack[a->colorBufferStackDepth].dither;
+ g->buffer.drawBuffer = a->colorBufferStack[a->colorBufferStackDepth].drawBuffer;
+ g->buffer.logicOp = a->colorBufferStack[a->colorBufferStackDepth].logicOp;
+ g->buffer.indexLogicOp = a->colorBufferStack[a->colorBufferStackDepth].indexLogicOp;
+ g->buffer.logicOpMode = a->colorBufferStack[a->colorBufferStackDepth].logicOpMode;
+ g->buffer.colorClearValue = a->colorBufferStack[a->colorBufferStackDepth].colorClearValue;
+ g->buffer.indexClearValue = a->colorBufferStack[a->colorBufferStackDepth].indexClearValue;
+ g->buffer.colorWriteMask = a->colorBufferStack[a->colorBufferStackDepth].colorWriteMask;
+ g->buffer.indexWriteMask = a->colorBufferStack[a->colorBufferStackDepth].indexWriteMask;
+ DIRTY(sb->buffer.dirty, g->neg_bitid);
+ DIRTY(sb->buffer.enable, g->neg_bitid);
+ DIRTY(sb->buffer.alphaFunc, g->neg_bitid);
+ DIRTY(sb->buffer.blendFunc, g->neg_bitid);
+#ifdef CR_EXT_blend_color
+ DIRTY(sb->buffer.blendColor, g->neg_bitid);
+#endif
+#if defined(CR_EXT_blend_minmax) || defined(CR_EXT_blend_subtract) || defined(CR_EXT_blend_logic_op)
+ DIRTY(sb->buffer.blendEquation, g->neg_bitid);
+#endif
+ DIRTY(sb->buffer.drawBuffer, g->neg_bitid);
+ DIRTY(sb->buffer.logicOp, g->neg_bitid);
+ DIRTY(sb->buffer.indexLogicOp, g->neg_bitid);
+ DIRTY(sb->buffer.clearColor, g->neg_bitid);
+ DIRTY(sb->buffer.clearIndex, g->neg_bitid);
+ DIRTY(sb->buffer.colorWriteMask, g->neg_bitid);
+ DIRTY(sb->buffer.indexMask, g->neg_bitid);
+ }
+ if (mask & GL_CURRENT_BIT)
+ {
+ if (a->currentStackDepth == 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty current stack!" );
+ return;
+ }
+ a->currentStackDepth--;
+ for (i = 0 ; i < CR_MAX_VERTEX_ATTRIBS ; i++)
+ {
+ COPY_4V(g->current.vertexAttrib[i], a->currentStack[a->currentStackDepth].attrib[i]);
+ COPY_4V(g->current.rasterAttrib[i], a->currentStack[a->currentStackDepth].rasterAttrib[i]);
+ DIRTY(sb->current.vertexAttrib[i], g->neg_bitid);
+ }
+ g->current.rasterValid = a->currentStack[a->currentStackDepth].rasterValid;
+ g->current.edgeFlag = a->currentStack[a->currentStackDepth].edgeFlag;
+ g->current.colorIndex = a->currentStack[a->currentStackDepth].colorIndex;
+ DIRTY(sb->current.dirty, g->neg_bitid);
+ DIRTY(sb->current.edgeFlag, g->neg_bitid);
+ DIRTY(sb->current.colorIndex, g->neg_bitid);
+ DIRTY(sb->current.rasterPos, g->neg_bitid);
+ }
+ if (mask & GL_DEPTH_BUFFER_BIT)
+ {
+ if (a->depthBufferStackDepth == 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty depth buffer stack!" );
+ return;
+ }
+ a->depthBufferStackDepth--;
+ g->buffer.depthTest = a->depthBufferStack[a->depthBufferStackDepth].depthTest;
+ g->buffer.depthFunc = a->depthBufferStack[a->depthBufferStackDepth].depthFunc;
+ g->buffer.depthClearValue = a->depthBufferStack[a->depthBufferStackDepth].depthClearValue;
+ g->buffer.depthMask = a->depthBufferStack[a->depthBufferStackDepth].depthMask;
+ DIRTY(sb->buffer.dirty, g->neg_bitid);
+ DIRTY(sb->buffer.enable, g->neg_bitid);
+ DIRTY(sb->buffer.depthFunc, g->neg_bitid);
+ DIRTY(sb->buffer.clearDepth, g->neg_bitid);
+ DIRTY(sb->buffer.depthMask, g->neg_bitid);
+ }
+ if (mask & GL_ENABLE_BIT)
+ {
+ if (a->enableStackDepth == 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty enable stack!" );
+ return;
+ }
+ a->enableStackDepth--;
+ g->buffer.alphaTest = a->enableStack[a->enableStackDepth].alphaTest;
+ g->eval.autoNormal = a->enableStack[a->enableStackDepth].autoNormal;
+ g->buffer.blend = a->enableStack[a->enableStackDepth].blend;
+ for (i = 0 ; i < g->limits.maxClipPlanes ; i++)
+ {
+ g->transform.clip[i] = a->enableStack[a->enableStackDepth].clip[i];
+ }
+ g->lighting.colorMaterial = a->enableStack[a->enableStackDepth].colorMaterial;
+ g->polygon.cullFace = a->enableStack[a->enableStackDepth].cullFace;
+ g->buffer.depthTest = a->enableStack[a->enableStackDepth].depthTest;
+ g->buffer.dither = a->enableStack[a->enableStackDepth].dither;
+ g->fog.enable = a->enableStack[a->enableStackDepth].fog;
+ for (i = 0 ; i < g->limits.maxLights ; i++)
+ {
+ g->lighting.light[i].enable = a->enableStack[a->enableStackDepth].light[i];
+ }
+ g->lighting.lighting = a->enableStack[a->enableStackDepth].lighting;
+ g->line.lineSmooth = a->enableStack[a->enableStackDepth].lineSmooth;
+ g->line.lineStipple = a->enableStack[a->enableStackDepth].lineStipple;
+ g->buffer.logicOp = a->enableStack[a->enableStackDepth].logicOp;
+ g->buffer.indexLogicOp = a->enableStack[a->enableStackDepth].indexLogicOp;
+ for (i = 0 ; i < GLEVAL_TOT ; i++)
+ {
+ g->eval.enable1D[i] = a->enableStack[a->enableStackDepth].map1[i];
+ g->eval.enable2D[i] = a->enableStack[a->enableStackDepth].map2[i];
+ }
+ g->transform.normalize = a->enableStack[a->enableStackDepth].normalize;
+ g->point.pointSmooth = a->enableStack[a->enableStackDepth].pointSmooth;
+#ifdef CR_ARB_point_sprite
+ g->point.pointSprite = a->enableStack[a->enableStackDepth].pointSprite;
+ for (i = 0; i < CR_MAX_TEXTURE_UNITS; i++)
+ g->point.coordReplacement[i] = a->enableStack[a->enableStackDepth].coordReplacement[i];
+#endif
+ g->polygon.polygonOffsetLine = a->enableStack[a->enableStackDepth].polygonOffsetLine;
+ g->polygon.polygonOffsetFill = a->enableStack[a->enableStackDepth].polygonOffsetFill;
+ g->polygon.polygonOffsetPoint = a->enableStack[a->enableStackDepth].polygonOffsetPoint;
+ g->polygon.polygonSmooth = a->enableStack[a->enableStackDepth].polygonSmooth;
+ g->polygon.polygonStipple = a->enableStack[a->enableStackDepth].polygonStipple;
+#ifdef CR_OPENGL_VERSION_1_2
+ g->transform.rescaleNormals = a->enableStack[a->enableStackDepth].rescaleNormals;
+#endif
+ g->viewport.scissorTest = a->enableStack[a->enableStackDepth].scissorTest;
+ g->stencil.stencilTest = a->enableStack[a->enableStackDepth].stencilTest;
+ for (i = 0 ; i < g->limits.maxTextureUnits; i++)
+ {
+ g->texture.unit[i].enabled1D = a->enableStack[a->enableStackDepth].texture1D[i];
+ g->texture.unit[i].enabled2D = a->enableStack[a->enableStackDepth].texture2D[i];
+#ifdef CR_OPENGL_VERSION_1_2
+ g->texture.unit[i].enabled3D = a->enableStack[a->enableStackDepth].texture3D[i];
+#endif
+#ifdef CR_ARB_texture_cube_map
+ g->texture.unit[i].enabledCubeMap = a->enableStack[a->enableStackDepth].textureCubeMap[i];
+#endif
+#ifdef CR_NV_texture_rectangle
+ g->texture.unit[i].enabledRect = a->enableStack[a->enableStackDepth].textureRect[i];
+#endif
+ g->texture.unit[i].textureGen.s = a->enableStack[a->enableStackDepth].textureGenS[i];
+ g->texture.unit[i].textureGen.t = a->enableStack[a->enableStackDepth].textureGenT[i];
+ g->texture.unit[i].textureGen.r = a->enableStack[a->enableStackDepth].textureGenR[i];
+ g->texture.unit[i].textureGen.q = a->enableStack[a->enableStackDepth].textureGenQ[i];
+ }
+ DIRTY(sb->buffer.dirty, g->neg_bitid);
+ DIRTY(sb->eval.dirty, g->neg_bitid);
+ DIRTY(sb->transform.dirty, g->neg_bitid);
+ DIRTY(sb->lighting.dirty, g->neg_bitid);
+ DIRTY(sb->fog.dirty, g->neg_bitid);
+ DIRTY(sb->line.dirty, g->neg_bitid);
+ DIRTY(sb->polygon.dirty, g->neg_bitid);
+ DIRTY(sb->viewport.dirty, g->neg_bitid);
+ DIRTY(sb->stencil.dirty, g->neg_bitid);
+ DIRTY(sb->texture.dirty, g->neg_bitid);
+
+ DIRTY(sb->buffer.enable, g->neg_bitid);
+ DIRTY(sb->eval.enable, g->neg_bitid);
+ DIRTY(sb->transform.enable, g->neg_bitid);
+ DIRTY(sb->lighting.enable, g->neg_bitid);
+ DIRTY(sb->fog.enable, g->neg_bitid);
+ DIRTY(sb->line.enable, g->neg_bitid);
+ DIRTY(sb->polygon.enable, g->neg_bitid);
+ DIRTY(sb->viewport.enable, g->neg_bitid);
+ DIRTY(sb->stencil.enable, g->neg_bitid);
+ for (i = 0 ; i < g->limits.maxTextureUnits ; i++)
+ {
+ DIRTY(sb->texture.enable[i], g->neg_bitid);
+ }
+ }
+ if (mask & GL_EVAL_BIT)
+ {
+ if (a->evalStackDepth == 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty eval stack!" );
+ return;
+ }
+ a->evalStackDepth--;
+ for (i = 0 ; i < GLEVAL_TOT ; i++)
+ {
+ int size1 = a->evalStack[a->evalStackDepth].eval1D[i].order * gleval_sizes[i] * sizeof(GLfloat);
+ int size2 = a->evalStack[a->evalStackDepth].eval2D[i].uorder * a->evalStack[a->evalStackDepth].eval2D[i].vorder * gleval_sizes[i] * sizeof (GLfloat);
+ g->eval.enable1D[i] = a->evalStack[a->evalStackDepth].enable1D[i];
+ g->eval.enable2D[i] = a->evalStack[a->evalStackDepth].enable2D[i];
+ g->eval.eval1D[i].u1 = a->evalStack[a->evalStackDepth].eval1D[i].u1;
+ g->eval.eval1D[i].u2 = a->evalStack[a->evalStackDepth].eval1D[i].u2;
+ g->eval.eval1D[i].order = a->evalStack[a->evalStackDepth].eval1D[i].order;
+ crMemcpy((char*)g->eval.eval1D[i].coeff, a->evalStack[a->evalStackDepth].eval1D[i].coeff, size1);
+ crFree(a->evalStack[a->evalStackDepth].eval1D[i].coeff);
+ a->evalStack[a->evalStackDepth].eval1D[i].coeff = NULL;
+ g->eval.eval2D[i].u1 = a->evalStack[a->evalStackDepth].eval2D[i].u1;
+ g->eval.eval2D[i].u2 = a->evalStack[a->evalStackDepth].eval2D[i].u2;
+ g->eval.eval2D[i].v1 = a->evalStack[a->evalStackDepth].eval2D[i].v1;
+ g->eval.eval2D[i].v2 = a->evalStack[a->evalStackDepth].eval2D[i].v2;
+ g->eval.eval2D[i].uorder = a->evalStack[a->evalStackDepth].eval2D[i].uorder;
+ g->eval.eval2D[i].vorder = a->evalStack[a->evalStackDepth].eval2D[i].vorder;
+ crMemcpy((char*)g->eval.eval2D[i].coeff, a->evalStack[a->evalStackDepth].eval2D[i].coeff, size2);
+ crFree(a->evalStack[a->evalStackDepth].eval2D[i].coeff);
+ a->evalStack[a->evalStackDepth].eval2D[i].coeff = NULL;
+ }
+ g->eval.autoNormal = a->evalStack[a->evalStackDepth].autoNormal;
+ g->eval.un1D = a->evalStack[a->evalStackDepth].un1D;
+ g->eval.u11D = a->evalStack[a->evalStackDepth].u11D;
+ g->eval.u21D = a->evalStack[a->evalStackDepth].u21D;
+ g->eval.un2D = a->evalStack[a->evalStackDepth].un2D;
+ g->eval.u12D = a->evalStack[a->evalStackDepth].u12D;
+ g->eval.u22D = a->evalStack[a->evalStackDepth].u22D;
+ g->eval.vn2D = a->evalStack[a->evalStackDepth].vn2D;
+ g->eval.v12D = a->evalStack[a->evalStackDepth].v12D;
+ g->eval.v22D = a->evalStack[a->evalStackDepth].v22D;
+ for (i = 0; i < GLEVAL_TOT; i++) {
+ DIRTY(sb->eval.eval1D[i], g->neg_bitid);
+ DIRTY(sb->eval.eval2D[i], g->neg_bitid);
+ }
+ DIRTY(sb->eval.dirty, g->neg_bitid);
+ DIRTY(sb->eval.grid1D, g->neg_bitid);
+ DIRTY(sb->eval.grid2D, g->neg_bitid);
+ DIRTY(sb->eval.enable, g->neg_bitid);
+ }
+ if (mask & GL_FOG_BIT)
+ {
+ if (a->fogStackDepth == 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty fog stack!" );
+ return;
+ }
+ a->fogStackDepth--;
+ g->fog.enable = a->fogStack[a->fogStackDepth].enable;
+ g->fog.color = a->fogStack[a->fogStackDepth].color;
+ g->fog.density = a->fogStack[a->fogStackDepth].density;
+ g->fog.start = a->fogStack[a->fogStackDepth].start;
+ g->fog.end = a->fogStack[a->fogStackDepth].end;
+ g->fog.index = a->fogStack[a->fogStackDepth].index;
+ g->fog.mode = a->fogStack[a->fogStackDepth].mode;
+ DIRTY(sb->fog.dirty, g->neg_bitid);
+ DIRTY(sb->fog.color, g->neg_bitid);
+ DIRTY(sb->fog.index, g->neg_bitid);
+ DIRTY(sb->fog.density, g->neg_bitid);
+ DIRTY(sb->fog.start, g->neg_bitid);
+ DIRTY(sb->fog.end, g->neg_bitid);
+ DIRTY(sb->fog.mode, g->neg_bitid);
+ DIRTY(sb->fog.enable, g->neg_bitid);
+ }
+ if (mask & GL_HINT_BIT)
+ {
+ if (a->hintStackDepth == 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty hint stack!" );
+ return;
+ }
+ a->hintStackDepth--;
+ g->hint.perspectiveCorrection = a->hintStack[a->hintStackDepth].perspectiveCorrection;
+ g->hint.pointSmooth = a->hintStack[a->hintStackDepth].pointSmooth;
+ g->hint.lineSmooth = a->hintStack[a->hintStackDepth].lineSmooth;
+ g->hint.polygonSmooth = a->hintStack[a->hintStackDepth].polygonSmooth;
+ g->hint.fog = a->hintStack[a->hintStackDepth].fog;
+ DIRTY(sb->hint.dirty, g->neg_bitid);
+ DIRTY(sb->hint.perspectiveCorrection, g->neg_bitid);
+ DIRTY(sb->hint.pointSmooth, g->neg_bitid);
+ DIRTY(sb->hint.lineSmooth, g->neg_bitid);
+ DIRTY(sb->hint.polygonSmooth, g->neg_bitid);
+#ifdef CR_EXT_clip_volume_hint
+ g->hint.clipVolumeClipping = a->hintStack[a->hintStackDepth].clipVolumeClipping;
+ DIRTY(sb->hint.clipVolumeClipping, g->neg_bitid);
+#endif
+#ifdef CR_ARB_texture_compression
+ g->hint.textureCompression = a->hintStack[a->hintStackDepth].textureCompression;
+ DIRTY(sb->hint.textureCompression, g->neg_bitid);
+#endif
+#ifdef CR_SGIS_generate_mipmap
+ g->hint.generateMipmap = a->hintStack[a->hintStackDepth].generateMipmap;
+ DIRTY(sb->hint.generateMipmap, g->neg_bitid);
+#endif
+ }
+ if (mask & GL_LIGHTING_BIT)
+ {
+ if (a->lightingStackDepth == 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty lighting stack!" );
+ return;
+ }
+ a->lightingStackDepth--;
+ g->lighting.lightModelAmbient = a->lightingStack[a->lightingStackDepth].lightModelAmbient;
+ g->lighting.lightModelLocalViewer = a->lightingStack[a->lightingStackDepth].lightModelLocalViewer;
+ g->lighting.lightModelTwoSide = a->lightingStack[a->lightingStackDepth].lightModelTwoSide;
+#if defined(CR_EXT_separate_specular_color) || defined(CR_OPENGL_VERSION_1_2)
+ g->lighting.lightModelColorControlEXT = a->lightingStack[a->lightingStackDepth].lightModelColorControlEXT;
+#endif
+ g->lighting.lighting = a->lightingStack[a->lightingStackDepth].lighting;
+ g->lighting.colorMaterial = a->lightingStack[a->lightingStackDepth].colorMaterial;
+ g->lighting.colorMaterialMode = a->lightingStack[a->lightingStackDepth].colorMaterialMode;
+ g->lighting.colorMaterialFace = a->lightingStack[a->lightingStackDepth].colorMaterialFace;
+ for (i = 0 ; i < g->limits.maxLights; i++)
+ {
+ g->lighting.light[i].enable = a->lightingStack[a->lightingStackDepth].light[i].enable;
+ g->lighting.light[i].ambient = a->lightingStack[a->lightingStackDepth].light[i].ambient;
+ g->lighting.light[i].diffuse = a->lightingStack[a->lightingStackDepth].light[i].diffuse;
+ g->lighting.light[i].specular = a->lightingStack[a->lightingStackDepth].light[i].specular;
+ g->lighting.light[i].spotDirection = a->lightingStack[a->lightingStackDepth].light[i].spotDirection;
+ g->lighting.light[i].position = a->lightingStack[a->lightingStackDepth].light[i].position;
+ g->lighting.light[i].spotExponent = a->lightingStack[a->lightingStackDepth].light[i].spotExponent;
+ g->lighting.light[i].spotCutoff = a->lightingStack[a->lightingStackDepth].light[i].spotCutoff;
+ g->lighting.light[i].constantAttenuation = a->lightingStack[a->lightingStackDepth].light[i].constantAttenuation;
+ g->lighting.light[i].linearAttenuation = a->lightingStack[a->lightingStackDepth].light[i].linearAttenuation;
+ g->lighting.light[i].quadraticAttenuation = a->lightingStack[a->lightingStackDepth].light[i].quadraticAttenuation;
+ }
+ for (i = 0 ; i < 2 ; i++)
+ {
+ g->lighting.ambient[i] = a->lightingStack[a->lightingStackDepth].ambient[i];
+ g->lighting.diffuse[i] = a->lightingStack[a->lightingStackDepth].diffuse[i];
+ g->lighting.specular[i] = a->lightingStack[a->lightingStackDepth].specular[i];
+ g->lighting.emission[i] = a->lightingStack[a->lightingStackDepth].emission[i];
+ g->lighting.shininess[i] = a->lightingStack[a->lightingStackDepth].shininess[i];
+ g->lighting.indexes[i][0] = a->lightingStack[a->lightingStackDepth].indexes[i][0];
+ g->lighting.indexes[i][1] = a->lightingStack[a->lightingStackDepth].indexes[i][1];
+ g->lighting.indexes[i][2] = a->lightingStack[a->lightingStackDepth].indexes[i][2];
+ }
+ g->lighting.shadeModel = a->lightingStack[a->lightingStackDepth].shadeModel;
+ DIRTY(sb->lighting.dirty, g->neg_bitid);
+ DIRTY(sb->lighting.shadeModel, g->neg_bitid);
+ DIRTY(sb->lighting.lightModel, g->neg_bitid);
+ DIRTY(sb->lighting.material, g->neg_bitid);
+ DIRTY(sb->lighting.enable, g->neg_bitid);
+ for (i = 0 ; i < g->limits.maxLights; i++)
+ {
+ DIRTY(sb->lighting.light[i].dirty, g->neg_bitid);
+ DIRTY(sb->lighting.light[i].enable, g->neg_bitid);
+ DIRTY(sb->lighting.light[i].ambient, g->neg_bitid);
+ DIRTY(sb->lighting.light[i].diffuse, g->neg_bitid);
+ DIRTY(sb->lighting.light[i].specular, g->neg_bitid);
+ DIRTY(sb->lighting.light[i].position, g->neg_bitid);
+ DIRTY(sb->lighting.light[i].attenuation, g->neg_bitid);
+ DIRTY(sb->lighting.light[i].spot, g->neg_bitid);
+ }
+ }
+ if (mask & GL_LINE_BIT)
+ {
+ if (a->lineStackDepth == 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty line stack!" );
+ return;
+ }
+ a->lineStackDepth--;
+ g->line.lineSmooth = a->lineStack[a->lineStackDepth].lineSmooth;
+ g->line.lineStipple = a->lineStack[a->lineStackDepth].lineStipple;
+ g->line.pattern = a->lineStack[a->lineStackDepth].pattern;
+ g->line.repeat = a->lineStack[a->lineStackDepth].repeat;
+ g->line.width = a->lineStack[a->lineStackDepth].width;
+ DIRTY(sb->line.dirty, g->neg_bitid);
+ DIRTY(sb->line.enable, g->neg_bitid);
+ DIRTY(sb->line.width, g->neg_bitid);
+ DIRTY(sb->line.stipple, g->neg_bitid);
+ }
+ if (mask & GL_LIST_BIT)
+ {
+ if (a->listStackDepth == 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty list stack!" );
+ return;
+ }
+ a->listStackDepth--;
+ g->lists.base = a->listStack[a->listStackDepth].base;
+ DIRTY(sb->lists.dirty, g->neg_bitid);
+ }
+ if (mask & GL_PIXEL_MODE_BIT)
+ {
+ if (a->pixelModeStackDepth == 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty pixel mode stack!" );
+ return;
+ }
+ a->pixelModeStackDepth--;
+ g->pixel.bias = a->pixelModeStack[a->pixelModeStackDepth].bias;
+ g->pixel.scale = a->pixelModeStack[a->pixelModeStackDepth].scale;
+ g->pixel.indexOffset = a->pixelModeStack[a->pixelModeStackDepth].indexOffset;
+ g->pixel.indexShift = a->pixelModeStack[a->pixelModeStackDepth].indexShift;
+ g->pixel.mapColor = a->pixelModeStack[a->pixelModeStackDepth].mapColor;
+ g->pixel.mapStencil = a->pixelModeStack[a->pixelModeStackDepth].mapStencil;
+ g->pixel.xZoom = a->pixelModeStack[a->pixelModeStackDepth].xZoom;
+ g->pixel.yZoom = a->pixelModeStack[a->pixelModeStackDepth].yZoom;
+ g->buffer.readBuffer = a->pixelModeStack[a->pixelModeStackDepth].readBuffer;
+ DIRTY(sb->pixel.dirty, g->neg_bitid);
+ DIRTY(sb->pixel.transfer, g->neg_bitid);
+ DIRTY(sb->pixel.zoom, g->neg_bitid);
+ DIRTY(sb->buffer.dirty, g->neg_bitid);
+ DIRTY(sb->buffer.readBuffer, g->neg_bitid);
+ }
+ if (mask & GL_POINT_BIT)
+ {
+ if (a->pointStackDepth == 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty point stack!" );
+ return;
+ }
+ a->pointStackDepth--;
+ g->point.pointSmooth = a->pointStack[a->pointStackDepth].pointSmooth;
+ g->point.pointSize = a->pointStack[a->pointStackDepth].pointSize;
+#if GL_ARB_point_sprite
+ g->point.pointSprite = a->pointStack[a->pointStackDepth].pointSprite;
+ DIRTY(sb->point.enableSprite, g->neg_bitid);
+ for (i = 0; i < CR_MAX_TEXTURE_UNITS; i++) {
+ g->point.coordReplacement[i] = a->enableStack[a->enableStackDepth].coordReplacement[i];
+ DIRTY(sb->point.coordReplacement[i], g->neg_bitid);
+ }
+#endif
+ DIRTY(sb->point.dirty, g->neg_bitid);
+ DIRTY(sb->point.size, g->neg_bitid);
+ DIRTY(sb->point.enableSmooth, g->neg_bitid);
+ }
+ if (mask & GL_POLYGON_BIT)
+ {
+ if (a->polygonStackDepth == 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty polygon stack!" );
+ return;
+ }
+ a->polygonStackDepth--;
+ g->polygon.cullFace = a->polygonStack[a->polygonStackDepth].cullFace;
+ g->polygon.cullFaceMode = a->polygonStack[a->polygonStackDepth].cullFaceMode;
+ g->polygon.frontFace = a->polygonStack[a->polygonStackDepth].frontFace;
+ g->polygon.frontMode = a->polygonStack[a->polygonStackDepth].frontMode;
+ g->polygon.backMode = a->polygonStack[a->polygonStackDepth].backMode;
+ g->polygon.polygonSmooth = a->polygonStack[a->polygonStackDepth].polygonSmooth;
+ g->polygon.polygonStipple = a->polygonStack[a->polygonStackDepth].polygonStipple;
+ g->polygon.polygonOffsetFill = a->polygonStack[a->polygonStackDepth].polygonOffsetFill;
+ g->polygon.polygonOffsetLine = a->polygonStack[a->polygonStackDepth].polygonOffsetLine;
+ g->polygon.polygonOffsetPoint = a->polygonStack[a->polygonStackDepth].polygonOffsetPoint;
+ g->polygon.offsetFactor = a->polygonStack[a->polygonStackDepth].offsetFactor;
+ g->polygon.offsetUnits = a->polygonStack[a->polygonStackDepth].offsetUnits;
+ DIRTY(sb->polygon.dirty, g->neg_bitid);
+ DIRTY(sb->polygon.enable, g->neg_bitid);
+ DIRTY(sb->polygon.offset, g->neg_bitid);
+ DIRTY(sb->polygon.mode, g->neg_bitid);
+ DIRTY(sb->polygon.stipple, g->neg_bitid);
+ }
+ if (mask & GL_POLYGON_STIPPLE_BIT)
+ {
+ if (a->polygonStippleStackDepth == 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty polygon stipple stack!" );
+ return;
+ }
+ a->polygonStippleStackDepth--;
+ crMemcpy( g->polygon.stipple, a->polygonStippleStack[a->polygonStippleStackDepth].pattern, 32*sizeof(GLint) );
+ DIRTY(sb->polygon.dirty, g->neg_bitid);
+ DIRTY(sb->polygon.stipple, g->neg_bitid);
+ }
+ if (mask & GL_SCISSOR_BIT)
+ {
+ if (a->scissorStackDepth == 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty scissor stack!" );
+ return;
+ }
+ a->scissorStackDepth--;
+ g->viewport.scissorTest = a->scissorStack[a->scissorStackDepth].scissorTest;
+ g->viewport.scissorX = a->scissorStack[a->scissorStackDepth].scissorX;
+ g->viewport.scissorY = a->scissorStack[a->scissorStackDepth].scissorY;
+ g->viewport.scissorW = a->scissorStack[a->scissorStackDepth].scissorW;
+ g->viewport.scissorH = a->scissorStack[a->scissorStackDepth].scissorH;
+ DIRTY(sb->viewport.dirty, g->neg_bitid);
+ DIRTY(sb->viewport.enable, g->neg_bitid);
+ DIRTY(sb->viewport.s_dims, g->neg_bitid);
+ }
+ if (mask & GL_STENCIL_BUFFER_BIT)
+ {
+ if (a->stencilBufferStackDepth == 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty stencil stack!" );
+ return;
+ }
+ a->stencilBufferStackDepth--;
+ g->stencil.stencilTest = a->stencilBufferStack[a->stencilBufferStackDepth].stencilTest;
+ 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.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)
+ {
+ CRTextureStack *tState;
+ if (a->textureStackDepth == 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty texture stack!" );
+ return;
+ }
+ a->textureStackDepth--;
+ tState = a->textureStack + a->textureStackDepth;
+
+ g->texture.curTextureUnit = tState->curTextureUnit;
+ for (i = 0 ; i < g->limits.maxTextureUnits ; i++)
+ {
+ copy_texunit(&g->texture.unit[i], &tState->unit[i]);
+ /* first, restore the bindings! */
+ g->texture.unit[i].currentTexture1D = crStateTextureGet(GL_TEXTURE_1D, tState->unit[i].Saved1D.id);
+ copy_texobj(g->texture.unit[i].currentTexture1D, &tState->unit[i].Saved1D, GL_FALSE);
+ g->texture.unit[i].currentTexture2D = crStateTextureGet(GL_TEXTURE_2D, tState->unit[i].Saved2D.id);
+ copy_texobj(g->texture.unit[i].currentTexture2D, &tState->unit[i].Saved2D, GL_FALSE);
+#ifdef CR_OPENGL_VERSION_1_2
+ g->texture.unit[i].currentTexture3D = crStateTextureGet(GL_TEXTURE_3D, tState->unit[i].Saved3D.id);
+ copy_texobj(g->texture.unit[i].currentTexture3D, &tState->unit[i].Saved3D, GL_FALSE);
+#endif
+#ifdef CR_ARB_texture_cube_map
+ g->texture.unit[i].currentTextureCubeMap = crStateTextureGet(GL_TEXTURE_CUBE_MAP_ARB, tState->unit[i].SavedCubeMap.id);
+ copy_texobj(g->texture.unit[i].currentTextureCubeMap, &tState->unit[i].SavedCubeMap, GL_FALSE);
+#endif
+#ifdef CR_NV_texture_rectangle
+ g->texture.unit[i].currentTextureRect = crStateTextureGet(GL_TEXTURE_CUBE_MAP_ARB, tState->unit[i].SavedRect.id);
+ copy_texobj(g->texture.unit[i].currentTextureRect, &tState->unit[i].SavedRect, GL_FALSE);
+#endif
+ }
+ DIRTY(sb->texture.dirty, g->neg_bitid);
+ for (i = 0 ; i < g->limits.maxTextureUnits ; i++)
+ {
+ DIRTY(sb->texture.enable[i], g->neg_bitid);
+ DIRTY(sb->texture.current[i], g->neg_bitid);
+ DIRTY(sb->texture.objGen[i], g->neg_bitid);
+ DIRTY(sb->texture.eyeGen[i], g->neg_bitid);
+ DIRTY(sb->texture.envBit[i], g->neg_bitid);
+ DIRTY(sb->texture.genMode[i], g->neg_bitid);
+ }
+
+ for (i = 0 ; i < g->limits.maxTextureUnits ; i++)
+ {
+ DIRTY(g->texture.unit[i].currentTexture1D->dirty, g->neg_bitid);
+ DIRTY(g->texture.unit[i].currentTexture2D->dirty, g->neg_bitid);
+ DIRTY(g->texture.unit[i].currentTexture3D->dirty, g->neg_bitid);
+#ifdef CR_ARB_texture_cube_map
+ DIRTY(g->texture.unit[i].currentTextureCubeMap->dirty, g->neg_bitid);
+#endif
+#ifdef CR_NV_texture_rectangle
+ DIRTY(g->texture.unit[i].currentTextureRect->dirty, g->neg_bitid);
+#endif
+ DIRTY(g->texture.unit[i].currentTexture1D->paramsBit[i], g->neg_bitid);
+ DIRTY(g->texture.unit[i].currentTexture2D->paramsBit[i], g->neg_bitid);
+ DIRTY(g->texture.unit[i].currentTexture3D->paramsBit[i], g->neg_bitid);
+#ifdef CR_ARB_texture_cube_map
+ DIRTY(g->texture.unit[i].currentTextureCubeMap->paramsBit[i], g->neg_bitid);
+#endif
+#ifdef CR_NV_texture_rectangle
+ DIRTY(g->texture.unit[i].currentTextureRect->paramsBit[i], g->neg_bitid);
+#endif
+ }
+ }
+ if (mask & GL_TRANSFORM_BIT)
+ {
+ if (a->transformStackDepth == 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty transform stack!" );
+ return;
+ }
+ a->transformStackDepth--;
+ g->transform.matrixMode = a->transformStack[a->transformStackDepth].matrixMode;
+ crStateMatrixMode(g->transform.matrixMode);
+ for (i = 0 ; i < g->limits.maxClipPlanes ; i++)
+ {
+ g->transform.clip[i] = a->transformStack[a->transformStackDepth].clip[i];
+ g->transform.clipPlane[i] = a->transformStack[a->transformStackDepth].clipPlane[i];
+ }
+ g->transform.normalize = a->transformStack[a->transformStackDepth].normalize;
+#ifdef CR_OPENGL_VERSION_1_2
+ g->transform.rescaleNormals = a->transformStack[a->transformStackDepth].rescaleNormals;
+#endif
+ DIRTY(sb->transform.dirty, g->neg_bitid);
+ DIRTY(sb->transform.matrixMode, g->neg_bitid);
+ DIRTY(sb->transform.clipPlane, g->neg_bitid);
+ DIRTY(sb->transform.enable, g->neg_bitid);
+ }
+ if (mask & GL_VIEWPORT_BIT)
+ {
+ if (a->viewportStackDepth == 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty viewport stack!" );
+ return;
+ }
+ a->viewportStackDepth--;
+ g->viewport.viewportX = a->viewportStack[a->viewportStackDepth].viewportX;
+ g->viewport.viewportY = a->viewportStack[a->viewportStackDepth].viewportY;
+ g->viewport.viewportW = a->viewportStack[a->viewportStackDepth].viewportW;
+ g->viewport.viewportH = a->viewportStack[a->viewportStackDepth].viewportH;
+ g->viewport.nearClip = a->viewportStack[a->viewportStackDepth].nearClip;
+ g->viewport.farClip = a->viewportStack[a->viewportStackDepth].farClip;
+ DIRTY(sb->viewport.dirty, g->neg_bitid);
+ DIRTY(sb->viewport.v_dims, g->neg_bitid);
+ DIRTY(sb->viewport.depth, g->neg_bitid);
+ }
+ DIRTY(ab->dirty, g->neg_bitid);
+}
+
+void crStateAttribSwitch( CRAttribBits *bb, CRbitvalue *bitID,
+ CRContext *fromCtx, CRContext *toCtx )
+{
+ CRAttribState *to = &(toCtx->attrib);
+ CRAttribState *from = &(fromCtx->attrib);
+ if (to->attribStackDepth != 0 || from->attribStackDepth != 0)
+ {
+ crWarning( "Trying to switch contexts when the attribute stacks "
+ "weren't empty. Currently, this is not supported." );
+ }
+ (void) bb;
+ (void) bitID;
+}
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..506da3c5
--- /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-2019 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
new file mode 100644
index 00000000..75090f84
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_buffer.c
@@ -0,0 +1,776 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#include <stdio.h>
+#include "state.h"
+#include "state/cr_statetypes.h"
+#include "state_internals.h"
+
+void crStateBufferInit (CRContext *ctx)
+{
+ CRBufferState *b = &ctx->buffer;
+ CRStateBits *sb = GetCurrentBits();
+ CRBufferBits *bb = &(sb->buffer);
+ GLcolorf zero_colorf = {0.0f, 0.0f, 0.0f, 0.0f};
+
+ b->width = 640;
+ b->height = 480;
+ b->storedWidth = 0;
+ b->storedHeight = 0;
+ b->pFrontImg = NULL;
+ b->pBackImg = NULL;
+
+ b->depthTest = GL_FALSE;
+ b->blend = GL_FALSE;
+ b->alphaTest = GL_FALSE;
+ b->dither = GL_TRUE;
+ RESET(bb->enable, ctx->bitid);
+
+ b->logicOp = GL_FALSE;
+ RESET(bb->logicOp, ctx->bitid);
+ b->indexLogicOp = GL_FALSE;
+ RESET(bb->indexLogicOp, ctx->bitid);
+ b->depthMask = GL_TRUE;
+ RESET(bb->depthMask, ctx->bitid);
+
+ b->alphaTestFunc = GL_ALWAYS;
+ b->alphaTestRef = 0;
+ RESET(bb->alphaFunc, ctx->bitid);
+ b->depthFunc = GL_LESS;
+ RESET(bb->depthFunc, ctx->bitid);
+ b->blendSrcRGB = GL_ONE;
+ b->blendDstRGB = GL_ZERO;
+ RESET(bb->blendFunc, ctx->bitid);
+#ifdef CR_EXT_blend_func_separate
+ b->blendSrcA = GL_ONE;
+ b->blendDstA = GL_ZERO;
+ RESET(bb->blendFuncSeparate, ctx->bitid);
+#endif
+ b->logicOpMode = GL_COPY;
+ b->drawBuffer = GL_BACK;
+ RESET(bb->drawBuffer, ctx->bitid);
+ b->readBuffer = GL_BACK;
+ RESET(bb->readBuffer, ctx->bitid);
+ b->indexWriteMask = 0xffffffff;
+ RESET(bb->indexMask, ctx->bitid);
+ b->colorWriteMask.r = GL_TRUE;
+ b->colorWriteMask.g = GL_TRUE;
+ b->colorWriteMask.b = GL_TRUE;
+ b->colorWriteMask.a = GL_TRUE;
+ RESET(bb->colorWriteMask, ctx->bitid);
+ b->colorClearValue = zero_colorf;
+ RESET(bb->clearColor, ctx->bitid);
+ b->indexClearValue = 0;
+ RESET(bb->clearIndex, ctx->bitid);
+ b->depthClearValue = (GLdefault) 1.0;
+ RESET(bb->clearDepth, ctx->bitid);
+ b->accumClearValue = zero_colorf;
+ RESET(bb->clearAccum, ctx->bitid);
+
+#ifdef CR_EXT_blend_color
+ b->blendColor = zero_colorf;
+ RESET(bb->blendColor, ctx->bitid);
+#endif
+#if defined(CR_EXT_blend_minmax) || defined(CR_EXT_blend_subtract) || defined(CR_EXT_blend_logic_op)
+ b->blendEquation = GL_FUNC_ADD_EXT;
+ RESET(bb->blendEquation, ctx->bitid);
+#endif
+
+ RESET(bb->dirty, ctx->bitid);
+}
+
+void STATE_APIENTRY crStateAlphaFunc (GLenum func, GLclampf ref)
+{
+ CRContext *g = GetCurrentContext();
+ CRBufferState *b = &(g->buffer);
+ CRStateBits *sb = GetCurrentBits();
+ CRBufferBits *bb = &(sb->buffer);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glAlphaFunc called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ switch (func)
+ {
+ case GL_NEVER:
+ case GL_LESS:
+ case GL_EQUAL:
+ case GL_LEQUAL:
+ case GL_GREATER:
+ case GL_GEQUAL:
+ case GL_NOTEQUAL:
+ case GL_ALWAYS:
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glAlphaFunc: Invalid func: %d", func);
+ return;
+ }
+
+ if (ref < 0.0f) ref = 0.0f;
+ if (ref > 1.0f) ref = 1.0f;
+
+ b->alphaTestFunc = func;
+ b->alphaTestRef = ref;
+ DIRTY(bb->dirty, g->neg_bitid);
+ DIRTY(bb->alphaFunc, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateDepthFunc (GLenum func)
+{
+ CRContext *g = GetCurrentContext();
+ CRBufferState *b = &(g->buffer);
+ CRStateBits *sb = GetCurrentBits();
+ CRBufferBits *bb = &(sb->buffer);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glDepthFunc called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ switch (func)
+ {
+ case GL_NEVER:
+ case GL_LESS:
+ case GL_EQUAL:
+ case GL_LEQUAL:
+ case GL_GREATER:
+ case GL_NOTEQUAL:
+ case GL_GEQUAL:
+ case GL_ALWAYS:
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glDepthFunc: Invalid func: %d", func);
+ return;
+ }
+
+
+ b->depthFunc = func;
+ DIRTY(bb->dirty, g->neg_bitid);
+ DIRTY(bb->depthFunc, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateBlendFunc (GLenum sfactor, GLenum dfactor)
+{
+ CRContext *g = GetCurrentContext();
+ CRBufferState *b = &(g->buffer);
+ CRStateBits *sb = GetCurrentBits();
+ CRBufferBits *bb = &(sb->buffer);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glBlendFunc called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ switch (sfactor)
+ {
+ case GL_ZERO:
+ case GL_ONE:
+ case GL_DST_COLOR:
+ case GL_ONE_MINUS_DST_COLOR:
+ case GL_SRC_ALPHA:
+ case GL_ONE_MINUS_SRC_ALPHA:
+ case GL_DST_ALPHA:
+ case GL_ONE_MINUS_DST_ALPHA:
+ case GL_SRC_ALPHA_SATURATE:
+ break; /* OK */
+#ifdef CR_EXT_blend_color
+ case GL_CONSTANT_COLOR_EXT:
+ case GL_ONE_MINUS_CONSTANT_COLOR_EXT:
+ case GL_CONSTANT_ALPHA_EXT:
+ case GL_ONE_MINUS_CONSTANT_ALPHA_EXT:
+ if (g->extensions.EXT_blend_color)
+ break; /* OK */
+#endif
+ RT_FALL_THRU();
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid sfactor passed to glBlendFunc: %d", sfactor);
+ return;
+ }
+
+ switch (dfactor)
+ {
+ case GL_ZERO:
+ case GL_ONE:
+ case GL_SRC_COLOR:
+ case GL_ONE_MINUS_SRC_COLOR:
+ case GL_SRC_ALPHA:
+ case GL_ONE_MINUS_SRC_ALPHA:
+ case GL_DST_ALPHA:
+ case GL_ONE_MINUS_DST_ALPHA:
+ break; /* OK */
+#ifdef CR_EXT_blend_color
+ case GL_CONSTANT_COLOR_EXT:
+ case GL_ONE_MINUS_CONSTANT_COLOR_EXT:
+ case GL_CONSTANT_ALPHA_EXT:
+ case GL_ONE_MINUS_CONSTANT_ALPHA_EXT:
+ if (g->extensions.EXT_blend_color)
+ break; /* OK */
+#endif
+ RT_FALL_THRU();
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid dfactor passed to glBlendFunc: %d", dfactor);
+ return;
+ }
+
+ b->blendSrcRGB = sfactor;
+ b->blendDstRGB = dfactor;
+ b->blendSrcA = sfactor;
+ b->blendDstA = dfactor;
+ DIRTY(bb->dirty, g->neg_bitid);
+ DIRTY(bb->blendFunc, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateBlendColorEXT( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
+{
+ CRContext *g = GetCurrentContext();
+ CRBufferState *b = &(g->buffer);
+ CRStateBits *sb = GetCurrentBits();
+ CRBufferBits *bb = &(sb->buffer);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError( __LINE__, __FILE__, GL_INVALID_OPERATION, "BlendColorEXT called inside a Begin/End" );
+ return;
+ }
+
+ b->blendColor.r = red;
+ b->blendColor.g = green;
+ b->blendColor.b = blue;
+ b->blendColor.a = alpha;
+ DIRTY(bb->blendColor, g->neg_bitid);
+ DIRTY(bb->dirty, g->neg_bitid);
+}
+
+#ifdef CR_EXT_blend_func_separate
+void STATE_APIENTRY crStateBlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorA, GLenum dfactorA )
+{
+ CRContext *g = GetCurrentContext();
+ CRBufferState *b = &(g->buffer);
+ CRStateBits *sb = GetCurrentBits();
+ CRBufferBits *bb = &(sb->buffer);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError( __LINE__, __FILE__, GL_INVALID_OPERATION, "BlendFuncSeparateEXT called inside a Begin/End" );
+ return;
+ }
+
+ FLUSH();
+
+ switch (sfactorRGB)
+ {
+ case GL_ZERO:
+ case GL_ONE:
+ case GL_DST_COLOR:
+ case GL_ONE_MINUS_DST_COLOR:
+ case GL_SRC_ALPHA:
+ case GL_ONE_MINUS_SRC_ALPHA:
+ case GL_DST_ALPHA:
+ case GL_ONE_MINUS_DST_ALPHA:
+ case GL_SRC_ALPHA_SATURATE:
+ break; /* OK */
+#ifdef CR_EXT_blend_color
+ case GL_CONSTANT_COLOR_EXT:
+ case GL_ONE_MINUS_CONSTANT_COLOR_EXT:
+ case GL_CONSTANT_ALPHA_EXT:
+ case GL_ONE_MINUS_CONSTANT_ALPHA_EXT:
+ if (g->extensions.EXT_blend_color)
+ break; /* OK */
+#endif
+ RT_FALL_THRU();
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid sfactorRGB passed to glBlendFuncSeparateEXT: %d", sfactorRGB);
+ return;
+ }
+
+ switch (sfactorA)
+ {
+ case GL_ZERO:
+ case GL_ONE:
+ case GL_DST_COLOR:
+ case GL_ONE_MINUS_DST_COLOR:
+ case GL_SRC_ALPHA:
+ case GL_ONE_MINUS_SRC_ALPHA:
+ case GL_DST_ALPHA:
+ case GL_ONE_MINUS_DST_ALPHA:
+ case GL_SRC_ALPHA_SATURATE:
+ break; /* OK */
+#ifdef CR_EXT_blend_color
+ case GL_CONSTANT_COLOR_EXT:
+ case GL_ONE_MINUS_CONSTANT_COLOR_EXT:
+ case GL_CONSTANT_ALPHA_EXT:
+ case GL_ONE_MINUS_CONSTANT_ALPHA_EXT:
+ if (g->extensions.EXT_blend_color)
+ break; /* OK */
+#endif
+ RT_FALL_THRU();
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid sfactorA passed to glBlendFuncSeparateEXT: %d", sfactorA);
+ return;
+ }
+
+ switch (dfactorRGB)
+ {
+ case GL_ZERO:
+ case GL_ONE:
+ case GL_SRC_COLOR:
+ case GL_DST_COLOR:
+ case GL_ONE_MINUS_DST_COLOR:
+ case GL_ONE_MINUS_SRC_COLOR:
+ case GL_SRC_ALPHA:
+ case GL_ONE_MINUS_SRC_ALPHA:
+ case GL_DST_ALPHA:
+ case GL_ONE_MINUS_DST_ALPHA:
+ case GL_SRC_ALPHA_SATURATE:
+ break; /* OK */
+#ifdef CR_EXT_blend_color
+ case GL_CONSTANT_COLOR_EXT:
+ case GL_ONE_MINUS_CONSTANT_COLOR_EXT:
+ case GL_CONSTANT_ALPHA_EXT:
+ case GL_ONE_MINUS_CONSTANT_ALPHA_EXT:
+ if (g->extensions.EXT_blend_color)
+ break; /* OK */
+#endif
+ RT_FALL_THRU();
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid dfactorRGB passed to glBlendFuncSeparateEXT: %d", dfactorRGB);
+ return;
+ }
+
+ switch (dfactorA)
+ {
+ case GL_ZERO:
+ case GL_ONE:
+ case GL_DST_COLOR:
+ case GL_SRC_COLOR:
+ case GL_ONE_MINUS_SRC_COLOR:
+ case GL_ONE_MINUS_DST_COLOR:
+ case GL_SRC_ALPHA:
+ case GL_ONE_MINUS_SRC_ALPHA:
+ case GL_DST_ALPHA:
+ case GL_ONE_MINUS_DST_ALPHA:
+ case GL_SRC_ALPHA_SATURATE:
+ break; /* OK */
+#ifdef CR_EXT_blend_color
+ case GL_CONSTANT_COLOR_EXT:
+ case GL_ONE_MINUS_CONSTANT_COLOR_EXT:
+ case GL_CONSTANT_ALPHA_EXT:
+ case GL_ONE_MINUS_CONSTANT_ALPHA_EXT:
+ if (g->extensions.EXT_blend_color)
+ break; /* OK */
+#endif
+ RT_FALL_THRU();
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid dfactorA passed to glBlendFuncSeparateEXT: %d", dfactorA);
+ return;
+ }
+
+ b->blendSrcRGB = sfactorRGB;
+ b->blendDstRGB = dfactorRGB;
+ b->blendSrcA = sfactorA;
+ b->blendDstA = dfactorA;
+ DIRTY(bb->dirty, g->neg_bitid);
+ DIRTY(bb->blendFuncSeparate, g->neg_bitid);
+}
+#endif
+
+void STATE_APIENTRY crStateBlendEquationEXT( GLenum mode )
+{
+ CRContext *g = GetCurrentContext();
+ CRBufferState *b = &(g->buffer);
+ CRStateBits *sb = GetCurrentBits();
+ CRBufferBits *bb = &(sb->buffer);
+
+ if( g->current.inBeginEnd )
+ {
+ crStateError( __LINE__, __FILE__, GL_INVALID_OPERATION, "BlendEquationEXT called inside a Begin/End" );
+ return;
+ }
+ switch( mode )
+ {
+#if defined(CR_EXT_blend_minmax) || defined(CR_EXT_blend_subtract) || defined(CR_EXT_blend_logic_op)
+ case GL_FUNC_ADD_EXT:
+#ifdef CR_EXT_blend_subtract
+ case GL_FUNC_SUBTRACT_EXT:
+ case GL_FUNC_REVERSE_SUBTRACT_EXT:
+#endif /* CR_EXT_blend_subtract */
+#ifdef CR_EXT_blend_minmax
+ case GL_MIN_EXT:
+ case GL_MAX_EXT:
+#endif /* CR_EXT_blend_minmax */
+#ifdef CR_EXT_blend_logic_op
+ case GL_LOGIC_OP:
+#endif /* CR_EXT_blend_logic_op */
+ b->blendEquation = mode;
+ break;
+#endif /* defined(CR_EXT_blend_minmax) || defined(CR_EXT_blend_subtract) || defined(CR_EXT_blend_logic_op) */
+ default:
+ crStateError( __LINE__, __FILE__, GL_INVALID_ENUM,
+ "BlendEquationEXT: mode called with illegal parameter: 0x%x", (GLenum) mode );
+ return;
+ }
+ DIRTY(bb->blendEquation, g->neg_bitid);
+ DIRTY(bb->dirty, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateLogicOp (GLenum opcode)
+{
+ CRContext *g = GetCurrentContext();
+ CRBufferState *b = &(g->buffer);
+ CRStateBits *sb = GetCurrentBits();
+ CRBufferBits *bb = &(sb->buffer);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glLogicOp called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ switch (opcode)
+ {
+ case GL_CLEAR:
+ case GL_SET:
+ case GL_COPY:
+ case GL_COPY_INVERTED:
+ case GL_NOOP:
+ case GL_INVERT:
+ case GL_AND:
+ case GL_NAND:
+ case GL_OR:
+ case GL_NOR:
+ case GL_XOR:
+ case GL_EQUIV:
+ case GL_AND_REVERSE:
+ case GL_AND_INVERTED:
+ case GL_OR_REVERSE:
+ case GL_OR_INVERTED:
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glLogicOp called with bogus opcode: %d", opcode);
+ return;
+ }
+
+ b->logicOpMode = opcode;
+ DIRTY(bb->dirty, g->neg_bitid);
+ DIRTY(bb->logicOp, g->neg_bitid);
+ DIRTY(bb->indexLogicOp, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateDrawBuffer (GLenum mode)
+{
+ CRContext *g = GetCurrentContext();
+ CRBufferState *b = &(g->buffer);
+ CRStateBits *sb = GetCurrentBits();
+ CRBufferBits *bb = &(sb->buffer);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glDrawBuffer called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ switch (mode)
+ {
+ case GL_NONE:
+ break;
+ case GL_FRONT_LEFT:
+ case GL_FRONT_RIGHT:
+ case GL_BACK_LEFT:
+ case GL_BACK_RIGHT:
+ case GL_FRONT:
+ case GL_BACK:
+ case GL_LEFT:
+ case GL_RIGHT:
+ case GL_FRONT_AND_BACK:
+ case GL_AUX0:
+ case GL_AUX1:
+ case GL_AUX2:
+ case GL_AUX3:
+ if (g->framebufferobject.drawFB)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glDrawBuffer invalid mode while fbo is active");
+ return;
+ }
+ break;
+ default:
+ if (mode>=GL_COLOR_ATTACHMENT0_EXT && mode<=GL_COLOR_ATTACHMENT15_EXT)
+ {
+ if (!g->framebufferobject.drawFB)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glDrawBuffer invalid mode while fbo is inactive");
+ return;
+ }
+ }
+ else
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glDrawBuffer called with bogus mode: %d", mode);
+ return;
+ }
+ }
+
+ if (g->framebufferobject.drawFB)
+ {
+ g->framebufferobject.drawFB->drawbuffer[0] = mode;
+ }
+ else
+ {
+ b->drawBuffer = mode;
+ DIRTY(bb->dirty, g->neg_bitid);
+ DIRTY(bb->drawBuffer, g->neg_bitid);
+ }
+}
+
+void STATE_APIENTRY crStateReadBuffer (GLenum mode)
+{
+ CRContext *g = GetCurrentContext();
+ CRBufferState *b = &(g->buffer);
+ CRStateBits *sb = GetCurrentBits();
+ CRBufferBits *bb = &(sb->buffer);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glReadBuffer called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ switch (mode)
+ {
+ case GL_NONE:
+ break;
+ case GL_FRONT_LEFT:
+ case GL_FRONT_RIGHT:
+ case GL_BACK_LEFT:
+ case GL_BACK_RIGHT:
+ case GL_FRONT:
+ case GL_BACK:
+ case GL_LEFT:
+ case GL_RIGHT:
+ case GL_FRONT_AND_BACK:
+ case GL_AUX0:
+ case GL_AUX1:
+ case GL_AUX2:
+ case GL_AUX3:
+ if (g->framebufferobject.readFB)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glReadBuffer invalid mode while fbo is active");
+ return;
+ }
+ break;
+ default:
+ if (mode>=GL_COLOR_ATTACHMENT0_EXT && mode<=GL_COLOR_ATTACHMENT15_EXT)
+ {
+ if (!g->framebufferobject.readFB)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glReadBuffer invalid mode while fbo is inactive");
+ return;
+ }
+ else
+ {
+ /*@todo, check if fbo binding is complete*/
+ }
+ }
+ else
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glReadBuffer called with bogus mode: %d", mode);
+ return;
+ }
+ }
+
+ if (g->framebufferobject.readFB)
+ {
+ g->framebufferobject.readFB->readbuffer = mode;
+ }
+ else
+ {
+ b->readBuffer = mode;
+ DIRTY(bb->dirty, g->neg_bitid);
+ DIRTY(bb->readBuffer, g->neg_bitid);
+ }
+}
+
+void STATE_APIENTRY crStateIndexMask (GLuint mask)
+{
+ CRContext *g = GetCurrentContext();
+ CRBufferState *b = &(g->buffer);
+ CRStateBits *sp = GetCurrentBits();
+ CRBufferBits *bb = &(sp->buffer);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glReadBuffer called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ b->indexWriteMask = mask;
+ DIRTY(bb->dirty, g->neg_bitid);
+ DIRTY(bb->indexMask, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
+{
+ CRContext *g = GetCurrentContext();
+ CRBufferState *b = &(g->buffer);
+ CRStateBits *sp = GetCurrentBits();
+ CRBufferBits *bb = &(sp->buffer);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glReadBuffer called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ b->colorWriteMask.r = red;
+ b->colorWriteMask.g = green;
+ b->colorWriteMask.b = blue;
+ b->colorWriteMask.a = alpha;
+ DIRTY(bb->dirty, g->neg_bitid);
+ DIRTY(bb->colorWriteMask, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+{
+ CRContext *g = GetCurrentContext();
+ CRBufferState *b = &(g->buffer);
+ CRStateBits *sp = GetCurrentBits();
+ CRBufferBits *bb = &(sp->buffer);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glClearColor called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ if (red < 0.0f) red = 0.0f;
+ if (red > 1.0f) red = 1.0f;
+ if (green < 0.0f) green = 0.0f;
+ if (green > 1.0f) green = 1.0f;
+ if (blue < 0.0f) blue = 0.0f;
+ if (blue > 1.0f) blue = 1.0f;
+ if (alpha < 0.0f) alpha = 0.0f;
+ if (alpha > 1.0f) alpha = 1.0f;
+
+ b->colorClearValue.r = red;
+ b->colorClearValue.g = green;
+ b->colorClearValue.b = blue;
+ b->colorClearValue.a = alpha;
+ DIRTY(bb->dirty, g->neg_bitid);
+ DIRTY(bb->clearColor, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateClearIndex (GLfloat c)
+{
+ CRContext *g = GetCurrentContext();
+ CRBufferState *b = &(g->buffer);
+ CRStateBits *sp = GetCurrentBits();
+ CRBufferBits *bb = &(sp->buffer);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glClearIndex called in begin/end");
+ return;
+ }
+
+ b->indexClearValue = c;
+ DIRTY(bb->dirty, g->neg_bitid);
+ DIRTY(bb->clearIndex, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateClearDepth (GLclampd depth)
+{
+ CRContext *g = GetCurrentContext();
+ CRBufferState *b = &(g->buffer);
+ CRStateBits *sp = GetCurrentBits();
+ CRBufferBits *bb = &(sp->buffer);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glClearDepth called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ if (depth < 0.0) depth = 0.0;
+ if (depth > 1.0) depth = 1.0;
+
+ b->depthClearValue = (GLdefault) depth;
+ DIRTY(bb->dirty, g->neg_bitid);
+ DIRTY(bb->clearDepth, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateClearAccum (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+{
+ CRContext *g = GetCurrentContext();
+ CRBufferState *b = &(g->buffer);
+ CRStateBits *sp = GetCurrentBits();
+ CRBufferBits *bb = &(sp->buffer);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glClearAccum called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ if (red < -1.0f) red = 0.0f;
+ if (red > 1.0f) red = 1.0f;
+ if (green < -1.0f) green = 0.0f;
+ if (green > 1.0f) green = 1.0f;
+ if (blue < -1.0f) blue = 0.0f;
+ if (blue > 1.0f) blue = 1.0f;
+ if (alpha < -1.0f) alpha = 0.0f;
+ if (alpha > 1.0f) alpha = 1.0f;
+
+ b->accumClearValue.r = red;
+ b->accumClearValue.g = green;
+ b->accumClearValue.b = blue;
+ b->accumClearValue.a = alpha;
+ DIRTY(bb->dirty, g->neg_bitid);
+ DIRTY(bb->clearAccum, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateDepthMask (GLboolean b)
+{
+ CRContext *g = GetCurrentContext();
+ CRBufferState *bs = &(g->buffer);
+ CRStateBits *sp = GetCurrentBits();
+ CRBufferBits *bb = &(sp->buffer);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "DepthMask called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ bs->depthMask = b;
+ DIRTY(bb->dirty, g->neg_bitid);
+ DIRTY(bb->depthMask, g->neg_bitid);
+}
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_buffer.txt b/src/VBox/GuestHost/OpenGL/state_tracker/state_buffer.txt
new file mode 100644
index 00000000..768a205b
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_buffer.txt
@@ -0,0 +1,34 @@
+# Copyright (c) 2001, Stanford University
+# All rights reserved.
+#
+# See the file LICENSE.txt for information on redistributing this software.
+#-:enable:*glAble able[2];
+#-:enable:*able[0] = diff_api.Disable;
+#-:enable:*able[1] = diff_api.Enable;
+#-:enable:*able[to->depthTest](GL_DEPTH_TEST);
+#-:enable:*FILLDIRTY(b->enable);
+#-:enable:*FILLDIRTY(b->dirty);
+#+:enable:depthTest:GL_DEPTH_TEST
+:enable:depthTest:GL_DEPTH_TEST
+:enable:blend:GL_BLEND
+:enable:alphaTest:GL_ALPHA_TEST
+:enable:logicOp:GL_COLOR_LOGIC_OP
+:enable:indexLogicOp:GL_INDEX_LOGIC_OP
+:enable:dither:GL_DITHER
+:alphaFunc:alphaTestFunc,alphaTestRef:AlphaFunc
+:depthFunc:depthFunc:DepthFunc
+:blendFunc:blendSrcRGB,blendDstRGB:BlendFunc
+:blendFuncSeparate:blendSrcRGB,blendDstRGB,blendSrcA,blendDstA:BlendFuncSeparateEXT
+:logicOp:logicOpMode:LogicOp
+:indexLogicOp:logicOpMode:LogicOp
+:drawBuffer:drawBuffer:DrawBuffer
+:readBuffer:readBuffer:ReadBuffer
+:indexMask:indexWriteMask:IndexMask
+:colorWriteMask:colorWriteMask|r,g,b,a:ColorMask
+:clearColor:colorClearValue|r,g,b,a:ClearColor
+:clearIndex:indexClearValue:ClearIndex
+:clearDepth:depthClearValue:ClearDepth
+:clearAccum:accumClearValue|r,g,b,a:ClearAccum
+:depthMask:depthMask:DepthMask
+:blendEquation:blendEquation:BlendEquationEXT
+:blendColor:blendColor|r,g,b,a:BlendColorEXT
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_bufferobject.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_bufferobject.c
new file mode 100644
index 00000000..373b24f8
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_bufferobject.c
@@ -0,0 +1,1126 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#include "state.h"
+#include "state/cr_statetypes.h"
+#include "state/cr_statefuncs.h"
+#include "state_internals.h"
+#include "cr_mem.h"
+#include "cr_string.h"
+
+
+static CRBufferObject *AllocBufferObject(GLuint name)
+{
+ CRBufferObject *b = crCalloc(sizeof(CRBufferObject));
+ if (b) {
+ b->refCount = 1;
+ b->id = name;
+ b->hwid = name;
+ b->usage = GL_STATIC_DRAW_ARB;
+ b->access = GL_READ_WRITE_ARB;
+ b->bResyncOnRead = GL_FALSE;
+ CR_STATE_SHAREDOBJ_USAGE_INIT(b);
+ }
+ return b;
+}
+
+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)
+ {
+ case GL_ARRAY_BUFFER_ARB:
+ return b->arrayBuffer->id!=0;
+ case GL_ELEMENT_ARRAY_BUFFER_ARB:
+ return b->elementsBuffer->id!=0;
+#ifdef CR_ARB_pixel_buffer_object
+ case GL_PIXEL_PACK_BUFFER_ARB:
+ return b->packBuffer->id!=0;
+ case GL_PIXEL_UNPACK_BUFFER_ARB:
+ return b->unpackBuffer->id!=0;
+#endif
+ default:
+ return GL_FALSE;
+ }
+}
+
+GLboolean crStateIsBufferBound(GLenum target)
+{
+ CRContext *g = GetCurrentContext();
+ return crStateIsBufferBoundForCtx(g, target);
+}
+
+CRBufferObject *crStateGetBoundBufferObject(GLenum target, CRBufferObjectState *b)
+{
+ switch (target)
+ {
+ case GL_ARRAY_BUFFER_ARB:
+ return b->arrayBuffer;
+ case GL_ELEMENT_ARRAY_BUFFER_ARB:
+ return b->elementsBuffer;
+#ifdef CR_ARB_pixel_buffer_object
+ case GL_PIXEL_PACK_BUFFER_ARB:
+ return b->packBuffer;
+ case GL_PIXEL_UNPACK_BUFFER_ARB:
+ return b->unpackBuffer;
+#endif
+ default:
+ return NULL;
+ }
+}
+
+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();
+ CRBufferObjectBits *bb = &sb->bufferobject;
+ CRBufferObjectState *b = &ctx->bufferobject;
+
+ RESET(bb->dirty, ctx->bitid);
+ RESET(bb->arrayBinding, ctx->bitid);
+ RESET(bb->elementsBinding, ctx->bitid);
+#ifdef CR_ARB_pixel_buffer_object
+ RESET(bb->unpackBinding, ctx->bitid);
+ RESET(bb->packBinding, ctx->bitid);
+#endif
+
+#ifdef IN_GUEST
+ b->retainBufferData = GL_TRUE;
+#else
+ b->retainBufferData = GL_FALSE;
+#endif
+
+ b->nullBuffer = AllocBufferObject(0);
+ b->arrayBuffer = b->nullBuffer;
+ b->elementsBuffer = b->nullBuffer;
+ b->nullBuffer->refCount += 2;
+#ifdef CR_ARB_pixel_buffer_object
+ b->packBuffer = b->nullBuffer;
+ b->unpackBuffer = b->nullBuffer;
+ b->nullBuffer->refCount += 2;
+#endif
+
+ ctx->shared->bVBOResyncNeeded = GL_FALSE;
+}
+
+void crStateFreeBufferObject(void *data)
+{
+ CRBufferObject *pObj = (CRBufferObject *)data;
+ if (pObj->data) crFree(pObj->data);
+
+#ifndef IN_GUEST
+ if (diff_api.DeleteBuffersARB)
+ {
+ diff_api.DeleteBuffersARB(1, &pObj->hwid);
+ }
+#endif
+
+ crFree(pObj);
+}
+
+void crStateBufferObjectDestroy (CRContext *ctx)
+{
+ CRBufferObjectState *b = &ctx->bufferobject;
+ crFree(b->nullBuffer);
+}
+
+static void crStateCheckBufferHWIDCB(unsigned long key, void *data1, void *data2)
+{
+ CRBufferObject *pObj = (CRBufferObject *) data1;
+ crCheckIDHWID_t *pParms = (crCheckIDHWID_t*) data2;
+ (void) key;
+
+ if (pObj->hwid==pParms->hwid)
+ pParms->id = pObj->id;
+}
+
+DECLEXPORT(GLuint) STATE_APIENTRY crStateBufferHWIDtoID(GLuint hwid)
+{
+ CRContext *g = GetCurrentContext();
+ crCheckIDHWID_t parms;
+
+ parms.id = hwid;
+ parms.hwid = hwid;
+
+ crHashtableWalk(g->shared->buffersTable, crStateCheckBufferHWIDCB, &parms);
+ return parms.id;
+}
+
+DECLEXPORT(GLuint) STATE_APIENTRY crStateGetBufferHWID(GLuint id)
+{
+ CRContext *g = GetCurrentContext();
+ CRBufferObject *pObj = (CRBufferObject *) crHashtableSearch(g->shared->buffersTable, id);
+
+ return pObj ? pObj->hwid : 0;
+}
+
+void STATE_APIENTRY
+crStateBindBufferARB (GLenum target, GLuint buffer)
+{
+ CRContext *g = GetCurrentContext();
+ CRBufferObjectState *b = &(g->bufferobject);
+ CRStateBits *sb = GetCurrentBits();
+ CRBufferObjectBits *bb = &(sb->bufferobject);
+ CRBufferObject *oldObj, *newObj;
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glBindBufferARB called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ oldObj = crStateGetBoundBufferObject(target, b);
+ if (!oldObj)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glBindBufferARB(target)");
+ return;
+ }
+
+ if (buffer == 0) {
+ newObj = b->nullBuffer;
+ }
+ 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);
+ 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 );
+ }
+
+ CR_STATE_SHAREDOBJ_USAGE_SET(newObj, g);
+ }
+
+ newObj->refCount++;
+ oldObj->refCount--;
+
+ switch (target)
+ {
+ case GL_ARRAY_BUFFER_ARB:
+ b->arrayBuffer = newObj;
+ DIRTY(bb->dirty, g->neg_bitid);
+ DIRTY(bb->arrayBinding, g->neg_bitid);
+ break;
+ case GL_ELEMENT_ARRAY_BUFFER_ARB:
+ b->elementsBuffer = newObj;
+ DIRTY(bb->dirty, g->neg_bitid);
+ DIRTY(bb->elementsBinding, g->neg_bitid);
+ break;
+#ifdef CR_ARB_pixel_buffer_object
+ case GL_PIXEL_PACK_BUFFER_ARB:
+ b->packBuffer = newObj;
+ DIRTY(bb->dirty, g->neg_bitid);
+ DIRTY(bb->packBinding, g->neg_bitid);
+ break;
+ case GL_PIXEL_UNPACK_BUFFER_ARB:
+ b->unpackBuffer = newObj;
+ DIRTY(bb->dirty, g->neg_bitid);
+ DIRTY(bb->unpackBinding, g->neg_bitid);
+ break;
+#endif
+ default: /*can't get here*/
+ CRASSERT(false);
+ return;
+ }
+
+ if (oldObj->refCount <= 0) {
+ /*we shouldn't reach this point*/
+ CRASSERT(false);
+ crHashtableDelete(g->shared->buffersTable, (unsigned long) oldObj->id, crStateFreeBufferObject);
+ }
+
+#ifdef IN_GUEST
+ if (target == GL_PIXEL_PACK_BUFFER_ARB)
+ {
+ newObj->bResyncOnRead = GL_TRUE;
+ }
+#endif
+}
+
+static void ctStateBuffersRefsCleanup(CRContext *ctx, CRBufferObject *obj, CRbitvalue *neg_bitid)
+{
+ CRBufferObjectState *b = &(ctx->bufferobject);
+ CRStateBits *sb = GetCurrentBits();
+ CRBufferObjectBits *bb = &(sb->bufferobject);
+ int j, k;
+
+ if (obj == b->arrayBuffer)
+ {
+ b->arrayBuffer = b->nullBuffer;
+ b->arrayBuffer->refCount++;
+ DIRTY(bb->dirty, neg_bitid);
+ DIRTY(bb->arrayBinding, neg_bitid);
+ }
+ if (obj == b->elementsBuffer)
+ {
+ b->elementsBuffer = b->nullBuffer;
+ b->elementsBuffer->refCount++;
+ DIRTY(bb->dirty, neg_bitid);
+ DIRTY(bb->elementsBinding, neg_bitid);
+ }
+#ifdef CR_ARB_pixel_buffer_object
+ 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
+
+#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
+crStateDeleteBuffersARB(GLsizei n, const GLuint *buffers)
+{
+ CRContext *g = GetCurrentContext();
+ int i;
+
+ FLUSH();
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glDeleteBuffersARB called in Begin/End");
+ return;
+ }
+
+ if (n < 0) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glDeleteBuffersARB(n < 0)");
+ return;
+ }
+
+ for (i = 0; i < n; i++) {
+ if (buffers[i]) {
+ CRBufferObject *obj = (CRBufferObject *)
+ crHashtableSearch(g->shared->buffersTable, buffers[i]);
+ if (obj) {
+ int j;
+
+ ctStateBuffersRefsCleanup(g, obj, g->neg_bitid);
+
+ 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);
+ }
+
+ crHashtableDelete(g->shared->buffersTable, buffers[i], crStateFreeBufferObject);
+ }
+ }
+ }
+}
+
+void STATE_APIENTRY
+crStateBufferDataARB(GLenum target, GLsizeiptrARB size, const GLvoid * data, GLenum usage)
+{
+ CRContext *g = GetCurrentContext();
+ CRBufferObjectState *b = &g->bufferobject;
+ CRBufferObject *obj;
+ CRStateBits *sb = GetCurrentBits();
+ CRBufferObjectBits *bb = &sb->bufferobject;
+
+ FLUSH();
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glBufferDataARB called in begin/end");
+ return;
+ }
+
+ if (size < 0) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glBufferDataARB(size < 0)");
+ return;
+ }
+
+ switch (usage) {
+ case GL_STREAM_DRAW_ARB:
+ case GL_STREAM_READ_ARB:
+ case GL_STREAM_COPY_ARB:
+ case GL_STATIC_DRAW_ARB:
+ case GL_STATIC_READ_ARB:
+ case GL_STATIC_COPY_ARB:
+ case GL_DYNAMIC_DRAW_ARB:
+ case GL_DYNAMIC_READ_ARB:
+ case GL_DYNAMIC_COPY_ARB:
+ /* OK */
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glBufferDataARB(usage)");
+ return;
+ }
+
+ obj = crStateGetBoundBufferObject(target, b);
+ if (!obj)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glBufferDataARB(target)");
+ return;
+ }
+
+ if (obj->id == 0) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glBufferDataARB");
+ return;
+ }
+
+ if (obj->pointer) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glBufferDataARB(buffer is mapped)");
+ return;
+ }
+
+ obj->usage = usage;
+ obj->size = size;
+
+ /* The user of the state tracker should set the retainBufferData field
+ * during context initialization, if needed.
+ */
+ if (b->retainBufferData) {
+ if (obj->data) {
+ crFree(obj->data);
+ }
+
+ obj->data = crAlloc(size);
+ if (!obj->data) {
+ crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, "glBufferDataARB");
+ return;
+ }
+ if (data)
+ crMemcpy(obj->data, data, size);
+ }
+
+ DIRTY(bb->dirty, g->neg_bitid);
+ DIRTY(obj->dirty, g->neg_bitid);
+ obj->dirtyStart = 0;
+ obj->dirtyLength = size;
+}
+
+
+void STATE_APIENTRY
+crStateBufferSubDataARB(GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid * data)
+{
+ CRContext *g = GetCurrentContext();
+ CRBufferObjectState *b = &g->bufferobject;
+ CRBufferObject *obj;
+ CRStateBits *sb = GetCurrentBits();
+ CRBufferObjectBits *bb = &sb->bufferobject;
+
+ FLUSH();
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glBufferSubDataARB called in begin/end");
+ return;
+ }
+
+ obj = crStateGetBoundBufferObject(target, b);
+ if (!obj)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glBufferSubDataARB(target)");
+ return;
+ }
+
+ if (obj->id == 0) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glBufferSubDataARB");
+ return;
+ }
+
+ if (obj->pointer) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glBufferSubDataARB(buffer is mapped)");
+ return;
+ }
+
+ if (size < 0 || offset < 0 || (unsigned int)offset + size > obj->size) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glBufferSubDataARB(bad offset and/or size)");
+ return;
+ }
+
+ if (b->retainBufferData && obj->data) {
+ crMemcpy((char *) obj->data + offset, data, size);
+ }
+
+ DIRTY(bb->dirty, g->neg_bitid);
+ DIRTY(obj->dirty, g->neg_bitid);
+ /* grow dirty region */
+ if (offset + size > obj->dirtyStart + obj->dirtyLength)
+ obj->dirtyLength = offset + size;
+ if (offset < obj->dirtyStart)
+ obj->dirtyStart = offset;
+}
+
+
+void STATE_APIENTRY
+crStateGetBufferSubDataARB(GLenum target, GLintptrARB offset, GLsizeiptrARB size, void * data)
+{
+ CRContext *g = GetCurrentContext();
+ CRBufferObjectState *b = &g->bufferobject;
+ CRBufferObject *obj;
+
+ FLUSH();
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetBufferSubDataARB called in begin/end");
+ return;
+ }
+
+ obj = crStateGetBoundBufferObject(target, b);
+ if (!obj)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetBufferSubDataARB(target)");
+ return;
+ }
+
+ if (obj->id == 0) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetBufferSubDataARB");
+ return;
+ }
+
+ if (obj->pointer) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetBufferSubDataARB(buffer is mapped)");
+ return;
+ }
+
+ if (size < 0 || offset < 0 || (unsigned int)offset + size > obj->size) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetBufferSubDataARB(bad offset and/or size)");
+ return;
+ }
+
+ if (b->retainBufferData && obj->data) {
+ crMemcpy(data, (char *) obj->data + offset, size);
+ }
+}
+
+
+void * STATE_APIENTRY
+crStateMapBufferARB(GLenum target, GLenum access)
+{
+ CRContext *g = GetCurrentContext();
+ CRBufferObjectState *b = &g->bufferobject;
+ CRBufferObject *obj;
+
+ FLUSH();
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glMapBufferARB called in begin/end");
+ return NULL;
+ }
+
+ obj = crStateGetBoundBufferObject(target, b);
+ if (!obj)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glMapBufferARB(target)");
+ return NULL;
+ }
+
+ if (obj->id == 0) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glMapBufferARB");
+ return GL_FALSE;
+ }
+
+ switch (access) {
+ case GL_READ_ONLY_ARB:
+ case GL_WRITE_ONLY_ARB:
+ case GL_READ_WRITE_ARB:
+ obj->access = access;
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glMapBufferARB(access)");
+ return NULL;
+ }
+
+ if (b->retainBufferData && obj->data)
+ obj->pointer = obj->data;
+
+ return obj->pointer;
+}
+
+
+GLboolean STATE_APIENTRY
+crStateUnmapBufferARB(GLenum target)
+{
+ CRContext *g = GetCurrentContext();
+ CRBufferObjectState *b = &g->bufferobject;
+ CRBufferObject *obj;
+ CRStateBits *sb = GetCurrentBits();
+ CRBufferObjectBits *bb = &sb->bufferobject;
+
+ FLUSH();
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glUnmapBufferARB called in begin/end");
+ return GL_FALSE;
+ }
+
+ obj = crStateGetBoundBufferObject(target, b);
+ if (!obj)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glUnmapBufferARB(target)");
+ return GL_FALSE;
+ }
+
+ if (obj->id == 0) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glUnmapBufferARB");
+ return GL_FALSE;
+ }
+
+ if (!obj->pointer) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glUnmapBufferARB");
+ return GL_FALSE;
+ }
+
+ obj->pointer = NULL;
+
+ if (obj->access != GL_READ_ONLY_ARB) {
+ /* the data was most likely modified */
+ DIRTY(bb->dirty, g->neg_bitid);
+ DIRTY(obj->dirty, g->neg_bitid);
+ obj->dirtyStart = 0;
+ obj->dirtyLength = obj->size;
+ }
+
+ return GL_TRUE;
+}
+
+
+void STATE_APIENTRY
+crStateGetBufferParameterivARB(GLenum target, GLenum pname, GLint *params)
+{
+ CRContext *g = GetCurrentContext();
+ CRBufferObjectState *b = &g->bufferobject;
+ CRBufferObject *obj;
+
+ FLUSH();
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetBufferParameterivARB called in begin/end");
+ return;
+ }
+
+ obj = crStateGetBoundBufferObject(target, b);
+ if (!obj)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetBufferParameterivARB(target)");
+ return;
+ }
+
+ switch (pname) {
+ case GL_BUFFER_SIZE_ARB:
+ *params = obj->size;
+ break;
+ case GL_BUFFER_USAGE_ARB:
+ *params = obj->usage;
+ break;
+ case GL_BUFFER_ACCESS_ARB:
+ *params = obj->access;
+ break;
+ case GL_BUFFER_MAPPED_ARB:
+ *params = (obj->pointer != NULL);
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetBufferParameterivARB(pname)");
+ return;
+ }
+}
+
+
+void STATE_APIENTRY
+crStateGetBufferPointervARB(GLenum target, GLenum pname, GLvoid **params)
+{
+ CRContext *g = GetCurrentContext();
+ CRBufferObjectState *b = &g->bufferobject;
+ CRBufferObject *obj;
+
+ FLUSH();
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetBufferPointervARB called in begin/end");
+ return;
+ }
+
+ obj = crStateGetBoundBufferObject(target, b);
+ if (!obj)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetBufferPointervARB(target)");
+ return;
+ }
+
+ if (pname != GL_BUFFER_MAP_POINTER_ARB) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetBufferPointervARB(pname)");
+ return;
+ }
+
+ *params = obj->pointer;
+}
+
+
+/**
+ * We need to check if the GL_EXT_vertex/pixel_buffer_object extensions
+ * are supported before calling any of the diff_api functions.
+ * This flag indicates if the extensions is available (1), not available (0)
+ * or needs to be tested for (-1).
+ * If we don't do this, we can segfault inside OpenGL.
+ * Ideally, the render SPU should no-op unsupported GL functions, but
+ * that's a bit complicated.
+ */
+static GLboolean
+HaveBufferObjectExtension(void)
+{
+ static GLint haveBufferObjectExt = -1;
+
+ if (haveBufferObjectExt == -1) {
+ const char *ext;
+ /* XXX this check is temporary. We need to make the tilesort SPU plug
+ * GetString into the diff'ing table in order for this to really work.
+ */
+ if (!diff_api.GetString) {
+ haveBufferObjectExt = 0;
+ return 0;
+ }
+ CRASSERT(diff_api.GetString);
+ ext = (const char *) diff_api.GetString(GL_EXTENSIONS);
+ if (crStrstr(ext, "GL_ARB_vertex_buffer_object") ||
+ crStrstr(ext, "GL_ARB_pixel_buffer_object")) {
+ haveBufferObjectExt = 1;
+ }
+ else {
+ haveBufferObjectExt = 0;
+ }
+ }
+ return haveBufferObjectExt;
+}
+
+static void crStateBufferObjectIntCmp(CRBufferObjectBits *bb, CRbitvalue *bitID,
+ CRContext *fromCtx, CRContext *toCtx,
+ GLboolean bSwitch)
+{
+ CRBufferObjectState *from = &(fromCtx->bufferobject);
+ const CRBufferObjectState *to = &(toCtx->bufferobject);
+
+ /* ARRAY_BUFFER */
+ if (CHECKDIRTY(bb->arrayBinding, bitID))
+ {
+ if (from->arrayBuffer != to->arrayBuffer)
+ {
+ GLuint bufferID = to->arrayBuffer ? to->arrayBuffer->hwid : 0;
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, bufferID);
+ if (bSwitch)
+ {
+ FILLDIRTY(bb->arrayBinding);
+ FILLDIRTY(bb->dirty);
+ }
+ else
+ {
+ CLEARDIRTY2(bb->arrayBinding, bitID);
+ from->arrayBuffer = to->arrayBuffer;
+ }
+ }
+ if (bSwitch) CLEARDIRTY2(bb->arrayBinding, bitID);
+ }
+
+ if (to->arrayBuffer && CHECKDIRTY(to->arrayBuffer->dirty, bitID))
+ {
+ /* update array buffer data */
+ CRBufferObject *bufObj = to->arrayBuffer;
+ CRASSERT(bufObj);
+ if (bufObj->dirtyStart == 0 && bufObj->dirtyLength == (int) bufObj->size)
+ {
+ /* update whole buffer */
+ diff_api.BufferDataARB(GL_ARRAY_BUFFER_ARB, bufObj->size,
+ bufObj->data, bufObj->usage);
+ }
+ else
+ {
+ /* update sub buffer */
+ diff_api.BufferSubDataARB(GL_ARRAY_BUFFER_ARB,
+ bufObj->dirtyStart, bufObj->dirtyLength,
+ (char *) bufObj->data + bufObj->dirtyStart);
+ }
+ if (bSwitch) FILLDIRTY(bufObj->dirty);
+ CLEARDIRTY2(bufObj->dirty, bitID);
+ }
+
+ /* ELEMENTS_BUFFER */
+ if (CHECKDIRTY(bb->elementsBinding, bitID))
+ {
+ if (from->elementsBuffer != to->elementsBuffer)
+ {
+ GLuint bufferID = to->elementsBuffer ? to->elementsBuffer->hwid : 0;
+ diff_api.BindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, bufferID);
+ if (bSwitch)
+ {
+ FILLDIRTY(bb->elementsBinding);
+ FILLDIRTY(bb->dirty);
+ }
+ else
+ {
+ CLEARDIRTY2(bb->elementsBinding, bitID);
+ from->elementsBuffer = to->elementsBuffer;
+ }
+ }
+ if (bSwitch) CLEARDIRTY2(bb->elementsBinding, bitID);
+ }
+
+ if (to->elementsBuffer && CHECKDIRTY(to->elementsBuffer->dirty, bitID))
+ {
+ /* update array buffer data */
+ CRBufferObject *bufObj = to->elementsBuffer;
+ CRASSERT(bufObj);
+ if (bufObj->dirtyStart == 0 && bufObj->dirtyLength == (int) bufObj->size)
+ {
+ /* update whole buffer */
+ diff_api.BufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, bufObj->size,
+ bufObj->data, bufObj->usage);
+ }
+ else
+ {
+ /* update sub buffer */
+ diff_api.BufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
+ bufObj->dirtyStart, bufObj->dirtyLength,
+ (char *) bufObj->data + bufObj->dirtyStart);
+ }
+ if (bSwitch) FILLDIRTY(bufObj->dirty);
+ CLEARDIRTY2(bufObj->dirty, bitID);
+ }
+
+#ifdef CR_ARB_pixel_buffer_object
+ /* PIXEL_PACK_BUFFER */
+ if (CHECKDIRTY(bb->packBinding, bitID))
+ {
+ if (from->packBuffer != to->packBuffer)
+ {
+ GLuint bufferID = to->packBuffer ? to->packBuffer->hwid : 0;
+ diff_api.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, bufferID);
+ if (bSwitch)
+ {
+ FILLDIRTY(bb->packBinding);
+ FILLDIRTY(bb->dirty);
+ }
+ else
+ {
+ CLEARDIRTY2(bb->packBinding, bitID);
+ from->packBuffer = to->packBuffer;
+ }
+ }
+ if (bSwitch) CLEARDIRTY2(bb->packBinding, bitID);
+ }
+
+ if (to->packBuffer && CHECKDIRTY(to->packBuffer->dirty, bitID))
+ {
+ /* update array buffer data */
+ CRBufferObject *bufObj = to->packBuffer;
+ CRASSERT(bufObj);
+ if (bufObj->dirtyStart == 0 && bufObj->dirtyLength == (int) bufObj->size)
+ {
+ /* update whole buffer */
+ diff_api.BufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, bufObj->size,
+ bufObj->data, bufObj->usage);
+ }
+ else
+ {
+ /* update sub buffer */
+ diff_api.BufferSubDataARB(GL_PIXEL_PACK_BUFFER_ARB,
+ bufObj->dirtyStart, bufObj->dirtyLength,
+ (char *) bufObj->data + bufObj->dirtyStart);
+ }
+ if (bSwitch) FILLDIRTY(bufObj->dirty);
+ CLEARDIRTY2(bufObj->dirty, bitID);
+ }
+
+ /* PIXEL_UNPACK_BUFFER */
+ if (CHECKDIRTY(bb->unpackBinding, bitID))
+ {
+ if (from->unpackBuffer != to->unpackBuffer)
+ {
+ GLuint bufferID = to->unpackBuffer ? to->unpackBuffer->hwid : 0;
+ diff_api.BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, bufferID);
+ if (bSwitch)
+ {
+ FILLDIRTY(bb->unpackBinding);
+ FILLDIRTY(bb->dirty);
+ }
+ else
+ {
+ CLEARDIRTY2(bb->unpackBinding, bitID);
+ from->unpackBuffer = to->unpackBuffer;
+ }
+ }
+ if (bSwitch) CLEARDIRTY2(bb->unpackBinding, bitID);
+ }
+
+ if (to->unpackBuffer && CHECKDIRTY(to->unpackBuffer->dirty, bitID))
+ {
+ /* update array buffer data */
+ CRBufferObject *bufObj = to->unpackBuffer;
+ CRASSERT(bufObj);
+ if (bufObj->dirtyStart == 0 && bufObj->dirtyLength == (int) bufObj->size)
+ {
+ /* update whole buffer */
+ diff_api.BufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, bufObj->size,
+ bufObj->data, bufObj->usage);
+ }
+ else
+ {
+ /* update sub buffer */
+ diff_api.BufferSubDataARB(GL_PIXEL_UNPACK_BUFFER_ARB,
+ bufObj->dirtyStart, bufObj->dirtyLength,
+ (char *) bufObj->data + bufObj->dirtyStart);
+ }
+ if (bSwitch) FILLDIRTY(bufObj->dirty);
+ CLEARDIRTY2(bufObj->dirty, bitID);
+ }
+#endif /*ifdef CR_ARB_pixel_buffer_object*/
+}
+
+void crStateBufferObjectDiff(CRBufferObjectBits *bb, CRbitvalue *bitID,
+ CRContext *fromCtx, CRContext *toCtx)
+{
+ /*CRBufferObjectState *from = &(fromCtx->bufferobject); - unused
+ const CRBufferObjectState *to = &(toCtx->bufferobject); - unused */
+
+ if (!HaveBufferObjectExtension())
+ return;
+
+ crStateBufferObjectIntCmp(bb, bitID, fromCtx, toCtx, GL_FALSE);
+}
+
+static void crStateBufferObjectSyncCB(unsigned long key, void *data1, void *data2)
+{
+ CRBufferObject *pBufferObj = (CRBufferObject *) data1;
+ CRBufferObjectState *pState = (CRBufferObjectState *) data2;
+ (void)key;
+
+ if (pBufferObj->id && !pBufferObj->hwid)
+ {
+ diff_api.GenBuffersARB(1, &pBufferObj->hwid);
+ CRASSERT(pBufferObj->hwid);
+ }
+
+ if (pBufferObj->data)
+ {
+ /** @todo http://www.opengl.org/registry/specs/ARB/pixel_buffer_object.txt
+ "While it is entirely legal to create a buffer object by binding
+ it to GL_ARRAY_BUFFER and loading it with data, then using it
+ with the GL_PIXEL_UNPACK_BUFFER_ARB or GL_PIXEL_PACK_BUFFER_ARB
+ binding, such behavior is liable to confuse the driver and may
+ hurt performance."
+ */
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, pBufferObj->hwid);
+ diff_api.BufferDataARB(GL_ARRAY_BUFFER_ARB, pBufferObj->size, pBufferObj->data, pBufferObj->usage);
+
+ if (!pState->retainBufferData)
+ {
+ crFree(pBufferObj->data);
+ pBufferObj->data = NULL;
+ }
+ }
+}
+
+/*
+ * XXX this function might need some testing/fixing.
+ */
+void crStateBufferObjectSwitch(CRBufferObjectBits *bb, CRbitvalue *bitID,
+ CRContext *fromCtx, CRContext *toCtx)
+{
+ /*const CRBufferObjectState *from = &(fromCtx->bufferobject); - unused */
+ CRBufferObjectState *to = &(toCtx->bufferobject);
+ int i;
+
+ if (!HaveBufferObjectExtension())
+ return;
+
+ if (toCtx->shared->bVBOResyncNeeded)
+ {
+ CRClientPointer *cp;
+ GLboolean locked = toCtx->client.array.locked;
+
+ crHashtableWalk(toCtx->shared->buffersTable, crStateBufferObjectSyncCB, to);
+ toCtx->shared->bVBOResyncNeeded = GL_FALSE;
+
+ /*@todo, move to state_client.c*/
+ cp = &toCtx->client.array.v;
+ if (cp->buffer && (cp->buffer->id || locked))
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, cp->buffer->hwid);
+ diff_api.VertexPointer(cp->size, cp->type, cp->stride, cp->p);
+ }
+
+ cp = &toCtx->client.array.c;
+ if (cp->buffer && (cp->buffer->id || locked))
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, cp->buffer->hwid);
+ diff_api.ColorPointer(cp->size, cp->type, cp->stride, cp->p);
+ }
+
+ cp = &toCtx->client.array.f;
+ if (cp->buffer && (cp->buffer->id || locked))
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, cp->buffer->hwid);
+ diff_api.FogCoordPointerEXT(cp->type, cp->stride, cp->p);
+ }
+
+ cp = &toCtx->client.array.s;
+ if (cp->buffer && (cp->buffer->id || locked))
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, cp->buffer->hwid);
+ diff_api.SecondaryColorPointerEXT(cp->size, cp->type, cp->stride, cp->p);
+ }
+
+ cp = &toCtx->client.array.e;
+ if (cp->buffer && (cp->buffer->id || locked))
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, cp->buffer->hwid);
+ diff_api.EdgeFlagPointer(cp->stride, cp->p);
+ }
+
+ cp = &toCtx->client.array.i;
+ if (cp->buffer && (cp->buffer->id || locked))
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, cp->buffer->hwid);
+ diff_api.IndexPointer(cp->type, cp->stride, cp->p);
+ }
+
+ cp = &toCtx->client.array.n;
+ if (cp->buffer && (cp->buffer->id || locked))
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, cp->buffer->hwid);
+ diff_api.NormalPointer(cp->type, cp->stride, cp->p);
+ }
+
+ for (i = 0; i < CR_MAX_TEXTURE_UNITS; i++)
+ {
+ cp = &toCtx->client.array.t[i];
+ if (cp->buffer && (cp->buffer->id || locked))
+ {
+ if (diff_api.ActiveTextureARB)
+ diff_api.ActiveTextureARB(i+GL_TEXTURE0_ARB);
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, cp->buffer->hwid);
+ diff_api.TexCoordPointer(cp->size, cp->type, cp->stride, cp->p);
+ }
+ }
+
+ if (diff_api.ActiveTextureARB)
+ diff_api.ActiveTextureARB(toCtx->client.curClientTextureUnit+GL_TEXTURE0_ARB);
+
+#ifdef CR_NV_vertex_program
+ for (i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++)
+ {
+ cp = &toCtx->client.array.a[i];
+ if (cp->buffer && (cp->buffer->id || locked))
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, cp->buffer->hwid);
+ diff_api.VertexAttribPointerARB(i, cp->size, cp->type, cp->normalized, cp->stride, cp->p);
+ }
+ }
+#endif
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, to->arrayBuffer->hwid);
+ diff_api.BindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, to->elementsBuffer->hwid);
+#ifdef CR_ARB_pixel_buffer_object
+ diff_api.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, to->packBuffer->hwid);
+ diff_api.BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, to->unpackBuffer->hwid);
+#endif
+ }
+ else
+ {
+ crStateBufferObjectIntCmp(bb, bitID, fromCtx, toCtx, GL_TRUE);
+ }
+}
+
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_client.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_client.c
new file mode 100644
index 00000000..6ca6e159
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_client.c
@@ -0,0 +1,2433 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+/*
+ * This file manages all the client-side state including:
+ * Pixel pack/unpack parameters
+ * Vertex arrays
+ */
+
+
+#include "cr_mem.h"
+#include "state.h"
+#include "state/cr_statetypes.h"
+#include "state/cr_statefuncs.h"
+#include "state_internals.h"
+
+const CRPixelPackState crStateNativePixelPacking = {
+ 0, /* rowLength */
+ 0, /* skipRows */
+ 0, /* skipPixels */
+ 1, /* alignment */
+ 0, /* imageHeight */
+ 0, /* skipImages */
+ GL_FALSE, /* swapBytes */
+ GL_FALSE, /* psLSBFirst */
+};
+
+
+void crStateClientInitBits (CRClientBits *c)
+{
+ int i;
+
+ /* XXX why GLCLIENT_BIT_ALLOC? */
+ c->v = (CRbitvalue *) crCalloc(GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+ c->n = (CRbitvalue *) crCalloc(GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+ c->c = (CRbitvalue *) crCalloc(GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+ c->s = (CRbitvalue *) crCalloc(GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+ c->i = (CRbitvalue *) crCalloc(GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+ for ( i = 0; i < CR_MAX_TEXTURE_UNITS; i++ )
+ c->t[i] = (CRbitvalue *) crCalloc(GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+ c->e = (CRbitvalue *) crCalloc(GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+ c->f = (CRbitvalue *) crCalloc(GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+
+#ifdef CR_NV_vertex_program
+ for ( i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++ )
+ c->a[i] = (CRbitvalue *) crCalloc(GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+#endif
+}
+
+void crStateClientDestroyBits (CRClientBits *c)
+{
+ int i;
+
+ crFree(c->v);
+ crFree(c->n);
+ crFree(c->c);
+ crFree(c->s);
+ crFree(c->i);
+
+ for ( i = 0; i < CR_MAX_TEXTURE_UNITS; i++ )
+ crFree(c->t[i]);
+
+ crFree(c->e);
+ crFree(c->f);
+
+#ifdef CR_NV_vertex_program
+ for ( i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++ )
+ crFree(c->a[i]);
+#endif
+}
+
+static void crStateUnlockClientPointer(CRClientPointer* cp)
+{
+ if (cp->locked)
+ {
+#ifndef IN_GUEST
+ if (cp->p) crFree(cp->p);
+#endif
+ cp->locked = GL_FALSE;
+ }
+}
+
+void crStateClientDestroy(CRContext *g)
+{
+ CRClientState *c = &(g->client);
+#ifdef CR_EXT_compiled_vertex_array
+ if (c->array.locked)
+ {
+ unsigned int i;
+
+ crStateUnlockClientPointer(&c->array.v);
+ crStateUnlockClientPointer(&c->array.c);
+ crStateUnlockClientPointer(&c->array.f);
+ crStateUnlockClientPointer(&c->array.s);
+ crStateUnlockClientPointer(&c->array.e);
+ crStateUnlockClientPointer(&c->array.i);
+ crStateUnlockClientPointer(&c->array.n);
+ for (i = 0 ; i < CR_MAX_TEXTURE_UNITS ; i++)
+ {
+ crStateUnlockClientPointer(&c->array.t[i]);
+ }
+ for (i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++)
+ {
+ crStateUnlockClientPointer(&c->array.a[i]);
+ }
+ }
+#endif
+}
+
+void crStateClientInit(CRContext *ctx)
+{
+ CRClientState *c = &(ctx->client);
+ unsigned int i;
+
+ /* pixel pack/unpack */
+ c->unpack.rowLength = 0;
+ c->unpack.skipRows = 0;
+ c->unpack.skipPixels = 0;
+ c->unpack.skipImages = 0;
+ c->unpack.alignment = 4;
+ c->unpack.imageHeight = 0;
+ c->unpack.swapBytes = GL_FALSE;
+ c->unpack.psLSBFirst = GL_FALSE;
+ c->pack.rowLength = 0;
+ c->pack.skipRows = 0;
+ c->pack.skipPixels = 0;
+ c->pack.skipImages = 0;
+ c->pack.alignment = 4;
+ c->pack.imageHeight = 0;
+ c->pack.swapBytes = GL_FALSE;
+ c->pack.psLSBFirst = GL_FALSE;
+
+ /* ARB multitexture */
+ c->curClientTextureUnit = 0;
+
+#ifdef CR_EXT_compiled_vertex_array
+ c->array.lockFirst = 0;
+ c->array.lockCount = 0;
+ c->array.locked = GL_FALSE;
+# ifdef IN_GUEST
+ c->array.synced = GL_FALSE;
+# endif
+#endif
+
+ /* vertex array */
+ c->array.v.p = NULL;
+ c->array.v.size = 4;
+ c->array.v.type = GL_FLOAT;
+ c->array.v.stride = 0;
+ c->array.v.enabled = 0;
+#ifdef CR_ARB_vertex_buffer_object
+ 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;
+ c->array.v.prevPtr = NULL;
+ c->array.v.prevStride = 0;
+#endif
+
+ /* color array */
+ c->array.c.p = NULL;
+ c->array.c.size = 4;
+ c->array.c.type = GL_FLOAT;
+ c->array.c.stride = 0;
+ c->array.c.enabled = 0;
+#ifdef CR_ARB_vertex_buffer_object
+ 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;
+ c->array.c.prevPtr = NULL;
+ c->array.c.prevStride = 0;
+#endif
+
+ /* fog array */
+ c->array.f.p = NULL;
+ c->array.f.size = 0;
+ c->array.f.type = GL_FLOAT;
+ c->array.f.stride = 0;
+ c->array.f.enabled = 0;
+#ifdef CR_ARB_vertex_buffer_object
+ 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;
+ c->array.f.prevPtr = NULL;
+ c->array.f.prevStride = 0;
+#endif
+
+ /* secondary color array */
+ c->array.s.p = NULL;
+ c->array.s.size = 3;
+ c->array.s.type = GL_FLOAT;
+ c->array.s.stride = 0;
+ c->array.s.enabled = 0;
+#ifdef CR_ARB_vertex_buffer_object
+ 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;
+ c->array.s.prevPtr = NULL;
+ c->array.s.prevStride = 0;
+#endif
+
+ /* edge flag array */
+ c->array.e.p = NULL;
+ c->array.e.size = 0;
+ c->array.e.type = GL_FLOAT;
+ c->array.e.stride = 0;
+ c->array.e.enabled = 0;
+#ifdef CR_ARB_vertex_buffer_object
+ 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;
+ c->array.e.prevPtr = NULL;
+ c->array.e.prevStride = 0;
+#endif
+
+ /* color index array */
+ c->array.i.p = NULL;
+ c->array.i.size = 0;
+ c->array.i.type = GL_FLOAT;
+ c->array.i.stride = 0;
+ c->array.i.enabled = 0;
+#ifdef CR_ARB_vertex_buffer_object
+ 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;
+ c->array.i.prevPtr = NULL;
+ c->array.i.prevStride = 0;
+#endif
+
+ /* normal array */
+ c->array.n.p = NULL;
+ c->array.n.size = 4;
+ c->array.n.type = GL_FLOAT;
+ c->array.n.stride = 0;
+ c->array.n.enabled = 0;
+#ifdef CR_ARB_vertex_buffer_object
+ 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;
+ c->array.n.prevPtr = NULL;
+ c->array.n.prevStride = 0;
+#endif
+
+ /* texcoord arrays */
+ for (i = 0 ; i < CR_MAX_TEXTURE_UNITS ; i++)
+ {
+ c->array.t[i].p = NULL;
+ c->array.t[i].size = 4;
+ c->array.t[i].type = GL_FLOAT;
+ c->array.t[i].stride = 0;
+ c->array.t[i].enabled = 0;
+#ifdef CR_ARB_vertex_buffer_object
+ 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;
+ c->array.t[i].prevPtr = NULL;
+ c->array.t[i].prevStride = 0;
+#endif
+ }
+
+ /* generic vertex attributes */
+#ifdef CR_NV_vertex_program
+ for (i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++) {
+ c->array.a[i].enabled = GL_FALSE;
+ c->array.a[i].type = GL_FLOAT;
+ c->array.a[i].size = 4;
+ c->array.a[i].stride = 0;
+#ifdef CR_ARB_vertex_buffer_object
+ 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;
+ c->array.a[i].prevPtr = NULL;
+ c->array.a[i].prevStride = 0;
+#endif
+ }
+#endif
+}
+
+
+/*
+ * PixelStore functions are here, not in state_pixel.c because this
+ * is client-side state, like vertex arrays.
+ */
+
+void STATE_APIENTRY crStatePixelStoref (GLenum pname, GLfloat param)
+{
+
+ /* The GL SPEC says I can do this on page 76. */
+ switch( pname )
+ {
+ case GL_PACK_SWAP_BYTES:
+ case GL_PACK_LSB_FIRST:
+ case GL_UNPACK_SWAP_BYTES:
+ case GL_UNPACK_LSB_FIRST:
+ crStatePixelStorei( pname, param == 0.0f ? 0: 1 );
+ break;
+ default:
+ crStatePixelStorei( pname, (GLint) param );
+ break;
+ }
+}
+
+void STATE_APIENTRY crStatePixelStorei (GLenum pname, GLint param)
+{
+ CRContext *g = GetCurrentContext();
+ CRClientState *c = &(g->client);
+ CRStateBits *sb = GetCurrentBits();
+ CRClientBits *cb = &(sb->client);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "PixelStore{if} called in Begin/End");
+ return;
+ }
+
+ FLUSH();
+
+ switch(pname) {
+ case GL_PACK_SWAP_BYTES:
+ c->pack.swapBytes = (GLboolean) param;
+ DIRTY(cb->pack, g->neg_bitid);
+ break;
+ case GL_PACK_LSB_FIRST:
+ c->pack.psLSBFirst = (GLboolean) param;
+ DIRTY(cb->pack, g->neg_bitid);
+ break;
+ case GL_PACK_ROW_LENGTH:
+ if (param < 0.0f)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Negative Row Length: %f", param);
+ return;
+ }
+ c->pack.rowLength = param;
+ DIRTY(cb->pack, g->neg_bitid);
+ break;
+#ifdef CR_OPENGL_VERSION_1_2
+ case GL_PACK_IMAGE_HEIGHT:
+ if (param < 0.0f)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Negative Image Height: %f", param);
+ return;
+ }
+ c->pack.imageHeight = param;
+ DIRTY(cb->pack, g->neg_bitid);
+ break;
+#endif
+ case GL_PACK_SKIP_IMAGES:
+ if (param < 0.0f)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Negative Skip Images: %f", param);
+ return;
+ }
+ c->pack.skipImages = param;
+ DIRTY(cb->pack, g->neg_bitid);
+ break;
+ case GL_PACK_SKIP_PIXELS:
+ if (param < 0.0f)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Negative Skip Pixels: %f", param);
+ return;
+ }
+ c->pack.skipPixels = param;
+ DIRTY(cb->pack, g->neg_bitid);
+ break;
+ case GL_PACK_SKIP_ROWS:
+ if (param < 0.0f)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Negative Row Skip: %f", param);
+ return;
+ }
+ c->pack.skipRows = param;
+ DIRTY(cb->pack, g->neg_bitid);
+ break;
+ case GL_PACK_ALIGNMENT:
+ if (((GLint) param) != 1 &&
+ ((GLint) param) != 2 &&
+ ((GLint) param) != 4 &&
+ ((GLint) param) != 8)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Invalid Alignment: %f", param);
+ return;
+ }
+ c->pack.alignment = param;
+ DIRTY(cb->pack, g->neg_bitid);
+ break;
+
+ case GL_UNPACK_SWAP_BYTES:
+ c->unpack.swapBytes = (GLboolean) param;
+ DIRTY(cb->unpack, g->neg_bitid);
+ break;
+ case GL_UNPACK_LSB_FIRST:
+ c->unpack.psLSBFirst = (GLboolean) param;
+ DIRTY(cb->unpack, g->neg_bitid);
+ break;
+ case GL_UNPACK_ROW_LENGTH:
+ if (param < 0.0f)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Negative Row Length: %f", param);
+ return;
+ }
+ c->unpack.rowLength = param;
+ DIRTY(cb->unpack, g->neg_bitid);
+ break;
+#ifdef CR_OPENGL_VERSION_1_2
+ case GL_UNPACK_IMAGE_HEIGHT:
+ if (param < 0.0f)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Negative Image Height: %f", param);
+ return;
+ }
+ c->unpack.imageHeight = param;
+ DIRTY(cb->unpack, g->neg_bitid);
+ break;
+#endif
+ case GL_UNPACK_SKIP_IMAGES:
+ if (param < 0.0f)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Negative Skip Images: %f", param);
+ return;
+ }
+ c->unpack.skipImages = param;
+ DIRTY(cb->unpack, g->neg_bitid);
+ break;
+ case GL_UNPACK_SKIP_PIXELS:
+ if (param < 0.0f)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Negative Skip Pixels: %f", param);
+ return;
+ }
+ c->unpack.skipPixels = param;
+ DIRTY(cb->unpack, g->neg_bitid);
+ break;
+ case GL_UNPACK_SKIP_ROWS:
+ if (param < 0.0f)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Negative Row Skip: %f", param);
+ return;
+ }
+ c->unpack.skipRows = param;
+ DIRTY(cb->unpack, g->neg_bitid);
+ break;
+ case GL_UNPACK_ALIGNMENT:
+ if (((GLint) param) != 1 &&
+ ((GLint) param) != 2 &&
+ ((GLint) param) != 4 &&
+ ((GLint) param) != 8)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Invalid Alignment: %f", param);
+ return;
+ }
+ c->unpack.alignment = param;
+ DIRTY(cb->unpack, g->neg_bitid);
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Unknown glPixelStore Pname: %d", pname);
+ return;
+ }
+ DIRTY(cb->dirty, g->neg_bitid);
+}
+
+
+static void setClientState(CRClientState *c, CRClientBits *cb,
+ CRbitvalue *neg_bitid, GLenum array, GLboolean state)
+{
+ CRContext *g = GetCurrentContext();
+
+ switch (array)
+ {
+#ifdef CR_NV_vertex_program
+ case GL_VERTEX_ATTRIB_ARRAY0_NV:
+ case GL_VERTEX_ATTRIB_ARRAY1_NV:
+ case GL_VERTEX_ATTRIB_ARRAY2_NV:
+ case GL_VERTEX_ATTRIB_ARRAY3_NV:
+ case GL_VERTEX_ATTRIB_ARRAY4_NV:
+ case GL_VERTEX_ATTRIB_ARRAY5_NV:
+ case GL_VERTEX_ATTRIB_ARRAY6_NV:
+ case GL_VERTEX_ATTRIB_ARRAY7_NV:
+ case GL_VERTEX_ATTRIB_ARRAY8_NV:
+ case GL_VERTEX_ATTRIB_ARRAY9_NV:
+ case GL_VERTEX_ATTRIB_ARRAY10_NV:
+ case GL_VERTEX_ATTRIB_ARRAY11_NV:
+ case GL_VERTEX_ATTRIB_ARRAY12_NV:
+ case GL_VERTEX_ATTRIB_ARRAY13_NV:
+ case GL_VERTEX_ATTRIB_ARRAY14_NV:
+ case GL_VERTEX_ATTRIB_ARRAY15_NV:
+ {
+ const GLuint i = array - GL_VERTEX_ATTRIB_ARRAY0_NV;
+ c->array.a[i].enabled = state;
+ }
+ break;
+#endif
+ case GL_VERTEX_ARRAY:
+ c->array.v.enabled = state;
+ break;
+ case GL_COLOR_ARRAY:
+ c->array.c.enabled = state;
+ break;
+ case GL_NORMAL_ARRAY:
+ c->array.n.enabled = state;
+ break;
+ case GL_INDEX_ARRAY:
+ c->array.i.enabled = state;
+ break;
+ case GL_TEXTURE_COORD_ARRAY:
+ c->array.t[c->curClientTextureUnit].enabled = state;
+ break;
+ case GL_EDGE_FLAG_ARRAY:
+ c->array.e.enabled = state;
+ break;
+#ifdef CR_EXT_fog_coord
+ case GL_FOG_COORDINATE_ARRAY_EXT:
+ c->array.f.enabled = state;
+ break;
+#endif
+#ifdef CR_EXT_secondary_color
+ case GL_SECONDARY_COLOR_ARRAY_EXT:
+ if( g->extensions.EXT_secondary_color ){
+ c->array.s.enabled = state;
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid Enum passed to Enable/Disable Client State: SECONDARY_COLOR_ARRAY_EXT - EXT_secondary_color is not enabled." );
+ return;
+ }
+ break;
+#endif
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid Enum passed to Enable/Disable Client State: 0x%x", array );
+ return;
+ }
+ DIRTY(cb->dirty, neg_bitid);
+ DIRTY(cb->enableClientState, neg_bitid);
+}
+
+void STATE_APIENTRY crStateEnableClientState (GLenum array)
+{
+ CRContext *g = GetCurrentContext();
+ CRClientState *c = &(g->client);
+ CRStateBits *sb = GetCurrentBits();
+ CRClientBits *cb = &(sb->client);
+
+ FLUSH();
+
+ setClientState(c, cb, g->neg_bitid, array, GL_TRUE);
+}
+
+void STATE_APIENTRY crStateDisableClientState (GLenum array)
+{
+ CRContext *g = GetCurrentContext();
+ CRClientState *c = &(g->client);
+ CRStateBits *sb = GetCurrentBits();
+ CRClientBits *cb = &(sb->client);
+
+ FLUSH();
+
+ setClientState(c, cb, g->neg_bitid, array, GL_FALSE);
+}
+
+static void
+crStateClientSetPointer(CRClientPointer *cp, GLint size,
+ GLenum type, GLboolean normalized,
+ GLsizei stride, const GLvoid *pointer)
+{
+ CRContext *g = GetCurrentContext();
+
+#ifdef CR_EXT_compiled_vertex_array
+ crStateUnlockClientPointer(cp);
+ cp->prevPtr = cp->p;
+ cp->prevStride = cp->stride;
+#endif
+
+ cp->p = (unsigned char *) pointer;
+ cp->size = size;
+ cp->type = type;
+ cp->normalized = normalized;
+
+ /* Calculate the bytes per index for address calculation */
+ cp->bytesPerIndex = size;
+ switch (type)
+ {
+ case GL_BYTE:
+ case GL_UNSIGNED_BYTE:
+ break;
+ case GL_SHORT:
+ case GL_UNSIGNED_SHORT:
+ cp->bytesPerIndex *= sizeof(GLshort);
+ break;
+ case GL_INT:
+ case GL_UNSIGNED_INT:
+ cp->bytesPerIndex *= sizeof(GLint);
+ break;
+ case GL_FLOAT:
+ cp->bytesPerIndex *= sizeof(GLfloat);
+ break;
+ case GL_DOUBLE:
+ cp->bytesPerIndex *= sizeof(GLdouble);
+ break;
+ default:
+ crStateError( __LINE__, __FILE__, GL_INVALID_VALUE,
+ "Unknown type of vertex array: %d", type );
+ return;
+ }
+
+ /*
+ ** Note: If stride==0 then we set the
+ ** stride equal address offset
+ ** therefore stride can never equal
+ ** zero.
+ */
+ if (stride)
+ cp->stride = stride;
+ else
+ 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
+}
+
+void STATE_APIENTRY crStateVertexPointer(GLint size, GLenum type,
+ GLsizei stride, const GLvoid *p)
+{
+ CRContext *g = GetCurrentContext();
+ CRClientState *c = &(g->client);
+ CRStateBits *sb = GetCurrentBits();
+ CRClientBits *cb = &(sb->client);
+
+ FLUSH();
+
+ if (size != 2 && size != 3 && size != 4)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glVertexPointer: invalid size: %d", size);
+ return;
+ }
+ if (type != GL_SHORT && type != GL_INT &&
+ type != GL_FLOAT && type != GL_DOUBLE)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glVertexPointer: invalid type: 0x%x", type);
+ return;
+ }
+ if (stride < 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glVertexPointer: stride was negative: %d", stride);
+ return;
+ }
+
+ crStateClientSetPointer(&(c->array.v), size, type, GL_FALSE, stride, p);
+ DIRTY(cb->dirty, g->neg_bitid);
+ DIRTY(cb->clientPointer, g->neg_bitid);
+ DIRTY(cb->v, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateColorPointer(GLint size, GLenum type,
+ GLsizei stride, const GLvoid *p)
+{
+ CRContext *g = GetCurrentContext();
+ CRClientState *c = &(g->client);
+ CRStateBits *sb = GetCurrentBits();
+ CRClientBits *cb = &(sb->client);
+
+ FLUSH();
+
+ if (size != 3 && size != 4)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glColorPointer: invalid size: %d", size);
+ return;
+ }
+ if (type != GL_BYTE && type != GL_UNSIGNED_BYTE &&
+ type != GL_SHORT && type != GL_UNSIGNED_SHORT &&
+ type != GL_INT && type != GL_UNSIGNED_INT &&
+ type != GL_FLOAT && type != GL_DOUBLE)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glColorPointer: invalid type: 0x%x", type);
+ return;
+ }
+ if (stride < 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glColorPointer: stride was negative: %d", stride);
+ return;
+ }
+
+ crStateClientSetPointer(&(c->array.c), size, type, GL_TRUE, stride, p);
+ DIRTY(cb->dirty, g->neg_bitid);
+ DIRTY(cb->clientPointer, g->neg_bitid);
+ DIRTY(cb->c, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateSecondaryColorPointerEXT(GLint size,
+ GLenum type, GLsizei stride, const GLvoid *p)
+{
+ CRContext *g = GetCurrentContext();
+ CRClientState *c = &(g->client);
+ CRStateBits *sb = GetCurrentBits();
+ CRClientBits *cb = &(sb->client);
+
+ FLUSH();
+
+ if ( !g->extensions.EXT_secondary_color )
+ {
+ crError( "glSecondaryColorPointerEXT called but EXT_secondary_color is disabled." );
+ return;
+ }
+
+ /*Note: According to opengl spec, only size==3 should be accepted here.
+ *But it turns out that most drivers accept size==4 here as well, and 4th value
+ *could even be accessed in shaders code.
+ *Having a strict check here, leads to difference between guest and host gpu states, which
+ *in turn could lead to crashes when using server side VBOs.
+ *@todo: add error reporting to state's VBO related functions and abort dispatching to
+ *real gpu on any failure to prevent other possible issues.
+ */
+
+ if ((size != 3) && (size != 4))
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glSecondaryColorPointerEXT: invalid size: %d", size);
+ return;
+ }
+ if (type != GL_BYTE && type != GL_UNSIGNED_BYTE &&
+ type != GL_SHORT && type != GL_UNSIGNED_SHORT &&
+ type != GL_INT && type != GL_UNSIGNED_INT &&
+ type != GL_FLOAT && type != GL_DOUBLE)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glSecondaryColorPointerEXT: invalid type: 0x%x", type);
+ return;
+ }
+ if (stride < 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glSecondaryColorPointerEXT: stride was negative: %d", stride);
+ return;
+ }
+
+ crStateClientSetPointer(&(c->array.s), size, type, GL_TRUE, stride, p);
+ DIRTY(cb->dirty, g->neg_bitid);
+ DIRTY(cb->clientPointer, g->neg_bitid);
+ DIRTY(cb->s, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateIndexPointer(GLenum type, GLsizei stride,
+ const GLvoid *p)
+{
+ CRContext *g = GetCurrentContext();
+ CRClientState *c = &(g->client);
+ CRStateBits *sb = GetCurrentBits();
+ CRClientBits *cb = &(sb->client);
+
+ FLUSH();
+
+ if (type != GL_SHORT && type != GL_INT && type != GL_UNSIGNED_BYTE &&
+ type != GL_FLOAT && type != GL_DOUBLE)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glIndexPointer: invalid type: 0x%x", type);
+ return;
+ }
+ if (stride < 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glIndexPointer: stride was negative: %d", stride);
+ return;
+ }
+
+ crStateClientSetPointer(&(c->array.i), 1, type, GL_TRUE, stride, p);
+ DIRTY(cb->dirty, g->neg_bitid);
+ DIRTY(cb->clientPointer, g->neg_bitid);
+ DIRTY(cb->i, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateNormalPointer(GLenum type, GLsizei stride,
+ const GLvoid *p)
+{
+ CRContext *g = GetCurrentContext();
+ CRClientState *c = &(g->client);
+ CRStateBits *sb = GetCurrentBits();
+ CRClientBits *cb = &(sb->client);
+
+ FLUSH();
+
+ if (type != GL_BYTE && type != GL_SHORT &&
+ type != GL_INT && type != GL_FLOAT &&
+ type != GL_DOUBLE)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glNormalPointer: invalid type: 0x%x", type);
+ return;
+ }
+ if (stride < 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glNormalPointer: stride was negative: %d", stride);
+ return;
+ }
+
+ crStateClientSetPointer(&(c->array.n), 3, type, GL_TRUE, stride, p);
+ DIRTY(cb->dirty, g->neg_bitid);
+ DIRTY(cb->clientPointer, g->neg_bitid);
+ DIRTY(cb->n, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateTexCoordPointer(GLint size, GLenum type,
+ GLsizei stride, const GLvoid *p)
+{
+ CRContext *g = GetCurrentContext();
+ CRClientState *c = &(g->client);
+ CRStateBits *sb = GetCurrentBits();
+ CRClientBits *cb = &(sb->client);
+
+ FLUSH();
+
+ if (size != 1 && size != 2 && size != 3 && size != 4)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glTexCoordPointer: invalid size: %d", size);
+ return;
+ }
+ if (type != GL_SHORT && type != GL_INT &&
+ type != GL_FLOAT && type != GL_DOUBLE)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexCoordPointer: invalid type: 0x%x", type);
+ return;
+ }
+ if (stride < 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glTexCoordPointer: stride was negative: %d", stride);
+ return;
+ }
+
+ crStateClientSetPointer(&(c->array.t[c->curClientTextureUnit]), size, type, GL_FALSE, stride, p);
+ DIRTY(cb->dirty, g->neg_bitid);
+ DIRTY(cb->clientPointer, g->neg_bitid);
+ DIRTY(cb->t[c->curClientTextureUnit], g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateEdgeFlagPointer(GLsizei stride, const GLvoid *p)
+{
+ CRContext *g = GetCurrentContext();
+ CRClientState *c = &(g->client);
+ CRStateBits *sb = GetCurrentBits();
+ CRClientBits *cb = &(sb->client);
+
+ FLUSH();
+
+ if (stride < 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glTexCoordPointer: stride was negative: %d", stride);
+ return;
+ }
+
+ crStateClientSetPointer(&(c->array.e), 1, GL_UNSIGNED_BYTE, GL_FALSE, stride, p);
+ DIRTY(cb->dirty, g->neg_bitid);
+ DIRTY(cb->clientPointer, g->neg_bitid);
+ DIRTY(cb->e, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateFogCoordPointerEXT(GLenum type, GLsizei stride, const GLvoid *p)
+{
+ CRContext *g = GetCurrentContext();
+ CRClientState *c = &(g->client);
+ CRStateBits *sb = GetCurrentBits();
+ CRClientBits *cb = &(sb->client);
+
+ FLUSH();
+
+ if (type != GL_BYTE && type != GL_UNSIGNED_BYTE &&
+ type != GL_SHORT && type != GL_UNSIGNED_SHORT &&
+ type != GL_INT && type != GL_UNSIGNED_INT &&
+ type != GL_FLOAT && type != GL_DOUBLE)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glFogCoordPointerEXT: invalid type: 0x%x", type);
+ return;
+ }
+ if (stride < 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glFogCoordPointerEXT: stride was negative: %d", stride);
+ return;
+ }
+
+ crStateClientSetPointer(&(c->array.f), 1, type, GL_FALSE, stride, p);
+ DIRTY(cb->dirty, g->neg_bitid);
+ DIRTY(cb->clientPointer, g->neg_bitid);
+ DIRTY(cb->f, g->neg_bitid);
+}
+
+
+void STATE_APIENTRY crStateVertexAttribPointerNV(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *p)
+{
+ GLboolean normalized = GL_FALSE;
+ /* Extra error checking for NV arrays */
+ if (type != GL_UNSIGNED_BYTE && type != GL_SHORT &&
+ type != GL_FLOAT && type != GL_DOUBLE) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glVertexAttribPointerNV: invalid type: 0x%x", type);
+ return;
+ }
+ crStateVertexAttribPointerARB(index, size, type, normalized, stride, p);
+}
+
+
+void STATE_APIENTRY crStateVertexAttribPointerARB(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *p)
+{
+ CRContext *g = GetCurrentContext();
+ CRClientState *c = &(g->client);
+ CRStateBits *sb = GetCurrentBits();
+ CRClientBits *cb = &(sb->client);
+
+ FLUSH();
+
+ if (index >= CR_MAX_VERTEX_ATTRIBS)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glVertexAttribPointerARB: invalid index: %d", (int) index);
+ return;
+ }
+ if (size != 1 && size != 2 && size != 3 && size != 4)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glVertexAttribPointerARB: invalid size: %d", size);
+ return;
+ }
+ if (type != GL_BYTE && type != GL_UNSIGNED_BYTE &&
+ type != GL_SHORT && type != GL_UNSIGNED_SHORT &&
+ type != GL_INT && type != GL_UNSIGNED_INT &&
+ type != GL_FLOAT && type != GL_DOUBLE)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glVertexAttribPointerARB: invalid type: 0x%x", type);
+ return;
+ }
+ if (stride < 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glVertexAttribPointerARB: stride was negative: %d", stride);
+ return;
+ }
+
+ crStateClientSetPointer(&(c->array.a[index]), size, type, normalized, stride, p);
+ DIRTY(cb->dirty, g->neg_bitid);
+ DIRTY(cb->clientPointer, g->neg_bitid);
+ DIRTY(cb->a[index], g->neg_bitid);
+}
+
+
+void STATE_APIENTRY crStateGetVertexAttribPointervNV(GLuint index, GLenum pname, GLvoid **pointer)
+{
+ CRContext *g = GetCurrentContext();
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetVertexAttribPointervNV called in Begin/End");
+ return;
+ }
+
+ if (index >= CR_MAX_VERTEX_ATTRIBS) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glGetVertexAttribPointervNV(index)");
+ return;
+ }
+
+ if (pname != GL_ATTRIB_ARRAY_POINTER_NV) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetVertexAttribPointervNV(pname)");
+ return;
+ }
+
+ *pointer = g->client.array.a[index].p;
+}
+
+
+void STATE_APIENTRY crStateGetVertexAttribPointervARB(GLuint index, GLenum pname, GLvoid **pointer)
+{
+ crStateGetVertexAttribPointervNV(index, pname, pointer);
+}
+
+
+
+/*
+** Currently I treat Interleaved Arrays as if the
+** user uses them as separate arrays.
+** Certainly not the most efficient method but it
+** lets me use the same glDrawArrays method.
+*/
+void STATE_APIENTRY crStateInterleavedArrays(GLenum format, GLsizei stride, const GLvoid *p)
+{
+ CRContext *g = GetCurrentContext();
+ CRClientState *c = &(g->client);
+ CRStateBits *sb = GetCurrentBits();
+ CRClientBits *cb = &(sb->client);
+ CRClientPointer *cp;
+ unsigned char *base = (unsigned char *) p;
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glInterleavedArrays called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ if (stride < 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glInterleavedArrays: stride < 0: %d", stride);
+ return;
+ }
+
+ switch (format)
+ {
+ case GL_T4F_C4F_N3F_V4F:
+ case GL_T2F_C4F_N3F_V3F:
+ case GL_C4F_N3F_V3F:
+ case GL_T4F_V4F:
+ case GL_T2F_C3F_V3F:
+ case GL_T2F_N3F_V3F:
+ case GL_C3F_V3F:
+ case GL_N3F_V3F:
+ case GL_T2F_C4UB_V3F:
+ case GL_T2F_V3F:
+ case GL_C4UB_V3F:
+ case GL_V3F:
+ case GL_C4UB_V2F:
+ case GL_V2F:
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glInterleavedArrays: Unrecognized format: %d", format);
+ return;
+ }
+
+ DIRTY(cb->dirty, g->neg_bitid);
+ DIRTY(cb->clientPointer, g->neg_bitid);
+
+/* p, size, type, stride, enabled, bytesPerIndex */
+/*
+** VertexPointer
+*/
+
+ cp = &(c->array.v);
+ cp->type = GL_FLOAT;
+ cp->enabled = GL_TRUE;
+
+#ifdef CR_EXT_compiled_vertex_array
+ crStateUnlockClientPointer(cp);
+#endif
+
+ switch (format)
+ {
+ case GL_T4F_C4F_N3F_V4F:
+ cp->p = base+4*sizeof(GLfloat)+4*sizeof(GLfloat)+3*sizeof(GLfloat);
+ cp->size = 4;
+ break;
+ case GL_T2F_C4F_N3F_V3F:
+ cp->p = base+2*sizeof(GLfloat)+4*sizeof(GLfloat)+3*sizeof(GLfloat);
+ cp->size = 3;
+ break;
+ case GL_C4F_N3F_V3F:
+ cp->p = base+4*sizeof(GLfloat)+3*sizeof(GLfloat);
+ cp->size = 3;
+ break;
+ case GL_T4F_V4F:
+ cp->p = base+4*sizeof(GLfloat);
+ cp->size = 4;
+ break;
+ case GL_T2F_C3F_V3F:
+ cp->p = base+2*sizeof(GLfloat)+3*sizeof(GLfloat);
+ cp->size = 3;
+ break;
+ case GL_T2F_N3F_V3F:
+ cp->p = base+2*sizeof(GLfloat)+3*sizeof(GLfloat);
+ cp->size = 3;
+ break;
+ case GL_C3F_V3F:
+ cp->p = base+3*sizeof(GLfloat);
+ cp->size = 3;
+ break;
+ case GL_N3F_V3F:
+ cp->p = base+3*sizeof(GLfloat);
+ cp->size = 3;
+ break;
+ case GL_T2F_C4UB_V3F:
+ cp->p = base+2*sizeof(GLfloat)+4*sizeof(GLubyte);
+ cp->size = 3;
+ break;
+ case GL_T2F_V3F:
+ cp->p = base+2*sizeof(GLfloat);
+ cp->size = 3;
+ break;
+ case GL_C4UB_V3F:
+ cp->p = base+4*sizeof(GLubyte);
+ cp->size = 3;
+ break;
+ case GL_V3F:
+ cp->p = base;
+ cp->size = 3;
+ break;
+ case GL_C4UB_V2F:
+ cp->p = base+4*sizeof(GLubyte);
+ cp->size = 2;
+ break;
+ case GL_V2F:
+ cp->p = base;
+ cp->size = 2;
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glInterleavedArrays: Unrecognized format: %d", format);
+ return;
+ }
+
+ cp->bytesPerIndex = cp->size * sizeof (GLfloat);
+
+ if (stride==0)
+ stride = cp->bytesPerIndex + (cp->p - base);
+ cp->stride = stride;
+
+/*
+** NormalPointer
+*/
+
+ cp = &(c->array.n);
+ cp->enabled = GL_TRUE;
+ cp->stride = stride;
+#ifdef CR_EXT_compiled_vertex_array
+ crStateUnlockClientPointer(cp);
+#endif
+
+ switch (format)
+ {
+ case GL_T4F_C4F_N3F_V4F:
+ cp->p = base+4*sizeof(GLfloat)+4*sizeof(GLfloat);
+ break;
+ case GL_T2F_C4F_N3F_V3F:
+ cp->p = base+2*sizeof(GLfloat)+4*sizeof(GLfloat);
+ break;
+ case GL_C4F_N3F_V3F:
+ cp->p = base+4*sizeof(GLfloat);
+ break;
+ case GL_T2F_N3F_V3F:
+ cp->p = base+2*sizeof(GLfloat);
+ break;
+ case GL_N3F_V3F:
+ cp->p = base;
+ break;
+ case GL_T4F_V4F:
+ case GL_T2F_C3F_V3F:
+ case GL_C3F_V3F:
+ case GL_T2F_C4UB_V3F:
+ case GL_T2F_V3F:
+ case GL_C4UB_V3F:
+ case GL_V3F:
+ case GL_C4UB_V2F:
+ case GL_V2F:
+ cp->enabled = GL_FALSE;
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glInterleavedArrays: Unrecognized format: %d", format);
+ return;
+ }
+
+ if (cp->enabled)
+ {
+ cp->type = GL_FLOAT;
+ cp->size = 3;
+ cp->bytesPerIndex = cp->size * sizeof (GLfloat);
+ }
+
+/*
+** ColorPointer
+*/
+
+ cp = &(c->array.c);
+ cp->enabled = GL_TRUE;
+ cp->stride = stride;
+#ifdef CR_EXT_compiled_vertex_array
+ crStateUnlockClientPointer(cp);
+#endif
+
+ switch (format)
+ {
+ case GL_T4F_C4F_N3F_V4F:
+ cp->size = 4;
+ cp->type = GL_FLOAT;
+ cp->bytesPerIndex = cp->size * sizeof(GLfloat);
+ cp->p = base+4*sizeof(GLfloat);
+ break;
+ case GL_T2F_C4F_N3F_V3F:
+ cp->size = 4;
+ cp->type = GL_FLOAT;
+ cp->bytesPerIndex = cp->size * sizeof(GLfloat);
+ cp->p = base+2*sizeof(GLfloat);
+ break;
+ case GL_C4F_N3F_V3F:
+ cp->size = 4;
+ cp->type = GL_FLOAT;
+ cp->bytesPerIndex = cp->size * sizeof(GLfloat);
+ cp->p = base;
+ break;
+ case GL_T2F_C3F_V3F:
+ cp->size = 3;
+ cp->type = GL_FLOAT;
+ cp->bytesPerIndex = cp->size * sizeof(GLfloat);
+ cp->p = base+2*sizeof(GLfloat);
+ break;
+ case GL_C3F_V3F:
+ cp->size = 3;
+ cp->type = GL_FLOAT;
+ cp->bytesPerIndex = cp->size * sizeof(GLfloat);
+ cp->p = base;
+ break;
+ case GL_T2F_C4UB_V3F:
+ cp->size = 4;
+ cp->type = GL_UNSIGNED_BYTE;
+ cp->bytesPerIndex = cp->size * sizeof(GLubyte);
+ cp->p = base+2*sizeof(GLfloat);
+ break;
+ case GL_C4UB_V3F:
+ cp->size = 4;
+ cp->type = GL_UNSIGNED_BYTE;
+ cp->bytesPerIndex = cp->size * sizeof(GLubyte);
+ cp->p = base;
+ break;
+ case GL_C4UB_V2F:
+ cp->size = 4;
+ cp->type = GL_UNSIGNED_BYTE;
+ cp->bytesPerIndex = cp->size * sizeof(GLubyte);
+ cp->p = base;
+ break;
+ case GL_T2F_N3F_V3F:
+ case GL_N3F_V3F:
+ case GL_T4F_V4F:
+ case GL_T2F_V3F:
+ case GL_V3F:
+ case GL_V2F:
+ cp->enabled = GL_FALSE;
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glInterleavedArrays: Unrecognized format: %d", format);
+ return;
+ }
+
+/*
+** TexturePointer
+*/
+
+ cp = &(c->array.t[c->curClientTextureUnit]);
+ cp->enabled = GL_TRUE;
+ cp->stride = stride;
+#ifdef CR_EXT_compiled_vertex_array
+ crStateUnlockClientPointer(cp);
+#endif
+
+ switch (format)
+ {
+ case GL_T4F_C4F_N3F_V4F:
+ cp->size = 4;
+ cp->p = base;
+ break;
+ case GL_T2F_C4F_N3F_V3F:
+ cp->size = 3;
+ cp->p = base;
+ break;
+ case GL_T2F_C3F_V3F:
+ case GL_T2F_N3F_V3F:
+ cp->size = 3;
+ cp->p = base;
+ break;
+ case GL_T2F_C4UB_V3F:
+ cp->size = 3;
+ cp->p = base;
+ break;
+ case GL_T4F_V4F:
+ cp->size = 4;
+ cp->p = base;
+ break;
+ case GL_T2F_V3F:
+ cp->size = 3;
+ cp->p = base;
+ break;
+ case GL_C4UB_V3F:
+ case GL_C4UB_V2F:
+ case GL_C3F_V3F:
+ case GL_C4F_N3F_V3F:
+ case GL_N3F_V3F:
+ case GL_V3F:
+ case GL_V2F:
+ cp->enabled = GL_FALSE;
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glInterleavedArrays: Unrecognized format: %d", format);
+ return;
+ }
+
+ if (cp->enabled)
+ {
+ cp->type = GL_FLOAT;
+ cp->bytesPerIndex = cp->size * sizeof (GLfloat);
+ }
+}
+
+void STATE_APIENTRY crStateGetPointerv(GLenum pname, GLvoid * * params)
+{
+ CRContext *g = GetCurrentContext();
+ CRClientState *c = &(g->client);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "GetPointerv called in begin/end");
+ return;
+ }
+
+ switch (pname)
+ {
+ case GL_VERTEX_ARRAY_POINTER:
+ *params = (GLvoid *) c->array.v.p;
+ break;
+ case GL_COLOR_ARRAY_POINTER:
+ *params = (GLvoid *) c->array.c.p;
+ break;
+ case GL_NORMAL_ARRAY_POINTER:
+ *params = (GLvoid *) c->array.n.p;
+ break;
+ case GL_INDEX_ARRAY_POINTER:
+ *params = (GLvoid *) c->array.i.p;
+ break;
+ case GL_TEXTURE_COORD_ARRAY_POINTER:
+ *params = (GLvoid *) c->array.t[c->curClientTextureUnit].p;
+ break;
+ case GL_EDGE_FLAG_ARRAY_POINTER:
+ *params = (GLvoid *) c->array.e.p;
+ break;
+#ifdef CR_EXT_fog_coord
+ case GL_FOG_COORDINATE_ARRAY_POINTER_EXT:
+ *params = (GLvoid *) c->array.f.p;
+ break;
+#endif
+#ifdef CR_EXT_secondary_color
+ case GL_SECONDARY_COLOR_ARRAY_POINTER_EXT:
+ if( g->extensions.EXT_secondary_color ){
+ *params = (GLvoid *) c->array.s.p;
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid Enum passed to glGetPointerv: SECONDARY_COLOR_ARRAY_EXT - EXT_secondary_color is not enabled." );
+ return;
+ }
+ break;
+#endif
+ case GL_FEEDBACK_BUFFER_POINTER:
+ case GL_SELECTION_BUFFER_POINTER:
+ /* do nothing - API switching should pick this up */
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetPointerv: invalid pname: %d", pname);
+ return;
+ }
+}
+
+
+void STATE_APIENTRY crStatePushClientAttrib( GLbitfield mask )
+{
+ CRContext *g = GetCurrentContext();
+ CRClientState *c = &(g->client);
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glPushClientAttrib called in Begin/End");
+ return;
+ }
+
+ if (c->attribStackDepth == CR_MAX_CLIENT_ATTRIB_STACK_DEPTH - 1) {
+ crStateError(__LINE__, __FILE__, GL_STACK_OVERFLOW,
+ "glPushClientAttrib called with a full stack!" );
+ return;
+ }
+
+ FLUSH();
+
+ c->pushMaskStack[c->attribStackDepth++] = mask;
+
+ if (mask & GL_CLIENT_PIXEL_STORE_BIT) {
+ c->pixelPackStoreStack[c->pixelStoreStackDepth] = c->pack;
+ c->pixelUnpackStoreStack[c->pixelStoreStackDepth] = c->unpack;
+ c->pixelStoreStackDepth++;
+ }
+ if (mask & GL_CLIENT_VERTEX_ARRAY_BIT) {
+ c->vertexArrayStack[c->vertexArrayStackDepth] = c->array;
+ c->vertexArrayStackDepth++;
+ }
+
+ /* dirty? - no, because we haven't really changed any state */
+}
+
+
+void STATE_APIENTRY crStatePopClientAttrib( void )
+{
+ CRContext *g = GetCurrentContext();
+ CRClientState *c = &(g->client);
+ CRStateBits *sb = GetCurrentBits();
+ CRClientBits *cb = &(sb->client);
+ CRbitvalue mask;
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glPopClientAttrib called in Begin/End");
+ return;
+ }
+
+ if (c->attribStackDepth == 0) {
+ crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW,
+ "glPopClientAttrib called with an empty stack!" );
+ return;
+ }
+
+ FLUSH();
+
+ mask = c->pushMaskStack[--c->attribStackDepth];
+
+ if (mask & GL_CLIENT_PIXEL_STORE_BIT) {
+ if (c->pixelStoreStackDepth == 0) {
+ crError("bug in glPopClientAttrib (pixel store) ");
+ return;
+ }
+ c->pixelStoreStackDepth--;
+ c->pack = c->pixelPackStoreStack[c->pixelStoreStackDepth];
+ c->unpack = c->pixelUnpackStoreStack[c->pixelStoreStackDepth];
+ DIRTY(cb->pack, g->neg_bitid);
+ }
+
+ if (mask & GL_CLIENT_VERTEX_ARRAY_BIT) {
+ if (c->vertexArrayStackDepth == 0) {
+ crError("bug in glPopClientAttrib (vertex array) ");
+ return;
+ }
+ c->vertexArrayStackDepth--;
+ c->array = c->vertexArrayStack[c->vertexArrayStackDepth];
+ DIRTY(cb->clientPointer, g->neg_bitid);
+ }
+
+ DIRTY(cb->dirty, g->neg_bitid);
+}
+
+static void crStateLockClientPointer(CRClientPointer* cp)
+{
+ crStateUnlockClientPointer(cp);
+ if (cp->enabled)
+ {
+ cp->locked = GL_TRUE;
+ }
+}
+
+static GLboolean crStateCanLockClientPointer(CRClientPointer* cp)
+{
+ return !(cp->enabled && cp->buffer && cp->buffer->id);
+}
+
+void STATE_APIENTRY crStateLockArraysEXT(GLint first, GLint count)
+{
+ CRContext *g = GetCurrentContext();
+ CRClientState *c = &(g->client);
+ int i;
+
+ for (i=0; i<CRSTATECLIENT_MAX_VERTEXARRAYS; ++i)
+ {
+ if (!crStateCanLockClientPointer(crStateGetClientPointerByIndex(i, &c->array)))
+ {
+ break;
+ }
+ }
+ if (i<CRSTATECLIENT_MAX_VERTEXARRAYS)
+ {
+ crDebug("crStateLockArraysEXT ignored because array %i have a bound VBO", i);
+ return;
+ }
+
+ c->array.locked = GL_TRUE;
+ c->array.lockFirst = first;
+ c->array.lockCount = count;
+#ifdef IN_GUEST
+ c->array.synced = GL_FALSE;
+#endif
+
+ for (i=0; i<CRSTATECLIENT_MAX_VERTEXARRAYS; ++i)
+ {
+ crStateLockClientPointer(crStateGetClientPointerByIndex(i, &c->array));
+ }
+}
+
+void STATE_APIENTRY crStateUnlockArraysEXT()
+{
+ CRContext *g = GetCurrentContext();
+ CRClientState *c = &(g->client);
+ int i;
+
+ if (!c->array.locked)
+ {
+ crDebug("crStateUnlockArraysEXT ignored because arrays aren't locked");
+ return;
+ }
+
+ c->array.locked = GL_FALSE;
+#ifdef IN_GUEST
+ c->array.synced = GL_FALSE;
+#endif
+
+ for (i=0; i<CRSTATECLIENT_MAX_VERTEXARRAYS; ++i)
+ {
+ crStateUnlockClientPointer(crStateGetClientPointerByIndex(i, &c->array));
+ }
+}
+
+void STATE_APIENTRY crStateVertexArrayRangeNV(GLsizei length, const GLvoid *pointer)
+{
+ /* XXX todo */
+ crWarning("crStateVertexArrayRangeNV not implemented");
+ (void)length; (void)pointer;
+}
+
+
+void STATE_APIENTRY crStateFlushVertexArrayRangeNV(void)
+{
+ /* XXX todo */
+ crWarning("crStateFlushVertexArrayRangeNV not implemented");
+}
+
+/*Returns if the given clientpointer could be used on server side directly*/
+#define CRSTATE_IS_SERVER_CP(cp) (!(cp).enabled || !(cp).p || ((cp).buffer && (cp).buffer->id) || ((cp).locked))
+
+#if defined(DEBUG) && 0
+static void crStateDumpClientPointer(CRClientPointer *cp, const char *name, int i)
+{
+ if (i<0 && cp->enabled)
+ {
+ crDebug("CP(%s): enabled:%d ptr:%p buffer:%p buffer.name:%i locked: %i %s",
+ name, cp->enabled, cp->p, cp->buffer, cp->buffer ? cp->buffer->id : ~(GLuint)0, (int)cp->locked,
+ CRSTATE_IS_SERVER_CP(*cp) ? "":"!FAIL!");
+ }
+ else if (0==i || cp->enabled)
+ {
+ crDebug("CP(%s%i): enabled:%d ptr:%p buffer:%p buffer.name:%i locked: %i %s",
+ name, i, cp->enabled, cp->p, cp->buffer, cp->buffer ? cp->buffer->id : ~(GLuint)0, (int)cp->locked,
+ CRSTATE_IS_SERVER_CP(*cp) ? "":"!FAIL!");
+ }
+}
+#endif
+
+#ifdef DEBUG_misha
+/* debugging */
+/*# define CR_NO_SERVER_ARRAYS*/
+#endif
+
+/*
+ * Determine if the enabled arrays all live on the server
+ * (via GL_ARB_vertex_buffer_object).
+ */
+GLboolean crStateUseServerArrays(void)
+{
+#if defined(CR_ARB_vertex_buffer_object) && !defined(CR_NO_SERVER_ARRAYS)
+ CRContext *g = GetCurrentContext();
+ CRClientState *c = &(g->client);
+ int i;
+ GLboolean res;
+
+ res = CRSTATE_IS_SERVER_CP(c->array.v)
+ && CRSTATE_IS_SERVER_CP(c->array.n)
+ && CRSTATE_IS_SERVER_CP(c->array.c)
+ && CRSTATE_IS_SERVER_CP(c->array.i)
+ && CRSTATE_IS_SERVER_CP(c->array.e)
+ && CRSTATE_IS_SERVER_CP(c->array.s)
+ && CRSTATE_IS_SERVER_CP(c->array.f);
+
+ if (res)
+ {
+ for (i = 0; (unsigned int)i < g->limits.maxTextureUnits; i++)
+ if (!CRSTATE_IS_SERVER_CP(c->array.t[i]))
+ {
+ res = GL_FALSE;
+ break;
+ }
+ }
+
+ if (res)
+ {
+ for (i = 0; (unsigned int)i < g->limits.maxVertexProgramAttribs; i++)
+ if (!CRSTATE_IS_SERVER_CP(c->array.a[i]))
+ {
+ res = GL_FALSE;
+ break;
+ }
+ }
+
+#if defined(DEBUG) && 0
+ if (!res)
+ {
+ crStateDumpClientPointer(&c->array.v, "v", -1);
+ crStateDumpClientPointer(&c->array.n, "n", -1);
+ crStateDumpClientPointer(&c->array.c, "c", -1);
+ crStateDumpClientPointer(&c->array.i, "i", -1);
+ crStateDumpClientPointer(&c->array.e, "e", -1);
+ crStateDumpClientPointer(&c->array.s, "s", -1);
+ crStateDumpClientPointer(&c->array.f, "f", -1);
+ for (i = 0; (unsigned int)i < g->limits.maxTextureUnits; i++)
+ crStateDumpClientPointer(&c->array.t[i], "tex", i);
+ for (i = 0; (unsigned int)i < g->limits.maxVertexProgramAttribs; i++)
+ crStateDumpClientPointer(&c->array.a[i], "attrib", i);
+ crDebug("crStateUseServerArrays->%d", res);
+ }
+#endif
+
+ return res;
+#else
+ return GL_FALSE;
+#endif
+}
+
+GLuint crStateNeedDummyZeroVertexArray(CRContext *g, CRCurrentStatePointers *current, GLfloat *pZva)
+{
+#if defined(CR_ARB_vertex_buffer_object)
+ CRClientState *c = &(g->client);
+ int i;
+ GLuint zvMax = 0;
+
+ if (c->array.a[0].enabled)
+ return 0;
+
+ for (i = 1; (unsigned int)i < g->limits.maxVertexProgramAttribs; i++)
+ {
+ if (c->array.a[i].enabled)
+ {
+ if (c->array.a[i].buffer && c->array.a[i].buffer->id)
+ {
+ GLuint cElements = c->array.a[i].buffer->size / c->array.a[i].stride;
+ if (zvMax < cElements)
+ zvMax = cElements;
+ }
+ else
+ {
+ zvMax = ~0;
+ break;
+ }
+ }
+ }
+
+ if (zvMax)
+ {
+ Assert(!c->array.v.enabled);
+
+ crStateCurrentRecoverNew(g, current);
+
+ crMemcpy(pZva, &g->current.vertexAttrib[0][0], sizeof (*pZva) * 4);
+ }
+
+ return zvMax;
+#else
+ return GL_FALSE;
+#endif
+}
+
+
+/**
+ * Determine if there's a server-side array element buffer.
+ * Called by glDrawElements() in packing SPUs to determine if glDrawElements
+ * should be evaluated (unrolled) locally or if glDrawElements should be
+ * packed and sent to the server.
+ */
+GLboolean
+crStateUseServerArrayElements(void)
+{
+#ifdef CR_ARB_vertex_buffer_object
+ CRContext *g = GetCurrentContext();
+ if (g->bufferobject.elementsBuffer &&
+ g->bufferobject.elementsBuffer->id > 0)
+ return GL_TRUE;
+ else
+ return GL_FALSE;
+#else
+ return GL_FALSE;
+#endif
+}
+
+#define CR_BUFFER_HWID(_p) ((_p) ? (_p)->hwid : 0)
+
+void
+crStateClientDiff(CRClientBits *cb, CRbitvalue *bitID,
+ CRContext *fromCtx, CRContext *toCtx)
+{
+ CRClientState *from = &(fromCtx->client);
+ 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 */
+ if (CHECKDIRTY(cb->v, 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;
+ 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;
+ }
+ CLEARDIRTY2(cb->v, bitID);
+ }
+ /* normal */
+ 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;
+ from->array.n.stride = to->array.n.stride;
+ from->array.n.p = to->array.n.p;
+ from->array.n.buffer = to->array.n.buffer;
+ }
+ CLEARDIRTY2(cb->n, bitID);
+ }
+ /* color */
+ if (CHECKDIRTY(cb->c, 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;
+ 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;
+ }
+ CLEARDIRTY2(cb->c, bitID);
+ }
+ /* index */
+ 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;
+ from->array.i.stride = to->array.i.stride;
+ from->array.i.p = to->array.i.p;
+ from->array.i.buffer = to->array.i.buffer;
+ }
+ CLEARDIRTY2(cb->i, bitID);
+ }
+ /* texcoords */
+ for (i = 0; (unsigned int)i < toCtx->limits.maxTextureUnits; i++) {
+ if (CHECKDIRTY(cb->t[i], 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,
+ to->array.t[i].stride, to->array.t[i].p);
+ 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;
+ }
+ CLEARDIRTY2(cb->t[i], 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;
+ from->array.e.buffer = to->array.e.buffer;
+ }
+ CLEARDIRTY2(cb->e, bitID);
+ }
+ /* secondary color */
+ if (CHECKDIRTY(cb->s, 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;
+ 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;
+ }
+ CLEARDIRTY2(cb->s, bitID);
+ }
+ /* fog coord */
+ 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;
+ from->array.f.stride = to->array.f.stride;
+ from->array.f.p = to->array.f.p;
+ from->array.f.buffer = to->array.f.buffer;
+ }
+ CLEARDIRTY2(cb->f, bitID);
+ }
+#if defined(CR_NV_vertex_program) || defined(CR_ARB_vertex_program)
+ /* vertex attributes */
+ for (i = 0; (unsigned int)i < toCtx->limits.maxVertexProgramAttribs; i++) {
+ if (CHECKDIRTY(cb->a[i], bitID)) {
+ if (from->array.a[i].size != to->array.a[i].size ||
+ 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,
+ to->array.a[i].stride,
+ to->array.a[i].p);
+ from->array.a[i].size = to->array.a[i].size;
+ 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;
+ }
+ CLEARDIRTY2(cb->a[i], 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.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;
+ }
+ if (from->array.n.enabled != to->array.n.enabled) {
+ able[to->array.n.enabled](GL_NORMAL_ARRAY);
+ from->array.n.enabled = to->array.n.enabled;
+ }
+ if (from->array.c.enabled != to->array.c.enabled) {
+ able[to->array.c.enabled](GL_COLOR_ARRAY);
+ from->array.c.enabled = to->array.c.enabled;
+ }
+ if (from->array.i.enabled != to->array.i.enabled) {
+ able[to->array.i.enabled](GL_INDEX_ARRAY);
+ from->array.i.enabled = to->array.i.enabled;
+ }
+ for (i = 0; (unsigned int)i < toCtx->limits.maxTextureUnits; i++) {
+ if (from->array.t[i].enabled != to->array.t[i].enabled) {
+ diff_api.ClientActiveTextureARB(GL_TEXTURE0_ARB + i);
+ curClientTextureUnit = i;
+ able[to->array.t[i].enabled](GL_TEXTURE_COORD_ARRAY);
+ from->array.t[i].enabled = to->array.t[i].enabled;
+ }
+ }
+ if (from->array.e.enabled != to->array.e.enabled) {
+ able[to->array.e.enabled](GL_EDGE_FLAG_ARRAY);
+ from->array.e.enabled = to->array.e.enabled;
+ }
+ if (from->array.s.enabled != to->array.s.enabled) {
+ able[to->array.s.enabled](GL_SECONDARY_COLOR_ARRAY_EXT);
+ from->array.s.enabled = to->array.s.enabled;
+ }
+ if (from->array.f.enabled != to->array.f.enabled) {
+ able[to->array.f.enabled](GL_FOG_COORDINATE_ARRAY_EXT);
+ from->array.f.enabled = to->array.f.enabled;
+ }
+ for (i = 0; (unsigned int)i < toCtx->limits.maxVertexProgramAttribs; i++) {
+ if (from->array.a[i].enabled != to->array.a[i].enabled) {
+ if (to->array.a[i].enabled)
+ diff_api.EnableVertexAttribArrayARB(i);
+ else
+ diff_api.DisableVertexAttribArrayARB(i);
+ from->array.a[i].enabled = to->array.a[i].enabled;
+ }
+ }
+ CLEARDIRTY2(cb->enableClientState, bitID);
+ }
+
+ if (to->curClientTextureUnit != curClientTextureUnit)
+ {
+ diff_api.ClientActiveTextureARB(GL_TEXTURE0_ARB + to->curClientTextureUnit);
+ }
+}
+
+
+void
+crStateClientSwitch(CRClientBits *cb, CRbitvalue *bitID,
+ CRContext *fromCtx, CRContext *toCtx)
+{
+ const CRClientState *from = &(fromCtx->client);
+ 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 */
+ if (CHECKDIRTY(cb->v, 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);
+ FILLDIRTY(cb->clientPointer);
+ FILLDIRTY(cb->dirty);
+ }
+ CLEARDIRTY2(cb->v, bitID);
+ }
+ /* normal */
+ 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);
+ FILLDIRTY(cb->clientPointer);
+ FILLDIRTY(cb->dirty);
+ }
+ CLEARDIRTY2(cb->n, bitID);
+ }
+ /* color */
+ if (CHECKDIRTY(cb->c, 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);
+ FILLDIRTY(cb->clientPointer);
+ FILLDIRTY(cb->dirty);
+ }
+ CLEARDIRTY2(cb->c, bitID);
+ }
+ /* index */
+ 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);
+ FILLDIRTY(cb->dirty);
+ FILLDIRTY(cb->clientPointer);
+ }
+ CLEARDIRTY2(cb->i, bitID);
+ }
+ /* texcoords */
+ for (i = 0; (unsigned int)i < toCtx->limits.maxTextureUnits; i++) {
+ if (CHECKDIRTY(cb->t[i], 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,
+ to->array.t[i].stride, to->array.t[i].p);
+ FILLDIRTY(cb->t[i]);
+ FILLDIRTY(cb->clientPointer);
+ FILLDIRTY(cb->dirty);
+ }
+ CLEARDIRTY2(cb->t[i], 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);
+ FILLDIRTY(cb->dirty);
+ }
+ CLEARDIRTY2(cb->e, bitID);
+ }
+ /* secondary color */
+ if (CHECKDIRTY(cb->s, 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);
+ FILLDIRTY(cb->clientPointer);
+ FILLDIRTY(cb->dirty);
+ }
+ CLEARDIRTY2(cb->s, bitID);
+ }
+ /* fog coord */
+ 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);
+ FILLDIRTY(cb->clientPointer);
+ FILLDIRTY(cb->dirty);
+ }
+ CLEARDIRTY2(cb->f, bitID);
+ }
+#if defined(CR_NV_vertex_program) || defined(CR_ARB_vertex_program)
+ /* vertex attributes */
+ for (i = 0; (unsigned int)i < toCtx->limits.maxVertexProgramAttribs; i++) {
+ if (CHECKDIRTY(cb->a[i], bitID)) {
+ if (from->array.a[i].size != to->array.a[i].size ||
+ 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,
+ to->array.a[i].stride,
+ to->array.a[i].p);
+ FILLDIRTY(cb->a[i]);
+ FILLDIRTY(cb->clientPointer);
+ FILLDIRTY(cb->dirty);
+ }
+ CLEARDIRTY2(cb->a[i], 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.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);
+ FILLDIRTY(cb->dirty);
+ }
+ if (from->array.n.enabled != to->array.n.enabled) {
+ able[to->array.n.enabled](GL_NORMAL_ARRAY);
+ FILLDIRTY(cb->enableClientState);
+ FILLDIRTY(cb->dirty);
+ }
+ if (from->array.c.enabled != to->array.c.enabled) {
+ able[to->array.c.enabled](GL_COLOR_ARRAY);
+ FILLDIRTY(cb->enableClientState);
+ FILLDIRTY(cb->dirty);
+ }
+ if (from->array.i.enabled != to->array.i.enabled) {
+ able[to->array.i.enabled](GL_INDEX_ARRAY);
+ FILLDIRTY(cb->enableClientState);
+ FILLDIRTY(cb->dirty);
+ }
+ for (i = 0; (unsigned int)i < toCtx->limits.maxTextureUnits; i++) {
+ if (from->array.t[i].enabled != to->array.t[i].enabled) {
+ diff_api.ClientActiveTextureARB(GL_TEXTURE0_ARB + i);
+ curClientTextureUnit = i;
+ able[to->array.t[i].enabled](GL_TEXTURE_COORD_ARRAY);
+ FILLDIRTY(cb->enableClientState);
+ FILLDIRTY(cb->dirty);
+ }
+ }
+ if (from->array.e.enabled != to->array.e.enabled) {
+ able[to->array.e.enabled](GL_EDGE_FLAG_ARRAY);
+ FILLDIRTY(cb->enableClientState);
+ FILLDIRTY(cb->dirty);
+ }
+ if (from->array.s.enabled != to->array.s.enabled) {
+ able[to->array.s.enabled](GL_SECONDARY_COLOR_ARRAY_EXT);
+ FILLDIRTY(cb->enableClientState);
+ FILLDIRTY(cb->dirty);
+ }
+ if (from->array.f.enabled != to->array.f.enabled) {
+ able[to->array.f.enabled](GL_FOG_COORDINATE_ARRAY_EXT);
+ FILLDIRTY(cb->enableClientState);
+ FILLDIRTY(cb->dirty);
+ }
+ for (i = 0; (unsigned int)i < toCtx->limits.maxVertexProgramAttribs; i++) {
+ if (from->array.a[i].enabled != to->array.a[i].enabled) {
+ if (to->array.a[i].enabled)
+ diff_api.EnableVertexAttribArrayARB(i);
+ else
+ diff_api.DisableVertexAttribArrayARB(i);
+ FILLDIRTY(cb->enableClientState);
+ FILLDIRTY(cb->dirty);
+ }
+ }
+ CLEARDIRTY2(cb->enableClientState, bitID);
+ }
+
+ if (to->curClientTextureUnit != curClientTextureUnit)
+ {
+ diff_api.ClientActiveTextureARB(GL_TEXTURE0_ARB + to->curClientTextureUnit);
+ }
+
+ if (CHECKDIRTY(cb->unpack, bitID))
+ {
+ if (from->unpack.rowLength != to->unpack.rowLength)
+ {
+ diff_api.PixelStorei(GL_UNPACK_ROW_LENGTH, to->unpack.rowLength);
+ FILLDIRTY(cb->unpack);
+ FILLDIRTY(cb->dirty);
+ }
+ if (from->unpack.skipRows != to->unpack.skipRows)
+ {
+ diff_api.PixelStorei(GL_UNPACK_SKIP_ROWS, to->unpack.skipRows);
+ FILLDIRTY(cb->unpack);
+ FILLDIRTY(cb->dirty);
+ }
+ if (from->unpack.skipPixels != to->unpack.skipPixels)
+ {
+ diff_api.PixelStorei(GL_UNPACK_SKIP_PIXELS, to->unpack.skipPixels);
+ FILLDIRTY(cb->unpack);
+ FILLDIRTY(cb->dirty);
+ }
+ if (from->unpack.alignment != to->unpack.alignment)
+ {
+ diff_api.PixelStorei(GL_UNPACK_ALIGNMENT, to->unpack.alignment);
+ FILLDIRTY(cb->unpack);
+ FILLDIRTY(cb->dirty);
+ }
+ if (from->unpack.imageHeight != to->unpack.imageHeight)
+ {
+ diff_api.PixelStorei(GL_UNPACK_IMAGE_HEIGHT, to->unpack.imageHeight);
+ FILLDIRTY(cb->unpack);
+ FILLDIRTY(cb->dirty);
+ }
+ if (from->unpack.skipImages != to->unpack.skipImages)
+ {
+ diff_api.PixelStorei(GL_UNPACK_SKIP_IMAGES, to->unpack.skipImages);
+ FILLDIRTY(cb->unpack);
+ FILLDIRTY(cb->dirty);
+ }
+ if (from->unpack.swapBytes != to->unpack.swapBytes)
+ {
+ diff_api.PixelStorei(GL_UNPACK_SWAP_BYTES, to->unpack.swapBytes);
+ FILLDIRTY(cb->unpack);
+ FILLDIRTY(cb->dirty);
+ }
+ if (from->unpack.psLSBFirst != to->unpack.psLSBFirst)
+ {
+ diff_api.PixelStorei(GL_UNPACK_LSB_FIRST, to->unpack.psLSBFirst);
+ FILLDIRTY(cb->unpack);
+ FILLDIRTY(cb->dirty);
+ }
+ CLEARDIRTY2(cb->unpack, bitID);
+ }
+
+ if (CHECKDIRTY(cb->pack, bitID))
+ {
+ if (from->pack.rowLength != to->pack.rowLength)
+ {
+ diff_api.PixelStorei(GL_PACK_ROW_LENGTH, to->pack.rowLength);
+ FILLDIRTY(cb->pack);
+ FILLDIRTY(cb->dirty);
+ }
+ if (from->pack.skipRows != to->pack.skipRows)
+ {
+ diff_api.PixelStorei(GL_PACK_SKIP_ROWS, to->pack.skipRows);
+ FILLDIRTY(cb->pack);
+ FILLDIRTY(cb->dirty);
+ }
+ if (from->pack.skipPixels != to->pack.skipPixels)
+ {
+ diff_api.PixelStorei(GL_PACK_SKIP_PIXELS, to->pack.skipPixels);
+ FILLDIRTY(cb->pack);
+ FILLDIRTY(cb->dirty);
+ }
+ if (from->pack.alignment != to->pack.alignment)
+ {
+ diff_api.PixelStorei(GL_PACK_ALIGNMENT, to->pack.alignment);
+ FILLDIRTY(cb->pack);
+ FILLDIRTY(cb->dirty);
+ }
+ if (from->pack.imageHeight != to->pack.imageHeight)
+ {
+ diff_api.PixelStorei(GL_PACK_IMAGE_HEIGHT, to->pack.imageHeight);
+ FILLDIRTY(cb->pack);
+ FILLDIRTY(cb->dirty);
+ }
+ if (from->pack.skipImages != to->pack.skipImages)
+ {
+ diff_api.PixelStorei(GL_PACK_SKIP_IMAGES, to->pack.skipImages);
+ FILLDIRTY(cb->pack);
+ FILLDIRTY(cb->dirty);
+ }
+ if (from->pack.swapBytes != to->pack.swapBytes)
+ {
+ diff_api.PixelStorei(GL_PACK_SWAP_BYTES, to->pack.swapBytes);
+ FILLDIRTY(cb->pack);
+ FILLDIRTY(cb->dirty);
+ }
+ if (from->pack.psLSBFirst != to->pack.psLSBFirst)
+ {
+ diff_api.PixelStorei(GL_PACK_LSB_FIRST, to->pack.psLSBFirst);
+ FILLDIRTY(cb->pack);
+ FILLDIRTY(cb->dirty);
+ }
+ CLEARDIRTY2(cb->pack, bitID);
+ }
+
+ CLEARDIRTY2(cb->dirty, bitID);
+}
+
+CRClientPointer* crStateGetClientPointerByIndex(int index, CRVertexArrays *array)
+{
+ CRASSERT(array && index>=0 && index<CRSTATECLIENT_MAX_VERTEXARRAYS);
+
+ if (array == NULL || index < 0 || index >= CRSTATECLIENT_MAX_VERTEXARRAYS)
+ {
+ return NULL;
+ }
+
+ if (index < 7)
+ {
+ switch (index)
+ {
+ case 0: return &array->v;
+ case 1: return &array->c;
+ case 2: return &array->f;
+ case 3: return &array->s;
+ case 4: return &array->e;
+ case 5: return &array->i;
+ case 6: return &array->n;
+ }
+ }
+ else if (index<(7+CR_MAX_TEXTURE_UNITS))
+ {
+ return &array->t[index-7];
+ }
+ else
+ {
+ return &array->a[index-7-CR_MAX_TEXTURE_UNITS];
+ }
+
+ /*silence the compiler warning*/
+ CRASSERT(false);
+ return NULL;
+}
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_client.txt b/src/VBox/GuestHost/OpenGL/state_tracker/state_client.txt
new file mode 100644
index 00000000..bdf7a729
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_client.txt
@@ -0,0 +1,32 @@
+# Copyright (c) 2001, Stanford University
+# All rights reserved.
+#
+# See the file LICENSE.txt for information on redistributing this software.
+:unpack:unpack.rowLength:PixelStorei,GL_UNPACK_ROW_LENGTH
+#:unpack:unpack.skipImages:PixelStorei,GL_UNPACK_SKIP_IMAGES
+:unpack:unpack.skipRows:PixelStorei,GL_UNPACK_SKIP_ROWS
+:unpack:unpack.skipPixels:PixelStorei,GL_UNPACK_SKIP_PIXELS
+#:unpack:unpack.imageHeight:PixelStorei,GL_UNPACK_IMAGE_HEIGHT
+:pack:pack.rowLength:PixelStorei,GL_PACK_ROW_LENGTH
+#:pack:pack.skipImages:PixelStorei,GL_PACK_SKIP_IMAGES
+:pack:pack.skipRows:PixelStorei,GL_PACK_SKIP_ROWS
+:pack:pack.skipPixels:PixelStorei,GL_PACK_SKIP_PIXELS
+#:pack:pack.imageHeight:PixelStorei,GL_PACK_IMAGE_HEIGHT
+#:clientPointer:v.size,v.type,v.stride,v.p:VertexPointer
+#:clientPointer:c.size,c.type,c.stride,c.p:ColorPointer
+#:clientPointer:s.size,s.type,s.stride,s.p:SecondaryColorPointerEXT
+#:clientPointer:i.type,i.stride,i.p:IndexPointer
+#:clientPointer:n.type,n.stride,n.p:NormalPointer
+#:clientPointer:t.size,t.type,t.stride,t.p:TexCoordPointer
+#:clientPointer:e.stride,e.p:EdgeFlagPointer
+#:enableClientState:*glAble able[2];
+#:enableClientState:*able[0] = diff_api.DisableClientState;
+#:enableClientState:*able[1] = diff_api.EnableClientState;
+#:enableClientState:v.enabled:*able[to->v.enabled](GL_VERTEX_ARRAY);
+#:enableClientState:c.enabled:*able[to->c.enabled](GL_COLOR_ARRAY);
+#:enableClientState:i.enabled:*able[to->i.enabled](GL_INDEX_ARRAY);
+#:enableClientState:n.enabled:*able[to->n.enabled](GL_NORMAL_ARRAY);
+#:enableClientState:t.enabled:*able[to->t.enabled](GL_TEXTURE_COORD_ARRAY);
+#:enableClientState:e.enabled:*able[to->e.enabled](GL_EDGE_FLAG_ARRAY);
+#:enableClientState:s.enabled:*able[to->s.enabled](GL_SECONDARY_COLOR_ARRAY_EXT);
+#+:element:*crError( "element in client state DiffContext!" ); /* __glclient_SendUpdates(b, bitID, from, to); */
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_current.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_current.c
new file mode 100644
index 00000000..511f997d
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_current.c
@@ -0,0 +1,435 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#include "cr_mem.h"
+#include "state.h"
+#include "state_internals.h"
+
+/*
+ * Note: regardless of GL_NV_vertex_program, we store all per-vertex
+ * attributes in an array now, instead of specially named attributes
+ * like color, normal, texcoord, etc.
+ */
+
+
+void crStateCurrentInit( CRContext *ctx )
+{
+ CRCurrentState *c = &ctx->current;
+ CRStateBits *sb = GetCurrentBits();
+ CRCurrentBits *cb = &(sb->current);
+ static const GLfloat default_normal[4] = {0.0f, 0.0f, 1.0f, 1.0f};
+ static const GLfloat default_color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+ static const GLfloat default_secondaryColor[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ static const GLfloat default_attrib[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ unsigned int i;
+
+ /*
+ * initialize all vertex attributes to <0,0,0,1> for starters
+ */
+ for (i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++) {
+ COPY_4V(c->vertexAttrib[i], default_attrib);
+ COPY_4V(c->vertexAttribPre[i], default_attrib);
+ }
+ /* now re-do the exceptions */
+ COPY_4V(c->vertexAttrib[VERT_ATTRIB_COLOR0], default_color);
+ COPY_4V(c->vertexAttrib[VERT_ATTRIB_COLOR1], default_secondaryColor);
+ COPY_4V(c->vertexAttrib[VERT_ATTRIB_NORMAL], default_normal);
+
+ c->rasterIndex = 1.0f;
+ c->colorIndex = c->colorIndexPre = 1.0;
+ c->edgeFlag = c->edgeFlagPre = GL_TRUE;
+
+ /* Set the "pre" values and raster position attributes */
+ for (i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++) {
+ COPY_4V(c->vertexAttribPre[i], c->vertexAttrib[i]);
+ COPY_4V(c->rasterAttrib[i], c->vertexAttrib[i]);
+ COPY_4V(c->rasterAttribPre[i], c->vertexAttrib[i]);
+ }
+
+ c->rasterValid = GL_TRUE;
+
+ c->inBeginEnd = GL_FALSE;
+ c->beginEndNum = 0;
+ /*c->beginEndMax = cfg->beginend_max;*/
+ c->mode = 0x10; /* Undefined Mode */
+ c->flushOnEnd = 0;
+
+ c->current = 0; /* picked up by crStateSetCurrentPointers() */
+
+ /* init dirty bits */
+ RESET(cb->dirty, ctx->bitid);
+ for (i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++) {
+ RESET(cb->vertexAttrib[i], ctx->bitid);
+ }
+ RESET(cb->edgeFlag, ctx->bitid);
+ RESET(cb->colorIndex, ctx->bitid);
+ RESET(cb->rasterPos, ctx->bitid);
+}
+
+void STATE_APIENTRY crStateColor3f( GLfloat r, GLfloat g, GLfloat b )
+{
+ crStateColor4f(r, g, b, 1.0F);
+}
+
+void STATE_APIENTRY crStateColor3fv( const GLfloat *color )
+{
+ crStateColor4f( color[0], color[1], color[2], 1.0F );
+}
+
+void STATE_APIENTRY crStateColor4f( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha )
+{
+ CRContext *g = GetCurrentContext();
+ CRCurrentState *c = &(g->current);
+ CRStateBits *sb = GetCurrentBits();
+ CRCurrentBits *cb = &(sb->current);
+
+ FLUSH();
+
+ c->vertexAttrib[VERT_ATTRIB_COLOR0][0] = red;
+ c->vertexAttrib[VERT_ATTRIB_COLOR0][1] = green;
+ c->vertexAttrib[VERT_ATTRIB_COLOR0][2] = blue;
+ c->vertexAttrib[VERT_ATTRIB_COLOR0][3] = alpha;
+
+ DIRTY(cb->dirty, g->neg_bitid);
+ DIRTY(cb->vertexAttrib[VERT_ATTRIB_COLOR0], g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateColor4fv( const GLfloat *color )
+{
+ crStateColor4f( color[0], color[1], color[2], color[3] );
+}
+
+void crStateSetCurrentPointers( CRContext *ctx, CRCurrentStatePointers *current )
+{
+ CRCurrentState *c = &(ctx->current);
+ c->current = current;
+}
+
+void crStateResetCurrentPointers( CRCurrentStatePointers *current )
+{
+ uint32_t attribsUsedMask = current->attribsUsedMask;
+
+ crMemset(current, 0, sizeof (*current));
+
+ current->attribsUsedMask = attribsUsedMask;
+}
+
+void STATE_APIENTRY crStateBegin( GLenum mode )
+{
+ CRContext *g = GetCurrentContext();
+ CRCurrentState *c = &(g->current);
+
+ if (mode > GL_POLYGON)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Begin called with invalid mode: %d", mode);
+ return;
+ }
+
+ if (c->inBeginEnd)
+ {
+ crStateError( __LINE__, __FILE__, GL_INVALID_OPERATION, "glBegin called inside Begin/End");
+ return;
+ }
+
+ c->attribsUsedMask = 0;
+ c->inBeginEnd = GL_TRUE;
+ c->mode = mode;
+ c->beginEndNum++;
+}
+
+void STATE_APIENTRY crStateEnd( void )
+{
+ CRContext *g = GetCurrentContext();
+ CRCurrentState *c = &(g->current);
+
+ if (!c->inBeginEnd)
+ {
+ crStateError( __LINE__, __FILE__, GL_INVALID_OPERATION, "glEnd called outside Begin/End" );
+ return;
+ }
+
+ c->inBeginEnd = GL_FALSE;
+}
+
+void crStateCurrentSwitch( CRCurrentBits *c, CRbitvalue *bitID,
+ CRContext *fromCtx, CRContext *toCtx )
+{
+ const CRCurrentState *from = &(fromCtx->current);
+ const CRCurrentState *to = &(toCtx->current);
+ const GLuint maxTextureUnits = fromCtx->limits.maxTextureUnits;
+ unsigned int i, j;
+ CRbitvalue nbitID[CR_MAX_BITARRAY];
+
+ for (j=0;j<CR_MAX_BITARRAY;j++)
+ nbitID[j] = ~bitID[j];
+
+ if (CHECKDIRTY(c->rasterPos, bitID)) {
+ if (to->rasterValid) {
+ const GLfloat fromX = from->rasterAttrib[VERT_ATTRIB_POS][0];
+ const GLfloat fromY = from->rasterAttrib[VERT_ATTRIB_POS][1];
+ const GLfloat fromZ = from->rasterAttrib[VERT_ATTRIB_POS][2];
+ const GLfloat toX = to->rasterAttrib[VERT_ATTRIB_POS][0];
+ const GLfloat toY = to->rasterAttrib[VERT_ATTRIB_POS][1];
+ const GLfloat toZ = to->rasterAttrib[VERT_ATTRIB_POS][2];
+ if (toX != fromX || toY != fromY || toZ != fromZ) {
+ /* Use glWindowPos (which updates raster color) */
+ diff_api.WindowPos3fvARB(to->rasterAttrib[VERT_ATTRIB_POS]);
+ FILLDIRTY(c->rasterPos);
+ FILLDIRTY(c->dirty);
+ }
+ }
+ CLEARDIRTY(c->rasterPos, nbitID);
+ }
+
+ /* Vertex Current State Switch Code */
+
+ /* Its important that we don't do a value check here because
+ ** current may not actually have the correct values, I think...
+ ** We also need to restore the current state tracking pointer
+ ** since the packing functions will set it.
+ */
+
+ if (CHECKDIRTY(c->colorIndex, bitID)) {
+ if (to->colorIndex != from->colorIndex) {
+ diff_api.Indexf(to->colorIndex);
+ FILLDIRTY(c->colorIndex);
+ FILLDIRTY(c->dirty);
+ }
+ CLEARDIRTY(c->colorIndex, nbitID);
+ }
+
+ if (CHECKDIRTY(c->edgeFlag, bitID)) {
+ if (to->edgeFlag != from->edgeFlag) {
+ diff_api.EdgeFlag(to->edgeFlag);
+ FILLDIRTY(c->edgeFlag);
+ FILLDIRTY(c->dirty);
+ }
+ CLEARDIRTY(c->edgeFlag, nbitID);
+ }
+
+ /* If using a vertex program, update the generic vertex attributes,
+ * which may or may not be aliased with conventional attributes.
+ */
+#if defined(CR_ARB_vertex_program) || defined(CR_NV_vertex_progra)
+ if (toCtx->program.vpEnabled &&
+ (toCtx->extensions.ARB_vertex_program ||
+ (toCtx->extensions.NV_vertex_program))) {
+ const unsigned attribsUsedMask = toCtx->current.attribsUsedMask;
+ for (i = 1; i < CR_MAX_VERTEX_ATTRIBS; i++) { /* skip zero */
+ if ((attribsUsedMask & (1 << i))
+ && CHECKDIRTY(c->vertexAttrib[i], bitID)) {
+ if (COMPARE_VECTOR (from->vertexAttrib[i], to->vertexAttribPre[i])) {
+ diff_api.VertexAttrib4fvARB(i, &(to->vertexAttrib[i][0]));
+ FILLDIRTY(c->vertexAttrib[i]);
+ FILLDIRTY(c->dirty);
+ }
+ CLEARDIRTY(c->vertexAttrib[i], nbitID);
+ }
+ }
+ }
+ /* Fall-through so that attributes which don't have their bit set in the
+ * attribsUsedMask get handled via the conventional attribute functions.
+ */
+#endif
+
+ {
+ /* use conventional attribute functions */
+
+ /* NEED TO FIX THIS!!!!!! */
+ if (CHECKDIRTY(c->vertexAttrib[VERT_ATTRIB_COLOR0], bitID)) {
+ if (COMPARE_COLOR(from->vertexAttrib[VERT_ATTRIB_COLOR0],to->vertexAttrib[VERT_ATTRIB_COLOR0])) {
+ diff_api.Color4fv ((GLfloat *) &(to->vertexAttrib[VERT_ATTRIB_COLOR0]));
+ FILLDIRTY(c->vertexAttrib[VERT_ATTRIB_COLOR0]);
+ FILLDIRTY(c->dirty);
+ }
+ CLEARDIRTY(c->vertexAttrib[VERT_ATTRIB_COLOR0], nbitID);
+ }
+
+ /* NEED TO FIX THIS, ALSO?!!!!! */
+#ifdef CR_EXT_secondary_color
+ if (CHECKDIRTY(c->vertexAttrib[VERT_ATTRIB_COLOR1], bitID)) {
+ if (COMPARE_COLOR(from->vertexAttrib[VERT_ATTRIB_COLOR1],to->vertexAttrib[VERT_ATTRIB_COLOR1])) {
+ diff_api.SecondaryColor3fvEXT ((GLfloat *) &(to->vertexAttrib[VERT_ATTRIB_COLOR1]));
+ FILLDIRTY(c->vertexAttrib[VERT_ATTRIB_COLOR1]);
+ FILLDIRTY(c->dirty);
+ }
+ CLEARDIRTY(c->vertexAttrib[VERT_ATTRIB_COLOR1], nbitID);
+ }
+#endif
+
+ /* NEED TO FIX THIS, ALSO?!!!!! */
+#ifdef CR_EXT_fog_coord
+ if (CHECKDIRTY(c->vertexAttrib[VERT_ATTRIB_FOG], bitID)) {
+ if (from->vertexAttrib[VERT_ATTRIB_FOG][0] != to->vertexAttrib[VERT_ATTRIB_FOG][0] ) {
+ diff_api.FogCoordfvEXT ((GLfloat *) &(to->vertexAttrib[VERT_ATTRIB_FOG][0] ));
+ FILLDIRTY(c->vertexAttrib[VERT_ATTRIB_FOG]);
+ FILLDIRTY(c->dirty);
+ }
+ CLEARDIRTY(c->vertexAttrib[VERT_ATTRIB_FOG], nbitID);
+ }
+#endif
+
+ if (CHECKDIRTY(c->vertexAttrib[VERT_ATTRIB_NORMAL], bitID)) {
+ if (COMPARE_VECTOR (from->vertexAttrib[VERT_ATTRIB_NORMAL], to->vertexAttrib[VERT_ATTRIB_NORMAL])) {
+ diff_api.Normal3fv ((GLfloat *) &(to->vertexAttrib[VERT_ATTRIB_NORMAL][0]));
+ FILLDIRTY(c->vertexAttrib[VERT_ATTRIB_NORMAL]);
+ FILLDIRTY(c->dirty);
+ }
+ CLEARDIRTY(c->vertexAttrib[VERT_ATTRIB_NORMAL], nbitID);
+ }
+
+ for (i = 0; i < maxTextureUnits; i++) {
+ if (CHECKDIRTY(c->vertexAttrib[VERT_ATTRIB_TEX0 + i], bitID)) {
+ if (COMPARE_TEXCOORD (from->vertexAttrib[VERT_ATTRIB_TEX0 + i], to->vertexAttribPre[VERT_ATTRIB_TEX0 + i])) {
+ diff_api.MultiTexCoord4fvARB (i+GL_TEXTURE0_ARB, (GLfloat *) &(to->vertexAttrib[VERT_ATTRIB_TEX0+ i][0]));
+ FILLDIRTY(c->vertexAttrib[VERT_ATTRIB_TEX0 + i]);
+ FILLDIRTY(c->dirty);
+ }
+ CLEARDIRTY(c->vertexAttrib[VERT_ATTRIB_TEX0 + i], nbitID);
+ }
+ }
+ }
+
+ CLEARDIRTY(c->dirty, nbitID);
+}
+
+void
+crStateCurrentDiff( CRCurrentBits *c, CRbitvalue *bitID,
+ CRContext *fromCtx, CRContext *toCtx )
+{
+ CRCurrentState *from = &(fromCtx->current);
+ const CRCurrentState *to = &(toCtx->current);
+ unsigned int i, j;
+ CRbitvalue nbitID[CR_MAX_BITARRAY];
+
+ for (j=0;j<CR_MAX_BITARRAY;j++)
+ nbitID[j] = ~bitID[j];
+
+ if (CHECKDIRTY(c->rasterPos, bitID)) {
+ from->rasterValid = to->rasterValid;
+ if (to->rasterValid) {
+ const GLfloat fromX = from->rasterAttrib[VERT_ATTRIB_POS][0];
+ const GLfloat fromY = from->rasterAttrib[VERT_ATTRIB_POS][1];
+ const GLfloat fromZ = from->rasterAttrib[VERT_ATTRIB_POS][2];
+ const GLfloat toX = to->rasterAttrib[VERT_ATTRIB_POS][0];
+ const GLfloat toY = to->rasterAttrib[VERT_ATTRIB_POS][1];
+ const GLfloat toZ = to->rasterAttrib[VERT_ATTRIB_POS][2];
+ if (toX != fromX || toY != fromY || toZ != fromZ) {
+ /* Use glWindowPos (which updates raster color) */
+ diff_api.WindowPos3fvARB(to->rasterAttrib[VERT_ATTRIB_POS]);
+ from->rasterAttrib[VERT_ATTRIB_POS][0] = toX;
+ from->rasterAttrib[VERT_ATTRIB_POS][1] = toY;
+ from->rasterAttrib[VERT_ATTRIB_POS][2] = toZ;
+ }
+ }
+ CLEARDIRTY(c->rasterPos, nbitID);
+ }
+
+ /* Vertex Current State Sync Code */
+ /* Some things to note here:
+ ** 1) Compare is done against the pre value since the
+ ** current value includes the geometry info.
+ ** 2) Update is done with the current value since
+ ** the server will be getting the geometry block
+ ** 3) Copy is done outside of the compare to ensure
+ ** that it happens.
+ */
+
+ /* edge flag */
+ if (CHECKDIRTY(c->edgeFlag, bitID)) {
+ if (from->edgeFlag != to->edgeFlagPre) {
+ diff_api.EdgeFlag (to->edgeFlagPre);
+ }
+ from->edgeFlag = to->edgeFlag;
+ CLEARDIRTY(c->edgeFlag, nbitID);
+ }
+
+ /* color index */
+ if (CHECKDIRTY(c->colorIndex, bitID)) {
+ if (from->colorIndex != to->colorIndexPre) {
+ diff_api.Indexf (to->colorIndex);
+ }
+ from->colorIndex = to->colorIndex;
+ CLEARDIRTY(c->colorIndex, nbitID);
+ }
+
+
+ /* If using a vertex program, update the generic vertex attributes,
+ * which may or may not be aliased with conventional attributes.
+ */
+#if defined(CR_ARB_vertex_program) || defined(CR_NV_vertex_progra)
+ if (toCtx->program.vpEnabled &&
+ (toCtx->extensions.ARB_vertex_program ||
+ (toCtx->extensions.NV_vertex_program))) {
+ const unsigned attribsUsedMask = toCtx->current.attribsUsedMask;
+ for (i = 1; i < CR_MAX_VERTEX_ATTRIBS; i++) { /* skip zero */
+ if ((attribsUsedMask & (1 << i))
+ && CHECKDIRTY(c->vertexAttrib[i], bitID)) {
+ if (COMPARE_VECTOR (from->vertexAttrib[i], to->vertexAttribPre[i])) {
+ diff_api.VertexAttrib4fvARB(i, &(to->vertexAttribPre[i][0]));
+ }
+ COPY_4V(from->vertexAttrib[i] , to->vertexAttrib[i]);
+ CLEARDIRTY(c->vertexAttrib[i], nbitID);
+ }
+ }
+ }
+ /* Fall-through so that attributes which don't have their bit set in the
+ * attribsUsedMask get handled via the conventional attribute functions.
+ */
+#endif
+
+ {
+ /* use conventional attribute functions */
+ if (CHECKDIRTY(c->vertexAttrib[VERT_ATTRIB_COLOR0], bitID)) {
+ if (COMPARE_COLOR(from->vertexAttrib[VERT_ATTRIB_COLOR0],to->vertexAttribPre[VERT_ATTRIB_COLOR0])) {
+ diff_api.Color4fv ((GLfloat *) &(to->vertexAttribPre[VERT_ATTRIB_COLOR0]));
+ }
+ COPY_4V(from->vertexAttrib[VERT_ATTRIB_COLOR0] , to->vertexAttrib[VERT_ATTRIB_COLOR0]);
+ CLEARDIRTY(c->vertexAttrib[VERT_ATTRIB_COLOR0], nbitID);
+ }
+
+#ifdef CR_EXT_secondary_color
+ if (CHECKDIRTY(c->vertexAttrib[VERT_ATTRIB_COLOR1], bitID)) {
+ if (COMPARE_COLOR(from->vertexAttrib[VERT_ATTRIB_COLOR1],to->vertexAttribPre[VERT_ATTRIB_COLOR1])) {
+ diff_api.SecondaryColor3fvEXT ((GLfloat *) &(to->vertexAttribPre[VERT_ATTRIB_COLOR1]));
+ }
+ COPY_4V(from->vertexAttrib[VERT_ATTRIB_COLOR1] , to->vertexAttrib[VERT_ATTRIB_COLOR1]);
+ CLEARDIRTY(c->vertexAttrib[VERT_ATTRIB_COLOR1], nbitID);
+ }
+#endif
+
+#ifdef CR_EXT_fog_coord
+ if (CHECKDIRTY(c->vertexAttrib[VERT_ATTRIB_FOG], bitID)) {
+ if (from->vertexAttrib[VERT_ATTRIB_FOG] != to->vertexAttribPre[VERT_ATTRIB_FOG]) {
+ diff_api.FogCoordfvEXT ((GLfloat *) &(to->vertexAttribPre[VERT_ATTRIB_FOG]));
+ }
+ COPY_4V(from->vertexAttrib[VERT_ATTRIB_FOG] , to->vertexAttrib[VERT_ATTRIB_FOG]);
+ CLEARDIRTY(c->vertexAttrib[VERT_ATTRIB_FOG], nbitID);
+ }
+#endif
+
+ if (CHECKDIRTY(c->vertexAttrib[VERT_ATTRIB_NORMAL], bitID)) {
+ if (COMPARE_VECTOR (from->vertexAttrib[VERT_ATTRIB_NORMAL], to->vertexAttribPre[VERT_ATTRIB_NORMAL])) {
+ diff_api.Normal3fv ((GLfloat *) &(to->vertexAttribPre[VERT_ATTRIB_NORMAL]));
+ }
+ COPY_4V(from->vertexAttrib[VERT_ATTRIB_NORMAL] , to->vertexAttrib[VERT_ATTRIB_NORMAL]);
+ CLEARDIRTY(c->vertexAttrib[VERT_ATTRIB_NORMAL], nbitID);
+ }
+
+ for ( i = 0 ; i < fromCtx->limits.maxTextureUnits ; i++)
+ {
+ if (CHECKDIRTY(c->vertexAttrib[VERT_ATTRIB_TEX0 + i], bitID)) {
+ if (COMPARE_TEXCOORD (from->vertexAttrib[VERT_ATTRIB_TEX0 + i], to->vertexAttribPre[VERT_ATTRIB_TEX0 + i])) {
+ diff_api.MultiTexCoord4fvARB (GL_TEXTURE0_ARB + i, (GLfloat *) &(to->vertexAttribPre[VERT_ATTRIB_TEX0 + i]));
+ }
+ COPY_4V(from->vertexAttrib[VERT_ATTRIB_TEX0 + i] , to->vertexAttrib[VERT_ATTRIB_TEX0 + i]);
+ CLEARDIRTY(c->vertexAttrib[VERT_ATTRIB_TEX0 + i], nbitID);
+ }
+ }
+ }
+
+ CLEARDIRTY(c->dirty, nbitID);
+}
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_current.py b/src/VBox/GuestHost/OpenGL/state_tracker/state_current.py
new file mode 100755
index 00000000..49a54aed
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_current.py
@@ -0,0 +1,485 @@
+# Copyright (c) 2001, Stanford University
+# All rights reserved.
+#
+# See the file LICENSE.txt for information on redistributing this software.
+
+from __future__ import print_function
+import sys
+
+from pack_currenttypes import *
+import apiutil
+
+apiutil.CopyrightC()
+
+print('''
+#include "state/cr_currentpointers.h"
+#include "state.h"
+
+#include <stdio.h>
+
+#ifdef WINDOWS
+#pragma warning( disable : 4127 )
+#endif
+
+typedef void (*convert_func) (GLfloat *, const unsigned char *);
+''')
+
+import convert
+
+for k in sorted(current_fns.keys()):
+ name = k
+ name = '%s%s' % (k[:1].lower(),k[1:])
+ ucname = k.upper()
+ num_members = len(current_fns[k]['default']) + 1
+
+ print('#define VPINCH_CONVERT_%s(op,data,dst) \\' % ucname)
+ print('{\\')
+ print('\tGLfloat vdata[%d] = {' % num_members, end=' ')
+
+## Copy dst data into vdata
+ i = 0;
+ for defaultvar in current_fns[k]['default']:
+ print('%d' % defaultvar, end=' ')
+ if i != num_members:
+ print(',', end=' ')
+ i += 1
+ print('};\\')
+
+ print('\tswitch (op) { \\')
+ for type in current_fns[k]['types']:
+ if type[0:1] == "N":
+ normalize = 1
+ type = type[1:]
+ else:
+ normalize = 0
+ for size in current_fns[k]['sizes']:
+ uctype = type.upper()
+ if ucname == 'EDGEFLAG':
+ print('\tcase CR_%s_OPCODE: \\' % ucname)
+ else:
+ print('\tcase CR_%s%d%s_OPCODE: \\' % (ucname,size,uctype))
+
+ if (ucname == 'COLOR' or ucname == 'NORMAL' or ucname == 'SECONDARYCOLOR' or normalize) and type != 'f' and type != 'd':
+ print('\t\t__convert_rescale_%s%d (vdata, (%s *) (data)); \\' % (type,size,gltypes[type]['type']))
+ else:
+ print('\t\t__convert_%s%d (vdata, (%s *) (data)); \\' % (type,size,gltypes[type]['type']))
+ print('\t\tbreak; \\')
+
+ print('\tdefault: \\')
+ print('\t\tcrSimpleError ( "Unknown opcode in VPINCH_CONVERT_%s" ); \\' % ucname)
+ print('\t}\\')
+
+ i = 0
+ for member in current_fns[k]['members']:
+ print('\t(dst).%s = vdata[%d];\\' % (member,i))
+ i += 1
+
+ print('}\n')
+
+print('''
+
+void crStateCurrentRecover( void )
+{
+ const unsigned char *v;
+ convert_func convert=NULL;
+ CRContext *g = GetCurrentContext();
+ CRCurrentState *c = &(g->current);
+ CRStateBits *sb = GetCurrentBits();
+ CRCurrentBits *cb = &(sb->current);
+ static const GLfloat color_default[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ static const GLfloat secondaryColor_default[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ static const GLfloat texCoord_default[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ static const GLfloat normal_default[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ static const GLfloat index_default = 0.0f;
+ static const GLboolean edgeFlag_default = GL_TRUE;
+ static const GLfloat vertexAttrib_default[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ static const GLfloat fogCoord_default = 0.0f;
+ GLnormal_p *normal = &(c->current->c.normal);
+ GLcolor_p *color = &(c->current->c.color);
+ GLsecondarycolor_p *secondaryColor = &(c->current->c.secondaryColor);
+ GLtexcoord_p *texCoord = &(c->current->c.texCoord);
+ GLindex_p *index = &(c->current->c.index);
+ GLedgeflag_p *edgeFlag = &(c->current->c.edgeFlag);
+ GLvertexattrib_p *vertexAttrib = &(c->current->c.vertexAttrib);
+ GLfogcoord_p *fogCoord = &(c->current->c.fogCoord);
+ unsigned int i;
+ CRbitvalue nbitID[CR_MAX_BITARRAY];
+
+ /*
+ * If the calling SPU hasn't called crStateSetCurrentPointers()
+ * we can't recover anything, so abort now. (i.e. we don't have
+ * a pincher, oh, and just emit the message once).
+ */
+ if (!c->current) {
+ static int donewarning = 0;
+ if (!donewarning)
+ crWarning("No pincher, please call crStateSetCurrentPointers() in your SPU");
+ donewarning = 1;
+ return; /* never get here */
+ }
+
+ c->attribsUsedMask = c->current->attribsUsedMask;
+
+ /* silence warnings */
+ (void) __convert_b1;
+ (void) __convert_b2;
+ (void) __convert_b3;
+ (void) __convert_b4;
+ (void) __convert_ui1;
+ (void) __convert_ui2;
+ (void) __convert_ui3;
+ (void) __convert_ui4;
+ (void) __convert_l1;
+ (void) __convert_l2;
+ (void) __convert_l3;
+ (void) __convert_l4;
+ (void) __convert_us1;
+ (void) __convert_us2;
+ (void) __convert_us3;
+ (void) __convert_us4;
+ (void) __convert_ub1;
+ (void) __convert_ub2;
+ (void) __convert_ub3;
+ (void) __convert_ub4;
+ (void) __convert_rescale_s1;
+ (void) __convert_rescale_s2;
+ (void) __convert_rescale_b1;
+ (void) __convert_rescale_b2;
+ (void) __convert_rescale_ui1;
+ (void) __convert_rescale_ui2;
+ (void) __convert_rescale_i1;
+ (void) __convert_rescale_i2;
+ (void) __convert_rescale_us1;
+ (void) __convert_rescale_us2;
+ (void) __convert_rescale_ub1;
+ (void) __convert_rescale_ub2;
+ (void) __convert_Ni1;
+ (void) __convert_Ni2;
+ (void) __convert_Ni3;
+ (void) __convert_Ni4;
+ (void) __convert_Nb1;
+ (void) __convert_Nb2;
+ (void) __convert_Nb3;
+ (void) __convert_Nb4;
+ (void) __convert_Nus1;
+ (void) __convert_Nus2;
+ (void) __convert_Nus3;
+ (void) __convert_Nus4;
+ (void) __convert_Nui1;
+ (void) __convert_Nui2;
+ (void) __convert_Nui3;
+ (void) __convert_Nui4;
+ (void) __convert_Ns1;
+ (void) __convert_Ns2;
+ (void) __convert_Ns3;
+ (void) __convert_Ns4;
+ (void) __convert_Nub1;
+ (void) __convert_Nub2;
+ (void) __convert_Nub3;
+ (void) __convert_Nub4;
+
+ DIRTY(nbitID, g->neg_bitid);
+
+ /* Save pre state */
+ for (i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++) {
+ COPY_4V(c->vertexAttribPre[i] , c->vertexAttrib[i]);
+ }
+ c->edgeFlagPre = c->edgeFlag;
+ c->colorIndexPre = c->colorIndex;
+
+''')
+
+for k in sorted(current_fns.keys()):
+ print('\t/* %s */' % k)
+ print('\tv = NULL;')
+ name = '%s%s' % (k[:1].lower(),k[1:])
+
+ indent = ""
+ if 'array' in current_fns[k]:
+ print('\tfor (i = 0; i < %s; i++)' % current_fns[k]['array'])
+ print('\t{')
+ indent += "\t"
+ for type in current_fns[k]['types']:
+ if type[0:1] == "N":
+ normalized = 1
+ type2 = type[1:]
+ else:
+ normalized = 0
+ type2 = type
+ for size in current_fns[k]['sizes']:
+ ptr = '%s->%s%d' % (name, type, size )
+ if 'array' in current_fns[k]:
+ ptr += "[i]"
+ print('%s\tif (v < %s)' % (indent, ptr))
+ print('%s\t{' % indent)
+ print('%s\t\tv = %s;' % (indent, ptr))
+ if (k == 'Color' or k == 'Normal' or k == 'SecondaryColor' or normalized) and type != 'f' and type != 'd' and type != 'l':
+ print('%s\t\tconvert = (convert_func) __convert_rescale_%s%d;' % (indent,type,size))
+ else:
+ print('%s\t\tconvert = (convert_func) __convert_%s%d;' % (indent,type,size))
+ print('%s\t}' % indent)
+ print('')
+ print('%s\tif (v != NULL) {' % indent)
+ if 'array' in current_fns[k]:
+ if k == 'TexCoord':
+ print('%s\t\tCOPY_4V(c->vertexAttrib[VERT_ATTRIB_TEX0 + i], %s_default);' % (indent,name))
+ else:
+ print('%s\t\tCOPY_4V(c->%s[i], %s_default);' % (indent,name,name))
+ else:
+ if k == 'Normal':
+ print('%s\t\tCOPY_4V(c->vertexAttrib[VERT_ATTRIB_NORMAL], %s_default);' % (indent,name))
+ elif k == 'FogCoord':
+ print('%s\t\tc->vertexAttrib[VERT_ATTRIB_FOG][0] = %s_default;' % (indent,name))
+ elif k == 'Color':
+ print('%s\t\tCOPY_4V(c->vertexAttrib[VERT_ATTRIB_COLOR0], %s_default);' % (indent,name))
+ elif k == 'SecondaryColor':
+ print('%s\t\tCOPY_4V(c->vertexAttrib[VERT_ATTRIB_COLOR1], %s_default);' % (indent,name))
+ elif k == 'TexCoord':
+ print('%s\t\tCOPY_4V(c->vertexAttrib[VERT_ATTRIB_TEX0], %s_default);' % (indent,name))
+ elif k == 'Index':
+ print('%s\t\tc->colorIndex = %s_default;' % (indent,name))
+ elif k == 'EdgeFlag':
+ print('%s\t\tc->edgeFlag = %s_default;' % (indent,name))
+ else:
+ print('%s\t\tc->%s = %s_default;' % (indent,name,name))
+ if k == 'EdgeFlag':
+ print('%s\t\t__convert_boolean (&c->edgeFlag, v);' % (indent))
+ dirtyVar = 'cb->edgeFlag'
+ elif k == 'Normal':
+ print('%s\t\tconvert(&(c->vertexAttrib[VERT_ATTRIB_NORMAL][0]), v);' % (indent))
+ dirtyVar = 'cb->vertexAttrib[VERT_ATTRIB_NORMAL]'
+ elif k == 'TexCoord':
+ print('%s\t\tconvert(&(c->vertexAttrib[VERT_ATTRIB_TEX0 + i][0]), v);' % (indent))
+ dirtyVar = 'cb->vertexAttrib[VERT_ATTRIB_TEX0 + i]'
+ elif k == 'Color':
+ print('%s\t\tconvert(&(c->vertexAttrib[VERT_ATTRIB_COLOR0][0]), v);' % (indent))
+ dirtyVar = 'cb->vertexAttrib[VERT_ATTRIB_COLOR0]'
+ elif k == 'Index':
+ print('%s\t\tconvert(&(c->colorIndex), v);' % (indent))
+ dirtyVar = 'cb->colorIndex'
+ elif k == 'SecondaryColor':
+ print('%s\t\tconvert(&(c->vertexAttrib[VERT_ATTRIB_COLOR1][0]), v);' % (indent))
+ dirtyVar = 'cb->vertexAttrib[VERT_ATTRIB_COLOR1]'
+ elif k == 'FogCoord':
+ print('%s\t\tconvert(&(c->vertexAttrib[VERT_ATTRIB_FOG][0]), v);' % (indent))
+ dirtyVar = 'cb->vertexAttrib[VERT_ATTRIB_FOG]'
+ elif k == 'VertexAttrib':
+ print('%s\t\tconvert(&(c->vertexAttrib[i][0]), v);' % (indent))
+ dirtyVar = 'cb->vertexAttrib[i]'
+ else:
+ assert 0 # should never get here
+
+ print('%s\t\tDIRTY(%s, nbitID);' % (indent, dirtyVar))
+
+# if current_fns[k].has_key( 'array' ):
+# print '%s\t\tDIRTY(cb->%s[i], nbitID);' % (indent,name)
+# else:
+# print '%s\t\tDIRTY(cb->%s, nbitID);' % (indent,name)
+
+
+
+ print('%s\t\tDIRTY(cb->dirty, nbitID);' % indent)
+ print('%s\t}' % indent)
+ if 'array' in current_fns[k]:
+ print('%s\t%s->ptr[i] = v;' % (indent, name ))
+ else:
+ print('%s\t%s->ptr = v;' % (indent, name ))
+ if 'array' in current_fns[k]:
+ print('\t}')
+print('}')
+
+print('''
+
+void crStateCurrentRecoverNew(CRContext *g, CRCurrentStatePointers *current)
+{
+ const unsigned char *v;
+ convert_func convert=NULL;
+ CRCurrentState *c = &(g->current);
+ CRStateBits *sb = GetCurrentBits();
+ CRCurrentBits *cb = &(sb->current);
+
+ static const GLfloat vertexAttrib_default[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+
+ GLvertexattrib_p *vertexAttrib = &(current->c.vertexAttrib);
+
+ unsigned int i;
+ CRbitvalue nbitID[CR_MAX_BITARRAY];
+
+ /* Invalid parameters, do nothing */
+ if (!g || !current)
+ return;
+
+ /* silence warnings */
+ (void) __convert_b1;
+ (void) __convert_b2;
+ (void) __convert_b3;
+ (void) __convert_b4;
+ (void) __convert_ui1;
+ (void) __convert_ui2;
+ (void) __convert_ui3;
+ (void) __convert_ui4;
+ (void) __convert_l1;
+ (void) __convert_l2;
+ (void) __convert_l3;
+ (void) __convert_l4;
+ (void) __convert_us1;
+ (void) __convert_us2;
+ (void) __convert_us3;
+ (void) __convert_us4;
+ (void) __convert_ub1;
+ (void) __convert_ub2;
+ (void) __convert_ub3;
+ (void) __convert_ub4;
+ (void) __convert_rescale_s1;
+ (void) __convert_rescale_s2;
+ (void) __convert_rescale_b1;
+ (void) __convert_rescale_b2;
+ (void) __convert_rescale_ui1;
+ (void) __convert_rescale_ui2;
+ (void) __convert_rescale_i1;
+ (void) __convert_rescale_i2;
+ (void) __convert_rescale_us1;
+ (void) __convert_rescale_us2;
+ (void) __convert_rescale_ub1;
+ (void) __convert_rescale_ub2;
+ (void) __convert_Ni1;
+ (void) __convert_Ni2;
+ (void) __convert_Ni3;
+ (void) __convert_Ni4;
+ (void) __convert_Nb1;
+ (void) __convert_Nb2;
+ (void) __convert_Nb3;
+ (void) __convert_Nb4;
+ (void) __convert_Nus1;
+ (void) __convert_Nus2;
+ (void) __convert_Nus3;
+ (void) __convert_Nus4;
+ (void) __convert_Nui1;
+ (void) __convert_Nui2;
+ (void) __convert_Nui3;
+ (void) __convert_Nui4;
+ (void) __convert_Ns1;
+ (void) __convert_Ns2;
+ (void) __convert_Ns3;
+ (void) __convert_Ns4;
+ (void) __convert_Nub1;
+ (void) __convert_Nub2;
+ (void) __convert_Nub3;
+ (void) __convert_Nub4;
+
+ DIRTY(nbitID, g->neg_bitid);
+
+''')
+
+for k in sorted(current_fns_new.keys()):
+ print('\t/* %s */' % k)
+ print('\tif (current->changed%s)' % k)
+ print('\t{')
+ print('\t\tv=NULL;')
+ name = '%s%s' % (k[:1].lower(),k[1:])
+
+ indent = ""
+ if 'array' in current_fns_new[k]:
+ print('\t\tfor (i = 0; i < %s; i++)' % current_fns_new[k]['array'])
+ print('\t\t{')
+ indent += "\t\t"
+ print('\t\tif (!(current->changed%s & (1 << i))) continue;' % k)
+ for type in current_fns_new[k]['types']:
+ if type[0:1] == "N":
+ normalized = 1
+ type2 = type[1:]
+ else:
+ normalized = 0
+ type2 = type
+ for size in current_fns_new[k]['sizes']:
+ ptr = '%s->%s%d' % (name, type, size )
+ if 'array' in current_fns_new[k]:
+ ptr += "[i]"
+ print('#ifdef DEBUG_misha')
+ print('%s\tif (%s)' % (indent, ptr))
+ print('%s\t{' % (indent))
+ print('%s\t\tuint32_t *pTst = (uint32_t*)(%s);' % (indent, ptr))
+ print('%s\t\t--pTst;' % (indent))
+ print('%s\t\tAssert((*pTst) == i);' % (indent))
+ print('%s\t}' % (indent))
+ print('#endif')
+ print('%s\tif (v < %s)' % (indent, ptr))
+ print('%s\t{' % indent)
+ print('%s\t\tv = %s;' % (indent, ptr))
+ if (k == 'Color' or k == 'Normal' or k == 'SecondaryColor' or normalized) and type != 'f' and type != 'd' and type != 'l':
+ print('%s\t\tconvert = (convert_func) __convert_rescale_%s%d;' % (indent,type,size))
+ else:
+ print('%s\t\tconvert = (convert_func) __convert_%s%d;' % (indent,type,size))
+ print('%s\t}' % indent)
+ print('')
+ print('%s\tif (v != NULL) {' % indent)
+ if 'array' in current_fns_new[k]:
+ if k == 'TexCoord':
+ print('%s\t\tCOPY_4V(c->vertexAttrib[VERT_ATTRIB_TEX0 + i], %s_default);' % (indent,name))
+ else:
+ print('%s\t\tCOPY_4V(c->%s[i], %s_default);' % (indent,name,name))
+ else:
+ if k == 'Normal':
+ print('%s\t\tCOPY_4V(c->vertexAttrib[VERT_ATTRIB_NORMAL], %s_default);' % (indent,name))
+ elif k == 'FogCoord':
+ print('%s\t\tc->vertexAttrib[VERT_ATTRIB_FOG][0] = %s_default;' % (indent,name))
+ elif k == 'Color':
+ print('%s\t\tCOPY_4V(c->vertexAttrib[VERT_ATTRIB_COLOR0], %s_default);' % (indent,name))
+ elif k == 'SecondaryColor':
+ print('%s\t\tCOPY_4V(c->vertexAttrib[VERT_ATTRIB_COLOR1], %s_default);' % (indent,name))
+ elif k == 'TexCoord':
+ print('%s\t\tCOPY_4V(c->vertexAttrib[VERT_ATTRIB_TEX0], %s_default);' % (indent,name))
+ elif k == 'Index':
+ print('%s\t\tc->colorIndex = %s_default;' % (indent,name))
+ elif k == 'EdgeFlag':
+ print('%s\t\tc->edgeFlag = %s_default;' % (indent,name))
+ else:
+ print('%s\t\tc->%s = %s_default;' % (indent,name,name))
+ if k == 'EdgeFlag':
+ print('%s\t\t__convert_boolean (&c->edgeFlag, v);' % (indent))
+ dirtyVar = 'cb->edgeFlag'
+ elif k == 'Normal':
+ print('%s\t\tconvert(&(c->vertexAttrib[VERT_ATTRIB_NORMAL][0]), v);' % (indent))
+ dirtyVar = 'cb->vertexAttrib[VERT_ATTRIB_NORMAL]'
+ elif k == 'TexCoord':
+ print('%s\t\tconvert(&(c->vertexAttrib[VERT_ATTRIB_TEX0 + i][0]), v);' % (indent))
+ dirtyVar = 'cb->vertexAttrib[VERT_ATTRIB_TEX0 + i]'
+ elif k == 'Color':
+ print('%s\t\tconvert(&(c->vertexAttrib[VERT_ATTRIB_COLOR0][0]), v);' % (indent))
+ dirtyVar = 'cb->vertexAttrib[VERT_ATTRIB_COLOR0]'
+ elif k == 'Index':
+ print('%s\t\tconvert(&(c->colorIndex), v);' % (indent))
+ dirtyVar = 'cb->colorIndex'
+ elif k == 'SecondaryColor':
+ print('%s\t\tconvert(&(c->vertexAttrib[VERT_ATTRIB_COLOR1][0]), v);' % (indent))
+ dirtyVar = 'cb->vertexAttrib[VERT_ATTRIB_COLOR1]'
+ elif k == 'FogCoord':
+ print('%s\t\tconvert(&(c->vertexAttrib[VERT_ATTRIB_FOG][0]), v);' % (indent))
+ dirtyVar = 'cb->vertexAttrib[VERT_ATTRIB_FOG]'
+ elif k == 'VertexAttrib':
+ print('%s\t\tconvert(&(c->vertexAttrib[i][0]), v);' % (indent))
+ dirtyVar = 'cb->vertexAttrib[i]'
+ else:
+ assert 0 # should never get here
+
+ print('%s\t\tDIRTY(%s, nbitID);' % (indent, dirtyVar))
+
+# if current_fns_new[k].has_key( 'array' ):
+# print '%s\t\tDIRTY(cb->%s[i], nbitID);' % (indent,name)
+# else:
+# print '%s\t\tDIRTY(cb->%s, nbitID);' % (indent,name)
+
+
+
+ print('%s\t\tDIRTY(cb->dirty, nbitID);' % indent)
+ print('%s\t}' % indent)
+ if 'array' in current_fns_new[k]:
+ print('%s\t%s->ptr[i] = v;' % (indent, name ))
+ else:
+ print('%s\t%s->ptr = v;' % (indent, name ))
+ if 'array' in current_fns_new[k]:
+ print('\t\t}')
+ print('\t\tcurrent->changed%s = 0;' % k)
+ print('\t}')
+print('\tcrStateResetCurrentPointers(current);')
+print('}')
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_defs.py b/src/VBox/GuestHost/OpenGL/state_tracker/state_defs.py
new file mode 100644
index 00000000..1fb1a384
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_defs.py
@@ -0,0 +1,64 @@
+# Copyright (c) 2001, Stanford University
+# All rights reserved.
+#
+# See the file LICENSE.txt for information on redistributing this software.
+
+
+import sys
+
+import apiutil
+
+apiutil.CopyrightDef()
+
+print """DESCRIPTION ""
+EXPORTS
+"""
+
+keys = apiutil.GetDispatchedFunctions(sys.argv[1]+"/APIspec.txt")
+
+for func_name in apiutil.AllSpecials( 'state' ):
+ print "crState%s" % func_name
+
+for func_name in apiutil.AllSpecials( 'state_feedback' ):
+ print "crStateFeedback%s" % func_name
+
+for func_name in apiutil.AllSpecials( 'state_select' ):
+ print "crStateSelect%s" % func_name
+
+print """crStateInit
+crStateReadPixels
+crStateGetChromiumParametervCR
+crStateCreateContext
+crStateCreateContextEx
+crStateDestroyContext
+crStateDiffContext
+crStateSwitchContext
+crStateMakeCurrent
+crStateSetCurrent
+crStateFlushFunc
+crStateFlushArg
+crStateDiffAPI
+crStateSetCurrentPointers
+crStateResetCurrentPointers
+crStateCurrentRecover
+crStateTransformUpdateTransform
+crStateColorMaterialRecover
+crStateError
+crStateUpdateColorBits
+crStateClientInit
+crStateGetCurrent
+crStateLimitsInit
+crStateMergeExtensions
+crStateRasterPosUpdate
+crStateTextureCheckDirtyImages
+crStateExtensionsInit
+crStateSetExtensionString
+crStateUseServerArrays
+crStateUseServerArrayElements
+crStateComputeVersion
+crStateTransformXformPointMatrixf
+crStateTransformXformPointMatrixd
+crStateInitMatrixStack
+crStateLoadMatrix
+__currentBits
+"""
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_diff.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_diff.c
new file mode 100644
index 00000000..daf22565
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_diff.c
@@ -0,0 +1,644 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#include "state.h"
+#include "cr_error.h"
+#include "cr_mem.h"
+#include "cr_pixeldata.h"
+#include <iprt/errcore.h>
+#include <stdio.h>
+
+void crStateDiffContext( CRContext *from, CRContext *to )
+{
+ CRbitvalue *bitID = from->bitid;
+ CRStateBits *sb = GetCurrentBits();
+
+ /*crDebug( "Diffing two contexts!" ); */
+
+ if (CHECKDIRTY(sb->transform.dirty, bitID))
+ {
+ crStateTransformDiff( &(sb->transform), bitID, from, to );
+ }
+ if (CHECKDIRTY(sb->pixel.dirty, bitID))
+ {
+ crStatePixelDiff( &(sb->pixel), bitID, from, to );
+ }
+ if (CHECKDIRTY(sb->viewport.dirty, bitID))
+ {
+ crStateViewportDiff( &(sb->viewport), bitID, from, to );
+ }
+ if (CHECKDIRTY(sb->fog.dirty, bitID))
+ {
+ crStateFogDiff( &(sb->fog), bitID, from, to );
+ }
+ if (CHECKDIRTY(sb->texture.dirty, bitID))
+ {
+ crStateTextureDiff( &(sb->texture), bitID, from, to );
+ }
+ if (CHECKDIRTY(sb->lists.dirty, bitID))
+ {
+ crStateListsDiff( &(sb->lists), bitID, from, to );
+ }
+ if (CHECKDIRTY(sb->buffer.dirty, bitID))
+ {
+ crStateBufferDiff( &(sb->buffer), bitID, from, to );
+ }
+#ifdef CR_ARB_vertex_buffer_object
+ if (CHECKDIRTY(sb->bufferobject.dirty, bitID))
+ {
+ crStateBufferObjectDiff( &(sb->bufferobject), bitID, from, to );
+ }
+#endif
+ if (CHECKDIRTY(sb->client.dirty, bitID))
+ {
+ crStateClientDiff(&(sb->client), bitID, from, to );
+ }
+ if (CHECKDIRTY(sb->hint.dirty, bitID))
+ {
+ crStateHintDiff( &(sb->hint), bitID, from, to );
+ }
+ if (CHECKDIRTY(sb->lighting.dirty, bitID))
+ {
+ crStateLightingDiff( &(sb->lighting), bitID, from, to );
+ }
+ if (CHECKDIRTY(sb->line.dirty, bitID))
+ {
+ crStateLineDiff( &(sb->line), bitID, from, to );
+ }
+ if (CHECKDIRTY(sb->occlusion.dirty, bitID))
+ {
+ crStateOcclusionDiff( &(sb->occlusion), bitID, from, to );
+ }
+ if (CHECKDIRTY(sb->point.dirty, bitID))
+ {
+ crStatePointDiff( &(sb->point), bitID, from, to );
+ }
+ if (CHECKDIRTY(sb->polygon.dirty, bitID))
+ {
+ crStatePolygonDiff( &(sb->polygon), bitID, from, to );
+ }
+ if (CHECKDIRTY(sb->program.dirty, bitID))
+ {
+ crStateProgramDiff( &(sb->program), bitID, from, to );
+ }
+ if (CHECKDIRTY(sb->stencil.dirty, bitID))
+ {
+ crStateStencilDiff( &(sb->stencil), bitID, from, to );
+ }
+ if (CHECKDIRTY(sb->eval.dirty, bitID))
+ {
+ crStateEvaluatorDiff( &(sb->eval), bitID, from, to );
+ }
+#ifdef CR_ARB_imaging
+ if (CHECKDIRTY(sb->imaging.dirty, bitID))
+ {
+ crStateImagingDiff( &(sb->imaging), bitID, from, to );
+ }
+#endif
+#if 0
+ if (CHECKDIRTY(sb->selection.dirty, bitID))
+ {
+ crStateSelectionDiff( &(sb->selection), bitID, from, to );
+ }
+#endif
+#ifdef CR_NV_register_combiners
+ if (CHECKDIRTY(sb->regcombiner.dirty, bitID) && to->extensions.NV_register_combiners)
+ {
+ crStateRegCombinerDiff( &(sb->regcombiner), bitID, from, to );
+ }
+#endif
+#ifdef CR_ARB_multisample
+ if (CHECKDIRTY(sb->multisample.dirty, bitID) &&
+ from->extensions.ARB_multisample)
+ {
+ crStateMultisampleDiff( &(sb->multisample), bitID, from, to );
+ }
+#endif
+ if (CHECKDIRTY(sb->current.dirty, bitID))
+ {
+ crStateCurrentDiff( &(sb->current), bitID, from, 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; - unused */
+ 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)
+{
+ {
+ /*CRBufferState *pBuf = &to->buffer; - unused */
+ CRPixelPackState unpack = to->client.unpack;
+ uint32_t i;
+
+ diff_api.PixelStorei(GL_UNPACK_SKIP_ROWS, 0);
+ diff_api.PixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
+ diff_api.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ diff_api.PixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+ diff_api.PixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
+ diff_api.PixelStorei(GL_UNPACK_SKIP_IMAGES, 0);
+ diff_api.PixelStorei(GL_UNPACK_SWAP_BYTES, 0);
+ diff_api.PixelStorei(GL_UNPACK_LSB_FIRST, 0);
+
+ if (to->bufferobject.unpackBuffer->hwid>0)
+ {
+ diff_api.BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
+ }
+
+ diff_api.Disable(GL_ALPHA_TEST);
+ 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);
+
+ for (i = 0; i < data->cElements; ++i)
+ {
+ 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
+
+ /* Before SSM version SHCROGL_SSM_VERSION_WITH_SEPARATE_DEPTH_STENCIL_BUFFERS
+ * saved state file contined invalid DEPTH/STENCIL data. In order to prevent
+ * crashes and improper guest App behavior, this data should be ignored. */
+ if ( data->u32Version < SHCROGL_SSM_VERSION_WITH_SEPARATE_DEPTH_STENCIL_BUFFERS
+ && ( el->enmFormat == GL_DEPTH_COMPONENT
+ || el->enmFormat == GL_STENCIL_INDEX
+ || el->enmFormat == GL_DEPTH_STENCIL))
+ continue;
+
+ 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]);
+ if (to->bufferobject.unpackBuffer->hwid>0)
+ {
+ diff_api.BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, to->bufferobject.unpackBuffer->hwid);
+ }
+ 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);
+ }
+ if (to->buffer.alphaTest)
+ {
+ diff_api.Enable(GL_ALPHA_TEST);
+ }
+ if (to->viewport.scissorTest)
+ {
+ diff_api.Enable(GL_SCISSOR_TEST);
+ }
+ if (to->buffer.blend)
+ {
+ diff_api.Enable(GL_BLEND);
+ }
+ if (to->buffer.logicOp)
+ {
+ 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);
+ diff_api.PixelStorei(GL_UNPACK_ALIGNMENT, unpack.alignment);
+ diff_api.PixelStorei(GL_UNPACK_ROW_LENGTH, unpack.rowLength);
+ diff_api.PixelStorei(GL_UNPACK_IMAGE_HEIGHT, unpack.imageHeight);
+ diff_api.PixelStorei(GL_UNPACK_SKIP_IMAGES, unpack.skipImages);
+ diff_api.PixelStorei(GL_UNPACK_SWAP_BYTES, unpack.swapBytes);
+ diff_api.PixelStorei(GL_UNPACK_LSB_FIRST, unpack.psLSBFirst);
+
+ diff_api.Finish();
+ }
+}
+
+void crStateSwitchContext( CRContext *from, CRContext *to )
+{
+ CRbitvalue *bitID = to->bitid;
+ CRStateBits *sb = GetCurrentBits();
+
+ if (CHECKDIRTY(sb->attrib.dirty, bitID))
+ {
+ crStateAttribSwitch(&(sb->attrib), bitID, from, to );
+ }
+ if (CHECKDIRTY(sb->transform.dirty, bitID))
+ {
+ crStateTransformSwitch( &(sb->transform), bitID, from, to );
+ }
+ if (CHECKDIRTY(sb->pixel.dirty, bitID))
+ {
+ crStatePixelSwitch(&(sb->pixel), bitID, from, to );
+ }
+ if (CHECKDIRTY(sb->viewport.dirty, bitID))
+ {
+ crStateViewportSwitch(&(sb->viewport), bitID, from, to );
+ }
+ if (CHECKDIRTY(sb->fog.dirty, bitID))
+ {
+ crStateFogSwitch(&(sb->fog), bitID, from, to );
+ }
+ if (CHECKDIRTY(sb->texture.dirty, bitID))
+ {
+ crStateTextureSwitch( &(sb->texture), bitID, from, to );
+ }
+ if (CHECKDIRTY(sb->lists.dirty, bitID))
+ {
+ crStateListsSwitch(&(sb->lists), bitID, from, to );
+ }
+ if (CHECKDIRTY(sb->buffer.dirty, bitID))
+ {
+ crStateBufferSwitch( &(sb->buffer), bitID, from, to );
+ }
+#ifdef CR_ARB_vertex_buffer_object
+ if (CHECKDIRTY(sb->bufferobject.dirty, bitID))
+ {
+ crStateBufferObjectSwitch( &(sb->bufferobject), bitID, from, to );
+ }
+#endif
+ if (CHECKDIRTY(sb->client.dirty, bitID))
+ {
+ crStateClientSwitch( &(sb->client), bitID, from, to );
+ }
+#if 0
+ if (CHECKDIRTY(sb->hint.dirty, bitID))
+ {
+ crStateHintSwitch( &(sb->hint), bitID, from, to );
+ }
+#endif
+ if (CHECKDIRTY(sb->lighting.dirty, bitID))
+ {
+ crStateLightingSwitch( &(sb->lighting), bitID, from, to );
+ }
+ if (CHECKDIRTY(sb->occlusion.dirty, bitID))
+ {
+ crStateOcclusionSwitch( &(sb->occlusion), bitID, from, to );
+ }
+ if (CHECKDIRTY(sb->line.dirty, bitID))
+ {
+ crStateLineSwitch( &(sb->line), bitID, from, to );
+ }
+ if (CHECKDIRTY(sb->point.dirty, bitID))
+ {
+ crStatePointSwitch( &(sb->point), bitID, from, to );
+ }
+ if (CHECKDIRTY(sb->polygon.dirty, bitID))
+ {
+ crStatePolygonSwitch( &(sb->polygon), bitID, from, to );
+ }
+ if (CHECKDIRTY(sb->program.dirty, bitID))
+ {
+ crStateProgramSwitch( &(sb->program), bitID, from, to );
+ }
+ if (CHECKDIRTY(sb->stencil.dirty, bitID))
+ {
+ crStateStencilSwitch( &(sb->stencil), bitID, from, to );
+ }
+ if (CHECKDIRTY(sb->eval.dirty, bitID))
+ {
+ crStateEvaluatorSwitch( &(sb->eval), bitID, from, to );
+ }
+#ifdef CR_ARB_imaging
+ if (CHECKDIRTY(sb->imaging.dirty, bitID))
+ {
+ crStateImagingSwitch( &(sb->imaging), bitID, from, to );
+ }
+#endif
+#if 0
+ if (CHECKDIRTY(sb->selection.dirty, bitID))
+ {
+ crStateSelectionSwitch( &(sb->selection), bitID, from, to );
+ }
+#endif
+#ifdef CR_NV_register_combiners
+ if (CHECKDIRTY(sb->regcombiner.dirty, bitID) && to->extensions.NV_register_combiners)
+ {
+ crStateRegCombinerSwitch( &(sb->regcombiner), bitID, from, to );
+ }
+#endif
+#ifdef CR_ARB_multisample
+ if (CHECKDIRTY(sb->multisample.dirty, bitID))
+ {
+ crStateMultisampleSwitch( &(sb->multisample), bitID, from, to );
+ }
+#endif
+#ifdef CR_ARB_multisample
+ if (CHECKDIRTY(sb->multisample.dirty, bitID))
+ {
+ crStateMultisampleSwitch(&(sb->multisample), bitID, from, to );
+ }
+#endif
+#ifdef CR_EXT_framebuffer_object
+ /*Note, this should go after crStateTextureSwitch*/
+ crStateFramebufferObjectSwitch(from, to);
+#endif
+#ifdef CR_OPENGL_VERSION_2_0
+ crStateGLSLSwitch(from, to);
+#endif
+ if (CHECKDIRTY(sb->current.dirty, bitID))
+ {
+ crStateCurrentSwitch( &(sb->current), bitID, from, to );
+ }
+
+#ifdef WINDOWS
+ if (to->buffer.pFrontImg)
+ {
+ CRFBData *pLazyData = (CRFBData *)to->buffer.pFrontImg;
+ crStateApplyFBImage(to, pLazyData);
+ crStateFreeFBImageLegacy(to);
+ }
+#endif
+}
+
+void crStateSyncHWErrorState(CRContext *ctx)
+{
+ GLenum err;
+ while ((err = diff_api.GetError()) != GL_NO_ERROR)
+ {
+ if (ctx->error != GL_NO_ERROR)
+ ctx->error = err;
+ }
+}
+
+GLenum crStateCleanHWErrorState(void)
+{
+ GLenum err;
+ while ((err = diff_api.GetError()) != GL_NO_ERROR)
+ {
+ static int cErrPrints = 0;
+#ifndef DEBUG_misha
+ if (cErrPrints < 5)
+#endif
+ {
+ ++cErrPrints;
+ WARN(("cleaning gl error (0x%x), ignoring.. (%d out of 5) ..", err, cErrPrints));
+ }
+ }
+
+ return 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
+ crStateFramebufferObjectDisableHW(fromCtx, idDrawFBO, idReadFBO);
+#endif
+}
+
+void crStateSwitchPostprocess(CRContext *toCtx, CRContext *fromCtx, GLuint idDrawFBO, GLuint idReadFBO)
+{
+ if (!toCtx)
+ return;
+
+#ifdef CR_EXT_framebuffer_object
+ crStateFramebufferObjectReenableHW(fromCtx, toCtx, idDrawFBO, idReadFBO);
+#endif
+
+ if (g_bVBoxEnableDiffOnMakeCurrent && fromCtx && toCtx != fromCtx)
+ {
+ CR_STATE_CLEAN_HW_ERR_WARN("error on make current");
+ }
+}
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_enable.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_enable.c
new file mode 100644
index 00000000..dca7d98d
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_enable.c
@@ -0,0 +1,544 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#include <stdio.h>
+#include "state.h"
+#include "state/cr_statetypes.h"
+#include "state_internals.h"
+
+static void __enableSet (CRContext *g, CRStateBits *sb, CRbitvalue *neg_bitid,
+ GLenum cap, GLboolean val)
+{
+ unsigned int i;
+ i = cap - GL_CLIP_PLANE0;
+ if (i < g->limits.maxClipPlanes) {
+ g->transform.clip[i] = val;
+ DIRTY(sb->transform.enable, neg_bitid);
+ DIRTY(sb->transform.dirty, neg_bitid);
+ return;
+ }
+ i = cap - GL_LIGHT0;
+ if (i < g->limits.maxLights) {
+ g->lighting.light[i].enable = val;
+ DIRTY(sb->lighting.light[i].dirty, neg_bitid);
+ DIRTY(sb->lighting.light[i].enable, neg_bitid);
+ DIRTY(sb->lighting.dirty, neg_bitid);
+ return;
+ }
+
+ switch (cap) {
+ case GL_AUTO_NORMAL:
+ g->eval.autoNormal = val;
+ DIRTY(sb->eval.enable, neg_bitid);
+ DIRTY(sb->eval.dirty, neg_bitid);
+ break;
+ case GL_ALPHA_TEST:
+ g->buffer.alphaTest = val;
+ DIRTY(sb->buffer.enable, neg_bitid);
+ DIRTY(sb->buffer.dirty, neg_bitid);
+ break;
+ case GL_BLEND:
+ g->buffer.blend = val;
+ DIRTY(sb->buffer.enable, neg_bitid);
+ DIRTY(sb->buffer.dirty, neg_bitid);
+ break;
+ case GL_COLOR_MATERIAL :
+ if (!val)
+ {
+ /* We're TURNING OFF color material. In this case,
+ * we should make sure that the very very latest
+ * color that was specified gets copied into the
+ * material parameters, since this might be our
+ * last chance (see frame 1 of progs/kirchner
+ * for an example of why). */
+
+ crStateCurrentRecover( );
+ crStateColorMaterialRecover( );
+ }
+ g->lighting.colorMaterial = val;
+ DIRTY(sb->lighting.enable, neg_bitid);
+ DIRTY(sb->lighting.dirty, neg_bitid);
+ break;
+#ifdef CR_EXT_secondary_color
+ case GL_COLOR_SUM_EXT :
+ if (g->extensions.EXT_secondary_color) { /* XXX does EXT_separate_specular color support this enable, too? */
+ g->lighting.colorSumEXT = val;
+ DIRTY(sb->lighting.enable, neg_bitid);
+ DIRTY(sb->lighting.dirty, neg_bitid);
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glEnable/glDisable(GL_COLOR_SUM_EXT) - No support for secondary color!");
+ return;
+ }
+ break;
+#endif
+ case GL_CULL_FACE :
+ g->polygon.cullFace = val;
+ DIRTY(sb->polygon.enable, neg_bitid);
+ DIRTY(sb->polygon.dirty, neg_bitid);
+ break;
+ case GL_DEPTH_TEST :
+ g->buffer.depthTest = val;
+ DIRTY(sb->buffer.enable, neg_bitid);
+ DIRTY(sb->buffer.dirty, neg_bitid);
+ break;
+ case GL_DITHER :
+ g->buffer.dither = val;
+ DIRTY(sb->buffer.enable, neg_bitid);
+ DIRTY(sb->buffer.dirty, neg_bitid);
+ break;
+ case GL_FOG :
+ g->fog.enable = val;
+ DIRTY(sb->fog.enable, neg_bitid);
+ DIRTY(sb->fog.dirty, neg_bitid);
+ break;
+ case GL_LIGHTING :
+ g->lighting.lighting = val;
+ DIRTY(sb->lighting.enable, neg_bitid);
+ DIRTY(sb->lighting.dirty, neg_bitid);
+ break;
+ case GL_LINE_SMOOTH :
+ g->line.lineSmooth = val;
+ DIRTY(sb->line.enable, neg_bitid);
+ DIRTY(sb->line.dirty, neg_bitid);
+ break;
+ case GL_LINE_STIPPLE :
+ g->line.lineStipple = val;
+ DIRTY(sb->line.enable, neg_bitid);
+ DIRTY(sb->line.dirty, neg_bitid);
+ break;
+ case GL_COLOR_LOGIC_OP :
+ g->buffer.logicOp = val;
+ DIRTY(sb->buffer.enable, neg_bitid);
+ DIRTY(sb->buffer.dirty, neg_bitid);
+ break;
+ case GL_INDEX_LOGIC_OP :
+ g->buffer.indexLogicOp = val;
+ DIRTY(sb->buffer.enable, neg_bitid);
+ DIRTY(sb->buffer.dirty, neg_bitid);
+ break;
+ case GL_NORMALIZE :
+ g->transform.normalize = val;
+ DIRTY(sb->transform.enable, neg_bitid);
+ DIRTY(sb->transform.dirty, neg_bitid);
+ break;
+ case GL_POINT_SMOOTH :
+ g->point.pointSmooth = val;
+ DIRTY(sb->point.enableSmooth, neg_bitid);
+ DIRTY(sb->point.dirty, neg_bitid);
+ break;
+ case GL_POLYGON_OFFSET_FILL:
+ g->polygon.polygonOffsetFill = val;
+ DIRTY(sb->polygon.enable, neg_bitid);
+ DIRTY(sb->polygon.dirty, neg_bitid);
+ break;
+ case GL_POLYGON_OFFSET_LINE:
+ g->polygon.polygonOffsetLine = val;
+ DIRTY(sb->polygon.enable, neg_bitid);
+ DIRTY(sb->polygon.dirty, neg_bitid);
+ break;
+ case GL_POLYGON_OFFSET_POINT:
+ g->polygon.polygonOffsetPoint = val;
+ DIRTY(sb->polygon.enable, neg_bitid);
+ DIRTY(sb->polygon.dirty, neg_bitid);
+ break;
+ case GL_POLYGON_SMOOTH :
+ g->polygon.polygonSmooth = val;
+ DIRTY(sb->polygon.enable, neg_bitid);
+ DIRTY(sb->polygon.dirty, neg_bitid);
+ break;
+ case GL_POLYGON_STIPPLE :
+ g->polygon.polygonStipple = val;
+ DIRTY(sb->polygon.enable, neg_bitid);
+ DIRTY(sb->polygon.dirty, neg_bitid);
+ break;
+#ifdef CR_NV_register_combiners
+ case GL_REGISTER_COMBINERS_NV :
+ if (g->extensions.NV_register_combiners) {
+ g->regcombiner.enabledRegCombiners = val;
+ DIRTY(sb->regcombiner.enable, neg_bitid);
+ DIRTY(sb->regcombiner.dirty, neg_bitid);
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glEnable/glDisable(GL_REGISTER_COMBINERS_NV) - No support for NV_register_combiners");
+ return;
+ }
+ break;
+#endif
+#ifdef CR_NV_register_combiners2
+ case GL_PER_STAGE_CONSTANTS_NV :
+ if (g->extensions.NV_register_combiners2) {
+ g->regcombiner.enabledPerStageConstants = val;
+ DIRTY(sb->regcombiner.enable, neg_bitid);
+ DIRTY(sb->regcombiner.dirty, neg_bitid);
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glEnable/glDisable(GL_PER_STAGE_CONSTANTS_NV) - No support for NV_register_combiners2");
+ return;
+ }
+ break;
+#endif
+#ifdef CR_NV_texture_rectangle
+ case GL_TEXTURE_RECTANGLE_NV:
+ if (g->extensions.NV_texture_rectangle) {
+ g->texture.unit[g->texture.curTextureUnit].enabledRect = val;
+ DIRTY(sb->texture.enable[g->texture.curTextureUnit], neg_bitid);
+ DIRTY(sb->texture.dirty, neg_bitid);
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glEnable/glDisable(0x%x)", cap);
+ return;
+ }
+ break;
+#endif /* CR_NV_texture_rectangle */
+#ifdef CR_OPENGL_VERSION_1_2
+ case GL_RESCALE_NORMAL :
+ g->transform.rescaleNormals = val;
+ DIRTY(sb->transform.enable, neg_bitid);
+ DIRTY(sb->transform.dirty, neg_bitid);
+ break;
+#endif
+ case GL_SCISSOR_TEST :
+ g->viewport.scissorTest = val;
+ DIRTY(sb->viewport.enable, neg_bitid);
+ DIRTY(sb->viewport.dirty, neg_bitid);
+ break;
+ case GL_STENCIL_TEST :
+ g->stencil.stencilTest= val;
+ DIRTY(sb->stencil.enable, neg_bitid);
+ DIRTY(sb->stencil.dirty, neg_bitid);
+ break;
+ case GL_TEXTURE_1D :
+ g->texture.unit[g->texture.curTextureUnit].enabled1D = val;
+ DIRTY(sb->texture.enable[g->texture.curTextureUnit], neg_bitid);
+ DIRTY(sb->texture.dirty, neg_bitid);
+ break;
+ case GL_TEXTURE_2D :
+ g->texture.unit[g->texture.curTextureUnit].enabled2D = val;
+ DIRTY(sb->texture.enable[g->texture.curTextureUnit], neg_bitid);
+ DIRTY(sb->texture.dirty, neg_bitid);
+ break;
+#ifdef CR_OPENGL_VERSION_1_2
+ case GL_TEXTURE_3D :
+ g->texture.unit[g->texture.curTextureUnit].enabled3D = val;
+ DIRTY(sb->texture.enable[g->texture.curTextureUnit], neg_bitid);
+ DIRTY(sb->texture.dirty, neg_bitid);
+ break;
+#endif
+#ifdef CR_ARB_texture_cube_map
+ case GL_TEXTURE_CUBE_MAP_ARB:
+ if (g->extensions.ARB_texture_cube_map) {
+ g->texture.unit[g->texture.curTextureUnit].enabledCubeMap = val;
+ DIRTY(sb->texture.enable[g->texture.curTextureUnit], neg_bitid);
+ DIRTY(sb->texture.dirty, neg_bitid);
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glEnable/glDisable(0x%x)", cap);
+ return;
+ }
+ break;
+#endif /* CR_ARB_texture_cube_map */
+ case GL_TEXTURE_GEN_Q :
+ g->texture.unit[g->texture.curTextureUnit].textureGen.q = val;
+ DIRTY(sb->texture.enable[g->texture.curTextureUnit], neg_bitid);
+ DIRTY(sb->texture.dirty, neg_bitid);
+ break;
+ case GL_TEXTURE_GEN_R :
+ g->texture.unit[g->texture.curTextureUnit].textureGen.r = val;
+ DIRTY(sb->texture.enable[g->texture.curTextureUnit], neg_bitid);
+ DIRTY(sb->texture.dirty, neg_bitid);
+ break;
+ case GL_TEXTURE_GEN_S :
+ g->texture.unit[g->texture.curTextureUnit].textureGen.s = val;
+ DIRTY(sb->texture.enable[g->texture.curTextureUnit], neg_bitid);
+ DIRTY(sb->texture.dirty, neg_bitid);
+ break;
+ case GL_TEXTURE_GEN_T :
+ g->texture.unit[g->texture.curTextureUnit].textureGen.t = val;
+ DIRTY(sb->texture.enable[g->texture.curTextureUnit], neg_bitid);
+ DIRTY(sb->texture.dirty, neg_bitid);
+ break;
+ case GL_MAP1_COLOR_4 :
+ case GL_MAP1_INDEX :
+ case GL_MAP1_NORMAL :
+ case GL_MAP1_TEXTURE_COORD_1 :
+ case GL_MAP1_TEXTURE_COORD_2 :
+ case GL_MAP1_TEXTURE_COORD_3 :
+ case GL_MAP1_TEXTURE_COORD_4 :
+ case GL_MAP1_VERTEX_3 :
+ case GL_MAP1_VERTEX_4 :
+ if (g->texture.curTextureUnit != 0)
+ {
+ crStateError( __LINE__, __FILE__, GL_INVALID_OPERATION, "Map stuff was enabled while the current texture unit was not GL_TEXTURE0_ARB!" );
+ return;
+ }
+ g->eval.enable1D[cap - GL_MAP1_COLOR_4] = val;
+ DIRTY(sb->eval.enable1D[cap - GL_MAP1_COLOR_4], neg_bitid);
+ DIRTY(sb->eval.dirty, neg_bitid);
+ break;
+ case GL_MAP2_COLOR_4 :
+ case GL_MAP2_INDEX :
+ case GL_MAP2_NORMAL :
+ case GL_MAP2_TEXTURE_COORD_1 :
+ case GL_MAP2_TEXTURE_COORD_2 :
+ case GL_MAP2_TEXTURE_COORD_3 :
+ case GL_MAP2_TEXTURE_COORD_4 :
+ case GL_MAP2_VERTEX_3 :
+ case GL_MAP2_VERTEX_4 :
+#if 0
+ if (g->texture.curTextureUnit != 0)
+ {
+ crStateError( __LINE__, __FILE__, GL_INVALID_OPERATION, "Map stuff was enabled while the current texture unit was not GL_TEXTURE0_ARB!" );
+ return;
+ }
+#endif
+ g->eval.enable2D[cap - GL_MAP2_COLOR_4] = val;
+ DIRTY(sb->eval.enable2D[cap - GL_MAP2_COLOR_4], neg_bitid);
+ DIRTY(sb->eval.dirty, neg_bitid);
+ break;
+#ifdef CR_ARB_multisample
+ case GL_MULTISAMPLE_ARB:
+ g->multisample.enabled = val;
+ DIRTY(sb->multisample.enable, neg_bitid);
+ DIRTY(sb->multisample.dirty, neg_bitid);
+ break;
+ case GL_SAMPLE_ALPHA_TO_COVERAGE_ARB:
+ g->multisample.sampleAlphaToCoverage = val;
+ DIRTY(sb->multisample.sampleAlphaToCoverage, neg_bitid);
+ DIRTY(sb->multisample.dirty, neg_bitid);
+ break;
+ case GL_SAMPLE_ALPHA_TO_ONE_ARB:
+ g->multisample.sampleAlphaToOne = val;
+ DIRTY(sb->multisample.sampleAlphaToOne, neg_bitid);
+ DIRTY(sb->multisample.dirty, neg_bitid);
+ break;
+ case GL_SAMPLE_COVERAGE_ARB:
+ g->multisample.sampleCoverage = val;
+ DIRTY(sb->multisample.sampleCoverage, neg_bitid);
+ DIRTY(sb->multisample.dirty, neg_bitid);
+ break;
+#endif
+#ifdef CR_NV_vertex_program
+ case GL_VERTEX_PROGRAM_NV:
+ if (g->extensions.NV_vertex_program) {
+ g->program.vpEnabled = val;
+ DIRTY(sb->program.vpEnable, neg_bitid);
+ DIRTY(sb->program.dirty, neg_bitid);
+ }
+ else if (g->extensions.ARB_vertex_program) {
+ g->program.vpEnabled = val;
+ DIRTY(sb->program.vpEnable, neg_bitid);
+ DIRTY(sb->program.dirty, neg_bitid);
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glEnable/glDisable(0x%x)", cap);
+ return;
+ }
+ break;
+ case GL_VERTEX_PROGRAM_POINT_SIZE_NV:
+ if (g->extensions.NV_vertex_program) {
+ g->program.vpPointSize = val;
+ DIRTY(sb->program.vpEnable, neg_bitid);
+ DIRTY(sb->program.dirty, neg_bitid);
+ }
+ else if (g->extensions.ARB_vertex_program) {
+ g->program.vpPointSize = val;
+ DIRTY(sb->program.vpEnable, neg_bitid);
+ DIRTY(sb->program.dirty, neg_bitid);
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glEnable/glDisable(0x%x)", cap);
+ return;
+ }
+ break;
+ case GL_VERTEX_PROGRAM_TWO_SIDE_NV:
+ if (g->extensions.NV_vertex_program) {
+ g->program.vpTwoSide = val;
+ DIRTY(sb->program.vpEnable, neg_bitid);
+ DIRTY(sb->program.dirty, neg_bitid);
+ }
+ else if (g->extensions.ARB_vertex_program) {
+ g->program.vpTwoSide = val;
+ DIRTY(sb->program.vpEnable, neg_bitid);
+ DIRTY(sb->program.dirty, neg_bitid);
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glEnable/glDisable(0x%x)", cap);
+ return;
+ }
+ break;
+
+ case GL_MAP1_VERTEX_ATTRIB0_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB1_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB2_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB3_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB4_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB5_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB6_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB7_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB8_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB9_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB10_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB11_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB12_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB13_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB14_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB15_4_NV:
+ {
+ const GLint idx = cap - GL_MAP1_VERTEX_ATTRIB0_4_NV;
+ g->eval.enableAttrib1D[idx] = val;
+ DIRTY(sb->program.map1AttribArrayEnable[idx], neg_bitid);
+ DIRTY(sb->program.dirty, neg_bitid);
+ }
+ break;
+ case GL_MAP2_VERTEX_ATTRIB0_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB1_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB2_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB3_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB4_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB5_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB6_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB7_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB8_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB9_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB10_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB11_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB12_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB13_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB14_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB15_4_NV:
+ {
+ const GLint idx = cap - GL_MAP2_VERTEX_ATTRIB0_4_NV;
+ g->eval.enableAttrib2D[idx] = val;
+ DIRTY(sb->program.map2AttribArrayEnable[idx], neg_bitid);
+ DIRTY(sb->program.dirty, neg_bitid);
+ }
+ break;
+#endif
+#ifdef CR_NV_fragment_program
+ case GL_FRAGMENT_PROGRAM_NV:
+ if (g->extensions.NV_fragment_program) {
+ g->program.fpEnabled = val;
+ DIRTY(sb->program.fpEnable, neg_bitid);
+ DIRTY(sb->program.dirty, neg_bitid);
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glEnable/glDisable(0x%x)", cap);
+ return;
+ }
+ break;
+#endif
+#ifdef CR_ARB_fragment_program
+ case GL_FRAGMENT_PROGRAM_ARB:
+ if (g->extensions.ARB_fragment_program) {
+ g->program.fpEnabledARB = val;
+ DIRTY(sb->program.fpEnable, neg_bitid);
+ DIRTY(sb->program.dirty, neg_bitid);
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glEnable/glDisable(0x%x)", cap);
+ return;
+ }
+ break;
+#endif
+#ifdef CR_IBM_rasterpos_clip
+ case GL_RASTER_POSITION_UNCLIPPED_IBM:
+ g->transform.rasterPositionUnclipped = val;
+ DIRTY(sb->transform.enable, neg_bitid);
+ DIRTY(sb->transform.dirty, neg_bitid);
+ break;
+#endif
+
+#ifdef CR_ARB_point_sprite
+ case GL_POINT_SPRITE_ARB:
+ g->point.pointSprite = val;
+ DIRTY(sb->point.enableSprite, neg_bitid);
+ DIRTY(sb->point.dirty, neg_bitid);
+ break;
+#endif
+
+ /* Client-side enables */
+ case GL_VERTEX_ARRAY:
+ case GL_COLOR_ARRAY:
+ case GL_NORMAL_ARRAY:
+ case GL_INDEX_ARRAY:
+ case GL_TEXTURE_COORD_ARRAY:
+ case GL_EDGE_FLAG_ARRAY:
+#ifdef CR_EXT_fog_coord
+ case GL_FOG_COORDINATE_ARRAY_POINTER_EXT:
+#endif
+#ifdef CR_EXT_secondary_color
+ case GL_SECONDARY_COLOR_ARRAY_EXT:
+#endif
+#ifdef CR_NV_vertex_program
+ case GL_VERTEX_ATTRIB_ARRAY0_NV:
+ case GL_VERTEX_ATTRIB_ARRAY1_NV:
+ case GL_VERTEX_ATTRIB_ARRAY2_NV:
+ case GL_VERTEX_ATTRIB_ARRAY3_NV:
+ case GL_VERTEX_ATTRIB_ARRAY4_NV:
+ case GL_VERTEX_ATTRIB_ARRAY5_NV:
+ case GL_VERTEX_ATTRIB_ARRAY6_NV:
+ case GL_VERTEX_ATTRIB_ARRAY7_NV:
+ case GL_VERTEX_ATTRIB_ARRAY8_NV:
+ case GL_VERTEX_ATTRIB_ARRAY9_NV:
+ case GL_VERTEX_ATTRIB_ARRAY10_NV:
+ case GL_VERTEX_ATTRIB_ARRAY11_NV:
+ case GL_VERTEX_ATTRIB_ARRAY12_NV:
+ case GL_VERTEX_ATTRIB_ARRAY13_NV:
+ case GL_VERTEX_ATTRIB_ARRAY14_NV:
+ case GL_VERTEX_ATTRIB_ARRAY15_NV:
+#endif
+ if (val)
+ crStateEnableClientState(cap);
+ 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;
+ }
+}
+
+
+void STATE_APIENTRY crStateEnable (GLenum cap)
+{
+ CRContext *g = GetCurrentContext();
+ CRStateBits *sb = GetCurrentBits();
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glEnable called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ __enableSet(g, sb, g->neg_bitid, cap, GL_TRUE);
+}
+
+
+void STATE_APIENTRY crStateDisable (GLenum cap)
+{
+ CRContext *g = GetCurrentContext();
+ CRStateBits *sb = GetCurrentBits();
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glDisable called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ __enableSet(g, sb, g->neg_bitid, cap, GL_FALSE);
+}
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_error.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_error.c
new file mode 100644
index 00000000..07a7b494
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_error.c
@@ -0,0 +1,86 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#include "state/cr_stateerror.h"
+#include "state/cr_statetypes.h"
+#include "state.h"
+#include "cr_error.h"
+#include "cr_environment.h"
+#include <stdarg.h>
+#include <stdio.h>
+
+void crStateError( int line, const char *file, GLenum error, const char *format, ... )
+{
+ CRContext *g = GetCurrentContext();
+ char errstr[8096];
+ va_list args;
+
+ 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 );
+ vsprintf( errstr, format, args );
+ va_end( args );
+
+ switch (error) {
+ case GL_NO_ERROR:
+ glerr = "GL_NO_ERROR";
+ break;
+ case GL_INVALID_VALUE:
+ glerr = "GL_INVALID_VALUE";
+ break;
+ case GL_INVALID_ENUM:
+ glerr = "GL_INVALID_ENUM";
+ break;
+ case GL_INVALID_OPERATION:
+ glerr = "GL_INVALID_OPERATION";
+ break;
+ case GL_STACK_OVERFLOW:
+ glerr = "GL_STACK_OVERFLOW";
+ break;
+ case GL_STACK_UNDERFLOW:
+ glerr = "GL_STACK_UNDERFLOW";
+ break;
+ case GL_OUT_OF_MEMORY:
+ glerr = "GL_OUT_OF_MEMORY";
+ break;
+ case GL_TABLE_TOO_LARGE:
+ glerr = "GL_TABLE_TOO_LARGE";
+ break;
+ default:
+ glerr = "unknown";
+ break;
+ }
+
+ crWarning( "OpenGL error in %s, line %d: %s: %s\n",
+ file, line, glerr, errstr );
+ }
+}
+
+
+GLenum STATE_APIENTRY crStateGetError(void)
+{
+ CRContext *g = GetCurrentContext();
+ GLenum e = g->error;
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError( __LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glStateGetError() called between glBegin/glEnd" );
+ return 0;
+ }
+
+ g->error = GL_NO_ERROR;
+
+ return e;
+}
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_evaluators.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_evaluators.c
new file mode 100644
index 00000000..0219994d
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_evaluators.c
@@ -0,0 +1,1084 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+/*
+ * The majority of this file is pulled from Mesa 4.0.x with the
+ * permission of Brian Paul
+ */
+
+#include <stdio.h>
+#include "cr_mem.h"
+#include "state.h"
+#include "state/cr_statetypes.h"
+#include "state_internals.h"
+
+/* free the 1-D evaluator map */
+static void
+free_1d_map(CRContext *ctx, GLenum map)
+{
+ CREvaluatorState *e = &ctx->eval;
+ const GLint k = map - GL_MAP1_COLOR_4;
+
+ crFree( e->eval1D[k].coeff );
+}
+
+/* free the 2-D evaluator map */
+static void
+free_2d_map(CRContext *ctx, GLenum map)
+{
+ CREvaluatorState *e = &ctx->eval;
+ const GLint k = map - GL_MAP2_COLOR_4;
+
+ crFree( e->eval2D[k].coeff );
+}
+
+/* Initialize a 1-D evaluator map */
+static void
+init_1d_map(CRContext *ctx, GLenum map, int n, const float *initial)
+{
+ CREvaluatorState *e = &ctx->eval;
+ CRStateBits *sb = GetCurrentBits();
+ CREvaluatorBits *eb = &(sb->eval);
+ GLint i;
+ const GLint k = map - GL_MAP1_COLOR_4;
+ CRASSERT(k >= 0);
+ CRASSERT(k < GLEVAL_TOT);
+ e->eval1D[k].u1 = 0.0;
+ e->eval1D[k].u2 = 1.0;
+ e->eval1D[k].du = 0.0;
+ e->eval1D[k].order = 1;
+ e->eval1D[k].coeff = (GLfloat *) crAlloc(n * sizeof(GLfloat));
+ for (i = 0; i < n; i++)
+ e->eval1D[k].coeff[i] = initial[i];
+ RESET(eb->eval1D[i], ctx->bitid);
+}
+
+
+/* Initialize a 2-D evaluator map */
+static void
+init_2d_map(CRContext *ctx, GLenum map, int n, const float *initial)
+{
+ CREvaluatorState *e = &ctx->eval;
+ CRStateBits *sb = GetCurrentBits();
+ CREvaluatorBits *eb = &(sb->eval);
+ GLint i;
+ const GLint k = map - GL_MAP2_COLOR_4;
+ CRASSERT(k >= 0);
+ CRASSERT(k < GLEVAL_TOT);
+ e->eval2D[k].u1 = 0.0;
+ e->eval2D[k].u2 = 1.0;
+ e->eval2D[k].du = 0.0;
+ e->eval2D[k].v1 = 0.0;
+ e->eval2D[k].v2 = 1.0;
+ e->eval2D[k].dv = 0.0;
+ e->eval2D[k].uorder = 1;
+ e->eval2D[k].vorder = 1;
+ e->eval2D[k].coeff = (GLfloat *) crAlloc(n * sizeof(GLfloat));
+ for (i = 0; i < n; i++)
+ e->eval2D[k].coeff[i] = initial[i];
+ RESET(eb->eval2D[i], ctx->bitid);
+}
+
+void
+crStateEvaluatorDestroy(CRContext *ctx)
+{
+ free_1d_map(ctx, GL_MAP1_VERTEX_3);
+ free_1d_map(ctx, GL_MAP1_VERTEX_4);
+ free_1d_map(ctx, GL_MAP1_INDEX);
+ free_1d_map(ctx, GL_MAP1_COLOR_4);
+ free_1d_map(ctx, GL_MAP1_NORMAL);
+ free_1d_map(ctx, GL_MAP1_TEXTURE_COORD_1);
+ free_1d_map(ctx, GL_MAP1_TEXTURE_COORD_2);
+ free_1d_map(ctx, GL_MAP1_TEXTURE_COORD_3);
+ free_1d_map(ctx, GL_MAP1_TEXTURE_COORD_4);
+
+ free_2d_map(ctx, GL_MAP2_VERTEX_3);
+ free_2d_map(ctx, GL_MAP2_VERTEX_4);
+ free_2d_map(ctx, GL_MAP2_INDEX);
+ free_2d_map(ctx, GL_MAP2_COLOR_4);
+ free_2d_map(ctx, GL_MAP2_NORMAL);
+ free_2d_map(ctx, GL_MAP2_TEXTURE_COORD_1);
+ free_2d_map(ctx, GL_MAP2_TEXTURE_COORD_2);
+ free_2d_map(ctx, GL_MAP2_TEXTURE_COORD_3);
+ free_2d_map(ctx, GL_MAP2_TEXTURE_COORD_4);
+}
+
+void
+crStateEvaluatorInit(CRContext *ctx)
+{
+ CREvaluatorState *e = &ctx->eval;
+ CRStateBits *sb = GetCurrentBits();
+ CREvaluatorBits *eb = &(sb->eval);
+ static GLfloat vertex[4] = { 0.0, 0.0, 0.0, 1.0 };
+ static GLfloat normal[3] = { 0.0, 0.0, 1.0 };
+ static GLfloat index[1] = { 1.0 };
+ static GLfloat color[4] = { 1.0, 1.0, 1.0, 1.0 };
+ static GLfloat texcoord[4] = { 0.0, 0.0, 0.0, 1.0 };
+
+ e->autoNormal = GL_FALSE;
+ RESET(eb->enable, ctx->bitid);
+
+ init_1d_map(ctx, GL_MAP1_VERTEX_3, 3, vertex);
+ init_1d_map(ctx, GL_MAP1_VERTEX_4, 4, vertex);
+ init_1d_map(ctx, GL_MAP1_INDEX, 1, index);
+ init_1d_map(ctx, GL_MAP1_COLOR_4, 4, color);
+ init_1d_map(ctx, GL_MAP1_NORMAL, 3, normal);
+ init_1d_map(ctx, GL_MAP1_TEXTURE_COORD_1, 1, texcoord);
+ init_1d_map(ctx, GL_MAP1_TEXTURE_COORD_2, 2, texcoord);
+ init_1d_map(ctx, GL_MAP1_TEXTURE_COORD_3, 3, texcoord);
+ init_1d_map(ctx, GL_MAP1_TEXTURE_COORD_4, 4, texcoord);
+
+ init_2d_map(ctx, GL_MAP2_VERTEX_3, 3, vertex);
+ init_2d_map(ctx, GL_MAP2_VERTEX_4, 4, vertex);
+ init_2d_map(ctx, GL_MAP2_INDEX, 1, index);
+ init_2d_map(ctx, GL_MAP2_COLOR_4, 4, color);
+ init_2d_map(ctx, GL_MAP2_NORMAL, 3, normal);
+ init_2d_map(ctx, GL_MAP2_TEXTURE_COORD_1, 1, texcoord);
+ init_2d_map(ctx, GL_MAP2_TEXTURE_COORD_2, 2, texcoord);
+ init_2d_map(ctx, GL_MAP2_TEXTURE_COORD_3, 3, texcoord);
+ init_2d_map(ctx, GL_MAP2_TEXTURE_COORD_4, 4, texcoord);
+
+ e->un1D = 1;
+ e->u11D = 0.0;
+ e->u21D = 1.0;
+ RESET(eb->grid1D, ctx->bitid);
+
+ e->un2D = 1;
+ e->vn2D = 1;
+ e->u12D = 0.0;
+ e->u22D = 1.0;
+ e->v12D = 0.0;
+ e->v22D = 1.0;
+ RESET(eb->grid1D, ctx->bitid);
+
+ RESET(eb->dirty, ctx->bitid);
+}
+
+const int gleval_sizes[] = { 4, 1, 3, 1, 2, 3, 4, 3, 4 };
+
+/**********************************************************************/
+/*** Copy and deallocate control points ***/
+/**********************************************************************/
+
+
+/*
+ * Copy 1-parametric evaluator control points from user-specified
+ * memory space to a buffer of contiguous control points.
+ * Input: see glMap1f for details
+ * Return: pointer to buffer of contiguous control points or NULL if out
+ * of memory.
+ */
+static GLfloat *
+_copy_map_points1f(GLint size, GLint ustride, GLint uorder,
+ const GLfloat * points)
+{
+ GLfloat *buffer, *p;
+ GLint i, k;
+
+ if (!points || size == 0) {
+ return NULL;
+ }
+
+ buffer = (GLfloat *) crAlloc(uorder * size * sizeof(GLfloat));
+
+ if (buffer)
+ for (i = 0, p = buffer; i < uorder; i++, points += ustride)
+ for (k = 0; k < size; k++)
+ *p++ = points[k];
+
+ return buffer;
+}
+
+
+
+/*
+ * Same as above but convert doubles to floats.
+ */
+static GLfloat *
+_copy_map_points1d(GLint size, GLint ustride, GLint uorder,
+ const GLdouble * points)
+{
+ GLfloat *buffer, *p;
+ GLint i, k;
+
+ if (!points || size == 0) {
+ return NULL;
+ }
+
+ buffer = (GLfloat *) crAlloc(uorder * size * sizeof(GLfloat));
+
+ if (buffer)
+ for (i = 0, p = buffer; i < uorder; i++, points += ustride)
+ for (k = 0; k < size; k++)
+ *p++ = (GLfloat) points[k];
+
+ return buffer;
+}
+
+
+
+/*
+ * Copy 2-parametric evaluator control points from user-specified
+ * memory space to a buffer of contiguous control points.
+ * Additional memory is allocated to be used by the Horner and
+ * de Casteljau evaluation schemes.
+ *
+ * Input: see glMap2f for details
+ * Return: pointer to buffer of contiguous control points or NULL if out
+ * of memory.
+ */
+static GLfloat *
+_copy_map_points2f(GLint size,
+ GLint ustride, GLint uorder,
+ GLint vstride, GLint vorder, const GLfloat * points)
+{
+ GLfloat *buffer, *p;
+ GLint i, j, k, dsize, hsize;
+ GLint uinc;
+
+ if (!points || size == 0) {
+ return NULL;
+ }
+
+ /* max(uorder, vorder) additional points are used in */
+ /* Horner evaluation and uorder*vorder additional */
+ /* values are needed for de Casteljau */
+ dsize = (uorder == 2 && vorder == 2) ? 0 : uorder * vorder;
+ hsize = (uorder > vorder ? uorder : vorder) * size;
+
+ if (hsize > dsize)
+ buffer =
+ (GLfloat *) crAlloc((uorder * vorder * size + hsize) * sizeof(GLfloat));
+ else
+ buffer =
+ (GLfloat *) crAlloc((uorder * vorder * size + dsize) * sizeof(GLfloat));
+
+ /* compute the increment value for the u-loop */
+ uinc = ustride - vorder * vstride;
+
+ if (buffer)
+ for (i = 0, p = buffer; i < uorder; i++, points += uinc)
+ for (j = 0; j < vorder; j++, points += vstride)
+ for (k = 0; k < size; k++)
+ *p++ = points[k];
+
+ return buffer;
+}
+
+
+
+/*
+ * Same as above but convert doubles to floats.
+ */
+static GLfloat *
+_copy_map_points2d(GLint size,
+ GLint ustride, GLint uorder,
+ GLint vstride, GLint vorder, const GLdouble * points)
+{
+ GLfloat *buffer, *p;
+ GLint i, j, k, hsize, dsize;
+ GLint uinc;
+
+ if (!points || size == 0) {
+ return NULL;
+ }
+
+ /* max(uorder, vorder) additional points are used in */
+ /* Horner evaluation and uorder*vorder additional */
+ /* values are needed for de Casteljau */
+ dsize = (uorder == 2 && vorder == 2) ? 0 : uorder * vorder;
+ hsize = (uorder > vorder ? uorder : vorder) * size;
+
+ if (hsize > dsize)
+ buffer =
+ (GLfloat *) crAlloc((uorder * vorder * size + hsize) * sizeof(GLfloat));
+ else
+ buffer =
+ (GLfloat *) crAlloc((uorder * vorder * size + dsize) * sizeof(GLfloat));
+
+ /* compute the increment value for the u-loop */
+ uinc = ustride - vorder * vstride;
+
+ if (buffer)
+ for (i = 0, p = buffer; i < uorder; i++, points += uinc)
+ for (j = 0; j < vorder; j++, points += vstride)
+ for (k = 0; k < size; k++)
+ *p++ = (GLfloat) points[k];
+
+ return buffer;
+}
+
+
+
+
+/**********************************************************************/
+/*** API entry points ***/
+/**********************************************************************/
+
+
+/*
+ * This does the work of glMap1[fd].
+ */
+static void
+map1(GLenum target, GLfloat u1, GLfloat u2, GLint ustride,
+ GLint uorder, const GLvoid * points, GLenum type)
+{
+ CRContext *g = GetCurrentContext();
+ CREvaluatorState *e = &(g->eval);
+ CRStateBits *sb = GetCurrentBits();
+ CREvaluatorBits *eb = &(sb->eval);
+ CRTextureState *t = &(g->texture);
+ GLint i;
+ GLint k;
+ GLfloat *pnts;
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "Map1d called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ CRASSERT(type == GL_FLOAT || type == GL_DOUBLE);
+
+ if (u1 == u2) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glMap1d(u1==u2)");
+ return;
+ }
+ if (uorder < 1 || uorder > MAX_EVAL_ORDER) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glMap1d(bad uorder)");
+ return;
+ }
+ if (!points) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glMap1d(null points)");
+ return;
+ }
+
+ i = target - GL_MAP1_COLOR_4;
+
+ k = gleval_sizes[i];
+
+ if (k == 0) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glMap1d(k=0)");
+ return;
+ }
+
+ if (ustride < k) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glMap1d(bad ustride");
+ return;
+ }
+
+ if (t->curTextureUnit != 0) {
+ /* See OpenGL 1.2.1 spec, section F.2.13 */
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glMap1d(current texture unit must be zero)");
+ return;
+ }
+
+ switch (target) {
+ case GL_MAP1_VERTEX_3:
+ case GL_MAP1_VERTEX_4:
+ case GL_MAP1_INDEX:
+ case GL_MAP1_COLOR_4:
+ case GL_MAP1_NORMAL:
+ case GL_MAP1_TEXTURE_COORD_1:
+ case GL_MAP1_TEXTURE_COORD_2:
+ case GL_MAP1_TEXTURE_COORD_3:
+ case GL_MAP1_TEXTURE_COORD_4:
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glMap1d(bad target)");
+ return;
+ }
+
+ /* make copy of the control points */
+ if (type == GL_FLOAT)
+ pnts = _copy_map_points1f(k, ustride, uorder, (GLfloat *) points);
+ else
+ pnts = _copy_map_points1d(k, ustride, uorder, (GLdouble *) points);
+
+ e->eval1D[i].order = uorder;
+ e->eval1D[i].u1 = u1;
+ e->eval1D[i].u2 = u2;
+ e->eval1D[i].du = 1.0f / (u2 - u1);
+ if (e->eval1D[i].coeff)
+ crFree(e->eval1D[i].coeff);
+ e->eval1D[i].coeff = pnts;
+
+ DIRTY(eb->dirty, g->neg_bitid);
+ DIRTY(eb->eval1D[i], g->neg_bitid);
+}
+
+
+
+void STATE_APIENTRY
+crStateMap1f(GLenum target, GLfloat u1, GLfloat u2,
+ GLint stride, GLint order, const GLfloat * points)
+{
+ map1(target, u1, u2, stride, order, points, GL_FLOAT);
+}
+
+void STATE_APIENTRY
+crStateMap1d(GLenum target, GLdouble u1, GLdouble u2, GLint stride,
+ GLint order, const GLdouble * points)
+{
+ map1(target, (GLfloat) u1, (GLfloat) u2, stride, order, points, GL_DOUBLE);
+}
+
+static void
+map2(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder,
+ GLfloat v1, GLfloat v2, GLint vstride, GLint vorder,
+ const GLvoid * points, GLenum type)
+{
+ CRContext *g = GetCurrentContext();
+ CRStateBits *sb = GetCurrentBits();
+ CREvaluatorState *e = &(g->eval);
+ CREvaluatorBits *eb = &(sb->eval);
+#if 0
+ CRTextureState *t = &(g->texture);
+#endif
+ GLint i;
+ GLint k;
+ GLfloat *pnts;
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glMap2d()");
+ return;
+ }
+
+ FLUSH();
+
+ if (u1 == u2) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glMap2d()");
+ return;
+ }
+
+ if (v1 == v2) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glMap2d()");
+ return;
+ }
+
+ if (uorder < 1 || uorder > MAX_EVAL_ORDER) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glMap2d()");
+ return;
+ }
+
+ if (vorder < 1 || vorder > MAX_EVAL_ORDER) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glMap2d()");
+ return;
+ }
+
+ if (g->extensions.NV_vertex_program) {
+/* XXX FIXME */
+ i = target - GL_MAP2_COLOR_4;
+ } else {
+ i = target - GL_MAP2_COLOR_4;
+ }
+
+ k = gleval_sizes[i];
+
+ if (k == 0) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glMap2d()");
+ return;
+ }
+
+ if (ustride < k) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glMap2d()");
+ return;
+ }
+ if (vstride < k) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glMap2d()");
+ return;
+ }
+
+#if 00
+ /* Disable this check for now - it looks like various OpenGL drivers
+ * don't do this error check. So, a bunch of the NVIDIA demos
+ * generate errors/warnings.
+ */
+ if (t->curTextureUnit != 0) {
+ /* See OpenGL 1.2.1 spec, section F.2.13 */
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glMap2d()");
+ return;
+ }
+#endif
+
+ switch (target) {
+ case GL_MAP2_VERTEX_3:
+ case GL_MAP2_VERTEX_4:
+ case GL_MAP2_INDEX:
+ case GL_MAP2_COLOR_4:
+ case GL_MAP2_NORMAL:
+ case GL_MAP2_TEXTURE_COORD_1:
+ case GL_MAP2_TEXTURE_COORD_2:
+ case GL_MAP2_TEXTURE_COORD_3:
+ case GL_MAP2_TEXTURE_COORD_4:
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glMap2d()");
+ return;
+ }
+
+ /* make copy of the control points */
+ if (type == GL_FLOAT)
+ pnts = _copy_map_points2f(k, ustride, uorder,
+ vstride, vorder, (GLfloat *) points);
+ else
+ pnts = _copy_map_points2d(k, ustride, uorder,
+ vstride, vorder, (GLdouble *) points);
+
+ e->eval2D[i].uorder = uorder;
+ e->eval2D[i].u1 = u1;
+ e->eval2D[i].u2 = u2;
+ e->eval2D[i].du = 1.0f / (u2 - u1);
+ e->eval2D[i].vorder = vorder;
+ e->eval2D[i].v1 = v1;
+ e->eval2D[i].v2 = v2;
+ e->eval2D[i].dv = 1.0f / (v2 - v1);
+ if (e->eval2D[i].coeff)
+ crFree(e->eval2D[i].coeff);
+ e->eval2D[i].coeff = pnts;
+
+ DIRTY(eb->dirty, g->neg_bitid);
+ DIRTY(eb->eval2D[i], g->neg_bitid);
+}
+
+void STATE_APIENTRY
+crStateMap2f(GLenum target, GLfloat u1, GLfloat u2,
+ GLint ustride, GLint uorder,
+ GLfloat v1, GLfloat v2,
+ GLint vstride, GLint vorder, const GLfloat * points)
+{
+ map2(target, u1, u2, ustride, uorder, v1, v2, vstride, vorder,
+ points, GL_FLOAT);
+}
+
+
+void STATE_APIENTRY
+crStateMap2d(GLenum target, GLdouble u1, GLdouble u2,
+ GLint ustride, GLint uorder,
+ GLdouble v1, GLdouble v2,
+ GLint vstride, GLint vorder, const GLdouble * points)
+{
+ map2(target, (GLfloat) u1, (GLfloat) u2, ustride, uorder,
+ (GLfloat) v1, (GLfloat) v2, vstride, vorder, points, GL_DOUBLE);
+}
+
+void STATE_APIENTRY
+crStateGetMapdv(GLenum target, GLenum query, GLdouble * v)
+{
+ CRContext *g = GetCurrentContext();
+ CRStateBits *sb = GetCurrentBits();
+ CREvaluatorState *e = &(g->eval);
+ GLint size;
+ GLint i, j;
+ (void) sb;
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "Map1d called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ i = target - GL_MAP1_COLOR_4;
+
+ if (i < 0 || i >= GLEVAL_TOT) {
+ i = target - GL_MAP2_COLOR_4;
+
+ if (i < 0 || i >= GLEVAL_TOT) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "GetMapdv: invalid target: %d", target);
+ return;
+ }
+
+ switch (query) {
+ case GL_COEFF:
+ size = gleval_sizes[i] * e->eval2D[i].uorder * e->eval2D[i].vorder;
+ for (j = 0; j < size; j++) {
+ v[j] = e->eval2D[i].coeff[j];
+ }
+ break;
+ case GL_ORDER:
+ v[0] = (GLdouble) e->eval2D[i].uorder;
+ v[1] = (GLdouble) e->eval2D[i].vorder;
+ break;
+ case GL_DOMAIN:
+ v[0] = e->eval2D[i].u1;
+ v[1] = e->eval2D[i].u2;
+ v[2] = e->eval2D[i].v1;
+ v[3] = e->eval2D[i].v2;
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "GetMapdv: invalid target: %d", target);
+ return;
+ }
+ }
+ else {
+ switch (query) {
+ case GL_COEFF:
+ size = gleval_sizes[i] * e->eval1D[i].order;
+ for (j = 0; j < size; j++) {
+ v[j] = e->eval1D[i].coeff[j];
+ }
+ break;
+ case GL_ORDER:
+ *v = (GLdouble) e->eval1D[i].order;
+ break;
+ case GL_DOMAIN:
+ v[0] = e->eval1D[i].u1;
+ v[1] = e->eval1D[i].u2;
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "GetMapdv: invalid target: %d", target);
+ return;
+ }
+ }
+}
+
+void STATE_APIENTRY
+crStateGetMapfv(GLenum target, GLenum query, GLfloat * v)
+{
+ CRContext *g = GetCurrentContext();
+ CRStateBits *sb = GetCurrentBits();
+ CREvaluatorState *e = &(g->eval);
+ GLint size;
+ GLint i, j;
+ (void) sb;
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "Map1d called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ i = target - GL_MAP1_COLOR_4;
+ if (i < 0 || i >= GLEVAL_TOT) {
+ i = target - GL_MAP2_COLOR_4;
+ if (i < 0 || i >= GLEVAL_TOT) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "GetMapfv: invalid target: %d", target);
+ return;
+ }
+ switch (query) {
+ case GL_COEFF:
+ size = gleval_sizes[i] * e->eval2D[i].uorder * e->eval2D[i].vorder;
+ for (j = 0; j < size; j++) {
+ v[j] = (GLfloat) e->eval2D[i].coeff[j];
+ }
+ break;
+ case GL_ORDER:
+ v[0] = (GLfloat) e->eval2D[i].uorder;
+ v[1] = (GLfloat) e->eval2D[i].vorder;
+ break;
+ case GL_DOMAIN:
+ v[0] = (GLfloat) e->eval2D[i].u1;
+ v[1] = (GLfloat) e->eval2D[i].u2;
+ v[2] = (GLfloat) e->eval2D[i].v1;
+ v[3] = (GLfloat) e->eval2D[i].v2;
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "GetMapfv: invalid target: %d", target);
+ return;
+ }
+ }
+ else {
+ switch (query) {
+ case GL_COEFF:
+ size = gleval_sizes[i] * e->eval1D[i].order;
+ for (j = 0; j < size; j++) {
+ v[j] = (GLfloat) e->eval1D[i].coeff[j];
+ }
+ break;
+ case GL_ORDER:
+ *v = (GLfloat) e->eval1D[i].order;
+ break;
+ case GL_DOMAIN:
+ v[0] = (GLfloat) e->eval1D[i].u1;
+ v[1] = (GLfloat) e->eval1D[i].u2;
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "GetMapfv: invalid target: %d", target);
+ return;
+ }
+ }
+}
+
+void STATE_APIENTRY
+crStateGetMapiv(GLenum target, GLenum query, GLint * v)
+{
+ CRContext *g = GetCurrentContext();
+ CRStateBits *sb = GetCurrentBits();
+ CREvaluatorState *e = &(g->eval);
+ GLint size;
+ GLint i, j;
+ (void) sb;
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "Map1d called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ i = target - GL_MAP1_COLOR_4;
+ if (i < 0 || i >= GLEVAL_TOT) {
+ i = target - GL_MAP2_COLOR_4;
+ if (i < 0 || i >= GLEVAL_TOT) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "GetMapiv: invalid target: %d", target);
+ return;
+ }
+ switch (query) {
+ case GL_COEFF:
+ size = gleval_sizes[i] * e->eval2D[i].uorder * e->eval2D[i].vorder;
+ for (j = 0; j < size; j++) {
+ v[j] = (GLint) e->eval2D[i].coeff[j];
+ }
+ break;
+ case GL_ORDER:
+ v[0] = e->eval2D[i].uorder;
+ v[1] = e->eval2D[i].vorder;
+ break;
+ case GL_DOMAIN:
+ v[0] = (GLint) e->eval2D[i].u1;
+ v[1] = (GLint) e->eval2D[i].u2;
+ v[2] = (GLint) e->eval2D[i].v1;
+ v[3] = (GLint) e->eval2D[i].v2;
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "GetMapiv: invalid target: %d", target);
+ return;
+ }
+ }
+ else {
+ switch (query) {
+ case GL_COEFF:
+ size = gleval_sizes[i] * e->eval1D[i].order;
+ for (j = 0; j < size; j++) {
+ v[j] = (GLint) e->eval1D[i].coeff[j];
+ }
+ break;
+ case GL_ORDER:
+ *v = e->eval1D[i].order;
+ break;
+ case GL_DOMAIN:
+ v[0] = (GLint) e->eval1D[i].u1;
+ v[1] = (GLint) e->eval1D[i].u2;
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "GetMapiv: invalid target: %d", target);
+ return;
+ }
+ }
+}
+
+void STATE_APIENTRY
+crStateMapGrid1f(GLint un, GLfloat u1, GLfloat u2)
+{
+ CRContext *g = GetCurrentContext();
+ CRStateBits *sb = GetCurrentBits();
+ CREvaluatorState *e = &(g->eval);
+ CREvaluatorBits *eb = &(sb->eval);
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "Map1d called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ if (un < 1) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glMapGrid1f(bad un)");
+ return;
+ }
+
+ e->un1D = un;
+ e->u11D = u1;
+ e->u21D = u2;
+
+ DIRTY(eb->dirty, g->neg_bitid);
+ DIRTY(eb->grid1D, g->neg_bitid);
+}
+
+void STATE_APIENTRY
+crStateMapGrid1d(GLint un, GLdouble u1, GLdouble u2)
+{
+ crStateMapGrid1f(un, (GLfloat) u1, (GLfloat) u2);
+}
+
+
+void STATE_APIENTRY
+crStateMapGrid2f(GLint un, GLfloat u1, GLfloat u2,
+ GLint vn, GLfloat v1, GLfloat v2)
+{
+ CRContext *g = GetCurrentContext();
+ CRStateBits *sb = GetCurrentBits();
+ CREvaluatorState *e = &(g->eval);
+ CREvaluatorBits *eb = &(sb->eval);
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "Map1d called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ if (un < 1) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glMapGrid2f(bad un)");
+ return;
+ }
+ if (vn < 1) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glMapGrid2f(bad vn)");
+ return;
+ }
+
+ e->un2D = un;
+ e->vn2D = vn;
+ e->u12D = u1;
+ e->u22D = u2;
+ e->v12D = v1;
+ e->v22D = v2;
+
+ DIRTY(eb->dirty, g->neg_bitid);
+ DIRTY(eb->grid2D, g->neg_bitid);
+}
+
+void STATE_APIENTRY
+crStateMapGrid2d(GLint un, GLdouble u1, GLdouble u2,
+ GLint vn, GLdouble v1, GLdouble v2)
+{
+ crStateMapGrid2f(un, (GLfloat) u1, (GLfloat) u2,
+ vn, (GLfloat) v1, (GLfloat) v2);
+}
+
+void
+crStateEvaluatorSwitch(CREvaluatorBits *e, CRbitvalue * bitID,
+ CRContext *fromCtx, CRContext *toCtx)
+{
+ CREvaluatorState *from = &(fromCtx->eval);
+ CREvaluatorState *to = &(toCtx->eval);
+ int i, j;
+ CRbitvalue nbitID[CR_MAX_BITARRAY];
+
+ for (j = 0; j < CR_MAX_BITARRAY; j++)
+ nbitID[j] = ~bitID[j];
+
+ if (CHECKDIRTY(e->enable, bitID)) {
+ if (from->autoNormal != to->autoNormal) {
+ glAble able[2];
+ able[0] = diff_api.Disable;
+ able[1] = diff_api.Enable;
+ able[to->autoNormal] (GL_AUTO_NORMAL);
+ FILLDIRTY(e->enable);
+ FILLDIRTY(e->dirty);
+ }
+ CLEARDIRTY(e->enable, nbitID);
+ }
+ for (i = 0; i < GLEVAL_TOT; i++) {
+ if (CHECKDIRTY(e->eval1D[i], bitID)) {
+ int size = from->eval1D[i].order * gleval_sizes[i] *
+ sizeof(*from->eval1D[i].coeff);
+ if (from->eval1D[i].order != to->eval1D[i].order ||
+ from->eval1D[i].u1 != to->eval1D[i].u1 ||
+ from->eval1D[i].u2 != to->eval1D[i].u2 ||
+ crMemcmp((const void *) from->eval1D[i].coeff,
+ (const void *) to->eval1D[i].coeff, size)) {
+ diff_api.Map1f(i + GL_MAP1_COLOR_4, to->eval1D[i].u1,
+ to->eval1D[i].u2, gleval_sizes[i], to->eval1D[i].order,
+ to->eval1D[i].coeff);
+ FILLDIRTY(e->dirty);
+ FILLDIRTY(e->eval1D[i]);
+ }
+ CLEARDIRTY(e->eval1D[i], nbitID);
+ }
+ }
+
+ for (i = 0; i < GLEVAL_TOT; i++) {
+ if (CHECKDIRTY(e->eval2D[i], bitID)) {
+ int size = from->eval2D[i].uorder * from->eval2D[i].vorder
+ * gleval_sizes[i] * sizeof(*from->eval2D[i].coeff);
+ if (from->eval2D[i].uorder != to->eval2D[i].uorder ||
+ from->eval2D[i].vorder != to->eval2D[i].vorder ||
+ from->eval2D[i].u1 != to->eval2D[i].u1 ||
+ from->eval2D[i].u2 != to->eval2D[i].u2 ||
+ from->eval2D[i].v1 != to->eval2D[i].v1 ||
+ from->eval2D[i].v2 != to->eval2D[i].v2 ||
+ crMemcmp((const void *) from->eval2D[i].coeff,
+ (const void *) to->eval2D[i].coeff, size)) {
+ diff_api.Map2f(i + GL_MAP2_COLOR_4,
+ to->eval2D[i].u1, to->eval2D[i].u2,
+ gleval_sizes[i], to->eval2D[i].uorder,
+ to->eval2D[i].v1, to->eval2D[i].v2,
+ gleval_sizes[i], to->eval2D[i].vorder,
+ to->eval2D[i].coeff);
+ FILLDIRTY(e->dirty);
+ FILLDIRTY(e->eval2D[i]);
+ }
+ CLEARDIRTY(e->eval2D[i], nbitID);
+ }
+ }
+ if (CHECKDIRTY(e->grid1D, bitID)) {
+ if (from->u11D != to->u11D ||
+ from->u21D != to->u21D ||
+ from->un1D != to->un1D) {
+ diff_api.MapGrid1d(to->un1D, to->u11D, to->u21D);
+ FILLDIRTY(e->dirty);
+ FILLDIRTY(e->grid1D);
+ }
+ CLEARDIRTY(e->grid1D, nbitID);
+ }
+ if (CHECKDIRTY(e->grid2D, bitID)) {
+ if (from->u12D != to->u12D ||
+ from->u22D != to->u22D ||
+ from->un2D != to->un2D ||
+ from->v12D != to->v12D ||
+ from->v22D != to->v22D ||
+ from->vn2D != to->vn2D) {
+ diff_api.MapGrid2d(to->un2D, to->u12D, to->u22D,
+ to->vn2D, to->v12D, to->v22D);
+ FILLDIRTY(e->dirty);
+ FILLDIRTY(e->grid1D);
+ }
+ CLEARDIRTY(e->grid1D, nbitID);
+ }
+ CLEARDIRTY(e->dirty, nbitID);
+}
+
+void
+crStateEvaluatorDiff(CREvaluatorBits *e, CRbitvalue *bitID,
+ CRContext *fromCtx, CRContext *toCtx)
+{
+ CREvaluatorState *from = &(fromCtx->eval);
+ CREvaluatorState *to = &(toCtx->eval);
+ glAble able[2];
+ int i, j;
+ CRbitvalue nbitID[CR_MAX_BITARRAY];
+
+ for (j = 0; j < CR_MAX_BITARRAY; j++)
+ nbitID[j] = ~bitID[j];
+
+ able[0] = diff_api.Disable;
+ able[1] = diff_api.Enable;
+
+ if (CHECKDIRTY(e->enable, bitID)) {
+ if (from->autoNormal != to->autoNormal) {
+ able[to->autoNormal] (GL_AUTO_NORMAL);
+ from->autoNormal = to->autoNormal;
+ }
+ CLEARDIRTY(e->enable, nbitID);
+ }
+ for (i = 0; i < GLEVAL_TOT; i++) {
+ if (CHECKDIRTY(e->enable1D[i], bitID)) {
+ if (from->enable1D[i] != to->enable1D[i]) {
+ able[to->enable1D[i]] (i + GL_MAP1_COLOR_4);
+ from->enable1D[i] = to->enable1D[i];
+ }
+ CLEARDIRTY(e->enable1D[i], nbitID);
+ }
+ if (to->enable1D[i] && CHECKDIRTY(e->eval1D[i], bitID)) {
+ int size = from->eval1D[i].order * gleval_sizes[i] *
+ sizeof(*from->eval1D[i].coeff);
+ if (from->eval1D[i].order != to->eval1D[i].order ||
+ from->eval1D[i].u1 != to->eval1D[i].u1 ||
+ from->eval1D[i].u2 != to->eval1D[i].u2 ||
+ crMemcmp((const void *) from->eval1D[i].coeff,
+ (const void *) to->eval1D[i].coeff, size)) {
+ diff_api.Map1f(i + GL_MAP1_COLOR_4, to->eval1D[i].u1,
+ to->eval1D[i].u2, gleval_sizes[i], to->eval1D[i].order,
+ to->eval1D[i].coeff);
+ from->eval1D[i].order = to->eval1D[i].order;
+ from->eval1D[i].u1 = to->eval1D[i].u1;
+ from->eval1D[i].u2 = to->eval1D[i].u2;
+ crMemcpy((void *) from->eval1D[i].coeff,
+ (const void *) to->eval1D[i].coeff, size);
+ }
+ CLEARDIRTY(e->eval1D[i], nbitID);
+ }
+ }
+
+ for (i = 0; i < GLEVAL_TOT; i++) {
+ if (CHECKDIRTY(e->enable2D[i], bitID)) {
+ if (from->enable2D[i] != to->enable2D[i]) {
+ able[to->enable2D[i]] (i + GL_MAP2_COLOR_4);
+ from->enable2D[i] = to->enable2D[i];
+ }
+ CLEARDIRTY(e->enable2D[i], nbitID);
+ }
+ if (to->enable2D[i] && CHECKDIRTY(e->eval2D[i], bitID)) {
+ int size = from->eval2D[i].uorder * from->eval2D[i].vorder
+ * gleval_sizes[i] * sizeof(*from->eval2D[i].coeff);
+ if (from->eval2D[i].uorder != to->eval2D[i].uorder ||
+ from->eval2D[i].vorder != to->eval2D[i].vorder ||
+ from->eval2D[i].u1 != to->eval2D[i].u1 ||
+ from->eval2D[i].u2 != to->eval2D[i].u2 ||
+ from->eval2D[i].v1 != to->eval2D[i].v1 ||
+ from->eval2D[i].v2 != to->eval2D[i].v2 ||
+ crMemcmp((const void *) from->eval2D[i].coeff,
+ (const void *) to->eval2D[i].coeff, size)) {
+ diff_api.Map2f(i + GL_MAP2_COLOR_4,
+ to->eval2D[i].u1, to->eval2D[i].u2,
+ gleval_sizes[i], to->eval2D[i].uorder,
+ to->eval2D[i].v1, to->eval2D[i].v2,
+ gleval_sizes[i], to->eval2D[i].vorder,
+ to->eval2D[i].coeff);
+ from->eval2D[i].uorder = to->eval2D[i].uorder;
+ from->eval2D[i].vorder = to->eval2D[i].vorder;
+ from->eval2D[i].u1 = to->eval2D[i].u1;
+ from->eval2D[i].u2 = to->eval2D[i].u2;
+ from->eval2D[i].v1 = to->eval2D[i].v1;
+ from->eval2D[i].v2 = to->eval2D[i].v2;
+ crMemcpy((void *) from->eval2D[i].coeff,
+ (const void *) to->eval2D[i].coeff, size);
+ }
+ CLEARDIRTY(e->eval2D[i], nbitID);
+ }
+ }
+ if (CHECKDIRTY(e->grid1D, bitID)) {
+ if (from->u11D != to->u11D ||
+ from->u21D != to->u21D ||
+ from->un1D != to->un1D) {
+ diff_api.MapGrid1d(to->un1D, to->u11D, to->u21D);
+ from->u11D = to->u11D;
+ from->u21D = to->u21D;
+ from->un1D = to->un1D;
+ }
+ CLEARDIRTY(e->grid1D, nbitID);
+ }
+ if (CHECKDIRTY(e->grid2D, bitID)) {
+ if (from->u12D != to->u12D ||
+ from->u22D != to->u22D ||
+ from->un2D != to->un2D ||
+ from->v12D != to->v12D ||
+ from->v22D != to->v22D ||
+ from->vn2D != to->vn2D) {
+ diff_api.MapGrid2d(to->un2D, to->u12D, to->u22D,
+ to->vn2D, to->v12D, to->v22D);
+ from->u12D = to->u12D;
+ from->u22D = to->u22D;
+ from->un2D = to->un2D;
+ from->v12D = to->v12D;
+ from->v22D = to->v22D;
+ from->vn2D = to->vn2D;
+ }
+ CLEARDIRTY(e->grid1D, nbitID);
+ }
+ CLEARDIRTY(e->dirty, nbitID);
+}
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_extensions_get.txt b/src/VBox/GuestHost/OpenGL/state_tracker/state_extensions_get.txt
new file mode 100644
index 00000000..7eb5ec35
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_extensions_get.txt
@@ -0,0 +1,138 @@
+# Copyright (c) 2001, Stanford University
+# All rights reserved.
+#
+# See the file LICENSE.txt for information on redistributing this software.
+
+# GL_NV_fog_distance
+
+GLenum GL_FOG_DISTANCE_MODE_NV GL_NV_fog_distance g->fog.fogDistanceMode
+
+
+# GL_EXT_texture_filter_anisotropic
+
+GLenum GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT GL_EXT_texture_filter_anisotropic g->limits.maxTextureAnisotropy
+
+
+# GL_EXT_blend_color
+
+GLclampf GL_BLEND_COLOR_EXT GL_EXT_blend_color g->buffer.blendColor.r g->buffer.blendColor.g g->buffer.blendColor.b g->buffer.blendColor.a
+
+# GL_OPENGL_VERSION_1_2
+
+GLboolean GL_RESCALE_NORMAL GL_OPENGL_VERSION_1_2 g->transform.rescaleNormals
+GLenum GL_LIGHT_MODEL_COLOR_CONTROL GL_OPENGL_VERSION_1_2 g->lighting.lightModelColorControlEXT
+
+# GL_EXT_separate_specular_color
+
+GLenum GL_LIGHT_MODEL_COLOR_CONTROL_EXT GL_EXT_separate_specular_color g->lighting.lightModelColorControlEXT
+
+# GL_EXT_blend_minmax
+
+GLenum GL_BLEND_EQUATION_EXT GL_EXT_blend_minmax g->buffer.blendEquation
+
+# GL_EXT_blend_func_separate
+
+GLenum GL_BLEND_SRC_RGB_EXT GL_EXT_blend_func_separate g->buffer.blendSrcRGB
+GLenum GL_BLEND_DST_RGB_EXT GL_EXT_blend_func_separate g->buffer.blendDstRGB
+GLenum GL_BLEND_SRC_ALPHA_EXT GL_EXT_blend_func_separate g->buffer.blendSrcA
+GLenum GL_BLEND_DST_ALPHA_EXT GL_EXT_blend_func_separate g->buffer.blendDstA
+
+# GL_NV_register_combiners
+
+GLint GL_NUM_GENERAL_COMBINERS_NV GL_NV_register_combiners g->regcombiner.numGeneralCombiners
+GLboolean GL_REGISTER_COMBINERS_NV GL_NV_register_combiners g->regcombiner.enabledRegCombiners
+GLboolean GL_COLOR_SUM_CLAMP_NV GL_NV_register_combiners g->regcombiner.colorSumClamp
+GLfloat GL_CONSTANT_COLOR0_NV GL_NV_register_combiners g->regcombiner.constantColor0.r g->regcombiner.constantColor0.g g->regcombiner.constantColor0.b g->regcombiner.constantColor0.a
+GLfloat GL_CONSTANT_COLOR1_NV GL_NV_register_combiners g->regcombiner.constantColor1.r g->regcombiner.constantColor1.g g->regcombiner.constantColor1.b g->regcombiner.constantColor1.a
+GLint GL_MAX_GENERAL_COMBINERS_NV GL_NV_register_combiners g->limits.maxGeneralCombiners
+
+
+# GL_NV_register_combiners2
+
+GLboolean GL_PER_STAGE_CONSTANTS_NV GL_NV_register_combiners2 g->regcombiner.enabledPerStageConstants
+
+
+# GL_ARB_texture_cube_map
+
+GLboolean GL_TEXTURE_CUBE_MAP_ARB GL_ARB_texture_cube_map g->texture.unit[g->texture.curTextureUnit].enabledCubeMap
+GLint GL_TEXTURE_BINDING_CUBE_MAP_ARB GL_ARB_texture_cube_map g->texture.unit[g->texture.curTextureUnit].currentTextureCubeMap->id
+GLint GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB GL_ARB_texture_cube_map g->limits.maxCubeMapTextureSize
+
+# GL_NV_texture_rectangle
+GLboolean GL_TEXTURE_RECTANGLE_NV GL_NV_texture_rectangle g->texture.unit[g->texture.curTextureUnit].enabledRect
+GLint GL_TEXTURE_BINDING_RECTANGLE_NV GL_NV_texture_rectangle g->texture.unit[g->texture.curTextureUnit].currentTextureRect->id
+GLint GL_MAX_RECTANGLE_TEXTURE_SIZE_NV GL_NV_texture_rectangle g->limits.maxRectTextureSize
+
+# GL_NV_fragment_program
+GLboolean GL_FRAGMENT_PROGRAM_NV GL_NV_fragment_program g->program.fpEnabled
+GLuint GL_MAX_TEXTURE_COORDS_NV GL_NV_fragment_program g->limits.maxTextureCoords
+GLuint GL_MAX_TEXTURE_IMAGE_UNITS_NV GL_NV_fragment_program g->limits.maxTextureImageUnits
+GLuint GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV GL_NV_fragment_program g->limits.maxFragmentProgramLocalParams
+# GLint GL_PROGRAM_ERROR_POSITION_NV GL_NV_fragment_program g->program.errorPos
+GLuint GL_FRAGMENT_PROGRAM_BINDING_NV GL_NV_fragment_program g->program.fpProgramBinding
+
+# GL_NV_vertex_program
+GLboolean GL_VERTEX_PROGRAM_NV GL_any_vertex_program g->program.vpEnabled
+GLint GL_PROGRAM_ERROR_POSITION_NV GL_any_program g->program.errorPos
+GLuint GL_VERTEX_PROGRAM_BINDING_NV GL_NV_vertex_program g->program.vpProgramBinding
+GLboolean GL_VERTEX_PROGRAM_POINT_SIZE_NV GL_any_vertex_program g->program.vpPointSize
+GLboolean GL_VERTEX_PROGRAM_TWO_SIDE_NV GL_any_vertex_program g->program.vpTwoSide
+
+
+# GL_ARB_fragment_program
+GLboolean GL_FRAGMENT_PROGRAM_ARB GL_ARB_fragment_program g->program.fpEnabledARB
+
+
+# GL_ARB_transpose_matrix
+GLdefault GL_TRANSPOSE_MODELVIEW_MATRIX GL_ARB_transpose_matrix g->transform.modelViewStack.top->m00 g->transform.modelViewStack.top->m10 g->transform.modelViewStack.top->m20 g->transform.modelViewStack.top->m30 g->transform.modelViewStack.top->m01 g->transform.modelViewStack.top->m11 g->transform.modelViewStack.top->m21 g->transform.modelViewStack.top->m31 g->transform.modelViewStack.top->m02 g->transform.modelViewStack.top->m12 g->transform.modelViewStack.top->m22 g->transform.modelViewStack.top->m32 g->transform.modelViewStack.top->m03 g->transform.modelViewStack.top->m13 g->transform.modelViewStack.top->m23 g->transform.modelViewStack.top->m33
+GLdefault GL_TRANSPOSE_PROJECTION_MATRIX GL_ARB_transpose_matrix g->transform.projectionStack.top->m00 g->transform.projectionStack.top->m10 g->transform.projectionStack.top->m20 g->transform.projectionStack.top->m30 g->transform.projectionStack.top->m01 g->transform.projectionStack.top->m11 g->transform.projectionStack.top->m21 g->transform.projectionStack.top->m31 g->transform.projectionStack.top->m02 g->transform.projectionStack.top->m12 g->transform.projectionStack.top->m22 g->transform.projectionStack.top->m32 g->transform.projectionStack.top->m03 g->transform.projectionStack.top->m13 g->transform.projectionStack.top->m23 g->transform.projectionStack.top->m33
+GLdefault GL_TRANSPOSE_TEXTURE_MATRIX GL_ARB_transpose_matrix g->transform.textureStack[g->texture.curTextureUnit].top->m00 g->transform.textureStack[g->texture.curTextureUnit].top->m10 g->transform.textureStack[g->texture.curTextureUnit].top->m20 g->transform.textureStack[g->texture.curTextureUnit].top->m30 g->transform.textureStack[g->texture.curTextureUnit].top->m01 g->transform.textureStack[g->texture.curTextureUnit].top->m11 g->transform.textureStack[g->texture.curTextureUnit].top->m21 g->transform.textureStack[g->texture.curTextureUnit].top->m31 g->transform.textureStack[g->texture.curTextureUnit].top->m02 g->transform.textureStack[g->texture.curTextureUnit].top->m12 g->transform.textureStack[g->texture.curTextureUnit].top->m22 g->transform.textureStack[g->texture.curTextureUnit].top->m32 g->transform.textureStack[g->texture.curTextureUnit].top->m03 g->transform.textureStack[g->texture.curTextureUnit].top->m13 g->transform.textureStack[g->texture.curTextureUnit].top->m23 g->transform.textureStack[g->texture.curTextureUnit].top->m33
+
+# GL_ARB_multisample
+
+GLboolean GL_MULTISAMPLE_ARB GL_ARB_multisample g->multisample.enabled
+GLboolean GL_SAMPLE_ALPHA_TO_COVERAGE_ARB GL_ARB_multisample g->multisample.sampleAlphaToCoverage
+GLboolean GL_SAMPLE_ALPHA_TO_ONE_ARB GL_ARB_multisample g->multisample.sampleAlphaToOne
+GLboolean GL_SAMPLE_COVERAGE_ARB GL_ARB_multisample g->multisample.sampleCoverage
+GLint GL_SAMPLE_BUFFERS_ARB GL_ARB_multisample g->limits.sampleBuffers
+GLint GL_SAMPLES_ARB GL_ARB_multisample g->limits.samples
+GLint GL_SAMPLE_COVERAGE_VALUE_ARB GL_ARB_multisample g->multisample.sampleCoverageValue
+GLboolean GL_SAMPLE_COVERAGE_INVERT_ARB GL_ARB_multisample g->multisample.sampleCoverageInvert
+
+# GL_ARB_texture_compression
+
+GLint GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB GL_ARB_texture_compression g->limits.numCompressedFormats
+GLint GL_COMPRESSED_TEXTURE_FORMATS_ARB GL_ARB_texture_compression g->limits.compressedFormats[0]
+GLint GL_TEXTURE_COMPRESSION_HINT_ARB GL_ARB_texture_compression g->hint.textureCompression
+
+# GL_EXT_texture_lod_bias
+GLfloat GL_MAX_TEXTURE_LOD_BIAS_EXT GL_EXT_texture_lod_bias g->limits.maxTextureLodBias
+
+# GL_EXT_fog_coordinate
+GLfloat GL_CURRENT_FOG_COORDINATE_EXT GL_EXT_fog_coord g->current.vertexAttrib[VERT_ATTRIB_FOG][0]
+GLboolean GL_FOG_COORDINATE_ARRAY_EXT GL_EXT_fog_coord g->client.array.f.enabled
+GLint GL_FOG_COORDINATE_ARRAY_TYPE_EXT GL_EXT_fog_coord g->client.array.f.type
+GLint GL_FOG_COORDINATE_ARRAY_STRIDE_EXT GL_EXT_fog_coord g->client.array.f.stride
+GLenum GL_FOG_COORDINATE_SOURCE_EXT GL_EXT_fog_coord g->fog.fogCoordinateSource
+
+# GL_EXT_secondary_color
+GLboolean GL_COLOR_SUM_EXT GL_EXT_secondary_color g->lighting.colorSumEXT
+GLfloat GL_CURRENT_SECONDARY_COLOR_EXT GL_EXT_secondary_color g->current.vertexAttrib[VERT_ATTRIB_COLOR1][0] g->current.vertexAttrib[VERT_ATTRIB_COLOR1][1] g->current.vertexAttrib[VERT_ATTRIB_COLOR1][2]
+GLboolean GL_SECONDARY_COLOR_ARRAY_EXT GL_EXT_secondary_color g->client.array.s.enabled
+GLint GL_SECONDARY_COLOR_ARRAY_TYPE_EXT GL_EXT_secondary_color g->client.array.s.type
+GLint GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT GL_EXT_secondary_color g->client.array.s.stride
+GLint GL_SECONDARY_COLOR_ARRAY_SIZE_EXT GL_EXT_secondary_color g->client.array.s.size
+
+# GL_SGIS_generate_mipmap
+GLint GL_GENERATE_MIPMAP_HINT GL_SGIS_generate_mipmap g->hint.generateMipmap
+
+# GL_ARB_point_sprite
+GLboolean GL_POINT_SPRITE_ARB GL_ARB_point_sprite g->point.pointSprite
+
+# GL_ARB_vertex_buffer_object
+GLuint GL_ARRAY_BUFFER_BINDING_ARB GL_ARB_vertex_buffer_object g->bufferobject.arrayBuffer->id
+GLuint GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB GL_ARB_vertex_buffer_object g->bufferobject.elementsBuffer->id
+
+# GL_ARB_pixel_buffer_object
+GLuint GL_PIXEL_PACK_BUFFER_BINDING_ARB GL_ARB_pixel_buffer_object g->bufferobject.packBuffer->id
+GLuint GL_PIXEL_UNPACK_BUFFER_BINDING_ARB GL_ARB_pixel_buffer_object g->bufferobject.unpackBuffer->id
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_extensions_isenabled.txt b/src/VBox/GuestHost/OpenGL/state_tracker/state_extensions_isenabled.txt
new file mode 100644
index 00000000..d9c1da64
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_extensions_isenabled.txt
@@ -0,0 +1,71 @@
+# Copyright (c) 2001, Stanford University
+# All rights reserved.
+#
+# See the file LICENSE.txt for information on redistributing this software.
+
+# GL_OPENGL_VERSION_1_2
+
+GLboolean GL_RESCALE_NORMAL OPENGL_VERSION_1_2 g->transform.rescaleNormals
+GLboolean GL_TEXTURE_3D OPENGL_VERSION_1_2 g->texture.unit[g->texture.curTextureUnit].enabled3D
+GLboolean GL_MULTISAMPLE_ARB ARB_multisample g->multisample.enabled
+GLboolean GL_SAMPLE_ALPHA_TO_COVERAGE_ARB ARB_multisample g->multisample.sampleAlphaToCoverage
+GLboolean GL_SAMPLE_ALPHA_TO_ONE_ARB ARB_multisample g->multisample.sampleAlphaToOne
+GLboolean GL_SAMPLE_COVERAGE_ARB ARB_multisample g->multisample.sampleCoverage
+GLboolean GL_VERTEX_PROGRAM_NV NV_vertex_program g->program.vpEnabled
+GLboolean GL_VERTEX_PROGRAM_POINT_SIZE_NV NV_vertex_program g->program.vpPointSize
+GLboolean GL_VERTEX_PROGRAM_TWO_SIDE_NV NV_vertex_program g->program.vpTwoSide
+
+GLboolean GL_FRAGMENT_PROGRAM_NV NV_fragment_program g->program.fpEnabled
+GLboolean GL_FRAGMENT_PROGRAM_ARB ARB_fragment_program g->program.fpEnabledARB
+GLboolean GL_SECONDARY_COLOR_ARRAY_EXT EXT_secondary_color g->client.array.s.enabled
+GLboolean GL_FOG_COORDINATE_ARRAY_EXT EXT_fog_coord g->client.array.f.enabled
+GLboolean GL_TEXTURE_RECTANGLE_NV NV_texture_rectangle g->texture.unit[g->texture.curTextureUnit].enabledRect
+GLboolean GL_VERTEX_ATTRIB_ARRAY0_NV NV_vertex_program g->client.array.a[0].enabled
+GLboolean GL_VERTEX_ATTRIB_ARRAY1_NV NV_vertex_program g->client.array.a[1].enabled
+GLboolean GL_VERTEX_ATTRIB_ARRAY2_NV NV_vertex_program g->client.array.a[2].enabled
+GLboolean GL_VERTEX_ATTRIB_ARRAY3_NV NV_vertex_program g->client.array.a[3].enabled
+GLboolean GL_VERTEX_ATTRIB_ARRAY4_NV NV_vertex_program g->client.array.a[4].enabled
+GLboolean GL_VERTEX_ATTRIB_ARRAY5_NV NV_vertex_program g->client.array.a[5].enabled
+GLboolean GL_VERTEX_ATTRIB_ARRAY6_NV NV_vertex_program g->client.array.a[6].enabled
+GLboolean GL_VERTEX_ATTRIB_ARRAY7_NV NV_vertex_program g->client.array.a[7].enabled
+GLboolean GL_VERTEX_ATTRIB_ARRAY8_NV NV_vertex_program g->client.array.a[8].enabled
+GLboolean GL_VERTEX_ATTRIB_ARRAY9_NV NV_vertex_program g->client.array.a[9].enabled
+GLboolean GL_VERTEX_ATTRIB_ARRAY10_NV NV_vertex_program g->client.array.a[10].enabled
+GLboolean GL_VERTEX_ATTRIB_ARRAY11_NV NV_vertex_program g->client.array.a[11].enabled
+GLboolean GL_VERTEX_ATTRIB_ARRAY12_NV NV_vertex_program g->client.array.a[12].enabled
+GLboolean GL_VERTEX_ATTRIB_ARRAY13_NV NV_vertex_program g->client.array.a[13].enabled
+GLboolean GL_VERTEX_ATTRIB_ARRAY14_NV NV_vertex_program g->client.array.a[14].enabled
+GLboolean GL_VERTEX_ATTRIB_ARRAY15_NV NV_vertex_program g->client.array.a[15].enabled
+GLboolean GL_MAP1_VERTEX_ATTRIB0_4_NV NV_vertex_program g->eval.enableAttrib1D[0]
+GLboolean GL_MAP1_VERTEX_ATTRIB1_4_NV NV_vertex_program g->eval.enableAttrib1D[1]
+GLboolean GL_MAP1_VERTEX_ATTRIB2_4_NV NV_vertex_program g->eval.enableAttrib1D[2]
+GLboolean GL_MAP1_VERTEX_ATTRIB3_4_NV NV_vertex_program g->eval.enableAttrib1D[3]
+GLboolean GL_MAP1_VERTEX_ATTRIB4_4_NV NV_vertex_program g->eval.enableAttrib1D[4]
+GLboolean GL_MAP1_VERTEX_ATTRIB5_4_NV NV_vertex_program g->eval.enableAttrib1D[5]
+GLboolean GL_MAP1_VERTEX_ATTRIB6_4_NV NV_vertex_program g->eval.enableAttrib1D[6]
+GLboolean GL_MAP1_VERTEX_ATTRIB7_4_NV NV_vertex_program g->eval.enableAttrib1D[7]
+GLboolean GL_MAP1_VERTEX_ATTRIB8_4_NV NV_vertex_program g->eval.enableAttrib1D[8]
+GLboolean GL_MAP1_VERTEX_ATTRIB9_4_NV NV_vertex_program g->eval.enableAttrib1D[9]
+GLboolean GL_MAP1_VERTEX_ATTRIB10_4_NV NV_vertex_program g->eval.enableAttrib1D[10]
+GLboolean GL_MAP1_VERTEX_ATTRIB11_4_NV NV_vertex_program g->eval.enableAttrib1D[11]
+GLboolean GL_MAP1_VERTEX_ATTRIB12_4_NV NV_vertex_program g->eval.enableAttrib1D[12]
+GLboolean GL_MAP1_VERTEX_ATTRIB13_4_NV NV_vertex_program g->eval.enableAttrib1D[13]
+GLboolean GL_MAP1_VERTEX_ATTRIB14_4_NV NV_vertex_program g->eval.enableAttrib1D[14]
+GLboolean GL_MAP1_VERTEX_ATTRIB15_4_NV NV_vertex_program g->eval.enableAttrib1D[15]
+GLboolean GL_MAP2_VERTEX_ATTRIB0_4_NV NV_vertex_program g->eval.enableAttrib2D[0]
+GLboolean GL_MAP2_VERTEX_ATTRIB1_4_NV NV_vertex_program g->eval.enableAttrib2D[1]
+GLboolean GL_MAP2_VERTEX_ATTRIB2_4_NV NV_vertex_program g->eval.enableAttrib2D[2]
+GLboolean GL_MAP2_VERTEX_ATTRIB3_4_NV NV_vertex_program g->eval.enableAttrib2D[3]
+GLboolean GL_MAP2_VERTEX_ATTRIB4_4_NV NV_vertex_program g->eval.enableAttrib2D[4]
+GLboolean GL_MAP2_VERTEX_ATTRIB5_4_NV NV_vertex_program g->eval.enableAttrib2D[5]
+GLboolean GL_MAP2_VERTEX_ATTRIB6_4_NV NV_vertex_program g->eval.enableAttrib2D[6]
+GLboolean GL_MAP2_VERTEX_ATTRIB7_4_NV NV_vertex_program g->eval.enableAttrib2D[7]
+GLboolean GL_MAP2_VERTEX_ATTRIB8_4_NV NV_vertex_program g->eval.enableAttrib2D[8]
+GLboolean GL_MAP2_VERTEX_ATTRIB9_4_NV NV_vertex_program g->eval.enableAttrib2D[9]
+GLboolean GL_MAP2_VERTEX_ATTRIB10_4_NV NV_vertex_program g->eval.enableAttrib2D[10]
+GLboolean GL_MAP2_VERTEX_ATTRIB11_4_NV NV_vertex_program g->eval.enableAttrib2D[11]
+GLboolean GL_MAP2_VERTEX_ATTRIB12_4_NV NV_vertex_program g->eval.enableAttrib2D[12]
+GLboolean GL_MAP2_VERTEX_ATTRIB13_4_NV NV_vertex_program g->eval.enableAttrib2D[13]
+GLboolean GL_MAP2_VERTEX_ATTRIB14_4_NV NV_vertex_program g->eval.enableAttrib2D[14]
+GLboolean GL_MAP2_VERTEX_ATTRIB15_4_NV NV_vertex_program g->eval.enableAttrib2D[15]
+GLboolean GL_RASTER_POSITION_UNCLIPPED_IBM IBM_rasterpos_clip g->transform.rasterPositionUnclipped
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_feedback.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_feedback.c
new file mode 100644
index 00000000..a8591976
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_feedback.c
@@ -0,0 +1,2423 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#include "state.h"
+#include "state_internals.h"
+#include "state/cr_statetypes.h"
+#include "state/cr_feedback.h"
+
+/*
+ * This file is really a complement to the feedbackSPU and as such
+ * has big dependencies upon it. We have to monitor a whole bunch
+ * of state in the feedbackSPU to be able to properly implement
+ * full functionality.
+ *
+ * We have to intercept glColor3f(v)/4f(v) to get state updates on
+ * color properties and also glTexCoord* too, as unlike the tilesortSPU
+ * we don't have a pincher that pulls these out as they're passing
+ * through.
+ *
+ * - Alan.
+ */
+
+
+/*
+ * Selection and feedback
+ *
+ * TODO:
+ * 1. Implement lighting for vertex colors for feedback
+ * 2. Implement user clip planes for points and lines
+ */
+
+
+/**********************************************************************/
+/***** Vertex Transformation and Clipping *****/
+/**********************************************************************/
+
+/*
+ * Transform a point (column vector) by a matrix: Q = M * P
+ */
+#define TRANSFORM_POINT( Q, M, P ) \
+ Q.x = (M).m00 * P.x + (M).m10 * P.y + (M).m20 * P.z + (M).m30 * P.w; \
+ Q.y = (M).m01 * P.x + (M).m11 * P.y + (M).m21 * P.z + (M).m31 * P.w; \
+ Q.z = (M).m02 * P.x + (M).m12 * P.y + (M).m22 * P.z + (M).m32 * P.w; \
+ Q.w = (M).m03 * P.x + (M).m13 * P.y + (M).m23 * P.z + (M).m33 * P.w;
+
+#define TRANSFORM_POINTA( Q, M, P ) \
+ Q.x = (M).m00 * (P)[0] + (M).m10 * (P)[1] + (M).m20 * (P)[2] + (M).m30 * (P)[3]; \
+ Q.y = (M).m01 * (P)[0] + (M).m11 * (P)[1] + (M).m21 * (P)[2] + (M).m31 * (P)[3]; \
+ Q.z = (M).m02 * (P)[0] + (M).m12 * (P)[1] + (M).m22 * (P)[2] + (M).m32 * (P)[3]; \
+ Q.w = (M).m03 * (P)[0] + (M).m13 * (P)[1] + (M).m23 * (P)[2] + (M).m33 * (P)[3];
+
+/*
+ * clip coord to window coord mapping
+ */
+#define MAP_POINT( Q, P, VP ) \
+ Q.x = (GLfloat) (((P.x / P.w) + 1.0) * VP.viewportW / 2.0 + VP.viewportX); \
+ Q.y = (GLfloat) (((P.y / P.w) + 1.0) * VP.viewportH / 2.0 + VP.viewportY); \
+ Q.z = (GLfloat) (((P.z / P.w) + 1.0) * (VP.farClip - VP.nearClip) / 2.0 + VP.nearClip);\
+ Q.w = (GLfloat) P.w;
+
+
+/*
+ * Linear interpolation:
+ */
+#define INTERPOLATE(T, A, B) ((A) + ((B) - (A)) * (T))
+
+
+/*
+ * Interpolate vertex position, color, texcoords, etc.
+ */
+static void
+interpolate_vertex(GLfloat t,
+ const CRVertex *v0, const CRVertex *v1,
+ CRVertex *vOut)
+{
+ vOut->eyePos.x = INTERPOLATE(t, v0->eyePos.x, v1->eyePos.x);
+ vOut->eyePos.y = INTERPOLATE(t, v0->eyePos.y, v1->eyePos.y);
+ vOut->eyePos.z = INTERPOLATE(t, v0->eyePos.z, v1->eyePos.z);
+ vOut->eyePos.w = INTERPOLATE(t, v0->eyePos.w, v1->eyePos.w);
+
+ vOut->clipPos.x = INTERPOLATE(t, v0->clipPos.x, v1->clipPos.x);
+ vOut->clipPos.y = INTERPOLATE(t, v0->clipPos.y, v1->clipPos.y);
+ vOut->clipPos.z = INTERPOLATE(t, v0->clipPos.z, v1->clipPos.z);
+ vOut->clipPos.w = INTERPOLATE(t, v0->clipPos.w, v1->clipPos.w);
+
+ vOut->attrib[VERT_ATTRIB_COLOR0][0] = INTERPOLATE(t, v0->attrib[VERT_ATTRIB_COLOR0][0], v1->attrib[VERT_ATTRIB_COLOR0][0]);
+ vOut->attrib[VERT_ATTRIB_COLOR0][1] = INTERPOLATE(t, v0->attrib[VERT_ATTRIB_COLOR0][1], v1->attrib[VERT_ATTRIB_COLOR0][1]);
+ vOut->attrib[VERT_ATTRIB_COLOR0][2] = INTERPOLATE(t, v0->attrib[VERT_ATTRIB_COLOR0][2], v1->attrib[VERT_ATTRIB_COLOR0][2]);
+ vOut->attrib[VERT_ATTRIB_COLOR0][3] = INTERPOLATE(t, v0->attrib[VERT_ATTRIB_COLOR0][3], v1->attrib[VERT_ATTRIB_COLOR0][3]);
+
+ vOut->colorIndex = INTERPOLATE(t, v0->colorIndex, v1->colorIndex);
+
+ vOut->attrib[VERT_ATTRIB_TEX0][0] = INTERPOLATE(t, v0->attrib[VERT_ATTRIB_TEX0][0], v1->attrib[VERT_ATTRIB_TEX0][0]);
+ vOut->attrib[VERT_ATTRIB_TEX0][1] = INTERPOLATE(t, v0->attrib[VERT_ATTRIB_TEX0][1], v1->attrib[VERT_ATTRIB_TEX0][0]);
+ vOut->attrib[VERT_ATTRIB_TEX0][2] = INTERPOLATE(t, v0->attrib[VERT_ATTRIB_TEX0][2], v1->attrib[VERT_ATTRIB_TEX0][0]);
+ vOut->attrib[VERT_ATTRIB_TEX0][3] = INTERPOLATE(t, v0->attrib[VERT_ATTRIB_TEX0][3], v1->attrib[VERT_ATTRIB_TEX0][0]);
+}
+
+
+
+
+/* clip bit codes */
+#define CLIP_LEFT 1
+#define CLIP_RIGHT 2
+#define CLIP_BOTTOM 4
+#define CLIP_TOP 8
+#define CLIP_NEAR 16
+#define CLIP_FAR 32
+#define CLIP_USER0 64
+#define CLIP_USER1 128
+
+
+/*
+ * Apply clip testing to a point.
+ * Return: 0 - visible
+ * non-zero - clip code mask (or of above CLIP_ bits)
+ */
+static GLuint
+clip_point(const CRVertex *v)
+{
+ CRContext *g = GetCurrentContext();
+ GLuint mask = 0;
+ GLuint i;
+
+ /* user-defined clip planes */
+ for (i = 0; i < g->limits.maxClipPlanes; i++)
+ {
+ if (g->transform.clip[i])
+ {
+ const GLvectord *plane = g->transform.clipPlane + i;
+ if (plane->x * v->eyePos.x +
+ plane->y * v->eyePos.y +
+ plane->z * v->eyePos.z +
+ plane->w * v->eyePos.w < 0.0)
+ mask |= (CLIP_USER0 << i);
+ }
+ }
+
+ /* view volume clipping */
+ if (v->clipPos.x > v->clipPos.w)
+ mask |= CLIP_RIGHT;
+ if (v->clipPos.x < -v->clipPos.w)
+ mask |= CLIP_LEFT;
+ if (v->clipPos.y > v->clipPos.w)
+ mask |= CLIP_TOP;
+ if (v->clipPos.y < -v->clipPos.w)
+ mask |= CLIP_BOTTOM;
+ if (v->clipPos.z > v->clipPos.w)
+ mask |= CLIP_FAR;
+ if (v->clipPos.z < -v->clipPos.w)
+ mask |= CLIP_NEAR;
+ return mask;
+}
+
+
+/*
+ * Apply clipping to a line segment.
+ * Input: v0, v1 - incoming vertices
+ * Output: v0out, v1out - result/clipped vertices
+ * Return: GL_TRUE: visible
+ * GL_FALSE: totally clipped
+ */
+static GLboolean
+clip_line(const CRVertex *v0in, const CRVertex *v1in,
+ CRVertex *v0new, CRVertex *v1new)
+{
+ CRVertex v0, v1, vNew;
+ GLfloat dx, dy, dz, dw, t;
+ GLuint code0, code1;
+
+ /* XXX need to do user-clip planes */
+
+ code0 = clip_point(v0in);
+ code1 = clip_point(v1in);
+ if (code0 & code1)
+ return GL_FALSE; /* totally clipped */
+
+ *v0new = *v0in;
+ *v1new = *v1in;
+ if (code0 == 0 && code1 == 0)
+ return GL_TRUE; /* no clipping needed */
+
+ v0 = *v0in;
+ v1 = *v1in;
+
+
+/*
+ * We use 6 instances of this code to clip agains the 6 planes.
+ * For each plane, we define the OUTSIDE and COMPUTE_INTERSECTION
+ * macros appropriately.
+ */
+#define GENERAL_CLIP \
+ if (OUTSIDE(v0)) { \
+ if (OUTSIDE(v1)) { \
+ /* both verts are outside ==> return 0 */ \
+ return 0; \
+ } \
+ else { \
+ /* v0 is outside, v1 is inside ==> clip */ \
+ COMPUTE_INTERSECTION( v1, v0, vNew ) \
+ interpolate_vertex(t, &v1, &v0, &vNew); \
+ v0 = vNew; \
+ } \
+ } \
+ else { \
+ if (OUTSIDE(v1)) { \
+ /* v0 is inside, v1 is outside ==> clip */ \
+ COMPUTE_INTERSECTION( v0, v1, vNew ) \
+ interpolate_vertex(t, &v0, &v1, &vNew); \
+ v1 = vNew; \
+ } \
+ /* else both verts are inside ==> do nothing */ \
+ }
+
+ /*** Clip against +X side ***/
+#define OUTSIDE(V) (V.clipPos.x > V.clipPos.w)
+#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
+ dx = OUT.clipPos.x - IN.clipPos.x; \
+ dw = OUT.clipPos.w - IN.clipPos.w; \
+ t = (IN.clipPos.x - IN.clipPos.w) / (dw-dx);
+ GENERAL_CLIP
+#undef OUTSIDE
+#undef COMPUTE_INTERSECTION
+
+ /*** Clip against -X side ***/
+#define OUTSIDE(V) (V.clipPos.x < -(V.clipPos.w))
+#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
+ dx = OUT.clipPos.x - IN.clipPos.x; \
+ dw = OUT.clipPos.w - IN.clipPos.w; \
+ t = -(IN.clipPos.x + IN.clipPos.w) / (dw+dx);
+ GENERAL_CLIP
+#undef OUTSIDE
+#undef COMPUTE_INTERSECTION
+
+ /*** Clip against +Y side ***/
+#define OUTSIDE(V) (V.clipPos.y > V.clipPos.w)
+#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
+ dy = OUT.clipPos.y - IN.clipPos.y; \
+ dw = OUT.clipPos.w - IN.clipPos.w; \
+ t = (IN.clipPos.y - IN.clipPos.w) / (dw-dy);
+ GENERAL_CLIP
+#undef OUTSIDE
+#undef COMPUTE_INTERSECTION
+
+ /*** Clip against -Y side ***/
+#define OUTSIDE(V) (V.clipPos.y < -(V.clipPos.w))
+#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
+ dy = OUT.clipPos.y - IN.clipPos.y; \
+ dw = OUT.clipPos.w - IN.clipPos.w; \
+ t = -(IN.clipPos.y + IN.clipPos.w) / (dw+dy);
+ GENERAL_CLIP
+#undef OUTSIDE
+#undef COMPUTE_INTERSECTION
+
+ /*** Clip against +Z side ***/
+#define OUTSIDE(V) (V.clipPos.z > V.clipPos.w)
+#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
+ dz = OUT.clipPos.z - IN.clipPos.z; \
+ dw = OUT.clipPos.w - IN.clipPos.w; \
+ t = (IN.clipPos.z - IN.clipPos.w) / (dw-dz);
+ GENERAL_CLIP
+#undef OUTSIDE
+#undef COMPUTE_INTERSECTION
+
+ /*** Clip against -Z side ***/
+#define OUTSIDE(V) (V.clipPos.z < -(V.clipPos.w))
+#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
+ dz = OUT.clipPos.z - IN.clipPos.z; \
+ dw = OUT.clipPos.w - IN.clipPos.w; \
+ t = -(IN.clipPos.z + IN.clipPos.w) / (dw+dz);
+ GENERAL_CLIP
+#undef OUTSIDE
+#undef COMPUTE_INTERSECTION
+
+#undef GENERAL_CLIP
+
+ *v0new = v0;
+ *v1new = v1;
+ return GL_TRUE;
+}
+
+
+
+/*
+ * Apply clipping to a polygon.
+ * Input: vIn - array of input vertices
+ * inCount - number of input vertices
+ * Output: vOut - new vertices
+ * Return: number of vertices in vOut
+ */
+static GLuint
+clip_polygon(const CRVertex *vIn, unsigned int inCount,
+ CRVertex *vOut)
+{
+ CRVertex inlist[20], outlist[20];
+ GLfloat dx, dy, dz, dw, t;
+ GLuint incount, outcount, previ, curri, result;
+ const CRVertex *currVert, *prevVert;
+ CRVertex *newVert;
+
+ /* XXX need to do user-clip planes */
+
+#define GENERAL_CLIP(INCOUNT, INLIST, OUTCOUNT, OUTLIST) \
+ if (INCOUNT < 3) \
+ return GL_FALSE; \
+ previ = INCOUNT - 1; /* let previous = last vertex */ \
+ prevVert = INLIST + previ; \
+ OUTCOUNT = 0; \
+ for (curri = 0; curri < INCOUNT; curri++) { \
+ currVert = INLIST + curri; \
+ if (INSIDE(currVert)) { \
+ if (INSIDE(prevVert)) { \
+ /* both verts are inside ==> copy current to outlist */ \
+ OUTLIST[OUTCOUNT] = *currVert; \
+ OUTCOUNT++; \
+ } \
+ else { \
+ newVert = OUTLIST + OUTCOUNT; \
+ /* current is inside and previous is outside ==> clip */ \
+ COMPUTE_INTERSECTION( currVert, prevVert, newVert ) \
+ OUTCOUNT++; \
+ /* Output current */ \
+ OUTLIST[OUTCOUNT] = *currVert; \
+ OUTCOUNT++; \
+ } \
+ } \
+ else { \
+ if (INSIDE(prevVert)) { \
+ newVert = OUTLIST + OUTCOUNT; \
+ /* current is outside and previous is inside ==> clip */ \
+ COMPUTE_INTERSECTION( prevVert, currVert, newVert ); \
+ OUTLIST[OUTCOUNT] = *newVert; \
+ OUTCOUNT++; \
+ } \
+ /* else both verts are outside ==> do nothing */ \
+ } \
+ /* let previous = current */ \
+ previ = curri; \
+ prevVert = currVert; \
+ }
+
+/*
+ * Clip against +X
+ */
+#define INSIDE(V) (V->clipPos.x <= V->clipPos.w)
+#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
+ dx = OUT->clipPos.x - IN->clipPos.x; \
+ dw = OUT->clipPos.w - IN->clipPos.w; \
+ t = (IN->clipPos.x - IN->clipPos.w) / (dw - dx); \
+ interpolate_vertex(t, IN, OUT, NEW );
+
+ GENERAL_CLIP(inCount, vIn, outcount, outlist)
+
+#undef INSIDE
+#undef COMPUTE_INTERSECTION
+
+/*
+ * Clip against -X
+ */
+#define INSIDE(V) (V->clipPos.x >= -V->clipPos.w)
+#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
+ dx = OUT->clipPos.x - IN->clipPos.x; \
+ dw = OUT->clipPos.w - IN->clipPos.w; \
+ t = -(IN->clipPos.x + IN->clipPos.w) / (dw + dx); \
+ interpolate_vertex(t, IN, OUT, NEW );
+
+ GENERAL_CLIP(outcount, outlist, incount, inlist)
+
+#undef INSIDE
+#undef COMPUTE_INTERSECTION
+
+/*
+ * Clip against +Y
+ */
+#define INSIDE(V) (V->clipPos.y <= V->clipPos.w)
+#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
+ dy = OUT->clipPos.y - IN->clipPos.y; \
+ dw = OUT->clipPos.w - IN->clipPos.w; \
+ t = (IN->clipPos.y - IN->clipPos.w) / (dw - dy); \
+ interpolate_vertex(t, IN, OUT, NEW );
+
+ GENERAL_CLIP(incount, inlist, outcount, outlist)
+
+#undef INSIDE
+#undef COMPUTE_INTERSECTION
+
+/*
+ * Clip against -Y
+ */
+#define INSIDE(V) (V->clipPos.y >= -V->clipPos.w)
+#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
+ dy = OUT->clipPos.y - IN->clipPos.y; \
+ dw = OUT->clipPos.w - IN->clipPos.w; \
+ t = -(IN->clipPos.y + IN->clipPos.w) / (dw + dy); \
+ interpolate_vertex(t, IN, OUT, NEW );
+
+ GENERAL_CLIP(outcount, outlist, incount, inlist)
+
+#undef INSIDE
+#undef COMPUTE_INTERSECTION
+
+/*
+ * Clip against +Z
+ */
+#define INSIDE(V) (V->clipPos.z <= V->clipPos.w)
+#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
+ dz = OUT->clipPos.z - IN->clipPos.z; \
+ dw = OUT->clipPos.w - IN->clipPos.w; \
+ t = (IN->clipPos.z - IN->clipPos.w) / (dw - dz); \
+ interpolate_vertex(t, IN, OUT, NEW );
+
+ GENERAL_CLIP(incount, inlist, outcount, outlist)
+
+#undef INSIDE
+#undef COMPUTE_INTERSECTION
+
+/*
+ * Clip against -Z
+ */
+#define INSIDE(V) (V->clipPos.z >= -V->clipPos.w)
+#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
+ dz = OUT->clipPos.z - IN->clipPos.z; \
+ dw = OUT->clipPos.w - IN->clipPos.w; \
+ t = -(IN->clipPos.z + IN->clipPos.w) / (dw + dz); \
+ interpolate_vertex(t, IN, OUT, NEW );
+
+ GENERAL_CLIP(outcount, outlist, result, vOut)
+
+#undef INSIDE
+#undef COMPUTE_INTERSECTION
+
+#undef GENERAL_CLIP
+
+ return result;
+}
+
+
+/**********************************************************************/
+/***** Feedback *****/
+/**********************************************************************/
+
+
+#define FB_3D 0x01
+#define FB_4D 0x02
+#define FB_INDEX 0x04
+#define FB_COLOR 0x08
+#define FB_TEXTURE 0X10
+
+#define FEEDBACK_TOKEN( T ) \
+ do { \
+ if (f->count < f->bufferSize) { \
+ f->buffer[f->count] = (GLfloat) (T); \
+ } \
+ f->count++; \
+ } while (0)
+
+/*
+ * Put a vertex into the feedback buffer.
+ */
+static void
+feedback_vertex(const CRVertex *v)
+{
+ CRContext *g = GetCurrentContext();
+ CRFeedbackState *f = &(g->feedback);
+ CRTransformState *t = &(g->transform);
+
+ FEEDBACK_TOKEN(v->winPos.x);
+ FEEDBACK_TOKEN(v->winPos.y);
+
+ if (f->mask & FB_3D)
+ {
+ FEEDBACK_TOKEN(v->winPos.z);
+ }
+
+ if (f->mask & FB_4D)
+ {
+ FEEDBACK_TOKEN(v->winPos.w);
+ }
+
+ /* We don't deal with color index in Chromium */
+ if (f->mask & FB_INDEX)
+ {
+ FEEDBACK_TOKEN(v->colorIndex);
+ }
+
+ if (f->mask & FB_COLOR)
+ {
+ FEEDBACK_TOKEN(v->attrib[VERT_ATTRIB_COLOR0][0]);
+ FEEDBACK_TOKEN(v->attrib[VERT_ATTRIB_COLOR0][1]);
+ FEEDBACK_TOKEN(v->attrib[VERT_ATTRIB_COLOR0][2]);
+ FEEDBACK_TOKEN(v->attrib[VERT_ATTRIB_COLOR0][3]);
+ }
+
+ if (f->mask & FB_TEXTURE)
+ {
+ GLvectorf coord, transCoord;
+ /* Ugh, copy (s,t,r,q) to (x,y,z,w) */
+ coord.x = v->attrib[VERT_ATTRIB_TEX0][0];
+ coord.y = v->attrib[VERT_ATTRIB_TEX0][1];
+ coord.z = v->attrib[VERT_ATTRIB_TEX0][2];
+ coord.w = v->attrib[VERT_ATTRIB_TEX0][3];
+ TRANSFORM_POINT(transCoord, *(t->textureStack[0].top), coord);
+ FEEDBACK_TOKEN(transCoord.x);
+ FEEDBACK_TOKEN(transCoord.y);
+ FEEDBACK_TOKEN(transCoord.z);
+ FEEDBACK_TOKEN(transCoord.w);
+ }
+}
+
+
+
+static void
+feedback_rasterpos(void)
+{
+ CRContext *g = GetCurrentContext();
+ CRVertex *tv = g->vBuffer + g->vCount;
+ CRVertex v;
+
+ v.winPos.x = g->current.rasterAttrib[VERT_ATTRIB_POS][0];
+ v.winPos.y = g->current.rasterAttrib[VERT_ATTRIB_POS][1];
+ v.winPos.z = g->current.rasterAttrib[VERT_ATTRIB_POS][2];
+ v.winPos.w = g->current.rasterAttrib[VERT_ATTRIB_POS][3];
+ COPY_4V(v.attrib[VERT_ATTRIB_COLOR0] , g->current.rasterAttrib[VERT_ATTRIB_COLOR0]); /* XXX need to apply lighting */
+ COPY_4V(v.attrib[VERT_ATTRIB_COLOR1] , g->current.rasterAttrib[VERT_ATTRIB_COLOR1]);
+ v.colorIndex = (GLfloat) g->current.rasterIndex;
+
+ /* Don't do this, we're capturing TexCoord ourselves and
+ * we'd miss the conversion in RasterPosUpdate */
+ /* v.texCoord[0] = g->current.rasterTexture; */
+
+ /* So we do this instead, and pluck it from the current vertex */
+ COPY_4V(v.attrib[VERT_ATTRIB_TEX0] , tv->attrib[VERT_ATTRIB_TEX0]);
+
+ feedback_vertex(&v);
+}
+
+
+static void
+feedback_point(const CRVertex *v)
+{
+ CRContext *g = GetCurrentContext();
+ CRFeedbackState *f = &(g->feedback);
+ if (clip_point(v) == 0)
+ {
+ CRVertex c = *v;
+ MAP_POINT(c.winPos, c.clipPos, g->viewport);
+ FEEDBACK_TOKEN((GLfloat) GL_POINT_TOKEN);
+ feedback_vertex(&c);
+ }
+}
+
+
+static void
+feedback_line(const CRVertex *v0, const CRVertex *v1, GLboolean reset)
+{
+ CRContext *g = GetCurrentContext();
+ CRFeedbackState *f = &(g->feedback);
+ CRVertex c0, c1;
+ if (clip_line(v0, v1, &c0, &c1))
+ {
+ MAP_POINT(c0.winPos, c0.clipPos, g->viewport);
+ MAP_POINT(c1.winPos, c1.clipPos, g->viewport);
+ if (reset)
+ FEEDBACK_TOKEN((GLfloat) GL_LINE_RESET_TOKEN);
+ else
+ FEEDBACK_TOKEN((GLfloat) GL_LINE_TOKEN);
+ feedback_vertex(&c0);
+ feedback_vertex(&c1);
+ }
+}
+
+
+static void
+feedback_triangle(const CRVertex *v0, const CRVertex *v1, const CRVertex *v2)
+{
+ CRContext *g = GetCurrentContext();
+ CRFeedbackState *f = &(g->feedback);
+ CRVertex vlist[3], vclipped[8];
+ GLuint i, n;
+
+ vlist[0] = *v0;
+ vlist[1] = *v1;
+ vlist[2] = *v2;
+ n = clip_polygon(vlist, 3, vclipped);
+ FEEDBACK_TOKEN( (GLfloat) GL_POLYGON_TOKEN );
+ FEEDBACK_TOKEN( (GLfloat) n );
+ for (i = 0; i < n; i++) {
+ MAP_POINT(vclipped[i].winPos, vclipped[i].clipPos, g->viewport);
+ feedback_vertex(vclipped + i);
+ }
+}
+
+
+void STATE_APIENTRY
+crStateFeedbackVertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ CRContext *g = GetCurrentContext();
+ CRTransformState *t = &(g->transform);
+ CRPolygonState *p = &(g->polygon);
+ CRVertex *v = g->vBuffer + g->vCount;
+
+ /* store the vertex */
+ v->attrib[VERT_ATTRIB_POS][0] = x;
+ v->attrib[VERT_ATTRIB_POS][1] = y;
+ v->attrib[VERT_ATTRIB_POS][2] = z;
+ v->attrib[VERT_ATTRIB_POS][3] = w;
+ COPY_4V(v->attrib[VERT_ATTRIB_COLOR0] , g->current.vertexAttrib[VERT_ATTRIB_COLOR0]); /* XXX need to apply lighting */
+ v->colorIndex = g->current.colorIndex; /* XXX need to apply lighting */
+ /* Don't do this, we're capturing TexCoord ourselves as
+ * we don't have a pincher like the tilesortSPU */
+ /* v->texCoord[0] = g->current.texCoord[0]; */
+
+ /* transform to eye space, then clip space */
+ TRANSFORM_POINTA(v->eyePos, *(t->modelViewStack.top), v->attrib[VERT_ATTRIB_POS]);
+ TRANSFORM_POINT(v->clipPos, *(t->projectionStack.top), v->eyePos);
+
+ switch (g->current.mode) {
+ case GL_POINTS:
+ CRASSERT(g->vCount == 0);
+ feedback_point(v);
+ break;
+ case GL_LINES:
+ if (g->vCount == 0)
+ {
+ g->vCount = 1;
+ }
+ else
+ {
+ CRASSERT(g->vCount == 1);
+ feedback_line(g->vBuffer + 0, g->vBuffer + 1, g->lineReset);
+ g->vCount = 0;
+ }
+ break;
+ case GL_LINE_STRIP:
+ if (g->vCount == 0)
+ {
+ g->vCount = 1;
+ }
+ else
+ {
+ CRASSERT(g->vCount == 1);
+ feedback_line(g->vBuffer + 0, g->vBuffer + 1, g->lineReset);
+ g->vBuffer[0] = g->vBuffer[1];
+ g->lineReset = GL_FALSE;
+ /* leave g->vCount at 1 */
+ }
+ break;
+ case GL_LINE_LOOP:
+ if (g->vCount == 0)
+ {
+ g->lineLoop = GL_FALSE;
+ g->vCount = 1;
+ }
+ else if (g->vCount == 1)
+ {
+ feedback_line(g->vBuffer + 0, g->vBuffer + 1, g->lineReset);
+ g->lineReset = GL_FALSE;
+ g->lineLoop = GL_TRUE;
+ g->vCount = 2;
+ }
+ else
+ {
+ CRASSERT(g->vCount == 2);
+ CRASSERT(g->lineReset == GL_FALSE);
+ g->lineLoop = GL_FALSE;
+ feedback_line(g->vBuffer + 1, g->vBuffer + 2, g->lineReset);
+ g->vBuffer[1] = g->vBuffer[2];
+ /* leave g->vCount at 2 */
+ }
+ break;
+ case GL_TRIANGLES:
+ if (g->vCount == 0 || g->vCount == 1)
+ {
+ g->vCount++;
+ }
+ else
+ {
+ CRASSERT(g->vCount == 2);
+ feedback_triangle(g->vBuffer + 0, g->vBuffer + 1, g->vBuffer + 2);
+ g->vCount = 0;
+ }
+ break;
+ case GL_TRIANGLE_STRIP:
+ if (g->vCount == 0 || g->vCount == 1)
+ {
+ g->vCount++;
+ }
+ else if (g->vCount == 2)
+ {
+ feedback_triangle(g->vBuffer + 0, g->vBuffer + 1, g->vBuffer + 2);
+ g->vCount = 3;
+ }
+ else
+ {
+ CRASSERT(g->vCount == 3);
+ feedback_triangle(g->vBuffer + 1, g->vBuffer + 3, g->vBuffer + 2);
+ g->vBuffer[0] = g->vBuffer[2];
+ g->vBuffer[1] = g->vBuffer[3];
+ g->vCount = 2;
+ }
+ break;
+ case GL_TRIANGLE_FAN:
+ if (g->vCount == 0 || g->vCount == 1)
+ {
+ g->vCount++;
+ }
+ else
+ {
+ CRASSERT(g->vCount == 2);
+ feedback_triangle(g->vBuffer + 0, g->vBuffer + 1, g->vBuffer + 2);
+ g->vBuffer[1] = g->vBuffer[2];
+ /* leave g->vCount = 2 */
+ }
+ break;
+ case GL_QUADS:
+ if (g->vCount < 3)
+ {
+ g->vCount++;
+ }
+ else
+ {
+ CRASSERT(g->vCount == 3);
+ feedback_triangle(g->vBuffer + 0, g->vBuffer + 1, g->vBuffer + 2);
+ feedback_triangle(g->vBuffer + 0, g->vBuffer + 2, g->vBuffer + 3);
+ g->vCount = 0;
+ }
+ break;
+ case GL_QUAD_STRIP:
+ if (g->vCount < 3)
+ {
+ g->vCount++;
+ }
+ else
+ {
+ CRASSERT(g->vCount == 3);
+ feedback_triangle(g->vBuffer + 0, g->vBuffer + 1, g->vBuffer + 2);
+ feedback_triangle(g->vBuffer + 1, g->vBuffer + 3, g->vBuffer + 2);
+ g->vBuffer[0] = g->vBuffer[2];
+ g->vBuffer[1] = g->vBuffer[3];
+ g->vCount = 2;
+ }
+ break;
+ case GL_POLYGON:
+ /* XXX need to observe polygon mode for the above TRI/QUAD prims */
+ switch (p->frontMode) {
+ case GL_POINT:
+ CRASSERT(g->vCount == 0);
+ feedback_point(v);
+ break;
+ case GL_LINE:
+ if (g->vCount == 0)
+ {
+ g->lineLoop = GL_FALSE;
+ g->vCount = 1;
+ }
+ else if (g->vCount == 1)
+ {
+ feedback_line(g->vBuffer + 0, g->vBuffer + 1, g->lineReset);
+ g->lineReset = GL_FALSE;
+ g->lineLoop = GL_TRUE;
+ g->vCount = 2;
+ }
+ else
+ {
+ CRASSERT(g->vCount == 2);
+ CRASSERT(g->lineReset == GL_FALSE);
+ g->lineLoop = GL_FALSE;
+ feedback_line(g->vBuffer + 1, g->vBuffer + 2, g->lineReset);
+ g->vBuffer[1] = g->vBuffer[2];
+ /* leave g->vCount at 2 */
+ }
+ break;
+ case GL_FILL:
+ /* draw as a tri-fan */
+ if (g->vCount == 0 || g->vCount == 1)
+ {
+ g->vCount++;
+ }
+ else
+ {
+ CRASSERT(g->vCount == 2);
+ feedback_triangle(g->vBuffer + 0, g->vBuffer + 1, g->vBuffer + 2);
+ g->vBuffer[1] = g->vBuffer[2];
+ /* leave g->vCount = 2 */
+ }
+ break;
+ default:
+ ; /* impossible */
+ }
+ break;
+ default:
+ ; /* impossible */
+ }
+}
+
+
+void STATE_APIENTRY
+crStateFeedbackBegin(GLenum mode)
+{
+ CRContext *g = GetCurrentContext();
+
+ crStateBegin(mode);
+
+ g->vCount = 0;
+ g->lineReset = GL_TRUE;
+ g->lineLoop = GL_FALSE;
+}
+
+
+void STATE_APIENTRY
+crStateFeedbackEnd(void)
+{
+ CRContext *g = GetCurrentContext();
+
+ if ( (g->current.mode == GL_LINE_LOOP ||
+ (g->current.mode == GL_POLYGON && g->polygon.frontMode == GL_LINE))
+ && g->vCount == 2 )
+ {
+ /* draw the last line segment */
+ if (g->lineLoop)
+ feedback_line(g->vBuffer + 1, g->vBuffer + 0, GL_FALSE);
+ else
+ feedback_line(g->vBuffer + 2, g->vBuffer + 0, GL_FALSE);
+ }
+
+ crStateEnd();
+}
+
+
+void STATE_APIENTRY
+crStateFeedbackBuffer(GLsizei size, GLenum type, GLfloat * buffer)
+{
+ CRContext *g = GetCurrentContext();
+ CRFeedbackState *f = &(g->feedback);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "FeedbackBuffer called in begin/end");
+ return;
+ }
+
+ if (g->renderMode == GL_FEEDBACK)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "Invalid Operation GL_FEEDBACK");
+ return;
+ }
+ if (size < 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "Invalid Value size < 0");
+ return;
+ }
+ if (!buffer)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "Invalid Value buffer = NULL");
+ f->bufferSize = 0;
+ return;
+ }
+
+ FLUSH();
+
+ switch (type)
+ {
+ case GL_2D:
+ f->mask = 0;
+ break;
+ case GL_3D:
+ f->mask = FB_3D;
+ break;
+ case GL_3D_COLOR:
+ f->mask = (FB_3D | FB_COLOR); /* FB_INDEX ?? */
+ break;
+ case GL_3D_COLOR_TEXTURE:
+ f->mask = (FB_3D | FB_COLOR | FB_TEXTURE); /* FB_INDEX ?? */
+ break;
+ case GL_4D_COLOR_TEXTURE:
+ f->mask = (FB_3D | FB_4D | FB_COLOR | FB_TEXTURE); /* FB_INDEX ?? */
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "invalid type");
+ return;
+ }
+
+ f->type = type;
+ f->bufferSize = size;
+ f->buffer = buffer;
+ f->count = 0;
+}
+
+
+void STATE_APIENTRY
+crStatePassThrough(GLfloat token)
+{
+ CRContext *g = GetCurrentContext();
+ CRFeedbackState *f = &(g->feedback);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "PassThrough called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ if (g->renderMode == GL_FEEDBACK)
+ {
+ FEEDBACK_TOKEN((GLfloat) (GLint) GL_PASS_THROUGH_TOKEN);
+ FEEDBACK_TOKEN(token);
+ }
+}
+
+
+/*
+ * Although these functions are used by the feedbackSPU alone,
+ * I've left them here as they interface to the other functions.....
+ */
+void STATE_APIENTRY
+crStateFeedbackGetBooleanv(GLenum pname, GLboolean * params)
+{
+ CRContext *g = GetCurrentContext();
+
+ switch (pname)
+ {
+
+ case GL_FEEDBACK_BUFFER_SIZE:
+ params[0] = (GLboolean) (g->feedback.bufferSize != 0);
+ break;
+ case GL_FEEDBACK_BUFFER_TYPE:
+ params[0] = (GLboolean) (g->feedback.type != 0);
+ break;
+ case GL_SELECTION_BUFFER_SIZE:
+ params[0] = (GLboolean) (g->selection.bufferSize != 0);
+ break;
+ default:
+ break;
+ }
+}
+
+
+void STATE_APIENTRY
+crStateFeedbackGetDoublev(GLenum pname, GLdouble * params)
+{
+ CRContext *g = GetCurrentContext();
+
+ switch (pname)
+ {
+
+ case GL_FEEDBACK_BUFFER_SIZE:
+ params[0] = (GLdouble) g->feedback.bufferSize;
+ break;
+ case GL_FEEDBACK_BUFFER_TYPE:
+ params[0] = (GLdouble) g->feedback.type;
+ break;
+ case GL_SELECTION_BUFFER_SIZE:
+ params[0] = (GLdouble) g->selection.bufferSize;
+ break;
+ default:
+ break;
+ }
+}
+
+
+void STATE_APIENTRY
+crStateFeedbackGetFloatv(GLenum pname, GLfloat * params)
+{
+ CRContext *g = GetCurrentContext();
+
+ switch (pname)
+ {
+
+ case GL_FEEDBACK_BUFFER_SIZE:
+ params[0] = (GLfloat) g->feedback.bufferSize;
+ break;
+ case GL_FEEDBACK_BUFFER_TYPE:
+ params[0] = (GLfloat) g->feedback.type;
+ break;
+ case GL_SELECTION_BUFFER_SIZE:
+ params[0] = (GLfloat) g->selection.bufferSize;
+ break;
+ default:
+ break;
+ }
+}
+
+
+void STATE_APIENTRY
+crStateFeedbackGetIntegerv(GLenum pname, GLint * params)
+{
+ CRContext *g = GetCurrentContext();
+
+ switch (pname)
+ {
+
+ case GL_FEEDBACK_BUFFER_SIZE:
+ params[0] = (GLint) g->feedback.bufferSize;
+ break;
+ case GL_FEEDBACK_BUFFER_TYPE:
+ params[0] = (GLint) g->feedback.type;
+ break;
+ case GL_SELECTION_BUFFER_SIZE:
+ params[0] = (GLint) g->selection.bufferSize;
+ break;
+ default:
+ break;
+ }
+}
+
+
+void STATE_APIENTRY
+crStateFeedbackDrawPixels(GLsizei width, GLsizei height, GLenum format,
+ GLenum type, const GLvoid * pixels)
+{
+ CRContext *g = GetCurrentContext();
+ CRFeedbackState *f = &(g->feedback);
+
+ (void) width;
+ (void) height;
+ (void) format;
+ (void) type;
+ (void) pixels;
+
+ FEEDBACK_TOKEN((GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN);
+
+ feedback_rasterpos();
+}
+
+void STATE_APIENTRY
+crStateFeedbackCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum type)
+{
+ CRContext *g = GetCurrentContext();
+ CRFeedbackState *f = &(g->feedback);
+
+ (void) x;
+ (void) y;
+ (void) width;
+ (void) height;
+ (void) type;
+
+ FEEDBACK_TOKEN((GLfloat) (GLint) GL_COPY_PIXEL_TOKEN);
+ feedback_rasterpos();
+}
+
+void STATE_APIENTRY
+crStateFeedbackBitmap(GLsizei width, GLsizei height, GLfloat xorig,
+ GLfloat yorig, GLfloat xmove, GLfloat ymove,
+ const GLubyte * bitmap)
+{
+ CRContext *g = GetCurrentContext();
+ CRFeedbackState *f = &(g->feedback);
+
+ (void) width;
+ (void) height;
+ (void) bitmap;
+ (void) xorig;
+ (void) yorig;
+
+ FEEDBACK_TOKEN((GLfloat) (GLint) GL_BITMAP_TOKEN);
+
+ feedback_rasterpos();
+
+ if (g->current.rasterValid)
+ {
+ g->current.rasterAttrib[VERT_ATTRIB_POS][0] += xmove;
+ g->current.rasterAttrib[VERT_ATTRIB_POS][1] += ymove;
+ }
+}
+
+
+void STATE_APIENTRY
+crStateFeedbackVertex4fv(const GLfloat * v)
+{
+ crStateFeedbackVertex4f(v[0], v[1], v[2], v[3]);
+}
+
+void STATE_APIENTRY
+crStateFeedbackVertex4s(GLshort v0, GLshort v1, GLshort v2, GLshort v3)
+{
+ crStateFeedbackVertex4f((GLfloat) v0, (GLfloat) v1, (GLfloat) v2,
+ (GLfloat) v3);
+}
+
+void STATE_APIENTRY
+crStateFeedbackVertex4sv(const GLshort * v)
+{
+ crStateFeedbackVertex4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2],
+ (GLfloat) v[3]);
+}
+
+void STATE_APIENTRY
+crStateFeedbackVertex4i(GLint v0, GLint v1, GLint v2, GLint v3)
+{
+ crStateFeedbackVertex4f((GLfloat) v0, (GLfloat) v1, (GLfloat) v2,
+ (GLfloat) v3);
+}
+
+void STATE_APIENTRY
+crStateFeedbackVertex4iv(const GLint * v)
+{
+ crStateFeedbackVertex4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2],
+ (GLfloat) v[3]);
+}
+
+void STATE_APIENTRY
+crStateFeedbackVertex4d(GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3)
+{
+ crStateFeedbackVertex4f((GLfloat) v0, (GLfloat) v1, (GLfloat) v2,
+ (GLfloat) v3);
+}
+
+void STATE_APIENTRY
+crStateFeedbackVertex4dv(const GLdouble * v)
+{
+ crStateFeedbackVertex4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2],
+ (GLfloat) v[3]);
+}
+
+void STATE_APIENTRY
+crStateFeedbackVertex2i(GLint v0, GLint v1)
+{
+ crStateFeedbackVertex4f((GLfloat) v0, (GLfloat) v1, 0.0f, 1.0f);
+}
+
+void STATE_APIENTRY
+crStateFeedbackVertex2iv(const GLint * v)
+{
+ crStateFeedbackVertex4f((GLfloat) v[0], (GLfloat) v[1], 0.0f, 1.0f);
+}
+
+void STATE_APIENTRY
+crStateFeedbackVertex2s(GLshort v0, GLshort v1)
+{
+ crStateFeedbackVertex4f((GLfloat) v0, (GLfloat) v1, 0.0f, 1.0f);
+}
+
+void STATE_APIENTRY
+crStateFeedbackVertex2sv(const GLshort * v)
+{
+ crStateFeedbackVertex4f((GLfloat) v[0], (GLfloat) v[1], 0.0f, 1.0f);
+}
+
+void STATE_APIENTRY
+crStateFeedbackVertex2f(GLfloat v0, GLfloat v1)
+{
+ crStateFeedbackVertex4f(v0, v1, 0.0f, 1.0f);
+}
+
+void STATE_APIENTRY
+crStateFeedbackVertex2fv(const GLfloat * v)
+{
+ crStateFeedbackVertex4f(v[0], v[1], 0.0f, 1.0f);
+}
+
+void STATE_APIENTRY
+crStateFeedbackVertex2d(GLdouble v0, GLdouble v1)
+{
+ crStateFeedbackVertex4f((GLfloat) v0, (GLfloat) v1, 0.0f, 1.0f);
+}
+
+void STATE_APIENTRY
+crStateFeedbackVertex2dv(const GLdouble * v)
+{
+ crStateFeedbackVertex4f((GLfloat) v[0], (GLfloat) v[1], 0.0f, 1.0f);
+}
+
+void STATE_APIENTRY
+crStateFeedbackVertex3i(GLint v0, GLint v1, GLint v2)
+{
+ crStateFeedbackVertex4f((GLfloat) v0, (GLfloat) v1, (GLfloat) v2, 1.0f);
+}
+
+void STATE_APIENTRY
+crStateFeedbackVertex3iv(const GLint * v)
+{
+ crStateFeedbackVertex4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0f);
+}
+
+void STATE_APIENTRY
+crStateFeedbackVertex3s(GLshort v0, GLshort v1, GLshort v2)
+{
+ crStateFeedbackVertex4f((GLfloat) v0, (GLfloat) v1, (GLfloat) v2, 1.0f);
+}
+
+void STATE_APIENTRY
+crStateFeedbackVertex3sv(const GLshort * v)
+{
+ crStateFeedbackVertex4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2],
+ 1.0f);
+}
+
+void STATE_APIENTRY
+crStateFeedbackVertex3f(GLfloat v0, GLfloat v1, GLfloat v2)
+{
+ crStateFeedbackVertex4f(v0, v1, v2, 1.0f);
+}
+
+void STATE_APIENTRY
+crStateFeedbackVertex3fv(const GLfloat * v)
+{
+ crStateFeedbackVertex4f(v[0], v[1], v[2], 1.0f);
+}
+
+void STATE_APIENTRY
+crStateFeedbackVertex3d(GLdouble v0, GLdouble v1, GLdouble v2)
+{
+ crStateFeedbackVertex4f((GLfloat) v0, (GLfloat) v1, (GLfloat) v2, 1.0f);
+}
+
+void STATE_APIENTRY
+crStateFeedbackVertex3dv(const GLdouble * v)
+{
+ crStateFeedbackVertex4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2],
+ 1.0f);
+}
+
+void STATE_APIENTRY
+crStateFeedbackTexCoord4f( GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3 )
+{
+ CRContext *g = GetCurrentContext();
+ CRVertex *v = g->vBuffer + g->vCount;
+
+ /* store the texCoord in the current vertex */
+ v->attrib[VERT_ATTRIB_TEX0][0] = v0;
+ v->attrib[VERT_ATTRIB_TEX0][1] = v1;
+ v->attrib[VERT_ATTRIB_TEX0][2] = v2;
+ v->attrib[VERT_ATTRIB_TEX0][3] = v3;
+}
+
+void STATE_APIENTRY
+crStateFeedbackTexCoord4fv( const GLfloat *v )
+{
+ crStateFeedbackTexCoord4f( v[0], v[1], v[2], v[3] );
+}
+
+void STATE_APIENTRY
+crStateFeedbackTexCoord4s( GLshort v0, GLshort v1, GLshort v2, GLshort v3 )
+{
+ crStateFeedbackTexCoord4f( (GLfloat)v0, (GLfloat)v1, (GLfloat)v2, (GLfloat)v3 );
+}
+
+void STATE_APIENTRY
+crStateFeedbackTexCoord4sv( const GLshort *v )
+{
+ crStateFeedbackTexCoord4f( (GLfloat)v[0], (GLfloat)v[1], (GLfloat)v[2], (GLfloat)v[3] );
+}
+
+void STATE_APIENTRY
+crStateFeedbackTexCoord4i( GLint v0, GLint v1, GLint v2, GLint v3 )
+{
+ crStateFeedbackTexCoord4f( (GLfloat)v0, (GLfloat)v1, (GLfloat)v2, (GLfloat)v3 );
+}
+
+void STATE_APIENTRY
+crStateFeedbackTexCoord4iv( const GLint *v )
+{
+ crStateFeedbackTexCoord4f( (GLfloat)v[0], (GLfloat)v[1], (GLfloat)v[2], (GLfloat)v[3] );
+}
+
+void STATE_APIENTRY
+crStateFeedbackTexCoord4d( GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3 )
+{
+ crStateFeedbackTexCoord4f( (GLfloat)v0, (GLfloat)v1, (GLfloat)v2, (GLfloat)v3 );
+}
+
+void STATE_APIENTRY
+crStateFeedbackTexCoord4dv( const GLdouble *v )
+{
+ crStateFeedbackTexCoord4f( (GLfloat)v[0], (GLfloat)v[1], (GLfloat)v[2], (GLfloat)v[3] );
+}
+
+void STATE_APIENTRY
+crStateFeedbackTexCoord1i( GLint v0 )
+{
+ crStateFeedbackTexCoord4f( (GLfloat)v0, 0.0f, 0.0f, 1.0f );
+}
+
+void STATE_APIENTRY
+crStateFeedbackTexCoord1iv( const GLint *v )
+{
+ crStateFeedbackTexCoord4f( (GLfloat)v[0], 0.0f, 0.0f, 1.0f );
+}
+
+void STATE_APIENTRY
+crStateFeedbackTexCoord1s( GLshort v0 )
+{
+ crStateFeedbackTexCoord4f( (GLfloat)v0, 0.0f, 0.0f, 1.0f );
+}
+
+void STATE_APIENTRY
+crStateFeedbackTexCoord1sv( const GLshort *v )
+{
+ crStateFeedbackTexCoord4f( (GLfloat)v[0], 0.0f, 0.0f, 1.0f );
+}
+
+void STATE_APIENTRY
+crStateFeedbackTexCoord1f( GLfloat v0 )
+{
+ crStateFeedbackTexCoord4f( v0, 0.0f, 0.0f, 1.0f );
+}
+
+void STATE_APIENTRY
+crStateFeedbackTexCoord1fv( const GLfloat *v )
+{
+ crStateFeedbackTexCoord4f( v[0], 0.0f, 0.0f, 1.0f );
+}
+
+void STATE_APIENTRY
+crStateFeedbackTexCoord1d( GLdouble v0 )
+{
+ crStateFeedbackTexCoord4f( (GLfloat)v0, 0.0f, 0.0f, 1.0f );
+}
+
+void STATE_APIENTRY
+crStateFeedbackTexCoord1dv( const GLdouble *v )
+{
+ crStateFeedbackTexCoord4f( (GLfloat)v[0], 0.0f, 0.0f, 1.0f );
+}
+
+void STATE_APIENTRY
+crStateFeedbackTexCoord2i( GLint v0, GLint v1 )
+{
+ crStateFeedbackTexCoord4f( (GLfloat)v0, (GLfloat)v1, 0.0f, 1.0f );
+}
+
+void STATE_APIENTRY
+crStateFeedbackTexCoord2iv( const GLint *v )
+{
+ crStateFeedbackTexCoord4f( (GLfloat)v[0], (GLfloat)v[1], 0.0f, 1.0f );
+}
+
+void STATE_APIENTRY
+crStateFeedbackTexCoord2s( GLshort v0, GLshort v1 )
+{
+ crStateFeedbackTexCoord4f( (GLfloat)v0, (GLfloat)v1, 0.0f, 1.0f );
+}
+
+void STATE_APIENTRY
+crStateFeedbackTexCoord2sv( const GLshort *v )
+{
+ crStateFeedbackTexCoord4f( (GLfloat)v[0], (GLfloat)v[1], 0.0f, 1.0f );
+}
+
+void STATE_APIENTRY
+crStateFeedbackTexCoord2f( GLfloat v0, GLfloat v1 )
+{
+ crStateFeedbackTexCoord4f( v0, v1, 0.0f, 1.0f );
+}
+
+void STATE_APIENTRY
+crStateFeedbackTexCoord2fv( const GLfloat *v )
+{
+ crStateFeedbackTexCoord4f( v[0], v[1], 0.0f, 1.0f );
+}
+
+void STATE_APIENTRY
+crStateFeedbackTexCoord2d( GLdouble v0, GLdouble v1 )
+{
+ crStateFeedbackTexCoord4f( (GLfloat)v0, (GLfloat)v1, 0.0f, 1.0f );
+}
+
+void STATE_APIENTRY
+crStateFeedbackTexCoord2dv( const GLdouble *v )
+{
+ crStateFeedbackTexCoord4f( (GLfloat)v[0], (GLfloat)v[1], 0.0f, 1.0f );
+}
+
+void STATE_APIENTRY
+crStateFeedbackTexCoord3i( GLint v0, GLint v1, GLint v2 )
+{
+ crStateFeedbackTexCoord4f( (GLfloat)v0, (GLfloat)v1, (GLfloat)v2, 1.0f );
+}
+
+void STATE_APIENTRY
+crStateFeedbackTexCoord3iv( const GLint *v )
+{
+ crStateFeedbackTexCoord4f( (GLfloat)v[0], (GLfloat)v[1], 0.0f, 1.0f );
+}
+
+void STATE_APIENTRY
+crStateFeedbackTexCoord3s( GLshort v0, GLshort v1, GLshort v2 )
+{
+ crStateFeedbackTexCoord4f( (GLfloat)v0, (GLfloat)v1, (GLfloat)v2, 1.0f );
+}
+
+void STATE_APIENTRY
+crStateFeedbackTexCoord3sv( const GLshort *v )
+{
+ crStateFeedbackTexCoord4f( (GLfloat)v[0], (GLfloat)v[1], (GLfloat)v[2], 1.0f );
+}
+
+void STATE_APIENTRY
+crStateFeedbackTexCoord3f( GLfloat v0, GLfloat v1, GLfloat v2 )
+{
+ crStateFeedbackTexCoord4f( v0, v1, v2, 1.0f );
+}
+
+void STATE_APIENTRY
+crStateFeedbackTexCoord3fv( const GLfloat *v )
+{
+ crStateFeedbackTexCoord4f( v[0], v[1], v[2], 1.0f );
+}
+
+void STATE_APIENTRY
+crStateFeedbackTexCoord3d( GLdouble v0, GLdouble v1, GLdouble v2 )
+{
+ crStateFeedbackTexCoord4f( (GLfloat)v0, (GLfloat)v1, (GLfloat)v2, 1.0f );
+}
+
+void STATE_APIENTRY
+crStateFeedbackTexCoord3dv( const GLdouble *v )
+{
+ crStateFeedbackTexCoord4f( (GLfloat)v[0], (GLfloat)v[1], (GLfloat)v[2], 1.0f );
+}
+
+void STATE_APIENTRY
+crStateFeedbackRectf(GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1)
+{
+ crStateFeedbackBegin(GL_QUADS);
+ crStateFeedbackVertex2f(x0, y0);
+ crStateFeedbackVertex2f(x0, y1);
+ crStateFeedbackVertex2f(x1, y1);
+ crStateFeedbackVertex2f(x1, y0);
+ crStateFeedbackEnd();
+}
+
+void STATE_APIENTRY
+crStateFeedbackRecti(GLint x0, GLint y0, GLint x1, GLint y1)
+{
+ crStateFeedbackRectf((GLfloat) x0, (GLfloat) y0, (GLfloat) x1, (GLfloat) y1);
+}
+
+void STATE_APIENTRY
+crStateFeedbackRectd(GLdouble x0, GLdouble y0, GLdouble x1, GLdouble y1)
+{
+ crStateFeedbackRectf((GLfloat) x0, (GLfloat) y0, (GLfloat) x1, (GLfloat) y1);
+}
+
+void STATE_APIENTRY
+crStateFeedbackRects(GLshort x0, GLshort y0, GLshort x1, GLshort y1)
+{
+ crStateFeedbackRectf((GLfloat) x0, (GLfloat) y0, (GLfloat) x1, (GLfloat) y1);
+}
+
+void STATE_APIENTRY
+crStateFeedbackRectiv(const GLint *v0, const GLint *v1)
+{
+ crStateFeedbackRectf((GLfloat) v0[0], (GLfloat) v0[1], (GLfloat) v1[0], (GLfloat) v1[1]);
+}
+
+void STATE_APIENTRY
+crStateFeedbackRectfv(const GLfloat *v0, const GLfloat *v1)
+{
+ crStateFeedbackRectf(v0[0], v0[1], v1[0], v1[1]);
+}
+
+void STATE_APIENTRY
+crStateFeedbackRectdv(const GLdouble *v0, const GLdouble *v1)
+{
+ crStateFeedbackRectf((GLfloat) v0[0], (GLfloat) v0[1], (GLfloat) v1[0], (GLfloat) v1[1]);
+}
+
+void STATE_APIENTRY
+crStateFeedbackRectsv(const GLshort *v0, const GLshort *v1)
+{
+ crStateFeedbackRectf((GLfloat) v0[0], (GLfloat) v0[1], (GLfloat) v1[0], (GLfloat) v1[1]);
+}
+
+/**********************************************************************/
+/***** Selection *****/
+/**********************************************************************/
+
+
+void STATE_APIENTRY
+crStateSelectBuffer(GLsizei size, GLuint * buffer)
+{
+ CRContext *g = GetCurrentContext();
+ CRSelectionState *se = &(g->selection);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "SelectBuffer called in begin/end");
+ return;
+ }
+
+ if (g->renderMode == GL_SELECT)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "SelectBuffer called with RenderMode = GL_SELECT");
+ return;
+ }
+
+ FLUSH();
+
+ se->buffer = buffer;
+ se->bufferSize = size;
+ se->bufferCount = 0;
+ se->hitFlag = GL_FALSE;
+ se->hitMinZ = 1.0;
+ se->hitMaxZ = 0.0;
+}
+
+
+#define WRITE_RECORD( V ) \
+ if (se->bufferCount < se->bufferSize) { \
+ se->buffer[se->bufferCount] = (V); \
+ } \
+ se->bufferCount++;
+
+
+static void
+write_hit_record(CRSelectionState * se)
+{
+ GLuint i;
+ GLuint zmin, zmax, zscale = (~0u);
+
+ /* hitMinZ and hitMaxZ are in [0,1]. Multiply these values by */
+ /* 2^32-1 and round to nearest unsigned integer. */
+
+ zmin = (GLuint) ((GLfloat) zscale * se->hitMinZ);
+ zmax = (GLuint) ((GLfloat) zscale * se->hitMaxZ);
+
+ WRITE_RECORD(se->nameStackDepth);
+ WRITE_RECORD(zmin);
+ WRITE_RECORD(zmax);
+ for (i = 0; i < se->nameStackDepth; i++)
+ {
+ WRITE_RECORD(se->nameStack[i]);
+ }
+
+ se->hits++;
+ se->hitFlag = GL_FALSE;
+ se->hitMinZ = 1.0;
+ se->hitMaxZ = -1.0;
+}
+
+
+
+void STATE_APIENTRY
+crStateInitNames(void)
+{
+ CRContext *g = GetCurrentContext();
+ CRSelectionState *se = &(g->selection);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "InitNames called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ /* Record the hit before the hitFlag is wiped out again. */
+ if (g->renderMode == GL_SELECT)
+ {
+ if (se->hitFlag)
+ {
+ write_hit_record(se);
+ }
+ }
+
+ se->nameStackDepth = 0;
+ se->hitFlag = GL_FALSE;
+ se->hitMinZ = 1.0;
+ se->hitMaxZ = 0.0;
+}
+
+
+void STATE_APIENTRY
+crStateLoadName(GLuint name)
+{
+ CRContext *g = GetCurrentContext();
+ CRSelectionState *se = &(g->selection);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "LoadName called in begin/end");
+ return;
+ }
+
+
+ if (g->renderMode != GL_SELECT)
+ {
+ return;
+ }
+
+ if (se->nameStackDepth == 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "nameStackDepth = 0");
+ return;
+ }
+
+ FLUSH();
+
+ if (se->hitFlag)
+ {
+ write_hit_record(se);
+ }
+ if (se->nameStackDepth < MAX_NAME_STACK_DEPTH)
+ {
+ se->nameStack[se->nameStackDepth - 1] = name;
+ }
+ else
+ {
+ se->nameStack[MAX_NAME_STACK_DEPTH - 1] = name;
+ }
+}
+
+
+void STATE_APIENTRY
+crStatePushName(GLuint name)
+{
+ CRContext *g = GetCurrentContext();
+ CRSelectionState *se = &(g->selection);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "PushName called in begin/end");
+ return;
+ }
+
+
+ if (g->renderMode != GL_SELECT)
+ {
+ return;
+ }
+
+ FLUSH();
+
+ if (se->hitFlag)
+ {
+ write_hit_record(se);
+ }
+ if (se->nameStackDepth >= MAX_NAME_STACK_DEPTH)
+ {
+ crStateError(__LINE__, __FILE__, GL_STACK_OVERFLOW,
+ "nameStackDepth overflow");
+ }
+ else
+ se->nameStack[se->nameStackDepth++] = name;
+}
+
+void STATE_APIENTRY
+crStatePopName(void)
+{
+ CRContext *g = GetCurrentContext();
+ CRSelectionState *se = &(g->selection);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "PopName called in begin/end");
+ return;
+ }
+
+ if (g->renderMode != GL_SELECT)
+ {
+ return;
+ }
+
+ FLUSH();
+
+ if (se->hitFlag)
+ {
+ write_hit_record(se);
+ }
+
+ if (se->nameStackDepth == 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW,
+ "nameStackDepth underflow");
+ }
+ else
+ se->nameStackDepth--;
+}
+
+
+static void
+update_hitflag(GLfloat z)
+{
+ CRContext *g = GetCurrentContext();
+ CRSelectionState *se = &(g->selection);
+
+ se->hitFlag = GL_TRUE;
+
+ if (z < se->hitMinZ)
+ se->hitMinZ = z;
+
+ if (z > se->hitMaxZ)
+ se->hitMaxZ = z;
+}
+
+
+static void
+select_rasterpos(void)
+{
+ CRContext *g = GetCurrentContext();
+
+ if (g->current.rasterValid)
+ update_hitflag(g->current.rasterAttrib[VERT_ATTRIB_POS][2]);
+}
+
+static void
+select_point(const CRVertex *v)
+{
+ CRContext *g = GetCurrentContext();
+ if (clip_point(v) == 0)
+ {
+ CRVertex c = *v;
+ MAP_POINT(c.winPos, c.clipPos, g->viewport);
+ update_hitflag(c.winPos.z);
+ }
+}
+
+
+static void
+select_line(const CRVertex *v0, const CRVertex *v1)
+{
+ CRContext *g = GetCurrentContext();
+ CRVertex c0, c1;
+ if (clip_line(v0, v1, &c0, &c1))
+ {
+ MAP_POINT(c0.winPos, c0.clipPos, g->viewport);
+ MAP_POINT(c1.winPos, c1.clipPos, g->viewport);
+ update_hitflag(c0.winPos.z);
+ update_hitflag(c1.winPos.z);
+ }
+}
+
+
+static void
+select_triangle(const CRVertex *v0,
+ const CRVertex *v1,
+ const CRVertex *v2)
+{
+ CRContext *g = GetCurrentContext();
+ CRVertex vlist[3], vclipped[8];
+ GLuint i, n;
+
+ vlist[0] = *v0;
+ vlist[1] = *v1;
+ vlist[2] = *v2;
+ n = clip_polygon(vlist, 3, vclipped);
+ for (i = 0; i < n; i++) {
+ MAP_POINT(vclipped[i].winPos, vclipped[i].clipPos, g->viewport);
+ update_hitflag(vclipped[i].winPos.z);
+ }
+}
+
+
+void STATE_APIENTRY
+crStateSelectVertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ CRContext *g = GetCurrentContext();
+ CRTransformState *t = &(g->transform);
+ CRVertex *v = g->vBuffer + g->vCount;
+
+ /* store the vertex */
+ v->attrib[VERT_ATTRIB_POS][0] = x;
+ v->attrib[VERT_ATTRIB_POS][1] = y;
+ v->attrib[VERT_ATTRIB_POS][2] = z;
+ v->attrib[VERT_ATTRIB_POS][3] = w;
+ COPY_4V(v->attrib[VERT_ATTRIB_COLOR0] , g->current.vertexAttrib[VERT_ATTRIB_COLOR0]); /* XXX need to apply lighting */
+ v->colorIndex = g->current.colorIndex; /* XXX need to apply lighting */
+ /* Don't do this, we're capturing TexCoord ourselves as
+ * we don't have a pincher like the tilesortSPU */
+ /* v->texCoord[0] = g->current.texCoord[0]; */
+
+ /* transform to eye space, then clip space */
+ TRANSFORM_POINTA(v->eyePos, *(t->modelViewStack.top), v->attrib[VERT_ATTRIB_POS]);
+ TRANSFORM_POINT(v->clipPos, *(t->projectionStack.top), v->eyePos);
+
+ switch (g->current.mode) {
+ case GL_POINTS:
+ CRASSERT(g->vCount == 0);
+ select_point(v);
+ break;
+ case GL_LINES:
+ if (g->vCount == 0)
+ {
+ g->vCount = 1;
+ }
+ else
+ {
+ CRASSERT(g->vCount == 1);
+ select_line(g->vBuffer + 0, g->vBuffer + 1);
+ g->vCount = 0;
+ }
+ break;
+ case GL_LINE_STRIP:
+ if (g->vCount == 0)
+ {
+ g->vCount = 1;
+ }
+ else
+ {
+ CRASSERT(g->vCount == 1);
+ select_line(g->vBuffer + 0, g->vBuffer + 1);
+ g->vBuffer[0] = g->vBuffer[1];
+ /* leave g->vCount at 1 */
+ }
+ break;
+ case GL_LINE_LOOP:
+ if (g->vCount == 0)
+ {
+ g->vCount = 1;
+ g->lineLoop = GL_FALSE;
+ }
+ else if (g->vCount == 1)
+ {
+ select_line(g->vBuffer + 0, g->vBuffer + 1);
+ g->lineLoop = GL_TRUE;
+ g->vCount = 2;
+ }
+ else
+ {
+ CRASSERT(g->vCount == 2);
+ g->lineLoop = GL_FALSE;
+ select_line(g->vBuffer + 1, g->vBuffer + 2);
+ g->vBuffer[1] = g->vBuffer[2];
+ /* leave g->vCount at 2 */
+ }
+ break;
+ case GL_TRIANGLES:
+ if (g->vCount == 0 || g->vCount == 1)
+ {
+ g->vCount++;
+ }
+ else
+ {
+ CRASSERT(g->vCount == 2);
+ select_triangle(g->vBuffer + 0, g->vBuffer + 1, g->vBuffer + 2);
+ g->vCount = 0;
+ }
+ break;
+ case GL_TRIANGLE_STRIP:
+ if (g->vCount == 0 || g->vCount == 1)
+ {
+ g->vCount++;
+ }
+ else if (g->vCount == 2)
+ {
+ select_triangle(g->vBuffer + 0, g->vBuffer + 1, g->vBuffer + 2);
+ g->vCount = 3;
+ }
+ else
+ {
+ CRASSERT(g->vCount == 3);
+ select_triangle(g->vBuffer + 1, g->vBuffer + 3, g->vBuffer + 2);
+ g->vBuffer[0] = g->vBuffer[2];
+ g->vBuffer[1] = g->vBuffer[3];
+ g->vCount = 2;
+ }
+ break;
+ case GL_TRIANGLE_FAN:
+ if (g->vCount == 0 || g->vCount == 1)
+ {
+ g->vCount++;
+ }
+ else
+ {
+ CRASSERT(g->vCount == 2);
+ select_triangle(g->vBuffer + 0, g->vBuffer + 1, g->vBuffer + 2);
+ g->vBuffer[1] = g->vBuffer[2];
+ /* leave g->vCount = 2 */
+ }
+ break;
+ case GL_QUADS:
+ if (g->vCount < 3)
+ {
+ g->vCount++;
+ }
+ else
+ {
+ CRASSERT(g->vCount == 3);
+ select_triangle(g->vBuffer + 0, g->vBuffer + 1, g->vBuffer + 2);
+ select_triangle(g->vBuffer + 0, g->vBuffer + 2, g->vBuffer + 3);
+ g->vCount = 0;
+ }
+ break;
+ case GL_QUAD_STRIP:
+ if (g->vCount < 3)
+ {
+ g->vCount++;
+ }
+ else
+ {
+ CRASSERT(g->vCount == 3);
+ select_triangle(g->vBuffer + 0, g->vBuffer + 1, g->vBuffer + 2);
+ select_triangle(g->vBuffer + 1, g->vBuffer + 3, g->vBuffer + 2);
+ g->vBuffer[0] = g->vBuffer[2];
+ g->vBuffer[1] = g->vBuffer[3];
+ g->vCount = 2;
+ }
+ break;
+ case GL_POLYGON:
+ /* draw as a tri-fan */
+ if (g->vCount == 0 || g->vCount == 1)
+ {
+ g->vCount++;
+ }
+ else
+ {
+ CRASSERT(g->vCount == 2);
+ select_triangle(g->vBuffer + 0, g->vBuffer + 1, g->vBuffer + 2);
+ g->vBuffer[1] = g->vBuffer[2];
+ /* leave g->vCount = 2 */
+ }
+ break;
+ default:
+ ; /* impossible */
+ }
+}
+
+void STATE_APIENTRY
+crStateSelectRasterPos4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ crStateRasterPos4f( x, y, z, w );
+
+ select_rasterpos();
+}
+
+void STATE_APIENTRY
+crStateSelectBegin(GLenum mode)
+{
+ CRContext *g = GetCurrentContext();
+
+ crStateBegin(mode);
+
+ g->vCount = 0;
+ g->lineReset = GL_TRUE;
+ g->lineLoop = GL_FALSE;
+}
+
+
+void STATE_APIENTRY
+crStateSelectEnd(void)
+{
+ CRContext *g = GetCurrentContext();
+
+ if (g->current.mode == GL_LINE_LOOP && g->vCount == 2)
+ {
+ /* draw the last line segment */
+ select_line(g->vBuffer + 1, g->vBuffer + 0);
+ }
+
+ crStateEnd();
+}
+
+void STATE_APIENTRY
+crStateSelectVertex2d(GLdouble x, GLdouble y)
+{
+ crStateSelectVertex4f((GLfloat) x, (GLfloat) y, 0.0, 1.0);
+}
+
+void STATE_APIENTRY
+crStateSelectVertex2dv(const GLdouble * v)
+{
+ crStateSelectVertex4f((GLfloat) v[0], (GLfloat) v[1], 0.0, 1.0);
+}
+
+void STATE_APIENTRY
+crStateSelectVertex2f(GLfloat x, GLfloat y)
+{
+ crStateSelectVertex4f(x, y, 0.0, 1.0);
+}
+
+void STATE_APIENTRY
+crStateSelectVertex2fv(const GLfloat * v)
+{
+ crStateSelectVertex4f(v[0], v[1], 0.0, 1.0);
+}
+
+void STATE_APIENTRY
+crStateSelectVertex2i(GLint x, GLint y)
+{
+ crStateSelectVertex4f((GLfloat) x, (GLfloat) y, 0.0, 1.0);
+}
+
+void STATE_APIENTRY
+crStateSelectVertex2iv(const GLint * v)
+{
+ crStateSelectVertex4f((GLfloat) v[0], (GLfloat) v[1], 0.0, 1.0);
+}
+
+void STATE_APIENTRY
+crStateSelectVertex2s(GLshort x, GLshort y)
+{
+ crStateSelectVertex4f((GLfloat) x, (GLfloat) y, 0.0, 1.0);
+}
+
+void STATE_APIENTRY
+crStateSelectVertex2sv(const GLshort * v)
+{
+ crStateSelectVertex4f((GLfloat) v[0], (GLfloat) v[1], 0.0, 1.0);
+}
+
+void STATE_APIENTRY
+crStateSelectVertex3d(GLdouble x, GLdouble y, GLdouble z)
+{
+ crStateSelectVertex4f((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0);
+}
+
+void STATE_APIENTRY
+crStateSelectVertex3dv(const GLdouble * v)
+{
+ crStateSelectVertex4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0);
+}
+
+void STATE_APIENTRY
+crStateSelectVertex3f(GLfloat x, GLfloat y, GLfloat z)
+{
+ crStateSelectVertex4f(x, y, z, 1.0);
+}
+
+void STATE_APIENTRY
+crStateSelectVertex3fv(const GLfloat * v)
+{
+ crStateSelectVertex4f(v[0], v[1], v[2], 1.0);
+}
+
+void STATE_APIENTRY
+crStateSelectVertex3i(GLint x, GLint y, GLint z)
+{
+ crStateSelectVertex4f((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0);
+}
+
+void STATE_APIENTRY
+crStateSelectVertex3iv(const GLint * v)
+{
+ crStateSelectVertex4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0);
+}
+
+void STATE_APIENTRY
+crStateSelectVertex3s(GLshort x, GLshort y, GLshort z)
+{
+ crStateSelectVertex4f((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0);
+}
+
+void STATE_APIENTRY
+crStateSelectVertex3sv(const GLshort * v)
+{
+ crStateSelectVertex4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0);
+}
+
+void STATE_APIENTRY
+crStateSelectVertex4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w)
+{
+ crStateSelectVertex4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
+}
+
+void STATE_APIENTRY
+crStateSelectVertex4dv(const GLdouble * v)
+{
+ crStateSelectVertex4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]);
+}
+
+void STATE_APIENTRY
+crStateSelectVertex4fv(const GLfloat * v)
+{
+ crStateSelectVertex4f(v[0], v[1], v[2], v[3]);
+}
+
+void STATE_APIENTRY
+crStateSelectVertex4i(GLint x, GLint y, GLint z, GLint w)
+{
+ crStateSelectVertex4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
+}
+
+void STATE_APIENTRY
+crStateSelectVertex4iv(const GLint * v)
+{
+ crStateSelectVertex4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]);
+}
+
+void STATE_APIENTRY
+crStateSelectVertex4s(GLshort x, GLshort y, GLshort z, GLshort w)
+{
+ crStateSelectVertex4f(x, y, z, w);
+}
+
+void STATE_APIENTRY
+crStateSelectVertex4sv(const GLshort * v)
+{
+ crStateSelectVertex4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]);
+}
+
+void STATE_APIENTRY
+crStateSelectRasterPos2d(GLdouble x, GLdouble y)
+{
+ crStateSelectRasterPos4f((GLfloat) x, (GLfloat) y, 0.0, 1.0);
+}
+
+void STATE_APIENTRY
+crStateSelectRasterPos2dv(const GLdouble * v)
+{
+ crStateSelectRasterPos4f((GLfloat) v[0], (GLfloat) v[1], 0.0, 1.0);
+}
+
+void STATE_APIENTRY
+crStateSelectRasterPos2f(GLfloat x, GLfloat y)
+{
+ crStateSelectRasterPos4f(x, y, 0.0, 1.0);
+}
+
+void STATE_APIENTRY
+crStateSelectRasterPos2fv(const GLfloat * v)
+{
+ crStateSelectRasterPos4f(v[0], v[1], 0.0, 1.0);
+}
+
+void STATE_APIENTRY
+crStateSelectRasterPos2i(GLint x, GLint y)
+{
+ crStateSelectRasterPos4f((GLfloat) x, (GLfloat) y, 0.0, 1.0);
+}
+
+void STATE_APIENTRY
+crStateSelectRasterPos2iv(const GLint * v)
+{
+ crStateSelectRasterPos4f((GLfloat) v[0], (GLfloat) v[1], 0.0, 1.0);
+}
+
+void STATE_APIENTRY
+crStateSelectRasterPos2s(GLshort x, GLshort y)
+{
+ crStateSelectRasterPos4f((GLfloat) x, (GLfloat) y, 0.0, 1.0);
+}
+
+void STATE_APIENTRY
+crStateSelectRasterPos2sv(const GLshort * v)
+{
+ crStateSelectRasterPos4f((GLfloat) v[0], (GLfloat) v[1], 0.0, 1.0);
+}
+
+void STATE_APIENTRY
+crStateSelectRasterPos3d(GLdouble x, GLdouble y, GLdouble z)
+{
+ crStateSelectRasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0);
+}
+
+void STATE_APIENTRY
+crStateSelectRasterPos3dv(const GLdouble * v)
+{
+ crStateSelectRasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2] , 1.0);
+}
+
+void STATE_APIENTRY
+crStateSelectRasterPos3f(GLfloat x, GLfloat y, GLfloat z)
+{
+ crStateSelectRasterPos4f(x, y, z, 1.0);
+}
+
+void STATE_APIENTRY
+crStateSelectRasterPos3fv(const GLfloat * v)
+{
+ crStateSelectRasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2] , 1.0);
+}
+
+void STATE_APIENTRY
+crStateSelectRasterPos3i(GLint x, GLint y, GLint z)
+{
+ crStateSelectRasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0);
+}
+
+void STATE_APIENTRY
+crStateSelectRasterPos3iv(const GLint * v)
+{
+ crStateSelectRasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2] , 1.0);
+}
+
+void STATE_APIENTRY
+crStateSelectRasterPos3s(GLshort x, GLshort y, GLshort z)
+{
+ crStateSelectRasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0);
+}
+
+void STATE_APIENTRY
+crStateSelectRasterPos3sv(const GLshort * v)
+{
+ crStateSelectRasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2] , 1.0);
+}
+
+void STATE_APIENTRY
+crStateSelectRasterPos4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w)
+{
+ crStateSelectRasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
+}
+
+void STATE_APIENTRY
+crStateSelectRasterPos4dv(const GLdouble * v)
+{
+ crStateSelectRasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2] , (GLfloat) v[3]);
+}
+
+void STATE_APIENTRY
+crStateSelectRasterPos4fv(const GLfloat * v)
+{
+ crStateSelectRasterPos4f(v[0], v[1], v[2], v[3]);
+}
+
+void STATE_APIENTRY
+crStateSelectRasterPos4i(GLint x, GLint y, GLint z, GLint w)
+{
+ crStateSelectRasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
+}
+
+void STATE_APIENTRY
+crStateSelectRasterPos4iv(const GLint * v)
+{
+ crStateSelectRasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]);
+}
+
+void STATE_APIENTRY
+crStateSelectRasterPos4s(GLshort x, GLshort y, GLshort z, GLshort w)
+{
+ crStateSelectRasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
+}
+
+void STATE_APIENTRY
+crStateSelectRasterPos4sv(const GLshort * v)
+{
+ crStateSelectRasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2] , (GLfloat) v[3]);
+}
+
+void STATE_APIENTRY
+crStateSelectRectf(GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1)
+{
+ crStateSelectBegin(GL_QUADS);
+ crStateSelectVertex2f(x0, y0);
+ crStateSelectVertex2f(x0, y1);
+ crStateSelectVertex2f(x1, y1);
+ crStateSelectVertex2f(x1, y0);
+ crStateSelectEnd();
+}
+
+void STATE_APIENTRY
+crStateSelectRecti(GLint x0, GLint y0, GLint x1, GLint y1)
+{
+ crStateSelectRectf((GLfloat) x0, (GLfloat) y0, (GLfloat) x1, (GLfloat) y1);
+}
+
+void STATE_APIENTRY
+crStateSelectRectd(GLdouble x0, GLdouble y0, GLdouble x1, GLdouble y1)
+{
+ crStateSelectRectf((GLfloat) x0, (GLfloat) y0, (GLfloat) x1, (GLfloat) y1);
+}
+
+void STATE_APIENTRY
+crStateSelectRects(GLshort x0, GLshort y0, GLshort x1, GLshort y1)
+{
+ crStateSelectRectf((GLfloat) x0, (GLfloat) y0, (GLfloat) x1, (GLfloat) y1);
+}
+
+void STATE_APIENTRY
+crStateSelectRectiv(const GLint *v0, const GLint *v1)
+{
+ crStateSelectRectf((GLfloat) v0[0], (GLfloat) v0[1], (GLfloat) v1[0], (GLfloat) v1[1]);
+}
+
+void STATE_APIENTRY
+crStateSelectRectfv(const GLfloat *v0, const GLfloat *v1)
+{
+ crStateSelectRectf(v0[0], v0[1], v1[0], v1[1]);
+}
+
+void STATE_APIENTRY
+crStateSelectRectdv(const GLdouble *v0, const GLdouble *v1)
+{
+ crStateSelectRectf((GLfloat) v0[0], (GLfloat) v0[1], (GLfloat) v1[0], (GLfloat) v1[1]);
+}
+
+void STATE_APIENTRY
+crStateSelectRectsv(const GLshort *v0, const GLshort *v1)
+{
+ crStateSelectRectf((GLfloat) v0[0], (GLfloat) v0[1], (GLfloat) v1[0], (GLfloat) v1[1]);
+}
+
+
+GLint STATE_APIENTRY
+crStateRenderMode(GLenum mode)
+{
+ CRContext *g = GetCurrentContext();
+ CRFeedbackState *f = &(g->feedback);
+ CRSelectionState *se = &(g->selection);
+ GLint result;
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "RenderMode called in begin/end");
+ return 0;
+ }
+
+ FLUSH();
+
+ switch (g->renderMode)
+ {
+ case GL_RENDER:
+ result = 0;
+ break;
+ case GL_SELECT:
+ if (se->hitFlag)
+ {
+ write_hit_record(se);
+ }
+
+ if (se->bufferCount > se->bufferSize)
+ {
+ /* overflow */
+ result = -1;
+ }
+ else
+ {
+ result = se->hits;
+ }
+ se->bufferCount = 0;
+ se->hits = 0;
+ se->nameStackDepth = 0;
+ break;
+ case GL_FEEDBACK:
+ if (f->count > f->bufferSize)
+ {
+ /* overflow */
+ result = -1;
+ }
+ else
+ {
+ result = f->count;
+ }
+ f->count = 0;
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "invalid rendermode");
+ return 0;
+ }
+
+ switch (mode)
+ {
+ case GL_RENDER:
+ break;
+ case GL_SELECT:
+ if (se->bufferSize == 0)
+ {
+ /* haven't called glSelectBuffer yet */
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "buffersize = 0");
+ }
+ break;
+ case GL_FEEDBACK:
+ if (f->bufferSize == 0)
+ {
+ /* haven't called glFeedbackBuffer yet */
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "buffersize = 0");
+ }
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "invalid rendermode");
+ return 0;
+ }
+
+ g->renderMode = mode;
+
+ return result;
+}
+
+
+void STATE_APIENTRY
+crStateSelectDrawPixels(GLsizei width, GLsizei height, GLenum format,
+ GLenum type, const GLvoid * pixels)
+{
+ (void) width;
+ (void) height;
+ (void) format;
+ (void) type;
+ (void) pixels;
+ select_rasterpos();
+}
+
+void STATE_APIENTRY
+crStateSelectCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum type)
+{
+ (void) x;
+ (void) y;
+ (void) width;
+ (void) height;
+ (void) type;
+ select_rasterpos();
+}
+
+void STATE_APIENTRY
+crStateSelectBitmap(GLsizei width, GLsizei height, GLfloat xorig,
+ GLfloat yorig, GLfloat xmove, GLfloat ymove,
+ const GLubyte * bitmap)
+{
+ CRContext *g = GetCurrentContext();
+ (void) width;
+ (void) height;
+ (void) xorig;
+ (void) yorig;
+ (void) bitmap;
+
+ select_rasterpos();
+ if (g->current.rasterValid)
+ {
+ g->current.rasterAttrib[VERT_ATTRIB_POS][0] += xmove;
+ g->current.rasterAttrib[VERT_ATTRIB_POS][1] += ymove;
+ }
+}
+
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_feedback_special b/src/VBox/GuestHost/OpenGL/state_tracker/state_feedback_special
new file mode 100644
index 00000000..e0b16e71
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_feedback_special
@@ -0,0 +1,73 @@
+Vertex4f
+Begin
+End
+GetBooleanv
+GetDoublev
+GetFloatv
+GetIntegerv
+DrawPixels
+CopyPixels
+Bitmap
+Vertex4fv
+Vertex4s
+Vertex4sv
+Vertex4i
+Vertex4iv
+Vertex4d
+Vertex4dv
+Vertex2i
+Vertex2iv
+Vertex2s
+Vertex2sv
+Vertex2f
+Vertex2fv
+Vertex2d
+Vertex2dv
+Vertex3i
+Vertex3iv
+Vertex3s
+Vertex3sv
+Vertex3f
+Vertex3fv
+Vertex3d
+Vertex3dv
+Rectf
+Recti
+Rectd
+Rects
+Rectiv
+Rectfv
+Rectdv
+Rectsv
+TexCoord1d
+TexCoord1dv
+TexCoord1f
+TexCoord1fv
+TexCoord1i
+TexCoord1iv
+TexCoord1s
+TexCoord1sv
+TexCoord2d
+TexCoord2dv
+TexCoord2f
+TexCoord2fv
+TexCoord2i
+TexCoord2iv
+TexCoord2s
+TexCoord2sv
+TexCoord3d
+TexCoord3dv
+TexCoord3f
+TexCoord3fv
+TexCoord3i
+TexCoord3iv
+TexCoord3s
+TexCoord3sv
+TexCoord4d
+TexCoord4dv
+TexCoord4f
+TexCoord4fv
+TexCoord4i
+TexCoord4iv
+TexCoord4s
+TexCoord4sv
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_fence.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_fence.c
new file mode 100644
index 00000000..054f1c4b
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_fence.c
@@ -0,0 +1,50 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#include "state.h"
+#include "state_internals.h"
+#include "state/cr_statetypes.h"
+
+
+
+void APIENTRY crStateGenFencesNV(GLsizei n, GLuint *fences)
+{
+ (void)n; (void)fences;
+}
+
+
+void APIENTRY crStateDeleteFencesNV(GLsizei n, const GLuint *fences)
+{
+ (void)n; (void)fences;
+}
+
+void APIENTRY crStateSetFenceNV(GLuint fence, GLenum condition)
+{
+ (void)fence; (void)condition;
+}
+
+GLboolean APIENTRY crStateTestFenceNV(GLuint fence)
+{
+ (void)fence;
+ return GL_FALSE;
+}
+
+void APIENTRY crStateFinishFenceNV(GLuint fence)
+{
+ (void)fence;
+}
+
+GLboolean APIENTRY crStateIsFenceNV(GLuint fence)
+{
+ (void)fence;
+ return GL_FALSE;
+}
+
+void APIENTRY crStateGetFenceivNV(GLuint fence, GLenum pname, GLint *params)
+{
+ (void)fence; (void)pname; (void)params;
+}
+
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_flush.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_flush.c
new file mode 100644
index 00000000..052080e0
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_flush.c
@@ -0,0 +1,34 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#include "state.h"
+#include "cr_spu.h"
+
+SPUDispatchTable diff_api;
+
+void crStateFlushFunc( CRStateFlushFunc func )
+{
+ CRContext *g = GetCurrentContext();
+
+ g->flush_func = func;
+}
+
+void crStateFlushArg( void *arg )
+{
+ CRContext *g = GetCurrentContext();
+
+ g->flush_arg = arg;
+}
+
+void crStateDiffAPI( SPUDispatchTable *api )
+{
+ if (!diff_api.AlphaFunc)
+ {
+ /* Called when starting up Chromium */
+ crSPUInitDispatchTable( &(diff_api) );
+ }
+ crSPUCopyDispatchTable( &(diff_api), api );
+}
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_fog.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_fog.c
new file mode 100644
index 00000000..41f1f313
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_fog.c
@@ -0,0 +1,199 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#include <stdio.h>
+#include "state.h"
+#include "state/cr_statetypes.h"
+#include "state_internals.h"
+
+void crStateFogInit (CRContext *ctx)
+{
+ CRFogState *f = &ctx->fog;
+ CRStateBits *sb = GetCurrentBits();
+ CRFogBits *fb = &(sb->fog);
+ GLcolorf black = {0.0f, 0.0f, 0.0f, 0.0f};
+
+ f->color = black;
+ RESET(fb->color, ctx->bitid);
+ f->density = 1.0f;
+ RESET(fb->density, ctx->bitid);
+ f->end = 1.0f;
+ RESET(fb->end, ctx->bitid);
+ f->start = 0.0f;
+ RESET(fb->start, ctx->bitid);
+ f->mode = GL_EXP;
+ RESET(fb->mode, ctx->bitid);
+ f->index = 0;
+ RESET(fb->index, ctx->bitid);
+ f->enable = GL_FALSE;
+ RESET(fb->enable, ctx->bitid);
+
+#ifdef CR_NV_fog_distance
+ f->fogDistanceMode = GL_EYE_PLANE_ABSOLUTE_NV;
+ RESET(fb->fogDistanceMode, ctx->bitid);
+#endif
+#ifdef CR_EXT_fog_coord
+ f->fogCoordinateSource = GL_FRAGMENT_DEPTH_EXT;
+ RESET(fb->fogCoordinateSource, ctx->bitid);
+#endif
+ RESET(fb->dirty, ctx->bitid);
+}
+
+void STATE_APIENTRY crStateFogf(GLenum pname, GLfloat param)
+{
+ crStateFogfv( pname, &param );
+}
+
+void STATE_APIENTRY crStateFogi(GLenum pname, GLint param)
+{
+ GLfloat f_param = (GLfloat) param;
+ crStateFogfv( pname, &f_param );
+}
+
+void STATE_APIENTRY crStateFogiv(GLenum pname, const GLint *param)
+{
+ GLcolor f_color;
+ GLfloat f_param;
+ switch (pname)
+ {
+ case GL_FOG_MODE:
+ case GL_FOG_DENSITY:
+ case GL_FOG_START:
+ case GL_FOG_END:
+ case GL_FOG_INDEX:
+ f_param = (GLfloat) (*param);
+ crStateFogfv( pname, &f_param );
+ break;
+ case GL_FOG_COLOR:
+ f_color.r = ((GLfloat) param[0]) / ((GLfloat) CR_MAXINT);
+ f_color.g = ((GLfloat) param[1]) / ((GLfloat) CR_MAXINT);
+ f_color.b = ((GLfloat) param[2]) / ((GLfloat) CR_MAXINT);
+ f_color.a = ((GLfloat) param[3]) / ((GLfloat) CR_MAXINT);
+ crStateFogfv( pname, (GLfloat *) &f_color );
+ break;
+#ifdef CR_NV_fog_distance
+ case GL_FOG_DISTANCE_MODE_NV:
+ f_param = (GLfloat) (*param);
+ crStateFogfv( pname, &f_param );
+ break;
+#endif
+#ifdef CR_EXT_fog_coord
+ case GL_FOG_COORDINATE_SOURCE_EXT:
+ f_param = (GLfloat) (*param);
+ crStateFogfv( pname, &f_param );
+ break;
+#endif
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Invalid glFog Param: %d", param);
+ return;
+ }
+}
+
+void STATE_APIENTRY crStateFogfv(GLenum pname, const GLfloat *param)
+{
+ CRContext *g = GetCurrentContext();
+ CRFogState *f = &(g->fog);
+ CRStateBits *sb = GetCurrentBits();
+ CRFogBits *fb = &(sb->fog);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glFogfv called in Begin/End");
+ return;
+ }
+
+ FLUSH();
+
+ switch (pname)
+ {
+ case GL_FOG_MODE:
+ {
+ GLenum e = (GLenum) *param;
+ if (e != GL_LINEAR && e != GL_EXP && e != GL_EXP2)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid param for glFog: %d", e);
+ return;
+ }
+ f->mode = e;
+ DIRTY(fb->mode, g->neg_bitid);
+ }
+ break;
+ case GL_FOG_DENSITY:
+ f->density = *param;
+ if (f->density < 0.0f)
+ {
+ f->density = 0.0f;
+ }
+ DIRTY(fb->density, g->neg_bitid);
+ break;
+ case GL_FOG_START:
+ f->start = *param;
+ DIRTY(fb->start, g->neg_bitid);
+ break;
+ case GL_FOG_END:
+ f->end = *param;
+ DIRTY(fb->end, g->neg_bitid);
+ break;
+ case GL_FOG_INDEX:
+ f->index = (GLint) *param;
+ DIRTY(fb->index, g->neg_bitid);
+ break;
+ case GL_FOG_COLOR:
+ f->color.r = param[0];
+ f->color.g = param[1];
+ f->color.b = param[2];
+ f->color.a = param[3];
+ DIRTY(fb->color, g->neg_bitid);
+ break;
+#ifdef CR_NV_fog_distance
+ case GL_FOG_DISTANCE_MODE_NV:
+ if (g->extensions.NV_fog_distance)
+ {
+ if (param[0] != GL_EYE_RADIAL_NV &&
+ param[0] != GL_EYE_PLANE &&
+ param[0] != GL_EYE_PLANE_ABSOLUTE_NV )
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "Fogfv: GL_FOG_DISTANCE_MODE_NV called with illegal parameter: 0x%x", (GLenum) param[0]);
+ return;
+ }
+ f->fogDistanceMode = (GLenum) param[0];
+ DIRTY(fb->fogDistanceMode, g->neg_bitid);
+ }
+ else
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Invalid glFog Param: %d", param);
+ return;
+ }
+ break;
+#endif
+#ifdef CR_EXT_fog_coord
+ case GL_FOG_COORDINATE_SOURCE_EXT:
+ if (g->extensions.EXT_fog_coord)
+ {
+ if ((GLenum) param[0] != GL_FOG_COORDINATE_EXT &&
+ (GLenum) param[0] != GL_FRAGMENT_DEPTH_EXT)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "Fogfv: GL_FOG_COORDINATE_SOURCE_EXT called with illegal parameter: 0x%x", (GLenum) param[0]);
+ return;
+ }
+ f->fogCoordinateSource = (GLenum) param[0];
+ DIRTY(fb->fogCoordinateSource, g->neg_bitid);
+ }
+ else
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Invalid glFog Param: 0x%x", (GLint) param[0]);
+ return;
+ }
+ break;
+#endif
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Invalid glFog Param: %d", param);
+ return;
+ }
+ DIRTY(fb->dirty, g->neg_bitid);
+}
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_fog.txt b/src/VBox/GuestHost/OpenGL/state_tracker/state_fog.txt
new file mode 100644
index 00000000..d8e62c0e
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_fog.txt
@@ -0,0 +1,13 @@
+# Copyright (c) 2001, Stanford University
+# All rights reserved.
+#
+# See the file LICENSE.txt for information on redistributing this software.
+:enable:enable:GL_FOG
+:color:color|r,g,b,a:Fogfv,GL_FOG_COLOR
+:index:index:Fogi,GL_FOG_INDEX
+:density:density:Fogf,GL_FOG_DENSITY
+:start:start:Fogf,GL_FOG_START
+:end:end:Fogf,GL_FOG_END
+:mode:mode:Fogi,GL_FOG_MODE
+:fogDistanceMode:fogDistanceMode:Fogi,GL_FOG_DISTANCE_MODE_NV
+:fogCoordinateSource:fogCoordinateSource:Fogi,GL_FOG_COORDINATE_SOURCE_EXT
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_framebuffer.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_framebuffer.c
new file mode 100644
index 00000000..c82d53a3
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_framebuffer.c
@@ -0,0 +1,1202 @@
+/* $Id: state_framebuffer.c $ */
+
+/** @file
+ * VBox OpenGL: EXT_framebuffer_object state tracking
+ */
+
+/*
+ * Copyright (C) 2009-2019 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 "state.h"
+#include "state/cr_statetypes.h"
+#include "state/cr_statefuncs.h"
+#include "state_internals.h"
+#include "cr_mem.h"
+
+DECLEXPORT(void) STATE_APIENTRY
+crStateFramebufferObjectInit(CRContext *ctx)
+{
+ CRFramebufferObjectState *fbo = &ctx->framebufferobject;
+
+ fbo->readFB = NULL;
+ fbo->drawFB = NULL;
+ fbo->renderbuffer = NULL;
+ 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;
+
+#ifndef IN_GUEST
+ if (diff_api.DeleteFramebuffersEXT)
+ {
+ diff_api.DeleteFramebuffersEXT(1, &pObj->hwid);
+ }
+#endif
+
+ crFree(pObj);
+}
+
+void crStateFreeRBO(void *data)
+{
+ CRRenderbufferObject *pObj = (CRRenderbufferObject *)data;
+
+#ifndef IN_GUEST
+ if (diff_api.DeleteRenderbuffersEXT)
+ {
+ diff_api.DeleteRenderbuffersEXT(1, &pObj->hwid);
+ }
+#endif
+
+ crFree(pObj);
+}
+
+DECLEXPORT(void) STATE_APIENTRY
+crStateFramebufferObjectDestroy(CRContext *ctx)
+{
+ CRFramebufferObjectState *fbo = &ctx->framebufferobject;
+
+ fbo->readFB = NULL;
+ fbo->drawFB = NULL;
+ fbo->renderbuffer = NULL;
+}
+
+DECLEXPORT(void) STATE_APIENTRY
+crStateBindRenderbufferEXT(GLenum target, GLuint renderbuffer)
+{
+ CRContext *g = GetCurrentContext();
+ CRFramebufferObjectState *fbo = &g->framebufferobject;
+
+ 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)
+ {
+ CRSTATE_CHECKERR(!crHashtableIsKeyUsed(g->shared->rbTable, renderbuffer), GL_INVALID_OPERATION, "name is not a renderbuffer");
+ fbo->renderbuffer = crStateRenderbufferAllocate(g, renderbuffer);
+ }
+ CR_STATE_SHAREDOBJ_USAGE_SET(fbo->renderbuffer, g);
+ }
+ else fbo->renderbuffer = NULL;
+}
+
+static void crStateCheckFBOAttachments(CRFramebufferObject *pFBO, GLuint rbo, GLenum target)
+{
+ CRFBOAttachmentPoint *ap;
+ int u;
+
+ if (!pFBO)
+ return;
+
+ for (u=0; u<CR_MAX_COLOR_ATTACHMENTS; ++u)
+ {
+ ap = &pFBO->color[u];
+ if (ap->type==GL_RENDERBUFFER_EXT && ap->name==rbo)
+ {
+ crStateFramebufferRenderbufferEXT(target, u+GL_COLOR_ATTACHMENT0_EXT, 0, 0);
+#ifdef IN_GUEST
+ pFBO->status = GL_FRAMEBUFFER_UNDEFINED;
+#endif
+ }
+ }
+
+ ap = &pFBO->depth;
+ if (ap->type==GL_RENDERBUFFER_EXT && ap->name==rbo)
+ {
+ crStateFramebufferRenderbufferEXT(target, GL_DEPTH_ATTACHMENT_EXT, 0, 0);
+#ifdef IN_GUEST
+ pFBO->status = GL_FRAMEBUFFER_UNDEFINED;
+#endif
+ }
+ ap = &pFBO->stencil;
+ if (ap->type==GL_RENDERBUFFER_EXT && ap->name==rbo)
+ {
+ crStateFramebufferRenderbufferEXT(target, GL_STENCIL_ATTACHMENT_EXT, 0, 0);
+#ifdef IN_GUEST
+ pFBO->status = GL_FRAMEBUFFER_UNDEFINED;
+#endif
+ }
+}
+
+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)
+{
+ CRContext *g = GetCurrentContext();
+ /*CRFramebufferObjectState *fbo = &g->framebufferobject; - unused */
+ int i;
+
+ 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++)
+ {
+ if (renderbuffers[i])
+ {
+ CRRenderbufferObject *rbo;
+ rbo = (CRRenderbufferObject*) crHashtableSearch(g->shared->rbTable, renderbuffers[i]);
+ if (rbo)
+ {
+ int j;
+
+ ctStateRenderbufferRefsCleanup(g, renderbuffers[i], rbo);
+ CR_STATE_SHAREDOBJ_USAGE_FOREACH_USED_IDX(rbo, 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)
+ {
+ 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);
+ }
+ crHashtableDelete(g->shared->rbTable, renderbuffers[i], crStateFreeRBO);
+ }
+ }
+ }
+}
+
+DECLEXPORT(void) STATE_APIENTRY
+crStateRenderbufferStorageEXT(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
+{
+ CRContext *g = GetCurrentContext();
+ CRFramebufferObjectState *fbo = &g->framebufferobject;
+ CRRenderbufferObject *rb = fbo->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;
+ rb->internalformat = internalformat;
+}
+
+DECLEXPORT(void) STATE_APIENTRY
+crStateGetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint *params)
+{
+ CRContext *g = GetCurrentContext();
+ CRFramebufferObjectState *fbo = &g->framebufferobject;
+ CRRenderbufferObject *rb = fbo->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)
+ {
+ case GL_RENDERBUFFER_WIDTH_EXT:
+ *params = rb->width;
+ break;
+ case GL_RENDERBUFFER_HEIGHT_EXT:
+ *params = rb->height;
+ break;
+ case GL_RENDERBUFFER_INTERNAL_FORMAT_EXT:
+ *params = rb->internalformat;
+ break;
+ case GL_RENDERBUFFER_RED_SIZE_EXT:
+ case GL_RENDERBUFFER_GREEN_SIZE_EXT:
+ case GL_RENDERBUFFER_BLUE_SIZE_EXT:
+ case GL_RENDERBUFFER_ALPHA_SIZE_EXT:
+ case GL_RENDERBUFFER_DEPTH_SIZE_EXT:
+ case GL_RENDERBUFFER_STENCIL_SIZE_EXT:
+ CRSTATE_CHECKERR(GL_TRUE, GL_INVALID_OPERATION, "unimplemented");
+ break;
+ default:
+ CRSTATE_CHECKERR(GL_TRUE, GL_INVALID_ENUM, "invalid pname");
+ }
+}
+
+static void crStateInitFBOAttachmentPoint(CRFBOAttachmentPoint *fboap)
+{
+ fboap->type = GL_NONE;
+ fboap->name = 0;
+ fboap->level = 0;
+ fboap->face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
+ fboap->zoffset = 0;
+}
+
+static void crStateInitFrameBuffer(CRFramebufferObject *fbo)
+{
+ int i;
+
+ for (i=0; i<CR_MAX_COLOR_ATTACHMENTS; ++i)
+ crStateInitFBOAttachmentPoint(&fbo->color[i]);
+
+ crStateInitFBOAttachmentPoint(&fbo->depth);
+ crStateInitFBOAttachmentPoint(&fbo->stencil);
+
+ fbo->readbuffer = GL_COLOR_ATTACHMENT0_EXT;
+ fbo->drawbuffer[0] = GL_COLOR_ATTACHMENT0_EXT;
+
+#ifdef IN_GUEST
+ fbo->status = GL_FRAMEBUFFER_UNDEFINED;
+#endif
+}
+
+static GLboolean crStateGetFBOAttachmentPoint(CRFramebufferObject *fb, GLenum attachment, CRFBOAttachmentPoint **ap)
+{
+ switch (attachment)
+ {
+ case GL_DEPTH_ATTACHMENT_EXT:
+ *ap = &fb->depth;
+ break;
+ case GL_STENCIL_ATTACHMENT_EXT:
+ *ap = &fb->stencil;
+ break;
+ default:
+ if (attachment>=GL_COLOR_ATTACHMENT0_EXT && attachment<=GL_COLOR_ATTACHMENT15_EXT)
+ {
+ *ap = &fb->color[attachment-GL_COLOR_ATTACHMENT0_EXT];
+ }
+ else return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+DECLEXPORT(void) STATE_APIENTRY
+crStateBindFramebufferEXT(GLenum target, GLuint framebuffer)
+{
+ CRContext *g = GetCurrentContext();
+ CRFramebufferObjectState *fbo = &g->framebufferobject;
+ CRFramebufferObject *pFBO=NULL;
+
+ 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)
+ {
+ pFBO = (CRFramebufferObject*) crHashtableSearch(g->shared->fbTable, framebuffer);
+ if (!pFBO)
+ {
+ CRSTATE_CHECKERR(!crHashtableIsKeyUsed(g->shared->fbTable, framebuffer), GL_INVALID_OPERATION, "name is not a framebuffer");
+ pFBO = crStateFramebufferAllocate(g, framebuffer);
+ }
+
+
+ CR_STATE_SHAREDOBJ_USAGE_SET(pFBO, g);
+ }
+
+ /** @todo http://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
+ * FBO status might change when binding a different FBO here...but I doubt it happens.
+ * So no status reset here until a proper check.
+ */
+
+ switch (target)
+ {
+ case GL_FRAMEBUFFER_EXT:
+ fbo->readFB = pFBO;
+ fbo->drawFB = pFBO;
+ break;
+ case GL_READ_FRAMEBUFFER:
+ fbo->readFB = pFBO;
+ break;
+ case GL_DRAW_FRAMEBUFFER:
+ fbo->drawFB = pFBO;
+ break;
+ }
+}
+
+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();
+ int i;
+
+ 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++)
+ {
+ if (framebuffers[i])
+ {
+ CRFramebufferObject *fb;
+ fb = (CRFramebufferObject*) crHashtableSearch(g->shared->fbTable, framebuffers[i]);
+ if (fb)
+ {
+ int j;
+
+ ctStateFramebufferRefsCleanup(g, fb);
+
+ CR_STATE_SHAREDOBJ_USAGE_FOREACH_USED_IDX(fb, 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)
+ {
+ 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);
+ }
+ }
+ }
+}
+
+/** @todo move this function somewhere else*/
+/*return floor of base 2 log of x. log(0)==0*/
+static unsigned int crLog2Floor(unsigned int x)
+{
+ x |= (x >> 1);
+ x |= (x >> 2);
+ x |= (x >> 4);
+ x |= (x >> 8);
+ x |= (x >> 16);
+ x -= ((x >> 1) & 0x55555555);
+ x = (((x >> 2) & 0x33333333) + (x & 0x33333333));
+ x = (((x >> 4) + x) & 0x0f0f0f0f);
+ x += (x >> 8);
+ x += (x >> 16);
+ return (x & 0x0000003f) - 1;
+}
+
+static GLuint crStateFramebufferGet(CRFramebufferObjectState *fbo, GLenum target, CRFramebufferObject **apFBOs)
+{
+ /** @todo Since this function returns not more than one FBO, callers can be cleaned up. */
+ GLuint cPBOs = 0;
+ switch (target)
+ {
+ case GL_READ_FRAMEBUFFER:
+ cPBOs = 1;
+ apFBOs[0] = fbo->readFB;
+ break;
+ /* OpenGL glFramebufferTexture, glFramebufferRenderbuffer, glFramebufferRenderbuffer specs:
+ * "GL_FRAMEBUFFER is equivalent to GL_DRAW_FRAMEBUFFER."
+ */
+ case GL_FRAMEBUFFER:
+ case GL_DRAW_FRAMEBUFFER:
+ cPBOs = 1;
+ apFBOs[0] = 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 *apFBOs[2];
+ GLuint cFBOs = 0, i;
+ GLuint maxtexsizelog2;
+
+ 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);
+
+ 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)
+ {
+ return cFBOs;
+ }
+
+ switch (textarget)
+ {
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ maxtexsizelog2 = crLog2Floor(g->limits.maxCubeMapTextureSize);
+ *tobj = crStateTextureGet(GL_TEXTURE_CUBE_MAP_ARB, texture);
+ break;
+ case GL_TEXTURE_RECTANGLE_ARB:
+ maxtexsizelog2 = 0;
+ *tobj = crStateTextureGet(textarget, texture);
+ break;
+ case GL_TEXTURE_3D:
+ maxtexsizelog2 = crLog2Floor(g->limits.max3DTextureSize);
+ *tobj = crStateTextureGet(textarget, texture);
+ break;
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_1D:
+ maxtexsizelog2 = crLog2Floor(g->limits.maxTextureSize);
+ *tobj = crStateTextureGet(textarget, texture);
+ break;
+ default:
+ CRSTATE_CHECKERR_RET(GL_TRUE, GL_INVALID_OPERATION, "invalid textarget", 0);
+ }
+
+ CRSTATE_CHECKERR_RET(!*tobj, GL_INVALID_OPERATION, "invalid textarget/texture combo", 0);
+
+ if (GL_TEXTURE_RECTANGLE_ARB==textarget)
+ {
+ CRSTATE_CHECKERR_RET(level!=0, GL_INVALID_VALUE, "non zero mipmap level", 0);
+ }
+
+ CRSTATE_CHECKERR_RET(level<0, GL_INVALID_VALUE, "level<0", 0);
+ CRSTATE_CHECKERR_RET((GLuint)level>maxtexsizelog2, GL_INVALID_VALUE, "level too big", 0);
+
+#ifdef IN_GUEST
+ for (i = 0; i < cFBOs; ++i)
+ {
+ 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
+crStateFramebufferTexture1DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+{
+ CRContext *g = GetCurrentContext();
+ /*CRFramebufferObjectState *fbo = &g->framebufferobject; - unused */
+ CRFBOAttachmentPoint *aap[2];
+ GLuint cap, i;
+ CRTextureObj *tobj;
+
+ cap = crStateFramebufferTextureCheck(target, attachment, textarget, texture, level, aap, &tobj);
+ if (!cap) return;
+
+ if (!texture)
+ {
+ for (i = 0; i < cap; ++i)
+ {
+ crStateInitFBOAttachmentPoint(aap[i]);
+ }
+ return;
+ }
+
+ CRSTATE_CHECKERR(textarget!=GL_TEXTURE_1D, GL_INVALID_OPERATION, "textarget");
+
+ CR_STATE_SHAREDOBJ_USAGE_SET(tobj, g);
+
+ 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
+crStateFramebufferTexture2DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+{
+ CRContext *g = GetCurrentContext();
+ /* CRFramebufferObjectState *fbo = &g->framebufferobject; - unused */
+ CRFBOAttachmentPoint *aap[2];
+ GLuint cap, i;
+ CRTextureObj *tobj;
+
+ cap = crStateFramebufferTextureCheck(target, attachment, textarget, texture, level, aap, &tobj);
+ if (!cap) return;
+
+ if (!texture)
+ {
+ for (i = 0; i < cap; ++i)
+ {
+ crStateInitFBOAttachmentPoint(aap[i]);
+ }
+ return;
+ }
+
+ CRSTATE_CHECKERR(GL_TEXTURE_1D==textarget || GL_TEXTURE_3D==textarget, GL_INVALID_OPERATION, "textarget");
+
+ CR_STATE_SHAREDOBJ_USAGE_SET(tobj, g);
+
+ for (i = 0; i < cap; ++i)
+ {
+ 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;
+ }
+ }
+}
+
+DECLEXPORT(void) STATE_APIENTRY
+crStateFramebufferTexture3DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
+{
+ CRContext *g = GetCurrentContext();
+ /* CRFramebufferObjectState *fbo = &g->framebufferobject; - unused */
+ CRFBOAttachmentPoint *aap[2];
+ GLuint cap, i;
+ CRTextureObj *tobj;
+
+ cap = crStateFramebufferTextureCheck(target, attachment, textarget, texture, level, aap, &tobj);
+ if (!cap) return;
+
+ if (!texture)
+ {
+ for (i = 0; i < cap; ++i)
+ {
+ crStateInitFBOAttachmentPoint(aap[i]);
+ }
+ return;
+ }
+
+ CRSTATE_CHECKERR(zoffset>((GLint)g->limits.max3DTextureSize-1), GL_INVALID_VALUE, "zoffset too big");
+ CRSTATE_CHECKERR(textarget!=GL_TEXTURE_3D, GL_INVALID_OPERATION, "textarget");
+
+ CR_STATE_SHAREDOBJ_USAGE_SET(tobj, g);
+
+ 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
+crStateFramebufferRenderbufferEXT(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
+{
+ CRContext *g = GetCurrentContext();
+ CRFramebufferObjectState *fbo = &g->framebufferobject;
+ CRFramebufferObject *apFBOs[2];
+ GLuint cFBOs, i;
+ CRFBOAttachmentPoint *aap[2];
+ CRRenderbufferObject *rb;
+ (void)renderbuffertarget;
+
+ 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");
+ 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)
+ {
+ for (i = 0; i < cFBOs; ++i)
+ {
+#ifdef IN_GUEST
+ if (&aap[i]->type!=GL_NONE)
+ {
+ apFBOs[i]->status = GL_FRAMEBUFFER_UNDEFINED;
+ }
+#endif
+ crStateInitFBOAttachmentPoint(aap[i]);
+ }
+ return;
+ }
+
+ rb = (CRRenderbufferObject*) crHashtableSearch(g->shared->rbTable, renderbuffer);
+ 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 (aap[i]->type!=GL_RENDERBUFFER_EXT || aap[i]->name!=renderbuffer)
+ {
+ apFBOs[i]->status = GL_FRAMEBUFFER_UNDEFINED;
+ }
+#endif
+ crStateInitFBOAttachmentPoint(aap[i]);
+ aap[i]->type = GL_RENDERBUFFER_EXT;
+ aap[i]->name = renderbuffer;
+ }
+}
+
+DECLEXPORT(void) STATE_APIENTRY
+crStateGetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, GLenum pname, GLint *params)
+{
+ CRContext *g = GetCurrentContext();
+ CRFramebufferObjectState *fbo = &g->framebufferobject;
+ CRFramebufferObject *apFBOs[2];
+ GLint cFBOs = 0, i;
+ CRFBOAttachmentPoint *ap;
+
+ 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");
+
+ 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");
+ }
+
+ 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
+crStateGenerateMipmapEXT(GLenum target)
+{
+ (void)target;
+ /** @todo */
+}
+
+static void crStateSyncRenderbuffersCB(unsigned long key, void *data1, void *data2)
+{
+ CRRenderbufferObject *pRBO = (CRRenderbufferObject*) data1;
+ (void)key; (void)data2;
+
+ diff_api.GenRenderbuffersEXT(1, &pRBO->hwid);
+
+ 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)
+{
+ CRRenderbufferObject *pRBO;
+ CRTextureObj *tobj;
+
+ switch (pAP->type)
+ {
+ case GL_TEXTURE:
+ CRASSERT(pAP->name!=0);
+
+ tobj = (CRTextureObj *) crHashtableSearch(ctx->shared->textureTable, pAP->name);
+ if (tobj)
+ {
+ CRASSERT(!tobj->id || tobj->hwid);
+
+ switch (tobj->target)
+ {
+ case GL_TEXTURE_1D:
+ diff_api.FramebufferTexture1DEXT(GL_FRAMEBUFFER_EXT, ap, tobj->target, crStateGetTextureObjHWID(tobj), pAP->level);
+ break;
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_RECTANGLE_ARB:
+ diff_api.FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, ap, tobj->target, crStateGetTextureObjHWID(tobj), pAP->level);
+ break;
+ case GL_TEXTURE_CUBE_MAP_ARB:
+ diff_api.FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, ap, pAP->face, crStateGetTextureObjHWID(tobj), pAP->level);
+ break;
+ case GL_TEXTURE_3D:
+ diff_api.FramebufferTexture3DEXT(GL_FRAMEBUFFER_EXT, ap, tobj->target, crStateGetTextureObjHWID(tobj), pAP->level, pAP->zoffset);
+ break;
+ default:
+ crWarning("Unexpected textarget %d", tobj->target);
+ }
+ }
+ else
+ {
+ crWarning("Unknown texture id %d", pAP->name);
+ }
+ break;
+ case GL_RENDERBUFFER_EXT:
+ pRBO = (CRRenderbufferObject*) crHashtableSearch(ctx->shared->rbTable, pAP->name);
+ diff_api.FramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, ap, GL_RENDERBUFFER_EXT, pRBO->hwid);
+ break;
+ case GL_NONE:
+ /* Intentionally left blank */
+ break;
+ default: crWarning("Invalid attachment point type %d (ap: %i)", pAP->type, ap);
+ }
+}
+
+static void crStateSyncFramebuffersCB(unsigned long key, void *data1, void *data2)
+{
+ CRFramebufferObject *pFBO = (CRFramebufferObject*) data1;
+ CRContext *ctx = (CRContext*) data2;
+ GLint i;
+ (void)key;
+
+ diff_api.GenFramebuffersEXT(1, &pFBO->hwid);
+
+ diff_api.BindFramebufferEXT(GL_FRAMEBUFFER_EXT, pFBO->hwid);
+
+ for (i=0; i<CR_MAX_COLOR_ATTACHMENTS; ++i)
+ {
+ crStateSyncAP(&pFBO->color[i], GL_COLOR_ATTACHMENT0_EXT+i, ctx);
+ }
+
+ crStateSyncAP(&pFBO->depth, GL_DEPTH_ATTACHMENT_EXT, ctx);
+ crStateSyncAP(&pFBO->stencil, GL_STENCIL_ATTACHMENT_EXT, ctx);
+}
+
+DECLEXPORT(void) STATE_APIENTRY
+crStateFramebufferObjectSwitch(CRContext *from, CRContext *to)
+{
+ if (to->shared->bFBOResyncNeeded)
+ {
+ to->shared->bFBOResyncNeeded = GL_FALSE;
+
+ crHashtableWalk(to->shared->rbTable, crStateSyncRenderbuffersCB, NULL);
+ crHashtableWalk(to->shared->fbTable, crStateSyncFramebuffersCB, to);
+
+ if (to->framebufferobject.drawFB==to->framebufferobject.readFB)
+ {
+ diff_api.BindFramebufferEXT(GL_FRAMEBUFFER_EXT, to->framebufferobject.drawFB?
+ to->framebufferobject.drawFB->hwid:0);
+ }
+ else
+ {
+ diff_api.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, to->framebufferobject.drawFB?
+ to->framebufferobject.drawFB->hwid:0);
+
+ diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, to->framebufferobject.readFB?
+ to->framebufferobject.readFB->hwid:0);
+ }
+
+ diff_api.BindRenderbufferEXT(GL_RENDERBUFFER_EXT, to->framebufferobject.renderbuffer?
+ to->framebufferobject.renderbuffer->hwid:0);
+ }
+ else
+ {
+ if (to->framebufferobject.drawFB!=from->framebufferobject.drawFB
+ || to->framebufferobject.readFB!=from->framebufferobject.readFB)
+ {
+ if (to->framebufferobject.drawFB==to->framebufferobject.readFB)
+ {
+ diff_api.BindFramebufferEXT(GL_FRAMEBUFFER_EXT, to->framebufferobject.drawFB?
+ to->framebufferobject.drawFB->hwid:0);
+ }
+ else
+ {
+ diff_api.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, to->framebufferobject.drawFB?
+ to->framebufferobject.drawFB->hwid:0);
+
+ diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, to->framebufferobject.readFB?
+ to->framebufferobject.readFB->hwid:0);
+ }
+
+ diff_api.DrawBuffer(to->framebufferobject.drawFB?to->framebufferobject.drawFB->drawbuffer[0]:to->buffer.drawBuffer);
+ diff_api.ReadBuffer(to->framebufferobject.readFB?to->framebufferobject.readFB->readbuffer:to->buffer.readBuffer);
+ }
+
+ if (to->framebufferobject.renderbuffer!=from->framebufferobject.renderbuffer)
+ {
+ diff_api.BindRenderbufferEXT(GL_RENDERBUFFER_EXT, to->framebufferobject.renderbuffer?
+ to->framebufferobject.renderbuffer->hwid:0);
+ }
+ }
+}
+
+DECLEXPORT(void) STATE_APIENTRY
+crStateFramebufferObjectDisableHW(CRContext *ctx, GLuint idDrawFBO, GLuint idReadFBO)
+{
+ GLenum idDrawBuffer = 0, idReadBuffer = 0;
+
+ if (ctx->framebufferobject.drawFB || idDrawFBO)
+ {
+ diff_api.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0);
+ idDrawBuffer = ctx->buffer.drawBuffer;
+ }
+
+ if (ctx->framebufferobject.readFB || idReadFBO)
+ {
+ diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, 0);
+ idReadBuffer = ctx->buffer.readBuffer;
+ }
+
+ 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 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 */
+ {
+ diff_api.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, toCtx->framebufferobject.drawFB->hwid);
+ idDrawBuffer = toCtx->framebufferobject.drawFB->drawbuffer[0];
+ }
+ else if (idDrawFBO && !toCtx->framebufferobject.drawFB)
+ {
+ diff_api.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, idDrawFBO);
+ idDrawBuffer = GL_COLOR_ATTACHMENT0;
+ }
+
+ if ((fromCtx->framebufferobject.readFB) /* <- the FBO state was reset in crStateFramebufferObjectDisableHW */
+ && fromCtx->framebufferobject.readFB == toCtx->framebufferobject.readFB) /* .. and it was NOT restored properly in crStateFramebufferObjectSwitch */
+ {
+ diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, toCtx->framebufferobject.readFB->hwid);
+ idReadBuffer = toCtx->framebufferobject.readFB->readbuffer;
+ }
+ else if (idReadFBO && !toCtx->framebufferobject.readFB)
+ {
+ diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, idReadFBO);
+ idReadBuffer = GL_COLOR_ATTACHMENT0;
+ }
+
+ if (idDrawBuffer)
+ diff_api.DrawBuffer(idDrawBuffer);
+ if (idReadBuffer)
+ diff_api.ReadBuffer(idReadBuffer);
+
+ if (fromCtx->framebufferobject.renderbuffer /* <- the FBO state was reset in crStateFramebufferObjectDisableHW */
+ && fromCtx->framebufferobject.renderbuffer==toCtx->framebufferobject.renderbuffer) /* .. and it was NOT restored properly in crStateFramebufferObjectSwitch */
+ {
+ diff_api.BindRenderbufferEXT(GL_RENDERBUFFER_EXT, toCtx->framebufferobject.renderbuffer->hwid);
+ }
+}
+
+
+DECLEXPORT(GLuint) STATE_APIENTRY crStateGetFramebufferHWID(GLuint id)
+{
+ CRContext *g = GetCurrentContext();
+ CRFramebufferObject *pFBO = (CRFramebufferObject*) crHashtableSearch(g->shared->fbTable, id);
+#if 0 /*def DEBUG_misha*/
+ crDebug("FB id(%d) hw(%d)", id, pFBO ? pFBO->hwid : 0);
+#endif
+ return pFBO ? pFBO->hwid : 0;
+}
+
+DECLEXPORT(GLuint) STATE_APIENTRY crStateGetRenderbufferHWID(GLuint id)
+{
+ CRContext *g = GetCurrentContext();
+ CRRenderbufferObject *pRBO = (CRRenderbufferObject*) crHashtableSearch(g->shared->rbTable, id);
+
+ return pRBO ? pRBO->hwid : 0;
+}
+
+static void crStateCheckFBOHWIDCB(unsigned long key, void *data1, void *data2)
+{
+ CRFramebufferObject *pFBO = (CRFramebufferObject *) data1;
+ crCheckIDHWID_t *pParms = (crCheckIDHWID_t*) data2;
+ (void) key;
+
+ if (pFBO->hwid==pParms->hwid)
+ pParms->id = pFBO->id;
+}
+
+static void crStateCheckRBOHWIDCB(unsigned long key, void *data1, void *data2)
+{
+ CRRenderbufferObject *pRBO = (CRRenderbufferObject *) data1;
+ crCheckIDHWID_t *pParms = (crCheckIDHWID_t*) data2;
+ (void) key;
+
+ if (pRBO->hwid==pParms->hwid)
+ pParms->id = pRBO->id;
+}
+
+DECLEXPORT(GLuint) STATE_APIENTRY crStateFBOHWIDtoID(GLuint hwid)
+{
+ CRContext *g = GetCurrentContext();
+ crCheckIDHWID_t parms;
+
+ parms.id = hwid;
+ parms.hwid = hwid;
+
+ crHashtableWalk(g->shared->fbTable, crStateCheckFBOHWIDCB, &parms);
+ return parms.id;
+}
+
+DECLEXPORT(GLuint) STATE_APIENTRY crStateRBOHWIDtoID(GLuint hwid)
+{
+ CRContext *g = GetCurrentContext();
+ crCheckIDHWID_t parms;
+
+ parms.id = hwid;
+ parms.hwid = hwid;
+
+ crHashtableWalk(g->shared->rbTable, crStateCheckRBOHWIDCB, &parms);
+ return parms.id;
+}
+
+#ifdef IN_GUEST
+DECLEXPORT(GLenum) STATE_APIENTRY crStateCheckFramebufferStatusEXT(GLenum target)
+{
+ GLenum status = GL_FRAMEBUFFER_UNDEFINED;
+ CRContext *g = GetCurrentContext();
+ CRFramebufferObjectState *fbo = &g->framebufferobject;
+ CRFramebufferObject *pFBO=NULL;
+
+ switch (target)
+ {
+ case GL_FRAMEBUFFER_EXT:
+ pFBO = fbo->drawFB;
+ break;
+ case GL_READ_FRAMEBUFFER:
+ pFBO = fbo->readFB;
+ break;
+ case GL_DRAW_FRAMEBUFFER:
+ pFBO = fbo->drawFB;
+ break;
+ }
+
+ if (pFBO) status = pFBO->status;
+
+ return status;
+}
+
+DECLEXPORT(GLenum) STATE_APIENTRY crStateSetFramebufferStatus(GLenum target, GLenum status)
+{
+ CRContext *g = GetCurrentContext();
+ CRFramebufferObjectState *fbo = &g->framebufferobject;
+ CRFramebufferObject *pFBO=NULL;
+
+ switch (target)
+ {
+ case GL_FRAMEBUFFER_EXT:
+ pFBO = fbo->drawFB;
+ break;
+ case GL_READ_FRAMEBUFFER:
+ pFBO = fbo->readFB;
+ break;
+ case GL_DRAW_FRAMEBUFFER:
+ pFBO = fbo->drawFB;
+ break;
+ }
+
+ if (pFBO) pFBO->status = status;
+
+ return status;
+}
+#endif
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_funcs.py b/src/VBox/GuestHost/OpenGL/state_tracker/state_funcs.py
new file mode 100755
index 00000000..ebf1b379
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_funcs.py
@@ -0,0 +1,62 @@
+# Copyright (c) 2001, Stanford University
+# All rights reserved.
+#
+# See the file LICENSE.txt for information on redistributing this software.
+
+
+from __future__ import print_function
+import sys
+
+sys.path.append( "../glapi_parser" )
+import apiutil
+
+
+apiutil.CopyrightC()
+
+print("""
+/* DO NOT EDIT - THIS FILE AUTOMATICALLY GENERATED BY state_funcs.py SCRIPT */
+#ifndef CR_STATE_FUNCS_H
+#define CR_STATE_FUNCS_H
+
+#include "chromium.h"
+#include "cr_error.h"
+
+#include <iprt/cdefs.h>
+
+#if defined(WINDOWS)
+#define STATE_APIENTRY __stdcall
+#else
+#define STATE_APIENTRY
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define STATE_UNUSED(x) ((void)x)""")
+
+
+
+for func_name in apiutil.AllSpecials( "state" ):
+ return_type = apiutil.ReturnType(func_name)
+ params = apiutil.Parameters(func_name)
+ print('DECLEXPORT(%s) STATE_APIENTRY crState%s(%s);' % (return_type, func_name, apiutil.MakeDeclarationString(params)))
+
+for func_name in apiutil.AllSpecials( "state_feedback" ):
+ return_type = apiutil.ReturnType(func_name)
+ params = apiutil.Parameters(func_name)
+ print('DECLEXPORT(%s) STATE_APIENTRY crStateFeedback%s(%s);' % (return_type, func_name, apiutil.MakeDeclarationString(params)))
+
+for func_name in apiutil.AllSpecials( "state_select" ):
+ return_type = apiutil.ReturnType(func_name)
+ params = apiutil.Parameters(func_name)
+ print('DECLEXPORT(%s) STATE_APIENTRY crStateSelect%s(%s);' % (return_type, func_name, apiutil.MakeDeclarationString(params)))
+
+
+print("""
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CR_STATE_FUNCS_H */
+""")
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_get.py b/src/VBox/GuestHost/OpenGL/state_tracker/state_get.py
new file mode 100755
index 00000000..d5238c45
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_get.py
@@ -0,0 +1,234 @@
+# Copyright (c) 2001, Stanford University
+# All rights reserved.
+#
+# See the file LICENSE.txt for information on redistributing this software.
+
+from __future__ import print_function
+import sys, re, string
+import apiutil
+
+line_re = re.compile (r'^(\S+)\s+(GL_\S+)\s+(.*)\s*$')
+extensions_line_re = re.compile(r'^(\S+)\s+(GL_\S+)\s+(GL_\S+)\s+(.*)\s*$')
+
+params = {}
+extended_params = {}
+
+input = open( sys.argv[2]+"/state_get.txt", 'r' )
+for line in input.readlines():
+ if line[0] == '#':
+ continue
+ match = line_re.match( line )
+ if match:
+ type = match.group(1)
+ pname = match.group(2)
+ fields = match.group(3).split()
+ params[pname] = ( type, fields )
+
+input = open( sys.argv[2]+"/state_extensions_get.txt", 'r' )
+for line in input.readlines():
+ if line[0] == '#':
+ continue
+ match = extensions_line_re.match( line )
+ if match:
+ type = match.group(1)
+ pname = match.group(2)
+ ifdef = match.group(3)
+ fields = match.group(4).split()
+ extended_params[pname] = ( type, ifdef, fields )
+
+convert = {
+ 'GLenum' : {
+ 'Boolean' : '(GLboolean) (%s != 0)',
+ 'Double' : '(GLdouble) %s',
+ 'Float' : '(GLfloat) %s',
+ 'Integer' : '(GLint) %s'
+ },
+ 'GLboolean' : {
+ 'Boolean' : '(GLboolean) (%s != 0)',
+ 'Double' : '(GLdouble) %s',
+ 'Float' : '(GLfloat) %s',
+ 'Integer' : '(GLint) %s'
+ },
+ 'GLint' : {
+ 'Boolean' : '(GLboolean) (%s != 0)',
+ 'Double' : '(GLdouble) %s',
+ 'Float' : '(GLfloat) %s',
+ 'Integer' : '(GLint) %s'
+ },
+ 'GLuint' : {
+ 'Boolean' : '(GLboolean) (%s != 0)',
+ 'Double' : '(GLdouble) %s',
+ 'Float' : '(GLfloat) %s',
+ 'Integer' : '(GLint) %s'
+ },
+ 'GLfloat' : {
+ 'Boolean' : '(GLboolean) (%s != 0.0f)',
+ 'Double' : '(GLdouble) %s',
+ 'Float' : '%s',
+ 'Integer' : '(GLint) %s'
+ },
+ 'GLdouble' : {
+ 'Boolean' : '(GLboolean) (%s != 0.0)',
+ 'Double' : '%s',
+ 'Float' : '(GLfloat) %s',
+ 'Integer' : '(GLint) %s'
+ },
+ 'GLdefault' : {
+ 'Boolean' : '(GLboolean) (%s != (GLdefault) 0.0)',
+ 'Double' : '(GLdouble) %s',
+ 'Float' : '(GLfloat) %s',
+ 'Integer' : '(GLint) %s'
+ },
+ 'GLclampd' : {
+ 'Boolean' : '(GLboolean) (%s != 0.0)',
+ 'Double' : '%s',
+ 'Float' : '(GLfloat) %s',
+ 'Integer' : '__clampd_to_int(%s)'
+ },
+ 'GLclampf' : {
+ 'Boolean' : '(GLboolean) (%s != 0.0f)',
+ 'Double' : '(GLdouble) %s',
+ 'Float' : '%s',
+ 'Integer' : '__clampf_to_int(%s)'
+ }
+ }
+
+types = [ "Boolean", "Double", "Float", "Integer" ]
+
+ctypes = {
+ 'Boolean' : 'GLboolean',
+ 'Double' : 'GLdouble',
+ 'Float' : 'GLfloat',
+ 'Integer' : 'GLint'
+ }
+
+apiutil.CopyrightC()
+
+print("""
+/* DO NOT EDIT - THIS FILE GENERATED BY state_get.txt AND THE state_get.py SCRIPT */
+#include <stdio.h>
+#include <math.h>
+
+#include "state.h"
+#include "state/cr_statetypes.h"
+
+static GLint __clampd_to_int(GLdouble d)
+{
+ /* -1.0 -> MIN_INT, 1.0 -> MAX_INT */
+ if (d > 1.0)
+ return 0x7fffffff;
+ if (d < -1.0)
+ return 0x80000000;
+ return (GLint) floor(d * 2147483647.5);
+}
+
+static GLint __clampf_to_int(GLfloat f)
+{
+ /* -1.0f -> MIN_INT, 1.0f -> MAX_INT */
+ if (f > 1.0f)
+ return 0x7fffffff;
+ if (f < -1.0f)
+ return 0x80000000;
+ return (GLint) floor(f * 2147483647.5f);
+}
+
+static GLenum __getDrawBuffer(CRContext *g)
+{
+ return g->framebufferobject.drawFB ? g->framebufferobject.drawFB->drawbuffer[0] : g->buffer.drawBuffer;
+}
+
+static GLenum __getReadBuffer(CRContext *g)
+{
+ return g->framebufferobject.readFB ? g->framebufferobject.readFB->readbuffer : g->buffer.readBuffer;
+}
+""")
+
+header = """
+{
+ CRContext *g = GetCurrentContext();
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGet called in Begin/End");
+ return;
+ }
+
+ if (pname == GL_CURRENT_INDEX || pname == GL_CURRENT_COLOR ||
+ pname == GL_CURRENT_SECONDARY_COLOR_EXT ||
+ pname == GL_CURRENT_FOG_COORDINATE_EXT ||
+ pname == GL_CURRENT_NORMAL || pname == GL_EDGE_FLAG ||
+ pname == GL_CURRENT_TEXTURE_COORDS )
+ {
+#if 0
+ crStateError(__LINE__,__FILE__, GL_INVALID_OPERATION,
+ "Unimplemented glGet of a 'current' value" );
+#else
+ crStateCurrentRecover();/* &g->current, &sb->current, g->bitID );*/
+
+#endif
+ }
+
+ switch (pname) {
+"""
+
+for rettype in types:
+ print('')
+ print('void STATE_APIENTRY crStateGet%sv( GLenum pname, %s *params )' % ( rettype, ctypes[rettype] ))
+ print(header)
+
+ for pname in sorted(params.keys()):
+ print('\t\tcase %s:' % pname)
+ (srctype,fields) = params[pname]
+ try:
+ cvt = convert[srctype][rettype]
+ i = 0
+ for field in fields:
+ expr = cvt % field
+ print('\t\t\tparams[%d] = %s;' % (i,expr))
+ i += 1
+ except:
+ print('\t\t\tcrStateError(__LINE__,__FILE__,GL_INVALID_OPERATION, "Unimplemented glGet!");')
+ print("\t\t\tbreak;")
+
+
+ for pname in sorted(extended_params.keys()):
+ (srctype,ifdef,fields) = extended_params[pname]
+ ext = ifdef[3:] # the extension name with the "GL_" prefix removed
+ #print '#ifdef %s' % ifdef
+ print('#ifdef CR_%s' % ext)
+ print('\t\tcase %s:' % pname)
+ if ext != 'OPENGL_VERSION_1_2':
+ print('\t\t\tif (g->extensions.%s) {' % ext)
+ try:
+ cvt = convert[srctype][rettype]
+ i = 0
+ for field in fields:
+ expr = cvt % field
+ if field[0] == '%':
+ command = string.split(field, '%')
+ print('\t\t\t\t%s;' % command[1])
+ continue
+ elif ext != 'OPENGL_VERSION_1_2':
+ print('\t\t\t\tparams[%d] = %s;' % (i,expr))
+ else:
+ print('\t\t\tparams[%d] = %s;' % (i,expr))
+ i += 1
+ except:
+ print('\t\t\tcrStateError(__LINE__,__FILE__,GL_INVALID_OPERATION, "Unimplemented glGet!");')
+ if ext != 'OPENGL_VERSION_1_2':
+ print("\t\t\t}")
+ print("\t\t\telse {")
+ print('\t\t\t\tcrStateError(__LINE__,__FILE__,GL_INVALID_ENUM, "glGet%sv");' % rettype)
+ print("\t\t\t}")
+ print("\t\t\tbreak;")
+ #print '#endif /* %s */' % ifdef
+ print('#endif /* CR_%s */' % ext)
+
+ print('\t\tdefault:')
+ print('\t\t\tcrStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGet: Unknown enum: 0x%x", pname);')
+ print('\t\t\treturn;')
+ print('\t}')
+ print('}')
+
+from get_components import *
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_get.txt b/src/VBox/GuestHost/OpenGL/state_tracker/state_get.txt
new file mode 100644
index 00000000..150d350b
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_get.txt
@@ -0,0 +1,319 @@
+# Copyright (c) 2001, Stanford University
+# All rights reserved.
+#
+# See the file LICENSE.txt for information on redistributing this software.
+GLenum GL_MATRIX_MODE g->transform.matrixMode
+GLint GL_MODELVIEW_STACK_DEPTH g->transform.modelViewStack.depth+1
+GLint GL_PROJECTION_STACK_DEPTH g->transform.projectionStack.depth+1
+GLint GL_TEXTURE_STACK_DEPTH g->transform.textureStack[g->texture.curTextureUnit].depth+1
+GLint GL_COLOR_MATRIX_STACK_DEPTH g->transform.colorStack.depth+1
+GLdefault GL_MODELVIEW_MATRIX g->transform.modelViewStack.top->m00 g->transform.modelViewStack.top->m01 g->transform.modelViewStack.top->m02 g->transform.modelViewStack.top->m03 g->transform.modelViewStack.top->m10 g->transform.modelViewStack.top->m11 g->transform.modelViewStack.top->m12 g->transform.modelViewStack.top->m13 g->transform.modelViewStack.top->m20 g->transform.modelViewStack.top->m21 g->transform.modelViewStack.top->m22 g->transform.modelViewStack.top->m23 g->transform.modelViewStack.top->m30 g->transform.modelViewStack.top->m31 g->transform.modelViewStack.top->m32 g->transform.modelViewStack.top->m33
+GLdefault GL_PROJECTION_MATRIX g->transform.projectionStack.top->m00 g->transform.projectionStack.top->m01 g->transform.projectionStack.top->m02 g->transform.projectionStack.top->m03 g->transform.projectionStack.top->m10 g->transform.projectionStack.top->m11 g->transform.projectionStack.top->m12 g->transform.projectionStack.top->m13 g->transform.projectionStack.top->m20 g->transform.projectionStack.top->m21 g->transform.projectionStack.top->m22 g->transform.projectionStack.top->m23 g->transform.projectionStack.top->m30 g->transform.projectionStack.top->m31 g->transform.projectionStack.top->m32 g->transform.projectionStack.top->m33
+GLdefault GL_TEXTURE_MATRIX g->transform.textureStack[g->texture.curTextureUnit].top->m00 g->transform.textureStack[g->texture.curTextureUnit].top->m01 g->transform.textureStack[g->texture.curTextureUnit].top->m02 g->transform.textureStack[g->texture.curTextureUnit].top->m03 g->transform.textureStack[g->texture.curTextureUnit].top->m10 g->transform.textureStack[g->texture.curTextureUnit].top->m11 g->transform.textureStack[g->texture.curTextureUnit].top->m12 g->transform.textureStack[g->texture.curTextureUnit].top->m13 g->transform.textureStack[g->texture.curTextureUnit].top->m20 g->transform.textureStack[g->texture.curTextureUnit].top->m21 g->transform.textureStack[g->texture.curTextureUnit].top->m22 g->transform.textureStack[g->texture.curTextureUnit].top->m23 g->transform.textureStack[g->texture.curTextureUnit].top->m30 g->transform.textureStack[g->texture.curTextureUnit].top->m31 g->transform.textureStack[g->texture.curTextureUnit].top->m32 g->transform.textureStack[g->texture.curTextureUnit].top->m33
+GLdefault GL_COLOR_MATRIX g->transform.colorStack.top->m00 g->transform.colorStack.top->m01 g->transform.colorStack.top->m02 g->transform.colorStack.top->m03 g->transform.colorStack.top->m10 g->transform.colorStack.top->m11 g->transform.colorStack.top->m12 g->transform.colorStack.top->m13 g->transform.colorStack.top->m20 g->transform.colorStack.top->m21 g->transform.colorStack.top->m22 g->transform.colorStack.top->m23 g->transform.colorStack.top->m30 g->transform.colorStack.top->m31 g->transform.colorStack.top->m32 g->transform.colorStack.top->m33
+
+GLint GL_ATTRIB_STACK_DEPTH g->attrib.attribStackDepth
+GLint GL_ACTIVE_TEXTURE_ARB g->texture.curTextureUnit+GL_TEXTURE0_ARB
+GLint GL_CLIENT_ACTIVE_TEXTURE_ARB g->client.curClientTextureUnit+GL_TEXTURE0_ARB
+
+GLint GL_VIEWPORT g->viewport.viewportX g->viewport.viewportY g->viewport.viewportW g->viewport.viewportH
+GLclampd GL_DEPTH_RANGE g->viewport.nearClip g->viewport.farClip
+GLint GL_SCISSOR_BOX g->viewport.scissorX g->viewport.scissorY g->viewport.scissorW g->viewport.scissorH
+GLboolean GL_SCISSOR_TEST g->viewport.scissorTest
+
+
+GLenum GL_COLOR_MATERIAL_PARAMETER g->lighting.colorMaterialMode
+GLenum GL_COLOR_MATERIAL_FACE g->lighting.colorMaterialFace
+GLclampf GL_LIGHT_MODEL_AMBIENT g->lighting.lightModelAmbient.r g->lighting.lightModelAmbient.g g->lighting.lightModelAmbient.b g->lighting.lightModelAmbient.a
+GLboolean GL_LIGHT_MODEL_LOCAL_VIEWER g->lighting.lightModelLocalViewer
+GLboolean GL_LIGHT_MODEL_TWO_SIDE g->lighting.lightModelTwoSide
+GLenum GL_SHADE_MODEL g->lighting.shadeModel
+
+GLfloat GL_FOG_COLOR g->fog.color.r g->fog.color.g g->fog.color.b g->fog.color.a
+GLfloat GL_FOG_DENSITY g->fog.density
+GLfloat GL_FOG_START g->fog.start
+GLfloat GL_FOG_END g->fog.end
+GLenum GL_FOG_MODE g->fog.mode
+GLint GL_FOG_INDEX g->fog.index
+
+GLenum GL_FRONT_FACE g->polygon.frontFace
+GLenum GL_CULL_FACE_MODE g->polygon.cullFaceMode
+GLenum GL_POLYGON_MODE g->polygon.frontMode g->polygon.backMode
+GLboolean GL_CULL_FACE g->polygon.cullFace
+GLboolean GL_POLYGON_OFFSET_FILL g->polygon.polygonOffsetFill
+GLboolean GL_POLYGON_OFFSET_LINE g->polygon.polygonOffsetLine
+GLboolean GL_POLYGON_OFFSET_POINT g->polygon.polygonOffsetPoint
+GLboolean GL_POLYGON_SMOOTH g->polygon.polygonSmooth
+GLboolean GL_POLYGON_STIPPLE g->polygon.polygonStipple
+GLfloat GL_POLYGON_OFFSET_FACTOR g->polygon.offsetFactor
+GLfloat GL_POLYGON_OFFSET_UNITS g->polygon.offsetUnits
+
+GLboolean GL_ALPHA_TEST g->buffer.alphaTest
+GLboolean GL_BLEND g->buffer.blend
+GLboolean GL_COLOR_LOGIC_OP g->buffer.logicOp
+GLboolean GL_COLOR_MATERIAL GL_FALSE
+GLboolean GL_CLIP_PLANE0 g->transform.clip[0]
+GLboolean GL_CLIP_PLANE1 g->transform.clip[1]
+GLboolean GL_CLIP_PLANE2 g->transform.clip[2]
+GLboolean GL_CLIP_PLANE3 g->transform.clip[3]
+GLboolean GL_CLIP_PLANE4 g->transform.clip[4]
+GLboolean GL_CLIP_PLANE5 g->transform.clip[5]
+GLboolean GL_DEPTH_TEST g->buffer.depthTest
+GLboolean GL_DEPTH_WRITEMASK g->buffer.depthMask
+GLboolean GL_DITHER g->buffer.dither
+GLboolean GL_INDEX_LOGIC_OP g->buffer.indexLogicOp
+GLboolean GL_FOG g->fog.enable
+GLboolean GL_LIGHT0 g->lighting.light[0].enable
+GLboolean GL_LIGHT1 g->lighting.light[1].enable
+GLboolean GL_LIGHT2 g->lighting.light[2].enable
+GLboolean GL_LIGHT3 g->lighting.light[3].enable
+GLboolean GL_LIGHT4 g->lighting.light[4].enable
+GLboolean GL_LIGHT5 g->lighting.light[5].enable
+GLboolean GL_LIGHT6 g->lighting.light[6].enable
+GLboolean GL_LIGHT7 g->lighting.light[7].enable
+GLboolean GL_LIGHTING g->lighting.lighting
+GLboolean GL_LINE_SMOOTH g->line.lineSmooth
+GLboolean GL_LINE_STIPPLE g->line.lineStipple
+GLint GL_LOGIC_OP_MODE g->buffer.logicOpMode
+GLboolean GL_POINT_SMOOTH g->point.pointSmooth
+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
+
+GLboolean GL_TEXTURE_GEN_S g->texture.unit[g->texture.curTextureUnit].textureGen.s
+GLboolean GL_TEXTURE_GEN_T g->texture.unit[g->texture.curTextureUnit].textureGen.t
+GLboolean GL_TEXTURE_GEN_R g->texture.unit[g->texture.curTextureUnit].textureGen.r
+GLboolean GL_TEXTURE_GEN_Q g->texture.unit[g->texture.curTextureUnit].textureGen.q
+GLboolean GL_TEXTURE_1D g->texture.unit[g->texture.curTextureUnit].enabled1D
+GLboolean GL_TEXTURE_2D g->texture.unit[g->texture.curTextureUnit].enabled2D
+GLboolean GL_TEXTURE_3D g->texture.unit[g->texture.curTextureUnit].enabled3D
+
+GLfloat GL_LINE_WIDTH g->line.width
+GLint GL_LINE_STIPPLE_PATTERN g->line.pattern
+GLint GL_LINE_STIPPLE_REPEAT g->line.repeat
+
+GLboolean GL_PACK_SWAP_BYTES g->client.pack.swapBytes
+GLboolean GL_PACK_LSB_FIRST g->client.pack.psLSBFirst
+GLboolean GL_UNPACK_SWAP_BYTES g->client.unpack.swapBytes
+GLboolean GL_UNPACK_LSB_FIRST g->client.unpack.psLSBFirst
+GLint GL_PACK_ROW_LENGTH g->client.pack.rowLength
+GLint GL_PACK_SKIP_ROWS g->client.pack.skipRows
+GLint GL_PACK_SKIP_PIXELS g->client.pack.skipPixels
+GLint GL_PACK_ALIGNMENT g->client.pack.alignment
+GLint GL_PACK_IMAGE_HEIGHT g->client.pack.imageHeight
+GLint GL_PACK_SKIP_IMAGES g->client.pack.skipImages
+GLint GL_UNPACK_ROW_LENGTH g->client.unpack.rowLength
+GLint GL_UNPACK_SKIP_ROWS g->client.unpack.skipRows
+GLint GL_UNPACK_SKIP_PIXELS g->client.unpack.skipPixels
+GLint GL_UNPACK_ALIGNMENT g->client.unpack.alignment
+GLint GL_UNPACK_IMAGE_HEIGHT g->client.unpack.imageHeight
+GLint GL_UNPACK_SKIP_IMAGES g->client.unpack.skipImages
+GLfloat GL_ZOOM_X g->pixel.xZoom
+GLfloat GL_ZOOM_Y g->pixel.yZoom
+GLfloat GL_RED_BIAS g->pixel.bias.r
+GLfloat GL_GREEN_BIAS g->pixel.bias.g
+GLfloat GL_BLUE_BIAS g->pixel.bias.b
+GLfloat GL_ALPHA_BIAS g->pixel.bias.a
+GLfloat GL_RED_SCALE g->pixel.scale.r
+GLfloat GL_GREEN_SCALE g->pixel.scale.g
+GLfloat GL_BLUE_SCALE g->pixel.scale.b
+GLfloat GL_ALPHA_SCALE g->pixel.scale.a
+GLfloat GL_DEPTH_BIAS g->pixel.depthBias
+GLfloat GL_DEPTH_SCALE g->pixel.depthScale
+GLint GL_INDEX_OFFSET g->pixel.indexOffset
+GLint GL_INDEX_SHIFT g->pixel.indexShift
+GLboolean GL_MAP_COLOR g->pixel.mapColor
+GLboolean GL_MAP_STENCIL g->pixel.mapStencil
+GLint GL_PIXEL_MAP_A_TO_A_SIZE g->pixel.mapAtoAsize
+GLint GL_PIXEL_MAP_B_TO_B_SIZE g->pixel.mapBtoBsize
+GLint GL_PIXEL_MAP_G_TO_G_SIZE g->pixel.mapGtoGsize
+GLint GL_PIXEL_MAP_I_TO_A_SIZE g->pixel.mapItoAsize
+GLint GL_PIXEL_MAP_I_TO_B_SIZE g->pixel.mapItoBsize
+GLint GL_PIXEL_MAP_I_TO_G_SIZE g->pixel.mapItoGsize
+GLint GL_PIXEL_MAP_I_TO_I_SIZE g->pixel.mapItoIsize
+GLint GL_PIXEL_MAP_I_TO_R_SIZE g->pixel.mapItoRsize
+GLint GL_PIXEL_MAP_R_TO_R_SIZE g->pixel.mapRtoRsize
+GLint GL_PIXEL_MAP_S_TO_S_SIZE g->pixel.mapStoSsize
+
+GLboolean GL_AUTO_NORMAL g->eval.autoNormal
+GLboolean GL_MAP1_COLOR_4 g->eval.enable1D[pname-GL_MAP1_COLOR_4]
+GLboolean GL_MAP1_INDEX g->eval.enable1D[pname-GL_MAP1_COLOR_4]
+GLboolean GL_MAP1_NORMAL g->eval.enable1D[pname-GL_MAP1_COLOR_4]
+GLboolean GL_MAP1_TEXTURE_COORD_1 g->eval.enable1D[pname-GL_MAP1_COLOR_4]
+GLboolean GL_MAP1_TEXTURE_COORD_2 g->eval.enable1D[pname-GL_MAP1_COLOR_4]
+GLboolean GL_MAP1_TEXTURE_COORD_3 g->eval.enable1D[pname-GL_MAP1_COLOR_4]
+GLboolean GL_MAP1_TEXTURE_COORD_4 g->eval.enable1D[pname-GL_MAP1_COLOR_4]
+GLboolean GL_MAP1_VERTEX_3 g->eval.enable1D[pname-GL_MAP1_COLOR_4]
+GLboolean GL_MAP1_VERTEX_4 g->eval.enable1D[pname-GL_MAP1_COLOR_4]
+GLboolean GL_MAP2_COLOR_4 g->eval.enable2D[pname-GL_MAP2_COLOR_4]
+GLboolean GL_MAP2_INDEX g->eval.enable2D[pname-GL_MAP2_COLOR_4]
+GLboolean GL_MAP2_NORMAL g->eval.enable2D[pname-GL_MAP2_COLOR_4]
+GLboolean GL_MAP2_TEXTURE_COORD_1 g->eval.enable2D[pname-GL_MAP2_COLOR_4]
+GLboolean GL_MAP2_TEXTURE_COORD_2 g->eval.enable2D[pname-GL_MAP2_COLOR_4]
+GLboolean GL_MAP2_TEXTURE_COORD_3 g->eval.enable2D[pname-GL_MAP2_COLOR_4]
+GLboolean GL_MAP2_TEXTURE_COORD_4 g->eval.enable2D[pname-GL_MAP2_COLOR_4]
+GLboolean GL_MAP2_VERTEX_3 g->eval.enable2D[pname-GL_MAP2_COLOR_4]
+GLboolean GL_MAP2_VERTEX_4 g->eval.enable2D[pname-GL_MAP2_COLOR_4]
+GLdouble GL_MAP1_GRID_DOMAIN g->eval.u11D g->eval.u21D
+GLint GL_MAP1_GRID_SEGMENTS g->eval.un1D
+GLdouble GL_MAP2_GRID_DOMAIN g->eval.u12D g->eval.u22D g->eval.v12D g->eval.v22D
+GLint GL_MAP2_GRID_SEGMENTS g->eval.un2D g->eval.vn2D
+
+GLint GL_NAME_STACK_DEPTH 0
+
+GLenum GL_FOG_HINT g->hint.fog
+GLenum GL_LINE_SMOOTH_HINT g->hint.lineSmooth
+GLenum GL_POINT_SMOOTH_HINT g->hint.pointSmooth
+GLenum GL_POLYGON_SMOOTH_HINT g->hint.polygonSmooth
+GLenum GL_PERSPECTIVE_CORRECTION_HINT g->hint.perspectiveCorrection
+
+GLint GL_TEXTURE_BINDING_1D g->texture.unit[g->texture.curTextureUnit].currentTexture1D->id
+GLint GL_TEXTURE_BINDING_2D g->texture.unit[g->texture.curTextureUnit].currentTexture2D->id
+GLint GL_TEXTURE_BINDING_3D g->texture.unit[g->texture.curTextureUnit].currentTexture3D->id
+GLenum GL_TEXTURE_ENV_MODE g->texture.unit[g->texture.curTextureUnit].envMode
+
+GLboolean GL_VERTEX_ARRAY g->client.array.v.enabled
+GLint GL_VERTEX_ARRAY_SIZE g->client.array.v.size
+GLint GL_VERTEX_ARRAY_STRIDE g->client.array.v.stride
+GLint GL_VERTEX_ARRAY_TYPE g->client.array.v.type
+GLboolean GL_NORMAL_ARRAY g->client.array.n.enabled
+GLint GL_NORMAL_ARRAY_STRIDE g->client.array.n.stride
+GLint GL_NORMAL_ARRAY_TYPE g->client.array.n.type
+GLboolean GL_COLOR_ARRAY g->client.array.c.enabled
+GLint GL_COLOR_ARRAY_SIZE g->client.array.c.size
+GLint GL_COLOR_ARRAY_STRIDE g->client.array.c.stride
+GLint GL_COLOR_ARRAY_TYPE g->client.array.c.type
+GLboolean GL_INDEX_ARRAY g->client.array.i.enabled
+GLint GL_INDEX_ARRAY_STRIDE g->client.array.i.stride
+GLint GL_INDEX_ARRAY_TYPE g->client.array.i.type
+GLboolean GL_TEXTURE_COORD_ARRAY g->client.array.t[g->client.curClientTextureUnit].enabled
+GLint GL_TEXTURE_COORD_ARRAY_SIZE g->client.array.t[g->client.curClientTextureUnit].size
+GLint GL_TEXTURE_COORD_ARRAY_STRIDE g->client.array.t[g->client.curClientTextureUnit].stride
+GLint GL_TEXTURE_COORD_ARRAY_TYPE g->client.array.t[g->client.curClientTextureUnit].type
+GLboolean GL_EDGE_FLAG_ARRAY g->client.array.e.enabled
+GLint GL_EDGE_FLAG_ARRAY_STRIDE g->client.array.e.stride
+
+GLboolean GL_RGBA_MODE g->limits.rgbaMode
+GLboolean GL_INDEX_MODE (!g->limits.rgbaMode)
+GLint GL_AUX_BUFFERS g->limits.auxBuffers
+GLboolean GL_STEREO g->limits.stereo
+GLboolean GL_DOUBLEBUFFER g->limits.doubleBuffer
+GLint GL_INDEX_BITS g->limits.indexBits
+GLint GL_DEPTH_BITS g->limits.depthBits
+GLint GL_RED_BITS g->limits.redBits
+GLint GL_GREEN_BITS g->limits.greenBits
+GLint GL_BLUE_BITS g->limits.blueBits
+GLint GL_ALPHA_BITS g->limits.alphaBits
+GLint GL_STENCIL_BITS g->limits.stencilBits
+GLint GL_ACCUM_RED_BITS g->limits.accumRedBits
+GLint GL_ACCUM_GREEN_BITS g->limits.accumGreenBits
+GLint GL_ACCUM_BLUE_BITS g->limits.accumBlueBits
+GLint GL_ACCUM_ALPHA_BITS g->limits.accumAlphaBits
+GLclampf GL_COLOR_CLEAR_VALUE g->buffer.colorClearValue.r g->buffer.colorClearValue.g g->buffer.colorClearValue.b g->buffer.colorClearValue.a
+GLclampf GL_INDEX_CLEAR_VALUE g->buffer.indexClearValue
+GLclampd GL_DEPTH_CLEAR_VALUE g->buffer.depthClearValue
+GLfloat GL_ACCUM_CLEAR_VALUE g->buffer.accumClearValue.r g->buffer.accumClearValue.g g->buffer.accumClearValue.b g->buffer.accumClearValue.a
+GLenum GL_BLEND_SRC g->buffer.blendSrcRGB
+GLenum GL_BLEND_DST g->buffer.blendDstRGB
+#GLenum GL_BLEND_EQUATION g->buffer.blendEquation
+#GLclampf GL_BLEND_COLOR g->buffer.blendColor.r g->buffer.blendColor.g g->buffer.blendColor.b g->buffer.blendColor.a
+GLenum GL_DEPTH_FUNC g->buffer.depthFunc
+GLenum GL_ALPHA_TEST_FUNC g->buffer.alphaTestFunc
+GLint GL_ALPHA_TEST_REF g->buffer.alphaTestRef
+GLenum GL_DRAW_BUFFER __getDrawBuffer(g)
+GLenum GL_READ_BUFFER __getReadBuffer(g)
+GLboolean GL_COLOR_WRITEMASK g->buffer.colorWriteMask.r g->buffer.colorWriteMask.g g->buffer.colorWriteMask.b g->buffer.colorWriteMask.a
+GLint GL_INDEX_WRITEMASK g->buffer.indexWriteMask
+
+GLint GL_LIST_BASE g->lists.base
+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.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.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
+GLclampf GL_CURRENT_COLOR g->current.vertexAttrib[VERT_ATTRIB_COLOR0][0] g->current.vertexAttrib[VERT_ATTRIB_COLOR0][1] g->current.vertexAttrib[VERT_ATTRIB_COLOR0][2] g->current.vertexAttrib[VERT_ATTRIB_COLOR0][3]
+GLclampf GL_CURRENT_NORMAL g->current.vertexAttrib[VERT_ATTRIB_NORMAL][0] g->current.vertexAttrib[VERT_ATTRIB_NORMAL][1] g->current.vertexAttrib[VERT_ATTRIB_NORMAL][2]
+GLfloat GL_CURRENT_TEXTURE_COORDS g->current.vertexAttrib[VERT_ATTRIB_TEX0+g->texture.curTextureUnit][0] g->current.vertexAttrib[VERT_ATTRIB_TEX0+g->texture.curTextureUnit][1] g->current.vertexAttrib[VERT_ATTRIB_TEX0+g->texture.curTextureUnit][2] g->current.vertexAttrib[VERT_ATTRIB_TEX0+g->texture.curTextureUnit][3]
+GLboolean GL_EDGE_FLAG g->current.edgeFlag
+
+#?b?ub?s?us?i?ui?f?d GL_CURRENT_RASTER_POSITION g->current.rasterpos?.x g->current.rasterpos?.y g->current.rasterpos?.z g->current.rasterpos?.w
+GLfloat GL_CURRENT_RASTER_POSITION g->current.rasterAttrib[VERT_ATTRIB_POS][0] g->current.rasterAttrib[VERT_ATTRIB_POS][1] g->current.rasterAttrib[VERT_ATTRIB_POS][2] g->current.rasterAttrib[VERT_ATTRIB_POS][3]
+GLboolean GL_CURRENT_RASTER_POSITION_VALID g->current.rasterValid
+#?s?i?f?d GL_CURRENT_RASTER_TEXTURE_COORDS g->current.rastertexture?.s g->current.rastertexture?.t g->current.rastertexture?.p g->current.rastertexture?.q
+GLfloat GL_CURRENT_RASTER_TEXTURE_COORDS g->current.rasterAttrib[VERT_ATTRIB_TEX0][0] g->current.rasterAttrib[VERT_ATTRIB_TEX0][1] g->current.rasterAttrib[VERT_ATTRIB_TEX0][2] g->current.rasterAttrib[VERT_ATTRIB_TEX0][3]
+#GLclampf?b?ub?s?us?i?ui?f?d GL_CURRENT_RASTER_COLOR g->current.rastercolor?.r g->current.rastercolor?.g g->current.rastercolor?.b g->current.rastercolor?.a
+GLfloat GL_CURRENT_RASTER_COLOR g->current.rasterAttrib[VERT_ATTRIB_COLOR0][0] g->current.rasterAttrib[VERT_ATTRIB_COLOR0][1] g->current.rasterAttrib[VERT_ATTRIB_COLOR0][2] g->current.rasterAttrib[VERT_ATTRIB_COLOR0][3]
+GLfloat GL_CURRENT_RASTER_DISTANCE g->current.rasterAttrib[VERT_ATTRIB_FOG][0]
+GLdouble GL_CURRENT_RASTER_INDEX g->current.rasterIndex
+
+#GLclampf GL_CURRENT_SECONDARY_COLOR_EXT g->lighting.vertexAttrib[VERT_ATTRIB_COLOR1][0] g->lighting.vertexAttrib[VERT_ATTRIB_COLOR1][1] g->lighting.vertexAttrib[VERT_ATTRIB_COLOR1][2]
+#GLint GL_SECONDARY_COLOR_ARRAY_SIZE_EXT
+#GLint GL_SECONDARY_COLOR_ARRAY_TYPE_EXT
+#GLint GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT
+
+GLint GL_MAX_VERTEX_ATTRIBS_ARB g->limits.maxVertexProgramAttribs
+
+# Implementation-dependent limits queries
+
+GLint GL_MAX_TEXTURE_UNITS_ARB g->limits.maxTextureUnits
+GLint GL_MAX_TEXTURE_SIZE g->limits.maxTextureSize
+GLint GL_MAX_3D_TEXTURE_SIZE g->limits.max3DTextureSize
+GLint GL_MAX_LIGHTS g->limits.maxLights
+GLint GL_MAX_CLIP_PLANES g->limits.maxClipPlanes
+GLint GL_MAX_PROJECTION_STACK_DEPTH g->limits.maxProjectionStackDepth
+GLint GL_MAX_MODELVIEW_STACK_DEPTH g->limits.maxModelviewStackDepth
+GLint GL_MAX_TEXTURE_STACK_DEPTH g->limits.maxTextureStackDepth
+GLint GL_MAX_COLOR_MATRIX_STACK_DEPTH g->limits.maxColorStackDepth
+GLint GL_MAX_ATTRIB_STACK_DEPTH g->limits.maxAttribStackDepth
+GLint GL_MAX_CLIENT_ATTRIB_STACK_DEPTH g->limits.maxClientAttribStackDepth
+GLint GL_MAX_NAME_STACK_DEPTH g->limits.maxNameStackDepth
+GLint GL_MAX_ELEMENTS_INDICES g->limits.maxElementsIndices
+GLint GL_MAX_ELEMENTS_VERTICES g->limits.maxElementsVertices
+GLint GL_MAX_EVAL_ORDER g->limits.maxEvalOrder
+GLint GL_MAX_LIST_NESTING g->limits.maxListNesting
+GLint GL_MAX_PIXEL_MAP_TABLE g->limits.maxPixelMapTable
+GLint GL_MAX_VIEWPORT_DIMS g->limits.maxViewportDims[0] g->limits.maxViewportDims[1]
+GLint GL_SUBPIXEL_BITS g->limits.subpixelBits
+GLfloat GL_ALIASED_POINT_SIZE_RANGE g->limits.aliasedPointSizeRange[0] g->limits.aliasedPointSizeRange[1]
+GLfloat GL_SMOOTH_POINT_SIZE_RANGE g->limits.smoothPointSizeRange[0] g->limits.smoothPointSizeRange[1]
+GLfloat GL_SMOOTH_POINT_SIZE_GRANULARITY g->limits.pointSizeGranularity
+GLfloat GL_ALIASED_LINE_WIDTH_RANGE g->limits.aliasedLineWidthRange[0] g->limits.aliasedLineWidthRange[1]
+GLfloat GL_SMOOTH_LINE_WIDTH_RANGE g->limits.smoothLineWidthRange[0] g->limits.smoothLineWidthRange[1]
+GLfloat GL_SMOOTH_LINE_WIDTH_GRANULARITY g->limits.lineWidthGranularity
+GLint GL_RENDER_MODE g->renderMode
+
+# Feedback
+
+GLint GL_FEEDBACK_BUFFER_SIZE g->feedback.bufferSize
+GLint GL_FEEDBACK_BUFFER_TYPE g->feedback.type
+GLint GL_SELECTION_BUFFER_SIZE g->selection.bufferSize
+
+# FBO
+GLint GL_FRAMEBUFFER_BINDING_EXT (g->framebufferobject.drawFB?g->framebufferobject.drawFB->id:0)
+GLint GL_READ_FRAMEBUFFER_BINDING (g->framebufferobject.readFB?g->framebufferobject.readFB->id:0)
+GLint GL_RENDERBUFFER_BINDING_EXT (g->framebufferobject.renderbuffer?g->framebufferobject.renderbuffer->id:0)
+
+#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_getstring.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_getstring.c
new file mode 100644
index 00000000..3bee1c3f
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_getstring.c
@@ -0,0 +1,55 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#include "cr_error.h"
+#include "cr_version.h"
+#include "state.h"
+#include "state/cr_statetypes.h"
+#include "cr_extstring.h"
+#include "cr_mem.h"
+#include "cr_string.h"
+
+
+const GLubyte * STATE_APIENTRY crStateGetString( GLenum name )
+{
+ CRContext *g = GetCurrentContext();
+ if (!g)
+ return NULL;
+
+ switch( name )
+ {
+ case GL_VENDOR:
+ return (const GLubyte *) CR_VENDOR;
+ case GL_RENDERER:
+ return (const GLubyte *) CR_RENDERER;
+ case GL_VERSION:
+ return (const GLubyte *) CR_OPENGL_VERSION_STRING " Chromium " CR_VERSION_STRING;
+ case GL_EXTENSIONS:
+ /* This shouldn't normally be queried - the relevant SPU should
+ * catch this query and do all the extension string merging/mucking.
+ */
+ {
+ static char *extensions = NULL;
+ if (!extensions) {
+ extensions = crAlloc(crStrlen(crExtensions) + crStrlen(crChromiumExtensions) + 2);
+ crStrcpy(extensions, crExtensions);
+ crStrcpy(extensions, " ");
+ crStrcat(extensions, crChromiumExtensions);
+ }
+ return (const GLubyte *) extensions;
+ }
+#if defined(CR_ARB_vertex_program) || defined(CR_ARB_fragment_program)
+ case GL_PROGRAM_ERROR_STRING_ARB:
+ return g->program.errorString;
+#endif
+ default:
+ crStateError( __LINE__, __FILE__, GL_INVALID_ENUM,
+ "calling glGetString() with invalid name" );
+ return NULL;
+ }
+
+ (void) crAppOnlyExtensions; /* silence warnings */
+}
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_glsl.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_glsl.c
new file mode 100644
index 00000000..5767ca91
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_glsl.c
@@ -0,0 +1,1527 @@
+/* $Id: state_glsl.c $ */
+
+/** @file
+ * VBox OpenGL: GLSL state tracking
+ */
+
+/*
+ * Copyright (C) 2009-2019 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 "state.h"
+#include "state/cr_statetypes.h"
+#include "state/cr_statefuncs.h"
+#include "state_internals.h"
+#include "cr_mem.h"
+#include "cr_string.h"
+
+static CRGLSLShader* crStateGetShaderObj(GLuint id)
+{
+ CRContext *g = GetCurrentContext();
+
+ if (!g)
+ {
+ crWarning("crStateGetShaderObj called without current ctx");
+ }
+
+ return !g ? NULL : (CRGLSLShader *) crHashtableSearch(g->glsl.shaders, id);
+}
+
+static CRGLSLProgram* crStateGetProgramObj(GLuint id)
+{
+ CRContext *g = GetCurrentContext();
+
+ if (!g)
+ {
+ crWarning("crStateGetProgramObj called without current ctx");
+ }
+
+ return !g ? NULL : (CRGLSLProgram *) crHashtableSearch(g->glsl.programs, id);
+}
+
+static void crStateFreeGLSLShader(void *data)
+{
+ CRGLSLShader* pShader = (CRGLSLShader *) data;
+
+ if (pShader->source)
+ crFree(pShader->source);
+
+ crFree(pShader);
+}
+
+#ifdef IN_GUEST
+static void crStateFreeProgramAttribsLocationCache(CRGLSLProgram* pProgram)
+{
+ if (pProgram->pAttribs) crFree(pProgram->pAttribs);
+
+ pProgram->pAttribs = NULL;
+ pProgram->cAttribs = 0;
+}
+#endif
+
+static void crStateFreeProgramAttribs(CRGLSLProgram* pProgram)
+{
+ GLuint i;
+
+ for (i=0; i<pProgram->activeState.cAttribs; ++i)
+ {
+ crFree(pProgram->activeState.pAttribs[i].name);
+ }
+
+ for (i=0; i<pProgram->currentState.cAttribs; ++i)
+ {
+ crFree(pProgram->currentState.pAttribs[i].name);
+ }
+
+ if (pProgram->activeState.pAttribs)
+ crFree(pProgram->activeState.pAttribs);
+
+ if (pProgram->currentState.pAttribs)
+ crFree(pProgram->currentState.pAttribs);
+
+#ifdef IN_GUEST
+ crStateFreeProgramAttribsLocationCache(pProgram);
+
+ pProgram->bAttribsSynced = GL_FALSE;
+#endif
+
+}
+
+static void crStateFreeProgramUniforms(CRGLSLProgram* pProgram)
+{
+ GLuint i;
+
+ for (i=0; i<pProgram->cUniforms; ++i)
+ {
+ if (pProgram->pUniforms[i].name) crFree(pProgram->pUniforms[i].name);
+ if (pProgram->pUniforms[i].data) crFree(pProgram->pUniforms[i].data);
+ }
+
+ if (pProgram->pUniforms) crFree(pProgram->pUniforms);
+
+ pProgram->pUniforms = NULL;
+ pProgram->cUniforms = 0;
+
+#ifdef IN_GUEST
+ pProgram->bUniformsSynced = GL_FALSE;
+#endif
+}
+
+static void crStateShaderDecRefCount(void *data)
+{
+ CRGLSLShader *pShader = (CRGLSLShader *) data;
+
+ CRASSERT(pShader->refCount>0);
+
+ pShader->refCount--;
+
+ if (0==pShader->refCount && pShader->deleted)
+ {
+ CRContext *g = GetCurrentContext();
+ crHashtableDelete(g->glsl.shaders, pShader->id, crStateFreeGLSLShader);
+ }
+}
+
+static void crStateFakeDecRefCountCB(unsigned long key, void *data1, void *data2)
+{
+ CRGLSLShader *pShader = (CRGLSLShader *) data1;
+ CRContext *ctx = (CRContext*) data2;
+ CRGLSLShader *pRealShader;
+ (void) key; (void)ctx;
+
+ pRealShader = crStateGetShaderObj(pShader->id);
+
+ if (pRealShader)
+ {
+ crStateShaderDecRefCount(pRealShader);
+ }
+ else
+ {
+ crWarning("crStateFakeDecRefCountCB: NULL pRealShader");
+ }
+}
+
+static void crStateFreeGLSLProgram(void *data)
+{
+ CRGLSLProgram* pProgram = (CRGLSLProgram *) data;
+
+ crFreeHashtable(pProgram->currentState.attachedShaders, crStateShaderDecRefCount);
+
+ if (pProgram->activeState.attachedShaders)
+ {
+ CRContext *g = GetCurrentContext();
+ crHashtableWalk(pProgram->activeState.attachedShaders, crStateFakeDecRefCountCB, g);
+ crFreeHashtable(pProgram->activeState.attachedShaders, crStateFreeGLSLShader);
+ }
+
+ crStateFreeProgramAttribs(pProgram);
+
+ crStateFreeProgramUniforms(pProgram);
+
+ crFree(pProgram);
+}
+
+DECLEXPORT(void) STATE_APIENTRY crStateGLSLInit(CRContext *ctx)
+{
+ ctx->glsl.shaders = crAllocHashtable();
+ ctx->glsl.programs = crAllocHashtable();
+ ctx->glsl.activeProgram = NULL;
+ ctx->glsl.bResyncNeeded = GL_FALSE;
+
+ if (!ctx->glsl.shaders || !ctx->glsl.programs)
+ {
+ crWarning("crStateGLSLInit: Out of memory!");
+ return;
+ }
+}
+
+DECLEXPORT(void) STATE_APIENTRY crStateGLSLDestroy(CRContext *ctx)
+{
+ CRContext *g = GetCurrentContext();
+
+ /** @todo hack to allow crStateFreeGLSLProgram to work correctly,
+ as the current context isn't the one being destroyed*/
+#ifdef CHROMIUM_THREADSAFE
+ CRASSERT(g != ctx);
+ VBoxTlsRefAddRef(ctx); /* <- this is a hack to avoid subsequent SetCurrentContext(g) do recursive Destroy for ctx */
+ if (g)
+ VBoxTlsRefAddRef(g); /* <- ensure the g is not destroyed by the following SetCurrentContext call */
+ SetCurrentContext(ctx);
+#else
+ __currentContext = ctx;
+#endif
+
+ crFreeHashtable(ctx->glsl.programs, crStateFreeGLSLProgram);
+ crFreeHashtable(ctx->glsl.shaders, crStateFreeGLSLShader);
+
+#ifdef CHROMIUM_THREADSAFE
+ SetCurrentContext(g);
+ if (g)
+ VBoxTlsRefRelease(g);
+ VBoxTlsRefRelease(ctx); /* <- restore back the cRefs (see above) */
+#else
+ __currentContext = g;
+#endif
+
+}
+
+DECLEXPORT(GLuint) STATE_APIENTRY crStateGetShaderHWID(GLuint id)
+{
+ CRGLSLShader *pShader = crStateGetShaderObj(id);
+#ifdef IN_GUEST
+ CRASSERT(!pShader || pShader->hwid == id);
+#endif
+ return pShader ? pShader->hwid : 0;
+}
+
+DECLEXPORT(GLuint) STATE_APIENTRY crStateGetProgramHWID(GLuint id)
+{
+ CRGLSLProgram *pProgram = crStateGetProgramObj(id);
+#ifdef IN_GUEST
+ CRASSERT(!pProgram || pProgram->hwid == id);
+#endif
+ return pProgram ? pProgram->hwid : 0;
+}
+
+static void crStateCheckShaderHWIDCB(unsigned long key, void *data1, void *data2)
+{
+ CRGLSLShader *pShader = (CRGLSLShader *) data1;
+ crCheckIDHWID_t *pParms = (crCheckIDHWID_t*) data2;
+ (void) key;
+
+ if (pShader->hwid==pParms->hwid)
+ pParms->id = pShader->id;
+}
+
+static void crStateCheckProgramHWIDCB(unsigned long key, void *data1, void *data2)
+{
+ CRGLSLProgram *pProgram = (CRGLSLProgram *) data1;
+ crCheckIDHWID_t *pParms = (crCheckIDHWID_t*) data2;
+ (void) key;
+
+ if (pProgram->hwid==pParms->hwid)
+ pParms->id = pProgram->id;
+}
+
+DECLEXPORT(GLuint) STATE_APIENTRY crStateGLSLShaderHWIDtoID(GLuint hwid)
+{
+ CRContext *g = GetCurrentContext();
+ crCheckIDHWID_t parms;
+
+ parms.id = hwid;
+ parms.hwid = hwid;
+
+ crHashtableWalk(g->glsl.shaders, crStateCheckShaderHWIDCB, &parms);
+ return parms.id;
+}
+
+DECLEXPORT(GLuint) STATE_APIENTRY crStateGLSLProgramHWIDtoID(GLuint hwid)
+{
+ CRContext *g = GetCurrentContext();
+ crCheckIDHWID_t parms;
+
+ parms.id = hwid;
+ parms.hwid = hwid;
+
+ crHashtableWalk(g->glsl.programs, crStateCheckProgramHWIDCB, &parms);
+ 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;
+ CRContext *g = GetCurrentContext();
+ GLuint stateId = hwid;
+
+#ifdef IN_GUEST
+ CRASSERT(!crStateGetShaderObj(stateId));
+#else
+ /* 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)
+ {
+ crWarning("failed to allocate program key");
+ return 0;
+ }
+
+ Assert((pShader = crStateGetShaderObj(stateId)) == NULL);
+#endif
+
+ pShader = (CRGLSLShader *) crAlloc(sizeof(*pShader));
+ if (!pShader)
+ {
+ crWarning("crStateCreateShader: Out of memory!");
+ return 0;
+ }
+
+ pShader->id = stateId;
+ pShader->hwid = hwid;
+ pShader->type = type;
+ pShader->source = NULL;
+ pShader->compiled = GL_FALSE;
+ pShader->deleted = GL_FALSE;
+ pShader->refCount = 0;
+
+ crHashtableAdd(g->glsl.shaders, stateId, pShader);
+
+ return stateId;
+}
+
+DECLEXPORT(GLuint) STATE_APIENTRY crStateCreateProgram(GLuint hwid)
+{
+ CRGLSLProgram *pProgram;
+ CRContext *g = GetCurrentContext();
+ GLuint stateId = hwid;
+
+#ifdef IN_GUEST
+ pProgram = crStateGetProgramObj(stateId);
+ if (pProgram)
+ {
+ crWarning("Program object %d already exists!", stateId);
+ crStateDeleteProgram(stateId);
+ CRASSERT(!crStateGetProgramObj(stateId));
+ }
+#else
+ stateId = crHashtableAllocKeys(g->glsl.programs, 1);
+ if (!stateId)
+ {
+ crWarning("failed to allocate program key");
+ return 0;
+ }
+#endif
+
+ pProgram = (CRGLSLProgram *) crAlloc(sizeof(*pProgram));
+ if (!pProgram)
+ {
+ crWarning("crStateCreateProgram: Out of memory!");
+ return 0;
+ }
+
+ pProgram->id = stateId;
+ pProgram->hwid = hwid;
+ pProgram->validated = GL_FALSE;
+ pProgram->linked = GL_FALSE;
+ pProgram->deleted = GL_FALSE;
+ pProgram->activeState.attachedShaders = NULL;
+ pProgram->currentState.attachedShaders = crAllocHashtable();
+
+ pProgram->activeState.cAttribs = 0;
+ pProgram->activeState.pAttribs = NULL;
+ pProgram->currentState.cAttribs = 0;
+ pProgram->currentState.pAttribs = NULL;
+
+ pProgram->pUniforms = NULL;
+ pProgram->cUniforms = 0;
+
+#ifdef IN_GUEST
+ pProgram->pAttribs = NULL;
+ pProgram->cAttribs = 0;
+
+ pProgram->bUniformsSynced = GL_FALSE;
+ pProgram->bAttribsSynced = GL_FALSE;
+#endif
+
+ crHashtableAdd(g->glsl.programs, stateId, pProgram);
+
+ return stateId;
+}
+
+DECLEXPORT(void) STATE_APIENTRY crStateCompileShader(GLuint shader)
+{
+ CRGLSLShader *pShader = crStateGetShaderObj(shader);
+ if (!pShader)
+ {
+ crWarning("Unknown shader %d", shader);
+ return;
+ }
+
+ pShader->compiled = GL_TRUE;
+}
+
+static void crStateDbgCheckNoProgramOfId(void *data)
+{
+ (void)data;
+ crError("Unexpected Program id");
+}
+
+DECLEXPORT(void) STATE_APIENTRY crStateDeleteShader(GLuint shader)
+{
+ CRGLSLShader *pShader = crStateGetShaderObj(shader);
+ if (!pShader)
+ {
+ crWarning("Unknown shader %d", shader);
+ return;
+ }
+
+ pShader->deleted = GL_TRUE;
+
+ if (0==pShader->refCount)
+ {
+ 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);
+ }
+}
+
+DECLEXPORT(void) STATE_APIENTRY crStateAttachShader(GLuint program, GLuint shader)
+{
+ CRGLSLProgram *pProgram = crStateGetProgramObj(program);
+ CRGLSLShader *pShader;
+
+ if (!pProgram)
+ {
+ crWarning("Unknown program %d", program);
+ return;
+ }
+
+ if (crHashtableSearch(pProgram->currentState.attachedShaders, shader))
+ {
+ /*shader already attached to this program*/
+ return;
+ }
+
+ pShader = crStateGetShaderObj(shader);
+
+ if (!pShader)
+ {
+ crWarning("Unknown shader %d", shader);
+ return;
+ }
+
+ pShader->refCount++;
+
+ crHashtableAdd(pProgram->currentState.attachedShaders, shader, pShader);
+}
+
+DECLEXPORT(void) STATE_APIENTRY crStateDetachShader(GLuint program, GLuint shader)
+{
+ CRGLSLProgram *pProgram = crStateGetProgramObj(program);
+ CRGLSLShader *pShader;
+
+ if (!pProgram)
+ {
+ crWarning("Unknown program %d", program);
+ return;
+ }
+
+ pShader = (CRGLSLShader *) crHashtableSearch(pProgram->currentState.attachedShaders, shader);
+ if (!pShader)
+ {
+ crWarning("Shader %d isn't attached to program %d", shader, program);
+ return;
+ }
+
+ crHashtableDelete(pProgram->currentState.attachedShaders, shader, NULL);
+
+ CRASSERT(pShader->refCount>0);
+ pShader->refCount--;
+
+ if (0==pShader->refCount)
+ {
+ CRContext *g = GetCurrentContext();
+ crHashtableDelete(g->glsl.shaders, shader, crStateFreeGLSLShader);
+ }
+}
+
+DECLEXPORT(void) STATE_APIENTRY crStateUseProgram(GLuint program)
+{
+ CRContext *g = GetCurrentContext();
+
+ if (program>0)
+ {
+ CRGLSLProgram *pProgram = crStateGetProgramObj(program);
+
+ if (!pProgram)
+ {
+ crWarning("Unknown program %d", program);
+ return;
+ }
+
+ g->glsl.activeProgram = pProgram;
+ }
+ else
+ {
+ g->glsl.activeProgram = NULL;
+ }
+}
+
+DECLEXPORT(void) STATE_APIENTRY crStateDeleteProgram(GLuint program)
+{
+ CRContext *g = GetCurrentContext();
+ CRGLSLProgram *pProgram = crStateGetProgramObj(program);
+
+ if (!pProgram)
+ {
+ crWarning("Unknown program %d", program);
+ return;
+ }
+
+ if (g->glsl.activeProgram == pProgram)
+ {
+ g->glsl.activeProgram = NULL;
+ }
+
+ crHashtableDelete(g->glsl.programs, program, crStateFreeGLSLProgram);
+}
+
+DECLEXPORT(void) STATE_APIENTRY crStateValidateProgram(GLuint program)
+{
+ CRGLSLProgram *pProgram = crStateGetProgramObj(program);
+
+ if (!pProgram)
+ {
+ crWarning("Unknown program %d", program);
+ return;
+ }
+
+ pProgram->validated = GL_TRUE;
+}
+
+static void crStateCopyShaderCB(unsigned long key, void *data1, void *data2)
+{
+ CRGLSLShader *pRealShader = (CRGLSLShader *) data1;
+ CRGLSLProgram *pProgram = (CRGLSLProgram *) data2;
+ CRGLSLShader *pShader;
+ GLint sLen=0;
+
+ CRASSERT(pRealShader);
+ pRealShader->refCount++;
+
+ pShader = (CRGLSLShader *) crAlloc(sizeof(*pShader));
+ if (!pShader)
+ {
+ crWarning("crStateCopyShaderCB: Out of memory!");
+ return;
+ }
+
+ crMemcpy(pShader, pRealShader, sizeof(*pShader));
+
+ diff_api.GetShaderiv(pShader->hwid, GL_SHADER_SOURCE_LENGTH, &sLen);
+ if (sLen>0)
+ {
+ pShader->source = (GLchar*) crAlloc(sLen);
+ diff_api.GetShaderSource(pShader->hwid, sLen, NULL, pShader->source);
+ }
+
+ crHashtableAdd(pProgram->activeState.attachedShaders, key, pShader);
+}
+
+DECLEXPORT(void) STATE_APIENTRY crStateLinkProgram(GLuint program)
+{
+ CRGLSLProgram *pProgram = crStateGetProgramObj(program);
+ GLuint i;
+
+ if (!pProgram)
+ {
+ crWarning("Unknown program %d", program);
+ return;
+ }
+
+ pProgram->linked = GL_TRUE;
+
+ /*Free program's active state*/
+ if (pProgram->activeState.attachedShaders)
+ {
+ crHashtableWalk(pProgram->activeState.attachedShaders, crStateFakeDecRefCountCB, NULL);
+ crFreeHashtable(pProgram->activeState.attachedShaders, crStateFreeGLSLShader);
+ pProgram->activeState.attachedShaders = NULL;
+ }
+ for (i=0; i<pProgram->activeState.cAttribs; ++i)
+ {
+ crFree(pProgram->activeState.pAttribs[i].name);
+ }
+ if (pProgram->activeState.pAttribs) crFree(pProgram->activeState.pAttribs);
+
+ /*copy current state to active state*/
+ crMemcpy(&pProgram->activeState, &pProgram->currentState, sizeof(CRGLSLProgramState));
+
+ pProgram->activeState.attachedShaders = crAllocHashtable();
+ if (!pProgram->activeState.attachedShaders)
+ {
+ crWarning("crStateLinkProgram: Out of memory!");
+ return;
+ }
+ crHashtableWalk(pProgram->currentState.attachedShaders, crStateCopyShaderCB, pProgram);
+
+ /*that's not a bug, note the memcpy above*/
+ if (pProgram->activeState.pAttribs)
+ {
+ pProgram->activeState.pAttribs = (CRGLSLAttrib *) crAlloc(pProgram->activeState.cAttribs * sizeof(CRGLSLAttrib));
+ }
+
+ for (i=0; i<pProgram->activeState.cAttribs; ++i)
+ {
+ crMemcpy(&pProgram->activeState.pAttribs[i], &pProgram->currentState.pAttribs[i], sizeof(CRGLSLAttrib));
+ pProgram->activeState.pAttribs[i].name = crStrdup(pProgram->currentState.pAttribs[i].name);
+ }
+
+#ifdef IN_GUEST
+ crStateFreeProgramAttribsLocationCache(pProgram);
+#endif
+
+ crStateFreeProgramUniforms(pProgram);
+}
+
+DECLEXPORT(void) STATE_APIENTRY crStateBindAttribLocation(GLuint program, GLuint index, const char * name)
+{
+ CRGLSLProgram *pProgram = crStateGetProgramObj(program);
+ GLuint i;
+ CRGLSLAttrib *pAttribs;
+
+ if (!pProgram)
+ {
+ crWarning("Unknown program %d", program);
+ return;
+ }
+
+ if (index>=CR_MAX_VERTEX_ATTRIBS)
+ {
+ crWarning("crStateBindAttribLocation: Index too big %d", index);
+ return;
+ }
+
+ for (i=0; i<pProgram->currentState.cAttribs; ++i)
+ {
+ if (!crStrcmp(pProgram->currentState.pAttribs[i].name, name))
+ {
+ pProgram->currentState.pAttribs[i].index = index;
+ return;
+ }
+ }
+
+ pAttribs = (CRGLSLAttrib*) crAlloc((pProgram->currentState.cAttribs+1)*sizeof(CRGLSLAttrib));
+ if (!pAttribs)
+ {
+ crWarning("crStateBindAttribLocation: Out of memory!");
+ return;
+ }
+
+ if (pProgram->currentState.cAttribs)
+ {
+ crMemcpy(&pAttribs[0], &pProgram->currentState.pAttribs[0], pProgram->currentState.cAttribs*sizeof(CRGLSLAttrib));
+ }
+ pAttribs[pProgram->currentState.cAttribs].index = index;
+ pAttribs[pProgram->currentState.cAttribs].name = crStrdup(name);
+
+ pProgram->currentState.cAttribs++;
+ if (pProgram->currentState.pAttribs) crFree(pProgram->currentState.pAttribs);
+ pProgram->currentState.pAttribs = pAttribs;
+}
+
+DECLEXPORT(GLint) STATE_APIENTRY crStateGetUniformSize(GLenum type)
+{
+ GLint size;
+
+ switch (type)
+ {
+ case GL_FLOAT:
+ size = 1;
+ break;
+ case GL_FLOAT_VEC2:
+ size = 2;
+ break;
+ case GL_FLOAT_VEC3:
+ size = 3;
+ break;
+ case GL_FLOAT_VEC4:
+ size = 4;
+ break;
+ case GL_INT:
+ size = 1;
+ break;
+ case GL_INT_VEC2:
+ size = 2;
+ break;
+ case GL_INT_VEC3:
+ size = 3;
+ break;
+ case GL_INT_VEC4:
+ size = 4;
+ break;
+ case GL_BOOL:
+ size = 1;
+ break;
+ case GL_BOOL_VEC2:
+ size = 2;
+ break;
+ case GL_BOOL_VEC3:
+ size = 3;
+ break;
+ case GL_BOOL_VEC4:
+ size = 4;
+ break;
+ case GL_FLOAT_MAT2:
+ size = 8;
+ break;
+ case GL_FLOAT_MAT3:
+ size = 12;
+ break;
+ case GL_FLOAT_MAT4:
+ size = 16;
+ break;
+ case GL_SAMPLER_1D:
+ case GL_SAMPLER_2D:
+ case GL_SAMPLER_3D:
+ case GL_SAMPLER_CUBE:
+ case GL_SAMPLER_1D_SHADOW:
+ case GL_SAMPLER_2D_SHADOW:
+ case GL_SAMPLER_2D_RECT_ARB:
+ case GL_SAMPLER_2D_RECT_SHADOW_ARB:
+ size = 1;
+ break;
+#ifdef CR_OPENGL_VERSION_2_1
+ case GL_FLOAT_MAT2x3:
+ size = 8;
+ break;
+ case GL_FLOAT_MAT2x4:
+ size = 8;
+ break;
+ case GL_FLOAT_MAT3x2:
+ size = 12;
+ break;
+ case GL_FLOAT_MAT3x4:
+ size = 12;
+ break;
+ case GL_FLOAT_MAT4x2:
+ size = 16;
+ break;
+ case GL_FLOAT_MAT4x3:
+ size = 16;
+ break;
+#endif
+ default:
+ crWarning("crStateGetUniformSize: unknown uniform type 0x%x", (GLint)type);
+ size = 16;
+ break;
+ }
+
+ return size;
+}
+
+DECLEXPORT(GLboolean) STATE_APIENTRY crStateIsIntUniform(GLenum type)
+{
+ if (GL_INT==type
+ || GL_INT_VEC2==type
+ || GL_INT_VEC3==type
+ || GL_INT_VEC4==type
+ || GL_BOOL==type
+ || GL_BOOL_VEC2==type
+ || GL_BOOL_VEC3==type
+ || GL_BOOL_VEC4==type
+ || GL_SAMPLER_1D==type
+ || GL_SAMPLER_2D==type
+ || GL_SAMPLER_3D==type
+ || GL_SAMPLER_CUBE==type
+ || GL_SAMPLER_1D_SHADOW==type
+ || GL_SAMPLER_2D_SHADOW==type
+ || GL_SAMPLER_2D_RECT_ARB==type
+ || GL_SAMPLER_2D_RECT_SHADOW_ARB==type)
+ {
+ return GL_TRUE;
+ }
+ else return GL_FALSE;
+}
+
+DECLEXPORT(GLboolean) STATE_APIENTRY crStateIsProgramUniformsCached(GLuint program)
+{
+ CRGLSLProgram *pProgram = crStateGetProgramObj(program);
+
+ if (!pProgram)
+ {
+ WARN(("Unknown program %d", program));
+ return GL_FALSE;
+ }
+
+#ifdef IN_GUEST
+ return pProgram->bUniformsSynced;
+#else
+ WARN(("crStateIsProgramUniformsCached called on host side!!"));
+ return GL_FALSE;
+#endif
+}
+
+DECLEXPORT(GLboolean) STATE_APIENTRY crStateIsProgramAttribsCached(GLuint program)
+{
+ CRGLSLProgram *pProgram = crStateGetProgramObj(program);
+
+ if (!pProgram)
+ {
+ WARN(("Unknown program %d", program));
+ return GL_FALSE;
+ }
+
+#ifdef IN_GUEST
+ return pProgram->bAttribsSynced;
+#else
+ WARN(("crStateIsProgramAttribsCached called on host side!!"));
+ return GL_FALSE;
+#endif
+}
+
+/** @todo one of those functions should ignore uniforms starting with "gl"*/
+
+#ifdef IN_GUEST
+DECLEXPORT(void) STATE_APIENTRY
+crStateGLSLProgramCacheUniforms(GLuint program, GLsizei cbData, GLvoid *pData)
+{
+ CRGLSLProgram *pProgram = crStateGetProgramObj(program);
+ char *pCurrent = pData;
+ GLsizei cbRead, cbName;
+ GLuint i;
+
+ if (!pProgram)
+ {
+ crWarning("Unknown program %d", program);
+ return;
+ }
+
+ if (pProgram->bUniformsSynced)
+ {
+ crWarning("crStateGLSLProgramCacheUniforms: this shouldn't happen!");
+ crStateFreeProgramUniforms(pProgram);
+ }
+
+ if (cbData<(GLsizei)sizeof(GLsizei))
+ {
+ crWarning("crStateGLSLProgramCacheUniforms: data too short");
+ return;
+ }
+
+ pProgram->cUniforms = ((GLsizei*)pCurrent)[0];
+ pCurrent += sizeof(GLsizei);
+ cbRead = sizeof(GLsizei);
+
+ /*crDebug("crStateGLSLProgramCacheUniforms: %i active uniforms", pProgram->cUniforms);*/
+
+ if (pProgram->cUniforms)
+ {
+ pProgram->pUniforms = crAlloc(pProgram->cUniforms*sizeof(CRGLSLUniform));
+ if (!pProgram->pUniforms)
+ {
+ crWarning("crStateGLSLProgramCacheUniforms: no memory");
+ pProgram->cUniforms = 0;
+ return;
+ }
+ }
+
+ for (i=0; i<pProgram->cUniforms; ++i)
+ {
+ cbRead += sizeof(GLuint)+sizeof(GLsizei);
+ if (cbRead>cbData)
+ {
+ crWarning("crStateGLSLProgramCacheUniforms: out of data reading uniform %i", i);
+ return;
+ }
+ pProgram->pUniforms[i].data = NULL;
+ pProgram->pUniforms[i].location = ((GLint*)pCurrent)[0];
+ pCurrent += sizeof(GLint);
+ cbName = ((GLsizei*)pCurrent)[0];
+ pCurrent += sizeof(GLsizei);
+
+ cbRead += cbName;
+ if (cbRead>cbData)
+ {
+ crWarning("crStateGLSLProgramCacheUniforms: out of data reading uniform's name %i", i);
+ return;
+ }
+
+ pProgram->pUniforms[i].name = crStrndup(pCurrent, cbName);
+ pCurrent += cbName;
+
+ /*crDebug("crStateGLSLProgramCacheUniforms: uniform[%i]=%d, %s", i, pProgram->pUniforms[i].location, pProgram->pUniforms[i].name);*/
+ }
+
+ pProgram->bUniformsSynced = GL_TRUE;
+
+ CRASSERT((pCurrent-((char*)pData))==cbRead);
+ CRASSERT(cbRead==cbData);
+}
+
+DECLEXPORT(void) STATE_APIENTRY
+crStateGLSLProgramCacheAttribs(GLuint program, GLsizei cbData, GLvoid *pData)
+{
+ CRGLSLProgram *pProgram = crStateGetProgramObj(program);
+ char *pCurrent = pData;
+ GLsizei cbRead, cbName;
+ GLuint i;
+
+ if (!pProgram)
+ {
+ WARN(("Unknown program %d", program));
+ return;
+ }
+
+ if (pProgram->bAttribsSynced)
+ {
+ WARN(("crStateGLSLProgramCacheAttribs: this shouldn't happen!"));
+ crStateFreeProgramAttribsLocationCache(pProgram);
+ }
+
+ if (cbData<(GLsizei)sizeof(GLsizei))
+ {
+ WARN(("crStateGLSLProgramCacheAttribs: data too short"));
+ return;
+ }
+
+ pProgram->cAttribs = ((GLsizei*)pCurrent)[0];
+ pCurrent += sizeof(GLsizei);
+ cbRead = sizeof(GLsizei);
+
+ crDebug("crStateGLSLProgramCacheAttribs: %i active attribs", pProgram->cAttribs);
+
+ if (pProgram->cAttribs)
+ {
+ pProgram->pAttribs = crAlloc(pProgram->cAttribs*sizeof(CRGLSLAttrib));
+ if (!pProgram->pAttribs)
+ {
+ WARN(("crStateGLSLProgramCacheAttribs: no memory"));
+ pProgram->cAttribs = 0;
+ return;
+ }
+ }
+
+ for (i=0; i<pProgram->cAttribs; ++i)
+ {
+ cbRead += sizeof(GLuint)+sizeof(GLsizei);
+ if (cbRead>cbData)
+ {
+ crWarning("crStateGLSLProgramCacheAttribs: out of data reading attrib %i", i);
+ return;
+ }
+ pProgram->pAttribs[i].index = ((GLint*)pCurrent)[0];
+ pCurrent += sizeof(GLint);
+ cbName = ((GLsizei*)pCurrent)[0];
+ pCurrent += sizeof(GLsizei);
+
+ cbRead += cbName;
+ if (cbRead>cbData)
+ {
+ crWarning("crStateGLSLProgramCacheAttribs: out of data reading attrib's name %i", i);
+ return;
+ }
+
+ pProgram->pAttribs[i].name = crStrndup(pCurrent, cbName);
+ pCurrent += cbName;
+
+ crDebug("crStateGLSLProgramCacheAttribs: attribs[%i]=%d, %s", i, pProgram->pAttribs[i].index, pProgram->pAttribs[i].name);
+ }
+
+ pProgram->bAttribsSynced = GL_TRUE;
+
+ CRASSERT((pCurrent-((char*)pData))==cbRead);
+ CRASSERT(cbRead==cbData);
+}
+#else /* IN_GUEST */
+static GLboolean crStateGLSLProgramCacheOneUniform(GLuint location, GLsizei cbName, GLchar *pName,
+ char **pCurrent, GLsizei *pcbWritten, GLsizei maxcbData)
+{
+ *pcbWritten += sizeof(GLint)+sizeof(GLsizei)+cbName;
+ if (*pcbWritten>maxcbData)
+ {
+ crWarning("crStateGLSLProgramCacheUniforms: buffer too small");
+ crFree(pName);
+ return GL_FALSE;
+ }
+
+ /*crDebug("crStateGLSLProgramCacheUniforms: uniform[%i]=%s.", location, pName);*/
+
+ ((GLint*)*pCurrent)[0] = location;
+ *pCurrent += sizeof(GLint);
+ ((GLsizei*)*pCurrent)[0] = cbName;
+ *pCurrent += sizeof(GLsizei);
+ crMemcpy(*pCurrent, pName, cbName);
+ *pCurrent += cbName;
+
+ return GL_TRUE;
+}
+
+DECLEXPORT(void) STATE_APIENTRY
+crStateGLSLProgramCacheUniforms(GLuint program, GLsizei maxcbData, GLsizei *cbData, GLvoid *pData)
+{
+ CRGLSLProgram *pProgram = crStateGetProgramObj(program);
+ GLint maxUniformLen = 0, activeUniforms=0, fakeUniformsCount, i, j;
+ char *pCurrent = pData;
+ GLsizei cbWritten;
+
+ if (!pProgram)
+ {
+ crWarning("Unknown program %d", program);
+ return;
+ }
+
+ /*
+ * OpenGL spec says about GL_ACTIVE_UNIFORM_MAX_LENGTH:
+ * "If no active uniform variable exist, 0 is returned."
+ */
+ diff_api.GetProgramiv(pProgram->hwid, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformLen);
+ if (maxUniformLen > 0)
+ diff_api.GetProgramiv(pProgram->hwid, GL_ACTIVE_UNIFORMS, &activeUniforms);
+
+ *cbData = 0;
+
+ cbWritten = sizeof(GLsizei);
+ if (cbWritten>maxcbData)
+ {
+ crWarning("crStateGLSLProgramCacheUniforms: buffer too small");
+ return;
+ }
+ ((GLsizei*)pCurrent)[0] = activeUniforms;
+ fakeUniformsCount = activeUniforms;
+ pCurrent += sizeof(GLsizei);
+
+ crDebug("crStateGLSLProgramCacheUniforms: %i active uniforms", activeUniforms);
+
+ if (activeUniforms>0)
+ {
+ /*+8 to make sure our array uniforms with higher indices and [] will fit in as well*/
+ GLchar *name = (GLchar *) crAlloc(maxUniformLen+8);
+ GLenum type;
+ GLint size;
+ GLsizei cbName;
+ GLint location;
+
+ if (!name)
+ {
+ crWarning("crStateGLSLProgramCacheUniforms: no memory");
+ return;
+ }
+
+ for (i=0; i<activeUniforms; ++i)
+ {
+ diff_api.GetActiveUniform(pProgram->hwid, i, maxUniformLen, &cbName, &size, &type, name);
+ location = diff_api.GetUniformLocation(pProgram->hwid, name);
+
+ if (!crStateGLSLProgramCacheOneUniform(location, cbName, name, &pCurrent, &cbWritten, maxcbData))
+ return;
+
+ /* Only one active uniform variable will be reported for a uniform array by glGetActiveUniform,
+ * so we insert fake elements for other array elements.
+ */
+ if (size!=1)
+ {
+ char *pIndexStr = crStrchr(name, '[');
+ GLint firstIndex=1;
+ fakeUniformsCount += size;
+
+ crDebug("crStateGLSLProgramCacheUniforms: expanding array uniform, size=%i", size);
+
+ /*For array uniforms it's valid to query location of 1st element as both uniform and uniform[0].
+ *The name returned by glGetActiveUniform is driver dependent,
+ *atleast it's with [0] on win/ati and without [0] on linux/nvidia.
+ */
+ if (!pIndexStr)
+ {
+ pIndexStr = name+cbName;
+ firstIndex=0;
+ }
+ else
+ {
+ cbName = pIndexStr-name;
+ if (!crStateGLSLProgramCacheOneUniform(location, cbName, name, &pCurrent, &cbWritten, maxcbData))
+ return;
+ }
+
+ for (j=firstIndex; j<size; ++j)
+ {
+ sprintf(pIndexStr, "[%i]", j);
+ cbName = crStrlen(name);
+
+ location = diff_api.GetUniformLocation(pProgram->hwid, name);
+
+ if (!crStateGLSLProgramCacheOneUniform(location, cbName, name, &pCurrent, &cbWritten, maxcbData))
+ return;
+ }
+ }
+ }
+
+ crFree(name);
+ }
+
+ if (fakeUniformsCount!=activeUniforms)
+ {
+ ((GLsizei*)pData)[0] = fakeUniformsCount;
+ crDebug("FakeCount %i", fakeUniformsCount);
+ }
+
+ *cbData = cbWritten;
+
+ CRASSERT((pCurrent-((char*)pData))==cbWritten);
+}
+
+static GLboolean crStateGLSLProgramCacheOneAttrib(GLuint location, GLsizei cbName, GLchar *pName,
+ char **pCurrent, GLsizei *pcbWritten, GLsizei maxcbData)
+{
+ *pcbWritten += sizeof(GLint)+sizeof(GLsizei)+cbName;
+ if (*pcbWritten>maxcbData)
+ {
+ WARN(("crStateGLSLProgramCacheOneAttrib: buffer too small"));
+ crFree(pName);
+ return GL_FALSE;
+ }
+
+ crDebug("crStateGLSLProgramCacheOneAttrib: attrib[%i]=%s.", location, pName);
+
+ ((GLint*)*pCurrent)[0] = location;
+ *pCurrent += sizeof(GLint);
+ ((GLsizei*)*pCurrent)[0] = cbName;
+ *pCurrent += sizeof(GLsizei);
+ crMemcpy(*pCurrent, pName, cbName);
+ *pCurrent += cbName;
+
+ return GL_TRUE;
+}
+
+DECLEXPORT(void) STATE_APIENTRY
+crStateGLSLProgramCacheAttribs(GLuint program, GLsizei maxcbData, GLsizei *cbData, GLvoid *pData)
+{
+ CRGLSLProgram *pProgram = crStateGetProgramObj(program);
+ GLint maxAttribLen, activeAttribs=0, fakeAttribsCount, i, j;
+ char *pCurrent = pData;
+ GLsizei cbWritten;
+
+ if (!pProgram)
+ {
+ crWarning("Unknown program %d", program);
+ return;
+ }
+
+ diff_api.GetProgramiv(pProgram->hwid, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxAttribLen);
+ diff_api.GetProgramiv(pProgram->hwid, GL_ACTIVE_ATTRIBUTES, &activeAttribs);
+
+ *cbData = 0;
+
+ cbWritten = sizeof(GLsizei);
+ if (cbWritten>maxcbData)
+ {
+ crWarning("crStateGLSLProgramCacheAttribs: buffer too small");
+ return;
+ }
+ ((GLsizei*)pCurrent)[0] = activeAttribs;
+ fakeAttribsCount = activeAttribs;
+ pCurrent += sizeof(GLsizei);
+
+ crDebug("crStateGLSLProgramCacheAttribs: %i active attribs", activeAttribs);
+
+ if (activeAttribs>0)
+ {
+ /*+8 to make sure our array attribs with higher indices and [] will fit in as well*/
+ GLchar *name = (GLchar *) crAlloc(maxAttribLen+8);
+ GLenum type;
+ GLint size;
+ GLsizei cbName;
+ GLint location;
+
+ if (!name)
+ {
+ crWarning("crStateGLSLProgramCacheAttribs: no memory");
+ return;
+ }
+
+ for (i=0; i<activeAttribs; ++i)
+ {
+ diff_api.GetActiveAttrib(pProgram->hwid, i, maxAttribLen, &cbName, &size, &type, name);
+ location = diff_api.GetAttribLocation(pProgram->hwid, name);
+
+ if (!crStateGLSLProgramCacheOneAttrib(location, cbName, name, &pCurrent, &cbWritten, maxcbData))
+ return;
+
+ /* Only one active attrib variable will be reported for a attrib array by glGetActiveAttrib,
+ * so we insert fake elements for other array elements.
+ */
+ if (size!=1)
+ {
+ char *pIndexStr = crStrchr(name, '[');
+ GLint firstIndex=1;
+ fakeAttribsCount += size;
+
+ crDebug("crStateGLSLProgramCacheAttribs: expanding array attrib, size=%i", size);
+
+ /*For array attribs it's valid to query location of 1st element as both attrib and attrib[0].
+ *The name returned by glGetActiveAttrib is driver dependent,
+ *atleast it's with [0] on win/ati and without [0] on linux/nvidia.
+ */
+ if (!pIndexStr)
+ {
+ pIndexStr = name+cbName;
+ firstIndex=0;
+ }
+ else
+ {
+ cbName = pIndexStr-name;
+ if (!crStateGLSLProgramCacheOneAttrib(location, cbName, name, &pCurrent, &cbWritten, maxcbData))
+ return;
+ }
+
+ for (j=firstIndex; j<size; ++j)
+ {
+ sprintf(pIndexStr, "[%i]", j);
+ cbName = crStrlen(name);
+
+ location = diff_api.GetAttribLocation(pProgram->hwid, name);
+
+ if (!crStateGLSLProgramCacheOneAttrib(location, cbName, name, &pCurrent, &cbWritten, maxcbData))
+ return;
+ }
+ }
+ }
+
+ crFree(name);
+ }
+
+ if (fakeAttribsCount!=activeAttribs)
+ {
+ ((GLsizei*)pData)[0] = fakeAttribsCount;
+ crDebug("FakeCount %i", fakeAttribsCount);
+ }
+
+ *cbData = cbWritten;
+
+ CRASSERT((pCurrent-((char*)pData))==cbWritten);
+}
+#endif
+
+DECLEXPORT(GLint) STATE_APIENTRY crStateGetUniformLocation(GLuint program, const char * name)
+{
+#ifdef IN_GUEST
+ CRGLSLProgram *pProgram = crStateGetProgramObj(program);
+ GLint result=-1;
+ GLuint i;
+
+ if (!pProgram)
+ {
+ crWarning("Unknown program %d", program);
+ return -1;
+ }
+
+ if (!pProgram->bUniformsSynced)
+ {
+ crWarning("crStateGetUniformLocation called for uncached uniforms");
+ return -1;
+ }
+
+ for (i=0; i<pProgram->cUniforms; ++i)
+ {
+ if (!crStrcmp(name, pProgram->pUniforms[i].name))
+ {
+ result = pProgram->pUniforms[i].location;
+ break;
+ }
+ }
+
+ return result;
+#else
+ crWarning("crStateGetUniformLocation called on host side!!");
+ return -1;
+#endif
+}
+
+DECLEXPORT(GLint) STATE_APIENTRY crStateGetAttribLocation(GLuint program, const char * name)
+{
+#ifdef IN_GUEST
+ CRGLSLProgram *pProgram = crStateGetProgramObj(program);
+ GLint result=-1;
+ GLuint i;
+
+ if (!pProgram)
+ {
+ WARN(("Unknown program %d", program));
+ return -1;
+ }
+
+ if (!pProgram->bAttribsSynced)
+ {
+ WARN(("crStateGetAttribLocation called for uncached attribs"));
+ return -1;
+ }
+
+ for (i=0; i<pProgram->cAttribs; ++i)
+ {
+ if (!crStrcmp(name, pProgram->pAttribs[i].name))
+ {
+ result = pProgram->pAttribs[i].index;
+ break;
+ }
+ }
+
+ return result;
+#else
+ crWarning("crStateGetAttribLocation called on host side!!");
+ return -1;
+#endif
+}
+
+static void crStateGLSLCreateShadersCB(unsigned long key, void *data1, void *data2)
+{
+ CRGLSLShader *pShader = (CRGLSLShader*) data1;
+ CRContext *ctx = (CRContext *) data2;
+ (void)ctx; (void)key;
+
+ pShader->hwid = diff_api.CreateShader(pShader->type);
+}
+
+static void crStateFixAttachedShaderHWIDsCB(unsigned long key, void *data1, void *data2)
+{
+ CRGLSLShader *pShader = (CRGLSLShader*) data1;
+ CRGLSLShader *pRealShader;
+ CRContext *pCtx = (CRContext *) data2;
+
+ pRealShader = (CRGLSLShader *) crHashtableSearch(pCtx->glsl.shaders, key);
+ CRASSERT(pRealShader);
+
+ pShader->hwid = pRealShader->hwid;
+}
+
+static void crStateGLSLSyncShadersCB(unsigned long key, void *data1, void *data2)
+{
+ CRGLSLShader *pShader = (CRGLSLShader*) data1;
+ (void) key;
+ (void) data2;
+
+ if (pShader->source)
+ {
+ diff_api.ShaderSource(pShader->hwid, 1, (const char**)&pShader->source, NULL);
+ if (pShader->compiled)
+ diff_api.CompileShader(pShader->hwid);
+ crFree(pShader->source);
+ pShader->source = NULL;
+ }
+
+ if (pShader->deleted)
+ diff_api.DeleteShader(pShader->hwid);
+}
+
+static void crStateAttachShaderCB(unsigned long key, void *data1, void *data2)
+{
+ CRGLSLShader *pShader = (CRGLSLShader*) data1;
+ CRGLSLProgram *pProgram = (CRGLSLProgram *) data2;
+ (void) key;
+
+ if (pShader->source)
+ {
+ diff_api.ShaderSource(pShader->hwid, 1, (const char**)&pShader->source, NULL);
+ if (pShader->compiled)
+ diff_api.CompileShader(pShader->hwid);
+ }
+
+ diff_api.AttachShader(pProgram->hwid, pShader->hwid);
+}
+
+static void crStateDetachShaderCB(unsigned long key, void *data1, void *data2)
+{
+ CRGLSLShader *pShader = (CRGLSLShader*) data1;
+ CRGLSLProgram *pProgram = (CRGLSLProgram *) data2;
+ (void) key;
+
+ diff_api.DetachShader(pProgram->hwid, pShader->hwid);
+}
+
+static void crStateGLSLCreateProgramCB(unsigned long key, void *data1, void *data2)
+{
+ CRGLSLProgram *pProgram = (CRGLSLProgram*) data1;
+ CRContext *ctx = (CRContext *) data2;
+ GLuint i;
+ (void)key;
+
+ pProgram->hwid = diff_api.CreateProgram();
+
+ if (pProgram->linked)
+ {
+ CRASSERT(pProgram->activeState.attachedShaders);
+
+ crHashtableWalk(pProgram->activeState.attachedShaders, crStateFixAttachedShaderHWIDsCB, ctx);
+ crHashtableWalk(pProgram->activeState.attachedShaders, crStateAttachShaderCB, pProgram);
+
+ for (i=0; i<pProgram->activeState.cAttribs; ++i)
+ {
+ diff_api.BindAttribLocation(pProgram->hwid, pProgram->activeState.pAttribs[i].index, pProgram->activeState.pAttribs[i].name);
+ }
+
+ if (pProgram->validated)
+ diff_api.ValidateProgram(pProgram->hwid);
+
+ diff_api.LinkProgram(pProgram->hwid);
+ }
+
+ diff_api.UseProgram(pProgram->hwid);
+
+ for (i=0; i<pProgram->cUniforms; ++i)
+ {
+ GLint location;
+ GLfloat *pFdata = (GLfloat*)pProgram->pUniforms[i].data;
+ GLint *pIdata = (GLint*)pProgram->pUniforms[i].data;
+
+ location = diff_api.GetUniformLocation(pProgram->hwid, pProgram->pUniforms[i].name);
+ switch (pProgram->pUniforms[i].type)
+ {
+ case GL_FLOAT:
+ diff_api.Uniform1fv(location, 1, pFdata);
+ break;
+ case GL_FLOAT_VEC2:
+ diff_api.Uniform2fv(location, 1, pFdata);
+ break;
+ case GL_FLOAT_VEC3:
+ diff_api.Uniform3fv(location, 1, pFdata);
+ break;
+ case GL_FLOAT_VEC4:
+ diff_api.Uniform4fv(location, 1, pFdata);
+ break;
+ case GL_INT:
+ case GL_BOOL:
+ diff_api.Uniform1iv(location, 1, pIdata);
+ break;
+ case GL_INT_VEC2:
+ case GL_BOOL_VEC2:
+ diff_api.Uniform2iv(location, 1, pIdata);
+ break;
+ case GL_INT_VEC3:
+ case GL_BOOL_VEC3:
+ diff_api.Uniform3iv(location, 1, pIdata);
+ break;
+ case GL_INT_VEC4:
+ case GL_BOOL_VEC4:
+ diff_api.Uniform4iv(location, 1, pIdata);
+ break;
+ case GL_FLOAT_MAT2:
+ diff_api.UniformMatrix2fv(location, 1, GL_FALSE, pFdata);
+ break;
+ case GL_FLOAT_MAT3:
+ diff_api.UniformMatrix3fv(location, 1, GL_FALSE, pFdata);
+ break;
+ case GL_FLOAT_MAT4:
+ diff_api.UniformMatrix4fv(location, 1, GL_FALSE, pFdata);
+ break;
+ case GL_SAMPLER_1D:
+ case GL_SAMPLER_2D:
+ case GL_SAMPLER_3D:
+ case GL_SAMPLER_CUBE:
+ case GL_SAMPLER_1D_SHADOW:
+ case GL_SAMPLER_2D_SHADOW:
+ case GL_SAMPLER_2D_RECT_ARB:
+ case GL_SAMPLER_2D_RECT_SHADOW_ARB:
+ diff_api.Uniform1iv(location, 1, pIdata);
+ break;
+#ifdef CR_OPENGL_VERSION_2_1
+ case GL_FLOAT_MAT2x3:
+ diff_api.UniformMatrix2x3fv(location, 1, GL_FALSE, pFdata);
+ break;
+ case GL_FLOAT_MAT2x4:
+ diff_api.UniformMatrix2x4fv(location, 1, GL_FALSE, pFdata);
+ break;
+ case GL_FLOAT_MAT3x2:
+ diff_api.UniformMatrix3x2fv(location, 1, GL_FALSE, pFdata);
+ break;
+ case GL_FLOAT_MAT3x4:
+ diff_api.UniformMatrix3x4fv(location, 1, GL_FALSE, pFdata);
+ break;
+ case GL_FLOAT_MAT4x2:
+ diff_api.UniformMatrix4x2fv(location, 1, GL_FALSE, pFdata);
+ break;
+ case GL_FLOAT_MAT4x3:
+ diff_api.UniformMatrix4x3fv(location, 1, GL_FALSE, pFdata);
+ break;
+#endif
+ default:
+ crWarning("crStateGLSLCreateProgramCB: unknown uniform type 0x%x", (GLint)pProgram->pUniforms[i].type);
+ break;
+ }
+ crFree(pProgram->pUniforms[i].data);
+ crFree(pProgram->pUniforms[i].name);
+ } /*for (i=0; i<pProgram->cUniforms; ++i)*/
+ if (pProgram->pUniforms) crFree(pProgram->pUniforms);
+ pProgram->pUniforms = NULL;
+ pProgram->cUniforms = 0;
+
+ crHashtableWalk(pProgram->activeState.attachedShaders, crStateDetachShaderCB, pProgram);
+ crHashtableWalk(pProgram->currentState.attachedShaders, crStateAttachShaderCB, pProgram);
+}
+
+DECLEXPORT(void) STATE_APIENTRY crStateGLSLSwitch(CRContext *from, CRContext *to)
+{
+ GLboolean fForceUseProgramSet = GL_FALSE;
+ if (to->glsl.bResyncNeeded)
+ {
+ to->glsl.bResyncNeeded = GL_FALSE;
+
+ crHashtableWalk(to->glsl.shaders, crStateGLSLCreateShadersCB, 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 || fForceUseProgramSet)
+ {
+ diff_api.UseProgram(to->glsl.activeProgram ? to->glsl.activeProgram->hwid : 0);
+ }
+}
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_hint.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_hint.c
new file mode 100644
index 00000000..a3989258
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_hint.c
@@ -0,0 +1,132 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#include <stdio.h>
+#include "state.h"
+#include "state/cr_statetypes.h"
+#include "state_internals.h"
+
+void crStateHintInit (CRContext *ctx)
+{
+ CRHintState *h = &ctx->hint;
+ CRStateBits *sb = GetCurrentBits();
+ CRHintBits *hb = &(sb->hint);
+
+ h->perspectiveCorrection = GL_DONT_CARE;
+ RESET(hb->perspectiveCorrection, ctx->bitid);
+ h->pointSmooth = GL_DONT_CARE;
+ RESET(hb->pointSmooth, ctx->bitid);
+ h->lineSmooth = GL_DONT_CARE;
+ RESET(hb->lineSmooth, ctx->bitid);
+ h->polygonSmooth = GL_DONT_CARE;
+ RESET(hb->polygonSmooth, ctx->bitid);
+ h->fog = GL_DONT_CARE;
+ RESET(hb->fog, ctx->bitid);
+#ifdef CR_EXT_clip_volume_hint
+ h->clipVolumeClipping = GL_DONT_CARE;
+ RESET(hb->clipVolumeClipping, ctx->bitid);
+#endif
+#ifdef CR_ARB_texture_compression
+ h->textureCompression = GL_DONT_CARE;
+ RESET(hb->textureCompression, ctx->bitid);
+#endif
+#ifdef CR_SGIS_generate_mipmap
+ h->generateMipmap = GL_DONT_CARE;
+ RESET(hb->generateMipmap, ctx->bitid);
+#endif
+ RESET(hb->dirty, ctx->bitid);
+}
+
+void STATE_APIENTRY crStateHint(GLenum target, GLenum mode)
+{
+ CRContext *g = GetCurrentContext();
+ CRHintState *h = &(g->hint);
+ CRStateBits *sb = GetCurrentBits();
+ CRHintBits *hb = &(sb->hint);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glHint called in Begin/End");
+ return;
+ }
+
+ FLUSH();
+
+ if (mode != GL_FASTEST && mode != GL_NICEST && mode != GL_DONT_CARE) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glHint(mode)");
+ return;
+ }
+
+ switch (target) {
+ case GL_PERSPECTIVE_CORRECTION_HINT:
+ h->perspectiveCorrection = mode;
+ DIRTY(hb->perspectiveCorrection, g->neg_bitid);
+ break;
+ case GL_FOG_HINT:
+ h->fog = mode;
+ DIRTY(hb->fog, g->neg_bitid);
+ break;
+ case GL_LINE_SMOOTH_HINT:
+ h->lineSmooth = mode;
+ DIRTY(hb->lineSmooth, g->neg_bitid);
+ break;
+ case GL_POINT_SMOOTH_HINT:
+ h->pointSmooth = mode;
+ DIRTY(hb->pointSmooth, g->neg_bitid);
+ break;
+ case GL_POLYGON_SMOOTH_HINT:
+ h->polygonSmooth = mode;
+ DIRTY(hb->polygonSmooth, g->neg_bitid);
+ break;
+#ifdef CR_EXT_clip_volume_hint
+ case GL_CLIP_VOLUME_CLIPPING_HINT_EXT:
+ if (g->extensions.EXT_clip_volume_hint) {
+ h->clipVolumeClipping = mode;
+ DIRTY(hb->clipVolumeClipping, g->neg_bitid);
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glHint(target)");
+ return;
+ }
+ break;
+#endif
+#ifdef CR_ARB_texture_compression
+ case GL_TEXTURE_COMPRESSION_HINT_ARB:
+ if (g->extensions.ARB_texture_compression) {
+ h->textureCompression = mode;
+ DIRTY(hb->textureCompression, g->neg_bitid);
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glHint(target)");
+ return;
+ }
+ break;
+#endif
+#ifdef CR_SGIS_generate_mipmap
+ case GL_GENERATE_MIPMAP_HINT_SGIS:
+ if (g->extensions.SGIS_generate_mipmap) {
+ h->generateMipmap = mode;
+ DIRTY(hb->generateMipmap, g->neg_bitid);
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glHint(target)");
+ return;
+ }
+ break;
+#endif
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glHint(target)");
+ return;
+ }
+
+ DIRTY(hb->dirty, g->neg_bitid);
+}
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_hint.txt b/src/VBox/GuestHost/OpenGL/state_tracker/state_hint.txt
new file mode 100644
index 00000000..9f129338
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_hint.txt
@@ -0,0 +1,12 @@
+# Copyright (c) 2001, Stanford University
+# All rights reserved.
+#
+# See the file LICENSE.txt for information on redistributing this software.
+:lineSmooth:lineSmooth:Hint,GL_LINE_SMOOTH_HINT
+:pointSmooth:pointSmooth:Hint,GL_POINT_SMOOTH_HINT
+:polygonSmooth:polygonSmooth:Hint,GL_POLYGON_SMOOTH_HINT
+:perspectiveCorrection:perspectiveCorrection:Hint,GL_PERSPECTIVE_CORRECTION_HINT
+:fog:fog:Hint,GL_FOG_HINT
+:clipVolumeClipping:clipVolumeClipping:Hint,GL_CLIP_VOLUME_CLIPPING_HINT_EXT
+:generateMipmap:generateMipmap:Hint,GL_GENERATE_MIPMAP_HINT_SGIS
+:textureCompression:textureCompression:Hint,GL_TEXTURE_COMPRESSION_HINT_ARB
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_init.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_init.c
new file mode 100644
index 00000000..61e73a1b
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_init.c
@@ -0,0 +1,892 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#include "state.h"
+#include "cr_mem.h"
+#include "cr_error.h"
+#include "cr_spu.h"
+
+#include <iprt/asm.h>
+
+#ifdef CHROMIUM_THREADSAFE
+static bool __isContextTLSInited = false;
+CRtsd __contextTSD;
+#else
+CRContext *__currentContext = NULL;
+#endif
+
+CRStateBits *__currentBits = NULL;
+CRContext *g_pAvailableContexts[CR_MAX_CONTEXTS];
+uint32_t g_cContexts = 0;
+
+static CRSharedState *gSharedState=NULL;
+
+static CRContext *defaultContext = NULL;
+
+GLboolean g_bVBoxEnableDiffOnMakeCurrent = GL_TRUE;
+
+
+/**
+ * Allocate a new shared state object.
+ * Contains texture objects, display lists, etc.
+ */
+static CRSharedState *
+crStateAllocShared(void)
+{
+ CRSharedState *s = (CRSharedState *) crCalloc(sizeof(CRSharedState));
+ if (s) {
+ s->textureTable = crAllocHashtable();
+ s->dlistTable = crAllocHashtable();
+ s->buffersTable = crAllocHashtable();
+ s->fbTable = crAllocHashtable();
+ s->rbTable = crAllocHashtable();
+ s->refCount = 1; /* refcount is number of contexts using this state */
+ s->saveCount = 0;
+ }
+ return s;
+}
+
+/**
+ * Callback used for crFreeHashtable().
+ */
+DECLEXPORT(void)
+crStateDeleteTextureCallback(void *texObj)
+{
+#ifndef IN_GUEST
+ diff_api.DeleteTextures(1, &((CRTextureObj *)texObj)->hwid);
+#endif
+ crStateDeleteTextureObject((CRTextureObj *) texObj);
+}
+
+typedef struct CR_STATE_RELEASEOBJ
+{
+ CRContext *pCtx;
+ CRSharedState *s;
+} CR_STATE_RELEASEOBJ, *PCR_STATE_RELEASEOBJ;
+
+void crStateOnTextureUsageRelease(CRSharedState *pS, CRTextureObj *pObj)
+{
+ if (!pObj->pinned)
+ crHashtableDelete(pS->textureTable, pObj->id, crStateDeleteTextureCallback);
+ else
+ Assert(crHashtableSearch(pS->textureTable, pObj->id));
+}
+
+static void crStateReleaseTextureInternal(CRSharedState *pS, CRContext *pCtx, CRTextureObj *pObj)
+{
+ Assert(CR_STATE_SHAREDOBJ_USAGE_IS_USED(pObj) || pObj->pinned);
+ CR_STATE_SHAREDOBJ_USAGE_CLEAR(pObj, pCtx);
+ if (CR_STATE_SHAREDOBJ_USAGE_IS_USED(pObj))
+ return;
+
+ crStateOnTextureUsageRelease(pS, pObj);
+}
+
+DECLEXPORT(void) crStateReleaseTexture(CRContext *pCtx, CRTextureObj *pObj)
+{
+ Assert(CR_STATE_SHAREDOBJ_USAGE_IS_USED(pObj));
+ CR_STATE_SHAREDOBJ_USAGE_CLEAR(pObj, pCtx);
+ if (CR_STATE_SHAREDOBJ_USAGE_IS_USED(pObj))
+ return;
+
+ if (!gSharedState)
+ {
+ WARN(("no global shared"));
+ return;
+ }
+
+ crStateOnTextureUsageRelease(gSharedState, pObj);
+}
+
+static void crStateReleaseBufferObjectInternal(CRSharedState *pS, CRContext *pCtx, CRBufferObject *pObj)
+{
+ Assert(CR_STATE_SHAREDOBJ_USAGE_IS_USED(pObj));
+ CR_STATE_SHAREDOBJ_USAGE_CLEAR(pObj, pCtx);
+ if (!CR_STATE_SHAREDOBJ_USAGE_IS_USED(pObj))
+ crHashtableDelete(pS->buffersTable, pObj->id, crStateFreeBufferObject);
+}
+
+static void crStateReleaseFBOInternal(CRSharedState *pS, CRContext *pCtx, CRFramebufferObject *pObj)
+{
+ Assert(CR_STATE_SHAREDOBJ_USAGE_IS_USED(pObj));
+ CR_STATE_SHAREDOBJ_USAGE_CLEAR(pObj, pCtx);
+ if (!CR_STATE_SHAREDOBJ_USAGE_IS_USED(pObj))
+ crHashtableDelete(pS->fbTable, pObj->id, crStateFreeFBO);
+}
+
+static void crStateReleaseRBOInternal(CRSharedState *pS, CRContext *pCtx, CRRenderbufferObject *pObj)
+{
+ Assert(CR_STATE_SHAREDOBJ_USAGE_IS_USED(pObj));
+ CR_STATE_SHAREDOBJ_USAGE_CLEAR(pObj, pCtx);
+ if (!CR_STATE_SHAREDOBJ_USAGE_IS_USED(pObj))
+ crHashtableDelete(pS->rbTable, pObj->id, crStateFreeRBO);
+}
+
+static void ReleaseTextureCallback(unsigned long key, void *data1, void *data2)
+{
+ PCR_STATE_RELEASEOBJ pData = (PCR_STATE_RELEASEOBJ)data2;
+ CRTextureObj *pObj = (CRTextureObj *)data1;
+ (void)key;
+ crStateReleaseTextureInternal(pData->s, pData->pCtx, pObj);
+}
+
+static void ReleaseBufferObjectCallback(unsigned long key, void *data1, void *data2)
+{
+ PCR_STATE_RELEASEOBJ pData = (PCR_STATE_RELEASEOBJ)data2;
+ CRBufferObject *pObj = (CRBufferObject *)data1;
+ (void)key;
+ crStateReleaseBufferObjectInternal(pData->s, pData->pCtx, pObj);
+}
+
+static void ReleaseFBOCallback(unsigned long key, void *data1, void *data2)
+{
+ PCR_STATE_RELEASEOBJ pData = (PCR_STATE_RELEASEOBJ)data2;
+ CRFramebufferObject *pObj = (CRFramebufferObject *)data1;
+ (void)key;
+ crStateReleaseFBOInternal(pData->s, pData->pCtx, pObj);
+}
+
+static void ReleaseRBOCallback(unsigned long key, void *data1, void *data2)
+{
+ PCR_STATE_RELEASEOBJ pData = (PCR_STATE_RELEASEOBJ)data2;
+ CRRenderbufferObject *pObj = (CRRenderbufferObject *)data1;
+ (void)key;
+ crStateReleaseRBOInternal(pData->s, pData->pCtx, pObj);
+}
+
+
+/**
+ * Decrement shared state's refcount and delete when it hits zero.
+ */
+#ifndef IN_GUEST
+DECLEXPORT(void) crStateFreeShared(CRContext *pContext, CRSharedState *s)
+#else
+static void crStateFreeShared(CRContext *pContext, CRSharedState *s)
+#endif
+{
+ int32_t refCount = ASMAtomicDecS32(&s->refCount);
+
+ Assert(refCount >= 0);
+ if (refCount <= 0) {
+ if (s==gSharedState)
+ {
+ gSharedState = NULL;
+ }
+ crFreeHashtable(s->textureTable, crStateDeleteTextureCallback);
+ crFreeHashtable(s->dlistTable, crFree); /* call crFree for each entry */
+ crFreeHashtable(s->buffersTable, crStateFreeBufferObject);
+ crFreeHashtable(s->fbTable, crStateFreeFBO);
+ crFreeHashtable(s->rbTable, crStateFreeRBO);
+ crFree(s);
+ }
+ else if (pContext)
+ {
+ /* evaluate usage bits*/
+ CR_STATE_RELEASEOBJ CbData;
+ CbData.pCtx = pContext;
+ CbData.s = s;
+ crHashtableWalk(s->textureTable, ReleaseTextureCallback, &CbData);
+ crHashtableWalk(s->buffersTable, ReleaseBufferObjectCallback , &CbData);
+ crHashtableWalk(s->fbTable, ReleaseFBOCallback, &CbData);
+ crHashtableWalk(s->rbTable, ReleaseRBOCallback, &CbData);
+ }
+}
+
+#ifndef IN_GUEST
+
+DECLEXPORT(CRSharedState *) crStateGlobalSharedAcquire(void)
+{
+ if (!gSharedState)
+ {
+ crWarning("No Global Shared State!");
+ return NULL;
+ }
+ ASMAtomicIncS32(&gSharedState->refCount);
+ return gSharedState;
+}
+
+DECLEXPORT(void) crStateGlobalSharedRelease(void)
+{
+ crStateFreeShared(NULL, gSharedState);
+}
+
+#endif /* IN_GUEST */
+
+DECLEXPORT(void) STATE_APIENTRY
+crStateShareContext(GLboolean value)
+{
+ CRContext *pCtx = GetCurrentContext();
+ CRASSERT(pCtx && pCtx->shared);
+
+ if (value)
+ {
+ if (pCtx->shared == gSharedState)
+ {
+ return;
+ }
+
+ crDebug("Context(%i) shared", pCtx->id);
+
+ if (!gSharedState)
+ {
+ gSharedState = pCtx->shared;
+ }
+ else
+ {
+ crStateFreeShared(pCtx, pCtx->shared);
+ pCtx->shared = gSharedState;
+ ASMAtomicIncS32(&gSharedState->refCount);
+ }
+ }
+ else
+ {
+ if (pCtx->shared != gSharedState)
+ {
+ return;
+ }
+
+ crDebug("Context(%i) unshared", pCtx->id);
+
+ if (gSharedState->refCount==1)
+ {
+ gSharedState = NULL;
+ }
+ else
+ {
+ pCtx->shared = crStateAllocShared();
+ pCtx->shared->id = pCtx->id;
+ crStateFreeShared(pCtx, gSharedState);
+ }
+ }
+}
+
+DECLEXPORT(void) STATE_APIENTRY
+crStateShareLists(CRContext *pContext1, CRContext *pContext2)
+{
+ CRASSERT(pContext1->shared);
+ CRASSERT(pContext2->shared);
+
+ if (pContext2->shared == pContext1->shared)
+ {
+ return;
+ }
+
+ crStateFreeShared(pContext1, pContext1->shared);
+ pContext1->shared = pContext2->shared;
+ ASMAtomicIncS32(&pContext2->shared->refCount);
+}
+
+DECLEXPORT(GLboolean) STATE_APIENTRY
+crStateContextIsShared(CRContext *pCtx)
+{
+ return pCtx->shared==gSharedState;
+}
+
+DECLEXPORT(void) STATE_APIENTRY
+crStateSetSharedContext(CRContext *pCtx)
+{
+ if (gSharedState)
+ {
+ crWarning("crStateSetSharedContext: shared is being changed from %p to %p", gSharedState, pCtx->shared);
+ }
+
+ gSharedState = pCtx->shared;
+}
+
+#ifdef CHROMIUM_THREADSAFE
+static void
+crStateFreeContext(CRContext *ctx);
+static DECLCALLBACK(void) crStateContextDtor(void *pvCtx)
+{
+ crStateFreeContext((CRContext*)pvCtx);
+}
+#endif
+
+/*
+ * Helper for crStateCreateContext, below.
+ */
+static CRContext *
+crStateCreateContextId(int i, const CRLimitsState *limits, GLint visBits, CRContext *shareCtx)
+{
+ CRContext *ctx;
+ int j;
+ int node32 = i >> 5;
+ int node = i & 0x1f;
+ (void)limits;
+
+ 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);
+#endif
+ ctx->flush_func = NULL;
+ for (j=0;j<CR_MAX_BITARRAY;j++){
+ if (j == node32) {
+ ctx->bitid[j] = (1 << node);
+ } else {
+ ctx->bitid[j] = 0;
+ }
+ ctx->neg_bitid[j] = ~(ctx->bitid[j]);
+ }
+
+ if (shareCtx) {
+ CRASSERT(shareCtx->shared);
+ ctx->shared = shareCtx->shared;
+ ASMAtomicIncS32(&ctx->shared->refCount);
+ }
+ else {
+ ctx->shared = crStateAllocShared();
+ ctx->shared->id = ctx->id;
+ }
+
+ /* use Chromium's OpenGL defaults */
+ crStateLimitsInit( &(ctx->limits) );
+ crStateExtensionsInit( &(ctx->limits), &(ctx->extensions) );
+
+ crStateBufferObjectInit( ctx ); /* must precede client state init! */
+ crStateClientInit( ctx );
+
+ crStateBufferInit( ctx );
+ crStateCurrentInit( ctx );
+ crStateEvaluatorInit( ctx );
+ crStateFogInit( ctx );
+ crStateHintInit( ctx );
+ crStateLightingInit( ctx );
+ crStateLineInit( ctx );
+ crStateListsInit( ctx );
+ crStateMultisampleInit( ctx );
+ crStateOcclusionInit( ctx );
+ crStatePixelInit( ctx );
+ crStatePolygonInit( ctx );
+ crStatePointInit( ctx );
+ crStateProgramInit( ctx );
+ crStateRegCombinerInit( ctx );
+ crStateStencilInit( ctx );
+ crStateTextureInit( ctx );
+ crStateTransformInit( ctx );
+ crStateViewportInit ( ctx );
+ crStateFramebufferObjectInit(ctx);
+ crStateGLSLInit(ctx);
+
+ /* This has to come last. */
+ crStateAttribInit( &(ctx->attrib) );
+
+ ctx->renderMode = GL_RENDER;
+
+ /* Initialize values that depend on the visual mode */
+ if (visBits & CR_DOUBLE_BIT) {
+ ctx->limits.doubleBuffer = GL_TRUE;
+ }
+ if (visBits & CR_RGB_BIT) {
+ ctx->limits.redBits = 8;
+ ctx->limits.greenBits = 8;
+ ctx->limits.blueBits = 8;
+ if (visBits & CR_ALPHA_BIT) {
+ ctx->limits.alphaBits = 8;
+ }
+ }
+ else {
+ ctx->limits.indexBits = 8;
+ }
+ if (visBits & CR_DEPTH_BIT) {
+ ctx->limits.depthBits = 24;
+ }
+ if (visBits & CR_STENCIL_BIT) {
+ ctx->limits.stencilBits = 8;
+ }
+ if (visBits & CR_ACCUM_BIT) {
+ ctx->limits.accumRedBits = 16;
+ ctx->limits.accumGreenBits = 16;
+ ctx->limits.accumBlueBits = 16;
+ if (visBits & CR_ALPHA_BIT) {
+ ctx->limits.accumAlphaBits = 16;
+ }
+ }
+ if (visBits & CR_STEREO_BIT) {
+ ctx->limits.stereo = GL_TRUE;
+ }
+ if (visBits & CR_MULTISAMPLE_BIT) {
+ ctx->limits.sampleBuffers = 1;
+ ctx->limits.samples = 4;
+ ctx->multisample.enabled = GL_TRUE;
+ }
+
+ if (visBits & CR_OVERLAY_BIT) {
+ ctx->limits.level = 1;
+ }
+
+ return ctx;
+}
+
+/** @todo crStateAttribDestroy*/
+static void
+crStateFreeContext(CRContext *ctx)
+{
+#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 );
+ crStateListsDestroy( ctx );
+ crStateLightingDestroy( ctx );
+ crStateOcclusionDestroy( ctx );
+ crStateProgramDestroy( ctx );
+ crStateTextureDestroy( ctx );
+ crStateTransformDestroy( ctx );
+ crStateFreeShared(ctx, ctx->shared);
+ crStateFramebufferObjectDestroy(ctx);
+ crStateGLSLDestroy(ctx);
+ if (ctx->buffer.pFrontImg) crFree(ctx->buffer.pFrontImg);
+ if (ctx->buffer.pBackImg) crFree(ctx->buffer.pBackImg);
+ crFree( ctx );
+}
+
+#ifdef CHROMIUM_THREADSAFE
+# ifndef RT_OS_WINDOWS
+static void crStateThreadTlsDtor(void *pvValue)
+{
+ CRContext *pCtx = (CRContext*)pvValue;
+ VBoxTlsRefRelease(pCtx);
+}
+# endif
+#endif
+
+/*
+ * Allocate the state (dirty) bits data structures.
+ * This should be called before we create any contexts.
+ * We'll also create the default/NULL context at this time and make
+ * it the current context by default. This means that if someone
+ * tries to set GL state before calling MakeCurrent() they'll be
+ * modifying the default state object, and not segfaulting on a NULL
+ * pointer somewhere.
+ */
+void crStateInit(void)
+{
+ unsigned int i;
+
+ /* Purely initialize the context bits */
+ if (!__currentBits) {
+ __currentBits = (CRStateBits *) crCalloc( sizeof(CRStateBits) );
+ 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_pAvailableContexts[i] = NULL;
+ g_cContexts = 0;
+
+#ifdef CHROMIUM_THREADSAFE
+ if (!__isContextTLSInited)
+ {
+# ifndef RT_OS_WINDOWS
+ /* tls destructor is implemented for all platforms except windows*/
+ crInitTSDF(&__contextTSD, crStateThreadTlsDtor);
+# else
+ /* windows should do cleanup via DllMain THREAD_DETACH notification */
+ crInitTSD(&__contextTSD);
+# endif
+ __isContextTLSInited = 1;
+ }
+#endif
+
+ if (defaultContext) {
+ /* Free the default/NULL context.
+ * Ensures context bits are reset */
+#ifdef CHROMIUM_THREADSAFE
+ SetCurrentContext(NULL);
+ VBoxTlsRefRelease(defaultContext);
+#else
+ crStateFreeContext(defaultContext);
+ __currentContext = NULL;
+#endif
+ }
+
+ /* 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_pAvailableContexts[0] == defaultContext);
+ CRASSERT(g_cContexts == 1);
+#ifdef CHROMIUM_THREADSAFE
+ SetCurrentContext(defaultContext);
+#else
+ __currentContext = defaultContext;
+#endif
+}
+
+void crStateDestroy(void)
+{
+ int i;
+ if (__currentBits)
+ {
+ crStateClientDestroyBits(&(__currentBits->client));
+ crStateLightingDestroyBits(&(__currentBits->lighting));
+ crFree(__currentBits);
+ __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;
+#endif
+}
+
+/*
+ * Notes on context switching and the "default context".
+ *
+ * See the paper "Tracking Graphics State for Networked Rendering"
+ * by Ian Buck, Greg Humphries and Pat Hanrahan for background
+ * information about how the state tracker and context switching
+ * works.
+ *
+ * When we make a new context current, we call crStateSwitchContext()
+ * in order to transform the 'from' context into the 'to' context
+ * (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,
+ * we point __currentContext to the new context.
+ *
+ * A subtle problem we have to deal with is context destruction.
+ * This issue arose while testing with Glean. We found that when
+ * the currently bound context was getting destroyed that state
+ * tracking was incorrect when a subsequent new context was activated.
+ * In DestroyContext, the __hwcontext was being set to NULL and effectively
+ * going away. Later in MakeCurrent we had no idea what the state of the
+ * downstream GL machine was (since __hwcontext was gone). This meant
+ * we had nothing to 'diff' against and the downstream GL machine was
+ * in an unknown state.
+ *
+ * The solution to this problem is the "default/NULL" context. The
+ * default context is created the first time CreateContext is called
+ * and is never freed. Whenever we get a crStateMakeCurrent(NULL) call
+ * or destroy the currently bound context in crStateDestroyContext()
+ * we call crStateSwitchContext() to switch to the default context and
+ * then set the __currentContext pointer to point to the default context.
+ * This ensures that the dirty bits are updated and the diff_api functions
+ * are called to keep the downstream GL machine in a known state.
+ * Finally, the __hwcontext variable is no longer needed now.
+ *
+ * Yeah, this is kind of a mind-bender, but it really solves the problem
+ * pretty cleanly.
+ *
+ * -Brian
+ */
+
+
+CRContext *
+crStateCreateContext(const CRLimitsState *limits, GLint visBits, CRContext *share)
+{
+ 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);
+
+ if (presetID>0)
+ {
+ if(g_pAvailableContexts[presetID])
+ {
+ crWarning("requesting to create context with already allocated id");
+ return NULL;
+ }
+ }
+ else
+ {
+ 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;
+ }
+ }
+
+ return crStateCreateContextId(presetID, limits, visBits, share);
+}
+
+void crStateDestroyContext( CRContext *ctx )
+{
+ CRContext *current = GetCurrentContext();
+
+ if (current == ctx) {
+ /* destroying the current context - have to be careful here */
+ CRASSERT(defaultContext);
+ /* Check to see if the differencer exists first,
+ we may not have one, aka the packspu */
+ if (diff_api.AlphaFunc)
+ crStateSwitchContext(current, defaultContext);
+#ifdef CHROMIUM_THREADSAFE
+ SetCurrentContext(defaultContext);
+#else
+ __currentContext = defaultContext;
+#endif
+ /* ensure matrix state is also current */
+ crStateMatrixMode(defaultContext->transform.matrixMode);
+ }
+
+#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);
+#endif
+}
+
+GLboolean crStateEnableDiffOnMakeCurrent(GLboolean fEnable)
+{
+ GLboolean bOld = g_bVBoxEnableDiffOnMakeCurrent;
+ g_bVBoxEnableDiffOnMakeCurrent = fEnable;
+ return bOld;
+}
+
+void crStateMakeCurrent( CRContext *ctx )
+{
+ CRContext *current = GetCurrentContext();
+ CRContext *pLocalCtx = ctx;
+
+ if (pLocalCtx == NULL)
+ pLocalCtx = defaultContext;
+
+ if (current == pLocalCtx)
+ return; /* no-op */
+
+ CRASSERT(pLocalCtx);
+
+ if (g_bVBoxEnableDiffOnMakeCurrent && current) {
+ /* Check to see if the differencer exists first,
+ we may not have one, aka the packspu */
+ if (diff_api.AlphaFunc)
+ crStateSwitchContext( current, pLocalCtx );
+ }
+
+#ifdef CHROMIUM_THREADSAFE
+ SetCurrentContext(pLocalCtx);
+#else
+ __currentContext = pLocalCtx;
+#endif
+
+ /* ensure matrix state is also current */
+ crStateMatrixMode(pLocalCtx->transform.matrixMode);
+}
+
+
+/*
+ * As above, but don't call crStateSwitchContext().
+ */
+static void crStateSetCurrentEx( CRContext *ctx, GLboolean fCleanupDefault )
+{
+ CRContext *current = GetCurrentContext();
+ CRContext *pLocalCtx = ctx;
+
+ if (pLocalCtx == NULL && !fCleanupDefault)
+ pLocalCtx = defaultContext;
+
+ if (current == pLocalCtx)
+ return; /* no-op */
+
+#ifdef CHROMIUM_THREADSAFE
+ SetCurrentContext(pLocalCtx);
+#else
+ __currentContext = pLocalCtx;
+#endif
+
+ if (pLocalCtx)
+ {
+ /* ensure matrix state is also current */
+ crStateMatrixMode(pLocalCtx->transform.matrixMode);
+ }
+}
+
+void crStateSetCurrent( CRContext *ctx )
+{
+ crStateSetCurrentEx( ctx, GL_FALSE );
+}
+
+void crStateCleanupCurrent()
+{
+ crStateSetCurrentEx( NULL, GL_TRUE );
+}
+
+
+CRContext *crStateGetCurrent(void)
+{
+ return GetCurrentContext();
+}
+
+
+void crStateUpdateColorBits(void)
+{
+ /* This is a hack to force updating the 'current' attribs */
+ CRStateBits *sb = GetCurrentBits();
+ FILLDIRTY(sb->current.dirty);
+ FILLDIRTY(sb->current.vertexAttrib[VERT_ATTRIB_COLOR0]);
+}
+
+
+void STATE_APIENTRY
+crStateChromiumParameteriCR( GLenum target, GLint value )
+{
+ /* This no-op function helps smooth code-gen */
+ (void)target; (void)value;
+}
+
+void STATE_APIENTRY
+crStateChromiumParameterfCR( GLenum target, GLfloat value )
+{
+ /* This no-op function helps smooth code-gen */
+ (void)target; (void)value;
+}
+
+void STATE_APIENTRY
+crStateChromiumParametervCR( GLenum target, GLenum type, GLsizei count, const GLvoid *values )
+{
+ /* This no-op function helps smooth code-gen */
+ (void)target; (void)type; (void)count; (void)values;
+}
+
+void STATE_APIENTRY
+crStateGetChromiumParametervCR( GLenum target, GLuint index, GLenum type, GLsizei count, GLvoid *values )
+{
+ /* This no-op function helps smooth code-gen */
+ (void)target; (void)index; (void)type; (void)count; (void)values;
+}
+
+void STATE_APIENTRY
+crStateReadPixels( GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type, GLvoid *pixels )
+{
+ /* This no-op function helps smooth code-gen */
+ (void)x; (void)y; (void)width; (void)height; (void)format; (void)type; (void)pixels;
+}
+
+void crStateVBoxDetachThread(void)
+{
+ /* release the context ref so that it can be freed */
+ SetCurrentContext(NULL);
+}
+
+
+void crStateVBoxAttachThread(void)
+{
+}
+
+#if 0 /* who's refering to these? */
+
+GLint crStateVBoxCreateContext( GLint con, const char * dpyName, GLint visual, GLint shareCtx )
+{
+ (void)con; (void)dpyName; (void)visual; (void)shareCtx;
+ return 0;
+}
+
+GLint crStateVBoxWindowCreate( GLint con, const char *dpyName, GLint visBits )
+{
+ (void)con; (void)dpyName; (void)visBits;
+ return 0;
+}
+
+void crStateVBoxWindowDestroy( GLint con, GLint window )
+{
+ (void)con; (void)window;
+}
+
+GLint crStateVBoxConCreate(struct VBOXUHGSMI *pHgsmi)
+{
+ (void)pHgsmi;
+ return 0;
+}
+
+void crStateVBoxConDestroy(GLint con)
+{
+ (void)con;
+}
+
+void crStateVBoxConFlush(GLint con)
+{
+ (void)con;
+}
+
+#endif /* unused? */
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_internals.h b/src/VBox/GuestHost/OpenGL/state_tracker/state_internals.h
new file mode 100644
index 00000000..6610ca8a
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_internals.h
@@ -0,0 +1,29 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved.
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#ifndef STATE_INTERNALS_H
+#define STATE_INTERNALS_H
+
+#include "cr_spu.h"
+#include "state/cr_statetypes.h"
+
+/* Set the flush_func to NULL *before* it's called, so that we can
+ * call state functions from within flush without infinite recursion.
+ * Yucky, but "necessary" for color material. */
+
+#define FLUSH() \
+ if (g->flush_func != NULL) \
+ { \
+ CRStateFlushFunc cached_ff = g->flush_func; \
+ g->flush_func = NULL; \
+ cached_ff( g->flush_arg ); \
+ }
+
+typedef void (SPU_APIENTRY *glAble)(GLenum);
+
+#define GLCLIENT_BIT_ALLOC 1024
+
+#endif
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_isenabled.py b/src/VBox/GuestHost/OpenGL/state_tracker/state_isenabled.py
new file mode 100755
index 00000000..35a3815a
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_isenabled.py
@@ -0,0 +1,75 @@
+# Copyright (c) 2001, Stanford University
+# All rights reserved.
+#
+# See the file LICENSE.txt for information on redistributing this software.
+
+from __future__ import print_function
+import sys, re, string
+import apiutil
+
+
+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 = match.group(3).split()
+ 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 = match.group(4).split()
+ extended_params[pname] = ( type, ifdef, fields )
+
+apiutil.CopyrightC()
+
+print("""
+/* DO NOT EDIT - THIS FILE GENERATED BY THE state_isenabled.py SCRIPT */
+#include <stdio.h>
+#include <math.h>
+
+#include "state.h"
+#include "state/cr_statetypes.h"
+
+GLboolean STATE_APIENTRY crStateIsEnabled( GLenum pname )
+{
+ CRContext *g = GetCurrentContext();
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glGet called in Begin/End");
+ return 0;
+ }
+
+ switch (pname) {
+""")
+
+for pname in sorted(params.keys()):
+ print("\tcase %s:" % pname)
+ print("\t\treturn %s;" % params[pname][1][0])
+
+for pname in sorted(extended_params.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("\tcase %s:" % pname)
+ print("\t\treturn %s;" % extended_params[pname][2][0])
+ print('#endif /* CR_%s */' % ext)
+print("\tdefault:")
+print("\t\tcrStateError(__LINE__, __FILE__, GL_INVALID_ENUM, \"glIsEnabled: Unknown enum: %d\", pname);")
+print("\t\treturn 0;")
+print("\t}")
+print("}")
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_isenabled.txt b/src/VBox/GuestHost/OpenGL/state_tracker/state_isenabled.txt
new file mode 100644
index 00000000..4e7435dd
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_isenabled.txt
@@ -0,0 +1,76 @@
+# Copyright (c) 2001, Stanford University
+# All rights reserved.
+#
+# See the file LICENSE.txt for information on redistributing this software.
+GLboolean GL_ALPHA_TEST g->buffer.alphaTest
+GLboolean GL_AUTO_NORMAL g->eval.autoNormal
+GLboolean GL_BLEND g->buffer.blend
+GLboolean GL_CULL_FACE g->polygon.cullFace
+GLboolean GL_COLOR_MATERIAL GL_FALSE
+GLboolean GL_CLIP_PLANE0 g->transform.clip[0]
+GLboolean GL_CLIP_PLANE1 g->transform.clip[1]
+GLboolean GL_CLIP_PLANE2 g->transform.clip[2]
+GLboolean GL_CLIP_PLANE3 g->transform.clip[3]
+GLboolean GL_CLIP_PLANE4 g->transform.clip[4]
+GLboolean GL_CLIP_PLANE5 g->transform.clip[5]
+GLboolean GL_COLOR_LOGIC_OP g->buffer.logicOp
+GLboolean GL_DEPTH_TEST g->buffer.depthTest
+GLboolean GL_DEPTH_WRITEMASK g->buffer.depthMask
+GLboolean GL_DITHER g->buffer.dither
+GLboolean GL_FOG g->fog.enable
+GLboolean GL_INDEX_LOGIC_OP g->buffer.indexLogicOp
+GLboolean GL_LIGHT0 g->lighting.light[0].enable
+GLboolean GL_LIGHT1 g->lighting.light[1].enable
+GLboolean GL_LIGHT2 g->lighting.light[2].enable
+GLboolean GL_LIGHT3 g->lighting.light[3].enable
+GLboolean GL_LIGHT4 g->lighting.light[4].enable
+GLboolean GL_LIGHT5 g->lighting.light[5].enable
+GLboolean GL_LIGHT6 g->lighting.light[6].enable
+GLboolean GL_LIGHT7 g->lighting.light[7].enable
+GLboolean GL_LIGHTING g->lighting.lighting
+GLboolean GL_LINE_SMOOTH g->line.lineSmooth
+GLboolean GL_LINE_STIPPLE g->line.lineStipple
+GLboolean GL_MAP1_COLOR_4 g->eval.enable1D[GL_MAP1_COLOR_4-GL_MAP1_COLOR_4]
+GLboolean GL_MAP1_INDEX g->eval.enable1D[GL_MAP1_INDEX-GL_MAP1_COLOR_4]
+GLboolean GL_MAP1_NORMAL g->eval.enable1D[GL_MAP1_NORMAL-GL_MAP1_COLOR_4]
+GLboolean GL_MAP1_TEXTURE_COORD_1 g->eval.enable1D[GL_MAP1_TEXTURE_COORD_1-GL_MAP1_COLOR_4]
+GLboolean GL_MAP1_TEXTURE_COORD_2 g->eval.enable1D[GL_MAP1_TEXTURE_COORD_2-GL_MAP1_COLOR_4]
+GLboolean GL_MAP1_TEXTURE_COORD_3 g->eval.enable1D[GL_MAP1_TEXTURE_COORD_3-GL_MAP1_COLOR_4]
+GLboolean GL_MAP1_TEXTURE_COORD_4 g->eval.enable1D[GL_MAP1_TEXTURE_COORD_4-GL_MAP1_COLOR_4]
+GLboolean GL_MAP1_VERTEX_3 g->eval.enable1D[GL_MAP1_VERTEX_3-GL_MAP1_COLOR_4]
+GLboolean GL_MAP1_VERTEX_4 g->eval.enable1D[GL_MAP1_VERTEX_4-GL_MAP1_COLOR_4]
+GLboolean GL_MAP2_COLOR_4 g->eval.enable2D[GL_MAP2_COLOR_4-GL_MAP2_COLOR_4]
+GLboolean GL_MAP2_INDEX g->eval.enable2D[GL_MAP2_INDEX-GL_MAP2_COLOR_4]
+GLboolean GL_MAP2_NORMAL g->eval.enable2D[GL_MAP2_NORMAL-GL_MAP2_COLOR_4]
+GLboolean GL_MAP2_TEXTURE_COORD_1 g->eval.enable2D[GL_MAP2_TEXTURE_COORD_1-GL_MAP2_COLOR_4]
+GLboolean GL_MAP2_TEXTURE_COORD_2 g->eval.enable2D[GL_MAP2_TEXTURE_COORD_2-GL_MAP2_COLOR_4]
+GLboolean GL_MAP2_TEXTURE_COORD_3 g->eval.enable2D[GL_MAP2_TEXTURE_COORD_3-GL_MAP2_COLOR_4]
+GLboolean GL_MAP2_TEXTURE_COORD_4 g->eval.enable2D[GL_MAP2_TEXTURE_COORD_4-GL_MAP2_COLOR_4]
+GLboolean GL_MAP2_VERTEX_3 g->eval.enable2D[GL_MAP2_VERTEX_3-GL_MAP2_COLOR_4]
+GLboolean GL_MAP2_VERTEX_4 g->eval.enable2D[GL_MAP2_VERTEX_4-GL_MAP2_COLOR_4]
+GLboolean GL_PACK_SWAP_BYTES g->client.pack.swapBytes
+GLboolean GL_PACK_LSB_FIRST g->client.pack.psLSBFirst
+GLboolean GL_POINT_SMOOTH g->point.pointSmooth
+GLboolean GL_POLYGON_SMOOTH g->polygon.polygonSmooth
+GLboolean GL_POLYGON_STIPPLE g->polygon.polygonStipple
+GLboolean GL_POLYGON_OFFSET_POINT g->polygon.polygonOffsetPoint
+GLboolean GL_POLYGON_OFFSET_LINE g->polygon.polygonOffsetLine
+GLboolean GL_POLYGON_OFFSET_FILL g->polygon.polygonOffsetFill
+GLboolean GL_NORMALIZE g->transform.normalize
+GLboolean GL_RGBA_MODE GL_TRUE
+GLboolean GL_SCISSOR_TEST g->viewport.scissorTest
+GLboolean GL_STENCIL_TEST g->stencil.stencilTest
+GLboolean GL_TEXTURE_GEN_S g->texture.unit[g->texture.curTextureUnit].textureGen.s
+GLboolean GL_TEXTURE_GEN_T g->texture.unit[g->texture.curTextureUnit].textureGen.t
+GLboolean GL_TEXTURE_GEN_R g->texture.unit[g->texture.curTextureUnit].textureGen.r
+GLboolean GL_TEXTURE_GEN_Q g->texture.unit[g->texture.curTextureUnit].textureGen.q
+GLboolean GL_TEXTURE_1D g->texture.unit[g->texture.curTextureUnit].enabled1D
+GLboolean GL_TEXTURE_2D g->texture.unit[g->texture.curTextureUnit].enabled2D
+# GLboolean GL_TEXTURE_3D g->texture.unit[g->texture.curTextureUnit].enabled3D
+GLboolean GL_TEXTURE_CUBE_MAP_ARB g->texture.unit[g->texture.curTextureUnit].enabledCubeMap
+
+GLboolean GL_UNPACK_SWAP_BYTES g->client.unpack.swapBytes
+GLboolean GL_UNPACK_LSB_FIRST g->client.unpack.psLSBFirst
+GLboolean GL_REGISTER_COMBINERS_NV g->regcombiner.enabledRegCombiners
+GLboolean GL_PER_STAGE_CONSTANTS_NV g->regcombiner.enabledPerStageConstants
+GLboolean GL_COLOR_SUM_EXT g->lighting.colorSumEXT
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_lighting.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_lighting.c
new file mode 100644
index 00000000..bfea8559
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_lighting.c
@@ -0,0 +1,1212 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#include <stdio.h>
+#include "state.h"
+#include "cr_mem.h"
+#include "state/cr_statetypes.h"
+#include "state_internals.h"
+
+void crStateLightingInitBits (CRLightingBits *l)
+{
+ l->light = (CRLightBits *) crCalloc (sizeof(*(l->light)) * CR_MAX_LIGHTS);
+}
+
+void crStateLightingDestroyBits (CRLightingBits *l)
+{
+ crFree(l->light);
+}
+
+void crStateLightingDestroy (CRContext *ctx)
+{
+ crFree(ctx->lighting.light);
+}
+
+void crStateLightingInit (CRContext *ctx)
+{
+ CRLightingState *l = &ctx->lighting;
+ CRStateBits *sb = GetCurrentBits();
+ CRLightingBits *lb = &(sb->lighting);
+ int i;
+ GLvectorf zero_vector = {0.0f, 0.0f, 0.0f, 1.0f};
+ GLcolorf zero_color = {0.0f, 0.0f, 0.0f, 1.0f};
+ GLcolorf ambient_color = {0.2f, 0.2f, 0.2f, 1.0f};
+ GLcolorf diffuse_color = {0.8f, 0.8f, 0.8f, 1.0f};
+ GLvectorf spot_vector = {0.0f, 0.0f, -1.0f, 0.0f};
+ GLcolorf one_color = {1.0f, 1.0f, 1.0f, 1.0f};
+
+ l->lighting = GL_FALSE;
+ RESET(lb->enable, ctx->bitid);
+ l->colorMaterial = GL_FALSE;
+ RESET(lb->colorMaterial, ctx->bitid);
+ l->shadeModel = GL_SMOOTH;
+ RESET(lb->shadeModel, ctx->bitid);
+ l->colorMaterialMode = GL_AMBIENT_AND_DIFFUSE;
+ l->colorMaterialFace = GL_FRONT_AND_BACK;
+ l->ambient[0] = ambient_color;
+ l->diffuse[0] = diffuse_color;
+ l->specular[0] = zero_color;
+ l->emission[0] = zero_color;
+ l->shininess[0] = 0.0f;
+ l->indexes[0][0] = 0;
+ l->indexes[0][1] = 1;
+ l->indexes[0][2] = 1;
+ l->ambient[1] = ambient_color;
+ l->diffuse[1] = diffuse_color;
+ l->specular[1] = zero_color;
+ l->emission[1] = zero_color;
+ l->shininess[1] = 0.0f;
+ l->indexes[1][0] = 0;
+ l->indexes[1][1] = 1;
+ l->indexes[1][2] = 1;
+ RESET(lb->material, ctx->bitid);
+ l->lightModelAmbient = ambient_color;
+ l->lightModelLocalViewer = GL_FALSE;
+ l->lightModelTwoSide = GL_FALSE;
+#if defined(CR_EXT_separate_specular_color)
+ l->lightModelColorControlEXT = GL_SINGLE_COLOR_EXT;
+#elif defined(CR_OPENGL_VERSION_1_2)
+ l->lightModelColorControlEXT = GL_SINGLE_COLOR;
+#endif
+ RESET(lb->lightModel, ctx->bitid);
+#if defined(CR_EXT_secondary_color)
+ l->colorSumEXT = GL_FALSE;
+#endif
+ l->light = (CRLight *) crCalloc (sizeof (*(l->light)) * CR_MAX_LIGHTS);
+
+ for (i=0; i<CR_MAX_LIGHTS; i++)
+ {
+ CRLightBits *ltb = lb->light + i;
+ l->light[i].enable = GL_FALSE;
+ RESET(ltb->enable, ctx->bitid);
+ l->light[i].ambient = zero_color;
+ RESET(ltb->ambient, ctx->bitid);
+ l->light[i].diffuse = zero_color;
+ RESET(ltb->diffuse, ctx->bitid);
+ l->light[i].specular = zero_color;
+ RESET(ltb->specular, ctx->bitid);
+ l->light[i].position = zero_vector;
+ l->light[i].position.z = 1.0f;
+ l->light[i].position.w = 0.0f;
+ l->light[i].objPosition = l->light[i].position;
+ RESET(ltb->position, ctx->bitid);
+ l->light[i].spotDirection = spot_vector;
+ l->light[i].spotExponent = 0.0f;
+ l->light[i].spotCutoff = 180.0f;
+ RESET(ltb->spot, ctx->bitid);
+ l->light[i].constantAttenuation= 1.0f;
+ l->light[i].linearAttenuation= 0.0f;
+ l->light[i].quadraticAttenuation = 0.0f;
+ RESET(ltb->attenuation, ctx->bitid);
+ RESET(ltb->dirty, ctx->bitid);
+ }
+ l->light[0].diffuse = one_color;
+ l->light[0].specular = one_color;
+
+ RESET(lb->dirty, ctx->bitid);
+}
+
+void STATE_APIENTRY crStateShadeModel (GLenum mode)
+{
+ CRContext *g = GetCurrentContext();
+ CRLightingState *l = &(g->lighting);
+ CRStateBits *sb = GetCurrentBits();
+ CRLightingBits *lb = &(sb->lighting);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "ShadeModel called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ if (mode != GL_SMOOTH &&
+ mode != GL_FLAT)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "ShadeModel: Bogus mode 0x%x", mode);
+ return;
+ }
+
+ l->shadeModel = mode;
+ DIRTY(lb->shadeModel, g->neg_bitid);
+ DIRTY(lb->dirty, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateColorMaterial (GLenum face, GLenum mode)
+{
+ CRContext *g = GetCurrentContext();
+ CRLightingState *l = &(g->lighting);
+ CRStateBits *sb = GetCurrentBits();
+ CRLightingBits *lb = &(sb->lighting);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "ColorMaterial called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ if (face != GL_FRONT &&
+ face != GL_BACK &&
+ face != GL_FRONT_AND_BACK)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "ColorMaterial: Bogus face &d", face);
+ return;
+ }
+
+ if (mode != GL_EMISSION &&
+ mode != GL_AMBIENT &&
+ mode != GL_DIFFUSE &&
+ mode != GL_SPECULAR &&
+ mode != GL_AMBIENT_AND_DIFFUSE)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "ColorMaterial: Bogus mode &d", mode);
+ return;
+ }
+
+ l->colorMaterialFace = face;
+ l->colorMaterialMode = mode;
+ /* XXX this could conceivably be needed here (BP) */
+ /*
+ crStateColorMaterialRecover();
+ */
+ DIRTY(lb->colorMaterial, g->neg_bitid);
+ DIRTY(lb->dirty, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateLightModelfv (GLenum pname, const GLfloat *param)
+{
+ CRContext *g = GetCurrentContext();
+ CRLightingState *l = &(g->lighting);
+ CRStateBits *sb = GetCurrentBits();
+ CRLightingBits *lb = &(sb->lighting);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "LightModelfv called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ switch (pname)
+ {
+ case GL_LIGHT_MODEL_LOCAL_VIEWER:
+ l->lightModelLocalViewer = (GLboolean) (*param==0.0f?GL_FALSE:GL_TRUE);
+ break;
+ case GL_LIGHT_MODEL_TWO_SIDE:
+ l->lightModelTwoSide = (GLboolean) (*param==0.0f?GL_FALSE:GL_TRUE);
+ break;
+ case GL_LIGHT_MODEL_AMBIENT:
+ l->lightModelAmbient.r = param[0];
+ l->lightModelAmbient.g = param[1];
+ l->lightModelAmbient.b = param[2];
+ l->lightModelAmbient.a = param[3];
+ break;
+#if defined(CR_OPENGL_VERSION_1_2)
+ case GL_LIGHT_MODEL_COLOR_CONTROL:
+ if (param[0] == GL_SEPARATE_SPECULAR_COLOR || param[0] == GL_SINGLE_COLOR)
+ {
+ l->lightModelColorControlEXT = (GLenum) param[0];
+ }
+ else
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "LightModel: Invalid param for LIGHT_MODEL_COLOR_CONTROL: 0x%x", param[0]);
+ return;
+ }
+ break;
+#else
+#if defined(CR_EXT_separate_specular_color)
+ case GL_LIGHT_MODEL_COLOR_CONTROL_EXT:
+ if(g->extensions.EXT_separate_specular_color)
+ {
+ if (param[0] == GL_SEPARATE_SPECULAR_COLOR_EXT || param[0] == GL_SINGLE_COLOR_EXT)
+ {
+ l->lightModelColorControlEXT = (GLenum) param[0];
+ }
+ else
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "LightModel: Invalid param for LIGHT_MODEL_COLOR_CONTROL: 0x%x", param[0]);
+ return;
+ }
+ }
+ else
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "LightModel( LIGHT_MODEL_COLOR_CONTROL, ...) - EXT_separate_specular_color is unavailable.");
+ return;
+ }
+ break;
+#endif
+#endif
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "LightModelfv: Invalid pname: 0x%x", pname);
+ return;
+ }
+ DIRTY(lb->lightModel, g->neg_bitid);
+ DIRTY(lb->dirty, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateLightModeliv (GLenum pname, const GLint *param)
+{
+ GLfloat f_param;
+ GLcolor f_color;
+#ifndef CR_OPENGL_VERSION_1_2
+ CRContext *g = GetCurrentContext();
+#endif
+
+ switch (pname)
+ {
+ case GL_LIGHT_MODEL_LOCAL_VIEWER:
+ case GL_LIGHT_MODEL_TWO_SIDE:
+ f_param = (GLfloat) (*param);
+ crStateLightModelfv(pname, &f_param);
+ break;
+ case GL_LIGHT_MODEL_AMBIENT:
+ f_color.r = ((GLfloat)param[0])/CR_MAXINT;
+ f_color.g = ((GLfloat)param[1])/CR_MAXINT;
+ f_color.b = ((GLfloat)param[2])/CR_MAXINT;
+ f_color.a = ((GLfloat)param[3])/CR_MAXINT;
+ crStateLightModelfv(pname, (GLfloat *) &f_color);
+ break;
+#if defined(CR_OPENGL_VERSION_1_2)
+ case GL_LIGHT_MODEL_COLOR_CONTROL:
+ f_param = (GLfloat) (*param);
+ crStateLightModelfv(pname, &f_param);
+ break;
+#else
+#ifdef CR_EXT_separate_specular_color
+ case GL_LIGHT_MODEL_COLOR_CONTROL_EXT:
+ if (g->extensions.EXT_separate_specular_color) {
+ f_param = (GLfloat) (*param);
+ crStateLightModelfv(pname, &f_param);
+ } else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "LightModeliv(GL_LIGHT_MODEL_COLOR_CONTROL_EXT, ...) - EXT_separate_specular_color not enabled!");
+ return;
+ }
+ break;
+#endif
+#endif
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "LightModeliv: Invalid pname: 0x%x", pname);
+ return;
+ }
+}
+
+void STATE_APIENTRY crStateLightModelf (GLenum pname, GLfloat param)
+{
+ crStateLightModelfv(pname, &param);
+}
+
+void STATE_APIENTRY crStateLightModeli (GLenum pname, GLint param)
+{
+ GLfloat f_param = (GLfloat) param;
+ crStateLightModelfv(pname, &f_param);
+}
+
+void STATE_APIENTRY crStateLightfv (GLenum light, GLenum pname, const GLfloat *param)
+{
+ CRContext *g = GetCurrentContext();
+ CRLightingState *l = &(g->lighting);
+ CRTransformState *t = &(g->transform);
+ CRLight *lt;
+ unsigned int i;
+ GLfloat x, y, z, w;
+ CRmatrix inv;
+ CRmatrix *mat;
+ CRStateBits *sb = GetCurrentBits();
+ CRLightingBits *lb = &(sb->lighting);
+ CRLightBits *ltb;
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glLightfv called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ i = light - GL_LIGHT0;
+ if (i>=g->limits.maxLights)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glLight: invalid light specified: 0x%x", light);
+ return;
+ }
+
+ lt = l->light + i;
+ ltb = lb->light + i;
+
+ switch (pname)
+ {
+ case GL_AMBIENT:
+ lt->ambient.r = param[0];
+ lt->ambient.g = param[1];
+ lt->ambient.b = param[2];
+ lt->ambient.a = param[3];
+ DIRTY(ltb->ambient, g->neg_bitid);
+ break;
+ case GL_DIFFUSE:
+ lt->diffuse.r = param[0];
+ lt->diffuse.g = param[1];
+ lt->diffuse.b = param[2];
+ lt->diffuse.a = param[3];
+ DIRTY(ltb->diffuse, g->neg_bitid);
+ break;
+ case GL_SPECULAR:
+ lt->specular.r = param[0];
+ lt->specular.g = param[1];
+ lt->specular.b = param[2];
+ lt->specular.a = param[3];
+ DIRTY(ltb->specular, g->neg_bitid);
+ break;
+ case GL_POSITION:
+ x = param[0];
+ y = param[1];
+ z = param[2];
+ w = param[3];
+ mat = t->modelViewStack.top;
+ lt->objPosition.x = x;
+ lt->objPosition.y = y;
+ lt->objPosition.z = z;
+ lt->objPosition.w = w;
+
+ lt->position.x = mat->m00*x + mat->m10*y + mat->m20*z + mat->m30*w;
+ lt->position.y = mat->m01*x + mat->m11*y + mat->m21*z + mat->m31*w;
+ lt->position.z = mat->m02*x + mat->m12*y + mat->m22*z + mat->m32*w;
+ lt->position.w = mat->m03*x + mat->m13*y + mat->m23*z + mat->m33*w;
+
+ DIRTY(ltb->position, g->neg_bitid);
+ break;
+ case GL_SPOT_DIRECTION:
+ lt->spotDirection.x = param[0];
+ lt->spotDirection.y = param[1];
+ lt->spotDirection.z = param[2];
+ lt->spotDirection.w = 0.0f;
+ mat = t->modelViewStack.top;
+
+ if (lt->objPosition.w != 0.0f)
+ {
+ lt->spotDirection.w = - ( ( lt->objPosition.x * lt->spotDirection.x +
+ lt->objPosition.y * lt->spotDirection.y +
+ lt->objPosition.z * lt->spotDirection.z ) /
+ lt->objPosition.w );
+ }
+
+ crMatrixInvertTranspose(&inv, mat);
+ crStateTransformXformPointMatrixf (&inv, &(lt->spotDirection));
+
+ DIRTY(ltb->spot, g->neg_bitid);
+ break;
+ case GL_SPOT_EXPONENT:
+ if (*param < 0.0f || *param > 180.0f)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glLight: spot exponent out of range: %f", *param);
+ return;
+ }
+ lt->spotExponent = *param;
+ DIRTY(ltb->spot, g->neg_bitid);
+ break;
+ case GL_SPOT_CUTOFF:
+ if ((*param < 0.0f || *param > 90.0f) && *param != 180.0f)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glLight: spot cutoff out of range: %f", *param);
+ return;
+ }
+ lt->spotCutoff = *param;
+ DIRTY(ltb->spot, g->neg_bitid);
+ break;
+ case GL_CONSTANT_ATTENUATION:
+ if (*param < 0.0f)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glLight: constant Attenuation negative: %f", *param);
+ return;
+ }
+ lt->constantAttenuation = *param;
+ DIRTY(ltb->attenuation, g->neg_bitid);
+ break;
+ case GL_LINEAR_ATTENUATION:
+ if (*param < 0.0f)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glLight: linear Attenuation negative: %f", *param);
+ return;
+ }
+ lt->linearAttenuation = *param;
+ DIRTY(ltb->attenuation, g->neg_bitid);
+ break;
+ case GL_QUADRATIC_ATTENUATION:
+ if (*param < 0.0f)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glLight: quadratic Attenuation negative: %f", *param);
+ return;
+ }
+ lt->quadraticAttenuation = *param;
+ DIRTY(ltb->attenuation, g->neg_bitid);
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glLight: invalid pname: 0x%x", pname);
+ return;
+ }
+ DIRTY(ltb->dirty, g->neg_bitid);
+ DIRTY(lb->dirty, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateLightiv (GLenum light, GLenum pname, const GLint *param)
+{
+ GLfloat f_param;
+ GLcolor f_color;
+ GLvector f_vector;
+
+ switch (pname)
+ {
+ case GL_AMBIENT:
+ case GL_DIFFUSE:
+ case GL_SPECULAR:
+ f_color.r = ((GLfloat)param[0])/CR_MAXINT;
+ f_color.g = ((GLfloat)param[1])/CR_MAXINT;
+ f_color.b = ((GLfloat)param[2])/CR_MAXINT;
+ f_color.a = ((GLfloat)param[3])/CR_MAXINT;
+ crStateLightfv(light, pname, (GLfloat *) &f_color);
+ break;
+ case GL_POSITION:
+ case GL_SPOT_DIRECTION:
+ f_vector.x = (GLfloat) param[0];
+ f_vector.y = (GLfloat) param[1];
+ f_vector.z = (GLfloat) param[2];
+ f_vector.w = (GLfloat) param[3];
+ crStateLightfv(light, pname, (GLfloat *) &f_vector);
+ break;
+ case GL_SPOT_EXPONENT:
+ case GL_SPOT_CUTOFF:
+ case GL_CONSTANT_ATTENUATION:
+ case GL_LINEAR_ATTENUATION:
+ case GL_QUADRATIC_ATTENUATION:
+ f_param = (GLfloat) (*param);
+ crStateLightfv(light, pname, &f_param);
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glLight: invalid pname: 0x%x", pname);
+ return;
+ }
+}
+
+void STATE_APIENTRY crStateLightf (GLenum light, GLenum pname, GLfloat param)
+{
+ crStateLightfv(light, pname, &param);
+}
+
+void STATE_APIENTRY crStateLighti (GLenum light, GLenum pname, GLint param)
+{
+ GLfloat f_param = (GLfloat) param;
+ crStateLightfv(light, pname, &f_param);
+}
+
+void STATE_APIENTRY crStateMaterialfv (GLenum face, GLenum pname, const GLfloat *param)
+{
+ CRContext *g = GetCurrentContext();
+ CRLightingState *l = &(g->lighting);
+ CRStateBits *sb = GetCurrentBits();
+ CRLightingBits *lb = &(sb->lighting);
+
+ if (!g->current.inBeginEnd)
+ {
+ FLUSH();
+ }
+
+ switch (pname)
+ {
+ case GL_AMBIENT :
+ switch (face)
+ {
+ case GL_FRONT:
+ l->ambient[0].r = param[0];
+ l->ambient[0].g = param[1];
+ l->ambient[0].b = param[2];
+ l->ambient[0].a = param[3];
+ break;
+ case GL_FRONT_AND_BACK:
+ l->ambient[0].r = param[0];
+ l->ambient[0].g = param[1];
+ l->ambient[0].b = param[2];
+ l->ambient[0].a = param[3];
+ RT_FALL_THRU();
+ case GL_BACK:
+ l->ambient[1].r = param[0];
+ l->ambient[1].g = param[1];
+ l->ambient[1].b = param[2];
+ l->ambient[1].a = param[3];
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glMaterialfv: bad face: 0x%x", face);
+ return;
+ }
+ break;
+ case GL_AMBIENT_AND_DIFFUSE :
+ switch (face)
+ {
+ case GL_FRONT:
+ l->ambient[0].r = param[0];
+ l->ambient[0].g = param[1];
+ l->ambient[0].b = param[2];
+ l->ambient[0].a = param[3];
+ break;
+ case GL_FRONT_AND_BACK:
+ l->ambient[0].r = param[0];
+ l->ambient[0].g = param[1];
+ l->ambient[0].b = param[2];
+ l->ambient[0].a = param[3];
+ RT_FALL_THRU();
+ case GL_BACK:
+ l->ambient[1].r = param[0];
+ l->ambient[1].g = param[1];
+ l->ambient[1].b = param[2];
+ l->ambient[1].a = param[3];
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glMaterialfv: bad face: 0x%x", face);
+ return;
+ }
+ RT_FALL_THRU();
+ case GL_DIFFUSE :
+ switch (face)
+ {
+ case GL_FRONT:
+ l->diffuse[0].r = param[0];
+ l->diffuse[0].g = param[1];
+ l->diffuse[0].b = param[2];
+ l->diffuse[0].a = param[3];
+ break;
+ case GL_FRONT_AND_BACK:
+ l->diffuse[0].r = param[0];
+ l->diffuse[0].g = param[1];
+ l->diffuse[0].b = param[2];
+ l->diffuse[0].a = param[3];
+ RT_FALL_THRU();
+ case GL_BACK:
+ l->diffuse[1].r = param[0];
+ l->diffuse[1].g = param[1];
+ l->diffuse[1].b = param[2];
+ l->diffuse[1].a = param[3];
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glMaterialfv: bad face: 0x%x", face);
+ return;
+ }
+ break;
+ case GL_SPECULAR :
+ switch (face)
+ {
+ case GL_FRONT:
+ l->specular[0].r = param[0];
+ l->specular[0].g = param[1];
+ l->specular[0].b = param[2];
+ l->specular[0].a = param[3];
+ break;
+ case GL_FRONT_AND_BACK:
+ l->specular[0].r = param[0];
+ l->specular[0].g = param[1];
+ l->specular[0].b = param[2];
+ l->specular[0].a = param[3];
+ RT_FALL_THRU();
+ case GL_BACK:
+ l->specular[1].r = param[0];
+ l->specular[1].g = param[1];
+ l->specular[1].b = param[2];
+ l->specular[1].a = param[3];
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glMaterialfv: bad face: 0x%x", face);
+ return;
+ }
+ break;
+ case GL_EMISSION :
+ switch (face)
+ {
+ case GL_FRONT:
+ l->emission[0].r = param[0];
+ l->emission[0].g = param[1];
+ l->emission[0].b = param[2];
+ l->emission[0].a = param[3];
+ break;
+ case GL_FRONT_AND_BACK:
+ l->emission[0].r = param[0];
+ l->emission[0].g = param[1];
+ l->emission[0].b = param[2];
+ l->emission[0].a = param[3];
+ RT_FALL_THRU();
+ case GL_BACK:
+ l->emission[1].r = param[0];
+ l->emission[1].g = param[1];
+ l->emission[1].b = param[2];
+ l->emission[1].a = param[3];
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glMaterialfv: bad face: 0x%x", face);
+ return;
+ }
+ break;
+ case GL_SHININESS:
+ if (*param > 180.0f || *param < 0.0f)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glMaterialfv: param out of range: %f", param);
+ return;
+ }
+
+ switch (face)
+ {
+ case GL_FRONT:
+ l->shininess[0] = *param;
+ break;
+ case GL_FRONT_AND_BACK:
+ l->shininess[0] = *param;
+ RT_FALL_THRU();
+ case GL_BACK:
+ l->shininess[1] = *param;
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glMaterialfv: bad face: 0x%x", face);
+ return;
+ }
+ break;
+ case GL_COLOR_INDEXES :
+ switch (face)
+ {
+ case GL_FRONT:
+ l->indexes[0][0] = (GLint) param[0];
+ l->indexes[0][1] = (GLint) param[1];
+ l->indexes[0][2] = (GLint) param[2];
+ break;
+ case GL_FRONT_AND_BACK:
+ l->indexes[0][0] = (GLint) param[0];
+ l->indexes[0][1] = (GLint) param[1];
+ l->indexes[0][2] = (GLint) param[2];
+ RT_FALL_THRU();
+ case GL_BACK:
+ l->indexes[1][0] = (GLint) param[0];
+ l->indexes[1][1] = (GLint) param[1];
+ l->indexes[1][2] = (GLint) param[2];
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glMaterialfv: bad face: 0x%x", face);
+ return;
+ }
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glMaterialfv: bad pname: 0x%x", pname);
+ return;
+ }
+ DIRTY(lb->material, g->neg_bitid);
+ DIRTY(lb->dirty, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateMaterialiv (GLenum face, GLenum pname, const GLint *param)
+{
+ GLfloat f_param;
+ GLcolor f_color;
+
+ switch (pname)
+ {
+ case GL_AMBIENT :
+ case GL_AMBIENT_AND_DIFFUSE :
+ case GL_DIFFUSE :
+ case GL_SPECULAR :
+ case GL_EMISSION :
+ f_color.r = ((GLfloat) param[0]) / ((GLfloat) CR_MAXINT);
+ f_color.g = ((GLfloat) param[1]) / ((GLfloat) CR_MAXINT);
+ f_color.b = ((GLfloat) param[2]) / ((GLfloat) CR_MAXINT);
+ f_color.a = ((GLfloat) param[3]) / ((GLfloat) CR_MAXINT);
+ crStateMaterialfv(face, pname, (GLfloat *) &f_color);
+ break;
+ case GL_SHININESS:
+ f_param = (GLfloat) (*param);
+ crStateMaterialfv(face, pname, (GLfloat *) &f_param);
+ break;
+ case GL_COLOR_INDEXES :
+ f_param = (GLfloat) (*param);
+ crStateMaterialfv(face, pname, (GLfloat *) &f_param);
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glMaterialiv: bad pname: 0x%x", pname);
+ return;
+ }
+}
+
+void STATE_APIENTRY crStateMaterialf (GLenum face, GLenum pname, GLfloat param)
+{
+ crStateMaterialfv(face, pname, &param);
+}
+
+void STATE_APIENTRY crStateMateriali (GLenum face, GLenum pname, GLint param)
+{
+ GLfloat f_param = (GLfloat) param;
+ crStateMaterialfv(face, pname, &f_param);
+}
+
+void STATE_APIENTRY crStateGetLightfv (GLenum light, GLenum pname, GLfloat *param)
+{
+ CRContext *g = GetCurrentContext();
+ CRLightingState *l = &(g->lighting);
+ CRLight *lt;
+ unsigned int i;
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetLightfv called in begin/end");
+ return;
+ }
+
+ i = light - GL_LIGHT0;
+ if (i>=g->limits.maxLights)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetLight: invalid light specified: 0x%x", light);
+ return;
+ }
+
+ lt = l->light + i;
+
+ switch (pname)
+ {
+ case GL_AMBIENT:
+ param[0] = lt->ambient.r;
+ param[1] = lt->ambient.g;
+ param[2] = lt->ambient.b;
+ param[3] = lt->ambient.a;
+ break;
+ case GL_DIFFUSE:
+ param[0] = lt->diffuse.r;
+ param[1] = lt->diffuse.g;
+ param[2] = lt->diffuse.b;
+ param[3] = lt->diffuse.a;
+ break;
+ case GL_SPECULAR:
+ param[0] = lt->specular.r;
+ param[1] = lt->specular.g;
+ param[2] = lt->specular.b;
+ param[3] = lt->specular.a;
+ break;
+ case GL_POSITION:
+ param[0] = lt->position.x;
+ param[1] = lt->position.y;
+ param[2] = lt->position.z;
+ param[3] = lt->position.w;
+ break;
+ case GL_SPOT_DIRECTION:
+ param[0] = lt->spotDirection.x;
+ param[1] = lt->spotDirection.y;
+ param[2] = lt->spotDirection.z;
+#if 0
+ /* the w-component of the direction, although possibly (?)
+ useful to keep around internally, is not returned as part
+ of the get. */
+ param[3] = lt->spotDirection.w;
+#endif
+ break;
+ case GL_SPOT_EXPONENT:
+ *param = lt->spotExponent;
+ break;
+ case GL_SPOT_CUTOFF:
+ *param = lt->spotCutoff;
+ break;
+ case GL_CONSTANT_ATTENUATION:
+ *param = lt->constantAttenuation;
+ break;
+ case GL_LINEAR_ATTENUATION:
+ *param = lt->linearAttenuation;
+ break;
+ case GL_QUADRATIC_ATTENUATION:
+ *param = lt->quadraticAttenuation;
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetLight: invalid pname: 0x%x", pname);
+ return;
+ }
+}
+
+void STATE_APIENTRY crStateGetLightiv (GLenum light, GLenum pname, GLint *param)
+{
+ CRContext *g = GetCurrentContext();
+ CRLightingState *l = &(g->lighting);
+ CRLight *lt;
+ unsigned int i;
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetLightiv called in begin/end");
+ return;
+ }
+
+ i = light - GL_LIGHT0;
+ if (i>=g->limits.maxLights)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetLight: invalid light specified: 0x%x", light);
+ return;
+ }
+
+ lt = l->light + i;
+
+ switch (pname)
+ {
+ case GL_AMBIENT:
+ param[0] = (GLint) (lt->ambient.r * CR_MAXINT);
+ param[1] = (GLint) (lt->ambient.g * CR_MAXINT);
+ param[2] = (GLint) (lt->ambient.b * CR_MAXINT);
+ param[3] = (GLint) (lt->ambient.a * CR_MAXINT);
+ break;
+ case GL_DIFFUSE:
+ param[0] = (GLint) (lt->diffuse.r * CR_MAXINT);
+ param[1] = (GLint) (lt->diffuse.g * CR_MAXINT);
+ param[2] = (GLint) (lt->diffuse.b * CR_MAXINT);
+ param[3] = (GLint) (lt->diffuse.a * CR_MAXINT);
+ break;
+ case GL_SPECULAR:
+ param[0] = (GLint) (lt->specular.r * CR_MAXINT);
+ param[1] = (GLint) (lt->specular.g * CR_MAXINT);
+ param[2] = (GLint) (lt->specular.b * CR_MAXINT);
+ param[3] = (GLint) (lt->specular.a * CR_MAXINT);
+ break;
+ case GL_POSITION:
+ param[0] = (GLint) (lt->position.x);
+ param[1] = (GLint) (lt->position.y);
+ param[2] = (GLint) (lt->position.z);
+ param[3] = (GLint) (lt->position.w);
+ break;
+ case GL_SPOT_DIRECTION:
+ param[0] = (GLint) (lt->spotDirection.x);
+ param[1] = (GLint) (lt->spotDirection.y);
+ param[2] = (GLint) (lt->spotDirection.z);
+#if 0
+ /* the w-component of the direction, although possibly (?)
+ useful to keep around internally, is not returned as part
+ of the get. */
+ param[3] = (GLint) (lt->spotDirection.w);
+#endif
+ break;
+ case GL_SPOT_EXPONENT:
+ *param = (GLint) (lt->spotExponent);
+ break;
+ case GL_SPOT_CUTOFF:
+ *param = (GLint) (lt->spotCutoff);
+ break;
+ case GL_CONSTANT_ATTENUATION:
+ *param = (GLint) (lt->constantAttenuation);
+ break;
+ case GL_LINEAR_ATTENUATION:
+ *param = (GLint) (lt->linearAttenuation);
+ break;
+ case GL_QUADRATIC_ATTENUATION:
+ *param = (GLint) (lt->quadraticAttenuation);
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetLight: invalid pname: 0x%x", pname);
+ return;
+ }
+}
+
+void STATE_APIENTRY crStateGetMaterialfv (GLenum face, GLenum pname, GLfloat *param)
+{
+ CRContext *g = GetCurrentContext();
+ CRLightingState *l = &(g->lighting);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetMaterialfv called in begin/end");
+ return;
+ }
+
+ switch (pname)
+ {
+ case GL_AMBIENT:
+ switch (face)
+ {
+ case GL_FRONT:
+ param[0] = l->ambient[0].r;
+ param[1] = l->ambient[0].g;
+ param[2] = l->ambient[0].b;
+ param[3] = l->ambient[0].a;
+ break;
+ case GL_BACK:
+ param[0] = l->ambient[1].r;
+ param[1] = l->ambient[1].g;
+ param[2] = l->ambient[1].b;
+ param[3] = l->ambient[1].a;
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetMaterialfv: bad face: 0x%x", face);
+ return;
+ }
+ break;
+ case GL_DIFFUSE:
+ switch (face)
+ {
+ case GL_FRONT:
+ param[0] = l->diffuse[0].r;
+ param[1] = l->diffuse[0].g;
+ param[2] = l->diffuse[0].b;
+ param[3] = l->diffuse[0].a;
+ break;
+ case GL_BACK:
+ param[0] = l->diffuse[1].r;
+ param[1] = l->diffuse[1].g;
+ param[2] = l->diffuse[1].b;
+ param[3] = l->diffuse[1].a;
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetMaterialfv: bad face: 0x%x", face);
+ return;
+ }
+ break;
+ case GL_SPECULAR :
+ switch (face)
+ {
+ case GL_FRONT:
+ param[0] = l->specular[0].r;
+ param[1] = l->specular[0].g;
+ param[2] = l->specular[0].b;
+ param[3] = l->specular[0].a;
+ break;
+ case GL_BACK:
+ param[0] = l->specular[1].r;
+ param[1] = l->specular[1].g;
+ param[2] = l->specular[1].b;
+ param[3] = l->specular[1].a;
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetMaterialfv: bad face: 0x%x", face);
+ return;
+ }
+ break;
+ case GL_EMISSION:
+ switch (face)
+ {
+ case GL_FRONT:
+ param[0] = l->emission[0].r;
+ param[1] = l->emission[0].g;
+ param[2] = l->emission[0].b;
+ param[3] = l->emission[0].a;
+ break;
+ case GL_BACK:
+ param[0] = l->emission[1].r;
+ param[1] = l->emission[1].g;
+ param[2] = l->emission[1].b;
+ param[3] = l->emission[1].a;
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetMaterialfv: bad face: 0x%x", face);
+ return;
+ }
+ break;
+ case GL_SHININESS:
+ switch (face)
+ {
+ case GL_FRONT:
+ *param = l->shininess[0];
+ break;
+ case GL_BACK:
+ *param = l->shininess[1];
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetMaterialfv: bad face: 0x%x", face);
+ return;
+ }
+ break;
+ case GL_COLOR_INDEXES :
+ switch (face)
+ {
+ case GL_FRONT:
+ param[0] = (GLfloat) l->indexes[0][0];
+ param[1] = (GLfloat) l->indexes[0][1];
+ param[2] = (GLfloat) l->indexes[0][2];
+ break;
+ case GL_BACK:
+ param[0] = (GLfloat) l->indexes[1][0];
+ param[1] = (GLfloat) l->indexes[1][1];
+ param[2] = (GLfloat) l->indexes[1][2];
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetMaterialfv: bad face: 0x%x", face);
+ return;
+ }
+ return;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetMaterialfv: bad pname: 0x%x", pname);
+ return;
+ }
+}
+
+
+void STATE_APIENTRY crStateGetMaterialiv (GLenum face, GLenum pname, GLint *param)
+{
+ CRContext *g = GetCurrentContext();
+ CRLightingState *l = &(g->lighting);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetMaterialiv called in begin/end");
+ return;
+ }
+
+ switch (pname)
+ {
+ case GL_AMBIENT:
+ switch (face)
+ {
+ case GL_FRONT:
+ param[0] = (GLint) (l->ambient[0].r * CR_MAXINT);
+ param[1] = (GLint) (l->ambient[0].g * CR_MAXINT);
+ param[2] = (GLint) (l->ambient[0].b * CR_MAXINT);
+ param[3] = (GLint) (l->ambient[0].a * CR_MAXINT);
+ break;
+ case GL_BACK:
+ param[0] = (GLint) (l->ambient[1].r * CR_MAXINT);
+ param[1] = (GLint) (l->ambient[1].g * CR_MAXINT);
+ param[2] = (GLint) (l->ambient[1].b * CR_MAXINT);
+ param[3] = (GLint) (l->ambient[1].a * CR_MAXINT);
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetMaterialiv: bad face: 0x%x", face);
+ return;
+ }
+ break;
+ case GL_DIFFUSE:
+ switch (face)
+ {
+ case GL_FRONT:
+ param[0] = (GLint) (l->diffuse[0].r * CR_MAXINT);
+ param[1] = (GLint) (l->diffuse[0].g * CR_MAXINT);
+ param[2] = (GLint) (l->diffuse[0].b * CR_MAXINT);
+ param[3] = (GLint) (l->diffuse[0].a * CR_MAXINT);
+ break;
+ case GL_BACK:
+ param[0] = (GLint) (l->diffuse[1].r * CR_MAXINT);
+ param[1] = (GLint) (l->diffuse[1].g * CR_MAXINT);
+ param[2] = (GLint) (l->diffuse[1].b * CR_MAXINT);
+ param[3] = (GLint) (l->diffuse[1].a * CR_MAXINT);
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetMaterialiv: bad face: 0x%x", face);
+ return;
+ }
+ break;
+ case GL_SPECULAR:
+ switch (face)
+ {
+ case GL_FRONT:
+ param[0] = (GLint) (l->specular[0].r * CR_MAXINT);
+ param[1] = (GLint) (l->specular[0].g * CR_MAXINT);
+ param[2] = (GLint) (l->specular[0].b * CR_MAXINT);
+ param[3] = (GLint) (l->specular[0].a * CR_MAXINT);
+ break;
+ case GL_BACK:
+ param[0] = (GLint) (l->specular[1].r * CR_MAXINT);
+ param[1] = (GLint) (l->specular[1].g * CR_MAXINT);
+ param[2] = (GLint) (l->specular[1].b * CR_MAXINT);
+ param[3] = (GLint) (l->specular[1].a * CR_MAXINT);
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetMaterialiv: bad face: 0x%x", face);
+ return;
+ }
+ break;
+ case GL_EMISSION:
+ switch (face)
+ {
+ case GL_FRONT:
+ param[0] = (GLint) (l->emission[0].r * CR_MAXINT);
+ param[1] = (GLint) (l->emission[0].g * CR_MAXINT);
+ param[2] = (GLint) (l->emission[0].b * CR_MAXINT);
+ param[3] = (GLint) (l->emission[0].a * CR_MAXINT);
+ break;
+ case GL_BACK:
+ param[0] = (GLint) (l->emission[1].r * CR_MAXINT);
+ param[1] = (GLint) (l->emission[1].g * CR_MAXINT);
+ param[2] = (GLint) (l->emission[1].b * CR_MAXINT);
+ param[3] = (GLint) (l->emission[1].a * CR_MAXINT);
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetMaterialiv: bad face: 0x%x", face);
+ return;
+ }
+ break;
+ case GL_SHININESS:
+ switch (face) {
+ case GL_FRONT:
+ *param = (GLint) l->shininess[0];
+ break;
+ case GL_BACK:
+ *param = (GLint) l->shininess[1];
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetMaterialiv: bad face: 0x%x", face);
+ return;
+ }
+ break;
+ case GL_COLOR_INDEXES :
+ switch (face)
+ {
+ case GL_FRONT:
+ param[0] = (GLint) l->indexes[0][0];
+ param[1] = (GLint) l->indexes[0][1];
+ param[2] = (GLint) l->indexes[0][2];
+ break;
+ case GL_BACK:
+ param[0] = (GLint) l->indexes[1][0];
+ param[1] = (GLint) l->indexes[1][1];
+ param[2] = (GLint) l->indexes[1][2];
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetMaterialiv: bad face: 0x%x", face);
+ return;
+ }
+ return;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetMaterialiv: bad pname: 0x%x", pname);
+ return;
+ }
+}
+
+void crStateColorMaterialRecover(void)
+{
+ CRContext *g = GetCurrentContext();
+ CRLightingState *l = &(g->lighting);
+ CRCurrentState *c = &(g->current);
+
+ /* Assuming that the "current" values are up to date,
+ * this function will extract them into the material
+ * values if COLOR_MATERIAL has been enabled on the
+ * client. */
+
+ if (l->colorMaterial)
+ {
+ /* prevent recursion here (was in tilesortspu_flush.c's doFlush() for a
+ * short time. Without this, kirchner_colormaterial fails.
+ */
+ crStateFlushFunc(NULL);
+
+ crStateMaterialfv(l->colorMaterialFace, l->colorMaterialMode, &(c->vertexAttrib[VERT_ATTRIB_COLOR0][0]));
+ }
+}
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_lighting.txt b/src/VBox/GuestHost/OpenGL/state_tracker/state_lighting.txt
new file mode 100644
index 00000000..0a072213
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_lighting.txt
@@ -0,0 +1,63 @@
+# Copyright (c) 2001, Stanford University
+# All rights reserved.
+#
+# See the file LICENSE.txt for information on redistributing this software.
+:colorMaterial:colorMaterialFace,colorMaterialMode:ColorMaterial
+:enable:lighting:GL_LIGHTING
+:enable:colorMaterial:GL_COLOR_MATERIAL
+:enable:colorSumEXT:GL_COLOR_SUM_EXT
+:shadeModel:shadeModel:ShadeModel
+:lightModel:lightModelAmbient|r,g,b,a:LightModelfv,GL_LIGHT_MODEL_AMBIENT
+:lightModel:lightModelLocalViewer:*diff_api.LightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, to->lightModelLocalViewer==GL_TRUE);
+:lightModel:lightModelTwoSide:*diff_api.LightModeli(GL_LIGHT_MODEL_TWO_SIDE, to->lightModelTwoSide==GL_TRUE);
+:lightModel:lightModelColorControlEXT:*diff_api.LightModeli(GL_LIGHT_MODEL_COLOR_CONTROL_EXT, to->lightModelColorControlEXT);
+%flush
+:material:ambient[0]|r,g,b,a:Materialfv, GL_FRONT, GL_AMBIENT
+:material:ambient[1]|r,g,b,a:Materialfv, GL_BACK, GL_AMBIENT
+:material:diffuse[0]|r,g,b,a:Materialfv, GL_FRONT, GL_DIFFUSE
+:material:diffuse[1]|r,g,b,a:Materialfv, GL_BACK, GL_DIFFUSE
+:material:specular[0]|r,g,b,a:Materialfv, GL_FRONT, GL_SPECULAR
+:material:specular[1]|r,g,b,a:Materialfv, GL_BACK, GL_SPECULAR
+:material:emission[0]|r,g,b,a:Materialfv, GL_FRONT, GL_EMISSION
+:material:emission[1]|r,g,b,a:Materialfv, GL_BACK, GL_EMISSION
+:material:shininess[0]:Materialf, GL_FRONT, GL_SHININESS
+:material:shininess[1]:Materialf, GL_BACK, GL_SHININESS
+%flush
+>for (i=0; i<CR_MAX_LIGHTS; i++) {
+>CRLightBits *lb = b->light+i;
+>CRLight *tl = to->light+i;
+>CRLight *cl = from->light+i;
+>if (!(CHECKDIRTY(lb->dirty, bitID))) continue;
+%target=tl
+%current=cl
+%bit=lb
+%extrabit=b
+:enable:enable:GL_LIGHT0+i
+%flush
+:ambient:ambient|r,g,b,a:Lightfv, GL_LIGHT0+i, GL_AMBIENT
+:diffuse:diffuse|r,g,b,a:Lightfv, GL_LIGHT0+i, GL_DIFFUSE
+:specular:specular|r,g,b,a:Lightfv, GL_LIGHT0+i, GL_SPECULAR
+:attenuation:constantAttenuation:Lightf, GL_LIGHT0+i, GL_CONSTANT_ATTENUATION
+:attenuation:linearAttenuation:Lightf, GL_LIGHT0+i, GL_LINEAR_ATTENUATION
+:attenuation:quadraticAttenuation:Lightf, GL_LIGHT0+i, GL_QUADRATIC_ATTENUATION
+:position:*diff_api.MatrixMode(GL_MODELVIEW);
+:position:*diff_api.PushMatrix();
+:position:*diff_api.LoadIdentity();
+:position:position|x,y,z,w:Lightfv, GL_LIGHT0+i, GL_POSITION
+:position:*diff_api.PopMatrix();
+:position:*diff_api.MatrixMode(toCtx->transform.matrixMode);
+:spot:*diff_api.MatrixMode(GL_MODELVIEW);
+:spot:*diff_api.PushMatrix();
+:spot:*diff_api.LoadIdentity();
+:spot:spotDirection|x,y,z:Lightfv, GL_LIGHT0+i, GL_SPOT_DIRECTION
+:spot:spotExponent:Lightf, GL_LIGHT0+i, GL_SPOT_EXPONENT
+:spot:spotCutoff:Lightf, GL_LIGHT0+i, GL_SPOT_CUTOFF
+:spot:*diff_api.PopMatrix();
+:spot:*diff_api.MatrixMode(toCtx->transform.matrixMode);
+%flush
+>CLEARDIRTY(lb->dirty, nbitID);
+>}
+%target=to
+%current=from
+%bit=b
+%extrabit=
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_limits.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_limits.c
new file mode 100644
index 00000000..91cdd84f
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_limits.c
@@ -0,0 +1,475 @@
+
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#include <stdio.h>
+#include "state.h"
+#include "state/cr_statetypes.h"
+#include "cr_mem.h"
+#include "cr_string.h"
+#include "cr_extstring.h"
+
+#ifdef WINDOWS
+#pragma warning( disable : 4127 )
+#endif
+
+
+/* This is a debug helper function. */
+void crStateLimitsPrint (const CRLimitsState *l)
+{
+ fprintf(stderr, "----------- OpenGL limits ----------------\n");
+ fprintf(stderr, "GL_MAX_TEXTURE_UNITS = %d\n", (int) l->maxTextureUnits);
+ fprintf(stderr, "GL_MAX_TEXTURE_SIZE = %d\n", (int) l->maxTextureSize);
+ fprintf(stderr, "GL_MAX_3D_TEXTURE_SIZE = %d\n", (int) l->max3DTextureSize);
+ fprintf(stderr, "GL_MAX_CUBE_MAP_TEXTURE_SIZE = %d\n", (int) l->maxCubeMapTextureSize);
+ fprintf(stderr, "GL_MAX_TEXTURE_ANISOTROPY = %f\n", l->maxTextureAnisotropy);
+ fprintf(stderr, "GL_MAX_LIGHTS = %d\n", (int) l->maxLights);
+ fprintf(stderr, "GL_MAX_CLIP_PLANES = %d\n", (int) l->maxClipPlanes);
+ fprintf(stderr, "GL_MAX_ATTRIB_STACK_DEPTH = %d\n", (int) l->maxClientAttribStackDepth);
+ fprintf(stderr, "GL_MAX_PROJECTION_STACK_DEPTH = %d\n", (int) l->maxProjectionStackDepth);
+ fprintf(stderr, "GL_MAX_MODELVIEW_STACK_DEPTH = %d\n", (int) l->maxModelviewStackDepth);
+ fprintf(stderr, "GL_MAX_TEXTURE_STACK_DEPTH = %d\n", (int) l->maxTextureStackDepth);
+ fprintf(stderr, "GL_MAX_COLOR_STACK_DEPTH = %d\n", (int) l->maxColorStackDepth);
+ fprintf(stderr, "GL_MAX_ATTRIB_STACK_DEPTH = %d\n", (int) l->maxAttribStackDepth);
+ fprintf(stderr, "GL_MAX_ATTRIB_STACK_DEPTH = %d\n", (int) l->maxClientAttribStackDepth);
+ fprintf(stderr, "GL_MAX_NAME_STACK_DEPTH = %d\n", (int) l->maxNameStackDepth);
+ fprintf(stderr, "GL_MAX_ELEMENTS_INDICES = %d\n", (int) l->maxElementsIndices);
+ fprintf(stderr, "GL_MAX_ELEMENTS_VERTICES = %d\n", (int) l->maxElementsVertices);
+ fprintf(stderr, "GL_MAX_EVAL_ORDER = %d\n", (int) l->maxEvalOrder);
+ fprintf(stderr, "GL_MAX_LIST_NESTING = %d\n", (int) l->maxListNesting);
+ fprintf(stderr, "GL_MAX_PIXEL_MAP_TABLE = %d\n", (int) l->maxPixelMapTable);
+ fprintf(stderr, "GL_MAX_VIEWPORT_DIMS = %d %d\n",
+ (int) l->maxViewportDims[0], (int) l->maxViewportDims[1]);
+ fprintf(stderr, "GL_SUBPIXEL_BITS = %d\n", (int) l->subpixelBits);
+ fprintf(stderr, "GL_ALIASED_POINT_SIZE_RANGE = %f .. %f\n",
+ l->aliasedPointSizeRange[0], l->aliasedPointSizeRange[1]);
+ fprintf(stderr, "GL_SMOOTH_POINT_SIZE_RANGE = %f .. %f\n",
+ l->aliasedPointSizeRange[0], l->aliasedPointSizeRange[1]);
+ fprintf(stderr, "GL_POINT_SIZE_GRANULARITY = %f\n", l->pointSizeGranularity);
+ fprintf(stderr, "GL_ALIASED_LINE_WIDTH_RANGE = %f .. %f\n",
+ l->aliasedLineWidthRange[0], l->aliasedLineWidthRange[1]);
+ fprintf(stderr, "GL_SMOOTH_LINE_WIDTH_RANGE = %f .. %f\n",
+ l->smoothLineWidthRange[0], l->smoothLineWidthRange[1]);
+ fprintf(stderr, "GL_LINE_WIDTH_GRANULARITY = %f\n", l->lineWidthGranularity);
+ fprintf(stderr, "GL_MAX_GENERAL_COMBINERS_NV = %d\n", (int) l->maxGeneralCombiners);
+ fprintf(stderr, "GL_EXTENSIONS = %s\n", (const char *) l->extensions);
+ fprintf(stderr, "------------------------------------------\n");
+}
+
+
+void crStateLimitsDestroy(CRLimitsState *l)
+{
+ if (l->extensions) {
+ crFree((void *) l->extensions);
+ l->extensions = NULL;
+ }
+}
+
+
+/*
+ * Initialize the CRLimitsState object to Chromium's defaults.
+ */
+void crStateLimitsInit (CRLimitsState *l)
+{
+ l->maxTextureUnits = CR_MAX_TEXTURE_UNITS;
+ l->maxTextureSize = CR_MAX_TEXTURE_SIZE;
+ l->max3DTextureSize = CR_MAX_3D_TEXTURE_SIZE;
+ l->maxCubeMapTextureSize = CR_MAX_CUBE_TEXTURE_SIZE;
+#ifdef CR_NV_texture_rectangle
+ l->maxRectTextureSize = CR_MAX_RECTANGLE_TEXTURE_SIZE;
+#endif
+ l->maxTextureAnisotropy = CR_MAX_TEXTURE_ANISOTROPY;
+ l->maxGeneralCombiners = CR_MAX_GENERAL_COMBINERS;
+ l->maxLights = CR_MAX_LIGHTS;
+ l->maxClipPlanes = CR_MAX_CLIP_PLANES;
+ l->maxClientAttribStackDepth = CR_MAX_ATTRIB_STACK_DEPTH;
+ l->maxProjectionStackDepth = CR_MAX_PROJECTION_STACK_DEPTH;
+ l->maxModelviewStackDepth = CR_MAX_MODELVIEW_STACK_DEPTH;
+ l->maxTextureStackDepth = CR_MAX_TEXTURE_STACK_DEPTH;
+ l->maxColorStackDepth = CR_MAX_COLOR_STACK_DEPTH;
+ l->maxAttribStackDepth = CR_MAX_ATTRIB_STACK_DEPTH;
+ l->maxClientAttribStackDepth = CR_MAX_ATTRIB_STACK_DEPTH;
+ l->maxNameStackDepth = CR_MAX_NAME_STACK_DEPTH;
+ l->maxElementsIndices = CR_MAX_ELEMENTS_INDICES;
+ l->maxElementsVertices = CR_MAX_ELEMENTS_VERTICES;
+ l->maxEvalOrder = CR_MAX_EVAL_ORDER;
+ l->maxListNesting = CR_MAX_LIST_NESTING;
+ l->maxPixelMapTable = CR_MAX_PIXEL_MAP_TABLE;
+ l->maxViewportDims[0] = l->maxViewportDims[1] = CR_MAX_VIEWPORT_DIM;
+ l->subpixelBits = CR_SUBPIXEL_BITS;
+ l->aliasedPointSizeRange[0] = CR_ALIASED_POINT_SIZE_MIN;
+ l->aliasedPointSizeRange[1] = CR_ALIASED_POINT_SIZE_MAX;
+ l->smoothPointSizeRange[0] = CR_SMOOTH_POINT_SIZE_MIN;
+ l->smoothPointSizeRange[1] = CR_SMOOTH_POINT_SIZE_MAX;
+ l->pointSizeGranularity = CR_POINT_SIZE_GRANULARITY;
+ l->aliasedLineWidthRange[0] = CR_ALIASED_LINE_WIDTH_MIN;
+ l->aliasedLineWidthRange[1] = CR_ALIASED_LINE_WIDTH_MAX;
+ l->smoothLineWidthRange[0] = CR_SMOOTH_LINE_WIDTH_MIN;
+ l->smoothLineWidthRange[1] = CR_SMOOTH_LINE_WIDTH_MAX;
+ l->lineWidthGranularity = CR_LINE_WIDTH_GRANULARITY;
+#ifdef CR_EXT_texture_lod_bias
+ l->maxTextureLodBias = CR_MAX_TEXTURE_LOD_BIAS;
+#endif
+#ifdef CR_NV_fragment_program
+ l->maxTextureCoords = CR_MAX_TEXTURE_COORDS;
+ l->maxTextureImageUnits = CR_MAX_TEXTURE_IMAGE_UNITS;
+ l->maxFragmentProgramLocalParams = CR_MAX_FRAGMENT_LOCAL_PARAMS;
+#endif
+#ifdef CR_NV_vertex_program
+ l->maxProgramMatrixStackDepth = CR_MAX_PROGRAM_MATRIX_STACK_DEPTH;
+ l->maxProgramMatrices = CR_MAX_PROGRAM_MATRICES;
+#endif
+#ifdef CR_ARB_fragment_program
+ l->maxFragmentProgramInstructions = CR_MAX_FRAGMENT_PROGRAM_INSTRUCTIONS;
+ l->maxFragmentProgramLocalParams = CR_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMS;
+ l->maxFragmentProgramEnvParams = CR_MAX_FRAGMENT_PROGRAM_ENV_PARAMS;
+ l->maxFragmentProgramTemps = CR_MAX_FRAGMENT_PROGRAM_TEMPS;
+ l->maxFragmentProgramAttribs = CR_MAX_FRAGMENT_PROGRAM_ATTRIBS;
+ l->maxFragmentProgramAddressRegs = CR_MAX_FRAGMENT_PROGRAM_ADDRESS_REGS;
+ l->maxFragmentProgramAluInstructions = CR_MAX_FRAGMENT_PROGRAM_ALU_INSTRUCTIONS;
+ l->maxFragmentProgramTexInstructions = CR_MAX_FRAGMENT_PROGRAM_TEX_INSTRUCTIONS;
+ l->maxFragmentProgramTexIndirections = CR_MAX_FRAGMENT_PROGRAM_TEX_INDIRECTIONS;
+#endif
+#ifdef CR_ARB_vertex_program
+ l->maxVertexProgramInstructions = CR_MAX_VERTEX_PROGRAM_INSTRUCTIONS;
+ l->maxVertexProgramLocalParams = CR_MAX_VERTEX_PROGRAM_LOCAL_PARAMS;
+ l->maxVertexProgramEnvParams = CR_MAX_VERTEX_PROGRAM_ENV_PARAMS;
+ l->maxVertexProgramTemps = CR_MAX_VERTEX_PROGRAM_TEMPS;
+ l->maxVertexProgramAttribs = CR_MAX_VERTEX_PROGRAM_ATTRIBS;
+ l->maxVertexProgramAddressRegs = CR_MAX_VERTEX_PROGRAM_ADDRESS_REGS;
+#endif
+
+ l->extensions = (GLubyte *) crStrdup(crExtensions);
+
+ /* These will get properly set in crStateCreateContext() by examining
+ * the visBits bitfield parameter.
+ */
+ l->redBits = 0;
+ l->greenBits = 0;
+ l->blueBits = 0;
+ l->alphaBits = 0;
+ l->depthBits = 0;
+ l->stencilBits = 0;
+ l->accumRedBits = 0;
+ l->accumGreenBits = 0;
+ l->accumBlueBits = 0;
+ l->accumAlphaBits = 0;
+ l->auxBuffers = 0;
+ l->rgbaMode = GL_TRUE;
+ l->doubleBuffer = GL_FALSE;
+ l->stereo = GL_FALSE;
+ l->sampleBuffers = 0;
+ l->samples = 0;
+ l->level = 0;
+
+ (void) crAppOnlyExtensions; /* silence warning */
+}
+
+
+/*
+ * Given the GL version number returned from a real GL renderer,
+ * compute the version number supported by Chromium.
+ */
+GLfloat crStateComputeVersion(float minVersion)
+{
+ const GLfloat crVersion = crStrToFloat(CR_OPENGL_VERSION_STRING);
+ if (crVersion < minVersion)
+ minVersion = crVersion;
+ return minVersion;
+}
+
+
+/*
+ * <extenions> is an array [n] of GLubyte pointers which contain lists of
+ * OpenGL extensions.
+ * Compute the intersection of those strings, then append the Chromium
+ * extension strings.
+ */
+GLubyte * crStateMergeExtensions(GLuint n, const GLubyte **extensions)
+{
+ char *merged, *result;
+ GLuint i;
+
+ /* find intersection of all extension strings */
+ merged = crStrdup(crExtensions);
+ for (i = 0; i < n; i++)
+ {
+ char *m = crStrIntersect(merged, (const char *) extensions[i]);
+ if (merged)
+ crFree(merged);
+ merged = m;
+ }
+
+ /* append Cr extensions */
+ result = crStrjoin(merged, crChromiumExtensions);
+ crFree(merged);
+ return (GLubyte *) result;
+}
+
+static GLboolean hasExtension(const char *haystack, const char *needle)
+{
+ const int needleLen = crStrlen(needle);
+ const char *s;
+
+ while (1) {
+ s = crStrstr(haystack, needle);
+ if (!s)
+ return GL_FALSE;
+ if (s && (s[needleLen] == ' ' || s[needleLen] == 0))
+ return GL_TRUE;
+ haystack += needleLen;
+ }
+}
+
+/*
+ * Examine the context's extension string and set the boolean extension
+ * flags accordingly. This is to be called during context initialization.
+ */
+void crStateExtensionsInit( CRLimitsState *limits, CRExtensionState *extensions )
+{
+ /* init all booleans to false */
+ crMemZero(extensions, sizeof(CRExtensionState));
+
+ if (hasExtension((const char*)limits->extensions, "GL_ARB_depth_texture"))
+ extensions->ARB_depth_texture = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_ARB_fragment_program"))
+ extensions->ARB_fragment_program = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_ARB_imaging"))
+ extensions->ARB_imaging = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_ARB_multisample"))
+ extensions->ARB_multisample = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_ARB_multitexture"))
+ extensions->ARB_multitexture = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_ARB_occlusion_query"))
+ extensions->ARB_occlusion_query = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_ARB_point_parameters"))
+ extensions->ARB_point_parameters = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_ARB_point_sprite"))
+ extensions->ARB_point_sprite = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_ARB_shadow"))
+ extensions->ARB_shadow = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_ARB_shadow_ambient"))
+ extensions->ARB_shadow_ambient = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_ARB_texture_border_clamp") ||
+ hasExtension((const char*)limits->extensions, "GL_SGIS_texture_border_clamp"))
+ extensions->ARB_texture_border_clamp = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_ARB_texture_compression"))
+ extensions->ARB_texture_compression = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_ARB_texture_cube_map") ||
+ hasExtension((const char*)limits->extensions, "GL_EXT_texture_cube_map"))
+ extensions->ARB_texture_cube_map = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_ARB_texture_env_add"))
+ extensions->ARB_texture_env_add = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_ARB_texture_env_combine") ||
+ hasExtension((const char*)limits->extensions, "GL_EXT_texture_env_combine"))
+ extensions->ARB_texture_env_combine = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_ARB_texture_env_crossbar"))
+ extensions->ARB_texture_env_crossbar = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_ARB_texture_env_dot3") ||
+ hasExtension((const char*)limits->extensions, "GL_EXT_texture_env_dot3"))
+ extensions->ARB_texture_env_dot3 = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_ARB_texture_mirrored_repeat"))
+ extensions->ARB_texture_mirrored_repeat = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_ATI_texture_mirror_once"))
+ extensions->ATI_texture_mirror_once = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_ARB_texture_non_power_of_two"))
+ extensions->ARB_texture_non_power_of_two = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_ARB_transpose_matrix"))
+ extensions->ARB_transpose_matrix = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_ARB_vertex_buffer_object"))
+ extensions->ARB_vertex_buffer_object = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_ARB_pixel_buffer_object"))
+ extensions->ARB_pixel_buffer_object = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_ARB_vertex_program"))
+ extensions->ARB_vertex_program = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_ARB_window_pos"))
+ extensions->ARB_window_pos = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_EXT_blend_color"))
+ extensions->EXT_blend_color= GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_EXT_blend_minmax"))
+ extensions->EXT_blend_minmax = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_EXT_blend_func_separate"))
+ extensions->EXT_blend_func_separate = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_EXT_blend_logic_op"))
+ extensions->EXT_blend_logic_op = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_EXT_blend_subtract"))
+ extensions->EXT_blend_subtract = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_EXT_clip_volume_hint"))
+ extensions->EXT_clip_volume_hint = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_EXT_fog_coord"))
+ extensions->EXT_fog_coord = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_EXT_multi_draw_arrays"))
+ extensions->EXT_multi_draw_arrays = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_EXT_secondary_color"))
+ extensions->EXT_secondary_color = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_EXT_separate_specular_color"))
+ extensions->EXT_separate_specular_color = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_EXT_shadow_funcs"))
+ extensions->EXT_shadow_funcs = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_EXT_stencil_wrap"))
+ extensions->EXT_stencil_wrap = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_EXT_texture_edge_clamp") ||
+ hasExtension((const char*)limits->extensions, "GL_SGIS_texture_edge_clamp"))
+ extensions->EXT_texture_edge_clamp = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_EXT_texture_filter_anisotropic"))
+ extensions->EXT_texture_filter_anisotropic = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_EXT_texture_lod_bias"))
+ extensions->EXT_texture_lod_bias = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_IBM_rasterpos_clip"))
+ extensions->IBM_rasterpos_clip = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_NV_fog_distance"))
+ extensions->NV_fog_distance = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_NV_fragment_program"))
+ extensions->NV_fragment_program = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_NV_register_combiners"))
+ extensions->NV_register_combiners = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_NV_register_combiners2"))
+ extensions->NV_register_combiners2 = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_NV_texgen_reflection"))
+ extensions->NV_texgen_reflection = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_NV_texture_rectangle")
+ || hasExtension((const char*)limits->extensions, "GL_EXT_texture_rectangle"))
+ extensions->NV_texture_rectangle = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_NV_vertex_program"))
+ extensions->NV_vertex_program = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_NV_vertex_program1_1"))
+ extensions->NV_vertex_program1_1 = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_NV_vertex_program2"))
+ extensions->NV_vertex_program2 = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_EXT_texture3D"))
+ extensions->EXT_texture3D = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GL_SGIS_generate_mipmap"))
+ extensions->SGIS_generate_mipmap = GL_TRUE;
+
+ if (hasExtension((const char*)limits->extensions, "GLX_EXT_texture_from_pixmap"))
+ extensions->EXT_texture_from_pixmap = GL_TRUE;
+
+ if (extensions->NV_vertex_program2)
+ limits->maxVertexProgramEnvParams = 256;
+ else
+ limits->maxVertexProgramEnvParams = 96;
+
+ if (extensions->NV_vertex_program || extensions->ARB_vertex_program)
+ extensions->any_vertex_program = GL_TRUE;
+ if (extensions->NV_fragment_program || extensions->ARB_fragment_program)
+ extensions->any_fragment_program = GL_TRUE;
+ if (extensions->any_vertex_program || extensions->any_fragment_program)
+ extensions->any_program = GL_TRUE;
+
+#if 0
+ /* Now, determine what level of OpenGL we support */
+ if (extensions->ARB_multisample &&
+ extensions->ARB_multitexture &&
+ extensions->ARB_texture_border_clamp &&
+ extensions->ARB_texture_compression &&
+ extensions->ARB_texture_cube_map &&
+ extensions->ARB_texture_env_add &&
+ extensions->ARB_texture_env_combine &&
+ extensions->ARB_texture_env_dot3) {
+ if (extensions->ARB_depth_texture &&
+ extensions->ARB_point_parameters &&
+ extensions->ARB_shadow &&
+ extensions->ARB_texture_env_crossbar &&
+ extensions->ARB_texture_mirrored_repeat &&
+ extensions->ARB_window_pos &&
+ extensions->EXT_blend_color &&
+ extensions->EXT_blend_func_separate &&
+ extensions->EXT_blend_logic_op &&
+ extensions->EXT_blend_minmax &&
+ extensions->EXT_blend_subtract &&
+ extensions->EXT_fog_coord &&
+ extensions->EXT_multi_draw_arrays &&
+ extensions->EXT_secondary_color &&
+ extensions->EXT_shadow_funcs &&
+ extensions->EXT_stencil_wrap &&
+ extensions->SGIS_generate_mipmap) {
+ if (extensions->ARB_occlusion_query &&
+ extensions->ARB_vertex_buffer_object &&
+ extensions->ARB_texture_non_power_of_two &&
+ extensions->EXT_shadow_funcs) {
+ extensions->version = (const GLubyte *) "1.5 Chromium " CR_VERSION_STRING;
+ }
+ else {
+ extensions->version = (const GLubyte *) "1.4 Chromium " CR_VERSION_STRING;
+ }
+ }
+ else {
+ extensions->version = (const GLubyte *) "1.3 Chromium " CR_VERSION_STRING;
+ }
+ }
+ else {
+ extensions->version = (const GLubyte *) "1.2 Chromium " CR_VERSION_STRING;
+ }
+#endif
+}
+
+
+/*
+ * Set the GL_EXTENSIONS string for the given context. We'll make
+ * a copy of the given string.
+ */
+void
+crStateSetExtensionString( CRContext *ctx, const GLubyte *extensions )
+{
+ if (ctx->limits.extensions)
+ crFree((void *) ctx->limits.extensions);
+
+ ctx->limits.extensions = (const GLubyte *)crStrdup((const char*)extensions);
+
+ crStateExtensionsInit(&(ctx->limits), &(ctx->extensions));
+}
+
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_line.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_line.c
new file mode 100644
index 00000000..ef4a3b4a
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_line.c
@@ -0,0 +1,87 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#include <stdio.h>
+#include "state.h"
+#include "state/cr_statetypes.h"
+#include "state_internals.h"
+
+void crStateLineInit (CRContext *ctx)
+{
+ CRLineState *l = &ctx->line;
+ CRStateBits *sb = GetCurrentBits();
+ CRLineBits *lb = &(sb->line);
+
+ l->lineSmooth = GL_FALSE;
+ l->lineStipple = GL_FALSE;
+ RESET(lb->enable, ctx->bitid);
+ l->width = 1.0f;
+ RESET(lb->width, ctx->bitid);
+ l->pattern = 0xFFFF;
+ l->repeat = 1;
+ RESET(lb->stipple, ctx->bitid);
+ /*
+ *l->aliasedlinewidth_min = c->aliasedlinewidth_min;
+ *l->aliasedlinewidth_max = c->aliasedlinewidth_max;
+ *l->aliasedlinegranularity = c->aliasedlinegranularity;
+ *l->smoothlinewidth_min = c->smoothlinewidth_min;
+ *l->smoothlinewidth_max = c->smoothlinewidth_max;
+ *l->smoothlinegranularity = c->smoothlinegranularity; */
+
+ RESET(lb->dirty, ctx->bitid);
+}
+
+void STATE_APIENTRY crStateLineWidth(GLfloat width)
+{
+ CRContext *g = GetCurrentContext();
+ CRLineState *l = &(g->line);
+ CRStateBits *sb = GetCurrentBits();
+ CRLineBits *lb = &(sb->line);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glLineWidth called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ if (width <= 0.0f)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glLineWidth called with size <= 0.0: %f", width);
+ return;
+ }
+
+ l->width = width;
+ DIRTY(lb->width, g->neg_bitid);
+ DIRTY(lb->dirty, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateLineStipple(GLint factor, GLushort pattern)
+{
+ CRContext *g = GetCurrentContext();
+ CRLineState *l = &(g->line);
+ CRStateBits *sb = GetCurrentBits();
+ CRLineBits *lb = &(sb->line);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glLineStipple called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ if (factor < 1) factor = 1;
+ if (factor > 256) factor = 256;
+
+ l->pattern = pattern;
+ l->repeat = factor;
+ DIRTY(lb->stipple, g->neg_bitid);
+ DIRTY(lb->dirty, g->neg_bitid);
+}
+
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_line.txt b/src/VBox/GuestHost/OpenGL/state_tracker/state_line.txt
new file mode 100644
index 00000000..35ab8633
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_line.txt
@@ -0,0 +1,8 @@
+# Copyright (c) 2001, Stanford University
+# All rights reserved.
+#
+# See the file LICENSE.txt for information on redistributing this software.
+:enable:lineSmooth:GL_LINE_SMOOTH
+:enable:lineStipple:GL_LINE_STIPPLE
+:width:width:LineWidth
+lineStipple:stipple:repeat,pattern:LineStipple
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_lists.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_lists.c
new file mode 100644
index 00000000..73511399
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_lists.c
@@ -0,0 +1,1407 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#include <stdio.h>
+#include "cr_mem.h"
+#include "state.h"
+#include "state/cr_statetypes.h"
+#include "state_internals.h"
+
+void crStateListsDestroy(CRContext *ctx)
+{
+ /* nothing - dlists are in shared state */
+ (void)ctx;
+}
+
+void crStateListsInit(CRContext *ctx)
+{
+ CRListsState *l = &ctx->lists;
+ CRStateBits *sb = GetCurrentBits();
+ CRListsBits *lb = &(sb->lists);
+
+ l->newEnd = GL_FALSE;
+ l->mode = 0;
+ l->currentIndex = 0;
+ l->base = 0;
+
+ RESET(lb->base, ctx->bitid);
+ RESET(lb->dirty, ctx->bitid);
+}
+
+/*#define CRSTATE_DEBUG_QUERY_HW_STATE*/
+
+#ifndef CRSTATE_DEBUG_QUERY_HW_STATE
+# define CRSTATE_SET_CAP(state, value, format) g->state=value
+# define CR_STATE_SETTEX_MSG(state, st, hw)
+# define CR_STATE_SETMAT_MSG(state, st, hw)
+#else
+# define CRSTATE_SET_CAP(state, value, format) \
+ if (g->state!=value) { \
+ crDebug("crStateQueryHWState fixed %s from "format" to "format, #state, g->state, value); \
+ g->state=value; \
+ }
+# define CR_STATE_SETTEX_MSG(state, st, hw) crDebug("crStateQueryHWState fixed %s from %i to %i", state, st, hw)
+# define CR_STATE_SETMAT_MSG(state, st, hw) \
+ { \
+ crDebug("crStateQueryHWState fixed %s", state); \
+ crDebug("st: [%f, %f, %f, %f] [%f, %f, %f, %f] [%f, %f, %f, %f] [%f, %f, %f, %f]", \
+ st[0], st[1], st[2], st[3], st[4], st[5], st[6], st[7], \
+ st[8], st[9], st[10], st[11], st[12], st[13], st[14], st[15]); \
+ crDebug("hw: [%f, %f, %f, %f] [%f, %f, %f, %f] [%f, %f, %f, %f] [%f, %f, %f, %f]", \
+ hw[0], hw[1], hw[2], hw[3], hw[4], hw[5], hw[6], hw[7], \
+ hw[8], hw[9], hw[10], hw[11], hw[12], hw[13], hw[14], hw[15]); \
+ }
+#endif
+
+#define CRSTATE_SET_ENABLED(state, cap) CRSTATE_SET_CAP(state, diff_api.IsEnabled(cap), "%u")
+
+#define CRSTATE_SET_ENUM(state, cap) {GLenum _e=g->state; diff_api.GetIntegerv(cap, &_e); CRSTATE_SET_CAP(state, _e, "%#x");}
+#define CRSTATE_SET_FLOAT(state, cap) {GLfloat _f=g->state; diff_api.GetFloatv(cap, &_f); CRSTATE_SET_CAP(state, _f, "%f");}
+#define CRSTATE_SET_INT(state, cap) {GLint _i=g->state; diff_api.GetIntegerv(cap, &_i); CRSTATE_SET_CAP(state, _i, "%i");}
+#define CRSTATE_SET_BOOL(state, cap) {GLboolean _b=g->state; diff_api.GetBooleanv(cap, &_b); CRSTATE_SET_CAP(state, _b, "%u");}
+
+#define CRSTATE_SET_COLORF(state, cap) \
+ { \
+ GLfloat value[4]; \
+ value[0]=g->state.r; \
+ value[1]=g->state.g; \
+ value[2]=g->state.b; \
+ value[3]=g->state.a; \
+ diff_api.GetFloatv(cap, &value[0]); \
+ CRSTATE_SET_CAP(state.r, value[0], "%f"); \
+ CRSTATE_SET_CAP(state.g, value[1], "%f"); \
+ CRSTATE_SET_CAP(state.b, value[2], "%f"); \
+ CRSTATE_SET_CAP(state.a, value[3], "%f"); \
+ }
+
+#define CRSTATE_SET_TEXTURE(state, cap, target) \
+ { \
+ GLint _stex, _hwtex; \
+ _stex = _hwtex = crStateGetTextureObjHWID(g->state); \
+ diff_api.GetIntegerv(cap, &_hwtex); \
+ if (_stex!=_hwtex) \
+ { \
+ CR_STATE_SETTEX_MSG(#state, _stex, _hwtex); \
+ crStateBindTexture(target, crStateTextureHWIDtoID(_hwtex)); \
+ } \
+ }
+
+#define _CRSTATE_SET_4F_RGBA(state, p1, p2, func) \
+ { \
+ GLfloat value[4]; \
+ value[0]=g->state.r; \
+ value[1]=g->state.g; \
+ value[2]=g->state.b; \
+ value[3]=g->state.a; \
+ diff_api.func(p1, p2, &value[0]); \
+ CRSTATE_SET_CAP(state.r, value[0], "%f"); \
+ CRSTATE_SET_CAP(state.g, value[1], "%f"); \
+ CRSTATE_SET_CAP(state.b, value[2], "%f"); \
+ CRSTATE_SET_CAP(state.a, value[3], "%f"); \
+ }
+
+#define _CRSTATE_SET_4F_XYZW(state, p1, p2, func) \
+ { \
+ GLfloat value[4]; \
+ value[0]=g->state.x; \
+ value[1]=g->state.y; \
+ value[2]=g->state.z; \
+ value[3]=g->state.w; \
+ diff_api.func(p1, p2, &value[0]); \
+ CRSTATE_SET_CAP(state.x, value[0], "%f"); \
+ CRSTATE_SET_CAP(state.y, value[1], "%f"); \
+ CRSTATE_SET_CAP(state.z, value[2], "%f"); \
+ CRSTATE_SET_CAP(state.w, value[3], "%f"); \
+ }
+
+#define CRSTATE_SET_TEXGEN_4F(state, coord, pname) _CRSTATE_SET_4F_XYZW(state, coord, pname, GetTexGenfv)
+#define CRSTATE_SET_TEXGEN_I(state, coord, pname) {GLint _i=g->state; diff_api.GetTexGeniv(coord, pname, &_i); CRSTATE_SET_CAP(state, _i, "%i");}
+
+#define CRSTATE_SET_TEXENV_I(state, target, pname) {GLint _i=g->state; diff_api.GetTexEnviv(target, pname, &_i); CRSTATE_SET_CAP(state, _i, "%i");}
+#define CRSTATE_SET_TEXENV_F(state, target, pname) {GLfloat _f=g->state; diff_api.GetTexEnvfv(target, pname, &_f); CRSTATE_SET_CAP(state, _f, "%f");}
+#define CRSTATE_SET_TEXENV_COLOR(state, target, pname) _CRSTATE_SET_4F_RGBA(state, target, pname, GetTexEnvfv)
+
+#define CRSTATE_SET_MATERIAL_COLOR(state, face, pname) _CRSTATE_SET_4F_RGBA(state, face, pname, GetMaterialfv)
+#define CRSTATE_SET_MATERIAL_F(state, face, pname) {GLfloat _f=g->state; diff_api.GetMaterialfv(face, pname, &_f); CRSTATE_SET_CAP(state, _f, "%f");}
+
+#define CRSTATE_SET_LIGHT_COLOR(state, light, pname) _CRSTATE_SET_4F_RGBA(state, light, pname, GetLightfv)
+#define CRSTATE_SET_LIGHT_F(state, light, pname) {GLfloat _f=g->state; diff_api.GetLightfv(light, pname, &_f); CRSTATE_SET_CAP(state, _f, "%f");}
+#define CRSTATE_SET_LIGHT_4F(state, light, pname) _CRSTATE_SET_4F_XYZW(state, light, pname, GetLightfv)
+#define CRSTATE_SET_LIGHT_3F(state, light, pname) \
+ { \
+ GLfloat value[3]; \
+ value[0]=g->state.x; \
+ value[1]=g->state.y; \
+ value[2]=g->state.z; \
+ diff_api.GetLightfv(light, pname, &value[0]); \
+ CRSTATE_SET_CAP(state.x, value[0], "%f"); \
+ CRSTATE_SET_CAP(state.y, value[1], "%f"); \
+ CRSTATE_SET_CAP(state.z, value[2], "%f"); \
+ }
+
+#define CRSTATE_SET_CLIPPLANE_4D(state, plane) \
+ { \
+ GLdouble value[4]; \
+ value[0]=g->state.x; \
+ value[1]=g->state.y; \
+ value[2]=g->state.z; \
+ value[3]=g->state.w; \
+ diff_api.GetClipPlane(plane, &value[0]); \
+ CRSTATE_SET_CAP(state.x, value[0], "%G"); \
+ CRSTATE_SET_CAP(state.y, value[1], "%G"); \
+ CRSTATE_SET_CAP(state.z, value[2], "%G"); \
+ CRSTATE_SET_CAP(state.w, value[3], "%G"); \
+ }
+
+#define CRSTATE_SET_MATRIX(state, cap) \
+ { \
+ GLfloat f[16], sm[16]; \
+ crMatrixGetFloats(&f[0], g->state); \
+ crMemcpy(&sm[0], &f[0], 16*sizeof(GLfloat)); \
+ diff_api.GetFloatv(cap, &f[0]); \
+ if (crMemcmp(&f[0], &sm[0], 16*sizeof(GLfloat))) \
+ { \
+ CR_STATE_SETMAT_MSG(#state, sm, f); \
+ crMatrixInitFromFloats(g->state, &f[0]); \
+ } \
+ }
+
+void STATE_APIENTRY crStateQueryHWState(GLuint fbFbo, GLuint bbFbo)
+{
+ CRContext *g = GetCurrentContext();
+ CRStateBits *sb = GetCurrentBits();
+ CRbitvalue /* *bitID=g->bitid, */ *negbitID=g->neg_bitid;
+
+ CRASSERT(g_bVBoxEnableDiffOnMakeCurrent);
+
+ crStateSyncHWErrorState(g);
+
+ if (CHECKDIRTY(sb->buffer.dirty, negbitID))
+ {
+ if (CHECKDIRTY(sb->buffer.enable, negbitID))
+ {
+ CRSTATE_SET_ENABLED(buffer.depthTest, GL_DEPTH_TEST);
+ CRSTATE_SET_ENABLED(buffer.blend, GL_BLEND);
+ CRSTATE_SET_ENABLED(buffer.alphaTest, GL_ALPHA_TEST);
+ CRSTATE_SET_ENABLED(buffer.logicOp, GL_COLOR_LOGIC_OP);
+ CRSTATE_SET_ENABLED(buffer.indexLogicOp, GL_INDEX_LOGIC_OP);
+ CRSTATE_SET_ENABLED(buffer.dither, GL_DITHER);
+ }
+
+ if (CHECKDIRTY(sb->buffer.alphaFunc, negbitID))
+ {
+ CRSTATE_SET_ENUM(buffer.alphaTestFunc, GL_ALPHA_TEST_FUNC);
+ CRSTATE_SET_FLOAT(buffer.alphaTestRef, GL_ALPHA_TEST_REF);
+ }
+
+ if (CHECKDIRTY(sb->buffer.depthFunc, negbitID))
+ {
+ CRSTATE_SET_ENUM(buffer.depthFunc, GL_DEPTH_FUNC);
+ }
+
+ if (CHECKDIRTY(sb->buffer.blendFunc, negbitID))
+ {
+ CRSTATE_SET_ENUM(buffer.blendSrcRGB, GL_BLEND_SRC);
+ CRSTATE_SET_ENUM(buffer.blendDstRGB, GL_BLEND_DST);
+ }
+
+ if (CHECKDIRTY(sb->buffer.logicOp, negbitID))
+ {
+ CRSTATE_SET_ENUM(buffer.logicOpMode, GL_LOGIC_OP_MODE);
+ }
+
+/* seems to always match previous .logicOp
+ if (CHECKDIRTY(sb->buffer.indexLogicOp, negbitID))
+ {
+ CRSTATE_SET_ENUM(buffer.logicOpMode, GL_LOGIC_OP_MODE);
+ }
+*/
+
+ if (CHECKDIRTY(sb->buffer.drawBuffer, negbitID))
+ {
+ 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))
+ {
+ 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))
+ {
+ CRSTATE_SET_INT(buffer.indexWriteMask, GL_INDEX_WRITEMASK);
+ }
+
+ if (CHECKDIRTY(sb->buffer.colorWriteMask, negbitID))
+ {
+ GLboolean value[4];
+ value[0]=g->buffer.colorWriteMask.r;
+ value[1]=g->buffer.colorWriteMask.g;
+ value[2]=g->buffer.colorWriteMask.b;
+ value[3]=g->buffer.colorWriteMask.a;
+ diff_api.GetBooleanv(GL_COLOR_WRITEMASK, &value[0]);
+
+ CRSTATE_SET_CAP(buffer.colorWriteMask.r, value[0], "%u");
+ CRSTATE_SET_CAP(buffer.colorWriteMask.g, value[1], "%u");
+ CRSTATE_SET_CAP(buffer.colorWriteMask.b, value[2], "%u");
+ CRSTATE_SET_CAP(buffer.colorWriteMask.a, value[3], "%u");
+ }
+
+ if (CHECKDIRTY(sb->buffer.clearColor, negbitID))
+ {
+ CRSTATE_SET_COLORF(buffer.colorClearValue, GL_COLOR_CLEAR_VALUE);
+ }
+
+ if (CHECKDIRTY(sb->buffer.clearIndex, negbitID))
+ {
+ CRSTATE_SET_FLOAT(buffer.indexClearValue, GL_INDEX_CLEAR_VALUE);
+ }
+
+ if (CHECKDIRTY(sb->buffer.clearDepth, negbitID))
+ {
+ CRSTATE_SET_FLOAT(buffer.depthClearValue, GL_DEPTH_CLEAR_VALUE);
+ }
+
+ if (CHECKDIRTY(sb->buffer.clearAccum, negbitID))
+ {
+ CRSTATE_SET_COLORF(buffer.accumClearValue, GL_ACCUM_CLEAR_VALUE);
+ }
+
+ if (CHECKDIRTY(sb->buffer.depthMask, negbitID))
+ {
+ CRSTATE_SET_BOOL(buffer.depthMask, GL_DEPTH_WRITEMASK);
+ }
+
+#ifdef CR_EXT_blend_color
+ if (CHECKDIRTY(sb->buffer.blendColor, negbitID))
+ {
+ CRSTATE_SET_COLORF(buffer.blendColor, GL_BLEND_COLOR);
+ }
+#endif
+#if defined(CR_EXT_blend_minmax) || defined(CR_EXT_blend_subtract) || defined(CR_EXT_blend_logic_op)
+ if (CHECKDIRTY(sb->buffer.blendEquation, negbitID))
+ {
+ CRSTATE_SET_ENUM(buffer.blendEquation, GL_BLEND_EQUATION_EXT);
+ }
+#endif
+#if defined(CR_EXT_blend_func_separate)
+ if (CHECKDIRTY(sb->buffer.blendFuncSeparate, negbitID))
+ {
+ CRSTATE_SET_ENUM(buffer.blendSrcRGB, GL_BLEND_SRC_RGB_EXT);
+ CRSTATE_SET_ENUM(buffer.blendDstRGB, GL_BLEND_DST_RGB_EXT);
+ CRSTATE_SET_ENUM(buffer.blendSrcA, GL_BLEND_SRC_ALPHA_EXT);
+ CRSTATE_SET_ENUM(buffer.blendDstA, GL_BLEND_DST_ALPHA_EXT);
+ }
+#endif
+ }
+
+ 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.enableTwoSideEXT, negbitID))
+ {
+ CRSTATE_SET_ENABLED(stencil.stencilTwoSideEXT, GL_STENCIL_TEST_TWO_SIDE_EXT);
+ }
+
+ if (CHECKDIRTY(sb->stencil.activeStencilFace, negbitID))
+ {
+ 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))
+ {
+ CRSTATE_SET_INT(stencil.clearValue, GL_STENCIL_CLEAR_VALUE);
+ }
+
+ if (CHECKDIRTY(sb->stencil.writeMask, negbitID))
+ {
+ CRSTATE_SET_INT(stencil.writeMask, GL_STENCIL_WRITEMASK);
+ }
+ }
+
+ if (CHECKDIRTY(sb->texture.dirty, negbitID))
+ {
+ unsigned int i, activeUnit = g->texture.curTextureUnit;
+
+ for (i=0; i<g->limits.maxTextureUnits; ++i)
+ {
+ if (CHECKDIRTY(sb->texture.enable[i], negbitID))
+ {
+ if (i!=activeUnit)
+ {
+ diff_api.ActiveTextureARB(i + GL_TEXTURE0_ARB);
+ activeUnit=i;
+ }
+ CRSTATE_SET_ENABLED(texture.unit[i].enabled1D, GL_TEXTURE_1D);
+ CRSTATE_SET_ENABLED(texture.unit[i].enabled2D, GL_TEXTURE_2D);
+#ifdef CR_OPENGL_VERSION_1_2
+ CRSTATE_SET_ENABLED(texture.unit[i].enabled3D, GL_TEXTURE_3D);
+#endif
+#ifdef CR_ARB_texture_cube_map
+ if (g->extensions.ARB_texture_cube_map)
+ {
+ CRSTATE_SET_ENABLED(texture.unit[i].enabledCubeMap, GL_TEXTURE_CUBE_MAP_ARB);
+ }
+#endif
+#ifdef CR_NV_texture_rectangle
+ if (g->extensions.NV_texture_rectangle)
+ {
+ CRSTATE_SET_ENABLED(texture.unit[i].enabledRect, GL_TEXTURE_RECTANGLE_NV);
+ }
+#endif
+
+ CRSTATE_SET_ENABLED(texture.unit[i].textureGen.s, GL_TEXTURE_GEN_S);
+ CRSTATE_SET_ENABLED(texture.unit[i].textureGen.t, GL_TEXTURE_GEN_T);
+ CRSTATE_SET_ENABLED(texture.unit[i].textureGen.r, GL_TEXTURE_GEN_R);
+ CRSTATE_SET_ENABLED(texture.unit[i].textureGen.q, GL_TEXTURE_GEN_Q);
+ }
+
+ if (CHECKDIRTY(sb->texture.current[i], negbitID))
+ {
+ if (i!=activeUnit)
+ {
+ diff_api.ActiveTextureARB(i + GL_TEXTURE0_ARB);
+ activeUnit=i;
+ }
+
+ CRSTATE_SET_TEXTURE(texture.unit[i].currentTexture1D, GL_TEXTURE_BINDING_1D, GL_TEXTURE_1D);
+ CRSTATE_SET_TEXTURE(texture.unit[i].currentTexture2D, GL_TEXTURE_BINDING_2D, GL_TEXTURE_2D);
+#ifdef CR_OPENGL_VERSION_1_2
+ CRSTATE_SET_TEXTURE(texture.unit[i].currentTexture3D, GL_TEXTURE_BINDING_3D, GL_TEXTURE_3D);
+#endif
+#ifdef CR_ARB_texture_cube_map
+ if (g->extensions.ARB_texture_cube_map)
+ {
+ CRSTATE_SET_TEXTURE(texture.unit[i].currentTextureCubeMap, GL_TEXTURE_BINDING_CUBE_MAP_ARB, GL_TEXTURE_CUBE_MAP_ARB);
+ }
+#endif
+#ifdef CR_NV_texture_rectangle
+ if (g->extensions.NV_texture_rectangle)
+ {
+ CRSTATE_SET_TEXTURE(texture.unit[i].currentTextureRect, GL_TEXTURE_BINDING_RECTANGLE_NV, GL_TEXTURE_RECTANGLE_NV);
+ }
+#endif
+ }
+
+ if (CHECKDIRTY(sb->texture.objGen[i], negbitID))
+ {
+ if (i!=activeUnit)
+ {
+ diff_api.ActiveTextureARB(i + GL_TEXTURE0_ARB);
+ activeUnit=i;
+ }
+
+ CRSTATE_SET_TEXGEN_4F(texture.unit[i].objSCoeff, GL_S, GL_OBJECT_PLANE);
+ CRSTATE_SET_TEXGEN_4F(texture.unit[i].objTCoeff, GL_T, GL_OBJECT_PLANE);
+ CRSTATE_SET_TEXGEN_4F(texture.unit[i].objRCoeff, GL_R, GL_OBJECT_PLANE);
+ CRSTATE_SET_TEXGEN_4F(texture.unit[i].objQCoeff, GL_Q, GL_OBJECT_PLANE);
+ }
+
+ if (CHECKDIRTY(sb->texture.eyeGen[i], negbitID))
+ {
+ if (i!=activeUnit)
+ {
+ diff_api.ActiveTextureARB(i + GL_TEXTURE0_ARB);
+ activeUnit=i;
+ }
+
+ CRSTATE_SET_TEXGEN_4F(texture.unit[i].eyeSCoeff, GL_S, GL_EYE_PLANE);
+ CRSTATE_SET_TEXGEN_4F(texture.unit[i].eyeTCoeff, GL_T, GL_EYE_PLANE);
+ CRSTATE_SET_TEXGEN_4F(texture.unit[i].eyeRCoeff, GL_R, GL_EYE_PLANE);
+ CRSTATE_SET_TEXGEN_4F(texture.unit[i].eyeQCoeff, GL_Q, GL_EYE_PLANE);
+ }
+
+ if (CHECKDIRTY(sb->texture.genMode[i], negbitID))
+ {
+ if (i!=activeUnit)
+ {
+ diff_api.ActiveTextureARB(i + GL_TEXTURE0_ARB);
+ activeUnit=i;
+ }
+
+ CRSTATE_SET_TEXGEN_I(texture.unit[i].gen.s, GL_S, GL_TEXTURE_GEN_MODE);
+ CRSTATE_SET_TEXGEN_I(texture.unit[i].gen.t, GL_T, GL_TEXTURE_GEN_MODE);
+ CRSTATE_SET_TEXGEN_I(texture.unit[i].gen.r, GL_R, GL_TEXTURE_GEN_MODE);
+ CRSTATE_SET_TEXGEN_I(texture.unit[i].gen.q, GL_Q, GL_TEXTURE_GEN_MODE);
+ }
+
+ if (CHECKDIRTY(sb->texture.envBit[i], negbitID))
+ {
+ if (i!=activeUnit)
+ {
+ diff_api.ActiveTextureARB(i + GL_TEXTURE0_ARB);
+ activeUnit=i;
+ }
+
+ CRSTATE_SET_TEXENV_I(texture.unit[i].envMode, GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE);
+ CRSTATE_SET_TEXENV_COLOR(texture.unit[i].envColor, GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR);
+ CRSTATE_SET_TEXENV_I(texture.unit[i].combineModeRGB, GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB);
+ CRSTATE_SET_TEXENV_I(texture.unit[i].combineModeA, GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB);
+ CRSTATE_SET_TEXENV_I(texture.unit[i].combineSourceRGB[0], GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB);
+ CRSTATE_SET_TEXENV_I(texture.unit[i].combineSourceRGB[1], GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB);
+ CRSTATE_SET_TEXENV_I(texture.unit[i].combineSourceRGB[2], GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB);
+ CRSTATE_SET_TEXENV_I(texture.unit[i].combineSourceA[0], GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB);
+ CRSTATE_SET_TEXENV_I(texture.unit[i].combineSourceA[1], GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB);
+ CRSTATE_SET_TEXENV_I(texture.unit[i].combineSourceA[2], GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB);
+ CRSTATE_SET_TEXENV_I(texture.unit[i].combineOperandRGB[0], GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB);
+ CRSTATE_SET_TEXENV_I(texture.unit[i].combineOperandRGB[1], GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB);
+ CRSTATE_SET_TEXENV_I(texture.unit[i].combineOperandRGB[2], GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB);
+ CRSTATE_SET_TEXENV_I(texture.unit[i].combineOperandA[0], GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB);
+ CRSTATE_SET_TEXENV_I(texture.unit[i].combineOperandA[1], GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB);
+ CRSTATE_SET_TEXENV_I(texture.unit[i].combineOperandA[2], GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB);
+ CRSTATE_SET_TEXENV_F(texture.unit[i].combineScaleRGB, GL_TEXTURE_ENV, GL_RGB_SCALE_ARB);
+ CRSTATE_SET_TEXENV_F(texture.unit[i].combineScaleA, GL_TEXTURE_ENV, GL_ALPHA_SCALE);
+ }
+ }
+ if (activeUnit!=g->texture.curTextureUnit)
+ {
+ diff_api.ActiveTextureARB(g->texture.curTextureUnit + GL_TEXTURE0_ARB);
+ }
+ }
+
+ if (CHECKDIRTY(sb->lighting.dirty, negbitID))
+ {
+ int i;
+
+ if (CHECKDIRTY(sb->lighting.enable, negbitID))
+ {
+ CRSTATE_SET_ENABLED(lighting.lighting, GL_LIGHTING);
+ CRSTATE_SET_ENABLED(lighting.colorMaterial, GL_COLOR_MATERIAL);
+ CRSTATE_SET_ENABLED(lighting.colorSumEXT, GL_COLOR_SUM_EXT);
+ }
+
+ if (CHECKDIRTY(sb->lighting.shadeModel, negbitID))
+ {
+ CRSTATE_SET_ENUM(lighting.shadeModel, GL_SHADE_MODEL);
+ }
+
+ if (CHECKDIRTY(sb->lighting.colorMaterial, negbitID))
+ {
+ CRSTATE_SET_ENUM(lighting.colorMaterialFace, GL_COLOR_MATERIAL_FACE);
+ CRSTATE_SET_ENUM(lighting.colorMaterialMode, GL_COLOR_MATERIAL_PARAMETER);
+ }
+
+ if (CHECKDIRTY(sb->lighting.lightModel, negbitID))
+ {
+ CRSTATE_SET_COLORF(lighting.lightModelAmbient, GL_LIGHT_MODEL_AMBIENT);
+ CRSTATE_SET_BOOL(lighting.lightModelLocalViewer, GL_LIGHT_MODEL_LOCAL_VIEWER);
+ CRSTATE_SET_BOOL(lighting.lightModelTwoSide, GL_LIGHT_MODEL_TWO_SIDE);
+ CRSTATE_SET_ENUM(lighting.lightModelColorControlEXT, GL_LIGHT_MODEL_COLOR_CONTROL);
+ }
+
+ if (CHECKDIRTY(sb->lighting.material, negbitID))
+ {
+ 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_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);
+ }
+
+ for (i=0; i<CR_MAX_LIGHTS; ++i)
+ {
+ if (CHECKDIRTY(sb->lighting.light[i].dirty, negbitID))
+ {
+ if (CHECKDIRTY(sb->lighting.light[i].enable, negbitID))
+ {
+ CRSTATE_SET_ENABLED(lighting.light[i].enable, GL_LIGHT0+i);
+ }
+
+ if (CHECKDIRTY(sb->lighting.light[i].ambient, negbitID))
+ {
+ CRSTATE_SET_LIGHT_COLOR(lighting.light[i].ambient, GL_LIGHT0+i, GL_AMBIENT);
+ }
+
+ if (CHECKDIRTY(sb->lighting.light[i].diffuse, negbitID))
+ {
+ CRSTATE_SET_LIGHT_COLOR(lighting.light[i].diffuse, GL_LIGHT0+i, GL_DIFFUSE);
+ }
+
+ if (CHECKDIRTY(sb->lighting.light[i].specular, negbitID))
+ {
+ CRSTATE_SET_LIGHT_COLOR(lighting.light[i].specular, GL_LIGHT0+i, GL_SPECULAR);
+ }
+
+ if (CHECKDIRTY(sb->lighting.light[i].position, negbitID))
+ {
+ CRSTATE_SET_LIGHT_4F(lighting.light[i].position, GL_LIGHT0+i, GL_POSITION);
+ }
+
+ if (CHECKDIRTY(sb->lighting.light[i].attenuation, negbitID))
+ {
+ CRSTATE_SET_LIGHT_F(lighting.light[i].constantAttenuation, GL_LIGHT0+i, GL_CONSTANT_ATTENUATION);
+ CRSTATE_SET_LIGHT_F(lighting.light[i].linearAttenuation, GL_LIGHT0+i, GL_LINEAR_ATTENUATION);
+ CRSTATE_SET_LIGHT_F(lighting.light[i].quadraticAttenuation, GL_LIGHT0+i, GL_QUADRATIC_ATTENUATION);
+ }
+
+ if (CHECKDIRTY(sb->lighting.light[i].spot, negbitID))
+ {
+ CRSTATE_SET_LIGHT_3F(lighting.light[i].spotDirection, GL_LIGHT0+i, GL_SPOT_DIRECTION);
+ CRSTATE_SET_LIGHT_F(lighting.light[i].spotExponent, GL_LIGHT0+i, GL_SPOT_EXPONENT);
+ CRSTATE_SET_LIGHT_F(lighting.light[i].spotCutoff, GL_LIGHT0+i, GL_SPOT_CUTOFF);
+ }
+ }
+ }
+ }
+
+
+ if (CHECKDIRTY(sb->transform.dirty, negbitID))
+ {
+ if (CHECKDIRTY(sb->transform.enable, negbitID))
+ {
+ CRSTATE_SET_ENABLED(transform.normalize, GL_NORMALIZE);
+#ifdef CR_OPENGL_VERSION_1_2
+ CRSTATE_SET_ENABLED(transform.rescaleNormals, GL_RESCALE_NORMAL);
+#endif
+#ifdef CR_IBM_rasterpos_clip
+ CRSTATE_SET_ENABLED(transform.rasterPositionUnclipped, GL_RASTER_POSITION_UNCLIPPED_IBM);
+#endif
+ }
+
+ if (CHECKDIRTY(sb->transform.clipPlane, negbitID))
+ {
+ int i;
+ for (i=0; i<CR_MAX_CLIP_PLANES; i++)
+ {
+ CRSTATE_SET_CLIPPLANE_4D(transform.clipPlane[i], GL_CLIP_PLANE0+i);
+ }
+ }
+
+ if (CHECKDIRTY(sb->transform.modelviewMatrix, negbitID))
+ {
+ CRSTATE_SET_MATRIX(transform.modelViewStack.top, GL_MODELVIEW_MATRIX);
+ }
+
+ if (CHECKDIRTY(sb->transform.projectionMatrix, negbitID))
+ {
+ CRSTATE_SET_MATRIX(transform.projectionStack.top, GL_PROJECTION_MATRIX);
+ }
+
+ if (CHECKDIRTY(sb->transform.textureMatrix, negbitID))
+ {
+ unsigned int i;
+ for (i=0; i<g->limits.maxTextureUnits; i++)
+ {
+ diff_api.ActiveTextureARB(GL_TEXTURE0_ARB+i);
+ CRSTATE_SET_MATRIX(transform.textureStack[i].top, GL_TEXTURE_MATRIX);
+ }
+ diff_api.ActiveTextureARB(g->texture.curTextureUnit + GL_TEXTURE0_ARB);
+ }
+
+ if (CHECKDIRTY(sb->transform.colorMatrix, negbitID))
+ {
+ CRSTATE_SET_MATRIX(transform.colorStack.top, GL_COLOR_MATRIX);
+ }
+
+ if (CHECKDIRTY(sb->transform.matrixMode, negbitID))
+ {
+ CRSTATE_SET_ENUM(transform.matrixMode, GL_MATRIX_MODE);
+ }
+ }
+
+ if (CHECKDIRTY(sb->viewport.dirty, negbitID))
+ {
+ if (CHECKDIRTY(sb->viewport.enable, negbitID))
+ {
+ CRSTATE_SET_ENABLED(viewport.scissorTest, GL_SCISSOR_TEST);
+ }
+
+ if (CHECKDIRTY(sb->viewport.s_dims, negbitID))
+ {
+ GLint value[4];
+ value[0] = g->viewport.scissorX;
+ value[1] = g->viewport.scissorY;
+ value[2] = g->viewport.scissorW;
+ value[3] = g->viewport.scissorH;
+ diff_api.GetIntegerv(GL_SCISSOR_BOX, &value[0]);
+ CRSTATE_SET_CAP(viewport.scissorX, value[0], "%i");
+ CRSTATE_SET_CAP(viewport.scissorY, value[1], "%i");
+ CRSTATE_SET_CAP(viewport.scissorW, value[2], "%i");
+ CRSTATE_SET_CAP(viewport.scissorH, value[3], "%i");
+ }
+
+ if (CHECKDIRTY(sb->viewport.v_dims, negbitID))
+ {
+ GLint value[4];
+ value[0] = g->viewport.viewportX;
+ value[1] = g->viewport.viewportY;
+ value[2] = g->viewport.viewportW;
+ value[3] = g->viewport.viewportH;
+ diff_api.GetIntegerv(GL_VIEWPORT, &value[0]);
+ CRSTATE_SET_CAP(viewport.viewportX, value[0], "%i");
+ CRSTATE_SET_CAP(viewport.viewportY, value[1], "%i");
+ CRSTATE_SET_CAP(viewport.viewportW, value[2], "%i");
+ CRSTATE_SET_CAP(viewport.viewportH, value[3], "%i");
+ }
+
+ if (CHECKDIRTY(sb->viewport.depth, negbitID))
+ {
+ GLfloat value[2];
+ value[0] = g->viewport.nearClip;
+ value[1] = g->viewport.farClip;
+ diff_api.GetFloatv(GL_DEPTH_RANGE, &value[0]);
+ CRSTATE_SET_CAP(viewport.nearClip, value[0], "%f");
+ CRSTATE_SET_CAP(viewport.farClip, value[1], "%f");
+ }
+ }
+
+ if (CHECKDIRTY(sb->eval.dirty, negbitID))
+ {
+ int i;
+ const int gleval_sizes_dup[] = {4, 1, 3, 1, 2, 3, 4, 3, 4};
+
+ if (CHECKDIRTY(sb->eval.enable, negbitID))
+ {
+ CRSTATE_SET_ENABLED(eval.autoNormal, GL_AUTO_NORMAL);
+ }
+
+ for (i=0; i<GLEVAL_TOT; i++)
+ {
+ if (CHECKDIRTY(sb->eval.enable1D[i], negbitID))
+ {
+ CRSTATE_SET_ENABLED(eval.enable1D[i], i + GL_MAP1_COLOR_4);
+ }
+
+ if (CHECKDIRTY(sb->eval.enable2D[i], negbitID))
+ {
+ CRSTATE_SET_ENABLED(eval.enable2D[i], i + GL_MAP2_COLOR_4);
+ }
+
+ if (CHECKDIRTY(sb->eval.eval1D[i], negbitID) && g->eval.enable1D[i])
+ {
+ GLfloat *coeffs=NULL;
+ GLint order;
+ GLfloat uval[2];
+ order = g->eval.eval1D[i].order;
+ uval[0] = g->eval.eval1D[i].u1;
+ uval[1] = g->eval.eval1D[i].u2;
+ diff_api.GetMapiv(i + GL_MAP1_COLOR_4, GL_ORDER, &order);
+ diff_api.GetMapfv(i + GL_MAP1_COLOR_4, GL_DOMAIN, &uval[0]);
+ if (order>0)
+ {
+ coeffs = crAlloc(order * gleval_sizes_dup[i] * sizeof(GLfloat));
+ if (!coeffs)
+ {
+ crWarning("crStateQueryHWState: out of memory, at eval1D[%i]", i);
+ continue;
+ }
+ diff_api.GetMapfv(i + GL_MAP1_COLOR_4, GL_COEFF, coeffs);
+ }
+
+ CRSTATE_SET_CAP(eval.eval1D[i].order, order, "%i");
+ CRSTATE_SET_CAP(eval.eval1D[i].u1, uval[0], "%f");
+ CRSTATE_SET_CAP(eval.eval1D[i].u2, uval[1], "%f");
+ if (g->eval.eval1D[i].coeff)
+ {
+ crFree(g->eval.eval1D[i].coeff);
+ }
+ g->eval.eval1D[i].coeff = coeffs;
+
+ if (uval[0]!=uval[1])
+ {
+ g->eval.eval1D[i].du = 1.0f / (uval[0] - uval[1]);
+ }
+ }
+
+ if (CHECKDIRTY(sb->eval.eval2D[i], negbitID) && g->eval.enable2D[i])
+ {
+ GLfloat *coeffs=NULL;
+ GLint order[2];
+ GLfloat uval[4];
+ order[0] = g->eval.eval2D[i].uorder;
+ order[1] = g->eval.eval2D[i].vorder;
+ uval[0] = g->eval.eval2D[i].u1;
+ uval[1] = g->eval.eval2D[i].u2;
+ uval[2] = g->eval.eval2D[i].v1;
+ uval[3] = g->eval.eval2D[i].v2;
+ diff_api.GetMapiv(i + GL_MAP2_COLOR_4, GL_ORDER, &order[0]);
+ diff_api.GetMapfv(i + GL_MAP2_COLOR_4, GL_DOMAIN, &uval[0]);
+ if (order[0]>0 && order[1]>0)
+ {
+ coeffs = crAlloc(order[0] * order[1] * gleval_sizes_dup[i] * sizeof(GLfloat));
+ if (!coeffs)
+ {
+ crWarning("crStateQueryHWState: out of memory, at eval2D[%i]", i);
+ continue;
+ }
+ diff_api.GetMapfv(i + GL_MAP1_COLOR_4, GL_COEFF, coeffs);
+ }
+ CRSTATE_SET_CAP(eval.eval2D[i].uorder, order[0], "%i");
+ CRSTATE_SET_CAP(eval.eval2D[i].vorder, order[1], "%i");
+ CRSTATE_SET_CAP(eval.eval2D[i].u1, uval[0], "%f");
+ CRSTATE_SET_CAP(eval.eval2D[i].u2, uval[1], "%f");
+ CRSTATE_SET_CAP(eval.eval2D[i].v1, uval[2], "%f");
+ CRSTATE_SET_CAP(eval.eval2D[i].v2, uval[3], "%f");
+ if (g->eval.eval2D[i].coeff)
+ {
+ crFree(g->eval.eval2D[i].coeff);
+ }
+ g->eval.eval2D[i].coeff = coeffs;
+
+ if (uval[0]!=uval[1])
+ {
+ g->eval.eval2D[i].du = 1.0f / (uval[0] - uval[1]);
+ }
+ if (uval[2]!=uval[3])
+ {
+ g->eval.eval2D[i].dv = 1.0f / (uval[2] - uval[3]);
+ }
+ }
+ }
+
+ if (CHECKDIRTY(sb->eval.grid1D, negbitID))
+ {
+ GLfloat value[2];
+ CRSTATE_SET_INT(eval.un1D, GL_MAP1_GRID_SEGMENTS);
+ value[0] = g->eval.u11D;
+ value[1] = g->eval.u21D;
+ diff_api.GetFloatv(GL_MAP1_GRID_DOMAIN, &value[0]);
+ CRSTATE_SET_CAP(eval.u11D, value[0], "%f");
+ CRSTATE_SET_CAP(eval.u21D, value[1], "%f");
+ }
+
+ if (CHECKDIRTY(sb->eval.grid2D, negbitID))
+ {
+ GLint iv[2];
+ GLfloat value[4];
+ iv[0] = g->eval.un2D;
+ iv[1] = g->eval.vn2D;
+ diff_api.GetIntegerv(GL_MAP1_GRID_SEGMENTS, &iv[0]);
+ CRSTATE_SET_CAP(eval.un2D, iv[0], "%i");
+ CRSTATE_SET_CAP(eval.vn2D, iv[1], "%i");
+ value[0] = g->eval.u12D;
+ value[1] = g->eval.u22D;
+ value[2] = g->eval.v12D;
+ value[3] = g->eval.v22D;
+ diff_api.GetFloatv(GL_MAP2_GRID_DOMAIN, &value[0]);
+ CRSTATE_SET_CAP(eval.u12D, value[0], "%f");
+ CRSTATE_SET_CAP(eval.u22D, value[1], "%f");
+ CRSTATE_SET_CAP(eval.v12D, value[2], "%f");
+ CRSTATE_SET_CAP(eval.v22D, value[3], "%f");
+ }
+ }
+
+ if (CHECKDIRTY(sb->fog.dirty, negbitID))
+ {
+ if (CHECKDIRTY(sb->fog.enable, negbitID))
+ {
+ CRSTATE_SET_ENABLED(fog.enable, GL_FOG);
+ }
+
+ if (CHECKDIRTY(sb->fog.color, negbitID))
+ {
+ CRSTATE_SET_COLORF(fog.color, GL_FOG_COLOR);
+ }
+
+ if (CHECKDIRTY(sb->fog.index, negbitID))
+ {
+ CRSTATE_SET_INT(fog.index, GL_FOG_INDEX);
+ }
+
+ if (CHECKDIRTY(sb->fog.density, negbitID))
+ {
+ CRSTATE_SET_FLOAT(fog.density, GL_FOG_DENSITY);
+ }
+
+ if (CHECKDIRTY(sb->fog.start, negbitID))
+ {
+ CRSTATE_SET_FLOAT(fog.start, GL_FOG_START);
+ }
+
+ if (CHECKDIRTY(sb->fog.end, negbitID))
+ {
+ CRSTATE_SET_FLOAT(fog.end, GL_FOG_END);
+ }
+
+ if (CHECKDIRTY(sb->fog.mode, negbitID))
+ {
+ CRSTATE_SET_INT(fog.mode, GL_FOG_MODE);
+ }
+
+#ifdef CR_NV_fog_distance
+ if (CHECKDIRTY(sb->fog.fogDistanceMode, negbitID))
+ {
+ CRSTATE_SET_ENUM(fog.fogDistanceMode, GL_FOG_DISTANCE_MODE_NV);
+ }
+#endif
+#ifdef CR_EXT_fog_coord
+ if (CHECKDIRTY(sb->fog.fogCoordinateSource, negbitID))
+ {
+ CRSTATE_SET_ENUM(fog.fogCoordinateSource, GL_FOG_COORDINATE_SOURCE_EXT);
+ }
+#endif
+ }
+
+ if (CHECKDIRTY(sb->hint.dirty, negbitID))
+ {
+ if (CHECKDIRTY(sb->hint.perspectiveCorrection, negbitID))
+ {
+ CRSTATE_SET_ENUM(hint.perspectiveCorrection, GL_PERSPECTIVE_CORRECTION_HINT);
+ }
+
+ if (CHECKDIRTY(sb->hint.pointSmooth, negbitID))
+ {
+ CRSTATE_SET_ENUM(hint.pointSmooth, GL_POINT_SMOOTH_HINT);
+ }
+
+ if (CHECKDIRTY(sb->hint.lineSmooth, negbitID))
+ {
+ CRSTATE_SET_ENUM(hint.lineSmooth, GL_LINE_SMOOTH_HINT);
+ }
+
+ if (CHECKDIRTY(sb->hint.polygonSmooth, negbitID))
+ {
+ CRSTATE_SET_ENUM(hint.polygonSmooth, GL_POINT_SMOOTH_HINT);
+ }
+
+ if (CHECKDIRTY(sb->hint.fog, negbitID))
+ {
+ CRSTATE_SET_ENUM(hint.fog, GL_FOG_HINT);
+ }
+
+#ifdef CR_EXT_clip_volume_hint
+ if (CHECKDIRTY(sb->hint.clipVolumeClipping, negbitID))
+ {
+ CRSTATE_SET_ENUM(hint.clipVolumeClipping, GL_CLIP_VOLUME_CLIPPING_HINT_EXT);
+ }
+#endif
+#ifdef CR_ARB_texture_compression
+ if (CHECKDIRTY(sb->hint.textureCompression, negbitID))
+ {
+ CRSTATE_SET_ENUM(hint.textureCompression, GL_TEXTURE_COMPRESSION_HINT_ARB);
+ }
+#endif
+#ifdef CR_SGIS_generate_mipmap
+ if (CHECKDIRTY(sb->hint.generateMipmap, negbitID))
+ {
+ CRSTATE_SET_ENUM(hint.generateMipmap, GL_GENERATE_MIPMAP_HINT_SGIS);
+ }
+#endif
+ }
+
+ if (CHECKDIRTY(sb->line.dirty, negbitID))
+ {
+ if (CHECKDIRTY(sb->line.enable, negbitID))
+ {
+ CRSTATE_SET_ENABLED(line.lineSmooth, GL_LINE_SMOOTH);
+ CRSTATE_SET_ENABLED(line.lineStipple, GL_LINE_STIPPLE);
+ }
+
+ if (CHECKDIRTY(sb->line.width, negbitID))
+ {
+ CRSTATE_SET_FLOAT(line.width, GL_LINE_WIDTH);
+ }
+
+ if (CHECKDIRTY(sb->line.stipple, negbitID))
+ {
+ CRSTATE_SET_INT(line.repeat, GL_LINE_STIPPLE_REPEAT);
+ CRSTATE_SET_INT(line.pattern, GL_LINE_STIPPLE_PATTERN);
+ }
+ }
+
+ if (CHECKDIRTY(sb->multisample.dirty, negbitID))
+ {
+ if (CHECKDIRTY(sb->multisample.enable, negbitID))
+ {
+ CRSTATE_SET_ENABLED(multisample.enabled, GL_MULTISAMPLE_ARB);
+ CRSTATE_SET_ENABLED(multisample.sampleAlphaToCoverage, GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);
+ CRSTATE_SET_ENABLED(multisample.sampleAlphaToOne, GL_SAMPLE_ALPHA_TO_ONE_ARB);
+ CRSTATE_SET_ENABLED(multisample.sampleCoverage, GL_SAMPLE_COVERAGE_ARB);
+ }
+
+ if (CHECKDIRTY(sb->multisample.sampleCoverageValue, negbitID))
+ {
+ CRSTATE_SET_FLOAT(multisample.sampleCoverageValue, GL_SAMPLE_COVERAGE_VALUE_ARB)
+ CRSTATE_SET_BOOL(multisample.sampleCoverageInvert, GL_SAMPLE_COVERAGE_INVERT_ARB)
+ }
+ }
+
+ if (CHECKDIRTY(sb->point.dirty, negbitID))
+ {
+ if (CHECKDIRTY(sb->point.enableSmooth, negbitID))
+ {
+ CRSTATE_SET_ENABLED(point.pointSmooth, GL_POINT_SMOOTH);
+ }
+
+ if (CHECKDIRTY(sb->point.size, negbitID))
+ {
+ CRSTATE_SET_FLOAT(point.pointSize, GL_POINT_SIZE);
+ }
+
+#ifdef CR_ARB_point_parameters
+ if (CHECKDIRTY(sb->point.minSize, negbitID))
+ {
+ CRSTATE_SET_FLOAT(point.minSize, GL_POINT_SIZE_MIN_ARB);
+ }
+
+ if (CHECKDIRTY(sb->point.maxSize, negbitID))
+ {
+ CRSTATE_SET_FLOAT(point.maxSize, GL_POINT_SIZE_MAX_ARB);
+ }
+
+ if (CHECKDIRTY(sb->point.fadeThresholdSize, negbitID))
+ {
+ CRSTATE_SET_FLOAT(point.fadeThresholdSize, GL_POINT_FADE_THRESHOLD_SIZE_ARB);
+ }
+
+ if (CHECKDIRTY(sb->point.distanceAttenuation, negbitID))
+ {
+ GLfloat value[3];
+ value[0] = g->point.distanceAttenuation[0];
+ value[1] = g->point.distanceAttenuation[1];
+ value[2] = g->point.distanceAttenuation[2];
+ diff_api.GetFloatv(GL_POINT_DISTANCE_ATTENUATION, &value[0]);
+ CRSTATE_SET_CAP(point.distanceAttenuation[0], value[0], "%f");
+ CRSTATE_SET_CAP(point.distanceAttenuation[1], value[1], "%f");
+ CRSTATE_SET_CAP(point.distanceAttenuation[2], value[2], "%f");
+ }
+#endif
+#ifdef CR_ARB_point_sprite
+ if (CHECKDIRTY(sb->point.enableSprite, negbitID))
+ {
+ CRSTATE_SET_ENABLED(point.pointSprite, GL_POINT_SPRITE_ARB);
+ }
+
+ {
+ unsigned int i, activeUnit = g->texture.curTextureUnit;
+ for (i=0; i<g->limits.maxTextureUnits; ++i)
+ {
+ if (CHECKDIRTY(sb->point.coordReplacement[i], negbitID))
+ {
+ GLint val=g->point.coordReplacement[i];
+ if (activeUnit!=i)
+ {
+ diff_api.ActiveTextureARB(i + GL_TEXTURE0_ARB);
+ activeUnit=i;
+ }
+ diff_api.GetTexEnviv(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, &val);
+ CRSTATE_SET_CAP(point.coordReplacement[i], val, "%i");
+ }
+ }
+
+ if (activeUnit!=g->texture.curTextureUnit)
+ {
+ diff_api.ActiveTextureARB(g->texture.curTextureUnit + GL_TEXTURE0_ARB);
+ }
+ }
+#endif
+ }
+
+ if (CHECKDIRTY(sb->polygon.dirty, negbitID))
+ {
+ if (CHECKDIRTY(sb->polygon.enable, negbitID))
+ {
+ CRSTATE_SET_ENABLED(polygon.polygonSmooth, GL_POLYGON_SMOOTH);
+ CRSTATE_SET_ENABLED(polygon.polygonOffsetFill, GL_POLYGON_OFFSET_FILL);
+ CRSTATE_SET_ENABLED(polygon.polygonOffsetLine, GL_POLYGON_OFFSET_LINE);
+ CRSTATE_SET_ENABLED(polygon.polygonOffsetPoint, GL_POLYGON_OFFSET_POINT);
+ CRSTATE_SET_ENABLED(polygon.polygonStipple, GL_POLYGON_STIPPLE);
+ CRSTATE_SET_ENABLED(polygon.cullFace, GL_CULL_FACE);
+ }
+
+ if (CHECKDIRTY(sb->polygon.offset, negbitID))
+ {
+ CRSTATE_SET_FLOAT(polygon.offsetFactor, GL_POLYGON_OFFSET_FACTOR);
+ CRSTATE_SET_FLOAT(polygon.offsetUnits, GL_POLYGON_OFFSET_UNITS);
+ }
+
+ if (CHECKDIRTY(sb->polygon.mode, negbitID))
+ {
+ GLint val[2];
+ CRSTATE_SET_ENUM(polygon.frontFace, GL_FRONT_FACE);
+ CRSTATE_SET_ENUM(polygon.cullFaceMode, GL_CULL_FACE_MODE);
+ val[0] = g->polygon.frontMode;
+ val[1] = g->polygon.backMode;
+ diff_api.GetIntegerv(GL_POLYGON_MODE, &val[0]);
+ CRSTATE_SET_CAP(polygon.frontMode, val[0], "%#x");
+ CRSTATE_SET_CAP(polygon.backMode, val[1], "%#x");
+
+
+ }
+
+ if (CHECKDIRTY(sb->polygon.stipple, negbitID))
+ {
+ GLint stipple[32];
+ crMemcpy(&stipple[0], &g->polygon.stipple[0], sizeof(stipple));
+ diff_api.GetPolygonStipple((GLubyte*) &stipple[0]);
+ if (crMemcmp(&stipple[0], &g->polygon.stipple[0], sizeof(stipple)))
+ {
+#ifdef CRSTATE_DEBUG_QUERY_HW_STATE
+ {
+ crDebug("crStateQueryHWState fixed polygon.stipple");
+ }
+#endif
+ crMemcpy(&g->polygon.stipple[0], &stipple[0], sizeof(stipple));
+ }
+ }
+ }
+
+ CR_STATE_CLEAN_HW_ERR_WARN("error on hw sync");
+}
+
+void STATE_APIENTRY crStateNewList (GLuint list, GLenum mode)
+{
+ CRContext *g = GetCurrentContext();
+ CRListsState *l = &(g->lists);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glNewList called in Begin/End");
+ return;
+ }
+
+ if (list == 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glNewList(list=0)");
+ return;
+ }
+
+ if (l->currentIndex)
+ {
+ /* already building a list */
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glNewList called inside display list");
+ return;
+ }
+
+ if (mode != GL_COMPILE && mode != GL_COMPILE_AND_EXECUTE)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glNewList invalid mode");
+ return;
+ }
+
+ FLUSH();
+
+ /* Must log that this key is used */
+ if (!crHashtableIsKeyUsed(g->shared->dlistTable, list)) {
+ crHashtableAdd(g->shared->dlistTable, list, NULL);
+ }
+
+ /* Need this???
+ crStateCurrentRecover();
+ */
+
+ l->currentIndex = list;
+ l->mode = mode;
+}
+
+void STATE_APIENTRY crStateEndList (void)
+{
+ CRContext *g = GetCurrentContext();
+ CRListsState *l = &(g->lists);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glEndList called in Begin/End");
+ return;
+ }
+
+ if (!l->currentIndex)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glEndList called outside display list");
+ return;
+ }
+
+ l->currentIndex = 0;
+ l->mode = 0;
+}
+
+GLuint STATE_APIENTRY crStateGenLists(GLsizei range)
+{
+ CRContext *g = GetCurrentContext();
+ GLuint start;
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glGenLists called in Begin/End");
+ return 0;
+ }
+
+ if (range < 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Negative range passed to glGenLists: %d", range);
+ return 0;
+ }
+
+ start = crHashtableAllocKeys(g->shared->dlistTable, range);
+
+ CRASSERT(start > 0);
+ return start;
+}
+
+void STATE_APIENTRY crStateDeleteLists (GLuint list, GLsizei range)
+{
+ CRContext *g = GetCurrentContext();
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glDeleteLists called in Begin/End");
+ return;
+ }
+
+ if (range < 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Negative range passed to glDeleteLists: %d", range);
+ return;
+ }
+
+ crHashtableDeleteBlock(g->shared->dlistTable, list, range, crFree); /* call crFree to delete list data */
+}
+
+GLboolean STATE_APIENTRY crStateIsList(GLuint list)
+{
+ CRContext *g = GetCurrentContext();
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "GenLists called in Begin/End");
+ return GL_FALSE;
+ }
+
+ if (list == 0)
+ return GL_FALSE;
+
+ return crHashtableIsKeyUsed(g->shared->dlistTable, list);
+}
+
+void STATE_APIENTRY crStateListBase (GLuint base)
+{
+ CRContext *g = GetCurrentContext();
+ CRListsState *l = &(g->lists);
+ CRStateBits *sb = GetCurrentBits();
+ CRListsBits *lb = &(sb->lists);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "ListBase called in Begin/End");
+ return;
+ }
+
+ l->base = base;
+
+ DIRTY(lb->base, g->neg_bitid);
+ DIRTY(lb->dirty, g->neg_bitid);
+}
+
+
+void
+crStateListsDiff( CRListsBits *b, CRbitvalue *bitID,
+ CRContext *fromCtx, CRContext *toCtx )
+{
+ CRListsState *from = &(fromCtx->lists);
+ CRListsState *to = &(toCtx->lists);
+ unsigned int j;
+ CRbitvalue nbitID[CR_MAX_BITARRAY];
+
+ for (j=0;j<CR_MAX_BITARRAY;j++)
+ nbitID[j] = ~bitID[j];
+
+ if (CHECKDIRTY(b->base, bitID))
+ {
+ if (from->base != to->base) {
+ diff_api.ListBase(to->base);
+ from->base = to->base;
+ }
+ CLEARDIRTY(b->base, nbitID);
+ }
+
+ CLEARDIRTY(b->dirty, nbitID);
+}
+
+
+void
+crStateListsSwitch( CRListsBits *b, CRbitvalue *bitID,
+ CRContext *fromCtx, CRContext *toCtx )
+{
+ CRListsState *from = &(fromCtx->lists);
+ CRListsState *to = &(toCtx->lists);
+ unsigned int j;
+ CRbitvalue nbitID[CR_MAX_BITARRAY];
+
+ for (j=0;j<CR_MAX_BITARRAY;j++)
+ nbitID[j] = ~bitID[j];
+
+ if (CHECKDIRTY(b->base, bitID))
+ {
+ if (from->base != to->base) {
+ diff_api.ListBase(to->base);
+ FILLDIRTY(b->base);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->base, nbitID);
+ }
+
+ CLEARDIRTY(b->dirty, nbitID);
+}
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_multisample.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_multisample.c
new file mode 100644
index 00000000..3b7dba5b
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_multisample.c
@@ -0,0 +1,51 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#include <stdio.h>
+#include "state.h"
+#include "state/cr_statetypes.h"
+#include "state_internals.h"
+
+void crStateMultisampleInit (CRContext *ctx)
+{
+ CRMultisampleState *m = &ctx->multisample;
+ CRStateBits *sb = GetCurrentBits();
+ CRMultisampleBits *mb = &(sb->multisample);
+
+ m->enabled = GL_FALSE; /* TRUE if the visual supports it */
+ m->sampleAlphaToCoverage = GL_FALSE;
+ m->sampleAlphaToOne = GL_FALSE;
+ m->sampleCoverage = GL_FALSE;
+ RESET(mb->enable, ctx->bitid);
+
+ m->sampleCoverageValue = 1.0F;
+ m->sampleCoverageInvert = GL_FALSE;
+ RESET(mb->sampleCoverageValue, ctx->bitid);
+
+ RESET(mb->dirty, ctx->bitid);
+}
+
+void STATE_APIENTRY crStateSampleCoverageARB(GLclampf value, GLboolean invert)
+{
+ CRContext *g = GetCurrentContext();
+ CRMultisampleState *m = &(g->multisample);
+ CRStateBits *sb = GetCurrentBits();
+ CRMultisampleBits *mb = &(sb->multisample);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glStateSampleCoverageARB called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ m->sampleCoverageValue = value;
+ m->sampleCoverageInvert = invert;
+ DIRTY(mb->dirty, g->neg_bitid);
+ DIRTY(mb->sampleCoverageValue, g->neg_bitid);
+}
+
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_multisample.txt b/src/VBox/GuestHost/OpenGL/state_tracker/state_multisample.txt
new file mode 100644
index 00000000..a0ed8bcf
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_multisample.txt
@@ -0,0 +1,9 @@
+# Copyright (c) 2001, Stanford University
+# All rights reserved.
+#
+# See the file LICENSE.txt for information on redistributing this software.
+:enable:enabled:GL_MULTISAMPLE_ARB
+:enable:sampleAlphaToCoverage:GL_SAMPLE_ALPHA_TO_COVERAGE_ARB
+:enable:sampleAlphaToOne:GL_SAMPLE_ALPHA_TO_ONE_ARB
+:enable:sampleCoverage:GL_SAMPLE_COVERAGE_ARB
+enabled:sampleCoverageValue:sampleCoverageValue,sampleCoverageInvert:SampleCoverageARB
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_occlude.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_occlude.c
new file mode 100644
index 00000000..7249e908
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_occlude.c
@@ -0,0 +1,354 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#include "state.h"
+#include "state/cr_statetypes.h"
+#include "state/cr_statefuncs.h"
+#include "state_internals.h"
+#include "cr_mem.h"
+
+#if !defined(IN_GUEST)
+#include "cr_unpack.h"
+#endif
+
+void
+crStateOcclusionInit(CRContext *ctx)
+{
+ CROcclusionState *o = &ctx->occlusion;
+
+ o->objects = crAllocHashtable();
+ o->currentQueryObject = 0;
+}
+
+
+void
+crStateOcclusionDestroy(CRContext *ctx)
+{
+ CROcclusionState *o = &(ctx->occlusion);
+ crFreeHashtable(o->objects, crFree);
+}
+
+
+static CROcclusionObject *
+NewQueryObject(GLenum target, GLuint id)
+{
+ CROcclusionObject *q = (CROcclusionObject *) crAlloc(sizeof(CROcclusionObject));
+ if (q) {
+ q->target = target;
+ q->name = id;
+ q->passedCounter = 0;
+ q->active = GL_FALSE;
+ }
+ return q;
+}
+
+
+void STATE_APIENTRY
+crStateDeleteQueriesARB(GLsizei n, const GLuint *ids)
+{
+ CRContext *g = GetCurrentContext();
+ CROcclusionState *o = &(g->occlusion);
+ /*CRStateBits *sb = GetCurrentBits();*/
+ /*CROcclusionBits *bb = &(sb->occlusion);*/
+ int i;
+
+ FLUSH();
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glDeleteQueriesARB called in Begin/End");
+ return;
+ }
+
+ if (n <= 0 || n >= (GLsizei)(INT32_MAX / sizeof(GLuint)))
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glDeleteQueriesARB: parameter 'n' is out of range");
+ return;
+ }
+
+#if !defined(IN_GUEST)
+ if (!DATA_POINTER_CHECK(n * sizeof(GLuint)))
+ {
+ crError("glDeleteQueriesARB: parameter 'n' is out of range");
+ return;
+ }
+#endif
+
+ for (i = 0; i < n; i++) {
+ if (ids[i]) {
+ CROcclusionObject *q = (CROcclusionObject *)
+ crHashtableSearch(o->objects, ids[i]);
+ if (q) {
+ crHashtableDelete(o->objects, ids[i], crFree);
+ }
+ }
+ }
+}
+
+
+void STATE_APIENTRY
+crStateGenQueriesARB(GLsizei n, GLuint * queries)
+{
+ CRContext *g = GetCurrentContext();
+ CROcclusionState *o = &(g->occlusion);
+ GLint start;
+
+ FLUSH();
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGenQueriesARB called in Begin/End");
+ return;
+ }
+
+ if (n < 0) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glGenQueriesARB(n < 0)");
+ return;
+ }
+
+ start = crHashtableAllocKeys(o->objects, n);
+ if (start) {
+ GLint i;
+ for (i = 0; i < n; i++)
+ queries[i] = (GLuint) (start + i);
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, "glGenQueriesARB");
+ }
+}
+
+
+GLboolean STATE_APIENTRY
+crStateIsQueryARB(GLuint id)
+{
+ CRContext *g = GetCurrentContext();
+ CROcclusionState *o = &(g->occlusion);
+
+ FLUSH();
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glIsQueryARB called in begin/end");
+ return GL_FALSE;
+ }
+
+ if (id && crHashtableIsKeyUsed(o->objects, id))
+ return GL_TRUE;
+ else
+ return GL_FALSE;
+}
+
+
+void STATE_APIENTRY
+crStateGetQueryivARB(GLenum target, GLenum pname, GLint *params)
+{
+ CRContext *g = GetCurrentContext();
+ CROcclusionState *o = &(g->occlusion);
+ (void)target;
+
+ FLUSH();
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetGetQueryivARB called in begin/end");
+ return;
+ }
+
+ switch (pname) {
+ case GL_QUERY_COUNTER_BITS_ARB:
+ *params = 8 * sizeof(GLuint);
+ break;
+ case GL_CURRENT_QUERY_ARB:
+ *params = o->currentQueryObject;
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetGetQueryivARB(pname)");
+ return;
+ }
+}
+
+
+void STATE_APIENTRY
+crStateGetQueryObjectivARB(GLuint id, GLenum pname, GLint *params)
+{
+ CRContext *g = GetCurrentContext();
+ CROcclusionState *o = &(g->occlusion);
+ CROcclusionObject *q;
+
+ FLUSH();
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetGetQueryObjectivARB called in begin/end");
+ return;
+ }
+
+ q = (CROcclusionObject *) crHashtableSearch(o->objects, id);
+ if (!q || q->active) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetQueryObjectivARB");
+ return;
+ }
+
+ switch (pname) {
+ case GL_QUERY_RESULT_ARB:
+ *params = q->passedCounter;
+ break;
+ case GL_QUERY_RESULT_AVAILABLE_ARB:
+ *params = GL_TRUE;
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetQueryObjectivARB(pname)");
+ return;
+ }
+}
+
+
+void STATE_APIENTRY
+crStateGetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params)
+{
+ CRContext *g = GetCurrentContext();
+ CROcclusionState *o = &(g->occlusion);
+ CROcclusionObject *q;
+
+ FLUSH();
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetGetQueryObjectuivARB called in begin/end");
+ return;
+ }
+
+ q = (CROcclusionObject *) crHashtableSearch(o->objects, id);
+ if (!q || q->active) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetQueryObjectuivARB");
+ return;
+ }
+
+ switch (pname) {
+ case GL_QUERY_RESULT_ARB:
+ *params = q->passedCounter;
+ break;
+ case GL_QUERY_RESULT_AVAILABLE_ARB:
+ /* XXX revisit when we have a hardware implementation! */
+ *params = GL_TRUE;
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetQueryObjectuivARB(pname)");
+ return;
+ }
+}
+
+
+void STATE_APIENTRY
+crStateBeginQueryARB(GLenum target, GLuint id)
+{
+ CRContext *g = GetCurrentContext();
+ CROcclusionState *o = &(g->occlusion);
+ CROcclusionObject *q;
+
+ FLUSH();
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetGetQueryObjectuivARB called in begin/end");
+ return;
+ }
+
+ if (target != GL_SAMPLES_PASSED_ARB) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glBeginQueryARB(target)");
+ return;
+ }
+
+ if (o->currentQueryObject) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glBeginQueryARB(target)");
+ return;
+ }
+
+ q = (CROcclusionObject *) crHashtableSearch(o->objects, id);
+ if (q && q->active) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glBeginQueryARB");
+ return;
+ }
+ else if (!q) {
+ q = NewQueryObject(target, id);
+ if (!q) {
+ crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, "glBeginQueryARB");
+ return;
+ }
+ crHashtableAdd(o->objects, id, q);
+ }
+
+ q->active = GL_TRUE;
+ q->passedCounter = 0;
+ q->active = GL_TRUE;
+ q->passedCounter = 0;
+ o->currentQueryObject = id;
+}
+
+
+void STATE_APIENTRY
+crStateEndQueryARB(GLenum target)
+{
+ CRContext *g = GetCurrentContext();
+ CROcclusionState *o = &(g->occlusion);
+ CROcclusionObject *q;
+
+ FLUSH();
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetGetQueryObjectuivARB called in begin/end");
+ return;
+ }
+
+ if (target != GL_SAMPLES_PASSED_ARB) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glEndQueryARB(target)");
+ return;
+ }
+
+ q = (CROcclusionObject *) crHashtableSearch(o->objects, o->currentQueryObject);
+ if (!q || !q->active) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glEndQueryARB with glBeginQueryARB");
+ return;
+ }
+
+ q->passedCounter = 0;
+ q->active = GL_FALSE;
+ o->currentQueryObject = 0;
+}
+
+
+void crStateOcclusionDiff(CROcclusionBits *bb, CRbitvalue *bitID,
+ CRContext *fromCtx, CRContext *toCtx)
+{
+ /* Apparently, no occlusion state differencing needed */
+ (void)bb; (void)bitID; (void)fromCtx; (void)toCtx;
+}
+
+
+/*
+ * XXX this function might need some testing/fixing.
+ */
+void crStateOcclusionSwitch(CROcclusionBits *bb, CRbitvalue *bitID,
+ CRContext *fromCtx, CRContext *toCtx)
+{
+ /* Apparently, no occlusion state switching needed */
+ /* Note: we better not do a switch while we're inside a glBeginQuery/
+ * glEndQuery sequence.
+ */
+ (void)bb; (void)bitID; (void)fromCtx; (void)toCtx;
+ CRASSERT(!fromCtx->occlusion.currentQueryObject);
+}
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_pixel.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_pixel.c
new file mode 100644
index 00000000..58e08aec
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_pixel.c
@@ -0,0 +1,857 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#include <stdio.h>
+#include "cr_mem.h"
+#include "state.h"
+#include "state/cr_statetypes.h"
+#include "state_internals.h"
+
+void crStatePixelInit(CRContext *ctx)
+{
+ CRPixelState *p = &ctx->pixel;
+ CRStateBits *sb = GetCurrentBits();
+ CRPixelBits *pb = &(sb->pixel);
+ GLcolorf zero_color = {0.0f, 0.0f, 0.0f, 0.0f};
+ GLcolorf one_color = {1.0f, 1.0f, 1.0f, 1.0f};
+
+ p->mapColor = GL_FALSE;
+ p->mapStencil = GL_FALSE;
+ p->indexShift = 0;
+ p->indexOffset = 0;
+ p->scale = one_color;
+ p->depthScale = 1.0f;
+ p->bias = zero_color;
+ p->depthBias = 0.0f;
+ p->xZoom = 1.0f;
+ p->yZoom = 1.0f;
+ RESET(pb->transfer, ctx->bitid);
+ RESET(pb->zoom, ctx->bitid);
+
+ p->mapStoS[0] = 0;
+ p->mapItoI[0] = 0;
+ p->mapItoR[0] = 0.0;
+ p->mapItoG[0] = 0.0;
+ p->mapItoB[0] = 0.0;
+ p->mapItoA[0] = 0.0;
+ p->mapRtoR[0] = 0.0;
+ p->mapGtoG[0] = 0.0;
+ p->mapBtoB[0] = 0.0;
+ p->mapAtoA[0] = 0.0;
+
+ p->mapItoIsize = 1;
+ p->mapStoSsize = 1;
+ p->mapItoRsize = 1;
+ p->mapItoGsize = 1;
+ p->mapItoBsize = 1;
+ p->mapItoAsize = 1;
+ p->mapRtoRsize = 1;
+ p->mapGtoGsize = 1;
+ p->mapBtoBsize = 1;
+ p->mapAtoAsize = 1;
+ RESET(pb->maps, ctx->bitid);
+
+ RESET(pb->dirty, ctx->bitid);
+}
+
+void STATE_APIENTRY crStatePixelTransferi (GLenum pname, GLint param)
+{
+ crStatePixelTransferf( pname, (GLfloat) param );
+}
+
+void STATE_APIENTRY crStatePixelTransferf (GLenum pname, GLfloat param)
+{
+ CRContext *g = GetCurrentContext();
+ CRPixelState *p = &(g->pixel);
+ CRStateBits *sb = GetCurrentBits();
+ CRPixelBits *pb = &(sb->pixel);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "PixelTransfer{if} called in Begin/End");
+ return;
+ }
+
+ FLUSH();
+
+ switch( pname )
+ {
+ case GL_MAP_COLOR:
+ p->mapColor = (GLboolean) ((param == 0.0f) ? GL_FALSE : GL_TRUE);
+ break;
+ case GL_MAP_STENCIL:
+ p->mapStencil = (GLboolean) ((param == 0.0f) ? GL_FALSE : GL_TRUE);
+ break;
+ case GL_INDEX_SHIFT:
+ p->indexShift = (GLint) param;
+ break;
+ case GL_INDEX_OFFSET:
+ p->indexOffset = (GLint) param;
+ break;
+ case GL_RED_SCALE:
+ p->scale.r = param;
+ break;
+ case GL_GREEN_SCALE:
+ p->scale.g = param;
+ break;
+ case GL_BLUE_SCALE:
+ p->scale.b = param;
+ break;
+ case GL_ALPHA_SCALE:
+ p->scale.a = param;
+ break;
+ case GL_DEPTH_SCALE:
+ p->depthScale = param;
+ break;
+ case GL_RED_BIAS:
+ p->bias.r = param;
+ break;
+ case GL_GREEN_BIAS:
+ p->bias.g = param;
+ break;
+ case GL_BLUE_BIAS:
+ p->bias.b = param;
+ break;
+ case GL_ALPHA_BIAS:
+ p->bias.a = param;
+ break;
+ case GL_DEPTH_BIAS:
+ p->depthBias = param;
+ break;
+ default:
+ crStateError( __LINE__, __FILE__, GL_INVALID_VALUE, "Unknown glPixelTransfer pname: %d", pname );
+ return;
+ }
+ DIRTY(pb->transfer, g->neg_bitid);
+ DIRTY(pb->dirty, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStatePixelZoom (GLfloat xfactor, GLfloat yfactor)
+{
+ CRContext *g = GetCurrentContext();
+ CRPixelState *p = &(g->pixel);
+ CRStateBits *sb = GetCurrentBits();
+ CRPixelBits *pb = &(sb->pixel);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "PixelZoom called in Begin/End");
+ return;
+ }
+
+ FLUSH();
+
+ p->xZoom = xfactor;
+ p->yZoom = yfactor;
+ DIRTY(pb->zoom, g->neg_bitid);
+ DIRTY(pb->dirty, g->neg_bitid);
+}
+
+
+void STATE_APIENTRY crStateBitmap( GLsizei width, GLsizei height,
+ GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove,
+ const GLubyte *bitmap)
+{
+ CRContext *g = GetCurrentContext();
+ CRCurrentState *c = &(g->current);
+ CRStateBits *sb = GetCurrentBits();
+ CRCurrentBits *cb = &(sb->current);
+
+ (void) xorig;
+ (void) yorig;
+ (void) bitmap;
+
+ if (g->lists.mode == GL_COMPILE)
+ return;
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "Bitmap called in begin/end");
+ return;
+ }
+
+ if (width < 0 || height < 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "Bitmap called with neg dims: %dx%d", width, height);
+ return;
+ }
+
+ if (!c->rasterValid)
+ {
+ return;
+ }
+
+ c->rasterAttrib[VERT_ATTRIB_POS][0] += xmove;
+ c->rasterAttrib[VERT_ATTRIB_POS][1] += ymove;
+ DIRTY(cb->rasterPos, g->neg_bitid);
+ DIRTY(cb->dirty, g->neg_bitid);
+
+ c->rasterAttribPre[VERT_ATTRIB_POS][0] += xmove;
+ c->rasterAttribPre[VERT_ATTRIB_POS][1] += ymove;
+}
+
+
+#define UNUSED(x) ((void)(x))
+
+#define CLAMP(x, min, max) ((x) < (min) ? (min) : ((x) > (max) ? (max) : (x)))
+
+void STATE_APIENTRY crStatePixelMapfv (GLenum map, GLint mapsize, const GLfloat * values)
+{
+ CRContext *g = GetCurrentContext();
+ CRPixelState *p = &(g->pixel);
+ CRStateBits *sb = GetCurrentBits();
+ CRPixelBits *pb = &(sb->pixel);
+ GLint i;
+ GLboolean unpackbuffer = crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB);
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "PixelMap called in Begin/End");
+ return;
+ }
+
+ FLUSH();
+
+ if (mapsize < 0 || mapsize > CR_MAX_PIXEL_MAP_TABLE) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "PixelMap(mapsize)");
+ return;
+ }
+
+ if (map >= GL_PIXEL_MAP_S_TO_S && map <= GL_PIXEL_MAP_I_TO_A) {
+ /* XXX check that mapsize is a power of two */
+ }
+
+ switch (map) {
+ case GL_PIXEL_MAP_S_TO_S:
+ p->mapStoSsize = mapsize;
+ if (!unpackbuffer)
+ for (i=0;i<mapsize;i++) {
+ p->mapStoS[i] = (GLint) values[i];
+ }
+ break;
+ case GL_PIXEL_MAP_I_TO_I:
+ p->mapItoIsize = mapsize;
+ if (!unpackbuffer)
+ for (i=0;i<mapsize;i++) {
+ p->mapItoI[i] = (GLint) values[i];
+ }
+ break;
+ case GL_PIXEL_MAP_I_TO_R:
+ p->mapItoRsize = mapsize;
+ if (!unpackbuffer)
+ for (i=0;i<mapsize;i++) {
+ GLfloat val = CLAMP( values[i], 0.0F, 1.0F );
+ p->mapItoR[i] = val;
+ }
+ break;
+ case GL_PIXEL_MAP_I_TO_G:
+ p->mapItoGsize = mapsize;
+ if (!unpackbuffer)
+ for (i=0;i<mapsize;i++) {
+ GLfloat val = CLAMP( values[i], 0.0F, 1.0F );
+ p->mapItoG[i] = val;
+ }
+ break;
+ case GL_PIXEL_MAP_I_TO_B:
+ p->mapItoBsize = mapsize;
+ if (!unpackbuffer)
+ for (i=0;i<mapsize;i++) {
+ GLfloat val = CLAMP( values[i], 0.0F, 1.0F );
+ p->mapItoB[i] = val;
+ }
+ break;
+ case GL_PIXEL_MAP_I_TO_A:
+ p->mapItoAsize = mapsize;
+ if (!unpackbuffer)
+ for (i=0;i<mapsize;i++) {
+ GLfloat val = CLAMP( values[i], 0.0F, 1.0F );
+ p->mapItoA[i] = val;
+ }
+ break;
+ case GL_PIXEL_MAP_R_TO_R:
+ p->mapRtoRsize = mapsize;
+ if (!unpackbuffer)
+ for (i=0;i<mapsize;i++) {
+ p->mapRtoR[i] = CLAMP( values[i], 0.0F, 1.0F );
+ }
+ break;
+ case GL_PIXEL_MAP_G_TO_G:
+ p->mapGtoGsize = mapsize;
+ if (!unpackbuffer)
+ for (i=0;i<mapsize;i++) {
+ p->mapGtoG[i] = CLAMP( values[i], 0.0F, 1.0F );
+ }
+ break;
+ case GL_PIXEL_MAP_B_TO_B:
+ p->mapBtoBsize = mapsize;
+ if (!unpackbuffer)
+ for (i=0;i<mapsize;i++) {
+ p->mapBtoB[i] = CLAMP( values[i], 0.0F, 1.0F );
+ }
+ break;
+ case GL_PIXEL_MAP_A_TO_A:
+ p->mapAtoAsize = mapsize;
+ if (!unpackbuffer)
+ for (i=0;i<mapsize;i++) {
+ p->mapAtoA[i] = CLAMP( values[i], 0.0F, 1.0F );
+ }
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "PixelMap(map)");
+ return;
+ }
+
+ DIRTY(pb->maps, g->neg_bitid);
+ DIRTY(pb->dirty, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStatePixelMapuiv (GLenum map, GLint mapsize, const GLuint * values)
+{
+ if (mapsize < 0 || mapsize > CR_MAX_PIXEL_MAP_TABLE)
+ {
+ crError("crStatePixelMapuiv: parameter 'mapsize' is out of range");
+ return;
+ }
+
+ if (!crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB))
+ {
+ GLfloat fvalues[CR_MAX_PIXEL_MAP_TABLE];
+ GLint i;
+
+ if (map==GL_PIXEL_MAP_I_TO_I || map==GL_PIXEL_MAP_S_TO_S) {
+ for (i=0;i<mapsize;i++) {
+ fvalues[i] = (GLfloat) values[i];
+ }
+ }
+ else {
+ for (i=0;i<mapsize;i++) {
+ fvalues[i] = values[i] / 4294967295.0F;
+ }
+ }
+ crStatePixelMapfv(map, mapsize, fvalues);
+ }
+ else
+ {
+ crStatePixelMapfv(map, mapsize, (const GLfloat*) values);
+ }
+}
+
+void STATE_APIENTRY crStatePixelMapusv (GLenum map, GLint mapsize, const GLushort * values)
+{
+ if (mapsize < 0 || mapsize > CR_MAX_PIXEL_MAP_TABLE)
+ {
+ crError("crStatePixelMapusv: parameter 'mapsize' is out of range");
+ return;
+ }
+
+ if (!crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB))
+ {
+ GLfloat fvalues[CR_MAX_PIXEL_MAP_TABLE];
+ GLint i;
+
+ if (map==GL_PIXEL_MAP_I_TO_I || map==GL_PIXEL_MAP_S_TO_S) {
+ for (i=0;i<mapsize;i++) {
+ fvalues[i] = (GLfloat) values[i];
+ }
+ }
+ else {
+ for (i=0;i<mapsize;i++) {
+ fvalues[i] = values[i] / 65535.0F;
+ }
+ }
+ crStatePixelMapfv(map, mapsize, fvalues);
+ }
+ else
+ {
+ crStatePixelMapfv(map, mapsize, (const GLfloat*) values);
+ }
+}
+
+
+void STATE_APIENTRY crStateGetPixelMapfv (GLenum map, GLfloat * values)
+{
+ CRContext *g = GetCurrentContext();
+ CRPixelState *p = &(g->pixel);
+ GLint i;
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "GetPixelMapfv called in Begin/End");
+ return;
+ }
+
+ switch (map) {
+ case GL_PIXEL_MAP_S_TO_S:
+ for (i = 0; i < p->mapStoSsize; i++) {
+ values[i] = (GLfloat) p->mapStoS[i];
+ }
+ break;
+ case GL_PIXEL_MAP_I_TO_I:
+ for (i = 0; i < p->mapItoIsize; i++) {
+ values[i] = (GLfloat) p->mapItoI[i];
+ }
+ break;
+ case GL_PIXEL_MAP_I_TO_R:
+ crMemcpy(values, p->mapItoR, p->mapItoRsize * sizeof(GLfloat));
+ break;
+ case GL_PIXEL_MAP_I_TO_G:
+ crMemcpy(values, p->mapItoG, p->mapItoGsize * sizeof(GLfloat));
+ break;
+ case GL_PIXEL_MAP_I_TO_B:
+ crMemcpy(values, p->mapItoB, p->mapItoBsize * sizeof(GLfloat));
+ break;
+ case GL_PIXEL_MAP_I_TO_A:
+ crMemcpy(values, p->mapItoA, p->mapItoAsize * sizeof(GLfloat));
+ break;
+ case GL_PIXEL_MAP_R_TO_R:
+ crMemcpy(values, p->mapRtoR, p->mapRtoRsize * sizeof(GLfloat));
+ break;
+ case GL_PIXEL_MAP_G_TO_G:
+ crMemcpy(values, p->mapGtoG, p->mapGtoGsize * sizeof(GLfloat));
+ break;
+ case GL_PIXEL_MAP_B_TO_B:
+ crMemcpy(values, p->mapBtoB, p->mapBtoBsize * sizeof(GLfloat));
+ break;
+ case GL_PIXEL_MAP_A_TO_A:
+ crMemcpy(values, p->mapAtoA, p->mapAtoAsize * sizeof(GLfloat));
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "GetPixelMap(map)");
+ return;
+ }
+}
+
+void STATE_APIENTRY crStateGetPixelMapuiv (GLenum map, GLuint * values)
+{
+ CRContext *g = GetCurrentContext();
+ const GLfloat maxUint = 4294967295.0F;
+ CRPixelState *p = &(g->pixel);
+ GLint i;
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "GetPixelMapuiv called in Begin/End");
+ return;
+ }
+
+ switch (map) {
+ case GL_PIXEL_MAP_S_TO_S:
+ for (i = 0; i < p->mapStoSsize; i++) {
+ values[i] = p->mapStoS[i];
+ }
+ break;
+ case GL_PIXEL_MAP_I_TO_I:
+ for (i = 0; i < p->mapItoIsize; i++) {
+ values[i] = p->mapItoI[i];
+ }
+ break;
+ case GL_PIXEL_MAP_I_TO_R:
+ for (i = 0; i < p->mapItoRsize; i++) {
+ values[i] = (GLuint) (p->mapItoR[i] * maxUint);
+ }
+ break;
+ case GL_PIXEL_MAP_I_TO_G:
+ for (i = 0; i < p->mapItoGsize; i++) {
+ values[i] = (GLuint) (p->mapItoG[i] * maxUint);
+ }
+ break;
+ case GL_PIXEL_MAP_I_TO_B:
+ for (i = 0; i < p->mapItoBsize; i++) {
+ values[i] = (GLuint) (p->mapItoB[i] * maxUint);
+ }
+ break;
+ case GL_PIXEL_MAP_I_TO_A:
+ for (i = 0; i < p->mapItoAsize; i++) {
+ values[i] = (GLuint) (p->mapItoA[i] * maxUint);
+ }
+ break;
+ case GL_PIXEL_MAP_R_TO_R:
+ for (i = 0; i < p->mapRtoRsize; i++) {
+ values[i] = (GLuint) (p->mapRtoR[i] * maxUint);
+ }
+ break;
+ case GL_PIXEL_MAP_G_TO_G:
+ for (i = 0; i < p->mapGtoGsize; i++) {
+ values[i] = (GLuint) (p->mapGtoG[i] * maxUint);
+ }
+ break;
+ case GL_PIXEL_MAP_B_TO_B:
+ for (i = 0; i < p->mapBtoBsize; i++) {
+ values[i] = (GLuint) (p->mapBtoB[i] * maxUint);
+ }
+ break;
+ case GL_PIXEL_MAP_A_TO_A:
+ for (i = 0; i < p->mapAtoAsize; i++) {
+ values[i] = (GLuint) (p->mapAtoA[i] * maxUint);
+ }
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "GetPixelMapuiv(map)");
+ return;
+ }
+}
+
+void STATE_APIENTRY crStateGetPixelMapusv (GLenum map, GLushort * values)
+{
+ CRContext *g = GetCurrentContext();
+ const GLfloat maxUshort = 65535.0F;
+ CRPixelState *p = &(g->pixel);
+ GLint i;
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "GetPixelMapusv called in Begin/End");
+ return;
+ }
+
+ switch (map) {
+ case GL_PIXEL_MAP_S_TO_S:
+ for (i = 0; i < p->mapStoSsize; i++) {
+ values[i] = p->mapStoS[i];
+ }
+ break;
+ case GL_PIXEL_MAP_I_TO_I:
+ for (i = 0; i < p->mapItoIsize; i++) {
+ values[i] = p->mapItoI[i];
+ }
+ break;
+ case GL_PIXEL_MAP_I_TO_R:
+ for (i = 0; i < p->mapItoRsize; i++) {
+ values[i] = (GLushort) (p->mapItoR[i] * maxUshort);
+ }
+ break;
+ case GL_PIXEL_MAP_I_TO_G:
+ for (i = 0; i < p->mapItoGsize; i++) {
+ values[i] = (GLushort) (p->mapItoG[i] * maxUshort);
+ }
+ break;
+ case GL_PIXEL_MAP_I_TO_B:
+ for (i = 0; i < p->mapItoBsize; i++) {
+ values[i] = (GLushort) (p->mapItoB[i] * maxUshort);
+ }
+ break;
+ case GL_PIXEL_MAP_I_TO_A:
+ for (i = 0; i < p->mapItoAsize; i++) {
+ values[i] = (GLushort) (p->mapItoA[i] * maxUshort);
+ }
+ break;
+ case GL_PIXEL_MAP_R_TO_R:
+ for (i = 0; i < p->mapRtoRsize; i++) {
+ values[i] = (GLushort) (p->mapRtoR[i] * maxUshort);
+ }
+ break;
+ case GL_PIXEL_MAP_G_TO_G:
+ for (i = 0; i < p->mapGtoGsize; i++) {
+ values[i] = (GLushort) (p->mapGtoG[i] * maxUshort);
+ }
+ break;
+ case GL_PIXEL_MAP_B_TO_B:
+ for (i = 0; i < p->mapBtoBsize; i++) {
+ values[i] = (GLushort) (p->mapBtoB[i] * maxUshort);
+ }
+ break;
+ case GL_PIXEL_MAP_A_TO_A:
+ for (i = 0; i < p->mapAtoAsize; i++) {
+ values[i] = (GLushort) (p->mapAtoA[i] * maxUshort);
+ }
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "GetPixelMapusv(map)");
+ return;
+ }
+}
+
+void crStatePixelDiff(CRPixelBits *b, CRbitvalue *bitID,
+ CRContext *fromCtx, CRContext *toCtx)
+{
+ CRPixelState *from = &(fromCtx->pixel);
+ CRPixelState *to = &(toCtx->pixel);
+ int j, i;
+ CRbitvalue nbitID[CR_MAX_BITARRAY];
+ for (j=0;j<CR_MAX_BITARRAY;j++)
+ nbitID[j] = ~bitID[j];
+ i = 0; /* silence compiler */
+ if (CHECKDIRTY(b->transfer, bitID))
+ {
+ if (from->mapColor != to->mapColor)
+ {
+ diff_api.PixelTransferi (GL_MAP_COLOR, to->mapColor);
+ from->mapColor = to->mapColor;
+ }
+ if (from->mapStencil != to->mapStencil)
+ {
+ diff_api.PixelTransferi (GL_MAP_STENCIL, to->mapStencil);
+ from->mapStencil = to->mapStencil;
+ }
+ if (from->indexOffset != to->indexOffset)
+ {
+ diff_api.PixelTransferi (GL_INDEX_OFFSET, to->indexOffset);
+ from->indexOffset = to->indexOffset;
+ }
+ if (from->indexShift != to->indexShift)
+ {
+ diff_api.PixelTransferi (GL_INDEX_SHIFT, to->indexShift);
+ from->indexShift = to->indexShift;
+ }
+ if (from->scale.r != to->scale.r)
+ {
+ diff_api.PixelTransferf (GL_RED_SCALE, to->scale.r);
+ from->scale.r = to->scale.r;
+ }
+ if (from->scale.g != to->scale.g)
+ {
+ diff_api.PixelTransferf (GL_GREEN_SCALE, to->scale.g);
+ from->scale.g = to->scale.g;
+ }
+ if (from->scale.b != to->scale.b)
+ {
+ diff_api.PixelTransferf (GL_BLUE_SCALE, to->scale.b);
+ from->scale.b = to->scale.b;
+ }
+ if (from->scale.a != to->scale.a)
+ {
+ diff_api.PixelTransferf (GL_ALPHA_SCALE, to->scale.a);
+ from->scale.a = to->scale.a;
+ }
+ if (from->bias.r != to->bias.r)
+ {
+ diff_api.PixelTransferf (GL_RED_BIAS, to->bias.r);
+ from->bias.r = to->bias.r;
+ }
+ if (from->bias.g != to->bias.g)
+ {
+ diff_api.PixelTransferf (GL_GREEN_BIAS, to->bias.g);
+ from->bias.g = to->bias.g;
+ }
+ if (from->bias.b != to->bias.b)
+ {
+ diff_api.PixelTransferf (GL_BLUE_BIAS, to->bias.b);
+ from->bias.b = to->bias.b;
+ }
+ if (from->bias.a != to->bias.a)
+ {
+ diff_api.PixelTransferf (GL_ALPHA_BIAS, to->bias.a);
+ from->bias.a = to->bias.a;
+ }
+ if (from->depthScale != to->depthScale)
+ {
+ diff_api.PixelTransferf (GL_DEPTH_SCALE, to->depthScale);
+ from->depthScale = to->depthScale;
+ }
+ if (from->depthBias != to->depthBias)
+ {
+ diff_api.PixelTransferf (GL_DEPTH_BIAS, to->depthBias);
+ from->depthBias = to->depthBias;
+ }
+ CLEARDIRTY(b->transfer, nbitID);
+ }
+ if (CHECKDIRTY(b->zoom, bitID))
+ {
+ if (from->xZoom != to->xZoom ||
+ from->yZoom != to->yZoom)
+ {
+ diff_api.PixelZoom (to->xZoom,
+ to->yZoom);
+ from->xZoom = to->xZoom;
+ from->yZoom = to->yZoom;
+ }
+ CLEARDIRTY(b->zoom, nbitID);
+ }
+ if (CHECKDIRTY(b->maps, bitID))
+ {
+ if (crMemcmp(to->mapStoS, from->mapStoS, CR_MAX_PIXEL_MAP_TABLE*sizeof(GLfloat)))
+ diff_api.PixelMapfv(GL_PIXEL_MAP_S_TO_S,to->mapStoSsize,(GLfloat*)to->mapStoS);
+ if (crMemcmp(to->mapItoI, from->mapItoI, CR_MAX_PIXEL_MAP_TABLE*sizeof(GLfloat)))
+ diff_api.PixelMapfv(GL_PIXEL_MAP_I_TO_I,to->mapItoIsize,(GLfloat*)to->mapItoI);
+ if (crMemcmp(to->mapItoR, from->mapItoR, CR_MAX_PIXEL_MAP_TABLE*sizeof(GLfloat)))
+ diff_api.PixelMapfv(GL_PIXEL_MAP_I_TO_R,to->mapItoRsize,(GLfloat*)to->mapItoR);
+ if (crMemcmp(to->mapItoG, from->mapItoG, CR_MAX_PIXEL_MAP_TABLE*sizeof(GLfloat)))
+ diff_api.PixelMapfv(GL_PIXEL_MAP_I_TO_G,to->mapItoGsize,(GLfloat*)to->mapItoG);
+ if (crMemcmp(to->mapItoB, from->mapItoB, CR_MAX_PIXEL_MAP_TABLE*sizeof(GLfloat)))
+ diff_api.PixelMapfv(GL_PIXEL_MAP_I_TO_B,to->mapItoBsize,(GLfloat*)to->mapItoB);
+ if (crMemcmp(to->mapItoA, from->mapItoA, CR_MAX_PIXEL_MAP_TABLE*sizeof(GLfloat)))
+ diff_api.PixelMapfv(GL_PIXEL_MAP_I_TO_A,to->mapItoAsize,(GLfloat*)to->mapItoA);
+ if (crMemcmp(to->mapRtoR, from->mapRtoR, CR_MAX_PIXEL_MAP_TABLE*sizeof(GLfloat)))
+ diff_api.PixelMapfv(GL_PIXEL_MAP_R_TO_R,to->mapRtoRsize,(GLfloat*)to->mapRtoR);
+ if (crMemcmp(to->mapGtoG, from->mapGtoG, CR_MAX_PIXEL_MAP_TABLE*sizeof(GLfloat)))
+ diff_api.PixelMapfv(GL_PIXEL_MAP_G_TO_G,to->mapGtoGsize,(GLfloat*)to->mapGtoG);
+ if (crMemcmp(to->mapBtoB, from->mapBtoB, CR_MAX_PIXEL_MAP_TABLE*sizeof(GLfloat)))
+ diff_api.PixelMapfv(GL_PIXEL_MAP_B_TO_B,to->mapBtoBsize,(GLfloat*)to->mapBtoB);
+ if (crMemcmp(to->mapAtoA, from->mapAtoA, CR_MAX_PIXEL_MAP_TABLE*sizeof(GLfloat)))
+ diff_api.PixelMapfv(GL_PIXEL_MAP_A_TO_A,to->mapAtoAsize,(GLfloat*)to->mapAtoA);
+ CLEARDIRTY(b->maps, nbitID);
+ }
+ CLEARDIRTY(b->dirty, nbitID);
+}
+
+void crStatePixelSwitch(CRPixelBits *b, CRbitvalue *bitID,
+ CRContext *fromCtx, CRContext *toCtx)
+{
+ CRPixelState *from = &(fromCtx->pixel);
+ CRPixelState *to = &(toCtx->pixel);
+ int j, i;
+ CRbitvalue nbitID[CR_MAX_BITARRAY];
+ for (j=0;j<CR_MAX_BITARRAY;j++)
+ nbitID[j] = ~bitID[j];
+ i = 0; /* silence compiler */
+ if (CHECKDIRTY(b->transfer, bitID))
+ {
+ if (from->mapColor != to->mapColor)
+ {
+ diff_api.PixelTransferi (GL_MAP_COLOR, to->mapColor);
+ FILLDIRTY(b->transfer);
+ FILLDIRTY(b->dirty);
+ }
+ if (from->mapStencil != to->mapStencil)
+ {
+ diff_api.PixelTransferi (GL_MAP_STENCIL, to->mapStencil);
+ FILLDIRTY(b->transfer);
+ FILLDIRTY(b->dirty);
+ }
+ if (from->indexOffset != to->indexOffset)
+ {
+ diff_api.PixelTransferi (GL_INDEX_OFFSET, to->indexOffset);
+ FILLDIRTY(b->transfer);
+ FILLDIRTY(b->dirty);
+ }
+ if (from->indexShift != to->indexShift)
+ {
+ diff_api.PixelTransferi (GL_INDEX_SHIFT, to->indexShift);
+ FILLDIRTY(b->transfer);
+ FILLDIRTY(b->dirty);
+ }
+ if (from->scale.r != to->scale.r)
+ {
+ diff_api.PixelTransferf (GL_RED_SCALE, to->scale.r);
+ FILLDIRTY(b->transfer);
+ FILLDIRTY(b->dirty);
+ }
+ if (from->scale.g != to->scale.g)
+ {
+ diff_api.PixelTransferf (GL_GREEN_SCALE, to->scale.g);
+ FILLDIRTY(b->transfer);
+ FILLDIRTY(b->dirty);
+ }
+ if (from->scale.b != to->scale.b)
+ {
+ diff_api.PixelTransferf (GL_BLUE_SCALE, to->scale.b);
+ FILLDIRTY(b->transfer);
+ FILLDIRTY(b->dirty);
+ }
+ if (from->scale.a != to->scale.a)
+ {
+ diff_api.PixelTransferf (GL_ALPHA_SCALE, to->scale.a);
+ FILLDIRTY(b->transfer);
+ FILLDIRTY(b->dirty);
+ }
+ if (from->bias.r != to->bias.r)
+ {
+ diff_api.PixelTransferf (GL_RED_BIAS, to->bias.r);
+ FILLDIRTY(b->transfer);
+ FILLDIRTY(b->dirty);
+ }
+ if (from->bias.g != to->bias.g)
+ {
+ diff_api.PixelTransferf (GL_GREEN_BIAS, to->bias.g);
+ FILLDIRTY(b->transfer);
+ FILLDIRTY(b->dirty);
+ }
+ if (from->bias.b != to->bias.b)
+ {
+ diff_api.PixelTransferf (GL_BLUE_BIAS, to->bias.b);
+ FILLDIRTY(b->transfer);
+ FILLDIRTY(b->dirty);
+ }
+ if (from->bias.a != to->bias.a)
+ {
+ diff_api.PixelTransferf (GL_ALPHA_BIAS, to->bias.a);
+ FILLDIRTY(b->transfer);
+ FILLDIRTY(b->dirty);
+ }
+ if (from->depthScale != to->depthScale)
+ {
+ diff_api.PixelTransferf (GL_DEPTH_SCALE, to->depthScale);
+ FILLDIRTY(b->transfer);
+ FILLDIRTY(b->dirty);
+ }
+ if (from->depthBias != to->depthBias)
+ {
+ diff_api.PixelTransferf (GL_DEPTH_BIAS, to->depthBias);
+ FILLDIRTY(b->transfer);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->transfer, nbitID);
+ }
+ if (CHECKDIRTY(b->zoom, bitID))
+ {
+ if (from->xZoom != to->xZoom ||
+ from->yZoom != to->yZoom)
+ {
+ diff_api.PixelZoom (to->xZoom,
+ to->yZoom);
+ FILLDIRTY(b->zoom);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->zoom, nbitID);
+ }
+ if (CHECKDIRTY(b->maps, bitID))
+ {
+ if (crMemcmp(to->mapStoS, from->mapStoS, CR_MAX_PIXEL_MAP_TABLE)) {
+ diff_api.PixelMapfv(GL_PIXEL_MAP_S_TO_S,to->mapStoSsize,(GLfloat*)to->mapStoS);
+ FILLDIRTY(b->maps);
+ FILLDIRTY(b->dirty);
+ }
+ if (crMemcmp(to->mapItoI, from->mapItoI, CR_MAX_PIXEL_MAP_TABLE)) {
+ diff_api.PixelMapfv(GL_PIXEL_MAP_I_TO_I,to->mapItoIsize,(GLfloat*)to->mapItoI);
+ FILLDIRTY(b->maps);
+ FILLDIRTY(b->dirty);
+ }
+ if (crMemcmp(to->mapItoR, from->mapItoR, CR_MAX_PIXEL_MAP_TABLE)) {
+ diff_api.PixelMapfv(GL_PIXEL_MAP_I_TO_R,to->mapItoRsize,(GLfloat*)to->mapItoR);
+ FILLDIRTY(b->maps);
+ FILLDIRTY(b->dirty);
+ }
+ if (crMemcmp(to->mapItoG, from->mapItoG, CR_MAX_PIXEL_MAP_TABLE)) {
+ diff_api.PixelMapfv(GL_PIXEL_MAP_I_TO_G,to->mapItoGsize,(GLfloat*)to->mapItoG);
+ FILLDIRTY(b->maps);
+ FILLDIRTY(b->dirty);
+ }
+ if (crMemcmp(to->mapItoB, from->mapItoB, CR_MAX_PIXEL_MAP_TABLE)) {
+ diff_api.PixelMapfv(GL_PIXEL_MAP_I_TO_B,to->mapItoBsize,(GLfloat*)to->mapItoB);
+ FILLDIRTY(b->maps);
+ FILLDIRTY(b->dirty);
+ }
+ if (crMemcmp(to->mapItoA, from->mapItoA, CR_MAX_PIXEL_MAP_TABLE)) {
+ diff_api.PixelMapfv(GL_PIXEL_MAP_I_TO_A,to->mapItoAsize,(GLfloat*)to->mapItoA);
+ FILLDIRTY(b->maps);
+ FILLDIRTY(b->dirty);
+ }
+ if (crMemcmp(to->mapRtoR, from->mapRtoR, CR_MAX_PIXEL_MAP_TABLE)) {
+ diff_api.PixelMapfv(GL_PIXEL_MAP_R_TO_R,to->mapRtoRsize,(GLfloat*)to->mapRtoR);
+ FILLDIRTY(b->maps);
+ FILLDIRTY(b->dirty);
+ }
+ if (crMemcmp(to->mapGtoG, from->mapGtoG, CR_MAX_PIXEL_MAP_TABLE)) {
+ diff_api.PixelMapfv(GL_PIXEL_MAP_G_TO_G,to->mapGtoGsize,(GLfloat*)to->mapGtoG);
+ FILLDIRTY(b->maps);
+ FILLDIRTY(b->dirty);
+ }
+ if (crMemcmp(to->mapBtoB, from->mapBtoB, CR_MAX_PIXEL_MAP_TABLE)) {
+ diff_api.PixelMapfv(GL_PIXEL_MAP_B_TO_B,to->mapBtoBsize,(GLfloat*)to->mapBtoB);
+ FILLDIRTY(b->maps);
+ FILLDIRTY(b->dirty);
+ }
+ if (crMemcmp(to->mapAtoA, from->mapAtoA, CR_MAX_PIXEL_MAP_TABLE)) {
+ diff_api.PixelMapfv(GL_PIXEL_MAP_A_TO_A,to->mapAtoAsize,(GLfloat*)to->mapAtoA);
+ FILLDIRTY(b->maps);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->maps, nbitID);
+ }
+ CLEARDIRTY(b->dirty, nbitID);
+}
+
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_point.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_point.c
new file mode 100644
index 00000000..de40c089
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_point.c
@@ -0,0 +1,447 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#include "state.h"
+#include "state/cr_statetypes.h"
+#include "state_internals.h"
+
+void crStatePointInit (CRContext *ctx)
+{
+ CRPointState *p = &ctx->point;
+ CRStateBits *sb = GetCurrentBits();
+ CRPointBits *pb = &(sb->point);
+ int i;
+
+ p->pointSmooth = GL_FALSE;
+ RESET(pb->enableSmooth, ctx->bitid);
+ p->pointSize = 1.0f;
+ RESET(pb->size, ctx->bitid);
+#ifdef CR_ARB_point_parameters
+ p->minSize = 0.0f;
+ RESET(pb->minSize, ctx->bitid);
+ p->maxSize = CR_ALIASED_POINT_SIZE_MAX;
+ RESET(pb->maxSize, ctx->bitid);
+ p->fadeThresholdSize = 1.0f;
+ RESET(pb->fadeThresholdSize, ctx->bitid);
+ p->distanceAttenuation[0] = 1.0f;
+ p->distanceAttenuation[1] = 0.0f;
+ p->distanceAttenuation[2] = 0.0f;
+ RESET(pb->distanceAttenuation, ctx->bitid);
+#endif
+#ifdef CR_ARB_point_sprite
+ p->pointSprite = GL_FALSE;
+ RESET(pb->enableSprite, ctx->bitid);
+ for (i = 0; i < CR_MAX_TEXTURE_UNITS; i++) {
+ p->coordReplacement[i] = GL_FALSE;
+ RESET(pb->coordReplacement[i], ctx->bitid);
+ }
+#endif
+
+ p->spriteCoordOrigin = (GLfloat)GL_UPPER_LEFT;
+ RESET(pb->spriteCoordOrigin, ctx->bitid);
+
+ RESET(pb->dirty, ctx->bitid);
+
+ /*
+ *p->aliasedpointsizerange_min = c->aliasedpointsizerange_min;
+ *p->aliasedpointsizerange_max = c->aliasedpointsizerange_max;
+ *p->aliasedpointsizegranularity = c->aliasedpointsizegranularity;
+ *p->smoothpointsizerange_min = c->smoothpointsizerange_min;
+ *p->smoothpointsizerange_max = c->smoothpointsizerange_max;
+ *p->smoothpointgranularity = c->smoothpointgranularity;
+ */
+}
+
+void STATE_APIENTRY crStatePointSize(GLfloat size)
+{
+ CRContext *g = GetCurrentContext();
+ CRPointState *p = &(g->point);
+ CRStateBits *sb = GetCurrentBits();
+ CRPointBits *pb = &(sb->point);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glPointSize called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ if (size <= 0.0f)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glPointSize called with size <= 0.0: %f", size);
+ return;
+ }
+
+ p->pointSize = size;
+ DIRTY(pb->size, g->neg_bitid);
+ DIRTY(pb->dirty, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStatePointParameterfARB(GLenum pname, GLfloat param)
+{
+ CRContext *g = GetCurrentContext();
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glPointParameterfARB called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ crStatePointParameterfvARB(pname, &param);
+}
+
+void STATE_APIENTRY crStatePointParameterfvARB(GLenum pname, const GLfloat *params)
+{
+ CRContext *g = GetCurrentContext();
+ CRPointState *p = &(g->point);
+ CRStateBits *sb = GetCurrentBits();
+ CRPointBits *pb = &(sb->point);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glPointParameterfvARB called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ switch (pname) {
+ case GL_DISTANCE_ATTENUATION_EXT:
+ if (g->extensions.ARB_point_parameters) {
+ p->distanceAttenuation[0] = params[0];
+ p->distanceAttenuation[1] = params[1];
+ p->distanceAttenuation[2] = params[2];
+ DIRTY(pb->distanceAttenuation, g->neg_bitid);
+ }
+ else
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glPointParameterfvARB invalid enum: %f", pname);
+ return;
+ }
+ break;
+ case GL_POINT_SIZE_MIN_EXT:
+ if (g->extensions.ARB_point_parameters) {
+ if (params[0] < 0.0F) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glPointParameterfvARB invalid value: %f", params[0]);
+ return;
+ }
+ p->minSize = params[0];
+ DIRTY(pb->minSize, g->neg_bitid);
+ }
+ else
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glPointParameterfvARB invalid enum: %f", pname);
+ return;
+ }
+ break;
+ case GL_POINT_SIZE_MAX_EXT:
+ if (g->extensions.ARB_point_parameters) {
+ if (params[0] < 0.0F) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glPointParameterfvARB invalid value: %f", params[0]);
+ return;
+ }
+ p->maxSize = params[0];
+ DIRTY(pb->maxSize, g->neg_bitid);
+ }
+ else
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glPointParameterfvARB invalid enum: %f", pname);
+ return;
+ }
+ break;
+ case GL_POINT_FADE_THRESHOLD_SIZE_EXT:
+ if (g->extensions.ARB_point_parameters) {
+ if (params[0] < 0.0F) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glPointParameterfvARB invalid value: %f", params[0]);
+ return;
+ }
+ p->fadeThresholdSize = params[0];
+ DIRTY(pb->fadeThresholdSize, g->neg_bitid);
+ }
+ else
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glPointParameterfvARB invalid enum: %f", pname);
+ 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;
+ }
+
+ DIRTY(pb->dirty, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStatePointParameteri(GLenum pname, GLint param)
+{
+ GLfloat f_param = (GLfloat) param;
+ crStatePointParameterfvARB( pname, &f_param );
+}
+
+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
new file mode 100644
index 00000000..ba92c153
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_point.txt
@@ -0,0 +1,39 @@
+# Copyright (c) 2001, Stanford University
+# All rights reserved.
+#
+# See the file LICENSE.txt for information on redistributing this software.
+:enableSmooth:pointSmooth:GL_POINT_SMOOTH
+:size:pointSize:PointSize
+: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);
+-:distanceAttenuation:* FILLDIRTY(b->distanceAttenuation);
+-:distanceAttenuation:* FILLDIRTY(b->dirty);
+-:distanceAttenuation:*}
++: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);
++:distanceAttenuation:* from->distanceAttenuation[0] = to->distanceAttenuation[0];
++:distanceAttenuation:* from->distanceAttenuation[1] = to->distanceAttenuation[1];
++:distanceAttenuation:* from->distanceAttenuation[2] = to->distanceAttenuation[2];
++:distanceAttenuation:*}
+:enableSprite:pointSprite:GL_POINT_SPRITE_ARB
+%flush
+>{
+>unsigned int activeUnit = (unsigned int) -1;
+>for (i = 0; i < CR_MAX_TEXTURE_UNITS; i++) {
+:coordReplacement[i]:*GLint replacement = to->coordReplacement[i];
+:coordReplacement[i]:*if (activeUnit != i) {
+:coordReplacement[i]:* diff_api.ActiveTextureARB(i + GL_TEXTURE0_ARB );
+:coordReplacement[i]:* activeUnit = i;
+:coordReplacement[i]:*}
+:coordReplacement[i]:*diff_api.TexEnviv(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, &replacement);
++:coordReplacement[i]:*from->coordReplacement[i] = to->coordReplacement[i];
+%flush
+>}
+>if (activeUnit != toCtx->texture.curTextureUnit)
+> diff_api.ActiveTextureARB(GL_TEXTURE0 + toCtx->texture.curTextureUnit);
+>}
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_polygon.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_polygon.c
new file mode 100644
index 00000000..b00e8e80
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_polygon.c
@@ -0,0 +1,211 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#include "cr_mem.h"
+#include "state.h"
+#include "state/cr_statetypes.h"
+#include "state_internals.h"
+#include "cr_pixeldata.h"
+
+void crStatePolygonInit(CRContext *ctx)
+{
+ CRPolygonState *p = &ctx->polygon;
+ CRStateBits *sb = GetCurrentBits();
+ CRPolygonBits *pb = &(sb->polygon);
+ int i;
+
+ p->polygonSmooth = GL_FALSE;
+ p->polygonOffsetFill = GL_FALSE;
+ p->polygonOffsetLine = GL_FALSE;
+ p->polygonOffsetPoint = GL_FALSE;
+ p->polygonStipple = GL_FALSE;
+ p->cullFace = GL_FALSE;
+ RESET(pb->enable, ctx->bitid);
+
+ p->offsetFactor = 0;
+ p->offsetUnits = 0;
+ RESET(pb->offset, ctx->bitid);
+
+ p->cullFaceMode = GL_BACK;
+ p->frontFace = GL_CCW;
+ p->frontMode = GL_FILL;
+ p->backMode = GL_FILL;
+ RESET(pb->mode, ctx->bitid);
+
+ for (i=0; i<32; i++)
+ p->stipple[i] = 0xFFFFFFFF;
+ RESET(pb->stipple, ctx->bitid);
+
+ RESET(pb->dirty, ctx->bitid);
+}
+
+void STATE_APIENTRY crStateCullFace(GLenum mode)
+{
+ CRContext *g = GetCurrentContext();
+ CRPolygonState *p = &(g->polygon);
+ CRStateBits *sb = GetCurrentBits();
+ CRPolygonBits *pb = &(sb->polygon);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glCullFace called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ if (mode != GL_FRONT && mode != GL_BACK && mode != GL_FRONT_AND_BACK)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glCullFace called with bogus mode: 0x%x", mode);
+ return;
+ }
+
+ p->cullFaceMode = mode;
+ DIRTY(pb->mode, g->neg_bitid);
+ DIRTY(pb->dirty, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateFrontFace (GLenum mode)
+{
+ CRContext *g = GetCurrentContext();
+ CRPolygonState *p = &(g->polygon);
+ CRStateBits *sb = GetCurrentBits();
+ CRPolygonBits *pb = &(sb->polygon);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glFrontFace called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ if (mode != GL_CW && mode != GL_CCW)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glFrontFace called with bogus mode: 0x%x", mode);
+ return;
+ }
+
+ p->frontFace = mode;
+ DIRTY(pb->mode, g->neg_bitid);
+ DIRTY(pb->dirty, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStatePolygonMode (GLenum face, GLenum mode)
+{
+ CRContext *g = GetCurrentContext();
+ CRPolygonState *p = &(g->polygon);
+ CRStateBits *sb = GetCurrentBits();
+ CRPolygonBits *pb = &(sb->polygon);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glPolygonMode called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ if (mode != GL_POINT && mode != GL_LINE && mode != GL_FILL)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glPolygonMode called with bogus mode: 0x%x", mode);
+ return;
+ }
+
+ switch (face) {
+ case GL_FRONT:
+ p->frontMode = mode;
+ break;
+ case GL_FRONT_AND_BACK:
+ p->frontMode = mode;
+ RT_FALL_THRU();
+ case GL_BACK:
+ p->backMode = mode;
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glPolygonMode called with bogus face: 0x%x", face);
+ return;
+ }
+ DIRTY(pb->mode, g->neg_bitid);
+ DIRTY(pb->dirty, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStatePolygonOffset (GLfloat factor, GLfloat units)
+{
+ CRContext *g = GetCurrentContext();
+ CRPolygonState *p = &(g->polygon);
+ CRStateBits *sb = GetCurrentBits();
+ CRPolygonBits *pb = &(sb->polygon);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glPolygonOffset called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ p->offsetFactor = factor;
+ p->offsetUnits = units;
+
+ DIRTY(pb->offset, g->neg_bitid);
+ DIRTY(pb->dirty, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStatePolygonStipple (const GLubyte *p)
+{
+ CRContext *g = GetCurrentContext();
+ CRPolygonState *poly = &(g->polygon);
+ CRStateBits *sb = GetCurrentBits();
+ CRPolygonBits *pb = &(sb->polygon);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glPolygonStipple called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ if (!p && !crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB))
+ {
+ crDebug("Void pointer passed to PolygonStipple");
+ return;
+ }
+
+ /** @todo track mask if buffer is bound?*/
+ if (!crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB))
+ {
+ crMemcpy((char*)poly->stipple, (char*)p, 128);
+ }
+
+ DIRTY(pb->dirty, g->neg_bitid);
+ DIRTY(pb->stipple, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateGetPolygonStipple( GLubyte *b )
+{
+ CRContext *g = GetCurrentContext();
+ CRPolygonState *poly = &(g->polygon);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetPolygonStipple called in begin/end");
+ return;
+ }
+
+ crMemcpy((char*)b, (char*)poly->stipple, 128);
+}
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_polygon.txt b/src/VBox/GuestHost/OpenGL/state_tracker/state_polygon.txt
new file mode 100644
index 00000000..8867dfbc
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_polygon.txt
@@ -0,0 +1,22 @@
+# Copyright (c) 2001, Stanford University
+# All rights reserved.
+#
+# See the file LICENSE.txt for information on redistributing this software.
+:enable:polygonSmooth:GL_POLYGON_SMOOTH
+:enable:polygonOffsetFill:GL_POLYGON_OFFSET_FILL
+:enable:polygonOffsetLine:GL_POLYGON_OFFSET_LINE
+:enable:polygonOffsetPoint:GL_POLYGON_OFFSET_POINT
+:enable:polygonStipple:GL_POLYGON_STIPPLE
+:enable:cullFace:GL_CULL_FACE
+:offset:offsetFactor,offsetUnits:PolygonOffset
+:mode:frontFace:FrontFace
+:mode:cullFaceMode:CullFace
+:mode:backMode:PolygonMode,GL_BACK
+:mode:frontMode:PolygonMode,GL_FRONT
+-:stipple:stipple:*diff_api.PolygonStipple ((GLubyte *) to->stipple);
++:stipple:*int iStripple;
++:stipple:*diff_api.PolygonStipple ((GLubyte *) to->stipple);
++:stipple:*for (iStripple=0; iStripple<32; iStripple++)
++:stipple:*{
++:stipple:* from->stipple[iStripple] = to->stipple[iStripple];
++:stipple:*}
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_program.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_program.c
new file mode 100644
index 00000000..b7ed0fba
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_program.c
@@ -0,0 +1,2392 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#include "state.h"
+#include "state_internals.h"
+#include "cr_mem.h"
+#include "cr_string.h"
+
+
+/*
+ * General notes:
+ *
+ * Vertex programs can change vertices so bounding boxes may not be
+ * practical for tilesort. Tilesort may have to broadcast geometry
+ * when vertex programs are in effect. We could semi-parse vertex
+ * programs to determine if they write to the o[HPOS] register.
+ */
+
+
+/*
+ * Lookup the named program and return a pointer to it.
+ * If the program doesn't exist, create it and reserve its Id and put
+ * it into the hash table.
+ */
+static CRProgram *
+GetProgram(CRProgramState *p, GLenum target, GLuint id)
+{
+ CRProgram *prog;
+
+ prog = crHashtableSearch(p->programHash, id);
+ if (!prog) {
+ prog = (CRProgram *) crCalloc(sizeof(CRProgram));
+ if (!prog)
+ return NULL;
+ prog->target = target;
+ prog->id = id;
+ prog->format = GL_PROGRAM_FORMAT_ASCII_ARB;
+ prog->resident = GL_TRUE;
+ prog->symbolTable = NULL;
+
+ if (id > 0)
+ crHashtableAdd(p->programHash, id, (void *) prog);
+ }
+ return prog;
+}
+
+
+/*
+ * Delete a CRProgram object and all attached data.
+ */
+static void
+DeleteProgram(CRProgram *prog)
+{
+ CRProgramSymbol *symbol, *next;
+
+ if (prog->string)
+ crFree((void *) prog->string);
+
+ for (symbol = prog->symbolTable; symbol; symbol = next) {
+ next = symbol->next;
+ crFree((void *) symbol->name);
+ crFree(symbol);
+ }
+ crFree(prog);
+}
+
+
+/*
+ * Set the named symbol to the value (x, y, z, w).
+ * NOTE: Symbols should only really be added during parsing of the program.
+ * However, the state tracker does not parse the programs (yet). So, when
+ * someone calls glProgramNamedParameter4fNV() we always enter the symbol
+ * since we don't know if it's really valid or not.
+ */
+static void
+SetProgramSymbol(CRProgram *prog, const char *name, GLsizei len,
+ GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ CRProgramSymbol *symbol;
+
+ for (symbol = prog->symbolTable; symbol; symbol = symbol->next) {
+ /* NOTE: <name> may not be null-terminated! */
+ if (crStrncmp(symbol->name, name, len) == 0 && symbol->name[len] == 0) {
+ /* found it */
+ symbol->value[0] = x;
+ symbol->value[1] = y;
+ symbol->value[2] = z;
+ symbol->value[3] = w;
+ FILLDIRTY(symbol->dirty);
+ return;
+ }
+ }
+ /* add new symbol table entry */
+ symbol = (CRProgramSymbol *) crAlloc(sizeof(CRProgramSymbol));
+ if (symbol) {
+ symbol->name = crStrndup(name, len);
+ symbol->cbName = len;
+ symbol->value[0] = x;
+ symbol->value[1] = y;
+ symbol->value[2] = z;
+ symbol->value[3] = w;
+ symbol->next = prog->symbolTable;
+ prog->symbolTable = symbol;
+ FILLDIRTY(symbol->dirty);
+ }
+}
+
+
+/*
+ * Return a pointer to the values for the given symbol. Return NULL if
+ * the name doesn't exist in the symbol table.
+ */
+static const GLfloat *
+GetProgramSymbol(const CRProgram *prog, const char *name, GLsizei len)
+{
+ CRProgramSymbol *symbol = prog->symbolTable;
+ for (symbol = prog->symbolTable; symbol; symbol = symbol->next) {
+ /* NOTE: <name> may not be null-terminated! */
+ if (crStrncmp(symbol->name, name, len) == 0 && symbol->name[len] == 0) {
+ return symbol->value;
+ }
+ }
+ return NULL;
+}
+
+
+/*
+ * Used by both glBindProgramNV and glBindProgramARB
+ */
+static CRProgram *
+BindProgram(GLenum target, GLuint id,
+ GLenum vertexTarget, GLenum fragmentTarget)
+{
+ CRContext *g = GetCurrentContext();
+ CRProgramState *p = &(g->program);
+ CRStateBits *sb = GetCurrentBits();
+ CRProgramBits *pb = &(sb->program);
+ CRProgram *prog;
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glBindProgram called in Begin/End");
+ return NULL;
+ }
+
+ if (id == 0) {
+ if (target == vertexTarget) {
+ prog = p->defaultVertexProgram;
+ }
+ else if (target == fragmentTarget) {
+ prog = p->defaultFragmentProgram;
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glBindProgram(bad target)");
+ return NULL;
+ }
+ }
+ else {
+ prog = GetProgram(p, target, id );
+ }
+
+ if (!prog) {
+ crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, "glBindProgram");
+ return NULL;
+ }
+ else if (prog->target != target) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glBindProgram target mismatch");
+ return NULL;
+ }
+
+ if (target == vertexTarget) {
+ p->currentVertexProgram = prog;
+ p->vpProgramBinding = id;
+ DIRTY(pb->dirty, g->neg_bitid);
+ DIRTY(pb->vpBinding, g->neg_bitid);
+ }
+ else if (target == fragmentTarget) {
+ p->currentFragmentProgram = prog;
+ p->fpProgramBinding = id;
+ DIRTY(pb->dirty, g->neg_bitid);
+ DIRTY(pb->fpBinding, g->neg_bitid);
+ }
+ return prog;
+}
+
+
+void STATE_APIENTRY crStateBindProgramNV(GLenum target, GLuint id)
+{
+ CRProgram *prog = BindProgram(target, id, GL_VERTEX_PROGRAM_NV,
+ GL_FRAGMENT_PROGRAM_NV);
+ if (prog) {
+ prog->isARBprogram = GL_FALSE;
+ }
+}
+
+
+void STATE_APIENTRY crStateBindProgramARB(GLenum target, GLuint id)
+{
+ CRProgram *prog = BindProgram(target, id, GL_VERTEX_PROGRAM_ARB,
+ GL_FRAGMENT_PROGRAM_ARB);
+ if (prog) {
+ prog->isARBprogram = GL_TRUE;
+ }
+}
+
+
+void STATE_APIENTRY crStateDeleteProgramsARB(GLsizei n, const GLuint *ids)
+{
+ CRContext *g = GetCurrentContext();
+ CRProgramState *p = &(g->program);
+ CRStateBits *sb = GetCurrentBits();
+ CRProgramBits *pb = &(sb->program);
+ GLint i;
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glDeleteProgramsNV called in Begin/End");
+ return;
+ }
+
+ if (n < 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glDeleteProgramsNV(n)");
+ return;
+ }
+
+ for (i = 0; i < n; i++) {
+ CRProgram *prog;
+ if (ids[i] > 0) {
+ prog = (CRProgram *) crHashtableSearch(p->programHash, ids[i]);
+ if (prog == p->currentVertexProgram) {
+ p->currentVertexProgram = p->defaultVertexProgram;
+ DIRTY(pb->dirty, g->neg_bitid);
+ DIRTY(pb->vpBinding, g->neg_bitid);
+ }
+ else if (prog == p->currentFragmentProgram) {
+ p->currentFragmentProgram = p->defaultFragmentProgram;
+ DIRTY(pb->dirty, g->neg_bitid);
+ DIRTY(pb->fpBinding, g->neg_bitid);
+ }
+ if (prog) {
+ DeleteProgram(prog);
+ }
+ crHashtableDelete(p->programHash, ids[i], GL_FALSE);
+ }
+ }
+}
+
+
+void STATE_APIENTRY crStateExecuteProgramNV(GLenum target, GLuint id, const GLfloat *params)
+{
+ /* Hmmm, this is really hard to do if we don't actually execute
+ * the program in a software simulation.
+ */
+ (void)params;
+ (void)target;
+ (void)id;
+}
+
+
+void STATE_APIENTRY crStateGenProgramsNV(GLsizei n, GLuint *ids)
+{
+ CRContext *g = GetCurrentContext();
+ CRProgramState *p = &(g->program);
+
+ crStateGenNames(g, p->programHash, n, ids);
+}
+
+void STATE_APIENTRY crStateGenProgramsARB(GLsizei n, GLuint *ids)
+{
+ crStateGenProgramsNV(n, ids);
+}
+
+
+GLboolean STATE_APIENTRY crStateIsProgramARB(GLuint id)
+{
+ CRContext *g = GetCurrentContext();
+ CRProgramState *p = &(g->program);
+ CRProgram *prog;
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glIsProgram called in Begin/End");
+ return GL_FALSE;
+ }
+
+ if (id == 0) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glIsProgram(id==0)");
+ return GL_FALSE;
+ }
+
+ prog = (CRProgram *) crHashtableSearch(p->programHash, id);
+ if (prog)
+ return GL_TRUE;
+ else
+ return GL_FALSE;
+}
+
+
+GLboolean STATE_APIENTRY crStateAreProgramsResidentNV(GLsizei n, const GLuint *ids, GLboolean *residences)
+{
+ CRContext *g = GetCurrentContext();
+ CRProgramState *p = &(g->program);
+ int i;
+ GLboolean retVal = GL_TRUE;
+
+ if (n < 0) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glAreProgramsResidentNV(n)");
+ return GL_FALSE;
+ }
+
+ for (i = 0; i < n; i++) {
+ CRProgram *prog;
+
+ if (ids[i] == 0) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glAreProgramsResidentNV(id)");
+ return GL_FALSE;
+ }
+
+ prog = (CRProgram *) crHashtableSearch(p->programHash, ids[i]);
+ if (!prog) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glAreProgramsResidentNV(id)");
+ return GL_FALSE;
+ }
+
+ if (!prog->resident) {
+ retVal = GL_FALSE;
+ break;
+ }
+ }
+
+ if (retVal == GL_FALSE) {
+ for (i = 0; i < n; i++) {
+ CRProgram *prog = (CRProgram *)
+ crHashtableSearch(p->programHash, ids[i]);
+ residences[i] = prog->resident;
+ }
+ }
+
+ return retVal;
+}
+
+
+void STATE_APIENTRY crStateRequestResidentProgramsNV(GLsizei n, const GLuint *ids)
+{
+ CRContext *g = GetCurrentContext();
+ CRProgramState *p = &(g->program);
+ GLint i;
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glRequestResidentProgramsNV called in Begin/End");
+ return;
+ }
+
+ if (n < 0) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glRequestResidentProgramsNV(n<0)");
+ return;
+ }
+
+ for (i = 0; i < n ; i++) {
+ CRProgram *prog = (CRProgram *) crHashtableSearch(p->programHash, ids[i]);
+ if (prog)
+ prog->resident = GL_TRUE;
+ }
+}
+
+
+void STATE_APIENTRY crStateLoadProgramNV(GLenum target, GLuint id, GLsizei len,
+ const GLubyte *program)
+{
+ CRContext *g = GetCurrentContext();
+ CRProgramState *p = &(g->program);
+ CRStateBits *sb = GetCurrentBits();
+ CRProgramBits *pb = &(sb->program);
+ CRProgram *prog;
+ GLubyte *progCopy;
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glLoadProgramNV called in Begin/End");
+ return;
+ }
+
+ if (id == 0) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glLoadProgramNV(id==0)");
+ return;
+ }
+
+ prog = GetProgram(p, target, id);
+
+ if (!prog) {
+ crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, "glLoadProgramNV");
+ return;
+ }
+ else if (prog && prog->target != target) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glLoadProgramNV(target)");
+ return;
+ }
+
+ progCopy = crAlloc(len);
+ if (!progCopy) {
+ crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, "glLoadProgramNV");
+ return;
+ }
+ if (crStrncmp((const char *) program,"!!FP1.0", 7) != 0
+ && crStrncmp((const char *) program,"!!FCP1.0", 8) != 0
+ && crStrncmp((const char *) program,"!!VP1.0", 7) != 0
+ && crStrncmp((const char *) program,"!!VP1.1", 7) != 0
+ && crStrncmp((const char *) program,"!!VP2.0", 7) != 0
+ && crStrncmp((const char *) program,"!!VSP1.0", 8) != 0) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glLoadProgramNV");
+ crDebug("program = (%s)\n",program);
+ return;
+ }
+ crMemcpy(progCopy, program, len);
+ if (prog->string)
+ crFree((void *) prog->string);
+
+ prog->string = progCopy;
+ prog->length = len;
+ prog->isARBprogram = GL_FALSE;
+
+ DIRTY(prog->dirtyProgram, g->neg_bitid);
+ DIRTY(pb->dirty, g->neg_bitid);
+}
+
+
+void STATE_APIENTRY crStateProgramStringARB(GLenum target, GLenum format,
+ GLsizei len, const GLvoid *string)
+{
+ CRContext *g = GetCurrentContext();
+ CRProgramState *p = &(g->program);
+ CRStateBits *sb = GetCurrentBits();
+ CRProgramBits *pb = &(sb->program);
+ CRProgram *prog;
+ GLubyte *progCopy;
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glProgramStringARB called in Begin/End");
+ return;
+ }
+
+ if (format != GL_PROGRAM_FORMAT_ASCII_ARB) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glProgramStringARB(format)");
+ return;
+ }
+
+ if (target == GL_FRAGMENT_PROGRAM_ARB
+ && g->extensions.ARB_fragment_program) {
+ prog = p->currentFragmentProgram;
+ }
+ else if (target == GL_VERTEX_PROGRAM_ARB
+ && g->extensions.ARB_vertex_program) {
+ prog = p->currentVertexProgram;
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glProgramStringARB(target)");
+ return;
+ }
+
+ CRASSERT(prog);
+
+
+ progCopy = crAlloc(len);
+ if (!progCopy) {
+ crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, "glProgramStringARB");
+ return;
+ }
+ if (crStrncmp(string,"!!ARBvp1.0", 10) != 0
+ && crStrncmp(string,"!!ARBfp1.0", 10) != 0) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glProgramStringARB");
+ return;
+ }
+ crMemcpy(progCopy, string, len);
+ if (prog->string)
+ crFree((void *) prog->string);
+
+ prog->string = progCopy;
+ prog->length = len;
+ prog->format = format;
+ prog->isARBprogram = GL_TRUE;
+
+ DIRTY(prog->dirtyProgram, g->neg_bitid);
+ DIRTY(pb->dirty, g->neg_bitid);
+}
+
+
+void STATE_APIENTRY crStateGetProgramivNV(GLuint id, GLenum pname, GLint *params)
+{
+ CRContext *g = GetCurrentContext();
+ CRProgramState *p = &(g->program);
+ CRProgram *prog;
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetProgramivNV called in Begin/End");
+ return;
+ }
+
+ if (id == 0) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetProgramivNV(bad id)");
+ return;
+ }
+
+ prog = (CRProgram *) crHashtableSearch(p->programHash, id);
+ if (!prog) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetProgramivNV(bad id)");
+ return;
+ }
+
+ switch (pname) {
+ case GL_PROGRAM_TARGET_NV:
+ *params = prog->target;
+ return;
+ case GL_PROGRAM_LENGTH_NV:
+ *params = prog->length;
+ return;
+ case GL_PROGRAM_RESIDENT_NV:
+ *params = prog->resident;
+ return;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetProgramivNV(pname)");
+ return;
+ }
+}
+
+
+void STATE_APIENTRY crStateGetProgramStringNV(GLuint id, GLenum pname, GLubyte *program)
+{
+ CRContext *g = GetCurrentContext();
+ CRProgramState *p = &(g->program);
+ CRProgram *prog;
+
+ if (pname != GL_PROGRAM_STRING_NV) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetProgramStringNV(pname)");
+ return;
+ }
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetProgramStringNV called in Begin/End");
+ return;
+ }
+
+ if (id == 0) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetProgramStringNV(bad id)");
+ return;
+ }
+
+ prog = (CRProgram *) crHashtableSearch(p->programHash, id);
+ if (!prog) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetProgramStringNV(bad id)");
+ return;
+ }
+
+ crMemcpy(program, prog->string, prog->length);
+}
+
+
+void STATE_APIENTRY crStateGetProgramStringARB(GLenum target, GLenum pname, GLvoid *string)
+{
+ CRContext *g = GetCurrentContext();
+ CRProgramState *p = &(g->program);
+ CRProgram *prog;
+
+ if (target == GL_VERTEX_PROGRAM_ARB) {
+ prog = p->currentVertexProgram;
+ }
+ else if (target == GL_FRAGMENT_PROGRAM_ARB) {
+ prog = p->currentFragmentProgram;
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetProgramStringNV(target)");
+ return;
+ }
+
+ if (pname != GL_PROGRAM_STRING_NV) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetProgramStringNV(pname)");
+ return;
+ }
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetProgramStringNV called in Begin/End");
+ return;
+ }
+
+ crMemcpy(string, prog->string, prog->length);
+}
+
+
+void STATE_APIENTRY crStateProgramParameter4dNV(GLenum target, GLuint index,
+ GLdouble x, GLdouble y, GLdouble z, GLdouble w)
+{
+ crStateProgramParameter4fNV(target, index, (GLfloat) x, (GLfloat) y,
+ (GLfloat) z, (GLfloat) w);
+}
+
+
+void STATE_APIENTRY crStateProgramParameter4dvNV(GLenum target, GLuint index,
+ const GLdouble *params)
+{
+ crStateProgramParameter4fNV(target, index,
+ (GLfloat) params[0], (GLfloat) params[1],
+ (GLfloat) params[2], (GLfloat) params[3]);
+}
+
+
+void STATE_APIENTRY crStateProgramParameter4fNV(GLenum target, GLuint index,
+ GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ CRContext *g = GetCurrentContext();
+ CRProgramState *p = &(g->program);
+ CRStateBits *sb = GetCurrentBits();
+ CRProgramBits *pb = &(sb->program);
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glProgramParameterNV called in Begin/End");
+ return;
+ }
+
+ if (target == GL_VERTEX_PROGRAM_NV) {
+ if (index < g->limits.maxVertexProgramEnvParams) {
+ p->vertexParameters[index][0] = x;
+ p->vertexParameters[index][1] = y;
+ p->vertexParameters[index][2] = z;
+ p->vertexParameters[index][3] = w;
+ DIRTY(pb->dirty, g->neg_bitid);
+ DIRTY(pb->vertexEnvParameter[index], g->neg_bitid);
+ DIRTY(pb->vertexEnvParameters, g->neg_bitid);
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glProgramParameterNV(index=%d)", index);
+ return;
+ }
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glProgramParameterNV(target)");
+ return;
+ }
+}
+
+
+void STATE_APIENTRY crStateProgramParameter4fvNV(GLenum target, GLuint index,
+ const GLfloat *params)
+{
+ crStateProgramParameter4fNV(target, index,
+ params[0], params[1], params[2], params[3]);
+}
+
+
+void STATE_APIENTRY crStateProgramParameters4dvNV(GLenum target, GLuint index,
+ GLuint num, const GLdouble *params)
+{
+ CRContext *g = GetCurrentContext();
+ CRProgramState *p = &(g->program);
+ CRStateBits *sb = GetCurrentBits();
+ CRProgramBits *pb = &(sb->program);
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glProgramParameters4dvNV called in Begin/End");
+ return;
+ }
+
+ if (target == GL_VERTEX_PROGRAM_NV) {
+ if (index >= UINT32_MAX - num) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glProgramParameters4dvNV(index+num) integer overflow");
+ return;
+ }
+
+ if (index + num < g->limits.maxVertexProgramEnvParams) {
+ GLuint i;
+ for (i = 0; i < num; i++) {
+ p->vertexParameters[index+i][0] = (GLfloat) params[i*4+0];
+ p->vertexParameters[index+i][1] = (GLfloat) params[i*4+1];
+ p->vertexParameters[index+i][2] = (GLfloat) params[i*4+2];
+ p->vertexParameters[index+i][3] = (GLfloat) params[i*4+3];
+ }
+ DIRTY(pb->dirty, g->neg_bitid);
+ DIRTY(pb->vertexEnvParameters, g->neg_bitid);
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glProgramParameters4dvNV(index+num)");
+ return;
+ }
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glProgramParameterNV(target)");
+ return;
+ }
+}
+
+
+void STATE_APIENTRY crStateProgramParameters4fvNV(GLenum target, GLuint index,
+ GLuint num, const GLfloat *params)
+{
+ CRContext *g = GetCurrentContext();
+ CRProgramState *p = &(g->program);
+ CRStateBits *sb = GetCurrentBits();
+ CRProgramBits *pb = &(sb->program);
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glProgramParameters4dvNV called in Begin/End");
+ return;
+ }
+
+ if (target == GL_VERTEX_PROGRAM_NV) {
+ if (index >= UINT32_MAX - num) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glProgramParameters4dvNV(index+num) integer overflow");
+ return;
+ }
+
+ if (index + num < g->limits.maxVertexProgramEnvParams) {
+ GLuint i;
+ for (i = 0; i < num; i++) {
+ p->vertexParameters[index+i][0] = params[i*4+0];
+ p->vertexParameters[index+i][1] = params[i*4+1];
+ p->vertexParameters[index+i][2] = params[i*4+2];
+ p->vertexParameters[index+i][3] = params[i*4+3];
+ }
+ DIRTY(pb->dirty, g->neg_bitid);
+ DIRTY(pb->vertexEnvParameters, g->neg_bitid);
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glProgramParameters4dvNV(index+num)");
+ return;
+ }
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glProgramParameterNV(target)");
+ return;
+ }
+}
+
+
+void STATE_APIENTRY crStateGetProgramParameterfvNV(GLenum target, GLuint index,
+ GLenum pname, GLfloat *params)
+{
+ CRContext *g = GetCurrentContext();
+ CRProgramState *p = &(g->program);
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetProgramParameterfvNV called in Begin/End");
+ return;
+ }
+
+ if (target == GL_VERTEX_PROGRAM_NV) {
+ if (pname == GL_PROGRAM_PARAMETER_NV) {
+ if (index < g->limits.maxVertexProgramEnvParams) {
+ params[0] = p->vertexParameters[index][0];
+ params[1] = p->vertexParameters[index][1];
+ params[2] = p->vertexParameters[index][2];
+ params[3] = p->vertexParameters[index][3];
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glGetProgramParameterfvNV(index)");
+ return;
+ }
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetProgramParameterfvNV(pname)");
+ return;
+ }
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetProgramParameterfvNV(target)");
+ return;
+ }
+}
+
+
+void STATE_APIENTRY crStateGetProgramParameterdvNV(GLenum target, GLuint index,
+ GLenum pname, GLdouble *params)
+{
+ CRContext *g = GetCurrentContext();
+ CRProgramState *p = &(g->program);
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetProgramParameterdvNV called in Begin/End");
+ return;
+ }
+
+ if (target == GL_VERTEX_PROGRAM_NV) {
+ if (pname == GL_PROGRAM_PARAMETER_NV) {
+ if (index < g->limits.maxVertexProgramEnvParams) {
+ params[0] = p->vertexParameters[index][0];
+ params[1] = p->vertexParameters[index][1];
+ params[2] = p->vertexParameters[index][2];
+ params[3] = p->vertexParameters[index][3];
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glGetProgramParameterdvNV(index)");
+ return;
+ }
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetProgramParameterdvNV(pname)");
+ return;
+ }
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetProgramParameterdvNV(target)");
+ return;
+ }
+}
+
+
+void STATE_APIENTRY crStateTrackMatrixNV(GLenum target, GLuint address,
+ GLenum matrix, GLenum transform)
+{
+ CRContext *g = GetCurrentContext();
+ CRProgramState *p = &(g->program);
+ CRStateBits *sb = GetCurrentBits();
+ CRProgramBits *pb = &(sb->program);
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetTrackMatrixivNV called in Begin/End");
+ return;
+ }
+
+ if (target == GL_VERTEX_PROGRAM_NV) {
+ if (address & 0x3 || address >= g->limits.maxVertexProgramEnvParams) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glTrackMatrixNV(address)");
+ return;
+ }
+
+ switch (matrix) {
+ case GL_NONE:
+ case GL_MODELVIEW:
+ case GL_PROJECTION:
+ case GL_TEXTURE:
+ case GL_COLOR:
+ case GL_MODELVIEW_PROJECTION_NV:
+ case GL_MATRIX0_NV:
+ case GL_MATRIX1_NV:
+ case GL_MATRIX2_NV:
+ case GL_MATRIX3_NV:
+ case GL_MATRIX4_NV:
+ case GL_MATRIX5_NV:
+ case GL_MATRIX6_NV:
+ case GL_MATRIX7_NV:
+ case GL_TEXTURE0_ARB:
+ case GL_TEXTURE1_ARB:
+ case GL_TEXTURE2_ARB:
+ case GL_TEXTURE3_ARB:
+ case GL_TEXTURE4_ARB:
+ case GL_TEXTURE5_ARB:
+ case GL_TEXTURE6_ARB:
+ case GL_TEXTURE7_ARB:
+ /* OK, fallthrough */
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glTrackMatrixNV(matrix = %x)",matrix);
+ return;
+ }
+
+ switch (transform) {
+ case GL_IDENTITY_NV:
+ case GL_INVERSE_NV:
+ case GL_TRANSPOSE_NV:
+ case GL_INVERSE_TRANSPOSE_NV:
+ /* OK, fallthrough */
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glTrackMatrixNV(transform = %x)",transform);
+ return;
+ }
+
+ p->TrackMatrix[address / 4] = matrix;
+ p->TrackMatrixTransform[address / 4] = transform;
+ DIRTY(pb->trackMatrix[address/4], g->neg_bitid);
+ DIRTY(pb->dirty, g->neg_bitid);
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glTrackMatrixNV(target = %x)",target);
+ }
+}
+
+
+void STATE_APIENTRY crStateGetTrackMatrixivNV(GLenum target, GLuint address,
+ GLenum pname, GLint *params)
+{
+ CRContext *g = GetCurrentContext();
+ CRProgramState *p = &(g->program);
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetTrackMatrixivNV called in Begin/End");
+ return;
+ }
+
+ if (target == GL_VERTEX_PROGRAM_NV) {
+ if ((address & 0x3) || address >= g->limits.maxVertexProgramEnvParams) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glGetTrackMatrixivNV(address)");
+ return;
+ }
+ if (pname == GL_TRACK_MATRIX_NV) {
+ params[0] = (GLint) p->TrackMatrix[address / 4];
+ }
+ else if (pname == GL_TRACK_MATRIX_TRANSFORM_NV) {
+ params[0] = (GLint) p->TrackMatrixTransform[address / 4];
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetTrackMatrixivNV(pname)");
+ return;
+ }
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetTrackMatrixivNV(target)");
+ return;
+ }
+}
+
+
+void STATE_APIENTRY crStateGetVertexAttribdvNV(GLuint index, GLenum pname, GLdouble *params)
+{
+ /* init vars to prevent compiler warnings/errors */
+ GLfloat floatParams[4] = { 0.0, 0.0, 0.0, 0.0 };
+ crStateGetVertexAttribfvNV(index, pname, floatParams);
+ params[0] = floatParams[0];
+ if (pname == GL_CURRENT_ATTRIB_NV) {
+ params[1] = floatParams[1];
+ params[2] = floatParams[2];
+ params[3] = floatParams[3];
+ }
+}
+
+
+void STATE_APIENTRY crStateGetVertexAttribfvNV(GLuint index, GLenum pname, GLfloat *params)
+{
+ CRContext *g = GetCurrentContext();
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetVertexAttribfvNV called in Begin/End");
+ return;
+ }
+
+ if (index >= CR_MAX_VERTEX_ATTRIBS) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glGetVertexAttribfvNV(index)");
+ return;
+ }
+
+ switch (pname) {
+ case GL_ATTRIB_ARRAY_SIZE_NV:
+ params[0] = (GLfloat) g->client.array.a[index].size;
+ break;
+ case GL_ATTRIB_ARRAY_STRIDE_NV:
+ params[0] = (GLfloat) g->client.array.a[index].stride;
+ break;
+ case GL_ATTRIB_ARRAY_TYPE_NV:
+ params[0] = (GLfloat) g->client.array.a[index].type;
+ break;
+ case GL_CURRENT_ATTRIB_NV:
+ crStateCurrentRecover();
+ COPY_4V(params , g->current.vertexAttrib[index]);
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetVertexAttribfvNV");
+ return;
+ }
+}
+
+
+void STATE_APIENTRY crStateGetVertexAttribivNV(GLuint index, GLenum pname, GLint *params)
+{
+ /* init vars to prevent compiler warnings/errors */
+ GLfloat floatParams[4] = { 0.0, 0.0, 0.0, 0.0 };
+ crStateGetVertexAttribfvNV(index, pname, floatParams);
+ params[0] = (GLint) floatParams[0];
+ if (pname == GL_CURRENT_ATTRIB_NV) {
+ params[1] = (GLint) floatParams[1];
+ params[2] = (GLint) floatParams[2];
+ params[3] = (GLint) floatParams[3];
+ }
+}
+
+
+
+void STATE_APIENTRY crStateGetVertexAttribfvARB(GLuint index, GLenum pname, GLfloat *params)
+{
+ CRContext *g = GetCurrentContext();
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetVertexAttribfvARB called in Begin/End");
+ return;
+ }
+
+ if (index >= CR_MAX_VERTEX_ATTRIBS) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glGetVertexAttribfvARB(index)");
+ return;
+ }
+
+ switch (pname) {
+ case GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB:
+ params[0] = (GLfloat) g->client.array.a[index].enabled;
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB:
+ params[0] = (GLfloat) g->client.array.a[index].size;
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB:
+ params[0] = (GLfloat) g->client.array.a[index].stride;
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB:
+ params[0] = (GLfloat) g->client.array.a[index].type;
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB:
+ params[0] = (GLfloat) g->client.array.a[index].normalized;
+ break;
+ case GL_CURRENT_VERTEX_ATTRIB_ARB:
+ crStateCurrentRecover();
+ COPY_4V(params , g->current.vertexAttrib[index]);
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetVertexAttribfvARB");
+ return;
+ }
+}
+
+
+void STATE_APIENTRY crStateGetVertexAttribivARB(GLuint index, GLenum pname, GLint *params)
+{
+ /* init vars to prevent compiler warnings/errors */
+ GLfloat floatParams[4] = { 0.0, 0.0, 0.0, 0.0 };
+ crStateGetVertexAttribfvARB(index, pname, floatParams);
+ params[0] = (GLint) floatParams[0];
+ if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
+ params[1] = (GLint) floatParams[1];
+ params[2] = (GLint) floatParams[2];
+ params[3] = (GLint) floatParams[3];
+ }
+}
+
+
+void STATE_APIENTRY crStateGetVertexAttribdvARB(GLuint index, GLenum pname, GLdouble *params)
+{
+ /* init vars to prevent compiler warnings/errors */
+ GLfloat floatParams[4] = { 0.0, 0.0, 0.0, 0.0 };
+ crStateGetVertexAttribfvARB(index, pname, floatParams);
+ params[0] = floatParams[0];
+ if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
+ params[1] = floatParams[1];
+ params[2] = floatParams[2];
+ params[3] = floatParams[3];
+ }
+}
+
+
+/**********************************************************************/
+
+/*
+ * Added by GL_NV_fragment_program
+ */
+
+void STATE_APIENTRY crStateProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ CRContext *g = GetCurrentContext();
+ CRProgramState *p = &(g->program);
+ CRProgram *prog;
+ CRStateBits *sb = GetCurrentBits();
+ CRProgramBits *pb = &(sb->program);
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glProgramNamedParameterfNV called in Begin/End");
+ return;
+ }
+
+ prog = (CRProgram *) crHashtableSearch(p->programHash, id);
+ if (!prog) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glProgramNamedParameterNV(bad id %d)", id);
+ return;
+ }
+
+ if (prog->target != GL_FRAGMENT_PROGRAM_NV) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glProgramNamedParameterNV(target)");
+ return;
+ }
+
+ SetProgramSymbol(prog, (const char *)name, len, x, y, z, w);
+ DIRTY(prog->dirtyNamedParams, g->neg_bitid);
+ DIRTY(pb->dirty, g->neg_bitid);
+}
+
+
+void STATE_APIENTRY crStateProgramNamedParameter4dNV(GLuint id, GLsizei len, const GLubyte *name, GLdouble x, GLdouble y, GLdouble z, GLdouble w)
+{
+ crStateProgramNamedParameter4fNV(id, len, name, (GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
+}
+
+
+void STATE_APIENTRY crStateProgramNamedParameter4fvNV(GLuint id, GLsizei len, const GLubyte *name, const GLfloat v[])
+{
+ crStateProgramNamedParameter4fNV(id, len, name, v[0], v[1], v[2], v[3]);
+}
+
+
+void STATE_APIENTRY crStateProgramNamedParameter4dvNV(GLuint id, GLsizei len, const GLubyte *name, const GLdouble v[])
+{
+ crStateProgramNamedParameter4fNV(id, len, name, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]);
+}
+
+
+void STATE_APIENTRY crStateGetProgramNamedParameterfvNV(GLuint id, GLsizei len, const GLubyte *name, GLfloat *params)
+{
+ CRContext *g = GetCurrentContext();
+ CRProgramState *p = &(g->program);
+ const CRProgram *prog;
+ const GLfloat *value;
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetProgramNamedParameterfNV called in Begin/End");
+ return;
+ }
+
+ prog = (const CRProgram *) crHashtableSearch(p->programHash, id);
+ if (!prog) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetProgramNamedParameterNV(bad id)");
+ return;
+ }
+
+ if (prog->target != GL_FRAGMENT_PROGRAM_NV) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetProgramNamedParameterNV(target)");
+ return;
+ }
+
+ value = GetProgramSymbol(prog, (const char *)name, len);
+ if (!value) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glGetProgramNamedParameterNV(name)");
+ return;
+ }
+
+ params[0] = value[0];
+ params[1] = value[1];
+ params[2] = value[2];
+ params[3] = value[3];
+}
+
+
+void STATE_APIENTRY crStateGetProgramNamedParameterdvNV(GLuint id, GLsizei len, const GLubyte *name, GLdouble *params)
+{
+ GLfloat floatParams[4];
+ crStateGetProgramNamedParameterfvNV(id, len, name, floatParams);
+ params[0] = floatParams[0];
+ params[1] = floatParams[1];
+ params[2] = floatParams[2];
+ params[3] = floatParams[3];
+}
+
+
+void STATE_APIENTRY crStateProgramLocalParameter4dARB(GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w)
+{
+ crStateProgramLocalParameter4fARB(target, index, (GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
+}
+
+
+void STATE_APIENTRY crStateProgramLocalParameter4dvARB(GLenum target, GLuint index, const GLdouble *params)
+{
+ crStateProgramLocalParameter4fARB(target, index, (GLfloat) params[0], (GLfloat) params[1],
+ (GLfloat) params[2], (GLfloat) params[3]);
+}
+
+
+void STATE_APIENTRY crStateProgramLocalParameter4fARB(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ CRContext *g = GetCurrentContext();
+ CRProgramState *p = &(g->program);
+ CRProgram *prog;
+ CRStateBits *sb = GetCurrentBits();
+ CRProgramBits *pb = &(sb->program);
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glProgramLocalParameterARB called in Begin/End");
+ return;
+ }
+
+ if (target == GL_FRAGMENT_PROGRAM_ARB || target == GL_FRAGMENT_PROGRAM_NV) {
+ if (index >= CR_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMS) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glProgramLocalParameterARB(index)");
+ return;
+ }
+ prog = p->currentFragmentProgram;
+ }
+ else if (target == GL_VERTEX_PROGRAM_ARB) {
+ if (index >= CR_MAX_VERTEX_PROGRAM_LOCAL_PARAMS) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glProgramLocalParameterARB(index)");
+ return;
+ }
+ prog = p->currentVertexProgram;
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glProgramLocalParameterARB(target)");
+ return;
+ }
+
+ CRASSERT(prog);
+
+ prog->parameters[index][0] = x;
+ prog->parameters[index][1] = y;
+ prog->parameters[index][2] = z;
+ prog->parameters[index][3] = w;
+ DIRTY(prog->dirtyParam[index], g->neg_bitid);
+ DIRTY(prog->dirtyParams, g->neg_bitid);
+ DIRTY(pb->dirty, g->neg_bitid);
+}
+
+
+void STATE_APIENTRY crStateProgramLocalParameter4fvARB(GLenum target, GLuint index, const GLfloat *params)
+{
+ crStateProgramLocalParameter4fARB(target, index, params[0], params[1], params[2], params[3]);
+}
+
+
+void STATE_APIENTRY crStateGetProgramLocalParameterfvARB(GLenum target, GLuint index, GLfloat *params)
+{
+ CRContext *g = GetCurrentContext();
+ CRProgramState *p = &(g->program);
+ const CRProgram *prog = NULL;
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetProgramLocalParameterARB called in Begin/End");
+ return;
+ }
+
+ if (target == GL_FRAGMENT_PROGRAM_ARB || target == GL_FRAGMENT_PROGRAM_NV) {
+ prog = p->currentFragmentProgram;
+ if (index >= g->limits.maxFragmentProgramLocalParams) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glGetProgramLocalParameterARB(index)");
+ return;
+ }
+ }
+ else if ( target == GL_VERTEX_PROGRAM_ARB
+#if GL_VERTEX_PROGRAM_ARB != GL_VERTEX_PROGRAM_NV
+ || target == GL_VERTEX_PROGRAM_NV
+#endif
+ ) {
+ prog = p->currentVertexProgram;
+ if (index >= g->limits.maxVertexProgramLocalParams) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glGetProgramLocalParameterARB(index)");
+ return;
+ }
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetProgramLocalParameterARB(target)");
+ return;
+ }
+ if (!prog) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetProgramLocalParameterARB(no program)");
+ return;
+ }
+
+ if (!prog) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetProgramLocalParameterARB(no program)");
+ return;
+ }
+
+ CRASSERT(prog);
+ CRASSERT(index < CR_MAX_PROGRAM_LOCAL_PARAMS);
+ params[0] = prog->parameters[index][0];
+ params[1] = prog->parameters[index][1];
+ params[2] = prog->parameters[index][2];
+ params[3] = prog->parameters[index][3];
+}
+
+
+void STATE_APIENTRY crStateGetProgramLocalParameterdvARB(GLenum target, GLuint index, GLdouble *params)
+{
+ GLfloat floatParams[4];
+ crStateGetProgramLocalParameterfvARB(target, index, floatParams);
+ params[0] = floatParams[0];
+ params[1] = floatParams[1];
+ params[2] = floatParams[2];
+ params[3] = floatParams[3];
+}
+
+
+
+void STATE_APIENTRY crStateGetProgramivARB(GLenum target, GLenum pname, GLint *params)
+{
+ CRProgram *prog;
+ CRContext *g = GetCurrentContext();
+ CRProgramState *p = &(g->program);
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetProgramivARB called in Begin/End");
+ return;
+ }
+
+ if (target == GL_VERTEX_PROGRAM_ARB) {
+ prog = p->currentVertexProgram;
+ }
+ else if (target == GL_FRAGMENT_PROGRAM_ARB) {
+ prog = p->currentFragmentProgram;
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetProgramivARB(target)");
+ return;
+ }
+
+ CRASSERT(prog);
+
+ switch (pname) {
+ case GL_PROGRAM_LENGTH_ARB:
+ *params = prog->length;
+ break;
+ case GL_PROGRAM_FORMAT_ARB:
+ *params = prog->format;
+ break;
+ case GL_PROGRAM_BINDING_ARB:
+ *params = prog->id;
+ break;
+ case GL_PROGRAM_INSTRUCTIONS_ARB:
+ *params = prog->numInstructions;
+ break;
+ case GL_MAX_PROGRAM_INSTRUCTIONS_ARB:
+ if (target == GL_VERTEX_PROGRAM_ARB)
+ *params = g->limits.maxVertexProgramInstructions;
+ else
+ *params = g->limits.maxFragmentProgramInstructions;
+ break;
+ case GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB:
+ *params = prog->numInstructions;
+ break;
+ case GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB:
+ if (target == GL_VERTEX_PROGRAM_ARB)
+ *params = g->limits.maxVertexProgramInstructions;
+ else
+ *params = g->limits.maxFragmentProgramInstructions;
+ break;
+ case GL_PROGRAM_TEMPORARIES_ARB:
+ *params = prog->numTemporaries;
+ break;
+ case GL_MAX_PROGRAM_TEMPORARIES_ARB:
+ if (target == GL_VERTEX_PROGRAM_ARB)
+ *params = g->limits.maxVertexProgramTemps;
+ else
+ *params = g->limits.maxFragmentProgramTemps;
+ break;
+ case GL_PROGRAM_NATIVE_TEMPORARIES_ARB:
+ /* XXX same as GL_PROGRAM_TEMPORARIES_ARB? */
+ *params = prog->numTemporaries;
+ break;
+ case GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB:
+ /* XXX same as GL_MAX_PROGRAM_TEMPORARIES_ARB? */
+ if (target == GL_VERTEX_PROGRAM_ARB)
+ *params = g->limits.maxVertexProgramTemps;
+ else
+ *params = g->limits.maxFragmentProgramTemps;
+ break;
+ case GL_PROGRAM_PARAMETERS_ARB:
+ *params = prog->numParameters;
+ break;
+ case GL_MAX_PROGRAM_PARAMETERS_ARB:
+ if (target == GL_VERTEX_PROGRAM_ARB)
+ *params = g->limits.maxVertexProgramLocalParams;
+ else
+ *params = g->limits.maxFragmentProgramLocalParams;
+ break;
+ case GL_PROGRAM_NATIVE_PARAMETERS_ARB:
+ /* XXX same as GL_MAX_PROGRAM_PARAMETERS_ARB? */
+ *params = prog->numParameters;
+ break;
+ case GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB:
+ /* XXX same as GL_MAX_PROGRAM_PARAMETERS_ARB? */
+ if (target == GL_VERTEX_PROGRAM_ARB)
+ *params = g->limits.maxVertexProgramLocalParams;
+ else
+ *params = g->limits.maxFragmentProgramLocalParams;
+ break;
+ case GL_PROGRAM_ATTRIBS_ARB:
+ *params = prog->numAttributes;
+ break;
+ case GL_MAX_PROGRAM_ATTRIBS_ARB:
+ if (target == GL_VERTEX_PROGRAM_ARB)
+ *params = g->limits.maxVertexProgramAttribs;
+ else
+ *params = g->limits.maxFragmentProgramAttribs;
+ break;
+ case GL_PROGRAM_NATIVE_ATTRIBS_ARB:
+ /* XXX same as GL_PROGRAM_ATTRIBS_ARB? */
+ *params = prog->numAttributes;
+ break;
+ case GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB:
+ /* XXX same as GL_MAX_PROGRAM_ATTRIBS_ARB? */
+ if (target == GL_VERTEX_PROGRAM_ARB)
+ *params = g->limits.maxVertexProgramAttribs;
+ else
+ *params = g->limits.maxFragmentProgramAttribs;
+ break;
+ case GL_PROGRAM_ADDRESS_REGISTERS_ARB:
+ *params = prog->numAddressRegs;
+ break;
+ case GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB:
+ if (target == GL_VERTEX_PROGRAM_ARB)
+ *params = g->limits.maxVertexProgramAddressRegs;
+ else
+ *params = g->limits.maxFragmentProgramAddressRegs;
+ break;
+ case GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB:
+ /* XXX same as GL_PROGRAM_ADDRESS_REGISTERS_ARB? */
+ *params = prog->numAddressRegs;
+ break;
+ case GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB:
+ /* XXX same as GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB? */
+ if (target == GL_VERTEX_PROGRAM_ARB)
+ *params = g->limits.maxVertexProgramAddressRegs;
+ else
+ *params = g->limits.maxFragmentProgramAddressRegs;
+ break;
+ case GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB:
+ if (target == GL_VERTEX_PROGRAM_ARB)
+ *params = g->limits.maxVertexProgramLocalParams;
+ else
+ *params = g->limits.maxFragmentProgramLocalParams;
+ break;
+ case GL_MAX_PROGRAM_ENV_PARAMETERS_ARB:
+ if (target == GL_VERTEX_PROGRAM_ARB)
+ *params = g->limits.maxVertexProgramEnvParams;
+ else
+ *params = g->limits.maxFragmentProgramEnvParams;
+ break;
+ case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB:
+ /* XXX ok? */
+ *params = GL_TRUE;
+ break;
+
+ /*
+ * These are for fragment programs only
+ */
+ case GL_PROGRAM_ALU_INSTRUCTIONS_ARB:
+ if (target != GL_FRAGMENT_PROGRAM_ARB || !g->extensions.ARB_fragment_program) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "crStateGetProgramivARB(target or pname)");
+ return;
+ }
+ *params = prog->numAluInstructions;
+ break;
+ case GL_PROGRAM_TEX_INSTRUCTIONS_ARB:
+ if (target != GL_FRAGMENT_PROGRAM_ARB || !g->extensions.ARB_fragment_program) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "crStateGetProgramivARB(target or pname)");
+ return;
+ }
+ *params = prog->numTexInstructions;
+ break;
+ case GL_PROGRAM_TEX_INDIRECTIONS_ARB:
+ if (target != GL_FRAGMENT_PROGRAM_ARB || !g->extensions.ARB_fragment_program) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "crStateGetProgramivARB(target or pname)");
+ return;
+ }
+ *params = prog->numTexIndirections;
+ break;
+ case GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB:
+ /* XXX same as GL_PROGRAM_ALU_INSTRUCTIONS_ARB? */
+ if (target != GL_FRAGMENT_PROGRAM_ARB || !g->extensions.ARB_fragment_program) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "crStateGetProgramivARB(target or pname)");
+ return;
+ }
+ *params = prog->numAluInstructions;
+ break;
+ case GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB:
+ /* XXX same as GL_PROGRAM_ALU_INSTRUCTIONS_ARB? */
+ if (target != GL_FRAGMENT_PROGRAM_ARB || !g->extensions.ARB_fragment_program) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "crStateGetProgramivARB(target or pname)");
+ return;
+ }
+ *params = prog->numTexInstructions;
+ break;
+ case GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB:
+ if (target != GL_FRAGMENT_PROGRAM_ARB || !g->extensions.ARB_fragment_program) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "crStateGetProgramivARB(target or pname)");
+ return;
+ }
+ *params = prog->numTexIndirections;
+ break;
+ case GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB:
+ case GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB:
+ if (target != GL_FRAGMENT_PROGRAM_ARB || !g->extensions.ARB_fragment_program) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "crStateGetProgramivARB(target or pname)");
+ return;
+ }
+ *params = g->limits.maxFragmentProgramAluInstructions;
+ break;
+ case GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB:
+ case GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB:
+ if (target != GL_FRAGMENT_PROGRAM_ARB || !g->extensions.ARB_fragment_program) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "crStateGetProgramivARB(target or pname)");
+ return;
+ }
+ *params = g->limits.maxFragmentProgramTexInstructions;
+ break;
+ case GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB:
+ case GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB:
+ if (target != GL_FRAGMENT_PROGRAM_ARB || !g->extensions.ARB_fragment_program) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "crStateGetProgramivARB(target or pname)");
+ return;
+ }
+ *params = g->limits.maxFragmentProgramTexIndirections;
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "crStateGetProgramivARB(pname)");
+ return;
+ }
+}
+
+
+/* XXX maybe move these two functions into state_client.c? */
+void STATE_APIENTRY crStateDisableVertexAttribArrayARB(GLuint index)
+{
+ CRContext *g = GetCurrentContext();
+ CRClientState *c = &(g->client);
+ CRStateBits *sb = GetCurrentBits();
+ CRClientBits *cb = &(sb->client);
+
+ if (index >= g->limits.maxVertexProgramAttribs) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glDisableVertexAttribArrayARB(index)");
+ return;
+ }
+ c->array.a[index].enabled = GL_FALSE;
+ DIRTY(cb->dirty, g->neg_bitid);
+ DIRTY(cb->enableClientState, g->neg_bitid);
+}
+
+
+void STATE_APIENTRY crStateEnableVertexAttribArrayARB(GLuint index)
+{
+ CRContext *g = GetCurrentContext();
+ CRClientState *c = &(g->client);
+ CRStateBits *sb = GetCurrentBits();
+ CRClientBits *cb = &(sb->client);
+
+ if (index >= g->limits.maxVertexProgramAttribs) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glEnableVertexAttribArrayARB(index)");
+ return;
+ }
+ c->array.a[index].enabled = GL_TRUE;
+ DIRTY(cb->dirty, g->neg_bitid);
+ DIRTY(cb->enableClientState, g->neg_bitid);
+}
+
+
+void STATE_APIENTRY crStateGetProgramEnvParameterdvARB(GLenum target, GLuint index, GLdouble *params)
+{
+ GLfloat fparams[4];
+ crStateGetProgramEnvParameterfvARB(target, index, fparams);
+ params[0] = fparams[0];
+ params[1] = fparams[1];
+ params[2] = fparams[2];
+ params[3] = fparams[3];
+}
+
+void STATE_APIENTRY crStateGetProgramEnvParameterfvARB(GLenum target, GLuint index, GLfloat *params)
+{
+ CRContext *g = GetCurrentContext();
+ CRProgramState *p = &(g->program);
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetProgramEnvParameterARB called in Begin/End");
+ return;
+ }
+
+ if (target == GL_FRAGMENT_PROGRAM_ARB || target == GL_FRAGMENT_PROGRAM_NV) {
+ if (index >= g->limits.maxFragmentProgramEnvParams) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glGetProgramEnvParameterARB(index)");
+ return;
+ }
+ params[0] = p->fragmentParameters[index][0];
+ params[1] = p->fragmentParameters[index][1];
+ params[2] = p->fragmentParameters[index][2];
+ params[3] = p->fragmentParameters[index][3];
+ }
+ else if ( target == GL_VERTEX_PROGRAM_ARB
+#if GL_VERTEX_PROGRAM_ARB != GL_VERTEX_PROGRAM_NV
+ || target == GL_VERTEX_PROGRAM_NV
+#endif
+ ) {
+ if (index >= g->limits.maxVertexProgramEnvParams) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glGetProgramEnvParameterARB(index)");
+ return;
+ }
+ params[0] = p->vertexParameters[index][0];
+ params[1] = p->vertexParameters[index][1];
+ params[2] = p->vertexParameters[index][2];
+ params[3] = p->vertexParameters[index][3];
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetProgramEnvParameterARB(target)");
+ return;
+ }
+}
+
+
+void STATE_APIENTRY crStateProgramEnvParameter4dARB(GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w)
+{
+ crStateProgramEnvParameter4fARB(target, index, (GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
+}
+
+void STATE_APIENTRY crStateProgramEnvParameter4dvARB(GLenum target, GLuint index, const GLdouble *params)
+{
+ crStateProgramEnvParameter4fARB(target, index, (GLfloat) params[0], (GLfloat) params[1], (GLfloat) params[2], (GLfloat) params[3]);
+}
+
+void STATE_APIENTRY crStateProgramEnvParameter4fARB(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ CRContext *g = GetCurrentContext();
+ CRProgramState *p = &(g->program);
+ CRStateBits *sb = GetCurrentBits();
+ CRProgramBits *pb = &(sb->program);
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glProgramEnvParameterARB called in Begin/End");
+ return;
+ }
+
+ if (target == GL_FRAGMENT_PROGRAM_ARB || target == GL_FRAGMENT_PROGRAM_NV) {
+ if (index >= g->limits.maxFragmentProgramEnvParams) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glProgramEnvParameterARB(index)");
+ return;
+ }
+ p->fragmentParameters[index][0] = x;
+ p->fragmentParameters[index][1] = y;
+ p->fragmentParameters[index][2] = z;
+ p->fragmentParameters[index][3] = w;
+ DIRTY(pb->fragmentEnvParameter[index], g->neg_bitid);
+ DIRTY(pb->fragmentEnvParameters, g->neg_bitid);
+ }
+ else if ( target == GL_VERTEX_PROGRAM_ARB
+#if GL_VERTEX_PROGRAM_ARB != GL_VERTEX_PROGRAM_NV
+ || target == GL_VERTEX_PROGRAM_NV
+#endif
+ ) {
+ if (index >= g->limits.maxVertexProgramEnvParams) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glProgramEnvParameterARB(index)");
+ return;
+ }
+ p->vertexParameters[index][0] = x;
+ p->vertexParameters[index][1] = y;
+ p->vertexParameters[index][2] = z;
+ p->vertexParameters[index][3] = w;
+ DIRTY(pb->vertexEnvParameter[index], g->neg_bitid);
+ DIRTY(pb->vertexEnvParameters, g->neg_bitid);
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glProgramEnvParameterARB(target)");
+ return;
+ }
+
+ DIRTY(pb->dirty, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateProgramEnvParameter4fvARB(GLenum target, GLuint index, const GLfloat *params)
+{
+ crStateProgramEnvParameter4fARB(target, index, params[0], params[1], params[2], params[3]);
+}
+
+
+/**********************************************************************/
+
+
+void crStateProgramInit( CRContext *ctx )
+{
+ CRProgramState *p = &(ctx->program);
+ CRStateBits *sb = GetCurrentBits();
+ CRProgramBits *pb = &(sb->program);
+ GLuint i;
+
+ CRASSERT(CR_MAX_PROGRAM_ENV_PARAMS >= CR_MAX_VERTEX_PROGRAM_ENV_PARAMS);
+ CRASSERT(CR_MAX_PROGRAM_ENV_PARAMS >= CR_MAX_FRAGMENT_PROGRAM_ENV_PARAMS);
+
+ CRASSERT(CR_MAX_PROGRAM_LOCAL_PARAMS >= CR_MAX_VERTEX_PROGRAM_LOCAL_PARAMS);
+ CRASSERT(CR_MAX_PROGRAM_LOCAL_PARAMS >= CR_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMS);
+
+ p->programHash = crAllocHashtable();
+
+ /* ARB_vertex/fragment_program define default program objects */
+ p->defaultVertexProgram = GetProgram(p, GL_VERTEX_PROGRAM_ARB, 0);
+ p->defaultFragmentProgram = GetProgram(p, GL_FRAGMENT_PROGRAM_ARB, 0);
+
+ p->currentVertexProgram = p->defaultVertexProgram;
+ p->currentFragmentProgram = p->defaultFragmentProgram;
+ p->errorPos = -1;
+ p->errorString = NULL;
+
+ for (i = 0; i < ctx->limits.maxVertexProgramEnvParams / 4; i++) {
+ p->TrackMatrix[i] = GL_NONE;
+ p->TrackMatrixTransform[i] = GL_IDENTITY_NV;
+ }
+ for (i = 0; i < ctx->limits.maxVertexProgramEnvParams; i++) {
+ p->vertexParameters[i][0] = 0.0;
+ p->vertexParameters[i][1] = 0.0;
+ p->vertexParameters[i][2] = 0.0;
+ p->vertexParameters[i][3] = 0.0;
+ }
+ for (i = 0; i < CR_MAX_FRAGMENT_PROGRAM_ENV_PARAMS; i++) {
+ p->fragmentParameters[i][0] = 0.0;
+ p->fragmentParameters[i][1] = 0.0;
+ p->fragmentParameters[i][2] = 0.0;
+ p->fragmentParameters[i][3] = 0.0;
+ }
+
+ p->vpEnabled = GL_FALSE;
+ p->fpEnabled = GL_FALSE;
+ p->fpEnabledARB = GL_FALSE;
+ p->vpPointSize = GL_FALSE;
+ p->vpTwoSide = GL_FALSE;
+ RESET(pb->dirty, ctx->bitid);
+}
+
+
+static void DeleteProgramCallback( void *data )
+{
+ CRProgram *prog = (CRProgram *) data;
+ DeleteProgram(prog);
+}
+
+void crStateProgramDestroy(CRContext *ctx)
+{
+ CRProgramState *p = &(ctx->program);
+ crFreeHashtable(p->programHash, DeleteProgramCallback);
+ DeleteProgram(p->defaultVertexProgram);
+ DeleteProgram(p->defaultFragmentProgram);
+}
+
+
+/* XXX it would be nice to autogenerate this, but we can't for now.
+ */
+void
+crStateProgramDiff(CRProgramBits *b, CRbitvalue *bitID,
+ CRContext *fromCtx, CRContext *toCtx)
+{
+ CRProgramState *from = &(fromCtx->program);
+ CRProgramState *to = &(toCtx->program);
+ unsigned int i, j;
+ CRbitvalue nbitID[CR_MAX_BITARRAY];
+
+ CRASSERT(from->currentVertexProgram);
+ CRASSERT(to->currentVertexProgram);
+ CRASSERT(from->currentFragmentProgram);
+ CRASSERT(to->currentFragmentProgram);
+
+ for (j=0;j<CR_MAX_BITARRAY;j++)
+ nbitID[j] = ~bitID[j];
+
+ /* vertex program enable */
+ if (CHECKDIRTY(b->vpEnable, bitID)) {
+ glAble able[2];
+ CRProgram *toProg = to->currentVertexProgram;
+
+ able[0] = diff_api.Disable;
+ able[1] = diff_api.Enable;
+ if (from->vpEnabled != to->vpEnabled) {
+ if (toProg->isARBprogram)
+ able[to->vpEnabled](GL_VERTEX_PROGRAM_ARB);
+ else
+ able[to->vpEnabled](GL_VERTEX_PROGRAM_NV);
+ from->vpEnabled = to->vpEnabled;
+ }
+ if (from->vpTwoSide != to->vpTwoSide) {
+ able[to->vpTwoSide](GL_VERTEX_PROGRAM_TWO_SIDE_NV);
+ from->vpTwoSide = to->vpTwoSide;
+ }
+ if (from->vpPointSize != to->vpPointSize) {
+ able[to->vpPointSize](GL_VERTEX_PROGRAM_POINT_SIZE_NV);
+ from->vpPointSize = to->vpPointSize;
+ }
+ CLEARDIRTY(b->vpEnable, nbitID);
+ }
+
+ /* fragment program enable */
+ if (CHECKDIRTY(b->fpEnable, bitID)) {
+ glAble able[2];
+ able[0] = diff_api.Disable;
+ able[1] = diff_api.Enable;
+ if (from->fpEnabled != to->fpEnabled) {
+ able[to->fpEnabled](GL_FRAGMENT_PROGRAM_NV);
+ from->fpEnabled = to->fpEnabled;
+ }
+ if (from->fpEnabledARB != to->fpEnabledARB) {
+ able[to->fpEnabledARB](GL_FRAGMENT_PROGRAM_ARB);
+ from->fpEnabledARB = to->fpEnabledARB;
+ }
+ CLEARDIRTY(b->fpEnable, nbitID);
+ }
+
+ /* program/track matrices */
+ if (to->vpEnabled) {
+ for (i = 0; i < toCtx->limits.maxVertexProgramEnvParams / 4; i++) {
+ if (CHECKDIRTY(b->trackMatrix[i], bitID)) {
+ if (from->TrackMatrix[i] != to->TrackMatrix[i] ||
+ from->TrackMatrixTransform[i] != to->TrackMatrixTransform[i]) {
+ diff_api.TrackMatrixNV(GL_VERTEX_PROGRAM_NV, i * 4,
+ to->TrackMatrix[i],
+ to->TrackMatrixTransform[i]);
+ from->TrackMatrix[i] = to->TrackMatrix[i];
+ from->TrackMatrixTransform[i] = to->TrackMatrixTransform[i];
+ }
+ CLEARDIRTY(b->trackMatrix[i], nbitID);
+ }
+ }
+ }
+
+ if (to->vpEnabled) {
+ /* vertex program binding */
+ CRProgram *fromProg = from->currentVertexProgram;
+ CRProgram *toProg = to->currentVertexProgram;
+
+ if (CHECKDIRTY(b->vpBinding, bitID)) {
+ if (fromProg->id != toProg->id) {
+ if (toProg->isARBprogram)
+ diff_api.BindProgramARB(GL_VERTEX_PROGRAM_ARB, toProg->id);
+ else
+ diff_api.BindProgramNV(GL_VERTEX_PROGRAM_NV, toProg->id);
+ from->currentVertexProgram = toProg;
+ }
+ CLEARDIRTY(b->vpBinding, nbitID);
+ }
+
+ if (toProg) {
+ /* vertex program text */
+ if (CHECKDIRTY(toProg->dirtyProgram, bitID)) {
+ if (toProg->isARBprogram) {
+ diff_api.ProgramStringARB( GL_VERTEX_PROGRAM_ARB, toProg->format, toProg->length, toProg->string );
+ }
+ else {
+ diff_api.LoadProgramNV( GL_VERTEX_PROGRAM_NV, toProg->id, toProg->length, toProg->string );
+ }
+ CLEARDIRTY(toProg->dirtyProgram, nbitID);
+ }
+
+ /* vertex program global/env parameters */
+ if (CHECKDIRTY(b->vertexEnvParameters, bitID)) {
+ for (i = 0; i < toCtx->limits.maxVertexProgramEnvParams; i++) {
+ if (CHECKDIRTY(b->vertexEnvParameter[i], bitID)) {
+ if (toProg->isARBprogram)
+ diff_api.ProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i,
+ to->vertexParameters[i]);
+ else
+ diff_api.ProgramParameter4fvNV(GL_VERTEX_PROGRAM_NV, i,
+ to->vertexParameters[i]);
+ if (fromProg) {
+ COPY_4V(from->vertexParameters[i],
+ to->vertexParameters[i]);
+ }
+ CLEARDIRTY(b->vertexEnvParameter[i], nbitID);
+ }
+ }
+ CLEARDIRTY(b->vertexEnvParameters, nbitID);
+ }
+
+ /* vertex program local parameters */
+ if (CHECKDIRTY(toProg->dirtyParams, bitID)) {
+ for (i = 0; i < toCtx->limits.maxVertexProgramLocalParams; i++) {
+ if (CHECKDIRTY(toProg->dirtyParam[i], bitID)) {
+ if (toProg->isARBprogram)
+ diff_api.ProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, toProg->parameters[i]);
+ else
+ diff_api.ProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_NV, i, toProg->parameters[i]);
+ CLEARDIRTY(toProg->dirtyParam[i], nbitID);
+ }
+ }
+ CLEARDIRTY(toProg->dirtyParams, nbitID);
+ }
+ }
+ }
+
+ /*
+ * Separate paths for NV vs ARB fragment program
+ */
+ if (to->fpEnabled) {
+ /* NV fragment program binding */
+ CRProgram *fromProg = from->currentFragmentProgram;
+ CRProgram *toProg = to->currentFragmentProgram;
+ if (CHECKDIRTY(b->fpBinding, bitID)) {
+ if (fromProg->id != toProg->id) {
+ diff_api.BindProgramNV(GL_FRAGMENT_PROGRAM_NV, toProg->id);
+ from->currentFragmentProgram = toProg;
+ }
+ CLEARDIRTY(b->fpBinding, nbitID);
+ }
+
+ if (toProg) {
+ /* fragment program text */
+ if (CHECKDIRTY(toProg->dirtyProgram, bitID)) {
+ diff_api.LoadProgramNV( GL_FRAGMENT_PROGRAM_NV, toProg->id,
+ toProg->length, toProg->string );
+ CLEARDIRTY(toProg->dirtyProgram, nbitID);
+ }
+
+ /* fragment program global/env parameters */
+ if (CHECKDIRTY(b->fragmentEnvParameters, bitID)) {
+ for (i = 0; i < toCtx->limits.maxFragmentProgramEnvParams; i++) {
+ if (CHECKDIRTY(b->fragmentEnvParameter[i], bitID)) {
+ diff_api.ProgramParameter4fvNV(GL_FRAGMENT_PROGRAM_NV, i,
+ to->fragmentParameters[i]);
+ if (fromProg) {
+ COPY_4V(from->fragmentParameters[i],
+ to->fragmentParameters[i]);
+ }
+ CLEARDIRTY(b->fragmentEnvParameter[i], nbitID);
+ }
+ }
+ CLEARDIRTY(b->fragmentEnvParameters, nbitID);
+ }
+
+ /* named local parameters */
+ if (CHECKDIRTY(toProg->dirtyNamedParams, bitID)) {
+ CRProgramSymbol *symbol;
+ for (symbol = toProg->symbolTable; symbol; symbol = symbol->next) {
+ if (CHECKDIRTY(symbol->dirty, bitID)) {
+ GLint len = crStrlen(symbol->name);
+ diff_api.ProgramNamedParameter4fvNV(toProg->id, len,
+ (const GLubyte *) symbol->name,
+ symbol->value);
+ if (fromProg) {
+ SetProgramSymbol(fromProg, symbol->name, len,
+ symbol->value[0], symbol->value[1],
+ symbol->value[2], symbol->value[3]);
+ }
+ CLEARDIRTY(symbol->dirty, nbitID);
+ }
+ }
+ CLEARDIRTY(toProg->dirtyNamedParams, nbitID);
+ }
+
+ /* numbered local parameters */
+ if (CHECKDIRTY(toProg->dirtyParams, bitID)) {
+ for (i = 0; i < CR_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMS; i++) {
+ if (CHECKDIRTY(toProg->dirtyParam[i], bitID)) {
+ diff_api.ProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_NV, i,
+ toProg->parameters[i]);
+ if (fromProg) {
+ COPY_4V(fromProg->parameters[i], toProg->parameters[i]);
+ }
+ CLEARDIRTY(toProg->dirtyParam[i], nbitID);
+ }
+ }
+ CLEARDIRTY(toProg->dirtyParams, nbitID);
+ }
+ }
+ }
+ else if (to->fpEnabledARB) {
+ /* ARB fragment program binding */
+ CRProgram *fromProg = from->currentFragmentProgram;
+ CRProgram *toProg = to->currentFragmentProgram;
+ if (CHECKDIRTY(b->fpBinding, bitID)) {
+ if (fromProg->id != toProg->id) {
+ diff_api.BindProgramARB(GL_FRAGMENT_PROGRAM_ARB, toProg->id);
+ from->currentFragmentProgram = toProg;
+ }
+ CLEARDIRTY(b->fpBinding, nbitID);
+ }
+
+ if (toProg) {
+ /* fragment program text */
+ if (CHECKDIRTY(toProg->dirtyProgram, bitID)) {
+ diff_api.ProgramStringARB( GL_FRAGMENT_PROGRAM_ARB, toProg->format,
+ toProg->length, toProg->string );
+ CLEARDIRTY(toProg->dirtyProgram, nbitID);
+ }
+
+ /* fragment program global/env parameters */
+ if (CHECKDIRTY(b->fragmentEnvParameters, bitID)) {
+ for (i = 0; i < toCtx->limits.maxFragmentProgramEnvParams; i++) {
+ if (CHECKDIRTY(b->fragmentEnvParameter[i], bitID)) {
+ diff_api.ProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i,
+ to->fragmentParameters[i]);
+ if (fromProg) {
+ COPY_4V(from->fragmentParameters[i],
+ to->fragmentParameters[i]);
+ }
+ CLEARDIRTY(b->fragmentEnvParameter[i], nbitID);
+ }
+ }
+ CLEARDIRTY(b->fragmentEnvParameters, nbitID);
+ }
+
+ /* numbered local parameters */
+ if (CHECKDIRTY(toProg->dirtyParams, bitID)) {
+ for (i = 0; i < CR_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMS; i++) {
+ if (CHECKDIRTY(toProg->dirtyParam[i], bitID)) {
+ diff_api.ProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i,
+ toProg->parameters[i]);
+ if (fromProg) {
+ COPY_4V(fromProg->parameters[i], toProg->parameters[i]);
+ }
+ CLEARDIRTY(toProg->dirtyParam[i], nbitID);
+ }
+ }
+ CLEARDIRTY(toProg->dirtyParams, nbitID);
+ }
+ }
+ }
+
+ CLEARDIRTY(b->dirty, nbitID);
+}
+
+
+void
+crStateProgramSwitch(CRProgramBits *b, CRbitvalue *bitID,
+ CRContext *fromCtx, CRContext *toCtx)
+{
+ CRProgramState *from = &(fromCtx->program);
+ CRProgramState *to = &(toCtx->program);
+ unsigned int i, j;
+ CRbitvalue nbitID[CR_MAX_BITARRAY];
+ GLenum whichVert = fromCtx->extensions.ARB_vertex_program && toCtx->extensions.ARB_vertex_program ? GL_VERTEX_PROGRAM_ARB : GL_VERTEX_PROGRAM_NV;
+
+
+ for (j=0;j<CR_MAX_BITARRAY;j++)
+ nbitID[j] = ~bitID[j];
+
+ /* vertex program enable */
+ if (CHECKDIRTY(b->vpEnable, bitID)) {
+ glAble able[2];
+ able[0] = diff_api.Disable;
+ able[1] = diff_api.Enable;
+ if (from->vpEnabled != to->vpEnabled) {
+ able[to->vpEnabled](whichVert);
+ }
+ if (from->vpTwoSide != to->vpTwoSide) {
+ able[to->vpTwoSide](GL_VERTEX_PROGRAM_TWO_SIDE_NV);
+ }
+ if (from->vpPointSize != to->vpPointSize) {
+ able[to->vpPointSize](GL_VERTEX_PROGRAM_POINT_SIZE_NV);
+ }
+ DIRTY(b->vpEnable, nbitID);
+ }
+
+ /* fragment program enable */
+ if (CHECKDIRTY(b->fpEnable, bitID)) {
+ glAble able[2];
+ able[0] = diff_api.Disable;
+ able[1] = diff_api.Enable;
+ if (from->fpEnabled != to->fpEnabled) {
+ able[to->fpEnabled](GL_FRAGMENT_PROGRAM_NV);
+ }
+ if (from->fpEnabledARB != to->fpEnabledARB) {
+ able[to->fpEnabledARB](GL_FRAGMENT_PROGRAM_ARB);
+ }
+ DIRTY(b->fpEnable, nbitID);
+ }
+
+ /* program/track matrices */
+ if (to->vpEnabled) {
+ for (i = 0; i < toCtx->limits.maxVertexProgramEnvParams / 4; i++) {
+ if (CHECKDIRTY(b->trackMatrix[i], bitID)) {
+ if (from->TrackMatrix[i] != to->TrackMatrix[i]) {
+ diff_api.TrackMatrixNV(GL_VERTEX_PROGRAM_NV, i * 4,
+ to->TrackMatrix[i],
+ to->TrackMatrixTransform[i]);
+ }
+ DIRTY(b->trackMatrix[i], nbitID);
+ }
+ }
+ }
+
+ if (to->vpEnabled) {
+ /* vertex program binding */
+ CRProgram *fromProg = from->currentVertexProgram;
+ CRProgram *toProg = to->currentVertexProgram;
+ if (CHECKDIRTY(b->vpBinding, bitID)) {
+ if (fromProg->id != toProg->id) {
+ if (toProg->isARBprogram)
+ diff_api.BindProgramARB(GL_VERTEX_PROGRAM_ARB, toProg->id);
+ else
+ diff_api.BindProgramNV(GL_VERTEX_PROGRAM_NV, toProg->id);
+ }
+ DIRTY(b->vpBinding, nbitID);
+ }
+
+ if (toProg) {
+ /* vertex program text */
+ if (CHECKDIRTY(toProg->dirtyProgram, bitID)) {
+ if (toProg->isARBprogram)
+ diff_api.ProgramStringARB(GL_VERTEX_PROGRAM_ARB, toProg->format, toProg->length, toProg->string);
+ else
+ diff_api.LoadProgramNV(GL_VERTEX_PROGRAM_NV, toProg->id, toProg->length, toProg->string);
+
+ DIRTY(toProg->dirtyProgram, nbitID);
+ }
+
+ /* vertex program global/env parameters */
+ if (CHECKDIRTY(b->vertexEnvParameters, bitID)) {
+ for (i = 0; i < toCtx->limits.maxVertexProgramEnvParams; i++) {
+ if (CHECKDIRTY(b->vertexEnvParameter[i], bitID)) {
+ if (toProg->isARBprogram)
+ diff_api.ProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, to->vertexParameters[i]);
+ else
+ diff_api.ProgramParameter4fvNV(GL_VERTEX_PROGRAM_NV, i, to->vertexParameters[i]);
+
+ DIRTY(b->vertexEnvParameter[i], nbitID);
+ }
+ }
+ DIRTY(b->vertexEnvParameters, nbitID);
+ }
+
+ /* vertex program local parameters */
+ if (CHECKDIRTY(toProg->dirtyParams, bitID)) {
+ for (i = 0; i < toCtx->limits.maxVertexProgramLocalParams; i++) {
+ if (CHECKDIRTY(toProg->dirtyParam[i], bitID)) {
+
+
+ if (toProg->isARBprogram)
+ diff_api.ProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, toProg->parameters[i]);
+ else
+ diff_api.ProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_NV, i, toProg->parameters[i]);
+ }
+ }
+ DIRTY(toProg->dirtyParams, nbitID);
+ }
+ }
+ }
+
+ /*
+ * Separate paths for NV vs ARB fragment program
+ */
+ if (to->fpEnabled) {
+ /* NV fragment program binding */
+ CRProgram *fromProg = from->currentFragmentProgram;
+ CRProgram *toProg = to->currentFragmentProgram;
+ if (CHECKDIRTY(b->fpBinding, bitID)) {
+ if (fromProg->id != toProg->id) {
+ diff_api.BindProgramNV(GL_FRAGMENT_PROGRAM_NV, toProg->id);
+ }
+ DIRTY(b->fpBinding, nbitID);
+ }
+
+ if (toProg) {
+ /* fragment program text */
+ if (CHECKDIRTY(toProg->dirtyProgram, bitID)) {
+ diff_api.LoadProgramNV(GL_FRAGMENT_PROGRAM_NV, toProg->id, toProg->length, toProg->string);
+ DIRTY(toProg->dirtyProgram, nbitID);
+ }
+
+ /* fragment program global/env parameters */
+ if (CHECKDIRTY(b->fragmentEnvParameters, bitID)) {
+ for (i = 0; i < toCtx->limits.maxFragmentProgramEnvParams; i++) {
+ if (CHECKDIRTY(b->fragmentEnvParameter[i], bitID)) {
+ diff_api.ProgramParameter4fvNV(GL_FRAGMENT_PROGRAM_NV, i,
+ to->fragmentParameters[i]);
+ DIRTY(b->fragmentEnvParameter[i], nbitID);
+ }
+ }
+ DIRTY(b->fragmentEnvParameters, nbitID);
+ }
+
+ /* named local parameters */
+ if (CHECKDIRTY(toProg->dirtyNamedParams, bitID)) {
+ CRProgramSymbol *symbol;
+ for (symbol = toProg->symbolTable; symbol; symbol = symbol->next) {
+ if (CHECKDIRTY(symbol->dirty, bitID)) {
+ GLint len = crStrlen(symbol->name);
+ diff_api.ProgramNamedParameter4fvNV(toProg->id, len,
+ (const GLubyte *) symbol->name,
+ symbol->value);
+ DIRTY(symbol->dirty, nbitID);
+ }
+ }
+ DIRTY(toProg->dirtyNamedParams, nbitID);
+ }
+
+ /* numbered local parameters */
+ if (CHECKDIRTY(toProg->dirtyParams, bitID)) {
+ for (i = 0; i < CR_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMS; i++) {
+ if (CHECKDIRTY(toProg->dirtyParam[i], bitID)) {
+ if (toProg->isARBprogram)
+ diff_api.ProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i, toProg->parameters[i]);
+ else
+ diff_api.ProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_NV, i, toProg->parameters[i]);
+ }
+ }
+ DIRTY(toProg->dirtyParams, nbitID);
+ }
+ }
+ }
+ else if (to->fpEnabledARB) {
+ /* ARB fragment program binding */
+ CRProgram *fromProg = from->currentFragmentProgram;
+ CRProgram *toProg = to->currentFragmentProgram;
+ if (CHECKDIRTY(b->fpBinding, bitID)) {
+ if (fromProg->id != toProg->id) {
+ diff_api.BindProgramARB(GL_FRAGMENT_PROGRAM_ARB, toProg->id);
+ }
+ DIRTY(b->fpBinding, nbitID);
+ }
+
+ if (toProg) {
+ /* fragment program text */
+ if (CHECKDIRTY(toProg->dirtyProgram, bitID)) {
+ diff_api.ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, toProg->format, toProg->length, toProg->string);
+ DIRTY(toProg->dirtyProgram, nbitID);
+ }
+
+ /* fragment program global/env parameters */
+ if (CHECKDIRTY(b->fragmentEnvParameters, bitID)) {
+ for (i = 0; i < toCtx->limits.maxFragmentProgramEnvParams; i++) {
+ if (CHECKDIRTY(b->fragmentEnvParameter[i], bitID)) {
+ diff_api.ProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i, to->fragmentParameters[i]);
+ DIRTY(b->fragmentEnvParameter[i], nbitID);
+ }
+ }
+ DIRTY(b->fragmentEnvParameters, nbitID);
+ }
+
+ /* numbered local parameters */
+ if (CHECKDIRTY(toProg->dirtyParams, bitID)) {
+ for (i = 0; i < CR_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMS; i++) {
+ if (CHECKDIRTY(toProg->dirtyParam[i], bitID)) {
+ diff_api.ProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i, toProg->parameters[i]);
+ DIRTY(toProg->dirtyParam[i], nbitID);
+ }
+ }
+ DIRTY(toProg->dirtyParams, nbitID);
+ }
+ }
+ }
+
+ DIRTY(b->dirty, nbitID);
+
+ /* Resend program data */
+ if (toCtx->program.bResyncNeeded)
+ {
+ toCtx->program.bResyncNeeded = GL_FALSE;
+
+ crStateDiffAllPrograms(toCtx, bitID, GL_TRUE);
+ }
+}
+
+/** @todo support NVprograms and add some data validity checks*/
+static void
+DiffProgramCallback(unsigned long key, void *pProg, void *pCtx)
+{
+ CRContext *pContext = (CRContext *) pCtx;
+ CRProgram *pProgram = (CRProgram *) pProg;
+ uint32_t i;
+ (void)key;
+
+ if (pProgram->isARBprogram)
+ {
+ diff_api.BindProgramARB(pProgram->target, pProgram->id);
+ diff_api.ProgramStringARB(pProgram->target, pProgram->format, pProgram->length, pProgram->string);
+
+ if (GL_VERTEX_PROGRAM_ARB == pProgram->target)
+ {
+ /* vertex program global/env parameters */
+ for (i = 0; i < pContext->limits.maxVertexProgramEnvParams; i++)
+ {
+ diff_api.ProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, pContext->program.vertexParameters[i]);
+ }
+ /* vertex program local parameters */
+ for (i = 0; i < pContext->limits.maxVertexProgramLocalParams; i++)
+ {
+ diff_api.ProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, pProgram->parameters[i]);
+ }
+ }
+ else if (GL_FRAGMENT_PROGRAM_ARB == pProgram->target)
+ {
+ /* vertex program global/env parameters */
+ for (i = 0; i < pContext->limits.maxFragmentProgramEnvParams; i++)
+ {
+ diff_api.ProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i, pContext->program.fragmentParameters[i]);
+ }
+ /* vertex program local parameters */
+ for (i = 0; i < CR_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMS; i++)
+ {
+ diff_api.ProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i, pProgram->parameters[i]);
+ }
+ }
+ else
+ {
+ crError("Unexpected program target");
+ }
+ }
+ else
+ {
+ diff_api.BindProgramNV(pProgram->target, pProgram->id);
+ }
+}
+
+void crStateDiffAllPrograms(CRContext *g, CRbitvalue *bitID, GLboolean bForceUpdate)
+{
+ CRProgram *pOrigVP, *pOrigFP;
+
+ (void) bForceUpdate; (void)bitID;
+
+ /* save original bindings */
+ pOrigVP = g->program.currentVertexProgram;
+ pOrigFP = g->program.currentFragmentProgram;
+
+ crHashtableWalk(g->program.programHash, DiffProgramCallback, g);
+
+ /* restore original bindings */
+ if (pOrigVP->isARBprogram)
+ diff_api.BindProgramARB(pOrigVP->target, pOrigVP->id);
+ else
+ diff_api.BindProgramNV(pOrigVP->target, pOrigVP->id);
+
+ if (pOrigFP->isARBprogram)
+ diff_api.BindProgramARB(pOrigFP->target, pOrigFP->id);
+ else
+ diff_api.BindProgramNV(pOrigFP->target, pOrigFP->id);
+}
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_program.txt b/src/VBox/GuestHost/OpenGL/state_tracker/state_program.txt
new file mode 100644
index 00000000..fdb5c75e
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_program.txt
@@ -0,0 +1,14 @@
+# Copyright (c) 2001, Stanford University
+# All rights reserved.
+#
+# See the file LICENSE.txt for information on redistributing this software.
+#:enable:lineSmooth:GL_LINE_SMOOTH
+#:enable:lineStipple:GL_LINE_STIPPLE
+#:width:width:LineWidth
+#lineStipple:stipple:repeat,pattern:LineStipple
+:vpEnable:vpEnabled:Enable:GL_VERTEX_PROGRAM_NV
+:fpEnable:fpEnabled:Enable:GL_FRAGMENT_PROGRAM_NV
+%flush
+:vpBinding:currentVertexProgram->id:BindProgramNV,GL_VERTEX_PROGRAM_NV
+:fpBinding:currentFragmentProgram->id:BindProgramNV,GL_FRAGMENT_PROGRAM_NV
+#:errorPos:errorPos:ErrorPos
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_rasterpos.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_rasterpos.c
new file mode 100644
index 00000000..29b23970
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_rasterpos.c
@@ -0,0 +1,327 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#include <stdio.h>
+#include "state.h"
+#include "state/cr_statetypes.h"
+#include "state_internals.h"
+
+
+/*
+ * Apply modelview, projection, viewport transformations to (x,y,z,w)
+ * and update the current raster position attributes.
+ * Do NOT set dirty state.
+ */
+void
+crStateRasterPosUpdate(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ CRContext *g = GetCurrentContext();
+ CRCurrentState *c = &(g->current);
+ CRTransformState *t = &(g->transform);
+ CRViewportState *v = &(g->viewport);
+ GLvectorf p;
+ int i;
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "RasterPos called in Begin/End");
+ return;
+ }
+
+ FLUSH();
+
+ /* update current color, texcoord, etc from the CurrentStatePointers */
+ crStateCurrentRecover();
+
+ p.x = x;
+ p.y = y;
+ p.z = z;
+ p.w = w;
+
+ /* Apply modelview and projection matrix */
+ crStateTransformXformPoint(t, &p);
+
+ /* clip test */
+ if (p.x > p.w || p.y > p.w || p.z > p.w ||
+ p.x < -p.w || p.y < -p.w || p.z < -p.w)
+ {
+ c->rasterValid = GL_FALSE;
+ return;
+ }
+
+ /* divide by W (perspective projection) */
+ p.x /= p.w;
+ p.y /= p.w;
+ p.z /= p.w;
+ p.w = 1.0f;
+
+ /* map from NDC to window coords */
+ crStateViewportApply(v, &p);
+
+ c->rasterValid = GL_TRUE;
+ ASSIGN_4V(c->rasterAttrib[VERT_ATTRIB_POS], p.x, p.y, p.z, p.w);
+ ASSIGN_4V(c->rasterAttribPre[VERT_ATTRIB_POS], p.x, p.y, p.z, p.w);
+ for (i = 1; i < CR_MAX_VERTEX_ATTRIBS; i++) {
+ COPY_4V(c->rasterAttrib[i] , c->vertexAttrib[i]);
+ }
+
+ /* XXX need to update raster distance... */
+ /* from Mesa... */
+#ifdef CR_EXT_fog_coord
+ if (g->fog.fogCoordinateSource == GL_FOG_COORDINATE_EXT)
+ c->rasterAttrib[VERT_ATTRIB_FOG][0] = c->vertexAttrib[VERT_ATTRIB_FOG][0];
+ else
+#endif
+ c->rasterAttrib[VERT_ATTRIB_FOG][0] = 0.0; /*(GLfloat)
+ sqrt( eye[0]*eye[0] + eye[1]*eye[1] + eye[2]*eye[2] );*/
+}
+
+
+/* As above, but set dirty flags */
+static void RasterPos4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ CRContext *g = GetCurrentContext();
+ CRStateBits *sb = GetCurrentBits();
+ CRCurrentBits *cb = &(sb->current);
+
+ crStateRasterPosUpdate(x, y, z, w);
+
+ DIRTY(cb->dirty, g->neg_bitid);
+ DIRTY(cb->rasterPos, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateRasterPos2d(GLdouble x, GLdouble y)
+{
+ RasterPos4f((GLfloat) x, (GLfloat) y, 0.0f, 1.0f);
+}
+
+void STATE_APIENTRY crStateRasterPos2f(GLfloat x, GLfloat y)
+{
+ RasterPos4f(x, y, 0.0f, 1.0f);
+}
+
+void STATE_APIENTRY crStateRasterPos2i(GLint x, GLint y)
+{
+ RasterPos4f((GLfloat) x, (GLfloat) y, 0.0f, 1.0f);
+}
+
+void STATE_APIENTRY crStateRasterPos2s(GLshort x, GLshort y)
+{
+ RasterPos4f((GLfloat) x, (GLfloat) y, 0.0f, 1.0f);
+}
+
+void STATE_APIENTRY crStateRasterPos3d(GLdouble x, GLdouble y, GLdouble z)
+{
+ RasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0f);
+}
+
+void STATE_APIENTRY crStateRasterPos3f(GLfloat x, GLfloat y, GLfloat z)
+{
+ RasterPos4f(x, y, z, 1.0f);
+}
+
+void STATE_APIENTRY crStateRasterPos3i(GLint x, GLint y, GLint z)
+{
+ RasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0f);
+}
+
+void STATE_APIENTRY crStateRasterPos3s(GLshort x, GLshort y, GLshort z)
+{
+ RasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0f);
+}
+
+void STATE_APIENTRY crStateRasterPos4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w)
+{
+ RasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
+}
+
+void STATE_APIENTRY crStateRasterPos4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ RasterPos4f(x, y, z, w);
+}
+
+void STATE_APIENTRY crStateRasterPos4i(GLint x, GLint y, GLint z, GLint w)
+{
+ RasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
+}
+
+void STATE_APIENTRY crStateRasterPos4s(GLshort x, GLshort y, GLshort z, GLshort w)
+{
+ RasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
+}
+
+void STATE_APIENTRY crStateRasterPos2dv(const GLdouble *v)
+{
+ RasterPos4f((GLfloat) v[0], (GLfloat) v[1], 0.0f, 1.0f);
+}
+
+void STATE_APIENTRY crStateRasterPos2fv(const GLfloat *v)
+{
+ RasterPos4f(v[0], v[1], 0.0f, 1.0f);
+}
+
+void STATE_APIENTRY crStateRasterPos2iv(const GLint *v)
+{
+ RasterPos4f((GLfloat) v[0], (GLfloat) v[1], 0.0f, 1.0f);
+}
+
+void STATE_APIENTRY crStateRasterPos2sv(const GLshort *v)
+{
+ RasterPos4f((GLfloat) v[0], (GLfloat) v[1], 0.0f, 1.0f);
+}
+
+void STATE_APIENTRY crStateRasterPos3dv(const GLdouble *v)
+{
+ RasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0f);
+}
+
+void STATE_APIENTRY crStateRasterPos3fv(const GLfloat *v)
+{
+ RasterPos4f(v[0], v[1], v[2], 1.0f);
+}
+
+void STATE_APIENTRY crStateRasterPos3iv(const GLint *v)
+{
+ RasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0f);
+}
+
+void STATE_APIENTRY crStateRasterPos3sv(const GLshort *v)
+{
+ RasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0f);
+}
+
+void STATE_APIENTRY crStateRasterPos4dv(const GLdouble *v)
+{
+ RasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]);
+}
+
+void STATE_APIENTRY crStateRasterPos4fv(const GLfloat *v)
+{
+ RasterPos4f(v[0], v[1], v[2], v[3]);
+}
+
+void STATE_APIENTRY crStateRasterPos4iv(const GLint *v)
+{
+ RasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]);
+}
+
+void STATE_APIENTRY crStateRasterPos4sv(const GLshort *v)
+{
+ RasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]);
+}
+
+
+/**********************************************************************/
+
+
+static void
+crStateWindowPosUpdate(GLfloat x, GLfloat y, GLfloat z)
+{
+ CRContext *g = GetCurrentContext();
+ CRCurrentState *c = &(g->current);
+ CRStateBits *sb = GetCurrentBits();
+ CRCurrentBits *cb = &(sb->current);
+ int i;
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "WindowPos called in Begin/End");
+ return;
+ }
+
+ FLUSH();
+ DIRTY(cb->dirty, g->neg_bitid);
+ DIRTY(cb->rasterPos, g->neg_bitid);
+
+ c->rasterValid = GL_TRUE;
+ ASSIGN_4V(c->rasterAttrib[VERT_ATTRIB_POS], x, y , z, 1.0);
+ ASSIGN_4V(c->rasterAttribPre[VERT_ATTRIB_POS], x, y, z, 1.0);
+ for (i = 1; i < CR_MAX_VERTEX_ATTRIBS; i++) {
+ COPY_4V(c->rasterAttrib[i] , c->vertexAttrib[i]);
+ }
+}
+
+
+void STATE_APIENTRY crStateWindowPos2dARB (GLdouble x, GLdouble y)
+{
+ crStateWindowPosUpdate((GLfloat) x, (GLfloat) y, 0.0);
+}
+
+void STATE_APIENTRY crStateWindowPos2dvARB (const GLdouble *v)
+{
+ crStateWindowPosUpdate((GLfloat) v[0], (GLfloat) v[1], 0.0);
+}
+
+void STATE_APIENTRY crStateWindowPos2fARB (GLfloat x, GLfloat y)
+{
+ crStateWindowPosUpdate(x, y, 0.0);
+}
+
+void STATE_APIENTRY crStateWindowPos2fvARB (const GLfloat *v)
+{
+ crStateWindowPosUpdate(v[0], v[1], 0.0);
+}
+
+void STATE_APIENTRY crStateWindowPos2iARB (GLint x, GLint y)
+{
+ crStateWindowPosUpdate((GLfloat) x, (GLfloat) y, 0.0);
+}
+
+void STATE_APIENTRY crStateWindowPos2ivARB (const GLint *v)
+{
+ crStateWindowPosUpdate((GLfloat) v[0], (GLfloat) v[1], 0.0);
+}
+
+void STATE_APIENTRY crStateWindowPos2sARB (GLshort x, GLshort y)
+{
+ crStateWindowPosUpdate((GLfloat) x, (GLfloat) y, 0.0);
+}
+
+void STATE_APIENTRY crStateWindowPos2svARB (const GLshort *v)
+{
+ crStateWindowPosUpdate((GLfloat) v[0], (GLfloat) v[1], 0.0);
+}
+
+void STATE_APIENTRY crStateWindowPos3dARB (GLdouble x, GLdouble y, GLdouble z)
+{
+ crStateWindowPosUpdate((GLfloat) x, (GLfloat) y, (GLfloat) z);
+}
+
+void STATE_APIENTRY crStateWindowPos3dvARB (const GLdouble *v)
+{
+ crStateWindowPosUpdate((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2]);
+}
+
+void STATE_APIENTRY crStateWindowPos3fARB (GLfloat x, GLfloat y, GLfloat z)
+{
+ crStateWindowPosUpdate(x, y, z);
+}
+
+void STATE_APIENTRY crStateWindowPos3fvARB (const GLfloat *v)
+{
+ crStateWindowPosUpdate(v[0], v[1], v[2]);
+}
+
+void STATE_APIENTRY crStateWindowPos3iARB (GLint x, GLint y, GLint z)
+{
+ crStateWindowPosUpdate((GLfloat) x, (GLfloat) y, (GLfloat) z);
+}
+
+void STATE_APIENTRY crStateWindowPos3ivARB (const GLint *v)
+{
+ crStateWindowPosUpdate((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2]);
+}
+
+void STATE_APIENTRY crStateWindowPos3sARB (GLshort x, GLshort y, GLshort z)
+{
+ crStateWindowPosUpdate((GLfloat) x, (GLfloat) y, (GLfloat) z);
+}
+
+void STATE_APIENTRY crStateWindowPos3svARB (const GLshort *v)
+{
+ crStateWindowPosUpdate((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2]);
+}
+
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_regcombiner.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_regcombiner.c
new file mode 100644
index 00000000..069c6fa5
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_regcombiner.c
@@ -0,0 +1,705 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#include "state.h"
+#include "state/cr_statetypes.h"
+
+
+#define UNUSED(x) ((void) (x))
+
+
+void crStateRegCombinerInit( CRContext *ctx )
+{
+ CRRegCombinerState *reg = &ctx->regcombiner;
+ CRStateBits *sb = GetCurrentBits();
+ CRRegCombinerBits *rb = &(sb->regcombiner);
+#ifndef CR_NV_register_combiners
+ UNUSED(reg)
+#else
+ GLcolorf zero_color = {0.0f, 0.0f, 0.0f, 0.0f};
+ int i;
+
+ reg->enabledRegCombiners = GL_FALSE;
+ RESET(rb->enable, ctx->bitid);
+ reg->constantColor0 = zero_color;
+ RESET(rb->regCombinerColor0, ctx->bitid);
+ reg->constantColor1 = zero_color;
+ RESET(rb->regCombinerColor1, ctx->bitid);
+ for( i=0; i<CR_MAX_GENERAL_COMBINERS; i++ )
+ {
+ /* RGB Portion */
+ reg->rgb[i].a = GL_PRIMARY_COLOR_NV;
+ reg->rgb[i].b = GL_ZERO;
+ reg->rgb[i].c = GL_ZERO;
+ reg->rgb[i].d = GL_ZERO;
+ reg->rgb[i].aMapping = GL_UNSIGNED_IDENTITY_NV;
+ reg->rgb[i].bMapping = GL_UNSIGNED_INVERT_NV;
+ reg->rgb[i].cMapping = GL_UNSIGNED_IDENTITY_NV;
+ reg->rgb[i].dMapping = GL_UNSIGNED_IDENTITY_NV;
+ reg->rgb[i].aPortion = GL_RGB;
+ reg->rgb[i].bPortion = GL_RGB;
+ reg->rgb[i].cPortion = GL_RGB;
+ reg->rgb[i].dPortion = GL_RGB;
+ reg->rgb[i].scale = GL_NONE;
+ reg->rgb[i].bias = GL_NONE;
+ reg->rgb[i].abOutput = GL_DISCARD_NV;
+ reg->rgb[i].cdOutput = GL_DISCARD_NV;
+ reg->rgb[i].sumOutput = GL_SPARE0_NV;
+ reg->rgb[i].abDotProduct = GL_FALSE;
+ reg->rgb[i].cdDotProduct = GL_FALSE;
+ reg->rgb[i].muxSum = GL_FALSE;
+
+ /* Alpha Portion */
+ reg->alpha[i].a = GL_PRIMARY_COLOR_NV;
+ reg->alpha[i].b = GL_ZERO;
+ reg->alpha[i].c = GL_ZERO;
+ reg->alpha[i].d = GL_ZERO;
+ reg->alpha[i].aMapping = GL_UNSIGNED_IDENTITY_NV;
+ reg->alpha[i].bMapping = GL_UNSIGNED_INVERT_NV;
+ reg->alpha[i].cMapping = GL_UNSIGNED_IDENTITY_NV;
+ reg->alpha[i].dMapping = GL_UNSIGNED_IDENTITY_NV;
+ reg->alpha[i].aPortion = GL_ALPHA;
+ reg->alpha[i].bPortion = GL_ALPHA;
+ reg->alpha[i].cPortion = GL_ALPHA;
+ reg->alpha[i].dPortion = GL_ALPHA;
+ reg->alpha[i].scale = GL_NONE;
+ reg->alpha[i].bias = GL_NONE;
+ reg->alpha[i].abOutput = GL_DISCARD_NV;
+ reg->alpha[i].cdOutput = GL_DISCARD_NV;
+ reg->alpha[i].sumOutput = GL_SPARE0_NV;
+ reg->alpha[i].abDotProduct = GL_FALSE;
+ reg->alpha[i].cdDotProduct = GL_FALSE;
+ reg->alpha[i].muxSum = GL_FALSE;
+ RESET(rb->regCombinerInput[i], ctx->bitid);
+ RESET(rb->regCombinerOutput[i], ctx->bitid);
+ }
+ RESET(rb->regCombinerVars, ctx->bitid);
+ reg->numGeneralCombiners = 1;
+ reg->colorSumClamp = GL_TRUE;
+ reg->a = GL_FOG;
+ reg->b = GL_SPARE0_PLUS_SECONDARY_COLOR_NV;
+ reg->c = GL_FOG;
+ reg->d = GL_ZERO;
+ reg->e = GL_ZERO;
+ reg->f = GL_ZERO;
+ reg->g = GL_SPARE0_NV;
+ reg->aMapping = GL_UNSIGNED_IDENTITY_NV;
+ reg->bMapping = GL_UNSIGNED_IDENTITY_NV;
+ reg->cMapping = GL_UNSIGNED_IDENTITY_NV;
+ reg->dMapping = GL_UNSIGNED_IDENTITY_NV;
+ reg->eMapping = GL_UNSIGNED_IDENTITY_NV;
+ reg->fMapping = GL_UNSIGNED_IDENTITY_NV;
+ reg->gMapping = GL_UNSIGNED_IDENTITY_NV;
+ reg->aPortion = GL_ALPHA;
+ reg->bPortion = GL_RGB;
+ reg->cPortion = GL_RGB;
+ reg->dPortion = GL_RGB;
+ reg->ePortion = GL_RGB;
+ reg->fPortion = GL_RGB;
+ reg->gPortion = GL_ALPHA;
+ RESET(rb->regCombinerFinalInput, ctx->bitid);
+#ifdef CR_NV_register_combiners2
+ reg->enabledPerStageConstants = GL_FALSE;
+ for( i=0; i<CR_MAX_GENERAL_COMBINERS; i++ )
+ {
+ reg->stageConstantColor0[i] = zero_color;
+ reg->stageConstantColor1[i] = zero_color;
+ RESET(rb->regCombinerStageColor0[i], ctx->bitid);
+ RESET(rb->regCombinerStageColor1[i], ctx->bitid);
+ }
+#endif /* CR_NV_register_combiners2 */
+#endif /* CR_NV_register_combiners */
+
+ RESET(rb->dirty, ctx->bitid);
+}
+
+void STATE_APIENTRY crStateCombinerParameterfvNV( GLenum pname, const GLfloat *params )
+{
+ CRContext *g = GetCurrentContext();
+ CRRegCombinerState *r = &(g->regcombiner);
+ CRStateBits *sb = GetCurrentBits();
+ CRRegCombinerBits *rb = &(sb->regcombiner);
+
+ switch( pname )
+ {
+ case GL_CONSTANT_COLOR0_NV:
+ r->constantColor0.r = params[0];
+ r->constantColor0.g = params[1];
+ r->constantColor0.b = params[2];
+ r->constantColor0.a = params[3];
+ DIRTY(rb->regCombinerColor0, g->neg_bitid);
+ break;
+ case GL_CONSTANT_COLOR1_NV:
+ r->constantColor1.r = params[0];
+ r->constantColor1.g = params[1];
+ r->constantColor1.b = params[2];
+ r->constantColor1.a = params[3];
+ DIRTY(rb->regCombinerColor1, g->neg_bitid);
+ break;
+ case GL_NUM_GENERAL_COMBINERS_NV:
+ if( *params < 1 || *params > g->limits.maxGeneralCombiners )
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "CombinerParameter passed invalid NUM_GENERAL_COMBINERS param: %d", (GLint)*params );
+ return;
+ }
+ r->numGeneralCombiners = (GLint)*params;
+ DIRTY(rb->regCombinerVars, g->neg_bitid);
+ break;
+ case GL_COLOR_SUM_CLAMP_NV:
+ r->colorSumClamp = (GLboolean)*params;
+ DIRTY(rb->regCombinerVars, g->neg_bitid);
+ break;
+ default:
+ crStateError( __LINE__, __FILE__, GL_INVALID_ENUM, "CombinerParameter passed bogus pname: 0x%x", pname );
+ return;
+ }
+
+ DIRTY(rb->dirty, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateCombinerParameterivNV( GLenum pname, const GLint *params )
+{
+ GLfloat fparams[4];
+ int i;
+
+ if( pname == GL_CONSTANT_COLOR0_NV || pname == GL_CONSTANT_COLOR1_NV )
+ {
+ for( i=0; i<4; i++ )
+ {
+ fparams[i] = (GLfloat)params[i] * (GLfloat)(1.0/255.0);
+ }
+ }
+ else
+ {
+ /* Only one parameter: */
+ *fparams = (GLfloat) *params;
+ }
+ crStateCombinerParameterfvNV( pname, fparams );
+}
+
+void STATE_APIENTRY crStateCombinerParameterfNV( GLenum pname, GLfloat param )
+{
+ GLfloat fparam[1];
+ *fparam = (GLfloat) param;
+ if( pname == GL_CONSTANT_COLOR0_NV || pname == GL_CONSTANT_COLOR1_NV )
+ {
+ crStateError( __LINE__, __FILE__, GL_INVALID_ENUM, "Invalid pname (CONSTANT_COLOR%d) passed to CombinerParameterfNV: 0x%x", (GLint)param-GL_CONSTANT_COLOR0_NV, pname );
+ return;
+ }
+ crStateCombinerParameterfvNV( pname, fparam );
+}
+
+void STATE_APIENTRY crStateCombinerParameteriNV( GLenum pname, GLint param )
+{
+ GLfloat fparam[1];
+ *fparam = (GLfloat) param;
+ if( pname == GL_CONSTANT_COLOR0_NV || pname == GL_CONSTANT_COLOR1_NV )
+ {
+ crStateError( __LINE__, __FILE__, GL_INVALID_ENUM, "Invalid pname (CONSTANT_COLOR%d) passed to CombinerParameteriNV: 0x%x", param-GL_CONSTANT_COLOR0_NV, pname );
+ return;
+ }
+ crStateCombinerParameterfvNV( pname, fparam );
+}
+
+void STATE_APIENTRY crStateCombinerInputNV( GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage )
+{
+ CRContext *g = GetCurrentContext();
+ CRRegCombinerState *r = &(g->regcombiner);
+ CRStateBits *sb = GetCurrentBits();
+ CRRegCombinerBits *rb = &(sb->regcombiner);
+
+ if( stage < GL_COMBINER0_NV || stage >= GL_COMBINER0_NV + g->limits.maxGeneralCombiners )
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "CombinerInputNV passed bogus stage: 0x%x", stage );
+ return;
+ }
+ if( input != GL_ZERO && input != GL_CONSTANT_COLOR0_NV && input != GL_CONSTANT_COLOR1_NV && input != GL_FOG && input != GL_PRIMARY_COLOR_NV && input != GL_SECONDARY_COLOR_NV && input != GL_SPARE0_NV && input != GL_SPARE1_NV && ( input < GL_TEXTURE0_ARB || input >= GL_TEXTURE0_ARB + g->limits.maxTextureUnits ))
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "CombinerInputNV passed bogus input: 0x%x", input );
+ return;
+ }
+ if( mapping != GL_UNSIGNED_IDENTITY_NV && mapping != GL_UNSIGNED_INVERT_NV && mapping != GL_EXPAND_NORMAL_NV && mapping != GL_EXPAND_NEGATE_NV && mapping != GL_HALF_BIAS_NORMAL_NV && mapping != GL_HALF_BIAS_NEGATE_NV && mapping != GL_SIGNED_IDENTITY_NV && mapping != GL_SIGNED_NEGATE_NV )
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "CombinerInputNV passed bogus mapping: 0x%x", mapping );
+ return;
+ }
+ if( componentUsage != GL_RGB && componentUsage != GL_ALPHA && componentUsage != GL_BLUE )
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "CombinerInputNV passed bogus componentUsage: 0x%x", componentUsage );
+ return;
+ }
+
+ if(( componentUsage == GL_RGB && portion == GL_ALPHA )||( componentUsage == GL_BLUE && portion == GL_RGB ))
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "Incompatible portion and componentUsage passed to CombinerInputNV: portion = 0x%x, componentUsage = 0x%x", portion, componentUsage );
+ return;
+ }
+ if( componentUsage == GL_ALPHA && input == GL_FOG )
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "CombinerInputNV can not have input of GL_FOG if componentUsage is GL_ALPHA" );
+ return;
+ }
+
+ stage -= GL_COMBINER0_NV;
+ if( portion == GL_RGB )
+ {
+ switch( variable )
+ {
+ case GL_VARIABLE_A_NV:
+ r->rgb[stage].a = input;
+ r->rgb[stage].aMapping = mapping;
+ r->rgb[stage].aPortion = componentUsage;
+ break;
+ case GL_VARIABLE_B_NV:
+ r->rgb[stage].b = input;
+ r->rgb[stage].bMapping = mapping;
+ r->rgb[stage].bPortion = componentUsage;
+ break;
+ case GL_VARIABLE_C_NV:
+ r->rgb[stage].c = input;
+ r->rgb[stage].cMapping = mapping;
+ r->rgb[stage].cPortion = componentUsage;
+ break;
+ case GL_VARIABLE_D_NV:
+ r->rgb[stage].d = input;
+ r->rgb[stage].dMapping = mapping;
+ r->rgb[stage].dPortion = componentUsage;
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "CombinerInputNV passed bogus variable: 0x%x", variable );
+ return;
+ }
+ }
+ else if( portion == GL_ALPHA )
+ {
+ switch( variable )
+ {
+ case GL_VARIABLE_A_NV:
+ r->alpha[stage].a = input;
+ r->alpha[stage].aMapping = mapping;
+ r->alpha[stage].aPortion = componentUsage;
+ break;
+ case GL_VARIABLE_B_NV:
+ r->alpha[stage].b = input;
+ r->alpha[stage].bMapping = mapping;
+ r->alpha[stage].bPortion = componentUsage;
+ break;
+ case GL_VARIABLE_C_NV:
+ r->alpha[stage].c = input;
+ r->alpha[stage].cMapping = mapping;
+ r->alpha[stage].cPortion = componentUsage;
+ break;
+ case GL_VARIABLE_D_NV:
+ r->alpha[stage].d = input;
+ r->alpha[stage].dMapping = mapping;
+ r->alpha[stage].dPortion = componentUsage;
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "CombinerInputNV passed bogus variable: 0x%x", variable );
+ return;
+ }
+ }
+ else
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "CombinerInputNV passed bogus portion: 0x%x", portion );
+ return;
+ }
+
+ DIRTY(rb->regCombinerInput[stage], g->neg_bitid);
+ DIRTY(rb->dirty, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateCombinerOutputNV( GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum )
+{
+ CRContext *g = GetCurrentContext();
+ CRRegCombinerState *r = &(g->regcombiner);
+ CRStateBits *sb = GetCurrentBits();
+ CRRegCombinerBits *rb = &(sb->regcombiner);
+
+ /*
+ crDebug("%s(stage=0x%x portion=0x%x abOutput=0x%x cdOutput=0x%x "
+ "sumOutput=0x%x scale=0x%x bias=0x%x abDotProduct=0x%x "
+ "cdDotProduct=%d muxSum=%d)\n",
+ __FUNCTION__,
+ stage, portion, abOutput, cdOutput, sumOutput, scale, bias,
+ abDotProduct, cdDotProduct, muxSum);
+ */
+ if( stage < GL_COMBINER0_NV || stage >= GL_COMBINER0_NV + g->limits.maxGeneralCombiners )
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "CombinerOutputNV passed bogus stage: 0x%x", stage );
+ return;
+ }
+ if( abOutput != GL_DISCARD_NV && abOutput != GL_PRIMARY_COLOR_NV && abOutput != GL_SECONDARY_COLOR_NV && abOutput != GL_SPARE0_NV && abOutput != GL_SPARE1_NV && ( abOutput < GL_TEXTURE0_ARB || abOutput >= g->limits.maxTextureUnits + GL_TEXTURE0_ARB ))
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "CombinerOutputNV passed bogus abOutput: 0x%x", abOutput );
+ return;
+ }
+ if( cdOutput != GL_DISCARD_NV && cdOutput != GL_PRIMARY_COLOR_NV && cdOutput != GL_SECONDARY_COLOR_NV && cdOutput != GL_SPARE0_NV && cdOutput != GL_SPARE1_NV && ( cdOutput < GL_TEXTURE0_ARB || cdOutput >= g->limits.maxTextureUnits + GL_TEXTURE0_ARB ))
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "CombinerOutputNV passed bogus cdOutput: 0x%x", cdOutput );
+ return;
+ }
+ if( sumOutput != GL_DISCARD_NV && sumOutput != GL_PRIMARY_COLOR_NV && sumOutput != GL_SECONDARY_COLOR_NV && sumOutput != GL_SPARE0_NV && sumOutput != GL_SPARE1_NV && sumOutput != GL_TEXTURE0_ARB && sumOutput != GL_TEXTURE1_ARB )
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "CombinerOutputNV passed bogus sumOutput: 0x%x", sumOutput );
+ return;
+ }
+ if( scale != GL_NONE && scale != GL_SCALE_BY_TWO_NV && scale != GL_SCALE_BY_FOUR_NV && scale != GL_SCALE_BY_ONE_HALF_NV )
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "CombinerOutputNV passed bogus scale: 0x%x", scale );
+ return;
+ }
+ if( bias != GL_NONE && bias != GL_BIAS_BY_NEGATIVE_ONE_HALF_NV )
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "CombinerOutputNV passed bogus bias: 0x%x", bias );
+ return;
+ }
+
+ if( bias == GL_BIAS_BY_NEGATIVE_ONE_HALF_NV && ( scale == GL_SCALE_BY_ONE_HALF_NV || scale == GL_SCALE_BY_FOUR_NV ))
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "CombinerOutputNV can't accept bias of -1/2 if scale is by 1/2 or 4" );
+ return;
+ }
+ if(( abOutput == cdOutput && abOutput != GL_DISCARD_NV )||( abOutput == sumOutput && abOutput != GL_DISCARD_NV )||( cdOutput == sumOutput && cdOutput != GL_DISCARD_NV ))
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "CombinerOutputNV register output names must be unique unless discarded: abOutput = 0x%x, cdOutput = 0x%x, sumOutput = 0x%x", abOutput, cdOutput, sumOutput );
+ return;
+ }
+ if( abDotProduct || cdDotProduct )
+ {
+ if( portion == GL_ALPHA )
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "CombinerOutputNV can not do Dot Products when portion = GL_ALPHA" );
+ return;
+ }
+ if( sumOutput != GL_DISCARD_NV )
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "CombinerOutputNV can not do Dot Products when sumOutput is not discarded" );
+ return;
+ }
+ }
+
+ stage -= GL_COMBINER0_NV;
+ if( portion == GL_RGB )
+ {
+ r->rgb[stage].abOutput = abOutput;
+ r->rgb[stage].cdOutput = cdOutput;
+ r->rgb[stage].sumOutput = sumOutput;
+ r->rgb[stage].scale = scale;
+ r->rgb[stage].bias = bias;
+ r->rgb[stage].abDotProduct = abDotProduct;
+ r->rgb[stage].cdDotProduct = cdDotProduct;
+ r->rgb[stage].muxSum = muxSum;
+ }
+ else if( portion == GL_ALPHA )
+ {
+ r->alpha[stage].abOutput = abOutput;
+ r->alpha[stage].cdOutput = cdOutput;
+ r->alpha[stage].sumOutput = sumOutput;
+ r->alpha[stage].scale = scale;
+ r->alpha[stage].bias = bias;
+ r->alpha[stage].abDotProduct = abDotProduct;
+ r->alpha[stage].cdDotProduct = cdDotProduct;
+ r->alpha[stage].muxSum = muxSum;
+ }
+ else
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "CombinerOutputNV passed bogus portion: 0x%x", portion );
+ return;
+ }
+
+ DIRTY(rb->regCombinerOutput[stage], g->neg_bitid);
+ DIRTY(rb->dirty, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateFinalCombinerInputNV( GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage )
+{
+ CRContext *g = GetCurrentContext();
+ CRRegCombinerState *r = &(g->regcombiner);
+ CRStateBits *sb = GetCurrentBits();
+ CRRegCombinerBits *rb = &(sb->regcombiner);
+
+ if( input != GL_ZERO && input != GL_CONSTANT_COLOR0_NV && input != GL_CONSTANT_COLOR1_NV && input != GL_FOG && input != GL_PRIMARY_COLOR_NV && input != GL_SECONDARY_COLOR_NV && input != GL_SPARE0_NV && input != GL_SPARE1_NV && ( input < GL_TEXTURE0_ARB || input >= GL_TEXTURE0_ARB + g->limits.maxTextureUnits ) && input != GL_E_TIMES_F_NV && input != GL_SPARE0_PLUS_SECONDARY_COLOR_NV )
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "FinalCombinerInputNV passed bogus input: 0x%x", input );
+ return;
+ }
+ if( mapping != GL_UNSIGNED_IDENTITY_NV && mapping != GL_UNSIGNED_INVERT_NV && mapping != GL_EXPAND_NORMAL_NV && mapping != GL_EXPAND_NEGATE_NV && mapping != GL_HALF_BIAS_NORMAL_NV && mapping != GL_HALF_BIAS_NEGATE_NV && mapping != GL_SIGNED_IDENTITY_NV && mapping != GL_SIGNED_NEGATE_NV )
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "FinalCombinerInputNV passed bogus mapping: 0x%x", mapping );
+ return;
+ }
+ if( componentUsage != GL_RGB && componentUsage != GL_ALPHA && componentUsage != GL_BLUE )
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "FinalCombinerInputNV passed bogus componentUsage: 0x%x", componentUsage );
+ return;
+ }
+
+ if( componentUsage == GL_ALPHA && ( input == GL_E_TIMES_F_NV || input == GL_SPARE0_PLUS_SECONDARY_COLOR_NV ))
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "FinalCombinerInputNV does not allow componentUsage of ALPHA when input is E_TIMES_F or SPARE0_PLUS_SECONDARY_COLOR" );
+ return;
+ }
+
+ switch( variable )
+ {
+ case GL_VARIABLE_A_NV:
+ r->a = input;
+ r->aMapping = mapping;
+ r->aPortion = componentUsage;
+ break;
+ case GL_VARIABLE_B_NV:
+ r->b = input;
+ r->bMapping = mapping;
+ r->bPortion = componentUsage;
+ break;
+ case GL_VARIABLE_C_NV:
+ r->c = input;
+ r->cMapping = mapping;
+ r->cPortion = componentUsage;
+ break;
+ case GL_VARIABLE_D_NV:
+ r->d = input;
+ r->dMapping = mapping;
+ r->dPortion = componentUsage;
+ break;
+ case GL_VARIABLE_E_NV:
+ r->e = input;
+ r->eMapping = mapping;
+ r->ePortion = componentUsage;
+ break;
+ case GL_VARIABLE_F_NV:
+ r->f = input;
+ r->fMapping = mapping;
+ r->fPortion = componentUsage;
+ break;
+ case GL_VARIABLE_G_NV:
+ if( componentUsage != GL_ALPHA )
+ {
+ crStateError( __LINE__, __FILE__, GL_INVALID_OPERATION, "FinalCombinerInputNV can not have variable G when componentUsage is RGB or BLUE" );
+ return;
+ }
+ r->g = input;
+ r->gMapping = mapping;
+ r->gPortion = componentUsage;
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "CombinerOutputNV passed bogus variable: 0x%x", variable );
+ return;
+ }
+
+ DIRTY(rb->regCombinerFinalInput, g->neg_bitid);
+ DIRTY(rb->dirty, g->neg_bitid);
+}
+
+
+/* XXX Unfinished RegCombiner State functions */
+void STATE_APIENTRY crStateGetCombinerOutputParameterfvNV( GLenum stage, GLenum portion, GLenum pname, GLfloat *params )
+{
+ (void) stage;
+ (void) portion;
+ (void) pname;
+ (void) params;
+}
+
+void STATE_APIENTRY crStateGetCombinerOutputParameterivNV( GLenum stage, GLenum portion, GLenum pname, GLint *params )
+{
+ (void) stage;
+ (void) portion;
+ (void) pname;
+ (void) params;
+}
+
+void STATE_APIENTRY crStateGetFinalCombinerInputParameterfvNV( GLenum variable, GLenum pname, GLfloat *params )
+{
+ (void) variable;
+ (void) pname;
+ (void) params;
+}
+
+void STATE_APIENTRY crStateGetFinalCombinerInputParameterivNV( GLenum variable, GLenum pname, GLint *params )
+{
+ (void) variable;
+ (void) pname;
+ (void) params;
+}
+
+
+void STATE_APIENTRY crStateGetCombinerInputParameterivNV( GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint *params )
+{
+ CRContext *g = GetCurrentContext();
+ CRRegCombinerState *r = &(g->regcombiner);
+ int i = stage - GL_COMBINER0_NV;
+ GLenum input = 0, mapping = 0, usage = 0;
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetCombinerParameterivNV called in begin/end");
+ return;
+ }
+
+ if (i < 0 || i >= CR_MAX_GENERAL_COMBINERS) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "GetCombinerInputParameterivNV(stage=0x%x)", stage);
+ return;
+ }
+
+ if (portion == GL_RGB) {
+ switch (variable) {
+ case GL_VARIABLE_A_NV:
+ input = r->rgb[i].a;
+ mapping = r->rgb[i].aMapping;
+ usage = r->rgb[i].aPortion;
+ break;
+ case GL_VARIABLE_B_NV:
+ input = r->rgb[i].b;
+ mapping = r->rgb[i].bMapping;
+ usage = r->rgb[i].bPortion;
+ break;
+ case GL_VARIABLE_C_NV:
+ input = r->rgb[i].c;
+ mapping = r->rgb[i].cMapping;
+ usage = r->rgb[i].cPortion;
+ break;
+ case GL_VARIABLE_D_NV:
+ input = r->rgb[i].d;
+ mapping = r->rgb[i].dMapping;
+ usage = r->rgb[i].dPortion;
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetCombinerInputParameterivNV(variable=0x%x)", variable);
+ return;
+ }
+ }
+ else if (portion == GL_ALPHA) {
+ switch (variable) {
+ case GL_VARIABLE_A_NV:
+ input = r->alpha[i].a;
+ mapping = r->alpha[i].aMapping;
+ usage = r->alpha[i].aPortion;
+ break;
+ case GL_VARIABLE_B_NV:
+ input = r->alpha[i].b;
+ mapping = r->alpha[i].bMapping;
+ usage = r->alpha[i].bPortion;
+ break;
+ case GL_VARIABLE_C_NV:
+ input = r->alpha[i].c;
+ mapping = r->alpha[i].cMapping;
+ usage = r->alpha[i].cPortion;
+ break;
+ case GL_VARIABLE_D_NV:
+ input = r->alpha[i].d;
+ mapping = r->alpha[i].dMapping;
+ usage = r->alpha[i].dPortion;
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetCombinerInputParameterivNV(variable=0x%x)", variable);
+ return;
+ }
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetCombinerInputParameterivNV(portion=0x%x)", portion);
+ }
+ switch (pname) {
+ case GL_COMBINER_INPUT_NV:
+ *params = input;
+ return;
+ case GL_COMBINER_MAPPING_NV:
+ *params = mapping;
+ return;
+ case GL_COMBINER_COMPONENT_USAGE_NV:
+ *params = usage;
+ return;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetCombinerInputParameterivNV(pname=0x%x)", pname);
+ return;
+ }
+}
+
+
+void STATE_APIENTRY crStateGetCombinerInputParameterfvNV( GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat *params )
+{
+ GLint iparams;
+ crStateGetCombinerInputParameterivNV(stage, portion, variable, pname, &iparams);
+ *params = (GLfloat) iparams;
+}
+
+
+void STATE_APIENTRY crStateCombinerStageParameterfvNV( GLenum stage, GLenum pname, const GLfloat *params )
+{
+ CRContext *g = GetCurrentContext();
+ CRRegCombinerState *r = &(g->regcombiner);
+ CRStateBits *sb = GetCurrentBits();
+ CRRegCombinerBits *rb = &(sb->regcombiner);
+
+ stage -= GL_COMBINER0_NV;
+ if( stage >= g->limits.maxGeneralCombiners )
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "CombinerStageParameterfvNV passed bogus stage: 0x%x", stage+GL_COMBINER0_NV );
+ return;
+ }
+
+ switch( pname )
+ {
+ case GL_CONSTANT_COLOR0_NV:
+ r->stageConstantColor0[stage].r = params[0];
+ r->stageConstantColor0[stage].g = params[1];
+ r->stageConstantColor0[stage].b = params[2];
+ r->stageConstantColor0[stage].a = params[3];
+ DIRTY(rb->regCombinerStageColor0[stage], g->neg_bitid);
+ break;
+ case GL_CONSTANT_COLOR1_NV:
+ r->stageConstantColor1[stage].r = params[0];
+ r->stageConstantColor1[stage].g = params[1];
+ r->stageConstantColor1[stage].b = params[2];
+ r->stageConstantColor1[stage].a = params[3];
+ DIRTY(rb->regCombinerStageColor1[stage], g->neg_bitid);
+ break;
+ default:
+ crStateError( __LINE__, __FILE__, GL_INVALID_ENUM, "CombinerStageParameter passed bogus pname: 0x%x", pname );
+ return;
+ }
+
+ DIRTY(rb->dirty, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateGetCombinerStageParameterfvNV( GLenum stage, GLenum pname, GLfloat *params )
+{
+ CRContext *g = GetCurrentContext();
+ CRRegCombinerState *r = &(g->regcombiner);
+
+ stage -= GL_COMBINER0_NV;
+ if( stage >= g->limits.maxGeneralCombiners )
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "GetCombinerStageParameterfvNV passed bogus stage: 0x%x", stage+GL_COMBINER0_NV );
+ return;
+ }
+ switch( pname )
+ {
+ case GL_CONSTANT_COLOR0_NV:
+ params[0] = r->stageConstantColor0[stage].r;
+ params[1] = r->stageConstantColor0[stage].g;
+ params[2] = r->stageConstantColor0[stage].b;
+ params[3] = r->stageConstantColor0[stage].a;
+ break;
+ case GL_CONSTANT_COLOR1_NV:
+ params[0] = r->stageConstantColor1[stage].r;
+ params[1] = r->stageConstantColor1[stage].g;
+ params[2] = r->stageConstantColor1[stage].b;
+ params[3] = r->stageConstantColor1[stage].a;
+ break;
+ default:
+ crStateError( __LINE__, __FILE__, GL_INVALID_ENUM, "GetCombinerStageParameter passed bogus pname: 0x%x", pname );
+ return;
+ }
+ return;
+}
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_regcombiner.txt b/src/VBox/GuestHost/OpenGL/state_tracker/state_regcombiner.txt
new file mode 100644
index 00000000..4b867ee5
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_regcombiner.txt
@@ -0,0 +1,38 @@
+# Copyright (c) 2001, Stanford University
+# All rights reserved.
+#
+# See the file LICENSE.txt for information on redistributing this software.
+:enable:enabledRegCombiners:GL_REGISTER_COMBINERS_NV
+:enable:enabledPerStageConstants:GL_PER_STAGE_CONSTANTS_NV
+%flush
+:regCombinerVars:numGeneralCombiners:CombinerParameteriNV, GL_NUM_GENERAL_COMBINERS_NV
+:regCombinerVars:colorSumClamp:CombinerParameteriNV, GL_COLOR_SUM_CLAMP_NV
+:regCombinerColor0:constantColor0|r,g,b,a:CombinerParameterfvNV, GL_CONSTANT_COLOR0_NV
+:regCombinerColor1:constantColor1|r,g,b,a:CombinerParameterfvNV, GL_CONSTANT_COLOR1_NV
+%flush
+>for( i=0; i<CR_MAX_GENERAL_COMBINERS; i++ ) {
+:regCombinerStageColor0[i]:stageConstantColor0[i]|r,g,b,a:CombinerStageParameterfvNV, GL_COMBINER0_NV+i, GL_CONSTANT_COLOR0_NV
+:regCombinerStageColor1[i]:stageConstantColor1[i]|r,g,b,a:CombinerStageParameterfvNV, GL_COMBINER0_NV+i, GL_CONSTANT_COLOR1_NV
+:regCombinerInput[i]:rgb[i].a,rgb[i].aMapping,rgb[i].aPortion:*diff_api.CombinerInputNV( GL_COMBINER0_NV+i, GL_RGB, GL_VARIABLE_A_NV, to->rgb[i].a, to->rgb[i].aMapping, to->rgb[i].aPortion );
+:regCombinerInput[i]:rgb[i].b,rgb[i].bMapping,rgb[i].bPortion:*diff_api.CombinerInputNV( GL_COMBINER0_NV+i, GL_RGB, GL_VARIABLE_B_NV, to->rgb[i].b, to->rgb[i].bMapping, to->rgb[i].bPortion );
+:regCombinerInput[i]:rgb[i].c,rgb[i].cMapping,rgb[i].cPortion:*diff_api.CombinerInputNV( GL_COMBINER0_NV+i, GL_RGB, GL_VARIABLE_C_NV, to->rgb[i].c, to->rgb[i].cMapping, to->rgb[i].cPortion );
+:regCombinerInput[i]:rgb[i].d,rgb[i].dMapping,rgb[i].dPortion:*diff_api.CombinerInputNV( GL_COMBINER0_NV+i, GL_RGB, GL_VARIABLE_D_NV, to->rgb[i].d, to->rgb[i].dMapping, to->rgb[i].dPortion );
+:regCombinerInput[i]:alpha[i].a,alpha[i].aMapping,alpha[i].aPortion:*diff_api.CombinerInputNV( GL_COMBINER0_NV+i, GL_ALPHA, GL_VARIABLE_A_NV, to->alpha[i].a, to->alpha[i].aMapping, to->alpha[i].aPortion );
+:regCombinerInput[i]:alpha[i].b,alpha[i].bMapping,alpha[i].bPortion:*diff_api.CombinerInputNV( GL_COMBINER0_NV+i, GL_ALPHA, GL_VARIABLE_B_NV, to->alpha[i].b, to->alpha[i].bMapping, to->alpha[i].bPortion );
+:regCombinerInput[i]:alpha[i].c,alpha[i].cMapping,alpha[i].cPortion:*diff_api.CombinerInputNV( GL_COMBINER0_NV+i, GL_ALPHA, GL_VARIABLE_C_NV, to->alpha[i].c, to->alpha[i].cMapping, to->alpha[i].cPortion );
+:regCombinerInput[i]:alpha[i].d,alpha[i].dMapping,alpha[i].dPortion:*diff_api.CombinerInputNV( GL_COMBINER0_NV+i, GL_ALPHA, GL_VARIABLE_D_NV, to->alpha[i].d, to->alpha[i].dMapping, to->alpha[i].dPortion );
+:regCombinerOutput[i]:rgb[i]|abOutput,cdOutput,sumOutput,scale,bias,abDotProduct,cdDotProduct,muxSum:*diff_api.CombinerOutputNV( GL_COMBINER0_NV+i, GL_RGB, to->rgb[i].abOutput, to->rgb[i].cdOutput, to->rgb[i].sumOutput, to->rgb[i].scale, to->rgb[i].bias, to->rgb[i].abDotProduct, to->rgb[i].cdDotProduct, to->rgb[i].muxSum );
+:regCombinerOutput[i]:alpha[i]|abOutput,cdOutput,sumOutput,scale,bias,abDotProduct,cdDotProduct,muxSum:*diff_api.CombinerOutputNV( GL_COMBINER0_NV+i, GL_ALPHA, to->alpha[i].abOutput, to->alpha[i].cdOutput, to->alpha[i].sumOutput, to->alpha[i].scale, to->alpha[i].bias, to->alpha[i].abDotProduct, to->alpha[i].cdDotProduct, to->alpha[i].muxSum );
+%flush
+>}
+:regCombinerFinalInput:a,aMapping,aPortion:*diff_api.FinalCombinerInputNV( GL_VARIABLE_A_NV, to->a, to->aMapping, to->aPortion );
+:regCombinerFinalInput:b,bMapping,bPortion:*diff_api.FinalCombinerInputNV( GL_VARIABLE_B_NV, to->b, to->bMapping, to->bPortion );
+:regCombinerFinalInput:c,cMapping,cPortion:*diff_api.FinalCombinerInputNV( GL_VARIABLE_C_NV, to->c, to->cMapping, to->cPortion );
+:regCombinerFinalInput:d,dMapping,dPortion:*diff_api.FinalCombinerInputNV( GL_VARIABLE_D_NV, to->d, to->dMapping, to->dPortion );
+:regCombinerFinalInput:e,eMapping,ePortion:*diff_api.FinalCombinerInputNV( GL_VARIABLE_E_NV, to->e, to->eMapping, to->ePortion );
+:regCombinerFinalInput:f,fMapping,fPortion:*diff_api.FinalCombinerInputNV( GL_VARIABLE_F_NV, to->f, to->fMapping, to->fPortion );
+:regCombinerFinalInput:g,gMapping,gPortion:*diff_api.FinalCombinerInputNV( GL_VARIABLE_G_NV, to->g, to->gMapping, to->gPortion );
+%flush
+%target=to
+%current=from
+%bit=b
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_select_special b/src/VBox/GuestHost/OpenGL/state_tracker/state_select_special
new file mode 100644
index 00000000..e7b41e36
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_select_special
@@ -0,0 +1,61 @@
+Vertex4f
+Begin
+End
+Vertex2d
+Vertex2dv
+Vertex2f
+Vertex2fv
+Vertex2i
+Vertex2iv
+Vertex2s
+Vertex2sv
+Vertex3d
+Vertex3dv
+Vertex3f
+Vertex3fv
+Vertex3i
+Vertex3iv
+Vertex3s
+Vertex3sv
+Vertex4d
+Vertex4dv
+Vertex4fv
+Vertex4i
+Vertex4iv
+Vertex4s
+Vertex4sv
+Rectf
+Recti
+Rectd
+Rects
+Rectiv
+Rectfv
+Rectdv
+Rectsv
+DrawPixels
+CopyPixels
+Bitmap
+RasterPos2d
+RasterPos2dv
+RasterPos2f
+RasterPos2fv
+RasterPos2i
+RasterPos2iv
+RasterPos2s
+RasterPos2sv
+RasterPos3d
+RasterPos3dv
+RasterPos3f
+RasterPos3fv
+RasterPos3i
+RasterPos3iv
+RasterPos3s
+RasterPos3sv
+RasterPos4d
+RasterPos4dv
+RasterPos4f
+RasterPos4fv
+RasterPos4i
+RasterPos4iv
+RasterPos4s
+RasterPos4sv
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_snapshot.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_snapshot.c
new file mode 100644
index 00000000..ee17cd37
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_snapshot.c
@@ -0,0 +1,2678 @@
+/* $Id: state_snapshot.c $ */
+/** @file
+ * VBox Context state saving/loading used by VM snapshot
+ */
+
+/*
+ * Copyright (C) 2008-2019 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 "state.h"
+#include "state_internals.h"
+#include "state/cr_statetypes.h"
+#include "state/cr_texture.h"
+#include "cr_mem.h"
+#include "cr_string.h"
+#include "cr_pixeldata.h"
+#include <stdio.h>
+
+#include <iprt/assert.h>
+#include <iprt/types.h>
+#include <iprt/err.h>
+#include <VBox/err.h>
+#include <VBox/log.h>
+
+/** @todo
+ * We have two ways of saving/loading states.
+ *
+ * First which is being used atm, just pure saving/loading of structures.
+ * The drawback is we have to deal with all the pointers around those structures,
+ * we'd have to update this code if we'd change state tracking.
+ * On the bright side it's fast, though it's not really needed as it's not that often operation.
+ * It could also worth to split those functions into appropriate parts,
+ * similar to the way context creation is being done.
+ *
+ * Second way would be to implement full dispatch api table and substitute diff_api during saving/loading.
+ * Then if we implement that api in a similar way to packer/unpacker with a change to store/load
+ * via provided pSSM handle instead of pack buffer,
+ * saving state could be done by simple diffing against empty "dummy" context.
+ * Restoring state in such case would look like unpacking commands from pSSM instead of network buffer.
+ * This would be slower (who cares) but most likely will not require any code changes to support in future.
+ * We will reduce amount of saved data as we'd save only changed state parts, but I doubt it'd be that much.
+ * It could be done for the first way as well, but requires tons of bit checks.
+ */
+
+static int32_t crStateAllocAndSSMR3GetMem(PSSMHANDLE pSSM, void **pBuffer, size_t cbBuffer)
+{
+ CRASSERT(pSSM && pBuffer && cbBuffer>0);
+
+ *pBuffer = crAlloc((unsigned int /* this case is just so stupid */)cbBuffer);
+ if (!*pBuffer)
+ return VERR_NO_MEMORY;
+
+ return SSMR3GetMem(pSSM, *pBuffer, cbBuffer);
+}
+
+#define SHCROGL_GET_STRUCT_PART(_pPtr, _type, _from, _to) do { \
+ rc = SSMR3GetMem(pSSM, &(_pPtr)->_from, RT_UOFFSETOF(_type, _to) - RT_UOFFSETOF(_type, _from)); \
+ AssertRCReturn(rc, rc); \
+ } while (0)
+
+#define SHCROGL_GET_STRUCT_TAIL(_pPtr, _type, _from) do { \
+ rc = SSMR3GetMem(pSSM, &(_pPtr)->_from, sizeof (_type) - RT_UOFFSETOF(_type, _from)); \
+ AssertRCReturn(rc, rc); \
+ } while (0)
+
+#define SHCROGL_GET_STRUCT_HEAD(_pPtr, _type, _to) do { \
+ rc = SSMR3GetMem(pSSM, (_pPtr), RT_UOFFSETOF(_type, _to)); \
+ AssertRCReturn(rc, rc); \
+ } while (0)
+
+#define SHCROGL_CUT_FIELD_ALIGNMENT_SIZE(_type, _prevField, _field) (RT_UOFFSETOF(_type, _field) - RT_UOFFSETOF(_type, _prevField) - RT_SIZEOFMEMB(_type, _prevField))
+#define SHCROGL_CUT_FIELD_ALIGNMENT(_type, _prevField, _field) do { \
+ const int32_t cbAlignment = SHCROGL_CUT_FIELD_ALIGNMENT_SIZE(_type, _prevField, _field) ; \
+ /*AssertCompile(SHCROGL_CUT_FIELD_ALIGNMENT_SIZE(_type, _prevField, _field) >= 0 && SHCROGL_CUT_FIELD_ALIGNMENT_SIZE(_type, _prevField, _field) < sizeof (void*));*/ \
+ if (cbAlignment) { \
+ rc = SSMR3Skip(pSSM, cbAlignment); \
+ } \
+ } 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_UOFFSETOF(_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_UOFFSETOF(_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); \
+ /*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)
+
+static int32_t crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(CRTextureObj *pTexture, PSSMHANDLE pSSM)
+{
+ int32_t rc;
+ uint32_t cbObj = RT_UOFFSETOF(CRTextureObj, ctxUsage);
+ cbObj = ((cbObj + sizeof (void*) - 1) & ~(sizeof (void*) - 1));
+ rc = SSMR3GetMem(pSSM, pTexture, cbObj);
+ AssertRCReturn(rc, rc);
+ /* just make all bits are used so that we fall back to the pre-ctxUsage behavior,
+ * i.e. all shared resources will be destructed on last shared context termination */
+ FILLDIRTY(pTexture->ctxUsage);
+ return rc;
+}
+
+static int32_t crStateLoadTextureUnit_v_BEFORE_CTXUSAGE_BITS(CRTextureUnit *t, PSSMHANDLE pSSM)
+{
+ int32_t rc;
+ SHCROGL_GET_STRUCT_HEAD(t, CRTextureUnit, Saved1D);
+ rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->Saved1D, pSSM);
+ AssertRCReturn(rc, rc);
+ SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureUnit, Saved1D, Saved2D);
+ rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->Saved2D, pSSM);
+ AssertRCReturn(rc, rc);
+ SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureUnit, Saved2D, Saved3D);
+ rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->Saved3D, pSSM);
+ AssertRCReturn(rc, rc);
+#ifdef CR_ARB_texture_cube_map
+ SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureUnit, Saved3D, SavedCubeMap);
+ rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->SavedCubeMap, pSSM);
+ AssertRCReturn(rc, rc);
+# define SHCROGL_INTERNAL_LAST_FIELD SavedCubeMap
+#else
+# define SHCROGL_INTERNAL_LAST_FIELD Saved3D
+#endif
+#ifdef CR_NV_texture_rectangle
+ SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureUnit, SHCROGL_INTERNAL_LAST_FIELD, SavedRect);
+ rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->SavedRect, pSSM);
+ AssertRCReturn(rc, rc);
+# undef SHCROGL_INTERNAL_LAST_FIELD
+# define SHCROGL_INTERNAL_LAST_FIELD SavedRect
+#endif
+ SHCROGL_CUT_TAIL_ALIGNMENT(CRTextureUnit, SHCROGL_INTERNAL_LAST_FIELD);
+#undef SHCROGL_INTERNAL_LAST_FIELD
+ 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;
+ int32_t rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->base1D, pSSM);
+ AssertRCReturn(rc, rc);
+ SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureState, base1D, base2D);
+ rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->base2D, pSSM);
+ AssertRCReturn(rc, rc);
+ rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->base3D, pSSM);
+ SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureState, base2D, base3D);
+ AssertRCReturn(rc, rc);
+#ifdef CR_ARB_texture_cube_map
+ SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureState, base3D, baseCubeMap);
+ rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->baseCubeMap, pSSM);
+ AssertRCReturn(rc, rc);
+# define SHCROGL_INTERNAL_LAST_FIELD baseCubeMap
+#else
+# define SHCROGL_INTERNAL_LAST_FIELD base3D
+#endif
+#ifdef CR_NV_texture_rectangle
+ SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureState, SHCROGL_INTERNAL_LAST_FIELD, baseRect);
+ rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->baseRect, pSSM);
+ AssertRCReturn(rc, rc);
+# undef SHCROGL_INTERNAL_LAST_FIELD
+# define SHCROGL_INTERNAL_LAST_FIELD baseRect
+#endif
+ SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureState, SHCROGL_INTERNAL_LAST_FIELD, proxy1D);
+ rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->proxy1D, pSSM);
+ AssertRCReturn(rc, rc);
+#undef SHCROGL_INTERNAL_LAST_FIELD
+ SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureState, proxy1D, proxy2D);
+ rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->proxy2D, pSSM);
+ AssertRCReturn(rc, rc);
+ SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureState, proxy2D, proxy3D);
+ rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->proxy3D, pSSM);
+ AssertRCReturn(rc, rc);
+#ifdef CR_ARB_texture_cube_map
+ SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureState, proxy3D, proxyCubeMap);
+ rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->proxyCubeMap, pSSM);
+ AssertRCReturn(rc, rc);
+# define SHCROGL_INTERNAL_LAST_FIELD proxyCubeMap
+#else
+# define SHCROGL_INTERNAL_LAST_FIELD proxy3D
+#endif
+#ifdef CR_NV_texture_rectangle
+ SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureState, SHCROGL_INTERNAL_LAST_FIELD, proxyRect);
+ rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->proxyRect, pSSM);
+ AssertRCReturn(rc, rc);
+# undef SHCROGL_INTERNAL_LAST_FIELD
+# define SHCROGL_INTERNAL_LAST_FIELD proxyRect
+#endif
+ SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureState, SHCROGL_INTERNAL_LAST_FIELD, curTextureUnit);
+# undef SHCROGL_INTERNAL_LAST_FIELD
+ SHCROGL_GET_STRUCT_PART(t, CRTextureState, curTextureUnit, unit);
+
+ for (i = 0; i < CR_MAX_TEXTURE_UNITS; ++i)
+ {
+ rc = crStateLoadTextureUnit_v_BEFORE_CTXUSAGE_BITS(&t->unit[i], pSSM);
+ AssertRCReturn(rc, rc);
+ }
+
+ 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));
+ AssertLogRelReturn(rc, rc);
+
+ 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;
+}
+
+static int32_t crStateLoadTextureStack_v_BEFORE_CTXUSAGE_BITS(CRTextureStack *t, PSSMHANDLE pSSM)
+{
+ int32_t i, rc;
+ SHCROGL_GET_STRUCT_HEAD(t, CRTextureStack, unit);
+ for (i = 0; i < CR_MAX_TEXTURE_UNITS; ++i)
+ {
+ rc = crStateLoadTextureUnit_v_BEFORE_CTXUSAGE_BITS(&t->unit[i], pSSM);
+ AssertRCReturn(rc, rc);
+ }
+ SHCROGL_CUT_TAIL_ALIGNMENT(CRTextureStack, unit);
+ return rc;
+}
+
+static int32_t crStateLoadAttribState_v_BEFORE_CTXUSAGE_BITS(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_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);
+ AssertRCReturn(rc, rc);
+ }
+ SHCROGL_GET_STRUCT_TAIL(t, CRAttribState, transformStackDepth);
+ return rc;
+}
+
+
+static int32_t crStateLoadTextureObj(CRTextureObj *pTexture, PSSMHANDLE pSSM, uint32_t u32Version)
+{
+ int32_t rc;
+ if (u32Version == SHCROGL_SSM_VERSION_BEFORE_CTXUSAGE_BITS)
+ return crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(pTexture, pSSM);
+ rc = SSMR3GetMem(pSSM, pTexture, sizeof (*pTexture));
+ AssertRCReturn(rc, rc);
+ return rc;
+}
+
+static int32_t crStateLoadBufferObject(CRBufferObject *pBufferObj, PSSMHANDLE pSSM, uint32_t u32Version)
+{
+ int32_t rc;
+ if (u32Version == SHCROGL_SSM_VERSION_BEFORE_CTXUSAGE_BITS)
+ {
+ uint32_t cbObj = RT_UOFFSETOF(CRBufferObject, ctxUsage);
+ cbObj = ((cbObj + sizeof (void*) - 1) & ~(sizeof (void*) - 1));
+ rc = SSMR3GetMem(pSSM, pBufferObj, cbObj);
+ AssertRCReturn(rc, rc);
+ /* just make all bits are used so that we fall back to the pre-ctxUsage behavior,
+ * i.e. all shared resources will be destructed on last shared context termination */
+ FILLDIRTY(pBufferObj->ctxUsage);
+ }
+ else
+ {
+ rc = SSMR3GetMem(pSSM, pBufferObj, sizeof(*pBufferObj));
+ AssertRCReturn(rc, rc);
+ }
+ return rc;
+}
+
+static int32_t crStateLoadFramebufferObject(CRFramebufferObject *pFBO, PSSMHANDLE pSSM, uint32_t u32Version)
+{
+ int32_t rc;
+ if (u32Version == SHCROGL_SSM_VERSION_BEFORE_CTXUSAGE_BITS)
+ {
+ uint32_t cbObj = RT_UOFFSETOF(CRFramebufferObject, ctxUsage);
+ cbObj = ((cbObj + sizeof (void*) - 1) & ~(sizeof (void*) - 1));
+ rc = SSMR3GetMem(pSSM, pFBO, cbObj);
+ AssertRCReturn(rc, rc);
+ /* just make all bits are used so that we fall back to the pre-ctxUsage behavior,
+ * i.e. all shared resources will be destructed on last shared context termination */
+ FILLDIRTY(pFBO->ctxUsage);
+ }
+ else
+ {
+ rc = SSMR3GetMem(pSSM, pFBO, sizeof(*pFBO));
+ AssertRCReturn(rc, rc);
+ }
+ return rc;
+}
+
+static int32_t crStateLoadRenderbufferObject(CRRenderbufferObject *pRBO, PSSMHANDLE pSSM, uint32_t u32Version)
+{
+ int32_t rc;
+ if (u32Version == SHCROGL_SSM_VERSION_BEFORE_CTXUSAGE_BITS)
+ {
+ uint32_t cbObj = RT_UOFFSETOF(CRRenderbufferObject, ctxUsage);
+ cbObj = ((cbObj + sizeof (void*) - 1) & ~(sizeof (void*) - 1));
+ rc = SSMR3GetMem(pSSM, pRBO, cbObj);
+ AssertRCReturn(rc, rc);
+ /* just make all bits are used so that we fall back to the pre-ctxUsage behavior,
+ * i.e. all shared resources will be destructed on last shared context termination */
+ FILLDIRTY(pRBO->ctxUsage);
+ }
+ else
+ {
+ rc = SSMR3GetMem(pSSM, pRBO, sizeof(*pRBO));
+ AssertRCReturn(rc, rc);
+ }
+ return rc;
+}
+
+static int32_t crStateSaveTextureObjData(CRTextureObj *pTexture, PSSMHANDLE pSSM)
+{
+ int32_t rc, face, i;
+ GLint bound = 0;
+
+ CRASSERT(pTexture && pSSM);
+
+ crDebug("crStateSaveTextureObjData %u. START", pTexture->id);
+
+ for (face = 0; face < 6; face++) {
+ CRASSERT(pTexture->level[face]);
+
+ for (i = 0; i < CR_MAX_MIPMAP_LEVELS; i++) {
+ CRTextureLevel *ptl = &(pTexture->level[face][i]);
+ rc = SSMR3PutMem(pSSM, ptl, sizeof(*ptl));
+ AssertRCReturn(rc, rc);
+ if (ptl->img)
+ {
+ CRASSERT(ptl->bytes);
+ rc = SSMR3PutMem(pSSM, ptl->img, ptl->bytes);
+ AssertRCReturn(rc, rc);
+ }
+#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
+ /* Note, this is not a bug.
+ * Even with CR_STATE_NO_TEXTURE_IMAGE_STORE defined, it's possible that ptl->img!=NULL.
+ * For ex. we're saving snapshot right after it was loaded
+ * and some context hasn't been used by the guest application yet
+ * (pContext->shared->bTexResyncNeeded==GL_TRUE).
+ */
+ else if (ptl->bytes)
+ {
+ char *pImg;
+ GLenum target;
+
+ if (!bound)
+ {
+ GLenum getEnum;
+ diff_api.BindTexture(pTexture->target, pTexture->hwid);
+ bound = 1;
+
+ /* osx nvidia drivers seem to have a bug that 1x1 TEXTURE_2D texture becmes inaccessible for some reason
+ * saw that for 1x1 dummy textures generated by wine
+ * to avoid crashes we skip texture data save if that is the case */
+ switch (pTexture->target)
+ {
+ case GL_TEXTURE_1D:
+ getEnum = GL_TEXTURE_BINDING_1D;
+ break;
+ case GL_TEXTURE_2D:
+ getEnum = GL_TEXTURE_BINDING_2D;
+ break;
+ case GL_TEXTURE_3D:
+ getEnum = GL_TEXTURE_BINDING_3D;
+ break;
+ case GL_TEXTURE_RECTANGLE_ARB:
+ getEnum = GL_TEXTURE_BINDING_RECTANGLE_ARB;
+ break;
+ case GL_TEXTURE_CUBE_MAP_ARB:
+ getEnum = GL_TEXTURE_BINDING_CUBE_MAP_ARB;
+ break;
+ default:
+ crWarning("unknown texture target: 0x%x", pTexture->target);
+ getEnum = 0;
+ break;
+ }
+
+ if (getEnum)
+ {
+ GLint curTex;
+ diff_api.GetIntegerv(getEnum, &curTex);
+ if ((GLuint)curTex != pTexture->hwid)
+ {
+ crWarning("texture not bound properly: expected %d, but was %d. Texture state data: target(0x%x), id(%d), w(%d), h(%d)",
+ pTexture->hwid, curTex,
+ pTexture->target,
+ pTexture->id,
+ ptl->width,
+ ptl->height);
+ bound = -1;
+ }
+ }
+
+ }
+
+ if (pTexture->target!=GL_TEXTURE_CUBE_MAP_ARB)
+ {
+ target = pTexture->target;
+ }
+ else
+ {
+ target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
+ }
+
+#ifdef DEBUG
+ pImg = crAlloc(ptl->bytes+4);
+#else
+ pImg = crAlloc(ptl->bytes);
+#endif
+ if (!pImg) return VERR_NO_MEMORY;
+
+#ifdef DEBUG
+ *(int*)((char*)pImg+ptl->bytes) = 0xDEADDEAD;
+#endif
+ if (bound > 0)
+ {
+#ifdef DEBUG
+ {
+ GLint w,h=0;
+ crDebug("get image: compressed %i, face %i, level %i, width %i, height %i, bytes %i",
+ ptl->compressed, face, i, ptl->width, ptl->height, ptl->bytes);
+ diff_api.GetTexLevelParameteriv(target, i, GL_TEXTURE_WIDTH, &w);
+ diff_api.GetTexLevelParameteriv(target, i, GL_TEXTURE_HEIGHT, &h);
+ if (w!=ptl->width || h!=ptl->height)
+ {
+ crWarning("!!!tex size mismatch %i, %i!!!", w, h);
+ }
+ }
+#endif
+
+ /** @todo ugly workaround for crashes inside ati driver,
+ * they overwrite their own allocated memory in cases where texlevel >=4
+ and width or height <=2.
+ */
+ if (i<4 || (ptl->width>2 && ptl->height>2))
+ {
+ if (!ptl->compressed)
+ {
+ diff_api.GetTexImage(target, i, ptl->format, ptl->type, pImg);
+ }
+ else
+ {
+ diff_api.GetCompressedTexImageARB(target, i, pImg);
+ }
+ }
+ }
+ else
+ {
+ crMemset(pImg, 0, ptl->bytes);
+ }
+
+#ifdef DEBUG
+ if (*(int*)((char*)pImg+ptl->bytes) != 0xDEADDEAD)
+ {
+ crWarning("Texture is bigger than expected!!!");
+ }
+#endif
+
+ rc = SSMR3PutMem(pSSM, pImg, ptl->bytes);
+ crFree(pImg);
+ AssertRCReturn(rc, rc);
+ }
+#endif
+ }
+ }
+
+ crDebug("crStateSaveTextureObjData %u. END", pTexture->id);
+
+ return VINF_SUCCESS;
+}
+
+static int32_t crStateLoadTextureObjData(CRTextureObj *pTexture, PSSMHANDLE pSSM)
+{
+ int32_t rc, face, i;
+
+ CRASSERT(pTexture && pSSM);
+
+ for (face = 0; face < 6; face++) {
+ CRASSERT(pTexture->level[face]);
+
+ for (i = 0; i < CR_MAX_MIPMAP_LEVELS; i++) {
+ CRTextureLevel *ptl = &(pTexture->level[face][i]);
+ CRASSERT(!ptl->img);
+
+ rc = SSMR3GetMem(pSSM, ptl, sizeof(*ptl));
+ AssertRCReturn(rc, rc);
+ if (ptl->img)
+ {
+ CRASSERT(ptl->bytes);
+
+ ptl->img = crAlloc(ptl->bytes);
+ if (!ptl->img) return VERR_NO_MEMORY;
+
+ rc = SSMR3GetMem(pSSM, ptl->img, ptl->bytes);
+ AssertRCReturn(rc, rc);
+ }
+#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
+ /* Same story as in crStateSaveTextureObjData */
+ else if (ptl->bytes)
+ {
+ ptl->img = crAlloc(ptl->bytes);
+ if (!ptl->img) return VERR_NO_MEMORY;
+
+ rc = SSMR3GetMem(pSSM, ptl->img, ptl->bytes);
+ AssertRCReturn(rc, rc);
+ }
+#endif
+ crStateTextureInitTextureFormat(ptl, ptl->internalFormat);
+ }
+ }
+
+ return VINF_SUCCESS;
+}
+
+static void crStateSaveSharedTextureCB(unsigned long key, void *data1, void *data2)
+{
+ CRTextureObj *pTexture = (CRTextureObj *) data1;
+ PSSMHANDLE pSSM = (PSSMHANDLE) data2;
+ int32_t rc;
+
+ CRASSERT(pTexture && pSSM);
+
+ rc = SSMR3PutMem(pSSM, &key, sizeof(key));
+ CRASSERT(rc == VINF_SUCCESS);
+ rc = SSMR3PutMem(pSSM, pTexture, sizeof(*pTexture));
+ CRASSERT(rc == VINF_SUCCESS);
+ rc = crStateSaveTextureObjData(pTexture, pSSM);
+ CRASSERT(rc == VINF_SUCCESS);
+}
+
+static int32_t crStateSaveMatrixStack(CRMatrixStack *pStack, PSSMHANDLE pSSM)
+{
+ return SSMR3PutMem(pSSM, pStack->stack, sizeof(CRmatrix) * pStack->maxDepth);
+}
+
+static int32_t crStateLoadMatrixStack(CRMatrixStack *pStack, PSSMHANDLE pSSM)
+{
+ int32_t rc;
+
+ CRASSERT(pStack && pSSM);
+
+ rc = SSMR3GetMem(pSSM, pStack->stack, sizeof(CRmatrix) * pStack->maxDepth);
+ /* fixup stack top pointer */
+ pStack->top = &pStack->stack[pStack->depth];
+ return rc;
+}
+
+static int32_t crStateSaveTextureObjPtr(CRTextureObj *pTexture, PSSMHANDLE pSSM)
+{
+ /* Current texture pointer can't be NULL for real texture unit states,
+ * but it could be NULL for unused attribute stack depths.
+ */
+ if (pTexture)
+ return SSMR3PutU32(pSSM, pTexture->id);
+ else
+ return VINF_SUCCESS;
+}
+
+static int32_t crStateLoadTextureObjPtr(CRTextureObj **pTexture, CRContext *pContext, GLenum target, PSSMHANDLE pSSM)
+{
+ uint32_t texName;
+ int32_t rc;
+
+ /* We're loading attrib stack with unused state */
+ if (!*pTexture)
+ return VINF_SUCCESS;
+
+ rc = SSMR3GetU32(pSSM, &texName);
+ AssertRCReturn(rc, rc);
+
+ if (texName)
+ {
+ *pTexture = (CRTextureObj *) crHashtableSearch(pContext->shared->textureTable, texName);
+ }
+ else
+ {
+ switch (target)
+ {
+ case GL_TEXTURE_1D:
+ *pTexture = &(pContext->texture.base1D);
+ break;
+ case GL_TEXTURE_2D:
+ *pTexture = &(pContext->texture.base2D);
+ break;
+#ifdef CR_OPENGL_VERSION_1_2
+ case GL_TEXTURE_3D:
+ *pTexture = &(pContext->texture.base3D);
+ break;
+#endif
+#ifdef CR_ARB_texture_cube_map
+ case GL_TEXTURE_CUBE_MAP_ARB:
+ *pTexture = &(pContext->texture.baseCubeMap);
+ break;
+#endif
+#ifdef CR_NV_texture_rectangle
+ case GL_TEXTURE_RECTANGLE_NV:
+ *pTexture = &(pContext->texture.baseRect);
+ break;
+#endif
+ default:
+ crError("LoadTextureObjPtr: Unknown texture target %d", target);
+ }
+ }
+
+ return rc;
+}
+
+static int32_t crStateSaveTexUnitCurrentTexturePtrs(CRTextureUnit *pTexUnit, PSSMHANDLE pSSM)
+{
+ int32_t rc;
+
+ rc = crStateSaveTextureObjPtr(pTexUnit->currentTexture1D, pSSM);
+ AssertRCReturn(rc, rc);
+ rc = crStateSaveTextureObjPtr(pTexUnit->currentTexture2D, pSSM);
+ AssertRCReturn(rc, rc);
+ rc = crStateSaveTextureObjPtr(pTexUnit->currentTexture3D, pSSM);
+ AssertRCReturn(rc, rc);
+#ifdef CR_ARB_texture_cube_map
+ rc = crStateSaveTextureObjPtr(pTexUnit->currentTextureCubeMap, pSSM);
+ AssertRCReturn(rc, rc);
+#endif
+#ifdef CR_NV_texture_rectangle
+ rc = crStateSaveTextureObjPtr(pTexUnit->currentTextureRect, pSSM);
+ AssertRCReturn(rc, rc);
+#endif
+
+ return rc;
+}
+
+static int32_t crStateLoadTexUnitCurrentTexturePtrs(CRTextureUnit *pTexUnit, CRContext *pContext, PSSMHANDLE pSSM)
+{
+ int32_t rc;
+
+ rc = crStateLoadTextureObjPtr(&pTexUnit->currentTexture1D, pContext, GL_TEXTURE_1D, pSSM);
+ AssertRCReturn(rc, rc);
+ rc = crStateLoadTextureObjPtr(&pTexUnit->currentTexture2D, pContext, GL_TEXTURE_1D, pSSM);
+ AssertRCReturn(rc, rc);
+ rc = crStateLoadTextureObjPtr(&pTexUnit->currentTexture3D, pContext, GL_TEXTURE_2D, pSSM);
+ AssertRCReturn(rc, rc);
+#ifdef CR_ARB_texture_cube_map
+ rc = crStateLoadTextureObjPtr(&pTexUnit->currentTextureCubeMap, pContext, GL_TEXTURE_CUBE_MAP_ARB, pSSM);
+ AssertRCReturn(rc, rc);
+#endif
+#ifdef CR_NV_texture_rectangle
+ rc = crStateLoadTextureObjPtr(&pTexUnit->currentTextureRect, pContext, GL_TEXTURE_RECTANGLE_NV, pSSM);
+ AssertRCReturn(rc, rc);
+#endif
+
+ return rc;
+}
+
+static int32_t crSateSaveEvalCoeffs1D(CREvaluator1D *pEval, PSSMHANDLE pSSM)
+{
+ int32_t rc, i;
+
+ for (i=0; i<GLEVAL_TOT; ++i)
+ {
+ if (pEval[i].coeff)
+ {
+ rc = SSMR3PutMem(pSSM, pEval[i].coeff, pEval[i].order * gleval_sizes[i] * sizeof(GLfloat));
+ AssertRCReturn(rc, rc);
+ }
+ }
+
+ return VINF_SUCCESS;
+}
+
+static int32_t crSateSaveEvalCoeffs2D(CREvaluator2D *pEval, PSSMHANDLE pSSM)
+{
+ int32_t rc, i;
+
+ for (i=0; i<GLEVAL_TOT; ++i)
+ {
+ if (pEval[i].coeff)
+ {
+ rc = SSMR3PutMem(pSSM, pEval[i].coeff, pEval[i].uorder * pEval[i].vorder * gleval_sizes[i] * sizeof(GLfloat));
+ AssertRCReturn(rc, rc);
+ }
+ }
+
+ return VINF_SUCCESS;
+}
+
+static int32_t crSateLoadEvalCoeffs1D(CREvaluator1D *pEval, GLboolean bReallocMem, PSSMHANDLE pSSM)
+{
+ int32_t rc, i;
+ size_t size;
+
+ for (i=0; i<GLEVAL_TOT; ++i)
+ {
+ if (pEval[i].coeff)
+ {
+ size = pEval[i].order * gleval_sizes[i] * sizeof(GLfloat);
+ if (bReallocMem)
+ {
+ pEval[i].coeff = (GLfloat*) crAlloc((unsigned int /* this case is just so stupid */)size);
+ if (!pEval[i].coeff) return VERR_NO_MEMORY;
+ }
+ rc = SSMR3GetMem(pSSM, pEval[i].coeff, size);
+ AssertRCReturn(rc, rc);
+ }
+ }
+
+ return VINF_SUCCESS;
+}
+
+static int32_t crSateLoadEvalCoeffs2D(CREvaluator2D *pEval, GLboolean bReallocMem, PSSMHANDLE pSSM)
+{
+ int32_t rc, i;
+ size_t size;
+
+ for (i=0; i<GLEVAL_TOT; ++i)
+ {
+ if (pEval[i].coeff)
+ {
+ size = pEval[i].uorder * pEval[i].vorder * gleval_sizes[i] * sizeof(GLfloat);
+ if (bReallocMem)
+ {
+ pEval[i].coeff = (GLfloat*) crAlloc((unsigned int /* this case is just so stupid */)size);
+ if (!pEval[i].coeff) return VERR_NO_MEMORY;
+ }
+ rc = SSMR3GetMem(pSSM, pEval[i].coeff, size);
+ AssertRCReturn(rc, rc);
+ }
+ }
+
+ return VINF_SUCCESS;
+}
+
+static void crStateCopyEvalPtrs1D(CREvaluator1D *pDst, CREvaluator1D *pSrc)
+{
+ int32_t i;
+
+ for (i=0; i<GLEVAL_TOT; ++i)
+ pDst[i].coeff = pSrc[i].coeff;
+
+ /*
+ pDst[GL_MAP1_VERTEX_3-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_VERTEX_3-GL_MAP1_COLOR_4].coeff;
+ pDst[GL_MAP1_VERTEX_4-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_VERTEX_4-GL_MAP1_COLOR_4].coeff;
+ pDst[GL_MAP1_INDEX-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_INDEX-GL_MAP1_COLOR_4].coeff;
+ pDst[GL_MAP1_COLOR_4-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_COLOR_4-GL_MAP1_COLOR_4].coeff;
+ pDst[GL_MAP1_NORMAL-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_NORMAL-GL_MAP1_COLOR_4].coeff;
+ pDst[GL_MAP1_TEXTURE_COORD_1-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_TEXTURE_COORD_1-GL_MAP1_COLOR_4].coeff;
+ pDst[GL_MAP1_TEXTURE_COORD_2-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_TEXTURE_COORD_2-GL_MAP1_COLOR_4].coeff;
+ pDst[GL_MAP1_TEXTURE_COORD_3-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_TEXTURE_COORD_3-GL_MAP1_COLOR_4].coeff;
+ pDst[GL_MAP1_TEXTURE_COORD_4-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_TEXTURE_COORD_4-GL_MAP1_COLOR_4].coeff;
+ */
+}
+
+static void crStateCopyEvalPtrs2D(CREvaluator2D *pDst, CREvaluator2D *pSrc)
+{
+ int32_t i;
+
+ for (i=0; i<GLEVAL_TOT; ++i)
+ pDst[i].coeff = pSrc[i].coeff;
+
+ /*
+ pDst[GL_MAP2_VERTEX_3-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_VERTEX_3-GL_MAP2_COLOR_4].coeff;
+ pDst[GL_MAP2_VERTEX_4-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_VERTEX_4-GL_MAP2_COLOR_4].coeff;
+ pDst[GL_MAP2_INDEX-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_INDEX-GL_MAP2_COLOR_4].coeff;
+ pDst[GL_MAP2_COLOR_4-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_COLOR_4-GL_MAP2_COLOR_4].coeff;
+ pDst[GL_MAP2_NORMAL-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_NORMAL-GL_MAP2_COLOR_4].coeff;
+ pDst[GL_MAP2_TEXTURE_COORD_1-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_TEXTURE_COORD_1-GL_MAP2_COLOR_4].coeff;
+ pDst[GL_MAP2_TEXTURE_COORD_2-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_TEXTURE_COORD_2-GL_MAP2_COLOR_4].coeff;
+ pDst[GL_MAP2_TEXTURE_COORD_3-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_TEXTURE_COORD_3-GL_MAP2_COLOR_4].coeff;
+ pDst[GL_MAP2_TEXTURE_COORD_4-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_TEXTURE_COORD_4-GL_MAP2_COLOR_4].coeff;
+ */
+}
+
+static void crStateSaveBufferObjectCB(unsigned long key, void *data1, void *data2)
+{
+ CRBufferObject *pBufferObj = (CRBufferObject *) data1;
+ PSSMHANDLE pSSM = (PSSMHANDLE) data2;
+ int32_t rc;
+
+ CRASSERT(pBufferObj && pSSM);
+
+ rc = SSMR3PutMem(pSSM, &key, sizeof(key));
+ CRASSERT(rc == VINF_SUCCESS);
+ rc = SSMR3PutMem(pSSM, pBufferObj, sizeof(*pBufferObj));
+ CRASSERT(rc == VINF_SUCCESS);
+
+ if (pBufferObj->data)
+ {
+ /*We could get here even though retainBufferData is false on host side, in case when we're taking snapshot
+ after state load and before this context was ever made current*/
+ CRASSERT(pBufferObj->size>0);
+ rc = SSMR3PutMem(pSSM, pBufferObj->data, pBufferObj->size);
+ CRASSERT(rc == VINF_SUCCESS);
+ }
+ else if (pBufferObj->id!=0 && pBufferObj->size>0)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, pBufferObj->hwid);
+ pBufferObj->pointer = diff_api.MapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB);
+ rc = SSMR3PutMem(pSSM, &pBufferObj->pointer, sizeof(pBufferObj->pointer));
+ CRASSERT(rc == VINF_SUCCESS);
+ if (pBufferObj->pointer)
+ {
+ rc = SSMR3PutMem(pSSM, pBufferObj->pointer, pBufferObj->size);
+ CRASSERT(rc == VINF_SUCCESS);
+ }
+ diff_api.UnmapBufferARB(GL_ARRAY_BUFFER_ARB);
+ pBufferObj->pointer = NULL;
+ }
+}
+
+static void crStateSaveProgramCB(unsigned long key, void *data1, void *data2)
+{
+ CRProgram *pProgram = (CRProgram *) data1;
+ PSSMHANDLE pSSM = (PSSMHANDLE) data2;
+ CRProgramSymbol *pSymbol;
+ int32_t rc;
+
+ CRASSERT(pProgram && pSSM);
+
+ rc = SSMR3PutMem(pSSM, &key, sizeof(key));
+ CRASSERT(rc == VINF_SUCCESS);
+ rc = SSMR3PutMem(pSSM, pProgram, sizeof(*pProgram));
+ CRASSERT(rc == VINF_SUCCESS);
+ if (pProgram->string)
+ {
+ CRASSERT(pProgram->length);
+ rc = SSMR3PutMem(pSSM, pProgram->string, pProgram->length);
+ CRASSERT(rc == VINF_SUCCESS);
+ }
+
+ for (pSymbol = pProgram->symbolTable; pSymbol; pSymbol=pSymbol->next)
+ {
+ rc = SSMR3PutMem(pSSM, pSymbol, sizeof(*pSymbol));
+ CRASSERT(rc == VINF_SUCCESS);
+ if (pSymbol->name)
+ {
+ CRASSERT(pSymbol->cbName>0);
+ rc = SSMR3PutMem(pSSM, pSymbol->name, pSymbol->cbName);
+ CRASSERT(rc == VINF_SUCCESS);
+ }
+ }
+}
+
+static void crStateSaveFramebuffersCB(unsigned long key, void *data1, void *data2)
+{
+ CRFramebufferObject *pFBO = (CRFramebufferObject*) data1;
+ PSSMHANDLE pSSM = (PSSMHANDLE) data2;
+ int32_t rc;
+
+ rc = SSMR3PutMem(pSSM, &key, sizeof(key));
+ CRASSERT(rc == VINF_SUCCESS);
+
+ rc = SSMR3PutMem(pSSM, pFBO, sizeof(*pFBO));
+ CRASSERT(rc == VINF_SUCCESS);
+}
+
+static void crStateSaveRenderbuffersCB(unsigned long key, void *data1, void *data2)
+{
+ CRRenderbufferObject *pRBO = (CRRenderbufferObject*) data1;
+ PSSMHANDLE pSSM = (PSSMHANDLE) data2;
+ int32_t rc;
+
+ rc = SSMR3PutMem(pSSM, &key, sizeof(key));
+ CRASSERT(rc == VINF_SUCCESS);
+
+ rc = SSMR3PutMem(pSSM, pRBO, sizeof(*pRBO));
+ CRASSERT(rc == VINF_SUCCESS);
+}
+
+static int32_t crStateLoadProgram(CRProgram **ppProgram, PSSMHANDLE pSSM)
+{
+ CRProgramSymbol **ppSymbol;
+ int32_t rc;
+ unsigned long key;
+
+ rc = SSMR3GetMem(pSSM, &key, sizeof(key));
+ AssertRCReturn(rc, rc);
+
+ /* we're loading default vertex or pixel program*/
+ if (*ppProgram)
+ {
+ if (key!=0) return VERR_SSM_UNEXPECTED_DATA;
+ }
+ else
+ {
+ *ppProgram = (CRProgram*) crAlloc(sizeof(CRProgram));
+ if (!ppProgram) return VERR_NO_MEMORY;
+ if (key==0) return VERR_SSM_UNEXPECTED_DATA;
+ }
+
+ rc = SSMR3GetMem(pSSM, *ppProgram, sizeof(**ppProgram));
+ AssertRCReturn(rc, rc);
+
+ if ((*ppProgram)->string)
+ {
+ CRASSERT((*ppProgram)->length);
+ (*ppProgram)->string = crAlloc((*ppProgram)->length);
+ if (!(*ppProgram)->string) return VERR_NO_MEMORY;
+ rc = SSMR3GetMem(pSSM, (void*) (*ppProgram)->string, (*ppProgram)->length);
+ AssertRCReturn(rc, rc);
+ }
+
+ for (ppSymbol = &(*ppProgram)->symbolTable; *ppSymbol; ppSymbol=&(*ppSymbol)->next)
+ {
+ *ppSymbol = crAlloc(sizeof(CRProgramSymbol));
+ if (!ppSymbol) return VERR_NO_MEMORY;
+
+ rc = SSMR3GetMem(pSSM, *ppSymbol, sizeof(**ppSymbol));
+ AssertRCReturn(rc, rc);
+
+ if ((*ppSymbol)->name)
+ {
+ CRASSERT((*ppSymbol)->cbName>0);
+ (*ppSymbol)->name = crAlloc((*ppSymbol)->cbName);
+ if (!(*ppSymbol)->name) return VERR_NO_MEMORY;
+
+ rc = SSMR3GetMem(pSSM, (void*) (*ppSymbol)->name, (*ppSymbol)->cbName);
+ AssertRCReturn(rc, rc);
+ }
+ }
+
+ return VINF_SUCCESS;
+}
+
+static void crStateSaveString(const char *pStr, PSSMHANDLE pSSM)
+{
+ int32_t len;
+ int32_t rc;
+
+ if (pStr)
+ {
+ len = crStrlen(pStr)+1;
+
+ rc = SSMR3PutS32(pSSM, len);
+ CRASSERT(rc == VINF_SUCCESS);
+
+ rc = SSMR3PutMem(pSSM, pStr, len*sizeof(*pStr));
+ CRASSERT(rc == VINF_SUCCESS);
+ }
+ else
+ {
+ rc = SSMR3PutS32(pSSM, 0);
+ CRASSERT(rc == VINF_SUCCESS);
+ }
+}
+
+static char* crStateLoadString(PSSMHANDLE pSSM)
+{
+ int32_t len, rc;
+ char* pStr = NULL;
+
+ rc = SSMR3GetS32(pSSM, &len);
+ CRASSERT(rc == VINF_SUCCESS);
+
+ if (len!=0)
+ {
+ pStr = crAlloc(len*sizeof(*pStr));
+
+ rc = SSMR3GetMem(pSSM, pStr, len*sizeof(*pStr));
+ CRASSERT(rc == VINF_SUCCESS);
+ }
+
+ return pStr;
+}
+
+static void crStateSaveGLSLShaderCB(unsigned long key, void *data1, void *data2)
+{
+ CRGLSLShader *pShader = (CRGLSLShader*) data1;
+ PSSMHANDLE pSSM = (PSSMHANDLE) data2;
+ int32_t rc;
+
+ rc = SSMR3PutMem(pSSM, &key, sizeof(key));
+ CRASSERT(rc == VINF_SUCCESS);
+
+ rc = SSMR3PutMem(pSSM, pShader, sizeof(*pShader));
+ CRASSERT(rc == VINF_SUCCESS);
+
+ if (pShader->source)
+ {
+ crStateSaveString(pShader->source, pSSM);
+ }
+ else
+ {
+ GLint sLen=0;
+ GLchar *source=NULL;
+
+ diff_api.GetShaderiv(pShader->hwid, GL_SHADER_SOURCE_LENGTH, &sLen);
+ if (sLen>0)
+ {
+ source = (GLchar*) crAlloc(sLen);
+ diff_api.GetShaderSource(pShader->hwid, sLen, NULL, source);
+ }
+
+ crStateSaveString(source, pSSM);
+ if (source) crFree(source);
+ }
+}
+
+static CRGLSLShader* crStateLoadGLSLShader(PSSMHANDLE pSSM)
+{
+ CRGLSLShader *pShader;
+ int32_t rc;
+ unsigned long key;
+
+ pShader = crAlloc(sizeof(*pShader));
+ if (!pShader) return NULL;
+
+ rc = SSMR3GetMem(pSSM, &key, sizeof(key));
+ CRASSERT(rc == VINF_SUCCESS);
+
+ rc = SSMR3GetMem(pSSM, pShader, sizeof(*pShader));
+ CRASSERT(rc == VINF_SUCCESS);
+
+ pShader->source = crStateLoadString(pSSM);
+
+ return pShader;
+}
+
+
+static void crStateSaveGLSLShaderKeyCB(unsigned long key, void *data1, void *data2)
+{
+ //CRGLSLShader *pShader = (CRGLSLShader*) data1;
+ PSSMHANDLE pSSM = (PSSMHANDLE) data2;
+ int32_t rc;
+
+ rc = SSMR3PutMem(pSSM, &key, sizeof(key));
+ CRASSERT(rc == VINF_SUCCESS);
+}
+
+static void crStateSaveGLSLProgramAttribs(CRGLSLProgramState *pState, PSSMHANDLE pSSM)
+{
+ GLuint i;
+ int32_t rc;
+
+ for (i=0; i<pState->cAttribs; ++i)
+ {
+ rc = SSMR3PutMem(pSSM, &pState->pAttribs[i].index, sizeof(pState->pAttribs[i].index));
+ CRASSERT(rc == VINF_SUCCESS);
+ crStateSaveString(pState->pAttribs[i].name, pSSM);
+ }
+}
+
+static void crStateSaveGLSLProgramCB(unsigned long key, void *data1, void *data2)
+{
+ CRGLSLProgram *pProgram = (CRGLSLProgram*) data1;
+ PSSMHANDLE pSSM = (PSSMHANDLE) data2;
+ int32_t rc;
+ uint32_t ui32;
+ GLint maxUniformLen, activeUniforms=0, uniformsCount=0, i, j;
+ GLchar *name = NULL;
+ GLenum type;
+ GLint size, location;
+
+ rc = SSMR3PutMem(pSSM, &key, sizeof(key));
+ CRASSERT(rc == VINF_SUCCESS);
+
+ rc = SSMR3PutMem(pSSM, pProgram, sizeof(*pProgram));
+ CRASSERT(rc == VINF_SUCCESS);
+
+ ui32 = crHashtableNumElements(pProgram->currentState.attachedShaders);
+ rc = SSMR3PutU32(pSSM, ui32);
+ CRASSERT(rc == VINF_SUCCESS);
+
+ crHashtableWalk(pProgram->currentState.attachedShaders, crStateSaveGLSLShaderKeyCB, pSSM);
+
+ if (pProgram->activeState.attachedShaders)
+ {
+ ui32 = crHashtableNumElements(pProgram->activeState.attachedShaders);
+ rc = SSMR3PutU32(pSSM, ui32);
+ CRASSERT(rc == VINF_SUCCESS);
+ crHashtableWalk(pProgram->currentState.attachedShaders, crStateSaveGLSLShaderCB, pSSM);
+ }
+
+ crStateSaveGLSLProgramAttribs(&pProgram->currentState, pSSM);
+ crStateSaveGLSLProgramAttribs(&pProgram->activeState, pSSM);
+
+ 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));
+
+ if (!name)
+ {
+ crWarning("crStateSaveGLSLProgramCB: out of memory");
+ return;
+ }
+ }
+
+ for (i=0; i<activeUniforms; ++i)
+ {
+ diff_api.GetActiveUniform(pProgram->hwid, i, maxUniformLen, NULL, &size, &type, name);
+ uniformsCount += size;
+ }
+ CRASSERT(uniformsCount>=activeUniforms);
+
+ rc = SSMR3PutS32(pSSM, uniformsCount);
+ CRASSERT(rc == VINF_SUCCESS);
+
+ if (activeUniforms>0)
+ {
+ GLfloat fdata[16];
+ GLint idata[16];
+ char *pIndexStr=NULL;
+
+ for (i=0; i<activeUniforms; ++i)
+ {
+ diff_api.GetActiveUniform(pProgram->hwid, i, maxUniformLen, NULL, &size, &type, name);
+
+ if (size>1)
+ {
+ pIndexStr = crStrchr(name, '[');
+ if (!pIndexStr)
+ {
+ pIndexStr = name+crStrlen(name);
+ }
+ }
+
+ for (j=0; j<size; ++j)
+ {
+ if (size>1)
+ {
+ sprintf(pIndexStr, "[%i]", j);
+ }
+ location = diff_api.GetUniformLocation(pProgram->hwid, name);
+
+ rc = SSMR3PutMem(pSSM, &type, sizeof(type));
+ CRASSERT(rc == VINF_SUCCESS);
+
+ crStateSaveString(name, pSSM);
+
+ if (crStateIsIntUniform(type))
+ {
+ diff_api.GetUniformiv(pProgram->hwid, location, &idata[0]);
+ rc = SSMR3PutMem(pSSM, &idata[0], crStateGetUniformSize(type)*sizeof(idata[0]));
+ CRASSERT(rc == VINF_SUCCESS);
+ }
+ else
+ {
+ diff_api.GetUniformfv(pProgram->hwid, location, &fdata[0]);
+ rc = SSMR3PutMem(pSSM, &fdata[0], crStateGetUniformSize(type)*sizeof(fdata[0]));
+ CRASSERT(rc == VINF_SUCCESS);
+ }
+ }
+ }
+
+ crFree(name);
+ }
+}
+
+static int32_t crStateSaveClientPointer(CRVertexArrays *pArrays, int32_t index, PSSMHANDLE pSSM)
+{
+ int32_t rc;
+ CRClientPointer *cp;
+
+ cp = crStateGetClientPointerByIndex(index, pArrays);
+
+ if (cp->buffer)
+ rc = SSMR3PutU32(pSSM, cp->buffer->id);
+ else
+ rc = SSMR3PutU32(pSSM, 0);
+
+ AssertRCReturn(rc, rc);
+
+#ifdef CR_EXT_compiled_vertex_array
+ if (cp->locked)
+ {
+ CRASSERT(cp->p);
+ rc = SSMR3PutMem(pSSM, cp->p, cp->stride*(pArrays->lockFirst+pArrays->lockCount));
+ AssertRCReturn(rc, rc);
+ }
+#endif
+
+ return VINF_SUCCESS;
+}
+
+static int32_t crStateLoadClientPointer(CRVertexArrays *pArrays, int32_t index, CRContext *pContext, PSSMHANDLE pSSM)
+{
+ int32_t rc;
+ uint32_t ui;
+ CRClientPointer *cp;
+
+ cp = crStateGetClientPointerByIndex(index, pArrays);
+
+ rc = SSMR3GetU32(pSSM, &ui);
+ AssertRCReturn(rc, rc);
+ cp->buffer = ui==0 ? pContext->bufferobject.nullBuffer : crHashtableSearch(pContext->shared->buffersTable, ui);
+
+ if (!cp->buffer)
+ {
+ crWarning("crStateLoadClientPointer: ui=%d loaded as NULL buffer!", ui);
+ }
+
+#ifdef CR_EXT_compiled_vertex_array
+ if (cp->locked)
+ {
+ rc = crStateAllocAndSSMR3GetMem(pSSM, (void**)&cp->p, cp->stride*(pArrays->lockFirst+pArrays->lockCount));
+ AssertRCReturn(rc, rc);
+ }
+#endif
+
+ return VINF_SUCCESS;
+}
+
+static int32_t crStateSaveCurrentBits(CRStateBits *pBits, PSSMHANDLE pSSM)
+{
+ int32_t rc, i;
+
+ rc = SSMR3PutMem(pSSM, pBits, sizeof(*pBits));
+ AssertRCReturn(rc, rc);
+
+ rc = SSMR3PutMem(pSSM, pBits->client.v, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+ AssertRCReturn(rc, rc);
+ rc = SSMR3PutMem(pSSM, pBits->client.n, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+ AssertRCReturn(rc, rc);
+ rc = SSMR3PutMem(pSSM, pBits->client.c, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+ AssertRCReturn(rc, rc);
+ rc = SSMR3PutMem(pSSM, pBits->client.s, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+ AssertRCReturn(rc, rc);
+ rc = SSMR3PutMem(pSSM, pBits->client.i, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+ AssertRCReturn(rc, rc);
+ for (i=0; i<CR_MAX_TEXTURE_UNITS; i++)
+ {
+ rc = SSMR3PutMem(pSSM, pBits->client.t[i], GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+ AssertRCReturn(rc, rc);
+ }
+ rc = SSMR3PutMem(pSSM, pBits->client.e, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+ AssertRCReturn(rc, rc);
+ rc = SSMR3PutMem(pSSM, pBits->client.f, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+ AssertRCReturn(rc, rc);
+#ifdef CR_NV_vertex_program
+ for (i=0; i<CR_MAX_VERTEX_ATTRIBS; i++)
+ {
+ rc = SSMR3PutMem(pSSM, pBits->client.a[i], GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+ AssertRCReturn(rc, rc);
+ }
+#endif
+
+ rc = SSMR3PutMem(pSSM, pBits->lighting.light, CR_MAX_LIGHTS*sizeof(pBits->lighting.light));
+ AssertRCReturn(rc, rc);
+
+ return VINF_SUCCESS;
+}
+
+static int32_t crStateLoadCurrentBits(CRStateBits *pBits, PSSMHANDLE pSSM)
+{
+ int32_t rc, i;
+ CRClientBits client;
+ CRLightingBits lighting;
+
+ CRASSERT(pBits);
+
+ client.v = pBits->client.v;
+ client.n = pBits->client.n;
+ client.c = pBits->client.c;
+ client.s = pBits->client.s;
+ client.i = pBits->client.i;
+ client.e = pBits->client.e;
+ client.f = pBits->client.f;
+ for (i=0; i<CR_MAX_TEXTURE_UNITS; i++)
+ {
+ client.t[i] = pBits->client.t[i];
+ }
+#ifdef CR_NV_vertex_program
+ for (i=0; i<CR_MAX_VERTEX_ATTRIBS; i++)
+ {
+ client.a[i] = pBits->client.a[i];
+ }
+#endif
+ lighting.light = pBits->lighting.light;
+
+ rc = SSMR3GetMem(pSSM, pBits, sizeof(*pBits));
+ AssertRCReturn(rc, rc);
+
+ pBits->client.v = client.v;
+ rc = SSMR3GetMem(pSSM, pBits->client.v, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+ AssertRCReturn(rc, rc);
+ pBits->client.n = client.n;
+ rc = SSMR3GetMem(pSSM, pBits->client.n, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+ AssertRCReturn(rc, rc);
+ pBits->client.c = client.c;
+ rc = SSMR3GetMem(pSSM, pBits->client.c, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+ AssertRCReturn(rc, rc);
+ pBits->client.s = client.s;
+ rc = SSMR3GetMem(pSSM, pBits->client.s, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+ AssertRCReturn(rc, rc);
+ pBits->client.i = client.i;
+ rc = SSMR3GetMem(pSSM, pBits->client.i, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+ AssertRCReturn(rc, rc);
+ pBits->client.e = client.e;
+ rc = SSMR3GetMem(pSSM, pBits->client.e, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+ AssertRCReturn(rc, rc);
+ pBits->client.f = client.f;
+ rc = SSMR3GetMem(pSSM, pBits->client.f, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+ AssertRCReturn(rc, rc);
+ for (i=0; i<CR_MAX_TEXTURE_UNITS; i++)
+ {
+ pBits->client.t[i] = client.t[i];
+ rc = SSMR3GetMem(pSSM, pBits->client.t[i], GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+ AssertRCReturn(rc, rc);
+ }
+#ifdef CR_NV_vertex_program
+ for (i=0; i<CR_MAX_VERTEX_ATTRIBS; i++)
+ {
+ pBits->client.a[i] = client.a[i];
+ rc = SSMR3GetMem(pSSM, pBits->client.a[i], GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+ AssertRCReturn(rc, rc);
+ }
+#endif
+
+ pBits->lighting.light = lighting.light;
+ rc = SSMR3GetMem(pSSM, pBits->lighting.light, CR_MAX_LIGHTS*sizeof(pBits->lighting.light));
+ AssertRCReturn(rc, rc);
+
+ 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); NOREF(fIsNew);
+#if 0 //def DEBUG_misha
+ CRASSERT(fIsNew);
+#endif
+ }
+ }
+ }
+ /* not reached*/
+}
+
+
+int32_t crStateSaveContext(CRContext *pContext, PSSMHANDLE pSSM)
+{
+ int32_t rc, i;
+ uint32_t ui32, j;
+ GLboolean bSaveShared = GL_TRUE;
+
+ CRASSERT(pContext && pSSM);
+
+ CRASSERT(pContext->client.attribStackDepth == 0);
+
+ /* this stuff is not used anymore, zero it up for sanity */
+ pContext->buffer.storedWidth = 0;
+ pContext->buffer.storedHeight = 0;
+
+ CRASSERT(VBoxTlsRefIsFunctional(pContext));
+
+ /* 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, sizeof (*pContext));
+ AssertRCReturn(rc, rc);
+
+ if (crHashtableNumElements(pContext->shared->dlistTable)>0)
+ crWarning("Saving state with %d display lists, unsupported", crHashtableNumElements(pContext->shared->dlistTable));
+
+ if (crHashtableNumElements(pContext->program.programHash)>0)
+ crDebug("Saving state with %d programs", crHashtableNumElements(pContext->program.programHash));
+
+ rc = SSMR3PutS32(pSSM, pContext->shared->id);
+ AssertRCReturn(rc, rc);
+
+ rc = SSMR3PutS32(pSSM, crStateContextIsShared(pContext));
+ AssertRCReturn(rc, rc);
+
+ if (pContext->shared->refCount>1)
+ {
+ bSaveShared = pContext->shared->saveCount==0;
+
+ ++pContext->shared->saveCount;
+ if (pContext->shared->saveCount == pContext->shared->refCount)
+ {
+ pContext->shared->saveCount=0;
+ }
+ }
+
+ /* Save transform state */
+ rc = SSMR3PutMem(pSSM, pContext->transform.clipPlane, sizeof(GLvectord)*CR_MAX_CLIP_PLANES);
+ AssertRCReturn(rc, rc);
+ rc = SSMR3PutMem(pSSM, pContext->transform.clip, sizeof(GLboolean)*CR_MAX_CLIP_PLANES);
+ AssertRCReturn(rc, rc);
+ rc = crStateSaveMatrixStack(&pContext->transform.modelViewStack, pSSM);
+ AssertRCReturn(rc, rc);
+ rc = crStateSaveMatrixStack(&pContext->transform.projectionStack, pSSM);
+ AssertRCReturn(rc, rc);
+ rc = crStateSaveMatrixStack(&pContext->transform.colorStack, pSSM);
+ AssertRCReturn(rc, rc);
+ for (i = 0 ; i < CR_MAX_TEXTURE_UNITS ; i++)
+ {
+ rc = crStateSaveMatrixStack(&pContext->transform.textureStack[i], pSSM);
+ AssertRCReturn(rc, rc);
+ }
+ for (i = 0 ; i < CR_MAX_PROGRAM_MATRICES ; i++)
+ {
+ rc = crStateSaveMatrixStack(&pContext->transform.programStack[i], pSSM);
+ AssertRCReturn(rc, rc);
+ }
+
+ /* Save textures */
+ rc = crStateSaveTextureObjData(&pContext->texture.base1D, pSSM);
+ AssertRCReturn(rc, rc);
+ rc = crStateSaveTextureObjData(&pContext->texture.base2D, pSSM);
+ AssertRCReturn(rc, rc);
+ rc = crStateSaveTextureObjData(&pContext->texture.base3D, pSSM);
+ AssertRCReturn(rc, rc);
+ rc = crStateSaveTextureObjData(&pContext->texture.proxy1D, pSSM);
+ AssertRCReturn(rc, rc);
+ rc = crStateSaveTextureObjData(&pContext->texture.proxy2D, pSSM);
+ AssertRCReturn(rc, rc);
+ rc = crStateSaveTextureObjData(&pContext->texture.proxy3D, pSSM);
+#ifdef CR_ARB_texture_cube_map
+ rc = crStateSaveTextureObjData(&pContext->texture.baseCubeMap, pSSM);
+ AssertRCReturn(rc, rc);
+ rc = crStateSaveTextureObjData(&pContext->texture.proxyCubeMap, pSSM);
+ AssertRCReturn(rc, rc);
+#endif
+#ifdef CR_NV_texture_rectangle
+ rc = crStateSaveTextureObjData(&pContext->texture.baseRect, pSSM);
+ AssertRCReturn(rc, rc);
+ rc = crStateSaveTextureObjData(&pContext->texture.proxyRect, pSSM);
+ AssertRCReturn(rc, rc);
+#endif
+
+ /* Save shared textures */
+ 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);
+ crHashtableWalk(pContext->shared->textureTable, crStateSaveSharedTextureCB, pSSM);
+
+#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
+ /* Restore previous texture bindings via diff_api */
+ if (ui32)
+ {
+ CRTextureUnit *pTexUnit;
+
+ pTexUnit = &pContext->texture.unit[pContext->texture.curTextureUnit];
+
+ diff_api.BindTexture(GL_TEXTURE_1D, pTexUnit->currentTexture1D->hwid);
+ diff_api.BindTexture(GL_TEXTURE_2D, pTexUnit->currentTexture2D->hwid);
+ diff_api.BindTexture(GL_TEXTURE_3D, pTexUnit->currentTexture3D->hwid);
+#ifdef CR_ARB_texture_cube_map
+ diff_api.BindTexture(GL_TEXTURE_CUBE_MAP_ARB, pTexUnit->currentTextureCubeMap->hwid);
+#endif
+#ifdef CR_NV_texture_rectangle
+ diff_api.BindTexture(GL_TEXTURE_RECTANGLE_NV, pTexUnit->currentTextureRect->hwid);
+#endif
+ }
+#endif
+ }
+
+ /* Save current texture pointers */
+ for (i=0; i<CR_MAX_TEXTURE_UNITS; ++i)
+ {
+ rc = crStateSaveTexUnitCurrentTexturePtrs(&pContext->texture.unit[i], pSSM);
+ AssertRCReturn(rc, rc);
+ }
+
+ /* Save lights */
+ CRASSERT(pContext->lighting.light);
+ rc = SSMR3PutMem(pSSM, pContext->lighting.light, CR_MAX_LIGHTS * sizeof(*pContext->lighting.light));
+ AssertRCReturn(rc, rc);
+
+ /* Save attrib stack*/
+ /** @todo could go up to used stack depth here?*/
+ for ( i = 0 ; i < CR_MAX_ATTRIB_STACK_DEPTH ; i++)
+ {
+ if (pContext->attrib.enableStack[i].clip)
+ {
+ rc = SSMR3PutMem(pSSM, pContext->attrib.enableStack[i].clip,
+ pContext->limits.maxClipPlanes*sizeof(GLboolean));
+ AssertRCReturn(rc, rc);
+ }
+
+ if (pContext->attrib.enableStack[i].light)
+ {
+ rc = SSMR3PutMem(pSSM, pContext->attrib.enableStack[i].light,
+ pContext->limits.maxLights*sizeof(GLboolean));
+ AssertRCReturn(rc, rc);
+ }
+
+ if (pContext->attrib.lightingStack[i].light)
+ {
+ rc = SSMR3PutMem(pSSM, pContext->attrib.lightingStack[i].light,
+ pContext->limits.maxLights*sizeof(CRLight));
+ AssertRCReturn(rc, rc);
+ }
+
+ for (j=0; j<pContext->limits.maxTextureUnits; ++j)
+ {
+ rc = crStateSaveTexUnitCurrentTexturePtrs(&pContext->attrib.textureStack[i].unit[j], pSSM);
+ AssertRCReturn(rc, rc);
+ }
+
+ if (pContext->attrib.transformStack[i].clip)
+ {
+ rc = SSMR3PutMem(pSSM, pContext->attrib.transformStack[i].clip,
+ pContext->limits.maxClipPlanes*sizeof(GLboolean));
+ AssertRCReturn(rc, rc);
+ }
+
+ if (pContext->attrib.transformStack[i].clipPlane)
+ {
+ rc = SSMR3PutMem(pSSM, pContext->attrib.transformStack[i].clipPlane,
+ pContext->limits.maxClipPlanes*sizeof(GLvectord));
+ AssertRCReturn(rc, rc);
+ }
+
+ rc = crSateSaveEvalCoeffs1D(pContext->attrib.evalStack[i].eval1D, pSSM);
+ AssertRCReturn(rc, rc);
+ rc = crSateSaveEvalCoeffs2D(pContext->attrib.evalStack[i].eval2D, pSSM);
+ AssertRCReturn(rc, rc);
+ }
+
+ /* Save evaluator coeffs */
+ rc = crSateSaveEvalCoeffs1D(pContext->eval.eval1D, pSSM);
+ AssertRCReturn(rc, rc);
+ rc = crSateSaveEvalCoeffs2D(pContext->eval.eval2D, pSSM);
+ AssertRCReturn(rc, rc);
+
+#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);
+
+ /* Save default one*/
+ crStateSaveBufferObjectCB(0, pContext->bufferobject.nullBuffer, pSSM);
+
+ if (bSaveShared)
+ {
+ /* Save all the rest */
+ crHashtableWalk(pContext->shared->buffersTable, crStateSaveBufferObjectCB, pSSM);
+ }
+
+ /* Restore binding */
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, pContext->bufferobject.arrayBuffer->hwid);
+
+ /* Save pointers */
+ rc = SSMR3PutU32(pSSM, pContext->bufferobject.arrayBuffer->id);
+ AssertRCReturn(rc, rc);
+ rc = SSMR3PutU32(pSSM, pContext->bufferobject.elementsBuffer->id);
+ AssertRCReturn(rc, rc);
+#ifdef CR_ARB_pixel_buffer_object
+ rc = SSMR3PutU32(pSSM, pContext->bufferobject.packBuffer->id);
+ AssertRCReturn(rc, rc);
+ rc = SSMR3PutU32(pSSM, pContext->bufferobject.unpackBuffer->id);
+ AssertRCReturn(rc, rc);
+#endif
+ /* Save clint pointers and buffer bindings*/
+ for (i=0; i<CRSTATECLIENT_MAX_VERTEXARRAYS; ++i)
+ {
+ rc = crStateSaveClientPointer(&pContext->client.array, i, pSSM);
+ AssertRCReturn(rc, rc);
+ }
+
+ crDebug("client.vertexArrayStackDepth %i", pContext->client.vertexArrayStackDepth);
+ for (i=0; i<pContext->client.vertexArrayStackDepth; ++i)
+ {
+ CRVertexArrays *pArray = &pContext->client.vertexArrayStack[i];
+ for (j=0; j<CRSTATECLIENT_MAX_VERTEXARRAYS; ++j)
+ {
+ rc = crStateSaveClientPointer(pArray, j, pSSM);
+ AssertRCReturn(rc, rc);
+ }
+ }
+#endif /*CR_ARB_vertex_buffer_object*/
+
+ /* Save pixel/vertex programs */
+ ui32 = crHashtableNumElements(pContext->program.programHash);
+ rc = SSMR3PutU32(pSSM, ui32);
+ AssertRCReturn(rc, rc);
+ /* Save defaults programs */
+ crStateSaveProgramCB(0, pContext->program.defaultVertexProgram, pSSM);
+ crStateSaveProgramCB(0, pContext->program.defaultFragmentProgram, pSSM);
+ /* Save all the rest */
+ crHashtableWalk(pContext->program.programHash, crStateSaveProgramCB, pSSM);
+ /* Save Pointers */
+ rc = SSMR3PutU32(pSSM, pContext->program.currentVertexProgram->id);
+ AssertRCReturn(rc, rc);
+ rc = SSMR3PutU32(pSSM, pContext->program.currentFragmentProgram->id);
+ AssertRCReturn(rc, rc);
+ /* This one is unused it seems*/
+ CRASSERT(!pContext->program.errorString);
+
+#ifdef CR_EXT_framebuffer_object
+ /* 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);
+ crHashtableWalk(pContext->shared->rbTable, crStateSaveRenderbuffersCB, pSSM);
+ }
+ rc = SSMR3PutU32(pSSM, pContext->framebufferobject.drawFB?pContext->framebufferobject.drawFB->id:0);
+ AssertRCReturn(rc, rc);
+ rc = SSMR3PutU32(pSSM, pContext->framebufferobject.readFB?pContext->framebufferobject.readFB->id:0);
+ AssertRCReturn(rc, rc);
+ rc = SSMR3PutU32(pSSM, pContext->framebufferobject.renderbuffer?pContext->framebufferobject.renderbuffer->id:0);
+ AssertRCReturn(rc, rc);
+#endif
+
+#ifdef CR_OPENGL_VERSION_2_0
+ /* Save GLSL related info */
+ ui32 = crHashtableNumElements(pContext->glsl.shaders);
+ rc = SSMR3PutU32(pSSM, ui32);
+ AssertRCReturn(rc, rc);
+ crHashtableWalk(pContext->glsl.shaders, crStateSaveGLSLShaderCB, pSSM);
+ ui32 = crHashtableNumElements(pContext->glsl.programs);
+ rc = SSMR3PutU32(pSSM, ui32);
+ AssertRCReturn(rc, rc);
+ crHashtableWalk(pContext->glsl.programs, crStateSaveGLSLProgramCB, pSSM);
+ rc = SSMR3PutU32(pSSM, pContext->glsl.activeProgram?pContext->glsl.activeProgram->id:0);
+ AssertRCReturn(rc, rc);
+#endif
+
+ return VINF_SUCCESS;
+}
+
+typedef struct _crFindSharedCtxParms {
+ PFNCRSTATE_CONTEXT_GET pfnCtxGet;
+ CRContext *pSrcCtx, *pDstCtx;
+} crFindSharedCtxParms_t;
+
+static void crStateFindSharedCB(unsigned long key, void *data1, void *data2)
+{
+ crFindSharedCtxParms_t *pParms = (crFindSharedCtxParms_t *) data2;
+ CRContext *pContext = pParms->pfnCtxGet(data1);
+ (void) key;
+
+ if (pContext!=pParms->pSrcCtx && pContext->shared->id==pParms->pSrcCtx->shared->id)
+ {
+ pParms->pDstCtx->shared = pContext->shared;
+ }
+}
+
+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)
+
+AssertCompile(VBOXTLSREFDATA_SIZE() <= CR_MAX_BITARRAY);
+AssertCompile(VBOXTLSREFDATA_STATE_INITIALIZED != 0);
+AssertCompile(RTASSERT_OFFSET_OF(CRContext, shared) >= VBOXTLSREFDATA_ASSERT_OFFSET(CRContext)
+ + VBOXTLSREFDATA_SIZE()
+ + RT_SIZEOFMEMB(CRContext, bitid)
+ + RT_SIZEOFMEMB(CRContext, neg_bitid));
+
+int32_t crStateLoadContext(CRContext *pContext, CRHashTable * pCtxTable, PFNCRSTATE_CONTEXT_GET pfnCtxGet, PSSMHANDLE pSSM, uint32_t u32Version)
+{
+ CRContext* pTmpContext;
+ int32_t rc, i, j;
+ uint32_t uiNumElems, ui, k;
+ unsigned long key;
+ GLboolean bLoadShared = GL_TRUE;
+ GLenum err;
+
+ CRASSERT(pContext && pSSM);
+
+ /* This one is rather big for stack allocation and causes macs to crash */
+ pTmpContext = (CRContext*)crAlloc(sizeof(*pTmpContext));
+ if (!pTmpContext)
+ return VERR_NO_MEMORY;
+
+ CRASSERT(VBoxTlsRefIsFunctional(pContext));
+
+ if (u32Version <= SHCROGL_SSM_VERSION_WITH_INVALID_ERROR_STATE)
+ {
+ 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);
+
+ /* 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)
+ {
+ /* 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 = VBOXTLSREFDATA_OFFSET(CRContext) + VBOXTLSREFDATA_SIZE() + sizeof (pTmpContext->bitid) + sizeof (pTmpContext->neg_bitid);
+ ui = RT_UOFFSETOF(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);
+
+ /* 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);
+
+ ui &= (sizeof (void*) - 1);
+ }
+
+ 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_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, 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);
+ }
+ 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
+ {
+ 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;
+ int32_t shared;
+
+ rc = SSMR3GetS32(pSSM, &pContext->shared->id);
+ AssertRCReturn(rc, rc);
+
+ rc = SSMR3GetS32(pSSM, &shared);
+ AssertRCReturn(rc, rc);
+
+ pTmpContext->shared = NULL;
+ parms.pfnCtxGet = pfnCtxGet;
+ parms.pSrcCtx = pContext;
+ parms.pDstCtx = pTmpContext;
+ crHashtableWalk(pCtxTable, crStateFindSharedCB, &parms);
+
+ if (pTmpContext->shared)
+ {
+ CRASSERT(pContext->shared->refCount==1);
+ bLoadShared = GL_FALSE;
+ crStateFreeShared(pContext, pContext->shared);
+ pContext->shared = NULL;
+ pTmpContext->shared->refCount++;
+ }
+ else
+ {
+ SLC_COPYPTR(shared);
+ }
+
+ if (bLoadShared && shared)
+ {
+ crStateSetSharedContext(pTmpContext);
+ }
+ }
+
+ SLC_COPYPTR(flush_func);
+ SLC_COPYPTR(flush_arg);
+
+ /* We're supposed to be loading into an empty context, so those pointers should be NULL */
+ for ( i = 0 ; i < CR_MAX_ATTRIB_STACK_DEPTH ; i++)
+ {
+ SLC_ASSSERT_NULL_PTR(attrib.enableStack[i].clip);
+ SLC_ASSSERT_NULL_PTR(attrib.enableStack[i].light);
+
+ SLC_ASSSERT_NULL_PTR(attrib.lightingStack[i].light);
+ SLC_ASSSERT_NULL_PTR(attrib.transformStack[i].clip);
+ SLC_ASSSERT_NULL_PTR(attrib.transformStack[i].clipPlane);
+
+ for (j=0; j<GLEVAL_TOT; ++j)
+ {
+ SLC_ASSSERT_NULL_PTR(attrib.evalStack[i].eval1D[j].coeff);
+ SLC_ASSSERT_NULL_PTR(attrib.evalStack[i].eval2D[j].coeff);
+ }
+ }
+
+#ifdef CR_ARB_vertex_buffer_object
+ SLC_COPYPTR(bufferobject.nullBuffer);
+#endif
+
+/*@todo, that should be removed probably as those should hold the offset values, so loading should be fine
+ but better check*/
+#if 0
+#ifdef CR_EXT_compiled_vertex_array
+ SLC_COPYPTR(client.array.v.prevPtr);
+ SLC_COPYPTR(client.array.c.prevPtr);
+ SLC_COPYPTR(client.array.f.prevPtr);
+ SLC_COPYPTR(client.array.s.prevPtr);
+ SLC_COPYPTR(client.array.e.prevPtr);
+ SLC_COPYPTR(client.array.i.prevPtr);
+ SLC_COPYPTR(client.array.n.prevPtr);
+ for (i = 0 ; i < CR_MAX_TEXTURE_UNITS ; i++)
+ {
+ SLC_COPYPTR(client.array.t[i].prevPtr);
+ }
+
+# ifdef CR_NV_vertex_program
+ for (i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++)
+ {
+ SLC_COPYPTR(client.array.a[i].prevPtr);
+ }
+# endif
+#endif
+#endif
+
+#ifdef CR_ARB_vertex_buffer_object
+ /*That just sets those pointers to NULL*/
+ SLC_COPYPTR(client.array.v.buffer);
+ SLC_COPYPTR(client.array.c.buffer);
+ SLC_COPYPTR(client.array.f.buffer);
+ SLC_COPYPTR(client.array.s.buffer);
+ SLC_COPYPTR(client.array.e.buffer);
+ SLC_COPYPTR(client.array.i.buffer);
+ SLC_COPYPTR(client.array.n.buffer);
+ for (i = 0 ; i < CR_MAX_TEXTURE_UNITS ; i++)
+ {
+ SLC_COPYPTR(client.array.t[i].buffer);
+ }
+# ifdef CR_NV_vertex_program
+ for (i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++)
+ {
+ SLC_COPYPTR(client.array.a[i].buffer);
+ }
+# endif
+#endif /*CR_ARB_vertex_buffer_object*/
+
+ /** @todo CR_NV_vertex_program*/
+ crStateCopyEvalPtrs1D(pTmpContext->eval.eval1D, pContext->eval.eval1D);
+ crStateCopyEvalPtrs2D(pTmpContext->eval.eval2D, pContext->eval.eval2D);
+
+ SLC_COPYPTR(feedback.buffer); /** @todo */
+ SLC_COPYPTR(selection.buffer); /** @todo */
+
+ SLC_COPYPTR(lighting.light);
+
+ /*This one could be tricky if we're loading snapshot on host with different GPU*/
+ SLC_COPYPTR(limits.extensions);
+
+#if CR_ARB_occlusion_query
+ SLC_COPYPTR(occlusion.objects); /** @todo */
+#endif
+
+ SLC_COPYPTR(program.errorString);
+ SLC_COPYPTR(program.programHash);
+ SLC_COPYPTR(program.defaultVertexProgram);
+ SLC_COPYPTR(program.defaultFragmentProgram);
+
+ /* Texture pointers */
+ for (i=0; i<6; ++i)
+ {
+ SLC_COPYPTR(texture.base1D.level[i]);
+ SLC_COPYPTR(texture.base2D.level[i]);
+ SLC_COPYPTR(texture.base3D.level[i]);
+ SLC_COPYPTR(texture.proxy1D.level[i]);
+ SLC_COPYPTR(texture.proxy2D.level[i]);
+ SLC_COPYPTR(texture.proxy3D.level[i]);
+#ifdef CR_ARB_texture_cube_map
+ SLC_COPYPTR(texture.baseCubeMap.level[i]);
+ SLC_COPYPTR(texture.proxyCubeMap.level[i]);
+#endif
+#ifdef CR_NV_texture_rectangle
+ SLC_COPYPTR(texture.baseRect.level[i]);
+ SLC_COPYPTR(texture.proxyRect.level[i]);
+#endif
+ }
+
+ /* Load transform state */
+ SLC_COPYPTR(transform.clipPlane);
+ SLC_COPYPTR(transform.clip);
+ /* Don't have to worry about pContext->transform.current as it'd be set in crStateSetCurrent call */
+ /*SLC_COPYPTR(transform.currentStack);*/
+ SLC_COPYPTR(transform.modelViewStack.stack);
+ SLC_COPYPTR(transform.projectionStack.stack);
+ SLC_COPYPTR(transform.colorStack.stack);
+
+ for (i = 0 ; i < CR_MAX_TEXTURE_UNITS ; i++)
+ {
+ SLC_COPYPTR(transform.textureStack[i].stack);
+ }
+ for (i = 0 ; i < CR_MAX_PROGRAM_MATRICES ; i++)
+ {
+ SLC_COPYPTR(transform.programStack[i].stack);
+ }
+
+#ifdef CR_OPENGL_VERSION_2_0
+ SLC_COPYPTR(glsl.shaders);
+ SLC_COPYPTR(glsl.programs);
+#endif
+
+ /* Have to preserve original context id */
+ CRASSERT(pTmpContext->id == pContext->id);
+ CRASSERT(VBOXTLSREFDATA_EQUAL(pContext, pTmpContext));
+ /* Copy ordinary state to real context */
+ crMemcpy(pContext, pTmpContext, sizeof(*pTmpContext));
+ crFree(pTmpContext);
+ pTmpContext = NULL;
+
+ /* Now deal with pointers */
+
+ /* Load transform state */
+ rc = SSMR3GetMem(pSSM, pContext->transform.clipPlane, sizeof(GLvectord)*CR_MAX_CLIP_PLANES);
+ AssertRCReturn(rc, rc);
+ rc = SSMR3GetMem(pSSM, pContext->transform.clip, sizeof(GLboolean)*CR_MAX_CLIP_PLANES);
+ AssertRCReturn(rc, rc);
+ rc = crStateLoadMatrixStack(&pContext->transform.modelViewStack, pSSM);
+ AssertRCReturn(rc, rc);
+ rc = crStateLoadMatrixStack(&pContext->transform.projectionStack, pSSM);
+ AssertRCReturn(rc, rc);
+ rc = crStateLoadMatrixStack(&pContext->transform.colorStack, pSSM);
+ AssertRCReturn(rc, rc);
+ for (i = 0 ; i < CR_MAX_TEXTURE_UNITS ; i++)
+ {
+ rc = crStateLoadMatrixStack(&pContext->transform.textureStack[i], pSSM);
+ AssertRCReturn(rc, rc);
+ }
+ for (i = 0 ; i < CR_MAX_PROGRAM_MATRICES ; i++)
+ {
+ rc = crStateLoadMatrixStack(&pContext->transform.programStack[i], pSSM);
+ AssertRCReturn(rc, rc);
+ }
+
+ /* Load Textures */
+ rc = crStateLoadTextureObjData(&pContext->texture.base1D, pSSM);
+ AssertRCReturn(rc, rc);
+ rc = crStateLoadTextureObjData(&pContext->texture.base2D, pSSM);
+ AssertRCReturn(rc, rc);
+ rc = crStateLoadTextureObjData(&pContext->texture.base3D, pSSM);
+ AssertRCReturn(rc, rc);
+ rc = crStateLoadTextureObjData(&pContext->texture.proxy1D, pSSM);
+ AssertRCReturn(rc, rc);
+ rc = crStateLoadTextureObjData(&pContext->texture.proxy2D, pSSM);
+ AssertRCReturn(rc, rc);
+ rc = crStateLoadTextureObjData(&pContext->texture.proxy3D, pSSM);
+ AssertRCReturn(rc, rc);
+#ifdef CR_ARB_texture_cube_map
+ rc = crStateLoadTextureObjData(&pContext->texture.baseCubeMap, pSSM);
+ AssertRCReturn(rc, rc);
+ rc = crStateLoadTextureObjData(&pContext->texture.proxyCubeMap, pSSM);
+ AssertRCReturn(rc, rc);
+#endif
+#ifdef CR_NV_texture_rectangle
+ rc = crStateLoadTextureObjData(&pContext->texture.baseRect, pSSM);
+ AssertRCReturn(rc, rc);
+ rc = crStateLoadTextureObjData(&pContext->texture.proxyRect, pSSM);
+ AssertRCReturn(rc, rc);
+#endif
+
+ if (bLoadShared)
+ {
+ /* 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)
+ {
+ CRTextureObj *pTexture;
+
+ rc = SSMR3GetMem(pSSM, &key, sizeof(key));
+ AssertRCReturn(rc, rc);
+
+ pTexture = (CRTextureObj *) crCalloc(sizeof(CRTextureObj));
+ if (!pTexture) return VERR_NO_MEMORY;
+
+ rc = crStateLoadTextureObj(pTexture, pSSM, u32Version);
+ AssertRCReturn(rc, rc);
+
+ pTexture->hwid = 0;
+
+ /*allocate actual memory*/
+ for (i=0; i<6; ++i) {
+ pTexture->level[i] = (CRTextureLevel *) crCalloc(sizeof(CRTextureLevel) * CR_MAX_MIPMAP_LEVELS);
+ if (!pTexture->level[i]) return VERR_NO_MEMORY;
+ }
+
+ rc = crStateLoadTextureObjData(pTexture, pSSM);
+ AssertRCReturn(rc, rc);
+
+ crHashtableAdd(pContext->shared->textureTable, key, pTexture);
+ }
+ }
+
+ /* Load current texture pointers */
+ for (i=0; i<CR_MAX_TEXTURE_UNITS; ++i)
+ {
+ rc = crStateLoadTexUnitCurrentTexturePtrs(&pContext->texture.unit[i], pContext, pSSM);
+ AssertRCReturn(rc, rc);
+ }
+
+ /* Mark textures for resending to GPU */
+ pContext->shared->bTexResyncNeeded = GL_TRUE;
+
+ /* Load lights */
+ CRASSERT(pContext->lighting.light);
+ rc = SSMR3GetMem(pSSM, pContext->lighting.light, CR_MAX_LIGHTS * sizeof(*pContext->lighting.light));
+ AssertRCReturn(rc, rc);
+
+ /* Load attrib stack*/
+ for ( i = 0 ; i < CR_MAX_ATTRIB_STACK_DEPTH ; i++)
+ {
+ if (pContext->attrib.enableStack[i].clip)
+ {
+ rc = crStateAllocAndSSMR3GetMem(pSSM, (void**)&pContext->attrib.enableStack[i].clip,
+ pContext->limits.maxClipPlanes*sizeof(GLboolean));
+ AssertRCReturn(rc, rc);
+ }
+
+ if (pContext->attrib.enableStack[i].light)
+ {
+ rc = crStateAllocAndSSMR3GetMem(pSSM, (void**)&pContext->attrib.enableStack[i].light,
+ pContext->limits.maxLights*sizeof(GLboolean));
+ AssertRCReturn(rc, rc);
+ }
+
+ if (pContext->attrib.lightingStack[i].light)
+ {
+ rc = crStateAllocAndSSMR3GetMem(pSSM, (void**)&pContext->attrib.lightingStack[i].light,
+ pContext->limits.maxLights*sizeof(CRLight));
+ AssertRCReturn(rc, rc);
+ }
+
+ for (k=0; k<pContext->limits.maxTextureUnits; ++k)
+ {
+ rc = crStateLoadTexUnitCurrentTexturePtrs(&pContext->attrib.textureStack[i].unit[k], pContext, pSSM);
+ AssertRCReturn(rc, rc);
+ }
+
+ if (pContext->attrib.transformStack[i].clip)
+ {
+ rc = crStateAllocAndSSMR3GetMem(pSSM, (void*)&pContext->attrib.transformStack[i].clip,
+ pContext->limits.maxClipPlanes*sizeof(GLboolean));
+ AssertRCReturn(rc, rc);
+ }
+
+ if (pContext->attrib.transformStack[i].clipPlane)
+ {
+ rc = crStateAllocAndSSMR3GetMem(pSSM, (void**)&pContext->attrib.transformStack[i].clipPlane,
+ pContext->limits.maxClipPlanes*sizeof(GLvectord));
+ AssertRCReturn(rc, rc);
+ }
+ rc = crSateLoadEvalCoeffs1D(pContext->attrib.evalStack[i].eval1D, GL_TRUE, pSSM);
+ AssertRCReturn(rc, rc);
+ rc = crSateLoadEvalCoeffs2D(pContext->attrib.evalStack[i].eval2D, GL_TRUE, pSSM);
+ AssertRCReturn(rc, rc);
+ }
+
+ /* Load evaluator coeffs */
+ rc = crSateLoadEvalCoeffs1D(pContext->eval.eval1D, GL_FALSE, pSSM);
+ AssertRCReturn(rc, rc);
+ rc = crSateLoadEvalCoeffs2D(pContext->eval.eval2D, GL_FALSE, pSSM);
+ AssertRCReturn(rc, rc);
+
+ /* 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*/
+ {
+ CRBufferObject *pBufferObj;
+
+ rc = SSMR3GetMem(pSSM, &key, sizeof(key));
+ AssertRCReturn(rc, rc);
+
+ /* default one should be already allocated */
+ if (key==0)
+ {
+ pBufferObj = pContext->bufferobject.nullBuffer;
+ if (!pBufferObj) return VERR_SSM_UNEXPECTED_DATA;
+ }
+ else
+ {
+ pBufferObj = (CRBufferObject *) crCalloc(sizeof(*pBufferObj));
+ if (!pBufferObj) return VERR_NO_MEMORY;
+ }
+
+ rc = crStateLoadBufferObject(pBufferObj, pSSM, u32Version);
+ AssertRCReturn(rc, rc);
+
+ pBufferObj->hwid = 0;
+
+ if (pBufferObj->data)
+ {
+ CRASSERT(pBufferObj->size>0);
+ pBufferObj->data = crAlloc(pBufferObj->size);
+ rc = SSMR3GetMem(pSSM, pBufferObj->data, pBufferObj->size);
+ AssertRCReturn(rc, rc);
+ }
+ else if (pBufferObj->id!=0 && pBufferObj->size>0)
+ {
+ rc = SSMR3GetMem(pSSM, &pBufferObj->data, sizeof(pBufferObj->data));
+ AssertRCReturn(rc, rc);
+
+ if (pBufferObj->data)
+ {
+ pBufferObj->data = crAlloc(pBufferObj->size);
+ rc = SSMR3GetMem(pSSM, pBufferObj->data, pBufferObj->size);
+ AssertRCReturn(rc, rc);
+ }
+ }
+
+
+ if (key!=0)
+ crHashtableAdd(pContext->shared->buffersTable, key, pBufferObj);
+ }
+ /* Load pointers */
+#define CRS_GET_BO(name) (((name)==0) ? (pContext->bufferobject.nullBuffer) : crHashtableSearch(pContext->shared->buffersTable, name))
+ rc = SSMR3GetU32(pSSM, &ui);
+ AssertRCReturn(rc, rc);
+ pContext->bufferobject.arrayBuffer = CRS_GET_BO(ui);
+ rc = SSMR3GetU32(pSSM, &ui);
+ AssertRCReturn(rc, rc);
+ pContext->bufferobject.elementsBuffer = CRS_GET_BO(ui);
+#ifdef CR_ARB_pixel_buffer_object
+ rc = SSMR3GetU32(pSSM, &ui);
+ AssertRCReturn(rc, rc);
+ pContext->bufferobject.packBuffer = CRS_GET_BO(ui);
+ rc = SSMR3GetU32(pSSM, &ui);
+ AssertRCReturn(rc, rc);
+ pContext->bufferobject.unpackBuffer = CRS_GET_BO(ui);
+#endif
+#undef CRS_GET_BO
+
+ /* Load client pointers and array buffer bindings*/
+ for (i=0; i<CRSTATECLIENT_MAX_VERTEXARRAYS; ++i)
+ {
+ rc = crStateLoadClientPointer(&pContext->client.array, i, pContext, pSSM);
+ AssertRCReturn(rc, rc);
+ }
+ for (j=0; j<pContext->client.vertexArrayStackDepth; ++j)
+ {
+ CRVertexArrays *pArray = &pContext->client.vertexArrayStack[j];
+ for (i=0; i<CRSTATECLIENT_MAX_VERTEXARRAYS; ++i)
+ {
+ rc = crStateLoadClientPointer(pArray, i, pContext, pSSM);
+ AssertRCReturn(rc, rc);
+ }
+ }
+
+ pContext->shared->bVBOResyncNeeded = GL_TRUE;
+#endif
+
+ /* Load pixel/vertex programs */
+ rc = SSMR3GetU32(pSSM, &uiNumElems);
+ AssertRCReturn(rc, rc);
+ /* Load defaults programs */
+ rc = crStateLoadProgram(&pContext->program.defaultVertexProgram, pSSM);
+ AssertRCReturn(rc, rc);
+ rc = crStateLoadProgram(&pContext->program.defaultFragmentProgram, pSSM);
+ AssertRCReturn(rc, rc);
+ /* Load all the rest */
+ for (ui=0; ui<uiNumElems; ++ui)
+ {
+ CRProgram *pProgram = NULL;
+ rc = crStateLoadProgram(&pProgram, pSSM);
+ AssertRCReturn(rc, rc);
+ crHashtableAdd(pContext->program.programHash, pProgram->id, pProgram);
+ //DIRTY(pProgram->dirtyProgram, pContext->neg_bitid);
+
+ }
+ /* Load Pointers */
+ rc = SSMR3GetU32(pSSM, &ui);
+ AssertRCReturn(rc, rc);
+ pContext->program.currentVertexProgram = ui==0 ? pContext->program.defaultVertexProgram
+ : crHashtableSearch(pContext->program.programHash, ui);
+ rc = SSMR3GetU32(pSSM, &ui);
+ AssertRCReturn(rc, rc);
+ pContext->program.currentFragmentProgram = ui==0 ? pContext->program.defaultFragmentProgram
+ : crHashtableSearch(pContext->program.programHash, ui);
+
+ /* Mark programs for resending to GPU */
+ pContext->program.bResyncNeeded = GL_TRUE;
+
+#ifdef CR_EXT_framebuffer_object
+ /* 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)
+ {
+ CRFramebufferObject *pFBO;
+ pFBO = crAlloc(sizeof(*pFBO));
+ if (!pFBO) return VERR_NO_MEMORY;
+
+ rc = SSMR3GetMem(pSSM, &key, sizeof(key));
+ AssertRCReturn(rc, rc);
+
+ 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)
+ {
+ CRRenderbufferObject *pRBO;
+ pRBO = crAlloc(sizeof(*pRBO));
+ if (!pRBO) return VERR_NO_MEMORY;
+
+ rc = SSMR3GetMem(pSSM, &key, sizeof(key));
+ AssertRCReturn(rc, rc);
+
+ rc = crStateLoadRenderbufferObject(pRBO, pSSM, u32Version);
+ AssertRCReturn(rc, rc);
+
+ crHashtableAdd(pContext->shared->rbTable, key, pRBO);
+ }
+ }
+
+ rc = SSMR3GetU32(pSSM, &ui);
+ AssertRCReturn(rc, rc);
+ pContext->framebufferobject.drawFB = ui==0 ? NULL
+ : crHashtableSearch(pContext->shared->fbTable, ui);
+
+ rc = SSMR3GetU32(pSSM, &ui);
+ AssertRCReturn(rc, rc);
+ pContext->framebufferobject.readFB = ui==0 ? NULL
+ : crHashtableSearch(pContext->shared->fbTable, ui);
+
+ rc = SSMR3GetU32(pSSM, &ui);
+ AssertRCReturn(rc, rc);
+ pContext->framebufferobject.renderbuffer = ui==0 ? NULL
+ : crHashtableSearch(pContext->shared->rbTable, ui);
+
+ /* Mark FBOs/RBOs for resending to GPU */
+ pContext->shared->bFBOResyncNeeded = GL_TRUE;
+#endif
+
+#ifdef CR_OPENGL_VERSION_2_0
+ /* Load GLSL related info */
+ rc = SSMR3GetU32(pSSM, &uiNumElems);
+ AssertRCReturn(rc, rc);
+
+ 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);
+ }
+
+ rc = SSMR3GetU32(pSSM, &uiNumElems);
+ AssertRCReturn(rc, rc);
+
+ for (ui=0; ui<uiNumElems; ++ui)
+ {
+ CRGLSLProgram *pProgram;
+ uint32_t numShaders;
+
+ pProgram = crAlloc(sizeof(*pProgram));
+ if (!pProgram) return VERR_NO_MEMORY;
+
+ rc = SSMR3GetMem(pSSM, &key, sizeof(key));
+ AssertRCReturn(rc, rc);
+
+ rc = SSMR3GetMem(pSSM, pProgram, sizeof(*pProgram));
+ AssertRCReturn(rc, rc);
+
+ crHashtableAdd(pContext->glsl.programs, key, pProgram);
+
+ pProgram->currentState.attachedShaders = crAllocHashtable();
+
+ rc = SSMR3GetU32(pSSM, &numShaders);
+ AssertRCReturn(rc, rc);
+
+ for (k=0; k<numShaders; ++k)
+ {
+ rc = SSMR3GetMem(pSSM, &key, sizeof(key));
+ AssertRCReturn(rc, rc);
+ crHashtableAdd(pProgram->currentState.attachedShaders, key, crHashtableSearch(pContext->glsl.shaders, key));
+ }
+
+ if (pProgram->activeState.attachedShaders)
+ {
+ pProgram->activeState.attachedShaders = crAllocHashtable();
+
+ rc = SSMR3GetU32(pSSM, &numShaders);
+ AssertRCReturn(rc, rc);
+
+ for (k=0; k<numShaders; ++k)
+ {
+ CRGLSLShader *pShader = crStateLoadGLSLShader(pSSM);
+ if (!pShader) return VERR_SSM_UNEXPECTED_DATA;
+ crHashtableAdd(pProgram->activeState.attachedShaders, pShader->id, pShader);
+ }
+ }
+
+ if (pProgram->currentState.cAttribs)
+ pProgram->currentState.pAttribs = (CRGLSLAttrib*) crAlloc(pProgram->currentState.cAttribs*sizeof(CRGLSLAttrib));
+ for (k=0; k<pProgram->currentState.cAttribs; ++k)
+ {
+ rc = SSMR3GetMem(pSSM, &pProgram->currentState.pAttribs[k].index, sizeof(pProgram->currentState.pAttribs[k].index));
+ AssertRCReturn(rc, rc);
+ pProgram->currentState.pAttribs[k].name = crStateLoadString(pSSM);
+ }
+
+ if (pProgram->activeState.cAttribs)
+ pProgram->activeState.pAttribs = (CRGLSLAttrib*) crAlloc(pProgram->activeState.cAttribs*sizeof(CRGLSLAttrib));
+ for (k=0; k<pProgram->activeState.cAttribs; ++k)
+ {
+ rc = SSMR3GetMem(pSSM, &pProgram->activeState.pAttribs[k].index, sizeof(pProgram->activeState.pAttribs[k].index));
+ AssertRCReturn(rc, rc);
+ pProgram->activeState.pAttribs[k].name = crStateLoadString(pSSM);
+ }
+
+ {
+ int32_t cUniforms;
+ rc = SSMR3GetS32(pSSM, &cUniforms);
+ pProgram->cUniforms = cUniforms;
+ AssertRCReturn(rc, rc);
+ }
+
+ if (pProgram->cUniforms)
+ {
+ pProgram->pUniforms = crAlloc(pProgram->cUniforms*sizeof(CRGLSLUniform));
+ if (!pProgram->pUniforms) return VERR_NO_MEMORY;
+
+ for (k=0; k<pProgram->cUniforms; ++k)
+ {
+ size_t itemsize, datasize;
+
+ rc = SSMR3GetMem(pSSM, &pProgram->pUniforms[k].type, sizeof(GLenum));
+ AssertRCReturn(rc, rc);
+ pProgram->pUniforms[k].name = crStateLoadString(pSSM);
+
+ if (crStateIsIntUniform(pProgram->pUniforms[k].type))
+ {
+ itemsize = sizeof(GLint);
+ } else itemsize = sizeof(GLfloat);
+
+ datasize = crStateGetUniformSize(pProgram->pUniforms[k].type)*itemsize;
+ pProgram->pUniforms[k].data = crAlloc((unsigned int /* this case is just so stupid */)datasize);
+ if (!pProgram->pUniforms[k].data) return VERR_NO_MEMORY;
+
+ rc = SSMR3GetMem(pSSM, pProgram->pUniforms[k].data, datasize);
+ AssertRCReturn(rc, rc);
+ }
+ }
+ }
+
+ rc = SSMR3GetU32(pSSM, &ui);
+ AssertRCReturn(rc, rc);
+ pContext->glsl.activeProgram = ui==0 ? NULL
+ : crHashtableSearch(pContext->glsl.programs, ui);
+
+ /*Mark for resending to GPU*/
+ pContext->glsl.bResyncNeeded = GL_TRUE;
+#endif
+
+ if (pContext->error != err)
+ {
+ 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
new file mode 100644
index 00000000..46b6805a
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_special
@@ -0,0 +1,385 @@
+# Copyright (c) 2001, Stanford University
+# All rights reserved.
+#
+# See the file LICENSE.txt for information on redistributing this software.
+Begin
+End
+GetString
+PixelStoref
+PixelStorei
+PixelTransferf
+PixelTransferi
+PixelZoom
+PixelMapfv
+PixelMapuiv
+PixelMapusv
+PopClientAttrib
+PushClientAttrib
+GetPixelMapfv
+GetPixelMapuiv
+GetPixelMapusv
+AlphaFunc
+DepthFunc
+BlendFunc
+BlendColorEXT
+BlendEquationEXT
+BlendFuncSeparateEXT
+LogicOp
+DrawBuffer
+ReadBuffer
+IndexMask
+ColorMask
+ClearColor
+ClearIndex
+ClearDepth
+ClearAccum
+DepthMask
+Enable
+Disable
+Map1d
+Map1f
+Map2d
+Map2f
+MapGrid1d
+MapGrid1f
+MapGrid2d
+MapGrid2f
+GetMapdv
+GetMapfv
+GetMapiv
+Fogi
+Fogf
+Fogiv
+Fogfv
+ShadeModel
+ColorMaterial
+LightModelf
+LightModeli
+LightModelfv
+LightModeliv
+Lightf
+Lighti
+Lightfv
+Lightiv
+GetLightfv
+GetLightiv
+Materialf
+Materiali
+Materialfv
+Materialiv
+GetMaterialfv
+GetMaterialiv
+ShadeModel
+ColorMaterial
+LightModelf
+LightModeli
+LightModelfv
+LightModeliv
+Lightf
+Lighti
+Lightfv
+Lightiv
+Materialf
+Materiali
+Materialfv
+Materialiv
+ClipPlane
+GetClipPlane
+MatrixMode
+LoadIdentity
+PopMatrix
+PushMatrix
+LoadMatrixf
+LoadMatrixd
+LoadTransposeMatrixfARB
+LoadTransposeMatrixdARB
+MultMatrixf
+MultMatrixd
+MultTransposeMatrixfARB
+MultTransposeMatrixdARB
+Translatef
+Translated
+Rotatef
+Rotated
+Scalef
+Scaled
+Frustum
+Ortho
+PointSize
+LineWidth
+LineStipple
+CullFace
+FrontFace
+PolygonMode
+PolygonOffset
+PolygonStipple
+GetPolygonStipple
+GenTextures
+DeleteTextures
+BindTexture
+TexImage1D
+TexImage2D
+TexImage3D
+TexImage3DEXT
+TexSubImage1D
+TexSubImage2D
+TexSubImage3D
+TexParameterfv
+TexParameteriv
+TexParameterf
+TexParameteri
+TexEnvfv
+TexEnviv
+TexEnvf
+TexEnvi
+GetTexEnvfv
+GetTexEnviv
+TexGendv
+TexGenfv
+TexGeniv
+TexGend
+TexGenf
+TexGeni
+GetTexGendv
+GetTexGenfv
+GetTexGeniv
+GetTexImage
+GetTexLevelParameterfv
+GetTexLevelParameteriv
+GetTexParameterfv
+GetTexParameteriv
+PrioritizeTextures
+AreTexturesResident
+GetBooleanv
+GetDoublev
+GetFloatv
+GetIntegerv
+GetError
+StencilFunc
+StencilOp
+StencilFuncSeparate
+StencilOpSeparate
+ActiveStencilFaceEXT
+ClearStencil
+StencilMask
+Viewport
+DepthRange
+Scissor
+IsEnabled
+RasterPos2d
+RasterPos2f
+RasterPos2i
+RasterPos2s
+RasterPos3d
+RasterPos3f
+RasterPos3i
+RasterPos3s
+RasterPos4d
+RasterPos4f
+RasterPos4i
+RasterPos4s
+RasterPos2dv
+RasterPos2fv
+RasterPos2iv
+RasterPos2sv
+RasterPos3dv
+RasterPos3fv
+RasterPos3iv
+RasterPos3sv
+RasterPos4dv
+RasterPos4fv
+RasterPos4iv
+RasterPos4sv
+GenLists
+NewList
+EndList
+DeleteLists
+IsList
+IsTexture
+ListBase
+EnableClientState
+DisableClientState
+VertexPointer
+ColorPointer
+SecondaryColorPointerEXT
+IndexPointer
+NormalPointer
+TexCoordPointer
+EdgeFlagPointer
+InterleavedArrays
+GetPointerv
+PushAttrib
+PopAttrib
+Bitmap
+ActiveTextureARB
+ClientActiveTextureARB
+CombinerParameterfvNV
+CombinerParameterivNV
+CombinerParameterfNV
+CombinerParameteriNV
+CombinerInputNV
+CombinerOutputNV
+FinalCombinerInputNV
+GetCombinerInputParameterfvNV
+GetCombinerInputParameterivNV
+GetCombinerOutputParameterfvNV
+GetCombinerOutputParameterivNV
+GetFinalCombinerInputParameterfvNV
+GetFinalCombinerInputParameterivNV
+CombinerStageParameterfvNV
+GetCombinerStageParameterfvNV
+Color3f
+Color3fv
+Color4f
+Color4fv
+Hint
+FeedbackBuffer
+SelectBuffer
+RenderMode
+InitNames
+LoadName
+PushName
+PopName
+PassThrough
+FogCoordPointerEXT
+VertexAttribPointerNV
+PointParameterfARB
+PointParameterfvARB
+PointParameteri
+PointParameteriv
+SampleCoverageARB
+WindowPos2dARB
+WindowPos2dvARB
+WindowPos2fARB
+WindowPos2fvARB
+WindowPos2iARB
+WindowPos2ivARB
+WindowPos2sARB
+WindowPos2svARB
+WindowPos3dARB
+WindowPos3dvARB
+WindowPos3fARB
+WindowPos3fvARB
+WindowPos3iARB
+WindowPos3ivARB
+WindowPos3sARB
+WindowPos3svARB
+CompressedTexImage3DARB
+CompressedTexImage2DARB
+CompressedTexImage1DARB
+CompressedTexSubImage3DARB
+CompressedTexSubImage2DARB
+CompressedTexSubImage1DARB
+GetCompressedTexImageARB
+BindProgramNV
+ExecuteProgramNV
+GenProgramsNV
+AreProgramsResidentNV
+RequestResidentProgramsNV
+LoadProgramNV
+GetProgramivNV
+GetProgramStringNV
+ProgramParameter4dNV
+ProgramParameter4dvNV
+ProgramParameter4fNV
+ProgramParameter4fvNV
+ProgramParameters4dvNV
+ProgramParameters4fvNV
+GetProgramParameterfvNV
+GetProgramParameterdvNV
+TrackMatrixNV
+GetTrackMatrixivNV
+GetVertexAttribdvNV
+GetVertexAttribfvNV
+GetVertexAttribivNV
+GetVertexAttribPointervNV
+ProgramNamedParameter4fNV
+ProgramNamedParameter4dNV
+ProgramNamedParameter4fvNV
+ProgramNamedParameter4dvNV
+GetProgramNamedParameterfvNV
+GetProgramNamedParameterdvNV
+GetProgramStringARB
+ProgramLocalParameter4dARB
+ProgramLocalParameter4dvARB
+ProgramLocalParameter4fARB
+ProgramLocalParameter4fvARB
+GetProgramLocalParameterfvARB
+GetProgramLocalParameterdvARB
+GetVertexAttribdvARB
+GetVertexAttribfvARB
+GetVertexAttribivARB
+EnableVertexAttribArrayARB
+DisableVertexAttribArrayARB
+ProgramStringARB
+BindProgramARB
+DeleteProgramsARB
+GenProgramsARB
+ProgramEnvParameter4dARB
+ProgramEnvParameter4dvARB
+ProgramEnvParameter4fARB
+ProgramEnvParameter4fvARB
+GetProgramEnvParameterdvARB
+GetProgramEnvParameterfvARB
+GetProgramivARB
+GetProgramStringARB
+IsProgramARB
+VertexAttribPointerARB
+GetVertexAttribPointervARB
+GenFencesNV
+DeleteFencesNV
+SetFenceNV
+TestFenceNV
+FinishFenceNV
+IsFenceNV
+GetFenceivNV
+VertexArrayRangeNV
+FlushVertexArrayRangeNV
+BindBufferARB
+GenBuffersARB
+IsBufferARB
+GetBufferParameterivARB
+GetBufferPointervARB
+GetBufferSubDataARB
+DeleteBuffersARB
+BufferDataARB
+BufferSubDataARB
+MapBufferARB
+UnmapBufferARB
+GenQueriesARB
+DeleteQueriesARB
+IsQueryARB
+BeginQueryARB
+EndQueryARB
+GetQueryivARB
+GetQueryObjectivARB
+GetQueryObjectuivARB
+BindRenderbufferEXT
+DeleteRenderbuffersEXT
+RenderbufferStorageEXT
+BindFramebufferEXT
+DeleteFramebuffersEXT
+FramebufferTexture1DEXT
+FramebufferTexture2DEXT
+FramebufferTexture3DEXT
+FramebufferRenderbufferEXT
+GetFramebufferAttachmentParameterivEXT
+GenerateMipmapEXT
+LockArraysEXT
+UnlockArraysEXT
+CompileShader
+DeleteShader
+AttachShader
+DetachShader
+LinkProgram
+UseProgram
+DeleteProgram
+ValidateProgram
+BindAttribLocation
+GetAttribLocation
+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
new file mode 100644
index 00000000..2fc438cd
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_stencil.c
@@ -0,0 +1,1450 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#include <stdio.h>
+#include "state.h"
+#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;
+ }
+#ifndef VBOX /* unreachable */
+ crError("should never be here!");
+ return 0;
+#endif
+}
+
+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->stencilTwoSideEXT = GL_FALSE;
+ RESET(sb->enableTwoSideEXT, ctx->bitid);
+
+ s->activeStencilFace = GL_FRONT;
+ RESET(sb->activeStencilFace, ctx->bitid);
+
+ s->clearValue = 0;
+ RESET(sb->clearValue, ctx->bitid);
+
+ s->writeMask = 0xFFFFFFFF;
+ 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]);
+ }
+}
+
+static void crStateStencilBufferFunc(CRContext *g, CRStencilBufferState *s, GLenum func, GLint ref, GLuint mask)
+{
+ (void)g;
+ 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 (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;
+ }
+
+ 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 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)
+{
+ (void)g;
+ 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)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glStencilOp called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ switch (fail) {
+ case GL_KEEP:
+ case GL_ZERO:
+ case GL_REPLACE:
+ case GL_INCR:
+ case GL_DECR:
+ case GL_INVERT:
+#ifdef CR_EXT_stencil_wrap
+ case GL_INCR_WRAP_EXT:
+ case GL_DECR_WRAP_EXT:
+#endif
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glStencilOp called with bogus fail: %d", fail);
+ return;
+ }
+
+ switch (zfail) {
+ case GL_KEEP:
+ case GL_ZERO:
+ case GL_REPLACE:
+ case GL_INCR:
+ case GL_DECR:
+ case GL_INVERT:
+#ifdef CR_EXT_stencil_wrap
+ case GL_INCR_WRAP_EXT:
+ case GL_DECR_WRAP_EXT:
+#endif
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glStencilOp called with bogus zfail: %d", zfail);
+ return;
+ }
+
+ switch (zpass) {
+ case GL_KEEP:
+ case GL_ZERO:
+ case GL_REPLACE:
+ case GL_INCR:
+ case GL_DECR:
+ case GL_INVERT:
+#ifdef CR_EXT_stencil_wrap
+ case GL_INCR_WRAP_EXT:
+ case GL_DECR_WRAP_EXT:
+#endif
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glStencilOp called with bogus zpass: %d", zpass);
+ return;
+ }
+
+ 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->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)
+{
+ CRContext *g = GetCurrentContext();
+ CRStencilState *s = &(g->stencil);
+ CRStateBits *stateb = GetCurrentBits();
+ CRStencilBits *sb = &(stateb->stencil);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glClearStencil called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ s->clearValue = c;
+
+ DIRTY(sb->clearValue, g->neg_bitid);
+ DIRTY(sb->dirty, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateStencilMask (GLuint mask)
+{
+ CRContext *g = GetCurrentContext();
+ CRStencilState *s = &(g->stencil);
+ CRStateBits *stateb = GetCurrentBits();
+ CRStencilBits *sb = &(stateb->stencil);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glStencilMask called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ s->writeMask = 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_stencil.txt b/src/VBox/GuestHost/OpenGL/state_tracker/state_stencil.txt
new file mode 100644
index 00000000..9632e0c3
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_stencil.txt
@@ -0,0 +1,9 @@
+# Copyright (c) 2001, Stanford University
+# All rights reserved.
+#
+# See the file LICENSE.txt for information on redistributing this software.
+:enable:stencilTest:GL_STENCIL_TEST
+:clearValue:clearValue:ClearStencil
+stencilTest:func:func,ref,mask:StencilFunc
+stencilTest:op:fail,passDepthFail,passDepthPass:StencilOp
+stencilTest:writeMask:writeMask:StencilMask
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_texdiff.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_texdiff.c
new file mode 100644
index 00000000..6854334b
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_texdiff.c
@@ -0,0 +1,1469 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#include "state.h"
+#include "state/cr_statetypes.h"
+#include "state/cr_texture.h"
+#include "cr_hash.h"
+#include "cr_string.h"
+#include "cr_mem.h"
+#include "cr_version.h"
+#include "state_internals.h"
+
+
+#define UNIMPLEMENTED() crStateError(__LINE__,__FILE__,GL_INVALID_OPERATION, "Unimplemented something or other" )
+
+
+#if 0 /* NOT USED??? */
+void crStateTextureObjSwitchCallback( unsigned long key, void *data1, void *data2 )
+{
+ CRTextureObj *tobj = (CRTextureObj *) data1;
+ CRContext *fromCtx = (CRContext *) data2;
+ unsigned int i = 0;
+ unsigned int j = 0;
+ CRbitvalue *bitID = fromCtx->bitid;
+ CRbitvalue nbitID[CR_MAX_BITARRAY];
+
+ for (j=0;j<CR_MAX_BITARRAY;j++)
+ nbitID[j] = ~bitID[j];
+
+ if (!tobj) return;
+
+ FILLDIRTY(tobj->dirty);
+ FILLDIRTY(tobj->imageBit);
+
+ for (i = 0; i < fromCtx->limits.maxTextureUnits; i++)
+ {
+ int j;
+
+ FILLDIRTY(tobj->paramsBit[i]);
+
+ switch (tobj->target)
+ {
+ case GL_TEXTURE_1D:
+ case GL_TEXTURE_2D:
+ for (j = 0; j <= fromCtx->texture.maxLevel; j++)
+ {
+ CRTextureLevel *tl = &(tobj->level[j]);
+ FILLDIRTY(tl->dirty);
+ }
+ break;
+#ifdef CR_OPENGL_VERSION_1_2
+ case GL_TEXTURE_3D:
+#endif
+ for (j = 0; j <= fromCtx->texture.max3DLevel; j++)
+ {
+ CRTextureLevel *tl = &(tobj->level[j]);
+ FILLDIRTY(tl->dirty);
+ }
+ break;
+#ifdef CR_ARB_texture_cube_map
+ case GL_TEXTURE_CUBE_MAP_ARB:
+ for (j = 0; j <= fromCtx->texture.maxCubeMapLevel; j++)
+ {
+ CRTextureLevel *tl;
+ /* Positive X */
+ tl = &(tobj->level[j]);
+ FILLDIRTY(tl->dirty);
+ /* Negative X */
+ tl = &(tobj->negativeXlevel[j]);
+ FILLDIRTY(tl->dirty);
+ /* Positive Y */
+ tl = &(tobj->positiveYlevel[j]);
+ FILLDIRTY(tl->dirty);
+ /* Negative Y */
+ tl = &(tobj->negativeYlevel[j]);
+ FILLDIRTY(tl->dirty);
+ /* Positive Z */
+ tl = &(tobj->positiveZlevel[j]);
+ FILLDIRTY(tl->dirty);
+ /* Negative Z */
+ tl = &(tobj->negativeZlevel[j]);
+ FILLDIRTY(tl->dirty);
+ }
+ break;
+#endif
+ default:
+ UNIMPLEMENTED();
+ }
+ }
+}
+#endif
+
+
+void crStateTextureSwitch( CRTextureBits *tb, CRbitvalue *bitID,
+ CRContext *fromCtx, CRContext *toCtx )
+{
+ CRTextureState *from = &(fromCtx->texture);
+ const CRTextureState *to = &(toCtx->texture);
+ unsigned int i,j;
+ glAble able[2];
+ CRbitvalue nbitID[CR_MAX_BITARRAY];
+ unsigned int activeUnit = (unsigned int) -1;
+
+ for (j=0;j<CR_MAX_BITARRAY;j++)
+ nbitID[j] = ~bitID[j];
+ able[0] = diff_api.Disable;
+ able[1] = diff_api.Enable;
+
+ for (i = 0; i < fromCtx->limits.maxTextureUnits; i++)
+ {
+ if (CHECKDIRTY(tb->enable[i], bitID))
+ {
+ if (activeUnit != i) {
+ diff_api.ActiveTextureARB( i + GL_TEXTURE0_ARB );
+ activeUnit = i;
+ }
+ if (from->unit[i].enabled1D != to->unit[i].enabled1D)
+ {
+ able[to->unit[i].enabled1D](GL_TEXTURE_1D);
+ FILLDIRTY(tb->enable[i]);
+ FILLDIRTY(tb->dirty);
+ }
+ if (from->unit[i].enabled2D != to->unit[i].enabled2D)
+ {
+ able[to->unit[i].enabled2D](GL_TEXTURE_2D);
+ FILLDIRTY(tb->enable[i]);
+ FILLDIRTY(tb->dirty);
+ }
+#ifdef CR_OPENGL_VERSION_1_2
+ if (from->unit[i].enabled3D != to->unit[i].enabled3D)
+ {
+ able[to->unit[i].enabled3D](GL_TEXTURE_3D);
+ FILLDIRTY(tb->enable[i]);
+ FILLDIRTY(tb->dirty);
+ }
+#endif
+#ifdef CR_ARB_texture_cube_map
+ if (fromCtx->extensions.ARB_texture_cube_map &&
+ from->unit[i].enabledCubeMap != to->unit[i].enabledCubeMap)
+ {
+ able[to->unit[i].enabledCubeMap](GL_TEXTURE_CUBE_MAP_ARB);
+ FILLDIRTY(tb->enable[i]);
+ FILLDIRTY(tb->dirty);
+ }
+#endif
+#ifdef CR_NV_texture_rectangle
+ if (fromCtx->extensions.NV_texture_rectangle &&
+ from->unit[i].enabledRect != to->unit[i].enabledRect)
+ {
+ able[to->unit[i].enabledRect](GL_TEXTURE_RECTANGLE_NV);
+ FILLDIRTY(tb->enable[i]);
+ FILLDIRTY(tb->dirty);
+ }
+#endif
+ if (from->unit[i].textureGen.s != to->unit[i].textureGen.s ||
+ from->unit[i].textureGen.t != to->unit[i].textureGen.t ||
+ from->unit[i].textureGen.r != to->unit[i].textureGen.r ||
+ from->unit[i].textureGen.q != to->unit[i].textureGen.q)
+ {
+ able[to->unit[i].textureGen.s](GL_TEXTURE_GEN_S);
+ able[to->unit[i].textureGen.t](GL_TEXTURE_GEN_T);
+ able[to->unit[i].textureGen.r](GL_TEXTURE_GEN_R);
+ able[to->unit[i].textureGen.q](GL_TEXTURE_GEN_Q);
+ FILLDIRTY(tb->enable[i]);
+ FILLDIRTY(tb->dirty);
+ }
+ CLEARDIRTY(tb->enable[i], nbitID);
+ }
+
+ /*
+ ** A thought on switching with textures:
+ ** Since we are only performing a switch
+ ** and not a sync, we won't need to
+ ** update individual textures, just
+ ** the bindings....
+ */
+
+ if (CHECKDIRTY(tb->current[i], bitID))
+ {
+ if (activeUnit != i) {
+ diff_api.ActiveTextureARB( i + GL_TEXTURE0_ARB );
+ activeUnit = i;
+ }
+ if (from->unit[i].currentTexture1D->hwid != to->unit[i].currentTexture1D->hwid)
+ {
+ diff_api.BindTexture(GL_TEXTURE_1D, crStateGetTextureObjHWID(to->unit[i].currentTexture1D));
+ FILLDIRTY(tb->current[i]);
+ FILLDIRTY(tb->dirty);
+ }
+ if (from->unit[i].currentTexture2D->hwid != to->unit[i].currentTexture2D->hwid)
+ {
+ diff_api.BindTexture(GL_TEXTURE_2D, crStateGetTextureObjHWID(to->unit[i].currentTexture2D));
+ FILLDIRTY(tb->current[i]);
+ FILLDIRTY(tb->dirty);
+ }
+#ifdef CR_OPENGL_VERSION_1_2
+ if (from->unit[i].currentTexture3D->hwid != to->unit[i].currentTexture3D->hwid)
+ {
+ diff_api.BindTexture(GL_TEXTURE_3D, crStateGetTextureObjHWID(to->unit[i].currentTexture3D));
+ FILLDIRTY(tb->current[i]);
+ FILLDIRTY(tb->dirty);
+ }
+#endif
+#ifdef CR_ARB_texture_cube_map
+ if (fromCtx->extensions.ARB_texture_cube_map &&
+ from->unit[i].currentTextureCubeMap->hwid != to->unit[i].currentTextureCubeMap->hwid)
+ {
+ diff_api.BindTexture(GL_TEXTURE_CUBE_MAP_ARB, crStateGetTextureObjHWID(to->unit[i].currentTextureCubeMap));
+ FILLDIRTY(tb->current[i]);
+ FILLDIRTY(tb->dirty);
+ }
+#endif
+#ifdef CR_NV_texture_rectangle
+ if (fromCtx->extensions.NV_texture_rectangle &&
+ from->unit[i].currentTextureRect->hwid != to->unit[i].currentTextureRect->hwid)
+ {
+ diff_api.BindTexture(GL_TEXTURE_RECTANGLE_NV, crStateGetTextureObjHWID(to->unit[i].currentTextureRect));
+ FILLDIRTY(tb->current[i]);
+ FILLDIRTY(tb->dirty);
+ }
+#endif
+ CLEARDIRTY(tb->current[i], nbitID);
+ }
+
+ if (CHECKDIRTY(tb->objGen[i], bitID))
+ {
+ if (activeUnit != i) {
+ diff_api.ActiveTextureARB( i + GL_TEXTURE0_ARB );
+ activeUnit = i;
+ }
+ if (from->unit[i].objSCoeff.x != to->unit[i].objSCoeff.x ||
+ from->unit[i].objSCoeff.y != to->unit[i].objSCoeff.y ||
+ from->unit[i].objSCoeff.z != to->unit[i].objSCoeff.z ||
+ from->unit[i].objSCoeff.w != to->unit[i].objSCoeff.w)
+ {
+ GLfloat f[4];
+ f[0] = to->unit[i].objSCoeff.x;
+ f[1] = to->unit[i].objSCoeff.y;
+ f[2] = to->unit[i].objSCoeff.z;
+ f[3] = to->unit[i].objSCoeff.w;
+ diff_api.TexGenfv (GL_S, GL_OBJECT_PLANE, (const GLfloat *) f);
+ FILLDIRTY(tb->objGen[i]);
+ FILLDIRTY(tb->dirty);
+ }
+ if (from->unit[i].objTCoeff.x != to->unit[i].objTCoeff.x ||
+ from->unit[i].objTCoeff.y != to->unit[i].objTCoeff.y ||
+ from->unit[i].objTCoeff.z != to->unit[i].objTCoeff.z ||
+ from->unit[i].objTCoeff.w != to->unit[i].objTCoeff.w) {
+ GLfloat f[4];
+ f[0] = to->unit[i].objTCoeff.x;
+ f[1] = to->unit[i].objTCoeff.y;
+ f[2] = to->unit[i].objTCoeff.z;
+ f[3] = to->unit[i].objTCoeff.w;
+ diff_api.TexGenfv (GL_T, GL_OBJECT_PLANE, (const GLfloat *) f);
+ FILLDIRTY(tb->objGen[i]);
+ FILLDIRTY(tb->dirty);
+ }
+ if (from->unit[i].objRCoeff.x != to->unit[i].objRCoeff.x ||
+ from->unit[i].objRCoeff.y != to->unit[i].objRCoeff.y ||
+ from->unit[i].objRCoeff.z != to->unit[i].objRCoeff.z ||
+ from->unit[i].objRCoeff.w != to->unit[i].objRCoeff.w) {
+ GLfloat f[4];
+ f[0] = to->unit[i].objRCoeff.x;
+ f[1] = to->unit[i].objRCoeff.y;
+ f[2] = to->unit[i].objRCoeff.z;
+ f[3] = to->unit[i].objRCoeff.w;
+ diff_api.TexGenfv (GL_R, GL_OBJECT_PLANE, (const GLfloat *) f);
+ FILLDIRTY(tb->objGen[i]);
+ FILLDIRTY(tb->dirty);
+ }
+ if (from->unit[i].objQCoeff.x != to->unit[i].objQCoeff.x ||
+ from->unit[i].objQCoeff.y != to->unit[i].objQCoeff.y ||
+ from->unit[i].objQCoeff.z != to->unit[i].objQCoeff.z ||
+ from->unit[i].objQCoeff.w != to->unit[i].objQCoeff.w) {
+ GLfloat f[4];
+ f[0] = to->unit[i].objQCoeff.x;
+ f[1] = to->unit[i].objQCoeff.y;
+ f[2] = to->unit[i].objQCoeff.z;
+ f[3] = to->unit[i].objQCoeff.w;
+ diff_api.TexGenfv (GL_Q, GL_OBJECT_PLANE, (const GLfloat *) f);
+ FILLDIRTY(tb->objGen[i]);
+ FILLDIRTY(tb->dirty);
+ }
+ CLEARDIRTY(tb->objGen[i], nbitID);
+ }
+ if (CHECKDIRTY(tb->eyeGen[i], bitID))
+ {
+ if (activeUnit != i) {
+ diff_api.ActiveTextureARB( i + GL_TEXTURE0_ARB );
+ activeUnit = i;
+ }
+ diff_api.MatrixMode(GL_MODELVIEW);
+ diff_api.PushMatrix();
+ diff_api.LoadIdentity();
+ if (from->unit[i].eyeSCoeff.x != to->unit[i].eyeSCoeff.x ||
+ from->unit[i].eyeSCoeff.y != to->unit[i].eyeSCoeff.y ||
+ from->unit[i].eyeSCoeff.z != to->unit[i].eyeSCoeff.z ||
+ from->unit[i].eyeSCoeff.w != to->unit[i].eyeSCoeff.w) {
+ GLfloat f[4];
+ f[0] = to->unit[i].eyeSCoeff.x;
+ f[1] = to->unit[i].eyeSCoeff.y;
+ f[2] = to->unit[i].eyeSCoeff.z;
+ f[3] = to->unit[i].eyeSCoeff.w;
+ diff_api.TexGenfv (GL_S, GL_EYE_PLANE, (const GLfloat *) f);
+ FILLDIRTY(tb->eyeGen[i]);
+ FILLDIRTY(tb->dirty);
+ }
+ if (from->unit[i].eyeTCoeff.x != to->unit[i].eyeTCoeff.x ||
+ from->unit[i].eyeTCoeff.y != to->unit[i].eyeTCoeff.y ||
+ from->unit[i].eyeTCoeff.z != to->unit[i].eyeTCoeff.z ||
+ from->unit[i].eyeTCoeff.w != to->unit[i].eyeTCoeff.w) {
+ GLfloat f[4];
+ f[0] = to->unit[i].eyeTCoeff.x;
+ f[1] = to->unit[i].eyeTCoeff.y;
+ f[2] = to->unit[i].eyeTCoeff.z;
+ f[3] = to->unit[i].eyeTCoeff.w;
+ diff_api.TexGenfv (GL_T, GL_EYE_PLANE, (const GLfloat *) f);
+ FILLDIRTY(tb->eyeGen[i]);
+ FILLDIRTY(tb->dirty);
+ }
+ if (from->unit[i].eyeRCoeff.x != to->unit[i].eyeRCoeff.x ||
+ from->unit[i].eyeRCoeff.y != to->unit[i].eyeRCoeff.y ||
+ from->unit[i].eyeRCoeff.z != to->unit[i].eyeRCoeff.z ||
+ from->unit[i].eyeRCoeff.w != to->unit[i].eyeRCoeff.w) {
+ GLfloat f[4];
+ f[0] = to->unit[i].eyeRCoeff.x;
+ f[1] = to->unit[i].eyeRCoeff.y;
+ f[2] = to->unit[i].eyeRCoeff.z;
+ f[3] = to->unit[i].eyeRCoeff.w;
+ diff_api.TexGenfv (GL_R, GL_EYE_PLANE, (const GLfloat *) f);
+ FILLDIRTY(tb->eyeGen[i]);
+ FILLDIRTY(tb->dirty);
+ }
+ if (from->unit[i].eyeQCoeff.x != to->unit[i].eyeQCoeff.x ||
+ from->unit[i].eyeQCoeff.y != to->unit[i].eyeQCoeff.y ||
+ from->unit[i].eyeQCoeff.z != to->unit[i].eyeQCoeff.z ||
+ from->unit[i].eyeQCoeff.w != to->unit[i].eyeQCoeff.w) {
+ GLfloat f[4];
+ f[0] = to->unit[i].eyeQCoeff.x;
+ f[1] = to->unit[i].eyeQCoeff.y;
+ f[2] = to->unit[i].eyeQCoeff.z;
+ f[3] = to->unit[i].eyeQCoeff.w;
+ diff_api.TexGenfv (GL_Q, GL_EYE_PLANE, (const GLfloat *) f);
+ FILLDIRTY(tb->eyeGen[i]);
+ FILLDIRTY(tb->dirty);
+ }
+ diff_api.PopMatrix();
+ CLEARDIRTY(tb->eyeGen[i], nbitID);
+ }
+ if (CHECKDIRTY(tb->genMode[i], bitID))
+ {
+ if (activeUnit != i) {
+ diff_api.ActiveTextureARB( i + GL_TEXTURE0_ARB );
+ activeUnit = i;
+ }
+ if (from->unit[i].gen.s != to->unit[i].gen.s ||
+ from->unit[i].gen.t != to->unit[i].gen.t ||
+ from->unit[i].gen.r != to->unit[i].gen.r ||
+ from->unit[i].gen.q != to->unit[i].gen.q)
+ {
+ diff_api.TexGeni (GL_S, GL_TEXTURE_GEN_MODE, to->unit[i].gen.s);
+ diff_api.TexGeni (GL_T, GL_TEXTURE_GEN_MODE, to->unit[i].gen.t);
+ diff_api.TexGeni (GL_R, GL_TEXTURE_GEN_MODE, to->unit[i].gen.r);
+ diff_api.TexGeni (GL_Q, GL_TEXTURE_GEN_MODE, to->unit[i].gen.q);
+ FILLDIRTY(tb->genMode[i]);
+ FILLDIRTY(tb->dirty);
+ }
+ CLEARDIRTY(tb->genMode[i], nbitID);
+ }
+ CLEARDIRTY(tb->dirty, nbitID);
+
+ /* Texture enviroment */
+ if (CHECKDIRTY(tb->envBit[i], bitID))
+ {
+ if (activeUnit != i) {
+ diff_api.ActiveTextureARB( i + GL_TEXTURE0_ARB );
+ activeUnit = i;
+ }
+ if (from->unit[i].envMode != to->unit[i].envMode)
+ {
+ diff_api.TexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, to->unit[i].envMode);
+ FILLDIRTY(tb->envBit[i]);
+ FILLDIRTY(tb->dirty);
+ }
+ if (from->unit[i].envColor.r != to->unit[i].envColor.r ||
+ from->unit[i].envColor.g != to->unit[i].envColor.g ||
+ from->unit[i].envColor.b != to->unit[i].envColor.b ||
+ from->unit[i].envColor.a != to->unit[i].envColor.a)
+ {
+ GLfloat f[4];
+ f[0] = to->unit[i].envColor.r;
+ f[1] = to->unit[i].envColor.g;
+ f[2] = to->unit[i].envColor.b;
+ f[3] = to->unit[i].envColor.a;
+ diff_api.TexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, (const GLfloat *) f);
+ FILLDIRTY(tb->envBit[i]);
+ FILLDIRTY(tb->dirty);
+ }
+ if (from->unit[i].combineModeRGB != to->unit[i].combineModeRGB)
+ {
+ diff_api.TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, to->unit[i].combineModeRGB);
+ FILLDIRTY(tb->envBit[i]);
+ FILLDIRTY(tb->dirty);
+ }
+ if (from->unit[i].combineModeA != to->unit[i].combineModeA)
+ {
+ diff_api.TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, to->unit[i].combineModeA);
+ FILLDIRTY(tb->envBit[i]);
+ FILLDIRTY(tb->dirty);
+ }
+ if (from->unit[i].combineSourceRGB[0] != to->unit[i].combineSourceRGB[0])
+ {
+ diff_api.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, to->unit[i].combineSourceRGB[0]);
+ FILLDIRTY(tb->envBit[i]);
+ FILLDIRTY(tb->dirty);
+ }
+ if (from->unit[i].combineSourceRGB[1] != to->unit[i].combineSourceRGB[1])
+ {
+ diff_api.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, to->unit[i].combineSourceRGB[1]);
+ FILLDIRTY(tb->envBit[i]);
+ FILLDIRTY(tb->dirty);
+ }
+ if (from->unit[i].combineSourceRGB[2] != to->unit[i].combineSourceRGB[2])
+ {
+ diff_api.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, to->unit[i].combineSourceRGB[2]);
+ FILLDIRTY(tb->envBit[i]);
+ FILLDIRTY(tb->dirty);
+ }
+ if (from->unit[i].combineSourceA[0] != to->unit[i].combineSourceA[0])
+ {
+ diff_api.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, to->unit[i].combineSourceA[0]);
+ FILLDIRTY(tb->envBit[i]);
+ FILLDIRTY(tb->dirty);
+ }
+ if (from->unit[i].combineSourceA[1] != to->unit[i].combineSourceA[1])
+ {
+ diff_api.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, to->unit[i].combineSourceA[1]);
+ FILLDIRTY(tb->envBit[i]);
+ FILLDIRTY(tb->dirty);
+ }
+ if (from->unit[i].combineSourceA[2] != to->unit[i].combineSourceA[2])
+ {
+ diff_api.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, to->unit[i].combineSourceA[2]);
+ FILLDIRTY(tb->envBit[i]);
+ FILLDIRTY(tb->dirty);
+ }
+ if (from->unit[i].combineOperandRGB[0] != to->unit[i].combineOperandRGB[0])
+ {
+ diff_api.TexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, to->unit[i].combineOperandRGB[0]);
+ FILLDIRTY(tb->envBit[i]);
+ FILLDIRTY(tb->dirty);
+ }
+ if (from->unit[i].combineOperandRGB[1] != to->unit[i].combineOperandRGB[1])
+ {
+ diff_api.TexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, to->unit[i].combineOperandRGB[1]);
+ FILLDIRTY(tb->envBit[i]);
+ FILLDIRTY(tb->dirty);
+ }
+ if (from->unit[i].combineOperandRGB[2] != to->unit[i].combineOperandRGB[2])
+ {
+ diff_api.TexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, to->unit[i].combineOperandRGB[2]);
+ FILLDIRTY(tb->envBit[i]);
+ FILLDIRTY(tb->dirty);
+ }
+ if (from->unit[i].combineOperandA[0] != to->unit[i].combineOperandA[0])
+ {
+ diff_api.TexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, to->unit[i].combineOperandA[0]);
+ FILLDIRTY(tb->envBit[i]);
+ FILLDIRTY(tb->dirty);
+ }
+ if (from->unit[i].combineOperandA[1] != to->unit[i].combineOperandA[1])
+ {
+ diff_api.TexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, to->unit[i].combineOperandA[1]);
+ FILLDIRTY(tb->envBit[i]);
+ FILLDIRTY(tb->dirty);
+ }
+ if (from->unit[i].combineOperandA[2] != to->unit[i].combineOperandA[2])
+ {
+ diff_api.TexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, to->unit[i].combineOperandA[2]);
+ FILLDIRTY(tb->envBit[i]);
+ FILLDIRTY(tb->dirty);
+ }
+ if (from->unit[i].combineScaleRGB != to->unit[i].combineScaleRGB)
+ {
+ diff_api.TexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, to->unit[i].combineScaleRGB);
+ FILLDIRTY(tb->envBit[i]);
+ FILLDIRTY(tb->dirty);
+ }
+ if (from->unit[i].combineScaleA != to->unit[i].combineScaleA)
+ {
+ diff_api.TexEnvf(GL_TEXTURE_ENV, GL_ALPHA_SCALE, to->unit[i].combineScaleA);
+ FILLDIRTY(tb->envBit[i]);
+ FILLDIRTY(tb->dirty);
+ }
+ CLEARDIRTY(tb->envBit[i], nbitID);
+ }
+ }
+
+ /* Resend texture images */
+ if (toCtx->shared->bTexResyncNeeded)
+ {
+ toCtx->shared->bTexResyncNeeded = GL_FALSE;
+
+ crStateDiffAllTextureObjects(toCtx, bitID, GL_TRUE);
+ }
+
+ /* After possible fiddling put them back now */
+ if (activeUnit != toCtx->texture.curTextureUnit) {
+ diff_api.ActiveTextureARB( toCtx->texture.curTextureUnit + GL_TEXTURE0_ARB );
+ }
+ diff_api.MatrixMode(toCtx->transform.matrixMode);
+}
+
+
+/*
+ * Check the dirty bits for the specified texture on a given unit to
+ * determine if any of its images are dirty.
+ * Return: 1 -- dirty, 0 -- clean
+ */
+int crStateTextureCheckDirtyImages(CRContext *from, CRContext *to, GLenum target, int textureUnit)
+{
+ CRContext *g = GetCurrentContext();
+ CRTextureState *tsto;
+ CRbitvalue *bitID;
+ CRTextureObj *tobj = NULL;
+ int maxLevel = 0, i;
+ int face, numFaces;
+
+ CRASSERT(to);
+ CRASSERT(from);
+
+ tsto = &(to->texture);
+ bitID = from->bitid;
+
+ CRASSERT(tsto);
+
+ switch(target)
+ {
+ case GL_TEXTURE_1D:
+ tobj = tsto->unit[textureUnit].currentTexture1D;
+ maxLevel = tsto->maxLevel;
+ break;
+ case GL_TEXTURE_2D:
+ tobj = tsto->unit[textureUnit].currentTexture2D;
+ maxLevel = tsto->maxLevel;
+ break;
+#ifdef CR_OPENGL_VERSION_1_2
+ case GL_TEXTURE_3D:
+ tobj = tsto->unit[textureUnit].currentTexture3D;
+ maxLevel = tsto->max3DLevel;
+ break;
+#endif
+#ifdef CR_ARB_texture_cube_map
+ case GL_TEXTURE_CUBE_MAP:
+ if (g->extensions.ARB_texture_cube_map) {
+ tobj = tsto->unit[textureUnit].currentTextureCubeMap;
+ maxLevel = tsto->maxCubeMapLevel;
+ }
+ break;
+#endif
+#ifdef CR_NV_texture_rectangle
+ case GL_TEXTURE_RECTANGLE_NV:
+ if (g->extensions.NV_texture_rectangle) {
+ tobj = tsto->unit[textureUnit].currentTextureRect;
+ maxLevel = 1;
+ }
+ break;
+#endif
+ default:
+ crError("Bad texture target in crStateTextureCheckDirtyImages()");
+ return 0;
+ }
+
+ if (!tobj)
+ {
+ return 0;
+ }
+
+ numFaces = (target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
+
+ for (face = 0; face < numFaces; face++) {
+ for (i = 0; i < maxLevel; i++) {
+ if (CHECKDIRTY(tobj->level[face][i].dirty, bitID))
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+
+/*
+ * Do texture state differencing for the given texture object.
+ */
+void
+crStateTextureObjectDiff(CRContext *fromCtx,
+ const CRbitvalue *bitID, const CRbitvalue *nbitID,
+ CRTextureObj *tobj, GLboolean alwaysDirty)
+{
+ 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;
+
+#if 0
+ /* XXX disabling this code fixed Wes Bethel's problem with missing/white
+ * textures. Setting the active texture unit here can screw up the
+ * current texture object bindings.
+ */
+ /* Set active texture unit, and bind this texture object */
+ if (from->curTextureUnit != u) {
+ diff_api.ActiveTextureARB( u + GL_TEXTURE0_ARB );
+ from->curTextureUnit = u;
+ }
+#endif
+
+ diff_api.BindTexture(tobj->target, hwid);
+
+ if (alwaysDirty || CHECKDIRTY(tobj->paramsBit[u], bitID))
+ {
+ GLfloat f[4];
+ f[0] = tobj->borderColor.r;
+ f[1] = tobj->borderColor.g;
+ f[2] = tobj->borderColor.b;
+ f[3] = tobj->borderColor.a;
+ diff_api.TexParameteri(tobj->target, GL_TEXTURE_BASE_LEVEL, tobj->baseLevel);
+ diff_api.TexParameteri(tobj->target, GL_TEXTURE_MAX_LEVEL, tobj->maxLevel);
+ diff_api.TexParameteri(tobj->target, GL_TEXTURE_MIN_FILTER, tobj->minFilter);
+ diff_api.TexParameteri(tobj->target, GL_TEXTURE_MAG_FILTER, tobj->magFilter);
+ diff_api.TexParameteri(tobj->target, GL_TEXTURE_WRAP_S, tobj->wrapS);
+ diff_api.TexParameteri(tobj->target, GL_TEXTURE_WRAP_T, tobj->wrapT);
+#ifdef CR_OPENGL_VERSION_1_2
+ diff_api.TexParameteri(tobj->target, GL_TEXTURE_WRAP_R, tobj->wrapR);
+ diff_api.TexParameterf(tobj->target, GL_TEXTURE_PRIORITY, tobj->priority);
+#endif
+ diff_api.TexParameterfv(tobj->target, GL_TEXTURE_BORDER_COLOR, (const GLfloat *) f);
+#ifdef CR_EXT_texture_filter_anisotropic
+ if (fromCtx->extensions.EXT_texture_filter_anisotropic) {
+ diff_api.TexParameterf(tobj->target, GL_TEXTURE_MAX_ANISOTROPY_EXT, tobj->maxAnisotropy);
+ }
+#endif
+#ifdef CR_ARB_depth_texture
+ if (fromCtx->extensions.ARB_depth_texture)
+ diff_api.TexParameteri(tobj->target, GL_DEPTH_TEXTURE_MODE_ARB, tobj->depthMode);
+#endif
+#ifdef CR_ARB_shadow
+ if (fromCtx->extensions.ARB_shadow) {
+ diff_api.TexParameteri(tobj->target, GL_TEXTURE_COMPARE_MODE_ARB, tobj->compareMode);
+ diff_api.TexParameteri(tobj->target, GL_TEXTURE_COMPARE_FUNC_ARB, tobj->compareFunc);
+ }
+#endif
+#ifdef CR_ARB_shadow_ambient
+ if (fromCtx->extensions.ARB_shadow_ambient) {
+ diff_api.TexParameterf(tobj->target, GL_TEXTURE_COMPARE_FAIL_VALUE_ARB, tobj->compareFailValue);
+ }
+#endif
+#ifdef CR_SGIS_generate_mipmap
+ if (fromCtx->extensions.SGIS_generate_mipmap) {
+ diff_api.TexParameteri(tobj->target, GL_GENERATE_MIPMAP_SGIS, tobj->generateMipmap);
+ }
+#endif
+ if (!alwaysDirty)
+ CLEARDIRTY(tobj->paramsBit[u], nbitID);
+ }
+
+ /* now, if the texture images are dirty */
+ if (alwaysDirty || CHECKDIRTY(tobj->imageBit, bitID))
+ {
+ int lvl;
+ int face;
+
+ switch (tobj->target)
+ {
+ case GL_TEXTURE_1D:
+ for (lvl = 0; lvl <= from->maxLevel; lvl++)
+ {
+ CRTextureLevel *tl = &(tobj->level[0][lvl]);
+ if (alwaysDirty || CHECKDIRTY(tl->dirty, bitID))
+ {
+ if (tl->generateMipmap) {
+ diff_api.TexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, 1);
+ }
+ if (tl->width)
+ {
+ if (tl->compressed) {
+ diff_api.CompressedTexImage1DARB(GL_TEXTURE_1D, lvl,
+ tl->internalFormat, tl->width,
+ tl->border, tl->bytes, tl->img);
+ }
+ else {
+ /* alignment must be one */
+ diff_api.PixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+ diff_api.PixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
+ diff_api.PixelStorei(GL_UNPACK_SKIP_ROWS, 0);
+ diff_api.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ if (tl->generateMipmap) {
+ diff_api.TexParameteri(GL_TEXTURE_1D, GL_GENERATE_MIPMAP_SGIS, 1);
+ }
+ diff_api.TexImage1D(GL_TEXTURE_1D, lvl,
+ tl->internalFormat,
+ tl->width, tl->border,
+ tl->format, tl->type, tl->img);
+ }
+ }
+ if (!alwaysDirty)
+ {
+ CLEARDIRTY(tl->dirty, nbitID);
+ }
+#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
+ else
+ {
+ crFree(tl->img);
+ tl->img = NULL;
+ }
+#endif
+ }
+ }
+ break;
+ case GL_TEXTURE_2D:
+ for (lvl = 0; lvl <= from->maxLevel; lvl++)
+ {
+ CRTextureLevel *tl = &(tobj->level[0][lvl]);
+ if (alwaysDirty || CHECKDIRTY(tl->dirty, bitID))
+ {
+ if (tl->generateMipmap) {
+ diff_api.TexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, 1);
+ }
+
+ if (tl->width && tl->height)
+ {
+ if (tl->compressed) {
+ diff_api.CompressedTexImage2DARB(GL_TEXTURE_2D, lvl,
+ tl->internalFormat, tl->width,
+ tl->height, tl->border,
+ tl->bytes, tl->img);
+ }
+ else {
+ /* alignment must be one */
+ diff_api.PixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+ diff_api.PixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
+ diff_api.PixelStorei(GL_UNPACK_SKIP_ROWS, 0);
+ diff_api.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ diff_api.TexImage2D(GL_TEXTURE_2D, lvl,
+ tl->internalFormat,
+ tl->width, tl->height, tl->border,
+ tl->format, tl->type, tl->img);
+ }
+ }
+
+ if (!alwaysDirty)
+ {
+ CLEARDIRTY(tl->dirty, nbitID);
+ }
+#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
+ else
+ {
+ crFree(tl->img);
+ tl->img = NULL;
+ }
+#endif
+ }
+ }
+ break;
+#ifdef CR_OPENGL_VERSION_1_2
+ case GL_TEXTURE_3D:
+ for (lvl = 0; lvl <= from->max3DLevel; lvl++)
+ {
+ CRTextureLevel *tl = &(tobj->level[0][lvl]);
+ if (alwaysDirty || CHECKDIRTY(tl->dirty, bitID))
+ {
+ if (tl->generateMipmap) {
+ diff_api.TexParameteri(GL_TEXTURE_3D, GL_GENERATE_MIPMAP_SGIS, 1);
+ }
+
+ if (tl->width && tl->height)
+ {
+ if (tl->compressed) {
+ diff_api.CompressedTexImage3DARB(GL_TEXTURE_3D, lvl,
+ tl->internalFormat, tl->width,
+ tl->height, tl->depth,
+ tl->border, tl->bytes, tl->img);
+ }
+ else {
+ /* alignment must be one */
+ diff_api.PixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+ diff_api.PixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
+ diff_api.PixelStorei(GL_UNPACK_SKIP_ROWS, 0);
+ diff_api.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ diff_api.TexImage3D(GL_TEXTURE_3D, lvl,
+ tl->internalFormat,
+ tl->width, tl->height, tl->depth,
+ tl->border, tl->format,
+ tl->type, tl->img);
+ }
+ }
+
+ if (!alwaysDirty)
+ {
+ CLEARDIRTY(tl->dirty, nbitID);
+ }
+#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
+ else
+ {
+ crFree(tl->img);
+ tl->img = NULL;
+ }
+#endif
+ }
+ }
+ break;
+#endif
+#ifdef CR_NV_texture_rectangle
+ case GL_TEXTURE_RECTANGLE_NV:
+ /* only one level */
+ for (lvl = 0; lvl <= from->maxRectLevel; lvl++)
+ {
+ CRTextureLevel *tl = &(tobj->level[0][lvl]);
+ if (alwaysDirty || CHECKDIRTY(tl->dirty, bitID))
+ {
+ if (tl->width && tl->height)
+ {
+ if (tl->compressed) {
+ diff_api.CompressedTexImage2DARB(GL_TEXTURE_RECTANGLE_NV, lvl,
+ tl->internalFormat, tl->width,
+ tl->height, tl->border,
+ tl->bytes, tl->img);
+ }
+ else {
+ /* alignment must be one */
+ diff_api.PixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+ diff_api.PixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
+ diff_api.PixelStorei(GL_UNPACK_SKIP_ROWS, 0);
+ diff_api.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ diff_api.TexImage2D(GL_TEXTURE_RECTANGLE_NV, lvl,
+ tl->internalFormat,
+ tl->width, tl->height, tl->border,
+ tl->format, tl->type, tl->img);
+ }
+ }
+
+ if (!alwaysDirty)
+ {
+ CLEARDIRTY(tl->dirty, nbitID);
+ }
+#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
+ else
+ {
+ crFree(tl->img);
+ tl->img = NULL;
+ }
+#endif
+ }
+ }
+ break;
+#endif
+#ifdef CR_ARB_texture_cube_map
+ case GL_TEXTURE_CUBE_MAP_ARB:
+ for (face = 0; face < 6; face++)
+ {
+ const GLenum target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
+ for (lvl = 0; lvl <= from->maxCubeMapLevel; lvl++)
+ {
+ CRTextureLevel *tl = &(tobj->level[face][lvl]);
+ if (alwaysDirty || CHECKDIRTY(tl->dirty, bitID))
+ {
+ if (tl->generateMipmap) {
+ diff_api.TexParameteri(GL_TEXTURE_CUBE_MAP_ARB,
+ GL_GENERATE_MIPMAP_SGIS, 1);
+ }
+
+ if (tl->width && tl->height)
+ {
+ if (tl->compressed) {
+ diff_api.CompressedTexImage2DARB(target,
+ lvl, tl->internalFormat,
+ tl->width, tl->height,
+ tl->border, tl->bytes, tl->img);
+ }
+ else {
+ /* alignment must be one */
+ diff_api.PixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+ diff_api.PixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
+ diff_api.PixelStorei(GL_UNPACK_SKIP_ROWS, 0);
+ diff_api.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ diff_api.TexImage2D(target, lvl,
+ tl->internalFormat,
+ tl->width, tl->height, tl->border,
+ tl->format, tl->type, tl->img);
+ }
+ }
+
+ if (!alwaysDirty)
+ {
+ CLEARDIRTY(tl->dirty, nbitID);
+ }
+#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
+ else
+ {
+ crFree(tl->img);
+ tl->img = NULL;
+ }
+#endif
+ }
+ } /* for lvl */
+ } /* for face */
+ break;
+#endif
+ default:
+ UNIMPLEMENTED();
+
+ } /* switch */
+ } /* if (CHECKDIRTY(tobj->imageBit, bitID)) */
+}
+
+
+
+void
+crStateTextureDiff( CRTextureBits *tb, CRbitvalue *bitID,
+ CRContext *fromCtx, CRContext *toCtx )
+{
+ CRTextureState *from = &(fromCtx->texture);
+ CRTextureState *to = &(toCtx->texture);
+ unsigned int u, t, j;
+ glAble able[2];
+ CRbitvalue nbitID[CR_MAX_BITARRAY];
+ const GLboolean haveFragProg = fromCtx->extensions.ARB_fragment_program || fromCtx->extensions.NV_fragment_program;
+
+ for (j=0;j<CR_MAX_BITARRAY;j++)
+ nbitID[j] = ~bitID[j];
+
+ able[0] = diff_api.Disable;
+ able[1] = diff_api.Enable;
+
+ /* loop over texture units */
+ for (u = 0; u < fromCtx->limits.maxTextureUnits; u++)
+ {
+ CRTextureObj **fromBinding = NULL;
+ CRTextureObj *tobj;
+
+ /* take care of enables/disables */
+ if (CHECKDIRTY(tb->enable[u], bitID))
+ {
+
+ /* Activate texture unit u if needed */
+ if (fromCtx->texture.curTextureUnit != u) {
+ diff_api.ActiveTextureARB( GL_TEXTURE0_ARB + u);
+ fromCtx->texture.curTextureUnit = u;
+ }
+
+ if (from->unit[u].enabled1D != to->unit[u].enabled1D)
+ {
+ able[to->unit[u].enabled1D](GL_TEXTURE_1D);
+ from->unit[u].enabled1D = to->unit[u].enabled1D;
+ }
+ if (from->unit[u].enabled2D != to->unit[u].enabled2D)
+ {
+ able[to->unit[u].enabled2D](GL_TEXTURE_2D);
+ from->unit[u].enabled2D = to->unit[u].enabled2D;
+ }
+#ifdef CR_OPENGL_VERSION_1_2
+ if (from->unit[u].enabled3D != to->unit[u].enabled3D)
+ {
+ able[to->unit[u].enabled3D](GL_TEXTURE_3D);
+ from->unit[u].enabled3D = to->unit[u].enabled3D;
+ }
+#endif
+#ifdef CR_ARB_texture_cube_map
+ if (fromCtx->extensions.ARB_texture_cube_map &&
+ from->unit[u].enabledCubeMap != to->unit[u].enabledCubeMap)
+ {
+ able[to->unit[u].enabledCubeMap](GL_TEXTURE_CUBE_MAP_ARB);
+ from->unit[u].enabledCubeMap = to->unit[u].enabledCubeMap;
+ }
+#endif
+#ifdef CR_NV_texture_rectangle
+ if (fromCtx->extensions.NV_texture_rectangle &&
+ from->unit[u].enabledRect != to->unit[u].enabledRect)
+ {
+ able[to->unit[u].enabledRect](GL_TEXTURE_RECTANGLE_NV);
+ from->unit[u].enabledRect = to->unit[u].enabledRect;
+ }
+#endif
+
+ /* texgen enables */
+ if (from->unit[u].textureGen.s != to->unit[u].textureGen.s ||
+ from->unit[u].textureGen.t != to->unit[u].textureGen.t ||
+ from->unit[u].textureGen.r != to->unit[u].textureGen.r ||
+ from->unit[u].textureGen.q != to->unit[u].textureGen.q)
+ {
+ able[to->unit[u].textureGen.s](GL_TEXTURE_GEN_S);
+ able[to->unit[u].textureGen.t](GL_TEXTURE_GEN_T);
+ able[to->unit[u].textureGen.r](GL_TEXTURE_GEN_R);
+ able[to->unit[u].textureGen.q](GL_TEXTURE_GEN_Q);
+ from->unit[u].textureGen = to->unit[u].textureGen;
+ }
+ CLEARDIRTY(tb->enable[u], nbitID);
+ }
+
+
+ /* Texgen coefficients */
+ if (CHECKDIRTY(tb->objGen[u], bitID))
+ {
+ if (fromCtx->texture.curTextureUnit != u) {
+ diff_api.ActiveTextureARB( u + GL_TEXTURE0_ARB );
+ fromCtx->texture.curTextureUnit = u;
+ }
+ if (from->unit[u].objSCoeff.x != to->unit[u].objSCoeff.x ||
+ from->unit[u].objSCoeff.y != to->unit[u].objSCoeff.y ||
+ from->unit[u].objSCoeff.z != to->unit[u].objSCoeff.z ||
+ from->unit[u].objSCoeff.w != to->unit[u].objSCoeff.w)
+ {
+ GLfloat f[4];
+ f[0] = to->unit[u].objSCoeff.x;
+ f[1] = to->unit[u].objSCoeff.y;
+ f[2] = to->unit[u].objSCoeff.z;
+ f[3] = to->unit[u].objSCoeff.w;
+ diff_api.TexGenfv (GL_S, GL_OBJECT_PLANE, (const GLfloat *) f);
+ from->unit[u].objSCoeff = to->unit[u].objSCoeff;
+ }
+ if (from->unit[u].objTCoeff.x != to->unit[u].objTCoeff.x ||
+ from->unit[u].objTCoeff.y != to->unit[u].objTCoeff.y ||
+ from->unit[u].objTCoeff.z != to->unit[u].objTCoeff.z ||
+ from->unit[u].objTCoeff.w != to->unit[u].objTCoeff.w)
+ {
+ GLfloat f[4];
+ f[0] = to->unit[u].objTCoeff.x;
+ f[1] = to->unit[u].objTCoeff.y;
+ f[2] = to->unit[u].objTCoeff.z;
+ f[3] = to->unit[u].objTCoeff.w;
+ diff_api.TexGenfv (GL_T, GL_OBJECT_PLANE, (const GLfloat *) f);
+ from->unit[u].objTCoeff = to->unit[u].objTCoeff;
+ }
+ if (from->unit[u].objRCoeff.x != to->unit[u].objRCoeff.x ||
+ from->unit[u].objRCoeff.y != to->unit[u].objRCoeff.y ||
+ from->unit[u].objRCoeff.z != to->unit[u].objRCoeff.z ||
+ from->unit[u].objRCoeff.w != to->unit[u].objRCoeff.w)
+ {
+ GLfloat f[4];
+ f[0] = to->unit[u].objRCoeff.x;
+ f[1] = to->unit[u].objRCoeff.y;
+ f[2] = to->unit[u].objRCoeff.z;
+ f[3] = to->unit[u].objRCoeff.w;
+ diff_api.TexGenfv (GL_R, GL_OBJECT_PLANE, (const GLfloat *) f);
+ from->unit[u].objRCoeff = to->unit[u].objRCoeff;
+ }
+ if (from->unit[u].objQCoeff.x != to->unit[u].objQCoeff.x ||
+ from->unit[u].objQCoeff.y != to->unit[u].objQCoeff.y ||
+ from->unit[u].objQCoeff.z != to->unit[u].objQCoeff.z ||
+ from->unit[u].objQCoeff.w != to->unit[u].objQCoeff.w)
+ {
+ GLfloat f[4];
+ f[0] = to->unit[u].objQCoeff.x;
+ f[1] = to->unit[u].objQCoeff.y;
+ f[2] = to->unit[u].objQCoeff.z;
+ f[3] = to->unit[u].objQCoeff.w;
+ diff_api.TexGenfv (GL_Q, GL_OBJECT_PLANE, (const GLfloat *) f);
+ from->unit[u].objQCoeff = to->unit[u].objQCoeff;
+ }
+ CLEARDIRTY(tb->objGen[u], nbitID);
+ }
+ if (CHECKDIRTY(tb->eyeGen[u], bitID))
+ {
+ if (fromCtx->texture.curTextureUnit != u) {
+ diff_api.ActiveTextureARB( u + GL_TEXTURE0_ARB );
+ fromCtx->texture.curTextureUnit = u;
+ }
+ if (fromCtx->transform.matrixMode != GL_MODELVIEW) {
+ diff_api.MatrixMode(GL_MODELVIEW);
+ fromCtx->transform.matrixMode = GL_MODELVIEW;
+ }
+ diff_api.PushMatrix();
+ diff_api.LoadIdentity();
+ if (from->unit[u].eyeSCoeff.x != to->unit[u].eyeSCoeff.x ||
+ from->unit[u].eyeSCoeff.y != to->unit[u].eyeSCoeff.y ||
+ from->unit[u].eyeSCoeff.z != to->unit[u].eyeSCoeff.z ||
+ from->unit[u].eyeSCoeff.w != to->unit[u].eyeSCoeff.w)
+ {
+ GLfloat f[4];
+ f[0] = to->unit[u].eyeSCoeff.x;
+ f[1] = to->unit[u].eyeSCoeff.y;
+ f[2] = to->unit[u].eyeSCoeff.z;
+ f[3] = to->unit[u].eyeSCoeff.w;
+ diff_api.TexGenfv (GL_S, GL_EYE_PLANE, (const GLfloat *) f);
+ from->unit[u].eyeSCoeff = to->unit[u].eyeSCoeff;
+ }
+ if (from->unit[u].eyeTCoeff.x != to->unit[u].eyeTCoeff.x ||
+ from->unit[u].eyeTCoeff.y != to->unit[u].eyeTCoeff.y ||
+ from->unit[u].eyeTCoeff.z != to->unit[u].eyeTCoeff.z ||
+ from->unit[u].eyeTCoeff.w != to->unit[u].eyeTCoeff.w)
+ {
+ GLfloat f[4];
+ f[0] = to->unit[u].eyeTCoeff.x;
+ f[1] = to->unit[u].eyeTCoeff.y;
+ f[2] = to->unit[u].eyeTCoeff.z;
+ f[3] = to->unit[u].eyeTCoeff.w;
+ diff_api.TexGenfv (GL_T, GL_EYE_PLANE, (const GLfloat *) f);
+ from->unit[u].eyeTCoeff = to->unit[u].eyeTCoeff;
+ }
+ if (from->unit[u].eyeRCoeff.x != to->unit[u].eyeRCoeff.x ||
+ from->unit[u].eyeRCoeff.y != to->unit[u].eyeRCoeff.y ||
+ from->unit[u].eyeRCoeff.z != to->unit[u].eyeRCoeff.z ||
+ from->unit[u].eyeRCoeff.w != to->unit[u].eyeRCoeff.w)
+ {
+ GLfloat f[4];
+ f[0] = to->unit[u].eyeRCoeff.x;
+ f[1] = to->unit[u].eyeRCoeff.y;
+ f[2] = to->unit[u].eyeRCoeff.z;
+ f[3] = to->unit[u].eyeRCoeff.w;
+ diff_api.TexGenfv (GL_R, GL_EYE_PLANE, (const GLfloat *) f);
+ from->unit[u].eyeRCoeff = to->unit[u].eyeRCoeff;
+ }
+ if (from->unit[u].eyeQCoeff.x != to->unit[u].eyeQCoeff.x ||
+ from->unit[u].eyeQCoeff.y != to->unit[u].eyeQCoeff.y ||
+ from->unit[u].eyeQCoeff.z != to->unit[u].eyeQCoeff.z ||
+ from->unit[u].eyeQCoeff.w != to->unit[u].eyeQCoeff.w)
+ {
+ GLfloat f[4];
+ f[0] = to->unit[u].eyeQCoeff.x;
+ f[1] = to->unit[u].eyeQCoeff.y;
+ f[2] = to->unit[u].eyeQCoeff.z;
+ f[3] = to->unit[u].eyeQCoeff.w;
+ diff_api.TexGenfv (GL_Q, GL_EYE_PLANE, (const GLfloat *) f);
+ from->unit[u].eyeQCoeff = to->unit[u].eyeQCoeff;
+ }
+ diff_api.PopMatrix();
+ CLEARDIRTY(tb->eyeGen[u], nbitID);
+ }
+ if (CHECKDIRTY(tb->genMode[u], bitID))
+ {
+ if (fromCtx->texture.curTextureUnit != u) {
+ diff_api.ActiveTextureARB( u + GL_TEXTURE0_ARB );
+ fromCtx->texture.curTextureUnit = u;
+ }
+ if (from->unit[u].gen.s != to->unit[u].gen.s ||
+ from->unit[u].gen.t != to->unit[u].gen.t ||
+ from->unit[u].gen.r != to->unit[u].gen.r ||
+ from->unit[u].gen.q != to->unit[u].gen.q)
+ {
+ diff_api.TexGeni (GL_S, GL_TEXTURE_GEN_MODE, to->unit[u].gen.s);
+ diff_api.TexGeni (GL_T, GL_TEXTURE_GEN_MODE, to->unit[u].gen.t);
+ diff_api.TexGeni (GL_R, GL_TEXTURE_GEN_MODE, to->unit[u].gen.r);
+ diff_api.TexGeni (GL_Q, GL_TEXTURE_GEN_MODE, to->unit[u].gen.q);
+ from->unit[u].gen = to->unit[u].gen;
+ }
+ CLEARDIRTY(tb->genMode[u], nbitID);
+ }
+
+ /* Texture enviroment */
+ if (CHECKDIRTY(tb->envBit[u], bitID))
+ {
+ if (from->unit[u].envMode != to->unit[u].envMode)
+ {
+ diff_api.TexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, to->unit[u].envMode);
+ from->unit[u].envMode = to->unit[u].envMode;
+ }
+ if (from->unit[u].envColor.r != to->unit[u].envColor.r ||
+ from->unit[u].envColor.g != to->unit[u].envColor.g ||
+ from->unit[u].envColor.b != to->unit[u].envColor.b ||
+ from->unit[u].envColor.a != to->unit[u].envColor.a)
+ {
+ GLfloat f[4];
+ f[0] = to->unit[u].envColor.r;
+ f[1] = to->unit[u].envColor.g;
+ f[2] = to->unit[u].envColor.b;
+ f[3] = to->unit[u].envColor.a;
+ diff_api.TexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, (const GLfloat *) f);
+ from->unit[u].envColor = to->unit[u].envColor;
+ }
+#ifdef CR_ARB_texture_env_combine
+ if (from->unit[u].combineModeRGB != to->unit[u].combineModeRGB)
+ {
+ diff_api.TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, to->unit[u].combineModeRGB);
+ from->unit[u].combineModeRGB = to->unit[u].combineModeRGB;
+ }
+ if (from->unit[u].combineModeA != to->unit[u].combineModeA)
+ {
+ diff_api.TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, to->unit[u].combineModeA);
+ from->unit[u].combineModeA = to->unit[u].combineModeA;
+ }
+ if (from->unit[u].combineSourceRGB[0] != to->unit[u].combineSourceRGB[0])
+ {
+ diff_api.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, to->unit[u].combineSourceRGB[0]);
+ from->unit[u].combineSourceRGB[0] = to->unit[u].combineSourceRGB[0];
+ }
+ if (from->unit[u].combineSourceRGB[1] != to->unit[u].combineSourceRGB[1])
+ {
+ diff_api.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, to->unit[u].combineSourceRGB[1]);
+ from->unit[u].combineSourceRGB[1] = to->unit[u].combineSourceRGB[1];
+ }
+ if (from->unit[u].combineSourceRGB[2] != to->unit[u].combineSourceRGB[2])
+ {
+ diff_api.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, to->unit[u].combineSourceRGB[2]);
+ from->unit[u].combineSourceRGB[2] = to->unit[u].combineSourceRGB[2];
+ }
+ if (from->unit[u].combineSourceA[0] != to->unit[u].combineSourceA[0])
+ {
+ diff_api.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, to->unit[u].combineSourceA[0]);
+ from->unit[u].combineSourceA[0] = to->unit[u].combineSourceA[0];
+ }
+ if (from->unit[u].combineSourceA[1] != to->unit[u].combineSourceA[1])
+ {
+ diff_api.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, to->unit[u].combineSourceA[1]);
+ from->unit[u].combineSourceA[1] = to->unit[u].combineSourceA[1];
+ }
+ if (from->unit[u].combineSourceA[2] != to->unit[u].combineSourceA[2])
+ {
+ diff_api.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, to->unit[u].combineSourceA[2]);
+ from->unit[u].combineSourceA[2] = to->unit[u].combineSourceA[2];
+ }
+ if (from->unit[u].combineOperandRGB[0] != to->unit[u].combineOperandRGB[0])
+ {
+ diff_api.TexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, to->unit[u].combineOperandRGB[0]);
+ from->unit[u].combineOperandRGB[0] = to->unit[u].combineOperandRGB[0];
+ }
+ if (from->unit[u].combineOperandRGB[1] != to->unit[u].combineOperandRGB[1])
+ {
+ diff_api.TexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, to->unit[u].combineOperandRGB[1]);
+ from->unit[u].combineOperandRGB[1] = to->unit[u].combineOperandRGB[1];
+ }
+ if (from->unit[u].combineOperandRGB[2] != to->unit[u].combineOperandRGB[2])
+ {
+ diff_api.TexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, to->unit[u].combineOperandRGB[2]);
+ from->unit[u].combineOperandRGB[2] = to->unit[u].combineOperandRGB[2];
+ }
+ if (from->unit[u].combineOperandA[0] != to->unit[u].combineOperandA[0])
+ {
+ diff_api.TexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, to->unit[u].combineOperandA[0]);
+ from->unit[u].combineOperandA[0] = to->unit[u].combineOperandA[0];
+ }
+ if (from->unit[u].combineOperandA[1] != to->unit[u].combineOperandA[1])
+ {
+ diff_api.TexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, to->unit[u].combineOperandA[1]);
+ from->unit[u].combineOperandA[1] = to->unit[u].combineOperandA[1];
+ }
+ if (from->unit[u].combineOperandA[2] != to->unit[u].combineOperandA[2])
+ {
+ diff_api.TexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, to->unit[u].combineOperandA[2]);
+ from->unit[u].combineOperandA[2] = to->unit[u].combineOperandA[2];
+ }
+ if (from->unit[u].combineScaleRGB != to->unit[u].combineScaleRGB)
+ {
+ diff_api.TexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, to->unit[u].combineScaleRGB);
+ from->unit[u].combineScaleRGB = to->unit[u].combineScaleRGB;
+ }
+ if (from->unit[u].combineScaleA != to->unit[u].combineScaleA)
+ {
+ diff_api.TexEnvf(GL_TEXTURE_ENV, GL_ALPHA_SCALE, to->unit[u].combineScaleA);
+ from->unit[u].combineScaleA = to->unit[u].combineScaleA;
+ }
+#endif
+#if CR_EXT_texture_lod_bias
+ if (from->unit[u].lodBias != to->unit[u].lodBias)
+ {
+ diff_api.TexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, to->unit[u].lodBias);
+ from->unit[u].lodBias = to->unit[u].lodBias;
+ }
+#endif
+ CLEARDIRTY(tb->envBit[u], nbitID);
+ }
+
+ /* loop over texture targets */
+ for (t = 0; t < 5; t++)
+ {
+ tobj = NULL;
+
+ switch (t) {
+ case 0:
+ if (to->unit[u].enabled1D || haveFragProg) {
+ tobj = to->unit[u].currentTexture1D;
+ fromBinding = &(from->unit[u].currentTexture1D);
+ }
+ break;
+ case 1:
+ if (to->unit[u].enabled2D || haveFragProg) {
+ tobj = to->unit[u].currentTexture2D;
+ fromBinding = &(from->unit[u].currentTexture2D);
+ }
+ break;
+#ifdef CR_OPENGL_VERSION_1_2
+ case 2:
+ if (to->unit[u].enabled3D || haveFragProg) {
+ tobj = to->unit[u].currentTexture3D;
+ fromBinding = &(from->unit[u].currentTexture3D);
+ }
+ break;
+#endif
+#ifdef CR_ARB_texture_cube_map
+ case 3:
+ if (fromCtx->extensions.ARB_texture_cube_map &&
+ (to->unit[u].enabledCubeMap || haveFragProg)) {
+ tobj = to->unit[u].currentTextureCubeMap;
+ fromBinding = &(from->unit[u].currentTextureCubeMap);
+ }
+ break;
+#endif
+#ifdef CR_NV_texture_rectangle
+ case 4:
+ if (fromCtx->extensions.NV_texture_rectangle &&
+ (to->unit[u].enabledRect || haveFragProg)) {
+ tobj = to->unit[u].currentTextureRect;
+ fromBinding = &(from->unit[u].currentTextureRect);
+ }
+ break;
+#endif
+ default:
+ /* maybe don't support cube maps or rects */
+ continue;
+ }
+
+ if (!tobj) {
+ continue; /* with next target */
+ }
+
+ /* Activate texture unit u if needed */
+ if (fromCtx->texture.curTextureUnit != u) {
+ diff_api.ActiveTextureARB( GL_TEXTURE0_ARB + u);
+ fromCtx->texture.curTextureUnit = u;
+ }
+
+ /* bind this texture if needed */
+ if (CHECKDIRTY(tb->current[u], bitID))
+ {
+ if (*fromBinding != tobj)
+ {
+ diff_api.BindTexture(tobj->target, crStateGetTextureObjHWID(tobj));
+ *fromBinding = tobj;
+ }
+ }
+
+ /* now, if the texture object is dirty */
+ if (CHECKDIRTY(tobj->dirty, bitID))
+ {
+ crStateTextureObjectDiff(fromCtx, bitID, nbitID, tobj, GL_FALSE);
+ }
+ CLEARDIRTY(tobj->dirty, nbitID);
+
+ } /* loop over targets */
+
+ CLEARDIRTY(tb->current[u], nbitID);
+
+ } /* loop over units */
+
+ /* After possible fiddling with the active unit, put it back now */
+ if (fromCtx->texture.curTextureUnit != toCtx->texture.curTextureUnit) {
+ diff_api.ActiveTextureARB( toCtx->texture.curTextureUnit + GL_TEXTURE0_ARB );
+ fromCtx->texture.curTextureUnit = toCtx->texture.curTextureUnit;
+ }
+ if (fromCtx->transform.matrixMode != toCtx->transform.matrixMode) {
+ diff_api.MatrixMode(toCtx->transform.matrixMode);
+ fromCtx->transform.matrixMode = toCtx->transform.matrixMode;
+ }
+
+ CLEARDIRTY(tb->dirty, nbitID);
+}
+
+
+
+struct callback_info
+{
+ CRbitvalue *bitID, *nbitID;
+ CRContext *g;
+ GLboolean bForceUpdate;
+};
+
+
+/* Called by crHashtableWalk() below */
+static void
+DiffTextureObjectCallback( unsigned long key, void *texObj , void *cbData)
+{
+ struct callback_info *info = (struct callback_info *) cbData;
+ CRTextureObj *tobj = (CRTextureObj *) texObj;
+ (void)key;
+
+ /*
+ printf(" Checking %d 0x%x bitid=0x%x\n",tobj->name, tobj->dirty[0], info->bitID[0]);
+ */
+ if (info->bForceUpdate || CHECKDIRTY(tobj->dirty, info->bitID)) {
+ /*
+ printf(" Found Dirty! %d\n", tobj->name);
+ */
+ crStateTextureObjectDiff(info->g, info->bitID, info->nbitID, tobj, info->bForceUpdate);
+ CLEARDIRTY(tobj->dirty, info->nbitID);
+ }
+}
+
+
+/*
+ * This isn't used right now, but will be used in the future to fix some
+ * potential display list problems. Specifically, if glBindTexture is
+ * in a display list, we have to be sure that all outstanding texture object
+ * updates are resolved before the list is called. If we don't, we may
+ * wind up binding texture objects that are stale.
+ */
+void
+crStateDiffAllTextureObjects( CRContext *g, CRbitvalue *bitID, GLboolean bForceUpdate )
+{
+ CRbitvalue nbitID[CR_MAX_BITARRAY];
+ struct callback_info info;
+ int j;
+ int origUnit, orig1D, orig2D, orig3D, origCube, origRect;
+
+ for (j = 0; j < CR_MAX_BITARRAY; j++)
+ nbitID[j] = ~bitID[j];
+
+ info.bitID = bitID;
+ info.nbitID = nbitID;
+ info.g = g;
+ info.bForceUpdate = bForceUpdate;
+
+ /* save current texture bindings */
+ origUnit = g->texture.curTextureUnit;
+ orig1D = crStateGetTextureObjHWID(g->texture.unit[0].currentTexture1D);
+ orig2D = crStateGetTextureObjHWID(g->texture.unit[0].currentTexture2D);
+ orig3D = crStateGetTextureObjHWID(g->texture.unit[0].currentTexture3D);
+#ifdef CR_ARB_texture_cube_map
+ origCube = crStateGetTextureObjHWID(g->texture.unit[0].currentTextureCubeMap);
+#endif
+#ifdef CR_NV_texture_rectangle
+ origRect = crStateGetTextureObjHWID(g->texture.unit[0].currentTextureRect);
+#endif
+
+ /* use texture unit 0 for updates */
+ diff_api.ActiveTextureARB(GL_TEXTURE0_ARB);
+
+ /* diff all the textures */
+ crHashtableWalk(g->shared->textureTable, DiffTextureObjectCallback, (void *) &info);
+
+ /* default ones */
+ crStateTextureObjectDiff(g, bitID, nbitID, &g->texture.base1D, GL_TRUE);
+ crStateTextureObjectDiff(g, bitID, nbitID, &g->texture.base2D, GL_TRUE);
+ crStateTextureObjectDiff(g, bitID, nbitID, &g->texture.base3D, GL_TRUE);
+ crStateTextureObjectDiff(g, bitID, nbitID, &g->texture.proxy1D, GL_TRUE);
+ crStateTextureObjectDiff(g, bitID, nbitID, &g->texture.proxy2D, GL_TRUE);
+ crStateTextureObjectDiff(g, bitID, nbitID, &g->texture.proxy3D, GL_TRUE);
+#ifdef CR_ARB_texture_cube_map
+ crStateTextureObjectDiff(g, bitID, nbitID, &g->texture.baseCubeMap, GL_TRUE);
+ crStateTextureObjectDiff(g, bitID, nbitID, &g->texture.proxyCubeMap, GL_TRUE);
+#endif
+#ifdef CR_NV_texture_rectangle
+ if (g->extensions.NV_texture_rectangle)
+ {
+ crStateTextureObjectDiff(g, bitID, nbitID, &g->texture.baseRect, GL_TRUE);
+ crStateTextureObjectDiff(g, bitID, nbitID, &g->texture.proxyRect, GL_TRUE);
+ }
+#endif
+
+ /* restore bindings */
+ /* 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);
+#ifdef CR_ARB_texture_cube_map
+ diff_api.BindTexture(GL_TEXTURE_CUBE_MAP_ARB, origCube);
+#endif
+#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
new file mode 100644
index 00000000..295ea36f
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_teximage.c
@@ -0,0 +1,1762 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+
+#include "state.h"
+#include "state/cr_statetypes.h"
+#include "state/cr_texture.h"
+#include "cr_pixeldata.h"
+#include "cr_string.h"
+#include "cr_mem.h"
+#include "cr_version.h"
+#include "state_internals.h"
+
+#ifndef IN_GUEST
+/*# define CR_DUMP_TEXTURES_2D*/
+#endif
+
+#ifdef CR_DUMP_TEXTURES_2D
+static int _tnum = 0;
+
+#pragma pack(1)
+typedef struct tgaheader_tag
+{
+ char idlen;
+
+ char colormap;
+
+ char imagetype;
+
+ short cm_index;
+ short cm_len;
+ char cm_entrysize;
+
+ short x, y, w, h;
+ char depth;
+ char imagedesc;
+
+} tgaheader_t;
+#pragma pack()
+
+static crDumpTGA(short w, short h, char* data)
+{
+ char fname[200];
+ tgaheader_t header;
+ FILE *out;
+
+ if (!w || !h) return;
+
+ sprintf(fname, "tex%i.tga", _tnum++);
+ out = fopen(fname, "w");
+ if (!out) crError("can't create %s!", fname);
+
+ header.idlen = 0;
+ header.colormap = 0;
+ header.imagetype = 2;
+ header.cm_index = 0;
+ header.cm_len = 0;
+ header.cm_entrysize = 0;
+ header.x = 0;
+ header.y = 0;
+ header.w = w;
+ header.h = h;
+ header.depth = 32;
+ header.imagedesc = 0x08;
+ fwrite(&header, sizeof(header), 1, out);
+
+ fwrite(data, w*h*4, 1, out);
+
+ fclose(out);
+}
+#endif
+
+
+static int
+bitcount(int value)
+{
+ int bits = 0;
+ for (; value > 0; value >>= 1) {
+ if (value & 0x1)
+ bits++;
+ }
+ return bits;
+}
+
+
+/**
+ * Return 1 if the target is a proxy target, 0 otherwise.
+ */
+static GLboolean
+IsProxyTarget(GLenum target)
+{
+ return (target == GL_PROXY_TEXTURE_1D ||
+ target == GL_PROXY_TEXTURE_2D ||
+ target == GL_PROXY_TEXTURE_3D ||
+ target == GL_PROXY_TEXTURE_RECTANGLE_NV ||
+ target == GL_PROXY_TEXTURE_CUBE_MAP);
+}
+
+
+/**
+ * Test if a texture width, height or depth is legal.
+ * It must be true that 0 <= size <= max.
+ * Furthermore, if the ARB_texture_non_power_of_two extension isn't
+ * present, size must also be a power of two.
+ */
+static GLboolean
+isLegalSize(CRContext *g, GLsizei size, GLsizei max)
+{
+ if (size < 0 || size > max)
+ return GL_FALSE;
+ if (!g->extensions.ARB_texture_non_power_of_two) {
+ /* check for power of two */
+ if (size > 0 && bitcount(size) != 1)
+ return GL_FALSE;
+ }
+ return GL_TRUE;
+}
+
+
+/**
+ * Return the max legal texture level parameter for the given target.
+ */
+static GLint
+MaxTextureLevel(CRContext *g, GLenum target)
+{
+ CRTextureState *t = &(g->texture);
+ switch (target) {
+ case GL_TEXTURE_1D:
+ case GL_PROXY_TEXTURE_1D:
+ case GL_TEXTURE_2D:
+ case GL_PROXY_TEXTURE_2D:
+ return t->maxLevel;
+ case GL_TEXTURE_3D:
+ case GL_PROXY_TEXTURE_3D:
+ return t->max3DLevel;
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
+ case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
+ return t->maxCubeMapLevel;
+ case GL_TEXTURE_RECTANGLE_NV:
+ case GL_PROXY_TEXTURE_RECTANGLE_NV:
+ return t->maxRectLevel;
+ default:
+ return 0;
+ }
+}
+
+
+/**
+ * If GL_GENERATE_MIPMAP_SGIS is true and we modify the base level texture
+ * image we have to finish the mipmap.
+ * All we really have to do is fill in the width/height/format/etc for the
+ * remaining image levels. The image data doesn't matter here - the back-
+ * end OpenGL library will fill those in.
+ */
+static void
+generate_mipmap(CRTextureObj *tobj, GLenum target)
+{
+ CRTextureLevel *levels;
+ GLint level, width, height, depth;
+
+ if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
+ target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
+ levels = tobj->level[target - GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB];
+ }
+ else {
+ levels = tobj->level[0];
+ }
+
+ width = levels[tobj->baseLevel].width;
+ height = levels[tobj->baseLevel].height;
+ depth = levels[tobj->baseLevel].depth;
+
+ for (level = tobj->baseLevel + 1; level <= tobj->maxLevel; level++)
+ {
+ if (width > 1)
+ width /= 2;
+ if (height > 1)
+ height /= 2;
+ if (depth > 1)
+ depth /= 2;
+ levels[level].width = width;
+ levels[level].height = height;
+ levels[level].depth = depth;
+ levels[level].internalFormat = levels[tobj->baseLevel].internalFormat;
+ levels[level].format = levels[tobj->baseLevel].format;
+ levels[level].type = levels[tobj->baseLevel].type;
+#ifdef CR_ARB_texture_compression
+ levels[level].compressed = levels[tobj->baseLevel].compressed;
+#endif
+ levels[level].texFormat = levels[tobj->baseLevel].texFormat;
+ if (width == 1 && height == 1 && depth == 1)
+ break;
+ }
+
+ /* Set this flag so when we do the state diff, we enable GENERATE_MIPMAP
+ * prior to calling diff.TexImage().
+ */
+ levels[tobj->baseLevel].generateMipmap = GL_TRUE;
+}
+
+
+/**
+ * Given a texture target and level, return pointers to the corresponding
+ * texture object and texture image level.
+ */
+void
+crStateGetTextureObjectAndImage(CRContext *g, GLenum texTarget, GLint level,
+ CRTextureObj **obj, CRTextureLevel **img)
+{
+ CRTextureState *t = &(g->texture);
+ CRTextureUnit *unit = t->unit + t->curTextureUnit;
+
+ switch (texTarget) {
+ case GL_TEXTURE_1D:
+ *obj = unit->currentTexture1D;
+ *img = unit->currentTexture1D->level[0] + level;
+ return;
+ case GL_PROXY_TEXTURE_1D:
+ *obj = &(t->proxy1D);
+ *img = t->proxy1D.level[0] + level;
+ return;
+ case GL_TEXTURE_2D:
+ *obj = unit->currentTexture2D;
+ *img = unit->currentTexture2D->level[0] + level;
+ return;
+ case GL_PROXY_TEXTURE_2D:
+ *obj = &(t->proxy2D);
+ *img = t->proxy2D.level[0] + level;
+ return;
+ case GL_TEXTURE_3D:
+ *obj = unit->currentTexture3D;
+ *img = unit->currentTexture3D->level[0] + level;
+ return;
+ case GL_PROXY_TEXTURE_3D:
+ *obj = &(t->proxy3D);
+ *img = t->proxy3D.level[0] + level;
+ return;
+ default:
+ /* fall-through */
+ ;
+ }
+
+#ifdef CR_NV_texture_rectangle
+ if (g->extensions.NV_texture_rectangle) {
+ switch (texTarget) {
+ case GL_PROXY_TEXTURE_RECTANGLE_NV:
+ *obj = &(t->proxyRect);
+ *img = t->proxyRect.level[0] + level;
+ return;
+ case GL_TEXTURE_RECTANGLE_NV:
+ *obj = unit->currentTextureRect;
+ *img = unit->currentTextureRect->level[0] + level;
+ return;
+ default:
+ /* fall-through */
+ ;
+ }
+ }
+#endif
+
+#ifdef CR_ARB_texture_cube_map
+ if (g->extensions.ARB_texture_cube_map) {
+ switch (texTarget) {
+ case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
+ *obj = &(t->proxyCubeMap);
+ *img = t->proxyCubeMap.level[0] + level;
+ return;
+ case GL_TEXTURE_CUBE_MAP_ARB:
+ *obj = unit->currentTextureCubeMap;
+ *img = NULL;
+ return;
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
+ *obj = unit->currentTextureCubeMap;
+ *img = unit->currentTextureCubeMap->level[0] + level;
+ return;
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
+ *obj = unit->currentTextureCubeMap;
+ *img = unit->currentTextureCubeMap->level[1] + level;
+ return;
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
+ *obj = unit->currentTextureCubeMap;
+ *img = unit->currentTextureCubeMap->level[2] + level;
+ return;
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
+ *obj = unit->currentTextureCubeMap;
+ *img = unit->currentTextureCubeMap->level[3] + level;
+ return;
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
+ *obj = unit->currentTextureCubeMap;
+ *img = unit->currentTextureCubeMap->level[4] + level;
+ return;
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
+ *obj = unit->currentTextureCubeMap;
+ *img = unit->currentTextureCubeMap->level[5] + level;
+ return;
+ default:
+ /* fall-through */
+ ;
+ }
+ }
+#endif
+
+ crWarning("unexpected texTarget 0x%x", texTarget);
+ *obj = NULL;
+ *img = NULL;
+}
+
+
+/**
+ * Do parameter error checking for glTexImagexD functions.
+ * We'll call crStateError if we detect any errors, unless it's a proxy target.
+ * Return GL_TRUE if any errors, GL_FALSE if no errors.
+ */
+static GLboolean
+ErrorCheckTexImage(GLuint dims, GLenum target, GLint level,
+ GLsizei width, GLsizei height, GLsizei depth, GLint border)
+{
+ CRContext *g = GetCurrentContext();
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glTexImage%uD called in Begin/End", dims);
+ return GL_TRUE;
+ }
+
+ /*
+ * Test target
+ */
+ switch (target)
+ {
+ case GL_TEXTURE_1D:
+ case GL_PROXY_TEXTURE_1D:
+ if (dims != 1) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glTexImage(invalid target=0x%x)", target);
+ return GL_TRUE;
+ }
+ break;
+ case GL_TEXTURE_2D:
+ case GL_PROXY_TEXTURE_2D:
+ if (dims != 2) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glTexImage(invalid target=0x%x)", target);
+ return GL_TRUE;
+ }
+ break;
+ case GL_TEXTURE_3D:
+ case GL_PROXY_TEXTURE_3D:
+ if (dims != 3) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glTexImage(invalid target=0x%x)", target);
+ return GL_TRUE;
+ }
+ break;
+#ifdef CR_NV_texture_rectangle
+ case GL_TEXTURE_RECTANGLE_NV:
+ case GL_PROXY_TEXTURE_RECTANGLE_NV:
+ if (dims != 2 || !g->extensions.NV_texture_rectangle) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glTexImage2D(invalid target=0x%x)", target);
+ return GL_TRUE;
+ }
+ break;
+#endif
+#ifdef CR_ARB_texture_cube_map
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
+ case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
+ if (dims != 2 || !g->extensions.ARB_texture_cube_map) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glTexImage2D(invalid target=0x%x)", target);
+ return GL_TRUE;
+ }
+ break;
+#endif
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glTexImage%uD(invalid target=0x%x)", dims, target);
+ return GL_TRUE;
+ }
+
+ /*
+ * Test level
+ */
+ if (level < 0 || level > MaxTextureLevel(g, target)) {
+ if (!IsProxyTarget(target))
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glTexImage%uD(level=%d)", dims, level);
+ return GL_TRUE;
+ }
+
+ /*
+ * Test border
+ */
+ if (border != 0 && border != 1) {
+ if (!IsProxyTarget(target))
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glTexImage%uD(border=%d)", dims, border);
+ return GL_TRUE;
+ }
+
+ if ((target == GL_PROXY_TEXTURE_RECTANGLE_NV ||
+ target == GL_TEXTURE_RECTANGLE_NV) && border != 0) {
+ if (!IsProxyTarget(target))
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glTexImage2D(border=%d)", border);
+ return GL_TRUE;
+ }
+
+ /*
+ * Test width, height, depth
+ */
+ if (target == GL_PROXY_TEXTURE_1D || target == GL_TEXTURE_1D) {
+ if (!isLegalSize(g, width - 2 * border, g->limits.maxTextureSize)) {
+ if (!IsProxyTarget(target))
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glTexImage1D(width=%d)", width);
+ return GL_TRUE;
+ }
+ }
+ else if (target == GL_PROXY_TEXTURE_2D || target == GL_TEXTURE_2D) {
+ if (!isLegalSize(g, width - 2 * border, g->limits.maxTextureSize) ||
+ !isLegalSize(g, height - 2 * border, g->limits.maxTextureSize)) {
+ if (!IsProxyTarget(target))
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glTexImage2D(width=%d, height=%d)", width, height);
+ return GL_TRUE;
+ }
+ }
+ else if (target == GL_PROXY_TEXTURE_3D || target == GL_TEXTURE_3D) {
+ if (!isLegalSize(g, width - 2 * border, g->limits.max3DTextureSize) ||
+ !isLegalSize(g, height - 2 * border, g->limits.max3DTextureSize) ||
+ !isLegalSize(g, depth - 2 * border, g->limits.max3DTextureSize)) {
+ if (!IsProxyTarget(target))
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glTexImage3D(width=%d, height=%d, depth=%d)",
+ width, height, depth);
+ return GL_TRUE;
+ }
+ }
+ else if (target == GL_PROXY_TEXTURE_RECTANGLE_NV ||
+ target == GL_TEXTURE_RECTANGLE_NV) {
+ if (width < 0 || width > (int) g->limits.maxRectTextureSize ||
+ height < 0 || height > (int) g->limits.maxRectTextureSize) {
+ if (!IsProxyTarget(target))
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glTexImage2D(width=%d, height=%d)", width, height);
+ return GL_TRUE;
+ }
+ }
+ else {
+ /* cube map */
+ if (!isLegalSize(g, width - 2*border, g->limits.maxCubeMapTextureSize) ||
+ !isLegalSize(g, height - 2*border, g->limits.maxCubeMapTextureSize) ||
+ width != height) {
+ if (!IsProxyTarget(target))
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glTexImage2D(width=%d, height=%d)", width, height);
+ return GL_TRUE;
+ }
+ }
+
+ /* OK, no errors */
+ return GL_FALSE;
+}
+
+
+/**
+ * Do error check for glTexSubImage() functions.
+ * We'll call crStateError if we detect any errors.
+ * Return GL_TRUE if any errors, GL_FALSE if no errors.
+ */
+static GLboolean
+ErrorCheckTexSubImage(GLuint dims, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height, GLsizei depth)
+{
+ CRContext *g = GetCurrentContext();
+ CRTextureObj *tobj;
+ CRTextureLevel *tl;
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glTexSubImage%uD called in Begin/End", dims);
+ return GL_TRUE;
+ }
+
+ if (dims == 1) {
+ if (target != GL_TEXTURE_1D) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glTexSubImage1D(target=0x%x)", target);
+ return GL_TRUE;
+ }
+ }
+ else if (dims == 2) {
+ if (target != GL_TEXTURE_2D &&
+ target != GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
+ target != GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB &&
+ target != GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB &&
+ target != GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB &&
+ target != GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB &&
+ target != GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB &&
+ target != GL_TEXTURE_RECTANGLE_NV) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glTexSubImage2D(target=0x%x)", target);
+ return GL_TRUE;
+ }
+ }
+ else if (dims == 3) {
+ if (target != GL_TEXTURE_3D) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glTexSubImage3D(target=0x%x)", target);
+ return GL_TRUE;
+ }
+ }
+
+ /* test level */
+ if (level < 0 || level > MaxTextureLevel(g, target)) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glTexSubImage%uD(level=%d)", dims, level);
+ return GL_TRUE;
+ }
+
+ crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl);
+ if (!tobj || !tl) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glTexSubImage%uD(target or level)", dims);
+ return GL_TRUE;
+ }
+
+ /* test x/y/zoffset and size */
+ if (xoffset < -tl->border || xoffset + width > tl->width) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glTexSubImage%uD(xoffset=%d + width=%d > %d)",
+ dims, xoffset, width, tl->width);
+ return GL_TRUE;
+ }
+ if (dims > 1 && (yoffset < -tl->border || yoffset + height > tl->height)) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glTexSubImage%uD(yoffset=%d + height=%d > %d)",
+ dims, yoffset, height, tl->height);
+ return GL_TRUE;
+ }
+ if (dims > 2 && (zoffset < -tl->border || zoffset + depth > tl->depth)) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glTexSubImage%uD(zoffset=%d and/or depth=%d)",
+ dims, zoffset, depth);
+ return GL_TRUE;
+ }
+
+ /* OK, no errors */
+ return GL_FALSE;
+}
+
+
+
+void STATE_APIENTRY
+crStateTexImage1D(GLenum target, GLint level, GLint internalFormat,
+ GLsizei width, GLint border, GLenum format,
+ GLenum type, const GLvoid * pixels)
+{
+ CRContext *g = GetCurrentContext();
+ CRTextureState *t = &(g->texture);
+#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
+ CRClientState *c = &(g->client);
+#endif
+ CRTextureObj *tobj;
+ CRTextureLevel *tl;
+ CRStateBits *sb = GetCurrentBits();
+ CRTextureBits *tb = &(sb->texture);
+#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
+ (void)pixels;
+#endif
+
+ FLUSH();
+
+ if (ErrorCheckTexImage(1, target, level, width, 1, 1, border)) {
+ if (IsProxyTarget(target)) {
+ /* clear all state, but don't generate error */
+ crStateTextureInitTextureObj(g, &(t->proxy1D), 0, GL_TEXTURE_1D);
+ }
+ else {
+ /* error was already recorded */
+ }
+ return;
+ }
+
+ crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl);
+ CRASSERT(tobj);
+ CRASSERT(tl);
+
+ if (IsProxyTarget(target))
+ tl->bytes = 0;
+ else
+ tl->bytes = crImageSize(format, type, width, 1);
+
+#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
+ if (tl->bytes)
+ {
+ /* this is not a proxy texture target so alloc storage */
+ if (tl->img)
+ crFree(tl->img);
+ tl->img = (GLubyte *) crAlloc(tl->bytes);
+ if (!tl->img)
+ {
+ crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY,
+ "glTexImage1D out of memory");
+ return;
+ }
+ if (pixels)
+ crPixelCopy1D((GLvoid *) tl->img, format, type,
+ pixels, format, type, width, &(c->unpack));
+ }
+#endif
+
+ tl->width = width;
+ tl->height = 1;
+ tl->depth = 1;
+ tl->format = format;
+ tl->border = border;
+ tl->internalFormat = internalFormat;
+ crStateTextureInitTextureFormat(tl, internalFormat);
+ tl->type = type;
+ tl->compressed = GL_FALSE;
+ if (width)
+ tl->bytesPerPixel = tl->bytes / width;
+ else
+ tl->bytesPerPixel = 0;
+
+#ifdef CR_SGIS_generate_mipmap
+ if (level == tobj->baseLevel && tobj->generateMipmap) {
+ generate_mipmap(tobj, target);
+ }
+ else {
+ tl->generateMipmap = GL_FALSE;
+ }
+#endif
+
+ /* XXX may need to do some fine-tuning here for proxy textures */
+ DIRTY(tobj->dirty, g->neg_bitid);
+ DIRTY(tobj->imageBit, g->neg_bitid);
+ DIRTY(tl->dirty, g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+}
+
+static void crStateNukeMipmaps(CRTextureObj *tobj)
+{
+ int i, face;
+
+ for (face = 0; face < 6; face++)
+ {
+ CRTextureLevel *levels = tobj->level[face];
+
+ if (levels)
+ {
+ for (i = 0; i < CR_MAX_MIPMAP_LEVELS; i++)
+ {
+ if (levels[i].img)
+ {
+ crFree(levels[i].img);
+ }
+ levels[i].img = NULL;
+ levels[i].bytes = 0;
+ levels[i].internalFormat = GL_ONE;
+ levels[i].format = GL_RGBA;
+ levels[i].type = GL_UNSIGNED_BYTE;
+
+ }
+ }
+ }
+}
+
+void STATE_APIENTRY
+crStateCopyTexImage2D(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
+{
+ CRContext *g = GetCurrentContext();
+ CRTextureObj *tobj = NULL;
+ CRTextureLevel *tl = NULL;
+ (void)x; (void)y;
+
+ crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl);
+ CRASSERT(tobj);
+ CRASSERT(tl);
+
+ if (tobj == NULL || tl == NULL)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "crStateCopyTexImage2D: invalid target: 0x%x", target);
+ return;
+ }
+
+ crStateNukeMipmaps(tobj);
+
+ tl->bytes = crImageSize(GL_RGBA, GL_UNSIGNED_BYTE, width, height);
+
+ tl->width = width;
+ tl->height = height;
+ tl->depth = 1;
+ tl->format = GL_RGBA;
+ tl->internalFormat = internalFormat;
+ crStateTextureInitTextureFormat(tl, internalFormat);
+ tl->border = border;
+ tl->type = GL_UNSIGNED_BYTE;
+ tl->compressed = GL_FALSE;
+ if (width && height)
+ {
+ tl->bytesPerPixel = tl->bytes / (width * height);
+ }
+ else
+ tl->bytesPerPixel = 0;
+
+#ifdef CR_SGIS_generate_mipmap
+ if (level == tobj->baseLevel && tobj->generateMipmap) {
+ generate_mipmap(tobj, target);
+ }
+ else {
+ tl->generateMipmap = GL_FALSE;
+ }
+#endif
+}
+
+void STATE_APIENTRY
+crStateTexImage2D(GLenum target, GLint level, GLint internalFormat,
+ GLsizei width, GLsizei height, GLint border,
+ GLenum format, GLenum type, const GLvoid * pixels)
+{
+ CRContext *g = GetCurrentContext();
+ CRTextureState *t = &(g->texture);
+#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
+ CRClientState *c = &(g->client);
+#endif
+ CRTextureObj *tobj = NULL;
+ CRTextureLevel *tl = NULL;
+ CRStateBits *sb = GetCurrentBits();
+ CRTextureBits *tb = &(sb->texture);
+ // Distributed textures are not used by VBox
+ const int is_distrib = 0; // ((type == GL_TRUE) || (type == GL_FALSE));
+
+ FLUSH();
+
+ /* NOTE: we skip parameter error checking if this is a distributed
+ * texture! The user better provide correct parameters!!!
+ */
+ if (!is_distrib
+ && ErrorCheckTexImage(2, target, level, width, height, 1, border)) {
+ if (IsProxyTarget(target)) {
+ /* clear all state, but don't generate error */
+ crStateTextureInitTextureObj(g, &(t->proxy2D), 0, GL_TEXTURE_2D);
+ }
+ else {
+ /* error was already recorded */
+ }
+ return;
+ }
+
+ crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl);
+ CRASSERT(tobj);
+ CRASSERT(tl);
+
+ if (level==tobj->baseLevel && (tl->width!=width || tl->height!=height))
+ {
+ crStateNukeMipmaps(tobj);
+ }
+
+ /* compute size of image buffer */
+ if (is_distrib) {
+ tl->bytes = crStrlen((char *) pixels) + 1;
+ tl->bytes += crImageSize(format, GL_UNSIGNED_BYTE, width, height);
+ }
+ else if (IsProxyTarget(target)) {
+ tl->bytes = 0;
+ }
+ else {
+ tl->bytes = crImageSize(format, type, width, height);
+ }
+
+#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
+ /* allocate the image buffer and fill it */
+ if (tl->bytes)
+ {
+ /* this is not a proxy texture target so alloc storage */
+ if (tl->img)
+ crFree(tl->img);
+ tl->img = (GLubyte *) crAlloc(tl->bytes);
+ if (!tl->img)
+ {
+ crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY,
+ "glTexImage2D out of memory");
+ return;
+ }
+ if (pixels)
+ {
+ if (is_distrib)
+ {
+ crMemcpy((void *) tl->img, (void *) pixels, tl->bytes);
+ }
+ else
+ {
+ crPixelCopy2D(width, height,
+ (GLvoid *) tl->img, format, type, NULL, /* dst */
+ pixels, format, type, &(c->unpack)); /* src */
+ }
+ }
+ }
+#endif
+
+ tl->width = width;
+ tl->height = height;
+ tl->depth = 1;
+ tl->format = format;
+ tl->internalFormat = internalFormat;
+ crStateTextureInitTextureFormat(tl, internalFormat);
+ tl->border = border;
+ tl->type = type;
+ tl->compressed = GL_FALSE;
+ if (width && height)
+ {
+ if (is_distrib)
+ tl->bytesPerPixel = 3; /* only support GL_RGB */
+ else
+ tl->bytesPerPixel = tl->bytes / (width * height);
+ }
+ else
+ tl->bytesPerPixel = 0;
+
+#ifdef CR_SGIS_generate_mipmap
+ if (level == tobj->baseLevel && tobj->generateMipmap) {
+ generate_mipmap(tobj, target);
+ }
+ else {
+ tl->generateMipmap = GL_FALSE;
+ }
+#endif
+
+ /* XXX may need to do some fine-tuning here for proxy textures */
+ DIRTY(tobj->dirty, g->neg_bitid);
+ DIRTY(tobj->imageBit, g->neg_bitid);
+ DIRTY(tl->dirty, g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+
+#ifdef CR_DUMP_TEXTURES_2D
+ if (pixels)
+ {
+ GLint w,h;
+ char *data;
+
+ diff_api.GetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &w);
+ diff_api.GetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &h);
+
+ data = crAlloc(w*h*4);
+ if (!data) crError("no memory!");
+ diff_api.GetTexImage(target, level, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ crDumpTGA(w, h, data);
+ crFree(data);
+ }
+#endif
+}
+
+#if defined( CR_OPENGL_VERSION_1_2 ) || defined( GL_EXT_texture3D )
+void STATE_APIENTRY
+crStateTexImage3D(GLenum target, GLint level,
+ GLint internalFormat,
+ GLsizei width, GLsizei height,
+ GLsizei depth, GLint border,
+ GLenum format, GLenum type, const GLvoid * pixels)
+{
+ CRContext *g = GetCurrentContext();
+ CRTextureState *t = &(g->texture);
+#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
+ CRClientState *c = &(g->client);
+#endif
+ CRTextureObj *tobj = NULL;
+ CRTextureLevel *tl = NULL;
+ CRStateBits *sb = GetCurrentBits();
+ CRTextureBits *tb = &(sb->texture);
+ (void)pixels;
+
+ FLUSH();
+
+ if (ErrorCheckTexImage(3, target, level, width, height, depth, border)) {
+ if (IsProxyTarget(target)) {
+ /* clear all state, but don't generate error */
+ crStateTextureInitTextureObj(g, &(t->proxy3D), 0, GL_TEXTURE_3D);
+ }
+ else {
+ /* error was already recorded */
+ }
+ return;
+ }
+
+ crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl);
+ CRASSERT(tobj);
+ CRASSERT(tl);
+
+ if (IsProxyTarget(target))
+ tl->bytes = 0;
+ else
+ tl->bytes = crTextureSize(format, type, width, height, depth);
+
+#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
+ if (tl->bytes)
+ {
+ /* this is not a proxy texture target so alloc storage */
+ if (tl->img)
+ crFree(tl->img);
+ tl->img = (GLubyte *) crAlloc(tl->bytes);
+ if (!tl->img)
+ {
+ crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY,
+ "glTexImage3D out of memory");
+ return;
+ }
+ if (pixels)
+ crPixelCopy3D(width, height, depth, (GLvoid *) (tl->img), format, type,
+ NULL, pixels, format, type, &(c->unpack));
+ }
+#endif
+
+ tl->internalFormat = internalFormat;
+ tl->border = border;
+ tl->width = width;
+ tl->height = height;
+ tl->depth = depth;
+ tl->format = format;
+ tl->type = type;
+ tl->compressed = GL_FALSE;
+
+#ifdef CR_SGIS_generate_mipmap
+ if (level == tobj->baseLevel && tobj->generateMipmap) {
+ generate_mipmap(tobj, target);
+ }
+ else {
+ tl->generateMipmap = GL_FALSE;
+ }
+#endif
+
+ /* XXX may need to do some fine-tuning here for proxy textures */
+ DIRTY(tobj->dirty, g->neg_bitid);
+ DIRTY(tobj->imageBit, g->neg_bitid);
+ DIRTY(tl->dirty, g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+}
+#endif /* CR_OPENGL_VERSION_1_2 || GL_EXT_texture3D */
+
+
+#ifdef GL_EXT_texture3D
+void STATE_APIENTRY
+crStateTexImage3DEXT(GLenum target, GLint level,
+ GLenum internalFormat,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLint border, GLenum format, GLenum type,
+ const GLvoid * pixels)
+{
+ crStateTexImage3D(target, level, (GLint) internalFormat, width, height,
+ depth, border, format, type, pixels);
+}
+#endif /* GL_EXT_texture3D */
+
+
+void STATE_APIENTRY
+crStateTexSubImage1D(GLenum target, GLint level, GLint xoffset,
+ GLsizei width, GLenum format,
+ GLenum type, const GLvoid * pixels)
+{
+ CRContext *g = GetCurrentContext();
+ CRTextureState *t = &(g->texture);
+#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
+ CRClientState *c = &(g->client);
+#endif
+ CRStateBits *sb = GetCurrentBits();
+ CRTextureBits *tb = &(sb->texture);
+ CRTextureUnit *unit = t->unit + t->curTextureUnit;
+ CRTextureObj *tobj = unit->currentTexture1D;
+ CRTextureLevel *tl = tobj->level[0] + level;
+ (void)format; (void)type; (void)pixels;
+
+ FLUSH();
+
+ if (ErrorCheckTexSubImage(1, target, level, xoffset, 0, 0,
+ width, 1, 1)) {
+ 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;
+
+ crPixelCopy1D((void *) (tl->img + xoffset * tl->bytesPerPixel),
+ tl->format, tl->type,
+ pixels, format, type, width, &(c->unpack));
+#endif
+
+#ifdef CR_SGIS_generate_mipmap
+ if (level == tobj->baseLevel && tobj->generateMipmap) {
+ generate_mipmap(tobj, target);
+ }
+ else {
+ tl->generateMipmap = GL_FALSE;
+ }
+#endif
+
+ DIRTY(tobj->dirty, g->neg_bitid);
+ DIRTY(tobj->imageBit, g->neg_bitid);
+ DIRTY(tl->dirty, g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+}
+
+
+void STATE_APIENTRY
+crStateTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type, const GLvoid * pixels)
+{
+ CRContext *g = GetCurrentContext();
+ CRStateBits *sb = GetCurrentBits();
+ CRTextureBits *tb = &(sb->texture);
+ CRTextureObj *tobj;
+ CRTextureLevel *tl;
+#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
+ CRClientState *c = &(g->client);
+ GLubyte *subimg = NULL;
+ GLubyte *img = NULL;
+ GLubyte *src;
+ int i;
+#endif
+ (void)format; (void)type; (void)pixels;
+
+ FLUSH();
+
+ if (ErrorCheckTexSubImage(2, target, level, xoffset, yoffset, 0,
+ width, height, 1)) {
+ return; /* GL error state already set */
+ }
+
+ crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl);
+ 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;
+
+ subimg = (GLubyte *) crAlloc(crImageSize(tl->format, tl->type, width, height));
+
+ crPixelCopy2D(width, height, subimg, tl->format, tl->type, NULL, /* dst */
+ pixels, format, type, &(c->unpack)); /* src */
+
+ img = tl->img +
+ xoffset * tl->bytesPerPixel + yoffset * tl->width * tl->bytesPerPixel;
+
+ src = subimg;
+
+ /* Copy the data into the texture */
+ for (i = 0; i < height; i++)
+ {
+ crMemcpy(img, src, tl->bytesPerPixel * width);
+ img += tl->width * tl->bytesPerPixel;
+ src += width * tl->bytesPerPixel;
+ }
+
+ crFree(subimg);
+#endif
+
+#ifdef CR_SGIS_generate_mipmap
+ if (level == tobj->baseLevel && tobj->generateMipmap) {
+ generate_mipmap(tobj, target);
+ }
+ else {
+ tl->generateMipmap = GL_FALSE;
+ }
+#endif
+
+ DIRTY(tobj->dirty, g->neg_bitid);
+ DIRTY(tobj->imageBit, g->neg_bitid);
+ DIRTY(tl->dirty, g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+
+#ifdef CR_DUMP_TEXTURES_2D
+ {
+ GLint w,h;
+ char *data;
+
+ diff_api.GetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &w);
+ diff_api.GetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &h);
+
+ data = crAlloc(w*h*4);
+ if (!data) crError("no memory!");
+ diff_api.GetTexImage(target, level, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ crDumpTGA(w, h, data);
+ crFree(data);
+ }
+#endif
+}
+
+#if defined( CR_OPENGL_VERSION_1_2 )
+void STATE_APIENTRY
+crStateTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
+ GLint zoffset, GLsizei width, GLsizei height,
+ GLsizei depth, GLenum format, GLenum type,
+ const GLvoid * pixels)
+{
+ CRContext *g = GetCurrentContext();
+ CRTextureState *t = &(g->texture);
+ CRStateBits *sb = GetCurrentBits();
+ CRTextureBits *tb = &(sb->texture);
+ CRTextureUnit *unit = t->unit + t->curTextureUnit;
+ CRTextureObj *tobj = unit->currentTexture3D;
+ CRTextureLevel *tl = tobj->level[0] + level;
+#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
+ CRClientState *c = &(g->client);
+ GLubyte *subimg = NULL;
+ GLubyte *img = NULL;
+ GLubyte *src;
+ int i;
+#endif
+ (void)format; (void)type; (void)pixels;
+
+ FLUSH();
+
+ if (ErrorCheckTexSubImage(3, target, level, xoffset, yoffset, zoffset,
+ width, height, depth)) {
+ 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;
+ zoffset += tl->border;
+
+ subimg =
+ (GLubyte *)
+ crAlloc(crTextureSize(tl->format, tl->type, width, height, depth));
+
+ crPixelCopy3D(width, height, depth, subimg, tl->format, tl->type, NULL,
+ pixels, format, type, &(c->unpack));
+
+ img = tl->img + xoffset * tl->bytesPerPixel +
+ yoffset * tl->width * tl->bytesPerPixel +
+ zoffset * tl->width * tl->height * tl->bytesPerPixel;
+
+ src = subimg;
+
+ /* Copy the data into the texture */
+ for (i = 0; i < depth; i++)
+ {
+ crMemcpy(img, src, tl->bytesPerPixel * width * height);
+ img += tl->width * tl->height * tl->bytesPerPixel;
+ src += width * height * tl->bytesPerPixel;
+ }
+
+ crFree(subimg);
+#endif
+
+#ifdef CR_SGIS_generate_mipmap
+ if (level == tobj->baseLevel && tobj->generateMipmap) {
+ generate_mipmap(tobj, target);
+ }
+ else {
+ tl->generateMipmap = GL_FALSE;
+ }
+#endif
+
+ DIRTY(tobj->dirty, g->neg_bitid);
+ DIRTY(tobj->imageBit, g->neg_bitid);
+ DIRTY(tl->dirty, g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+}
+#endif /* CR_OPENGL_VERSION_1_2 || GL_EXT_texture3D */
+
+
+void STATE_APIENTRY
+crStateCompressedTexImage1DARB(GLenum target, GLint level,
+ GLenum internalFormat, GLsizei width,
+ GLint border, GLsizei imageSize,
+ const GLvoid * data)
+{
+ CRContext *g = GetCurrentContext();
+ CRTextureState *t = &(g->texture);
+ CRTextureObj *tobj;
+ CRTextureLevel *tl;
+ CRStateBits *sb = GetCurrentBits();
+ CRTextureBits *tb = &(sb->texture);
+ (void)data;
+
+ FLUSH();
+
+ if (ErrorCheckTexImage(1, target, level, width, 1, 1, border)) {
+ if (IsProxyTarget(target)) {
+ /* clear all state, but don't generate error */
+ crStateTextureInitTextureObj(g, &(t->proxy1D), 0, GL_TEXTURE_1D);
+ }
+ else {
+ /* error was already recorded */
+ }
+ return;
+ }
+
+ crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl);
+ CRASSERT(tobj);
+ CRASSERT(tl);
+
+ if (IsProxyTarget(target))
+ tl->bytes = 0;
+ else
+ tl->bytes = imageSize;
+
+#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
+ if (tl->bytes)
+ {
+ /* this is not a proxy texture target so alloc storage */
+ if (tl->img)
+ crFree(tl->img);
+ tl->img = (GLubyte *) crAlloc(tl->bytes);
+ if (!tl->img)
+ {
+ crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY,
+ "glTexImage1D out of memory");
+ return;
+ }
+ if (data)
+ crMemcpy(tl->img, data, imageSize);
+ }
+#endif
+
+ tl->width = width;
+ tl->height = 1;
+ tl->depth = 1;
+ tl->border = border;
+ tl->format = GL_NONE;
+ tl->type = GL_NONE;
+ tl->internalFormat = internalFormat;
+ crStateTextureInitTextureFormat(tl, internalFormat);
+ tl->compressed = GL_TRUE;
+ tl->bytesPerPixel = 0; /* n/a */
+
+#ifdef CR_SGIS_generate_mipmap
+ if (level == tobj->baseLevel && tobj->generateMipmap) {
+ generate_mipmap(tobj, target);
+ }
+ else {
+ tl->generateMipmap = GL_FALSE;
+ }
+#endif
+
+ DIRTY(tobj->dirty, g->neg_bitid);
+ DIRTY(tobj->imageBit, g->neg_bitid);
+ DIRTY(tl->dirty, g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+}
+
+
+void STATE_APIENTRY
+crStateCompressedTexImage2DARB(GLenum target, GLint level,
+ GLenum internalFormat, GLsizei width,
+ GLsizei height, GLint border,
+ GLsizei imageSize, const GLvoid * data)
+{
+ CRContext *g = GetCurrentContext();
+ CRTextureState *t = &(g->texture);
+ CRTextureObj *tobj = NULL;
+ CRTextureLevel *tl = NULL;
+ CRStateBits *sb = GetCurrentBits();
+ CRTextureBits *tb = &(sb->texture);
+ (void)data;
+
+ FLUSH();
+
+ if (ErrorCheckTexImage(2, target, level, width, height, 1, border)) {
+ if (IsProxyTarget(target)) {
+ /* clear all state, but don't generate error */
+ crStateTextureInitTextureObj(g, &(t->proxy2D), 0, GL_TEXTURE_2D);
+ }
+ else {
+ /* error was already recorded */
+ }
+ return;
+ }
+
+ crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl);
+ CRASSERT(tobj);
+ CRASSERT(tl);
+
+ if (IsProxyTarget(target))
+ tl->bytes = 0;
+ else
+ tl->bytes = imageSize;
+
+#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
+ if (tl->bytes)
+ {
+ /* this is not a proxy texture target so alloc storage */
+ if (tl->img)
+ crFree(tl->img);
+ tl->img = (GLubyte *) crAlloc(tl->bytes);
+ if (!tl->img)
+ {
+ crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY,
+ "glTexImage2D out of memory");
+ return;
+ }
+ if (data)
+ crMemcpy(tl->img, data, imageSize);
+ }
+#endif
+
+ tl->width = width;
+ tl->height = height;
+ tl->depth = 1;
+ tl->border = border;
+ tl->format = GL_NONE;
+ tl->type = GL_NONE;
+ tl->internalFormat = internalFormat;
+ crStateTextureInitTextureFormat(tl, internalFormat);
+ tl->compressed = GL_TRUE;
+ tl->bytesPerPixel = 0; /* n/a */
+
+#ifdef CR_SGIS_generate_mipmap
+ if (level == tobj->baseLevel && tobj->generateMipmap) {
+ generate_mipmap(tobj, target);
+ }
+ else {
+ tl->generateMipmap = GL_FALSE;
+ }
+#endif
+
+ /* XXX may need to do some fine-tuning here for proxy textures */
+ DIRTY(tobj->dirty, g->neg_bitid);
+ DIRTY(tobj->imageBit, g->neg_bitid);
+ DIRTY(tl->dirty, g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+}
+
+
+void STATE_APIENTRY
+crStateCompressedTexImage3DARB(GLenum target, GLint level,
+ GLenum internalFormat, GLsizei width,
+ GLsizei height, GLsizei depth, GLint border,
+ GLsizei imageSize, const GLvoid * data)
+{
+ CRContext *g = GetCurrentContext();
+ CRTextureState *t = &(g->texture);
+ CRTextureObj *tobj = NULL;
+ CRTextureLevel *tl = NULL;
+ CRStateBits *sb = GetCurrentBits();
+ CRTextureBits *tb = &(sb->texture);
+ (void)data;
+
+ FLUSH();
+
+ if (ErrorCheckTexImage(3, target, level, width, height, depth, border)) {
+ if (IsProxyTarget(target)) {
+ /* clear all state, but don't generate error */
+ crStateTextureInitTextureObj(g, &(t->proxy3D), 0, GL_TEXTURE_3D);
+ }
+ else {
+ /* error was already recorded */
+ }
+ return;
+ }
+
+ crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl);
+ CRASSERT(tobj);
+ CRASSERT(tl);
+
+ if (IsProxyTarget(target))
+ tl->bytes = 0;
+ else
+ tl->bytes = imageSize;
+
+#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
+ if (tl->bytes)
+ {
+ /* this is not a proxy texture target so alloc storage */
+ if (tl->img)
+ crFree(tl->img);
+ tl->img = (GLubyte *) crAlloc(tl->bytes);
+ if (!tl->img)
+ {
+ crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY,
+ "glCompressedTexImage3D out of memory");
+ return;
+ }
+ if (data)
+ crMemcpy(tl->img, data, imageSize);
+ }
+#endif
+
+ tl->width = width;
+ tl->height = height;
+ tl->depth = depth;
+ tl->border = border;
+ tl->format = GL_NONE;
+ tl->type = GL_NONE;
+ tl->internalFormat = internalFormat;
+ crStateTextureInitTextureFormat(tl, internalFormat);
+ tl->compressed = GL_TRUE;
+ tl->bytesPerPixel = 0; /* n/a */
+
+#ifdef CR_SGIS_generate_mipmap
+ if (level == tobj->baseLevel && tobj->generateMipmap) {
+ generate_mipmap(tobj, target);
+ }
+ else {
+ tl->generateMipmap = GL_FALSE;
+ }
+#endif
+
+ /* XXX may need to do some fine-tuning here for proxy textures */
+ DIRTY(tobj->dirty, g->neg_bitid);
+ DIRTY(tobj->imageBit, g->neg_bitid);
+ DIRTY(tl->dirty, g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+}
+
+
+void STATE_APIENTRY
+crStateCompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
+ GLsizei width, GLenum format,
+ GLsizei imageSize, const GLvoid * data)
+{
+ CRContext *g = GetCurrentContext();
+ CRTextureState *t = &(g->texture);
+ CRStateBits *sb = GetCurrentBits();
+ CRTextureBits *tb = &(sb->texture);
+ CRTextureUnit *unit = t->unit + t->curTextureUnit;
+ CRTextureObj *tobj = unit->currentTexture1D;
+ CRTextureLevel *tl = tobj->level[0] + level;
+ (void)format; (void)imageSize; (void)data;
+
+ FLUSH();
+
+ if (ErrorCheckTexSubImage(1, target, level, xoffset, 0, 0, width, 1, 1)) {
+ 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;
+
+ if (xoffset == 0 && width == tl->width) {
+ /* just memcpy */
+ crMemcpy(tl->img, data, imageSize);
+ }
+ else {
+ /* XXX this depends on the exact compression method */
+ crWarning("Not implemented part crStateCompressedTexSubImage1DARB");
+ }
+#endif
+
+#ifdef CR_SGIS_generate_mipmap
+ if (level == tobj->baseLevel && tobj->generateMipmap) {
+ generate_mipmap(tobj, target);
+ }
+ else {
+ tl->generateMipmap = GL_FALSE;
+ }
+#endif
+
+ DIRTY(tobj->dirty, g->neg_bitid);
+ DIRTY(tobj->imageBit, g->neg_bitid);
+ DIRTY(tl->dirty, g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+}
+
+
+void STATE_APIENTRY
+crStateCompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
+ GLint yoffset, GLsizei width,
+ GLsizei height, GLenum format,
+ GLsizei imageSize, const GLvoid * data)
+{
+ CRContext *g = GetCurrentContext();
+ CRTextureState *t = &(g->texture);
+ CRStateBits *sb = GetCurrentBits();
+ CRTextureBits *tb = &(sb->texture);
+ CRTextureUnit *unit = t->unit + t->curTextureUnit;
+ CRTextureObj *tobj = unit->currentTexture2D;
+ CRTextureLevel *tl = tobj->level[0] + level;
+ (void)format; (void)imageSize; (void)data;
+
+ 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 */
+ }
+
+#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
+ xoffset += tl->border;
+ yoffset += tl->border;
+
+ if (xoffset == 0 && width == tl->width
+ && yoffset == 0 && height == tl->height)
+ {
+ /* just memcpy */
+ crMemcpy(tl->img, data, imageSize);
+ }
+ else {
+ /* XXX this depends on the exact compression method */
+ crWarning("Not implemented part crStateCompressedTexSubImage2DARB");
+ }
+#endif
+
+#ifdef CR_SGIS_generate_mipmap
+ if (level == tobj->baseLevel && tobj->generateMipmap) {
+ generate_mipmap(tobj, target);
+ }
+ else {
+ tl->generateMipmap = GL_FALSE;
+ }
+#endif
+
+ DIRTY(tobj->dirty, g->neg_bitid);
+ DIRTY(tobj->imageBit, g->neg_bitid);
+ DIRTY(tl->dirty, g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+}
+
+
+void STATE_APIENTRY
+crStateCompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
+ GLint yoffset, GLint zoffset, GLsizei width,
+ GLsizei height, GLsizei depth,
+ GLenum format, GLsizei imageSize,
+ const GLvoid * data)
+{
+ CRContext *g = GetCurrentContext();
+ CRTextureState *t = &(g->texture);
+ CRStateBits *sb = GetCurrentBits();
+ CRTextureBits *tb = &(sb->texture);
+ CRTextureUnit *unit = t->unit + t->curTextureUnit;
+ CRTextureObj *tobj = unit->currentTexture3D;
+ CRTextureLevel *tl = tobj->level[0] + level;
+ (void)format; (void)imageSize; (void)data;
+
+ 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 */
+ }
+
+#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
+ xoffset += tl->border;
+ yoffset += tl->border;
+ zoffset += tl->border;
+
+ if (xoffset == 0 && width == tl->width &&
+ yoffset == 0 && height == tl->height &&
+ zoffset == 0 && depth == tl->depth) {
+ /* just memcpy */
+ crMemcpy(tl->img, data, imageSize);
+ }
+ else {
+ /* XXX this depends on the exact compression method */
+ crWarning("Not implemented part crStateCompressedTexSubImage3DARB");
+ }
+#endif
+
+#ifdef CR_SGIS_generate_mipmap
+ if (level == tobj->baseLevel && tobj->generateMipmap) {
+ generate_mipmap(tobj, target);
+ }
+ else {
+ tl->generateMipmap = GL_FALSE;
+ }
+#endif
+
+ DIRTY(tobj->dirty, g->neg_bitid);
+ DIRTY(tobj->imageBit, g->neg_bitid);
+ DIRTY(tl->dirty, g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+}
+
+
+void STATE_APIENTRY
+crStateGetCompressedTexImageARB(GLenum target, GLint level, GLvoid * img)
+{
+ CRContext *g = GetCurrentContext();
+ CRTextureObj *tobj;
+ CRTextureLevel *tl;
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetCompressedTexImage called in begin/end");
+ return;
+ }
+
+ crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl);
+ if (!tobj || !tl) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetCompressedTexImage(invalid target or level)");
+ return;
+ }
+
+ if (!tl->compressed) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetCompressedTexImage(not a compressed texture)");
+ 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
+ diff_api.GetCompressedTexImageARB(target, level, img);
+#endif
+}
+
+
+void STATE_APIENTRY
+crStateGetTexImage(GLenum target, GLint level, GLenum format,
+ GLenum type, GLvoid * pixels)
+{
+ CRContext *g = GetCurrentContext();
+#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
+ CRClientState *c = &(g->client);
+#endif
+ CRTextureObj *tobj;
+ CRTextureLevel *tl;
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetTexImage called in begin/end");
+ return;
+ }
+
+ crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl);
+ if (!tobj || !tl) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetTexImage(invalid target or level)");
+ return;
+ }
+
+ if (tl->compressed) {
+ crWarning("glGetTexImage cannot decompress a compressed texture!");
+ return;
+ }
+
+#ifdef DEBUG_misha
+ CRASSERT(tl->bytes);
+ CRASSERT(tl->height);
+ CRASSERT(tl->width);
+ CRASSERT(tl->depth);
+#endif
+
+ switch (format)
+ {
+ case GL_RED:
+ case GL_GREEN:
+ case GL_BLUE:
+ case GL_ALPHA:
+ case GL_RGB:
+ case GL_RGBA:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetTexImage called with bogus format: %d", format);
+ return;
+ }
+
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ case GL_BYTE:
+ case GL_UNSIGNED_SHORT:
+ case GL_SHORT:
+ case GL_UNSIGNED_INT:
+ case GL_INT:
+ case GL_FLOAT:
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetTexImage called with bogus type: %d", type);
+ return;
+ }
+
+#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
+#ifdef CR_OPENGL_VERSION_1_2
+ if (target == GL_TEXTURE_3D)
+ {
+ crPixelCopy3D(tl->width, tl->height, tl->depth, (GLvoid *) pixels, format,
+ type, NULL, (tl->img), format, type, &(c->pack));
+ }
+ else
+#endif
+ if ((target == GL_TEXTURE_1D) || (target == GL_TEXTURE_2D))
+ {
+ crPixelCopy2D(tl->width, tl->height, (GLvoid *) pixels, format, type, NULL, /* dst */
+ tl->img, format, type, &(c->pack)); /* src */
+ }
+#else
+ diff_api.GetTexImage(target, level, format, type, pixels);
+#endif
+}
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_texture.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_texture.c
new file mode 100644
index 00000000..5184feb6
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_texture.c
@@ -0,0 +1,3418 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#include "state.h"
+#include "state/cr_statetypes.h"
+#include "state/cr_texture.h"
+#include "cr_hash.h"
+#include "cr_string.h"
+#include "cr_mem.h"
+#include "cr_version.h"
+#include "state_internals.h"
+
+#ifdef DEBUG_misha
+#include <iprt/assert.h>
+#endif
+
+#define UNUSED(x) ((void) (x))
+
+#define GET_TOBJ(tobj, state, id) \
+ tobj = (CRTextureObj *) crHashtableSearch(g->shared->textureTable, id);
+
+
+void crStateTextureDestroy(CRContext *ctx)
+{
+ crStateDeleteTextureObjectData(&ctx->texture.base1D);
+ crStateDeleteTextureObjectData(&ctx->texture.proxy1D);
+ crStateDeleteTextureObjectData(&ctx->texture.base2D);
+ crStateDeleteTextureObjectData(&ctx->texture.proxy2D);
+#ifdef CR_OPENGL_VERSION_1_2
+ crStateDeleteTextureObjectData(&ctx->texture.base3D);
+ crStateDeleteTextureObjectData(&ctx->texture.proxy3D);
+#endif
+#ifdef CR_ARB_texture_cube_map
+ crStateDeleteTextureObjectData(&ctx->texture.baseCubeMap);
+ crStateDeleteTextureObjectData(&ctx->texture.proxyCubeMap);
+#endif
+#ifdef CR_NV_texture_rectangle
+ crStateDeleteTextureObjectData(&ctx->texture.baseRect);
+ crStateDeleteTextureObjectData(&ctx->texture.proxyRect);
+#endif
+}
+
+
+void crStateTextureInit(CRContext *ctx)
+{
+ CRLimitsState *limits = &ctx->limits;
+ CRTextureState *t = &ctx->texture;
+ CRStateBits *sb = GetCurrentBits();
+ CRTextureBits *tb = &(sb->texture);
+ unsigned int i;
+ unsigned int a;
+ GLvectorf zero_vector = {0.0f, 0.0f, 0.0f, 0.0f};
+ GLcolorf zero_color = {0.0f, 0.0f, 0.0f, 0.0f};
+ GLvectorf x_vector = {1.0f, 0.0f, 0.0f, 0.0f};
+ GLvectorf y_vector = {0.0f, 1.0f, 0.0f, 0.0f};
+
+ /* compute max levels from max sizes */
+ for (i=0, a=limits->maxTextureSize; a; i++, a=a>>1);
+ t->maxLevel = i-1;
+ for (i=0, a=limits->max3DTextureSize; a; i++, a=a>>1);
+ t->max3DLevel = i-1;
+#ifdef CR_ARB_texture_cube_map
+ for (i=0, a=limits->maxCubeMapTextureSize; a; i++, a=a>>1);
+ t->maxCubeMapLevel = i-1;
+#endif
+#ifdef CR_NV_texture_rectangle
+ for (i=0, a=limits->maxRectTextureSize; a; i++, a=a>>1);
+ t->maxRectLevel = i-1;
+#endif
+
+ crStateTextureInitTextureObj(ctx, &(t->base1D), 0, GL_TEXTURE_1D);
+ crStateTextureInitTextureObj(ctx, &(t->base2D), 0, GL_TEXTURE_2D);
+#ifdef CR_OPENGL_VERSION_1_2
+ crStateTextureInitTextureObj(ctx, &(t->base3D), 0, GL_TEXTURE_3D);
+#endif
+#ifdef CR_ARB_texture_cube_map
+ crStateTextureInitTextureObj(ctx, &(t->baseCubeMap), 0,
+ GL_TEXTURE_CUBE_MAP_ARB);
+#endif
+#ifdef CR_NV_texture_rectangle
+ crStateTextureInitTextureObj(ctx, &(t->baseRect), 0,
+ GL_TEXTURE_RECTANGLE_NV);
+#endif
+
+ crStateTextureInitTextureObj(ctx, &(t->proxy1D), 0, GL_TEXTURE_1D);
+ crStateTextureInitTextureObj(ctx, &(t->proxy2D), 0, GL_TEXTURE_2D);
+#ifdef CR_OPENGL_VERSION_1_2
+ crStateTextureInitTextureObj(ctx, &(t->proxy3D), 0, GL_TEXTURE_3D);
+#endif
+#ifdef CR_ARB_texture_cube_map
+ crStateTextureInitTextureObj(ctx, &(t->proxyCubeMap), 0,
+ GL_TEXTURE_CUBE_MAP_ARB);
+#endif
+#ifdef CR_NV_texture_rectangle
+ crStateTextureInitTextureObj(ctx, &(t->proxyRect), 0,
+ GL_TEXTURE_RECTANGLE_NV);
+#endif
+
+ t->curTextureUnit = 0;
+
+ /* Per-unit initialization */
+ for (i = 0; i < limits->maxTextureUnits; i++)
+ {
+ t->unit[i].currentTexture1D = &(t->base1D);
+ t->unit[i].currentTexture2D = &(t->base2D);
+ t->unit[i].currentTexture3D = &(t->base3D);
+#ifdef CR_ARB_texture_cube_map
+ t->unit[i].currentTextureCubeMap = &(t->baseCubeMap);
+#endif
+#ifdef CR_NV_texture_rectangle
+ t->unit[i].currentTextureRect = &(t->baseRect);
+#endif
+
+ t->unit[i].enabled1D = GL_FALSE;
+ t->unit[i].enabled2D = GL_FALSE;
+ t->unit[i].enabled3D = GL_FALSE;
+ t->unit[i].enabledCubeMap = GL_FALSE;
+#ifdef CR_NV_texture_rectangle
+ t->unit[i].enabledRect = GL_FALSE;
+#endif
+ t->unit[i].textureGen.s = GL_FALSE;
+ t->unit[i].textureGen.t = GL_FALSE;
+ t->unit[i].textureGen.r = GL_FALSE;
+ t->unit[i].textureGen.q = GL_FALSE;
+
+ t->unit[i].gen.s = GL_EYE_LINEAR;
+ t->unit[i].gen.t = GL_EYE_LINEAR;
+ t->unit[i].gen.r = GL_EYE_LINEAR;
+ t->unit[i].gen.q = GL_EYE_LINEAR;
+
+ t->unit[i].objSCoeff = x_vector;
+ t->unit[i].objTCoeff = y_vector;
+ t->unit[i].objRCoeff = zero_vector;
+ t->unit[i].objQCoeff = zero_vector;
+
+ t->unit[i].eyeSCoeff = x_vector;
+ t->unit[i].eyeTCoeff = y_vector;
+ t->unit[i].eyeRCoeff = zero_vector;
+ t->unit[i].eyeQCoeff = zero_vector;
+ t->unit[i].envMode = GL_MODULATE;
+ t->unit[i].envColor = zero_color;
+
+ t->unit[i].combineModeRGB = GL_MODULATE;
+ t->unit[i].combineModeA = GL_MODULATE;
+ t->unit[i].combineSourceRGB[0] = GL_TEXTURE;
+ t->unit[i].combineSourceRGB[1] = GL_PREVIOUS_EXT;
+ t->unit[i].combineSourceRGB[2] = GL_CONSTANT_EXT;
+ t->unit[i].combineSourceA[0] = GL_TEXTURE;
+ t->unit[i].combineSourceA[1] = GL_PREVIOUS_EXT;
+ t->unit[i].combineSourceA[2] = GL_CONSTANT_EXT;
+ t->unit[i].combineOperandRGB[0] = GL_SRC_COLOR;
+ t->unit[i].combineOperandRGB[1] = GL_SRC_COLOR;
+ t->unit[i].combineOperandRGB[2] = GL_SRC_ALPHA;
+ t->unit[i].combineOperandA[0] = GL_SRC_ALPHA;
+ t->unit[i].combineOperandA[1] = GL_SRC_ALPHA;
+ t->unit[i].combineOperandA[2] = GL_SRC_ALPHA;
+ t->unit[i].combineScaleRGB = 1.0F;
+ t->unit[i].combineScaleA = 1.0F;
+#ifdef CR_EXT_texture_lod_bias
+ t->unit[i].lodBias = 0.0F;
+#endif
+ RESET(tb->enable[i], ctx->bitid);
+ RESET(tb->current[i], ctx->bitid);
+ RESET(tb->objGen[i], ctx->bitid);
+ RESET(tb->eyeGen[i], ctx->bitid);
+ RESET(tb->genMode[i], ctx->bitid);
+ RESET(tb->envBit[i], ctx->bitid);
+ }
+ RESET(tb->dirty, ctx->bitid);
+}
+
+
+void
+crStateTextureInitTextureObj(CRContext *ctx, CRTextureObj *tobj,
+ GLuint name, GLenum target)
+{
+ const CRTextureState *t = &(ctx->texture);
+ int i, face;
+
+ tobj->borderColor.r = 0.0f;
+ tobj->borderColor.g = 0.0f;
+ tobj->borderColor.b = 0.0f;
+ tobj->borderColor.a = 0.0f;
+ tobj->minFilter = GL_NEAREST_MIPMAP_LINEAR;
+ tobj->magFilter = GL_LINEAR;
+ tobj->wrapS = GL_REPEAT;
+ tobj->wrapT = GL_REPEAT;
+#ifdef CR_OPENGL_VERSION_1_2
+ tobj->wrapR = GL_REPEAT;
+ tobj->priority = 1.0f;
+ tobj->minLod = -1000.0;
+ tobj->maxLod = 1000.0;
+ tobj->baseLevel = 0;
+ tobj->maxLevel = t->maxLevel;
+#endif
+ tobj->target = target;
+ tobj->id = name;
+ tobj->hwid = 0;
+
+#ifndef IN_GUEST
+ crStateGetTextureObjHWID(tobj);
+#endif
+
+ CRASSERT(t->maxLevel);
+
+ /* XXX don't always need all six faces */
+ for (face = 0; face < 6; face++) {
+ /* allocate array of mipmap levels */
+ CRASSERT(t->maxLevel < CR_MAX_MIPMAP_LEVELS);
+ tobj->level[face] = (CRTextureLevel *)
+ crCalloc(sizeof(CRTextureLevel) * CR_MAX_MIPMAP_LEVELS);
+
+ if (!tobj->level[face])
+ return; /* out of memory */
+
+ /* init non-zero fields */
+ for (i = 0; i <= t->maxLevel; i++) {
+ CRTextureLevel *tl = &(tobj->level[face][i]);
+ tl->internalFormat = GL_ONE;
+ tl->format = GL_RGBA;
+ tl->type = GL_UNSIGNED_BYTE;
+ crStateTextureInitTextureFormat( tl, tl->internalFormat );
+ }
+ }
+
+#ifdef CR_EXT_texture_filter_anisotropic
+ tobj->maxAnisotropy = 1.0f;
+#endif
+
+#ifdef CR_ARB_depth_texture
+ tobj->depthMode = GL_LUMINANCE;
+#endif
+
+#ifdef CR_ARB_shadow
+ tobj->compareMode = GL_NONE;
+ tobj->compareFunc = GL_LEQUAL;
+#endif
+
+#ifdef CR_ARB_shadow_ambient
+ tobj->compareFailValue = 0.0;
+#endif
+
+ RESET(tobj->dirty, ctx->bitid);
+ RESET(tobj->imageBit, ctx->bitid);
+ for (i = 0; i < CR_MAX_TEXTURE_UNITS; i++)
+ {
+ RESET(tobj->paramsBit[i], ctx->bitid);
+ }
+
+ CR_STATE_SHAREDOBJ_USAGE_INIT(tobj);
+ CR_STATE_SHAREDOBJ_USAGE_SET(tobj, ctx);
+}
+
+
+/* ================================================================
+ * Texture internal formats:
+ */
+
+const CRTextureFormat _texformat_rgba8888 = {
+ 8, /* RedBits */
+ 8, /* GreenBits */
+ 8, /* BlueBits */
+ 8, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+};
+
+const CRTextureFormat _texformat_argb8888 = {
+ 8, /* RedBits */
+ 8, /* GreenBits */
+ 8, /* BlueBits */
+ 8, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+};
+
+const CRTextureFormat _texformat_rgb888 = {
+ 8, /* RedBits */
+ 8, /* GreenBits */
+ 8, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+};
+
+const CRTextureFormat _texformat_rgb565 = {
+ 5, /* RedBits */
+ 6, /* GreenBits */
+ 5, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+};
+
+const CRTextureFormat _texformat_argb4444 = {
+ 4, /* RedBits */
+ 4, /* GreenBits */
+ 4, /* BlueBits */
+ 4, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+};
+
+const CRTextureFormat _texformat_argb1555 = {
+ 5, /* RedBits */
+ 5, /* GreenBits */
+ 5, /* BlueBits */
+ 1, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+};
+
+const CRTextureFormat _texformat_al88 = {
+ 0, /* RedBits */
+ 0, /* GreenBits */
+ 0, /* BlueBits */
+ 8, /* AlphaBits */
+ 8, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+};
+
+const CRTextureFormat _texformat_rgb332 = {
+ 3, /* RedBits */
+ 3, /* GreenBits */
+ 2, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+};
+
+const CRTextureFormat _texformat_a8 = {
+ 0, /* RedBits */
+ 0, /* GreenBits */
+ 0, /* BlueBits */
+ 8, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+};
+
+const CRTextureFormat _texformat_l8 = {
+ 0, /* RedBits */
+ 0, /* GreenBits */
+ 0, /* BlueBits */
+ 0, /* AlphaBits */
+ 8, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+};
+
+const CRTextureFormat _texformat_i8 = {
+ 0, /* RedBits */
+ 0, /* GreenBits */
+ 0, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 8, /* IntensityBits */
+ 0, /* IndexBits */
+};
+
+const CRTextureFormat _texformat_ci8 = {
+ 0, /* RedBits */
+ 0, /* GreenBits */
+ 0, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 8, /* IndexBits */
+};
+
+
+/**
+ * Given an internal texture format enum or 1, 2, 3, 4 initialize the
+ * texture levels texture format. This basically just indicates the
+ * number of red, green, blue, alpha, luminance, etc. bits are used to
+ * store the image.
+ */
+void
+crStateTextureInitTextureFormat( CRTextureLevel *tl, GLenum internalFormat )
+{
+ switch (internalFormat) {
+ case 4:
+ case GL_RGBA:
+ case GL_COMPRESSED_RGBA_ARB:
+#ifdef CR_EXT_texture_sRGB
+ case GL_SRGB_ALPHA_EXT:
+ case GL_SRGB8_ALPHA8_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_EXT:
+#endif
+ tl->texFormat = &_texformat_rgba8888;
+ break;
+
+ case 3:
+ case GL_RGB:
+ case GL_COMPRESSED_RGB_ARB:
+#ifdef CR_EXT_texture_sRGB
+ case GL_SRGB_EXT:
+ case GL_SRGB8_EXT:
+ case GL_COMPRESSED_SRGB_EXT:
+#endif
+ tl->texFormat = &_texformat_rgb888;
+ break;
+
+ case GL_RGBA2:
+ case GL_RGBA4:
+ case GL_RGB5_A1:
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ tl->texFormat = &_texformat_rgba8888;
+ break;
+
+ case GL_R3_G3_B2:
+ tl->texFormat = &_texformat_rgb332;
+ break;
+ case GL_RGB4:
+ case GL_RGB5:
+ case GL_RGB8:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ tl->texFormat = &_texformat_rgb888;
+ break;
+
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ case GL_COMPRESSED_ALPHA_ARB:
+ tl->texFormat = &_texformat_a8;
+ break;
+
+ case 1:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ case GL_COMPRESSED_LUMINANCE_ARB:
+#ifdef CR_EXT_texture_sRGB
+ case GL_SLUMINANCE_EXT:
+ case GL_SLUMINANCE8_EXT:
+ case GL_COMPRESSED_SLUMINANCE_EXT:
+#endif
+ tl->texFormat = &_texformat_l8;
+ break;
+
+ case 2:
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE4_ALPHA4:
+ case GL_LUMINANCE6_ALPHA2:
+ case GL_LUMINANCE8_ALPHA8:
+ case GL_LUMINANCE12_ALPHA4:
+ case GL_LUMINANCE12_ALPHA12:
+ case GL_LUMINANCE16_ALPHA16:
+ case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
+#ifdef CR_EXT_texture_sRGB
+ case GL_SLUMINANCE_ALPHA_EXT:
+ case GL_SLUMINANCE8_ALPHA8_EXT:
+ case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT:
+#endif
+ tl->texFormat = &_texformat_al88;
+ break;
+
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ case GL_COMPRESSED_INTENSITY_ARB:
+ tl->texFormat = &_texformat_i8;
+ break;
+
+ case GL_COLOR_INDEX:
+ case GL_COLOR_INDEX1_EXT:
+ case GL_COLOR_INDEX2_EXT:
+ case GL_COLOR_INDEX4_EXT:
+ case GL_COLOR_INDEX8_EXT:
+ case GL_COLOR_INDEX12_EXT:
+ case GL_COLOR_INDEX16_EXT:
+ tl->texFormat = &_texformat_ci8;
+ break;
+
+ default:
+ return;
+ }
+}
+
+#if 0
+void crStateTextureInitTexture (GLuint name)
+{
+ CRContext *g = GetCurrentContext();
+ CRTextureState *t = &(g->texture);
+ CRTextureObj *tobj;
+
+ GET_TOBJ(tobj, name);
+ if (!tobj) return;
+
+ crStateTextureInitTextureObj(g, tobj, name, GL_NONE);
+}
+#endif
+
+
+
+/**
+ * Return the texture object corresponding to the given target and ID.
+ */
+CRTextureObj *
+crStateTextureGet(GLenum target, GLuint name)
+{
+ CRContext *g = GetCurrentContext();
+ CRTextureState *t = &(g->texture);
+ CRTextureObj *tobj;
+
+ if (name == 0)
+ {
+ switch (target) {
+ case GL_TEXTURE_1D:
+ return &t->base1D;
+ case GL_TEXTURE_2D:
+ return &t->base2D;
+ case GL_TEXTURE_3D:
+ return &t->base3D;
+#ifdef CR_ARB_texture_cube_map
+ case GL_TEXTURE_CUBE_MAP_ARB:
+ return &t->baseCubeMap;
+#endif
+#ifdef CR_NV_texture_rectangle
+ case GL_TEXTURE_RECTANGLE_NV:
+ return &t->baseRect;
+#endif
+ default:
+ return NULL;
+ }
+ }
+
+ GET_TOBJ(tobj, g, name);
+
+ return tobj;
+}
+
+
+/*
+ * Allocate a new texture object with the given name.
+ * Also insert into hash table.
+ */
+static CRTextureObj *
+crStateTextureAllocate_t(CRContext *ctx, GLuint name)
+{
+ CRTextureObj *tobj;
+
+ if (!name)
+ return NULL;
+
+ tobj = crCalloc(sizeof(CRTextureObj));
+ if (!tobj)
+ return NULL;
+
+ crHashtableAdd( ctx->shared->textureTable, name, (void *) tobj );
+
+ crStateTextureInitTextureObj(ctx, tobj, name, GL_NONE);
+
+ return tobj;
+}
+
+
+/**
+ * Delete all the data that hangs off a CRTextureObj, but don't
+ * delete the texture object itself, since it may not have been
+ * dynamically allocated.
+ */
+void
+crStateDeleteTextureObjectData(CRTextureObj *tobj)
+{
+ int k;
+ int face;
+
+ CRASSERT(tobj);
+
+ /* Free the texture images */
+ for (face = 0; face < 6; face++) {
+ CRTextureLevel *levels = NULL;
+ levels = tobj->level[face];
+ if (levels) {
+ /* free all mipmap levels for this face */
+ for (k = 0; k < CR_MAX_MIPMAP_LEVELS; k++) {
+ CRTextureLevel *tl = levels + k;
+ if (tl->img) {
+ crFree(tl->img);
+ tl->img = NULL;
+ tl->bytes = 0;
+ }
+ }
+ crFree(levels);
+ }
+ tobj->level[face] = NULL;
+ }
+}
+
+
+void
+crStateDeleteTextureObject(CRTextureObj *tobj)
+{
+ crStateDeleteTextureObjectData(tobj);
+ crFree(tobj);
+}
+
+void crStateRegNames(CRContext *g, CRHashTable *table, GLsizei n, GLuint *names)
+{
+ GLint i;
+ (void)g;
+ 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();
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "crStateGenNames called in Begin/End");
+ return;
+ }
+
+ if (n < 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "Negative n passed to crStateGenNames: %d", n);
+ return;
+ }
+
+ start = crHashtableAllocKeys(table, n);
+ if (start)
+ {
+ GLint i;
+ for (i = 0; i < n; i++)
+ names[i] = (GLuint) (start + i);
+ }
+ else
+ {
+ crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, "glGenTextures");
+ }
+}
+
+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;
+ CRFBOAttachmentPoint *ap;
+ CRContext *g = GetCurrentContext();
+ CRFramebufferObjectState *fbo = &g->framebufferobject;
+ CRFramebufferObject *pFBO;
+
+ pFBO = GL_READ_FRAMEBUFFER==target ? fbo->readFB : fbo->drawFB;
+ if (!pFBO) return;
+
+ for (u=0; u<CR_MAX_COLOR_ATTACHMENTS; ++u)
+ {
+ ap = &pFBO->color[u];
+ if (ap->type==GL_TEXTURE && ap->name==texture)
+ {
+ crStateFramebufferTexture1DEXT(target, u+GL_COLOR_ATTACHMENT0_EXT, 0, 0, 0);
+ }
+ }
+
+ ap = &pFBO->depth;
+ if (ap->type==GL_TEXTURE && ap->name==texture)
+ {
+ crStateFramebufferTexture1DEXT(target, GL_DEPTH_ATTACHMENT_EXT, 0, 0, 0);
+ }
+
+ ap = &pFBO->stencil;
+ if (ap->type==GL_TEXTURE && ap->name==texture)
+ {
+ crStateFramebufferTexture1DEXT(target, GL_STENCIL_ATTACHMENT_EXT, 0, 0, 0);
+ }
+}
+
+static void crStateCleanupTextureRefs(CRContext *g, CRTextureObj *tObj)
+{
+ CRTextureState *t = &(g->texture);
+ GLuint u;
+
+ /*
+ ** reset back to the base texture.
+ */
+ for (u = 0; u < g->limits.maxTextureUnits; u++)
+ {
+ if (tObj == t->unit[u].currentTexture1D)
+ {
+ t->unit[u].currentTexture1D = &(t->base1D);
+ }
+ if (tObj == t->unit[u].currentTexture2D)
+ {
+ t->unit[u].currentTexture2D = &(t->base2D);
+ }
+#ifdef CR_OPENGL_VERSION_1_2
+ if (tObj == t->unit[u].currentTexture3D)
+ {
+ t->unit[u].currentTexture3D = &(t->base3D);
+ }
+#endif
+#ifdef CR_ARB_texture_cube_map
+ if (tObj == t->unit[u].currentTextureCubeMap)
+ {
+ t->unit[u].currentTextureCubeMap = &(t->baseCubeMap);
+ }
+#endif
+#ifdef CR_NV_texture_rectangle
+ if (tObj == t->unit[u].currentTextureRect)
+ {
+ t->unit[u].currentTextureRect = &(t->baseRect);
+ }
+#endif
+
+#ifdef CR_EXT_framebuffer_object
+ crStateTextureCheckFBOAPs(GL_DRAW_FRAMEBUFFER, tObj->id);
+ crStateTextureCheckFBOAPs(GL_READ_FRAMEBUFFER, tObj->id);
+#endif
+ }
+}
+
+void STATE_APIENTRY crStateDeleteTextures(GLsizei n, const GLuint *textures)
+{
+ CRContext *g = GetCurrentContext();
+ CRTextureState *t = &(g->texture);
+ CRStateBits *sb = GetCurrentBits();
+ CRTextureBits *tb = &(sb->texture);
+ int i;
+
+ FLUSH();
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glDeleteTextures called in Begin/End");
+ return;
+ }
+
+ if (n < 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "Negative n passed to glDeleteTextures: %d", n);
+ return;
+ }
+
+ for (i=0; i<n; i++)
+ {
+ GLuint name = textures[i];
+ CRTextureObj *tObj;
+ if (!name)
+ continue;
+
+ GET_TOBJ(tObj, g, name);
+ if (tObj)
+ {
+ GLuint j;
+
+ crStateCleanupTextureRefs(g, tObj);
+
+ CR_STATE_SHAREDOBJ_USAGE_CLEAR(tObj, g);
+
+ 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);
+ CR_STATE_SHAREDOBJ_USAGE_CLEAR(tObj, g);
+ }
+ 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);
+ DIRTY(tb->current[t->curTextureUnit], g->neg_bitid);
+}
+
+
+
+void STATE_APIENTRY crStateClientActiveTextureARB( GLenum texture )
+{
+ CRContext *g = GetCurrentContext();
+ CRClientState *c = &(g->client);
+
+ FLUSH();
+
+ if (!g->extensions.ARB_multitexture) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glClientActiveTextureARB not available");
+ return;
+ }
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glClientActiveTextureARB called in Begin/End");
+ return;
+ }
+
+ if ( texture < GL_TEXTURE0_ARB ||
+ texture >= GL_TEXTURE0_ARB + g->limits.maxTextureUnits)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "crStateClientActiveTexture: unit = %d (max is %d)",
+ texture, g->limits.maxTextureUnits );
+ return;
+ }
+
+ c->curClientTextureUnit = texture - GL_TEXTURE0_ARB;
+
+ DIRTY(GetCurrentBits()->client.dirty, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateActiveTextureARB( GLenum texture )
+{
+ CRContext *g = GetCurrentContext();
+ CRTextureState *t = &(g->texture);
+
+ FLUSH();
+
+ if (!g->extensions.ARB_multitexture) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glActiveTextureARB not available");
+ return;
+ }
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glActiveTextureARB called in Begin/End");
+ return;
+ }
+
+ if ( texture < GL_TEXTURE0_ARB || texture >= GL_TEXTURE0_ARB + g->limits.maxTextureUnits)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "Bad texture unit passed to crStateActiveTexture: %d (max is %d)", texture, g->limits.maxTextureUnits );
+ return;
+ }
+
+ t->curTextureUnit = texture - GL_TEXTURE0_ARB;
+
+ /* update the current matrix pointer, etc. */
+ if (g->transform.matrixMode == GL_TEXTURE) {
+ crStateMatrixMode(GL_TEXTURE);
+ }
+}
+
+#ifndef IN_GUEST
+# ifdef DEBUG
+static uint32_t gDbgNumPinned = 0;
+# endif
+
+DECLEXPORT(void) crStatePinTexture(GLuint texture, GLboolean pin)
+{
+ CRTextureObj * pTobj;
+ CRSharedState *pShared = crStateGlobalSharedAcquire();
+ if (pShared)
+ {
+ pTobj = (CRTextureObj*)crHashtableSearch(pShared->textureTable, texture);
+
+ if (pTobj)
+ {
+# ifdef DEBUG
+ if (!pTobj->pinned != !pin)
+ {
+ if (pin)
+ ++gDbgNumPinned;
+ else
+ {
+ Assert(gDbgNumPinned);
+ --gDbgNumPinned;
+ }
+ }
+# endif
+ pTobj->pinned = !!pin;
+ if (!pin)
+ {
+ if (!CR_STATE_SHAREDOBJ_USAGE_IS_USED(pTobj))
+ crStateOnTextureUsageRelease(pShared, pTobj);
+ }
+ }
+ else
+ WARN(("texture %d not defined", texture));
+
+ crStateGlobalSharedRelease();
+ }
+ else
+ WARN(("no global shared"));
+}
+#endif
+
+DECLEXPORT(void) crStateSetTextureUsed(GLuint texture, GLboolean used)
+{
+ CRContext *g = GetCurrentContext();
+ CRTextureObj *tobj;
+
+ if (!texture)
+ {
+ crWarning("crStateSetTextureUsed: null texture name specified!");
+ return;
+ }
+
+ GET_TOBJ(tobj, g, texture);
+ if (!tobj)
+ {
+#ifdef IN_GUEST
+ if (used)
+ {
+ tobj = crStateTextureAllocate_t(g, texture);
+ }
+ else
+#endif
+ {
+ WARN(("crStateSetTextureUsed: failed to fined a HW name for texture(%d)!", texture));
+ return;
+ }
+ }
+
+ if (used)
+ CR_STATE_SHAREDOBJ_USAGE_SET(tobj, g);
+ else
+ {
+ CRStateBits *sb = GetCurrentBits();
+ CRTextureBits *tb = &(sb->texture);
+ CRTextureState *t = &(g->texture);
+
+ crStateCleanupTextureRefs(g, tobj);
+
+ crStateReleaseTexture(g, tobj);
+
+ DIRTY(tb->dirty, g->neg_bitid);
+ DIRTY(tb->current[t->curTextureUnit], g->neg_bitid);
+ }
+}
+
+void STATE_APIENTRY crStateBindTexture(GLenum target, GLuint texture)
+{
+ CRContext *g = GetCurrentContext();
+ CRTextureState *t = &(g->texture);
+ CRTextureObj *tobj;
+ CRStateBits *sb = GetCurrentBits();
+ CRTextureBits *tb = &(sb->texture);
+
+ FLUSH();
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glBindTexture called in Begin/End");
+ return;
+ }
+
+ /* Special Case name = 0 */
+ if (!texture)
+ {
+ switch (target)
+ {
+ case GL_TEXTURE_1D:
+ t->unit[t->curTextureUnit].currentTexture1D = &(t->base1D);
+ break;
+ case GL_TEXTURE_2D:
+ t->unit[t->curTextureUnit].currentTexture2D = &(t->base2D);
+ break;
+#ifdef CR_OPENGL_VERSION_1_2
+ case GL_TEXTURE_3D:
+ t->unit[t->curTextureUnit].currentTexture3D = &(t->base3D);
+ break;
+#endif
+#ifdef CR_ARB_texture_cube_map
+ case GL_TEXTURE_CUBE_MAP_ARB:
+ if (!g->extensions.ARB_texture_cube_map) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "Invalid target passed to glBindTexture: %d", target);
+ return;
+ }
+ t->unit[t->curTextureUnit].currentTextureCubeMap = &(t->baseCubeMap);
+ break;
+#endif
+#ifdef CR_NV_texture_rectangle
+ case GL_TEXTURE_RECTANGLE_NV:
+ if (!g->extensions.NV_texture_rectangle) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "Invalid target passed to glBindTexture: %d", target);
+ return;
+ }
+ t->unit[t->curTextureUnit].currentTextureRect = &(t->baseRect);
+ break;
+#endif
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid target passed to glBindTexture: %d", target);
+ return;
+ }
+
+ DIRTY(tb->dirty, g->neg_bitid);
+ DIRTY(tb->current[t->curTextureUnit], g->neg_bitid);
+ return;
+ }
+
+ /* texture != 0 */
+ /* Get the texture */
+ GET_TOBJ(tobj, g, texture);
+ if (!tobj)
+ {
+ Assert(crHashtableIsKeyUsed(g->shared->textureTable, texture));
+ tobj = crStateTextureAllocate_t(g, texture);
+ }
+
+ CR_STATE_SHAREDOBJ_USAGE_SET(tobj, g);
+
+ /* Check the targets */
+ if (tobj->target == GL_NONE)
+ {
+ /* Target isn't set so set it now.*/
+ tobj->target = target;
+ }
+ else if ((tobj->target != target)
+ && !((target==GL_TEXTURE_RECTANGLE_NV && tobj->target==GL_TEXTURE_2D)
+ ||(target==GL_TEXTURE_2D && tobj->target==GL_TEXTURE_RECTANGLE_NV)))
+ {
+ crWarning( "You called glBindTexture with a target of 0x%x, but the texture you wanted was target 0x%x [1D: %x 2D: %x 3D: %x cube: %x]", (int) target, (int) tobj->target, GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP );
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "Attempt to bind a texture of different dimensions");
+ return;
+ }
+
+ /* Set the current texture */
+ switch (target)
+ {
+ case GL_TEXTURE_1D:
+ t->unit[t->curTextureUnit].currentTexture1D = tobj;
+ break;
+ case GL_TEXTURE_2D:
+ t->unit[t->curTextureUnit].currentTexture2D = tobj;
+ break;
+#ifdef CR_OPENGL_VERSION_1_2
+ case GL_TEXTURE_3D:
+ t->unit[t->curTextureUnit].currentTexture3D = tobj;
+ break;
+#endif
+#ifdef CR_ARB_texture_cube_map
+ case GL_TEXTURE_CUBE_MAP_ARB:
+ t->unit[t->curTextureUnit].currentTextureCubeMap = tobj;
+ break;
+#endif
+#ifdef CR_NV_texture_rectangle
+ case GL_TEXTURE_RECTANGLE_NV:
+ t->unit[t->curTextureUnit].currentTextureRect = tobj;
+ break;
+#endif
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "Invalid target passed to glBindTexture: %d", target);
+ return;
+ }
+
+ DIRTY(tb->dirty, g->neg_bitid);
+ DIRTY(tb->current[t->curTextureUnit], g->neg_bitid);
+}
+
+
+void STATE_APIENTRY
+crStateTexParameterfv(GLenum target, GLenum pname, const GLfloat *param)
+{
+ CRContext *g = GetCurrentContext();
+ CRTextureObj *tobj = NULL;
+ CRTextureLevel *tl = NULL;
+ GLenum e = (GLenum) *param;
+ CRStateBits *sb = GetCurrentBits();
+ CRTextureBits *tb = &(sb->texture);
+ unsigned int i;
+
+ FLUSH();
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "TexParameterfv called in Begin/End");
+ return;
+ }
+
+ crStateGetTextureObjectAndImage(g, target, 0, &tobj, &tl);
+ if (!tobj) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "TexParamterfv(invalid target=0x%x)", target);
+ return;
+ }
+
+ switch (pname)
+ {
+ case GL_TEXTURE_MIN_FILTER:
+ if (e != GL_NEAREST &&
+ e != GL_LINEAR &&
+ e != GL_NEAREST_MIPMAP_NEAREST &&
+ e != GL_LINEAR_MIPMAP_NEAREST &&
+ e != GL_NEAREST_MIPMAP_LINEAR &&
+ e != GL_LINEAR_MIPMAP_LINEAR)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "TexParamterfv: GL_TEXTURE_MIN_FILTER invalid param: %d", e);
+ return;
+ }
+ tobj->minFilter = e;
+ break;
+ case GL_TEXTURE_MAG_FILTER:
+ if (e != GL_NEAREST && e != GL_LINEAR)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "TexParamterfv: GL_TEXTURE_MAG_FILTER invalid param: %d", e);
+ return;
+ }
+ tobj->magFilter = e;
+ break;
+ case GL_TEXTURE_WRAP_S:
+ if (e == GL_CLAMP || e == GL_REPEAT) {
+ tobj->wrapS = e;
+ }
+#ifdef CR_OPENGL_VERSION_1_2
+ else if (e == GL_CLAMP_TO_EDGE) {
+ tobj->wrapS = e;
+ }
+#endif
+#ifdef GL_CLAMP_TO_EDGE_EXT
+ else if (e == GL_CLAMP_TO_EDGE_EXT && g->extensions.EXT_texture_edge_clamp) {
+ tobj->wrapS = e;
+ }
+#endif
+#ifdef CR_ARB_texture_border_clamp
+ else if (e == GL_CLAMP_TO_BORDER_ARB && g->extensions.ARB_texture_border_clamp) {
+ tobj->wrapS = e;
+ }
+#endif
+#ifdef CR_ARB_texture_mirrored_repeat
+ else if (e == GL_MIRRORED_REPEAT_ARB && g->extensions.ARB_texture_mirrored_repeat) {
+ tobj->wrapS = e;
+ }
+#endif
+#ifdef CR_ATI_texture_mirror_once
+ else if ((e == GL_MIRROR_CLAMP_ATI || e == GL_MIRROR_CLAMP_TO_EDGE_ATI) && g->extensions.ATI_texture_mirror_once) {
+ tobj->wrapS = e;
+ }
+#endif
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "TexParameterfv: GL_TEXTURE_WRAP_S invalid param: 0x%x", e);
+ return;
+ }
+ break;
+ case GL_TEXTURE_WRAP_T:
+ if (e == GL_CLAMP || e == GL_REPEAT) {
+ tobj->wrapT = e;
+ }
+#ifdef CR_OPENGL_VERSION_1_2
+ else if (e == GL_CLAMP_TO_EDGE) {
+ tobj->wrapT = e;
+ }
+#endif
+#ifdef GL_CLAMP_TO_EDGE_EXT
+ else if (e == GL_CLAMP_TO_EDGE_EXT && g->extensions.EXT_texture_edge_clamp) {
+ tobj->wrapT = e;
+ }
+#endif
+#ifdef CR_ARB_texture_border_clamp
+ else if (e == GL_CLAMP_TO_BORDER_ARB && g->extensions.ARB_texture_border_clamp) {
+ tobj->wrapT = e;
+ }
+#endif
+#ifdef CR_ARB_texture_mirrored_repeat
+ else if (e == GL_MIRRORED_REPEAT_ARB && g->extensions.ARB_texture_mirrored_repeat) {
+ tobj->wrapT = e;
+ }
+#endif
+#ifdef CR_ATI_texture_mirror_once
+ else if ((e == GL_MIRROR_CLAMP_ATI || e == GL_MIRROR_CLAMP_TO_EDGE_ATI) && g->extensions.ATI_texture_mirror_once) {
+ tobj->wrapT = e;
+ }
+#endif
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "TexParameterfv: GL_TEXTURE_WRAP_T invalid param: 0x%x", e);
+ return;
+ }
+ break;
+#ifdef CR_OPENGL_VERSION_1_2
+ case GL_TEXTURE_WRAP_R:
+ if (e == GL_CLAMP || e == GL_REPEAT) {
+ tobj->wrapR = e;
+ }
+ else if (e == GL_CLAMP_TO_EDGE) {
+ tobj->wrapR = e;
+ }
+#ifdef GL_CLAMP_TO_EDGE_EXT
+ else if (e == GL_CLAMP_TO_EDGE_EXT && g->extensions.EXT_texture_edge_clamp) {
+ tobj->wrapR = e;
+ }
+#endif
+#ifdef CR_ARB_texture_border_clamp
+ else if (e == GL_CLAMP_TO_BORDER_ARB && g->extensions.ARB_texture_border_clamp) {
+ tobj->wrapR = e;
+ }
+#endif
+#ifdef CR_ARB_texture_mirrored_repeat
+ else if (e == GL_MIRRORED_REPEAT_ARB && g->extensions.ARB_texture_mirrored_repeat) {
+ tobj->wrapR = e;
+ }
+#endif
+#ifdef CR_ATI_texture_mirror_once
+ else if ((e == GL_MIRROR_CLAMP_ATI || e == GL_MIRROR_CLAMP_TO_EDGE_ATI) && g->extensions.ATI_texture_mirror_once) {
+ tobj->wrapR = e;
+ }
+#endif
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "TexParameterfv: GL_TEXTURE_WRAP_R invalid param: 0x%x", e);
+ return;
+ }
+ break;
+ case GL_TEXTURE_PRIORITY:
+ tobj->priority = param[0];
+ break;
+ case GL_TEXTURE_MIN_LOD:
+ tobj->minLod = param[0];
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ tobj->maxLod = param[0];
+ break;
+ case GL_TEXTURE_BASE_LEVEL:
+ if (e < 0.0f)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "TexParameterfv: GL_TEXTURE_BASE_LEVEL invalid param: 0x%x", e);
+ return;
+ }
+ tobj->baseLevel = e;
+ break;
+ case GL_TEXTURE_MAX_LEVEL:
+ if (e < 0.0f)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "TexParameterfv: GL_TEXTURE_MAX_LEVEL invalid param: 0x%x", e);
+ return;
+ }
+ tobj->maxLevel = e;
+ break;
+#endif
+ case GL_TEXTURE_BORDER_COLOR:
+ tobj->borderColor.r = param[0];
+ tobj->borderColor.g = param[1];
+ tobj->borderColor.b = param[2];
+ tobj->borderColor.a = param[3];
+ break;
+#ifdef CR_EXT_texture_filter_anisotropic
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ if (g->extensions.EXT_texture_filter_anisotropic) {
+ if (param[0] < 1.0f)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "TexParameterfv: GL_TEXTURE_MAX_ANISOTROPY_EXT called with parameter less than 1: %f", param[0]);
+ return;
+ }
+ tobj->maxAnisotropy = param[0];
+ if (tobj->maxAnisotropy > g->limits.maxTextureAnisotropy)
+ {
+ tobj->maxAnisotropy = g->limits.maxTextureAnisotropy;
+ }
+ }
+ break;
+#endif
+#ifdef CR_ARB_depth_texture
+ case GL_DEPTH_TEXTURE_MODE_ARB:
+ if (g->extensions.ARB_depth_texture) {
+ if (param[0] == GL_LUMINANCE ||
+ param[0] == GL_INTENSITY ||
+ param[0] == GL_ALPHA) {
+ tobj->depthMode = (GLenum) param[0];
+ }
+ else
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "TexParameterfv: GL_DEPTH_TEXTURE_MODE_ARB called with invalid parameter: 0x%x", param[0]);
+ return;
+ }
+ }
+ break;
+#endif
+#ifdef CR_ARB_shadow
+ case GL_TEXTURE_COMPARE_MODE_ARB:
+ if (g->extensions.ARB_shadow) {
+ if (param[0] == GL_NONE ||
+ param[0] == GL_COMPARE_R_TO_TEXTURE_ARB) {
+ tobj->compareMode = (GLenum) param[0];
+ }
+ else
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "TexParameterfv: GL_TEXTURE_COMPARE_MODE_ARB called with invalid parameter: 0x%x", param[0]);
+ return;
+ }
+ }
+ break;
+ case GL_TEXTURE_COMPARE_FUNC_ARB:
+ if (g->extensions.ARB_shadow) {
+ if (param[0] == GL_LEQUAL ||
+ param[0] == GL_GEQUAL) {
+ tobj->compareFunc = (GLenum) param[0];
+ }
+ }
+#ifdef CR_EXT_shadow_funcs
+ else if (g->extensions.EXT_shadow_funcs) {
+ if (param[0] == GL_LEQUAL ||
+ param[0] == GL_GEQUAL ||
+ param[0] == GL_LESS ||
+ param[0] == GL_GREATER ||
+ param[0] == GL_ALWAYS ||
+ param[0] == GL_NEVER ) {
+ tobj->compareFunc = (GLenum) param[0];
+ }
+ }
+#endif
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "TexParameterfv: GL_TEXTURE_COMPARE_FUNC_ARB called with invalid parameter: 0x%x", param[0]);
+ return;
+ }
+ break;
+#endif
+#ifdef CR_ARB_shadow_ambient
+ case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB:
+ if (g->extensions.ARB_shadow_ambient) {
+ tobj->compareFailValue = param[0];
+ }
+ break;
+#endif
+#ifdef CR_SGIS_generate_mipmap
+ case GL_GENERATE_MIPMAP_SGIS:
+ if (g->extensions.SGIS_generate_mipmap) {
+ tobj->generateMipmap = param[0] ? GL_TRUE : GL_FALSE;
+ }
+ break;
+#endif
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "TexParamterfv: Invalid pname: %d", pname);
+ return;
+ }
+
+ DIRTY(tobj->dirty, g->neg_bitid);
+ for (i = 0; i < g->limits.maxTextureUnits; i++)
+ {
+ DIRTY(tobj->paramsBit[i], g->neg_bitid);
+ }
+ DIRTY(tb->dirty, g->neg_bitid);
+}
+
+
+void STATE_APIENTRY
+crStateTexParameteriv(GLenum target, GLenum pname, const GLint *param)
+{
+ GLfloat f_param;
+ GLcolor f_color;
+ switch (pname)
+ {
+ case GL_TEXTURE_MIN_FILTER:
+ case GL_TEXTURE_MAG_FILTER:
+ case GL_TEXTURE_WRAP_S:
+ case GL_TEXTURE_WRAP_T:
+#ifdef CR_OPENGL_VERSION_1_2
+ case GL_TEXTURE_WRAP_R:
+ case GL_TEXTURE_PRIORITY:
+ case GL_TEXTURE_MIN_LOD:
+ case GL_TEXTURE_MAX_LOD:
+ case GL_TEXTURE_BASE_LEVEL:
+ case GL_TEXTURE_MAX_LEVEL:
+#endif
+#ifdef CR_EXT_texture_filter_anisotropic
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+#endif
+#ifdef CR_ARB_depth_texture
+ case GL_DEPTH_TEXTURE_MODE_ARB:
+#endif
+#ifdef CR_ARB_shadow
+ case GL_TEXTURE_COMPARE_MODE_ARB:
+ case GL_TEXTURE_COMPARE_FUNC_ARB:
+#endif
+#ifdef CR_ARB_shadow_ambinet
+ case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB:
+#endif
+#ifdef CR_SGIS_generate_mipmap
+ case GL_GENERATE_MIPMAP_SGIS:
+#endif
+ f_param = (GLfloat) (*param);
+ crStateTexParameterfv( target, pname, &(f_param) );
+ break;
+ case GL_TEXTURE_BORDER_COLOR:
+ f_color.r = ((GLfloat) param[0])/CR_MAXINT;
+ f_color.g = ((GLfloat) param[1])/CR_MAXINT;
+ f_color.b = ((GLfloat) param[2])/CR_MAXINT;
+ f_color.a = ((GLfloat) param[3])/CR_MAXINT;
+ crStateTexParameterfv( target, pname, (const GLfloat *) &(f_color) );
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "TexParamteriv: Invalid pname: %d", pname);
+ return;
+ }
+}
+
+
+void STATE_APIENTRY
+crStateTexParameterf(GLenum target, GLenum pname, GLfloat param)
+{
+ crStateTexParameterfv( target, pname, &param );
+}
+
+
+void STATE_APIENTRY
+crStateTexParameteri(GLenum target, GLenum pname, GLint param) {
+ GLfloat f_param = (GLfloat) param;
+ crStateTexParameterfv( target, pname, &f_param );
+}
+
+
+void STATE_APIENTRY
+crStateTexEnvfv(GLenum target, GLenum pname, const GLfloat *param)
+{
+ CRContext *g = GetCurrentContext();
+ CRTextureState *t = &(g->texture);
+ CRStateBits *sb = GetCurrentBits();
+ CRTextureBits *tb = &(sb->texture);
+ GLenum e;
+ GLcolorf c;
+ GLuint stage = 0;
+
+ (void) stage;
+
+ FLUSH();
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glTexEnvfv called in begin/end");
+ return;
+ }
+
+#if CR_EXT_texture_lod_bias
+ if (target == GL_TEXTURE_FILTER_CONTROL_EXT) {
+ if (!g->extensions.EXT_texture_lod_bias || pname != GL_TEXTURE_LOD_BIAS_EXT) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexEnv");
+ }
+ else {
+ t->unit[t->curTextureUnit].lodBias = *param;
+ DIRTY(tb->envBit[t->curTextureUnit], g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+ }
+ return;
+ }
+ else
+#endif
+#if CR_ARB_point_sprite
+ if (target == GL_POINT_SPRITE_ARB) {
+ if (!g->extensions.ARB_point_sprite || pname != GL_COORD_REPLACE_ARB) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexEnv");
+ }
+ else {
+ CRPointBits *pb = &(sb->point);
+ g->point.coordReplacement[t->curTextureUnit] = *param ? GL_TRUE : GL_FALSE;
+ DIRTY(pb->coordReplacement[t->curTextureUnit], g->neg_bitid);
+ DIRTY(pb->dirty, g->neg_bitid);
+ }
+ return;
+ }
+ else
+#endif
+ if (target != GL_TEXTURE_ENV)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glTexEnvfv: target != GL_TEXTURE_ENV: %d", target);
+ return;
+ }
+
+ switch (pname)
+ {
+ case GL_TEXTURE_ENV_MODE:
+ e = (GLenum) *param;
+ if (e != GL_MODULATE &&
+ e != GL_DECAL &&
+ e != GL_BLEND &&
+ e != GL_ADD &&
+ e != GL_REPLACE &&
+ e != GL_COMBINE_ARB)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glTexEnvfv: invalid param: %f", *param);
+ return;
+ }
+ t->unit[t->curTextureUnit].envMode = e;
+ break;
+ case GL_TEXTURE_ENV_COLOR:
+ c.r = param[0];
+ c.g = param[1];
+ c.b = param[2];
+ c.a = param[3];
+ if (c.r > 1.0f) c.r = 1.0f;
+ if (c.g > 1.0f) c.g = 1.0f;
+ if (c.b > 1.0f) c.b = 1.0f;
+ if (c.a > 1.0f) c.a = 1.0f;
+ if (c.r < 0.0f) c.r = 0.0f;
+ if (c.g < 0.0f) c.g = 0.0f;
+ if (c.b < 0.0f) c.b = 0.0f;
+ if (c.a < 0.0f) c.a = 0.0f;
+ t->unit[t->curTextureUnit].envColor = c;
+ break;
+
+#ifdef CR_ARB_texture_env_combine
+ case GL_COMBINE_RGB_ARB:
+ e = (GLenum) (GLint) *param;
+ if (g->extensions.ARB_texture_env_combine &&
+ (e == GL_REPLACE ||
+ e == GL_MODULATE ||
+ e == GL_ADD ||
+ e == GL_ADD_SIGNED_ARB ||
+ e == GL_INTERPOLATE_ARB ||
+ e == GL_SUBTRACT_ARB)) {
+ t->unit[t->curTextureUnit].combineModeRGB = e;
+ }
+#ifdef CR_ARB_texture_env_dot3
+ else if (g->extensions.ARB_texture_env_dot3 &&
+ (e == GL_DOT3_RGB_ARB ||
+ e == GL_DOT3_RGBA_ARB ||
+ e == GL_DOT3_RGB_EXT ||
+ e == GL_DOT3_RGBA_EXT)) {
+ t->unit[t->curTextureUnit].combineModeRGB = e;
+ }
+#endif
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexEnvfv(param=0x%x", e);
+ return;
+ }
+ break;
+ case GL_COMBINE_ALPHA_EXT:
+ e = (GLenum) *param;
+ if (g->extensions.ARB_texture_env_combine &&
+ (e == GL_REPLACE ||
+ e == GL_MODULATE ||
+ e == GL_ADD ||
+ e == GL_ADD_SIGNED_ARB ||
+ e == GL_INTERPOLATE_ARB ||
+ e == GL_SUBTRACT_ARB)) {
+ t->unit[t->curTextureUnit].combineModeA = e;
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexEnvfv");
+ return;
+ }
+ break;
+ case GL_SOURCE0_RGB_ARB:
+ case GL_SOURCE1_RGB_ARB:
+ case GL_SOURCE2_RGB_ARB:
+ e = (GLenum) *param;
+ stage = pname - GL_SOURCE0_RGB_ARB;
+ if (g->extensions.ARB_texture_env_combine &&
+ (e == GL_TEXTURE ||
+ e == GL_CONSTANT_ARB ||
+ e == GL_PRIMARY_COLOR_ARB ||
+ e == GL_PREVIOUS_ARB)) {
+ t->unit[t->curTextureUnit].combineSourceRGB[stage] = e;
+ }
+ else if (g->extensions.ARB_texture_env_crossbar &&
+ e >= GL_TEXTURE0_ARB &&
+ e < GL_TEXTURE0_ARB + g->limits.maxTextureUnits) {
+ t->unit[t->curTextureUnit].combineSourceRGB[stage] = e;
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexEnvfv");
+ return;
+ }
+ break;
+ case GL_SOURCE0_ALPHA_ARB:
+ case GL_SOURCE1_ALPHA_ARB:
+ case GL_SOURCE2_ALPHA_ARB:
+ e = (GLenum) *param;
+ stage = pname - GL_SOURCE0_ALPHA_ARB;
+ if (g->extensions.ARB_texture_env_combine &&
+ (e == GL_TEXTURE ||
+ e == GL_CONSTANT_ARB ||
+ e == GL_PRIMARY_COLOR_ARB ||
+ e == GL_PREVIOUS_ARB)) {
+ t->unit[t->curTextureUnit].combineSourceA[stage] = e;
+ }
+ else if (g->extensions.ARB_texture_env_crossbar &&
+ e >= GL_TEXTURE0_ARB &&
+ e < GL_TEXTURE0_ARB + g->limits.maxTextureUnits) {
+ t->unit[t->curTextureUnit].combineSourceA[stage] = e;
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexEnvfv");
+ return;
+ }
+ break;
+ case GL_OPERAND0_RGB_ARB:
+ case GL_OPERAND1_RGB_ARB:
+ case GL_OPERAND2_RGB_ARB:
+ e = (GLenum) *param;
+ stage = pname - GL_OPERAND0_RGB_ARB;
+ if (g->extensions.ARB_texture_env_combine &&
+ (e == GL_SRC_COLOR ||
+ e == GL_ONE_MINUS_SRC_COLOR ||
+ e == GL_SRC_ALPHA ||
+ e == GL_ONE_MINUS_SRC_ALPHA)) {
+ t->unit[t->curTextureUnit].combineOperandRGB[stage] = e;
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexEnvfv");
+ return;
+ }
+ break;
+ case GL_OPERAND0_ALPHA_ARB:
+ case GL_OPERAND1_ALPHA_ARB:
+ case GL_OPERAND2_ALPHA_ARB:
+ e = (GLenum) *param;
+ stage = pname - GL_OPERAND0_ALPHA_ARB;
+ if (g->extensions.ARB_texture_env_combine &&
+ (e == GL_SRC_ALPHA ||
+ e == GL_ONE_MINUS_SRC_ALPHA)) {
+ t->unit[t->curTextureUnit].combineOperandA[stage] = e;
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexEnvfv(param=0x%x)", e);
+ return;
+ }
+ break;
+ case GL_RGB_SCALE_ARB:
+ if (g->extensions.ARB_texture_env_combine &&
+ (*param == 1.0 ||
+ *param == 2.0 ||
+ *param == 4.0)) {
+ t->unit[t->curTextureUnit].combineScaleRGB = *param;
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glTexEnvfv");
+ return;
+ }
+ break;
+ case GL_ALPHA_SCALE:
+ if (g->extensions.ARB_texture_env_combine &&
+ (*param == 1.0 ||
+ *param == 2.0 ||
+ *param == 4.0)) {
+ t->unit[t->curTextureUnit].combineScaleA = *param;
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glTexEnvfv");
+ return;
+ }
+ break;
+#endif /* CR_ARB_texture_env_combine */
+
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glTexEnvfv: invalid pname: %d", pname);
+ return;
+ }
+
+ DIRTY(tb->envBit[t->curTextureUnit], g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+}
+
+
+void STATE_APIENTRY
+crStateTexEnviv(GLenum target, GLenum pname, const GLint *param)
+{
+ GLfloat f_param;
+ GLcolor f_color;
+
+ switch (pname) {
+ case GL_TEXTURE_ENV_MODE:
+ f_param = (GLfloat) (*param);
+ crStateTexEnvfv( target, pname, &f_param );
+ break;
+ case GL_TEXTURE_ENV_COLOR:
+ f_color.r = ((GLfloat) param[0]) / CR_MAXINT;
+ f_color.g = ((GLfloat) param[1]) / CR_MAXINT;
+ f_color.b = ((GLfloat) param[2]) / CR_MAXINT;
+ f_color.a = ((GLfloat) param[3]) / CR_MAXINT;
+ crStateTexEnvfv( target, pname, (const GLfloat *) &f_color );
+ break;
+#ifdef CR_ARB_texture_env_combine
+ case GL_COMBINE_RGB_ARB:
+ case GL_COMBINE_ALPHA_EXT:
+ case GL_SOURCE0_RGB_ARB:
+ case GL_SOURCE1_RGB_ARB:
+ case GL_SOURCE2_RGB_ARB:
+ case GL_SOURCE0_ALPHA_ARB:
+ case GL_SOURCE1_ALPHA_ARB:
+ case GL_SOURCE2_ALPHA_ARB:
+ case GL_OPERAND0_RGB_ARB:
+ case GL_OPERAND1_RGB_ARB:
+ case GL_OPERAND2_RGB_ARB:
+ case GL_OPERAND0_ALPHA_ARB:
+ case GL_OPERAND1_ALPHA_ARB:
+ case GL_OPERAND2_ALPHA_ARB:
+ case GL_RGB_SCALE_ARB:
+ case GL_ALPHA_SCALE:
+ f_param = (GLfloat) (*param);
+ crStateTexEnvfv( target, pname, &f_param );
+ break;
+#endif
+#ifdef CR_EXT_texture_lod_bias
+ case GL_TEXTURE_LOD_BIAS_EXT:
+ f_param = (GLfloat) (*param);
+ crStateTexEnvfv( target, pname, &f_param);
+ break;
+#endif
+#ifdef CR_ARB_point_sprite
+ case GL_COORD_REPLACE_ARB:
+ f_param = (GLfloat) *param;
+ crStateTexEnvfv( target, pname, &f_param);
+ break;
+#endif
+
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glTexEnvfv: invalid pname: %d", pname);
+ return;
+ }
+}
+
+
+void STATE_APIENTRY
+crStateTexEnvf(GLenum target, GLenum pname, GLfloat param)
+{
+ crStateTexEnvfv( target, pname, &param );
+}
+
+
+void STATE_APIENTRY
+crStateTexEnvi(GLenum target, GLenum pname, GLint param)
+{
+ GLfloat f_param = (GLfloat) param;
+ crStateTexEnvfv( target, pname, &f_param );
+}
+
+
+void STATE_APIENTRY
+crStateGetTexEnvfv(GLenum target, GLenum pname, GLfloat *param)
+{
+ CRContext *g = GetCurrentContext();
+ CRTextureState *t = &(g->texture);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__,GL_INVALID_OPERATION,
+ "glGetTexEnvfv called in begin/end");
+ return;
+ }
+
+#if CR_EXT_texture_lod_bias
+ if (target == GL_TEXTURE_FILTER_CONTROL_EXT) {
+ if (!g->extensions.EXT_texture_lod_bias || pname != GL_TEXTURE_LOD_BIAS_EXT) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnv");
+ }
+ else {
+ *param = t->unit[t->curTextureUnit].lodBias;
+ }
+ return;
+ }
+ else
+#endif
+#if CR_ARB_point_sprite
+ if (target == GL_POINT_SPRITE_ARB) {
+ if (!g->extensions.ARB_point_sprite || pname != GL_COORD_REPLACE_ARB) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnv");
+ }
+ else {
+ *param = (GLfloat) g->point.coordReplacement[t->curTextureUnit];
+ }
+ return;
+ }
+ else
+#endif
+ if (target != GL_TEXTURE_ENV)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetTexEnvfv: target != GL_TEXTURE_ENV: %d", target);
+ return;
+ }
+
+ switch (pname) {
+ case GL_TEXTURE_ENV_MODE:
+ *param = (GLfloat) t->unit[t->curTextureUnit].envMode;
+ break;
+ case GL_TEXTURE_ENV_COLOR:
+ param[0] = t->unit[t->curTextureUnit].envColor.r;
+ param[1] = t->unit[t->curTextureUnit].envColor.g;
+ param[2] = t->unit[t->curTextureUnit].envColor.b;
+ param[3] = t->unit[t->curTextureUnit].envColor.a;
+ break;
+ case GL_COMBINE_RGB_ARB:
+ if (g->extensions.ARB_texture_env_combine) {
+ *param = (GLfloat) t->unit[t->curTextureUnit].combineModeRGB;
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ return;
+ }
+ break;
+ case GL_COMBINE_ALPHA_ARB:
+ if (g->extensions.ARB_texture_env_combine) {
+ *param = (GLfloat) t->unit[t->curTextureUnit].combineModeA;
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ return;
+ }
+ break;
+ case GL_SOURCE0_RGB_ARB:
+ if (g->extensions.ARB_texture_env_combine) {
+ *param = (GLfloat) t->unit[t->curTextureUnit].combineSourceRGB[0];
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ return;
+ }
+ break;
+ case GL_SOURCE1_RGB_ARB:
+ if (g->extensions.ARB_texture_env_combine) {
+ *param = (GLfloat) t->unit[t->curTextureUnit].combineSourceRGB[1];
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ return;
+ }
+ break;
+ case GL_SOURCE2_RGB_ARB:
+ if (g->extensions.ARB_texture_env_combine) {
+ *param = (GLfloat) t->unit[t->curTextureUnit].combineSourceRGB[2];
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ return;
+ }
+ break;
+ case GL_SOURCE0_ALPHA_ARB:
+ if (g->extensions.ARB_texture_env_combine) {
+ *param = (GLfloat) t->unit[t->curTextureUnit].combineSourceA[0];
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ return;
+ }
+ break;
+ case GL_SOURCE1_ALPHA_ARB:
+ if (g->extensions.ARB_texture_env_combine) {
+ *param = (GLfloat) t->unit[t->curTextureUnit].combineSourceA[1];
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ return;
+ }
+ break;
+ case GL_SOURCE2_ALPHA_ARB:
+ if (g->extensions.ARB_texture_env_combine) {
+ *param = (GLfloat) t->unit[t->curTextureUnit].combineSourceA[2];
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ return;
+ }
+ break;
+ case GL_OPERAND0_RGB_ARB:
+ if (g->extensions.ARB_texture_env_combine) {
+ *param = (GLfloat) t->unit[t->curTextureUnit].combineOperandRGB[0];
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ return;
+ }
+ break;
+ case GL_OPERAND1_RGB_ARB:
+ if (g->extensions.ARB_texture_env_combine) {
+ *param = (GLfloat) t->unit[t->curTextureUnit].combineOperandRGB[1];
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ return;
+ }
+ break;
+ case GL_OPERAND2_RGB_ARB:
+ if (g->extensions.ARB_texture_env_combine) {
+ *param = (GLfloat) t->unit[t->curTextureUnit].combineOperandRGB[2];
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ return;
+ }
+ break;
+ case GL_OPERAND0_ALPHA_ARB:
+ if (g->extensions.ARB_texture_env_combine) {
+ *param = (GLfloat) t->unit[t->curTextureUnit].combineOperandA[0];
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ return;
+ }
+ break;
+ case GL_OPERAND1_ALPHA_ARB:
+ if (g->extensions.ARB_texture_env_combine) {
+ *param = (GLfloat) t->unit[t->curTextureUnit].combineOperandA[1];
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ return;
+ }
+ break;
+ case GL_OPERAND2_ALPHA_ARB:
+ if (g->extensions.ARB_texture_env_combine) {
+ *param = (GLfloat) t->unit[t->curTextureUnit].combineOperandA[2];
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ return;
+ }
+ break;
+ case GL_RGB_SCALE_ARB:
+ if (g->extensions.ARB_texture_env_combine) {
+ *param = t->unit[t->curTextureUnit].combineScaleRGB;
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ return;
+ }
+ break;
+ case GL_ALPHA_SCALE:
+ if (g->extensions.ARB_texture_env_combine) {
+ *param = t->unit[t->curTextureUnit].combineScaleA;
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ return;
+ }
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetTexEnvfv: invalid pname: %d", pname);
+ return;
+ }
+}
+
+
+void STATE_APIENTRY
+crStateGetTexEnviv(GLenum target, GLenum pname, GLint *param)
+{
+ CRContext *g = GetCurrentContext();
+ CRTextureState *t = &(g->texture);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__,GL_INVALID_OPERATION,
+ "glGetTexEnviv called in begin/end");
+ return;
+ }
+
+#if CR_EXT_texture_lod_bias
+ if (target == GL_TEXTURE_FILTER_CONTROL_EXT) {
+ if (!g->extensions.EXT_texture_lod_bias || pname != GL_TEXTURE_LOD_BIAS_EXT) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnv");
+ }
+ else {
+ *param = (GLint) t->unit[t->curTextureUnit].lodBias;
+ }
+ return;
+ }
+ else
+#endif
+#if CR_ARB_point_sprite
+ if (target == GL_POINT_SPRITE_ARB) {
+ if (!g->extensions.ARB_point_sprite || pname != GL_COORD_REPLACE_ARB) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnv");
+ }
+ else {
+ *param = (GLint) g->point.coordReplacement[t->curTextureUnit];
+ }
+ return;
+ }
+ else
+#endif
+ if (target != GL_TEXTURE_ENV)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetTexEnviv: target != GL_TEXTURE_ENV: %d", target);
+ return;
+ }
+
+ switch (pname) {
+ case GL_TEXTURE_ENV_MODE:
+ *param = (GLint) t->unit[t->curTextureUnit].envMode;
+ break;
+ case GL_TEXTURE_ENV_COLOR:
+ param[0] = (GLint) (t->unit[t->curTextureUnit].envColor.r * CR_MAXINT);
+ param[1] = (GLint) (t->unit[t->curTextureUnit].envColor.g * CR_MAXINT);
+ param[2] = (GLint) (t->unit[t->curTextureUnit].envColor.b * CR_MAXINT);
+ param[3] = (GLint) (t->unit[t->curTextureUnit].envColor.a * CR_MAXINT);
+ break;
+ case GL_COMBINE_RGB_ARB:
+ if (g->extensions.ARB_texture_env_combine) {
+ *param = (GLint) t->unit[t->curTextureUnit].combineModeRGB;
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
+ return;
+ }
+ break;
+ case GL_COMBINE_ALPHA_ARB:
+ if (g->extensions.ARB_texture_env_combine) {
+ *param = (GLint) t->unit[t->curTextureUnit].combineModeA;
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
+ return;
+ }
+ break;
+ case GL_SOURCE0_RGB_ARB:
+ if (g->extensions.ARB_texture_env_combine) {
+ *param = (GLint) t->unit[t->curTextureUnit].combineSourceRGB[0];
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
+ return;
+ }
+ break;
+ case GL_SOURCE1_RGB_ARB:
+ if (g->extensions.ARB_texture_env_combine) {
+ *param = (GLint) t->unit[t->curTextureUnit].combineSourceRGB[1];
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
+ return;
+ }
+ break;
+ case GL_SOURCE2_RGB_ARB:
+ if (g->extensions.ARB_texture_env_combine) {
+ *param = (GLint) t->unit[t->curTextureUnit].combineSourceRGB[2];
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
+ return;
+ }
+ break;
+ case GL_SOURCE0_ALPHA_ARB:
+ if (g->extensions.ARB_texture_env_combine) {
+ *param = (GLint) t->unit[t->curTextureUnit].combineSourceA[0];
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
+ return;
+ }
+ break;
+ case GL_SOURCE1_ALPHA_ARB:
+ if (g->extensions.ARB_texture_env_combine) {
+ *param = (GLint) t->unit[t->curTextureUnit].combineSourceA[1];
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
+ return;
+ }
+ break;
+ case GL_SOURCE2_ALPHA_ARB:
+ if (g->extensions.ARB_texture_env_combine) {
+ *param = (GLint) t->unit[t->curTextureUnit].combineSourceA[2];
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
+ return;
+ }
+ break;
+ case GL_OPERAND0_RGB_ARB:
+ if (g->extensions.ARB_texture_env_combine) {
+ *param = (GLint) t->unit[t->curTextureUnit].combineOperandRGB[0];
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
+ return;
+ }
+ break;
+ case GL_OPERAND1_RGB_ARB:
+ if (g->extensions.ARB_texture_env_combine) {
+ *param = (GLint) t->unit[t->curTextureUnit].combineOperandRGB[1];
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
+ return;
+ }
+ break;
+ case GL_OPERAND2_RGB_ARB:
+ if (g->extensions.ARB_texture_env_combine) {
+ *param = (GLint) t->unit[t->curTextureUnit].combineOperandRGB[2];
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
+ return;
+ }
+ break;
+ case GL_OPERAND0_ALPHA_ARB:
+ if (g->extensions.ARB_texture_env_combine) {
+ *param = (GLint) t->unit[t->curTextureUnit].combineOperandA[0];
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
+ return;
+ }
+ break;
+ case GL_OPERAND1_ALPHA_ARB:
+ if (g->extensions.ARB_texture_env_combine) {
+ *param = (GLint) t->unit[t->curTextureUnit].combineOperandA[1];
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
+ return;
+ }
+ break;
+ case GL_OPERAND2_ALPHA_ARB:
+ if (g->extensions.ARB_texture_env_combine) {
+ *param = (GLint) t->unit[t->curTextureUnit].combineOperandA[2];
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
+ return;
+ }
+ break;
+ case GL_RGB_SCALE_ARB:
+ if (g->extensions.ARB_texture_env_combine) {
+ *param = (GLint) t->unit[t->curTextureUnit].combineScaleRGB;
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
+ return;
+ }
+ break;
+ case GL_ALPHA_SCALE:
+ if (g->extensions.ARB_texture_env_combine) {
+ *param = (GLint) t->unit[t->curTextureUnit].combineScaleA;
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
+ return;
+ }
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetTexEnviv: invalid pname: %d", pname);
+ return;
+ }
+}
+
+
+void STATE_APIENTRY
+crStateTexGendv(GLenum coord, GLenum pname, const GLdouble *param)
+{
+ CRContext *g = GetCurrentContext();
+ CRTextureState *t = &(g->texture);
+ CRTransformState *trans = &(g->transform);
+ GLvectorf v;
+ GLenum e;
+ CRmatrix inv;
+ CRStateBits *sb = GetCurrentBits();
+ CRTextureBits *tb = &(sb->texture);
+
+ FLUSH();
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glTexGen called in begin/end");
+ return;
+ }
+
+ switch (coord)
+ {
+ case GL_S:
+ switch (pname)
+ {
+ case GL_TEXTURE_GEN_MODE:
+ e = (GLenum) *param;
+ if (e == GL_OBJECT_LINEAR ||
+ e == GL_EYE_LINEAR ||
+ e == GL_SPHERE_MAP
+#if defined(GL_ARB_texture_cube_map) || defined(GL_EXT_texture_cube_map) || defined(GL_NV_texgen_reflection)
+ || ((e == GL_REFLECTION_MAP_ARB || e == GL_NORMAL_MAP_ARB)
+ && g->extensions.ARB_texture_cube_map)
+#endif
+ ) {
+ t->unit[t->curTextureUnit].gen.s = e;
+ DIRTY(tb->genMode[t->curTextureUnit], g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glTexGendv called with bad param: %lf", *param);
+ return;
+ }
+ break;
+ case GL_OBJECT_PLANE:
+ v.x = (GLfloat) param[0];
+ v.y = (GLfloat) param[1];
+ v.z = (GLfloat) param[2];
+ v.w = (GLfloat) param[3];
+ t->unit[t->curTextureUnit].objSCoeff = v;
+ DIRTY(tb->objGen[t->curTextureUnit], g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+ break;
+ case GL_EYE_PLANE:
+ v.x = (GLfloat) param[0];
+ v.y = (GLfloat) param[1];
+ v.z = (GLfloat) param[2];
+ v.w = (GLfloat) param[3];
+ crMatrixInvertTranspose(&inv, trans->modelViewStack.top);
+ crStateTransformXformPointMatrixf(&inv, &v);
+ t->unit[t->curTextureUnit].eyeSCoeff = v;
+ DIRTY(tb->eyeGen[t->curTextureUnit], g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glTexGendv called with bogus pname: %d", pname);
+ return;
+ }
+ break;
+ case GL_T:
+ switch (pname) {
+ case GL_TEXTURE_GEN_MODE:
+ e = (GLenum) *param;
+ if (e == GL_OBJECT_LINEAR ||
+ e == GL_EYE_LINEAR ||
+ e == GL_SPHERE_MAP
+#if defined(GL_ARB_texture_cube_map) || defined(GL_EXT_texture_cube_map) || defined(GL_NV_texgen_reflection)
+ || ((e == GL_REFLECTION_MAP_ARB || e == GL_NORMAL_MAP_ARB)
+ && g->extensions.ARB_texture_cube_map)
+#endif
+ ) {
+ t->unit[t->curTextureUnit].gen.t = e;
+ DIRTY(tb->genMode[t->curTextureUnit], g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glTexGendv called with bad param: %lf", *param);
+ return;
+ }
+ break;
+ case GL_OBJECT_PLANE:
+ v.x = (GLfloat) param[0];
+ v.y = (GLfloat) param[1];
+ v.z = (GLfloat) param[2];
+ v.w = (GLfloat) param[3];
+ t->unit[t->curTextureUnit].objTCoeff = v;
+ DIRTY(tb->objGen[t->curTextureUnit], g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+ break;
+ case GL_EYE_PLANE:
+ v.x = (GLfloat) param[0];
+ v.y = (GLfloat) param[1];
+ v.z = (GLfloat) param[2];
+ v.w = (GLfloat) param[3];
+ crMatrixInvertTranspose(&inv, trans->modelViewStack.top);
+ crStateTransformXformPointMatrixf(&inv, &v);
+ t->unit[t->curTextureUnit].eyeTCoeff = v;
+ DIRTY(tb->eyeGen[t->curTextureUnit], g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glTexGen called with bogus pname: %d", pname);
+ return;
+ }
+ break;
+ case GL_R:
+ switch (pname) {
+ case GL_TEXTURE_GEN_MODE:
+ e = (GLenum) *param;
+ if (e == GL_OBJECT_LINEAR ||
+ e == GL_EYE_LINEAR ||
+ e == GL_SPHERE_MAP
+#if defined(GL_ARB_texture_cube_map) || defined(GL_EXT_texture_cube_map) || defined(GL_NV_texgen_reflection)
+ || ((e == GL_REFLECTION_MAP_ARB || e == GL_NORMAL_MAP_ARB)
+ && g->extensions.ARB_texture_cube_map)
+#endif
+ ) {
+ t->unit[t->curTextureUnit].gen.r = e;
+ DIRTY(tb->genMode[t->curTextureUnit], g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glTexGen called with bad param: %lf", *param);
+ return;
+ }
+ break;
+ case GL_OBJECT_PLANE:
+ v.x = (GLfloat) param[0];
+ v.y = (GLfloat) param[1];
+ v.z = (GLfloat) param[2];
+ v.w = (GLfloat) param[3];
+ t->unit[t->curTextureUnit].objRCoeff = v;
+ DIRTY(tb->objGen[t->curTextureUnit], g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+ break;
+ case GL_EYE_PLANE:
+ v.x = (GLfloat) param[0];
+ v.y = (GLfloat) param[1];
+ v.z = (GLfloat) param[2];
+ v.w = (GLfloat) param[3];
+ crMatrixInvertTranspose(&inv, trans->modelViewStack.top);
+ crStateTransformXformPointMatrixf(&inv, &v);
+ t->unit[t->curTextureUnit].eyeRCoeff = v;
+ DIRTY(tb->eyeGen[t->curTextureUnit], g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glTexGen called with bogus pname: %d", pname);
+ return;
+ }
+ break;
+ case GL_Q:
+ switch (pname) {
+ case GL_TEXTURE_GEN_MODE:
+ e = (GLenum) *param;
+ if (e == GL_OBJECT_LINEAR ||
+ e == GL_EYE_LINEAR ||
+ e == GL_SPHERE_MAP
+#if defined(GL_ARB_texture_cube_map) || defined(GL_EXT_texture_cube_map) || defined(GL_NV_texgen_reflection)
+ || ((e == GL_REFLECTION_MAP_ARB || e == GL_NORMAL_MAP_ARB)
+ && g->extensions.ARB_texture_cube_map)
+#endif
+ ) {
+ t->unit[t->curTextureUnit].gen.q = e;
+ DIRTY(tb->genMode[t->curTextureUnit], g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glTexGen called with bad param: %lf", *param);
+ return;
+ }
+ break;
+ case GL_OBJECT_PLANE:
+ v.x = (GLfloat) param[0];
+ v.y = (GLfloat) param[1];
+ v.z = (GLfloat) param[2];
+ v.w = (GLfloat) param[3];
+ t->unit[t->curTextureUnit].objQCoeff = v;
+ DIRTY(tb->objGen[t->curTextureUnit], g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+ break;
+ case GL_EYE_PLANE:
+ v.x = (GLfloat) param[0];
+ v.y = (GLfloat) param[1];
+ v.z = (GLfloat) param[2];
+ v.w = (GLfloat) param[3];
+ crMatrixInvertTranspose(&inv, trans->modelViewStack.top);
+ crStateTransformXformPointMatrixf(&inv, &v);
+ t->unit[t->curTextureUnit].eyeQCoeff = v;
+ DIRTY(tb->eyeGen[t->curTextureUnit], g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glTexGen called with bogus pname: %d", pname);
+ return;
+ }
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glTexGen called with bogus coord: %d", coord);
+ return;
+ }
+}
+
+
+void STATE_APIENTRY
+crStateTexGenfv(GLenum coord, GLenum pname, const GLfloat *param)
+{
+ GLdouble d_param;
+ GLvectord d_vector;
+ switch (pname)
+ {
+ case GL_TEXTURE_GEN_MODE:
+ d_param = (GLdouble) *param;
+ crStateTexGendv( coord, pname, &d_param );
+ break;
+ case GL_OBJECT_PLANE:
+ case GL_EYE_PLANE:
+ d_vector.x = (GLdouble) param[0];
+ d_vector.y = (GLdouble) param[1];
+ d_vector.z = (GLdouble) param[2];
+ d_vector.w = (GLdouble) param[3];
+ crStateTexGendv( coord, pname, (const double *) &d_vector );
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glTexGen called with bogus pname: %d", pname);
+ return;
+ }
+}
+
+
+void STATE_APIENTRY
+crStateTexGeniv(GLenum coord, GLenum pname, const GLint *param)
+{
+ GLdouble d_param;
+ GLvectord d_vector;
+ switch (pname)
+ {
+ case GL_TEXTURE_GEN_MODE:
+ d_param = (GLdouble) *param;
+ crStateTexGendv( coord, pname, &d_param );
+ break;
+ case GL_OBJECT_PLANE:
+ case GL_EYE_PLANE:
+ d_vector.x = (GLdouble) param[0];
+ d_vector.y = (GLdouble) param[1];
+ d_vector.z = (GLdouble) param[2];
+ d_vector.w = (GLdouble) param[3];
+ crStateTexGendv( coord, pname, (const double *) &d_vector );
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glTexGen called with bogus pname: %d", pname);
+ return;
+ }
+}
+
+
+void STATE_APIENTRY
+crStateTexGend (GLenum coord, GLenum pname, GLdouble param)
+{
+ crStateTexGendv( coord, pname, &param );
+}
+
+
+void STATE_APIENTRY
+crStateTexGenf(GLenum coord, GLenum pname, GLfloat param)
+{
+ GLdouble d_param = (GLdouble) param;
+ crStateTexGendv( coord, pname, &d_param );
+}
+
+
+void STATE_APIENTRY
+crStateTexGeni(GLenum coord, GLenum pname, GLint param)
+{
+ GLdouble d_param = (GLdouble) param;
+ crStateTexGendv( coord, pname, &d_param );
+}
+
+
+void STATE_APIENTRY
+crStateGetTexGendv(GLenum coord, GLenum pname, GLdouble *param)
+{
+ CRContext *g = GetCurrentContext();
+ CRTextureState *t = &(g->texture);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetTexGen called in begin/end");
+ return;
+ }
+
+ switch (pname) {
+ case GL_TEXTURE_GEN_MODE:
+ switch (coord) {
+ case GL_S:
+ *param = (GLdouble) t->unit[t->curTextureUnit].gen.s;
+ break;
+ case GL_T:
+ *param = (GLdouble) t->unit[t->curTextureUnit].gen.t;
+ break;
+ case GL_R:
+ *param = (GLdouble) t->unit[t->curTextureUnit].gen.r;
+ break;
+ case GL_Q:
+ *param = (GLdouble) t->unit[t->curTextureUnit].gen.q;
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetTexGen called with bogus coord: %d", coord);
+ return;
+ }
+ break;
+ case GL_OBJECT_PLANE:
+ switch (coord) {
+ case GL_S:
+ param[0] = (GLdouble) t->unit[t->curTextureUnit].objSCoeff.x;
+ param[1] = (GLdouble) t->unit[t->curTextureUnit].objSCoeff.y;
+ param[2] = (GLdouble) t->unit[t->curTextureUnit].objSCoeff.z;
+ param[3] = (GLdouble) t->unit[t->curTextureUnit].objSCoeff.w;
+ break;
+ case GL_T:
+ param[0] = (GLdouble) t->unit[t->curTextureUnit].objTCoeff.x;
+ param[1] = (GLdouble) t->unit[t->curTextureUnit].objTCoeff.y;
+ param[2] = (GLdouble) t->unit[t->curTextureUnit].objTCoeff.z;
+ param[3] = (GLdouble) t->unit[t->curTextureUnit].objTCoeff.w;
+ break;
+ case GL_R:
+ param[0] = (GLdouble) t->unit[t->curTextureUnit].objRCoeff.x;
+ param[1] = (GLdouble) t->unit[t->curTextureUnit].objRCoeff.y;
+ param[2] = (GLdouble) t->unit[t->curTextureUnit].objRCoeff.z;
+ param[3] = (GLdouble) t->unit[t->curTextureUnit].objRCoeff.w;
+ break;
+ case GL_Q:
+ param[0] = (GLdouble) t->unit[t->curTextureUnit].objQCoeff.x;
+ param[1] = (GLdouble) t->unit[t->curTextureUnit].objQCoeff.y;
+ param[2] = (GLdouble) t->unit[t->curTextureUnit].objQCoeff.z;
+ param[3] = (GLdouble) t->unit[t->curTextureUnit].objQCoeff.w;
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetTexGen called with bogus coord: %d", coord);
+ return;
+ }
+ break;
+ case GL_EYE_PLANE:
+ switch (coord) {
+ case GL_S:
+ param[0] = (GLdouble) t->unit[t->curTextureUnit].eyeSCoeff.x;
+ param[1] = (GLdouble) t->unit[t->curTextureUnit].eyeSCoeff.y;
+ param[2] = (GLdouble) t->unit[t->curTextureUnit].eyeSCoeff.z;
+ param[3] = (GLdouble) t->unit[t->curTextureUnit].eyeSCoeff.w;
+ break;
+ case GL_T:
+ param[0] = (GLdouble) t->unit[t->curTextureUnit].eyeTCoeff.x;
+ param[1] = (GLdouble) t->unit[t->curTextureUnit].eyeTCoeff.y;
+ param[2] = (GLdouble) t->unit[t->curTextureUnit].eyeTCoeff.z;
+ param[3] = (GLdouble) t->unit[t->curTextureUnit].eyeTCoeff.w;
+ break;
+ case GL_R:
+ param[0] = (GLdouble) t->unit[t->curTextureUnit].eyeRCoeff.x;
+ param[1] = (GLdouble) t->unit[t->curTextureUnit].eyeRCoeff.y;
+ param[2] = (GLdouble) t->unit[t->curTextureUnit].eyeRCoeff.z;
+ param[3] = (GLdouble) t->unit[t->curTextureUnit].eyeRCoeff.w;
+ break;
+ case GL_Q:
+ param[0] = (GLdouble) t->unit[t->curTextureUnit].eyeQCoeff.x;
+ param[1] = (GLdouble) t->unit[t->curTextureUnit].eyeQCoeff.y;
+ param[2] = (GLdouble) t->unit[t->curTextureUnit].eyeQCoeff.z;
+ param[3] = (GLdouble) t->unit[t->curTextureUnit].eyeQCoeff.w;
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetTexGen called with bogus coord: %d", coord);
+ return;
+ }
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetTexGen called with bogus pname: %d", pname);
+ return;
+ }
+}
+
+
+void STATE_APIENTRY
+crStateGetTexGenfv(GLenum coord, GLenum pname, GLfloat *param)
+{
+ CRContext *g = GetCurrentContext();
+ CRTextureState *t = &(g->texture);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetTexGenfv called in begin/end");
+ return;
+ }
+
+ switch (pname) {
+ case GL_TEXTURE_GEN_MODE:
+ switch (coord) {
+ case GL_S:
+ *param = (GLfloat) t->unit[t->curTextureUnit].gen.s;
+ break;
+ case GL_T:
+ *param = (GLfloat) t->unit[t->curTextureUnit].gen.t;
+ break;
+ case GL_R:
+ *param = (GLfloat) t->unit[t->curTextureUnit].gen.r;
+ break;
+ case GL_Q:
+ *param = (GLfloat) t->unit[t->curTextureUnit].gen.q;
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetTexGenfv called with bogus coord: %d", coord);
+ return;
+ }
+ break;
+ case GL_OBJECT_PLANE:
+ switch (coord) {
+ case GL_S:
+ param[0] = t->unit[t->curTextureUnit].objSCoeff.x;
+ param[1] = t->unit[t->curTextureUnit].objSCoeff.y;
+ param[2] = t->unit[t->curTextureUnit].objSCoeff.z;
+ param[3] = t->unit[t->curTextureUnit].objSCoeff.w;
+ break;
+ case GL_T:
+ param[0] = t->unit[t->curTextureUnit].objTCoeff.x;
+ param[1] = t->unit[t->curTextureUnit].objTCoeff.y;
+ param[2] = t->unit[t->curTextureUnit].objTCoeff.z;
+ param[3] = t->unit[t->curTextureUnit].objTCoeff.w;
+ break;
+ case GL_R:
+ param[0] = t->unit[t->curTextureUnit].objRCoeff.x;
+ param[1] = t->unit[t->curTextureUnit].objRCoeff.y;
+ param[2] = t->unit[t->curTextureUnit].objRCoeff.z;
+ param[3] = t->unit[t->curTextureUnit].objRCoeff.w;
+ break;
+ case GL_Q:
+ param[0] = t->unit[t->curTextureUnit].objQCoeff.x;
+ param[1] = t->unit[t->curTextureUnit].objQCoeff.y;
+ param[2] = t->unit[t->curTextureUnit].objQCoeff.z;
+ param[3] = t->unit[t->curTextureUnit].objQCoeff.w;
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetTexGenfv called with bogus coord: %d", coord);
+ return;
+ }
+ break;
+ case GL_EYE_PLANE:
+ switch (coord) {
+ case GL_S:
+ param[0] = t->unit[t->curTextureUnit].eyeSCoeff.x;
+ param[1] = t->unit[t->curTextureUnit].eyeSCoeff.y;
+ param[2] = t->unit[t->curTextureUnit].eyeSCoeff.z;
+ param[3] = t->unit[t->curTextureUnit].eyeSCoeff.w;
+ break;
+ case GL_T:
+ param[0] = t->unit[t->curTextureUnit].eyeTCoeff.x;
+ param[1] = t->unit[t->curTextureUnit].eyeTCoeff.y;
+ param[2] = t->unit[t->curTextureUnit].eyeTCoeff.z;
+ param[3] = t->unit[t->curTextureUnit].eyeTCoeff.w;
+ break;
+ case GL_R:
+ param[0] = t->unit[t->curTextureUnit].eyeRCoeff.x;
+ param[1] = t->unit[t->curTextureUnit].eyeRCoeff.y;
+ param[2] = t->unit[t->curTextureUnit].eyeRCoeff.z;
+ param[3] = t->unit[t->curTextureUnit].eyeRCoeff.w;
+ break;
+ case GL_Q:
+ param[0] = t->unit[t->curTextureUnit].eyeQCoeff.x;
+ param[1] = t->unit[t->curTextureUnit].eyeQCoeff.y;
+ param[2] = t->unit[t->curTextureUnit].eyeQCoeff.z;
+ param[3] = t->unit[t->curTextureUnit].eyeQCoeff.w;
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetTexGenfv called with bogus coord: %d", coord);
+ return;
+ }
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetTexGenfv called with bogus pname: %d", pname);
+ return;
+ }
+}
+
+
+void STATE_APIENTRY
+crStateGetTexGeniv(GLenum coord, GLenum pname, GLint *param)
+{
+ CRContext *g = GetCurrentContext();
+ CRTextureState *t = &(g->texture);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetTexGeniv called in begin/end");
+ return;
+ }
+
+ switch (pname) {
+ case GL_TEXTURE_GEN_MODE:
+ switch (coord) {
+ case GL_S:
+ *param = (GLint) t->unit[t->curTextureUnit].gen.s;
+ break;
+ case GL_T:
+ *param = (GLint) t->unit[t->curTextureUnit].gen.t;
+ break;
+ case GL_R:
+ *param = (GLint) t->unit[t->curTextureUnit].gen.r;
+ break;
+ case GL_Q:
+ *param = (GLint) t->unit[t->curTextureUnit].gen.q;
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetTexGeniv called with bogus coord: %d", coord);
+ return;
+ }
+ break;
+ case GL_OBJECT_PLANE:
+ switch (coord) {
+ case GL_S:
+ param[0] = (GLint) t->unit[t->curTextureUnit].objSCoeff.x;
+ param[1] = (GLint) t->unit[t->curTextureUnit].objSCoeff.y;
+ param[2] = (GLint) t->unit[t->curTextureUnit].objSCoeff.z;
+ param[3] = (GLint) t->unit[t->curTextureUnit].objSCoeff.w;
+ break;
+ case GL_T:
+ param[0] = (GLint) t->unit[t->curTextureUnit].objTCoeff.x;
+ param[1] = (GLint) t->unit[t->curTextureUnit].objTCoeff.y;
+ param[2] = (GLint) t->unit[t->curTextureUnit].objTCoeff.z;
+ param[3] = (GLint) t->unit[t->curTextureUnit].objTCoeff.w;
+ break;
+ case GL_R:
+ param[0] = (GLint) t->unit[t->curTextureUnit].objRCoeff.x;
+ param[1] = (GLint) t->unit[t->curTextureUnit].objRCoeff.y;
+ param[2] = (GLint) t->unit[t->curTextureUnit].objRCoeff.z;
+ param[3] = (GLint) t->unit[t->curTextureUnit].objRCoeff.w;
+ break;
+ case GL_Q:
+ param[0] = (GLint) t->unit[t->curTextureUnit].objQCoeff.x;
+ param[1] = (GLint) t->unit[t->curTextureUnit].objQCoeff.y;
+ param[2] = (GLint) t->unit[t->curTextureUnit].objQCoeff.z;
+ param[3] = (GLint) t->unit[t->curTextureUnit].objQCoeff.w;
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetTexGeniv called with bogus coord: %d", coord);
+ return;
+ }
+ break;
+ case GL_EYE_PLANE:
+ switch (coord) {
+ case GL_S:
+ param[0] = (GLint) t->unit[t->curTextureUnit].eyeSCoeff.x;
+ param[1] = (GLint) t->unit[t->curTextureUnit].eyeSCoeff.y;
+ param[2] = (GLint) t->unit[t->curTextureUnit].eyeSCoeff.z;
+ param[3] = (GLint) t->unit[t->curTextureUnit].eyeSCoeff.w;
+ break;
+ case GL_T:
+ param[0] = (GLint) t->unit[t->curTextureUnit].eyeTCoeff.x;
+ param[1] = (GLint) t->unit[t->curTextureUnit].eyeTCoeff.y;
+ param[2] = (GLint) t->unit[t->curTextureUnit].eyeTCoeff.z;
+ param[3] = (GLint) t->unit[t->curTextureUnit].eyeTCoeff.w;
+ break;
+ case GL_R:
+ param[0] = (GLint) t->unit[t->curTextureUnit].eyeRCoeff.x;
+ param[1] = (GLint) t->unit[t->curTextureUnit].eyeRCoeff.y;
+ param[2] = (GLint) t->unit[t->curTextureUnit].eyeRCoeff.z;
+ param[3] = (GLint) t->unit[t->curTextureUnit].eyeRCoeff.w;
+ break;
+ case GL_Q:
+ param[0] = (GLint) t->unit[t->curTextureUnit].eyeQCoeff.x;
+ param[1] = (GLint) t->unit[t->curTextureUnit].eyeQCoeff.y;
+ param[2] = (GLint) t->unit[t->curTextureUnit].eyeQCoeff.z;
+ param[3] = (GLint) t->unit[t->curTextureUnit].eyeQCoeff.w;
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetTexGeniv called with bogus coord: %d", coord);
+ return;
+ }
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetTexGen called with bogus pname: %d", pname);
+ return;
+ }
+}
+
+
+void STATE_APIENTRY
+crStateGetTexLevelParameterfv(GLenum target, GLint level,
+ GLenum pname, GLfloat *params)
+{
+ CRContext *g = GetCurrentContext();
+ CRTextureState *t = &(g->texture);
+ CRTextureObj *tobj;
+ CRTextureLevel *timg;
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetTexLevelParameterfv called in begin/end");
+ return;
+ }
+
+ if (level < 0 || level > t->maxLevel)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glGetTexLevelParameterfv: Invalid level: %d", level);
+ return;
+ }
+
+ crStateGetTextureObjectAndImage(g, target, level, &tobj, &timg);
+ if (!timg)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "GetTexLevelParameterfv: invalid target: 0x%x or level %d",
+ target, level);
+ return;
+ }
+
+ switch (pname)
+ {
+ case GL_TEXTURE_WIDTH:
+ *params = (GLfloat) timg->width;
+ break;
+ case GL_TEXTURE_HEIGHT:
+ *params = (GLfloat) timg->height;
+ break;
+#ifdef CR_OPENGL_VERSION_1_2
+ case GL_TEXTURE_DEPTH:
+ *params = (GLfloat) timg->depth;
+ break;
+#endif
+ case GL_TEXTURE_INTERNAL_FORMAT:
+ *params = (GLfloat) timg->internalFormat;
+ break;
+ case GL_TEXTURE_BORDER:
+ *params = (GLfloat) timg->border;
+ break;
+ case GL_TEXTURE_RED_SIZE:
+ *params = (GLfloat) timg->texFormat->redbits;
+ break;
+ case GL_TEXTURE_GREEN_SIZE:
+ *params = (GLfloat) timg->texFormat->greenbits;
+ break;
+ case GL_TEXTURE_BLUE_SIZE:
+ *params = (GLfloat) timg->texFormat->bluebits;
+ break;
+ case GL_TEXTURE_ALPHA_SIZE:
+ *params = (GLfloat) timg->texFormat->alphabits;
+ break;
+ case GL_TEXTURE_INTENSITY_SIZE:
+ *params = (GLfloat) timg->texFormat->intensitybits;
+ break;
+ case GL_TEXTURE_LUMINANCE_SIZE:
+ *params = (GLfloat) timg->texFormat->luminancebits;
+ break;
+#if CR_ARB_texture_compression
+ case GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB:
+ *params = (GLfloat) timg->bytes;
+ break;
+ case GL_TEXTURE_COMPRESSED_ARB:
+ *params = (GLfloat) timg->compressed;
+ break;
+#endif
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "GetTexLevelParameterfv: invalid pname: 0x%x",
+ pname);
+ return;
+ }
+}
+
+
+void STATE_APIENTRY
+crStateGetTexLevelParameteriv(GLenum target, GLint level,
+ GLenum pname, GLint *params)
+{
+ CRContext *g = GetCurrentContext();
+ CRTextureState *t = &(g->texture);
+ CRTextureObj *tobj;
+ CRTextureLevel *timg;
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetTexLevelParameteriv called in begin/end");
+ return;
+ }
+
+ if (level < 0 || level > t->maxLevel)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glGetTexLevelParameteriv: Invalid level: %d", level);
+ return;
+ }
+
+ crStateGetTextureObjectAndImage(g, target, level, &tobj, &timg);
+ if (!timg)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "GetTexLevelParameteriv: invalid target: 0x%x",
+ target);
+ return;
+ }
+
+ switch (pname)
+ {
+ case GL_TEXTURE_WIDTH:
+ *params = (GLint) timg->width;
+ break;
+ case GL_TEXTURE_HEIGHT:
+ *params = (GLint) timg->height;
+ break;
+#ifdef CR_OPENGL_VERSION_1_2
+ case GL_TEXTURE_DEPTH:
+ *params = (GLint) timg->depth;
+ break;
+#endif
+ case GL_TEXTURE_INTERNAL_FORMAT:
+ *params = (GLint) timg->internalFormat;
+ break;
+ case GL_TEXTURE_BORDER:
+ *params = (GLint) timg->border;
+ break;
+ case GL_TEXTURE_RED_SIZE:
+ *params = (GLint) timg->texFormat->redbits;
+ break;
+ case GL_TEXTURE_GREEN_SIZE:
+ *params = (GLint) timg->texFormat->greenbits;
+ break;
+ case GL_TEXTURE_BLUE_SIZE:
+ *params = (GLint) timg->texFormat->bluebits;
+ break;
+ case GL_TEXTURE_ALPHA_SIZE:
+ *params = (GLint) timg->texFormat->alphabits;
+ break;
+ case GL_TEXTURE_INTENSITY_SIZE:
+ *params = (GLint) timg->texFormat->intensitybits;
+ break;
+ case GL_TEXTURE_LUMINANCE_SIZE:
+ *params = (GLint) timg->texFormat->luminancebits;
+ break;
+
+#if 0
+ /* XXX TODO */
+ case GL_TEXTURE_DEPTH_SIZE:
+ *params = (GLint) timg->texFormat->depthSize;
+ break;
+#endif
+#if CR_ARB_texture_compression
+ case GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB:
+ *params = (GLint) timg->bytes;
+ break;
+ case GL_TEXTURE_COMPRESSED_ARB:
+ *params = (GLint) timg->compressed;
+ break;
+#endif
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "GetTexLevelParameteriv: invalid pname: 0x%x",
+ pname);
+ return;
+ }
+}
+
+
+void STATE_APIENTRY
+crStateGetTexParameterfv(GLenum target, GLenum pname, GLfloat *params)
+{
+ CRContext *g = GetCurrentContext();
+ CRTextureObj *tobj;
+ CRTextureLevel *tl;
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetTexParameterfv called in begin/end");
+ return;
+ }
+
+ crStateGetTextureObjectAndImage(g, target, 0, &tobj, &tl);
+ if (!tobj)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetTexParameterfv: invalid target: 0x%x", target);
+ return;
+ }
+
+ switch (pname)
+ {
+ case GL_TEXTURE_MAG_FILTER:
+ *params = (GLfloat) tobj->magFilter;
+ break;
+ case GL_TEXTURE_MIN_FILTER:
+ *params = (GLfloat) tobj->minFilter;
+ break;
+ case GL_TEXTURE_WRAP_S:
+ *params = (GLfloat) tobj->wrapS;
+ break;
+ case GL_TEXTURE_WRAP_T:
+ *params = (GLfloat) tobj->wrapT;
+ break;
+#ifdef CR_OPENGL_VERSION_1_2
+ case GL_TEXTURE_WRAP_R:
+ *params = (GLfloat) tobj->wrapR;
+ break;
+ case GL_TEXTURE_PRIORITY:
+ *params = (GLfloat) tobj->priority;
+ break;
+#endif
+ case GL_TEXTURE_BORDER_COLOR:
+ params[0] = tobj->borderColor.r;
+ params[1] = tobj->borderColor.g;
+ params[2] = tobj->borderColor.b;
+ params[3] = tobj->borderColor.a;
+ break;
+#ifdef CR_EXT_texture_filter_anisotropic
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ if (g->extensions.EXT_texture_filter_anisotropic) {
+ *params = (GLfloat) tobj->maxAnisotropy;
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetTexParameterfv: invalid pname: 0x%x", pname);
+ return;
+ }
+ break;
+#endif
+#ifdef CR_ARB_depth_texture
+ case GL_DEPTH_TEXTURE_MODE_ARB:
+ if (g->extensions.ARB_depth_texture) {
+ *params = (GLfloat) tobj->depthMode;
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetTexParameter: invalid pname: 0x%x", pname);
+ return;
+ }
+ break;
+#endif
+#ifdef CR_ARB_shadow
+ case GL_TEXTURE_COMPARE_MODE_ARB:
+ if (g->extensions.ARB_shadow) {
+ *params = (GLfloat) tobj->compareMode;
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetTexParameter: invalid pname: 0x%x", pname);
+ return;
+ }
+ break;
+ case GL_TEXTURE_COMPARE_FUNC_ARB:
+ if (g->extensions.ARB_shadow) {
+ *params = (GLfloat) tobj->compareFunc;
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetTexParameter: invalid pname: 0x%x", pname);
+ return;
+ }
+ break;
+#endif
+#ifdef CR_ARB_shadow_ambient
+ case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB:
+ if (g->extensions.ARB_shadow_ambient) {
+ *params = (GLfloat) tobj->compareFailValue;
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetTexParameter: invalid pname: 0x%x", pname);
+ return;
+ }
+ break;
+#endif
+#ifdef CR_SGIS_generate_mipmap
+ case GL_GENERATE_MIPMAP_SGIS:
+ if (g->extensions.SGIS_generate_mipmap) {
+ *params = (GLfloat) tobj->generateMipmap;
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetTexParameter: invalid pname: 0x%x", pname);
+ return;
+ }
+ break;
+#endif
+#ifdef CR_OPENGL_VERSION_1_2
+ case GL_TEXTURE_MIN_LOD:
+ *params = (GLfloat) tobj->minLod;
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ *params = (GLfloat) tobj->maxLod;
+ break;
+ case GL_TEXTURE_BASE_LEVEL:
+ *params = (GLfloat) tobj->baseLevel;
+ break;
+ case GL_TEXTURE_MAX_LEVEL:
+ *params = (GLfloat) tobj->maxLevel;
+ break;
+#endif
+#if 0
+ case GL_TEXTURE_LOD_BIAS_EXT:
+ /* XXX todo */
+ *params = (GLfloat) tobj->lodBias;
+ break;
+#endif
+ case GL_TEXTURE_RESIDENT:
+ /* XXX todo */
+ crWarning("glGetTexParameterfv GL_TEXTURE_RESIDENT is unimplemented");
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetTexParameterfv: invalid pname: %d", pname);
+ return;
+ }
+}
+
+
+void STATE_APIENTRY
+crStateGetTexParameteriv(GLenum target, GLenum pname, GLint *params)
+{
+ CRContext *g = GetCurrentContext();
+ CRTextureObj *tobj;
+ CRTextureLevel *tl;
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetTexParameter called in begin/end");
+ return;
+ }
+
+ crStateGetTextureObjectAndImage(g, target, 0, &tobj, &tl);
+ if (!tobj)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetTexParameteriv: invalid target: 0x%x", target);
+ return;
+ }
+
+ switch (pname)
+ {
+ case GL_TEXTURE_MAG_FILTER:
+ *params = (GLint) tobj->magFilter;
+ break;
+ case GL_TEXTURE_MIN_FILTER:
+ *params = (GLint) tobj->minFilter;
+ break;
+ case GL_TEXTURE_WRAP_S:
+ *params = (GLint) tobj->wrapS;
+ break;
+ case GL_TEXTURE_WRAP_T:
+ *params = (GLint) tobj->wrapT;
+ break;
+#ifdef CR_OPENGL_VERSION_1_2
+ case GL_TEXTURE_WRAP_R:
+ *params = (GLint) tobj->wrapR;
+ break;
+ case GL_TEXTURE_PRIORITY:
+ *params = (GLint) tobj->priority;
+ break;
+#endif
+ case GL_TEXTURE_BORDER_COLOR:
+ params[0] = (GLint) (tobj->borderColor.r * CR_MAXINT);
+ params[1] = (GLint) (tobj->borderColor.g * CR_MAXINT);
+ params[2] = (GLint) (tobj->borderColor.b * CR_MAXINT);
+ params[3] = (GLint) (tobj->borderColor.a * CR_MAXINT);
+ break;
+#ifdef CR_OPENGL_VERSION_1_2
+ case GL_TEXTURE_MIN_LOD:
+ *params = (GLint) tobj->minLod;
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ *params = (GLint) tobj->maxLod;
+ break;
+ case GL_TEXTURE_BASE_LEVEL:
+ *params = (GLint) tobj->baseLevel;
+ break;
+ case GL_TEXTURE_MAX_LEVEL:
+ *params = (GLint) tobj->maxLevel;
+ break;
+#endif
+#ifdef CR_EXT_texture_filter_anisotropic
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ if (g->extensions.EXT_texture_filter_anisotropic) {
+ *params = (GLint) tobj->maxAnisotropy;
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetTexParameter: invalid pname: 0x%x", pname);
+ return;
+ }
+ break;
+#endif
+#ifdef CR_ARB_depth_texture
+ case GL_DEPTH_TEXTURE_MODE_ARB:
+ if (g->extensions.ARB_depth_texture) {
+ *params = (GLint) tobj->depthMode;
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetTexParameter: invalid pname: 0x%x", pname);
+ return;
+ }
+ break;
+#endif
+#ifdef CR_ARB_shadow
+ case GL_TEXTURE_COMPARE_MODE_ARB:
+ if (g->extensions.ARB_shadow) {
+ *params = (GLint) tobj->compareMode;
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetTexParameter: invalid pname: 0x%x", pname);
+ return;
+ }
+ break;
+ case GL_TEXTURE_COMPARE_FUNC_ARB:
+ if (g->extensions.ARB_shadow) {
+ *params = (GLint) tobj->compareFunc;
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetTexParameter: invalid pname: 0x%x", pname);
+ return;
+ }
+ break;
+#endif
+#ifdef CR_ARB_shadow_ambient
+ case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB:
+ if (g->extensions.ARB_shadow_ambient) {
+ *params = (GLint) tobj->compareFailValue;
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetTexParameter: invalid pname: 0x%x", pname);
+ return;
+ }
+ break;
+#endif
+#ifdef CR_SGIS_generate_mipmap
+ case GL_GENERATE_MIPMAP_SGIS:
+ if (g->extensions.SGIS_generate_mipmap) {
+ *params = (GLint) tobj->generateMipmap;
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetTexParameter: invalid pname: 0x%x", pname);
+ return;
+ }
+ break;
+#endif
+ case GL_TEXTURE_RESIDENT:
+ /* XXX todo */
+ crWarning("glGetTexParameteriv GL_TEXTURE_RESIDENT is unimplemented");
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glGetTexParameter: invalid pname: %d", pname);
+ return;
+ }
+}
+
+
+void STATE_APIENTRY
+crStatePrioritizeTextures(GLsizei n, const GLuint *textures,
+ const GLclampf *priorities)
+{
+ CRContext *g = GetCurrentContext();
+ CRTextureObj *tobj;
+ GLsizei i;
+ UNUSED(priorities);
+
+ 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;
+}
+
+
+GLboolean STATE_APIENTRY
+crStateAreTexturesResident(GLsizei n, const GLuint *textures,
+ GLboolean *residences)
+{
+ UNUSED(n);
+ UNUSED(textures);
+ UNUSED(residences);
+ /** @todo */
+ return GL_TRUE;
+}
+
+
+GLboolean STATE_APIENTRY
+crStateIsTexture(GLuint texture)
+{
+ CRContext *g = GetCurrentContext();
+ CRTextureObj *tobj;
+
+ GET_TOBJ(tobj, g, texture);
+ return tobj != NULL;
+}
+
+static void crStateCheckTextureHWIDCB(unsigned long key, void *data1, void *data2)
+{
+ CRTextureObj *pTex = (CRTextureObj *) data1;
+ crCheckIDHWID_t *pParms = (crCheckIDHWID_t*) data2;
+ (void) key;
+
+ if (crStateGetTextureObjHWID(pTex)==pParms->hwid)
+ pParms->id = pTex->id;
+}
+
+DECLEXPORT(GLuint) STATE_APIENTRY crStateTextureHWIDtoID(GLuint hwid)
+{
+ CRContext *g = GetCurrentContext();
+ crCheckIDHWID_t parms;
+
+ parms.id = hwid;
+ parms.hwid = hwid;
+
+ crHashtableWalk(g->shared->textureTable, crStateCheckTextureHWIDCB, &parms);
+ return parms.id;
+}
+
+DECLEXPORT(GLuint) STATE_APIENTRY crStateGetTextureHWID(GLuint id)
+{
+ CRContext *g = GetCurrentContext();
+ CRTextureObj *tobj;
+
+ GET_TOBJ(tobj, g, id);
+
+#ifdef DEBUG_misha
+ if (id)
+ {
+ Assert(tobj);
+ }
+ else
+ {
+ Assert(!tobj);
+ }
+ if (tobj)
+ {
+/* crDebug("tex id(%d), hwid(%d)", tobj->id, tobj->hwid);*/
+ }
+#endif
+
+
+ return tobj ? crStateGetTextureObjHWID(tobj) : 0;
+}
+
+DECLEXPORT(GLuint) STATE_APIENTRY crStateGetTextureObjHWID(CRTextureObj *tobj)
+{
+ CRASSERT(tobj);
+
+#ifndef IN_GUEST
+ if (tobj->id && !tobj->hwid)
+ {
+ CRASSERT(diff_api.GenTextures);
+ diff_api.GenTextures(1, &tobj->hwid);
+#if 0 /*def DEBUG_misha*/
+ crDebug("tex id(%d), hwid(%d)", tobj->id, tobj->hwid);
+#endif
+ CRASSERT(tobj->hwid);
+ }
+#endif
+
+ return tobj->hwid;
+}
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_transform.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_transform.c
new file mode 100644
index 00000000..642561bd
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_transform.c
@@ -0,0 +1,1392 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#include "cr_bits.h"
+#include "cr_mem.h"
+#include "state.h"
+#include "state/cr_statetypes.h"
+#include "state_internals.h"
+
+#ifdef WINDOWS
+#pragma warning( disable : 4514 )
+#endif
+
+/*
+ * This used to be a macro.
+ */
+static INLINE void
+LOADMATRIX( const CRmatrix *a )
+{
+ if (a->m00 == 1.0F && a->m01 == 0.0F && a->m02 == 0.0F && a->m03 == 0.0F &&
+ a->m10 == 0.0F && a->m11 == 1.0F && a->m12 == 0.0F && a->m13 == 0.0F &&
+ a->m20 == 0.0F && a->m21 == 0.0F && a->m22 == 1.0F && a->m23 == 0.0F &&
+ a->m30 == 0.0F && a->m31 == 0.0F && a->m32 == 0.0F && a->m33 == 1.0F) {
+ diff_api.LoadIdentity();
+ }
+ else {
+ GLfloat f[16];
+ f[0] = a->m00; f[1] = a->m01; f[2] = a->m02; f[3] = a->m03;
+ f[4] = a->m10; f[5] = a->m11; f[6] = a->m12; f[7] = a->m13;
+ f[8] = a->m20; f[9] = a->m21; f[10] = a->m22; f[11] = a->m23;
+ f[12] = a->m30; f[13] = a->m31; f[14] = a->m32; f[15] = a->m33;
+ diff_api.LoadMatrixf(f);
+ }
+}
+
+
+static void _math_transposef( GLfloat to[16], const GLfloat from[16] )
+{
+ to[0] = from[0];
+ to[1] = from[4];
+ to[2] = from[8];
+ to[3] = from[12];
+ to[4] = from[1];
+ to[5] = from[5];
+ to[6] = from[9];
+ to[7] = from[13];
+ to[8] = from[2];
+ to[9] = from[6];
+ to[10] = from[10];
+ to[11] = from[14];
+ to[12] = from[3];
+ to[13] = from[7];
+ to[14] = from[11];
+ to[15] = from[15];
+}
+
+static void _math_transposed( GLdouble to[16], const GLdouble from[16] )
+{
+ to[0] = from[0];
+ to[1] = from[4];
+ to[2] = from[8];
+ to[3] = from[12];
+ to[4] = from[1];
+ to[5] = from[5];
+ to[6] = from[9];
+ to[7] = from[13];
+ to[8] = from[2];
+ to[9] = from[6];
+ to[10] = from[10];
+ to[11] = from[14];
+ to[12] = from[3];
+ to[13] = from[7];
+ to[14] = from[11];
+ to[15] = from[15];
+}
+
+
+void
+crStateInitMatrixStack(CRMatrixStack *stack, int maxDepth)
+{
+ stack->maxDepth = maxDepth;
+ stack->depth = 0;
+ stack->stack = crAlloc(maxDepth * sizeof(CRmatrix));
+ crMatrixInit(&stack->stack[0]);
+ stack->top = stack->stack;
+}
+
+static void
+free_matrix_stack_data(CRMatrixStack *stack)
+{
+ crFree(stack->stack);
+}
+
+void crStateTransformDestroy(CRContext *ctx)
+{
+ CRTransformState *t = &ctx->transform;
+ unsigned int i;
+
+ free_matrix_stack_data(&(t->modelViewStack));
+ free_matrix_stack_data(&(t->projectionStack));
+ free_matrix_stack_data(&(t->colorStack));
+ for (i = 0 ; i < ctx->limits.maxTextureUnits; i++)
+ free_matrix_stack_data(&(t->textureStack[i]));
+ for (i = 0; i < CR_MAX_PROGRAM_MATRICES; i++)
+ free_matrix_stack_data(&(t->programStack[i]));
+
+ crFree( t->clipPlane );
+ crFree( t->clip );
+}
+
+void crStateTransformInit(CRContext *ctx)
+{
+ CRLimitsState *limits = &ctx->limits;
+ CRTransformState *t = &ctx->transform;
+ CRStateBits *sb = GetCurrentBits();
+ CRTransformBits *tb = &(sb->transform);
+ unsigned int i;
+
+ t->matrixMode = GL_MODELVIEW;
+ RESET(tb->matrixMode, ctx->bitid);
+
+ crStateInitMatrixStack(&t->modelViewStack, CR_MAX_MODELVIEW_STACK_DEPTH);
+ crStateInitMatrixStack(&t->projectionStack, CR_MAX_PROJECTION_STACK_DEPTH);
+ crStateInitMatrixStack(&t->colorStack, CR_MAX_COLOR_STACK_DEPTH);
+ for (i = 0 ; i < limits->maxTextureUnits ; i++)
+ crStateInitMatrixStack(&t->textureStack[i], CR_MAX_TEXTURE_STACK_DEPTH);
+ for (i = 0 ; i < CR_MAX_PROGRAM_MATRICES ; i++)
+ crStateInitMatrixStack(&t->programStack[i], CR_MAX_PROGRAM_MATRIX_STACK_DEPTH);
+ t->currentStack = &(t->modelViewStack);
+
+ /* dirty bits */
+ RESET(tb->modelviewMatrix, ctx->bitid);
+ RESET(tb->projectionMatrix, ctx->bitid);
+ RESET(tb->colorMatrix, ctx->bitid);
+ RESET(tb->textureMatrix, ctx->bitid);
+ RESET(tb->programMatrix, ctx->bitid);
+ tb->currentMatrix = tb->modelviewMatrix;
+
+ t->normalize = GL_FALSE;
+ RESET(tb->enable, ctx->bitid);
+
+ t->clipPlane = (GLvectord *) crCalloc (sizeof (GLvectord) * CR_MAX_CLIP_PLANES);
+ t->clip = (GLboolean *) crCalloc (sizeof (GLboolean) * CR_MAX_CLIP_PLANES);
+ for (i = 0; i < CR_MAX_CLIP_PLANES; i++)
+ {
+ t->clipPlane[i].x = 0.0f;
+ t->clipPlane[i].y = 0.0f;
+ t->clipPlane[i].z = 0.0f;
+ t->clipPlane[i].w = 0.0f;
+ t->clip[i] = GL_FALSE;
+ }
+ RESET(tb->clipPlane, ctx->bitid);
+
+#ifdef CR_OPENGL_VERSION_1_2
+ t->rescaleNormals = GL_FALSE;
+#endif
+#ifdef CR_IBM_rasterpos_clip
+ t->rasterPositionUnclipped = GL_FALSE;
+#endif
+
+ t->modelViewProjectionValid = 0;
+
+ RESET(tb->dirty, ctx->bitid);
+}
+
+
+/*
+ * Compute the product of the modelview and projection matrices
+ */
+void crStateTransformUpdateTransform(CRTransformState *t)
+{
+ const CRmatrix *m1 = t->projectionStack.top;
+ const CRmatrix *m2 = t->modelViewStack.top;
+ CRmatrix *m = &(t->modelViewProjection);
+ crMatrixMultiply(m, m1, m2);
+ t->modelViewProjectionValid = 1;
+}
+
+void crStateTransformXformPoint(CRTransformState *t, GLvectorf *p)
+{
+ /* XXX is this flag really needed? We may be covering a bug elsewhere */
+ if (!t->modelViewProjectionValid)
+ crStateTransformUpdateTransform(t);
+
+ crStateTransformXformPointMatrixf(&(t->modelViewProjection), p);
+}
+
+void crStateTransformXformPointMatrixf(const CRmatrix *m, GLvectorf *p)
+{
+ GLfloat x = p->x;
+ GLfloat y = p->y;
+ GLfloat z = p->z;
+ GLfloat w = p->w;
+
+ p->x = m->m00*x + m->m10*y + m->m20*z + m->m30*w;
+ p->y = m->m01*x + m->m11*y + m->m21*z + m->m31*w;
+ p->z = m->m02*x + m->m12*y + m->m22*z + m->m32*w;
+ p->w = m->m03*x + m->m13*y + m->m23*z + m->m33*w;
+}
+
+void crStateTransformXformPointMatrixd(const CRmatrix *m, GLvectord *p)
+{
+ GLdouble x = p->x;
+ GLdouble y = p->y;
+ GLdouble z = p->z;
+ GLdouble w = p->w;
+
+ p->x = (GLdouble) (m->m00*x + m->m10*y + m->m20*z + m->m30*w);
+ p->y = (GLdouble) (m->m01*x + m->m11*y + m->m21*z + m->m31*w);
+ p->z = (GLdouble) (m->m02*x + m->m12*y + m->m22*z + m->m32*w);
+ p->w = (GLdouble) (m->m03*x + m->m13*y + m->m23*z + m->m33*w);
+}
+
+void STATE_APIENTRY crStateClipPlane (GLenum plane, const GLdouble *equation)
+{
+ CRContext *g = GetCurrentContext();
+ CRTransformState *t = &g->transform;
+ CRStateBits *sb = GetCurrentBits();
+ CRTransformBits *tb = &(sb->transform);
+ GLvectord e;
+ unsigned int i;
+ CRmatrix inv;
+
+ e.x = equation[0];
+ e.y = equation[1];
+ e.z = equation[2];
+ e.w = equation[3];
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "ClipPlane called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ i = plane - GL_CLIP_PLANE0;
+ if (i >= g->limits.maxClipPlanes)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "ClipPlane called with bad enumerant: %d", plane);
+ return;
+ }
+
+ crMatrixInvertTranspose(&inv, t->modelViewStack.top);
+ crStateTransformXformPointMatrixd (&inv, &e);
+ t->clipPlane[i] = e;
+ DIRTY(tb->clipPlane, g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateMatrixMode(GLenum e)
+{
+ CRContext *g = GetCurrentContext();
+ CRTransformState *t = &(g->transform);
+ CRTextureState *tex = &(g->texture);
+ CRStateBits *sb = GetCurrentBits();
+ CRTransformBits *tb = &(sb->transform);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "MatrixMode called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ switch (e)
+ {
+ case GL_MODELVIEW:
+ t->currentStack = &(t->modelViewStack);
+ t->matrixMode = GL_MODELVIEW;
+ tb->currentMatrix = tb->modelviewMatrix;
+ break;
+ case GL_PROJECTION:
+ t->currentStack = &(t->projectionStack);
+ t->matrixMode = GL_PROJECTION;
+ tb->currentMatrix = tb->projectionMatrix;
+ break;
+ case GL_TEXTURE:
+ t->currentStack = &(t->textureStack[tex->curTextureUnit]);
+ t->matrixMode = GL_TEXTURE;
+ tb->currentMatrix = tb->textureMatrix;
+ break;
+ case GL_COLOR:
+ t->currentStack = &(t->colorStack);
+ t->matrixMode = GL_COLOR;
+ tb->currentMatrix = tb->colorMatrix;
+ break;
+ case GL_MATRIX0_NV:
+ case GL_MATRIX1_NV:
+ case GL_MATRIX2_NV:
+ case GL_MATRIX3_NV:
+ case GL_MATRIX4_NV:
+ case GL_MATRIX5_NV:
+ case GL_MATRIX6_NV:
+ case GL_MATRIX7_NV:
+ if (g->extensions.NV_vertex_program) {
+ const GLint i = e - GL_MATRIX0_NV;
+ t->currentStack = &(t->programStack[i]);
+ t->matrixMode = e;
+ tb->currentMatrix = tb->programMatrix;
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid matrix mode: %d", e);
+ return;
+ }
+ break;
+ case GL_MATRIX0_ARB:
+ case GL_MATRIX1_ARB:
+ case GL_MATRIX2_ARB:
+ case GL_MATRIX3_ARB:
+ case GL_MATRIX4_ARB:
+ case GL_MATRIX5_ARB:
+ case GL_MATRIX6_ARB:
+ case GL_MATRIX7_ARB:
+ /* Note: the NV and ARB program matrices are the same, but
+ * use different enumerants.
+ */
+ if (g->extensions.ARB_vertex_program) {
+ const GLint i = e - GL_MATRIX0_ARB;
+ t->currentStack = &(t->programStack[i]);
+ t->matrixMode = e;
+ tb->currentMatrix = tb->programMatrix;
+ }
+ else {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid matrix mode: %d", e);
+ return;
+ }
+ break;
+ default:
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid matrix mode: %d", e);
+ return;
+ }
+ DIRTY(tb->matrixMode, g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+
+ CRASSERT(t->currentStack->top == t->currentStack->stack + t->currentStack->depth);
+}
+
+void STATE_APIENTRY crStateLoadIdentity()
+{
+ CRContext *g = GetCurrentContext();
+ CRTransformState *t = &(g->transform);
+ CRStateBits *sb = GetCurrentBits();
+ CRTransformBits *tb = &(sb->transform);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "LoadIdentity called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ crMatrixInit(t->currentStack->top);
+ t->modelViewProjectionValid = 0;
+
+ DIRTY(tb->currentMatrix, g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStatePopMatrix()
+{
+ CRContext *g = GetCurrentContext();
+ CRTransformState *t = &g->transform;
+ CRStateBits *sb = GetCurrentBits();
+ CRTransformBits *tb = &(sb->transform);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "PopMatrix called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ if (t->currentStack->depth == 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "PopMatrix of empty stack.");
+ return;
+ }
+
+ CRASSERT(t->currentStack->top == t->currentStack->stack + t->currentStack->depth);
+
+ t->currentStack->depth--;
+ t->currentStack->top = t->currentStack->stack + t->currentStack->depth;
+
+ t->modelViewProjectionValid = 0;
+
+ DIRTY(tb->currentMatrix, g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStatePushMatrix()
+{
+ CRContext *g = GetCurrentContext();
+ CRTransformState *t = &g->transform;
+ CRStateBits *sb = GetCurrentBits();
+ CRTransformBits *tb = &(sb->transform);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "PushMatrix called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ if (t->currentStack->depth + 1 >= t->currentStack->maxDepth)
+ {
+ crStateError(__LINE__, __FILE__, GL_STACK_OVERFLOW, "PushMatrix pass the end of allocated stack");
+ return;
+ }
+
+ CRASSERT(t->currentStack->top == t->currentStack->stack + t->currentStack->depth);
+ /* Perform the copy */
+ *(t->currentStack->top + 1) = *(t->currentStack->top);
+
+ /* Move the stack pointer */
+ t->currentStack->depth++;
+ t->currentStack->top = t->currentStack->stack + t->currentStack->depth;
+
+ DIRTY(tb->currentMatrix, g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+}
+
+
+/* Load a CRMatrix */
+void crStateLoadMatrix(const CRmatrix *m)
+{
+ CRContext *g = GetCurrentContext();
+ CRTransformState *t = &(g->transform);
+ CRStateBits *sb = GetCurrentBits();
+ CRTransformBits *tb = &(sb->transform);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "LoadMatrix called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ CRASSERT(t->currentStack->top == t->currentStack->stack + t->currentStack->depth);
+ *t->currentStack->top = *m;
+ t->modelViewProjectionValid = 0;
+ DIRTY(tb->currentMatrix, g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+}
+
+
+
+void STATE_APIENTRY crStateLoadMatrixf(const GLfloat *m1)
+{
+ CRContext *g = GetCurrentContext();
+ CRTransformState *t = &(g->transform);
+ CRStateBits *sb = GetCurrentBits();
+ CRTransformBits *tb = &(sb->transform);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "LoadMatrixf called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ crMatrixInitFromFloats(t->currentStack->top, m1);
+ t->modelViewProjectionValid = 0;
+ DIRTY(tb->currentMatrix, g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+}
+
+
+void STATE_APIENTRY crStateLoadMatrixd(const GLdouble *m1)
+{
+ CRContext *g = GetCurrentContext();
+ CRTransformState *t = &(g->transform);
+ CRStateBits *sb = GetCurrentBits();
+ CRTransformBits *tb = &(sb->transform);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "LoadMatrixd called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ crMatrixInitFromDoubles(t->currentStack->top, m1);
+ t->modelViewProjectionValid = 0;
+ DIRTY(tb->currentMatrix, g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+}
+
+
+void STATE_APIENTRY crStateLoadTransposeMatrixfARB(const GLfloat *m1)
+{
+ GLfloat tm[16];
+ if (!m1) return;
+ _math_transposef(tm, m1);
+ crStateLoadMatrixf(tm);
+}
+
+void STATE_APIENTRY crStateLoadTransposeMatrixdARB(const GLdouble *m1)
+{
+ GLdouble tm[16];
+ if (!m1) return;
+ _math_transposed(tm, m1);
+ crStateLoadMatrixd(tm);
+}
+
+/* This code is based on the Pomegranate stuff.
+ ** The theory is that by preloading everything,
+ ** the compiler could do optimizations that
+ ** were not doable in the array version
+ ** I'm not too sure with a PII with 4 registers
+ ** that this really helps.
+ */
+void STATE_APIENTRY crStateMultMatrixf(const GLfloat *m1)
+{
+ CRContext *g = GetCurrentContext();
+ CRTransformState *t = &(g->transform);
+ CRStateBits *sb = GetCurrentBits();
+ CRTransformBits *tb = &(sb->transform);
+ CRmatrix *m = t->currentStack->top;
+
+ const GLdefault lm00 = m->m00;
+ const GLdefault lm01 = m->m01;
+ const GLdefault lm02 = m->m02;
+ const GLdefault lm03 = m->m03;
+ const GLdefault lm10 = m->m10;
+ const GLdefault lm11 = m->m11;
+ const GLdefault lm12 = m->m12;
+ const GLdefault lm13 = m->m13;
+ const GLdefault lm20 = m->m20;
+ const GLdefault lm21 = m->m21;
+ const GLdefault lm22 = m->m22;
+ const GLdefault lm23 = m->m23;
+ const GLdefault lm30 = m->m30;
+ const GLdefault lm31 = m->m31;
+ const GLdefault lm32 = m->m32;
+ const GLdefault lm33 = m->m33;
+ const GLdefault rm00 = (GLdefault) m1[0];
+ const GLdefault rm01 = (GLdefault) m1[1];
+ const GLdefault rm02 = (GLdefault) m1[2];
+ const GLdefault rm03 = (GLdefault) m1[3];
+ const GLdefault rm10 = (GLdefault) m1[4];
+ const GLdefault rm11 = (GLdefault) m1[5];
+ const GLdefault rm12 = (GLdefault) m1[6];
+ const GLdefault rm13 = (GLdefault) m1[7];
+ const GLdefault rm20 = (GLdefault) m1[8];
+ const GLdefault rm21 = (GLdefault) m1[9];
+ const GLdefault rm22 = (GLdefault) m1[10];
+ const GLdefault rm23 = (GLdefault) m1[11];
+ const GLdefault rm30 = (GLdefault) m1[12];
+ const GLdefault rm31 = (GLdefault) m1[13];
+ const GLdefault rm32 = (GLdefault) m1[14];
+ const GLdefault rm33 = (GLdefault) m1[15];
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "MultMatrixf called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ m->m00 = lm00*rm00 + lm10*rm01 + lm20*rm02 + lm30*rm03;
+ m->m01 = lm01*rm00 + lm11*rm01 + lm21*rm02 + lm31*rm03;
+ m->m02 = lm02*rm00 + lm12*rm01 + lm22*rm02 + lm32*rm03;
+ m->m03 = lm03*rm00 + lm13*rm01 + lm23*rm02 + lm33*rm03;
+ m->m10 = lm00*rm10 + lm10*rm11 + lm20*rm12 + lm30*rm13;
+ m->m11 = lm01*rm10 + lm11*rm11 + lm21*rm12 + lm31*rm13;
+ m->m12 = lm02*rm10 + lm12*rm11 + lm22*rm12 + lm32*rm13;
+ m->m13 = lm03*rm10 + lm13*rm11 + lm23*rm12 + lm33*rm13;
+ m->m20 = lm00*rm20 + lm10*rm21 + lm20*rm22 + lm30*rm23;
+ m->m21 = lm01*rm20 + lm11*rm21 + lm21*rm22 + lm31*rm23;
+ m->m22 = lm02*rm20 + lm12*rm21 + lm22*rm22 + lm32*rm23;
+ m->m23 = lm03*rm20 + lm13*rm21 + lm23*rm22 + lm33*rm23;
+ m->m30 = lm00*rm30 + lm10*rm31 + lm20*rm32 + lm30*rm33;
+ m->m31 = lm01*rm30 + lm11*rm31 + lm21*rm32 + lm31*rm33;
+ m->m32 = lm02*rm30 + lm12*rm31 + lm22*rm32 + lm32*rm33;
+ m->m33 = lm03*rm30 + lm13*rm31 + lm23*rm32 + lm33*rm33;
+
+ t->modelViewProjectionValid = 0;
+
+ DIRTY(tb->currentMatrix, g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateMultMatrixd(const GLdouble *m1)
+{
+ CRContext *g = GetCurrentContext();
+ CRTransformState *t = &(g->transform);
+ CRStateBits *sb = GetCurrentBits();
+ CRTransformBits *tb = &(sb->transform);
+ CRmatrix *m = t->currentStack->top;
+ const GLdefault lm00 = m->m00;
+ const GLdefault lm01 = m->m01;
+ const GLdefault lm02 = m->m02;
+ const GLdefault lm03 = m->m03;
+ const GLdefault lm10 = m->m10;
+ const GLdefault lm11 = m->m11;
+ const GLdefault lm12 = m->m12;
+ const GLdefault lm13 = m->m13;
+ const GLdefault lm20 = m->m20;
+ const GLdefault lm21 = m->m21;
+ const GLdefault lm22 = m->m22;
+ const GLdefault lm23 = m->m23;
+ const GLdefault lm30 = m->m30;
+ const GLdefault lm31 = m->m31;
+ const GLdefault lm32 = m->m32;
+ const GLdefault lm33 = m->m33;
+ const GLdefault rm00 = (GLdefault) m1[0];
+ const GLdefault rm01 = (GLdefault) m1[1];
+ const GLdefault rm02 = (GLdefault) m1[2];
+ const GLdefault rm03 = (GLdefault) m1[3];
+ const GLdefault rm10 = (GLdefault) m1[4];
+ const GLdefault rm11 = (GLdefault) m1[5];
+ const GLdefault rm12 = (GLdefault) m1[6];
+ const GLdefault rm13 = (GLdefault) m1[7];
+ const GLdefault rm20 = (GLdefault) m1[8];
+ const GLdefault rm21 = (GLdefault) m1[9];
+ const GLdefault rm22 = (GLdefault) m1[10];
+ const GLdefault rm23 = (GLdefault) m1[11];
+ const GLdefault rm30 = (GLdefault) m1[12];
+ const GLdefault rm31 = (GLdefault) m1[13];
+ const GLdefault rm32 = (GLdefault) m1[14];
+ const GLdefault rm33 = (GLdefault) m1[15];
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "MultMatrixd called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ m->m00 = lm00*rm00 + lm10*rm01 + lm20*rm02 + lm30*rm03;
+ m->m01 = lm01*rm00 + lm11*rm01 + lm21*rm02 + lm31*rm03;
+ m->m02 = lm02*rm00 + lm12*rm01 + lm22*rm02 + lm32*rm03;
+ m->m03 = lm03*rm00 + lm13*rm01 + lm23*rm02 + lm33*rm03;
+ m->m10 = lm00*rm10 + lm10*rm11 + lm20*rm12 + lm30*rm13;
+ m->m11 = lm01*rm10 + lm11*rm11 + lm21*rm12 + lm31*rm13;
+ m->m12 = lm02*rm10 + lm12*rm11 + lm22*rm12 + lm32*rm13;
+ m->m13 = lm03*rm10 + lm13*rm11 + lm23*rm12 + lm33*rm13;
+ m->m20 = lm00*rm20 + lm10*rm21 + lm20*rm22 + lm30*rm23;
+ m->m21 = lm01*rm20 + lm11*rm21 + lm21*rm22 + lm31*rm23;
+ m->m22 = lm02*rm20 + lm12*rm21 + lm22*rm22 + lm32*rm23;
+ m->m23 = lm03*rm20 + lm13*rm21 + lm23*rm22 + lm33*rm23;
+ m->m30 = lm00*rm30 + lm10*rm31 + lm20*rm32 + lm30*rm33;
+ m->m31 = lm01*rm30 + lm11*rm31 + lm21*rm32 + lm31*rm33;
+ m->m32 = lm02*rm30 + lm12*rm31 + lm22*rm32 + lm32*rm33;
+ m->m33 = lm03*rm30 + lm13*rm31 + lm23*rm32 + lm33*rm33;
+
+ t->modelViewProjectionValid = 0;
+
+ DIRTY(tb->currentMatrix, g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateMultTransposeMatrixfARB(const GLfloat *m1)
+{
+ GLfloat tm[16];
+ if (!m1) return;
+ _math_transposef(tm, m1);
+ crStateMultMatrixf(tm);
+}
+
+void STATE_APIENTRY crStateMultTransposeMatrixdARB(const GLdouble *m1)
+{
+ GLdouble tm[16];
+ if (!m1) return;
+ _math_transposed(tm, m1);
+ crStateMultMatrixd(tm);
+}
+
+void STATE_APIENTRY crStateTranslatef(GLfloat x_arg, GLfloat y_arg, GLfloat z_arg)
+{
+ CRContext *g = GetCurrentContext();
+ CRTransformState *t = &(g->transform);
+ CRStateBits *sb = GetCurrentBits();
+ CRTransformBits *tb = &(sb->transform);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "Translatef called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ crMatrixTranslate(t->currentStack->top, x_arg, y_arg, z_arg);
+ t->modelViewProjectionValid = 0;
+ DIRTY(tb->currentMatrix, g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+}
+
+
+void STATE_APIENTRY crStateTranslated(GLdouble x_arg, GLdouble y_arg, GLdouble z_arg)
+{
+ CRContext *g = GetCurrentContext();
+ CRTransformState *t = &(g->transform);
+ CRStateBits *sb = GetCurrentBits();
+ CRTransformBits *tb = &(sb->transform);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "Translated called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ crMatrixTranslate(t->currentStack->top, (float)x_arg, (float)y_arg, (float)z_arg);
+ t->modelViewProjectionValid = 0;
+ DIRTY(tb->currentMatrix, g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+}
+
+
+void STATE_APIENTRY crStateRotatef(GLfloat ang, GLfloat x, GLfloat y, GLfloat z)
+{
+ CRContext *g = GetCurrentContext();
+ CRTransformState *t = &(g->transform);
+ CRStateBits *sb = GetCurrentBits();
+ CRTransformBits *tb = &(sb->transform);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "Rotatef called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ crMatrixRotate(t->currentStack->top, ang, x, y, z);
+ t->modelViewProjectionValid = 0;
+ DIRTY(tb->currentMatrix, g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateRotated(GLdouble ang, GLdouble x, GLdouble y, GLdouble z)
+{
+ CRContext *g = GetCurrentContext();
+ CRTransformState *t = &(g->transform);
+ CRStateBits *sb = GetCurrentBits();
+ CRTransformBits *tb = &(sb->transform);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "Rotated called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ crMatrixRotate(t->currentStack->top, (float)ang, (float)x, (float)y, (float)z);
+ t->modelViewProjectionValid = 0;
+ DIRTY(tb->currentMatrix, g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateScalef (GLfloat x_arg, GLfloat y_arg, GLfloat z_arg)
+{
+ CRContext *g = GetCurrentContext();
+ CRTransformState *t = &(g->transform);
+ CRStateBits *sb = GetCurrentBits();
+ CRTransformBits *tb = &(sb->transform);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "Scalef called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ crMatrixScale(t->currentStack->top, x_arg, y_arg, z_arg);
+ t->modelViewProjectionValid = 0;
+ DIRTY(tb->currentMatrix, g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateScaled (GLdouble x_arg, GLdouble y_arg, GLdouble z_arg)
+{
+ CRContext *g = GetCurrentContext();
+ CRTransformState *t = &(g->transform);
+ CRStateBits *sb = GetCurrentBits();
+ CRTransformBits *tb = &(sb->transform);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "Scaled called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ crMatrixScale(t->currentStack->top, (float)x_arg, (float)y_arg, (float)z_arg);
+ t->modelViewProjectionValid = 0;
+ DIRTY(tb->currentMatrix, g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateFrustum(GLdouble left, GLdouble right,
+ GLdouble bottom, GLdouble top,
+ GLdouble zNear, GLdouble zFar)
+{
+ CRContext *g = GetCurrentContext();
+ CRTransformState *t = &(g->transform);
+ CRStateBits *sb = GetCurrentBits();
+ CRTransformBits *tb = &(sb->transform);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "Frustum called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ crMatrixFrustum(t->currentStack->top, (float)left, (float)right, (float)bottom, (float)top, (float)zNear, (float)zFar);
+ t->modelViewProjectionValid = 0;
+ DIRTY(tb->currentMatrix, g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateOrtho(GLdouble left, GLdouble right,
+ GLdouble bottom, GLdouble top,
+ GLdouble zNear, GLdouble zFar)
+{
+ CRContext *g = GetCurrentContext();
+ CRTransformState *t = &(g->transform);
+ CRStateBits *sb = GetCurrentBits();
+ CRTransformBits *tb = &(sb->transform);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "Ortho called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ crMatrixOrtho(t->currentStack->top, (float)left, (float)right, (float)bottom, (float)top, (float)zNear, (float)zFar);
+ t->modelViewProjectionValid = 0;
+ DIRTY(tb->currentMatrix, g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateGetClipPlane(GLenum plane, GLdouble *equation)
+{
+ CRContext *g = GetCurrentContext();
+ CRTransformState *t = &g->transform;
+ unsigned int i;
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glGetClipPlane called in begin/end");
+ return;
+ }
+
+ i = plane - GL_CLIP_PLANE0;
+ if (i >= g->limits.maxClipPlanes)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "GetClipPlane called with bad enumerant: %d", plane);
+ return;
+ }
+
+ equation[0] = t->clipPlane[i].x;
+ equation[1] = t->clipPlane[i].y;
+ equation[2] = t->clipPlane[i].z;
+ equation[3] = t->clipPlane[i].w;
+}
+
+void crStateTransformSwitch( CRTransformBits *t, CRbitvalue *bitID,
+ CRContext *fromCtx, CRContext *toCtx )
+{
+ const GLuint maxTextureUnits = toCtx->limits.maxTextureUnits;
+ CRTransformState *from = &(fromCtx->transform);
+ CRTransformState *to = &(toCtx->transform);
+ GLuint i, j;
+ unsigned int checktex = 0;
+ CRbitvalue nbitID[CR_MAX_BITARRAY];
+
+ for (j=0;j<CR_MAX_BITARRAY;j++)
+ nbitID[j] = ~bitID[j];
+
+ if (CHECKDIRTY(t->enable, bitID))
+ {
+ glAble able[2];
+ able[0] = diff_api.Disable;
+ able[1] = diff_api.Enable;
+ if (from->normalize != to->normalize) {
+ if (to->normalize == GL_TRUE)
+ diff_api.Enable(GL_NORMALIZE);
+ else
+ diff_api.Disable(GL_NORMALIZE);
+ FILLDIRTY(t->enable);
+ FILLDIRTY(t->dirty);
+ }
+#ifdef CR_OPENGL_VERSION_1_2
+ if (from->rescaleNormals != to->rescaleNormals)
+ {
+ able[to->rescaleNormals](GL_RESCALE_NORMAL);
+ FILLDIRTY(t->enable);
+ FILLDIRTY(t->dirty);
+ }
+#else
+ (void) able;
+#endif
+#ifdef CR_IBM_rasterpos_clip
+ if (from->rasterPositionUnclipped != to->rasterPositionUnclipped)
+ {
+ able[to->rasterPositionUnclipped](GL_RASTER_POSITION_UNCLIPPED_IBM);
+ FILLDIRTY(t->enable);
+ FILLDIRTY(t->dirty);
+ }
+#endif
+ CLEARDIRTY(t->enable, nbitID);
+ }
+
+ if (CHECKDIRTY(t->clipPlane, bitID)) {
+ diff_api.MatrixMode(GL_MODELVIEW);
+ diff_api.PushMatrix();
+ diff_api.LoadIdentity();
+ for (i=0; i<CR_MAX_CLIP_PLANES; i++) {
+ if (from->clipPlane[i].x != to->clipPlane[i].x ||
+ from->clipPlane[i].y != to->clipPlane[i].y ||
+ from->clipPlane[i].z != to->clipPlane[i].z ||
+ from->clipPlane[i].w != to->clipPlane[i].w) {
+
+ GLdouble cp[4];
+ cp[0] = to->clipPlane[i].x;
+ cp[1] = to->clipPlane[i].y;
+ cp[2] = to->clipPlane[i].z;
+ cp[3] = to->clipPlane[i].w;
+
+ diff_api.ClipPlane(GL_CLIP_PLANE0 + i, (const GLdouble *)(cp));
+
+ FILLDIRTY(t->clipPlane);
+ FILLDIRTY(t->dirty);
+ }
+ }
+ diff_api.PopMatrix();
+ CLEARDIRTY(t->clipPlane, nbitID);
+ }
+
+ /* If the matrix stack depths don't match when we're
+ * updating the context - we can update the wrong matrix
+ * and get some lovely effects!!
+ * So we troll each depth list here and Pop & Push the matrix stack
+ * to bring it right up to date before checking the current
+ * matrix.
+ *
+ * - Alan H.
+ */
+ if ( (from->modelViewStack.depth != to->modelViewStack.depth) ||
+ CHECKDIRTY(t->modelviewMatrix, bitID) )
+ {
+ GLuint td = to->modelViewStack.depth;
+ GLuint fd = from->modelViewStack.depth;
+
+ if (td != fd ||
+ !crMatrixIsEqual(to->modelViewStack.top, from->modelViewStack.top))
+ {
+ diff_api.MatrixMode(GL_MODELVIEW);
+
+ if (fd > td)
+ {
+ for (i = td; i < fd; i++)
+ {
+ diff_api.PopMatrix();
+ }
+ fd = td;
+ }
+
+ for (i = fd; i <= td; i++)
+ {
+ LOADMATRIX(to->modelViewStack.stack + i);
+ FILLDIRTY(t->modelviewMatrix);
+ FILLDIRTY(t->dirty);
+
+ /* Don't want to push on the current matrix */
+ if (i != to->modelViewStack.depth)
+ diff_api.PushMatrix();
+ }
+ }
+ CLEARDIRTY(t->modelviewMatrix, nbitID);
+ }
+
+ /* Projection matrix */
+ if ( (from->projectionStack.depth != to->projectionStack.depth) ||
+ CHECKDIRTY(t->projectionMatrix, bitID) )
+ {
+ GLuint td = to->projectionStack.depth;
+ GLuint fd = from->projectionStack.depth;
+
+ if (td != fd ||
+ !crMatrixIsEqual(to->projectionStack.top, from->projectionStack.top)) {
+
+ diff_api.MatrixMode(GL_PROJECTION);
+
+ if (fd > td)
+ {
+ for (i = td; i < fd; i++)
+ {
+ diff_api.PopMatrix();
+ }
+ fd = td;
+ }
+
+ for (i = fd; i <= td; i++)
+ {
+ LOADMATRIX(to->projectionStack.stack + i);
+ FILLDIRTY(t->projectionMatrix);
+ FILLDIRTY(t->dirty);
+
+ /* Don't want to push on the current matrix */
+ if (i != to->projectionStack.depth)
+ diff_api.PushMatrix();
+ }
+ }
+ CLEARDIRTY(t->projectionMatrix, nbitID);
+ }
+
+ /* Texture matrices */
+ for (i = 0 ; i < maxTextureUnits ; i++)
+ if (from->textureStack[i].depth != to->textureStack[i].depth)
+ checktex = 1;
+
+ if ( checktex || CHECKDIRTY(t->textureMatrix, bitID) )
+ {
+ for (j = 0 ; j < maxTextureUnits ; j++)
+ {
+ GLuint td = to->textureStack[j].depth;
+ GLuint fd = from->textureStack[j].depth;
+
+ if (td != fd ||
+ !crMatrixIsEqual(to->textureStack[j].top, from->textureStack[j].top))
+ {
+ diff_api.MatrixMode(GL_TEXTURE);
+
+ if (fd > td)
+ {
+ for (i = td; i < fd; i++)
+ {
+ diff_api.PopMatrix();
+ }
+ fd = td;
+ }
+
+ diff_api.ActiveTextureARB( j + GL_TEXTURE0_ARB );
+ for (i = fd; i <= td; i++)
+ {
+ LOADMATRIX(to->textureStack[j].stack + i);
+ FILLDIRTY(t->textureMatrix);
+ FILLDIRTY(t->dirty);
+
+ /* Don't want to push on the current matrix */
+ if (i != to->textureStack[j].depth)
+ diff_api.PushMatrix();
+ }
+ }
+ }
+ /* Since we were mucking with the active texture unit above set it to the
+ * proper value now.
+ */
+ diff_api.ActiveTextureARB(GL_TEXTURE0_ARB + toCtx->texture.curTextureUnit);
+ CLEARDIRTY(t->textureMatrix, nbitID);
+ }
+
+ /* Color matrix */
+ if ( (from->colorStack.depth != to->colorStack.depth) ||
+ CHECKDIRTY(t->colorMatrix, bitID) )
+ {
+ GLuint td = to->colorStack.depth;
+ GLuint fd = from->colorStack.depth;
+ if (td != fd || !crMatrixIsEqual(to->colorStack.top, from->colorStack.top))
+ {
+ diff_api.MatrixMode(GL_COLOR);
+
+ if (fd > td)
+ {
+ for (i = td; i < fd; i++)
+ {
+ diff_api.PopMatrix();
+ }
+ fd = td;
+ }
+
+ for (i = fd; i <= td; i++)
+ {
+ LOADMATRIX(to->colorStack.stack + i);
+ FILLDIRTY(t->colorMatrix);
+ FILLDIRTY(t->dirty);
+
+ /* Don't want to push on the current matrix */
+ if (i != to->colorStack.depth)
+ diff_api.PushMatrix();
+ }
+ }
+ CLEARDIRTY(t->colorMatrix, nbitID);
+ }
+
+ to->modelViewProjectionValid = 0;
+ CLEARDIRTY(t->dirty, nbitID);
+
+ /* Since we were mucking with the current matrix above
+ * set it to the proper value now.
+ */
+ diff_api.MatrixMode(to->matrixMode);
+
+ /* sanity tests */
+ CRASSERT(from->modelViewStack.top == from->modelViewStack.stack + from->modelViewStack.depth);
+ CRASSERT(from->projectionStack.top == from->projectionStack.stack + from->projectionStack.depth);
+
+}
+
+void
+crStateTransformDiff( CRTransformBits *t, CRbitvalue *bitID,
+ CRContext *fromCtx, CRContext *toCtx )
+{
+ const GLuint maxTextureUnits = toCtx->limits.maxTextureUnits;
+ CRTransformState *from = &(fromCtx->transform);
+ CRTransformState *to = &(toCtx->transform);
+ CRTextureState *textureFrom = &(fromCtx->texture);
+ GLuint i, j;
+ unsigned int checktex = 0;
+ CRbitvalue nbitID[CR_MAX_BITARRAY];
+
+ for (j=0;j<CR_MAX_BITARRAY;j++)
+ nbitID[j] = ~bitID[j];
+
+ if (CHECKDIRTY(t->enable, bitID)) {
+ glAble able[2];
+ able[0] = diff_api.Disable;
+ able[1] = diff_api.Enable;
+ for (i=0; i<CR_MAX_CLIP_PLANES; i++) {
+ if (from->clip[i] != to->clip[i]) {
+ if (to->clip[i] == GL_TRUE)
+ diff_api.Enable(GL_CLIP_PLANE0 + i);
+ else
+ diff_api.Disable(GL_CLIP_PLANE0 + i);
+ from->clip[i] = to->clip[i];
+ }
+ }
+ if (from->normalize != to->normalize) {
+ if (to->normalize == GL_TRUE)
+ diff_api.Enable(GL_NORMALIZE);
+ else
+ diff_api.Disable(GL_NORMALIZE);
+ from->normalize = to->normalize;
+ }
+#ifdef CR_OPENGL_VERSION_1_2
+ if (from->rescaleNormals != to->rescaleNormals) {
+ able[to->rescaleNormals](GL_RESCALE_NORMAL);
+ from->rescaleNormals = to->rescaleNormals;
+ }
+#else
+ (void) able;
+#endif
+#ifdef CR_IBM_rasterpos_clip
+ if (from->rasterPositionUnclipped != to->rasterPositionUnclipped) {
+ able[to->rasterPositionUnclipped](GL_RASTER_POSITION_UNCLIPPED_IBM);
+ from->rasterPositionUnclipped = to->rasterPositionUnclipped;
+ }
+#endif
+
+ CLEARDIRTY(t->enable, nbitID);
+ }
+
+ if (CHECKDIRTY(t->clipPlane, bitID)) {
+ if (from->matrixMode != GL_MODELVIEW) {
+ diff_api.MatrixMode(GL_MODELVIEW);
+ from->matrixMode = GL_MODELVIEW;
+ }
+ diff_api.PushMatrix();
+ diff_api.LoadIdentity();
+ for (i=0; i<CR_MAX_CLIP_PLANES; i++) {
+ if (from->clipPlane[i].x != to->clipPlane[i].x ||
+ from->clipPlane[i].y != to->clipPlane[i].y ||
+ from->clipPlane[i].z != to->clipPlane[i].z ||
+ from->clipPlane[i].w != to->clipPlane[i].w) {
+
+ GLdouble cp[4];
+ cp[0] = to->clipPlane[i].x;
+ cp[1] = to->clipPlane[i].y;
+ cp[2] = to->clipPlane[i].z;
+ cp[3] = to->clipPlane[i].w;
+
+ diff_api.ClipPlane(GL_CLIP_PLANE0 + i, (const GLdouble *)(cp));
+ from->clipPlane[i] = to->clipPlane[i];
+ }
+ }
+ diff_api.PopMatrix();
+ CLEARDIRTY(t->clipPlane, nbitID);
+ }
+
+ /* If the matrix stack depths don't match when we're
+ * updating the context - we can update the wrong matrix
+ * and get some lovely effects!!
+ * So we troll each depth list here and Pop & Push the matrix stack
+ * to bring it right up to date before checking the current
+ * matrix.
+ *
+ * - Alan H.
+ */
+ if ( (from->modelViewStack.depth != to->modelViewStack.depth) ||
+ CHECKDIRTY(t->modelviewMatrix, bitID) )
+ {
+ if (from->matrixMode != GL_MODELVIEW) {
+ diff_api.MatrixMode(GL_MODELVIEW);
+ from->matrixMode = GL_MODELVIEW;
+ }
+
+ if (from->modelViewStack.depth > to->modelViewStack.depth)
+ {
+ for (i = to->modelViewStack.depth; i < from->modelViewStack.depth; i++)
+ {
+ diff_api.PopMatrix();
+ }
+
+ from->modelViewStack.depth = to->modelViewStack.depth;
+ }
+
+ for (i = from->modelViewStack.depth; i <= to->modelViewStack.depth; i++)
+ {
+ LOADMATRIX(to->modelViewStack.stack + i);
+ from->modelViewStack.stack[i] = to->modelViewStack.stack[i];
+
+ /* Don't want to push on the current matrix */
+ if (i != to->modelViewStack.depth)
+ diff_api.PushMatrix();
+ }
+ from->modelViewStack.depth = to->modelViewStack.depth;
+ from->modelViewStack.top = from->modelViewStack.stack + from->modelViewStack.depth;
+
+ CLEARDIRTY(t->modelviewMatrix, nbitID);
+ }
+
+ /* Projection matrix */
+ if ( (from->projectionStack.depth != to->projectionStack.depth) ||
+ CHECKDIRTY(t->projectionMatrix, bitID) )
+ {
+ if (from->matrixMode != GL_PROJECTION) {
+ diff_api.MatrixMode(GL_PROJECTION);
+ from->matrixMode = GL_PROJECTION;
+ }
+
+ if (from->projectionStack.depth > to->projectionStack.depth)
+ {
+ for (i = to->projectionStack.depth; i < from->projectionStack.depth; i++)
+ {
+ diff_api.PopMatrix();
+ }
+
+ from->projectionStack.depth = to->projectionStack.depth;
+ }
+
+ for (i = from->projectionStack.depth; i <= to->projectionStack.depth; i++)
+ {
+ LOADMATRIX(to->projectionStack.stack + i);
+ from->projectionStack.stack[i] = to->projectionStack.stack[i];
+
+ /* Don't want to push on the current matrix */
+ if (i != to->projectionStack.depth)
+ diff_api.PushMatrix();
+ }
+ from->projectionStack.depth = to->projectionStack.depth;
+ from->projectionStack.top = from->projectionStack.stack + from->projectionStack.depth;
+
+ CLEARDIRTY(t->projectionMatrix, nbitID);
+ }
+
+ /* Texture matrices */
+ for (i = 0 ; i < maxTextureUnits ; i++)
+ if (from->textureStack[i].depth != to->textureStack[i].depth)
+ checktex = 1;
+
+ if (checktex || CHECKDIRTY(t->textureMatrix, bitID))
+ {
+ if (from->matrixMode != GL_TEXTURE) {
+ diff_api.MatrixMode(GL_TEXTURE);
+ from->matrixMode = GL_TEXTURE;
+ }
+ for (j = 0 ; j < maxTextureUnits; j++)
+ {
+ if (from->textureStack[j].depth > to->textureStack[j].depth)
+ {
+ if (textureFrom->curTextureUnit != j) {
+ diff_api.ActiveTextureARB( j + GL_TEXTURE0_ARB );
+ textureFrom->curTextureUnit = j;
+ }
+ for (i = to->textureStack[j].depth; i < from->textureStack[j].depth; i++)
+ {
+ diff_api.PopMatrix();
+ }
+
+ from->textureStack[j].depth = to->textureStack[j].depth;
+ }
+
+ for (i = from->textureStack[j].depth; i <= to->textureStack[j].depth; i++)
+ {
+ if (textureFrom->curTextureUnit != j) {
+ diff_api.ActiveTextureARB( j + GL_TEXTURE0_ARB );
+ textureFrom->curTextureUnit = j;
+ }
+ LOADMATRIX(to->textureStack[j].stack + i);
+ from->textureStack[j].stack[i] = to->textureStack[j].stack[i];
+
+ /* Don't want to push on the current matrix */
+ if (i != to->textureStack[j].depth)
+ diff_api.PushMatrix();
+ }
+ from->textureStack[j].depth = to->textureStack[j].depth;
+ from->textureStack[j].top = from->textureStack[j].stack + from->textureStack[j].depth;
+ }
+ CLEARDIRTY(t->textureMatrix, nbitID);
+
+ /* Restore proper active texture unit */
+ diff_api.ActiveTextureARB(GL_TEXTURE0_ARB + toCtx->texture.curTextureUnit);
+ }
+
+ /* Color matrix */
+ if ( (from->colorStack.depth != to->colorStack.depth) ||
+ CHECKDIRTY(t->colorMatrix, bitID) )
+ {
+ if (from->matrixMode != GL_COLOR) {
+ diff_api.MatrixMode(GL_COLOR);
+ from->matrixMode = GL_COLOR;
+ }
+
+ if (from->colorStack.depth > to->colorStack.depth)
+ {
+ for (i = to->colorStack.depth; i < from->colorStack.depth; i++)
+ {
+ diff_api.PopMatrix();
+ }
+
+ from->colorStack.depth = to->colorStack.depth;
+ }
+
+ for (i = to->colorStack.depth; i <= to->colorStack.depth; i++)
+ {
+ LOADMATRIX(to->colorStack.stack + i);
+ from->colorStack.stack[i] = to->colorStack.stack[i];
+
+ /* Don't want to push on the current matrix */
+ if (i != to->colorStack.depth)
+ diff_api.PushMatrix();
+ }
+ from->colorStack.depth = to->colorStack.depth;
+ from->colorStack.top = from->colorStack.stack + from->colorStack.depth;
+
+ CLEARDIRTY(t->colorMatrix, nbitID);
+ }
+
+ to->modelViewProjectionValid = 0;
+ CLEARDIRTY(t->dirty, nbitID);
+
+ /* update MatrixMode now */
+ if (from->matrixMode != to->matrixMode) {
+ diff_api.MatrixMode(to->matrixMode);
+ from->matrixMode = to->matrixMode;
+ }
+
+ /* sanity tests */
+ CRASSERT(from->modelViewStack.top == from->modelViewStack.stack + from->modelViewStack.depth);
+ CRASSERT(from->projectionStack.top == from->projectionStack.stack + from->projectionStack.depth);
+}
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_viewport.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_viewport.c
new file mode 100644
index 00000000..e238f9ae
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_viewport.c
@@ -0,0 +1,166 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#include <stdio.h>
+#include "state.h"
+#include "state/cr_statetypes.h"
+#include "state_internals.h"
+
+void crStateViewportInit(CRContext *ctx)
+{
+ CRViewportState *v = &ctx->viewport;
+ CRStateBits *sb = GetCurrentBits();
+ CRViewportBits *vb = &(sb->viewport);
+ CRTransformBits *tb = &(sb->transform);
+
+ v->scissorTest = GL_FALSE;
+ RESET(vb->enable, ctx->bitid);
+
+ v->viewportValid = GL_FALSE;
+ v->viewportX = 0;
+ v->viewportY = 0;
+ /* These are defaults, the tilesort spu overrides when
+ * the context has been created */
+ v->viewportW = 640;
+ v->viewportH = 480;
+ RESET(vb->v_dims, ctx->bitid);
+
+ v->scissorValid = GL_FALSE;
+ v->scissorX = 0;
+ v->scissorY = 0;
+ /* These are defaults, the tilesort spu overrides when
+ * the context has been created */
+ v->scissorW = 640;
+ v->scissorH = 480;
+ RESET(vb->s_dims, ctx->bitid);
+
+ v->farClip = 1.0;
+ v->nearClip = 0.0;
+ RESET(vb->depth, ctx->bitid);
+
+ RESET(vb->dirty, ctx->bitid);
+
+ /* XXX why are these here? */
+ RESET(tb->base, ctx->bitid);
+ RESET(tb->dirty, ctx->bitid);
+}
+
+void crStateViewportApply(CRViewportState *v, GLvectorf *p)
+{
+ p->x = (p->x+1.0f)*(v->viewportW / 2.0f) + v->viewportX;
+ p->y = (p->y+1.0f)*(v->viewportH / 2.0f) + v->viewportY;
+ p->z = (GLfloat) ((p->z+1.0f)*((v->farClip - v->nearClip) / 2.0f) + v->nearClip);
+}
+
+void STATE_APIENTRY crStateViewport(GLint x, GLint y, GLsizei width,
+ GLsizei height)
+{
+ CRContext *g = GetCurrentContext();
+ CRViewportState *v = &(g->viewport);
+ CRStateBits *sb = GetCurrentBits();
+ CRViewportBits *vb = &(sb->viewport);
+ CRTransformBits *tb = &(sb->transform);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError( __LINE__, __FILE__, GL_INVALID_OPERATION,
+ "calling glViewport() between glBegin/glEnd" );
+ return;
+ }
+
+ FLUSH();
+
+ if (width < 0 || height < 0)
+ {
+ crStateError( __LINE__, __FILE__, GL_INVALID_VALUE,
+ "glViewport(bad width or height)" );
+ return;
+ }
+
+ if (x > g->limits.maxViewportDims[0]) x = g->limits.maxViewportDims[0];
+ if (x < -g->limits.maxViewportDims[0]) x = -g->limits.maxViewportDims[0];
+ if (y > g->limits.maxViewportDims[1]) y = g->limits.maxViewportDims[1];
+ if (y < -g->limits.maxViewportDims[1]) y = -g->limits.maxViewportDims[1];
+ if (width > g->limits.maxViewportDims[0]) width = g->limits.maxViewportDims[0];
+ if (height > g->limits.maxViewportDims[1]) height = g->limits.maxViewportDims[1];
+
+ v->viewportX = (GLint) (x);
+ v->viewportY = (GLint) (y);
+ v->viewportW = (GLint) (width);
+ v->viewportH = (GLint) (height);
+
+ v->viewportValid = GL_TRUE;
+
+ DIRTY(vb->v_dims, g->neg_bitid);
+ DIRTY(vb->dirty, g->neg_bitid);
+ /* XXX why are these here? */
+ DIRTY(tb->base, g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateDepthRange(GLclampd znear, GLclampd zfar)
+{
+ CRContext *g = GetCurrentContext();
+ CRViewportState *v = &(g->viewport);
+ CRStateBits *sb = GetCurrentBits();
+ CRViewportBits *vb = &(sb->viewport);
+ CRTransformBits *tb = &(sb->transform);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glDepthRange called in Begin/End");
+ return;
+ }
+
+ FLUSH();
+
+ v->nearClip = znear;
+ v->farClip = zfar;
+ if (v->nearClip < 0.0) v->nearClip = 0.0;
+ if (v->nearClip > 1.0) v->nearClip = 1.0;
+ if (v->farClip < 0.0) v->farClip = 0.0;
+ if (v->farClip > 1.0) v->farClip = 1.0;
+
+ DIRTY(vb->depth, g->neg_bitid);
+ DIRTY(vb->dirty, g->neg_bitid);
+ DIRTY(tb->dirty, g->neg_bitid);
+}
+
+void STATE_APIENTRY crStateScissor (GLint x, GLint y,
+ GLsizei width, GLsizei height)
+{
+ CRContext *g = GetCurrentContext();
+ CRViewportState *v = &(g->viewport);
+ CRStateBits *sb = GetCurrentBits();
+ CRViewportBits *vb = &(sb->viewport);
+
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glScissor called in begin/end");
+ return;
+ }
+
+ FLUSH();
+
+ if (width < 0 || height < 0)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
+ "glScissor called with negative width/height: %d,%d",
+ width, height);
+ return;
+ }
+
+ v->scissorX = (GLint) (x);
+ v->scissorY = (GLint) (y);
+ v->scissorW = (GLint) (width);
+ v->scissorH = (GLint) (height);
+
+ v->scissorValid = GL_TRUE;
+
+ DIRTY(vb->s_dims, g->neg_bitid);
+ DIRTY(vb->dirty, g->neg_bitid);
+}
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_viewport.txt b/src/VBox/GuestHost/OpenGL/state_tracker/state_viewport.txt
new file mode 100644
index 00000000..f2857d25
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_viewport.txt
@@ -0,0 +1,14 @@
+# Copyright (c) 2001, Stanford University
+# All rights reserved.
+#
+# See the file LICENSE.txt for information on redistributing this software.
+:enable:scissorTest:GL_SCISSOR_TEST
+:s_dims:scissorX,scissorY,scissorW,scissorH:Scissor
+#+scissorTest:s_dims:*CRrecti p;
+#+scissorTest:s_dims:scissorX,scissorY,scissorW,scissorH:*diff_api.Scissor(p.x1, p.y1, p.x2-p.x1, p.y2-p.y1);
+#-scissorTest:s_dims:scissorX,scissorY,scissorW,scissorH:Scissor
+#+:v_dims:*CRrecti p;
+#+:v_dims:viewportX,viewportY,viewportW,viewportH:*diff_api.Viewport(p.x1, p.y1, p.x2-p.x1, p.y2-p.y1);
+:v_dims:viewportX,viewportY,viewportW,viewportH:Viewport
+#-:v_dims:viewportX,viewportY,viewportW,viewportH:Viewport
+:depth:nearClip,farClip:DepthRange